diff --git a/.all-contributorsrc b/.all-contributorsrc index a2d13c2fc..ced3b155b 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -1,7 +1,6 @@ { "files": [ - "website/src/pages/credits.mdx", - "docs/src/assets/contributors.html" + "website/src/pages/credits.mdx" ], "imageSize": 75, "commit": false, diff --git a/.beads/issues.jsonl b/.beads/issues.jsonl deleted file mode 100644 index 67f7a6830..000000000 --- a/.beads/issues.jsonl +++ /dev/null @@ -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"}]} diff --git a/.coderabbit.yaml b/.coderabbit.yaml deleted file mode 100644 index 5edf609fa..000000000 --- a/.coderabbit.yaml +++ /dev/null @@ -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: [] diff --git a/.gitattributes b/.gitattributes deleted file mode 100644 index 807d5983d..000000000 --- a/.gitattributes +++ /dev/null @@ -1,3 +0,0 @@ - -# Use bd merge for beads JSONL files -.beads/issues.jsonl merge=beads diff --git a/.github/ISSUE_TEMPLATE/bug_report.yml b/.github/ISSUE_TEMPLATE/bug_report.yml index c8ace9747..9faf71704 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yml +++ b/.github/ISSUE_TEMPLATE/bug_report.yml @@ -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`. diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 9f8d049ba..d73efffa8 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -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 diff --git a/.github/workflows/auto-label-issues.yml b/.github/workflows/auto-label-issues.yml index 097eba533..3d7a86450 100644 --- a/.github/workflows/auto-label-issues.yml +++ b/.github/workflows/auto-label-issues.yml @@ -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: diff --git a/.github/workflows/automated-releases.yml b/.github/workflows/automated-releases.yml deleted file mode 100644 index 83445d869..000000000 --- a/.github/workflows/automated-releases.yml +++ /dev/null @@ -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<> $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 " - - # 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<> $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 " - - # 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 \ No newline at end of file diff --git a/.github/workflows/build-and-test-v3.yml b/.github/workflows/build-and-test-v3.yml index cc2c6ded0..bfcef85a3 100644 --- a/.github/workflows/build-and-test-v3.yml +++ b/.github/workflows/build-and-test-v3.yml @@ -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,173 +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) - webkit-gtk6-support branch only - if: matrix.os == 'ubuntu-latest' && github.head_ref == 'feature/webkit-gtk6-support' - 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 experimental) - if: matrix.os == 'ubuntu-latest' && github.head_ref == 'feature/webkit-gtk6-support' - 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 experimental - if: matrix.os == 'ubuntu-latest' && github.head_ref == 'feature/webkit-gtk6-support' - working-directory: v3 - # Skip all service tests that hang in CI due to GTK4 display requirements - # The services tests require a fully functional GTK4 display which xvfb cannot provide - 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: @@ -236,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) - webkit-gtk6-support branch only - if: matrix.os == 'ubuntu-latest' && github.head_ref == 'feature/webkit-gtk6-support' - 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 @@ -268,33 +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 - # Note: GTK4 template builds are not tested here as wails build doesn't - # support -tags flag yet. GTK4 compilation is verified by Go tests. - build_results: if: ${{ always() }} runs-on: ubuntu-latest diff --git a/.github/workflows/build-and-test.yml b/.github/workflows/build-and-test.yml index a6ee1a0bb..8fe647c6f 100644 --- a/.github/workflows/build-and-test.yml +++ b/.github/workflows/build-and-test.yml @@ -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' diff --git a/.github/workflows/build-cross-image.yml b/.github/workflows/build-cross-image.yml index 1af95a59b..83b40f2be 100644 --- a/.github/workflows/build-cross-image.yml +++ b/.github/workflows/build-cross-image.yml @@ -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 + + 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 diff --git a/.github/workflows/changelog-v3.yml b/.github/workflows/changelog-v3.yml new file mode 100644 index 000000000..688959b9e --- /dev/null +++ b/.github/workflows/changelog-v3.yml @@ -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' + + '
\\n' + + '📝 Click to see the corrected changelog content\\n\\n' + + '```mdx\\n' + + fixedContent + + '\\n```\\n\\n' + + '
\\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 \ No newline at end of file diff --git a/.github/workflows/changelog-validation-v3.yml b/.github/workflows/changelog-validation-v3.yml deleted file mode 100644 index 8d4b97726..000000000 --- a/.github/workflows/changelog-validation-v3.yml +++ /dev/null @@ -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 - }); - diff --git a/.github/workflows/claude-code-review.yml b/.github/workflows/claude-code-review.yml new file mode 100644 index 000000000..b5e8cfd4d --- /dev/null +++ b/.github/workflows/claude-code-review.yml @@ -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 + diff --git a/.github/workflows/claude.yml b/.github/workflows/claude.yml new file mode 100644 index 000000000..d300267f1 --- /dev/null +++ b/.github/workflows/claude.yml @@ -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:*)' + diff --git a/.github/workflows/cross-compile-test-v3.yml b/.github/workflows/cross-compile-test-v3.yml deleted file mode 100644 index 2d7c3dbcb..000000000 --- a/.github/workflows/cross-compile-test-v3.yml +++ /dev/null @@ -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 diff --git a/.github/workflows/generate-sponsor-image.yml b/.github/workflows/generate-sponsor-image.yml index 585d7e19f..56548ab43 100644 --- a/.github/workflows/generate-sponsor-image.yml +++ b/.github/workflows/generate-sponsor-image.yml @@ -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" diff --git a/.github/workflows/issue-triage-automation.yml b/.github/workflows/issue-triage-automation.yml index 4a827d527..99159a2f5 100644 --- a/.github/workflows/issue-triage-automation.yml +++ b/.github/workflows/issue-triage-automation.yml @@ -2,7 +2,7 @@ name: Issue Triage Automation on: issues: - types: [opened, reopened, labeled, unlabeled] + types: [opened] jobs: triage: diff --git a/.github/workflows/pr-master.yml b/.github/workflows/pr-master.yml index 1de533199..c961b4434 100644 --- a/.github/workflows/pr-master.yml +++ b/.github/workflows/pr-master.yml @@ -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 diff --git a/.github/workflows/publish-npm.yml b/.github/workflows/publish-npm.yml deleted file mode 100644 index 3ebd2f282..000000000 --- a/.github/workflows/publish-npm.yml +++ /dev/null @@ -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 }} diff --git a/.github/workflows/test-nightly-releases.yml b/.github/workflows/test-nightly-releases.yml index 1e6f12a69..63df09935 100644 --- a/.github/workflows/test-nightly-releases.yml +++ b/.github/workflows/test-nightly-releases.yml @@ -1,6 +1,4 @@ name: Test Nightly Releases (Dry Run) -permissions: - contents: read on: workflow_dispatch: diff --git a/.github/workflows/test-simple.yml b/.github/workflows/test-simple.yml deleted file mode 100644 index 8c4c88295..000000000 --- a/.github/workflows/test-simple.yml +++ /dev/null @@ -1,11 +0,0 @@ -name: Test Simple - -on: - workflow_dispatch: - -jobs: - test: - runs-on: ubuntu-latest - steps: - - name: Test - run: echo "Hello World" \ No newline at end of file diff --git a/.github/workflows/unreleased-changelog-trigger.yml b/.github/workflows/unreleased-changelog-trigger.yml index 381023052..8cfe85de0 100644 --- a/.github/workflows/unreleased-changelog-trigger.yml +++ b/.github/workflows/unreleased-changelog-trigger.yml @@ -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' diff --git a/.github/workflows/v3-docs.yml b/.github/workflows/v3-docs.yml deleted file mode 100644 index c70bffb8a..000000000 --- a/.github/workflows/v3-docs.yml +++ /dev/null @@ -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 \ No newline at end of file diff --git a/.gitignore b/.gitignore index 61efe756b..e7888b44a 100644 --- a/.gitignore +++ b/.gitignore @@ -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 diff --git a/.prettierrc.yml b/.prettierrc.yml index 1e2d2dada..685d8b6e7 100644 --- a/.prettierrc.yml +++ b/.prettierrc.yml @@ -1,7 +1,6 @@ overrides: - files: - "**/*.md" - - "**/*.mdx" options: printWidth: 80 proseWrap: always diff --git a/.replit b/.replit new file mode 100644 index 000000000..619bd7227 --- /dev/null +++ b/.replit @@ -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"] diff --git a/AGENTS.md b/AGENTS.md deleted file mode 100644 index 0d4177023..000000000 --- a/AGENTS.md +++ /dev/null @@ -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 --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 --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:` -5. **Complete**: `bd close --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 --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 --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 diff --git a/CNAME b/CNAME deleted file mode 100644 index 23caa94af..000000000 --- a/CNAME +++ /dev/null @@ -1 +0,0 @@ -v3alpha.wails.io \ No newline at end of file diff --git a/IMPLEMENTATION.md b/IMPLEMENTATION.md deleted file mode 100644 index 16d048f3f..000000000 --- a/IMPLEMENTATION.md +++ /dev/null @@ -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: -- `q` - Ctrl+Q -- `s` - Ctrl+Shift+S -- `F4` - Alt+F4 -- `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 diff --git a/IOS_ARCHITECTURE.md b/IOS_ARCHITECTURE.md deleted file mode 100644 index 2e07f4f0c..000000000 --- a/IOS_ARCHITECTURE.md +++ /dev/null @@ -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 -``` -- 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 -``` -- 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. \ No newline at end of file diff --git a/README.de.md b/README.de.md index b1616d2f9..5df35de5b 100644 --- a/README.de.md +++ b/README.de.md @@ -25,7 +25,7 @@ Erschaffe Desktop Anwendungen mit Go & Web Technologien. Awesome - Discord + Discord
diff --git a/README.es.md b/README.es.md index 59cbcf132..277d1c1fd 100644 --- a/README.es.md +++ b/README.es.md @@ -25,7 +25,7 @@ Awesome - Discord + Discord
diff --git a/README.fr.md b/README.fr.md index 2f405b46a..61230f353 100644 --- a/README.fr.md +++ b/README.fr.md @@ -25,7 +25,7 @@ Awesome - Discord + Discord
diff --git a/README.ja.md b/README.ja.md index d4edb662c..ffd9f8103 100644 --- a/README.ja.md +++ b/README.ja.md @@ -27,7 +27,7 @@ Awesome - Discord + Discord
diff --git a/README.ko.md b/README.ko.md index fc27dfbe1..075e04229 100644 --- a/README.ko.md +++ b/README.ko.md @@ -27,7 +27,7 @@ Awesome - Discord + Discord
diff --git a/README.md b/README.md index 12ff1d6dc..5ab9309b4 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,7 @@ Awesome - Discord + Discord
@@ -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: -

- -

+## Powered By + +[![JetBrains logo.](https://resources.jetbrains.com/storage/products/company/brand/logos/jetbrains.svg)](https://jb.gg/OpenSource) ## FAQ diff --git a/README.pt-br.md b/README.pt-br.md index 8129ac853..0e3883352 100644 --- a/README.pt-br.md +++ b/README.pt-br.md @@ -25,7 +25,7 @@ Awesome
- Discord + Discord
diff --git a/README.ru.md b/README.ru.md index 4a24b9bcb..76fa59d07 100644 --- a/README.ru.md +++ b/README.ru.md @@ -25,7 +25,7 @@ Awesome - Discord + Discord
diff --git a/README.tr.md b/README.tr.md index b9e88c0b9..e9b16ca76 100644 --- a/README.tr.md +++ b/README.tr.md @@ -25,7 +25,7 @@ Awesome - Discord + Discord
diff --git a/README.uz.md b/README.uz.md index 88744e94e..807262405 100644 --- a/README.uz.md +++ b/README.uz.md @@ -25,7 +25,7 @@ Awesome - Discord + Discord
diff --git a/README.zh-Hans.md b/README.zh-Hans.md index baeeb420e..4c09d0c45 100644 --- a/README.zh-Hans.md +++ b/README.zh-Hans.md @@ -27,7 +27,7 @@ Awesome - Discord + Discord
diff --git a/Taskfile.yaml b/Taskfile.yaml index 051da3e42..7cc165825 100644 --- a/Taskfile.yaml +++ b/Taskfile.yaml @@ -16,11 +16,6 @@ includes: dir: v3 optional: true - docs: - taskfile: docs - dir: docs - optional: true - tasks: contributors:check: cmds: diff --git a/docs/.gitignore b/docs/.gitignore deleted file mode 100644 index 6240da8b1..000000000 --- a/docs/.gitignore +++ /dev/null @@ -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 diff --git a/docs/.npmrc b/docs/.npmrc deleted file mode 100644 index cffe8cdef..000000000 --- a/docs/.npmrc +++ /dev/null @@ -1 +0,0 @@ -save-exact=true diff --git a/docs/.vscode/extensions.json b/docs/.vscode/extensions.json deleted file mode 100644 index 22a15055d..000000000 --- a/docs/.vscode/extensions.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "recommendations": ["astro-build.astro-vscode"], - "unwantedRecommendations": [] -} diff --git a/docs/.vscode/launch.json b/docs/.vscode/launch.json deleted file mode 100644 index d64220976..000000000 --- a/docs/.vscode/launch.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "version": "0.2.0", - "configurations": [ - { - "command": "./node_modules/.bin/astro dev", - "name": "Development server", - "request": "launch", - "type": "node-terminal" - } - ] -} diff --git a/docs/CNAME b/docs/CNAME deleted file mode 100644 index 23caa94af..000000000 --- a/docs/CNAME +++ /dev/null @@ -1 +0,0 @@ -v3alpha.wails.io \ No newline at end of file diff --git a/docs/README.md b/docs/README.md deleted file mode 100644 index 108b2a1fa..000000000 --- a/docs/README.md +++ /dev/null @@ -1,65 +0,0 @@ -# Wails v3 Documentation - -[![Built with Starlight](https://astro.badg.es/v2/built-with-starlight/tiny.svg)](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). diff --git a/docs/Taskfile.yml b/docs/Taskfile.yml deleted file mode 100644 index 9f7c01fd6..000000000 --- a/docs/Taskfile.yml +++ /dev/null @@ -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' - diff --git a/docs/astro.config.mjs b/docs/astro.config.mjs deleted file mode 100644 index 352989727..000000000 --- a/docs/astro.config.mjs +++ /dev/null @@ -1,349 +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 = 'Sponsor'; - 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: "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" }, - ], - }), - ], -}); diff --git a/docs/package-lock.json b/docs/package-lock.json deleted file mode 100644 index 428b7ec7b..000000000 --- a/docs/package-lock.json +++ /dev/null @@ -1,9082 +0,0 @@ -{ - "name": "wails-docs", - "version": "0.0.1", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "wails-docs", - "version": "0.0.1", - "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" - } - }, - "node_modules/@astro-community/astro-embed-twitter": { - "version": "0.5.9", - "resolved": "https://registry.npmjs.org/@astro-community/astro-embed-twitter/-/astro-embed-twitter-0.5.9.tgz", - "integrity": "sha512-bTIP/2LB3iEzlZ58L7dFyLJuWLeFDXgzZUQZKlWIfsXiKYqKIfLTQ01U10sh9UiHpm1M+4kOVPpue5LbUpJXHw==", - "license": "MIT", - "dependencies": { - "@astro-community/astro-embed-utils": "^0.1.5" - }, - "peerDependencies": { - "astro": "^2.0.0 || ^3.0.0-beta || ^4.0.0-beta || ^5.0.0-beta" - } - }, - "node_modules/@astro-community/astro-embed-utils": { - "version": "0.1.5", - "resolved": "https://registry.npmjs.org/@astro-community/astro-embed-utils/-/astro-embed-utils-0.1.5.tgz", - "integrity": "sha512-0RlP7J1YEWrguWDfEDsm4uDCXk4FKn0HHakmSOSwHLg6YR8WNEN/LGMGhhsxLc/mDqO2lRh1VqfJy+yPLLkzsQ==", - "license": "MIT", - "dependencies": { - "linkedom": "^0.18.12" - } - }, - "node_modules/@astro-community/astro-embed-youtube": { - "version": "0.5.9", - "resolved": "https://registry.npmjs.org/@astro-community/astro-embed-youtube/-/astro-embed-youtube-0.5.9.tgz", - "integrity": "sha512-8Uk2SKbyZVb+jxwqSAMoEpQo+063XYwCI3yRy9cbkyHpu09mDabGZNTF5XrL8CKr3NtR5haBkeYK/kSuKUkJ/g==", - "license": "MIT", - "dependencies": { - "lite-youtube-embed": "^0.3.4" - }, - "peerDependencies": { - "astro": "^2.0.0 || ^3.0.0-beta || ^4.0.0-beta || ^5.0.0-beta" - } - }, - "node_modules/@astrojs/check": { - "version": "0.9.5", - "resolved": "https://registry.npmjs.org/@astrojs/check/-/check-0.9.5.tgz", - "integrity": "sha512-88vc8n2eJ1Oua74yXSGo/8ABMeypfQPGEzuoAx2awL9Ju8cE6tZ2Rz9jVx5hIExHK5gKVhpxfZj4WXm7e32g1w==", - "license": "MIT", - "dependencies": { - "@astrojs/language-server": "^2.15.0", - "chokidar": "^4.0.1", - "kleur": "^4.1.5", - "yargs": "^17.7.2" - }, - "bin": { - "astro-check": "dist/bin.js" - }, - "peerDependencies": { - "typescript": "^5.0.0" - } - }, - "node_modules/@astrojs/compiler": { - "version": "2.13.0", - "resolved": "https://registry.npmjs.org/@astrojs/compiler/-/compiler-2.13.0.tgz", - "integrity": "sha512-mqVORhUJViA28fwHYaWmsXSzLO9osbdZ5ImUfxBarqsYdMlPbqAqGJCxsNzvppp1BEzc1mJNjOVvQqeDN8Vspw==", - "license": "MIT" - }, - "node_modules/@astrojs/internal-helpers": { - "version": "0.7.5", - "resolved": "https://registry.npmjs.org/@astrojs/internal-helpers/-/internal-helpers-0.7.5.tgz", - "integrity": "sha512-vreGnYSSKhAjFJCWAwe/CNhONvoc5lokxtRoZims+0wa3KbHBdPHSSthJsKxPd8d/aic6lWKpRTYGY/hsgK6EA==", - "license": "MIT" - }, - "node_modules/@astrojs/language-server": { - "version": "2.16.0", - "resolved": "https://registry.npmjs.org/@astrojs/language-server/-/language-server-2.16.0.tgz", - "integrity": "sha512-oX2KkuIfEEM5d4/+lfuxy6usRDYko0S02YvtHFTrnqW0h9e4ElAfWZRKyqxWlwpuPdciBPKef5YJ7DFH3PPssw==", - "license": "MIT", - "dependencies": { - "@astrojs/compiler": "^2.10.3", - "@astrojs/yaml2ts": "^0.2.2", - "@jridgewell/sourcemap-codec": "^1.4.15", - "@volar/kit": "~2.4.23", - "@volar/language-core": "~2.4.23", - "@volar/language-server": "~2.4.23", - "@volar/language-service": "~2.4.23", - "fast-glob": "^3.2.12", - "muggle-string": "^0.4.1", - "volar-service-css": "0.0.66", - "volar-service-emmet": "0.0.66", - "volar-service-html": "0.0.66", - "volar-service-prettier": "0.0.66", - "volar-service-typescript": "0.0.66", - "volar-service-typescript-twoslash-queries": "0.0.66", - "volar-service-yaml": "0.0.66", - "vscode-html-languageservice": "^5.5.2", - "vscode-uri": "^3.1.0" - }, - "bin": { - "astro-ls": "bin/nodeServer.js" - }, - "peerDependencies": { - "prettier": "^3.0.0", - "prettier-plugin-astro": ">=0.11.0" - }, - "peerDependenciesMeta": { - "prettier": { - "optional": true - }, - "prettier-plugin-astro": { - "optional": true - } - } - }, - "node_modules/@astrojs/markdown-remark": { - "version": "6.3.9", - "resolved": "https://registry.npmjs.org/@astrojs/markdown-remark/-/markdown-remark-6.3.9.tgz", - "integrity": "sha512-hX2cLC/KW74Io1zIbn92kI482j9J7LleBLGCVU9EP3BeH5MVrnFawOnqD0t/q6D1Z+ZNeQG2gNKMslCcO36wng==", - "license": "MIT", - "dependencies": { - "@astrojs/internal-helpers": "0.7.5", - "@astrojs/prism": "3.3.0", - "github-slugger": "^2.0.0", - "hast-util-from-html": "^2.0.3", - "hast-util-to-text": "^4.0.2", - "import-meta-resolve": "^4.2.0", - "js-yaml": "^4.1.0", - "mdast-util-definitions": "^6.0.0", - "rehype-raw": "^7.0.0", - "rehype-stringify": "^10.0.1", - "remark-gfm": "^4.0.1", - "remark-parse": "^11.0.0", - "remark-rehype": "^11.1.2", - "remark-smartypants": "^3.0.2", - "shiki": "^3.13.0", - "smol-toml": "^1.4.2", - "unified": "^11.0.5", - "unist-util-remove-position": "^5.0.0", - "unist-util-visit": "^5.0.0", - "unist-util-visit-parents": "^6.0.2", - "vfile": "^6.0.3" - } - }, - "node_modules/@astrojs/mdx": { - "version": "4.3.12", - "resolved": "https://registry.npmjs.org/@astrojs/mdx/-/mdx-4.3.12.tgz", - "integrity": "sha512-pL3CVPtuQrPnDhWjy7zqbOibNyPaxP4VpQS8T8spwKqKzauJ4yoKyNkVTD8jrP7EAJHmBhZ7PTmUGZqOpKKp8g==", - "license": "MIT", - "dependencies": { - "@astrojs/markdown-remark": "6.3.9", - "@mdx-js/mdx": "^3.1.1", - "acorn": "^8.15.0", - "es-module-lexer": "^1.7.0", - "estree-util-visit": "^2.0.0", - "hast-util-to-html": "^9.0.5", - "piccolore": "^0.1.3", - "rehype-raw": "^7.0.0", - "remark-gfm": "^4.0.1", - "remark-smartypants": "^3.0.2", - "source-map": "^0.7.6", - "unist-util-visit": "^5.0.0", - "vfile": "^6.0.3" - }, - "engines": { - "node": "18.20.8 || ^20.3.0 || >=22.0.0" - }, - "peerDependencies": { - "astro": "^5.0.0" - } - }, - "node_modules/@astrojs/prism": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/@astrojs/prism/-/prism-3.3.0.tgz", - "integrity": "sha512-q8VwfU/fDZNoDOf+r7jUnMC2//H2l0TuQ6FkGJL8vD8nw/q5KiL3DS1KKBI3QhI9UQhpJ5dc7AtqfbXWuOgLCQ==", - "license": "MIT", - "dependencies": { - "prismjs": "^1.30.0" - }, - "engines": { - "node": "18.20.8 || ^20.3.0 || >=22.0.0" - } - }, - "node_modules/@astrojs/react": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/@astrojs/react/-/react-4.4.2.tgz", - "integrity": "sha512-1tl95bpGfuaDMDn8O3x/5Dxii1HPvzjvpL2YTuqOOrQehs60I2DKiDgh1jrKc7G8lv+LQT5H15V6QONQ+9waeQ==", - "license": "MIT", - "dependencies": { - "@vitejs/plugin-react": "^4.7.0", - "ultrahtml": "^1.6.0", - "vite": "^6.4.1" - }, - "engines": { - "node": "18.20.8 || ^20.3.0 || >=22.0.0" - }, - "peerDependencies": { - "@types/react": "^17.0.50 || ^18.0.21 || ^19.0.0", - "@types/react-dom": "^17.0.17 || ^18.0.6 || ^19.0.0", - "react": "^17.0.2 || ^18.0.0 || ^19.0.0", - "react-dom": "^17.0.2 || ^18.0.0 || ^19.0.0" - } - }, - "node_modules/@astrojs/rss": { - "version": "4.0.14", - "resolved": "https://registry.npmjs.org/@astrojs/rss/-/rss-4.0.14.tgz", - "integrity": "sha512-KCe1imDcADKOOuO/wtKOMDO/umsBD6DWF+94r5auna1jKl5fmlK9vzf+sjA3EyveXA/FoB3khtQ/u/tQgETmTw==", - "license": "MIT", - "dependencies": { - "fast-xml-parser": "^5.3.0", - "piccolore": "^0.1.3" - } - }, - "node_modules/@astrojs/sitemap": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/@astrojs/sitemap/-/sitemap-3.6.0.tgz", - "integrity": "sha512-4aHkvcOZBWJigRmMIAJwRQXBS+ayoP5z40OklTXYXhUDhwusz+DyDl+nSshY6y9DvkVEavwNcFO8FD81iGhXjg==", - "license": "MIT", - "dependencies": { - "sitemap": "^8.0.0", - "stream-replace-string": "^2.0.0", - "zod": "^3.25.76" - } - }, - "node_modules/@astrojs/starlight": { - "version": "0.36.2", - "resolved": "https://registry.npmjs.org/@astrojs/starlight/-/starlight-0.36.2.tgz", - "integrity": "sha512-QR8NfO7+7DR13kBikhQwAj3IAoptLLNs9DkyKko2M2l3PrqpcpVUnw1JBJ0msGDIwE6tBbua2UeBND48mkh03w==", - "license": "MIT", - "peer": true, - "dependencies": { - "@astrojs/markdown-remark": "^6.3.1", - "@astrojs/mdx": "^4.2.3", - "@astrojs/sitemap": "^3.3.0", - "@pagefind/default-ui": "^1.3.0", - "@types/hast": "^3.0.4", - "@types/js-yaml": "^4.0.9", - "@types/mdast": "^4.0.4", - "astro-expressive-code": "^0.41.1", - "bcp-47": "^2.1.0", - "hast-util-from-html": "^2.0.1", - "hast-util-select": "^6.0.2", - "hast-util-to-string": "^3.0.0", - "hastscript": "^9.0.0", - "i18next": "^23.11.5", - "js-yaml": "^4.1.0", - "klona": "^2.0.6", - "mdast-util-directive": "^3.0.0", - "mdast-util-to-markdown": "^2.1.0", - "mdast-util-to-string": "^4.0.0", - "pagefind": "^1.3.0", - "rehype": "^13.0.1", - "rehype-format": "^5.0.0", - "remark-directive": "^3.0.0", - "ultrahtml": "^1.6.0", - "unified": "^11.0.5", - "unist-util-visit": "^5.0.0", - "vfile": "^6.0.2" - }, - "peerDependencies": { - "astro": "^5.5.0" - } - }, - "node_modules/@astrojs/telemetry": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/@astrojs/telemetry/-/telemetry-3.3.0.tgz", - "integrity": "sha512-UFBgfeldP06qu6khs/yY+q1cDAaArM2/7AEIqQ9Cuvf7B1hNLq0xDrZkct+QoIGyjq56y8IaE2I3CTvG99mlhQ==", - "license": "MIT", - "dependencies": { - "ci-info": "^4.2.0", - "debug": "^4.4.0", - "dlv": "^1.1.3", - "dset": "^3.1.4", - "is-docker": "^3.0.0", - "is-wsl": "^3.1.0", - "which-pm-runs": "^1.1.0" - }, - "engines": { - "node": "18.20.8 || ^20.3.0 || >=22.0.0" - } - }, - "node_modules/@astrojs/yaml2ts": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/@astrojs/yaml2ts/-/yaml2ts-0.2.2.tgz", - "integrity": "sha512-GOfvSr5Nqy2z5XiwqTouBBpy5FyI6DEe+/g/Mk5am9SjILN1S5fOEvYK0GuWHg98yS/dobP4m8qyqw/URW35fQ==", - "license": "MIT", - "dependencies": { - "yaml": "^2.5.0" - } - }, - "node_modules/@babel/code-frame": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", - "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==", - "license": "MIT", - "dependencies": { - "@babel/helper-validator-identifier": "^7.27.1", - "js-tokens": "^4.0.0", - "picocolors": "^1.1.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/compat-data": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.28.5.tgz", - "integrity": "sha512-6uFXyCayocRbqhZOB+6XcuZbkMNimwfVGFji8CTZnCzOHVGvDqzvitu1re2AU5LROliz7eQPhB8CpAMvnx9EjA==", - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/core": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.5.tgz", - "integrity": "sha512-e7jT4DxYvIDLk1ZHmU/m/mB19rex9sv0c2ftBtjSBv+kVM/902eh0fINUzD7UwLLNR+jU585GxUJ8/EBfAM5fw==", - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/code-frame": "^7.27.1", - "@babel/generator": "^7.28.5", - "@babel/helper-compilation-targets": "^7.27.2", - "@babel/helper-module-transforms": "^7.28.3", - "@babel/helpers": "^7.28.4", - "@babel/parser": "^7.28.5", - "@babel/template": "^7.27.2", - "@babel/traverse": "^7.28.5", - "@babel/types": "^7.28.5", - "@jridgewell/remapping": "^2.3.5", - "convert-source-map": "^2.0.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.2", - "json5": "^2.2.3", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/babel" - } - }, - "node_modules/@babel/generator": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.5.tgz", - "integrity": "sha512-3EwLFhZ38J4VyIP6WNtt2kUdW9dokXA9Cr4IVIFHuCpZ3H8/YFOl5JjZHisrn1fATPBmKKqXzDFvh9fUwHz6CQ==", - "license": "MIT", - "dependencies": { - "@babel/parser": "^7.28.5", - "@babel/types": "^7.28.5", - "@jridgewell/gen-mapping": "^0.3.12", - "@jridgewell/trace-mapping": "^0.3.28", - "jsesc": "^3.0.2" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-compilation-targets": { - "version": "7.27.2", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.2.tgz", - "integrity": "sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==", - "license": "MIT", - "dependencies": { - "@babel/compat-data": "^7.27.2", - "@babel/helper-validator-option": "^7.27.1", - "browserslist": "^4.24.0", - "lru-cache": "^5.1.1", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-globals": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz", - "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==", - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-module-imports": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz", - "integrity": "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==", - "license": "MIT", - "dependencies": { - "@babel/traverse": "^7.27.1", - "@babel/types": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-module-transforms": { - "version": "7.28.3", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.3.tgz", - "integrity": "sha512-gytXUbs8k2sXS9PnQptz5o0QnpLL51SwASIORY6XaBKF88nsOT0Zw9szLqlSGQDP/4TljBAD5y98p2U1fqkdsw==", - "license": "MIT", - "dependencies": { - "@babel/helper-module-imports": "^7.27.1", - "@babel/helper-validator-identifier": "^7.27.1", - "@babel/traverse": "^7.28.3" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/helper-plugin-utils": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.27.1.tgz", - "integrity": "sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw==", - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-string-parser": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", - "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-identifier": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", - "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-option": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz", - "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==", - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helpers": { - "version": "7.28.4", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.4.tgz", - "integrity": "sha512-HFN59MmQXGHVyYadKLVumYsA9dBFun/ldYxipEjzA4196jpLZd8UjEEBLkbEkvfYreDqJhZxYAWFPtrfhNpj4w==", - "license": "MIT", - "dependencies": { - "@babel/template": "^7.27.2", - "@babel/types": "^7.28.4" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/parser": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.5.tgz", - "integrity": "sha512-KKBU1VGYR7ORr3At5HAtUQ+TV3SzRCXmA/8OdDZiLDBIZxVyzXuztPjfLd3BV1PRAQGCMWWSHYhL0F8d5uHBDQ==", - "license": "MIT", - "dependencies": { - "@babel/types": "^7.28.5" - }, - "bin": { - "parser": "bin/babel-parser.js" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@babel/plugin-transform-react-jsx-self": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.27.1.tgz", - "integrity": "sha512-6UzkCs+ejGdZ5mFFC/OCUrv028ab2fp1znZmCZjAOBKiBK2jXD1O+BPSfX8X2qjJ75fZBMSnQn3Rq2mrBJK2mw==", - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-react-jsx-source": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.27.1.tgz", - "integrity": "sha512-zbwoTsBruTeKB9hSq73ha66iFeJHuaFkUbwvqElnygoNbj/jHRsSeokowZFN3CZ64IvEqcmmkVe89OPXc7ldAw==", - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/runtime": { - "version": "7.28.4", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.4.tgz", - "integrity": "sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ==", - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/template": { - "version": "7.27.2", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz", - "integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==", - "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.27.1", - "@babel/parser": "^7.27.2", - "@babel/types": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/traverse": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.5.tgz", - "integrity": "sha512-TCCj4t55U90khlYkVV/0TfkJkAkUg3jZFA3Neb7unZT8CPok7iiRfaX0F+WnqWqt7OxhOn0uBKXCw4lbL8W0aQ==", - "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.27.1", - "@babel/generator": "^7.28.5", - "@babel/helper-globals": "^7.28.0", - "@babel/parser": "^7.28.5", - "@babel/template": "^7.27.2", - "@babel/types": "^7.28.5", - "debug": "^4.3.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/types": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.5.tgz", - "integrity": "sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA==", - "license": "MIT", - "dependencies": { - "@babel/helper-string-parser": "^7.27.1", - "@babel/helper-validator-identifier": "^7.28.5" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@capsizecss/unpack": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@capsizecss/unpack/-/unpack-3.0.1.tgz", - "integrity": "sha512-8XqW8xGn++Eqqbz3e9wKuK7mxryeRjs4LOHLxbh2lwKeSbuNR4NFifDZT4KzvjU6HMOPbiNTsWpniK5EJfTWkg==", - "license": "MIT", - "dependencies": { - "fontkit": "^2.0.2" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/@ctrl/tinycolor": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/@ctrl/tinycolor/-/tinycolor-4.2.0.tgz", - "integrity": "sha512-kzyuwOAQnXJNLS9PSyrk0CWk35nWJW/zl/6KvnTBMFK65gm7U1/Z5BqjxeapjZCIhQcM/DsrEmcbRwDyXyXK4A==", - "license": "MIT", - "engines": { - "node": ">=14" - } - }, - "node_modules/@emmetio/abbreviation": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/@emmetio/abbreviation/-/abbreviation-2.3.3.tgz", - "integrity": "sha512-mgv58UrU3rh4YgbE/TzgLQwJ3pFsHHhCLqY20aJq+9comytTXUDNGG/SMtSeMJdkpxgXSXunBGLD8Boka3JyVA==", - "license": "MIT", - "dependencies": { - "@emmetio/scanner": "^1.0.4" - } - }, - "node_modules/@emmetio/css-abbreviation": { - "version": "2.1.8", - "resolved": "https://registry.npmjs.org/@emmetio/css-abbreviation/-/css-abbreviation-2.1.8.tgz", - "integrity": "sha512-s9yjhJ6saOO/uk1V74eifykk2CBYi01STTK3WlXWGOepyKa23ymJ053+DNQjpFcy1ingpaO7AxCcwLvHFY9tuw==", - "license": "MIT", - "dependencies": { - "@emmetio/scanner": "^1.0.4" - } - }, - "node_modules/@emmetio/css-parser": { - "version": "0.4.0", - "resolved": "git+ssh://git@github.com/ramya-rao-a/css-parser.git#370c480ac103bd17c7bcfb34bf5d577dc40d3660", - "license": "MIT", - "dependencies": { - "@emmetio/stream-reader": "^2.2.0", - "@emmetio/stream-reader-utils": "^0.1.0" - } - }, - "node_modules/@emmetio/html-matcher": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@emmetio/html-matcher/-/html-matcher-1.3.0.tgz", - "integrity": "sha512-NTbsvppE5eVyBMuyGfVu2CRrLvo7J4YHb6t9sBFLyY03WYhXET37qA4zOYUjBWFCRHO7pS1B9khERtY0f5JXPQ==", - "license": "ISC", - "dependencies": { - "@emmetio/scanner": "^1.0.0" - } - }, - "node_modules/@emmetio/scanner": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@emmetio/scanner/-/scanner-1.0.4.tgz", - "integrity": "sha512-IqRuJtQff7YHHBk4G8YZ45uB9BaAGcwQeVzgj/zj8/UdOhtQpEIupUhSk8dys6spFIWVZVeK20CzGEnqR5SbqA==", - "license": "MIT" - }, - "node_modules/@emmetio/stream-reader": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@emmetio/stream-reader/-/stream-reader-2.2.0.tgz", - "integrity": "sha512-fXVXEyFA5Yv3M3n8sUGT7+fvecGrZP4k6FnWWMSZVQf69kAq0LLpaBQLGcPR30m3zMmKYhECP4k/ZkzvhEW5kw==", - "license": "MIT" - }, - "node_modules/@emmetio/stream-reader-utils": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/@emmetio/stream-reader-utils/-/stream-reader-utils-0.1.0.tgz", - "integrity": "sha512-ZsZ2I9Vzso3Ho/pjZFsmmZ++FWeEd/txqybHTm4OgaZzdS8V9V/YYWQwg5TC38Z7uLWUV1vavpLLbjJtKubR1A==", - "license": "MIT" - }, - "node_modules/@emnapi/runtime": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.7.1.tgz", - "integrity": "sha512-PVtJr5CmLwYAU9PZDMITZoR5iAOShYREoR45EyyLrbntV50mdePTgUn4AmOw90Ifcj+x2kRjdzr1HP3RrNiHGA==", - "license": "MIT", - "optional": true, - "dependencies": { - "tslib": "^2.4.0" - } - }, - "node_modules/@esbuild/aix-ppc64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.12.tgz", - "integrity": "sha512-Hhmwd6CInZ3dwpuGTF8fJG6yoWmsToE+vYgD4nytZVxcu1ulHpUQRAB1UJ8+N1Am3Mz4+xOByoQoSZf4D+CpkA==", - "cpu": [ - "ppc64" - ], - "license": "MIT", - "optional": true, - "os": [ - "aix" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-arm": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.12.tgz", - "integrity": "sha512-VJ+sKvNA/GE7Ccacc9Cha7bpS8nyzVv0jdVgwNDaR4gDMC/2TTRc33Ip8qrNYUcpkOHUT5OZ0bUcNNVZQ9RLlg==", - "cpu": [ - "arm" - ], - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.12.tgz", - "integrity": "sha512-6AAmLG7zwD1Z159jCKPvAxZd4y/VTO0VkprYy+3N2FtJ8+BQWFXU+OxARIwA46c5tdD9SsKGZ/1ocqBS/gAKHg==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.12.tgz", - "integrity": "sha512-5jbb+2hhDHx5phYR2By8GTWEzn6I9UqR11Kwf22iKbNpYrsmRB18aX/9ivc5cabcUiAT/wM+YIZ6SG9QO6a8kg==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/darwin-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.12.tgz", - "integrity": "sha512-N3zl+lxHCifgIlcMUP5016ESkeQjLj/959RxxNYIthIg+CQHInujFuXeWbWMgnTo4cp5XVHqFPmpyu9J65C1Yg==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/darwin-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.12.tgz", - "integrity": "sha512-HQ9ka4Kx21qHXwtlTUVbKJOAnmG1ipXhdWTmNXiPzPfWKpXqASVcWdnf2bnL73wgjNrFXAa3yYvBSd9pzfEIpA==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/freebsd-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.12.tgz", - "integrity": "sha512-gA0Bx759+7Jve03K1S0vkOu5Lg/85dou3EseOGUes8flVOGxbhDDh/iZaoek11Y8mtyKPGF3vP8XhnkDEAmzeg==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/freebsd-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.12.tgz", - "integrity": "sha512-TGbO26Yw2xsHzxtbVFGEXBFH0FRAP7gtcPE7P5yP7wGy7cXK2oO7RyOhL5NLiqTlBh47XhmIUXuGciXEqYFfBQ==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-arm": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.12.tgz", - "integrity": "sha512-lPDGyC1JPDou8kGcywY0YILzWlhhnRjdof3UlcoqYmS9El818LLfJJc3PXXgZHrHCAKs/Z2SeZtDJr5MrkxtOw==", - "cpu": [ - "arm" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.12.tgz", - "integrity": "sha512-8bwX7a8FghIgrupcxb4aUmYDLp8pX06rGh5HqDT7bB+8Rdells6mHvrFHHW2JAOPZUbnjUpKTLg6ECyzvas2AQ==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-ia32": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.12.tgz", - "integrity": "sha512-0y9KrdVnbMM2/vG8KfU0byhUN+EFCny9+8g202gYqSSVMonbsCfLjUO+rCci7pM0WBEtz+oK/PIwHkzxkyharA==", - "cpu": [ - "ia32" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-loong64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.12.tgz", - "integrity": "sha512-h///Lr5a9rib/v1GGqXVGzjL4TMvVTv+s1DPoxQdz7l/AYv6LDSxdIwzxkrPW438oUXiDtwM10o9PmwS/6Z0Ng==", - "cpu": [ - "loong64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-mips64el": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.12.tgz", - "integrity": "sha512-iyRrM1Pzy9GFMDLsXn1iHUm18nhKnNMWscjmp4+hpafcZjrr2WbT//d20xaGljXDBYHqRcl8HnxbX6uaA/eGVw==", - "cpu": [ - "mips64el" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-ppc64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.12.tgz", - "integrity": "sha512-9meM/lRXxMi5PSUqEXRCtVjEZBGwB7P/D4yT8UG/mwIdze2aV4Vo6U5gD3+RsoHXKkHCfSxZKzmDssVlRj1QQA==", - "cpu": [ - "ppc64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-riscv64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.12.tgz", - "integrity": "sha512-Zr7KR4hgKUpWAwb1f3o5ygT04MzqVrGEGXGLnj15YQDJErYu/BGg+wmFlIDOdJp0PmB0lLvxFIOXZgFRrdjR0w==", - "cpu": [ - "riscv64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-s390x": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.12.tgz", - "integrity": "sha512-MsKncOcgTNvdtiISc/jZs/Zf8d0cl/t3gYWX8J9ubBnVOwlk65UIEEvgBORTiljloIWnBzLs4qhzPkJcitIzIg==", - "cpu": [ - "s390x" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.12.tgz", - "integrity": "sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/netbsd-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.12.tgz", - "integrity": "sha512-xXwcTq4GhRM7J9A8Gv5boanHhRa/Q9KLVmcyXHCTaM4wKfIpWkdXiMog/KsnxzJ0A1+nD+zoecuzqPmCRyBGjg==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/netbsd-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.12.tgz", - "integrity": "sha512-Ld5pTlzPy3YwGec4OuHh1aCVCRvOXdH8DgRjfDy/oumVovmuSzWfnSJg+VtakB9Cm0gxNO9BzWkj6mtO1FMXkQ==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openbsd-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.12.tgz", - "integrity": "sha512-fF96T6KsBo/pkQI950FARU9apGNTSlZGsv1jZBAlcLL1MLjLNIWPBkj5NlSz8aAzYKg+eNqknrUJ24QBybeR5A==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openbsd-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.12.tgz", - "integrity": "sha512-MZyXUkZHjQxUvzK7rN8DJ3SRmrVrke8ZyRusHlP+kuwqTcfWLyqMOE3sScPPyeIXN/mDJIfGXvcMqCgYKekoQw==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openharmony-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.12.tgz", - "integrity": "sha512-rm0YWsqUSRrjncSXGA7Zv78Nbnw4XL6/dzr20cyrQf7ZmRcsovpcRBdhD43Nuk3y7XIoW2OxMVvwuRvk9XdASg==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "openharmony" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/sunos-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.12.tgz", - "integrity": "sha512-3wGSCDyuTHQUzt0nV7bocDy72r2lI33QL3gkDNGkod22EsYl04sMf0qLb8luNKTOmgF/eDEDP5BFNwoBKH441w==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-arm64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.12.tgz", - "integrity": "sha512-rMmLrur64A7+DKlnSuwqUdRKyd3UE7oPJZmnljqEptesKM8wx9J8gx5u0+9Pq0fQQW8vqeKebwNXdfOyP+8Bsg==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-ia32": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.12.tgz", - "integrity": "sha512-HkqnmmBoCbCwxUKKNPBixiWDGCpQGVsrQfJoVGYLPT41XWF8lHuE5N6WhVia2n4o5QK5M4tYr21827fNhi4byQ==", - "cpu": [ - "ia32" - ], - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-x64": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.12.tgz", - "integrity": "sha512-alJC0uCZpTFrSL0CCDjcgleBXPnCrEAhTBILpeAp7M/OFgoqtAetfBzX0xM00MUsVVPpVjlPuMbREqnZCXaTnA==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@expressive-code/core": { - "version": "0.41.3", - "resolved": "https://registry.npmjs.org/@expressive-code/core/-/core-0.41.3.tgz", - "integrity": "sha512-9qzohqU7O0+JwMEEgQhnBPOw5DtsQRBXhW++5fvEywsuX44vCGGof1SL5OvPElvNgaWZ4pFZAFSlkNOkGyLwSQ==", - "license": "MIT", - "dependencies": { - "@ctrl/tinycolor": "^4.0.4", - "hast-util-select": "^6.0.2", - "hast-util-to-html": "^9.0.1", - "hast-util-to-text": "^4.0.1", - "hastscript": "^9.0.0", - "postcss": "^8.4.38", - "postcss-nested": "^6.0.1", - "unist-util-visit": "^5.0.0", - "unist-util-visit-parents": "^6.0.1" - } - }, - "node_modules/@expressive-code/plugin-frames": { - "version": "0.41.3", - "resolved": "https://registry.npmjs.org/@expressive-code/plugin-frames/-/plugin-frames-0.41.3.tgz", - "integrity": "sha512-rFQtmf/3N2CK3Cq/uERweMTYZnBu+CwxBdHuOftEmfA9iBE7gTVvwpbh82P9ZxkPLvc40UMhYt7uNuAZexycRQ==", - "license": "MIT", - "dependencies": { - "@expressive-code/core": "^0.41.3" - } - }, - "node_modules/@expressive-code/plugin-shiki": { - "version": "0.41.3", - "resolved": "https://registry.npmjs.org/@expressive-code/plugin-shiki/-/plugin-shiki-0.41.3.tgz", - "integrity": "sha512-RlTARoopzhFJIOVHLGvuXJ8DCEme/hjV+ZnRJBIxzxsKVpGPW4Oshqg9xGhWTYdHstTsxO663s0cdBLzZj9TQA==", - "license": "MIT", - "dependencies": { - "@expressive-code/core": "^0.41.3", - "shiki": "^3.2.2" - } - }, - "node_modules/@expressive-code/plugin-text-markers": { - "version": "0.41.3", - "resolved": "https://registry.npmjs.org/@expressive-code/plugin-text-markers/-/plugin-text-markers-0.41.3.tgz", - "integrity": "sha512-SN8tkIzDpA0HLAscEYD2IVrfLiid6qEdE9QLlGVSxO1KEw7qYvjpbNBQjUjMr5/jvTJ7ys6zysU2vLPHE0sb2g==", - "license": "MIT", - "dependencies": { - "@expressive-code/core": "^0.41.3" - } - }, - "node_modules/@img/colour": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/@img/colour/-/colour-1.0.0.tgz", - "integrity": "sha512-A5P/LfWGFSl6nsckYtjw9da+19jB8hkJ6ACTGcDfEJ0aE+l2n2El7dsVM7UVHZQ9s2lmYMWlrS21YLy2IR1LUw==", - "license": "MIT", - "optional": true, - "engines": { - "node": ">=18" - } - }, - "node_modules/@img/sharp-darwin-arm64": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.33.5.tgz", - "integrity": "sha512-UT4p+iz/2H4twwAoLCqfA9UH5pI6DggwKEGuaPy7nCVQ8ZsiY5PIcrRvD1DzuY3qYL07NtIQcWnBSY/heikIFQ==", - "cpu": [ - "arm64" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-darwin-arm64": "1.0.4" - } - }, - "node_modules/@img/sharp-darwin-x64": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.33.5.tgz", - "integrity": "sha512-fyHac4jIc1ANYGRDxtiqelIbdWkIuQaI84Mv45KvGRRxSAa7o7d1ZKAOBaYbnepLC1WqxfpimdeWfvqqSGwR2Q==", - "cpu": [ - "x64" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-darwin-x64": "1.0.4" - } - }, - "node_modules/@img/sharp-libvips-darwin-arm64": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.0.4.tgz", - "integrity": "sha512-XblONe153h0O2zuFfTAbQYAX2JhYmDHeWikp1LM9Hul9gVPjFY427k6dFEcOL72O01QxQsWi761svJ/ev9xEDg==", - "cpu": [ - "arm64" - ], - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "darwin" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-libvips-darwin-x64": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.0.4.tgz", - "integrity": "sha512-xnGR8YuZYfJGmWPvmlunFaWJsb9T/AO2ykoP3Fz/0X5XV2aoYBPkX6xqCQvUTKKiLddarLaxpzNe+b1hjeWHAQ==", - "cpu": [ - "x64" - ], - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "darwin" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-libvips-linux-arm": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.0.5.tgz", - "integrity": "sha512-gvcC4ACAOPRNATg/ov8/MnbxFDJqf/pDePbBnuBDcjsI8PssmjoKMAz4LtLaVi+OnSb5FK/yIOamqDwGmXW32g==", - "cpu": [ - "arm" - ], - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "linux" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-libvips-linux-arm64": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.0.4.tgz", - "integrity": "sha512-9B+taZ8DlyyqzZQnoeIvDVR/2F4EbMepXMc/NdVbkzsJbzkUjhXv/70GQJ7tdLA4YJgNP25zukcxpX2/SueNrA==", - "cpu": [ - "arm64" - ], - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "linux" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-libvips-linux-ppc64": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-ppc64/-/sharp-libvips-linux-ppc64-1.2.4.tgz", - "integrity": "sha512-FMuvGijLDYG6lW+b/UvyilUWu5Ayu+3r2d1S8notiGCIyYU/76eig1UfMmkZ7vwgOrzKzlQbFSuQfgm7GYUPpA==", - "cpu": [ - "ppc64" - ], - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "linux" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-libvips-linux-riscv64": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-riscv64/-/sharp-libvips-linux-riscv64-1.2.4.tgz", - "integrity": "sha512-oVDbcR4zUC0ce82teubSm+x6ETixtKZBh/qbREIOcI3cULzDyb18Sr/Wcyx7NRQeQzOiHTNbZFF1UwPS2scyGA==", - "cpu": [ - "riscv64" - ], - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "linux" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-libvips-linux-s390x": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.0.4.tgz", - "integrity": "sha512-u7Wz6ntiSSgGSGcjZ55im6uvTrOxSIS8/dgoVMoiGE9I6JAfU50yH5BoDlYA1tcuGS7g/QNtetJnxA6QEsCVTA==", - "cpu": [ - "s390x" - ], - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "linux" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-libvips-linux-x64": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.0.4.tgz", - "integrity": "sha512-MmWmQ3iPFZr0Iev+BAgVMb3ZyC4KeFc3jFxnNbEPas60e1cIfevbtuyf9nDGIzOaW9PdnDciJm+wFFaTlj5xYw==", - "cpu": [ - "x64" - ], - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "linux" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-libvips-linuxmusl-arm64": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.0.4.tgz", - "integrity": "sha512-9Ti+BbTYDcsbp4wfYib8Ctm1ilkugkA/uscUn6UXK1ldpC1JjiXbLfFZtRlBhjPZ5o1NCLiDbg8fhUPKStHoTA==", - "cpu": [ - "arm64" - ], - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "linux" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-libvips-linuxmusl-x64": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.0.4.tgz", - "integrity": "sha512-viYN1KX9m+/hGkJtvYYp+CCLgnJXwiQB39damAO7WMdKWlIhmYTfHjwSbQeUK/20vY154mwezd9HflVFM1wVSw==", - "cpu": [ - "x64" - ], - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "linux" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-linux-arm": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.33.5.tgz", - "integrity": "sha512-JTS1eldqZbJxjvKaAkxhZmBqPRGmxgu+qFKSInv8moZ2AmT5Yib3EQ1c6gp493HvrvV8QgdOXdyaIBrhvFhBMQ==", - "cpu": [ - "arm" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linux-arm": "1.0.5" - } - }, - "node_modules/@img/sharp-linux-arm64": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.33.5.tgz", - "integrity": "sha512-JMVv+AMRyGOHtO1RFBiJy/MBsgz0x4AWrT6QoEVVTyh1E39TrCUpTRI7mx9VksGX4awWASxqCYLCV4wBZHAYxA==", - "cpu": [ - "arm64" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linux-arm64": "1.0.4" - } - }, - "node_modules/@img/sharp-linux-ppc64": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-ppc64/-/sharp-linux-ppc64-0.34.5.tgz", - "integrity": "sha512-7zznwNaqW6YtsfrGGDA6BRkISKAAE1Jo0QdpNYXNMHu2+0dTrPflTLNkpc8l7MUP5M16ZJcUvysVWWrMefZquA==", - "cpu": [ - "ppc64" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linux-ppc64": "1.2.4" - } - }, - "node_modules/@img/sharp-linux-riscv64": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-riscv64/-/sharp-linux-riscv64-0.34.5.tgz", - "integrity": "sha512-51gJuLPTKa7piYPaVs8GmByo7/U7/7TZOq+cnXJIHZKavIRHAP77e3N2HEl3dgiqdD/w0yUfiJnII77PuDDFdw==", - "cpu": [ - "riscv64" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linux-riscv64": "1.2.4" - } - }, - "node_modules/@img/sharp-linux-s390x": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.33.5.tgz", - "integrity": "sha512-y/5PCd+mP4CA/sPDKl2961b+C9d+vPAveS33s6Z3zfASk2j5upL6fXVPZi7ztePZ5CuH+1kW8JtvxgbuXHRa4Q==", - "cpu": [ - "s390x" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linux-s390x": "1.0.4" - } - }, - "node_modules/@img/sharp-linux-x64": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.33.5.tgz", - "integrity": "sha512-opC+Ok5pRNAzuvq1AG0ar+1owsu842/Ab+4qvU879ippJBHvyY5n2mxF1izXqkPYlGuP/M556uh53jRLJmzTWA==", - "cpu": [ - "x64" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linux-x64": "1.0.4" - } - }, - "node_modules/@img/sharp-linuxmusl-arm64": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.33.5.tgz", - "integrity": "sha512-XrHMZwGQGvJg2V/oRSUfSAfjfPxO+4DkiRh6p2AFjLQztWUuY/o8Mq0eMQVIY7HJ1CDQUJlxGGZRw1a5bqmd1g==", - "cpu": [ - "arm64" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linuxmusl-arm64": "1.0.4" - } - }, - "node_modules/@img/sharp-linuxmusl-x64": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.33.5.tgz", - "integrity": "sha512-WT+d/cgqKkkKySYmqoZ8y3pxx7lx9vVejxW/W4DOFMYVSkErR+w7mf2u8m/y4+xHe7yY9DAXQMWQhpnMuFfScw==", - "cpu": [ - "x64" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linuxmusl-x64": "1.0.4" - } - }, - "node_modules/@img/sharp-wasm32": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.33.5.tgz", - "integrity": "sha512-ykUW4LVGaMcU9lu9thv85CbRMAwfeadCJHRsg2GmeRa/cJxsVY9Rbd57JcMxBkKHag5U/x7TSBpScF4U8ElVzg==", - "cpu": [ - "wasm32" - ], - "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT", - "optional": true, - "dependencies": { - "@emnapi/runtime": "^1.2.0" - }, - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-win32-arm64": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-win32-arm64/-/sharp-win32-arm64-0.34.5.tgz", - "integrity": "sha512-WQ3AgWCWYSb2yt+IG8mnC6Jdk9Whs7O0gxphblsLvdhSpSTtmu69ZG1Gkb6NuvxsNACwiPV6cNSZNzt0KPsw7g==", - "cpu": [ - "arm64" - ], - "license": "Apache-2.0 AND LGPL-3.0-or-later", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-win32-ia32": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.33.5.tgz", - "integrity": "sha512-T36PblLaTwuVJ/zw/LaH0PdZkRz5rd3SmMHX8GSmR7vtNSP5Z6bQkExdSK7xGWyxLw4sUknBuugTelgw2faBbQ==", - "cpu": [ - "ia32" - ], - "license": "Apache-2.0 AND LGPL-3.0-or-later", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@img/sharp-win32-x64": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.33.5.tgz", - "integrity": "sha512-MpY/o8/8kj+EcnxwvrP4aTJSWw/aZ7JIGR4aBeZkZw5B7/Jn+tY9/VNwtcoGmdT7GfggGIU4kygOMSbYnOrAbg==", - "cpu": [ - "x64" - ], - "license": "Apache-2.0 AND LGPL-3.0-or-later", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.13", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", - "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", - "license": "MIT", - "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.0", - "@jridgewell/trace-mapping": "^0.3.24" - } - }, - "node_modules/@jridgewell/remapping": { - "version": "2.3.5", - "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", - "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", - "license": "MIT", - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.24" - } - }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", - "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", - "license": "MIT", - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", - "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", - "license": "MIT" - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.31", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", - "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", - "license": "MIT", - "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" - } - }, - "node_modules/@mdx-js/mdx": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@mdx-js/mdx/-/mdx-3.1.1.tgz", - "integrity": "sha512-f6ZO2ifpwAQIpzGWaBQT2TXxPv6z3RBzQKpVftEWN78Vl/YweF1uwussDx8ECAXVtr3Rs89fKyG9YlzUs9DyGQ==", - "license": "MIT", - "dependencies": { - "@types/estree": "^1.0.0", - "@types/estree-jsx": "^1.0.0", - "@types/hast": "^3.0.0", - "@types/mdx": "^2.0.0", - "acorn": "^8.0.0", - "collapse-white-space": "^2.0.0", - "devlop": "^1.0.0", - "estree-util-is-identifier-name": "^3.0.0", - "estree-util-scope": "^1.0.0", - "estree-walker": "^3.0.0", - "hast-util-to-jsx-runtime": "^2.0.0", - "markdown-extensions": "^2.0.0", - "recma-build-jsx": "^1.0.0", - "recma-jsx": "^1.0.0", - "recma-stringify": "^1.0.0", - "rehype-recma": "^1.0.0", - "remark-mdx": "^3.0.0", - "remark-parse": "^11.0.0", - "remark-rehype": "^11.0.0", - "source-map": "^0.7.0", - "unified": "^11.0.0", - "unist-util-position-from-estree": "^2.0.0", - "unist-util-stringify-position": "^4.0.0", - "unist-util-visit": "^5.0.0", - "vfile": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "license": "MIT", - "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "license": "MIT", - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "license": "MIT", - "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@oslojs/encoding": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@oslojs/encoding/-/encoding-1.1.0.tgz", - "integrity": "sha512-70wQhgYmndg4GCPxPPxPGevRKqTIJ2Nh4OkiMWmDAVYsTQ+Ta7Sq+rPevXyXGdzr30/qZBnyOalCszoMxlyldQ==", - "license": "MIT" - }, - "node_modules/@pagefind/darwin-arm64": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@pagefind/darwin-arm64/-/darwin-arm64-1.4.0.tgz", - "integrity": "sha512-2vMqkbv3lbx1Awea90gTaBsvpzgRs7MuSgKDxW0m9oV1GPZCZbZBJg/qL83GIUEN2BFlY46dtUZi54pwH+/pTQ==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@pagefind/darwin-x64": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@pagefind/darwin-x64/-/darwin-x64-1.4.0.tgz", - "integrity": "sha512-e7JPIS6L9/cJfow+/IAqknsGqEPjJnVXGjpGm25bnq+NPdoD3c/7fAwr1OXkG4Ocjx6ZGSCijXEV4ryMcH2E3A==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@pagefind/default-ui": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@pagefind/default-ui/-/default-ui-1.4.0.tgz", - "integrity": "sha512-wie82VWn3cnGEdIjh4YwNESyS1G6vRHwL6cNjy9CFgNnWW/PGRjsLq300xjVH5sfPFK3iK36UxvIBymtQIEiSQ==", - "license": "MIT" - }, - "node_modules/@pagefind/freebsd-x64": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@pagefind/freebsd-x64/-/freebsd-x64-1.4.0.tgz", - "integrity": "sha512-WcJVypXSZ+9HpiqZjFXMUobfFfZZ6NzIYtkhQ9eOhZrQpeY5uQFqNWLCk7w9RkMUwBv1HAMDW3YJQl/8OqsV0Q==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ] - }, - "node_modules/@pagefind/linux-arm64": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@pagefind/linux-arm64/-/linux-arm64-1.4.0.tgz", - "integrity": "sha512-PIt8dkqt4W06KGmQjONw7EZbhDF+uXI7i0XtRLN1vjCUxM9vGPdtJc2mUyVPevjomrGz5M86M8bqTr6cgDp1Uw==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@pagefind/linux-x64": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@pagefind/linux-x64/-/linux-x64-1.4.0.tgz", - "integrity": "sha512-z4oddcWwQ0UHrTHR8psLnVlz6USGJ/eOlDPTDYZ4cI8TK8PgwRUPQZp9D2iJPNIPcS6Qx/E4TebjuGJOyK8Mmg==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@pagefind/windows-x64": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/@pagefind/windows-x64/-/windows-x64-1.4.0.tgz", - "integrity": "sha512-NkT+YAdgS2FPCn8mIA9bQhiBs+xmniMGq1LFPDhcFn0+2yIUEiIG06t7bsZlhdjknEQRTSdT7YitP6fC5qwP0g==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rolldown/pluginutils": { - "version": "1.0.0-beta.27", - "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.27.tgz", - "integrity": "sha512-+d0F4MKMCbeVUJwG96uQ4SgAznZNSq93I3V+9NHA4OpvqG8mRCpGdKmK8l/dl02h2CCDHwW2FqilnTyDcAnqjA==", - "license": "MIT" - }, - "node_modules/@rollup/pluginutils": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.3.0.tgz", - "integrity": "sha512-5EdhGZtnu3V88ces7s53hhfK5KSASnJZv8Lulpc04cWO3REESroJXg73DFsOmgbU2BhwV0E20bu2IDZb3VKW4Q==", - "license": "MIT", - "dependencies": { - "@types/estree": "^1.0.0", - "estree-walker": "^2.0.2", - "picomatch": "^4.0.2" - }, - "engines": { - "node": ">=14.0.0" - }, - "peerDependencies": { - "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" - }, - "peerDependenciesMeta": { - "rollup": { - "optional": true - } - } - }, - "node_modules/@rollup/pluginutils/node_modules/estree-walker": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", - "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", - "license": "MIT" - }, - "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.53.3.tgz", - "integrity": "sha512-mRSi+4cBjrRLoaal2PnqH82Wqyb+d3HsPUN/W+WslCXsZsyHa9ZeQQX/pQsZaVIWDkPcpV6jJ+3KLbTbgnwv8w==", - "cpu": [ - "arm" - ], - "license": "MIT", - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/@rollup/rollup-android-arm64": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.53.3.tgz", - "integrity": "sha512-CbDGaMpdE9sh7sCmTrTUyllhrg65t6SwhjlMJsLr+J8YjFuPmCEjbBSx4Z/e4SmDyH3aB5hGaJUP2ltV/vcs4w==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.53.3.tgz", - "integrity": "sha512-Nr7SlQeqIBpOV6BHHGZgYBuSdanCXuw09hon14MGOLGmXAFYjx1wNvquVPmpZnl0tLjg25dEdr4IQ6GgyToCUA==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.53.3.tgz", - "integrity": "sha512-DZ8N4CSNfl965CmPktJ8oBnfYr3F8dTTNBQkRlffnUarJ2ohudQD17sZBa097J8xhQ26AwhHJ5mvUyQW8ddTsQ==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.53.3.tgz", - "integrity": "sha512-yMTrCrK92aGyi7GuDNtGn2sNW+Gdb4vErx4t3Gv/Tr+1zRb8ax4z8GWVRfr3Jw8zJWvpGHNpss3vVlbF58DZ4w==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ] - }, - "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.53.3.tgz", - "integrity": "sha512-lMfF8X7QhdQzseM6XaX0vbno2m3hlyZFhwcndRMw8fbAGUGL3WFMBdK0hbUBIUYcEcMhVLr1SIamDeuLBnXS+Q==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ] - }, - "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.53.3.tgz", - "integrity": "sha512-k9oD15soC/Ln6d2Wv/JOFPzZXIAIFLp6B+i14KhxAfnq76ajt0EhYc5YPeX6W1xJkAdItcVT+JhKl1QZh44/qw==", - "cpu": [ - "arm" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.53.3.tgz", - "integrity": "sha512-vTNlKq+N6CK/8UktsrFuc+/7NlEYVxgaEgRXVUVK258Z5ymho29skzW1sutgYjqNnquGwVUObAaxae8rZ6YMhg==", - "cpu": [ - "arm" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.53.3.tgz", - "integrity": "sha512-RGrFLWgMhSxRs/EWJMIFM1O5Mzuz3Xy3/mnxJp/5cVhZ2XoCAxJnmNsEyeMJtpK+wu0FJFWz+QF4mjCA7AUQ3w==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.53.3.tgz", - "integrity": "sha512-kASyvfBEWYPEwe0Qv4nfu6pNkITLTb32p4yTgzFCocHnJLAHs+9LjUu9ONIhvfT/5lv4YS5muBHyuV84epBo/A==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-loong64-gnu": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.53.3.tgz", - "integrity": "sha512-JiuKcp2teLJwQ7vkJ95EwESWkNRFJD7TQgYmCnrPtlu50b4XvT5MOmurWNrCj3IFdyjBQ5p9vnrX4JM6I8OE7g==", - "cpu": [ - "loong64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-ppc64-gnu": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.53.3.tgz", - "integrity": "sha512-EoGSa8nd6d3T7zLuqdojxC20oBfNT8nexBbB/rkxgKj5T5vhpAQKKnD+h3UkoMuTyXkP5jTjK/ccNRmQrPNDuw==", - "cpu": [ - "ppc64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.53.3.tgz", - "integrity": "sha512-4s+Wped2IHXHPnAEbIB0YWBv7SDohqxobiiPA1FIWZpX+w9o2i4LezzH/NkFUl8LRci/8udci6cLq+jJQlh+0g==", - "cpu": [ - "riscv64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-riscv64-musl": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.53.3.tgz", - "integrity": "sha512-68k2g7+0vs2u9CxDt5ktXTngsxOQkSEV/xBbwlqYcUrAVh6P9EgMZvFsnHy4SEiUl46Xf0IObWVbMvPrr2gw8A==", - "cpu": [ - "riscv64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.53.3.tgz", - "integrity": "sha512-VYsFMpULAz87ZW6BVYw3I6sWesGpsP9OPcyKe8ofdg9LHxSbRMd7zrVrr5xi/3kMZtpWL/wC+UIJWJYVX5uTKg==", - "cpu": [ - "s390x" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.53.3.tgz", - "integrity": "sha512-3EhFi1FU6YL8HTUJZ51imGJWEX//ajQPfqWLI3BQq4TlvHy4X0MOr5q3D2Zof/ka0d5FNdPwZXm3Yyib/UEd+w==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.53.3.tgz", - "integrity": "sha512-eoROhjcc6HbZCJr+tvVT8X4fW3/5g/WkGvvmwz/88sDtSJzO7r/blvoBDgISDiCjDRZmHpwud7h+6Q9JxFwq1Q==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-openharmony-arm64": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.53.3.tgz", - "integrity": "sha512-OueLAWgrNSPGAdUdIjSWXw+u/02BRTcnfw9PN41D2vq/JSEPnJnVuBgw18VkN8wcd4fjUs+jFHVM4t9+kBSNLw==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "openharmony" - ] - }, - "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.53.3.tgz", - "integrity": "sha512-GOFuKpsxR/whszbF/bzydebLiXIHSgsEUp6M0JI8dWvi+fFa1TD6YQa4aSZHtpmh2/uAlj/Dy+nmby3TJ3pkTw==", - "cpu": [ - "arm64" - ], - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.53.3.tgz", - "integrity": "sha512-iah+THLcBJdpfZ1TstDFbKNznlzoxa8fmnFYK4V67HvmuNYkVdAywJSoteUszvBQ9/HqN2+9AZghbajMsFT+oA==", - "cpu": [ - "ia32" - ], - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-x64-gnu": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.53.3.tgz", - "integrity": "sha512-J9QDiOIZlZLdcot5NXEepDkstocktoVjkaKUtqzgzpt2yWjGlbYiKyp05rWwk4nypbYUNoFAztEgixoLaSETkg==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.53.3.tgz", - "integrity": "sha512-UhTd8u31dXadv0MopwGgNOBpUVROFKWVQgAg5N1ESyCz8AuBcMqm4AuTjrwgQKGDfoFuz02EuMRHQIw/frmYKQ==", - "cpu": [ - "x64" - ], - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@shikijs/core": { - "version": "3.15.0", - "resolved": "https://registry.npmjs.org/@shikijs/core/-/core-3.15.0.tgz", - "integrity": "sha512-8TOG6yG557q+fMsSVa8nkEDOZNTSxjbbR8l6lF2gyr6Np+jrPlslqDxQkN6rMXCECQ3isNPZAGszAfYoJOPGlg==", - "license": "MIT", - "dependencies": { - "@shikijs/types": "3.15.0", - "@shikijs/vscode-textmate": "^10.0.2", - "@types/hast": "^3.0.4", - "hast-util-to-html": "^9.0.5" - } - }, - "node_modules/@shikijs/engine-javascript": { - "version": "3.15.0", - "resolved": "https://registry.npmjs.org/@shikijs/engine-javascript/-/engine-javascript-3.15.0.tgz", - "integrity": "sha512-ZedbOFpopibdLmvTz2sJPJgns8Xvyabe2QbmqMTz07kt1pTzfEvKZc5IqPVO/XFiEbbNyaOpjPBkkr1vlwS+qg==", - "license": "MIT", - "dependencies": { - "@shikijs/types": "3.15.0", - "@shikijs/vscode-textmate": "^10.0.2", - "oniguruma-to-es": "^4.3.3" - } - }, - "node_modules/@shikijs/engine-oniguruma": { - "version": "3.15.0", - "resolved": "https://registry.npmjs.org/@shikijs/engine-oniguruma/-/engine-oniguruma-3.15.0.tgz", - "integrity": "sha512-HnqFsV11skAHvOArMZdLBZZApRSYS4LSztk2K3016Y9VCyZISnlYUYsL2hzlS7tPqKHvNqmI5JSUJZprXloMvA==", - "license": "MIT", - "dependencies": { - "@shikijs/types": "3.15.0", - "@shikijs/vscode-textmate": "^10.0.2" - } - }, - "node_modules/@shikijs/langs": { - "version": "3.15.0", - "resolved": "https://registry.npmjs.org/@shikijs/langs/-/langs-3.15.0.tgz", - "integrity": "sha512-WpRvEFvkVvO65uKYW4Rzxs+IG0gToyM8SARQMtGGsH4GDMNZrr60qdggXrFOsdfOVssG/QQGEl3FnJ3EZ+8w8A==", - "license": "MIT", - "dependencies": { - "@shikijs/types": "3.15.0" - } - }, - "node_modules/@shikijs/themes": { - "version": "3.15.0", - "resolved": "https://registry.npmjs.org/@shikijs/themes/-/themes-3.15.0.tgz", - "integrity": "sha512-8ow2zWb1IDvCKjYb0KiLNrK4offFdkfNVPXb1OZykpLCzRU6j+efkY+Y7VQjNlNFXonSw+4AOdGYtmqykDbRiQ==", - "license": "MIT", - "dependencies": { - "@shikijs/types": "3.15.0" - } - }, - "node_modules/@shikijs/types": { - "version": "3.15.0", - "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-3.15.0.tgz", - "integrity": "sha512-BnP+y/EQnhihgHy4oIAN+6FFtmfTekwOLsQbRw9hOKwqgNy8Bdsjq8B05oAt/ZgvIWWFrshV71ytOrlPfYjIJw==", - "license": "MIT", - "dependencies": { - "@shikijs/vscode-textmate": "^10.0.2", - "@types/hast": "^3.0.4" - } - }, - "node_modules/@shikijs/vscode-textmate": { - "version": "10.0.2", - "resolved": "https://registry.npmjs.org/@shikijs/vscode-textmate/-/vscode-textmate-10.0.2.tgz", - "integrity": "sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg==", - "license": "MIT" - }, - "node_modules/@swc/helpers": { - "version": "0.5.17", - "resolved": "https://registry.npmjs.org/@swc/helpers/-/helpers-0.5.17.tgz", - "integrity": "sha512-5IKx/Y13RsYd+sauPb2x+U/xZikHjolzfuDgTAl/Tdf3Q8rslRvC19NKDLgAJQ6wsqADk10ntlv08nPFw/gO/A==", - "license": "Apache-2.0", - "dependencies": { - "tslib": "^2.8.0" - } - }, - "node_modules/@types/babel__core": { - "version": "7.20.5", - "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", - "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", - "license": "MIT", - "dependencies": { - "@babel/parser": "^7.20.7", - "@babel/types": "^7.20.7", - "@types/babel__generator": "*", - "@types/babel__template": "*", - "@types/babel__traverse": "*" - } - }, - "node_modules/@types/babel__generator": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.27.0.tgz", - "integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==", - "license": "MIT", - "dependencies": { - "@babel/types": "^7.0.0" - } - }, - "node_modules/@types/babel__template": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", - "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", - "license": "MIT", - "dependencies": { - "@babel/parser": "^7.1.0", - "@babel/types": "^7.0.0" - } - }, - "node_modules/@types/babel__traverse": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.28.0.tgz", - "integrity": "sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==", - "license": "MIT", - "dependencies": { - "@babel/types": "^7.28.2" - } - }, - "node_modules/@types/debug": { - "version": "4.1.12", - "resolved": "https://registry.npmjs.org/@types/debug/-/debug-4.1.12.tgz", - "integrity": "sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==", - "license": "MIT", - "dependencies": { - "@types/ms": "*" - } - }, - "node_modules/@types/estree": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", - "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", - "license": "MIT" - }, - "node_modules/@types/estree-jsx": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/@types/estree-jsx/-/estree-jsx-1.0.5.tgz", - "integrity": "sha512-52CcUVNFyfb1A2ALocQw/Dd1BQFNmSdkuC3BkZ6iqhdMfQz7JWOFRuJFloOzjk+6WijU56m9oKXFAXc7o3Towg==", - "license": "MIT", - "dependencies": { - "@types/estree": "*" - } - }, - "node_modules/@types/fontkit": { - "version": "2.0.8", - "resolved": "https://registry.npmjs.org/@types/fontkit/-/fontkit-2.0.8.tgz", - "integrity": "sha512-wN+8bYxIpJf+5oZdrdtaX04qUuWHcKxcDEgRS9Qm9ZClSHjzEn13SxUC+5eRM+4yXIeTYk8mTzLAWGF64847ew==", - "license": "MIT", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/hast": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz", - "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==", - "license": "MIT", - "dependencies": { - "@types/unist": "*" - } - }, - "node_modules/@types/js-yaml": { - "version": "4.0.9", - "resolved": "https://registry.npmjs.org/@types/js-yaml/-/js-yaml-4.0.9.tgz", - "integrity": "sha512-k4MGaQl5TGo/iipqb2UDG2UwjXziSWkh0uysQelTlJpX1qGlpUZYm8PnO4DxG1qBomtJUdYJ6qR6xdIah10JLg==", - "license": "MIT" - }, - "node_modules/@types/mdast": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-4.0.4.tgz", - "integrity": "sha512-kGaNbPh1k7AFzgpud/gMdvIm5xuECykRR+JnWKQno9TAXVa6WIVCGTPvYGekIDL4uwCZQSYbUxNBSb1aUo79oA==", - "license": "MIT", - "dependencies": { - "@types/unist": "*" - } - }, - "node_modules/@types/mdx": { - "version": "2.0.13", - "resolved": "https://registry.npmjs.org/@types/mdx/-/mdx-2.0.13.tgz", - "integrity": "sha512-+OWZQfAYyio6YkJb3HLxDrvnx6SWWDbC0zVPfBRzUk0/nqoDyf6dNxQi3eArPe8rJ473nobTMQ/8Zk+LxJ+Yuw==", - "license": "MIT" - }, - "node_modules/@types/ms": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@types/ms/-/ms-2.1.0.tgz", - "integrity": "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==", - "license": "MIT" - }, - "node_modules/@types/nlcst": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@types/nlcst/-/nlcst-2.0.3.tgz", - "integrity": "sha512-vSYNSDe6Ix3q+6Z7ri9lyWqgGhJTmzRjZRqyq15N0Z/1/UnVsno9G/N40NBijoYx2seFDIl0+B2mgAb9mezUCA==", - "license": "MIT", - "dependencies": { - "@types/unist": "*" - } - }, - "node_modules/@types/node": { - "version": "24.10.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-24.10.1.tgz", - "integrity": "sha512-GNWcUTRBgIRJD5zj+Tq0fKOJ5XZajIiBroOF0yvj2bSU1WvNdYS/dn9UxwsujGW4JX06dnHyjV2y9rRaybH0iQ==", - "license": "MIT", - "dependencies": { - "undici-types": "~7.16.0" - } - }, - "node_modules/@types/picomatch": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/@types/picomatch/-/picomatch-2.3.3.tgz", - "integrity": "sha512-Yll76ZHikRFCyz/pffKGjrCwe/le2CDwOP5F210KQo27kpRE46U2rDnzikNlVn6/ezH3Mhn46bJMTfeVTtcYMg==", - "license": "MIT" - }, - "node_modules/@types/react": { - "version": "19.2.6", - "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.6.tgz", - "integrity": "sha512-p/jUvulfgU7oKtj6Xpk8cA2Y1xKTtICGpJYeJXz2YVO2UcvjQgeRMLDGfDeqeRW2Ta+0QNFwcc8X3GH8SxZz6w==", - "license": "MIT", - "peer": true, - "dependencies": { - "csstype": "^3.2.2" - } - }, - "node_modules/@types/react-dom": { - "version": "19.2.3", - "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.2.3.tgz", - "integrity": "sha512-jp2L/eY6fn+KgVVQAOqYItbF0VY/YApe5Mz2F0aykSO8gx31bYCZyvSeYxCHKvzHG5eZjc+zyaS5BrBWya2+kQ==", - "license": "MIT", - "peer": true, - "peerDependencies": { - "@types/react": "^19.2.0" - } - }, - "node_modules/@types/sax": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/@types/sax/-/sax-1.2.7.tgz", - "integrity": "sha512-rO73L89PJxeYM3s3pPPjiPgVVcymqU490g0YO5n5By0k2Erzj6tay/4lr1CHAAU4JyOWd1rpQ8bCf6cZfHU96A==", - "license": "MIT", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/unist": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz", - "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==", - "license": "MIT" - }, - "node_modules/@ungap/structured-clone": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/@ungap/structured-clone/-/structured-clone-1.3.0.tgz", - "integrity": "sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==", - "license": "ISC" - }, - "node_modules/@vitejs/plugin-react": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.7.0.tgz", - "integrity": "sha512-gUu9hwfWvvEDBBmgtAowQCojwZmJ5mcLn3aufeCsitijs3+f2NsrPtlAWIR6OPiqljl96GVCUbLe0HyqIpVaoA==", - "license": "MIT", - "dependencies": { - "@babel/core": "^7.28.0", - "@babel/plugin-transform-react-jsx-self": "^7.27.1", - "@babel/plugin-transform-react-jsx-source": "^7.27.1", - "@rolldown/pluginutils": "1.0.0-beta.27", - "@types/babel__core": "^7.20.5", - "react-refresh": "^0.17.0" - }, - "engines": { - "node": "^14.18.0 || >=16.0.0" - }, - "peerDependencies": { - "vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0" - } - }, - "node_modules/@volar/kit": { - "version": "2.4.23", - "resolved": "https://registry.npmjs.org/@volar/kit/-/kit-2.4.23.tgz", - "integrity": "sha512-YuUIzo9zwC2IkN7FStIcVl1YS9w5vkSFEZfPvnu0IbIMaR9WHhc9ZxvlT+91vrcSoRY469H2jwbrGqpG7m1KaQ==", - "license": "MIT", - "dependencies": { - "@volar/language-service": "2.4.23", - "@volar/typescript": "2.4.23", - "typesafe-path": "^0.2.2", - "vscode-languageserver-textdocument": "^1.0.11", - "vscode-uri": "^3.0.8" - }, - "peerDependencies": { - "typescript": "*" - } - }, - "node_modules/@volar/language-core": { - "version": "2.4.23", - "resolved": "https://registry.npmjs.org/@volar/language-core/-/language-core-2.4.23.tgz", - "integrity": "sha512-hEEd5ET/oSmBC6pi1j6NaNYRWoAiDhINbT8rmwtINugR39loROSlufGdYMF9TaKGfz+ViGs1Idi3mAhnuPcoGQ==", - "license": "MIT", - "dependencies": { - "@volar/source-map": "2.4.23" - } - }, - "node_modules/@volar/language-server": { - "version": "2.4.23", - "resolved": "https://registry.npmjs.org/@volar/language-server/-/language-server-2.4.23.tgz", - "integrity": "sha512-k0iO+tybMGMMyrNdWOxgFkP0XJTdbH0w+WZlM54RzJU3WZSjHEupwL30klpM7ep4FO6qyQa03h+VcGHD4Q8gEg==", - "license": "MIT", - "dependencies": { - "@volar/language-core": "2.4.23", - "@volar/language-service": "2.4.23", - "@volar/typescript": "2.4.23", - "path-browserify": "^1.0.1", - "request-light": "^0.7.0", - "vscode-languageserver": "^9.0.1", - "vscode-languageserver-protocol": "^3.17.5", - "vscode-languageserver-textdocument": "^1.0.11", - "vscode-uri": "^3.0.8" - } - }, - "node_modules/@volar/language-service": { - "version": "2.4.23", - "resolved": "https://registry.npmjs.org/@volar/language-service/-/language-service-2.4.23.tgz", - "integrity": "sha512-h5mU9DZ/6u3LCB9xomJtorNG6awBNnk9VuCioGsp6UtFiM8amvS5FcsaC3dabdL9zO0z+Gq9vIEMb/5u9K6jGQ==", - "license": "MIT", - "dependencies": { - "@volar/language-core": "2.4.23", - "vscode-languageserver-protocol": "^3.17.5", - "vscode-languageserver-textdocument": "^1.0.11", - "vscode-uri": "^3.0.8" - } - }, - "node_modules/@volar/source-map": { - "version": "2.4.23", - "resolved": "https://registry.npmjs.org/@volar/source-map/-/source-map-2.4.23.tgz", - "integrity": "sha512-Z1Uc8IB57Lm6k7q6KIDu/p+JWtf3xsXJqAX/5r18hYOTpJyBn0KXUR8oTJ4WFYOcDzWC9n3IflGgHowx6U6z9Q==", - "license": "MIT" - }, - "node_modules/@volar/typescript": { - "version": "2.4.23", - "resolved": "https://registry.npmjs.org/@volar/typescript/-/typescript-2.4.23.tgz", - "integrity": "sha512-lAB5zJghWxVPqfcStmAP1ZqQacMpe90UrP5RJ3arDyrhy4aCUQqmxPPLB2PWDKugvylmO41ljK7vZ+t6INMTag==", - "license": "MIT", - "dependencies": { - "@volar/language-core": "2.4.23", - "path-browserify": "^1.0.1", - "vscode-uri": "^3.0.8" - } - }, - "node_modules/@vscode/emmet-helper": { - "version": "2.11.0", - "resolved": "https://registry.npmjs.org/@vscode/emmet-helper/-/emmet-helper-2.11.0.tgz", - "integrity": "sha512-QLxjQR3imPZPQltfbWRnHU6JecWTF1QSWhx3GAKQpslx7y3Dp6sIIXhKjiUJ/BR9FX8PVthjr9PD6pNwOJfAzw==", - "license": "MIT", - "dependencies": { - "emmet": "^2.4.3", - "jsonc-parser": "^2.3.0", - "vscode-languageserver-textdocument": "^1.0.1", - "vscode-languageserver-types": "^3.15.1", - "vscode-uri": "^3.0.8" - } - }, - "node_modules/@vscode/l10n": { - "version": "0.0.18", - "resolved": "https://registry.npmjs.org/@vscode/l10n/-/l10n-0.0.18.tgz", - "integrity": "sha512-KYSIHVmslkaCDyw013pphY+d7x1qV8IZupYfeIfzNA+nsaWHbn5uPuQRvdRFsa9zFzGeudPuoGoZ1Op4jrJXIQ==", - "license": "MIT" - }, - "node_modules/acorn": { - "version": "8.15.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", - "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", - "license": "MIT", - "peer": true, - "bin": { - "acorn": "bin/acorn" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/acorn-jsx": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "license": "MIT", - "peerDependencies": { - "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" - } - }, - "node_modules/ajv": { - "version": "8.17.1", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz", - "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==", - "license": "MIT", - "peer": true, - "dependencies": { - "fast-deep-equal": "^3.1.3", - "fast-uri": "^3.0.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/ajv-draft-04": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/ajv-draft-04/-/ajv-draft-04-1.0.0.tgz", - "integrity": "sha512-mv00Te6nmYbRp5DCwclxtt7yV/joXJPGS7nM+97GdxvuttCOfgI3K4U25zboyeX0O+myI8ERluxQe5wljMmVIw==", - "license": "MIT", - "peerDependencies": { - "ajv": "^8.5.0" - }, - "peerDependenciesMeta": { - "ajv": { - "optional": true - } - } - }, - "node_modules/ansi-align": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/ansi-align/-/ansi-align-3.0.1.tgz", - "integrity": "sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w==", - "license": "ISC", - "dependencies": { - "string-width": "^4.1.0" - } - }, - "node_modules/ansi-align/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/ansi-align/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "license": "MIT" - }, - "node_modules/ansi-align/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/ansi-align/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/ansi-regex": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", - "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/ansi-styles": { - "version": "6.2.3", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", - "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/anymatch": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", - "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", - "license": "ISC", - "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/anymatch/node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "license": "MIT", - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/arg": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", - "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==", - "license": "MIT" - }, - "node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "license": "Python-2.0" - }, - "node_modules/aria-query": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.2.tgz", - "integrity": "sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==", - "license": "Apache-2.0", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/array-iterate": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/array-iterate/-/array-iterate-2.0.1.tgz", - "integrity": "sha512-I1jXZMjAgCMmxT4qxXfPXa6SthSoE8h6gkSI9BGGNv8mP8G/v0blc+qFnZu6K42vTOiuME596QaLO0TP3Lk0xg==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/astring": { - "version": "1.9.0", - "resolved": "https://registry.npmjs.org/astring/-/astring-1.9.0.tgz", - "integrity": "sha512-LElXdjswlqjWrPpJFg1Fx4wpkOCxj1TDHlSV4PlaRxHGWko024xICaa97ZkMfs6DRKlCguiAI+rbXv5GWwXIkg==", - "license": "MIT", - "bin": { - "astring": "bin/astring" - } - }, - "node_modules/astro": { - "version": "5.16.0", - "resolved": "https://registry.npmjs.org/astro/-/astro-5.16.0.tgz", - "integrity": "sha512-GaDRs2Mngpw3dr2vc085GnORh98NiXxwIjg/EoQQQl/icZt3Z7s0BRsYHDZ8swkZbOA6wZsqWJdrNirl+iKcDg==", - "license": "MIT", - "peer": true, - "dependencies": { - "@astrojs/compiler": "^2.13.0", - "@astrojs/internal-helpers": "0.7.5", - "@astrojs/markdown-remark": "6.3.9", - "@astrojs/telemetry": "3.3.0", - "@capsizecss/unpack": "^3.0.1", - "@oslojs/encoding": "^1.1.0", - "@rollup/pluginutils": "^5.3.0", - "acorn": "^8.15.0", - "aria-query": "^5.3.2", - "axobject-query": "^4.1.0", - "boxen": "8.0.1", - "ci-info": "^4.3.1", - "clsx": "^2.1.1", - "common-ancestor-path": "^1.0.1", - "cookie": "^1.0.2", - "cssesc": "^3.0.0", - "debug": "^4.4.3", - "deterministic-object-hash": "^2.0.2", - "devalue": "^5.5.0", - "diff": "^5.2.0", - "dlv": "^1.1.3", - "dset": "^3.1.4", - "es-module-lexer": "^1.7.0", - "esbuild": "^0.25.0", - "estree-walker": "^3.0.3", - "flattie": "^1.1.1", - "fontace": "~0.3.1", - "github-slugger": "^2.0.0", - "html-escaper": "3.0.3", - "http-cache-semantics": "^4.2.0", - "import-meta-resolve": "^4.2.0", - "js-yaml": "^4.1.1", - "magic-string": "^0.30.21", - "magicast": "^0.5.1", - "mrmime": "^2.0.1", - "neotraverse": "^0.6.18", - "p-limit": "^6.2.0", - "p-queue": "^8.1.1", - "package-manager-detector": "^1.5.0", - "piccolore": "^0.1.3", - "picomatch": "^4.0.3", - "prompts": "^2.4.2", - "rehype": "^13.0.2", - "semver": "^7.7.3", - "shiki": "^3.15.0", - "smol-toml": "^1.5.0", - "svgo": "^4.0.0", - "tinyexec": "^1.0.2", - "tinyglobby": "^0.2.15", - "tsconfck": "^3.1.6", - "ultrahtml": "^1.6.0", - "unifont": "~0.6.0", - "unist-util-visit": "^5.0.0", - "unstorage": "^1.17.2", - "vfile": "^6.0.3", - "vite": "^6.4.1", - "vitefu": "^1.1.1", - "xxhash-wasm": "^1.1.0", - "yargs-parser": "^21.1.1", - "yocto-spinner": "^0.2.3", - "zod": "^3.25.76", - "zod-to-json-schema": "^3.24.6", - "zod-to-ts": "^1.2.0" - }, - "bin": { - "astro": "astro.js" - }, - "engines": { - "node": "18.20.8 || ^20.3.0 || >=22.0.0", - "npm": ">=9.6.5", - "pnpm": ">=7.1.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/astrodotbuild" - }, - "optionalDependencies": { - "sharp": "^0.34.0" - } - }, - "node_modules/astro-d2": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/astro-d2/-/astro-d2-0.5.2.tgz", - "integrity": "sha512-JN5kHalh/dQIZD6JG8y+WXY/j+K9NigyW7dLa+VbPeQnoNkRbvVms6847gqU5czojR7uzpArL7ug27vKae4lQg==", - "license": "MIT", - "dependencies": { - "unist-util-visit": "5.0.0" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "astro": ">=4.0.0" - } - }, - "node_modules/astro-expressive-code": { - "version": "0.41.3", - "resolved": "https://registry.npmjs.org/astro-expressive-code/-/astro-expressive-code-0.41.3.tgz", - "integrity": "sha512-u+zHMqo/QNLE2eqYRCrK3+XMlKakv33Bzuz+56V1gs8H0y6TZ0hIi3VNbIxeTn51NLn+mJfUV/A0kMNfE4rANw==", - "license": "MIT", - "dependencies": { - "rehype-expressive-code": "^0.41.3" - }, - "peerDependencies": { - "astro": "^4.0.0-beta || ^5.0.0-beta || ^3.3.0" - } - }, - "node_modules/astro-remote": { - "version": "0.3.4", - "resolved": "https://registry.npmjs.org/astro-remote/-/astro-remote-0.3.4.tgz", - "integrity": "sha512-jL5skNQLA0YBc1R3bVGXyHew3FqGqsT7AgLzWAVeTLzFkwVMUYvs4/lKJSmS7ygcF1GnHnoKG6++8GL9VtWwGQ==", - "license": "MIT", - "dependencies": { - "entities": "^4.5.0", - "marked": "^12.0.0", - "marked-footnote": "^1.2.2", - "marked-smartypants": "^1.1.6", - "ultrahtml": "^1.5.3" - }, - "engines": { - "node": ">=18.14.1" - } - }, - "node_modules/astro-remote/node_modules/entities": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", - "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", - "license": "BSD-2-Clause", - "engines": { - "node": ">=0.12" - }, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, - "node_modules/astro-remote/node_modules/marked": { - "version": "12.0.2", - "resolved": "https://registry.npmjs.org/marked/-/marked-12.0.2.tgz", - "integrity": "sha512-qXUm7e/YKFoqFPYPa3Ukg9xlI5cyAtGmyEIzMfW//m6kXwCy2Ps9DYf5ioijFKQ8qyuscrHoY04iJGctu2Kg0Q==", - "license": "MIT", - "bin": { - "marked": "bin/marked.js" - }, - "engines": { - "node": ">= 18" - } - }, - "node_modules/astro/node_modules/@img/sharp-darwin-arm64": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.34.5.tgz", - "integrity": "sha512-imtQ3WMJXbMY4fxb/Ndp6HBTNVtWCUI0WdobyheGf5+ad6xX8VIDO8u2xE4qc/fr08CKG/7dDseFtn6M6g/r3w==", - "cpu": [ - "arm64" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-darwin-arm64": "1.2.4" - } - }, - "node_modules/astro/node_modules/@img/sharp-darwin-x64": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.34.5.tgz", - "integrity": "sha512-YNEFAF/4KQ/PeW0N+r+aVVsoIY0/qxxikF2SWdp+NRkmMB7y9LBZAVqQ4yhGCm/H3H270OSykqmQMKLBhBJDEw==", - "cpu": [ - "x64" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-darwin-x64": "1.2.4" - } - }, - "node_modules/astro/node_modules/@img/sharp-libvips-darwin-arm64": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.2.4.tgz", - "integrity": "sha512-zqjjo7RatFfFoP0MkQ51jfuFZBnVE2pRiaydKJ1G/rHZvnsrHAOcQALIi9sA5co5xenQdTugCvtb1cuf78Vf4g==", - "cpu": [ - "arm64" - ], - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "darwin" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/astro/node_modules/@img/sharp-libvips-darwin-x64": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.2.4.tgz", - "integrity": "sha512-1IOd5xfVhlGwX+zXv2N93k0yMONvUlANylbJw1eTah8K/Jtpi15KC+WSiaX/nBmbm2HxRM1gZ0nSdjSsrZbGKg==", - "cpu": [ - "x64" - ], - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "darwin" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/astro/node_modules/@img/sharp-libvips-linux-arm": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.2.4.tgz", - "integrity": "sha512-bFI7xcKFELdiNCVov8e44Ia4u2byA+l3XtsAj+Q8tfCwO6BQ8iDojYdvoPMqsKDkuoOo+X6HZA0s0q11ANMQ8A==", - "cpu": [ - "arm" - ], - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "linux" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/astro/node_modules/@img/sharp-libvips-linux-arm64": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.2.4.tgz", - "integrity": "sha512-excjX8DfsIcJ10x1Kzr4RcWe1edC9PquDRRPx3YVCvQv+U5p7Yin2s32ftzikXojb1PIFc/9Mt28/y+iRklkrw==", - "cpu": [ - "arm64" - ], - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "linux" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/astro/node_modules/@img/sharp-libvips-linux-s390x": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.2.4.tgz", - "integrity": "sha512-qmp9VrzgPgMoGZyPvrQHqk02uyjA0/QrTO26Tqk6l4ZV0MPWIW6LTkqOIov+J1yEu7MbFQaDpwdwJKhbJvuRxQ==", - "cpu": [ - "s390x" - ], - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "linux" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/astro/node_modules/@img/sharp-libvips-linux-x64": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.2.4.tgz", - "integrity": "sha512-tJxiiLsmHc9Ax1bz3oaOYBURTXGIRDODBqhveVHonrHJ9/+k89qbLl0bcJns+e4t4rvaNBxaEZsFtSfAdquPrw==", - "cpu": [ - "x64" - ], - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "linux" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/astro/node_modules/@img/sharp-libvips-linuxmusl-arm64": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.2.4.tgz", - "integrity": "sha512-FVQHuwx1IIuNow9QAbYUzJ+En8KcVm9Lk5+uGUQJHaZmMECZmOlix9HnH7n1TRkXMS0pGxIJokIVB9SuqZGGXw==", - "cpu": [ - "arm64" - ], - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "linux" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/astro/node_modules/@img/sharp-libvips-linuxmusl-x64": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.2.4.tgz", - "integrity": "sha512-+LpyBk7L44ZIXwz/VYfglaX/okxezESc6UxDSoyo2Ks6Jxc4Y7sGjpgU9s4PMgqgjj1gZCylTieNamqA1MF7Dg==", - "cpu": [ - "x64" - ], - "license": "LGPL-3.0-or-later", - "optional": true, - "os": [ - "linux" - ], - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/astro/node_modules/@img/sharp-linux-arm": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.34.5.tgz", - "integrity": "sha512-9dLqsvwtg1uuXBGZKsxem9595+ujv0sJ6Vi8wcTANSFpwV/GONat5eCkzQo/1O6zRIkh0m/8+5BjrRr7jDUSZw==", - "cpu": [ - "arm" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linux-arm": "1.2.4" - } - }, - "node_modules/astro/node_modules/@img/sharp-linux-arm64": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.34.5.tgz", - "integrity": "sha512-bKQzaJRY/bkPOXyKx5EVup7qkaojECG6NLYswgktOZjaXecSAeCWiZwwiFf3/Y+O1HrauiE3FVsGxFg8c24rZg==", - "cpu": [ - "arm64" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linux-arm64": "1.2.4" - } - }, - "node_modules/astro/node_modules/@img/sharp-linux-s390x": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.34.5.tgz", - "integrity": "sha512-nQtCk0PdKfho3eC5MrbQoigJ2gd1CgddUMkabUj+rBevs8tZ2cULOx46E7oyX+04WGfABgIwmMC0VqieTiR4jg==", - "cpu": [ - "s390x" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linux-s390x": "1.2.4" - } - }, - "node_modules/astro/node_modules/@img/sharp-linux-x64": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.34.5.tgz", - "integrity": "sha512-MEzd8HPKxVxVenwAa+JRPwEC7QFjoPWuS5NZnBt6B3pu7EG2Ge0id1oLHZpPJdn3OQK+BQDiw9zStiHBTJQQQQ==", - "cpu": [ - "x64" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linux-x64": "1.2.4" - } - }, - "node_modules/astro/node_modules/@img/sharp-linuxmusl-arm64": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.34.5.tgz", - "integrity": "sha512-fprJR6GtRsMt6Kyfq44IsChVZeGN97gTD331weR1ex1c1rypDEABN6Tm2xa1wE6lYb5DdEnk03NZPqA7Id21yg==", - "cpu": [ - "arm64" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linuxmusl-arm64": "1.2.4" - } - }, - "node_modules/astro/node_modules/@img/sharp-linuxmusl-x64": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.34.5.tgz", - "integrity": "sha512-Jg8wNT1MUzIvhBFxViqrEhWDGzqymo3sV7z7ZsaWbZNDLXRJZoRGrjulp60YYtV4wfY8VIKcWidjojlLcWrd8Q==", - "cpu": [ - "x64" - ], - "license": "Apache-2.0", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-libvips-linuxmusl-x64": "1.2.4" - } - }, - "node_modules/astro/node_modules/@img/sharp-wasm32": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.34.5.tgz", - "integrity": "sha512-OdWTEiVkY2PHwqkbBI8frFxQQFekHaSSkUIJkwzclWZe64O1X4UlUjqqqLaPbUpMOQk6FBu/HtlGXNblIs0huw==", - "cpu": [ - "wasm32" - ], - "license": "Apache-2.0 AND LGPL-3.0-or-later AND MIT", - "optional": true, - "dependencies": { - "@emnapi/runtime": "^1.7.0" - }, - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/astro/node_modules/@img/sharp-win32-ia32": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.34.5.tgz", - "integrity": "sha512-FV9m/7NmeCmSHDD5j4+4pNI8Cp3aW+JvLoXcTUo0IqyjSfAZJ8dIUmijx1qaJsIiU+Hosw6xM5KijAWRJCSgNg==", - "cpu": [ - "ia32" - ], - "license": "Apache-2.0 AND LGPL-3.0-or-later", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/astro/node_modules/@img/sharp-win32-x64": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.34.5.tgz", - "integrity": "sha512-+29YMsqY2/9eFEiW93eqWnuLcWcufowXewwSNIT6UwZdUUCrM3oFjMWH/Z6/TMmb4hlFenmfAVbpWeup2jryCw==", - "cpu": [ - "x64" - ], - "license": "Apache-2.0 AND LGPL-3.0-or-later", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - } - }, - "node_modules/astro/node_modules/semver": { - "version": "7.7.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", - "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/astro/node_modules/sharp": { - "version": "0.34.5", - "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.34.5.tgz", - "integrity": "sha512-Ou9I5Ft9WNcCbXrU9cMgPBcCK8LiwLqcbywW3t4oDV37n1pzpuNLsYiAV8eODnjbtQlSDwZ2cUEeQz4E54Hltg==", - "hasInstallScript": true, - "license": "Apache-2.0", - "optional": true, - "dependencies": { - "@img/colour": "^1.0.0", - "detect-libc": "^2.1.2", - "semver": "^7.7.3" - }, - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-darwin-arm64": "0.34.5", - "@img/sharp-darwin-x64": "0.34.5", - "@img/sharp-libvips-darwin-arm64": "1.2.4", - "@img/sharp-libvips-darwin-x64": "1.2.4", - "@img/sharp-libvips-linux-arm": "1.2.4", - "@img/sharp-libvips-linux-arm64": "1.2.4", - "@img/sharp-libvips-linux-ppc64": "1.2.4", - "@img/sharp-libvips-linux-riscv64": "1.2.4", - "@img/sharp-libvips-linux-s390x": "1.2.4", - "@img/sharp-libvips-linux-x64": "1.2.4", - "@img/sharp-libvips-linuxmusl-arm64": "1.2.4", - "@img/sharp-libvips-linuxmusl-x64": "1.2.4", - "@img/sharp-linux-arm": "0.34.5", - "@img/sharp-linux-arm64": "0.34.5", - "@img/sharp-linux-ppc64": "0.34.5", - "@img/sharp-linux-riscv64": "0.34.5", - "@img/sharp-linux-s390x": "0.34.5", - "@img/sharp-linux-x64": "0.34.5", - "@img/sharp-linuxmusl-arm64": "0.34.5", - "@img/sharp-linuxmusl-x64": "0.34.5", - "@img/sharp-wasm32": "0.34.5", - "@img/sharp-win32-arm64": "0.34.5", - "@img/sharp-win32-ia32": "0.34.5", - "@img/sharp-win32-x64": "0.34.5" - } - }, - "node_modules/axobject-query": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.1.0.tgz", - "integrity": "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==", - "license": "Apache-2.0", - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/bail": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/bail/-/bail-2.0.2.tgz", - "integrity": "sha512-0xO6mYd7JB2YesxDKplafRpsiOzPt9V02ddPCLbY1xYGPOX24NTyN50qnUxgCPcSoYMhKpAuBTjQoRZCAkUDRw==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/base-64": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/base-64/-/base-64-1.0.0.tgz", - "integrity": "sha512-kwDPIFCGx0NZHog36dj+tHiwP4QMzsZ3AgMViUBKI0+V5n4U0ufTCUMhnQ04diaRI8EX/QcPfql7zlhZ7j4zgg==", - "license": "MIT" - }, - "node_modules/base64-js": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, - "node_modules/baseline-browser-mapping": { - "version": "2.8.30", - "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.8.30.tgz", - "integrity": "sha512-aTUKW4ptQhS64+v2d6IkPzymEzzhw+G0bA1g3uBRV3+ntkH+svttKseW5IOR4Ed6NUVKqnY7qT3dKvzQ7io4AA==", - "license": "Apache-2.0", - "bin": { - "baseline-browser-mapping": "dist/cli.js" - } - }, - "node_modules/bcp-47": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/bcp-47/-/bcp-47-2.1.0.tgz", - "integrity": "sha512-9IIS3UPrvIa1Ej+lVDdDwO7zLehjqsaByECw0bu2RRGP73jALm6FYbzI5gWbgHLvNdkvfXB5YrSbocZdOS0c0w==", - "license": "MIT", - "dependencies": { - "is-alphabetical": "^2.0.0", - "is-alphanumerical": "^2.0.0", - "is-decimal": "^2.0.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/bcp-47-match": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/bcp-47-match/-/bcp-47-match-2.0.3.tgz", - "integrity": "sha512-JtTezzbAibu8G0R9op9zb3vcWZd9JF6M0xOYGPn0fNCd7wOpRB1mU2mH9T8gaBGbAAyIIVgB2G7xG0GP98zMAQ==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/boolbase": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", - "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", - "license": "ISC" - }, - "node_modules/boxen": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/boxen/-/boxen-8.0.1.tgz", - "integrity": "sha512-F3PH5k5juxom4xktynS7MoFY+NUWH5LC4CnH11YB8NPew+HLpmBLCybSAEyb2F+4pRXhuhWqFesoQd6DAyc2hw==", - "license": "MIT", - "dependencies": { - "ansi-align": "^3.0.1", - "camelcase": "^8.0.0", - "chalk": "^5.3.0", - "cli-boxes": "^3.0.0", - "string-width": "^7.2.0", - "type-fest": "^4.21.0", - "widest-line": "^5.0.0", - "wrap-ansi": "^9.0.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/braces": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", - "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", - "license": "MIT", - "dependencies": { - "fill-range": "^7.1.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/brotli": { - "version": "1.3.3", - "resolved": "https://registry.npmjs.org/brotli/-/brotli-1.3.3.tgz", - "integrity": "sha512-oTKjJdShmDuGW94SyyaoQvAjf30dZaHnjJ8uAF+u2/vGJkJbJPJAT1gDiOJP5v1Zb6f9KEyW/1HpuaWIXtGHPg==", - "license": "MIT", - "dependencies": { - "base64-js": "^1.1.2" - } - }, - "node_modules/browserslist": { - "version": "4.28.0", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.0.tgz", - "integrity": "sha512-tbydkR/CxfMwelN0vwdP/pLkDwyAASZ+VfWm4EOwlB6SWhx1sYnWLqo8N5j0rAzPfzfRaxt0mM/4wPU/Su84RQ==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "peer": true, - "dependencies": { - "baseline-browser-mapping": "^2.8.25", - "caniuse-lite": "^1.0.30001754", - "electron-to-chromium": "^1.5.249", - "node-releases": "^2.0.27", - "update-browserslist-db": "^1.1.4" - }, - "bin": { - "browserslist": "cli.js" - }, - "engines": { - "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" - } - }, - "node_modules/camelcase": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-8.0.0.tgz", - "integrity": "sha512-8WB3Jcas3swSvjIeA2yvCJ+Miyz5l1ZmB6HFb9R1317dt9LCQoswg/BGrmAmkWVEszSrrg4RwmO46qIm2OEnSA==", - "license": "MIT", - "engines": { - "node": ">=16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/caniuse-lite": { - "version": "1.0.30001756", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001756.tgz", - "integrity": "sha512-4HnCNKbMLkLdhJz3TToeVWHSnfJvPaq6vu/eRP0Ahub/07n484XHhBF5AJoSGHdVrS8tKFauUQz8Bp9P7LVx7A==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/caniuse-lite" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "CC-BY-4.0" - }, - "node_modules/ccount": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/ccount/-/ccount-2.0.1.tgz", - "integrity": "sha512-eyrF0jiFpY+3drT6383f1qhkbGsLSifNAjA61IUjZjmLCWjItY6LB9ft9YhoDgwfmclB2zhu51Lc7+95b8NRAg==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/chalk": { - "version": "5.6.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz", - "integrity": "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==", - "license": "MIT", - "engines": { - "node": "^12.17.0 || ^14.13 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/character-entities": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/character-entities/-/character-entities-2.0.2.tgz", - "integrity": "sha512-shx7oQ0Awen/BRIdkjkvz54PnEEI/EjwXDSIZp86/KKdbafHh1Df/RYGBhn4hbe2+uKC9FnT5UCEdyPz3ai9hQ==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/character-entities-html4": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/character-entities-html4/-/character-entities-html4-2.1.0.tgz", - "integrity": "sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/character-entities-legacy": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/character-entities-legacy/-/character-entities-legacy-3.0.0.tgz", - "integrity": "sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/character-reference-invalid": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/character-reference-invalid/-/character-reference-invalid-2.0.1.tgz", - "integrity": "sha512-iBZ4F4wRbyORVsu0jPV7gXkOsGYjGHPmAyv+HiHG8gi5PtC9KI2j1+v8/tlibRvjoWX027ypmG/n0HtO5t7unw==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/chokidar": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", - "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", - "license": "MIT", - "dependencies": { - "readdirp": "^4.0.1" - }, - "engines": { - "node": ">= 14.16.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/ci-info": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.3.1.tgz", - "integrity": "sha512-Wdy2Igu8OcBpI2pZePZ5oWjPC38tmDVx5WKUXKwlLYkA0ozo85sLsLvkBbBn/sZaSCMFOGZJ14fvW9t5/d7kdA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/sibiraj-s" - } - ], - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/cli-boxes": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-3.0.0.tgz", - "integrity": "sha512-/lzGpEWL/8PfI0BmBOPRwp0c/wFNX1RdUML3jK/RcSBA9T8mZDdQpqYBKtCFTOfQbwPqWEOpjqW+Fnayc0969g==", - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/cliui": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", - "license": "ISC", - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/cliui/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/cliui/node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/cliui/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "license": "MIT" - }, - "node_modules/cliui/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cliui/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cliui/node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/clone": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz", - "integrity": "sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==", - "license": "MIT", - "engines": { - "node": ">=0.8" - } - }, - "node_modules/clsx": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", - "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/collapse-white-space": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/collapse-white-space/-/collapse-white-space-2.1.0.tgz", - "integrity": "sha512-loKTxY1zCOuG4j9f6EPnuyyYkf58RnhhWTvRoZEokgB+WbdXehfjFviyOVYkqzEWz1Q5kRiZdBYS5SwxbQYwzw==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/color": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz", - "integrity": "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==", - "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1", - "color-string": "^1.9.0" - }, - "engines": { - "node": ">=12.5.0" - } - }, - "node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "license": "MIT", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "license": "MIT" - }, - "node_modules/color-string": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz", - "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==", - "license": "MIT", - "dependencies": { - "color-name": "^1.0.0", - "simple-swizzle": "^0.2.2" - } - }, - "node_modules/comma-separated-tokens": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/comma-separated-tokens/-/comma-separated-tokens-2.0.3.tgz", - "integrity": "sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/commander": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-11.1.0.tgz", - "integrity": "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==", - "license": "MIT", - "engines": { - "node": ">=16" - } - }, - "node_modules/common-ancestor-path": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/common-ancestor-path/-/common-ancestor-path-1.0.1.tgz", - "integrity": "sha512-L3sHRo1pXXEqX8VU28kfgUY+YGsk09hPqZiZmLacNib6XNTCM8ubYeT7ryXQw8asB1sKgcU5lkB7ONug08aB8w==", - "license": "ISC" - }, - "node_modules/convert-source-map": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", - "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", - "license": "MIT" - }, - "node_modules/cookie": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-1.0.2.tgz", - "integrity": "sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA==", - "license": "MIT", - "engines": { - "node": ">=18" - } - }, - "node_modules/cookie-es": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/cookie-es/-/cookie-es-1.2.2.tgz", - "integrity": "sha512-+W7VmiVINB+ywl1HGXJXmrqkOhpKrIiVZV6tQuV54ZyQC7MMuBt81Vc336GMLoHBq5hV/F9eXgt5Mnx0Rha5Fg==", - "license": "MIT" - }, - "node_modules/crossws": { - "version": "0.3.5", - "resolved": "https://registry.npmjs.org/crossws/-/crossws-0.3.5.tgz", - "integrity": "sha512-ojKiDvcmByhwa8YYqbQI/hg7MEU0NC03+pSdEq4ZUnZR9xXpwk7E43SMNGkn+JxJGPFtNvQ48+vV2p+P1ml5PA==", - "license": "MIT", - "dependencies": { - "uncrypto": "^0.1.3" - } - }, - "node_modules/css-select": { - "version": "5.2.2", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.2.2.tgz", - "integrity": "sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw==", - "license": "BSD-2-Clause", - "dependencies": { - "boolbase": "^1.0.0", - "css-what": "^6.1.0", - "domhandler": "^5.0.2", - "domutils": "^3.0.1", - "nth-check": "^2.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/fb55" - } - }, - "node_modules/css-selector-parser": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/css-selector-parser/-/css-selector-parser-3.2.0.tgz", - "integrity": "sha512-L1bdkNKUP5WYxiW5dW6vA2hd3sL8BdRNLy2FCX0rLVise4eNw9nBdeBuJHxlELieSE2H1f6bYQFfwVUwWCV9rQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/mdevils" - }, - { - "type": "patreon", - "url": "https://patreon.com/mdevils" - } - ], - "license": "MIT" - }, - "node_modules/css-tree": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-3.1.0.tgz", - "integrity": "sha512-0eW44TGN5SQXU1mWSkKwFstI/22X2bG1nYzZTYMAWjylYURhse752YgbE4Cx46AC+bAvI+/dYTPRk1LqSUnu6w==", - "license": "MIT", - "dependencies": { - "mdn-data": "2.12.2", - "source-map-js": "^1.0.1" - }, - "engines": { - "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0" - } - }, - "node_modules/css-what": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.2.2.tgz", - "integrity": "sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA==", - "license": "BSD-2-Clause", - "engines": { - "node": ">= 6" - }, - "funding": { - "url": "https://github.com/sponsors/fb55" - } - }, - "node_modules/cssesc": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", - "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", - "license": "MIT", - "bin": { - "cssesc": "bin/cssesc" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/csso": { - "version": "5.0.5", - "resolved": "https://registry.npmjs.org/csso/-/csso-5.0.5.tgz", - "integrity": "sha512-0LrrStPOdJj+SPCCrGhzryycLjwcgUSHBtxNA8aIDxf0GLsRh1cKYhB00Gd1lDOS4yGH69+SNn13+TWbVHETFQ==", - "license": "MIT", - "dependencies": { - "css-tree": "~2.2.0" - }, - "engines": { - "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0", - "npm": ">=7.0.0" - } - }, - "node_modules/csso/node_modules/css-tree": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.2.1.tgz", - "integrity": "sha512-OA0mILzGc1kCOCSJerOeqDxDQ4HOh+G8NbOJFOTgOCzpw7fCBubk0fEyxp8AgOL/jvLgYA/uV0cMbe43ElF1JA==", - "license": "MIT", - "dependencies": { - "mdn-data": "2.0.28", - "source-map-js": "^1.0.1" - }, - "engines": { - "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0", - "npm": ">=7.0.0" - } - }, - "node_modules/csso/node_modules/mdn-data": { - "version": "2.0.28", - "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.28.tgz", - "integrity": "sha512-aylIc7Z9y4yzHYAJNuESG3hfhC+0Ibp/MAMiaOZgNv4pmEdFyfZhhhny4MNiAfWdBQ1RQ2mfDWmM1x8SvGyp8g==", - "license": "CC0-1.0" - }, - "node_modules/cssom": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/cssom/-/cssom-0.5.0.tgz", - "integrity": "sha512-iKuQcq+NdHqlAcwUY0o/HL69XQrUaQdMjmStJ8JFmUaiiQErlhrmuigkg/CU4E2J0IyUKUrMAgl36TvN67MqTw==", - "license": "MIT" - }, - "node_modules/csstype": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", - "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", - "license": "MIT" - }, - "node_modules/debug": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", - "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", - "license": "MIT", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/decode-named-character-reference": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/decode-named-character-reference/-/decode-named-character-reference-1.2.0.tgz", - "integrity": "sha512-c6fcElNV6ShtZXmsgNgFFV5tVX2PaV4g+MOAkb8eXHvn6sryJBrZa9r0zV6+dtTyoCKxtDy5tyQ5ZwQuidtd+Q==", - "license": "MIT", - "dependencies": { - "character-entities": "^2.0.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/defu": { - "version": "6.1.4", - "resolved": "https://registry.npmjs.org/defu/-/defu-6.1.4.tgz", - "integrity": "sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==", - "license": "MIT" - }, - "node_modules/dequal": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz", - "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==", - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/destr": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/destr/-/destr-2.0.5.tgz", - "integrity": "sha512-ugFTXCtDZunbzasqBxrK93Ik/DRYsO6S/fedkWEMKqt04xZ4csmnmwGDBAb07QWNaGMAmnTIemsYZCksjATwsA==", - "license": "MIT" - }, - "node_modules/detect-libc": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", - "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", - "license": "Apache-2.0", - "engines": { - "node": ">=8" - } - }, - "node_modules/deterministic-object-hash": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/deterministic-object-hash/-/deterministic-object-hash-2.0.2.tgz", - "integrity": "sha512-KxektNH63SrbfUyDiwXqRb1rLwKt33AmMv+5Nhsw1kqZ13SJBRTgZHtGbE+hH3a1mVW1cz+4pqSWVPAtLVXTzQ==", - "license": "MIT", - "dependencies": { - "base-64": "^1.0.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/devalue": { - "version": "5.5.0", - "resolved": "https://registry.npmjs.org/devalue/-/devalue-5.5.0.tgz", - "integrity": "sha512-69sM5yrHfFLJt0AZ9QqZXGCPfJ7fQjvpln3Rq5+PS03LD32Ost1Q9N+eEnaQwGRIriKkMImXD56ocjQmfjbV3w==", - "license": "MIT" - }, - "node_modules/devlop": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/devlop/-/devlop-1.1.0.tgz", - "integrity": "sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==", - "license": "MIT", - "dependencies": { - "dequal": "^2.0.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/dfa": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/dfa/-/dfa-1.2.0.tgz", - "integrity": "sha512-ED3jP8saaweFTjeGX8HQPjeC1YYyZs98jGNZx6IiBvxW7JG5v492kamAQB3m2wop07CvU/RQmzcKr6bgcC5D/Q==", - "license": "MIT" - }, - "node_modules/diff": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-5.2.0.tgz", - "integrity": "sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==", - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.3.1" - } - }, - "node_modules/direction": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/direction/-/direction-2.0.1.tgz", - "integrity": "sha512-9S6m9Sukh1cZNknO1CWAr2QAWsbKLafQiyM5gZ7VgXHeuaoUwffKN4q6NC4A/Mf9iiPlOXQEKW/Mv/mh9/3YFA==", - "license": "MIT", - "bin": { - "direction": "cli.js" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/dlv": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", - "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==", - "license": "MIT" - }, - "node_modules/dom-serializer": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", - "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", - "license": "MIT", - "dependencies": { - "domelementtype": "^2.3.0", - "domhandler": "^5.0.2", - "entities": "^4.2.0" - }, - "funding": { - "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" - } - }, - "node_modules/dom-serializer/node_modules/entities": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", - "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", - "license": "BSD-2-Clause", - "engines": { - "node": ">=0.12" - }, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, - "node_modules/domelementtype": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", - "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fb55" - } - ], - "license": "BSD-2-Clause" - }, - "node_modules/domhandler": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", - "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", - "license": "BSD-2-Clause", - "dependencies": { - "domelementtype": "^2.3.0" - }, - "engines": { - "node": ">= 4" - }, - "funding": { - "url": "https://github.com/fb55/domhandler?sponsor=1" - } - }, - "node_modules/domutils": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.2.2.tgz", - "integrity": "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==", - "license": "BSD-2-Clause", - "dependencies": { - "dom-serializer": "^2.0.0", - "domelementtype": "^2.3.0", - "domhandler": "^5.0.3" - }, - "funding": { - "url": "https://github.com/fb55/domutils?sponsor=1" - } - }, - "node_modules/dset": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/dset/-/dset-3.1.4.tgz", - "integrity": "sha512-2QF/g9/zTaPDc3BjNcVTGoBbXBgYfMTTceLaYcFJ/W9kggFUkhxD/hMEeuLKbugyef9SqAx8cpgwlIP/jinUTA==", - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/electron-to-chromium": { - "version": "1.5.259", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.259.tgz", - "integrity": "sha512-I+oLXgpEJzD6Cwuwt1gYjxsDmu/S/Kd41mmLA3O+/uH2pFRO/DvOjUyGozL8j3KeLV6WyZ7ssPwELMsXCcsJAQ==", - "license": "ISC" - }, - "node_modules/emmet": { - "version": "2.4.11", - "resolved": "https://registry.npmjs.org/emmet/-/emmet-2.4.11.tgz", - "integrity": "sha512-23QPJB3moh/U9sT4rQzGgeyyGIrcM+GH5uVYg2C6wZIxAIJq7Ng3QLT79tl8FUwDXhyq9SusfknOrofAKqvgyQ==", - "license": "MIT", - "workspaces": [ - "./packages/scanner", - "./packages/abbreviation", - "./packages/css-abbreviation", - "./" - ], - "dependencies": { - "@emmetio/abbreviation": "^2.3.3", - "@emmetio/css-abbreviation": "^2.1.8" - } - }, - "node_modules/emoji-regex": { - "version": "10.6.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.6.0.tgz", - "integrity": "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==", - "license": "MIT" - }, - "node_modules/entities": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz", - "integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==", - "license": "BSD-2-Clause", - "engines": { - "node": ">=0.12" - }, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, - "node_modules/es-module-lexer": { - "version": "1.7.0", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.7.0.tgz", - "integrity": "sha512-jEQoCwk8hyb2AZziIOLhDqpm5+2ww5uIE6lkO/6jcOCusfk6LhMHpXXfBLXTZ7Ydyt0j4VoUQv6uGNYbdW+kBA==", - "license": "MIT" - }, - "node_modules/esast-util-from-estree": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/esast-util-from-estree/-/esast-util-from-estree-2.0.0.tgz", - "integrity": "sha512-4CyanoAudUSBAn5K13H4JhsMH6L9ZP7XbLVe/dKybkxMO7eDyLsT8UHl9TRNrU2Gr9nz+FovfSIjuXWJ81uVwQ==", - "license": "MIT", - "dependencies": { - "@types/estree-jsx": "^1.0.0", - "devlop": "^1.0.0", - "estree-util-visit": "^2.0.0", - "unist-util-position-from-estree": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/esast-util-from-js": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/esast-util-from-js/-/esast-util-from-js-2.0.1.tgz", - "integrity": "sha512-8Ja+rNJ0Lt56Pcf3TAmpBZjmx8ZcK5Ts4cAzIOjsjevg9oSXJnl6SUQ2EevU8tv3h6ZLWmoKL5H4fgWvdvfETw==", - "license": "MIT", - "dependencies": { - "@types/estree-jsx": "^1.0.0", - "acorn": "^8.0.0", - "esast-util-from-estree": "^2.0.0", - "vfile-message": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/esbuild": { - "version": "0.25.12", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.12.tgz", - "integrity": "sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg==", - "hasInstallScript": true, - "license": "MIT", - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=18" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.25.12", - "@esbuild/android-arm": "0.25.12", - "@esbuild/android-arm64": "0.25.12", - "@esbuild/android-x64": "0.25.12", - "@esbuild/darwin-arm64": "0.25.12", - "@esbuild/darwin-x64": "0.25.12", - "@esbuild/freebsd-arm64": "0.25.12", - "@esbuild/freebsd-x64": "0.25.12", - "@esbuild/linux-arm": "0.25.12", - "@esbuild/linux-arm64": "0.25.12", - "@esbuild/linux-ia32": "0.25.12", - "@esbuild/linux-loong64": "0.25.12", - "@esbuild/linux-mips64el": "0.25.12", - "@esbuild/linux-ppc64": "0.25.12", - "@esbuild/linux-riscv64": "0.25.12", - "@esbuild/linux-s390x": "0.25.12", - "@esbuild/linux-x64": "0.25.12", - "@esbuild/netbsd-arm64": "0.25.12", - "@esbuild/netbsd-x64": "0.25.12", - "@esbuild/openbsd-arm64": "0.25.12", - "@esbuild/openbsd-x64": "0.25.12", - "@esbuild/openharmony-arm64": "0.25.12", - "@esbuild/sunos-x64": "0.25.12", - "@esbuild/win32-arm64": "0.25.12", - "@esbuild/win32-ia32": "0.25.12", - "@esbuild/win32-x64": "0.25.12" - } - }, - "node_modules/escalade": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", - "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/escape-string-regexp": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-5.0.0.tgz", - "integrity": "sha512-/veY75JbMK4j1yjvuUxuVsiS/hr/4iHs9FTT6cgTexxdE0Ly/glccBAkloH/DofkjRbZU3bnoj38mOmhkZ0lHw==", - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/estree-util-attach-comments": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/estree-util-attach-comments/-/estree-util-attach-comments-3.0.0.tgz", - "integrity": "sha512-cKUwm/HUcTDsYh/9FgnuFqpfquUbwIqwKM26BVCGDPVgvaCl/nDCCjUfiLlx6lsEZ3Z4RFxNbOQ60pkaEwFxGw==", - "license": "MIT", - "dependencies": { - "@types/estree": "^1.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/estree-util-build-jsx": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/estree-util-build-jsx/-/estree-util-build-jsx-3.0.1.tgz", - "integrity": "sha512-8U5eiL6BTrPxp/CHbs2yMgP8ftMhR5ww1eIKoWRMlqvltHF8fZn5LRDvTKuxD3DUn+shRbLGqXemcP51oFCsGQ==", - "license": "MIT", - "dependencies": { - "@types/estree-jsx": "^1.0.0", - "devlop": "^1.0.0", - "estree-util-is-identifier-name": "^3.0.0", - "estree-walker": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/estree-util-is-identifier-name": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/estree-util-is-identifier-name/-/estree-util-is-identifier-name-3.0.0.tgz", - "integrity": "sha512-hFtqIDZTIUZ9BXLb8y4pYGyk6+wekIivNVTcmvk8NoOh+VeRn5y6cEHzbURrWbfp1fIqdVipilzj+lfaadNZmg==", - "license": "MIT", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/estree-util-scope": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/estree-util-scope/-/estree-util-scope-1.0.0.tgz", - "integrity": "sha512-2CAASclonf+JFWBNJPndcOpA8EMJwa0Q8LUFJEKqXLW6+qBvbFZuF5gItbQOs/umBUkjviCSDCbBwU2cXbmrhQ==", - "license": "MIT", - "dependencies": { - "@types/estree": "^1.0.0", - "devlop": "^1.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/estree-util-to-js": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/estree-util-to-js/-/estree-util-to-js-2.0.0.tgz", - "integrity": "sha512-WDF+xj5rRWmD5tj6bIqRi6CkLIXbbNQUcxQHzGysQzvHmdYG2G7p/Tf0J0gpxGgkeMZNTIjT/AoSvC9Xehcgdg==", - "license": "MIT", - "dependencies": { - "@types/estree-jsx": "^1.0.0", - "astring": "^1.8.0", - "source-map": "^0.7.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/estree-util-visit": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/estree-util-visit/-/estree-util-visit-2.0.0.tgz", - "integrity": "sha512-m5KgiH85xAhhW8Wta0vShLcUvOsh3LLPI2YVwcbio1l7E09NTLL1EyMZFM1OyWowoH0skScNbhOPl4kcBgzTww==", - "license": "MIT", - "dependencies": { - "@types/estree-jsx": "^1.0.0", - "@types/unist": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/estree-walker": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", - "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", - "license": "MIT", - "dependencies": { - "@types/estree": "^1.0.0" - } - }, - "node_modules/eventemitter3": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", - "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==", - "license": "MIT" - }, - "node_modules/expressive-code": { - "version": "0.41.3", - "resolved": "https://registry.npmjs.org/expressive-code/-/expressive-code-0.41.3.tgz", - "integrity": "sha512-YLnD62jfgBZYrXIPQcJ0a51Afv9h8VlWqEGK9uU2T5nL/5rb8SnA86+7+mgCZe5D34Tff5RNEA5hjNVJYHzrFg==", - "license": "MIT", - "dependencies": { - "@expressive-code/core": "^0.41.3", - "@expressive-code/plugin-frames": "^0.41.3", - "@expressive-code/plugin-shiki": "^0.41.3", - "@expressive-code/plugin-text-markers": "^0.41.3" - } - }, - "node_modules/extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", - "license": "MIT" - }, - "node_modules/fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "license": "MIT" - }, - "node_modules/fast-glob": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", - "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", - "license": "MIT", - "dependencies": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.8" - }, - "engines": { - "node": ">=8.6.0" - } - }, - "node_modules/fast-uri": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.0.tgz", - "integrity": "sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fastify" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/fastify" - } - ], - "license": "BSD-3-Clause" - }, - "node_modules/fast-xml-parser": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-5.3.2.tgz", - "integrity": "sha512-n8v8b6p4Z1sMgqRmqLJm3awW4NX7NkaKPfb3uJIBTSH7Pdvufi3PQ3/lJLQrvxcMYl7JI2jnDO90siPEpD8JBA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/NaturalIntelligence" - } - ], - "license": "MIT", - "dependencies": { - "strnum": "^2.1.0" - }, - "bin": { - "fxparser": "src/cli/cli.js" - } - }, - "node_modules/fastq": { - "version": "1.19.1", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz", - "integrity": "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==", - "license": "ISC", - "dependencies": { - "reusify": "^1.0.4" - } - }, - "node_modules/fdir": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", - "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", - "license": "MIT", - "engines": { - "node": ">=12.0.0" - }, - "peerDependencies": { - "picomatch": "^3 || ^4" - }, - "peerDependenciesMeta": { - "picomatch": { - "optional": true - } - } - }, - "node_modules/fill-range": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", - "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", - "license": "MIT", - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/flattie": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/flattie/-/flattie-1.1.1.tgz", - "integrity": "sha512-9UbaD6XdAL97+k/n+N7JwX46K/M6Zc6KcFYskrYL8wbBV/Uyk0CTAMY0VT+qiK5PM7AIc9aTWYtq65U7T+aCNQ==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/fontace": { - "version": "0.3.1", - "resolved": "https://registry.npmjs.org/fontace/-/fontace-0.3.1.tgz", - "integrity": "sha512-9f5g4feWT1jWT8+SbL85aLIRLIXUaDygaM2xPXRmzPYxrOMNok79Lr3FGJoKVNKibE0WCunNiEVG2mwuE+2qEg==", - "license": "MIT", - "dependencies": { - "@types/fontkit": "^2.0.8", - "fontkit": "^2.0.4" - } - }, - "node_modules/fontkit": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/fontkit/-/fontkit-2.0.4.tgz", - "integrity": "sha512-syetQadaUEDNdxdugga9CpEYVaQIxOwk7GlwZWWZ19//qW4zE5bknOKeMBDYAASwnpaSHKJITRLMF9m1fp3s6g==", - "license": "MIT", - "dependencies": { - "@swc/helpers": "^0.5.12", - "brotli": "^1.3.2", - "clone": "^2.1.2", - "dfa": "^1.2.0", - "fast-deep-equal": "^3.1.3", - "restructure": "^3.0.0", - "tiny-inflate": "^1.0.3", - "unicode-properties": "^1.4.0", - "unicode-trie": "^2.0.0" - } - }, - "node_modules/framer-motion": { - "version": "11.18.2", - "resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-11.18.2.tgz", - "integrity": "sha512-5F5Och7wrvtLVElIpclDT0CBzMVg3dL22B64aZwHtsIY8RB4mXICLrkajK4G9R+ieSAGcgrLeae2SeUTg2pr6w==", - "license": "MIT", - "dependencies": { - "motion-dom": "^11.18.1", - "motion-utils": "^11.18.1", - "tslib": "^2.4.0" - }, - "peerDependencies": { - "@emotion/is-prop-valid": "*", - "react": "^18.0.0 || ^19.0.0", - "react-dom": "^18.0.0 || ^19.0.0" - }, - "peerDependenciesMeta": { - "@emotion/is-prop-valid": { - "optional": true - }, - "react": { - "optional": true - }, - "react-dom": { - "optional": true - } - } - }, - "node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "hasInstallScript": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/gensync": { - "version": "1.0.0-beta.2", - "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", - "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "license": "ISC", - "engines": { - "node": "6.* || 8.* || >= 10.*" - } - }, - "node_modules/get-east-asian-width": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.4.0.tgz", - "integrity": "sha512-QZjmEOC+IT1uk6Rx0sX22V6uHWVwbdbxf1faPqJ1QhLdGgsRGCZoyaQBm/piRdJy/D2um6hM1UP7ZEeQ4EkP+Q==", - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/github-slugger": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/github-slugger/-/github-slugger-2.0.0.tgz", - "integrity": "sha512-IaOQ9puYtjrkq7Y0Ygl9KDZnrf/aiUJYUpVf89y8kyaxbRG7Y1SrX/jaumrv81vc61+kiMempujsM3Yw7w5qcw==", - "license": "ISC" - }, - "node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "license": "ISC", - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/h3": { - "version": "1.15.4", - "resolved": "https://registry.npmjs.org/h3/-/h3-1.15.4.tgz", - "integrity": "sha512-z5cFQWDffyOe4vQ9xIqNfCZdV4p//vy6fBnr8Q1AWnVZ0teurKMG66rLj++TKwKPUP3u7iMUvrvKaEUiQw2QWQ==", - "license": "MIT", - "dependencies": { - "cookie-es": "^1.2.2", - "crossws": "^0.3.5", - "defu": "^6.1.4", - "destr": "^2.0.5", - "iron-webcrypto": "^1.2.1", - "node-mock-http": "^1.0.2", - "radix3": "^1.1.2", - "ufo": "^1.6.1", - "uncrypto": "^0.1.3" - } - }, - "node_modules/hast-util-embedded": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/hast-util-embedded/-/hast-util-embedded-3.0.0.tgz", - "integrity": "sha512-naH8sld4Pe2ep03qqULEtvYr7EjrLK2QHY8KJR6RJkTUjPGObe1vnx585uzem2hGra+s1q08DZZpfgDVYRbaXA==", - "license": "MIT", - "dependencies": { - "@types/hast": "^3.0.0", - "hast-util-is-element": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/hast-util-format": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/hast-util-format/-/hast-util-format-1.1.0.tgz", - "integrity": "sha512-yY1UDz6bC9rDvCWHpx12aIBGRG7krurX0p0Fm6pT547LwDIZZiNr8a+IHDogorAdreULSEzP82Nlv5SZkHZcjA==", - "license": "MIT", - "dependencies": { - "@types/hast": "^3.0.0", - "hast-util-embedded": "^3.0.0", - "hast-util-minify-whitespace": "^1.0.0", - "hast-util-phrasing": "^3.0.0", - "hast-util-whitespace": "^3.0.0", - "html-whitespace-sensitive-tag-names": "^3.0.0", - "unist-util-visit-parents": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/hast-util-from-html": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/hast-util-from-html/-/hast-util-from-html-2.0.3.tgz", - "integrity": "sha512-CUSRHXyKjzHov8yKsQjGOElXy/3EKpyX56ELnkHH34vDVw1N1XSQ1ZcAvTyAPtGqLTuKP/uxM+aLkSPqF/EtMw==", - "license": "MIT", - "dependencies": { - "@types/hast": "^3.0.0", - "devlop": "^1.1.0", - "hast-util-from-parse5": "^8.0.0", - "parse5": "^7.0.0", - "vfile": "^6.0.0", - "vfile-message": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/hast-util-from-parse5": { - "version": "8.0.3", - "resolved": "https://registry.npmjs.org/hast-util-from-parse5/-/hast-util-from-parse5-8.0.3.tgz", - "integrity": "sha512-3kxEVkEKt0zvcZ3hCRYI8rqrgwtlIOFMWkbclACvjlDw8Li9S2hk/d51OI0nr/gIpdMHNepwgOKqZ/sy0Clpyg==", - "license": "MIT", - "dependencies": { - "@types/hast": "^3.0.0", - "@types/unist": "^3.0.0", - "devlop": "^1.0.0", - "hastscript": "^9.0.0", - "property-information": "^7.0.0", - "vfile": "^6.0.0", - "vfile-location": "^5.0.0", - "web-namespaces": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/hast-util-has-property": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/hast-util-has-property/-/hast-util-has-property-3.0.0.tgz", - "integrity": "sha512-MNilsvEKLFpV604hwfhVStK0usFY/QmM5zX16bo7EjnAEGofr5YyI37kzopBlZJkHD4t887i+q/C8/tr5Q94cA==", - "license": "MIT", - "dependencies": { - "@types/hast": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/hast-util-is-body-ok-link": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/hast-util-is-body-ok-link/-/hast-util-is-body-ok-link-3.0.1.tgz", - "integrity": "sha512-0qpnzOBLztXHbHQenVB8uNuxTnm/QBFUOmdOSsEn7GnBtyY07+ENTWVFBAnXd/zEgd9/SUG3lRY7hSIBWRgGpQ==", - "license": "MIT", - "dependencies": { - "@types/hast": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/hast-util-is-element": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/hast-util-is-element/-/hast-util-is-element-3.0.0.tgz", - "integrity": "sha512-Val9mnv2IWpLbNPqc/pUem+a7Ipj2aHacCwgNfTiK0vJKl0LF+4Ba4+v1oPHFpf3bLYmreq0/l3Gud9S5OH42g==", - "license": "MIT", - "dependencies": { - "@types/hast": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/hast-util-minify-whitespace": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/hast-util-minify-whitespace/-/hast-util-minify-whitespace-1.0.1.tgz", - "integrity": "sha512-L96fPOVpnclQE0xzdWb/D12VT5FabA7SnZOUMtL1DbXmYiHJMXZvFkIZfiMmTCNJHUeO2K9UYNXoVyfz+QHuOw==", - "license": "MIT", - "dependencies": { - "@types/hast": "^3.0.0", - "hast-util-embedded": "^3.0.0", - "hast-util-is-element": "^3.0.0", - "hast-util-whitespace": "^3.0.0", - "unist-util-is": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/hast-util-parse-selector": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/hast-util-parse-selector/-/hast-util-parse-selector-4.0.0.tgz", - "integrity": "sha512-wkQCkSYoOGCRKERFWcxMVMOcYE2K1AaNLU8DXS9arxnLOUEWbOXKXiJUNzEpqZ3JOKpnha3jkFrumEjVliDe7A==", - "license": "MIT", - "dependencies": { - "@types/hast": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/hast-util-phrasing": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/hast-util-phrasing/-/hast-util-phrasing-3.0.1.tgz", - "integrity": "sha512-6h60VfI3uBQUxHqTyMymMZnEbNl1XmEGtOxxKYL7stY2o601COo62AWAYBQR9lZbYXYSBoxag8UpPRXK+9fqSQ==", - "license": "MIT", - "dependencies": { - "@types/hast": "^3.0.0", - "hast-util-embedded": "^3.0.0", - "hast-util-has-property": "^3.0.0", - "hast-util-is-body-ok-link": "^3.0.0", - "hast-util-is-element": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/hast-util-raw": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/hast-util-raw/-/hast-util-raw-9.1.0.tgz", - "integrity": "sha512-Y8/SBAHkZGoNkpzqqfCldijcuUKh7/su31kEBp67cFY09Wy0mTRgtsLYsiIxMJxlu0f6AA5SUTbDR8K0rxnbUw==", - "license": "MIT", - "dependencies": { - "@types/hast": "^3.0.0", - "@types/unist": "^3.0.0", - "@ungap/structured-clone": "^1.0.0", - "hast-util-from-parse5": "^8.0.0", - "hast-util-to-parse5": "^8.0.0", - "html-void-elements": "^3.0.0", - "mdast-util-to-hast": "^13.0.0", - "parse5": "^7.0.0", - "unist-util-position": "^5.0.0", - "unist-util-visit": "^5.0.0", - "vfile": "^6.0.0", - "web-namespaces": "^2.0.0", - "zwitch": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/hast-util-select": { - "version": "6.0.4", - "resolved": "https://registry.npmjs.org/hast-util-select/-/hast-util-select-6.0.4.tgz", - "integrity": "sha512-RqGS1ZgI0MwxLaKLDxjprynNzINEkRHY2i8ln4DDjgv9ZhcYVIHN9rlpiYsqtFwrgpYU361SyWDQcGNIBVu3lw==", - "license": "MIT", - "dependencies": { - "@types/hast": "^3.0.0", - "@types/unist": "^3.0.0", - "bcp-47-match": "^2.0.0", - "comma-separated-tokens": "^2.0.0", - "css-selector-parser": "^3.0.0", - "devlop": "^1.0.0", - "direction": "^2.0.0", - "hast-util-has-property": "^3.0.0", - "hast-util-to-string": "^3.0.0", - "hast-util-whitespace": "^3.0.0", - "nth-check": "^2.0.0", - "property-information": "^7.0.0", - "space-separated-tokens": "^2.0.0", - "unist-util-visit": "^5.0.0", - "zwitch": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/hast-util-to-estree": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/hast-util-to-estree/-/hast-util-to-estree-3.1.3.tgz", - "integrity": "sha512-48+B/rJWAp0jamNbAAf9M7Uf//UVqAoMmgXhBdxTDJLGKY+LRnZ99qcG+Qjl5HfMpYNzS5v4EAwVEF34LeAj7w==", - "license": "MIT", - "dependencies": { - "@types/estree": "^1.0.0", - "@types/estree-jsx": "^1.0.0", - "@types/hast": "^3.0.0", - "comma-separated-tokens": "^2.0.0", - "devlop": "^1.0.0", - "estree-util-attach-comments": "^3.0.0", - "estree-util-is-identifier-name": "^3.0.0", - "hast-util-whitespace": "^3.0.0", - "mdast-util-mdx-expression": "^2.0.0", - "mdast-util-mdx-jsx": "^3.0.0", - "mdast-util-mdxjs-esm": "^2.0.0", - "property-information": "^7.0.0", - "space-separated-tokens": "^2.0.0", - "style-to-js": "^1.0.0", - "unist-util-position": "^5.0.0", - "zwitch": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/hast-util-to-html": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/hast-util-to-html/-/hast-util-to-html-9.0.5.tgz", - "integrity": "sha512-OguPdidb+fbHQSU4Q4ZiLKnzWo8Wwsf5bZfbvu7//a9oTYoqD/fWpe96NuHkoS9h0ccGOTe0C4NGXdtS0iObOw==", - "license": "MIT", - "dependencies": { - "@types/hast": "^3.0.0", - "@types/unist": "^3.0.0", - "ccount": "^2.0.0", - "comma-separated-tokens": "^2.0.0", - "hast-util-whitespace": "^3.0.0", - "html-void-elements": "^3.0.0", - "mdast-util-to-hast": "^13.0.0", - "property-information": "^7.0.0", - "space-separated-tokens": "^2.0.0", - "stringify-entities": "^4.0.0", - "zwitch": "^2.0.4" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/hast-util-to-jsx-runtime": { - "version": "2.3.6", - "resolved": "https://registry.npmjs.org/hast-util-to-jsx-runtime/-/hast-util-to-jsx-runtime-2.3.6.tgz", - "integrity": "sha512-zl6s8LwNyo1P9uw+XJGvZtdFF1GdAkOg8ujOw+4Pyb76874fLps4ueHXDhXWdk6YHQ6OgUtinliG7RsYvCbbBg==", - "license": "MIT", - "dependencies": { - "@types/estree": "^1.0.0", - "@types/hast": "^3.0.0", - "@types/unist": "^3.0.0", - "comma-separated-tokens": "^2.0.0", - "devlop": "^1.0.0", - "estree-util-is-identifier-name": "^3.0.0", - "hast-util-whitespace": "^3.0.0", - "mdast-util-mdx-expression": "^2.0.0", - "mdast-util-mdx-jsx": "^3.0.0", - "mdast-util-mdxjs-esm": "^2.0.0", - "property-information": "^7.0.0", - "space-separated-tokens": "^2.0.0", - "style-to-js": "^1.0.0", - "unist-util-position": "^5.0.0", - "vfile-message": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/hast-util-to-parse5": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/hast-util-to-parse5/-/hast-util-to-parse5-8.0.0.tgz", - "integrity": "sha512-3KKrV5ZVI8if87DVSi1vDeByYrkGzg4mEfeu4alwgmmIeARiBLKCZS2uw5Gb6nU9x9Yufyj3iudm6i7nl52PFw==", - "license": "MIT", - "dependencies": { - "@types/hast": "^3.0.0", - "comma-separated-tokens": "^2.0.0", - "devlop": "^1.0.0", - "property-information": "^6.0.0", - "space-separated-tokens": "^2.0.0", - "web-namespaces": "^2.0.0", - "zwitch": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/hast-util-to-parse5/node_modules/property-information": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/property-information/-/property-information-6.5.0.tgz", - "integrity": "sha512-PgTgs/BlvHxOu8QuEN7wi5A0OmXaBcHpmCSTehcs6Uuu9IkDIEo13Hy7n898RHfrQ49vKCoGeWZSaAK01nwVig==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/hast-util-to-string": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/hast-util-to-string/-/hast-util-to-string-3.0.1.tgz", - "integrity": "sha512-XelQVTDWvqcl3axRfI0xSeoVKzyIFPwsAGSLIsKdJKQMXDYJS4WYrBNF/8J7RdhIcFI2BOHgAifggsvsxp/3+A==", - "license": "MIT", - "dependencies": { - "@types/hast": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/hast-util-to-text": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/hast-util-to-text/-/hast-util-to-text-4.0.2.tgz", - "integrity": "sha512-KK6y/BN8lbaq654j7JgBydev7wuNMcID54lkRav1P0CaE1e47P72AWWPiGKXTJU271ooYzcvTAn/Zt0REnvc7A==", - "license": "MIT", - "dependencies": { - "@types/hast": "^3.0.0", - "@types/unist": "^3.0.0", - "hast-util-is-element": "^3.0.0", - "unist-util-find-after": "^5.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/hast-util-whitespace": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/hast-util-whitespace/-/hast-util-whitespace-3.0.0.tgz", - "integrity": "sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==", - "license": "MIT", - "dependencies": { - "@types/hast": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/hastscript": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/hastscript/-/hastscript-9.0.1.tgz", - "integrity": "sha512-g7df9rMFX/SPi34tyGCyUBREQoKkapwdY/T04Qn9TDWfHhAYt4/I0gMVirzK5wEzeUqIjEB+LXC/ypb7Aqno5w==", - "license": "MIT", - "dependencies": { - "@types/hast": "^3.0.0", - "comma-separated-tokens": "^2.0.0", - "hast-util-parse-selector": "^4.0.0", - "property-information": "^7.0.0", - "space-separated-tokens": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/html-escaper": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-3.0.3.tgz", - "integrity": "sha512-RuMffC89BOWQoY0WKGpIhn5gX3iI54O6nRA0yC124NYVtzjmFWBIiFd8M0x+ZdX0P9R4lADg1mgP8C7PxGOWuQ==", - "license": "MIT" - }, - "node_modules/html-void-elements": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/html-void-elements/-/html-void-elements-3.0.0.tgz", - "integrity": "sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/html-whitespace-sensitive-tag-names": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/html-whitespace-sensitive-tag-names/-/html-whitespace-sensitive-tag-names-3.0.1.tgz", - "integrity": "sha512-q+310vW8zmymYHALr1da4HyXUQ0zgiIwIicEfotYPWGN0OJVEN/58IJ3A4GBYcEq3LGAZqKb+ugvP0GNB9CEAA==", - "license": "MIT", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/htmlparser2": { - "version": "10.0.0", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-10.0.0.tgz", - "integrity": "sha512-TwAZM+zE5Tq3lrEHvOlvwgj1XLWQCtaaibSN11Q+gGBAS7Y1uZSWwXXRe4iF6OXnaq1riyQAPFOBtYc77Mxq0g==", - "funding": [ - "https://github.com/fb55/htmlparser2?sponsor=1", - { - "type": "github", - "url": "https://github.com/sponsors/fb55" - } - ], - "license": "MIT", - "dependencies": { - "domelementtype": "^2.3.0", - "domhandler": "^5.0.3", - "domutils": "^3.2.1", - "entities": "^6.0.0" - } - }, - "node_modules/http-cache-semantics": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz", - "integrity": "sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==", - "license": "BSD-2-Clause" - }, - "node_modules/i18next": { - "version": "23.16.8", - "resolved": "https://registry.npmjs.org/i18next/-/i18next-23.16.8.tgz", - "integrity": "sha512-06r/TitrM88Mg5FdUXAKL96dJMzgqLE5dv3ryBAra4KCwD9mJ4ndOTS95ZuymIGoE+2hzfdaMak2X11/es7ZWg==", - "funding": [ - { - "type": "individual", - "url": "https://locize.com" - }, - { - "type": "individual", - "url": "https://locize.com/i18next.html" - }, - { - "type": "individual", - "url": "https://www.i18next.com/how-to/faq#i18next-is-awesome.-how-can-i-support-the-project" - } - ], - "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.23.2" - } - }, - "node_modules/import-meta-resolve": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/import-meta-resolve/-/import-meta-resolve-4.2.0.tgz", - "integrity": "sha512-Iqv2fzaTQN28s/FwZAoFq0ZSs/7hMAHJVX+w8PZl3cY19Pxk6jFFalxQoIfW2826i/fDLXv8IiEZRIT0lDuWcg==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/inline-style-parser": { - "version": "0.2.7", - "resolved": "https://registry.npmjs.org/inline-style-parser/-/inline-style-parser-0.2.7.tgz", - "integrity": "sha512-Nb2ctOyNR8DqQoR0OwRG95uNWIC0C1lCgf5Naz5H6Ji72KZ8OcFZLz2P5sNgwlyoJ8Yif11oMuYs5pBQa86csA==", - "license": "MIT" - }, - "node_modules/iron-webcrypto": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/iron-webcrypto/-/iron-webcrypto-1.2.1.tgz", - "integrity": "sha512-feOM6FaSr6rEABp/eDfVseKyTMDt+KGpeB35SkVn9Tyn0CqvVsY3EwI0v5i8nMHyJnzCIQf7nsy3p41TPkJZhg==", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/brc-dd" - } - }, - "node_modules/is-absolute-url": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/is-absolute-url/-/is-absolute-url-4.0.1.tgz", - "integrity": "sha512-/51/TKE88Lmm7Gc4/8btclNXWS+g50wXhYJq8HWIBAGUBnoAdRu1aXeh364t/O7wXDAcTJDP8PNuNKWUDWie+A==", - "license": "MIT", - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-alphabetical": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-alphabetical/-/is-alphabetical-2.0.1.tgz", - "integrity": "sha512-FWyyY60MeTNyeSRpkM2Iry0G9hpr7/9kD40mD/cGQEuilcZYS4okz8SN2Q6rLCJ8gbCt6fN+rC+6tMGS99LaxQ==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/is-alphanumerical": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-alphanumerical/-/is-alphanumerical-2.0.1.tgz", - "integrity": "sha512-hmbYhX/9MUMF5uh7tOXyK/n0ZvWpad5caBA17GsC6vyuCqaWliRG5K1qS9inmUhEMaOBIW7/whAnSwveW/LtZw==", - "license": "MIT", - "dependencies": { - "is-alphabetical": "^2.0.0", - "is-decimal": "^2.0.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/is-arrayish": { - "version": "0.3.4", - "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.4.tgz", - "integrity": "sha512-m6UrgzFVUYawGBh1dUsWR5M2Clqic9RVXC/9f8ceNlv2IcO9j9J/z8UoCLPqtsPBFNzEpfR3xftohbfqDx8EQA==", - "license": "MIT" - }, - "node_modules/is-decimal": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-decimal/-/is-decimal-2.0.1.tgz", - "integrity": "sha512-AAB9hiomQs5DXWcRB1rqsxGUstbRroFOPPVAomNk/3XHR5JyEZChOyTWe2oayKnsSsr/kcGqF+z6yuH6HHpN0A==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/is-docker": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz", - "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==", - "license": "MIT", - "bin": { - "is-docker": "cli.js" - }, - "engines": { - "node": "^12.20.0 || ^14.13.1 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "license": "MIT", - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-hexadecimal": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-2.0.1.tgz", - "integrity": "sha512-DgZQp241c8oO6cA1SbTEWiXeoxV42vlcJxgH+B3hi1AiqqKruZR3ZGF8In3fj4+/y/7rHvlOZLZtgJ/4ttYGZg==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/is-inside-container": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz", - "integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==", - "license": "MIT", - "dependencies": { - "is-docker": "^3.0.0" - }, - "bin": { - "is-inside-container": "cli.js" - }, - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "license": "MIT", - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/is-plain-obj": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz", - "integrity": "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg==", - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-wsl": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-3.1.0.tgz", - "integrity": "sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw==", - "license": "MIT", - "dependencies": { - "is-inside-container": "^1.0.0" - }, - "engines": { - "node": ">=16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "license": "MIT" - }, - "node_modules/js-yaml": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", - "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", - "license": "MIT", - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/jsesc": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", - "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", - "license": "MIT", - "bin": { - "jsesc": "bin/jsesc" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "license": "MIT" - }, - "node_modules/json5": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", - "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", - "license": "MIT", - "bin": { - "json5": "lib/cli.js" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/jsonc-parser": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-2.3.1.tgz", - "integrity": "sha512-H8jvkz1O50L3dMZCsLqiuB2tA7muqbSg1AtGEkN0leAqGjsUzDJir3Zwr02BhqdcITPg3ei3mZ+HjMocAknhhg==", - "license": "MIT" - }, - "node_modules/kleur": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz", - "integrity": "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==", - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/klona": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/klona/-/klona-2.0.6.tgz", - "integrity": "sha512-dhG34DXATL5hSxJbIexCft8FChFXtmskoZYnoPWjXQuebWYCNkVeV3KkGegCK9CP1oswI/vQibS2GY7Em/sJJA==", - "license": "MIT", - "engines": { - "node": ">= 8" - } - }, - "node_modules/linkedom": { - "version": "0.18.12", - "resolved": "https://registry.npmjs.org/linkedom/-/linkedom-0.18.12.tgz", - "integrity": "sha512-jalJsOwIKuQJSeTvsgzPe9iJzyfVaEJiEXl+25EkKevsULHvMJzpNqwvj1jOESWdmgKDiXObyjOYwlUqG7wo1Q==", - "license": "ISC", - "dependencies": { - "css-select": "^5.1.0", - "cssom": "^0.5.0", - "html-escaper": "^3.0.3", - "htmlparser2": "^10.0.0", - "uhyphen": "^0.2.0" - }, - "engines": { - "node": ">=16" - }, - "peerDependencies": { - "canvas": ">= 2" - }, - "peerDependenciesMeta": { - "canvas": { - "optional": true - } - } - }, - "node_modules/lite-youtube-embed": { - "version": "0.3.4", - "resolved": "https://registry.npmjs.org/lite-youtube-embed/-/lite-youtube-embed-0.3.4.tgz", - "integrity": "sha512-aXgxpwK7AIW58GEbRzA8EYaY4LWvF3FKak6B9OtSJmuNyLhX2ouD4cMTxz/yR5HFInhknaYd2jLWOTRTvT8oAw==", - "license": "Apache-2.0" - }, - "node_modules/lodash": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", - "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", - "license": "MIT" - }, - "node_modules/longest-streak": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-3.1.0.tgz", - "integrity": "sha512-9Ri+o0JYgehTaVBBDoMqIl8GXtbWg711O3srftcHhZ0dqnETqLaoIK0x17fUw9rFSlK/0NlsKe0Ahhyl5pXE2g==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", - "license": "ISC", - "dependencies": { - "yallist": "^3.0.2" - } - }, - "node_modules/magic-string": { - "version": "0.30.21", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz", - "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==", - "license": "MIT", - "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.5" - } - }, - "node_modules/magicast": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/magicast/-/magicast-0.5.1.tgz", - "integrity": "sha512-xrHS24IxaLrvuo613F719wvOIv9xPHFWQHuvGUBmPnCA/3MQxKI3b+r7n1jAoDHmsbC5bRhTZYR77invLAxVnw==", - "license": "MIT", - "dependencies": { - "@babel/parser": "^7.28.5", - "@babel/types": "^7.28.5", - "source-map-js": "^1.2.1" - } - }, - "node_modules/markdown-extensions": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/markdown-extensions/-/markdown-extensions-2.0.0.tgz", - "integrity": "sha512-o5vL7aDWatOTX8LzaS1WMoaoxIiLRQJuIKKe2wAw6IeULDHaqbiqiggmx+pKvZDb1Sj+pE46Sn1T7lCqfFtg1Q==", - "license": "MIT", - "engines": { - "node": ">=16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/markdown-table": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/markdown-table/-/markdown-table-3.0.4.tgz", - "integrity": "sha512-wiYz4+JrLyb/DqW2hkFJxP7Vd7JuTDm77fvbM8VfEQdmSMqcImWeeRbHwZjBjIFki/VaMK2BhFi7oUUZeM5bqw==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/marked": { - "version": "15.0.12", - "resolved": "https://registry.npmjs.org/marked/-/marked-15.0.12.tgz", - "integrity": "sha512-8dD6FusOQSrpv9Z1rdNMdlSgQOIP880DHqnohobOmYLElGEqAL/JvxvuxZO16r4HtjTlfPRDC1hbvxC9dPN2nA==", - "license": "MIT", - "peer": true, - "bin": { - "marked": "bin/marked.js" - }, - "engines": { - "node": ">= 18" - } - }, - "node_modules/marked-footnote": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/marked-footnote/-/marked-footnote-1.4.0.tgz", - "integrity": "sha512-fZTxAhI1TcLEs5UOjCfYfTHpyKGaWQevbxaGTEA68B51l7i87SctPFtHETYqPkEN0ka5opvy4Dy1l/yXVC+hmg==", - "license": "MIT", - "peerDependencies": { - "marked": ">=7.0.0" - } - }, - "node_modules/marked-plaintify": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/marked-plaintify/-/marked-plaintify-1.1.1.tgz", - "integrity": "sha512-r3kMKArhfo2H3lD4ctFq/OJTzM0uNvXHh7FBTI1hMDpf4Ac1djjtq4g8NfTBWMxWLmaEz3KL1jCkLygik3gExA==", - "license": "MIT", - "peerDependencies": { - "marked": ">=13.0.0" - } - }, - "node_modules/marked-smartypants": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/marked-smartypants/-/marked-smartypants-1.1.11.tgz", - "integrity": "sha512-Jt0eq/6rf9oXDfEKPzQ0z7UzVWcEAK3L6QBBQzbwV8bT304OvPVLTqpH3yvkSung9foOM4s120TMHEHP76Metg==", - "license": "MIT", - "dependencies": { - "smartypants": "^0.2.2" - }, - "peerDependencies": { - "marked": ">=4 <18" - } - }, - "node_modules/mdast-util-definitions": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/mdast-util-definitions/-/mdast-util-definitions-6.0.0.tgz", - "integrity": "sha512-scTllyX6pnYNZH/AIp/0ePz6s4cZtARxImwoPJ7kS42n+MnVsI4XbnG6d4ibehRIldYMWM2LD7ImQblVhUejVQ==", - "license": "MIT", - "dependencies": { - "@types/mdast": "^4.0.0", - "@types/unist": "^3.0.0", - "unist-util-visit": "^5.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-directive": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/mdast-util-directive/-/mdast-util-directive-3.1.0.tgz", - "integrity": "sha512-I3fNFt+DHmpWCYAT7quoM6lHf9wuqtI+oCOfvILnoicNIqjh5E3dEJWiXuYME2gNe8vl1iMQwyUHa7bgFmak6Q==", - "license": "MIT", - "dependencies": { - "@types/mdast": "^4.0.0", - "@types/unist": "^3.0.0", - "ccount": "^2.0.0", - "devlop": "^1.0.0", - "mdast-util-from-markdown": "^2.0.0", - "mdast-util-to-markdown": "^2.0.0", - "parse-entities": "^4.0.0", - "stringify-entities": "^4.0.0", - "unist-util-visit-parents": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-find-and-replace": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/mdast-util-find-and-replace/-/mdast-util-find-and-replace-3.0.2.tgz", - "integrity": "sha512-Tmd1Vg/m3Xz43afeNxDIhWRtFZgM2VLyaf4vSTYwudTyeuTneoL3qtWMA5jeLyz/O1vDJmmV4QuScFCA2tBPwg==", - "license": "MIT", - "dependencies": { - "@types/mdast": "^4.0.0", - "escape-string-regexp": "^5.0.0", - "unist-util-is": "^6.0.0", - "unist-util-visit-parents": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-from-markdown": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/mdast-util-from-markdown/-/mdast-util-from-markdown-2.0.2.tgz", - "integrity": "sha512-uZhTV/8NBuw0WHkPTrCqDOl0zVe1BIng5ZtHoDk49ME1qqcjYmmLmOf0gELgcRMxN4w2iuIeVso5/6QymSrgmA==", - "license": "MIT", - "dependencies": { - "@types/mdast": "^4.0.0", - "@types/unist": "^3.0.0", - "decode-named-character-reference": "^1.0.0", - "devlop": "^1.0.0", - "mdast-util-to-string": "^4.0.0", - "micromark": "^4.0.0", - "micromark-util-decode-numeric-character-reference": "^2.0.0", - "micromark-util-decode-string": "^2.0.0", - "micromark-util-normalize-identifier": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0", - "unist-util-stringify-position": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-gfm": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/mdast-util-gfm/-/mdast-util-gfm-3.1.0.tgz", - "integrity": "sha512-0ulfdQOM3ysHhCJ1p06l0b0VKlhU0wuQs3thxZQagjcjPrlFRqY215uZGHHJan9GEAXd9MbfPjFJz+qMkVR6zQ==", - "license": "MIT", - "dependencies": { - "mdast-util-from-markdown": "^2.0.0", - "mdast-util-gfm-autolink-literal": "^2.0.0", - "mdast-util-gfm-footnote": "^2.0.0", - "mdast-util-gfm-strikethrough": "^2.0.0", - "mdast-util-gfm-table": "^2.0.0", - "mdast-util-gfm-task-list-item": "^2.0.0", - "mdast-util-to-markdown": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-gfm-autolink-literal": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/mdast-util-gfm-autolink-literal/-/mdast-util-gfm-autolink-literal-2.0.1.tgz", - "integrity": "sha512-5HVP2MKaP6L+G6YaxPNjuL0BPrq9orG3TsrZ9YXbA3vDw/ACI4MEsnoDpn6ZNm7GnZgtAcONJyPhOP8tNJQavQ==", - "license": "MIT", - "dependencies": { - "@types/mdast": "^4.0.0", - "ccount": "^2.0.0", - "devlop": "^1.0.0", - "mdast-util-find-and-replace": "^3.0.0", - "micromark-util-character": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-gfm-footnote": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mdast-util-gfm-footnote/-/mdast-util-gfm-footnote-2.1.0.tgz", - "integrity": "sha512-sqpDWlsHn7Ac9GNZQMeUzPQSMzR6Wv0WKRNvQRg0KqHh02fpTz69Qc1QSseNX29bhz1ROIyNyxExfawVKTm1GQ==", - "license": "MIT", - "dependencies": { - "@types/mdast": "^4.0.0", - "devlop": "^1.1.0", - "mdast-util-from-markdown": "^2.0.0", - "mdast-util-to-markdown": "^2.0.0", - "micromark-util-normalize-identifier": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-gfm-strikethrough": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/mdast-util-gfm-strikethrough/-/mdast-util-gfm-strikethrough-2.0.0.tgz", - "integrity": "sha512-mKKb915TF+OC5ptj5bJ7WFRPdYtuHv0yTRxK2tJvi+BDqbkiG7h7u/9SI89nRAYcmap2xHQL9D+QG/6wSrTtXg==", - "license": "MIT", - "dependencies": { - "@types/mdast": "^4.0.0", - "mdast-util-from-markdown": "^2.0.0", - "mdast-util-to-markdown": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-gfm-table": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/mdast-util-gfm-table/-/mdast-util-gfm-table-2.0.0.tgz", - "integrity": "sha512-78UEvebzz/rJIxLvE7ZtDd/vIQ0RHv+3Mh5DR96p7cS7HsBhYIICDBCu8csTNWNO6tBWfqXPWekRuj2FNOGOZg==", - "license": "MIT", - "dependencies": { - "@types/mdast": "^4.0.0", - "devlop": "^1.0.0", - "markdown-table": "^3.0.0", - "mdast-util-from-markdown": "^2.0.0", - "mdast-util-to-markdown": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-gfm-task-list-item": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/mdast-util-gfm-task-list-item/-/mdast-util-gfm-task-list-item-2.0.0.tgz", - "integrity": "sha512-IrtvNvjxC1o06taBAVJznEnkiHxLFTzgonUdy8hzFVeDun0uTjxxrRGVaNFqkU1wJR3RBPEfsxmU6jDWPofrTQ==", - "license": "MIT", - "dependencies": { - "@types/mdast": "^4.0.0", - "devlop": "^1.0.0", - "mdast-util-from-markdown": "^2.0.0", - "mdast-util-to-markdown": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-mdx": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/mdast-util-mdx/-/mdast-util-mdx-3.0.0.tgz", - "integrity": "sha512-JfbYLAW7XnYTTbUsmpu0kdBUVe+yKVJZBItEjwyYJiDJuZ9w4eeaqks4HQO+R7objWgS2ymV60GYpI14Ug554w==", - "license": "MIT", - "dependencies": { - "mdast-util-from-markdown": "^2.0.0", - "mdast-util-mdx-expression": "^2.0.0", - "mdast-util-mdx-jsx": "^3.0.0", - "mdast-util-mdxjs-esm": "^2.0.0", - "mdast-util-to-markdown": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-mdx-expression": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/mdast-util-mdx-expression/-/mdast-util-mdx-expression-2.0.1.tgz", - "integrity": "sha512-J6f+9hUp+ldTZqKRSg7Vw5V6MqjATc+3E4gf3CFNcuZNWD8XdyI6zQ8GqH7f8169MM6P7hMBRDVGnn7oHB9kXQ==", - "license": "MIT", - "dependencies": { - "@types/estree-jsx": "^1.0.0", - "@types/hast": "^3.0.0", - "@types/mdast": "^4.0.0", - "devlop": "^1.0.0", - "mdast-util-from-markdown": "^2.0.0", - "mdast-util-to-markdown": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-mdx-jsx": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/mdast-util-mdx-jsx/-/mdast-util-mdx-jsx-3.2.0.tgz", - "integrity": "sha512-lj/z8v0r6ZtsN/cGNNtemmmfoLAFZnjMbNyLzBafjzikOM+glrjNHPlf6lQDOTccj9n5b0PPihEBbhneMyGs1Q==", - "license": "MIT", - "dependencies": { - "@types/estree-jsx": "^1.0.0", - "@types/hast": "^3.0.0", - "@types/mdast": "^4.0.0", - "@types/unist": "^3.0.0", - "ccount": "^2.0.0", - "devlop": "^1.1.0", - "mdast-util-from-markdown": "^2.0.0", - "mdast-util-to-markdown": "^2.0.0", - "parse-entities": "^4.0.0", - "stringify-entities": "^4.0.0", - "unist-util-stringify-position": "^4.0.0", - "vfile-message": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-mdxjs-esm": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/mdast-util-mdxjs-esm/-/mdast-util-mdxjs-esm-2.0.1.tgz", - "integrity": "sha512-EcmOpxsZ96CvlP03NghtH1EsLtr0n9Tm4lPUJUBccV9RwUOneqSycg19n5HGzCf+10LozMRSObtVr3ee1WoHtg==", - "license": "MIT", - "dependencies": { - "@types/estree-jsx": "^1.0.0", - "@types/hast": "^3.0.0", - "@types/mdast": "^4.0.0", - "devlop": "^1.0.0", - "mdast-util-from-markdown": "^2.0.0", - "mdast-util-to-markdown": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-phrasing": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/mdast-util-phrasing/-/mdast-util-phrasing-4.1.0.tgz", - "integrity": "sha512-TqICwyvJJpBwvGAMZjj4J2n0X8QWp21b9l0o7eXyVJ25YNWYbJDVIyD1bZXE6WtV6RmKJVYmQAKWa0zWOABz2w==", - "license": "MIT", - "dependencies": { - "@types/mdast": "^4.0.0", - "unist-util-is": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-to-hast": { - "version": "13.2.0", - "resolved": "https://registry.npmjs.org/mdast-util-to-hast/-/mdast-util-to-hast-13.2.0.tgz", - "integrity": "sha512-QGYKEuUsYT9ykKBCMOEDLsU5JRObWQusAolFMeko/tYPufNkRffBAQjIE+99jbA87xv6FgmjLtwjh9wBWajwAA==", - "license": "MIT", - "dependencies": { - "@types/hast": "^3.0.0", - "@types/mdast": "^4.0.0", - "@ungap/structured-clone": "^1.0.0", - "devlop": "^1.0.0", - "micromark-util-sanitize-uri": "^2.0.0", - "trim-lines": "^3.0.0", - "unist-util-position": "^5.0.0", - "unist-util-visit": "^5.0.0", - "vfile": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-to-markdown": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/mdast-util-to-markdown/-/mdast-util-to-markdown-2.1.2.tgz", - "integrity": "sha512-xj68wMTvGXVOKonmog6LwyJKrYXZPvlwabaryTjLh9LuvovB/KAH+kvi8Gjj+7rJjsFi23nkUxRQv1KqSroMqA==", - "license": "MIT", - "dependencies": { - "@types/mdast": "^4.0.0", - "@types/unist": "^3.0.0", - "longest-streak": "^3.0.0", - "mdast-util-phrasing": "^4.0.0", - "mdast-util-to-string": "^4.0.0", - "micromark-util-classify-character": "^2.0.0", - "micromark-util-decode-string": "^2.0.0", - "unist-util-visit": "^5.0.0", - "zwitch": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdast-util-to-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/mdast-util-to-string/-/mdast-util-to-string-4.0.0.tgz", - "integrity": "sha512-0H44vDimn51F0YwvxSJSm0eCDOJTRlmN0R1yBh4HLj9wiV1Dn0QoXGbvFAWj2hSItVTlCmBF1hqKlIyUBVFLPg==", - "license": "MIT", - "dependencies": { - "@types/mdast": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/mdn-data": { - "version": "2.12.2", - "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.12.2.tgz", - "integrity": "sha512-IEn+pegP1aManZuckezWCO+XZQDplx1366JoVhTpMpBB1sPey/SbveZQUosKiKiGYjg1wH4pMlNgXbCiYgihQA==", - "license": "CC0-1.0" - }, - "node_modules/merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "license": "MIT", - "engines": { - "node": ">= 8" - } - }, - "node_modules/micromark": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/micromark/-/micromark-4.0.2.tgz", - "integrity": "sha512-zpe98Q6kvavpCr1NPVSCMebCKfD7CA2NqZ+rykeNhONIJBpc1tFKt9hucLGwha3jNTNI8lHpctWJWoimVF4PfA==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "@types/debug": "^4.0.0", - "debug": "^4.0.0", - "decode-named-character-reference": "^1.0.0", - "devlop": "^1.0.0", - "micromark-core-commonmark": "^2.0.0", - "micromark-factory-space": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-chunked": "^2.0.0", - "micromark-util-combine-extensions": "^2.0.0", - "micromark-util-decode-numeric-character-reference": "^2.0.0", - "micromark-util-encode": "^2.0.0", - "micromark-util-normalize-identifier": "^2.0.0", - "micromark-util-resolve-all": "^2.0.0", - "micromark-util-sanitize-uri": "^2.0.0", - "micromark-util-subtokenize": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-core-commonmark": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/micromark-core-commonmark/-/micromark-core-commonmark-2.0.3.tgz", - "integrity": "sha512-RDBrHEMSxVFLg6xvnXmb1Ayr2WzLAWjeSATAoxwKYJV94TeNavgoIdA0a9ytzDSVzBy2YKFK+emCPOEibLeCrg==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "decode-named-character-reference": "^1.0.0", - "devlop": "^1.0.0", - "micromark-factory-destination": "^2.0.0", - "micromark-factory-label": "^2.0.0", - "micromark-factory-space": "^2.0.0", - "micromark-factory-title": "^2.0.0", - "micromark-factory-whitespace": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-chunked": "^2.0.0", - "micromark-util-classify-character": "^2.0.0", - "micromark-util-html-tag-name": "^2.0.0", - "micromark-util-normalize-identifier": "^2.0.0", - "micromark-util-resolve-all": "^2.0.0", - "micromark-util-subtokenize": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-extension-directive": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/micromark-extension-directive/-/micromark-extension-directive-3.0.2.tgz", - "integrity": "sha512-wjcXHgk+PPdmvR58Le9d7zQYWy+vKEU9Se44p2CrCDPiLr2FMyiT4Fyb5UFKFC66wGB3kPlgD7q3TnoqPS7SZA==", - "license": "MIT", - "dependencies": { - "devlop": "^1.0.0", - "micromark-factory-space": "^2.0.0", - "micromark-factory-whitespace": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0", - "parse-entities": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/micromark-extension-gfm": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/micromark-extension-gfm/-/micromark-extension-gfm-3.0.0.tgz", - "integrity": "sha512-vsKArQsicm7t0z2GugkCKtZehqUm31oeGBV/KVSorWSy8ZlNAv7ytjFhvaryUiCUJYqs+NoE6AFhpQvBTM6Q4w==", - "license": "MIT", - "dependencies": { - "micromark-extension-gfm-autolink-literal": "^2.0.0", - "micromark-extension-gfm-footnote": "^2.0.0", - "micromark-extension-gfm-strikethrough": "^2.0.0", - "micromark-extension-gfm-table": "^2.0.0", - "micromark-extension-gfm-tagfilter": "^2.0.0", - "micromark-extension-gfm-task-list-item": "^2.0.0", - "micromark-util-combine-extensions": "^2.0.0", - "micromark-util-types": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/micromark-extension-gfm-autolink-literal": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/micromark-extension-gfm-autolink-literal/-/micromark-extension-gfm-autolink-literal-2.1.0.tgz", - "integrity": "sha512-oOg7knzhicgQ3t4QCjCWgTmfNhvQbDDnJeVu9v81r7NltNCVmhPy1fJRX27pISafdjL+SVc4d3l48Gb6pbRypw==", - "license": "MIT", - "dependencies": { - "micromark-util-character": "^2.0.0", - "micromark-util-sanitize-uri": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/micromark-extension-gfm-footnote": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/micromark-extension-gfm-footnote/-/micromark-extension-gfm-footnote-2.1.0.tgz", - "integrity": "sha512-/yPhxI1ntnDNsiHtzLKYnE3vf9JZ6cAisqVDauhp4CEHxlb4uoOTxOCJ+9s51bIB8U1N1FJ1RXOKTIlD5B/gqw==", - "license": "MIT", - "dependencies": { - "devlop": "^1.0.0", - "micromark-core-commonmark": "^2.0.0", - "micromark-factory-space": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-normalize-identifier": "^2.0.0", - "micromark-util-sanitize-uri": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/micromark-extension-gfm-strikethrough": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/micromark-extension-gfm-strikethrough/-/micromark-extension-gfm-strikethrough-2.1.0.tgz", - "integrity": "sha512-ADVjpOOkjz1hhkZLlBiYA9cR2Anf8F4HqZUO6e5eDcPQd0Txw5fxLzzxnEkSkfnD0wziSGiv7sYhk/ktvbf1uw==", - "license": "MIT", - "dependencies": { - "devlop": "^1.0.0", - "micromark-util-chunked": "^2.0.0", - "micromark-util-classify-character": "^2.0.0", - "micromark-util-resolve-all": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/micromark-extension-gfm-table": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/micromark-extension-gfm-table/-/micromark-extension-gfm-table-2.1.1.tgz", - "integrity": "sha512-t2OU/dXXioARrC6yWfJ4hqB7rct14e8f7m0cbI5hUmDyyIlwv5vEtooptH8INkbLzOatzKuVbQmAYcbWoyz6Dg==", - "license": "MIT", - "dependencies": { - "devlop": "^1.0.0", - "micromark-factory-space": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/micromark-extension-gfm-tagfilter": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-extension-gfm-tagfilter/-/micromark-extension-gfm-tagfilter-2.0.0.tgz", - "integrity": "sha512-xHlTOmuCSotIA8TW1mDIM6X2O1SiX5P9IuDtqGonFhEK0qgRI4yeC6vMxEV2dgyr2TiD+2PQ10o+cOhdVAcwfg==", - "license": "MIT", - "dependencies": { - "micromark-util-types": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/micromark-extension-gfm-task-list-item": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/micromark-extension-gfm-task-list-item/-/micromark-extension-gfm-task-list-item-2.1.0.tgz", - "integrity": "sha512-qIBZhqxqI6fjLDYFTBIa4eivDMnP+OZqsNwmQ3xNLE4Cxwc+zfQEfbs6tzAo2Hjq+bh6q5F+Z8/cksrLFYWQQw==", - "license": "MIT", - "dependencies": { - "devlop": "^1.0.0", - "micromark-factory-space": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/micromark-extension-mdx-expression": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/micromark-extension-mdx-expression/-/micromark-extension-mdx-expression-3.0.1.tgz", - "integrity": "sha512-dD/ADLJ1AeMvSAKBwO22zG22N4ybhe7kFIZ3LsDI0GlsNr2A3KYxb0LdC1u5rj4Nw+CHKY0RVdnHX8vj8ejm4Q==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "@types/estree": "^1.0.0", - "devlop": "^1.0.0", - "micromark-factory-mdx-expression": "^2.0.0", - "micromark-factory-space": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-events-to-acorn": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-extension-mdx-jsx": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/micromark-extension-mdx-jsx/-/micromark-extension-mdx-jsx-3.0.2.tgz", - "integrity": "sha512-e5+q1DjMh62LZAJOnDraSSbDMvGJ8x3cbjygy2qFEi7HCeUT4BDKCvMozPozcD6WmOt6sVvYDNBKhFSz3kjOVQ==", - "license": "MIT", - "dependencies": { - "@types/estree": "^1.0.0", - "devlop": "^1.0.0", - "estree-util-is-identifier-name": "^3.0.0", - "micromark-factory-mdx-expression": "^2.0.0", - "micromark-factory-space": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-events-to-acorn": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0", - "vfile-message": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/micromark-extension-mdx-md": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/micromark-extension-mdx-md/-/micromark-extension-mdx-md-2.0.0.tgz", - "integrity": "sha512-EpAiszsB3blw4Rpba7xTOUptcFeBFi+6PY8VnJ2hhimH+vCQDirWgsMpz7w1XcZE7LVrSAUGb9VJpG9ghlYvYQ==", - "license": "MIT", - "dependencies": { - "micromark-util-types": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/micromark-extension-mdxjs": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/micromark-extension-mdxjs/-/micromark-extension-mdxjs-3.0.0.tgz", - "integrity": "sha512-A873fJfhnJ2siZyUrJ31l34Uqwy4xIFmvPY1oj+Ean5PHcPBYzEsvqvWGaWcfEIr11O5Dlw3p2y0tZWpKHDejQ==", - "license": "MIT", - "dependencies": { - "acorn": "^8.0.0", - "acorn-jsx": "^5.0.0", - "micromark-extension-mdx-expression": "^3.0.0", - "micromark-extension-mdx-jsx": "^3.0.0", - "micromark-extension-mdx-md": "^2.0.0", - "micromark-extension-mdxjs-esm": "^3.0.0", - "micromark-util-combine-extensions": "^2.0.0", - "micromark-util-types": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/micromark-extension-mdxjs-esm": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/micromark-extension-mdxjs-esm/-/micromark-extension-mdxjs-esm-3.0.0.tgz", - "integrity": "sha512-DJFl4ZqkErRpq/dAPyeWp15tGrcrrJho1hKK5uBS70BCtfrIFg81sqcTVu3Ta+KD1Tk5vAtBNElWxtAa+m8K9A==", - "license": "MIT", - "dependencies": { - "@types/estree": "^1.0.0", - "devlop": "^1.0.0", - "micromark-core-commonmark": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-events-to-acorn": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0", - "unist-util-position-from-estree": "^2.0.0", - "vfile-message": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/micromark-factory-destination": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-factory-destination/-/micromark-factory-destination-2.0.1.tgz", - "integrity": "sha512-Xe6rDdJlkmbFRExpTOmRj9N3MaWmbAgdpSrBQvCFqhezUn4AHqJHbaEnfbVYYiexVSs//tqOdY/DxhjdCiJnIA==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "micromark-util-character": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-factory-label": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-factory-label/-/micromark-factory-label-2.0.1.tgz", - "integrity": "sha512-VFMekyQExqIW7xIChcXn4ok29YE3rnuyveW3wZQWWqF4Nv9Wk5rgJ99KzPvHjkmPXF93FXIbBp6YdW3t71/7Vg==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "devlop": "^1.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-factory-mdx-expression": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/micromark-factory-mdx-expression/-/micromark-factory-mdx-expression-2.0.3.tgz", - "integrity": "sha512-kQnEtA3vzucU2BkrIa8/VaSAsP+EJ3CKOvhMuJgOEGg9KDC6OAY6nSnNDVRiVNRqj7Y4SlSzcStaH/5jge8JdQ==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "@types/estree": "^1.0.0", - "devlop": "^1.0.0", - "micromark-factory-space": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-events-to-acorn": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0", - "unist-util-position-from-estree": "^2.0.0", - "vfile-message": "^4.0.0" - } - }, - "node_modules/micromark-factory-space": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-factory-space/-/micromark-factory-space-2.0.1.tgz", - "integrity": "sha512-zRkxjtBxxLd2Sc0d+fbnEunsTj46SWXgXciZmHq0kDYGnck/ZSGj9/wULTV95uoeYiK5hRXP2mJ98Uo4cq/LQg==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "micromark-util-character": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-factory-title": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-factory-title/-/micromark-factory-title-2.0.1.tgz", - "integrity": "sha512-5bZ+3CjhAd9eChYTHsjy6TGxpOFSKgKKJPJxr293jTbfry2KDoWkhBb6TcPVB4NmzaPhMs1Frm9AZH7OD4Cjzw==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "micromark-factory-space": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-factory-whitespace": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-factory-whitespace/-/micromark-factory-whitespace-2.0.1.tgz", - "integrity": "sha512-Ob0nuZ3PKt/n0hORHyvoD9uZhr+Za8sFoP+OnMcnWK5lngSzALgQYKMr9RJVOWLqQYuyn6ulqGWSXdwf6F80lQ==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "micromark-factory-space": "^2.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-util-character": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/micromark-util-character/-/micromark-util-character-2.1.1.tgz", - "integrity": "sha512-wv8tdUTJ3thSFFFJKtpYKOYiGP2+v96Hvk4Tu8KpCAsTMs6yi+nVmGh1syvSCsaxz45J6Jbw+9DD6g97+NV67Q==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-util-chunked": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-chunked/-/micromark-util-chunked-2.0.1.tgz", - "integrity": "sha512-QUNFEOPELfmvv+4xiNg2sRYeS/P84pTW0TCgP5zc9FpXetHY0ab7SxKyAQCNCc1eK0459uoLI1y5oO5Vc1dbhA==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "micromark-util-symbol": "^2.0.0" - } - }, - "node_modules/micromark-util-classify-character": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-classify-character/-/micromark-util-classify-character-2.0.1.tgz", - "integrity": "sha512-K0kHzM6afW/MbeWYWLjoHQv1sgg2Q9EccHEDzSkxiP/EaagNzCm7T/WMKZ3rjMbvIpvBiZgwR3dKMygtA4mG1Q==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "micromark-util-character": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-util-combine-extensions": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-combine-extensions/-/micromark-util-combine-extensions-2.0.1.tgz", - "integrity": "sha512-OnAnH8Ujmy59JcyZw8JSbK9cGpdVY44NKgSM7E9Eh7DiLS2E9RNQf0dONaGDzEG9yjEl5hcqeIsj4hfRkLH/Bg==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "micromark-util-chunked": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-util-decode-numeric-character-reference": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/micromark-util-decode-numeric-character-reference/-/micromark-util-decode-numeric-character-reference-2.0.2.tgz", - "integrity": "sha512-ccUbYk6CwVdkmCQMyr64dXz42EfHGkPQlBj5p7YVGzq8I7CtjXZJrubAYezf7Rp+bjPseiROqe7G6foFd+lEuw==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "micromark-util-symbol": "^2.0.0" - } - }, - "node_modules/micromark-util-decode-string": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-decode-string/-/micromark-util-decode-string-2.0.1.tgz", - "integrity": "sha512-nDV/77Fj6eH1ynwscYTOsbK7rR//Uj0bZXBwJZRfaLEJ1iGBR6kIfNmlNqaqJf649EP0F3NWNdeJi03elllNUQ==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "decode-named-character-reference": "^1.0.0", - "micromark-util-character": "^2.0.0", - "micromark-util-decode-numeric-character-reference": "^2.0.0", - "micromark-util-symbol": "^2.0.0" - } - }, - "node_modules/micromark-util-encode": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-encode/-/micromark-util-encode-2.0.1.tgz", - "integrity": "sha512-c3cVx2y4KqUnwopcO9b/SCdo2O67LwJJ/UyqGfbigahfegL9myoEFoDYZgkT7f36T0bLrM9hZTAaAyH+PCAXjw==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT" - }, - "node_modules/micromark-util-events-to-acorn": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/micromark-util-events-to-acorn/-/micromark-util-events-to-acorn-2.0.3.tgz", - "integrity": "sha512-jmsiEIiZ1n7X1Rr5k8wVExBQCg5jy4UXVADItHmNk1zkwEVhBuIUKRu3fqv+hs4nxLISi2DQGlqIOGiFxgbfHg==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "@types/estree": "^1.0.0", - "@types/unist": "^3.0.0", - "devlop": "^1.0.0", - "estree-util-visit": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0", - "vfile-message": "^4.0.0" - } - }, - "node_modules/micromark-util-html-tag-name": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-html-tag-name/-/micromark-util-html-tag-name-2.0.1.tgz", - "integrity": "sha512-2cNEiYDhCWKI+Gs9T0Tiysk136SnR13hhO8yW6BGNyhOC4qYFnwF1nKfD3HFAIXA5c45RrIG1ub11GiXeYd1xA==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT" - }, - "node_modules/micromark-util-normalize-identifier": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-normalize-identifier/-/micromark-util-normalize-identifier-2.0.1.tgz", - "integrity": "sha512-sxPqmo70LyARJs0w2UclACPUUEqltCkJ6PhKdMIDuJ3gSf/Q+/GIe3WKl0Ijb/GyH9lOpUkRAO2wp0GVkLvS9Q==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "micromark-util-symbol": "^2.0.0" - } - }, - "node_modules/micromark-util-resolve-all": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-resolve-all/-/micromark-util-resolve-all-2.0.1.tgz", - "integrity": "sha512-VdQyxFWFT2/FGJgwQnJYbe1jjQoNTS4RjglmSjTUlpUMa95Htx9NHeYW4rGDJzbjvCsl9eLjMQwGeElsqmzcHg==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-util-sanitize-uri": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-sanitize-uri/-/micromark-util-sanitize-uri-2.0.1.tgz", - "integrity": "sha512-9N9IomZ/YuGGZZmQec1MbgxtlgougxTodVwDzzEouPKo3qFWvymFHWcnDi2vzV1ff6kas9ucW+o3yzJK9YB1AQ==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "micromark-util-character": "^2.0.0", - "micromark-util-encode": "^2.0.0", - "micromark-util-symbol": "^2.0.0" - } - }, - "node_modules/micromark-util-subtokenize": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/micromark-util-subtokenize/-/micromark-util-subtokenize-2.1.0.tgz", - "integrity": "sha512-XQLu552iSctvnEcgXw6+Sx75GflAPNED1qx7eBJ+wydBb2KCbRZe+NwvIEEMM83uml1+2WSXpBAcp9IUCgCYWA==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT", - "dependencies": { - "devlop": "^1.0.0", - "micromark-util-chunked": "^2.0.0", - "micromark-util-symbol": "^2.0.0", - "micromark-util-types": "^2.0.0" - } - }, - "node_modules/micromark-util-symbol": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/micromark-util-symbol/-/micromark-util-symbol-2.0.1.tgz", - "integrity": "sha512-vs5t8Apaud9N28kgCrRUdEed4UJ+wWNvicHLPxCa9ENlYuAY31M0ETy5y1vA33YoNPDFTghEbnh6efaE8h4x0Q==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT" - }, - "node_modules/micromark-util-types": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/micromark-util-types/-/micromark-util-types-2.0.2.tgz", - "integrity": "sha512-Yw0ECSpJoViF1qTU4DC6NwtC4aWGt1EkzaQB8KPPyCRR8z9TWeV0HbEFGTO+ZY1wB22zmxnJqhPyTpOVCpeHTA==", - "funding": [ - { - "type": "GitHub Sponsors", - "url": "https://github.com/sponsors/unifiedjs" - }, - { - "type": "OpenCollective", - "url": "https://opencollective.com/unified" - } - ], - "license": "MIT" - }, - "node_modules/micromatch": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", - "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", - "license": "MIT", - "dependencies": { - "braces": "^3.0.3", - "picomatch": "^2.3.1" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/micromatch/node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "license": "MIT", - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/motion": { - "version": "11.18.2", - "resolved": "https://registry.npmjs.org/motion/-/motion-11.18.2.tgz", - "integrity": "sha512-JLjvFDuFr42NFtcVoMAyC2sEjnpA8xpy6qWPyzQvCloznAyQ8FIXioxWfHiLtgYhoVpfUqSWpn1h9++skj9+Wg==", - "license": "MIT", - "dependencies": { - "framer-motion": "^11.18.2", - "tslib": "^2.4.0" - }, - "peerDependencies": { - "@emotion/is-prop-valid": "*", - "react": "^18.0.0 || ^19.0.0", - "react-dom": "^18.0.0 || ^19.0.0" - }, - "peerDependenciesMeta": { - "@emotion/is-prop-valid": { - "optional": true - }, - "react": { - "optional": true - }, - "react-dom": { - "optional": true - } - } - }, - "node_modules/motion-dom": { - "version": "11.18.1", - "resolved": "https://registry.npmjs.org/motion-dom/-/motion-dom-11.18.1.tgz", - "integrity": "sha512-g76KvA001z+atjfxczdRtw/RXOM3OMSdd1f4DL77qCTF/+avrRJiawSG4yDibEQ215sr9kpinSlX2pCTJ9zbhw==", - "license": "MIT", - "dependencies": { - "motion-utils": "^11.18.1" - } - }, - "node_modules/motion-utils": { - "version": "11.18.1", - "resolved": "https://registry.npmjs.org/motion-utils/-/motion-utils-11.18.1.tgz", - "integrity": "sha512-49Kt+HKjtbJKLtgO/LKj9Ld+6vw9BjH5d9sc40R/kVyH8GLAXgT42M2NnuPcJNuA3s9ZfZBUcwIgpmZWGEE+hA==", - "license": "MIT" - }, - "node_modules/mrmime": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-2.0.1.tgz", - "integrity": "sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ==", - "license": "MIT", - "engines": { - "node": ">=10" - } - }, - "node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "license": "MIT" - }, - "node_modules/muggle-string": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/muggle-string/-/muggle-string-0.4.1.tgz", - "integrity": "sha512-VNTrAak/KhO2i8dqqnqnAHOa3cYBwXEZe9h+D5h/1ZqFSTEFHdM65lR7RoIqq3tBBYavsOXV84NoHXZ0AkPyqQ==", - "license": "MIT" - }, - "node_modules/nanoid": { - "version": "3.3.11", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", - "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "bin": { - "nanoid": "bin/nanoid.cjs" - }, - "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" - } - }, - "node_modules/neotraverse": { - "version": "0.6.18", - "resolved": "https://registry.npmjs.org/neotraverse/-/neotraverse-0.6.18.tgz", - "integrity": "sha512-Z4SmBUweYa09+o6pG+eASabEpP6QkQ70yHj351pQoEXIs8uHbaU2DWVmzBANKgflPa47A50PtB2+NgRpQvr7vA==", - "license": "MIT", - "engines": { - "node": ">= 10" - } - }, - "node_modules/nlcst-to-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/nlcst-to-string/-/nlcst-to-string-4.0.0.tgz", - "integrity": "sha512-YKLBCcUYKAg0FNlOBT6aI91qFmSiFKiluk655WzPF+DDMA02qIyy8uiRqI8QXtcFpEvll12LpL5MXqEmAZ+dcA==", - "license": "MIT", - "dependencies": { - "@types/nlcst": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/node-fetch-native": { - "version": "1.6.7", - "resolved": "https://registry.npmjs.org/node-fetch-native/-/node-fetch-native-1.6.7.tgz", - "integrity": "sha512-g9yhqoedzIUm0nTnTqAQvueMPVOuIY16bqgAJJC8XOOubYFNwz6IER9qs0Gq2Xd0+CecCKFjtdDTMA4u4xG06Q==", - "license": "MIT" - }, - "node_modules/node-mock-http": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/node-mock-http/-/node-mock-http-1.0.3.tgz", - "integrity": "sha512-jN8dK25fsfnMrVsEhluUTPkBFY+6ybu7jSB1n+ri/vOGjJxU8J9CZhpSGkHXSkFjtUhbmoncG/YG9ta5Ludqog==", - "license": "MIT" - }, - "node_modules/node-releases": { - "version": "2.0.27", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.27.tgz", - "integrity": "sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==", - "license": "MIT" - }, - "node_modules/normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/nth-check": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", - "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", - "license": "BSD-2-Clause", - "dependencies": { - "boolbase": "^1.0.0" - }, - "funding": { - "url": "https://github.com/fb55/nth-check?sponsor=1" - } - }, - "node_modules/ofetch": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/ofetch/-/ofetch-1.5.1.tgz", - "integrity": "sha512-2W4oUZlVaqAPAil6FUg/difl6YhqhUR7x2eZY4bQCko22UXg3hptq9KLQdqFClV+Wu85UX7hNtdGTngi/1BxcA==", - "license": "MIT", - "dependencies": { - "destr": "^2.0.5", - "node-fetch-native": "^1.6.7", - "ufo": "^1.6.1" - } - }, - "node_modules/ohash": { - "version": "2.0.11", - "resolved": "https://registry.npmjs.org/ohash/-/ohash-2.0.11.tgz", - "integrity": "sha512-RdR9FQrFwNBNXAr4GixM8YaRZRJ5PUWbKYbE5eOsrwAjJW0q2REGcf79oYPsLyskQCZG1PLN+S/K1V00joZAoQ==", - "license": "MIT" - }, - "node_modules/oniguruma-parser": { - "version": "0.12.1", - "resolved": "https://registry.npmjs.org/oniguruma-parser/-/oniguruma-parser-0.12.1.tgz", - "integrity": "sha512-8Unqkvk1RYc6yq2WBYRj4hdnsAxVze8i7iPfQr8e4uSP3tRv0rpZcbGUDvxfQQcdwHt/e9PrMvGCsa8OqG9X3w==", - "license": "MIT" - }, - "node_modules/oniguruma-to-es": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/oniguruma-to-es/-/oniguruma-to-es-4.3.4.tgz", - "integrity": "sha512-3VhUGN3w2eYxnTzHn+ikMI+fp/96KoRSVK9/kMTcFqj1NRDh2IhQCKvYxDnWePKRXY/AqH+Fuiyb7VHSzBjHfA==", - "license": "MIT", - "dependencies": { - "oniguruma-parser": "^0.12.1", - "regex": "^6.0.1", - "regex-recursion": "^6.0.2" - } - }, - "node_modules/p-limit": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-6.2.0.tgz", - "integrity": "sha512-kuUqqHNUqoIWp/c467RI4X6mmyuojY5jGutNU0wVTmEOOfcuwLqyMVoAi9MKi2Ak+5i9+nhmrK4ufZE8069kHA==", - "license": "MIT", - "dependencies": { - "yocto-queue": "^1.1.1" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-queue": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/p-queue/-/p-queue-8.1.1.tgz", - "integrity": "sha512-aNZ+VfjobsWryoiPnEApGGmf5WmNsCo9xu8dfaYamG5qaLP7ClhLN6NgsFe6SwJ2UbLEBK5dv9x8Mn5+RVhMWQ==", - "license": "MIT", - "dependencies": { - "eventemitter3": "^5.0.1", - "p-timeout": "^6.1.2" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-timeout": { - "version": "6.1.4", - "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-6.1.4.tgz", - "integrity": "sha512-MyIV3ZA/PmyBN/ud8vV9XzwTrNtR4jFrObymZYnZqMmW0zA8Z17vnT0rBgFE/TlohB+YCHqXMgZzb3Csp49vqg==", - "license": "MIT", - "engines": { - "node": ">=14.16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/package-manager-detector": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/package-manager-detector/-/package-manager-detector-1.5.0.tgz", - "integrity": "sha512-uBj69dVlYe/+wxj8JOpr97XfsxH/eumMt6HqjNTmJDf/6NO9s+0uxeOneIz3AsPt2m6y9PqzDzd3ATcU17MNfw==", - "license": "MIT" - }, - "node_modules/pagefind": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/pagefind/-/pagefind-1.4.0.tgz", - "integrity": "sha512-z2kY1mQlL4J8q5EIsQkLzQjilovKzfNVhX8De6oyE6uHpfFtyBaqUpcl/XzJC/4fjD8vBDyh1zolimIcVrCn9g==", - "license": "MIT", - "bin": { - "pagefind": "lib/runner/bin.cjs" - }, - "optionalDependencies": { - "@pagefind/darwin-arm64": "1.4.0", - "@pagefind/darwin-x64": "1.4.0", - "@pagefind/freebsd-x64": "1.4.0", - "@pagefind/linux-arm64": "1.4.0", - "@pagefind/linux-x64": "1.4.0", - "@pagefind/windows-x64": "1.4.0" - } - }, - "node_modules/pako": { - "version": "0.2.9", - "resolved": "https://registry.npmjs.org/pako/-/pako-0.2.9.tgz", - "integrity": "sha512-NUcwaKxUxWrZLpDG+z/xZaCgQITkA/Dv4V/T6bw7VON6l1Xz/VnrBqrYjZQ12TamKHzITTfOEIYUj48y2KXImA==", - "license": "MIT" - }, - "node_modules/parse-entities": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/parse-entities/-/parse-entities-4.0.2.tgz", - "integrity": "sha512-GG2AQYWoLgL877gQIKeRPGO1xF9+eG1ujIb5soS5gPvLQ1y2o8FL90w2QWNdf9I361Mpp7726c+lj3U0qK1uGw==", - "license": "MIT", - "dependencies": { - "@types/unist": "^2.0.0", - "character-entities-legacy": "^3.0.0", - "character-reference-invalid": "^2.0.0", - "decode-named-character-reference": "^1.0.0", - "is-alphanumerical": "^2.0.0", - "is-decimal": "^2.0.0", - "is-hexadecimal": "^2.0.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/parse-entities/node_modules/@types/unist": { - "version": "2.0.11", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.11.tgz", - "integrity": "sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA==", - "license": "MIT" - }, - "node_modules/parse-latin": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/parse-latin/-/parse-latin-7.0.0.tgz", - "integrity": "sha512-mhHgobPPua5kZ98EF4HWiH167JWBfl4pvAIXXdbaVohtK7a6YBOy56kvhCqduqyo/f3yrHFWmqmiMg/BkBkYYQ==", - "license": "MIT", - "dependencies": { - "@types/nlcst": "^2.0.0", - "@types/unist": "^3.0.0", - "nlcst-to-string": "^4.0.0", - "unist-util-modify-children": "^4.0.0", - "unist-util-visit-children": "^3.0.0", - "vfile": "^6.0.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/parse5": { - "version": "7.3.0", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.3.0.tgz", - "integrity": "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==", - "license": "MIT", - "dependencies": { - "entities": "^6.0.0" - }, - "funding": { - "url": "https://github.com/inikulin/parse5?sponsor=1" - } - }, - "node_modules/path-browserify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-1.0.1.tgz", - "integrity": "sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g==", - "license": "MIT" - }, - "node_modules/piccolore": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/piccolore/-/piccolore-0.1.3.tgz", - "integrity": "sha512-o8bTeDWjE086iwKrROaDf31K0qC/BENdm15/uH9usSC/uZjJOKb2YGiVHfLY4GhwsERiPI1jmwI2XrA7ACOxVw==", - "license": "ISC" - }, - "node_modules/picocolors": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", - "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", - "license": "ISC" - }, - "node_modules/picomatch": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", - "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/postcss": { - "version": "8.5.6", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", - "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "peer": true, - "dependencies": { - "nanoid": "^3.3.11", - "picocolors": "^1.1.1", - "source-map-js": "^1.2.1" - }, - "engines": { - "node": "^10 || ^12 || >=14" - } - }, - "node_modules/postcss-nested": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.2.0.tgz", - "integrity": "sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "postcss-selector-parser": "^6.1.1" - }, - "engines": { - "node": ">=12.0" - }, - "peerDependencies": { - "postcss": "^8.2.14" - } - }, - "node_modules/postcss-selector-parser": { - "version": "6.1.2", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz", - "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==", - "license": "MIT", - "dependencies": { - "cssesc": "^3.0.0", - "util-deprecate": "^1.0.2" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/prettier": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.6.2.tgz", - "integrity": "sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ==", - "license": "MIT", - "peer": true, - "bin": { - "prettier": "bin/prettier.cjs" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/prettier/prettier?sponsor=1" - } - }, - "node_modules/prismjs": { - "version": "1.30.0", - "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.30.0.tgz", - "integrity": "sha512-DEvV2ZF2r2/63V+tK8hQvrR2ZGn10srHbXviTlcv7Kpzw8jWiNTqbVgjO3IY8RxrrOUF8VPMQQFysYYYv0YZxw==", - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/prompts": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz", - "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==", - "license": "MIT", - "dependencies": { - "kleur": "^3.0.3", - "sisteransi": "^1.0.5" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/prompts/node_modules/kleur": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", - "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/property-information": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/property-information/-/property-information-7.1.0.tgz", - "integrity": "sha512-TwEZ+X+yCJmYfL7TPUOcvBZ4QfoT5YenQiJuX//0th53DE6w0xxLEtfK3iyryQFddXuvkIk51EEgrJQ0WJkOmQ==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, - "node_modules/radix3": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/radix3/-/radix3-1.1.2.tgz", - "integrity": "sha512-b484I/7b8rDEdSDKckSSBA8knMpcdsXudlE/LNL639wFoHKwLbEkQFZHWEYwDC0wa0FKUcCY+GAF73Z7wxNVFA==", - "license": "MIT" - }, - "node_modules/react": { - "version": "19.2.0", - "resolved": "https://registry.npmjs.org/react/-/react-19.2.0.tgz", - "integrity": "sha512-tmbWg6W31tQLeB5cdIBOicJDJRR2KzXsV7uSK9iNfLWQ5bIZfxuPEHp7M8wiHyHnn0DD1i7w3Zmin0FtkrwoCQ==", - "license": "MIT", - "peer": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/react-dom": { - "version": "19.2.0", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.0.tgz", - "integrity": "sha512-UlbRu4cAiGaIewkPyiRGJk0imDN2T3JjieT6spoL2UeSf5od4n5LB/mQ4ejmxhCFT1tYe8IvaFulzynWovsEFQ==", - "license": "MIT", - "peer": true, - "dependencies": { - "scheduler": "^0.27.0" - }, - "peerDependencies": { - "react": "^19.2.0" - } - }, - "node_modules/react-refresh": { - "version": "0.17.0", - "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.17.0.tgz", - "integrity": "sha512-z6F7K9bV85EfseRCp2bzrpyQ0Gkw1uLoCel9XBVWPg/TjRj94SkJzUTGfOa4bs7iJvBWtQG0Wq7wnI0syw3EBQ==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/readdirp": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", - "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", - "license": "MIT", - "engines": { - "node": ">= 14.18.0" - }, - "funding": { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/recma-build-jsx": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/recma-build-jsx/-/recma-build-jsx-1.0.0.tgz", - "integrity": "sha512-8GtdyqaBcDfva+GUKDr3nev3VpKAhup1+RvkMvUxURHpW7QyIvk9F5wz7Vzo06CEMSilw6uArgRqhpiUcWp8ew==", - "license": "MIT", - "dependencies": { - "@types/estree": "^1.0.0", - "estree-util-build-jsx": "^3.0.0", - "vfile": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/recma-jsx": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/recma-jsx/-/recma-jsx-1.0.1.tgz", - "integrity": "sha512-huSIy7VU2Z5OLv6oFLosQGGDqPqdO1iq6bWNAdhzMxSJP7RAso4fCZ1cKu8j9YHCZf3TPrq4dw3okhrylgcd7w==", - "license": "MIT", - "dependencies": { - "acorn-jsx": "^5.0.0", - "estree-util-to-js": "^2.0.0", - "recma-parse": "^1.0.0", - "recma-stringify": "^1.0.0", - "unified": "^11.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - }, - "peerDependencies": { - "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" - } - }, - "node_modules/recma-parse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/recma-parse/-/recma-parse-1.0.0.tgz", - "integrity": "sha512-OYLsIGBB5Y5wjnSnQW6t3Xg7q3fQ7FWbw/vcXtORTnyaSFscOtABg+7Pnz6YZ6c27fG1/aN8CjfwoUEUIdwqWQ==", - "license": "MIT", - "dependencies": { - "@types/estree": "^1.0.0", - "esast-util-from-js": "^2.0.0", - "unified": "^11.0.0", - "vfile": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/recma-stringify": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/recma-stringify/-/recma-stringify-1.0.0.tgz", - "integrity": "sha512-cjwII1MdIIVloKvC9ErQ+OgAtwHBmcZ0Bg4ciz78FtbT8In39aAYbaA7zvxQ61xVMSPE8WxhLwLbhif4Js2C+g==", - "license": "MIT", - "dependencies": { - "@types/estree": "^1.0.0", - "estree-util-to-js": "^2.0.0", - "unified": "^11.0.0", - "vfile": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/regex": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/regex/-/regex-6.0.1.tgz", - "integrity": "sha512-uorlqlzAKjKQZ5P+kTJr3eeJGSVroLKoHmquUj4zHWuR+hEyNqlXsSKlYYF5F4NI6nl7tWCs0apKJ0lmfsXAPA==", - "license": "MIT", - "dependencies": { - "regex-utilities": "^2.3.0" - } - }, - "node_modules/regex-recursion": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/regex-recursion/-/regex-recursion-6.0.2.tgz", - "integrity": "sha512-0YCaSCq2VRIebiaUviZNs0cBz1kg5kVS2UKUfNIx8YVs1cN3AV7NTctO5FOKBA+UT2BPJIWZauYHPqJODG50cg==", - "license": "MIT", - "dependencies": { - "regex-utilities": "^2.3.0" - } - }, - "node_modules/regex-utilities": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/regex-utilities/-/regex-utilities-2.3.0.tgz", - "integrity": "sha512-8VhliFJAWRaUiVvREIiW2NXXTmHs4vMNnSzuJVhscgmGav3g9VDxLrQndI3dZZVVdp0ZO/5v0xmX516/7M9cng==", - "license": "MIT" - }, - "node_modules/rehype": { - "version": "13.0.2", - "resolved": "https://registry.npmjs.org/rehype/-/rehype-13.0.2.tgz", - "integrity": "sha512-j31mdaRFrwFRUIlxGeuPXXKWQxet52RBQRvCmzl5eCefn/KGbomK5GMHNMsOJf55fgo3qw5tST5neDuarDYR2A==", - "license": "MIT", - "dependencies": { - "@types/hast": "^3.0.0", - "rehype-parse": "^9.0.0", - "rehype-stringify": "^10.0.0", - "unified": "^11.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/rehype-expressive-code": { - "version": "0.41.3", - "resolved": "https://registry.npmjs.org/rehype-expressive-code/-/rehype-expressive-code-0.41.3.tgz", - "integrity": "sha512-8d9Py4c/V6I/Od2VIXFAdpiO2kc0SV2qTJsRAaqSIcM9aruW4ASLNe2kOEo1inXAAkIhpFzAHTc358HKbvpNUg==", - "license": "MIT", - "dependencies": { - "expressive-code": "^0.41.3" - } - }, - "node_modules/rehype-format": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/rehype-format/-/rehype-format-5.0.1.tgz", - "integrity": "sha512-zvmVru9uB0josBVpr946OR8ui7nJEdzZobwLOOqHb/OOD88W0Vk2SqLwoVOj0fM6IPCCO6TaV9CvQvJMWwukFQ==", - "license": "MIT", - "dependencies": { - "@types/hast": "^3.0.0", - "hast-util-format": "^1.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/rehype-parse": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/rehype-parse/-/rehype-parse-9.0.1.tgz", - "integrity": "sha512-ksCzCD0Fgfh7trPDxr2rSylbwq9iYDkSn8TCDmEJ49ljEUBxDVCzCHv7QNzZOfODanX4+bWQ4WZqLCRWYLfhag==", - "license": "MIT", - "dependencies": { - "@types/hast": "^3.0.0", - "hast-util-from-html": "^2.0.0", - "unified": "^11.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/rehype-raw": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/rehype-raw/-/rehype-raw-7.0.0.tgz", - "integrity": "sha512-/aE8hCfKlQeA8LmyeyQvQF3eBiLRGNlfBJEvWH7ivp9sBqs7TNqBL5X3v157rM4IFETqDnIOO+z5M/biZbo9Ww==", - "license": "MIT", - "dependencies": { - "@types/hast": "^3.0.0", - "hast-util-raw": "^9.0.0", - "vfile": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/rehype-recma": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/rehype-recma/-/rehype-recma-1.0.0.tgz", - "integrity": "sha512-lqA4rGUf1JmacCNWWZx0Wv1dHqMwxzsDWYMTowuplHF3xH0N/MmrZ/G3BDZnzAkRmxDadujCjaKM2hqYdCBOGw==", - "license": "MIT", - "dependencies": { - "@types/estree": "^1.0.0", - "@types/hast": "^3.0.0", - "hast-util-to-estree": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/rehype-stringify": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/rehype-stringify/-/rehype-stringify-10.0.1.tgz", - "integrity": "sha512-k9ecfXHmIPuFVI61B9DeLPN0qFHfawM6RsuX48hoqlaKSF61RskNjSm1lI8PhBEM0MRdLxVVm4WmTqJQccH9mA==", - "license": "MIT", - "dependencies": { - "@types/hast": "^3.0.0", - "hast-util-to-html": "^9.0.0", - "unified": "^11.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/remark-directive": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/remark-directive/-/remark-directive-3.0.1.tgz", - "integrity": "sha512-gwglrEQEZcZYgVyG1tQuA+h58EZfq5CSULw7J90AFuCTyib1thgHPoqQ+h9iFvU6R+vnZ5oNFQR5QKgGpk741A==", - "license": "MIT", - "dependencies": { - "@types/mdast": "^4.0.0", - "mdast-util-directive": "^3.0.0", - "micromark-extension-directive": "^3.0.0", - "unified": "^11.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/remark-gfm": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/remark-gfm/-/remark-gfm-4.0.1.tgz", - "integrity": "sha512-1quofZ2RQ9EWdeN34S79+KExV1764+wCUGop5CPL1WGdD0ocPpu91lzPGbwWMECpEpd42kJGQwzRfyov9j4yNg==", - "license": "MIT", - "dependencies": { - "@types/mdast": "^4.0.0", - "mdast-util-gfm": "^3.0.0", - "micromark-extension-gfm": "^3.0.0", - "remark-parse": "^11.0.0", - "remark-stringify": "^11.0.0", - "unified": "^11.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/remark-mdx": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/remark-mdx/-/remark-mdx-3.1.1.tgz", - "integrity": "sha512-Pjj2IYlUY3+D8x00UJsIOg5BEvfMyeI+2uLPn9VO9Wg4MEtN/VTIq2NEJQfde9PnX15KgtHyl9S0BcTnWrIuWg==", - "license": "MIT", - "dependencies": { - "mdast-util-mdx": "^3.0.0", - "micromark-extension-mdxjs": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/remark-parse": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/remark-parse/-/remark-parse-11.0.0.tgz", - "integrity": "sha512-FCxlKLNGknS5ba/1lmpYijMUzX2esxW5xQqjWxw2eHFfS2MSdaHVINFmhjo+qN1WhZhNimq0dZATN9pH0IDrpA==", - "license": "MIT", - "dependencies": { - "@types/mdast": "^4.0.0", - "mdast-util-from-markdown": "^2.0.0", - "micromark-util-types": "^2.0.0", - "unified": "^11.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/remark-rehype": { - "version": "11.1.2", - "resolved": "https://registry.npmjs.org/remark-rehype/-/remark-rehype-11.1.2.tgz", - "integrity": "sha512-Dh7l57ianaEoIpzbp0PC9UKAdCSVklD8E5Rpw7ETfbTl3FqcOOgq5q2LVDhgGCkaBv7p24JXikPdvhhmHvKMsw==", - "license": "MIT", - "dependencies": { - "@types/hast": "^3.0.0", - "@types/mdast": "^4.0.0", - "mdast-util-to-hast": "^13.0.0", - "unified": "^11.0.0", - "vfile": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/remark-smartypants": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/remark-smartypants/-/remark-smartypants-3.0.2.tgz", - "integrity": "sha512-ILTWeOriIluwEvPjv67v7Blgrcx+LZOkAUVtKI3putuhlZm84FnqDORNXPPm+HY3NdZOMhyDwZ1E+eZB/Df5dA==", - "license": "MIT", - "dependencies": { - "retext": "^9.0.0", - "retext-smartypants": "^6.0.0", - "unified": "^11.0.4", - "unist-util-visit": "^5.0.0" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/remark-stringify": { - "version": "11.0.0", - "resolved": "https://registry.npmjs.org/remark-stringify/-/remark-stringify-11.0.0.tgz", - "integrity": "sha512-1OSmLd3awB/t8qdoEOMazZkNsfVTeY4fTsgzcQFdXNq8ToTN4ZGwrMnlda4K6smTFKD+GRV6O48i6Z4iKgPPpw==", - "license": "MIT", - "dependencies": { - "@types/mdast": "^4.0.0", - "mdast-util-to-markdown": "^2.0.0", - "unified": "^11.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/request-light": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/request-light/-/request-light-0.7.0.tgz", - "integrity": "sha512-lMbBMrDoxgsyO+yB3sDcrDuX85yYt7sS8BfQd11jtbW/z5ZWgLZRcEGLsLoYw7I0WSUGQBs8CC8ScIxkTX1+6Q==", - "license": "MIT" - }, - "node_modules/require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/require-from-string": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", - "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/restructure": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/restructure/-/restructure-3.0.2.tgz", - "integrity": "sha512-gSfoiOEA0VPE6Tukkrr7I0RBdE0s7H1eFCDBk05l1KIQT1UIKNc5JZy6jdyW6eYH3aR3g5b3PuL77rq0hvwtAw==", - "license": "MIT" - }, - "node_modules/retext": { - "version": "9.0.0", - "resolved": "https://registry.npmjs.org/retext/-/retext-9.0.0.tgz", - "integrity": "sha512-sbMDcpHCNjvlheSgMfEcVrZko3cDzdbe1x/e7G66dFp0Ff7Mldvi2uv6JkJQzdRcvLYE8CA8Oe8siQx8ZOgTcA==", - "license": "MIT", - "dependencies": { - "@types/nlcst": "^2.0.0", - "retext-latin": "^4.0.0", - "retext-stringify": "^4.0.0", - "unified": "^11.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/retext-latin": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/retext-latin/-/retext-latin-4.0.0.tgz", - "integrity": "sha512-hv9woG7Fy0M9IlRQloq/N6atV82NxLGveq+3H2WOi79dtIYWN8OaxogDm77f8YnVXJL2VD3bbqowu5E3EMhBYA==", - "license": "MIT", - "dependencies": { - "@types/nlcst": "^2.0.0", - "parse-latin": "^7.0.0", - "unified": "^11.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/retext-smartypants": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/retext-smartypants/-/retext-smartypants-6.2.0.tgz", - "integrity": "sha512-kk0jOU7+zGv//kfjXEBjdIryL1Acl4i9XNkHxtM7Tm5lFiCog576fjNC9hjoR7LTKQ0DsPWy09JummSsH1uqfQ==", - "license": "MIT", - "dependencies": { - "@types/nlcst": "^2.0.0", - "nlcst-to-string": "^4.0.0", - "unist-util-visit": "^5.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/retext-stringify": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/retext-stringify/-/retext-stringify-4.0.0.tgz", - "integrity": "sha512-rtfN/0o8kL1e+78+uxPTqu1Klt0yPzKuQ2BfWwwfgIUSayyzxpM1PJzkKt4V8803uB9qSy32MvI7Xep9khTpiA==", - "license": "MIT", - "dependencies": { - "@types/nlcst": "^2.0.0", - "nlcst-to-string": "^4.0.0", - "unified": "^11.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/reusify": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", - "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", - "license": "MIT", - "engines": { - "iojs": ">=1.0.0", - "node": ">=0.10.0" - } - }, - "node_modules/rollup": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.53.3.tgz", - "integrity": "sha512-w8GmOxZfBmKknvdXU1sdM9NHcoQejwF/4mNgj2JuEEdRaHwwF12K7e9eXn1nLZ07ad+du76mkVsyeb2rKGllsA==", - "license": "MIT", - "peer": true, - "dependencies": { - "@types/estree": "1.0.8" - }, - "bin": { - "rollup": "dist/bin/rollup" - }, - "engines": { - "node": ">=18.0.0", - "npm": ">=8.0.0" - }, - "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.53.3", - "@rollup/rollup-android-arm64": "4.53.3", - "@rollup/rollup-darwin-arm64": "4.53.3", - "@rollup/rollup-darwin-x64": "4.53.3", - "@rollup/rollup-freebsd-arm64": "4.53.3", - "@rollup/rollup-freebsd-x64": "4.53.3", - "@rollup/rollup-linux-arm-gnueabihf": "4.53.3", - "@rollup/rollup-linux-arm-musleabihf": "4.53.3", - "@rollup/rollup-linux-arm64-gnu": "4.53.3", - "@rollup/rollup-linux-arm64-musl": "4.53.3", - "@rollup/rollup-linux-loong64-gnu": "4.53.3", - "@rollup/rollup-linux-ppc64-gnu": "4.53.3", - "@rollup/rollup-linux-riscv64-gnu": "4.53.3", - "@rollup/rollup-linux-riscv64-musl": "4.53.3", - "@rollup/rollup-linux-s390x-gnu": "4.53.3", - "@rollup/rollup-linux-x64-gnu": "4.53.3", - "@rollup/rollup-linux-x64-musl": "4.53.3", - "@rollup/rollup-openharmony-arm64": "4.53.3", - "@rollup/rollup-win32-arm64-msvc": "4.53.3", - "@rollup/rollup-win32-ia32-msvc": "4.53.3", - "@rollup/rollup-win32-x64-gnu": "4.53.3", - "@rollup/rollup-win32-x64-msvc": "4.53.3", - "fsevents": "~2.3.2" - } - }, - "node_modules/run-parallel": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT", - "dependencies": { - "queue-microtask": "^1.2.2" - } - }, - "node_modules/sax": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.4.3.tgz", - "integrity": "sha512-yqYn1JhPczigF94DMS+shiDMjDowYO6y9+wB/4WgO0Y19jWYk0lQ4tuG5KI7kj4FTp1wxPj5IFfcrz/s1c3jjQ==", - "license": "BlueOak-1.0.0" - }, - "node_modules/scheduler": { - "version": "0.27.0", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.27.0.tgz", - "integrity": "sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==", - "license": "MIT" - }, - "node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/sharp": { - "version": "0.33.5", - "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.33.5.tgz", - "integrity": "sha512-haPVm1EkS9pgvHrQ/F3Xy+hgcuMV0Wm9vfIBSiwZ05k+xgb0PkBQpGsAA/oWdDobNaZTH5ppvHtzCFbnSEwHVw==", - "hasInstallScript": true, - "license": "Apache-2.0", - "dependencies": { - "color": "^4.2.3", - "detect-libc": "^2.0.3", - "semver": "^7.6.3" - }, - "engines": { - "node": "^18.17.0 || ^20.3.0 || >=21.0.0" - }, - "funding": { - "url": "https://opencollective.com/libvips" - }, - "optionalDependencies": { - "@img/sharp-darwin-arm64": "0.33.5", - "@img/sharp-darwin-x64": "0.33.5", - "@img/sharp-libvips-darwin-arm64": "1.0.4", - "@img/sharp-libvips-darwin-x64": "1.0.4", - "@img/sharp-libvips-linux-arm": "1.0.5", - "@img/sharp-libvips-linux-arm64": "1.0.4", - "@img/sharp-libvips-linux-s390x": "1.0.4", - "@img/sharp-libvips-linux-x64": "1.0.4", - "@img/sharp-libvips-linuxmusl-arm64": "1.0.4", - "@img/sharp-libvips-linuxmusl-x64": "1.0.4", - "@img/sharp-linux-arm": "0.33.5", - "@img/sharp-linux-arm64": "0.33.5", - "@img/sharp-linux-s390x": "0.33.5", - "@img/sharp-linux-x64": "0.33.5", - "@img/sharp-linuxmusl-arm64": "0.33.5", - "@img/sharp-linuxmusl-x64": "0.33.5", - "@img/sharp-wasm32": "0.33.5", - "@img/sharp-win32-ia32": "0.33.5", - "@img/sharp-win32-x64": "0.33.5" - } - }, - "node_modules/sharp/node_modules/semver": { - "version": "7.7.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", - "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/shiki": { - "version": "3.15.0", - "resolved": "https://registry.npmjs.org/shiki/-/shiki-3.15.0.tgz", - "integrity": "sha512-kLdkY6iV3dYbtPwS9KXU7mjfmDm25f5m0IPNFnaXO7TBPcvbUOY72PYXSuSqDzwp+vlH/d7MXpHlKO/x+QoLXw==", - "license": "MIT", - "dependencies": { - "@shikijs/core": "3.15.0", - "@shikijs/engine-javascript": "3.15.0", - "@shikijs/engine-oniguruma": "3.15.0", - "@shikijs/langs": "3.15.0", - "@shikijs/themes": "3.15.0", - "@shikijs/types": "3.15.0", - "@shikijs/vscode-textmate": "^10.0.2", - "@types/hast": "^3.0.4" - } - }, - "node_modules/simple-swizzle": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.4.tgz", - "integrity": "sha512-nAu1WFPQSMNr2Zn9PGSZK9AGn4t/y97lEm+MXTtUDwfP0ksAIX4nO+6ruD9Jwut4C49SB1Ws+fbXsm/yScWOHw==", - "license": "MIT", - "dependencies": { - "is-arrayish": "^0.3.1" - } - }, - "node_modules/sisteransi": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", - "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", - "license": "MIT" - }, - "node_modules/sitemap": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/sitemap/-/sitemap-8.0.2.tgz", - "integrity": "sha512-LwktpJcyZDoa0IL6KT++lQ53pbSrx2c9ge41/SeLTyqy2XUNA6uR4+P9u5IVo5lPeL2arAcOKn1aZAxoYbCKlQ==", - "license": "MIT", - "dependencies": { - "@types/node": "^17.0.5", - "@types/sax": "^1.2.1", - "arg": "^5.0.0", - "sax": "^1.4.1" - }, - "bin": { - "sitemap": "dist/cli.js" - }, - "engines": { - "node": ">=14.0.0", - "npm": ">=6.0.0" - } - }, - "node_modules/sitemap/node_modules/@types/node": { - "version": "17.0.45", - "resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.45.tgz", - "integrity": "sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw==", - "license": "MIT" - }, - "node_modules/smartypants": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/smartypants/-/smartypants-0.2.2.tgz", - "integrity": "sha512-TzobUYoEft/xBtb2voRPryAUIvYguG0V7Tt3de79I1WfXgCwelqVsGuZSnu3GFGRZhXR90AeEYIM+icuB/S06Q==", - "license": "BSD-3-Clause", - "bin": { - "smartypants": "bin/smartypants.js", - "smartypantsu": "bin/smartypantsu.js" - } - }, - "node_modules/smol-toml": { - "version": "1.5.2", - "resolved": "https://registry.npmjs.org/smol-toml/-/smol-toml-1.5.2.tgz", - "integrity": "sha512-QlaZEqcAH3/RtNyet1IPIYPsEWAaYyXXv1Krsi+1L/QHppjX4Ifm8MQsBISz9vE8cHicIq3clogsheili5vhaQ==", - "license": "BSD-3-Clause", - "engines": { - "node": ">= 18" - }, - "funding": { - "url": "https://github.com/sponsors/cyyynthia" - } - }, - "node_modules/source-map": { - "version": "0.7.6", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.6.tgz", - "integrity": "sha512-i5uvt8C3ikiWeNZSVZNWcfZPItFQOsYTUAOkcUPGd8DqDy1uOUikjt5dG+uRlwyvR108Fb9DOd4GvXfT0N2/uQ==", - "license": "BSD-3-Clause", - "engines": { - "node": ">= 12" - } - }, - "node_modules/source-map-js": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", - "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/space-separated-tokens": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/space-separated-tokens/-/space-separated-tokens-2.0.2.tgz", - "integrity": "sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/starlight-blog": { - "version": "0.25.1", - "resolved": "https://registry.npmjs.org/starlight-blog/-/starlight-blog-0.25.1.tgz", - "integrity": "sha512-T/4x+9brr0r2QbhxQIdesvsSuOdqLNFtE/MGhoDyGt73KdBTT3EPUq/CgKY+yTWq1QhKtw/GzMox6qbsqEBHXA==", - "license": "MIT", - "dependencies": { - "@astrojs/markdown-remark": "^6.3.1", - "@astrojs/mdx": "^4.0.8", - "@astrojs/rss": "^4.0.11", - "astro-remote": "^0.3.3", - "github-slugger": "^2.0.0", - "hast-util-from-html": "^2.0.3", - "hast-util-to-html": "^9.0.5", - "hast-util-to-string": "^3.0.1", - "marked": "^15.0.4", - "marked-plaintify": "^1.1.1", - "mdast-util-mdx-expression": "^2.0.1", - "unist-util-is": "^6.0.0", - "unist-util-remove": "^4.0.0", - "unist-util-visit": "^5.0.0" - }, - "engines": { - "node": ">=18.20.8" - }, - "peerDependencies": { - "@astrojs/starlight": ">=0.33.0" - } - }, - "node_modules/starlight-image-zoom": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/starlight-image-zoom/-/starlight-image-zoom-0.9.0.tgz", - "integrity": "sha512-XG87T80g5hsT6dvtNk9OKx0gD+M8lsloVTApQYnxdc3JD8lQBfu2kCsrwkyrwXZRtV7JRyd0PDHwx1UFmGmI1g==", - "license": "MIT", - "dependencies": { - "rehype-raw": "7.0.0", - "unist-util-visit": "5.0.0", - "unist-util-visit-parents": "6.0.1" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@astrojs/starlight": ">=0.22.0" - } - }, - "node_modules/starlight-image-zoom/node_modules/unist-util-visit-parents": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.1.tgz", - "integrity": "sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw==", - "license": "MIT", - "dependencies": { - "@types/unist": "^3.0.0", - "unist-util-is": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/starlight-links-validator": { - "version": "0.13.4", - "resolved": "https://registry.npmjs.org/starlight-links-validator/-/starlight-links-validator-0.13.4.tgz", - "integrity": "sha512-LdmLbJyPHVrSUhcuxiP3pJNnW8zRcOg/32C996Ic0LOCKbB8vylqHLvAMdIhT67FvEV4eAROun+2wTVU2J156A==", - "license": "MIT", - "dependencies": { - "@types/picomatch": "2.3.3", - "github-slugger": "2.0.0", - "hast-util-from-html": "2.0.1", - "hast-util-has-property": "3.0.0", - "is-absolute-url": "4.0.1", - "kleur": "4.1.5", - "mdast-util-to-string": "4.0.0", - "picomatch": "4.0.2", - "unist-util-visit": "5.0.0" - }, - "engines": { - "node": ">=18.14.1" - }, - "peerDependencies": { - "@astrojs/starlight": ">=0.15.0", - "astro": ">=4.0.0" - } - }, - "node_modules/starlight-links-validator/node_modules/hast-util-from-html": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/hast-util-from-html/-/hast-util-from-html-2.0.1.tgz", - "integrity": "sha512-RXQBLMl9kjKVNkJTIO6bZyb2n+cUH8LFaSSzo82jiLT6Tfc+Pt7VQCS+/h3YwG4jaNE2TA2sdJisGWR+aJrp0g==", - "license": "MIT", - "dependencies": { - "@types/hast": "^3.0.0", - "devlop": "^1.1.0", - "hast-util-from-parse5": "^8.0.0", - "parse5": "^7.0.0", - "vfile": "^6.0.0", - "vfile-message": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/starlight-links-validator/node_modules/picomatch": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", - "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/starlight-showcases": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/starlight-showcases/-/starlight-showcases-0.2.0.tgz", - "integrity": "sha512-YWJuTqArkUdVJV85VKZJ0BvKCQRu1SKtH/Cr5t6G/oIfI4IptWc92E7BmiuNnpuQ2U7TczTRidCYurPrbgQQVA==", - "license": "MIT", - "dependencies": { - "@astro-community/astro-embed-twitter": "^0.5.4", - "@astro-community/astro-embed-youtube": "^0.5.2" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "@astrojs/starlight": ">=0.23.0" - } - }, - "node_modules/stream-replace-string": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/stream-replace-string/-/stream-replace-string-2.0.0.tgz", - "integrity": "sha512-TlnjJ1C0QrmxRNrON00JvaFFlNh5TTG00APw23j74ET7gkQpTASi6/L2fuiav8pzK715HXtUeClpBTw2NPSn6w==", - "license": "MIT" - }, - "node_modules/string-width": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", - "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", - "license": "MIT", - "dependencies": { - "emoji-regex": "^10.3.0", - "get-east-asian-width": "^1.0.0", - "strip-ansi": "^7.1.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/stringify-entities": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-4.0.4.tgz", - "integrity": "sha512-IwfBptatlO+QCJUo19AqvrPNqlVMpW9YEL2LIVY+Rpv2qsjCGxaDLNRgeGsQWJhfItebuJhsGSLjaBbNSQ+ieg==", - "license": "MIT", - "dependencies": { - "character-entities-html4": "^2.0.0", - "character-entities-legacy": "^3.0.0" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/strip-ansi": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.2.tgz", - "integrity": "sha512-gmBGslpoQJtgnMAvOVqGZpEz9dyoKTCzy2nfz/n8aIFhN/jCE/rCmcxabB6jOOHV+0WNnylOxaxBQPSvcWklhA==", - "license": "MIT", - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "node_modules/strnum": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/strnum/-/strnum-2.1.1.tgz", - "integrity": "sha512-7ZvoFTiCnGxBtDqJ//Cu6fWtZtc7Y3x+QOirG15wztbdngGSkht27o2pyGWrVy0b4WAy3jbKmnoK6g5VlVNUUw==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/NaturalIntelligence" - } - ], - "license": "MIT" - }, - "node_modules/style-to-js": { - "version": "1.1.21", - "resolved": "https://registry.npmjs.org/style-to-js/-/style-to-js-1.1.21.tgz", - "integrity": "sha512-RjQetxJrrUJLQPHbLku6U/ocGtzyjbJMP9lCNK7Ag0CNh690nSH8woqWH9u16nMjYBAok+i7JO1NP2pOy8IsPQ==", - "license": "MIT", - "dependencies": { - "style-to-object": "1.0.14" - } - }, - "node_modules/style-to-object": { - "version": "1.0.14", - "resolved": "https://registry.npmjs.org/style-to-object/-/style-to-object-1.0.14.tgz", - "integrity": "sha512-LIN7rULI0jBscWQYaSswptyderlarFkjQ+t79nzty8tcIAceVomEVlLzH5VP4Cmsv6MtKhs7qaAiwlcp+Mgaxw==", - "license": "MIT", - "dependencies": { - "inline-style-parser": "0.2.7" - } - }, - "node_modules/svgo": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/svgo/-/svgo-4.0.0.tgz", - "integrity": "sha512-VvrHQ+9uniE+Mvx3+C9IEe/lWasXCU0nXMY2kZeLrHNICuRiC8uMPyM14UEaMOFA5mhyQqEkB02VoQ16n3DLaw==", - "license": "MIT", - "dependencies": { - "commander": "^11.1.0", - "css-select": "^5.1.0", - "css-tree": "^3.0.1", - "css-what": "^6.1.0", - "csso": "^5.0.5", - "picocolors": "^1.1.1", - "sax": "^1.4.1" - }, - "bin": { - "svgo": "bin/svgo.js" - }, - "engines": { - "node": ">=16" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/svgo" - } - }, - "node_modules/tiny-inflate": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/tiny-inflate/-/tiny-inflate-1.0.3.tgz", - "integrity": "sha512-pkY1fj1cKHb2seWDy0B16HeWyczlJA9/WW3u3c4z/NiWDsO3DOU5D7nhTLE9CF0yXv/QZFY7sEJmj24dK+Rrqw==", - "license": "MIT" - }, - "node_modules/tinyexec": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.0.2.tgz", - "integrity": "sha512-W/KYk+NFhkmsYpuHq5JykngiOCnxeVL8v8dFnqxSD8qEEdRfXk1SDM6JzNqcERbcGYj9tMrDQBYV9cjgnunFIg==", - "license": "MIT", - "engines": { - "node": ">=18" - } - }, - "node_modules/tinyglobby": { - "version": "0.2.15", - "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", - "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", - "license": "MIT", - "dependencies": { - "fdir": "^6.5.0", - "picomatch": "^4.0.3" - }, - "engines": { - "node": ">=12.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/SuperchupuDev" - } - }, - "node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "license": "MIT", - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/trim-lines": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/trim-lines/-/trim-lines-3.0.1.tgz", - "integrity": "sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/trough": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/trough/-/trough-2.2.0.tgz", - "integrity": "sha512-tmMpK00BjZiUyVyvrBK7knerNgmgvcV/KLVyuma/SC+TQN167GrMRciANTz09+k3zW8L8t60jWO1GpfkZdjTaw==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/tsconfck": { - "version": "3.1.6", - "resolved": "https://registry.npmjs.org/tsconfck/-/tsconfck-3.1.6.tgz", - "integrity": "sha512-ks6Vjr/jEw0P1gmOVwutM3B7fWxoWBL2KRDb1JfqGVawBmO5UsvmWOQFGHBPl5yxYz4eERr19E6L7NMv+Fej4w==", - "license": "MIT", - "bin": { - "tsconfck": "bin/tsconfck.js" - }, - "engines": { - "node": "^18 || >=20" - }, - "peerDependencies": { - "typescript": "^5.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "license": "0BSD" - }, - "node_modules/type-fest": { - "version": "4.41.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz", - "integrity": "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==", - "license": "(MIT OR CC0-1.0)", - "engines": { - "node": ">=16" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/typesafe-path": { - "version": "0.2.2", - "resolved": "https://registry.npmjs.org/typesafe-path/-/typesafe-path-0.2.2.tgz", - "integrity": "sha512-OJabfkAg1WLZSqJAJ0Z6Sdt3utnbzr/jh+NAHoyWHJe8CMSy79Gm085094M9nvTPy22KzTVn5Zq5mbapCI/hPA==", - "license": "MIT" - }, - "node_modules/typescript": { - "version": "5.9.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", - "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", - "license": "Apache-2.0", - "peer": true, - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=14.17" - } - }, - "node_modules/typescript-auto-import-cache": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/typescript-auto-import-cache/-/typescript-auto-import-cache-0.3.6.tgz", - "integrity": "sha512-RpuHXrknHdVdK7wv/8ug3Fr0WNsNi5l5aB8MYYuXhq2UH5lnEB1htJ1smhtD5VeCsGr2p8mUDtd83LCQDFVgjQ==", - "license": "MIT", - "dependencies": { - "semver": "^7.3.8" - } - }, - "node_modules/typescript-auto-import-cache/node_modules/semver": { - "version": "7.7.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", - "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/ufo": { - "version": "1.6.1", - "resolved": "https://registry.npmjs.org/ufo/-/ufo-1.6.1.tgz", - "integrity": "sha512-9a4/uxlTWJ4+a5i0ooc1rU7C7YOw3wT+UGqdeNNHWnOF9qcMBgLRS+4IYUqbczewFx4mLEig6gawh7X6mFlEkA==", - "license": "MIT" - }, - "node_modules/uhyphen": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/uhyphen/-/uhyphen-0.2.0.tgz", - "integrity": "sha512-qz3o9CHXmJJPGBdqzab7qAYuW8kQGKNEuoHFYrBwV6hWIMcpAmxDLXojcHfFr9US1Pe6zUswEIJIbLI610fuqA==", - "license": "ISC" - }, - "node_modules/ultrahtml": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/ultrahtml/-/ultrahtml-1.6.0.tgz", - "integrity": "sha512-R9fBn90VTJrqqLDwyMph+HGne8eqY1iPfYhPzZrvKpIfwkWZbcYlfpsb8B9dTvBfpy1/hqAD7Wi8EKfP9e8zdw==", - "license": "MIT" - }, - "node_modules/uncrypto": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/uncrypto/-/uncrypto-0.1.3.tgz", - "integrity": "sha512-Ql87qFHB3s/De2ClA9e0gsnS6zXG27SkTiSJwjCc9MebbfapQfuPzumMIUMi38ezPZVNFcHI9sUIepeQfw8J8Q==", - "license": "MIT" - }, - "node_modules/undici-types": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz", - "integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==", - "license": "MIT" - }, - "node_modules/unicode-properties": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/unicode-properties/-/unicode-properties-1.4.1.tgz", - "integrity": "sha512-CLjCCLQ6UuMxWnbIylkisbRj31qxHPAurvena/0iwSVbQ2G1VY5/HjV0IRabOEbDHlzZlRdCrD4NhB0JtU40Pg==", - "license": "MIT", - "dependencies": { - "base64-js": "^1.3.0", - "unicode-trie": "^2.0.0" - } - }, - "node_modules/unicode-trie": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unicode-trie/-/unicode-trie-2.0.0.tgz", - "integrity": "sha512-x7bc76x0bm4prf1VLg79uhAzKw8DVboClSN5VxJuQ+LKDOVEW9CdH+VY7SP+vX7xCYQqzzgQpFqz15zeLvAtZQ==", - "license": "MIT", - "dependencies": { - "pako": "^0.2.5", - "tiny-inflate": "^1.0.0" - } - }, - "node_modules/unified": { - "version": "11.0.5", - "resolved": "https://registry.npmjs.org/unified/-/unified-11.0.5.tgz", - "integrity": "sha512-xKvGhPWw3k84Qjh8bI3ZeJjqnyadK+GEFtazSfZv/rKeTkTjOJho6mFqh2SM96iIcZokxiOpg78GazTSg8+KHA==", - "license": "MIT", - "dependencies": { - "@types/unist": "^3.0.0", - "bail": "^2.0.0", - "devlop": "^1.0.0", - "extend": "^3.0.0", - "is-plain-obj": "^4.0.0", - "trough": "^2.0.0", - "vfile": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/unifont": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/unifont/-/unifont-0.6.0.tgz", - "integrity": "sha512-5Fx50fFQMQL5aeHyWnZX9122sSLckcDvcfFiBf3QYeHa7a1MKJooUy52b67moi2MJYkrfo/TWY+CoLdr/w0tTA==", - "license": "MIT", - "dependencies": { - "css-tree": "^3.0.0", - "ofetch": "^1.4.1", - "ohash": "^2.0.0" - } - }, - "node_modules/unist-util-find-after": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/unist-util-find-after/-/unist-util-find-after-5.0.0.tgz", - "integrity": "sha512-amQa0Ep2m6hE2g72AugUItjbuM8X8cGQnFoHk0pGfrFeT9GZhzN5SW8nRsiGKK7Aif4CrACPENkA6P/Lw6fHGQ==", - "license": "MIT", - "dependencies": { - "@types/unist": "^3.0.0", - "unist-util-is": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/unist-util-is": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/unist-util-is/-/unist-util-is-6.0.1.tgz", - "integrity": "sha512-LsiILbtBETkDz8I9p1dQ0uyRUWuaQzd/cuEeS1hoRSyW5E5XGmTzlwY1OrNzzakGowI9Dr/I8HVaw4hTtnxy8g==", - "license": "MIT", - "dependencies": { - "@types/unist": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/unist-util-modify-children": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/unist-util-modify-children/-/unist-util-modify-children-4.0.0.tgz", - "integrity": "sha512-+tdN5fGNddvsQdIzUF3Xx82CU9sMM+fA0dLgR9vOmT0oPT2jH+P1nd5lSqfCfXAw+93NhcXNY2qqvTUtE4cQkw==", - "license": "MIT", - "dependencies": { - "@types/unist": "^3.0.0", - "array-iterate": "^2.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/unist-util-position": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/unist-util-position/-/unist-util-position-5.0.0.tgz", - "integrity": "sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==", - "license": "MIT", - "dependencies": { - "@types/unist": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/unist-util-position-from-estree": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unist-util-position-from-estree/-/unist-util-position-from-estree-2.0.0.tgz", - "integrity": "sha512-KaFVRjoqLyF6YXCbVLNad/eS4+OfPQQn2yOd7zF/h5T/CSL2v8NpN6a5TPvtbXthAGw5nG+PuTtq+DdIZr+cRQ==", - "license": "MIT", - "dependencies": { - "@types/unist": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/unist-util-remove": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/unist-util-remove/-/unist-util-remove-4.0.0.tgz", - "integrity": "sha512-b4gokeGId57UVRX/eVKej5gXqGlc9+trkORhFJpu9raqZkZhU0zm8Doi05+HaiBsMEIJowL+2WtQ5ItjsngPXg==", - "license": "MIT", - "dependencies": { - "@types/unist": "^3.0.0", - "unist-util-is": "^6.0.0", - "unist-util-visit-parents": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/unist-util-remove-position": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/unist-util-remove-position/-/unist-util-remove-position-5.0.0.tgz", - "integrity": "sha512-Hp5Kh3wLxv0PHj9m2yZhhLt58KzPtEYKQQ4yxfYFEO7EvHwzyDYnduhHnY1mDxoqr7VUwVuHXk9RXKIiYS1N8Q==", - "license": "MIT", - "dependencies": { - "@types/unist": "^3.0.0", - "unist-util-visit": "^5.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/unist-util-stringify-position": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/unist-util-stringify-position/-/unist-util-stringify-position-4.0.0.tgz", - "integrity": "sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==", - "license": "MIT", - "dependencies": { - "@types/unist": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/unist-util-visit": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/unist-util-visit/-/unist-util-visit-5.0.0.tgz", - "integrity": "sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==", - "license": "MIT", - "dependencies": { - "@types/unist": "^3.0.0", - "unist-util-is": "^6.0.0", - "unist-util-visit-parents": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/unist-util-visit-children": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/unist-util-visit-children/-/unist-util-visit-children-3.0.0.tgz", - "integrity": "sha512-RgmdTfSBOg04sdPcpTSD1jzoNBjt9a80/ZCzp5cI9n1qPzLZWF9YdvWGN2zmTumP1HWhXKdUWexjy/Wy/lJ7tA==", - "license": "MIT", - "dependencies": { - "@types/unist": "^3.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/unist-util-visit-parents": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/unist-util-visit-parents/-/unist-util-visit-parents-6.0.2.tgz", - "integrity": "sha512-goh1s1TBrqSqukSc8wrjwWhL0hiJxgA8m4kFxGlQ+8FYQ3C/m11FcTs4YYem7V664AhHVvgoQLk890Ssdsr2IQ==", - "license": "MIT", - "dependencies": { - "@types/unist": "^3.0.0", - "unist-util-is": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/unstorage": { - "version": "1.17.3", - "resolved": "https://registry.npmjs.org/unstorage/-/unstorage-1.17.3.tgz", - "integrity": "sha512-i+JYyy0DoKmQ3FximTHbGadmIYb8JEpq7lxUjnjeB702bCPum0vzo6oy5Mfu0lpqISw7hCyMW2yj4nWC8bqJ3Q==", - "license": "MIT", - "dependencies": { - "anymatch": "^3.1.3", - "chokidar": "^4.0.3", - "destr": "^2.0.5", - "h3": "^1.15.4", - "lru-cache": "^10.4.3", - "node-fetch-native": "^1.6.7", - "ofetch": "^1.5.1", - "ufo": "^1.6.1" - }, - "peerDependencies": { - "@azure/app-configuration": "^1.8.0", - "@azure/cosmos": "^4.2.0", - "@azure/data-tables": "^13.3.0", - "@azure/identity": "^4.6.0", - "@azure/keyvault-secrets": "^4.9.0", - "@azure/storage-blob": "^12.26.0", - "@capacitor/preferences": "^6.0.3 || ^7.0.0", - "@deno/kv": ">=0.9.0", - "@netlify/blobs": "^6.5.0 || ^7.0.0 || ^8.1.0 || ^9.0.0 || ^10.0.0", - "@planetscale/database": "^1.19.0", - "@upstash/redis": "^1.34.3", - "@vercel/blob": ">=0.27.1", - "@vercel/functions": "^2.2.12 || ^3.0.0", - "@vercel/kv": "^1.0.1", - "aws4fetch": "^1.0.20", - "db0": ">=0.2.1", - "idb-keyval": "^6.2.1", - "ioredis": "^5.4.2", - "uploadthing": "^7.4.4" - }, - "peerDependenciesMeta": { - "@azure/app-configuration": { - "optional": true - }, - "@azure/cosmos": { - "optional": true - }, - "@azure/data-tables": { - "optional": true - }, - "@azure/identity": { - "optional": true - }, - "@azure/keyvault-secrets": { - "optional": true - }, - "@azure/storage-blob": { - "optional": true - }, - "@capacitor/preferences": { - "optional": true - }, - "@deno/kv": { - "optional": true - }, - "@netlify/blobs": { - "optional": true - }, - "@planetscale/database": { - "optional": true - }, - "@upstash/redis": { - "optional": true - }, - "@vercel/blob": { - "optional": true - }, - "@vercel/functions": { - "optional": true - }, - "@vercel/kv": { - "optional": true - }, - "aws4fetch": { - "optional": true - }, - "db0": { - "optional": true - }, - "idb-keyval": { - "optional": true - }, - "ioredis": { - "optional": true - }, - "uploadthing": { - "optional": true - } - } - }, - "node_modules/unstorage/node_modules/lru-cache": { - "version": "10.4.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", - "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", - "license": "ISC" - }, - "node_modules/update-browserslist-db": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.4.tgz", - "integrity": "sha512-q0SPT4xyU84saUX+tomz1WLkxUbuaJnR1xWt17M7fJtEJigJeWUNGUqrauFXsHnqev9y9JTRGwk13tFBuKby4A==", - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "escalade": "^3.2.0", - "picocolors": "^1.1.1" - }, - "bin": { - "update-browserslist-db": "cli.js" - }, - "peerDependencies": { - "browserslist": ">= 4.21.0" - } - }, - "node_modules/util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", - "license": "MIT" - }, - "node_modules/vfile": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/vfile/-/vfile-6.0.3.tgz", - "integrity": "sha512-KzIbH/9tXat2u30jf+smMwFCsno4wHVdNmzFyL+T/L3UGqqk6JKfVqOFOZEpZSHADH1k40ab6NUIXZq422ov3Q==", - "license": "MIT", - "dependencies": { - "@types/unist": "^3.0.0", - "vfile-message": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/vfile-location": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/vfile-location/-/vfile-location-5.0.3.tgz", - "integrity": "sha512-5yXvWDEgqeiYiBe1lbxYF7UMAIm/IcopxMHrMQDq3nvKcjPKIhZklUKL+AE7J7uApI4kwe2snsK+eI6UTj9EHg==", - "license": "MIT", - "dependencies": { - "@types/unist": "^3.0.0", - "vfile": "^6.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/vfile-message": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/vfile-message/-/vfile-message-4.0.3.tgz", - "integrity": "sha512-QTHzsGd1EhbZs4AsQ20JX1rC3cOlt/IWJruk893DfLRr57lcnOeMaWG4K0JrRta4mIJZKth2Au3mM3u03/JWKw==", - "license": "MIT", - "dependencies": { - "@types/unist": "^3.0.0", - "unist-util-stringify-position": "^4.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/unified" - } - }, - "node_modules/vite": { - "version": "6.4.1", - "resolved": "https://registry.npmjs.org/vite/-/vite-6.4.1.tgz", - "integrity": "sha512-+Oxm7q9hDoLMyJOYfUYBuHQo+dkAloi33apOPP56pzj+vsdJDzr+j1NISE5pyaAuKL4A3UD34qd0lx5+kfKp2g==", - "license": "MIT", - "peer": true, - "dependencies": { - "esbuild": "^0.25.0", - "fdir": "^6.4.4", - "picomatch": "^4.0.2", - "postcss": "^8.5.3", - "rollup": "^4.34.9", - "tinyglobby": "^0.2.13" - }, - "bin": { - "vite": "bin/vite.js" - }, - "engines": { - "node": "^18.0.0 || ^20.0.0 || >=22.0.0" - }, - "funding": { - "url": "https://github.com/vitejs/vite?sponsor=1" - }, - "optionalDependencies": { - "fsevents": "~2.3.3" - }, - "peerDependencies": { - "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", - "jiti": ">=1.21.0", - "less": "*", - "lightningcss": "^1.21.0", - "sass": "*", - "sass-embedded": "*", - "stylus": "*", - "sugarss": "*", - "terser": "^5.16.0", - "tsx": "^4.8.1", - "yaml": "^2.4.2" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - }, - "jiti": { - "optional": true - }, - "less": { - "optional": true - }, - "lightningcss": { - "optional": true - }, - "sass": { - "optional": true - }, - "sass-embedded": { - "optional": true - }, - "stylus": { - "optional": true - }, - "sugarss": { - "optional": true - }, - "terser": { - "optional": true - }, - "tsx": { - "optional": true - }, - "yaml": { - "optional": true - } - } - }, - "node_modules/vitefu": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/vitefu/-/vitefu-1.1.1.tgz", - "integrity": "sha512-B/Fegf3i8zh0yFbpzZ21amWzHmuNlLlmJT6n7bu5e+pCHUKQIfXSYokrqOBGEMMe9UG2sostKQF9mml/vYaWJQ==", - "license": "MIT", - "workspaces": [ - "tests/deps/*", - "tests/projects/*", - "tests/projects/workspace/packages/*" - ], - "peerDependencies": { - "vite": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0-beta.0" - }, - "peerDependenciesMeta": { - "vite": { - "optional": true - } - } - }, - "node_modules/volar-service-css": { - "version": "0.0.66", - "resolved": "https://registry.npmjs.org/volar-service-css/-/volar-service-css-0.0.66.tgz", - "integrity": "sha512-XrL1V9LEAHnunglYdDf/7shJbQXqKsHB+P69zPmJTqHx6hqvM9GWNbn2h7M0P/oElW8p/MTVHdfjl6C8cxdsBQ==", - "license": "MIT", - "dependencies": { - "vscode-css-languageservice": "^6.3.0", - "vscode-languageserver-textdocument": "^1.0.11", - "vscode-uri": "^3.0.8" - }, - "peerDependencies": { - "@volar/language-service": "~2.4.0" - }, - "peerDependenciesMeta": { - "@volar/language-service": { - "optional": true - } - } - }, - "node_modules/volar-service-emmet": { - "version": "0.0.66", - "resolved": "https://registry.npmjs.org/volar-service-emmet/-/volar-service-emmet-0.0.66.tgz", - "integrity": "sha512-BMPSpm6mk0DAEVdI2haxYIOt1Z2oaIZvCGtXuRu95x50a5pOSRPjdeHv2uGp1rQsq1Izigx+VR/bZUf2HcSnVQ==", - "license": "MIT", - "dependencies": { - "@emmetio/css-parser": "github:ramya-rao-a/css-parser#vscode", - "@emmetio/html-matcher": "^1.3.0", - "@vscode/emmet-helper": "^2.9.3", - "vscode-uri": "^3.0.8" - }, - "peerDependencies": { - "@volar/language-service": "~2.4.0" - }, - "peerDependenciesMeta": { - "@volar/language-service": { - "optional": true - } - } - }, - "node_modules/volar-service-html": { - "version": "0.0.66", - "resolved": "https://registry.npmjs.org/volar-service-html/-/volar-service-html-0.0.66.tgz", - "integrity": "sha512-MKKD2qM8qVZvBKBIugt00+Bm8j1ehgeX7Cm5XwgeEgdW/3PhUEEe/aeTxQGon1WJIGf2MM/cHPjZxPJOQN4WfQ==", - "license": "MIT", - "dependencies": { - "vscode-html-languageservice": "^5.3.0", - "vscode-languageserver-textdocument": "^1.0.11", - "vscode-uri": "^3.0.8" - }, - "peerDependencies": { - "@volar/language-service": "~2.4.0" - }, - "peerDependenciesMeta": { - "@volar/language-service": { - "optional": true - } - } - }, - "node_modules/volar-service-prettier": { - "version": "0.0.66", - "resolved": "https://registry.npmjs.org/volar-service-prettier/-/volar-service-prettier-0.0.66.tgz", - "integrity": "sha512-CVaQEyfmFWoq3NhNVExoyDKonPqdacmb/07w7OfTZljxLgZpDRygiHAvzBKIcenb7rKtJNHqfQJv99ULOinJBA==", - "license": "MIT", - "dependencies": { - "vscode-uri": "^3.0.8" - }, - "peerDependencies": { - "@volar/language-service": "~2.4.0", - "prettier": "^2.2 || ^3.0" - }, - "peerDependenciesMeta": { - "@volar/language-service": { - "optional": true - }, - "prettier": { - "optional": true - } - } - }, - "node_modules/volar-service-typescript": { - "version": "0.0.66", - "resolved": "https://registry.npmjs.org/volar-service-typescript/-/volar-service-typescript-0.0.66.tgz", - "integrity": "sha512-8irsfCEf86R1RqPijrU6p5NCqKDNzyJNWKM6ZXmCcJqhebtl7Hr/a0bnlr59AzqkS3Ym4PbbJZs1K/92CXTDsw==", - "license": "MIT", - "dependencies": { - "path-browserify": "^1.0.1", - "semver": "^7.6.2", - "typescript-auto-import-cache": "^0.3.5", - "vscode-languageserver-textdocument": "^1.0.11", - "vscode-nls": "^5.2.0", - "vscode-uri": "^3.0.8" - }, - "peerDependencies": { - "@volar/language-service": "~2.4.0" - }, - "peerDependenciesMeta": { - "@volar/language-service": { - "optional": true - } - } - }, - "node_modules/volar-service-typescript-twoslash-queries": { - "version": "0.0.66", - "resolved": "https://registry.npmjs.org/volar-service-typescript-twoslash-queries/-/volar-service-typescript-twoslash-queries-0.0.66.tgz", - "integrity": "sha512-PA3CyvEaBrkxJcBq+HFdks1TF1oJ8H+jTOTQUurLDRkVjmUFg8bfdya6U/dWfTsPaDSRM4m/2chwgew5zoQXfg==", - "license": "MIT", - "dependencies": { - "vscode-uri": "^3.0.8" - }, - "peerDependencies": { - "@volar/language-service": "~2.4.0" - }, - "peerDependenciesMeta": { - "@volar/language-service": { - "optional": true - } - } - }, - "node_modules/volar-service-typescript/node_modules/semver": { - "version": "7.7.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", - "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/volar-service-yaml": { - "version": "0.0.66", - "resolved": "https://registry.npmjs.org/volar-service-yaml/-/volar-service-yaml-0.0.66.tgz", - "integrity": "sha512-q6oTKD6EMEu1ws1FDjRw+cfCF69Gu51IEGM9jVbtmSZS1qQHKxMqlt2+wBInKl2D+xILtjzkWbfkjQyBYQMw7g==", - "license": "MIT", - "dependencies": { - "vscode-uri": "^3.0.8", - "yaml-language-server": "~1.19.2" - }, - "peerDependencies": { - "@volar/language-service": "~2.4.0" - }, - "peerDependenciesMeta": { - "@volar/language-service": { - "optional": true - } - } - }, - "node_modules/vscode-css-languageservice": { - "version": "6.3.8", - "resolved": "https://registry.npmjs.org/vscode-css-languageservice/-/vscode-css-languageservice-6.3.8.tgz", - "integrity": "sha512-dBk/9ullEjIMbfSYAohGpDOisOVU1x2MQHOeU12ohGJQI7+r0PCimBwaa/pWpxl/vH4f7ibrBfxIZY3anGmHKQ==", - "license": "MIT", - "dependencies": { - "@vscode/l10n": "^0.0.18", - "vscode-languageserver-textdocument": "^1.0.12", - "vscode-languageserver-types": "3.17.5", - "vscode-uri": "^3.1.0" - } - }, - "node_modules/vscode-html-languageservice": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/vscode-html-languageservice/-/vscode-html-languageservice-5.6.0.tgz", - "integrity": "sha512-FIVz83oGw2tBkOr8gQPeiREInnineCKGCz3ZD1Pi6opOuX3nSRkc4y4zLLWsuop+6ttYX//XZCI6SLzGhRzLmA==", - "license": "MIT", - "dependencies": { - "@vscode/l10n": "^0.0.18", - "vscode-languageserver-textdocument": "^1.0.12", - "vscode-languageserver-types": "^3.17.5", - "vscode-uri": "^3.1.0" - } - }, - "node_modules/vscode-json-languageservice": { - "version": "4.1.8", - "resolved": "https://registry.npmjs.org/vscode-json-languageservice/-/vscode-json-languageservice-4.1.8.tgz", - "integrity": "sha512-0vSpg6Xd9hfV+eZAaYN63xVVMOTmJ4GgHxXnkLCh+9RsQBkWKIghzLhW2B9ebfG+LQQg8uLtsQ2aUKjTgE+QOg==", - "license": "MIT", - "dependencies": { - "jsonc-parser": "^3.0.0", - "vscode-languageserver-textdocument": "^1.0.1", - "vscode-languageserver-types": "^3.16.0", - "vscode-nls": "^5.0.0", - "vscode-uri": "^3.0.2" - }, - "engines": { - "npm": ">=7.0.0" - } - }, - "node_modules/vscode-json-languageservice/node_modules/jsonc-parser": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.3.1.tgz", - "integrity": "sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==", - "license": "MIT" - }, - "node_modules/vscode-jsonrpc": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/vscode-jsonrpc/-/vscode-jsonrpc-8.2.0.tgz", - "integrity": "sha512-C+r0eKJUIfiDIfwJhria30+TYWPtuHJXHtI7J0YlOmKAo7ogxP20T0zxB7HZQIFhIyvoBPwWskjxrvAtfjyZfA==", - "license": "MIT", - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/vscode-languageserver": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/vscode-languageserver/-/vscode-languageserver-9.0.1.tgz", - "integrity": "sha512-woByF3PDpkHFUreUa7Hos7+pUWdeWMXRd26+ZX2A8cFx6v/JPTtd4/uN0/jB6XQHYaOlHbio03NTHCqrgG5n7g==", - "license": "MIT", - "dependencies": { - "vscode-languageserver-protocol": "3.17.5" - }, - "bin": { - "installServerIntoExtension": "bin/installServerIntoExtension" - } - }, - "node_modules/vscode-languageserver-protocol": { - "version": "3.17.5", - "resolved": "https://registry.npmjs.org/vscode-languageserver-protocol/-/vscode-languageserver-protocol-3.17.5.tgz", - "integrity": "sha512-mb1bvRJN8SVznADSGWM9u/b07H7Ecg0I3OgXDuLdn307rl/J3A9YD6/eYOssqhecL27hK1IPZAsaqh00i/Jljg==", - "license": "MIT", - "dependencies": { - "vscode-jsonrpc": "8.2.0", - "vscode-languageserver-types": "3.17.5" - } - }, - "node_modules/vscode-languageserver-textdocument": { - "version": "1.0.12", - "resolved": "https://registry.npmjs.org/vscode-languageserver-textdocument/-/vscode-languageserver-textdocument-1.0.12.tgz", - "integrity": "sha512-cxWNPesCnQCcMPeenjKKsOCKQZ/L6Tv19DTRIGuLWe32lyzWhihGVJ/rcckZXJxfdKCFvRLS3fpBIsV/ZGX4zA==", - "license": "MIT" - }, - "node_modules/vscode-languageserver-types": { - "version": "3.17.5", - "resolved": "https://registry.npmjs.org/vscode-languageserver-types/-/vscode-languageserver-types-3.17.5.tgz", - "integrity": "sha512-Ld1VelNuX9pdF39h2Hgaeb5hEZM2Z3jUrrMgWQAu82jMtZp7p3vJT3BzToKtZI7NgQssZje5o0zryOrhQvzQAg==", - "license": "MIT" - }, - "node_modules/vscode-nls": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/vscode-nls/-/vscode-nls-5.2.0.tgz", - "integrity": "sha512-RAaHx7B14ZU04EU31pT+rKz2/zSl7xMsfIZuo8pd+KZO6PXtQmpevpq3vxvWNcrGbdmhM/rr5Uw5Mz+NBfhVng==", - "license": "MIT" - }, - "node_modules/vscode-uri": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/vscode-uri/-/vscode-uri-3.1.0.tgz", - "integrity": "sha512-/BpdSx+yCQGnCvecbyXdxHDkuk55/G3xwnC0GqY4gmQ3j+A+g8kzzgB4Nk/SINjqn6+waqw3EgbVF2QKExkRxQ==", - "license": "MIT" - }, - "node_modules/web-namespaces": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/web-namespaces/-/web-namespaces-2.0.1.tgz", - "integrity": "sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - }, - "node_modules/which-pm-runs": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/which-pm-runs/-/which-pm-runs-1.1.0.tgz", - "integrity": "sha512-n1brCuqClxfFfq/Rb0ICg9giSZqCS+pLtccdag6C2HyufBrh3fBOiy9nb6ggRMvWOVH5GrdJskj5iGTZNxd7SA==", - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/widest-line": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/widest-line/-/widest-line-5.0.0.tgz", - "integrity": "sha512-c9bZp7b5YtRj2wOe6dlj32MK+Bx/M/d+9VB2SHM1OtsUHR0aV0tdP6DWh/iMt0kWi1t5g1Iudu6hQRNd1A4PVA==", - "license": "MIT", - "dependencies": { - "string-width": "^7.0.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/wrap-ansi": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.2.tgz", - "integrity": "sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==", - "license": "MIT", - "dependencies": { - "ansi-styles": "^6.2.1", - "string-width": "^7.0.0", - "strip-ansi": "^7.1.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/xxhash-wasm": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/xxhash-wasm/-/xxhash-wasm-1.1.0.tgz", - "integrity": "sha512-147y/6YNh+tlp6nd/2pWq38i9h6mz/EuQ6njIrmW8D1BS5nCqs0P6DG+m6zTGnNz5I+uhZ0SHxBs9BsPrwcKDA==", - "license": "MIT" - }, - "node_modules/y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "license": "ISC", - "engines": { - "node": ">=10" - } - }, - "node_modules/yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", - "license": "ISC" - }, - "node_modules/yaml": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.1.tgz", - "integrity": "sha512-lcYcMxX2PO9XMGvAJkJ3OsNMw+/7FKes7/hgerGUYWIoWu5j/+YQqcZr5JnPZWzOsEBgMbSbiSTn/dv/69Mkpw==", - "license": "ISC", - "bin": { - "yaml": "bin.mjs" - }, - "engines": { - "node": ">= 14.6" - } - }, - "node_modules/yaml-language-server": { - "version": "1.19.2", - "resolved": "https://registry.npmjs.org/yaml-language-server/-/yaml-language-server-1.19.2.tgz", - "integrity": "sha512-9F3myNmJzUN/679jycdMxqtydPSDRAarSj3wPiF7pchEPnO9Dg07Oc+gIYLqXR4L+g+FSEVXXv2+mr54StLFOg==", - "license": "MIT", - "dependencies": { - "@vscode/l10n": "^0.0.18", - "ajv": "^8.17.1", - "ajv-draft-04": "^1.0.0", - "lodash": "4.17.21", - "prettier": "^3.5.0", - "request-light": "^0.5.7", - "vscode-json-languageservice": "4.1.8", - "vscode-languageserver": "^9.0.0", - "vscode-languageserver-textdocument": "^1.0.1", - "vscode-languageserver-types": "^3.16.0", - "vscode-uri": "^3.0.2", - "yaml": "2.7.1" - }, - "bin": { - "yaml-language-server": "bin/yaml-language-server" - } - }, - "node_modules/yaml-language-server/node_modules/request-light": { - "version": "0.5.8", - "resolved": "https://registry.npmjs.org/request-light/-/request-light-0.5.8.tgz", - "integrity": "sha512-3Zjgh+8b5fhRJBQZoy+zbVKpAQGLyka0MPgW3zruTF4dFFJ8Fqcfu9YsAvi/rvdcaTeWG3MkbZv4WKxAn/84Lg==", - "license": "MIT" - }, - "node_modules/yaml-language-server/node_modules/yaml": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.7.1.tgz", - "integrity": "sha512-10ULxpnOCQXxJvBgxsn9ptjq6uviG/htZKk9veJGhlqn3w/DxQ631zFF+nlQXLwmImeS5amR2dl2U8sg6U9jsQ==", - "license": "ISC", - "bin": { - "yaml": "bin.mjs" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/yargs": { - "version": "17.7.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", - "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", - "license": "MIT", - "dependencies": { - "cliui": "^8.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/yargs-parser": { - "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", - "license": "ISC", - "engines": { - "node": ">=12" - } - }, - "node_modules/yargs/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/yargs/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "license": "MIT" - }, - "node_modules/yargs/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/yargs/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/yocto-queue": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.2.2.tgz", - "integrity": "sha512-4LCcse/U2MHZ63HAJVE+v71o7yOdIe4cZ70Wpf8D/IyjDKYQLV5GD46B+hSTjJsvV5PztjvHoU580EftxjDZFQ==", - "license": "MIT", - "engines": { - "node": ">=12.20" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/yocto-spinner": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/yocto-spinner/-/yocto-spinner-0.2.3.tgz", - "integrity": "sha512-sqBChb33loEnkoXte1bLg45bEBsOP9N1kzQh5JZNKj/0rik4zAPTNSAVPj3uQAdc6slYJ0Ksc403G2XgxsJQFQ==", - "license": "MIT", - "dependencies": { - "yoctocolors": "^2.1.1" - }, - "engines": { - "node": ">=18.19" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/yoctocolors": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/yoctocolors/-/yoctocolors-2.1.2.tgz", - "integrity": "sha512-CzhO+pFNo8ajLM2d2IW/R93ipy99LWjtwblvC1RsoSUMZgyLbYFr221TnSNT7GjGdYui6P459mw9JH/g/zW2ug==", - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/zod": { - "version": "3.25.76", - "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz", - "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==", - "license": "MIT", - "peer": true, - "funding": { - "url": "https://github.com/sponsors/colinhacks" - } - }, - "node_modules/zod-to-json-schema": { - "version": "3.25.0", - "resolved": "https://registry.npmjs.org/zod-to-json-schema/-/zod-to-json-schema-3.25.0.tgz", - "integrity": "sha512-HvWtU2UG41LALjajJrML6uQejQhNJx+JBO9IflpSja4R03iNWfKXrj6W2h7ljuLyc1nKS+9yDyL/9tD1U/yBnQ==", - "license": "ISC", - "peerDependencies": { - "zod": "^3.25 || ^4" - } - }, - "node_modules/zod-to-ts": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/zod-to-ts/-/zod-to-ts-1.2.0.tgz", - "integrity": "sha512-x30XE43V+InwGpvTySRNz9kB7qFU8DlyEy7BsSTCHPH1R0QasMmHWZDCzYm6bVXtj/9NNJAZF3jW8rzFvH5OFA==", - "peerDependencies": { - "typescript": "^4.9.4 || ^5.0.2", - "zod": "^3" - } - }, - "node_modules/zwitch": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/zwitch/-/zwitch-2.0.4.tgz", - "integrity": "sha512-bXE4cR/kVZhKZX/RjPEflHaKVhUVl85noU3v6b8apfQEc1x4A+zBxjZ4lN8LqGd6WZ3dl98pY4o717VFmoPp+A==", - "license": "MIT", - "funding": { - "type": "github", - "url": "https://github.com/sponsors/wooorm" - } - } - } -} diff --git a/docs/package.json b/docs/package.json deleted file mode 100644 index 773d51419..000000000 --- a/docs/package.json +++ /dev/null @@ -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" - } -} diff --git a/docs/public/d2/docs/DEVELOPER_GUIDE-0.svg b/docs/public/d2/docs/DEVELOPER_GUIDE-0.svg deleted file mode 100644 index a9b379378..000000000 --- a/docs/public/d2/docs/DEVELOPER_GUIDE-0.svg +++ /dev/null @@ -1,188 +0,0 @@ -DeveloperCLI Layer(cmd/wails3)Command Handlers(internal/commands)Task Runner(internal/commands/task.go)Taskfile(v3/Taskfile.yaml)Build/Packaging(internal/*)Templates(internal/templates)Runtime Assets(internal/runtime)Application Core(pkg/application)Asset Server(internal/assetserver)Message Processor(pkg/application/messageprocessor*.go)WebView Implementations(pkg/application/webview_window_*.go)Services & Bindings(pkg/services/*)Platform Layers(pkg/mac, pkg/w32, pkg/events, pkg/ui) runs wails3registers subcommandswraps build/package/devexecutes tasksinvokes packagers & generatorsrenders scaffoldsbuilds runtime JSembedded assetsserves HTTProutes runtime callsbridge over WebViewbinds Go servicesdispatches to OSfeeds frontendexpose methods - - - - - - - - - - - - - - - - - diff --git a/docs/public/d2/docs/DEVELOPER_GUIDE-1.svg b/docs/public/d2/docs/DEVELOPER_GUIDE-1.svg deleted file mode 100644 index ae97cb156..000000000 --- a/docs/public/d2/docs/DEVELOPER_GUIDE-1.svg +++ /dev/null @@ -1,181 +0,0 @@ -App.Run dispatch hubapplicationEventsEventManagerwindowEventsWindowswebviewRequestsAssetServerwindowMessagesMessageHandlerswindowKeyEventsKeyBindingdragDropBuffermenuItemClickedMenuManager goroutineEvent.handleApplicationEventgoroutinehandleWindowEventServeWebViewRequestHandleMessage / RawMessageHandlerHandleKeyEventHandleDragAndDrop - - - - - - - - - - diff --git a/docs/public/favicon.svg b/docs/public/favicon.svg deleted file mode 100644 index e682e4453..000000000 --- a/docs/public/favicon.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/docs/public/missing.png b/docs/public/missing.png deleted file mode 100644 index 05d2bafc3..000000000 Binary files a/docs/public/missing.png and /dev/null differ diff --git a/docs/public/showcase-images/bboard.webp b/docs/public/showcase-images/bboard.webp deleted file mode 100644 index 463d25de0..000000000 Binary files a/docs/public/showcase-images/bboard.webp and /dev/null differ diff --git a/docs/public/showcase-images/cfntracker.webp b/docs/public/showcase-images/cfntracker.webp deleted file mode 100644 index 6a2288a5c..000000000 Binary files a/docs/public/showcase-images/cfntracker.webp and /dev/null differ diff --git a/docs/public/showcase-images/edex-ui.webp b/docs/public/showcase-images/edex-ui.webp deleted file mode 100644 index 110ca1acf..000000000 Binary files a/docs/public/showcase-images/edex-ui.webp and /dev/null differ diff --git a/docs/public/showcase-images/emailit.webp b/docs/public/showcase-images/emailit.webp deleted file mode 100644 index fc1b9a51a..000000000 Binary files a/docs/public/showcase-images/emailit.webp and /dev/null differ diff --git a/docs/public/showcase-images/encrypteasy.webp b/docs/public/showcase-images/encrypteasy.webp deleted file mode 100644 index c0789a3e3..000000000 Binary files a/docs/public/showcase-images/encrypteasy.webp and /dev/null differ diff --git a/docs/public/showcase-images/filehound.webp b/docs/public/showcase-images/filehound.webp deleted file mode 100644 index 92769ca8e..000000000 Binary files a/docs/public/showcase-images/filehound.webp and /dev/null differ diff --git a/docs/public/showcase-images/hiposter.webp b/docs/public/showcase-images/hiposter.webp deleted file mode 100644 index 7c7510ea1..000000000 Binary files a/docs/public/showcase-images/hiposter.webp and /dev/null differ diff --git a/docs/public/showcase-images/mchat.webp b/docs/public/showcase-images/mchat.webp deleted file mode 100644 index 393b6f77b..000000000 Binary files a/docs/public/showcase-images/mchat.webp and /dev/null differ diff --git a/docs/public/showcase-images/minecraft-mod-updater.webp b/docs/public/showcase-images/minecraft-mod-updater.webp deleted file mode 100644 index c8e011cf3..000000000 Binary files a/docs/public/showcase-images/minecraft-mod-updater.webp and /dev/null differ diff --git a/docs/public/showcase-images/minesweeper-xp.webp b/docs/public/showcase-images/minesweeper-xp.webp deleted file mode 100644 index b3c5ca26b..000000000 Binary files a/docs/public/showcase-images/minesweeper-xp.webp and /dev/null differ diff --git a/docs/public/showcase-images/modalfilemanager.webp b/docs/public/showcase-images/modalfilemanager.webp deleted file mode 100644 index 2fdf219fc..000000000 Binary files a/docs/public/showcase-images/modalfilemanager.webp and /dev/null differ diff --git a/docs/public/showcase-images/mollywallet.webp b/docs/public/showcase-images/mollywallet.webp deleted file mode 100644 index 11641f8ca..000000000 Binary files a/docs/public/showcase-images/mollywallet.webp and /dev/null differ diff --git a/docs/public/showcase-images/october.webp b/docs/public/showcase-images/october.webp deleted file mode 100644 index ceec1c573..000000000 Binary files a/docs/public/showcase-images/october.webp and /dev/null differ diff --git a/docs/public/showcase-images/optimus.webp b/docs/public/showcase-images/optimus.webp deleted file mode 100644 index 0aac84058..000000000 Binary files a/docs/public/showcase-images/optimus.webp and /dev/null differ diff --git a/docs/public/showcase-images/portfall.webp b/docs/public/showcase-images/portfall.webp deleted file mode 100644 index 12f8d6e5b..000000000 Binary files a/docs/public/showcase-images/portfall.webp and /dev/null differ diff --git a/docs/public/showcase-images/resizem.webp b/docs/public/showcase-images/resizem.webp deleted file mode 100644 index aaee1c806..000000000 Binary files a/docs/public/showcase-images/resizem.webp and /dev/null differ diff --git a/docs/public/showcase-images/riftshare-main.webp b/docs/public/showcase-images/riftshare-main.webp deleted file mode 100644 index 2d6a8fb3a..000000000 Binary files a/docs/public/showcase-images/riftshare-main.webp and /dev/null differ diff --git a/docs/public/showcase-images/scriptbar.webp b/docs/public/showcase-images/scriptbar.webp deleted file mode 100644 index 92463fdb9..000000000 Binary files a/docs/public/showcase-images/scriptbar.webp and /dev/null differ diff --git a/docs/public/showcase-images/tiny-rdm1.webp b/docs/public/showcase-images/tiny-rdm1.webp deleted file mode 100644 index 11b375580..000000000 Binary files a/docs/public/showcase-images/tiny-rdm1.webp and /dev/null differ diff --git a/docs/public/showcase-images/tiny-rdm2.webp b/docs/public/showcase-images/tiny-rdm2.webp deleted file mode 100644 index 9de730fb4..000000000 Binary files a/docs/public/showcase-images/tiny-rdm2.webp and /dev/null differ diff --git a/docs/public/showcase-images/varly2.webp b/docs/public/showcase-images/varly2.webp deleted file mode 100644 index 6dbe0c9bf..000000000 Binary files a/docs/public/showcase-images/varly2.webp and /dev/null differ diff --git a/docs/public/showcase-images/wailsterm.webp b/docs/public/showcase-images/wailsterm.webp deleted file mode 100644 index 6d4251a75..000000000 Binary files a/docs/public/showcase-images/wailsterm.webp and /dev/null differ diff --git a/docs/public/showcase-images/wally.webp b/docs/public/showcase-images/wally.webp deleted file mode 100644 index 150c98c74..000000000 Binary files a/docs/public/showcase-images/wally.webp and /dev/null differ diff --git a/docs/public/showcase-images/wombat.webp b/docs/public/showcase-images/wombat.webp deleted file mode 100644 index 97f965834..000000000 Binary files a/docs/public/showcase-images/wombat.webp and /dev/null differ diff --git a/docs/public/showcase-images/ytd.webp b/docs/public/showcase-images/ytd.webp deleted file mode 100644 index c7988cee5..000000000 Binary files a/docs/public/showcase-images/ytd.webp and /dev/null differ diff --git a/docs/public/sponsors/jetbrains-grayscale.webp b/docs/public/sponsors/jetbrains-grayscale.webp deleted file mode 100644 index be39c4856..000000000 Binary files a/docs/public/sponsors/jetbrains-grayscale.webp and /dev/null differ diff --git a/docs/public/sponsors/sponsors.svg b/docs/public/sponsors/sponsors.svg deleted file mode 100644 index 1a9985e59..000000000 --- a/docs/public/sponsors/sponsors.svg +++ /dev/null @@ -1,197 +0,0 @@ - - - - -Champion - Masato Miura - -Bronze Sponsors - Cody Bentley - - - - Kazuya Gokita - - - - Simon Thomas - - - - CodeRabbit - -Covering Costs - Nick - - - - Marcus - - - - John - - - - Matt Holt - - - - Iain - - - - Julien - - - - Andrei - - - - Michael - -Buying Breakfast - tc-hib - - - - Tai Groot - - - - Tom Wu - - - - Arden - - - - igops - - - - vaaski - -Buying Coffee - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -Helpers - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/public/sponsors/zsa.png b/docs/public/sponsors/zsa.png deleted file mode 100644 index 507e983fa..000000000 Binary files a/docs/public/sponsors/zsa.png and /dev/null differ diff --git a/docs/src/assets/blog-images/browser.webp b/docs/src/assets/blog-images/browser.webp deleted file mode 100644 index a19d5b036..000000000 Binary files a/docs/src/assets/blog-images/browser.webp and /dev/null differ diff --git a/docs/src/assets/blog-images/build-cross-windows.webp b/docs/src/assets/blog-images/build-cross-windows.webp deleted file mode 100644 index ba1a538f6..000000000 Binary files a/docs/src/assets/blog-images/build-cross-windows.webp and /dev/null differ diff --git a/docs/src/assets/blog-images/build-darwin-amd.webp b/docs/src/assets/blog-images/build-darwin-amd.webp deleted file mode 100644 index 6126129ca..000000000 Binary files a/docs/src/assets/blog-images/build-darwin-amd.webp and /dev/null differ diff --git a/docs/src/assets/blog-images/build-darwin-arm.webp b/docs/src/assets/blog-images/build-darwin-arm.webp deleted file mode 100644 index 47fcf4583..000000000 Binary files a/docs/src/assets/blog-images/build-darwin-arm.webp and /dev/null differ diff --git a/docs/src/assets/blog-images/build-darwin-universal.webp b/docs/src/assets/blog-images/build-darwin-universal.webp deleted file mode 100644 index c95d92ccb..000000000 Binary files a/docs/src/assets/blog-images/build-darwin-universal.webp and /dev/null differ diff --git a/docs/src/assets/blog-images/devtools.png b/docs/src/assets/blog-images/devtools.png deleted file mode 100644 index e56a0d304..000000000 Binary files a/docs/src/assets/blog-images/devtools.png and /dev/null differ diff --git a/docs/src/assets/blog-images/linux-build-cross-windows.webp b/docs/src/assets/blog-images/linux-build-cross-windows.webp deleted file mode 100644 index cbed7585b..000000000 Binary files a/docs/src/assets/blog-images/linux-build-cross-windows.webp and /dev/null differ diff --git a/docs/src/assets/blog-images/montage.png b/docs/src/assets/blog-images/montage.png deleted file mode 100644 index ddd771851..000000000 Binary files a/docs/src/assets/blog-images/montage.png and /dev/null differ diff --git a/docs/src/assets/blog-images/multiwindow.webp b/docs/src/assets/blog-images/multiwindow.webp deleted file mode 100644 index 746a1d7f2..000000000 Binary files a/docs/src/assets/blog-images/multiwindow.webp and /dev/null differ diff --git a/docs/src/assets/blog-images/remote-linux.webp b/docs/src/assets/blog-images/remote-linux.webp deleted file mode 100644 index 25ad11ea3..000000000 Binary files a/docs/src/assets/blog-images/remote-linux.webp and /dev/null differ diff --git a/docs/src/assets/blog-images/remote-mac.webp b/docs/src/assets/blog-images/remote-mac.webp deleted file mode 100644 index bf4758e1a..000000000 Binary files a/docs/src/assets/blog-images/remote-mac.webp and /dev/null differ diff --git a/docs/src/assets/blog-images/remote.webp b/docs/src/assets/blog-images/remote.webp deleted file mode 100644 index 3968c5ddc..000000000 Binary files a/docs/src/assets/blog-images/remote.webp and /dev/null differ diff --git a/docs/src/assets/blog-images/vscode.webp b/docs/src/assets/blog-images/vscode.webp deleted file mode 100644 index 156fa3078..000000000 Binary files a/docs/src/assets/blog-images/vscode.webp and /dev/null differ diff --git a/docs/src/assets/blog-images/wails-linux.webp b/docs/src/assets/blog-images/wails-linux.webp deleted file mode 100644 index 45c76ed0e..000000000 Binary files a/docs/src/assets/blog-images/wails-linux.webp and /dev/null differ diff --git a/docs/src/assets/blog-images/wails-mac.webp b/docs/src/assets/blog-images/wails-mac.webp deleted file mode 100644 index 26ee0be13..000000000 Binary files a/docs/src/assets/blog-images/wails-mac.webp and /dev/null differ diff --git a/docs/src/assets/blog-images/wails-menus-linux.webp b/docs/src/assets/blog-images/wails-menus-linux.webp deleted file mode 100644 index 391225a35..000000000 Binary files a/docs/src/assets/blog-images/wails-menus-linux.webp and /dev/null differ diff --git a/docs/src/assets/blog-images/wails-menus-mac.webp b/docs/src/assets/blog-images/wails-menus-mac.webp deleted file mode 100644 index 033f68d35..000000000 Binary files a/docs/src/assets/blog-images/wails-menus-mac.webp and /dev/null differ diff --git a/docs/src/assets/blog-images/wails-menus.webp b/docs/src/assets/blog-images/wails-menus.webp deleted file mode 100644 index ba64152b4..000000000 Binary files a/docs/src/assets/blog-images/wails-menus.webp and /dev/null differ diff --git a/docs/src/assets/blog-images/wails.webp b/docs/src/assets/blog-images/wails.webp deleted file mode 100644 index 777f4d05c..000000000 Binary files a/docs/src/assets/blog-images/wails.webp and /dev/null differ diff --git a/docs/src/assets/contributors.html b/docs/src/assets/contributors.html deleted file mode 100644 index 465a64801..000000000 --- a/docs/src/assets/contributors.html +++ /dev/null @@ -1,246 +0,0 @@ -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Lea Anthony
Lea Anthony

💻 🤔 🎨 🖋 💡 🧑‍🏫 📆 🔧 🐛 📝 🚧 📦 👀 💬 🔬 ⚠️ 📢 👀 📖
stffabi
stffabi

💻 🤔 🎨 🐛 🚧 📦 👀 💬 🔬 👀 📖 ⚠️
Travis McLane
Travis McLane

💻 🔬 📦 🤔 🐛 👀 ⚠️ 💬 📖
Misite Bao
Misite Bao

📖 🌍 🔬 🚧
Byron Chris
Byron Chris

💻 🔬 🚧 🐛 👀 ⚠️ 💬 🤔 🎨 📦 🚇
konez2k
konez2k

💻 📦 🤔
Dario Emerson
Dario Emerson

💻 🐛 🤔 ⚠️
Ian M. Jones
Ian M. Jones

💻 🐛 🤔 ⚠️ 👀 📦
marktohark
marktohark

💻
Ryan H
Ryan H

💻
Cody Bentley
Cody Bentley

💻 📦 🤔 💵
Florent
Florent

💻 🐛
Alexander Hudek
Alexander Hudek

💻 💵
Tim Kipp
Tim Kipp

💻
Altynbek Kaliakbarov
Altynbek Kaliakbarov

💻
Nikolai Zimmermann
Nikolai Zimmermann

💻
k-muchmore
k-muchmore

💻
Snider
Snider

💻 🤔 📖 💵
Albert Sun
Albert Sun

💻 ⚠️
Ariel
Ariel

💻 🐛
Ilgıt Yıldırım
Ilgıt Yıldırım

💻 🐛 💵
Toyam Cox
Toyam Cox

💻 📦 🐛
hi019
hi019

💻 🐛
Arthur Wiebe
Arthur Wiebe

💻 🐛
Balakrishna Prasad Ganne
Balakrishna Prasad Ganne

💻
BillBuilt
BillBuilt

💻 📦 🤔 💬 💵
Eng Zer Jun
Eng Zer Jun

🚧 💻
LGiki
LGiki

📖
Lontten
Lontten

📖
Lukas Crepaz
Lukas Crepaz

💻 🐛
Marcus Crane
Marcus Crane

🐛 📖 💵
Qais Patankar
Qais Patankar

📖
Wakeful-Cloud
Wakeful-Cloud

💻 🐛
Zámbó, Levente
Zámbó, Levente

💻 📦 🐛 ⚠️
Ironpark
Ironpark

💻 🤔
mondy
mondy

💻 📖
Benjamin Ryan
Benjamin Ryan

🐛
fallendusk
fallendusk

📦 💻
Mat Ryer
Mat Ryer

💻 🤔 🐛
Abtin
Abtin

💻 🐛
Adrian Lanzafame
Adrian Lanzafame

📦 💻
Aleksey Polyakov
Aleksey Polyakov

🐛 💻
Alexander Matviychuk
Alexander Matviychuk

💻 📦
AlienRecall
AlienRecall

💻 📦
Aman
Aman

📖
Amaury Tobias Quiroz
Amaury Tobias Quiroz

💻 🐛
Andreas Wenk
Andreas Wenk

📖
Antonio Stanković
Antonio Stanković

💻 📦
Arpit Jain
Arpit Jain

📖
Austin Schey
Austin Schey

💻 🐛
Benjamin Thomas
Benjamin Thomas

💻 📦 🤔
Bertram Truong
Bertram Truong

💻 🐛
Blake Bourque
Blake Bourque

📖
Denis
Denis

📖
diogox
diogox

💻 📦
Dmitry Gomzyakov
Dmitry Gomzyakov

💻 📦
Edward Browncross
Edward Browncross

💻
Elie Grenon
Elie Grenon

💻
Florian Didron
Florian Didron

💻 🐛 🤔 ⚠️ 👀 📦
GargantuaX
GargantuaX

💵
Igor Minin
Igor Minin

💻 🐛
Jae-Sung Lee
Jae-Sung Lee

💻 🤔
Jarek
Jarek

💻 📦
Junker
Junker

📖
Kris Raney
Kris Raney

💻 🐛
Luken
Luken

📖
Mark Stenglein
Mark Stenglein

💻 🐛
buddyabaddon
buddyabaddon

💻
MikeSchaap
MikeSchaap

💻 🐛
NYSSEN Michaël
NYSSEN Michaël

💻 🐛
Nan0
Nan0

💻 🤔 ⚠️ 👀
oskar
oskar

📖
Pierre Joye
Pierre Joye

💻 🐛 🤔 ⚠️
Reuben Thomas-Davis
Reuben Thomas-Davis

💻 🐛
Robin
Robin

💻 🐛
Sebastian Bauer
Sebastian Bauer

💻 🤔 ⚠️ 👀 💬
Sidharth Rathi
Sidharth Rathi

📖 🐛
Sithembiso Khumalo
Sithembiso Khumalo

💻 🐛
Soheib El-Harrache
Soheib El-Harrache

💻 🐛 💵
Sophie Au
Sophie Au

💻 🐛
Stefanos Papadakis
Stefanos Papadakis

💻 🐛
Steve Chung
Steve Chung

💻 🐛
Timm Ortloff
Timm Ortloff

📖
Tom
Tom

💻
Valentin Trinqué
Valentin Trinqué

💻 🐛
mattn
mattn

💻 🐛
bearsh
bearsh

💻 🤔 📖
chenxiao
chenxiao

💻 🤔 📖
fengweiqiang
fengweiqiang

💻 📦
flin7
flin7

📖
fred21O4
fred21O4

📖
gardc
gardc

📖
rayshoo
rayshoo

📖
Ishiyama Yuzuki
Ishiyama Yuzuki

💻 🐛
佰阅
佰阅

💻
刀刀
刀刀

📖 🐛
归位
归位

💻 🐛
skamensky
skamensky

💻 🤔 📖
dependabot[bot]
dependabot[bot]

💻 🚧
Damian Sieradzki
Damian Sieradzki

💵
John Dorman
John Dorman

💵
Ian Sinnott
Ian Sinnott

💵
Arden Shackelford
Arden Shackelford

💵
Bironou
Bironou

💵
CharlieGo_
CharlieGo_

💵
overnet
overnet

💵
jugglingjsons
jugglingjsons

💵
Selvin Ortiz
Selvin Ortiz

💵
ZanderCodes
ZanderCodes

💵
Michael Voronov
Michael Voronov

💵
letheanVPN
letheanVPN

💵
Tai Groot
Tai Groot

💵
easy-web-it
easy-web-it

💵
Michael Olson
Michael Olson

💵
EdenNetwork Italia
EdenNetwork Italia

💵
ondoki
ondoki

💵
QuEST Rail LLC
QuEST Rail LLC

💵
Gilgameš
Gilgameš

💵
Bernt-Johan Bergshaven
Bernt-Johan Bergshaven

💵
Liam Bigelow
Liam Bigelow

💵
Nick Arellano
Nick Arellano

💵
Frank Chiarulli Jr.
Frank Chiarulli Jr.

💵
Tyler
Tyler

💵
Trea Hauet
Trea Hauet

💵
Kent 'picat' Gruber
Kent 'picat' Gruber

💵
tc-hib
tc-hib

💵
Antonio
Antonio

📖
MyNameIsAres
MyNameIsAres

📖
Maicarons J
Maicarons J

📖
kiddov
kiddov

📖 💵 ⚠️ 🤔
Nicolas Coutin
Nicolas Coutin

💵
Parvin Eyvazov
Parvin Eyvazov

📖
github-actions[bot]
github-actions[bot]

💻
Oleg Gulevskyy
Oleg Gulevskyy

💻 📖 🚧 📦
Richard Guay
Richard Guay

📖
Adam Tenderholt
Adam Tenderholt

💻
JulioDRF
JulioDRF

💻
Scott Opell
Scott Opell

💻
Vadim Shchepotev
Vadim Shchepotev

💻
Will Andrews
Will Andrews

💻
Gwyn
Gwyn

💻 👀 💬 🔬
希嘉嘉
希嘉嘉

💻
ALMAS
ALMAS

💻
Alex
Alex

💻
Arif Ali
Arif Ali

💻
Artur Siarohau
Artur Siarohau

💻
Binyamin Aron Green
Binyamin Aron Green

💻
Brian Dwyer
Brian Dwyer

💻
Christian Kilb
Christian Kilb

💻
David Florness
David Florness

📖
David Walton
David Walton

💻
Debdut Karmakar
Debdut Karmakar

💻
Dieter Zhu
Dieter Zhu

💻
Fredrik Holmqvist
Fredrik Holmqvist

💻
Giovanni Palma
Giovanni Palma

💻
Hao
Hao

💻
Igor Sementsov
Igor Sementsov

💻
Johannes Haseitl
Johannes Haseitl

💻
Joshua Hull
Joshua Hull

💻
Joshua Mangiola
Joshua Mangiola

📖
Kevin MacMartin
Kevin MacMartin

💻
Liang Li
Liang Li

💻
Marvin Collins Hosea
Marvin Collins Hosea

💻
Matt Holt
Matt Holt

💻
Niklas
Niklas

💻
Andy Hsu
Andy Hsu

💻
NullCode
NullCode

💻
Oussama Sethoum
Oussama Sethoum

💻
ParkourLiu
ParkourLiu

💻
Rachel Chen
Rachel Chen

💻
Rob Nice
Rob Nice

💻
Ryo TAGAMI
Ryo TAGAMI

💻
Sam Hennessy
Sam Hennessy

💻
Sean
Sean

💻
Sean Gosiaco
Sean Gosiaco

💻
Eric P Sheets
Eric P Sheets

💻
Supian M
Supian M

💻
Watson-Sei
Watson-Sei

💻 📖
Yuki Shindo
Yuki Shindo

💻
cuigege
cuigege

💻
cybertramp
cybertramp

💻
hiroki yagi
hiroki yagi

💻
imgbot[bot]
imgbot[bot]

💻
juju
juju

💻
Michael Eatherly
Michael Eatherly

💻
tk
tk

💻
allcontributors[bot]
allcontributors[bot]

📖
wander
wander

📖
- - -
\ No newline at end of file diff --git a/docs/src/assets/menus/context-menu.png b/docs/src/assets/menus/context-menu.png deleted file mode 100644 index dd43c0c7f..000000000 --- a/docs/src/assets/menus/context-menu.png +++ /dev/null @@ -1 +0,0 @@ -iVBORw0KGgoAAAANSUhEUgAAASwAAAEsCAYAAAB5fY51AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoV2luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6MTIzODU1NjI4RjU1MTFFQjg5QzVCNTY1QjY1NjY1QjYiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6MTIzODU1NjM4RjU1MTFFQjg5QzVCNTY1QjY1NjY1QjYiPiA8eG1wTU06RGVyaXZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDoxMjM4NTU2MDhGNTUxMUVCODlDNUI1NjVCNjU2NjVCNiIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDoxMjM4NTU2MThGNTUxMUVCODlDNUI1NjVCNjU2NjVCNiIvPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PgH//v38+/r5+Pf29fTz8vHw7+7t7Ovq6ejn5uXk4+Lh4N/e3dzb2tnY19bV1NPS0dDPzs3My8rJyMfGxcTDwsHAv769vLu6ubi3trW0s7KxsK+urayrqqmop6alpKOioaCfnp2cm5qZmJeWlZSTkpGQj46NjIuKiYiHhoWEg4KBgH9+fXx7enl4d3Z1dHNycXBvbm1sa2ppaGdmZWRjYmFgX15dXFtaWVhXVlVUU1JRUE9OTUxLSklIR0ZFRENCQUA/Pj08Ozo5ODc2NTQzMjEwLy4tLCsqKSgnJiUkIyIhIB8eHRwbGhkYFxYVFBMSERAPDg0MCwoJCAcGBQQDAgEAACH5BAEAAAAALAAAAAAsASwBAAL/hI+py+0Po5y02ouz3rz7D4biSJbmiabqyrbuC8fyTNf2jef6zvf+DwwKh8Si8YhMKpfMpvMJjUqn1Kr1is1qt9yu9wsOi8fksvmMTqvX7Lb7DY/L5/S6/Y7P6/f8vv8PGCg4SFhoeIiYqLjI2Oj4CBkpOUlZaXmJmam5ydnp+QkaKjpKWmp6ipqqusra6voKGys7S1tre4ubq7vL2+v7CxwsPExcbHyMnKy8zNzs/AwdLT1NXW19jZ2tvc3d7f0NHi4+Tl5ufo6err7O3u7+Dh8vP09fb3+Pn6+/z9/v/w8woMCBBAsaPIgwocKFDBs6fAgxosSJFCtavIgxo8aN/xw7evwIMqTIkSRLmjyJMqXKlSxbunwJM6bMmTRr2ryJM6fOnTx7+vwJNKjQoUSLGj2KNKnSpUybOn0KNarUqVSrWr2KNavWrVy7ev0KNqzYsWTLmj2LNq3atWzbun0LN67cuXTr2r2LN6/evXz7+v0LOLDgwYQLGz6MOLHixYwbO34MObLkyZQrW76MObPmzZw7e/4MOrTo0aRLmz6NOrXq1axbu34NO7bs2bRr276NO7fu3bx7+/4NPLjw4cSLGz+OPLny5cybO38OPbr06dSrW7+OPbv27dy7e/8OPrz48eTLmz+PPr369ezbu38PP778+fTr27+PP7/+/fz7+9OPX7//fwAGKOCABBZo4IEIJqjgggw26OCDEEYo4YQUVmjhhRhmqOGGHHbo4YcghijiiCSWaOKJKKao4oostujiizDGKOOMNNZo44045qjjjjz26OOPQAYp5JBEFmnkkUgmqeSSTDbp5JNQRinllFRWaeWVWGap5ZZcdunll2CGKeaYZJZp5plopqnmmmy26eabcMYp55x01mnnnXjmqeeefPbp55+ABirooIQWauihiCaq6KKMNuroo5BGKumklFZq6aWYZqrpppx26umnoIYq6qiklmrqqaimquqqrLbq6quwxirrqxEAADs= diff --git a/docs/src/assets/notes-app.png b/docs/src/assets/notes-app.png deleted file mode 100644 index 4e4953204..000000000 Binary files a/docs/src/assets/notes-app.png and /dev/null differ diff --git a/docs/src/assets/qr1.png b/docs/src/assets/qr1.png deleted file mode 100644 index 69885acbe..000000000 Binary files a/docs/src/assets/qr1.png and /dev/null differ diff --git a/docs/src/assets/qr2.png b/docs/src/assets/qr2.png deleted file mode 100644 index e2ce2a5f1..000000000 Binary files a/docs/src/assets/qr2.png and /dev/null differ diff --git a/docs/src/assets/showcase-images/bboard.webp b/docs/src/assets/showcase-images/bboard.webp deleted file mode 100644 index 463d25de0..000000000 Binary files a/docs/src/assets/showcase-images/bboard.webp and /dev/null differ diff --git a/docs/src/assets/showcase-images/cfntracker.webp b/docs/src/assets/showcase-images/cfntracker.webp deleted file mode 100644 index 6a2288a5c..000000000 Binary files a/docs/src/assets/showcase-images/cfntracker.webp and /dev/null differ diff --git a/docs/src/assets/showcase-images/clave.png b/docs/src/assets/showcase-images/clave.png deleted file mode 100644 index 3ee29c303..000000000 Binary files a/docs/src/assets/showcase-images/clave.png and /dev/null differ diff --git a/docs/src/assets/showcase-images/emailit.webp b/docs/src/assets/showcase-images/emailit.webp deleted file mode 100644 index fc1b9a51a..000000000 Binary files a/docs/src/assets/showcase-images/emailit.webp and /dev/null differ diff --git a/docs/src/assets/showcase-images/encrypteasy.webp b/docs/src/assets/showcase-images/encrypteasy.webp deleted file mode 100644 index c0789a3e3..000000000 Binary files a/docs/src/assets/showcase-images/encrypteasy.webp and /dev/null differ diff --git a/docs/src/assets/showcase-images/esp-studio.png b/docs/src/assets/showcase-images/esp-studio.png deleted file mode 100644 index 9cb7d39fa..000000000 Binary files a/docs/src/assets/showcase-images/esp-studio.png and /dev/null differ diff --git a/docs/src/assets/showcase-images/filehound.webp b/docs/src/assets/showcase-images/filehound.webp deleted file mode 100644 index 92769ca8e..000000000 Binary files a/docs/src/assets/showcase-images/filehound.webp and /dev/null differ diff --git a/docs/src/assets/showcase-images/hiposter.webp b/docs/src/assets/showcase-images/hiposter.webp deleted file mode 100644 index 7c7510ea1..000000000 Binary files a/docs/src/assets/showcase-images/hiposter.webp and /dev/null differ diff --git a/docs/src/assets/showcase-images/mac-app.png b/docs/src/assets/showcase-images/mac-app.png deleted file mode 100644 index 1f4c85304..000000000 Binary files a/docs/src/assets/showcase-images/mac-app.png and /dev/null differ diff --git a/docs/src/assets/showcase-images/mchat.png b/docs/src/assets/showcase-images/mchat.png deleted file mode 100644 index 0942c482b..000000000 Binary files a/docs/src/assets/showcase-images/mchat.png and /dev/null differ diff --git a/docs/src/assets/showcase-images/minecraft-mod-updater.webp b/docs/src/assets/showcase-images/minecraft-mod-updater.webp deleted file mode 100644 index c8e011cf3..000000000 Binary files a/docs/src/assets/showcase-images/minecraft-mod-updater.webp and /dev/null differ diff --git a/docs/src/assets/showcase-images/minesweeper-xp.webp b/docs/src/assets/showcase-images/minesweeper-xp.webp deleted file mode 100644 index b3c5ca26b..000000000 Binary files a/docs/src/assets/showcase-images/minesweeper-xp.webp and /dev/null differ diff --git a/docs/src/assets/showcase-images/modalfilemanager.webp b/docs/src/assets/showcase-images/modalfilemanager.webp deleted file mode 100644 index 2fdf219fc..000000000 Binary files a/docs/src/assets/showcase-images/modalfilemanager.webp and /dev/null differ diff --git a/docs/src/assets/showcase-images/mollywallet.webp b/docs/src/assets/showcase-images/mollywallet.webp deleted file mode 100644 index 11641f8ca..000000000 Binary files a/docs/src/assets/showcase-images/mollywallet.webp and /dev/null differ diff --git a/docs/src/assets/showcase-images/october.webp b/docs/src/assets/showcase-images/october.webp deleted file mode 100644 index ceec1c573..000000000 Binary files a/docs/src/assets/showcase-images/october.webp and /dev/null differ diff --git a/docs/src/assets/showcase-images/optimus.webp b/docs/src/assets/showcase-images/optimus.webp deleted file mode 100644 index 0aac84058..000000000 Binary files a/docs/src/assets/showcase-images/optimus.webp and /dev/null differ diff --git a/docs/src/assets/showcase-images/portfall.webp b/docs/src/assets/showcase-images/portfall.webp deleted file mode 100644 index 12f8d6e5b..000000000 Binary files a/docs/src/assets/showcase-images/portfall.webp and /dev/null differ diff --git a/docs/src/assets/showcase-images/resizem.webp b/docs/src/assets/showcase-images/resizem.webp deleted file mode 100644 index aaee1c806..000000000 Binary files a/docs/src/assets/showcase-images/resizem.webp and /dev/null differ diff --git a/docs/src/assets/showcase-images/restic-browser-2.png b/docs/src/assets/showcase-images/restic-browser-2.png deleted file mode 100644 index b986bfe68..000000000 Binary files a/docs/src/assets/showcase-images/restic-browser-2.png and /dev/null differ diff --git a/docs/src/assets/showcase-images/riftshare-main.webp b/docs/src/assets/showcase-images/riftshare-main.webp deleted file mode 100644 index 2d6a8fb3a..000000000 Binary files a/docs/src/assets/showcase-images/riftshare-main.webp and /dev/null differ diff --git a/docs/src/assets/showcase-images/scriptbar.webp b/docs/src/assets/showcase-images/scriptbar.webp deleted file mode 100644 index 92463fdb9..000000000 Binary files a/docs/src/assets/showcase-images/scriptbar.webp and /dev/null differ diff --git a/docs/src/assets/showcase-images/snippetexpandergui-add-snippet.png b/docs/src/assets/showcase-images/snippetexpandergui-add-snippet.png deleted file mode 100644 index 0f34e4f53..000000000 Binary files a/docs/src/assets/showcase-images/snippetexpandergui-add-snippet.png and /dev/null differ diff --git a/docs/src/assets/showcase-images/snippetexpandergui-search-and-paste.png b/docs/src/assets/showcase-images/snippetexpandergui-search-and-paste.png deleted file mode 100644 index d87878c29..000000000 Binary files a/docs/src/assets/showcase-images/snippetexpandergui-search-and-paste.png and /dev/null differ diff --git a/docs/src/assets/showcase-images/snippetexpandergui-select-snippet.png b/docs/src/assets/showcase-images/snippetexpandergui-select-snippet.png deleted file mode 100644 index b82468c80..000000000 Binary files a/docs/src/assets/showcase-images/snippetexpandergui-select-snippet.png and /dev/null differ diff --git a/docs/src/assets/showcase-images/surge.png b/docs/src/assets/showcase-images/surge.png deleted file mode 100644 index d732fabe8..000000000 Binary files a/docs/src/assets/showcase-images/surge.png and /dev/null differ diff --git a/docs/src/assets/showcase-images/tiny-rdm1.webp b/docs/src/assets/showcase-images/tiny-rdm1.webp deleted file mode 100644 index 11b375580..000000000 Binary files a/docs/src/assets/showcase-images/tiny-rdm1.webp and /dev/null differ diff --git a/docs/src/assets/showcase-images/tiny-rdm2.webp b/docs/src/assets/showcase-images/tiny-rdm2.webp deleted file mode 100644 index 9de730fb4..000000000 Binary files a/docs/src/assets/showcase-images/tiny-rdm2.webp and /dev/null differ diff --git a/docs/src/assets/showcase-images/varly2.webp b/docs/src/assets/showcase-images/varly2.webp deleted file mode 100644 index 6dbe0c9bf..000000000 Binary files a/docs/src/assets/showcase-images/varly2.webp and /dev/null differ diff --git a/docs/src/assets/showcase-images/wailsterm.webp b/docs/src/assets/showcase-images/wailsterm.webp deleted file mode 100644 index 6d4251a75..000000000 Binary files a/docs/src/assets/showcase-images/wailsterm.webp and /dev/null differ diff --git a/docs/src/assets/showcase-images/wally.webp b/docs/src/assets/showcase-images/wally.webp deleted file mode 100644 index 150c98c74..000000000 Binary files a/docs/src/assets/showcase-images/wally.webp and /dev/null differ diff --git a/docs/src/assets/showcase-images/warmine1.png b/docs/src/assets/showcase-images/warmine1.png deleted file mode 100644 index 38441d99d..000000000 Binary files a/docs/src/assets/showcase-images/warmine1.png and /dev/null differ diff --git a/docs/src/assets/showcase-images/warmine2.png b/docs/src/assets/showcase-images/warmine2.png deleted file mode 100644 index 4713462da..000000000 Binary files a/docs/src/assets/showcase-images/warmine2.png and /dev/null differ diff --git a/docs/src/assets/showcase-images/wombat.webp b/docs/src/assets/showcase-images/wombat.webp deleted file mode 100644 index 97f965834..000000000 Binary files a/docs/src/assets/showcase-images/wombat.webp and /dev/null differ diff --git a/docs/src/assets/showcase-images/ytd.webp b/docs/src/assets/showcase-images/ytd.webp deleted file mode 100644 index c7988cee5..000000000 Binary files a/docs/src/assets/showcase-images/ytd.webp and /dev/null differ diff --git a/docs/src/assets/todo-app.png b/docs/src/assets/todo-app.png deleted file mode 100644 index 319cc8fbf..000000000 Binary files a/docs/src/assets/todo-app.png and /dev/null differ diff --git a/docs/src/assets/wails-logo-dark.svg b/docs/src/assets/wails-logo-dark.svg deleted file mode 100644 index dfc54485c..000000000 --- a/docs/src/assets/wails-logo-dark.svg +++ /dev/null @@ -1,49 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/src/assets/wails-logo-horizontal-dark.svg b/docs/src/assets/wails-logo-horizontal-dark.svg deleted file mode 100644 index 01808dca5..000000000 --- a/docs/src/assets/wails-logo-horizontal-dark.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/docs/src/assets/wails-logo-horizontal-light.svg b/docs/src/assets/wails-logo-horizontal-light.svg deleted file mode 100644 index 465bc5cf9..000000000 --- a/docs/src/assets/wails-logo-horizontal-light.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/docs/src/assets/wails-logo-light.svg b/docs/src/assets/wails-logo-light.svg deleted file mode 100644 index ab02c827a..000000000 --- a/docs/src/assets/wails-logo-light.svg +++ /dev/null @@ -1,49 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/docs/src/assets/wails_build.mp4 b/docs/src/assets/wails_build.mp4 deleted file mode 100644 index 2d1ee783b..000000000 Binary files a/docs/src/assets/wails_build.mp4 and /dev/null differ diff --git a/docs/src/assets/wails_dev.mp4 b/docs/src/assets/wails_dev.mp4 deleted file mode 100644 index 29c2a45a4..000000000 Binary files a/docs/src/assets/wails_dev.mp4 and /dev/null differ diff --git a/docs/src/assets/wails_init.mp4 b/docs/src/assets/wails_init.mp4 deleted file mode 100644 index 337bc0f5a..000000000 Binary files a/docs/src/assets/wails_init.mp4 and /dev/null differ diff --git a/docs/src/components/CardAnimation.astro b/docs/src/components/CardAnimation.astro deleted file mode 100644 index 5d3de111b..000000000 --- a/docs/src/components/CardAnimation.astro +++ /dev/null @@ -1,62 +0,0 @@ ---- ---- - diff --git a/docs/src/content/authors.ts b/docs/src/content/authors.ts deleted file mode 100644 index 0500490f3..000000000 --- a/docs/src/content/authors.ts +++ /dev/null @@ -1,11 +0,0 @@ -import type { StarlightBlogUserConfig } from "starlight-blog"; - -type Authors = NonNullable["authors"]; -export const authors: Authors = { - leaanthony: { - name: "Lea Anthony", - title: "Maintainer of Wails", - url: "https://github.com/leaanthony", - picture: "https://github.com/leaanthony.png", - }, -}; diff --git a/docs/src/content/config.ts b/docs/src/content/config.ts deleted file mode 100644 index dae3197fe..000000000 --- a/docs/src/content/config.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { defineCollection } from "astro:content"; -import { docsSchema, i18nSchema } from "@astrojs/starlight/schema"; -import { blogSchema } from "starlight-blog/schema"; - -export const collections = { - i18n: defineCollection({ type: "data", schema: i18nSchema() }), - docs: defineCollection({ - schema: docsSchema({ extend: (context) => blogSchema(context) }), - }), -}; diff --git a/docs/src/content/docs/blog/2021-09-27-v2-beta1-release-notes.md b/docs/src/content/docs/blog/2021-09-27-v2-beta1-release-notes.md deleted file mode 100644 index dbc8d9776..000000000 --- a/docs/src/content/docs/blog/2021-09-27-v2-beta1-release-notes.md +++ /dev/null @@ -1,206 +0,0 @@ ---- -slug: blog/wails-v2-beta-for-windows -title: Wails v2 Beta for Windows -authors: [leaanthony] -tags: [wails, v2] -date: 2021-09-27 ---- - -![wails screenshot](../../../assets/blog-images/wails.webp) - -When I first announced Wails on Reddit, just over 2 years ago from a train in -Sydney, I did not expect it to get much attention. A few days later, a prolific -tech vlogger released a tutorial video, gave it a positive review and from that -point on, interest in the project has skyrocketed. - -It was clear that people were excited about adding web frontends to their Go -projects, and almost immediately pushed the project beyond the proof of concept -that I had created. At the time, Wails used the -[webview](https://github.com/webview/webview) project to handle the frontend, -and the only option for Windows was the IE11 renderer. Many bug reports were -rooted in this limitation: poor JavaScript/CSS support and no dev tools to debug -it. This was a frustrating development experience but there wasn't much that -could have been done to rectify it. - -For a long time, I'd firmly believed that Microsoft would eventually have to -sort out their browser situation. The world was moving on, frontend development -was booming and IE wasn't cutting it. When Microsoft announced the move to using -Chromium as the basis for their new browser direction, I knew it was only a -matter of time until Wails could use it, and move the Windows developer -experience to the next level. - -Today, I am pleased to announce: **Wails v2 Beta for Windows**! There's a huge -amount to unpack in this release, so grab a drink, take a seat and we'll -begin... - -### No CGO Dependency! - -No, I'm not joking: _No_ _CGO_ _dependency_ 🤯! The thing about Windows is that, -unlike MacOS and Linux, it doesn't come with a default compiler. In addition, -CGO requires a mingw compiler and there's a ton of different installation -options. Removing the CGO requirement has massively simplified setup, as well as -making debugging an awful lot easier. Whilst I have put a fair bit of effort in -getting this working, the majority of the credit should go to -[John Chadwick](https://github.com/jchv) for not only starting a couple of -projects to make this possible, but also being open to someone taking those -projects and building on them. Credit also to -[Tad Vizbaras](https://github.com/tadvi) whose -[winc](https://github.com/tadvi/winc) project started me down this path. - -### WebView2 Chromium Renderer - -![devtools screenshot](../../../assets/blog-images/devtools.png) - -Finally, Windows developers get a first class rendering engine for their -applications! Gone are the days of contorting your frontend code to work on -Windows. On top of that, you get a first-class developer tools experience! - -The WebView2 component does, however, have a requirement to have the -`WebView2Loader.dll` sitting alongside the binary. This makes distribution just -that little bit more painful than we gophers are used to. All solutions and -libraries (that I know of) that use WebView2 have this dependency. - -However, I'm really excited to announce that Wails applications _have no such -requirement_! Thanks to the wizardry of -[John Chadwick](https://github.com/jchv), we are able to bundle this dll inside -the binary and get Windows to load it as if it were present on disk. - -Gophers rejoice! The single binary dream lives on! - -### New Features - -![wails-menus screenshot](../../../assets/blog-images/wails-menus.webp) - -There were a lot of requests for native menu support. Wails has finally got you -covered. Application menus are now available and include support for most native -menu features. This includes standard menu items, checkboxes, radio groups, -submenus and separators. - -There were a huge number of requests in v1 for the ability to have greater -control of the window itself. I'm happy to announce that there's new runtime -APIs specifically for this. It's feature-rich and supports multi-monitor -configurations. There is also an improved dialogs API: Now, you can have modern, -native dialogs with rich configuration to cater for all your dialog needs. - -There is now the option to generate IDE configuration along with your project. -This means that if you open your project in a supported IDE, it will already be -configured for building and debugging your application. Currently VSCode is -supported but we hope to support other IDEs such as Goland soon. - -![vscode screenshot](../../../assets/blog-images/vscode.webp) - -### No requirement to bundle assets - -A huge pain-point of v1 was the need to condense your entire application down to -single JS & CSS files. I'm happy to announce that for v2, there is no -requirement to bundle assets, in any way, shape or form. Want to load a local -image? Use an `` tag with a local src path. Want to use a cool font? Copy -it in and add the path to it in your CSS. - -> Wow, that sounds like a webserver... - -Yes, it works just like a webserver, except it isn't. - -> So how do I include my assets? - -You just pass a single `embed.FS` that contains all your assets into your -application configuration. They don't even need to be in the top directory - -Wails will just work it out for you. - -### New Development Experience - -![browser screenshot](../../../assets/blog-images/browser.webp) - -Now that assets don't need to be bundled, it's enabled a whole new development -experience. The new `wails dev` command will build and run your application, but -instead of using the assets in the `embed.FS`, it loads them directly from disk. - -It also provides the additional features: - -- Hot reload - Any changes to frontend assets will trigger and auto reload of - the application frontend -- Auto rebuild - Any changes to your Go code will rebuild and relaunch your - application - -In addition to this, a webserver will start on port 34115. This will serve your -application to any browser that connects to it. All connected web browsers will -respond to system events like hot reload on asset change. - -In Go, we are used to dealing with structs in our applications. It's often -useful to send structs to our frontend and use them as state in our application. -In v1, this was a very manual process and a bit of a burden on the developer. -I'm happy to announce that in v2, any application run in dev mode will -automatically generate TypeScript models for all structs that are input or -output parameters to bound methods. This enables seamless interchange of data -models between the two worlds. - -In addition to this, another JS module is dynamically generated wrapping all -your bound methods. This provides JSDoc for your methods, providing code -completion and hinting in your IDE. It's really cool when you get data models -auto-imported when hitting tab in an auto-generated module wrapping your Go -code! - -### Remote Templates - -![remote screenshot](../../../assets/blog-images/remote.webp) - -Getting an application up and running quickly was always a key goal for the -Wails project. When we launched, we tried to cover a lot of the modern -frameworks at the time: react, vue and angular. The world of frontend -development is very opinionated, fast moving and hard to keep on top of! As a -result, we found our base templates getting out of date pretty quickly and this -caused a maintenance headache. It also meant that we didn't have cool modern -templates for the latest and greatest tech stacks. - -With v2, I wanted to empower the community by giving you the ability to create -and host templates yourselves, rather than rely on the Wails project. So now you -can create projects using community supported templates! I hope this will -inspire developers to create a vibrant ecosystem of project templates. I'm -really quite excited about what our developer community can create! - -### In Conclusion - -Wails v2 represents a new foundation for the project. The aim of this release is -to get feedback on the new approach, and to iron out any bugs before a full -release. Your input would be most welcome. Please direct any feedback to the -[v2 Beta](https://github.com/wailsapp/wails/discussions/828) discussion board. - -There were many twists and turns, pivots and u-turns to get to this point. This -was due partly to early technical decisions that needed changing, and partly -because some core problems we had spent time building workarounds for were fixed -upstream: Go’s embed feature is a good example. Fortunately, everything came -together at the right time, and today we have the very best solution that we can -have. I believe the wait has been worth it - this would not have been possible -even 2 months ago. - -I also need to give a huge thank you :pray: to the following people because -without them, this release just wouldn't exist: - -- [Misite Bao](https://github.com/misitebao) - An absolute workhorse on the - Chinese translations and an incredible bug finder. -- [John Chadwick](https://github.com/jchv) - His amazing work on - [go-webview2](https://github.com/jchv/go-webview2) and - [go-winloader](https://github.com/jchv/go-winloader) have made the Windows - version we have today possible. -- [Tad Vizbaras](https://github.com/tadvi) - Experimenting with his - [winc](https://github.com/tadvi/winc) project was the first step down the path - to a pure Go Wails. -- [Mat Ryer](https://github.com/matryer) - His support, encouragement and - feedback has really helped drive the project forward. - -And finally, I'd like to give a special thank you to all the -[project sponsors](/credits#sponsors), including -[JetBrains](https://www.jetbrains.com?from=Wails), whose support drives the -project in many ways behind the scenes. - -I look forward to seeing what people build with Wails in this next exciting -phase of the project! - -Lea. - -PS: MacOS and Linux users need not feel left out - porting to this new -foundation is actively under way and most of the hard work has already been -done. Hang in there! - -PPS: If you or your company find Wails useful, please consider -[sponsoring the project](https://github.com/sponsors/leaanthony). Thanks! diff --git a/docs/src/content/docs/blog/2021-11-08-v2-beta2-release-notes.md b/docs/src/content/docs/blog/2021-11-08-v2-beta2-release-notes.md deleted file mode 100644 index 31d53e1bc..000000000 --- a/docs/src/content/docs/blog/2021-11-08-v2-beta2-release-notes.md +++ /dev/null @@ -1,166 +0,0 @@ ---- -slug: blog/wails-v2-beta-for-mac -title: Wails v2 Beta for MacOS -authors: [leaanthony] -tags: [wails, v2] -date: 2021-11-08 ---- - -![wails-mac screenshot](../../../assets/blog-images/wails-mac.webp) - -Today marks the first beta release of Wails v2 for Mac! It's taken quite a while -to get to this point and I'm hoping that today's release will give you something -that's reasonably useful. There have been a number of twists and turns to get to -this point and I'm hoping, with your help, to iron out the crinkles and get the -Mac port polished for the final v2 release. - -You mean this isn't ready for production? For your use case, it may well be -ready, but there are still a number of known issues so keep your eye on -[this project board](https://github.com/wailsapp/wails/projects/7) and if you -would like to contribute, you'd be very welcome! - -So what's new for Wails v2 for Mac vs v1? Hint: It's pretty similar to the -Windows Beta :wink: - -### New Features - -![wails-menus-mac screenshot](../../../assets/blog-images/wails-menus-mac.webp) - -There were a lot of requests for native menu support. Wails has finally got you -covered. Application menus are now available and include support for most native -menu features. This includes standard menu items, checkboxes, radio groups, -submenus and separators. - -There were a huge number of requests in v1 for the ability to have greater -control of the window itself. I'm happy to announce that there's new runtime -APIs specifically for this. It's feature-rich and supports multi-monitor -configurations. There is also an improved dialogs API: Now, you can have modern, -native dialogs with rich configuration to cater for all your dialog needs. - -### Mac Specific Options - -In addition to the normal application options, Wails v2 for Mac also brings some -Mac extras: - -- Make your window all funky and translucent, like all the pretty swift apps! -- Highly customisable titlebar -- We support the NSAppearance options for the application -- Simple config to auto-create an "About" menu - -### No requirement to bundle assets - -A huge pain-point of v1 was the need to condense your entire application down to -single JS & CSS files. I'm happy to announce that for v2, there is no -requirement to bundle assets, in any way, shape or form. Want to load a local -image? Use an `` tag with a local src path. Want to use a cool font? Copy -it in and add the path to it in your CSS. - -> Wow, that sounds like a webserver... - -Yes, it works just like a webserver, except it isn't. - -> So how do I include my assets? - -You just pass a single `embed.FS` that contains all your assets into your -application configuration. They don't even need to be in the top directory - -Wails will just work it out for you. - -### New Development Experience - -Now that assets don't need to be bundled, it's enabled a whole new development -experience. The new `wails dev` command will build and run your application, but -instead of using the assets in the `embed.FS`, it loads them directly from disk. - -It also provides the additional features: - -- Hot reload - Any changes to frontend assets will trigger and auto reload of - the application frontend -- Auto rebuild - Any changes to your Go code will rebuild and relaunch your - application - -In addition to this, a webserver will start on port 34115. This will serve your -application to any browser that connects to it. All connected web browsers will -respond to system events like hot reload on asset change. - -In Go, we are used to dealing with structs in our applications. It's often -useful to send structs to our frontend and use them as state in our application. -In v1, this was a very manual process and a bit of a burden on the developer. -I'm happy to announce that in v2, any application run in dev mode will -automatically generate TypeScript models for all structs that are input or -output parameters to bound methods. This enables seamless interchange of data -models between the two worlds. - -In addition to this, another JS module is dynamically generated wrapping all -your bound methods. This provides JSDoc for your methods, providing code -completion and hinting in your IDE. It's really cool when you get data models -auto-imported when hitting tab in an auto-generated module wrapping your Go -code! - -### Remote Templates - -![remote-mac screenshot](../../../assets/blog-images/remote-mac.webp) - -Getting an application up and running quickly was always a key goal for the -Wails project. When we launched, we tried to cover a lot of the modern -frameworks at the time: react, vue and angular. The world of frontend -development is very opinionated, fast moving and hard to keep on top of! As a -result, we found our base templates getting out of date pretty quickly and this -caused a maintenance headache. It also meant that we didn't have cool modern -templates for the latest and greatest tech stacks. - -With v2, I wanted to empower the community by giving you the ability to create -and host templates yourselves, rather than rely on the Wails project. So now you -can create projects using community supported templates! I hope this will -inspire developers to create a vibrant ecosystem of project templates. I'm -really quite excited about what our developer community can create! - -### Native M1 Support - -Thanks to the amazing support of [Mat Ryer](https://github.com/matryer/), the -Wails project now supports M1 native builds: - -![build-darwin-arm screenshot](../../../assets/blog-images/build-darwin-arm.webp) - -You can also specify `darwin/amd64` as a target too: - -![build-darwin-amd screenshot](../../../assets/blog-images/build-darwin-amd.webp) - -Oh, I almost forgot.... you can also do `darwin/universal`.... :wink: - -![build-darwin-universal screenshot](../../../assets/blog-images/build-darwin-universal.webp) - -### Cross Compilation to Windows - -Because Wails v2 for Windows is pure Go, you can target Windows builds without -docker. - -![build-cross-windows screenshot](../../../assets/blog-images/build-cross-windows.webp) -bu - -### WKWebView Renderer - -V1 relied on a (now deprecated) WebView component. V2 uses the most recent -WKWebKit component so expect the latest and greatest from Apple. - -### In Conclusion - -As I'd said in the Windows release notes, Wails v2 represents a new foundation -for the project. The aim of this release is to get feedback on the new approach, -and to iron out any bugs before a full release. Your input would be most -welcome! Please direct any feedback to the -[v2 Beta](https://github.com/wailsapp/wails/discussions/828) discussion board. - -And finally, I'd like to give a special thank you to all the -[project sponsors](/credits#sponsors), including -[JetBrains](https://www.jetbrains.com?from=Wails), whose support drive the -project in many ways behind the scenes. - -I look forward to seeing what people build with Wails in this next exciting -phase of the project! - -Lea. - -PS: Linux users, you're next! - -PPS: If you or your company find Wails useful, please consider -[sponsoring the project](https://github.com/sponsors/leaanthony). Thanks! diff --git a/docs/src/content/docs/blog/2022-02-22-v2-beta3-release-notes.md b/docs/src/content/docs/blog/2022-02-22-v2-beta3-release-notes.md deleted file mode 100644 index 047236258..000000000 --- a/docs/src/content/docs/blog/2022-02-22-v2-beta3-release-notes.md +++ /dev/null @@ -1,129 +0,0 @@ ---- -slug: blog/wails-v2-beta-for-linux -title: Wails v2 Beta for Linux -authors: [leaanthony] -tags: [wails, v2] -date: 2022-02-22 ---- - -![wails-linux screenshot](../../../assets/blog-images/wails-linux.webp) - -I'm pleased to finally announce that Wails v2 is now in beta for Linux! It is -somewhat ironic that the very first experiments with v2 was on Linux and yet it -has ended up as the last release. That being said, the v2 we have today is very -different from those first experiments. So without further ado, let's go over -the new features: - -### New Features - -![wails-menus-linux screenshot](../../../assets/blog-images/wails-menus-linux.webp) - -There were a lot of requests for native menu support. Wails has finally got you -covered. Application menus are now available and include support for most native -menu features. This includes standard menu items, checkboxes, radio groups, -submenus and separators. - -There were a huge number of requests in v1 for the ability to have greater -control of the window itself. I'm happy to announce that there's new runtime -APIs specifically for this. It's feature-rich and supports multi-monitor -configurations. There is also an improved dialogs API: Now, you can have modern, -native dialogs with rich configuration to cater for all your dialog needs. - -### No requirement to bundle assets - -A huge pain-point of v1 was the need to condense your entire application down to -single JS & CSS files. I'm happy to announce that for v2, there is no -requirement to bundle assets, in any way, shape or form. Want to load a local -image? Use an `<../../../assets/blog-images>` tag with a local src path. Want to -use a cool font? Copy it in and add the path to it in your CSS. - -> Wow, that sounds like a webserver... - -Yes, it works just like a webserver, except it isn't. - -> So how do I include my assets? - -You just pass a single `embed.FS` that contains all your assets into your -application configuration. They don't even need to be in the top directory - -Wails will just work it out for you. - -### New Development Experience - -Now that assets don't need to be bundled, it's enabled a whole new development -experience. The new `wails dev` command will build and run your application, but -instead of using the assets in the `embed.FS`, it loads them directly from disk. - -It also provides the additional features: - -- Hot reload - Any changes to frontend assets will trigger an auto reload of the - application frontend -- Auto rebuild - Any changes to your Go code will rebuild and relaunch your - application - -In addition to this, a webserver will start on port 34115. This will serve your -application to any browser that connects to it. All connected web browsers will -respond to system events like hot reload on asset change. - -In Go, we are used to dealing with structs in our applications. It's often -useful to send structs to our frontend and use them as state in our application. -In v1, this was a very manual process and a bit of a burden on the developer. -I'm happy to announce that in v2, any application run in dev mode will -automatically generate TypeScript models for all structs that are input or -output parameters to bound methods. This enables seamless interchange of data -models between the two worlds. - -In addition to this, another JS module is dynamically generated wrapping all -your bound methods. This provides JSDoc for your methods, providing code -completion and hinting in your IDE. It's really cool when you get data models -auto-imported when hitting tab in an auto-generated module wrapping your Go -code! - -### Remote Templates - -![remote-linux screenshot](../../../assets/blog-images/remote-linux.webp) - -Getting an application up and running quickly was always a key goal for the -Wails project. When we launched, we tried to cover a lot of the modern -frameworks at the time: react, vue and angular. The world of frontend -development is very opinionated, fast moving and hard to keep on top of! As a -result, we found our base templates getting out of date pretty quickly and this -caused a maintenance headache. It also meant that we didn't have cool modern -templates for the latest and greatest tech stacks. - -With v2, I wanted to empower the community by giving you the ability to create -and host templates yourselves, rather than rely on the Wails project. So now you -can create projects using community supported templates! I hope this will -inspire developers to create a vibrant ecosystem of project templates. I'm -really quite excited about what our developer community can create! - -### Cross Compilation to Windows - -Because Wails v2 for Windows is pure Go, you can target Windows builds without -docker. - -![build-cross-windows screenshot](../../../assets/blog-images/linux-build-cross-windows.webp) - -### In Conclusion - -As I'd said in the Windows release notes, Wails v2 represents a new foundation -for the project. The aim of this release is to get feedback on the new approach, -and to iron out any bugs before a full release. Your input would be most -welcome! Please direct any feedback to the -[v2 Beta](https://github.com/wailsapp/wails/discussions/828) discussion board. - -Linux is **hard** to support. We expect there to be a number of quirks with the -beta. Please help us to help you by filing detailed bug reports! - -Finally, I'd like to give a special thank you to all the -[project sponsors](/credits#sponsors) whose support drives the project in many -ways behind the scenes. - -I look forward to seeing what people build with Wails in this next exciting -phase of the project! - -Lea. - -PS: The v2 release isn't far off now! - -PPS: If you or your company find Wails useful, please consider -[sponsoring the project](https://github.com/sponsors/leaanthony). Thanks! diff --git a/docs/src/content/docs/blog/2022-09-22-v2-release-notes.md b/docs/src/content/docs/blog/2022-09-22-v2-release-notes.md deleted file mode 100644 index c72d7f566..000000000 --- a/docs/src/content/docs/blog/2022-09-22-v2-release-notes.md +++ /dev/null @@ -1,198 +0,0 @@ ---- -slug: blog/wails-v2-released -title: Wails v2 Released -authors: [leaanthony] -tags: [wails, v2] -date: 2022-09-22 ---- - -![montage screenshot](../../../assets/blog-images/montage.png) - -# It's here! - -Today marks the release of [Wails](https://wails.io) v2. It's been about 18 -months since the first v2 alpha and about a year from the first beta release. -I'm truly grateful to everyone involved in the evolution of the project. - -Part of the reason it took that long was due to wanting to get to some -definition of completeness before officially calling it v2. The truth is, -there's never a perfect time to tag a release - there's always outstanding -issues or "just one more" feature to squeeze in. What tagging an imperfect major -release does do, however, is to provide a bit of stability for users of the -project, as well as a bit of a reset for the developers. - -This release is more than I'd ever expected it to be. I hope it gives you as -much pleasure as it has given us to develop it. - -# What _is_ Wails? - -If you are unfamiliar with Wails, it is a project that enables Go programmers to -provide rich frontends for their Go programs using familiar web technologies. -It's a lightweight, Go alternative to Electron. Much more information can be -found on the [official site](https://wails.io/docs/introduction). - -# What's new? - -The v2 release is a huge leap forward for the project, addressing many of the -pain points of v1. If you have not read any of the blog posts on the Beta -releases for [macOS](/blog/wails-v2-beta-for-mac), -[Windows](/blog/wails-v2-beta-for-windows) or -[Linux](/blog/wails-v2-beta-for-linux), then I encourage you to do so as it -covers all the major changes in more detail. In summary: - -- Webview2 component for Windows that supports modern web standards and - debugging capabilities. -- [Dark / Light theme](https://wails.io/docs/reference/options#theme) + - [custom theming](https://wails.io/docs/reference/options#customtheme) on Windows. -- Windows now has no CGO requirements. -- Out-of-the-box support for Svelte, Vue, React, Preact, Lit & Vanilla project - templates. -- [Vite](https://vitejs.dev/) integration providing a hot-reload development - environment for your application. -- Native application - [menus](https://wails.io/docs/guides/application-development#application-menu) and - [dialogs](https://wails.io/docs/reference/runtime/dialog). -- Native window translucency effects for - [Windows](https://wails.io/docs/reference/options#windowistranslucent) and - [macOS](https://wails.io/docs/reference/options#windowistranslucent-1). Support for Mica & - Acrylic backdrops. -- Easily generate an [NSIS installer](https://wails.io/docs/guides/windows-installer) for - Windows deployments. -- A rich [runtime library](https://wails.io/docs/reference/runtime/intro) providing utility - methods for window manipulation, eventing, dialogs, menus and logging. -- Support for [obfuscating](https://wails.io/docs/guides/obfuscated) your application using - [garble](https://github.com/burrowers/garble). -- Support for compressing your application using [UPX](https://upx.github.io/). -- Automatic TypeScript generation of Go structs. More info - [here](https://wails.io/docs/howdoesitwork#calling-bound-go-methods). -- No extra libraries or DLLs are required to be shipped with your application. - For any platform. -- No requirement to bundle frontend assets. Just develop your application like - any other web application. - -# Credit & Thanks - -Getting to v2 has been a huge effort. There have been ~2.2K commits by 89 -contributors between the initial alpha and the release today, and many, many -more that have provided translations, testing, feedback and help on the -discussion forums as well as the issue tracker. I'm so unbelievably grateful to -each one of you. I'd also like to give an extra special thank you to all the -project sponsors who have provided guidance, advice and feedback. Everything you -do is hugely appreciated. - -There are a few people I'd like to give special mention to: - -Firstly, a **huge** thank you to [@stffabi](https://github.com/stffabi) who has -provided so many contributions which we all benefit from, as well as providing a -lot of support on many issues. He has provided some key features such as the -external dev server support which transformed our dev mode offering by allowing -us to hook into [Vite](https://vitejs.dev/)'s superpowers. It's fair to say that -Wails v2 would be a far less exciting release without his -[incredible contributions](https://github.com/wailsapp/wails/commits?author=stffabi&since=2020-01-04). -Thank you so much @stffabi! - -I'd also like to give a huge shout-out to -[@misitebao](https://github.com/misitebao) who has tirelessly been maintaining -the website, as well as providing Chinese translations, managing Crowdin and -helping new translators get up to speed. This is a hugely important task, and -I'm extremely grateful for all the time and effort put into this! You rock! - -Last, but not least, a huge thank you to Mat Ryer who has provided advice and -support during the development of v2. Writing xBar together using an early Alpha -of v2 was helpful in shaping the direction of v2, as well as give me an -understanding of some design flaws in the early releases. I'm happy to announce -that as of today, we will start to port xBar to Wails v2, and it will become the -flagship application for the project. Cheers Mat! - -# Lessons Learnt - -There are a number of lessons learnt in getting to v2 that will shape -development moving forward. - -## Smaller, Quicker, Focused Releases - -In the course of developing v2, there were many features and bug fixes that were -developed on an ad-hoc basis. This led to longer release cycles and were harder -to debug. Moving forward, we are going to create releases more often that will -include a reduced number of features. A release will involve updates to -documentation as well as thorough testing. Hopefully, these smaller, quicker, -focussed releases will lead to fewer regressions and better quality -documentation. - -## Encourage Engagement - -When starting this project, I wanted to immediately help everyone who had a -problem. Issues were "personal" and I wanted them resolved as quickly as -possible. This is unsustainable and ultimately works against the longevity of -the project. Moving forward, I will be giving more space for people to get -involved in answering questions and triaging issues. It would be good to get -some tooling to help with this so if you have any suggestions, please join in -the discussion [here](https://github.com/wailsapp/wails/discussions/1855). - -## Learning to say No - -The more people that engage with an Open Source project, the more requests there -will be for additional features that may or may not be useful to the majority of -people. These features will take an initial amount of time to develop and debug, -and incur an ongoing maintenance cost from that point on. I myself am the most -guilty of this, often wanting to "boil the sea" rather than provide the minimum -viable feature. Moving forward, we will need to say "No" a bit more to adding -core features and focus our energies on a way to empower developers to provide -that functionality themselves. We are looking seriously into plugins for this -scenario. This will allow anyone to extend the project as they see fit, as well -as providing an easy way to contribute towards the project. - -# Looking to the Future - -There are so many core features we are looking at to add to Wails in the next -major development cycle already. The -[roadmap](https://github.com/wailsapp/wails/discussions/1484) is full of -interesting ideas, and I'm keen to start work on them. One of the big asks has -been for multiple window support. It's a tricky one and to do it right, and we -may need to look at providing an alternative API, as the current one was not -designed with this in mind. Based on some preliminary ideas and feedback, I -think you'll like where we're looking to go with it. - -I'm personally very excited at the prospect of getting Wails apps running on -mobile. We already have a demo project showing that it is possible to run a -Wails app on Android, so I'm really keen to explore where we can go with this! - -A final point I'd like to raise is that of feature parity. It has long been a -core principle that we wouldn't add anything to the project without there being -full cross-platform support for it. Whilst this has proven to be (mainly) -achievable so far, it has really held the project back in releasing new -features. Moving forward, we will be adopting a slightly different approach: any -new feature that cannot be immediately released for all platforms will be -released under an experimental configuration or API. This allows early adopters -on certain platforms to try the feature and provide feedback that will feed into -the final design of the feature. This, of course, means that there are no -guarantees of API stability until it is fully supported by all the platforms it -can be supported on, but at least it will unblock development. - -# Final Words - -I'm really proud of what we've been able to achieve with the V2 release. It's -amazing to see what people have already been able to build using the beta -releases so far. Quality applications like [Varly](https://varly.app/), -[Surge](https://getsurge.io/) and [October](https://october.utf9k.net/). I -encourage you to check them out. - -This release was achieved through the hard work of many contributors. Whilst it -is free to download and use, it has not come about through zero cost. Make no -mistakes, this project has come at considerable cost. It has not only been my -time and the time of each and every contributor, but also the cost of absence -from friends and families of each of those people too. That's why I'm extremely -grateful for every second that has been dedicated to making this project happen. -The more contributors we have, the more this effort can be spread out and the -more we can achieve together. I'd like to encourage you all to pick one thing -that you can contribute, whether it is confirming someone's bug, suggesting a -fix, making a documentation change or helping out someone who needs it. All of -these small things have such a huge impact! It would be so awesome if you too -were part of the story in getting to v3. - -Enjoy! - -‐ Lea - -PS: If you or your company find Wails useful, please consider -[sponsoring the project](https://github.com/sponsors/leaanthony). Thanks! diff --git a/docs/src/content/docs/blog/2023-01-17-v3-roadmap.md b/docs/src/content/docs/blog/2023-01-17-v3-roadmap.md deleted file mode 100644 index a7d0d3b94..000000000 --- a/docs/src/content/docs/blog/2023-01-17-v3-roadmap.md +++ /dev/null @@ -1,256 +0,0 @@ ---- -slug: blog/the-road-to-wails-v3 -title: The Road to Wails v3 -authors: [leaanthony] -tags: [wails, v3] -date: 2023-01-17 ---- - -![multiwindow screenshot](../../../assets/blog-images/multiwindow.webp) - -# Introduction - -Wails is a project that simplifies the ability to write cross-platform desktop -applications using Go. It uses native webview components for the frontend (not -embedded browsers), bringing the power of the world's most popular UI system to -Go, whilst remaining lightweight. - -Version 2 was released on the 22nd of September 2022 and brought with it a lot -of enhancements including: - -- Live development, leveraging the popular Vite project -- Rich functionality for managing windows and creating menus -- Microsoft's WebView2 component -- Generation of Typescript models that mirror your Go structs -- Creating of NSIS Installer -- Obfuscated builds - -Right now, Wails v2 provides powerful tooling for creating rich, cross-platform -desktop applications. - -This blog post aims to look at where the project is at right now and what we can -improve on moving forward. - -# Where are we now? - -It's been incredible to see the popularity of Wails rising since the v2 release. -I'm constantly amazed by the creativity of the community and the wonderful -things that are being built with it. With more popularity, comes more eyes on -the project. And with that, more feature requests and bug reports. - -Over time, I've been able to identify some of the most pressing issues facing -the project. I've also been able to identify some of the things that are holding -the project back. - -## Current issues - -I've identified the following areas that I feel are holding the project back: - -- The API -- Bindings generation -- The Build System - -### The API - -The API to build a Wails application currently consists of 2 parts: - -- The Application API -- The Runtime API - -The Application API famously has only 1 function: `Run()` which takes a heap of -options which govern how the application will work. Whilst this is very simple -to use, it is also very limiting. It is a "declarative" approach which hides a -lot of the underlying complexity. For instance, there is no handle to the main -window, so you can't interact with it directly. For that, you need to use the -Runtime API. This is a problem when you start to want to do more complex things -like create multiple windows. - -The Runtime API provides a lot of utility functions for the developer. This -includes: - -- Window management -- Dialogs -- Menus -- Events -- Logs - -There are a number of things I am not happy with the Runtime API. The first is -that it requires a "context" to be passed around. This is both frustrating and -confusing for new developers who pass in a context and then get a runtime error. - -The biggest issue with the Runtime API is that it was designed for applications -that only use a single window. Over time, the demand for multiple windows has -grown and the API is not well suited to this. - -### Thoughts on the v3 API - -Wouldn't it be great if we could do something like this? - -```go -func main() { - app := wails.NewApplication(options.App{}) - myWindow := app.NewWindow(options.Window{}) - myWindow.SetTitle("My Window") - myWindow.On(events.Window.Close, func() { - app.Quit() - }) - app.Run() -} -``` - -This programmatic approach is far more intuitive and allows the developer to -interact with the application elements directly. All current runtime methods for -windows would simply be methods on the window object. For the other runtime -methods, we could move them to the application object like so: - -```go -app := wails.NewApplication(options.App{}) -app.NewInfoDialog(options.InfoDialog{}) -app.Log.Info("Hello World") -``` - -This is a much more powerful API which will allow for more complex applications -to be built. It also allows for the creation of multiple windows, -[the most up-voted feature on GitHub](https://github.com/wailsapp/wails/issues/1480): - -```go -func main() { - app := wails.NewApplication(options.App{}) - myWindow := app.NewWindow(options.Window{}) - myWindow.SetTitle("My Window") - myWindow.On(events.Window.Close, func() { - app.Quit() - }) - myWindow2 := app.NewWindow(options.Window{}) - myWindow2.SetTitle("My Window 2") - myWindow2.On(events.Window.Close, func() { - app.Quit() - }) - app.Run() -} -``` - -### Bindings generation - -One of the key features of Wails is generating bindings for your Go methods so -they may be called from Javascript. The current method for doing this is a bit -of a hack. It involves building the application with a special flag and then -running the resultant binary which uses reflection to determine what has been -bound. This leads to a bit of a chicken and egg situation: You can't build the -application without the bindings and you can't generate the bindings without -building the application. There are many ways around this but the best one would -be not to use this approach at all. - -There were a number of attempts at writing a static analyser for Wails projects -but they didn't get very far. In more recent times, it has become slightly -easier to do this with more material available on the subject. - -Compared to reflection, the AST approach is much faster however it is -significantly more complicated. To start with, we may need to impose certain -constraints on how to specify bindings in the code. The goal is to support the -most common use cases and then expand it later on. - -### The Build System - -Like the declarative approach to the API, the build system was created to hide -the complexities of building a desktop application. When you run `wails build`, -it does a lot of things behind the scenes: - -- Builds the backend binary for bindings and generates the bindings -- Installs the frontend dependencies -- Builds the frontend assets -- Determines if the application icon is present and if so, embeds it -- Builds the final binary -- If the build is for `darwin/universal` it builds 2 binaries, one for - `darwin/amd64` and one for `darwin/arm64` and then creates a fat binary using - `lipo` -- If compression is required, it compresses the binary with UPX -- Determines if this binary is to be packaged and if so: - - Ensures the icon and application manifest are compiled into the binary - (Windows) - - Builds out the application bundle, generates the icon bundle and copies it, - the binary and Info.plist to the application bundle (Mac) -- If an NSIS installer is required, it builds it - -This entire process, whilst very powerful, is also very opaque. It is very -difficult to customise it and it is very difficult to debug. - -To address this in v3, I would like to move to a build system that exists -outside of Wails. After using [Task](https://taskfile.dev/) for a while, I am a -big fan of it. It is a great tool for configuring build systems and should be -reasonably familiar to anyone who has used Makefiles. - -The build system would be configured using a `Taskfile.yml` file which would be -generated by default with any of the supported templates. This would have all of -the steps required to do all the current tasks, such as building or packaging -the application, allowing for easy customisation. - -There will be no external requirement for this tooling as it would form part of -the Wails CLI. This means that you can still use `wails build` and it will do -all the things it does today. However, if you want to customise the build -process, you can do so by editing the `Taskfile.yml` file. It also means you can -easily understand the build steps and use your own build system if you wish. - -The missing piece in the build puzzle is the atomic operations in the build -process, such as icon generation, compression and packaging. To require a bunch -of external tooling would not be a great experience for the developer. To -address this, the Wails CLI will provide all these capabilities as part of the -CLI. This means that the builds still work as expected, with no extra external -tooling, however you can replace any step of the build with any tool you like. - -This will be a much more transparent build system which will allow for easier -customisation and address a lot of the issues that have been raised around it. - -## The Payoff - -These positive changes will be a huge benefit to the project: - -- The new API will be much more intuitive and will allow for more complex - applications to be built. -- Using static analysis for bindings generation will be much faster and reduce a - lot of the complexity around the current process. -- Using an established, external build system will make the build process - completely transparent, allowing for powerful customisation. - -Benefits to the project maintainers are: - -- The new API will be much easier to maintain and adapt to new features and - platforms. -- The new build system will be much easier to maintain and extend. I hope this - will lead to a new ecosystem of community driven build pipelines. -- Better separation of concerns within the project. This will make it easier to - add new features and platforms. - -## The Plan - -A lot of the experimentation for this has already been done and it's looking -good. There is no current timeline for this work but I'm hoping by the end of Q1 -2023, there will be an alpha release for Mac to allow the community to test, -experiment with and provide feedback. - -## Summary - -- The v2 API is declarative, hides a lot from the developer and not suitable for - features such as multiple windows. A new API will be created which will be - simpler, intuitive and more powerful. -- The build system is opaque and difficult to customise so we will move to an - external build system which will open it all up. -- The bindings generation is slow and complex so we will move to static analysis - which will remove a lot of the complexity the current method has. - -There has been a lot of work put into the guts of v2 and it's solid. It's now -time to address the layer on top of it and make it a much better experience for -the developer. - -I hope you are as excited about this as I am. I'm looking forward to hearing -your thoughts and feedback. - -Regards, - -‐ Lea - -PS: If you or your company find Wails useful, please consider -[sponsoring the project](https://github.com/sponsors/leaanthony). Thanks! - -PPS: Yes, that's a genuine screenshot of a multi-window application built with -Wails. It's not a mockup. It's real. It's awesome. It's coming soon. diff --git a/docs/src/content/docs/blog/2024-12-03-alpha10-and-new-release-strategy.md b/docs/src/content/docs/blog/2024-12-03-alpha10-and-new-release-strategy.md deleted file mode 100644 index 0cba0baa7..000000000 --- a/docs/src/content/docs/blog/2024-12-03-alpha10-and-new-release-strategy.md +++ /dev/null @@ -1,52 +0,0 @@ ---- -title: Alpha 10 Released - A New Chapter for Wails -description: Announcing Wails v3 Alpha 10 and our new daily release strategy -date: 2024-12-03 -author: The Wails Team ---- - -# Alpha 10 Released - A New Chapter for Wails - -We're thrilled to announce the release of **Wails v3 Alpha 10** - and it's big! While our release cadence may have seemed slow recently, there's been an incredible amount of work happening behind the scenes. Today marks not just another release, but a shift in how we approach the development of Wails. - -## Why the Wait? - -Like many development teams, we fell into the trap of trying to achieve perfection before each release. We wanted to squash every bug, polish every feature, and ensure everything was just right. But here's the thing - software is never truly bug-free, and waiting for that mythical state only delays getting improvements into your hands. - -## Our New Release Strategy - -Starting today, we're adopting a **daily release strategy**. Any new changes merged during the day will be released at the end of that day. This approach will: - -- Get bug fixes and features to you faster -- Provide more frequent feedback loops -- Speed up our journey to Beta -- Make the development process more transparent - -This means you might see more frequent, smaller releases rather than occasional large ones. We believe this will benefit everyone in the Wails community. - -## How You Can Help - -We've been overwhelmed by the number of people wanting to contribute to Wails! To make it easier for contributors to get involved, we're implementing a new system: - -- Firstly, we are opening up bug reporting for alpha releases. The frequent releases allow us to do this. -- Issues marked with **"Ready for Work"** are open for community contributions -- These issues have clear requirements and are ready to be tackled -- Most importantly, **we need people testing PRs** - this is one of the most valuable contributions you can make - -Testing doesn't require deep knowledge of the codebase, but it provides immense value by ensuring changes work across different environments and use cases. - -## What's Next? - -With our new daily release strategy, expect to see rapid progress toward Beta. We're committed to maintaining momentum and getting Wails v3 to a stable release as quickly as possible without sacrificing quality. - -And who knows? There might be a few surprises along the way... 😉 - -## Thank You - -To everyone who has contributed code, tested releases, reported bugs, or simply used Wails - thank you. Your support and feedback drive this project forward. - -Here's to more frequent releases, faster iteration, and an exciting journey ahead! - ---- - -*Want to get involved? Check out our [GitHub repository](https://github.com/wailsapp/wails) for issues marked "ready for work", or join our community to help test the latest changes.* \ No newline at end of file diff --git a/docs/src/content/docs/changelog.mdx b/docs/src/content/docs/changelog.mdx deleted file mode 100644 index a44e73055..000000000 --- a/docs/src/content/docs/changelog.mdx +++ /dev/null @@ -1,1149 +0,0 @@ ---- -title: Changelog ---- - - -Legend: --  - macOS -- ⊞ - Windows -- 🐧 - Linux - -/*-- -All notable changes to this project will be documented in this file. - -The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), -and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). - -- `Added` for new features. -- `Changed` for changes in existing functionality. -- `Deprecated` for soon-to-be removed features. -- `Removed` for now removed features. -- `Fixed` for any bug fixes. -- `Security` in case of vulnerabilities. - -*/ - -/* - ** PLEASE DO NOT UPDATE THIS FILE ** - Updates should be added to `v3/UNRELEASED_CHANGELOG.md` - Thank you! -*/ -## [Unreleased] - -## v3.0.0-alpha.68 - 2026-02-07 - -## Added -- Add Web API examples in `v3/examples/web-apis/` demonstrating 41 browser APIs including Storage (localStorage, sessionStorage, IndexedDB, Cache API), Network (Fetch, WebSocket, XMLHttpRequest, EventSource, Beacon), Media (Canvas, WebGL, Web Audio, MediaDevices, MediaRecorder, Speech Synthesis), Device (Geolocation, Clipboard, Fullscreen, Device Orientation, Vibration, Gamepad), Performance (Performance API, Mutation Observer, Intersection/Resize Observer), UI (Web Components, Pointer Events, Selection, Dialog, Drag and Drop), and more -- Add WebView API compatibility checker example (`v3/examples/webview-api-check/`) that tests 200+ browser APIs across platforms -- Add `internal/libpath` package for finding native library paths on Linux with parallel search, caching, and support for Flatpak/Snap/Nix -- **WIP:** Add experimental WebKitGTK 6.0 / GTK4 support for Linux, available via `-tags gtk4` (GTK3/WebKit2GTK 4.1 remains the default) - - Note: On tiling window managers (e.g., Hyprland, Sway), Minimize/Maximize operations may not work as expected since the WM controls window geometry - -## Changed -- **BREAKING**: Map keys in generated JS/TS bindings are now marked optional to accurately reflect Go map semantics. Map value access in Typescript now returns `T | undefined` instead of `T`, requiring null checks or assertions (#4943) by `@fbbdev` - -## Fixed -- Fix file drag-and-drop on Windows not working at non-100% display scaling -- Fix HTML5 internal drag-and-drop being broken when file drop was enabled on Windows -- Fix file drop coordinates being in wrong pixel space on Windows (physical vs CSS pixels) -- Fix file drag-and-drop on Linux not working reliably with hover effects -- Fix HTML5 internal drag-and-drop being broken when file drop was enabled on Linux -- Fix DPI scaling on Linux/GTK4 by implementing proper PhysicalBounds calculation and fractional scaling support via `gdk_monitor_get_scale` (GTK 4.14+) -- Fix menu items duplicating when creating new windows on Linux/GTK4 -- Fix generation of mapped types with enum keys in JS/TS bindings (#4437) by @fbbdev - -## v3.0.0-alpha.67 - 2026-02-04 - -## Added -- Added how to do `One Time Handlers` in the docs for `Listening to Events in JavaScript` by @AbdelhadiSeddar - -## Changed -- Changed the use of `Event` into `Events` according to changes in `@wailsio/runtime` and appropriate function calls in the docs in `Features/Events/Event System` by @AbdelhadiSeddar - -## Fixed -- Fix "ghost windows" issue on macOS caused by not accessing AppKit APIs from the Main Thread in App.Window.Current() (#4947) by @wimaha -- Fix HTML `` not working on macOS by implementing WKUIDelegate runOpenPanelWithParameters (#4862) -- Fix native file drag-and-drop not working when using `@wailsio/runtime` npm module on macOS/Linux (#4953) by @leaanthony -- Fix binding generation for cross-package type aliases (#4578) by @fbbdev - -## v3.0.0-alpha.66 - 2026-02-03 - -## Added -- Add `UseApplicationMenu` option to `WebviewWindowOptions` allowing windows on Windows/Linux to inherit the application menu set via `app.Menu.Set()` by @leaanthony - -## Changed -- Move `EnabledFeatures`, `DisabledFeatures`, and `AdditionalBrowserArgs` from per-window options to application-level `Options.Windows` (#4559) by @leaanthony - -## Fixed -- Fix OpenFileDialog crash on Linux due to GTK thread safety violation (#3683) by @ddmoney420 -- Fix SIGSEGV crash when calling `Focus()` on a hidden or destroyed window (#4890) by @ddmoney420 -- Fix potential panic when setting empty icon or bitmap on Linux (#4923) by @ddmoney420 -- Fix ErrorDialog crash when called from service binding on macOS (#3631) by @leaanthony -- Make menus to be displayed on Windows OS in `v3\examples\dialogs` by @ndianabasi -- Fix race condition causing TypeError during page reload (#4872) by @ddmoney420 -- Fix incorrect output from binding generator tests by removing global state in the `Collector.IsVoidAlias()` method (#4941) by @fbbdev -- Fix `` file picker not working on macOS (#4862) by @leaanthony - -## Removed -- **BREAKING**: Remove `EnabledFeatures`, `DisabledFeatures`, and `AdditionalLaunchArgs` from per-window `WindowsWindow` options. Use application-level `Options.Windows.EnabledFeatures`, `Options.Windows.DisabledFeatures`, and `Options.Windows.AdditionalBrowserArgs` instead. These flags apply globally to the shared WebView2 environment (#4559) by @leaanthony - -## v3.0.0-alpha.65 - 2026-02-01 - -## Added -- Add support for using `.icon` files (Apple Icon Composer format) for generating Liquid Glass icons and asset catalogs (macOS) (#4934) by @wimaha - -## v3.0.0-alpha.64 - 2026-01-26 - -## Added -- Add experimental server mode for headless/web deployments (`-tags server`). Enables running Wails apps as HTTP servers without native GUI dependencies. Build with `wails3 task build:server`. See `examples/server` for details. - -## v3.0.0-alpha.63 - 2026-01-25 - -## Fixed -- Fix `Position()` and `SetPosition()` using inconsistent coordinate systems on macOS, causing window position drift when saving/restoring state (#4816) by @leaanthony - -## v3.0.0-alpha.62 - 2026-01-22 - -## Fixed -- Fix SetProcessDpiAwarenessContext "Access is denied" error when DPI awareness is already set via application manifest (#4803) - -## v3.0.0-alpha.61 - 2026-01-20 - -## Fixed -- Update the docs page for keyboard shortcuts and corrects the type of the callback parameter for `KeyBinding.Add` by @ndianabasi -- Fix documentation regarding generating custom binding, must use `-d String` instead of `-o String` - -## v3.0.0-alpha.60 - 2026-01-14 - -## Fixed -- Fix menu not clearing children on `menu.Update()` - -## v3.0.0-alpha.59 - 2026-01-11 - -## Changed -- Update the README for the `Drag N Drop` example and highlights that `Internal Drag and Drop` is demonstrated with the example @ndianabasi - -## v3.0.0-alpha.58 - 2026-01-09 - -## Fixed -- Fix outdated Manager API references in documentation (31 files updated to use new pattern like `app.Window.New()`, `app.Event.Emit()`, etc.) by @leaanthony -- Fix Linux crash on panic in JS-bound Go methods due to WebKit overriding signal handlers (#3965) by @leaanthony - -## v3.0.0-alpha.57 - 2026-01-05 - -## Changed -- Replace various debug logs from Info to Debug (by @mbaklor) - -## Fixed -- Fix SaveFileDialog.SetFilename() having no effect on Linux (#4841) by @samstanier -- Fix drop coordinates showing as undefined in drag-n-drop example -- Fix macOS app bundle creation failing when APP_NAME contains spaces (brace expansion issue) -- Fix index out of bounds panic on Windows when calling service methods (revert goccy/go-json) - -## v3.0.0-alpha.56 - 2026-01-04 - -## Added -- Add `internal/libpath` package for finding native library paths on Linux with parallel search, caching, and support for Flatpak/Snap/Nix - -## Changed -- **BREAKING:** Rename `EnableDragAndDrop` to `EnableFileDrop` in window options -- **BREAKING:** Rename `DropZoneDetails` to `DropTargetDetails` in event context -- **BREAKING:** Rename `DropZoneDetails()` method to `DropTargetDetails()` on `WindowEventContext` -- **BREAKING:** Remove `WindowDropZoneFilesDropped` event, use `WindowFilesDropped` instead -- **BREAKING:** Change HTML attribute from `data-wails-dropzone` to `data-file-drop-target` -- **BREAKING:** Change CSS hover class from `wails-dropzone-hover` to `file-drop-target-active` -- **BREAKING:** Remove `DragEffect`, `OnEnterEffect`, `OnOverEffect` options from Windows (were part of removed IDropTarget) - -## Fixed -- Fix file drag-and-drop on Windows not working at non-100% display scaling -- Fix HTML5 internal drag-and-drop being broken when file drop was enabled on Windows -- Fix file drop coordinates being in wrong pixel space on Windows (physical vs CSS pixels) -- Fix file drag-and-drop on Linux not working reliably with hover effects -- Fix HTML5 internal drag-and-drop being broken when file drop was enabled on Linux - -## Removed -- Remove native `IDropTarget` implementation on Windows in favor of JavaScript-based approach (matches v2 behavior) - -## v3.0.0-alpha.55 - 2026-01-02 - -## Changed -- Switch to goccy/go-json for all runtime JSON processing (method bindings, events, webview requests, notifications, kvstore), improving performance by 21-63% and reducing memory allocations by 40-60% -- Optimize BoundMethod struct layout and cache isVariadic flag to reduce per-call overhead -- Use stack-allocated argument buffer for methods with `<=8` arguments to avoid heap allocations -- Optimize result collection in method calls to avoid slice allocation for single return values -- Use sync.Map for MIME type cache to improve concurrent performance -- Use buffer pool for HTTP transport request body reading -- Lazily allocate CloseNotify channel in content type sniffer to reduce per-request allocations -- Remove debug CSS logging from asset server -- Expand MIME type extension map to cover 50+ common web formats (fonts, audio, video, etc.) - -## Fixed -- Update all commands in Taskfile.yml files for all operating systems to accommodate spaces in variables such as `APP_NAME` by @ndianabasi - -## Removed -- Remove github.com/wailsapp/mimetype dependency in favor of expanded extension map + stdlib http.DetectContentType, reducing binary size by ~1.2MB -- Remove gopkg.in/ini.v1 dependency by implementing minimal .desktop file parser for Linux file explorer, saving ~45KB -- Remove samber/lo from runtime code by using Go 1.21+ stdlib slices package and minimal internal helpers, saving ~310KB - -## v3.0.0-alpha.54 - 2025-12-29 - -## Added -- Add `CollectionBehavior` option to `MacWindow` for controlling window behavior across macOS Spaces and fullscreen (#4756) by @leaanthony - -## Fixed -- Fix command argument error when executing 'build:universal:lipo:go' task on Linux by @wux1an -- Fix Docker error "undefined symbol: ___ubsan_handle_xxxxxxx" when running 'wails3 build GOOS=darwin GOARCH=arm64' on Linux by @wux1an - -## Removed -- Remove debug printf statements from Darwin URL scheme handler (#4834) - -## v3.0.0-alpha.53 - 2025-12-27 - -## Added -- Add unit tests for pkg/application by @leaanthony -- Add custom protocol support to MSIX packaging by @leaanthony - -## Fixed -- Consolidate custom protocol documentation and add Universal Links sections by @leaanthony - -## v3.0.0-alpha.52 - 2025-12-26 - -## Fixed -- Fix Windows systray menu crash when clicking icon repeatedly by adding guard against concurrent TrackPopupMenuEx calls (#4151) by @leaanthony - -## v3.0.0-alpha.51 - 2025-12-23 - -## Fixed -- Prevent app crashing when calling systray.Run() before app.Run() by @leaanthony - -## v3.0.0-alpha.50 - 2025-12-21 - -## Changed -- Update the documentation for Window `X/Y` options @ruhuang2001 - -## v3.0.0-alpha.49 - 2025-12-18 - -## Changed -- Update the `Frontend Runtime` documentation by adding more options for generating frontend bindings by @ndianabasi - -## v3.0.0-alpha.48 - 2025-12-16 - -## Added -- Add desktop environment detection on linux [PR #4797](https://github.com/wailsapp/wails/pull/4797) - -## Changed -- Update the documentation page for Wails v3 Asset Server by @ndianabasi -- **BREAKING**: Remove package-level dialog functions (`application.InfoDialog()`, `application.QuestionDialog()`, etc.). Use the `app.Dialog` manager instead: `app.Dialog.Info()`, `app.Dialog.Question()`, `app.Dialog.Warning()`, `app.Dialog.Error()`, `app.Dialog.OpenFile()`, `app.Dialog.SaveFile()` -- Update dialogs documentation to match actual API: use `app.Dialog.*`, `AddButton()` with callbacks (not `SetButtons()`), `SetDefaultButton(*Button)` (not string), `AddFilter()` (not `SetFilters()`), `SetFilename()` (not `SetDefaultFilename()`), and `app.Dialog.OpenFile().CanChooseDirectories(true)` for folder selection - -## Fixed -- Fix crash on macOS when toggling window visibility via Hide()/Show() with ApplicationShouldTerminateAfterLastWindowClosed enabled (#4389) by @leaanthony -- Fix memory leak in context menus on macOS and Windows when repeatedly opening menus (#4012) by @leaanthony -- Fix context menu native resources not being reused on macOS, causing fresh menu creation on each display (#4012) by @leaanthony - -## v3.0.0-alpha.47 - 2025-12-15 - -## Added -- Add `Window.Print()` method to JavaScript runtime for triggering print dialog from frontend (#4290) by @leaanthony - -## Fixed -- Fix macOS dock icon click not showing hidden windows when app started with `Hidden: true` (#4583) by @leaanthony -- Fix macOS print dialog not opening due to incorrect window pointer type in CGO call (#4290) by @leaanthony - -## v3.0.0-alpha.46 - 2025-12-14 - -## Added -- Add `XDG_SESSION_TYPE` to `wails3 doctor` output on Linux by @leaanthony -- Add additional WebKit2 load-change events for Linux: `WindowLoadStarted`, `WindowLoadRedirected`, `WindowLoadCommitted`, `WindowLoadFinished` (#3896) by @leaanthony - -## Removed -- **BREAKING**: Remove `linux:WindowLoadChanged` event - use `linux:WindowLoadFinished` instead for detecting when WebView has finished loading (#3896) by @leaanthony - -## v3.0.0-alpha.45 - 2025-12-13 - -## Added -- Add `XDG_SESSION_TYPE` to `wails3 doctor` output on Linux by @leaanthony -- Generate `.desktop` file during Linux build, not just packaging (#4575) -- Add Linux runtime dependencies documentation with distro-specific package names and nfpm packaging examples (#4339) by @leaanthony - -## Fixed -- Fix window menu crash on Wayland caused by appmenu-gtk-module accessing unrealized window (#4769) by @leaanthony -- Fix GTK application crash when app name contains invalid characters (spaces, parentheses, etc.) by @leaanthony -- Fix "not enough memory" error when initializing drag and drop on Windows (#4701) by @overlordtm -- Fix file explorer opening wrong directory on Linux due to incorrect URI escaping (#4397) by @leaanthony -- Fix AppImage build failure on modern Linux distributions (Arch, Fedora 39+, Ubuntu 24.04+) by auto-detecting `.relr.dyn` ELF sections and disabling stripping (#4642) by @leaanthony -- Fix `wails doctor` falsely reporting webkit packages as installed on Fedora/DNF-based systems (#4457) by @leaanthony - -## v3.0.0-alpha.44 - 2025-12-12 - -## Added -- Add NVIDIA driver version info to `wails3 doctor` output on Linux by @leaanthony - -## Changed -- **BREAKING**: Production builds are now the default. To create dev builds, set `DEV=true` in your Taskfiles. Generate a new project for examples by @leaanthony - -## Fixed -- Fix default `config.yml` would run `wails3 dev` with a production build by @mbaklor -- Fix iOS service stubs causing build failures due to non-existent package import by @leaanthony -- Fix structured logging in debug/info methods causing "no formatting directives" errors by @leaanthony -- Remove temporary debug print statements accidentally included from mobile platform merge by @leaanthony -- Fix WebKitGTK crash on Wayland with NVIDIA GPUs (Error 71 Protocol error) by auto-disabling DMA-BUF renderer by @leaanthony - -## v3.0.0-alpha.43 - 2025-12-11 - -## Added -- Add origin to raw message handler by @APshenkin in [PR](https://github.com/wailsapp/wails/pull/4710) -- Add universal link support for macOS by @APshenkin in [PR](https://github.com/wailsapp/wails/pull/4712) -- Refactor binding transport layer by @APshenkin in [PR](https://github.com/wailsapp/wails/pull/4702) -- Add aria-label identifiers to the helloworld templates so that the example app can be easily tested by Appium test clients by @chinenual in [PR](https://github.com/wailsapp/wails/pull/4760) - -## v3.0.0-alpha.42 - 2025-12-10 - -## Added -- Add origin to raw message handler by @APshenkin in [PR](https://github.com/wailsapp/wails/pull/4710) -- Add universal link support for macOS by @APshenkin in [PR](https://github.com/wailsapp/wails/pull/4712) -- Refactor binding transport layer by @APshenkin in [PR](https://github.com/wailsapp/wails/pull/4702) - -## v3.0.0-alpha.41 - 2025-11-23 - -## Fixed -- Resolve alpha value being ignored in `application.WebviewWindowOptions.BackgroundColour` on Linux ([#4722](https://github.com/wailsapp/wails/pull/4722), @BradHacker) - -## v3.0.0-alpha.40 - 2025-11-13 - -## Fixed -- Fix Windows systray icon not defaulting to application icon when no custom icon is provided (#4704) - -## v3.0.0-alpha.39 - 2025-11-12 - -## Added -- Typed Events by @fbbdev and @ianvs in [#4633](https://github.com/wailsapp/wails/pull/4633) - -## Changed -- When emitting a custom event with zero or one data argument, the data value will be assigned directly to the Data field without wrapping it in a slice by [@fbbdev](https://github.com/fbbdev) in [#4633](https://github.com/wailsapp/wails/pull/4633) - -## v3.0.0-alpha.38 - 2025-11-04 - -## Added -- Add `systray-clock` example showing a headless tray with live tooltip updates (#4653). - -## Changed -- Windows trays now honor `SystemTray.Show()`/`Hide()` by toggling `NIS_HIDDEN`, so apps can truly disappear and return (#4653). -- Tray registration reuses resolved icons, sets `NOTIFYICON_VERSION_4` once, and enables `NIF_SHOWTIP` so tooltips recover after Explorer restarts (#4653). - -## Fixed -- Track `HICON` ownership so only user-created handles are destroyed, preventing Explorer recycling crashes (#4653). -- Release the Windows system-theme listener and retained tray icons during destroy to stop leaking goroutines and device contexts (#4653). -- Truncate tray tooltips at 127 UTF-16 units to avoid corrupting surrogate pairs and multi-byte glyphs (#4653). - -## v3.0.0-alpha.37 - 2025-11-02 - -## Fixed -- Fix Windows package task failure (#4667) - -## v3.0.0-alpha.36 - 2025-10-15 - -## Fixed -- Fix Linux appimage appicon variable in Linux taskfile [PR #4644](https://github.com/wailsapp/wails/pull/4644) -- Fix Windows build error caused by go-webview2 v1.0.22 signature change (#4513, #4645) - -## v3.0.0-alpha.35 - 2025-10-14 - -## Fixed -- Fix Linux appimage appicon variable in Linux taskfile [PR #4644](https://github.com/wailsapp/wails/pull/4644) - -## v3.0.0-alpha.34 - 2025-10-06 - -## Added -- Added NSIS Protocol template for Windows by @Tolfx in #4510 -- Added tests for build-assets by @Tolfx in #4510 - -## Fixed -- Fixed linux desktop.tmpl protocol range, by removing `<.Info.Protocol>` to `<.Protocol>` by @Tolfx in #4510 -- Fixed redefinition error for liquid glass demo in [#4542](https://github.com/wailsapp/wails/pull/4542) by @Etesam913 - -## v3.0.0-alpha.33 - 2025-10-04 - -## Fixed -- Fixed systray menu updates on Linux [#4604](https://github.com/wailsapp/wails/issues/4604) by [@JackDoan](https://github.com/JackDoan) - -## v3.0.0-alpha.32 - 2025-10-02 - -## Fixed -- Fix the white window appearing on Windows when creating a hidden window by @leaanthony in [#4612](https://github.com/wailsapp/wails/pull/4612) -- Fix notifications package import path in documentation by @rxliuli in [#4617](https://github.com/wailsapp/wails/pull/4617) -- Fix drag-and-drop not working when using npm package @wailsio/runtime (#4489) by @leaanthony in #4616 - -## v3.0.0-alpha.31 - 2025-09-27 - -## Fixed -- Windows: Flicker of window at start and hidden windows being shown incorrectly in [PR](https://github.com/wailsapp/wails/pull/4600) by @leaanthony. -- Fixed Wayland window size maximising issues (https://github.com/wailsapp/wails/issues/4429) by [@samstanier](https://github.com/samstanier) - -## v3.0.0-alpha.30 - 2025-09-26 - -## Fixed -- Fixed Wayland window size maximising issues (https://github.com/wailsapp/wails/issues/4429) by [@samstanier](https://github.com/samstanier) - -## v3.0.0-alpha.29 - 2025-09-25 - -## Added -- macOS: Shows native window controls in the menu bar in [#4588](https://github.com/wailsapp/wails/pull/4588) by @nidib -- Add macOS Dock service to hide/show app icon in the dock @popaprozac in [PR](https://github.com/wailsapp/wails/pull/4451) - -## Changed -- macOS: Use `visibleFrame` instead of `frame` for window centering to exclude menu bar and dock areas - -## Fixed -- Fixed redefinition error for liquid glass demo in [#4542](https://github.com/wailsapp/wails/pull/4542) by @Etesam913 -- Fixed issue where AssetServer can crash on MacOS in [#4576](https://github.com/wailsapp/wails/pull/4576) by @jghiloni -- Fixed compilation issue when building with NextJs. Fixed in [#4585](https://github.com/wailsapp/wails/pull/4585) by @rev42 -- Fixed pipelines for nightly release in [#4597](https://github.com/wailsapp/wails/pull/4597) by @riadafridishibly - -## v3.0.0-alpha.29 - 2025-09-25 - -## Added -- Add macOS Dock service to hide/show app icon in the dock @popaprozac in [PR](https://github.com/wailsapp/wails/pull/4451) - -## Changed -- macOS: Use `visibleFrame` instead of `frame` for window centering to exclude menu bar and dock areas - -## Fixed -- Fixed redefinition error for liquid glass demo in [#4542](https://github.com/wailsapp/wails/pull/4542) by @Etesam913 -- Fixed issue where AssetServer can crash on MacOS in [#4576](https://github.com/wailsapp/wails/pull/4576) by @jghiloni -- Fixed compilation issue when building with NextJs. Fixed in [#4585](https://github.com/wailsapp/wails/pull/4585) by @rev42 -- Fixed pipelines for nightly release in [#4597](https://github.com/wailsapp/wails/pull/4597) by @riadafridishibly - -## v3.0.0-alpha.27 - 2025-09-07 - -## Fixed -- Fixed redefinition error for liquid glass demo in [#4542](https://github.com/wailsapp/wails/pull/4542) by @Etesam913 - - -## v3.0.0-alpha.26 - 2025-08-24 - -## Added -- Add native Liquid Glass effect support for macOS with NSGlassEffectView (macOS 15.0+) and NSVisualEffectView fallback, including comprehensive material customization options by @leaanthony in [#4534](https://github.com/wailsapp/wails/pull/4534) - -## v3.0.0-alpha.25 - 2025-08-16 - -## Changed -- When running `wails3 update build-assets` with the `-config` parameter, values set via the `-product*` parameters are - no longer ignored, and override the config value. - -## v3.0.0-alpha.24 - 2025-08-13 - -## Added -- Browser URL Sanitisation by @leaanthony in [#4500](https://github.dev/wailsapp/wails/pull/4500). Based on [#4484](https://github.com/wailsapp/wails/pull/4484) by @APShenkin. - -## v3.0.0-alpha.23 - 2025-08-11 - -## Fixed -- Fix SetBackgroundColour on Windows by @PPTGamer in [PR](https://github.com/wailsapp/wails/pull/4492) - -## v3.0.0-alpha.22 - 2025-08-10 - -## Added -- Add Content Protection on Windows/Mac by [@leaanthony](https://github.com/leaanthony) based on the original work of [@Taiterbase](https://github.com/Taiterbase) in this [PR](https://github.com/wailsapp/wails/pull/4241) -- Add support for passing CLI variables to Task commands through `wails3 build` and `wails3 package` aliases (#4422) by @leaanthony in [PR](https://github.com/wailsapp/wails/pull/4488) - -## Changed -- `window.NativeWindowHandle()` -> `window.NativeWindow()` by @leaanthony in [#4471](https://github.com/wailsapp/wails/pull/4471) -- Refactor internal window handling by @leaanthony in [#4471](https://github.com/wailsapp/wails/pull/4471) -+ Fix extra-broad Linux package dependencies, fix outdated RPM dependencies. - -## v3.0.0-alpha.21 - 2025-08-07 - -## Fixed -- Update docs to reflect changes from Manager API Refactoring by @yulesxoxo in [PR #4476](https://github.com/wailsapp/wails/pull/4476) -- Fix Linux .desktop file appicon variable in Linux taskfile [PR #4477](https://github.com/wailsapp/wails/pull/4477) - -## v3.0.0-alpha.20 - 2025-08-06 - -## Fixed -- Update docs to reflect changes from Manager API Refactoring by @yulesxoxo in [PR #4476](https://github.com/wailsapp/wails/pull/4476) - -## v3.0.0-alpha.19 - 2025-08-05 - -## Added -- Support for dropzones with event sourcing dropped element data [@atterpac](https://github.com/atterpac) in [#4318](https://github.com/wailsapp/wails/pull/4318) -- Added `AdditionalLaunchArgs` to `WindowsWindow` options to allow for additional command line arguments to be passed to the WebView2 browser. in [PR](https://github.com/wailsapp/wails/pull/4467) -- Added Run go mod tidy automatically after wails init [@triadmoko](https://github.com/triadmoko) in [PR](https://github.com/wailsapp/wails/pull/4286) -- Windows Snapassist feature by @leaanthony in [PR](https://github.dev/wailsapp/wails/pull/4463) - -## Fixed -- Fix Windows nil pointer dereference bug reported in [#4456](https://github.com/wailsapp/wails/issues/4456) by @leaanthony in [#4460](https://github.com/wailsapp/wails/pull/4460) -- Add support for `allowsBackForwardNavigationGestures` in macOS WKWebView to enable two-finger swipe navigation gestures (#1857) -- Fixes issue where onClick didn't work for menu items initially set as disabled by @leaanthony in [PR #4469](https://github.com/wailsapp/wails/pull/4469). Thanks to @IanVS for the initial investigation. -- Fix Vite server not being cleaned up when build fails (#4403) -- Fixed panic when closing or cancelling a `SaveFileDialog` on windows. Fixed in [PR](https://github.com/wailsapp/wails/pull/4284) by @hkhere -- Fixed HTML level drag and drop on Windows by [@mbaklor](https://github.com/mbaklor) in [#4259](https://github.com/wailsapp/wails/pull/4259) - -## v3.0.0-alpha.18 - 2025-08-03 - -## Added -- Added `AdditionalLaunchArgs` to `WindowsWindow` options to allow for additional command line arguments to be passed to the WebView2 browser. in [PR](https://github.com/wailsapp/wails/pull/4467) -- Added Run go mod tidy automatically after wails init [@triadmoko](https://github.com/triadmoko) in [PR](https://github.com/wailsapp/wails/pull/4286) -- Windows Snapassist feature by @leaanthony in [PR](https://github.dev/wailsapp/wails/pull/4463) - -## Fixed -- Add support for `allowsBackForwardNavigationGestures` in macOS WKWebView to enable two-finger swipe navigation gestures (#1857) -- Fixes issue where onClick didn't work for menu items initially set as disabled by @leaanthony in [PR #4469](https://github.com/wailsapp/wails/pull/4469). Thanks to @IanVS for the initial investigation. -- Fix Vite server not being cleaned up when build fails (#4403) - -## v3.0.0-alpha.17 - 2025-07-31 - -## Fixed -- Fixed notification parsing on Windows @popaprozac in [PR](https://github.com/wailsapp/wails/pull/4450) - -## v3.0.0-alpha.16 - 2025-07-25 - -## Added -- Add Windows `getAccentColor` implementation by [@almas-x](https://github.com/almas-x) in [PR](https://github.com/wailsapp/wails/pull/4427) - -## v3.0.0-alpha.15 - 2025-07-25 - -## Added -- Add Windows `getAccentColor` implementation by [@almas-x](https://github.com/almas-x) in [PR](https://github.com/wailsapp/wails/pull/4427) - -## v3.0.0-alpha.14 - 2025-07-25 - -## Added -- Windows dark theme menus + menubar. By @leaanthony in [a29b4f0861b1d0a700e9eb213c6f1076ec40efd5](https://github.com/wailsapp/wails/commit/a29b4f0861b1d0a700e9eb213c6f1076ec40efd5) -- Rename built-in services for clearer JS/TS bindings by @popaprozac in [PR](https://github.com/wailsapp/wails/pull/4405) - -## v3.0.0-alpha.12 - 2025-07-15 - -### Added -- `app.Env.GetAccentColor` to get the accent color of a user's system. Works on MacOS. by [@etesam913](https://github.com/etesam913) -- Add `window.ToggleFrameless()` api by [@atterpac](https://github.com/atterpac) in [#4137](https://github.com/wailsapp/wails/pull/4137) - -### Fixed -- Fixed doctor command to check for Windows SDK dependencies by [@kodumulo](https://github.com/kodumulo) in [#4390](https://github.com/wailsapp/wails/issues/4390) - - -## v3.0.0-alpha.11 - 2025-07-12 - -## Added -- Add distribution-specific build dependencies for Linux by @leaanthony in [PR](https://github.com/wailsapp/wails/pull/4345) -- Added bindings guide by @atterpac in [PR](https://github.com/wailsapp/wails/pull/4404) - -## v3.0.0-alpha.10 - 2025-07-06 - -### Breaking Changes -- **Manager API Refactoring**: Reorganized application API from flat structure to organized managers for better code organization and discoverability by [@leaanthony](https://github.com/leaanthony) in [#4359](https://github.com/wailsapp/wails/pull/4359) - - `app.NewWebviewWindow()` → `app.Window.New()` - - `app.CurrentWindow()` → `app.Window.Current()` - - `app.GetAllWindows()` → `app.Window.GetAll()` - - `app.WindowByName()` → `app.Window.GetByName()` - - `app.EmitEvent()` → `app.Event.Emit()` - - `app.OnApplicationEvent()` → `app.Event.OnApplicationEvent()` - - `app.OnWindowEvent()` → `app.Event.OnWindowEvent()` - - `app.SetApplicationMenu()` → `app.Menu.SetApplicationMenu()` - - `app.OpenFileDialog()` → `app.Dialog.OpenFile()` - - `app.SaveFileDialog()` → `app.Dialog.SaveFile()` - - `app.MessageDialog()` → `app.Dialog.Message()` - - `app.InfoDialog()` → `app.Dialog.Info()` - - `app.WarningDialog()` → `app.Dialog.Warning()` - - `app.ErrorDialog()` → `app.Dialog.Error()` - - `app.QuestionDialog()` → `app.Dialog.Question()` - - `app.NewSystemTray()` → `app.SystemTray.New()` - - `app.GetSystemTray()` → `app.SystemTray.Get()` - - `app.ShowContextMenu()` → `app.ContextMenu.Show()` - - `app.RegisterKeybinding()` → `app.KeyBinding.Register()` - - `app.UnregisterKeybinding()` → `app.KeyBinding.Unregister()` - - `app.GetPrimaryScreen()` → `app.Screen.GetPrimary()` - - `app.GetAllScreens()` → `app.Screen.GetAll()` - - `app.BrowserOpenURL()` → `app.Browser.OpenURL()` - - `app.Environment()` → `app.Env.GetAll()` - - `app.ClipboardGetText()` → `app.Clipboard.Text()` - - `app.ClipboardSetText()` → `app.Clipboard.SetText()` -- Renamed Service methods: `Name` -> `ServiceName`, `OnStartup` -> `ServiceStartup`, `OnShutdown` -> `ServiceShutdown` by [@leaanthony](https://github.com/leaanthony) -- Moved `Path` and `Paths` methods to `application` package by [@leaanthony](https://github.com/leaanthony) -- The application menu is now macOS only by [@leaanthony](https://github.com/leaanthony) - -### Added - -- **Organized Testing Infrastructure**: Moved Docker test files to dedicated `test/docker/` directory with optimized images and enhanced build reliability by [@leaanthony](https://github.com/leaanthony) in [#4359](https://github.com/wailsapp/wails/pull/4359) -- **Improved Resource Management Patterns**: Added proper event handler cleanup and context-aware goroutine management in examples by [@leaanthony](https://github.com/leaanthony) in [#4359](https://github.com/wailsapp/wails/pull/4359) -- Support aarch64 AppImage builds by [@AkshayKalose](https://github.com/AkshayKalose) in [#3981](https://github.com/wailsapp/wails/pull/3981) -- Add diagnostics section to `wails doctor` by [@leaanthony](https://github.com/leaanthony) -- Add window to context when calling a service method by [@leaanthony](https://github.com/leaanthony) -- Add `window-call` example to demonstrate how to know which window is calling a service by [@leaanthony](https://github.com/leaanthony) -- New Menu guide by [@leaanthony](https://github.com/leaanthony) -- Better panic handling by [@leaanthony](https://github.com/leaanthony) -- New Menu guide by [@leaanthony](https://github.com/leaanthony) -- Add doc comments for Service API by [@fbbdev](https://github.com/fbbdev) in [#4024](https://github.com/wailsapp/wails/pull/4024) -- Add function `application.NewServiceWithOptions` to initialise services with additional configuration by [@leaanthony](https://github.com/leaanthony) in [#4024](https://github.com/wailsapp/wails/pull/4024) -- Improved menu control by [@FalcoG](https://github.com/FalcoG) and [@leaanthony](https://github.com/leaanthony) in [#4031](https://github.com/wailsapp/wails/pull/4031) -- More documentation by [@leaanthony](https://github.com/leaanthony) -- Support cancellation of events in standard event listeners by [@leaanthony](https://github.com/leaanthony) -- Systray `Hide`, `Show` and `Destroy` support by [@leaanthony](https://github.com/leaanthony) -- Systray `SetTooltip` support by [@leaanthony](https://github.com/leaanthony). Original idea by [@lujihong](https://github.com/wailsapp/wails/issues/3487#issuecomment-2633242304) -- Report package path in binding generator warnings about unsupported types by [@fbbdev](https://github.com/fbbdev) in [#4045](https://github.com/wailsapp/wails/pull/4045) -- Add binding generator support for generic aliases by [@fbbdev](https://github.com/fbbdev) in [#4045](https://github.com/wailsapp/wails/pull/4045) -- Add binding generator support for `omitzero` JSON flag by [@fbbdev](https://github.com/fbbdev) in [#4045](https://github.com/wailsapp/wails/pull/4045) -- Add `//wails:ignore` directive to prevent binding generation for chosen service methods by [@fbbdev](https://github.com/fbbdev) in [#4045](https://github.com/wailsapp/wails/pull/4045) -- Add `//wails:internal` directive on services and models to allow for types that are exported in Go but not in JS/TS by [@fbbdev](https://github.com/fbbdev) in [#4045](https://github.com/wailsapp/wails/pull/4045) -- Add binding generator support for constants of alias type to allow for weakly typed enums by [@fbbdev](https://github.com/fbbdev) in [#4045](https://github.com/wailsapp/wails/pull/4045) -- Add binding generator tests for Go 1.24 features by [@fbbdev](https://github.com/fbbdev) in [#4068](https://github.com/wailsapp/wails/pull/4068) -- Add support for macOS 15 "Sequoia" to `OSInfo.Branding` for improved OS version detection in [#4065](https://github.com/wailsapp/wails/pull/4065) -- Add `PostShutdown` hook for running custom code after the shutdown process completes by [@fbbdev](https://github.com/fbbdev) in [#4066](https://github.com/wailsapp/wails/pull/4066) -- Add `FatalError` struct to support detection of fatal errors in custom error handlers by [@fbbdev](https://github.com/fbbdev) in [#4066](https://github.com/wailsapp/wails/pull/4066) -- Standardise and document service startup and shutdown order by [@fbbdev](https://github.com/fbbdev) in [#4066](https://github.com/wailsapp/wails/pull/4066) -- Add test harness for application startup/shutdown sequence and service startup/shutdown tests by [@fbbdev](https://github.com/fbbdev) in [#4066](https://github.com/wailsapp/wails/pull/4066) -- Add `RegisterService` method for registering services after the application has been created by [@fbbdev](https://github.com/fbbdev) in [#4066](https://github.com/wailsapp/wails/pull/4066) -- Add `MarshalError` field in application and service options for custom error handling in binding calls by [@fbbdev](https://github.com/fbbdev) in [#4066](https://github.com/wailsapp/wails/pull/4066) -- Add cancellable promise wrapper that propagates cancellation requests through promise chains by [@fbbdev](https://github.com/fbbdev) in [#4100](https://github.com/wailsapp/wails/pull/4100) -- Add the ability to tie binding call cancellation to an `AbortSignal` by [@fbbdev](https://github.com/fbbdev) in [#4100](https://github.com/wailsapp/wails/pull/4100) -- Support `data-wml-*` attributes for WML alongside the usual `wml-*` attributes by [@leaanthony](https://github.com/leaanthony) -- Add `Configure` method on all services for late configuration/dynamic reconfiguration by [@fbbdev](https://github.com/fbbdev) in [#4067](https://github.com/wailsapp/wails/pull/4067) -- `fileserver` service sends a 503 Service Unavailable response when unconfigured by [@fbbdev](https://github.com/fbbdev) in [#4067](https://github.com/wailsapp/wails/pull/4067) -- `kvstore` service provides an in-memory key-value store by default when unconfigured by [@fbbdev](https://github.com/fbbdev) in [#4067](https://github.com/wailsapp/wails/pull/4067) -- Add `Load` method on `kvstore` service to reload data from file after config changes by [@fbbdev](https://github.com/fbbdev) in [#4067](https://github.com/wailsapp/wails/pull/4067) -- Add `Clear` method on `kvstore` service to delete all keys by [@fbbdev](https://github.com/fbbdev) in [#4067](https://github.com/wailsapp/wails/pull/4067) -- Add type `Level` in `log` service to provide JS-side log-level constants by [@fbbdev](https://github.com/fbbdev) in [#4067](https://github.com/wailsapp/wails/pull/4067) -- Add `Log` method on `log` service to specify log-level dynamically by [@fbbdev](https://github.com/fbbdev) in [#4067](https://github.com/wailsapp/wails/pull/4067) -- `sqlite` service provides an in-memory DB by default when unconfigured by [@fbbdev](https://github.com/fbbdev) in [#4067](https://github.com/wailsapp/wails/pull/4067) -- Add method `Close` on `sqlite` service to close the DB manually by [@fbbdev](https://github.com/fbbdev) in [#4067](https://github.com/wailsapp/wails/pull/4067) -- Add cancellation support for query methods on `sqlite` service by [@fbbdev](https://github.com/fbbdev) in [#4067](https://github.com/wailsapp/wails/pull/4067) -- Add prepared statement support to `sqlite` service with JS bindings by [@fbbdev](https://github.com/fbbdev) in [#4067](https://github.com/wailsapp/wails/pull/4067) -- Gin support by [Lea Anthony](https://github.com/leaanthony) in [PR](https://github.com/wailsapp/wails/pull/3537) based on the original work of [@AnalogJ](https://github.com/AnalogJ) in this [PR](https://github.com/wailsapp/wails/pull/3537) -- Fix auto save and password auto save always enabled by [@oSethoum](https://github.com/osethoum) in [#4134](https://github.com/wailsapp/wails/pull/4134) -- Add `SetMenu()` on window to allow for setting a menu on a window by [@leaanthony](https://github.com/leaanthony) -- Add Notification support by [@popaprozac](https://github.com/popaprozac) in [#4098](https://github.com/wailsapp/wails/pull/4098) --  Add File Association support for mac by [@wimaha](https://github.com/wimaha) in [#4177](https://github.com/wailsapp/wails/pull/4177) -- Add `wails3 tool version` for semantic version bumping by [@leaanthony](https://github.com/leaanthony) -- Add badging support for macOS and Windows by [@popaprozac](https://github.com/popaprozac) in [#](https://github.com/wailsapp/wails/pull/4234) -- Add support for registered/strictly-typed events by [@fbbdev](https://github.com/fbbdev) and [@IanVS](https://github.com/IanVS) in [#4161](https://github.com/wailsapp/wails/pull/4161) -- Add the ability to register hooks for custom events by [@fbbdev](https://github.com/fbbdev) and [@IanVS](https://github.com/IanVS) in [#4161](https://github.com/wailsapp/wails/pull/4161) - -### Fixed - -- Fixed nil pointer dereference in processURLRequest for Mac by [@etesam913](https://github.com/etesam913) in [#4366](https://github.com/wailsapp/wails/pull/4366) -- Fixed a linux bug preventing filtered dialogs by [@bh90210](https://github.com/bh90210) in [#4287](https://github.com/wailsapp/wails/pull/4287) -- Fixed Windows+Linux Edit Menu issues by [@leaanthony](https://github.com/leaanthony) in [#3f78a3a](https://github.com/wailsapp/wails/commit/3f78a3a8ce7837e8b32242c8edbbed431c68c062) -- Updated the minimum system version in macOS .plist files from 10.13.0 to 10.15.0 by [@AkshayKalose](https://github.com/AkshayKalose) in [#3981](https://github.com/wailsapp/wails/pull/3981) -- Window ID skip issue by [@leaanthony](https://github.com/leaanthony) -- Fix nil menu issue when calling RegisterContextMenu by [@leaanthony](https://github.com/leaanthony) -- Fixed dependency cycles in binding generator output by [@fbbdev](https://github.com/fbbdev) in [#4001](https://github.com/wailsapp/wails/pull/4001) -- Fixed use-before-define errors in binding generator output by [@fbbdev](https://github.com/fbbdev) in [#4001](https://github.com/wailsapp/wails/pull/4001) -- Pass build flags to binding generator by [@fbbdev](https://github.com/fbbdev) in [#4023](https://github.com/wailsapp/wails/pull/4023) -- Change paths in windows Taskfile to forward slashes to ensure it works on non-Windows platforms by [@leaanthony](https://github.com/leaanthony) -- Mac + Mac JS events now fixed by [@leaanthony](https://github.com/leaanthony) -- Fixed event deadlock for macOS by [@leaanthony](https://github.com/leaanthony) -- Fixed a `Parameter incorrect` error in Window initialisation on Windows when HTML provided but no JS by [@leaanthony](https://github.com/leaanthony) -- Fixed size of response prefix used for content type sniffing in asset server by [@fbbdev](https://github.com/fbbdev) in [#4049](https://github.com/wailsapp/wails/pull/4049) -- Fixed handling of non-404 responses on root index path in asset server by [@fbbdev](https://github.com/fbbdev) in [#4049](https://github.com/wailsapp/wails/pull/4049) -- Fixed undefined behaviour in binding generator when testing properties of generic types by [@fbbdev](https://github.com/fbbdev) in [#4045](https://github.com/wailsapp/wails/pull/4045) -- Fixed binding generator output for models when underlying type has not the same properties as named wrapper by [@fbbdev](https://github.com/fbbdev) in [#4045](https://github.com/wailsapp/wails/pull/4045) -- Fixed binding generator output for map key types and preprocessing by [@fbbdev](https://github.com/fbbdev) in [#4045](https://github.com/wailsapp/wails/pull/4045) -- Fixed binding generator output for structs that implement marshaler interfaces by [@fbbdev](https://github.com/fbbdev) in [#4045](https://github.com/wailsapp/wails/pull/4045) -- Fixed detection of type cycles involving generic types in binding generator by [@fbbdev](https://github.com/fbbdev) in [#4045](https://github.com/wailsapp/wails/pull/4045) -- Fixed invalid references to unexported models in binding generator output by [@fbbdev](https://github.com/fbbdev) in [#4045](https://github.com/wailsapp/wails/pull/4045) -- Moved injected code to the end of service files by [@fbbdev](https://github.com/fbbdev) in [#4045](https://github.com/wailsapp/wails/pull/4045) -- Fixed handling of errors from file close operations in binding generator by [@fbbdev](https://github.com/fbbdev) in [#4045](https://github.com/wailsapp/wails/pull/4045) -- Suppressed warnings for services that define lifecycle or http methods but no other bound methods by [@fbbdev](https://github.com/fbbdev) in [#4045](https://github.com/wailsapp/wails/pull/4045) -- Fixed non-React templates failing to display Hello World footer when using light system colour scheme by [@marcus-crane](https://github.com/marcus-crane) in [#4056](https://github.com/wailsapp/wails/pull/4056) -- Fixed hidden menu items on macOS by [@leaanthony](https://github.com/leaanthony) -- Fixed handling and formatting of errors in message processors by [@fbbdev](https://github.com/fbbdev) in [#4066](https://github.com/wailsapp/wails/pull/4066) --  Fixed skipped service shutdown when quitting application by [@fbbdev](https://github.com/fbbdev) in [#4066](https://github.com/wailsapp/wails/pull/4066) --  Ensure menu updates occur on the main thread by [@leaanthony](https://github.com/leaanthony) -- The dragging and resizing mechanism is now more robust and matches expected platform behaviour more closely by [@fbbdev](https://github.com/fbbdev) in [#4100](https://github.com/wailsapp/wails/pull/4100) -- Fixed [#4097](https://github.com/wailsapp/wails/issues/4097) Webpack/angular discards runtime init code by [@fbbdev](https://github.com/fbbdev) in [#4100](https://github.com/wailsapp/wails/pull/4100) -- Fixed initially-hidden menu items by [@IanVS](https://github.com/IanVS) in [#4116](https://github.com/wailsapp/wails/pull/4116) -- Fixed assetFileServer not serving `.html` files when non-extension request when `[request]` doesn't exist but `[request].html` does -- Fixed icon generation paths by [@robin-samuel](https://github.com/robin-samuel) in [#4125](https://github.com/wailsapp/wails/pull/4125) -- Fixed `fullscreen`, `unfullscreen`, `unminimise` and `unmaximise` events not being emitted by [@oSethoum](https://github.com/osethoum) in [#4130](https://github.com/wailsapp/wails/pull/4130) -- Fixed NSIS Error because of incorrect prefix on default version in config by [@robin-samuel](https://github.com/robin-samuel) in [#4126](https://github.com/wailsapp/wails/pull/4126) -- Fixed Dialogs runtime function returning escaped paths on Windows by [TheGB0077](https://github.com/TheGB0077) in [#4188](https://github.com/wailsapp/wails/pull/4188) -- Fixed Webview2 detection path in HKCU by [@leaanthony](https://github.com/leaanthony). -- Fixed input issue with macOS by [@leaanthony](https://github.com/leaanthony). -- Fixed Windows icon generation task file name by [@yulesxoxo](https://github.com/yulesxoxo) in [#4219](https://github.com/wailsapp/wails/pull/4219). -- Fixed transparency issue for frameless windows by [@leaanthony](https://github.com/leaanthony) based on work by @kron. -- Fixed focus calls when window is disabled or minimised by [@leaanthony](https://github.com/leaanthony) based on work by @kron. -- Fixed system trays not showing after taskbar restarts by [@leaanthony](https://github.com/leaanthony) based on work by @kron. -- Fixed fallbackResponseWriter not implementing Flush() in [#4245](https://github.com/wailsapp/wails/pull/4245) -- Fixed fallbackResponseWriter not implementing Flush() by [@superDingda] in [#4236](https://github.com/wailsapp/wails/issues/4236) -- Fixed macOS window close with pending async Go-bound function call crashes by [@joshhardy](https://github.com/joshhardy) in [#4354](https://github.com/wailsapp/wails/pull/4354) -- Fixed Windows Efficiency mode startup race condition by [@leaanthony](https://github.com/leaanthony) -- Fixed Windows icon handle cleanup by [@leaanthony](https://github.com/leaanthony). -- Fixed `OpenFileManager` on Windows by [@PPTGamer](https://github.com/PPTGamer) in [#4375](https://github.com/wailsapp/wails/pull/4375). - -### Changed - -- Removed `application.WindowIDKey` and `application.WindowNameKey` (replaced by `application.WindowKey`) by [@leaanthony](https://github.com/leaanthony) -- ContextMenuData now returns a string instead of any by [@leaanthony](https://github.com/leaanthony) -- In JS/TS bindings, class fields of fixed-length array types are now initialized with their expected length instead of being empty by [@fbbdev](https://github.com/fbbdev) in [#4001](https://github.com/wailsapp/wails/pull/4001) -- ContextMenuData now returns a string instead of any by [@leaanthony](https://github.com/leaanthony) -- `application.NewService` does not accept options as an optional parameter anymore (use `application.NewServiceWithOptions` instead) by [@leaanthony](https://github.com/leaanthony) in [#4024](https://github.com/wailsapp/wails/pull/4024) -- Removed `nanoid` dependency by [@leaanthony](https://github.com/leaanthony) -- Updated Window example for mica/acrylic/tabbed window styles by [@leaanthony](https://github.com/leaanthony) -- In JS/TS bindings, `internal.js/ts` model files have been removed; all models can now be found in `models.js/ts` by [@fbbdev](https://github.com/fbbdev) in [#4045](https://github.com/wailsapp/wails/pull/4045) -- In JS/TS bindings, named types are never rendered as aliases for other named types; the old behaviour is now restricted to aliases by [@fbbdev](https://github.com/fbbdev) in [#4045](https://github.com/wailsapp/wails/pull/4045) -- In JS/TS bindings, in class mode, struct fields whose type is a type parameter are marked optional and never initialised automatically by [@fbbdev](https://github.com/fbbdev) in [#4045](https://github.com/wailsapp/wails/pull/4045) -- Remove ESLint from templates by by [@IanVS](https://github.com/IanVS) in [#4059](https://github.com/wailsapp/wails/pull/4059) -- Update copyright date to 2025 by [@IanVS](https://github.com/IanVS) in [#4037](https://github.com/wailsapp/wails/pull/4037) -- Add docs for event.Sender by [@IanVS](https://github.com/IanVS) in [#4075](https://github.com/wailsapp/wails/pull/4075) -- Go 1.24 support by [@leaanthony](https://github.com/leaanthony) -- `ServiceStartup` hooks are now invoked when `App.Run` is called, not in `application.New` by [@fbbdev](https://github.com/fbbdev) in [#4066](https://github.com/wailsapp/wails/pull/4066) -- `ServiceStartup` errors are now returned from `App.Run` instead of terminating the process by [@fbbdev](https://github.com/fbbdev) in [#4066](https://github.com/wailsapp/wails/pull/4066) -- Binding and dialog calls from JS now reject with error objects instead of strings by [@fbbdev](https://github.com/fbbdev) in [#4066](https://github.com/wailsapp/wails/pull/4066) -- Improved systray menu positioning on Windows by [@leaanthony](https://github.com/leaanthony) -- The JS runtime has been ported to TypeScript by [@fbbdev](https://github.com/fbbdev) in [#4100](https://github.com/wailsapp/wails/pull/4100) -- The runtime initialises as soon as it is imported, no need to wait for the window to load by [@fbbdev](https://github.com/fbbdev) in [#4100](https://github.com/wailsapp/wails/pull/4100) -- The runtime does not export an init method anymore. A side effects import can be used to initialise it by [@fbbdev](https://github.com/fbbdev) in [#4100](https://github.com/wailsapp/wails/pull/4100) -- Bound methods now return a `CancellablePromise` that rejects with a `CancelError` if cancelled. The actual result of the call is discarded by [@fbbdev](https://github.com/fbbdev) in [#4100](https://github.com/wailsapp/wails/pull/4100) -- Built-in service types are now consistently called `Service` by [@fbbdev](https://github.com/fbbdev) in [#4067](https://github.com/wailsapp/wails/pull/4067) -- Built-in service creation functions with options are now consistently called `NewWithConfig` by [@fbbdev](https://github.com/fbbdev) in [#4067](https://github.com/wailsapp/wails/pull/4067) -- `Select` method on `sqlite` service is now named `Query` for consistency with Go APIs by [@fbbdev](https://github.com/fbbdev) in [#4067](https://github.com/wailsapp/wails/pull/4067) -- Templates: moved runtime to "dependencies", organized package.json files by [@IanVS](https://github.com/IanVS) in [#4133](https://github.com/wailsapp/wails/pull/4133) -- Creates and ad-hoc signs app bundles in dev to enable certain macOS APIs by [@popaprozac](https://github.com/popaprozac) in [#4171](https://github.com/wailsapp/wails/pull/4171) - -## v3.0.0-alpha.9 - 2025-01-13 - -### Added - -- `app.OpenFileManager(path string, selectFile bool)` to open the system file manager to the path `path` with optional highlighting via `selectFile` by [@Krzysztofz01](https://github.com/Krzysztofz01) [@rcalixte](https://github.com/rcalixte) -- New `-git` flag for `wails3 init` command by [@leaanthony](https://github.com/leaanthony) -- New `wails3 generate webview2bootstrapper` command by [@leaanthony](https://github.com/leaanthony) -- Added `init()` method in runtime to allow manual initialisation of the runtime by [@leaanthony](https://github.com/leaanthony) -- Added `WindowDidMoveDebounceMS` option to Window's WindowOptions by [@leaanthony](https://github.com/leaanthony) -- Added Single Instance feature by [@leaanthony](https://github.com/leaanthony). Based on the [v2 PR](https://github.com/wailsapp/wails/pull/2951) by @APshenkin. -- `wails3 generate template` command by [@leaanthony](https://github.com/leaanthony) -- `wails3 releasenotes` command by [@leaanthony](https://github.com/leaanthony) -- `wails3 update cli` command by [@leaanthony](https://github.com/leaanthony) -- `-clean` option for `wails3 generate bindings` command by [@leaanthony](https://github.com/leaanthony) -- Allow for aarch64 (arm64) AppImage Linux builds by [@AkshayKalose](https://github.com/AkshayKalose) in [#3981](https://github.com/wailsapp/wails/pull/3981) - -### Fixed - -- Fixed min/max width options for linux by @atterpac in [#3979](https://github.com/wailsapp/wails/pull/3979) -- Typescript templates types definitions via npm version bump by @atterpac in [#3966](https://github.com/wailsapp/wails/pull/3966) -- Fix Sveltekit template CSS referance by @atterpac in [#3945](https://github.com/wailsapp/wails/pull/3945) -- Ensure key callbacks in window run() are called on the main thread by [@leaanthony](https://github.com/leaanthony) -- Fix dialog directory chooser examples by [@leaanthony](https://github.com/leaanthony) -- Created new Chinese error page when index.html is missing by [@leaanthony](https://github.com/leaanthony) --  Ensure `windowDidBecomeKey` callback is running on main thread by [@leaanthony](https://github.com/leaanthony) --  Support fullscreen for frameless windows by [@leaanthony](https://github.com/leaanthony) --  Improved window destroying logic by [@leaanthony](https://github.com/leaanthony) --  Fix window position logic when attached to system trays by [@leaanthony](https://github.com/leaanthony) --  Support fullscreen for frameless windows by [@leaanthony](https://github.com/leaanthony) -- Fix event handling by [@leaanthony](https://github.com/leaanthony) -- Fixed window shutdown logic by [@leaanthony](https://github.com/leaanthony) -- Common taskfile now defaults to generating Typescript bindings for Typescript templates by [@leaanthony](https://github.com/leaanthony) -- Fix Close application on WM_CLOSE message when no windows are open/systray only by [@mmalcek](https://github.com/mmalcek) in [#3990](https://github.com/wailsapp/wails/pull/3990) -- Fixed garble build by @5aaee9 in [#3192](https://github.com/wailsapp/wails/pull/3192) -- Fixed windows nsis builds by [@leaanthony](https://github.com/leaanthony) - -### Changed - -- Moved build assets to platform specific directories by [@leaanthony](https://github.com/leaanthony) -- Moved and renamed Taskfiles to platform specific directories by [@leaanthony](https://github.com/leaanthony) -- Created a much better experience when `index.html` is missing by [@leaanthony](https://github.com/leaanthony) -- [Windows] Improved performance of minimise and restore by [@leaanthony](https://github.com/leaanthony). Based on original [PR](https://github.com/wailsapp/wails/pull/3955) by [562589540](https://github.com/562589540) -- Removed `ShouldClose` option (Register a hook for events.Common.WindowClosing instead) by [@leaanthony](https://github.com/leaanthony) -- [Windows] Reduced flicker when opening a window by [@leaanthony](https://github.com/leaanthony) -- Removed `Window.Destroy` as this was intended to be an internal function by [@leaanthony](https://github.com/leaanthony) -- Renamed `WindowClose` events to `WindowClosing` by [@leaanthony](https://github.com/leaanthony) -- Frontend builds now use vite environment "development" or "production" depending on build type by [@leaanthony](https://github.com/leaanthony) -- Update to go-webview2 v1.19 by [@leaanthony](https://github.com/leaanthony) - -## v3.0.0-alpha.8.3 - 2024-12-07 - -### Changed - -- Ensure fork of taskfile is used by @leaanthony - -## v3.0.0-alpha.8.2 - 2024-12-07 - -### Changed - -- Update fork of Taskfile to fix version issues when installing using - `go install` by @leaanthony - -## v3.0.0-alpha.8.1 - 2024-12-07 - -### Changed - -- Using fork of Taskfile to fix version issues when installing using - `go install` by @leaanthony - -## v3.0.0-alpha.8 - 2024-12-06 - -### Added - -- Added hyperlink for sponsor by @ansxuman in [#3958](https://github.com/wailsapp/wails/pull/3958) -- Support of linux packaging of deb,rpm, and arch linux packager builds by - @atterpac in [#3909](https://github.com/wailsapp/wails/3909) -- Added Support for darwin universal builds and packages by - [ansxuman](https://github.com/ansxuman) in - [#3902](https://github.com/wailsapp/wails/pull/3902) -- Events documentation to the website by - [atterpac](https://github.com/atterpac) in - [#3867](https://github.com/wailsapp/wails/pull/3867) -- Templates for sveltekit and sveltekit-ts that are set for non-SSR development - by [atterpac](https://github.com/atterpac) in - [#3829](https://github.com/wailsapp/wails/pull/3829) -- Update build assets using new `wails3 update build-assets` command by - [leaanthony](https://github.com/leaanthony) -- Example to test the HTML Drag and Drop API by - [FerroO2000](https://github.com/FerroO2000) in - [#3856](https://github.com/wailsapp/wails/pull/3856) -- File Association support by [leaanthony](https://github.com/leaanthony) in - [#3873](https://github.com/wailsapp/wails/pull/3873) -- New `wails3 generate runtime` command by - [leaanthony](https://github.com/leaanthony) -- New `InitialPosition` option to specify if the window should be centered or - positioned at the given X/Y location by - [leaanthony](https://github.com/leaanthony) in - [#3885](https://github.com/wailsapp/wails/pull/3885) -- Add `Path` & `Paths` methods to `application` package by - [ansxuman](https://github.com/ansxuman) and - [leaanthony](https://github.com/leaanthony) in - [#3823](https://github.com/wailsapp/wails/pull/3823) -- Added `GeneralAutofillEnabled` and `PasswordAutosaveEnabled` Windows options - by [leaanthony](https://github.com/leaanthony) in - [#3766](https://github.com/wailsapp/wails/pull/3766) -- Added the ability to retrieve the window calling a service method by - [leaanthony](https://github.com/leaanthony) in - [#3888](https://github.com/wailsapp/wails/pull/3888) -- Added `EnabledFeatures` and `DisabledFeatures` options for Webview2 by - [leaanthony](https://github.com/leaanthony). -- - -### Changed - -- `service.OnStartup` now shutdowns the application on error and runs - `service.OnShutdown`for any prior services that started by @atterpac in - [#3920](https://github.com/wailsapp/wails/pull/3920) -- Refactored systray click messaging to better align with user interactions by - @atterpac in [#3907](https://github.com/wailsapp/wails/pull/3907) -- Asset embed to include `all:frontend/dist` to support frameworks that generate - subfolders by @atterpac in - [#3887](https://github.com/wailsapp/wails/pull/3887) -- Taskfile refactor by [leaanthony](https://github.com/leaanthony) in - [#3748](https://github.com/wailsapp/wails/pull/3748) -- Upgrade to `go-webview2` v1.0.16 by - [leaanthony](https://github.com/leaanthony) -- Fixed `Screen` type to include `ID` not `Id` by - [etesam913](https://github.com/etesam913) in - [#3778](https://github.com/wailsapp/wails/pull/3778) -- Update `go.mod.tmpl` wails version to support `application.ServiceOptions` by - [northes](https://github.com/northes) in - [#3836](https://github.com/wailsapp/wails/pull/3836) -- Fixed service name determination by [windom](https://github.com/windom/) in - [#3827](https://github.com/wailsapp/wails/pull/3827) -- mkdocs serve now uses docker by [leaanthony](https://github.com/leaanthony) -- Consolidated dev config into `config.yml` by - [leaanthony](https://github.com/leaanthony) -- Systray dialog now defaults to the application icon if available (Windows) by - [@leaanthony](https://github.com/leaanthony) -- Better reporting of GPU + Memory for macOS by - [@leaanthony](https://github.com/leaanthony) -- Removed `WebviewGpuIsDisabled` and `EnableFraudulentWebsiteWarnings` - (superseded by `EnabledFeatures` and `DisabledFeatures` options) by - [leaanthony](https://github.com/leaanthony) - -### Fixed - -- Fixed deadlock in Linux dialog for multiple selections caused by unclosed - channel variable by @michael-freling in - [#3925](https://github.com/wailsapp/wails/pull/3925) -- Fixed cross-platform cleanup for .syso files during Windows build by - [ansxuman](https://github.com/ansxuman) in - [#3924](https://github.com/wailsapp/wails/pull/3924) -- Fixed amd64 appimage compile by @atterpac in - [#3898](https://github.com/wailsapp/wails/pull/3898) -- Fixed build assets update by @ansxuman in - [#3901](https://github.com/wailsapp/wails/pull/3901) -- Fixed Linux systray `OnClick` and `OnRightClick` implementation by @atterpac - in [#3886](https://github.com/wailsapp/wails/pull/3886) -- Fixed `AlwaysOnTop` not working on Mac by - [leaanthony](https://github.com/leaanthony) in - [#3841](https://github.com/wailsapp/wails/pull/3841) --  Fixed `application.NewEditMenu` including a duplicate - `PasteAndMatchStyle` role in the edit menu on Darwin by - [johnmccabe](https://github.com/johnmccabe) in - [#3839](https://github.com/wailsapp/wails/pull/3839) -- 🐧 Fixed aarch64 compilation - [#3840](https://github.com/wailsapp/wails/issues/3840) in - [#3854](https://github.com/wailsapp/wails/pull/3854) by - [kodflow](https://github.com/kodflow) -- ⊞ Fixed radio group menu items by - [@leaanthony](https://github.com/leaanthony) -- Fix error on building runnable .app on MacOS when 'name' and 'outputfilename' - are different. by @nickisworking in - [#3789](https://github.com/wailsapp/wails/pull/3789) - -## v3.0.0-alpha.7 - 2024-09-18 - -### Added - -- ⊞ New DIP system for Enhanced High DPI Monitor Support by - [mmghv](https://github.com/mmghv) in - [#3665](https://github.com/wailsapp/wails/pull/3665) -- ⊞ Window class name option by [windom](https://github.com/windom/) in - [#3682](https://github.com/wailsapp/wails/pull/3682) -- Services have been expanded to provide plugin functionality. By - [atterpac](https://github.com/atterpac) and - [leaanthony](https://github.com/leaanthony) in - [#3570](https://github.com/wailsapp/wails/pull/3570) - -### Changed - -- Events API change: `On`/`Emit` -> user events, `OnApplicationEvent` -> - Application Events `OnWindowEvent` -> Window Events, by - [leaanthony](https://github.com/leaanthony) -- Fix for Events API on Linux by [TheGB0077](https://github.com/TheGB0077) in - [#3734](https://github.com/wailsapp/wails/pull/3734) -- [CI] improvements to actions & enable to run actions also in forks and - branches prefixed with `v3/` or `v3-` by - [stendler](https://github.com/stendler) in - [#3747](https://github.com/wailsapp/wails/pull/3747) - -### Fixed - -- Fixed bug with usage of customEventProcessor in drag-n-drop example by - [etesam913](https://github.com/etesam913) in - [#3742](https://github.com/wailsapp/wails/pull/3742) -- 🐧 Fixed linux compile error introduced by IgnoreMouseEvents addition by - [atterpac](https://github.com/atterpac) in - [#3721](https://github.com/wailsapp/wails/pull/3721) -- ⊞ Fixed syso icon file generation bug by - [atterpac](https://github.com/atterpac) in - [#3675](https://github.com/wailsapp/wails/pull/3675) -- 🐧 Fix to run natively in wayland incorporated from - [#1811](https://github.com/wailsapp/wails/pull/1811) in - [#3614](https://github.com/wailsapp/wails/pull/3614) by - [@stendler](https://github.com/stendler) -- Do not bind internal service methods in - [#3720](https://github.com/wailsapp/wails/pull/3720) by - [leaanthony](https://github.com/leaanthony) -- ⊞ Fixed system tray startup panic in - [#3693](https://github.com/wailsapp/wails/issues/3693) by - [@DeltaLaboratory](https://github.com/DeltaLaboratory) -- Do not bind internal service methods in - [#3720](https://github.com/wailsapp/wails/pull/3720) by - [leaanthony](https://github.com/leaanthony) -- ⊞ Fixed system tray startup panic in - [#3693](https://github.com/wailsapp/wails/issues/3693) by - [@DeltaLaboratory](https://github.com/DeltaLaboratory) -- Major menu item refactor and event handling. Mainly improves macOS for now. By - [leaanthony](https://github.com/leaanthony) -- Fix tests after plugins and event refactor in - [#3746](https://github.com/wailsapp/wails/pull/3746) by - [@stendler](https://github.com/stendler) -- ⊞ Fixed `Failed to unregister class Chrome_WidgetWin_0` warning. By - [leaanthony](https://github.com/leaanthony) - -## v3.0.0-alpha.6 - 2024-07-30 - -### Fixed - -- Module issues - -## v3.0.0-alpha.5 - 2024-07-30 - -### Added - -- 🐧 WindowDidMove / WindowDidResize events in - [#3580](https://github.com/wailsapp/wails/pull/3580) -- ⊞ WindowDidResize event in - [#3580](https://github.com/wailsapp/wails/pull/3580) --  add Event ApplicationShouldHandleReopen to be able to handle dock - icon click by @5aaee9 in [#2991](https://github.com/wailsapp/wails/pull/2991) --  add getPrimaryScreen/getScreens to impl by @tmclane in - [#2618](https://github.com/wailsapp/wails/pull/2618) --  add option for showing the toolbar in fullscreen mode on macOS by - [@fbbdev](https://github.com/fbbdev) in - [#3282](https://github.com/wailsapp/wails/pull/3282) -- 🐧 add onKeyPress logic to convert linux keypress into an accelerator - @[Atterpac](https://github.com/Atterpac) - in[#3022](https://github.com/wailsapp/wails/pull/3022]) -- 🐧 add task `run:linux` by - [@marcus-crane](https://github.com/marcus-crane) in - [#3146](https://github.com/wailsapp/wails/pull/3146) -- Export `SetIcon` method by [@almas-x](https://github.com/almas-x) in - [PR](https://github.com/wailsapp/wails/pull/3147) -- Improve `OnShutdown` by [@almas-x](https://github.com/almas-x) in - [PR](https://github.com/wailsapp/wails/pull/3189) -- Restore `ToggleMaximise` method in `Window` interface by - [@fbbdev](https://github.com/fbbdev) in - [#3281](https://github.com/wailsapp/wails/pull/3281) -- Added more information to `Environment()`. By @leaanthony in - [aba82cc](https://github.com/wailsapp/wails/commit/aba82cc52787c97fb99afa58b8b63a0004b7ff6c) - based on [PR](https://github.com/wailsapp/wails/pull/2044) by @Mai-Lapyst -- Expose the `WebviewWindow.IsFocused` method on the `Window` interface by - [@fbbdev](https://github.com/fbbdev) in - [#3295](https://github.com/wailsapp/wails/pull/3295) -- Support multiple space-separated trigger events in the WML system by - [@fbbdev](https://github.com/fbbdev) in - [#3295](https://github.com/wailsapp/wails/pull/3295) -- Add ESM exports from the bundled JS runtime script by - [@fbbdev](https://github.com/fbbdev) in - [#3295](https://github.com/wailsapp/wails/pull/3295) -- Add binding generator flag for using the bundled JS runtime script instead of - the npm package by [@fbbdev](https://github.com/fbbdev) in - [#3334](https://github.com/wailsapp/wails/pull/3334) -- Implement `setIcon` on linux by [@abichinger](https://github.com/abichinger) - in [#3354](https://github.com/wailsapp/wails/pull/3354) -- Add flag `-port` to dev command and support environment variable - `WAILS_VITE_PORT` by [@abichinger](https://github.com/abichinger) in - [#3429](https://github.com/wailsapp/wails/pull/3429) -- Add tests for bound method calls by - [@abichinger](https://github.com/abichinger) in - [#3431](https://github.com/wailsapp/wails/pull/3431) -- ⊞ add `SetIgnoreMouseEvents` for already created window by - [@bruxaodev](https://github.com/bruxaodev) in - [#3667](https://github.com/wailsapp/wails/pull/3667) --  Add ability to set a window's stacking level (order) by - [@OlegGulevskyy](https://github.com/OlegGulevskyy) in - [#3674](https://github.com/wailsapp/wails/pull/3674) - -### Fixed - -- Fixed resize event messaging by [atterpac](https://github.com/atterpac) in - [#3606](https://github.com/wailsapp/wails/pull/3606) -- 🐧Fixed theme handling error on NixOS by - [tmclane](https://github.com/tmclane) in - [#3515](https://github.com/wailsapp/wails/pull/3515) -- Fixed cross volume project install for windows by - [atterpac](https://github.com/atterac) in - [#3512](https://github.com/wailsapp/wails/pull/3512) -- Fixed react template css to show footer by - [atterpac](https://github.com/atterpac) in - [#3477](https://github.com/wailsapp/wails/pull/3477) -- Fixed zombie processes when working in devmode by updating to latest refresh - by [Atterpac](https://github.com/atterpac) in - [#3320](https://github.com/wailsapp/wails/pull/3320). -- Fixed appimage webkit file sourcing by [Atterpac](https://github.com/atterpac) - in [#3306](https://github.com/wailsapp/wails/pull/3306). -- Fixed Doctor apt package verify by [Atterpac](https://github.com/Atterpac) in - [#2972](https://github.com/wailsapp/wails/pull/2972). -- Fixed application frozen when quit (Darwin) by @5aaee9 in - [#2982](https://github.com/wailsapp/wails/pull/2982) -- Fixed background colours of examples on Windows by - [mmghv](https://github.com/mmghv) in - [#2750](https://github.com/wailsapp/wails/pull/2750). -- Fixed default context menus by [mmghv](https://github.com/mmghv) in - [#2753](https://github.com/wailsapp/wails/pull/2753). -- Fixed hex values for arrow keys on Darwin by - [jaybeecave](https://github.com/jaybeecave) in - [#3052](https://github.com/wailsapp/wails/pull/3052). -- Set drag-n-drop for windows to working. Added by - [@pylotlight](https://github.com/pylotlight) in - [PR](https://github.com/wailsapp/wails/pull/3039) -- Fixed bug for linux in doctor in the event user doesn't have proper drivers - installed. Added by [@pylotlight](https://github.com/pylotlight) in - [PR](https://github.com/wailsapp/wails/pull/3032) -- Fix dpi scaling on start up (windows). Changed by [@almas-x](https://github.com/almas-x) in - [PR](https://github.com/wailsapp/wails/pull/3145) -- Fix replace line in `go.mod` to use relative paths. Fixes Windows paths with - spaces - @leaanthony. -- Fix MacOS systray click handling when no attached window by - [thomas-senechal](https://github.com/thomas-senechal) in PR - [#3207](https://github.com/wailsapp/wails/pull/3207) -- Fix failing Windows build due to unknown option by - [thomas-senechal](https://github.com/thomas-senechal) in PR - [#3208](https://github.com/wailsapp/wails/pull/3208) -- Fix crash on windows left clicking the systray icon when not having an - attached window [tw1nk](https://github.com/tw1nk) in PR - [#3271](https://github.com/wailsapp/wails/pull/3271) -- Fix wrong baseURL when open window twice by @5aaee9 in PR - [#3273](https://github.com/wailsapp/wails/pull/3273) -- Fix ordering of if branches in `WebviewWindow.Restore` method by - [@fbbdev](https://github.com/fbbdev) in - [#3279](https://github.com/wailsapp/wails/pull/3279) -- Correctly compute `startURL` across multiple `GetStartURL` invocations when - `FRONTEND_DEVSERVER_URL` is present. - [#3299](https://github.com/wailsapp/wails/pull/3299) -- Fix the JS type of the `Screen` struct to match its Go counterpart by - [@fbbdev](https://github.com/fbbdev) in - [#3295](https://github.com/wailsapp/wails/pull/3295) -- Fix the `WML.Reload` method to ensure proper cleanup of registered event - listeners by [@fbbdev](https://github.com/fbbdev) in - [#3295](https://github.com/wailsapp/wails/pull/3295) -- Fix custom context menu closing immediately on linux by - [@abichinger](https://github.com/abichinger) in - [#3330](https://github.com/wailsapp/wails/pull/3330) -- Fix the output path and extension of model files produced by the binding - generator by [@fbbdev](https://github.com/fbbdev) in - [#3334](https://github.com/wailsapp/wails/pull/3334) -- Fix the import paths of model files in JS code produced by the binding - generator by [@fbbdev](https://github.com/fbbdev) in - [#3334](https://github.com/wailsapp/wails/pull/3334) -- Fix drag-n-drop on some linux distros by - [@abichinger](https://github.com/abichinger) in - [#3346](https://github.com/wailsapp/wails/pull/3346) -- Fix missing task for macOS when using `wails3 task dev` by - [@hfoxy](https://github.com/hfoxy) in - [#3417](https://github.com/wailsapp/wails/pull/3417) -- Fix registering events causing a nil map assignment by - [@hfoxy](https://github.com/hfoxy) in - [#3426](https://github.com/wailsapp/wails/pull/3426) -- Fix unmarshaling of bound method parameters by - [@fbbdev](https://github.com/fbbdev) in - [#3431](https://github.com/wailsapp/wails/pull/3431) -- Fix handling of multiple return values from bound methods by - [@fbbdev](https://github.com/fbbdev) in - [#3431](https://github.com/wailsapp/wails/pull/3431) -- Fix doctor detection of npm that is not installed with system package manager - by [@pekim](https://github.com/pekim) in - [#3458](https://github.com/wailsapp/wails/pull/3458) -- Fix missing MicrosoftEdgeWebview2Setup.exe. Thanks to - [@robin-samuel](https://github.com/robin-samuel). -- Fix random crash on linux due to window ID handling by @leaanthony. Based on - PR [#3466](https://github.com/wailsapp/wails/pull/3622) by - [@5aaee9](https://github.com/5aaee9). -- Fix systemTray.setIcon crashing on Linux by - [@windom](https://github.com/windom/) in - [#3636](https://github.com/wailsapp/wails/pull/3636). -- Fix Ensure Window Frame is Applied on First Call in `setFrameless` Function on - Windows by [@bruxaodev](https://github.com/bruxaodev/) in - [#3691](https://github.com/wailsapp/wails/pull/3691). - -### Changed - -- Renamed `AbsolutePosition()` to `Position()` by - [mmghv](https://github.com/mmghv) in - [#3611](https://github.com/wailsapp/wails/pull/3611) -- Update linux webkit dependency to webkit2gtk-4.1 over webkitgtk2-4.0 to - support Ubuntu 24.04 LTS by [atterpac](https://github.com/atterpac) in - [#3461](https://github.com/wailsapp/wails/pull/3461) -- The bundled JS runtime script is now an ESM module: script tags importing it - must have the `type="module"` attribute. By - [@fbbdev](https://github.com/fbbdev) in - [#3295](https://github.com/wailsapp/wails/pull/3295) -- The `@wailsio/runtime` package does not publish its API on the `window.wails` - object, and does not start the WML system. This has been done to improve - encapsulation. The WML system can be started manually if desired by calling - the new `WML.Enable` method. The bundled JS runtime script still performs both - operations automatically. By [@fbbdev](https://github.com/fbbdev) in - [#3295](https://github.com/wailsapp/wails/pull/3295) -- The Window API module `@wailsio/runtime/src/window` now exposes the containing - window object as a default export. It is not possible anymore to import - individual methods through ESM named or namespace import syntax. -- The JS window API has been updated to match the current Go `WebviewWindow` - API. Some methods have changed name or prototype, specifically: `Screen` - becomes `GetScreen`; `GetZoomLevel`/`SetZoomLevel` become `GetZoom`/`SetZoom`; - `GetZoom`, `Width` and `Height` now return values directly instead of wrapping - them within objects. By [@fbbdev](https://github.com/fbbdev) in - [#3295](https://github.com/wailsapp/wails/pull/3295) -- The binding generator now uses calls by ID by default. The `-id` CLI option - has been removed. Use the `-names` CLI option to switch back to calls by name. - By [@fbbdev](https://github.com/fbbdev) in - [#3468](https://github.com/wailsapp/wails/pull/3468) -- New binding code layout: output files were previously organised in folders - named after their containing package; now full Go import paths are used, - including the module path. By [@fbbdev](https://github.com/fbbdev) in - [#3468](https://github.com/wailsapp/wails/pull/3468) -- The struct field `application.Options.Bind` has been renamed to - `application.Options.Services`. By [@fbbdev](https://github.com/fbbdev) in - [#3468](https://github.com/wailsapp/wails/pull/3468) -- New syntax for binding services: service instances must now be wrapped in a - call to `application.NewService`. By [@fbbdev](https://github.com/fbbdev) in - [#3468](https://github.com/wailsapp/wails/pull/3468) -- Disable spinner on Non-Terminal or CI Environment by - [@DeltaLaboratory](https://github.com/DeltaLaboratory) in - [#3574](https://github.com/wailsapp/wails/pull/3574) diff --git a/docs/src/content/docs/community/links.md b/docs/src/content/docs/community/links.md deleted file mode 100644 index 9507991dd..000000000 --- a/docs/src/content/docs/community/links.md +++ /dev/null @@ -1,27 +0,0 @@ ---- -title: Links ---- - -This page serves as a list for community related links. - -:::tip[How to Submit a Link] - -You can click the `Edit page` at the bottom of this page to submit a PR. - -::: - -## Awesome Wails - -The [definitive list](https://github.com/wailsapp/awesome-wails) of links -related to Wails. - -## Support Channels - -- [Wails Discord Server](https://discord.gg/bdj28QNHmT) -- [Github Issues](https://github.com/wailsapp/wails/issues) - -## Social Media - -- [Twitter](https://x.com/wailsapp) -- [Wails Chinese Community QQ Group](https://qm.qq.com/cgi-bin/qm/qr?k=PmIURne5hFGNd7QWzW5qd6FV-INEjNJv&jump_from=webapi) - - Group number: 1067173054 diff --git a/docs/src/content/docs/community/showcase/_template.md b/docs/src/content/docs/community/showcase/_template.md deleted file mode 100644 index f98a2ef06..000000000 --- a/docs/src/content/docs/community/showcase/_template.md +++ /dev/null @@ -1,25 +0,0 @@ ---- -title: My Project -draft: true ---- - - - -![My Project Screenshot](../../../../assets/showcase-images/your-project.webp) - - - -Your project description goes here. Explain what it does, what makes it special, and why you built it with Wails. - - - -[Visit Project Website](https://your-project.com) | [View on GitHub](https://github.com/yourusername/your-project) diff --git a/docs/src/content/docs/community/showcase/bulletinboard.md b/docs/src/content/docs/community/showcase/bulletinboard.md deleted file mode 100644 index 58d24b97f..000000000 --- a/docs/src/content/docs/community/showcase/bulletinboard.md +++ /dev/null @@ -1,16 +0,0 @@ ---- -title: BulletinBoard ---- - -![BulletinBoard](../../../../assets/showcase-images/bboard.webp) - -The [BulletinBoard](https://github.com/raguay/BulletinBoard) application is a -versital message board for static messages or dialogs to get information from -the user for a script. It has a TUI for creating new dialogs that can latter be -used to get information from the user. It's design is to stay running on your -system and show the information as needed and then hide away. I have a process -for watching a file on my system and sending the contents to BulletinBoard when -changed. It works great with my workflows. T here is also an -[Alfred workflow](https://github.com/raguay/MyAlfred/blob/master/Alfred%205/EmailIt.alfredworkflow) -for sending information to the program. The workflow is also for working with -[EmailIt](https://github.com/raguay/EmailIt). diff --git a/docs/src/content/docs/community/showcase/cfntracker.md b/docs/src/content/docs/community/showcase/cfntracker.md deleted file mode 100644 index dc9c030f3..000000000 --- a/docs/src/content/docs/community/showcase/cfntracker.md +++ /dev/null @@ -1,36 +0,0 @@ ---- -title: CFN Tracker ---- - -![CFN Tracker](../../../../assets/showcase-images/cfntracker.webp) - -[CFN Tracker](https://github.com/williamsjokvist/cfn-tracker) - Track any Street -Fighter 6 or V CFN profile's live matches. Check -[the website](https://cfn.williamsjokvist.se/) to get started. - -## Features - -- Real-time match tracking -- Storing match logs and statistics -- Support for displaying live stats to OBS via Browser Source -- Support for both SF6 and SFV -- Ability for users to create their own OBS Browser themes with CSS - -### Major tech used alongside Wails - -- [Task](https://github.com/go-task/task) - wrapping the Wails CLI to make - common commands easy to use -- [React](https://github.com/facebook/react) - chosen for its rich ecosystem - (radix, framer-motion) -- [Bun](https://github.com/oven-sh/bun) - used for its fast dependency - resolution and build-time -- [Rod](https://github.com/go-rod/rod) - headless browser automation for - authentication and polling changes -- [SQLite](https://github.com/mattn/go-sqlite3) - used for storing matches, - sessions and profiles -- [Server-sent events](https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events) - - a http stream to send tracking updates to OBS browser sources -- [i18next](https://github.com/i18next/) - with backend connector to serve - localization objects from the Go layer -- [xstate](https://github.com/statelyai/xstate) - state machines for auth - process and tracking diff --git a/docs/src/content/docs/community/showcase/clave.md b/docs/src/content/docs/community/showcase/clave.md deleted file mode 100644 index 9c405e616..000000000 --- a/docs/src/content/docs/community/showcase/clave.md +++ /dev/null @@ -1,18 +0,0 @@ ---- -title: Clave ---- - -![Clave](../../../../assets/showcase-images/clave.png) - -Key Features - -- 🎨 Simple, intuitive design for hassle-free experience -- ✅ Add accounts easily via manual entry or QR code image import. -- 🔒 End-to-end encryption with PIN or Touch ID(macOS only). -- 💻 Available for macOS, Windows, and Linux -- ⚡ Quick access from system tray for convenience -- 📂 Easily backup and restore your profiles - -Try Clave Today! - -💻 [https://clave.rocks](https://clave.rocks) diff --git a/docs/src/content/docs/community/showcase/emailit.md b/docs/src/content/docs/community/showcase/emailit.md deleted file mode 100644 index 6afc1da5e..000000000 --- a/docs/src/content/docs/community/showcase/emailit.md +++ /dev/null @@ -1,14 +0,0 @@ ---- -title: EmailIt ---- - -![EmailIt](../../../../assets/showcase-images/emailit.webp) - -[EmailIt](https://github.com/raguay/EmailIt/) is a Wails 2 program that is a -markdown based email sender only with nine notepads, scripts to manipulate the -text, and templates. It also has a scripts terminal to run scripts in EmailIt on -files in your system. The scripts and templates can be used from the commandline -itself or with the Alfred, Keyboard Maestro, Dropzone, or PopClip extensions. It -also supports scripts and themes downloaded form GitHub. Documentation is not -complete, but the programs works. It’s built using Wails2 and Svelte, and the -download is a universal macOS application. diff --git a/docs/src/content/docs/community/showcase/encrypteasy.md b/docs/src/content/docs/community/showcase/encrypteasy.md deleted file mode 100644 index 3a098fac9..000000000 --- a/docs/src/content/docs/community/showcase/encrypteasy.md +++ /dev/null @@ -1,16 +0,0 @@ ---- -title: EncryptEasy ---- - -![EncryptEasy](../../../../assets/showcase-images/encrypteasy.webp) - -**[EncryptEasy](https://www.encrypteasy.app) is a simple and easy to use PGP -encryption tool, managing all your and your contacts keys. Encryption should be -simple. Developed with Wails.** - -Encrypting messages using PGP is the industry standard. Everyone has a private -and a public key. Your private key, well, needs to be kept private so only you -can read messages. Your public key is distributed to anyone who wants to send -you secret, encrypted messages. Managing keys, encrypting messages and -decrypting messages should be a smooth experience. EncryptEasy is all about -making it easy. diff --git a/docs/src/content/docs/community/showcase/espstudio.md b/docs/src/content/docs/community/showcase/espstudio.md deleted file mode 100644 index 0ac90a827..000000000 --- a/docs/src/content/docs/community/showcase/espstudio.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -title: ESP Studio ---- - -![ESP Studio](../../../../assets/showcase-images/esp-studio.png) - -[ESP Studio](https://github.com/torabian/esp-studio) - Cross platform, Desktop, -Cloud, and Embedded software for controlling ESP/Arduino devices, and building -complex IOT workflows and control systems diff --git a/docs/src/content/docs/community/showcase/filehound.md b/docs/src/content/docs/community/showcase/filehound.md deleted file mode 100644 index 627007f97..000000000 --- a/docs/src/content/docs/community/showcase/filehound.md +++ /dev/null @@ -1,29 +0,0 @@ ---- -title: FileHound Export Utility ---- - -![FileHound Export Utility](../../../../assets/showcase-images/filehound.webp) - -[FileHound Export Utility](https://www.filehound.co.uk/) FileHound is a cloud -document management platform made for secure file retention, business process -automation and SmartCapture capabilities. - -The FileHound Export Utility allows FileHound Administrators the ability to run -a secure document and data extraction tasks for alternative back-up and recovery -purposes. This application will download all documents and/or meta data saved in -FileHound based on the filters you choose. The metadata will be exported in both -JSON and XML formats. - -Backend built with: - -- Go 1.15 -- Wails 1.11.0 -- go-sqlite3 1.14.6 -- go-linq 3.2 - -Frontend with: - -- Vue 2.6.11 -- Vuex 3.4.0 -- TypeScript -- Tailwind 1.9.6 diff --git a/docs/src/content/docs/community/showcase/hiposter.md b/docs/src/content/docs/community/showcase/hiposter.md deleted file mode 100644 index 08acfa832..000000000 --- a/docs/src/content/docs/community/showcase/hiposter.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -title: hiposter ---- - -![hiposter](../../../../assets/showcase-images/hiposter.webp) - -[hiposter](https://github.com/obity/hiposter) is a simple and efficient http API -testing client tool. Based on Wails, Go and sveltejs. diff --git a/docs/src/content/docs/community/showcase/index.mdx b/docs/src/content/docs/community/showcase/index.mdx deleted file mode 100644 index e1da3f75d..000000000 --- a/docs/src/content/docs/community/showcase/index.mdx +++ /dev/null @@ -1,189 +0,0 @@ ---- -title: Overview -sidebar: - order: 1 ---- - -import { ShowcaseImage } from "starlight-showcases"; -import { Steps } from "@astrojs/starlight/components"; - -:::tip[See how to add your project] - -Check out the -[How to add my project in showcase](#how-to-add-my-project-in-showcase) section. - -::: - - - -## How to add my project in showcase - - - -1. Make a fork of the repository. -2. Add the image(s) under `docs/src/assets/showcase-images` folder. -3. Make a copy of the `_template.md` file under - `docs/src/content/docs/community/showcase` folder. -4. Rename the copied file to the name of your project. (Name should not start - with `_`)) -5. Update the title, image, link and content of the file. -6. Add it on the above list in - `docs/src/content/docs/community/showcase/index.mdx`. -7. Submit a PR. - - diff --git a/docs/src/content/docs/community/showcase/mchat.md b/docs/src/content/docs/community/showcase/mchat.md deleted file mode 100644 index 444aed343..000000000 --- a/docs/src/content/docs/community/showcase/mchat.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -title: Mchat ---- - -![Mchat](../../../../assets/showcase-images/mchat.png) - -[Official page](https://marcio199226.github.io/mchat-site/public/) Fully -anonymous end2end encrypted chat. diff --git a/docs/src/content/docs/community/showcase/minecraftupdater.md b/docs/src/content/docs/community/showcase/minecraftupdater.md deleted file mode 100644 index 57cd80e30..000000000 --- a/docs/src/content/docs/community/showcase/minecraftupdater.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -title: Minecraft Updater ---- - -![Minecraft Updater](../../../../assets/showcase-images/minecraft-mod-updater.webp) - -[Minecraft Updater](https://github.com/Gurkengewuerz/MinecraftModUpdater) is a -utility tool to update and synchronize Minecraft mods for your userbase. It’s -built using Wails2 and React with [antd](https://ant.design/) as frontend -framework. diff --git a/docs/src/content/docs/community/showcase/minesweeper-xp.md b/docs/src/content/docs/community/showcase/minesweeper-xp.md deleted file mode 100644 index 9ca30ed55..000000000 --- a/docs/src/content/docs/community/showcase/minesweeper-xp.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -title: Minesweeper XP ---- - -![Minesweeper XP](../../../../assets/showcase-images/minesweeper-xp.webp) - -[Minesweeper-XP](https://git.new/Minesweeper-XP) allows you to experience the -classic Minesweeper XP (+ 98 and 3.1) on macOS, Windows, and Linux! diff --git a/docs/src/content/docs/community/showcase/modalfilemanager.md b/docs/src/content/docs/community/showcase/modalfilemanager.md deleted file mode 100644 index 7a7748d4d..000000000 --- a/docs/src/content/docs/community/showcase/modalfilemanager.md +++ /dev/null @@ -1,21 +0,0 @@ ---- -title: Modal File Manager ---- - -![Modal File Manager](../../../../assets/showcase-images/modalfilemanager.webp) - -[Modal File Manager](https://github.com/raguay/ModalFileManager) is a dual pane -file manager using web technologies. My original design was based on NW.js and -can be found [here](https://github.com/raguay/ModalFileManager-NWjs). This -version uses the same Svelte based frontend code (but it has be greatly modified -since the departure from NW.js), but the backend is a -[Wails 2](https://wails.io/) implementation. By using this implementation, I no -longer use command line `rm`, `cp`, etc. commands, but a git install has to be -on the system to download themes and extensions. It is fully coded using Go and -runs much faster than the previous versions. - -This file manager is designed around the same principle as Vim: a state -controlled keyboard actions. The number of states isn't fixed, but very -programmable. Therefore, an infinite number of keyboard configurations can be -created and used. This is the main difference from other file managers. There -are themes and extensions available to download from GitHub. diff --git a/docs/src/content/docs/community/showcase/mollywallet.md b/docs/src/content/docs/community/showcase/mollywallet.md deleted file mode 100644 index 930aebd75..000000000 --- a/docs/src/content/docs/community/showcase/mollywallet.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -title: Molley Wallet ---- - -![Molly Wallet](../../../../assets/showcase-images/mollywallet.webp) - -[Molly Wallet](https://github.com/grvlle/constellation_wallet/) the official -$DAG wallet of the Constellation Network. It'll let users interact with the -Hypergraph Network in various ways, not limited to producing $DAG transactions. diff --git a/docs/src/content/docs/community/showcase/october.md b/docs/src/content/docs/community/showcase/october.md deleted file mode 100644 index 60a29e91b..000000000 --- a/docs/src/content/docs/community/showcase/october.md +++ /dev/null @@ -1,16 +0,0 @@ ---- -title: October ---- - -![October](../../../../assets/showcase-images/october.webp) - -[October](https://october.utf9k.net) is a small Wails application that makes it -really easy to extract highlights from -[Kobo eReaders](https://en.wikipedia.org/wiki/Kobo_eReader) and then forward -them to [Readwise](https://readwise.io). - -It has a relatively small scope with all platform versions weighing in under -10MB, and that's without enabling [UPX compression](https://upx.github.io/)! - -In contrast, the author's previous attempts with Electron quickly bloated to -several hundred megabytes. diff --git a/docs/src/content/docs/community/showcase/optimus.md b/docs/src/content/docs/community/showcase/optimus.md deleted file mode 100644 index 6128258b2..000000000 --- a/docs/src/content/docs/community/showcase/optimus.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -title: Optimus ---- - -![Optimus](../../../../assets/showcase-images/optimus.webp) - -[Optimus](https://github.com/splode/optimus) is a desktop image optimization -application. It supports conversion and compression between WebP, JPEG, and PNG -image formats. diff --git a/docs/src/content/docs/community/showcase/portfall.md b/docs/src/content/docs/community/showcase/portfall.md deleted file mode 100644 index c1ffc76f9..000000000 --- a/docs/src/content/docs/community/showcase/portfall.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -title: Portfall ---- - -![Portfall](../../../../assets/showcase-images/portfall.webp) - -[Portfall](https://github.com/rekon-oss/portfall) - A desktop k8s -port-forwarding portal for easy access to all your cluster UIs diff --git a/docs/src/content/docs/community/showcase/resizem.md b/docs/src/content/docs/community/showcase/resizem.md deleted file mode 100644 index 3e8761dbc..000000000 --- a/docs/src/content/docs/community/showcase/resizem.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -title: Resizem ---- - -![Resizem Screenshot](../../../../assets/showcase-images/resizem.webp) - -[Resizem](https://github.com/barats/resizem) - is an app designed for bulk image -process. It is particularly useful for users who need to resize, convert, and -manage large numbers of image files at once. diff --git a/docs/src/content/docs/community/showcase/restic-browser.md b/docs/src/content/docs/community/showcase/restic-browser.md deleted file mode 100644 index 5a68cb02e..000000000 --- a/docs/src/content/docs/community/showcase/restic-browser.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -title: Restic Browser ---- - -![Restic Browser](../../../../assets/showcase-images/restic-browser-2.png) - -[Restic-Browser](https://github.com/emuell/restic-browser) - A simple, -cross-platform [restic](https://github.com/restic/restic) backup GUI for -browsing and restoring restic repositories. diff --git a/docs/src/content/docs/community/showcase/riftshare.md b/docs/src/content/docs/community/showcase/riftshare.md deleted file mode 100644 index b6ed8f464..000000000 --- a/docs/src/content/docs/community/showcase/riftshare.md +++ /dev/null @@ -1,23 +0,0 @@ ---- -title: RiftShare ---- - -![RiftShare](../../../../assets/showcase-images/riftshare-main.webp) - -Easy, Secure, and Free file sharing for everyone. Learn more at -[Riftshare.app](https://riftshare.app) - -## Features - -- Easy secure file sharing between computers both in the local network and - through the internet -- Supports sending files or directories securely through the - [magic wormhole protocol](https://magic-wormhole.readthedocs.io/en/latest/) -- Compatible with all other apps using magic wormhole (magic-wormhole or - wormhole-william CLI, wormhole-gui, etc.) -- Automatic zipping of multiple selected files to send at once -- Full animations, progress bar, and cancellation support for sending and - receiving -- Native OS File Selection -- Open files in one click once received -- Auto Update - don't worry about having the latest release! diff --git a/docs/src/content/docs/community/showcase/scriptbar.md b/docs/src/content/docs/community/showcase/scriptbar.md deleted file mode 100644 index 1e03ab528..000000000 --- a/docs/src/content/docs/community/showcase/scriptbar.md +++ /dev/null @@ -1,14 +0,0 @@ ---- -title: ScriptBar ---- - -![ScriptBar](../../../../assets/showcase-images/scriptbar.webp) - -[ScriptBar](https://GitHub.com/raguay/ScriptBarApp) is a program to show the -output of scripts or [Node-Red](https://nodered.org) server. It runs scripts -defined in EmailIt program and shows the output. Scripts from xBar or TextBar -can be used, but currently on the TextBar scripts work well. It also displays -the output of scripts on your system. ScriptBar doesn't put them in the menubar, -but has them all in a convient window for easy viewing. You can have multiple -tabs to have many different things show. You can also keep the links to your -most visited web sites. diff --git a/docs/src/content/docs/community/showcase/snippetexpander.md b/docs/src/content/docs/community/showcase/snippetexpander.md deleted file mode 100644 index 0b5a88801..000000000 --- a/docs/src/content/docs/community/showcase/snippetexpander.md +++ /dev/null @@ -1,34 +0,0 @@ ---- -title: Snippet Expander ---- - -![Snippet Expander Screenshot](../../../../assets/showcase-images/snippetexpandergui-select-snippet.png) - -Screenshot of Snippet Expander's Select Snippet window - -![Snippet Expander Screenshot](../../../../assets/showcase-images/snippetexpandergui-add-snippet.png) - -Screenshot of Snippet Expander's Add Snippet screen - -![Snippet Expander Screenshot](../../../../assets/showcase-images/snippetexpandergui-search-and-paste.png) - -Screenshot of Snippet Expander's Search & Paste window - -[Snippet Expander](https://snippetexpander.org) is "Your little expandable text -snippets helper", for Linux. - -Snippet Expander comprises of a GUI application built with Wails for managing -snippets and settings, with a Search & Paste window mode for quickly selecting -and pasting a snippet. - -The Wails based GUI, go-lang CLI and vala-lang auto expander daemon all -communicate with a go-lang daemon via D-Bus. The daemon does the majority of the -work, managing the database of snippets and common settings, and providing -services for expanding and pasting snippets etc. - -Check out the -[source code](https://git.sr.ht/~ianmjones/snippetexpander/tree/trunk/item/cmd/snippetexpandergui/app.go#L38) -to see how the Wails app sends messages from the UI to the backend that are then -sent to the daemon, and subscribes to a D-Bus event to monitor changes to -snippets via another instance of the app or CLI and show them instantly in the -UI via a Wails event. diff --git a/docs/src/content/docs/community/showcase/surge.md b/docs/src/content/docs/community/showcase/surge.md deleted file mode 100644 index 3ab4444dd..000000000 --- a/docs/src/content/docs/community/showcase/surge.md +++ /dev/null @@ -1,9 +0,0 @@ ---- -title: Surge ---- - -![Surge Screenshot](../../../../assets/showcase-images/surge.png) - -[Surge](https://getsurge.io/) is a p2p filesharing app designed to utilize -blockchain technologies to enable 100% anonymous file transfers. Surge is -end-to-end encrypted, decentralized and open source. diff --git a/docs/src/content/docs/community/showcase/tinyrdm.md b/docs/src/content/docs/community/showcase/tinyrdm.md deleted file mode 100644 index f9551e046..000000000 --- a/docs/src/content/docs/community/showcase/tinyrdm.md +++ /dev/null @@ -1,12 +0,0 @@ ---- -title: Tiny RDM ---- - -![Tiny RDM Screenshot](../../../../assets/showcase-images/tiny-rdm1.webp) -![Tiny RDM Screenshot](../../../../assets/showcase-images/tiny-rdm2.webp) - -The [Tiny RDM](https://redis.tinycraft.cc/) application is an open-source, -modern lightweight Redis GUI. It has a beautful UI, intuitive Redis database -management, and compatible with Windows, Mac, and Linux. It provides visual -key-value data operations, supports various data decoding and viewing options, -built-in console for executing commands, slow log queries and more. diff --git a/docs/src/content/docs/community/showcase/wailsterm.md b/docs/src/content/docs/community/showcase/wailsterm.md deleted file mode 100644 index 0521aac70..000000000 --- a/docs/src/content/docs/community/showcase/wailsterm.md +++ /dev/null @@ -1,8 +0,0 @@ ---- -title: WailsTerm ---- - -![WailsTerm Screenshot](../../../../assets/showcase-images/wailsterm.webp) - -[WailsTerm](https://github.com/rlshukhov/wailsterm) is a simple translucent -terminal app powered by Wails and Xterm.js. diff --git a/docs/src/content/docs/community/showcase/wally.md b/docs/src/content/docs/community/showcase/wally.md deleted file mode 100644 index 3f4ddbfa2..000000000 --- a/docs/src/content/docs/community/showcase/wally.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -title: Wally ---- - -![Wally Screenshot](../../../../assets/showcase-images/wally.webp) - -[Wally](https://ergodox-ez.com/pages/wally) is the official firmware flasher for -[Ergodox](https://ergodox-ez.com/) keyboards. It looks great and is a fantastic -example of what you can achieve with Wails: the ability to combine the power of -Go and the rich graphical tools of the web development world. diff --git a/docs/src/content/docs/community/showcase/warmine.md b/docs/src/content/docs/community/showcase/warmine.md deleted file mode 100644 index 19de97f2a..000000000 --- a/docs/src/content/docs/community/showcase/warmine.md +++ /dev/null @@ -1,17 +0,0 @@ ---- -title: Minecraft launcher for WarMine ---- - -![WarMine Screenshot](../../../../assets/showcase-images/warmine1.png) -![WarMine Screenshot](../../../../assets/showcase-images/warmine2.png) - -[Minecraft launcher for WarMine](https://warmine.ru/) is a Wails application, -that allows you to easily join modded game servers and manage your game -accounts. - -The Launcher downloads the game files, checks their integrity and launches the -game with a wide range of customization options for the launch arguments from -the backend. - -Frontend is written in Svelte, whole launcher fits in 9MB and supports Windows -7-11. diff --git a/docs/src/content/docs/community/showcase/wombat.md b/docs/src/content/docs/community/showcase/wombat.md deleted file mode 100644 index d61bdd6c9..000000000 --- a/docs/src/content/docs/community/showcase/wombat.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -title: Wombat ---- - -![Wombat Screenshot](../../../../assets/showcase-images/wombat.webp) - -[Wombat](https://github.com/rogchap/wombat) is a cross platform gRPC client. diff --git a/docs/src/content/docs/community/showcase/ytd.md b/docs/src/content/docs/community/showcase/ytd.md deleted file mode 100644 index bbcd6979f..000000000 --- a/docs/src/content/docs/community/showcase/ytd.md +++ /dev/null @@ -1,10 +0,0 @@ ---- -title: Ytd ---- - -![Ytd Screenshot](../../../../assets/showcase-images/ytd.webp) - -[Ytd](https://github.com/marcio199226/ytd/tree/v2-wails) is an app for -downloading tracks from youtube, creating offline playlists and share them with -your friends, your friends will be able to playback your playlists or download -them for offline listening, has an built-in player. diff --git a/docs/src/content/docs/community/templates.md b/docs/src/content/docs/community/templates.md deleted file mode 100644 index 855b70c23..000000000 --- a/docs/src/content/docs/community/templates.md +++ /dev/null @@ -1,132 +0,0 @@ ---- -title: Templates ---- - -:::caution - -This page might be outdated for Wails v3. - -::: - - - -This page serves as a list for community supported templates. To build your own -template, please see the [Templates](https://wails.io/docs/guides/templates) -guide. - -:::tip[How to Submit a Template] - -You can click `Edit this page` at the bottom to include your templates. - -::: - -To use these templates, run -`wails init -n "Your Project Name" -t [the link below[@version]]` - -If there is no version suffix, the main branch code template is used by default. -If there is a version suffix, the code template corresponding to the tag of this -version is used. - -Example: -`wails init -n "Your Project Name" -t https://github.com/misitebao/wails-template-vue` - -:::danger[Attention] - -**The Wails project does not maintain, is not responsible nor liable for 3rd -party templates!** - -If you are unsure about a template, inspect `package.json` and `wails.json` for -what scripts are run and what packages are installed. - -::: - -## Vue - -- [wails-template-vue](https://github.com/misitebao/wails-template-vue) - Wails - template based on Vue ecology (Integrated TypeScript, Dark theme, - Internationalization, Single page routing, TailwindCSS) -- [wails-template-quasar-js](https://github.com/sgosiaco/wails-template-quasar-js) - - A template using JavaScript + Quasar V2 (Vue 3, Vite, Sass, Pinia, ESLint, - Prettier) -- [wails-template-quasar-ts](https://github.com/sgosiaco/wails-template-quasar-ts) - - A template using TypeScript + Quasar V2 (Vue 3, Vite, Sass, Pinia, ESLint, - Prettier, Composition API with <script setup>) -- [wails-template-naive](https://github.com/tk103331/wails-template-naive) - - Wails template based on Naive UI (A Vue 3 Component Library) -- [wails-template-nuxt](https://github.com/gornius/wails-template-nuxt) - Wails - template using clean Nuxt3 and TypeScript with auto-imports for wails js - runtime -- [Wails-Tool-Template](https://github.com/xisuo67/Wails-Tool-Template) - Wails - template using Vue+TypeScript+Vite+Element-plus(仿网易云) - -## Angular - -- [wails-template-angular](https://github.com/mateothegreat/wails-template-angular) - - Angular 15+ action packed & ready to roll to production. -- [wails-angular-template](https://github.com/TAINCER/wails-angular-template) - - Angular with TypeScript, Sass, Hot-Reload, Code-Splitting and i18n - -## React - -- [wails-react-template](https://github.com/AlienRecall/wails-react-template) - - A template using reactjs -- [wails-react-template](https://github.com/flin7/wails-react-template) - A - minimal template for React that supports live development -- [wails-template-nextjs](https://github.com/LGiki/wails-template-nextjs) - A - template using Next.js and TypeScript -- [wails-template-nextjs-app-router](https://github.com/thisisvk-in/wails-template-nextjs-app-router) - - A template using Next.js and TypeScript with App router -- [wails-template-nextjs-app-router-src](https://github.com/edai-git/wails-template-nextjs-app-router) - - A template using Next.js and TypeScript with App router src + example -- [wails-vite-react-ts-tailwind-template](https://github.com/hotafrika/wails-vite-react-ts-tailwind-template) - - A template for React + TypeScript + Vite + TailwindCSS -- [wails-vite-react-ts-tailwind-shadcnui-template](https://github.com/Mahcks/wails-vite-react-tailwind-shadcnui-ts) - - A template with Vite, React, TypeScript, TailwindCSS, and shadcn/ui - -## Svelte - -- [wails-svelte-template](https://github.com/raitonoberu/wails-svelte-template) - - A template using Svelte -- [wails-vite-svelte-template](https://github.com/BillBuilt/wails-vite-svelte-template) - - A template using Svelte and Vite -- [wails-vite-svelte-tailwind-template](https://github.com/BillBuilt/wails-vite-svelte-tailwind-template) - - A template using Svelte and Vite with TailwindCSS v3 -- [wails-svelte-tailwind-vite-template](https://github.com/PylotLight/wails-vite-svelte-tailwind-template/tree/master) - - An updated template using Svelte v4.2.0 and Vite with TailwindCSS v3.3.3 -- [wails-sveltekit-template](https://github.com/h8gi/wails-sveltekit-template) - - A template using SvelteKit -- [wails-template-shadcn-svelte](https://github.com/xijaja/wails-template-shadcn-svelte) - - A template using Sveltekit and Shadcn-Svelte - -## Solid - -- [wails-template-vite-solid-ts](https://github.com/xijaja/wails-template-solid-ts) - - A template using Solid + Ts + Vite -- [wails-template-vite-solid-js](https://github.com/xijaja/wails-template-solid-js) - - A template using Solid + Js + Vite - -## Elm - -- [wails-elm-template](https://github.com/benjamin-thomas/wails-elm-template) - - Develop your GUI app with functional programming and a **snappy** hot-reload - setup :tada: :rocket: -- [wails-template-elm-tailwind](https://github.com/rnice01/wails-template-elm-tailwind) - - Combine the powers :muscle: of Elm + Tailwind CSS + Wails! Hot reloading - supported. - -## HTMX - -- [wails-htmx-templ-chi-tailwind](https://github.com/PylotLight/wails-hmtx-templ-template) - - Use a unique combination of pure htmx for interactivity plus templ for - creating components and forms - -## Pure JavaScript (Vanilla) - -- [wails-pure-js-template](https://github.com/KiddoV/wails-pure-js-template) - A - template with nothing but just basic JavaScript, HTML, and CSS - -## Lit (web components) - -- [wails-lit-shoelace-esbuild-template](https://github.com/Braincompiler/wails-lit-shoelace-esbuild-template) - - Wails template providing frontend with lit, Shoelace component library + - pre-configured prettier and typescript. diff --git a/docs/src/content/docs/concepts/architecture.mdx b/docs/src/content/docs/concepts/architecture.mdx deleted file mode 100644 index d72affe3b..000000000 --- a/docs/src/content/docs/concepts/architecture.mdx +++ /dev/null @@ -1,655 +0,0 @@ ---- -title: How Wails Works -description: Understanding the Wails architecture and how it achieves native performance -sidebar: - order: 1 ---- - -import { Tabs, TabItem } from "@astrojs/starlight/components"; - -Wails is a framework for building desktop applications using **Go for the backend** and **web technologies for the frontend**. But unlike Electron, Wails doesn't bundle a browser—it uses the **operating system's native WebView**. - -```d2 -direction: right - -User: "User" { - shape: person - style.fill: "#3B82F6" -} - -Application: "Your Wails Application" { - Frontend: "Frontend\n(HTML/CSS/JS)" { - shape: rectangle - style.fill: "#8B5CF6" - } - - Runtime: "Wails Runtime" { - Bridge: "Message Bridge" { - shape: diamond - style.fill: "#10B981" - } - - Bindings: "Type-Safe Bindings" { - shape: rectangle - style.fill: "#10B981" - } - } - - Backend: "Go Backend" { - Services: "Your Services" { - shape: rectangle - style.fill: "#00ADD8" - } - - NativeAPIs: "OS APIs" { - shape: rectangle - style.fill: "#00ADD8" - } - } -} - -OS: "Operating System" { - WebView: "Native WebView\n(WebKit/WebView2/WebKitGTK)" { - shape: rectangle - style.fill: "#6B7280" - } - - SystemAPIs: "System APIs\n(Windows/macOS/Linux)" { - shape: rectangle - style.fill: "#6B7280" - } -} - -User -> Application.Frontend: "Interacts with UI" -Application.Frontend <-> Application.Runtime.Bridge: "JSON messages" -Application.Runtime.Bridge <-> Application.Backend.Services: "Direct function calls" -Application.Runtime.Bindings -> Application.Frontend: "TypeScript definitions" -Application.Frontend -> OS.WebView: "Renders in" -Application.Backend.NativeAPIs -> OS.SystemAPIs: "Native calls" -``` - -**Key differences from Electron:** - -| Aspect | Wails | Electron | -|--------|-------|----------| -| **Browser** | OS-provided WebView | Bundled Chromium (~100MB) | -| **Backend** | Go (compiled) | Node.js (interpreted) | -| **Communication** | In-memory bridge | IPC (inter-process) | -| **Bundle Size** | ~15MB | ~150MB | -| **Memory** | ~10MB | ~100MB+ | -| **Startup** | <0.5s | 2-3s | - -## Core Components - -### 1. Native WebView - -Wails uses the operating system's built-in web rendering engine: - - - - **WebView2** (Microsoft Edge WebView2) - - Based on Chromium (same as Edge browser) - - Pre-installed on Windows 10/11 - - Automatic updates via Windows Update - - Full modern web standards support - - - - **WebKit** (Safari's rendering engine) - - Built into macOS - - Same engine as Safari browser - - Excellent performance and battery life - - Full modern web standards support - - - - **WebKitGTK** (GTK port of WebKit) - - Installed via package manager - - Same engine as GNOME Web (Epiphany) - - Good standards support - - Lightweight and performant - - - -**Why this matters:** -- **No bundled browser** → Smaller app size -- **OS-native** → Better integration and performance -- **Auto-updates** → Security patches from OS updates -- **Familiar rendering** → Same as system browser - -### 2. The Wails Bridge - -The bridge is the heart of Wails—it enables **direct communication** between Go and JavaScript. - -```d2 -direction: down - -Frontend: "Frontend (JavaScript)" { - shape: rectangle - style.fill: "#8B5CF6" -} - -Bridge: "Wails Bridge" { - Encoder: "JSON Encoder" { - shape: rectangle - } - - Router: "Method Router" { - shape: diamond - style.fill: "#10B981" - } - - Decoder: "JSON Decoder" { - shape: rectangle - } -} - -Backend: "Backend (Go)" { - Services: "Registered Services" { - shape: rectangle - style.fill: "#00ADD8" - } -} - -Frontend -> Bridge.Encoder: "1. Call Go method\nGreet('Alice')" -Bridge.Encoder -> Bridge.Router: "2. Encode to JSON\n{method: 'Greet', args: ['Alice']}" -Bridge.Router -> Backend.Services: "3. Route to service\nGreetService.Greet('Alice')" -Backend.Services -> Bridge.Decoder: "4. Return result\n'Hello, Alice!'" -Bridge.Decoder -> Frontend: "5. Decode to JS\nPromise resolves" -``` - -**How it works:** - -1. **Frontend calls a Go method** (via auto-generated binding) -2. **Bridge encodes the call** to JSON (method name + arguments) -3. **Router finds the Go method** in registered services -4. **Go method executes** and returns a value -5. **Bridge decodes the result** and sends back to frontend -6. **Promise resolves** in JavaScript with the result - -**Performance characteristics:** -- **In-memory**: No network overhead, no HTTP -- **Zero-copy** where possible (for large data) -- **Async by default**: Non-blocking on both sides -- **Type-safe**: TypeScript definitions auto-generated - -### 3. Service System - -Services are the recommended way to expose Go functionality to the frontend. - -```go -// Define a service (just a regular Go struct) -type GreetService struct { - prefix string -} - -// Methods with exported names are automatically available -func (g *GreetService) Greet(name string) string { - return g.prefix + name + "!" -} - -func (g *GreetService) GetTime() time.Time { - return time.Now() -} - -// Register the service -app := application.New(application.Options{ - Services: []application.Service{ - application.NewService(&GreetService{prefix: "Hello, "}), - }, -}) -``` - -**Service discovery:** -- Wails **scans your struct** at startup -- **Exported methods** become callable from frontend -- **Type information** is extracted for TypeScript bindings -- **Error handling** is automatic (Go errors → JS exceptions) - -**Generated TypeScript binding:** -```typescript -// Auto-generated in frontend/bindings/GreetService.ts -export function Greet(name: string): Promise -export function GetTime(): Promise -``` - -**Why services?** -- **Type-safe**: Full TypeScript support -- **Auto-discovery**: No manual registration of methods -- **Organised**: Group related functionality -- **Testable**: Services are just Go structs - -[Learn more about services →](/features/bindings/services) - -### 4. Event System - -Events enable **pub/sub communication** between components. - -```d2 -direction: right - -GoService: "Go Service" { - shape: rectangle - style.fill: "#00ADD8" -} - -EventBus: "Event Bus" { - shape: cylinder - style.fill: "#10B981" -} - -Frontend1: "Window 1" { - shape: rectangle - style.fill: "#8B5CF6" -} - -Frontend2: "Window 2" { - shape: rectangle - style.fill: "#8B5CF6" -} - -GoService -> EventBus: "Emit('data-updated', data)" -EventBus -> Frontend1: "Notify subscribers" -EventBus -> Frontend2: "Notify subscribers" -Frontend1 -> EventBus: "On('data-updated', handler)" -Frontend2 -> EventBus: "On('data-updated', handler)" -``` - -**Use cases:** -- **Window communication**: One window notifies others -- **Background tasks**: Go service notifies UI of progress -- **State synchronisation**: Keep multiple windows in sync -- **Loose coupling**: Components don't need direct references - -**Example:** -```go -// Go: Emit an event -app.Event.Emit("user-logged-in", user) -``` - -```javascript -// JavaScript: Listen for event -import { On } from '@wailsio/runtime' - -On('user-logged-in', (user) => { - console.log('User logged in:', user) -}) -``` - -[Learn more about events →](/features/events/system) - -## Application Lifecycle - -Understanding the lifecycle helps you know when to initialise resources and clean up. - -```d2 -direction: down - -Start: "Application Start" { - shape: oval - style.fill: "#10B981" -} - -Init: "Initialisation" { - Create: "Create Application" { - shape: rectangle - } - - Register: "Register Services" { - shape: rectangle - } - - Setup: "Setup Windows/Menus" { - shape: rectangle - } -} - -Run: "Event Loop" { - Events: "Process Events" { - shape: rectangle - } - - Messages: "Handle Messages" { - shape: rectangle - } - - Render: "Update UI" { - shape: rectangle - } -} - -Shutdown: "Shutdown" { - Cleanup: "Cleanup Resources" { - shape: rectangle - } - - Save: "Save State" { - shape: rectangle - } -} - -End: "Application End" { - shape: oval - style.fill: "#EF4444" -} - -Start -> Init.Create -Init.Create -> Init.Register -Init.Register -> Init.Setup -Init.Setup -> Run.Events -Run.Events -> Run.Messages -Run.Messages -> Run.Render -Run.Render -> Run.Events: "Loop" -Run.Events -> Shutdown.Cleanup: "Quit signal" -Shutdown.Cleanup -> Shutdown.Save -Shutdown.Save -> End -``` - -**Lifecycle hooks:** - -```go -app := application.New(application.Options{ - Name: "My App", - - // Called before windows are created - OnStartup: func(ctx context.Context) { - // Initialise database, load config, etc. - }, - - // Called when app is about to quit - OnShutdown: func() { - // Save state, close connections, etc. - }, -}) -``` - -[Learn more about lifecycle →](/concepts/lifecycle) - -## Build Process - -Understanding how Wails builds your application: - -```d2 -direction: down - -Source: "Source Code" { - Go: "Go Code\n(main.go, services)" { - shape: rectangle - style.fill: "#00ADD8" - } - - Frontend: "Frontend Code\n(HTML/CSS/JS)" { - shape: rectangle - style.fill: "#8B5CF6" - } -} - -Build: "Build Process" { - AnalyseGo: "Analyse Go Code" { - shape: rectangle - } - - GenerateBindings: "Generate Bindings" { - shape: rectangle - } - - BuildFrontend: "Build Frontend" { - shape: rectangle - } - - CompileGo: "Compile Go" { - shape: rectangle - } - - Embed: "Embed Assets" { - shape: rectangle - } -} - -Output: "Output" { - Binary: "Native Binary\n(myapp.exe/.app)" { - shape: rectangle - style.fill: "#10B981" - } -} - -Source.Go -> Build.AnalyseGo -Build.AnalyseGo -> Build.GenerateBindings: "Extract types" -Build.GenerateBindings -> Source.Frontend: "TypeScript bindings" -Source.Frontend -> Build.BuildFrontend: "Compile (Vite/webpack)" -Build.BuildFrontend -> Build.Embed: "Bundled assets" -Source.Go -> Build.CompileGo -Build.CompileGo -> Build.Embed -Build.Embed -> Output.Binary -``` - -**Build steps:** - -1. **Analyse Go code** - - Scan services for exported methods - - Extract parameter and return types - - Generate method signatures - -2. **Generate TypeScript bindings** - - Create `.ts` files for each service - - Include full type definitions - - Add JSDoc comments - -3. **Build frontend** - - Run your bundler (Vite, webpack, etc.) - - Minify and optimise - - Output to `frontend/dist/` - -4. **Compile Go** - - Compile with optimisations (`-ldflags="-s -w"`) - - Include build metadata - - Platform-specific compilation - -5. **Embed assets** - - Embed frontend files into Go binary - - Compress assets - - Create single executable - -**Result:** A single native executable with everything embedded. - -[Learn more about building →](/guides/build/building) - -## Development vs Production - -Wails behaves differently in development and production: - - - - **Characteristics:** - - **Hot reload**: Frontend changes reload instantly - - **Source maps**: Debug with original source - - **DevTools**: Browser DevTools available - - **Logging**: Verbose logging enabled - - **External frontend**: Served from dev server (Vite) - - **How it works:** - ```d2 - direction: right - - WailsApp: "Wails App" { - shape: rectangle - style.fill: "#00ADD8" - } - - DevServer: "Vite Dev Server\n(localhost:5173)" { - shape: rectangle - style.fill: "#8B5CF6" - } - - WebView: "WebView" { - shape: rectangle - style.fill: "#6B7280" - } - - WailsApp -> DevServer: "Proxy requests" - DevServer -> WebView: "Serve with HMR" - WebView -> WailsApp: "Call Go methods" - ``` - - **Benefits:** - - Instant feedback on changes - - Full debugging capabilities - - Faster iteration - - - - **Characteristics:** - - **Embedded assets**: Frontend built into binary - - **Optimised**: Minified, compressed - - **No DevTools**: Disabled by default - - **Minimal logging**: Errors only - - **Single file**: Everything in one executable - - **How it works:** - ```d2 - direction: right - - Binary: "Single Binary\n(myapp.exe)" { - GoCode: "Compiled Go" { - shape: rectangle - style.fill: "#00ADD8" - } - - Assets: "Embedded Assets\n(HTML/CSS/JS)" { - shape: rectangle - style.fill: "#8B5CF6" - } - } - - WebView: "WebView" { - shape: rectangle - style.fill: "#6B7280" - } - - Binary.Assets -> WebView: "Serve from memory" - WebView -> Binary.GoCode: "Call Go methods" - ``` - - **Benefits:** - - Single file distribution - - Smaller size (minified) - - Better performance - - No external dependencies - - - -## Memory Model - -Understanding memory usage helps you build efficient applications. - -{/* VISUAL PLACEHOLDER: Memory Diagram -Description: Memory layout diagram showing: -1. Go Heap (services, application state) -2. WebView Memory (DOM, JavaScript heap) -3. Shared Memory (bridge communication) -4. Arrows showing data flow between regions -5. Annotations for zero-copy optimisations -Style: Technical diagram with memory regions as boxes, clear labels, size indicators -*/} - -**Memory regions:** - -1. **Go Heap** - - Your services and application state - - Managed by Go garbage collector - - Typically 5-10MB for simple apps - -2. **WebView Memory** - - DOM, JavaScript heap, CSS - - Managed by WebView's engine - - Typically 10-20MB for simple apps - -3. **Bridge Memory** - - Message buffers for communication - - Minimal overhead (\<1MB) - - Zero-copy for large data where possible - -**Optimisation tips:** -- **Avoid large data transfers**: Pass IDs, fetch details on demand -- **Use events for updates**: Don't poll from frontend -- **Stream large files**: Don't load entirely into memory -- **Clean up listeners**: Remove event listeners when done - -[Learn more about performance →](/guides/advanced/performance) - -## Security Model - -Wails provides a secure-by-default architecture: - -```d2 -direction: down - -Frontend: "Frontend (Untrusted)" { - shape: rectangle - style.fill: "#EF4444" -} - -Bridge: "Wails Bridge (Validation)" { - shape: diamond - style.fill: "#F59E0B" -} - -Backend: "Backend (Trusted)" { - shape: rectangle - style.fill: "#10B981" -} - -Frontend -> Bridge: "Call method" -Bridge -> Bridge: "Validate:\n- Method exists?\n- Types correct?\n- Access allowed?" -Bridge -> Backend: "Execute if valid" -Backend -> Bridge: "Return result" -Bridge -> Frontend: "Send response" -``` - -**Security features:** - -1. **Method whitelisting** - - Only exported methods are callable - - Private methods are inaccessible - - Explicit service registration required - -2. **Type validation** - - Arguments checked against Go types - - Invalid types rejected - - Prevents injection attacks - -3. **No eval()** - - Frontend can't execute arbitrary Go code - - Only predefined methods callable - - No dynamic code execution - -4. **Context isolation** - - Each window has its own context - - Services can check caller context - - Permissions per window possible - -**Best practices:** -- **Validate user input** in Go (don't trust frontend) -- **Use context** for authentication/authorisation -- **Sanitise file paths** before file operations -- **Rate limit** expensive operations - -[Learn more about security →](/guides/advanced/security) - -## Next Steps - -**Application Lifecycle** - Understand startup, shutdown, and lifecycle hooks -[Learn More →](/concepts/lifecycle) - -**Go-Frontend Bridge** - Deep dive into how the bridge works -[Learn More →](/concepts/bridge) - -**Build System** - Understand how Wails builds your application -[Learn More →](/concepts/build-system) - -**Start Building** - Apply what you've learned in a tutorial -[Tutorials →](/tutorials/03-notes-vanilla) - ---- - -**Questions about architecture?** Ask in [Discord](https://discord.gg/JDdSxwjhGf) or check the [API reference](/reference/overview). diff --git a/docs/src/content/docs/concepts/bridge.mdx b/docs/src/content/docs/concepts/bridge.mdx deleted file mode 100644 index 7593d896a..000000000 --- a/docs/src/content/docs/concepts/bridge.mdx +++ /dev/null @@ -1,700 +0,0 @@ ---- -title: Go-Frontend Bridge -description: Deep dive into how Wails enables direct communication between Go and JavaScript -sidebar: - order: 3 ---- - -import { Tabs, TabItem } from "@astrojs/starlight/components"; - -## Direct Go-JavaScript Communication - -Wails provides a **direct, in-memory bridge** between Go and JavaScript, enabling seamless communication without HTTP overhead, process boundaries, or serialisation bottlenecks. - -## The Big Picture - -```d2 -direction: right - -Frontend: "Frontend (JavaScript)" { - UI: "React/Vue/Vanilla" { - shape: rectangle - style.fill: "#8B5CF6" - } - - Bindings: "Auto-Generated Bindings" { - shape: rectangle - style.fill: "#A78BFA" - } -} - -Bridge: "Wails Bridge" { - Encoder: "JSON Encoder" { - shape: rectangle - style.fill: "#10B981" - } - - Router: "Method Router" { - shape: diamond - style.fill: "#10B981" - } - - Decoder: "JSON Decoder" { - shape: rectangle - style.fill: "#10B981" - } - - TypeGen: "Type Generator" { - shape: rectangle - style.fill: "#10B981" - } -} - -Backend: "Backend (Go)" { - Services: "Your Services" { - shape: rectangle - style.fill: "#00ADD8" - } - - Registry: "Service Registry" { - shape: rectangle - style.fill: "#00ADD8" - } -} - -Frontend.UI -> Frontend.Bindings: "import { Method }" -Frontend.Bindings -> Bridge.Encoder: "Call Method('arg')" -Bridge.Encoder -> Bridge.Router: "Encode to JSON" -Bridge.Router -> Backend.Registry: "Find service" -Backend.Registry -> Backend.Services: "Invoke method" -Backend.Services -> Bridge.Decoder: "Return result" -Bridge.Decoder -> Frontend.Bindings: "Decode to JS" -Frontend.Bindings -> Frontend.UI: "Promise resolves" -Bridge.TypeGen -> Frontend.Bindings: "Generate types" -``` - -**Key insight:** No HTTP, no IPC, no process boundaries. Just **direct function calls** with **type safety**. - -## How It Works: Step by Step - -### 1. Service Registration (Startup) - -When your application starts, Wails scans your services: - -```go -type GreetService struct { - prefix string -} - -func (g *GreetService) Greet(name string) string { - return g.prefix + name + "!" -} - -func (g *GreetService) Add(a, b int) int { - return a + b -} - -// Register service -app := application.New(application.Options{ - Services: []application.Service{ - application.NewService(&GreetService{prefix: "Hello, "}), - }, -}) -``` - -**What Wails does:** -1. **Scans the struct** for exported methods -2. **Extracts type information** (parameters, return types) -3. **Builds a registry** mapping method names to functions -4. **Generates TypeScript bindings** with full type definitions - -### 2. Binding Generation (Build Time) - -Wails generates TypeScript bindings automatically: - -```typescript -// Auto-generated: frontend/bindings/GreetService.ts -export function Greet(name: string): Promise -export function Add(a: number, b: number): Promise -``` - -**Type mapping:** - -| Go Type | TypeScript Type | -|---------|-----------------| -| `string` | `string` | -| `int`, `int32`, `int64` | `number` | -| `float32`, `float64` | `number` | -| `bool` | `boolean` | -| `[]T` | `T[]` | -| `map[string]T` | `Record` | -| `struct` | `interface` | -| `time.Time` | `Date` | -| `error` | Exception (thrown) | - -### 3. Frontend Call (Runtime) - -Developer calls the Go method from JavaScript: - -```javascript -import { Greet, Add } from './bindings/GreetService' - -// Call Go from JavaScript -const greeting = await Greet("World") -console.log(greeting) // "Hello, World!" - -const sum = await Add(5, 3) -console.log(sum) // 8 -``` - -**What happens:** -1. **Binding function called** - `Greet("World")` -2. **Message created** - `{ service: "GreetService", method: "Greet", args: ["World"] }` -3. **Sent to bridge** - Via WebView's JavaScript bridge -4. **Promise returned** - Awaits response - -### 4. Bridge Processing (Runtime) - -The bridge receives the message and processes it: - -```d2 -direction: down - -Receive: "Receive Message" { - shape: rectangle - style.fill: "#10B981" -} - -Parse: "Parse JSON" { - shape: rectangle -} - -Validate: "Validate" { - Check: "Service exists?" { - shape: diamond - } - - CheckMethod: "Method exists?" { - shape: diamond - } - - CheckTypes: "Types correct?" { - shape: diamond - } -} - -Invoke: "Invoke Go Method" { - shape: rectangle - style.fill: "#00ADD8" -} - -Encode: "Encode Result" { - shape: rectangle -} - -Send: "Send Response" { - shape: rectangle - style.fill: "#10B981" -} - -Error: "Send Error" { - shape: rectangle - style.fill: "#EF4444" -} - -Receive -> Parse -Parse -> Validate.Check -Validate.Check -> Validate.CheckMethod: "Yes" -Validate.Check -> Error: "No" -Validate.CheckMethod -> Validate.CheckTypes: "Yes" -Validate.CheckMethod -> Error: "No" -Validate.CheckTypes -> Invoke: "Yes" -Validate.CheckTypes -> Error: "No" -Invoke -> Encode: "Success" -Invoke -> Error: "Error" -Encode -> Send -``` - -**Security:** Only registered services and exported methods are callable. - -### 5. Go Execution (Runtime) - -The Go method executes: - -```go -func (g *GreetService) Greet(name string) string { - // This runs in Go - return g.prefix + name + "!" -} -``` - -**Execution context:** -- Runs in a **goroutine** (non-blocking) -- Has access to **all Go features** (file system, network, databases) -- Can call **other Go code** freely -- Returns result or error - -### 6. Response (Runtime) - -Result is sent back to JavaScript: - -```javascript -// Promise resolves with result -const greeting = await Greet("World") -// greeting = "Hello, World!" -``` - -**Error handling:** - -```go -func (g *GreetService) Divide(a, b float64) (float64, error) { - if b == 0 { - return 0, errors.New("division by zero") - } - return a / b, nil -} -``` - -```javascript -try { - const result = await Divide(10, 0) -} catch (error) { - console.error("Go error:", error) // "division by zero" -} -``` - -## Performance Characteristics - -### Speed - -**Typical call overhead:** <1ms - -``` -Frontend Call → Bridge → Go Execution → Bridge → Frontend Response - ↓ ↓ ↓ ↓ ↓ - <0.1ms <0.1ms [varies] <0.1ms <0.1ms -``` - -**Compared to alternatives:** -- **HTTP/REST:** 5-50ms (network stack, serialisation) -- **IPC:** 1-10ms (process boundaries, marshalling) -- **Wails Bridge:** <1ms (in-memory, direct call) - -### Memory - -**Per-call overhead:** ~1KB (message buffer) - -**Zero-copy optimisation:** Large data (>1MB) uses shared memory where possible. - -### Concurrency - -**Calls are concurrent:** -- Each call runs in its own goroutine -- Multiple calls can execute simultaneously -- No blocking between calls - -```javascript -// These run concurrently -const [result1, result2, result3] = await Promise.all([ - SlowOperation1(), - SlowOperation2(), - SlowOperation3(), -]) -``` - -## Type System - -### Supported Types - -#### Primitives - -```go -// Go -func Example( - s string, - i int, - f float64, - b bool, -) (string, int, float64, bool) { - return s, i, f, b -} -``` - -```typescript -// TypeScript (auto-generated) -function Example( - s: string, - i: number, - f: number, - b: boolean, -): Promise<[string, number, number, boolean]> -``` - -#### Slices and Arrays - -```go -// Go -func Sum(numbers []int) int { - total := 0 - for _, n := range numbers { - total += n - } - return total -} -``` - -```typescript -// TypeScript -function Sum(numbers: number[]): Promise - -// Usage -const total = await Sum([1, 2, 3, 4, 5]) // 15 -``` - -#### Maps - -```go -// Go -func GetConfig() map[string]interface{} { - return map[string]interface{}{ - "theme": "dark", - "fontSize": 14, - "enabled": true, - } -} -``` - -```typescript -// TypeScript -function GetConfig(): Promise> - -// Usage -const config = await GetConfig() -console.log(config.theme) // "dark" -``` - -#### Structs - -```go -// Go -type User struct { - ID int `json:"id"` - Name string `json:"name"` - Email string `json:"email"` -} - -func GetUser(id int) (*User, error) { - return &User{ - ID: id, - Name: "Alice", - Email: "alice@example.com", - }, nil -} -``` - -```typescript -// TypeScript (auto-generated) -interface User { - id: number - name: string - email: string -} - -function GetUser(id: number): Promise - -// Usage -const user = await GetUser(1) -console.log(user.name) // "Alice" -``` - -**JSON tags:** Use `json:` tags to control field names in TypeScript. - -#### Time - -```go -// Go -func GetTimestamp() time.Time { - return time.Now() -} -``` - -```typescript -// TypeScript -function GetTimestamp(): Promise - -// Usage -const timestamp = await GetTimestamp() -console.log(timestamp.toISOString()) -``` - -#### Errors - -```go -// Go -func Validate(input string) error { - if input == "" { - return errors.New("input cannot be empty") - } - return nil -} -``` - -```typescript -// TypeScript -function Validate(input: string): Promise - -// Usage -try { - await Validate("") -} catch (error) { - console.error(error) // "input cannot be empty" -} -``` - -### Unsupported Types - -These types **cannot** be passed across the bridge: - -- **Channels** (`chan T`) -- **Functions** (`func()`) -- **Interfaces** (except `interface{}` / `any`) -- **Pointers** (except to structs) -- **Unexported fields** (lowercase) - -**Workaround:** Use IDs or handles: - -```go -// ❌ Can't pass file handle -func OpenFile(path string) (*os.File, error) { - return os.Open(path) -} - -// ✅ Return file ID instead -var files = make(map[string]*os.File) - -func OpenFile(path string) (string, error) { - file, err := os.Open(path) - if err != nil { - return "", err - } - id := generateID() - files[id] = file - return id, nil -} - -func ReadFile(id string) ([]byte, error) { - file := files[id] - return io.ReadAll(file) -} - -func CloseFile(id string) error { - file := files[id] - delete(files, id) - return file.Close() -} -``` - -## Advanced Patterns - -### Context Passing - -Services can access the call context: - -```go -type UserService struct{} - -func (s *UserService) GetCurrentUser(ctx context.Context) (*User, error) { - // Access window that made the call - window := application.ContextWindow(ctx) - - // Access application - app := application.ContextApplication(ctx) - - // Your logic - return getCurrentUser(), nil -} -``` - -**Context provides:** -- Window that made the call -- Application instance -- Request metadata - -### Streaming Data - -For large data, use events instead of return values: - -```go -func ProcessLargeFile(path string) error { - file, err := os.Open(path) - if err != nil { - return err - } - defer file.Close() - - scanner := bufio.NewScanner(file) - lineNum := 0 - - for scanner.Scan() { - lineNum++ - // Emit progress events - app.Event.Emit("file-progress", map[string]interface{}{ - "line": lineNum, - "text": scanner.Text(), - }) - } - - return scanner.Err() -} -``` - -```javascript -import { On } from '@wailsio/runtime' -import { ProcessLargeFile } from './bindings/FileService' - -// Listen for progress -On('file-progress', (data) => { - console.log(`Line ${data.line}: ${data.text}`) -}) - -// Start processing -await ProcessLargeFile('/path/to/large/file.txt') -``` - -### Cancellation - -Use context for cancellable operations: - -```go -func LongRunningTask(ctx context.Context) error { - for i := 0; i < 1000; i++ { - // Check if cancelled - select { - case <-ctx.Done(): - return ctx.Err() - default: - // Continue work - time.Sleep(100 * time.Millisecond) - } - } - return nil -} -``` - -**Note:** Context cancellation on frontend disconnect is automatic. - -### Batch Operations - -Reduce bridge overhead by batching: - -```go -// ❌ Inefficient: N bridge calls -for _, item := range items { - await ProcessItem(item) -} - -// ✅ Efficient: 1 bridge call -await ProcessItems(items) -``` - -```go -func ProcessItems(items []Item) ([]Result, error) { - results := make([]Result, len(items)) - for i, item := range items { - results[i] = processItem(item) - } - return results, nil -} -``` - -## Debugging the Bridge - -### Enable Debug Logging - -```go -app := application.New(application.Options{ - Name: "My App", - Logger: application.NewDefaultLogger(), - LogLevel: logger.DEBUG, -}) -``` - -**Output shows:** -- Method calls -- Parameters -- Return values -- Errors -- Timing information - -### Inspect Generated Bindings - -Check `frontend/bindings/` to see generated TypeScript: - -```typescript -// frontend/bindings/MyService.ts -export function MyMethod(arg: string): Promise { - return window.wails.Call('MyService.MyMethod', arg) -} -``` - -### Test Services Directly - -Test Go services without the frontend: - -```go -func TestGreetService(t *testing.T) { - service := &GreetService{prefix: "Hello, "} - result := service.Greet("Test") - if result != "Hello, Test!" { - t.Errorf("Expected 'Hello, Test!', got '%s'", result) - } -} -``` - -## Performance Tips - -### ✅ Do - -- **Batch operations** - Reduce bridge calls -- **Use events for streaming** - Don't return large arrays -- **Keep methods fast** - <100ms ideal -- **Use goroutines** - For long operations -- **Cache on Go side** - Avoid repeated calculations - -### ❌ Don't - -- **Don't make excessive calls** - Batch when possible -- **Don't return huge data** - Use pagination or streaming -- **Don't block** - Use goroutines for long operations -- **Don't pass complex types** - Keep it simple -- **Don't ignore errors** - Always handle them - -## Security - -The bridge is secure by default: - -1. **Whitelist only** - Only registered services callable -2. **Type validation** - Arguments checked against Go types -3. **No eval()** - Frontend can't execute arbitrary Go code -4. **No reflection abuse** - Only exported methods accessible - -**Best practices:** -- **Validate input** in Go (don't trust frontend) -- **Use context** for authentication/authorisation -- **Rate limit** expensive operations -- **Sanitise** file paths and user input - -## Next Steps - -**Build System** - Learn how Wails builds and bundles your application -[Learn More →](/concepts/build-system) - -**Services** - Deep dive into the service system -[Learn More →](/features/bindings/services) - -**Events** - Use events for pub/sub communication -[Learn More →](/features/events/system) - ---- - -**Questions about the bridge?** Ask in [Discord](https://discord.gg/JDdSxwjhGf) or check the [binding examples](https://github.com/wailsapp/wails/tree/v3-alpha/v3/examples/binding). diff --git a/docs/src/content/docs/concepts/build-system.mdx b/docs/src/content/docs/concepts/build-system.mdx deleted file mode 100644 index f9de52bc5..000000000 --- a/docs/src/content/docs/concepts/build-system.mdx +++ /dev/null @@ -1,700 +0,0 @@ ---- -title: Build System -description: Understanding how Wails builds and packages your application -sidebar: - order: 4 ---- - -import { Tabs, TabItem } from "@astrojs/starlight/components"; - -## Unified Build System - -Wails provides a **unified build system** that compiles Go code, bundles frontend assets, embeds everything into a single executable, and handles platform-specific builds—all with one command. - -```bash -wails3 build -``` - -**Output:** Native executable with everything embedded. - -## Build Process Overview - -{/* -TODO: Fix D2 diagram generation or embed as image. -The previous D2 code block was causing MDX parsing errors in the build pipeline. -*/} - -**[Build Process Diagram Placeholder]** - - -## Build Phases - -### 1. Analysis Phase - -Wails scans your Go code to understand your services: - -```go -type GreetService struct { - prefix string -} - -func (g *GreetService) Greet(name string) string { - return g.prefix + name + "!" -} -``` - -**What Wails extracts:** -- Service name: `GreetService` -- Method name: `Greet` -- Parameter types: `string` -- Return types: `string` - -**Used for:** Generating TypeScript bindings - -### 2. Generation Phase - -#### TypeScript Bindings - -Wails generates type-safe bindings: - -```typescript -// Auto-generated: frontend/bindings/GreetService.ts -export function Greet(name: string): Promise { - return window.wails.Call('GreetService.Greet', name) -} -``` - -**Benefits:** -- Full type safety -- IDE autocomplete -- Compile-time errors -- JSDoc comments - -#### Frontend Build - -Your frontend bundler runs (Vite, webpack, etc.): - -```bash -# Vite example -vite build --outDir dist -``` - -**What happens:** -- JavaScript/TypeScript compiled -- CSS processed and minified -- Assets optimised -- Source maps generated (dev only) -- Output to `frontend/dist/` - -### 3. Compilation Phase - -#### Go Compilation - -Go code is compiled with optimisations: - -```bash -go build -ldflags="-s -w" -o myapp.exe -``` - -**Flags:** -- `-s`: Strip symbol table -- `-w`: Strip DWARF debugging info -- Result: Smaller binary (~30% reduction) - -**Platform-specific:** -- Windows: `.exe` with icon embedded -- macOS: `.app` bundle structure -- Linux: ELF binary - -#### Asset Embedding - -Frontend assets are embedded into the Go binary: - -```go -//go:embed frontend/dist -var assets embed.FS -``` - -**Result:** Single executable with everything inside. - -### 4. Output - -**Single native binary:** -- Windows: `myapp.exe` (~15MB) -- macOS: `myapp.app` (~15MB) -- Linux: `myapp` (~15MB) - -**No dependencies** (except system WebView). - -## Development vs Production - - - - **Optimised for speed:** - - ```bash - wails3 dev - ``` - - **What happens:** - 1. Starts frontend dev server (Vite on port 5173) - 2. Compiles Go without optimisations - 3. Launches app pointing to dev server - 4. Enables hot reload - 5. Includes source maps - - **Characteristics:** - - **Fast rebuilds** (<1s for frontend changes) - - **No asset embedding** (served from dev server) - - **Debug symbols** included - - **Source maps** enabled - - **Verbose logging** - - **File size:** Larger (~50MB with debug symbols) - - - - **Optimised for size and performance:** - - ```bash - wails3 build - ``` - - **What happens:** - 1. Builds frontend for production (minified) - 2. Compiles Go with optimisations - 3. Strips debug symbols - 4. Embeds assets - 5. Creates single binary - - **Characteristics:** - - **Optimised code** (minified, tree-shaken) - - **Assets embedded** (no external files) - - **Debug symbols stripped** - - **No source maps** - - **Minimal logging** - - **File size:** Smaller (~15MB) - - - -## Build Commands - -### Basic Build - -```bash -wails3 build -``` - -**Output:** `build/bin/myapp[.exe]` - -### Build for Specific Platform - -```bash -# Build for Windows (from any OS) -wails3 build -platform windows/amd64 - -# Build for macOS -wails3 build -platform darwin/amd64 -wails3 build -platform darwin/arm64 - -# Build for Linux -wails3 build -platform linux/amd64 -``` - -**Cross-compilation:** Build for any platform from any platform. - -### Build with Options - -```bash -# Custom output directory -wails3 build -o ./dist/myapp - -# Skip frontend build (use existing) -wails3 build -skipbindings - -# Clean build (remove cache) -wails3 build -clean - -# Verbose output -wails3 build -v -``` - -### Build Modes - -```bash -# Debug build (includes symbols) -wails3 build -debug - -# Production build (default, optimised) -wails3 build - -# Development build (fast, unoptimised) -wails3 build -devbuild -``` - -## Build Configuration - -### Taskfile.yml - -Wails uses [Taskfile](https://taskfile.dev/) for build configuration: - -```yaml -# Taskfile.yml -version: '3' - -tasks: - build: - desc: Build the application - cmds: - - wails3 build - - build:windows: - desc: Build for Windows - cmds: - - wails3 build -platform windows/amd64 - - build:macos: - desc: Build for macOS (Universal) - cmds: - - wails3 build -platform darwin/amd64 - - wails3 build -platform darwin/arm64 - - lipo -create -output build/bin/myapp.app build/bin/myapp-amd64.app build/bin/myapp-arm64.app - - build:linux: - desc: Build for Linux - cmds: - - wails3 build -platform linux/amd64 -``` - -**Run tasks:** - -```bash -task build:windows -task build:macos -task build:linux -``` - -### Build Options File - -Create `build/build.json` for persistent configuration: - -```json -{ - "name": "My Application", - "version": "1.0.0", - "author": "Your Name", - "description": "Application description", - "icon": "build/appicon.png", - "outputFilename": "myapp", - "platforms": ["windows/amd64", "darwin/amd64", "linux/amd64"], - "frontend": { - "dir": "./frontend", - "install": "npm install", - "build": "npm run build", - "dev": "npm run dev" - }, - "go": { - "ldflags": "-s -w -X main.version={{.Version}}" - } -} -``` - -## Asset Embedding - -### How It Works - -Wails uses Go's `embed` package: - -```go -package main - -import ( - "embed" - "github.com/wailsapp/wails/v3/pkg/application" -) - -//go:embed frontend/dist -var assets embed.FS - -func main() { - app := application.New(application.Options{ - Name: "My App", - Assets: application.AssetOptions{ - Handler: application.AssetFileServerFS(assets), - }, - }) - - app.Window.New() - app.Run() -} -``` - -**At build time:** -1. Frontend built to `frontend/dist/` -2. `//go:embed` directive includes files -3. Files compiled into binary -4. Binary contains everything - -**At runtime:** -1. App starts -2. Assets served from memory -3. No disk I/O for assets -4. Fast loading - -### Custom Assets - -Embed additional files: - -```go -//go:embed frontend/dist -var frontendAssets embed.FS - -//go:embed data/*.json -var dataAssets embed.FS - -//go:embed templates/*.html -var templateAssets embed.FS -``` - -## Build Optimisations - -### Frontend Optimisations - -**Vite (default):** - -```javascript -// vite.config.js -export default { - build: { - minify: 'terser', - terserOptions: { - compress: { - drop_console: true, // Remove console.log - drop_debugger: true, - }, - }, - rollupOptions: { - output: { - manualChunks: { - vendor: ['react', 'react-dom'], // Separate vendor bundle - }, - }, - }, - }, -} -``` - -**Results:** -- JavaScript minified (~70% reduction) -- CSS minified (~60% reduction) -- Images optimised -- Tree-shaking applied - -### Go Optimisations - -**Compiler flags:** - -```bash --ldflags="-s -w" -``` - -- `-s`: Strip symbol table (~10% reduction) -- `-w`: Strip DWARF debug info (~20% reduction) - -**Additional optimisations:** - -```bash --ldflags="-s -w -X main.version=1.0.0" -``` - -- `-X`: Set variable values at build time -- Useful for version numbers, build dates - -### Binary Compression - -**UPX (optional):** - -```bash -# After building -upx --best build/bin/myapp.exe -``` - -**Results:** -- ~50% size reduction -- Slightly slower startup (~100ms) -- Not recommended for macOS (code signing issues) - -## Platform-Specific Builds - -### Windows - -**Output:** `myapp.exe` - -**Includes:** -- Application icon -- Version information -- Manifest (UAC settings) - -**Icon:** - -```bash -# Specify icon -wails3 build -icon build/appicon.png -``` - -Wails converts PNG to `.ico` automatically. - -**Manifest:** - -```xml - - - - - - - - - - - - -``` - -### macOS - -**Output:** `myapp.app` (application bundle) - -**Structure:** - -``` -myapp.app/ -├── Contents/ -│ ├── Info.plist # App metadata -│ ├── MacOS/ -│ │ └── myapp # Binary -│ ├── Resources/ -│ │ └── icon.icns # Icon -│ └── _CodeSignature/ # Code signature (if signed) -``` - -**Info.plist:** - -```xml - - - - - CFBundleName - My App - CFBundleIdentifier - com.example.myapp - CFBundleVersion - 1.0.0 - - -``` - -**Universal Binary:** - -```bash -# Build for both architectures -wails3 build -platform darwin/amd64 -wails3 build -platform darwin/arm64 - -# Combine into universal binary -lipo -create -output myapp-universal \ - build/bin/myapp-amd64 \ - build/bin/myapp-arm64 -``` - -### Linux - -**Output:** `myapp` (ELF binary) - -**Dependencies:** -- GTK3 -- WebKitGTK - -**Desktop file:** - -```ini -# myapp.desktop -[Desktop Entry] -Name=My App -Exec=/usr/bin/myapp -Icon=myapp -Type=Application -Categories=Utility; -``` - -**Installation:** - -```bash -# Copy binary -sudo cp myapp /usr/bin/ - -# Copy desktop file -sudo cp myapp.desktop /usr/share/applications/ - -# Copy icon -sudo cp icon.png /usr/share/icons/hicolor/256x256/apps/myapp.png -``` - -## Build Performance - -### Typical Build Times - -| Phase | Time | Notes | -|-------|------|-------| -| Analysis | <1s | Go code scanning | -| Binding Generation | <1s | TypeScript generation | -| Frontend Build | 5-30s | Depends on project size | -| Go Compilation | 2-10s | Depends on code size | -| Asset Embedding | <1s | Embedding frontend | -| **Total** | **10-45s** | First build | -| **Incremental** | **5-15s** | Subsequent builds | - -### Speeding Up Builds - -**1. Use build cache:** - -```bash -# Go build cache is automatic -# Frontend cache (Vite) -npm run build # Uses cache by default -``` - -**2. Skip unchanged steps:** - -```bash -# Skip frontend if unchanged -wails3 build -skipbindings -``` - -**3. Parallel builds:** - -```bash -# Build multiple platforms in parallel -wails3 build -platform windows/amd64 & -wails3 build -platform darwin/amd64 & -wails3 build -platform linux/amd64 & -wait -``` - -**4. Use faster tools:** - -```bash -# Use esbuild instead of webpack -# (Vite uses esbuild by default) -``` - -## Troubleshooting - -### Build Fails - -**Symptom:** `wails3 build` exits with error - -**Common causes:** - -1. **Go compilation error** - ```bash - # Check Go code compiles - go build - ``` - -2. **Frontend build error** - ```bash - # Check frontend builds - cd frontend - npm run build - ``` - -3. **Missing dependencies** - ```bash - # Install dependencies - npm install - go mod download - ``` - -### Binary Too Large - -**Symptom:** Binary is >50MB - -**Solutions:** - -1. **Strip debug symbols** (should be automatic) - ```bash - wails3 build # Already includes -ldflags="-s -w" - ``` - -2. **Check embedded assets** - ```bash - # Remove unnecessary files from frontend/dist/ - # Check for large images, videos, etc. - ``` - -3. **Use UPX compression** - ```bash - upx --best build/bin/myapp.exe - ``` - -### Slow Builds - -**Symptom:** Builds take >1 minute - -**Solutions:** - -1. **Use build cache** - - Go cache is automatic - - Frontend cache (Vite) is automatic - -2. **Skip unchanged steps** - ```bash - wails3 build -skipbindings - ``` - -3. **Optimise frontend build** - ```javascript - // vite.config.js - export default { - build: { - minify: 'esbuild', // Faster than terser - }, - } - ``` - -## Best Practices - -### ✅ Do - -- **Use `wails3 dev` during development** - Fast iteration -- **Use `wails3 build` for releases** - Optimised output -- **Version your builds** - Use `-ldflags` to embed version -- **Test builds on target platforms** - Cross-compilation isn't perfect -- **Keep frontend builds fast** - Optimise bundler config -- **Use build cache** - Speeds up subsequent builds - -### ❌ Don't - -- **Don't commit `build/` directory** - Add to `.gitignore` -- **Don't skip testing builds** - Always test before release -- **Don't embed unnecessary assets** - Keep binaries small -- **Don't use debug builds for production** - Use optimised builds -- **Don't forget code signing** - Required for distribution - -## Next Steps - -**Building Applications** - Detailed guide to building and packaging -[Learn More →](/guides/building) - -**Cross-Platform Builds** - Build for all platforms from one machine -[Learn More →](/guides/cross-platform) - -**Creating Installers** - Create installers for end users -[Learn More →](/guides/installers) - ---- - -**Questions about building?** Ask in [Discord](https://discord.gg/JDdSxwjhGf) or check the [build examples](https://github.com/wailsapp/wails/tree/v3-alpha/v3/examples/build). diff --git a/docs/src/content/docs/concepts/lifecycle.mdx b/docs/src/content/docs/concepts/lifecycle.mdx deleted file mode 100644 index c7f6c0805..000000000 --- a/docs/src/content/docs/concepts/lifecycle.mdx +++ /dev/null @@ -1,807 +0,0 @@ ---- -title: Application Lifecycle -description: Understanding the Wails application lifecycle from startup to shutdown -sidebar: - order: 2 ---- - -import { Tabs, TabItem } from "@astrojs/starlight/components"; - -## Understanding Application Lifecycle - -Desktop applications have a lifecycle from startup to shutdown. Wails v3 provides **services**, **events**, and **hooks** to manage this lifecycle effectively. - -## The Lifecycle Stages - -```d2 -direction: down - -Start: "Application Start" { - shape: oval - style.fill: "#10B981" -} - -Init: "Initialisation" { - Parse: "Parse Options" { - shape: rectangle - } - Register: "Register Services" { - shape: rectangle - } - Setup: "Setup Runtime" { - shape: rectangle - } -} - -AppRun: "app.Run()" { - shape: rectangle - style.fill: "#3B82F6" -} - -ServiceStartup: "Service Startup" { - shape: rectangle - style.fill: "#8B5CF6" -} - -EventLoop: "Event Loop" { - Process: "Process Events" { - shape: rectangle - } - Handle: "Handle Messages" { - shape: rectangle - } - Update: "Update UI" { - shape: rectangle - } -} - -QuitSignal: "Quit Signal" { - shape: diamond - style.fill: "#F59E0B" -} - -ShouldQuit: "ShouldQuit Check" { - shape: rectangle - style.fill: "#3B82F6" -} - -OnShutdown: "OnShutdown Callbacks" { - shape: rectangle - style.fill: "#3B82F6" -} - -ServiceShutdown: "Service Shutdown" { - shape: rectangle - style.fill: "#8B5CF6" -} - -Cleanup: "Cleanup" { - Close: "Close Windows" { - shape: rectangle - } - Release: "Release Resources" { - shape: rectangle - } -} - -End: "Application End" { - shape: oval - style.fill: "#EF4444" -} - -Start -> Init.Parse -Init.Parse -> Init.Register -Init.Register -> Init.Setup -Init.Setup -> AppRun -AppRun -> ServiceStartup -ServiceStartup -> EventLoop.Process -EventLoop.Process -> EventLoop.Handle -EventLoop.Handle -> EventLoop.Update -EventLoop.Update -> EventLoop.Process: "Loop" -EventLoop.Process -> QuitSignal: "User quits" -QuitSignal -> ShouldQuit: "Check allowed?" -ShouldQuit -> EventLoop.Process: "Denied" -ShouldQuit -> OnShutdown: "Allowed" -OnShutdown -> ServiceShutdown -ServiceShutdown -> Cleanup.Close -Cleanup.Close -> Cleanup.Release -Cleanup.Release -> End -``` - -### 1. Application Creation - -Create your application with `application.New()`: - -```go -app := application.New(application.Options{ - Name: "My App", - Description: "An application built with Wails", - Services: []application.Service{ - application.NewService(&MyService{}), - }, - Assets: application.AssetOptions{ - Handler: application.BundledAssetFileServer(assets), - }, -}) -``` - -**What happens:** -1. Options are parsed and validated -2. Services are registered (but not started yet) -3. Asset server is configured -4. Runtime is set up - -### 2. Running the Application - -Call `app.Run()` to start the application: - -```go -err := app.Run() // Blocks until quit -if err != nil { - log.Fatal(err) -} -``` - -**What happens:** -1. Services are started in registration order -2. Event listeners are activated -3. Windows can be created -4. Event loop begins - -### 3. Event Loop - -The application enters the event loop where it spends most of its time: - -- OS events processed (mouse, keyboard, window events) -- Go-to-JS messages handled -- JS-to-Go calls executed -- UI updates rendered - -### 4. Shutdown - -When the application quits: - -1. `ShouldQuit` callback is checked (if set) -2. `OnShutdown` callbacks are executed -3. Services are shut down in reverse order -4. Windows are closed -5. Resources are released - -## Services Lifecycle - -Services are the primary way to manage lifecycle in Wails v3. They provide startup and shutdown hooks through interfaces. For complete documentation on services, see the [Services guide](/features/bindings/services). - -### Creating a Service - -```go -type MyService struct { - db *sql.DB -} - -// ServiceStartup is called when the application starts -func (s *MyService) ServiceStartup(ctx context.Context, options application.ServiceOptions) error { - var err error - s.db, err = sql.Open("sqlite3", "app.db") - if err != nil { - return err // Startup aborts if error returned - } - - // Run migrations - if err := s.runMigrations(); err != nil { - return err - } - - return nil -} - -// ServiceShutdown is called when the application shuts down -func (s *MyService) ServiceShutdown() error { - if s.db != nil { - return s.db.Close() - } - return nil -} -``` - -### Registering Services - -```go -app := application.New(application.Options{ - Services: []application.Service{ - application.NewService(&MyService{}), - application.NewService(&AnotherService{}), - }, -}) -``` - -**Key points:** -- Services start in registration order -- Services shut down in **reverse** registration order -- If a service's `ServiceStartup` returns an error, the application aborts -- The `ctx` passed to `ServiceStartup` is cancelled when shutdown begins - -### Using the Application Context - -The context passed to `ServiceStartup` is valid for the application's lifetime: - -```go -func (s *MyService) ServiceStartup(ctx context.Context, options application.ServiceOptions) error { - // Start a background task that respects shutdown - go func() { - ticker := time.NewTicker(5 * time.Minute) - defer ticker.Stop() - - for { - select { - case <-ticker.C: - s.performBackgroundSync() - case <-ctx.Done(): - // Application is shutting down - return - } - } - }() - - return nil -} -``` - -You can also access the context from the application instance: - -```go -app := application.Get() -ctx := app.Context() -``` - -## Application-Level Hooks - -These are convenience callbacks in `application.Options` that let you hook into the application lifecycle without creating a full service. They're useful for simple cleanup tasks, quit confirmation, or when you need to run code at specific points in the shutdown sequence. - -For more complex lifecycle management with startup logic, dependency injection, or stateful resources, use [Services](#services-lifecycle) instead. - -### ShouldQuit - -The `ShouldQuit` callback is called whenever a quit is requested—whether by the user closing the last window, pressing Cmd+Q (macOS) / Alt+F4 (Windows), or calling `app.Quit()` programmatically. - -**Return value:** -- Return `true` to allow the quit to proceed (application will shut down) -- Return `false` to cancel the quit (application continues running) - -This is your opportunity to intercept quit requests and optionally prevent them, for example to prompt the user about unsaved changes: - -```go -app := application.New(application.Options{ - ShouldQuit: func() bool { - if !hasUnsavedChanges() { - return true // No unsaved changes, allow quit - } - - // Prompt the user - result, _ := application.QuestionDialog(). - SetTitle("Unsaved Changes"). - SetMessage("You have unsaved changes. Quit anyway?"). - AddButton("Quit", "quit"). - AddButton("Cancel", "cancel"). - Show() - - // Only quit if user clicked "Quit" - return result == "quit" - }, -}) -``` - -If `ShouldQuit` is not set, the application will quit immediately when requested. - -**When ShouldQuit is called:** -- User closes the last window (unless `DisableQuitOnLastWindowClosed` is set) -- User presses Cmd+Q on macOS -- User presses Alt+F4 on Windows (when focused on last window) -- Code calls `app.Quit()` - -**When ShouldQuit is NOT called:** -- The process is killed (SIGKILL, Task Manager force-quit) -- `os.Exit()` is called directly - -### OnShutdown - -The `OnShutdown` callback is called when the application is confirmed to be quitting (after `ShouldQuit` returns `true`, if set). Use this for cleanup tasks like saving state, closing database connections, or releasing resources. - -```go -app := application.New(application.Options{ - OnShutdown: func() { - // Save application state - saveState() - - // Close connections - cleanup() - }, -}) -``` - -You can also register additional shutdown callbacks programmatically at any time during the application's lifecycle: - -```go -app.OnShutdown(func() { - log.Println("Application shutting down...") -}) -``` - -Multiple callbacks are executed in the order they were registered. The shutdown process blocks until all callbacks complete. - -**Important:** Keep shutdown callbacks fast (under 1 second). The operating system may force-terminate applications that take too long to quit, which could interrupt your cleanup and cause data loss. - -### PostShutdown - -The `PostShutdown` callback is called after all shutdown tasks have completed, just before the process terminates. At this point, the application instance is no longer usable—windows are closed, services are shut down, and resources are released. - -This is primarily useful for: -- Final logging that must happen after all other cleanup -- Testing and debugging shutdown behaviour -- Platforms where `app.Run()` doesn't return (the callback ensures your code runs) - -```go -app := application.New(application.Options{ - PostShutdown: func() { - // Final logging - log.Println("Application terminated cleanly") - - // Flush any buffered logs - logger.Sync() - }, -}) -``` - -**Note:** Do not attempt to use application features (windows, dialogs, etc.) in `PostShutdown`—they are no longer available. - -## Event-Based Lifecycle - -Wails provides an event system that notifies you when things happen in your application—windows opening, the application starting, theme changes, and more. You can listen to these events to react to lifecycle changes without blocking or intercepting them. - -For window events, you can also use `RegisterHook` instead of `OnWindowEvent` to intercept and cancel actions—for example, preventing a window from closing. See [Window Hooks](#window-hooks-cancellable-events) below. - -For full documentation on the event system, see the [Events guide](/features/events/system). - -### Application Events - -Listen to application lifecycle events: - -```go -app.Event.OnApplicationEvent(events.Common.ApplicationStarted, func(event *application.ApplicationEvent) { - app.Logger.Info("Application has started!") -}) -``` - -Platform-specific events are also available: - -```go -// macOS -app.Event.OnApplicationEvent(events.Mac.ApplicationDidFinishLaunching, func(event *application.ApplicationEvent) { - // Handle macOS launch -}) - -app.Event.OnApplicationEvent(events.Mac.ApplicationWillTerminate, func(event *application.ApplicationEvent) { - // Handle macOS termination -}) - -// Windows -app.Event.OnApplicationEvent(events.Windows.ApplicationStarted, func(event *application.ApplicationEvent) { - // Handle Windows start -}) -``` - -### Window Events - -Listen to window lifecycle events: - -```go -window := app.Window.New() - -window.OnWindowEvent(events.Common.WindowFocus, func(e *application.WindowEvent) { - app.Logger.Info("Window gained focus") -}) - -window.OnWindowEvent(events.Common.WindowClosing, func(e *application.WindowEvent) { - app.Logger.Info("Window is closing") -}) -``` - -### Window Hooks (Cancellable Events) - -Use `RegisterHook` instead of `OnWindowEvent` when you need to **cancel** an event: - -```go -window := app.Window.New() - -var countdown = 3 - -window.RegisterHook(events.Common.WindowClosing, func(e *application.WindowEvent) { - countdown-- - if countdown > 0 { - app.Logger.Info("Not closing yet!", "remaining", countdown) - e.Cancel() // Prevent the window from closing - return - } - app.Logger.Info("Window closing now") -}) -``` - -**Difference between OnWindowEvent and RegisterHook:** -- `OnWindowEvent`: Notifies you when an event happens (cannot cancel) -- `RegisterHook`: Lets you intercept and potentially cancel the event - -## Window Lifecycle - -Windows have their own lifecycle, from creation through to destruction. Each window loads its frontend content independently and can be shown, hidden, or closed at any time. When a user attempts to close a window, you can intercept this with a `RegisterHook` to prompt for confirmation or hide the window instead of destroying it. - -For complete window documentation, see the [Windows guide](/features/windows/basics). - -```d2 -direction: down - -Create: "Create Window" { - shape: oval - style.fill: "#10B981" -} - -Load: "Load Frontend" { - shape: rectangle -} - -Show: "Show Window" { - shape: rectangle -} - -Active: "Window Active" { - Events: "Handle Events" { - shape: rectangle - } -} - -CloseRequest: "Close Request" { - shape: diamond - style.fill: "#F59E0B" -} - -Hook: "WindowClosing Hook" { - shape: rectangle - style.fill: "#3B82F6" -} - -Destroy: "Destroy Window" { - shape: rectangle -} - -End: "Window Closed" { - shape: oval - style.fill: "#EF4444" -} - -Create -> Load -Load -> Show -Show -> Active.Events -Active.Events -> Active.Events: "Loop" -Active.Events -> CloseRequest: "User closes" -CloseRequest -> Hook -Hook -> Active.Events: "Cancelled" -Hook -> Destroy: "Allowed" -Destroy -> End -``` - -### Creating Windows - -```go -window := app.Window.NewWithOptions(application.WebviewWindowOptions{ - Title: "My Window", - Width: 800, - Height: 600, -}) -``` - -### Preventing Window Close - -```go -window.RegisterHook(events.Common.WindowClosing, func(e *application.WindowEvent) { - if hasUnsavedChanges() { - // Show dialog - result, _ := application.QuestionDialog(). - SetTitle("Unsaved Changes"). - SetMessage("Save before closing?"). - AddButton("Save", "save"). - AddButton("Discard", "discard"). - AddButton("Cancel", "cancel"). - Show() - - switch result { - case "save": - saveChanges() - // Allow close - case "cancel": - e.Cancel() // Prevent close - } - // "discard" falls through and allows close - } -}) -``` - -### Hide Instead of Close - -A common pattern for system tray apps: - -```go -window.RegisterHook(events.Common.WindowClosing, func(e *application.WindowEvent) { - window.Hide() // Hide instead of destroy - e.Cancel() // Prevent actual close -}) -``` - -## Multi-Window Lifecycle - -With multiple windows: - -```go -mainWindow := app.Window.NewWithOptions(application.WebviewWindowOptions{ - Title: "Main Window", -}) - -settingsWindow := app.Window.NewWithOptions(application.WebviewWindowOptions{ - Title: "Settings", - Width: 400, - Height: 600, - Hidden: true, // Start hidden -}) -``` - -**Default behaviour varies by platform:** - -| Platform | Default when last window closes | -|----------|--------------------------------| -| macOS | App stays running (menu bar remains) | -| Windows | App quits | -| Linux | App quits | - -macOS follows native platform conventions where applications typically remain active in the menu bar even with no windows. Windows and Linux quit by default. - -**Make all platforms quit when last window closes:** - -```go -app := application.New(application.Options{ - Mac: application.MacOptions{ - ApplicationShouldTerminateAfterLastWindowClosed: true, - }, -}) -``` - -**Make all platforms stay running when last window closes:** - -This is useful for system tray applications or apps that should remain running in the background. - -```go -app := application.New(application.Options{ - Windows: application.WindowsOptions{ - DisableQuitOnLastWindowClosed: true, - }, - Linux: application.LinuxOptions{ - DisableQuitOnLastWindowClosed: true, - }, -}) -``` - -## Common Patterns - -### Pattern 1: Database Service - -```go -type DatabaseService struct { - db *sql.DB -} - -func (s *DatabaseService) ServiceStartup(ctx context.Context, options application.ServiceOptions) error { - var err error - s.db, err = sql.Open("sqlite3", "app.db") - if err != nil { - return fmt.Errorf("failed to open database: %w", err) - } - - if err := s.db.PingContext(ctx); err != nil { - return fmt.Errorf("failed to connect to database: %w", err) - } - - return nil -} - -func (s *DatabaseService) ServiceShutdown() error { - if s.db != nil { - return s.db.Close() - } - return nil -} - -// Exported methods are available to the frontend -func (s *DatabaseService) GetUsers() ([]User, error) { - // Query implementation -} -``` - -### Pattern 2: Configuration Service - -```go -type ConfigService struct { - config *Config - path string -} - -func (s *ConfigService) ServiceStartup(ctx context.Context, options application.ServiceOptions) error { - s.path = "config.json" - - data, err := os.ReadFile(s.path) - if err != nil { - if os.IsNotExist(err) { - s.config = &Config{} // Default config - return nil - } - return err - } - - return json.Unmarshal(data, &s.config) -} - -func (s *ConfigService) ServiceShutdown() error { - data, err := json.MarshalIndent(s.config, "", " ") - if err != nil { - return err - } - return os.WriteFile(s.path, data, 0644) -} -``` - -### Pattern 3: Background Worker - -```go -type WorkerService struct { - cancel context.CancelFunc -} - -func (s *WorkerService) ServiceStartup(ctx context.Context, options application.ServiceOptions) error { - workerCtx, cancel := context.WithCancel(ctx) - s.cancel = cancel - - go s.runWorker(workerCtx) - - return nil -} - -func (s *WorkerService) ServiceShutdown() error { - if s.cancel != nil { - s.cancel() - } - return nil -} - -func (s *WorkerService) runWorker(ctx context.Context) { - ticker := time.NewTicker(time.Minute) - defer ticker.Stop() - - for { - select { - case <-ticker.C: - s.doWork() - case <-ctx.Done(): - return - } - } -} -``` - -## Lifecycle Reference - -| Hook/Interface | When Called | Can Cancel? | Use For | -|----------------|-------------|-------------|---------| -| `ServiceStartup` | During `app.Run()`, before event loop | No (return error to abort) | Initialisation | -| `ServiceShutdown` | During shutdown, after `OnShutdown` | No | Cleanup | -| `OnShutdown` | When quit confirmed | No | Application cleanup | -| `ShouldQuit` | When quit requested | Yes (return false) | Confirm quit | -| `RegisterHook(WindowClosing)` | When window close requested | Yes (`e.Cancel()`) | Prevent window close | -| `OnWindowEvent` | When event occurs | No | React to events | -| `OnApplicationEvent` | When event occurs | No | React to events | - -## Platform Differences - -### macOS - -- **Application menu** persists even with no windows -- **Cmd+Q** triggers quit (goes through `ShouldQuit`) -- **Dock icon** remains unless hidden -- Use `ApplicationShouldTerminateAfterLastWindowClosed` to control quit behaviour - -### Windows - -- **No application menu** without a window -- **Alt+F4** closes window (can be prevented with `RegisterHook`) -- **System tray** can keep app running - -### Linux - -- **Behaviour varies** by desktop environment -- **Generally similar to Windows** - -## Debugging Lifecycle Issues - -### Problem: Application Won't Quit - -**Causes:** -1. `ShouldQuit` returning `false` -2. `OnShutdown` taking too long -3. Background goroutines not stopping - -**Solution:** - -```go -// 1. Check ShouldQuit logic -ShouldQuit: func() bool { - log.Println("ShouldQuit called") - return true -} - -// 2. Keep OnShutdown fast -OnShutdown: func() { - log.Println("OnShutdown started") - // Fast cleanup only - log.Println("OnShutdown finished") -} - -// 3. Use context for background tasks -func (s *MyService) ServiceStartup(ctx context.Context, options application.ServiceOptions) error { - go func() { - <-ctx.Done() - log.Println("Context cancelled, stopping background work") - }() - return nil -} -``` - -### Problem: Service Startup Fails - -**Solution:** Return descriptive errors: - -```go -func (s *MyService) ServiceStartup(ctx context.Context, options application.ServiceOptions) error { - if err := s.init(); err != nil { - return fmt.Errorf("failed to initialise: %w", err) - } - return nil -} -``` - -The error will be logged and the application will not start. - -## Best Practices - -### Do - -- **Use services for lifecycle management** - They provide proper startup/shutdown hooks -- **Keep shutdown fast** - Target under 1 second for all cleanup -- **Use context for cancellation** - Stop background tasks properly -- **Handle errors in startup** - Return errors to abort cleanly -- **Log lifecycle events** - Helps with debugging - -### Don't - -- **Don't block in service startup** - Keep initialisation fast (under 2 seconds) -- **Don't show dialogs in shutdown** - App is quitting, UI may not work -- **Don't ignore the context** - Always check `ctx.Done()` in goroutines -- **Don't leak resources** - Always implement `ServiceShutdown` - -## Next Steps - -**Services** - Learn more about the service system -[Learn More →](/features/services) - -**Events System** - Use events for communication -[Learn More →](/features/events/system) - -**Window Management** - Create and manage windows -[Learn More →](/features/windows/basics) - ---- - -**Questions about lifecycle?** Ask in [Discord](https://discord.gg/JDdSxwjhGf) or check the [examples](https://github.com/wailsapp/wails/tree/v3-alpha/v3/examples). diff --git a/docs/src/content/docs/concepts/manager-api.mdx b/docs/src/content/docs/concepts/manager-api.mdx deleted file mode 100644 index 26f6de918..000000000 --- a/docs/src/content/docs/concepts/manager-api.mdx +++ /dev/null @@ -1,266 +0,0 @@ ---- -title: Manager API -description: Organized API structure with focused manager interfaces -sidebar: - order: 2 ---- - -import { Tabs, TabItem } from "@astrojs/starlight/components"; - -The Wails v3 Manager API provides an organized and discoverable way to access application functionality through focused manager structs. This new API structure groups related methods together while maintaining full backward compatibility with the traditional App API. - -## Overview - -The Manager API organizes application functionality into eleven focused areas: - -- **`app.Window`** - Window creation, management, and callbacks -- **`app.ContextMenu`** - Context menu registration and management -- **`app.KeyBinding`** - Global key binding management -- **`app.Browser`** - Browser integration (opening URLs and files) -- **`app.Env`** - Environment information and system state -- **`app.Dialog`** - File and message dialog operations -- **`app.Event`** - Custom event handling and application events -- **`app.Menu`** - Application menu management -- **`app.Screen`** - Screen management and coordinate transformations -- **`app.Clipboard`** - Clipboard text operations -- **`app.SystemTray`** - System tray icon creation and management - -## Benefits - -- **Better discoverability** - IDE autocomplete shows organized API surface -- **Improved code organization** - Related methods grouped together -- **Enhanced maintainability** - Separation of concerns across managers -- **Future extensibility** - Easier to add new features to specific areas - -## Usage - -The Manager API provides organized access to all application functionality: - -```go -// Events and custom event handling -app.Event.Emit("custom", data) -app.Event.On("custom", func(e *CustomEvent) { ... }) - -// Window management -window, _ := app.Window.GetByName("main") -app.Window.OnCreate(func(window Window) { ... }) - -// Browser integration -app.Browser.OpenURL("https://wails.io") - -// Menu management -menu := app.Menu.New() -app.Menu.Set(menu) - -// System tray -systray := app.SystemTray.New() -``` - -## Manager Reference - -### Window Manager - -Manages window creation, retrieval, and lifecycle callbacks. - -```go -// Create windows -window := app.Window.New() -window := app.Window.NewWithOptions(options) -current := app.Window.Current() - -// Find windows -window, exists := app.Window.GetByName("main") -windows := app.Window.GetAll() - -// Window callbacks -app.Window.OnCreate(func(window Window) { - // Handle window creation -}) -``` - -### Event Manager - -Handles custom events and application event listening. - -```go -// Custom events -app.Event.Emit("userAction", data) -cancelFunc := app.Event.On("userAction", func(e *CustomEvent) { - // Handle event -}) -app.Event.Off("userAction") -app.Event.Reset() // Remove all listeners - -// Application events -app.Event.OnApplicationEvent(events.Common.ThemeChanged, func(e *ApplicationEvent) { - // Handle system theme change -}) -``` - -### Browser Manager - -Provides browser integration for opening URLs and files. - -```go -// Open URLs and files in default browser -err := app.Browser.OpenURL("https://wails.io") -err := app.Browser.OpenFile("/path/to/document.pdf") -``` - -### Environment Manager - -Access to system environment information. - -```go -// Get environment info -env := app.Env.Info() -fmt.Printf("OS: %s, Arch: %s\n", env.OS, env.Arch) - -// Check system theme -if app.Env.IsDarkMode() { - // Dark mode is active -} - -// Open file manager -err := app.Env.OpenFileManager("/path/to/folder", false) -``` - -### Dialog Manager - -Organized access to file and message dialogs. - -```go -// File dialogs -result, err := app.Dialog.OpenFile(). - AddFilter("Text Files", "*.txt"). - PromptForSingleSelection() - -result, err = app.Dialog.SaveFile(). - SetDefaultFilename("document.txt"). - PromptForSingleSelection() - -// Message dialogs -app.Dialog.Info(). - SetTitle("Information"). - SetMessage("Operation completed successfully"). - Show() - -app.Dialog.Error(). - SetTitle("Error"). - SetMessage("An error occurred"). - Show() -``` - -### Menu Manager - -Application menu creation and management. - -```go -// Create and set application menu -menu := app.Menu.New() -fileMenu := menu.AddSubmenu("File") -fileMenu.Add("New").OnClick(func(ctx *Context) { - // Handle menu click -}) - -app.Menu.Set(menu) - -// Show about dialog -app.Menu.ShowAbout() -``` - -### Key Binding Manager - -Dynamic management of global key bindings. - -```go -// Add key bindings -app.KeyBinding.Add("ctrl+n", func(window *WebviewWindow) { - // Handle Ctrl+N -}) - -app.KeyBinding.Add("ctrl+q", func(window *WebviewWindow) { - app.Quit() -}) - -// Remove key bindings -app.KeyBinding.Remove("ctrl+n") - -// Get all bindings -bindings := app.KeyBinding.GetAll() -``` - -### Context Menu Manager - -Advanced context menu management (for library authors). - -```go -// Create and register context menu -menu := app.ContextMenu.New() -app.ContextMenu.Add("myMenu", menu) - -// Retrieve context menu -menu, exists := app.ContextMenu.Get("myMenu") - -// Remove context menu -app.ContextMenu.Remove("myMenu") -``` - -### Screen Manager - -Screen management and coordinate transformations for multi-monitor setups. - -```go -// Get screen information -screens := app.Screen.GetAll() -primary := app.Screen.GetPrimary() - -// Coordinate transformations -physicalPoint := app.Screen.DipToPhysicalPoint(logicalPoint) -logicalPoint := app.Screen.PhysicalToDipPoint(physicalPoint) - -// Screen detection -screen := app.Screen.ScreenNearestDipPoint(point) -screen = app.Screen.ScreenNearestDipRect(rect) -``` - -### Clipboard Manager - -Clipboard operations for reading and writing text. - -```go -// Set text to clipboard -success := app.Clipboard.SetText("Hello World") -if !success { - // Handle error -} - -// Get text from clipboard -text, ok := app.Clipboard.Text() -if !ok { - // Handle error -} else { - // Use the text -} -``` - -### SystemTray Manager - -System tray icon creation and management. - -```go -// Create system tray -systray := app.SystemTray.New() -systray.SetLabel("My App") -systray.SetIcon(iconBytes) - -// Add menu to system tray -menu := app.Menu.New() -menu.Add("Open").OnClick(func(ctx *Context) { - // Handle click -}) -systray.SetMenu(menu) - -// Destroy system tray when done -systray.Destroy() -``` \ No newline at end of file diff --git a/docs/src/content/docs/contributing.mdx b/docs/src/content/docs/contributing.mdx deleted file mode 100644 index 841c30282..000000000 --- a/docs/src/content/docs/contributing.mdx +++ /dev/null @@ -1,275 +0,0 @@ ---- -title: Contributing -description: Contribute to Wails -sidebar: - order: 100 ---- - -import { Card, CardGrid } from "@astrojs/starlight/components"; - -## Welcome Contributors! - -We welcome contributions to Wails! Whether you're fixing bugs, adding features, or improving documentation, your help is appreciated. - -## Ways to Contribute - -### 1. Report Issues - -Found a bug? [Open an issue](https://github.com/wailsapp/wails/issues/new) with: -- Clear description -- Steps to reproduce -- Expected vs actual behaviour -- System information -- Code samples - -### 2. Improve Documentation - -Documentation improvements are always welcome: -- Fix typos and errors -- Add examples -- Clarify explanations -- Translate content - -### 3. Submit Code - -Contribute code through pull requests: -- Bug fixes -- New features -- Performance improvements -- Tests - -## Getting Started - -### Fork and Clone - -```bash -# Fork the repository on GitHub -# Then clone your fork -git clone https://github.com/YOUR_USERNAME/wails.git -cd wails - -# Add upstream remote -git remote add upstream https://github.com/wailsapp/wails.git -``` - -### Build from Source - -```bash -# Install dependencies -go mod download - -# Build Wails CLI -cd v3/cmd/wails3 -go build - -# Test your build -./wails3 version -``` - -### Run Tests - -```bash -# Run all tests -go test ./... - -# Run specific package tests -go test ./v3/pkg/application - -# Run with coverage -go test -cover ./... -``` - -## Making Changes - -### Create a Branch - -```bash -# Update main -git checkout main -git pull upstream main - -# Create feature branch -git checkout -b feature/my-feature -``` - -### Make Your Changes - -1. **Write code** following Go conventions -2. **Add tests** for new functionality -3. **Update documentation** if needed -4. **Run tests** to ensure nothing breaks -5. **Commit changes** with clear messages - -### Commit Guidelines - -```bash -# Good commit messages -git commit -m "fix: resolve window focus issue on macOS" -git commit -m "feat: add support for custom window chrome" -git commit -m "docs: improve bindings documentation" - -# Use conventional commits: -# - feat: New feature -# - fix: Bug fix -# - docs: Documentation -# - test: Tests -# - refactor: Code refactoring -# - chore: Maintenance -``` - -### Submit Pull Request - -```bash -# Push to your fork -git push origin feature/my-feature - -# Open pull request on GitHub -# Provide clear description -# Reference related issues -``` - -## Pull Request Guidelines - -### Good PR Description - -```markdown -## Description -Brief description of changes - -## Changes -- Added feature X -- Fixed bug Y -- Updated documentation - -## Testing -- Tested on macOS 14 -- Tested on Windows 11 -- All tests passing - -## Related Issues -Fixes #123 -``` - -### PR Checklist - -- [ ] Code follows Go conventions -- [ ] Tests added/updated -- [ ] Documentation updated -- [ ] All tests passing -- [ ] No breaking changes (or documented) -- [ ] Commit messages clear - -## Code Guidelines - -### Go Code Style - -```go -// ✅ Good: Clear, documented, tested -// ProcessData processes the input data and returns the result. -// It returns an error if the data is invalid. -func ProcessData(data string) (string, error) { - if data == "" { - return "", errors.New("data cannot be empty") - } - - result := process(data) - return result, nil -} - -// ❌ Bad: No docs, no error handling -func ProcessData(data string) string { - return process(data) -} -``` - -### Testing - -```go -func TestProcessData(t *testing.T) { - tests := []struct { - name string - input string - want string - wantErr bool - }{ - {"valid input", "test", "processed", false}, - {"empty input", "", "", true}, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - got, err := ProcessData(tt.input) - if (err != nil) != tt.wantErr { - t.Errorf("ProcessData() error = %v, wantErr %v", err, tt.wantErr) - return - } - if got != tt.want { - t.Errorf("ProcessData() = %v, want %v", got, tt.want) - } - }) - } -} -``` - -## Documentation - -### Writing Docs - -Documentation uses Starlight (Astro): - -```bash -cd docs -npm install -npm run dev -``` - -### Documentation Style - -- Use International English spelling -- Start with the problem -- Provide working examples -- Include troubleshooting -- Cross-reference related content - -## Community - -### Get Help - -- **Discord:** [Join our community](https://discord.gg/JDdSxwjhGf) -- **GitHub Discussions:** Ask questions -- **GitHub Issues:** Report bugs - -### Code of Conduct - -Be respectful, inclusive, and professional. We're all here to build great software together. - -## Recognition - -Contributors are recognised in: -- Release notes -- Contributors list -- GitHub insights - -Thank you for contributing to Wails! 🎉 - -## Next Steps - - - - Visit the Wails repository. - - [View on GitHub →](https://github.com/wailsapp/wails) - - - - Join the community. - - [Join Discord →](https://discord.gg/JDdSxwjhGf) - - - - Read the docs. - - [Browse Docs →](/quick-start/why-wails) - - diff --git a/docs/src/content/docs/contributing/_category_.json b/docs/src/content/docs/contributing/_category_.json deleted file mode 100644 index 5f76b677d..000000000 --- a/docs/src/content/docs/contributing/_category_.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "label": "Technical Documentation", - "link": { - "type": "generated-index", - "description": "Deep dive into Wails v3 internals for developers who want to understand or contribute to the codebase." - }, - "order": 50, - "collapsed": false -} diff --git a/docs/src/content/docs/contributing/architecture.mdx b/docs/src/content/docs/contributing/architecture.mdx deleted file mode 100644 index ed4dab2d0..000000000 --- a/docs/src/content/docs/contributing/architecture.mdx +++ /dev/null @@ -1,99 +0,0 @@ ---- -title: Wails v3 Architecture -description: Deep-dive diagrams and explanations of every moving part inside Wails v3 -sidebar: - order: 1 ---- - - -Wails v3 is a **full-stack desktop framework** consisting of a Go runtime, -a JavaScript bridge, a task-driven tool-chain and a collection of templates that -let you ship native applications powered by modern web tech. - -This page presents the *big picture* in four diagrams: - -1. **Overall Architecture** – how every subsystem connects -2. **Runtime Flow** – what happens when JS calls Go and vice-versa -3. **Development vs Production** – two modes of the asset server -4. **Platform Implementations** – where OS-specific code lives - ---- - -## 1 · Overall Architecture - -**Wails v3 – High-Level Stack** - -{/* -TODO: Fix D2 diagram generation (triple quotes for multi-line strings) or embed as image. -The previous D2 code block was causing MDX parsing errors in the build pipeline. -*/} - -**[High-Level Stack Diagram Placeholder]** - ---- - -## 2 · Runtime Call Flow - -**Runtime – JavaScript ⇄ Go Calling Path** - -{/* -TODO: Fix D2 diagram generation (triple quotes for multi-line strings) or embed as image. -The previous D2 code block was causing MDX parsing errors in the build pipeline. -*/} - -**[Runtime Call Flow Diagram Placeholder]** - -Key points: - -* **No HTTP / IPC** – the bridge uses the native WebView’s in-memory channel -* **Method IDs** – deterministic FNV-hash enables O(1) lookup in Go -* **Promises** – errors propagate as rejections with stack & code - ---- - -## 3 · Development vs Production Asset Flow - -**Dev ↔ Prod Asset Server** - -{/* -TODO: Fix D2 diagram generation (triple quotes for multi-line strings) or embed as image. -The previous D2 code block was causing MDX parsing errors in the build pipeline. -*/} - -**[Asset Flow Diagram Placeholder]** - -* In **dev** the server proxies unknown paths to the framework’s live-reload - server and serves static assets from disk. -* In **prod** the same API is backed by `go:embed`, producing a zero-dependency - binary. - ---- - -## 4 · Platform-Specific Runtime Split - -**Per-OS Runtime Files** - -{/* -TODO: Fix D2 diagram generation (triple quotes for multi-line strings) or embed as image. -The previous D2 code block was causing MDX parsing errors in the build pipeline. -*/} - -**[Platform Split Diagram Placeholder]** - -Every feature follows this pattern: - -1. **Common interface** in `pkg/application` -2. **Message processor** entry in `pkg/application/messageprocessor_*.go` -3. **Implementation** per OS under `internal/runtime/*.go` guarded by build tags - -Missing functionality on an OS should return `ErrCapability` and register -availability via `internal/capabilities`. - ---- - -## Summary - -These diagrams outline **where the code lives**, **how data moves**, and -**which layers own which responsibilities**. -Keep them handy while exploring the detailed pages that follow – they are your -map to the Wails v3 source tree. diff --git a/docs/src/content/docs/contributing/architecture/bindings.mdx b/docs/src/content/docs/contributing/architecture/bindings.mdx deleted file mode 100644 index 9cfcfa2b6..000000000 --- a/docs/src/content/docs/contributing/architecture/bindings.mdx +++ /dev/null @@ -1,156 +0,0 @@ ---- -title: Binding System -description: How the binding system collects, processes, and generates JavaScript/TypeScript code -sidebar: - order: 1 ---- - -import { FileTree } from "@astrojs/starlight/components"; - -This guide explains how the Wails binding system works internally, providing insights for developers who want to understand the mechanics behind the automatic code generation. - -## Architecture Overview - -The Wails binding system consists of three main components: - -1. **Collection**: Analyzes Go code to extract information about services, models, and other declarations -2. **Configuration**: Manages settings and options for the binding generation process -3. **Rendering**: Generates JavaScript/TypeScript code based on the collected information - - -- internal/generator/ - - collect/ # Package analysis and information extraction - - config/ # Configuration structures and interfaces - - render/ # Code generation for JS/TS - - -## Collection Process - -The collection process is responsible for analyzing Go packages and extracting information about services, models, and other declarations. This is handled by the `collect` package. - -### Key Components - -- **Collector**: Manages package information and caches collected data -- **Package**: Represents a Go package being analyzed and stores collected services, models, and directives -- **Service**: Collects information about service types and their methods -- **Model**: Collects detailed information about model types, including fields, values, and type parameters -- **Directive**: Parses and interprets `//wails:` directives in Go source code - -### Collection Flow - -1. The collector scans the Go packages specified in the project -2. It identifies service types (structs with methods that will be exposed to the frontend) -3. For each service, it collects information about its methods -4. It identifies model types (structs used as parameters or return values in service methods) -5. For each model, it collects information about its fields and type parameters -6. It processes any `//wails:` directives found in the code - -## Rendering Process - -The rendering process is responsible for generating JavaScript/TypeScript code based on the collected information. This is handled by the `render` package. - -### Key Components - -- **Renderer**: Orchestrates the rendering of service, model, and index files -- **Module**: Represents a single generated JavaScript/TypeScript module -- **Templates**: Text templates used for code generation - -### Rendering Flow - -1. For each service, the renderer generates a JavaScript/TypeScript file with functions that mirror the service methods -2. For each model, the renderer generates a JavaScript/TypeScript class that mirrors the model struct -3. The renderer generates index files that re-export all services and models -4. The renderer applies any custom code injections specified by `//wails:inject` directives - -## Type Mapping - -One of the most important aspects of the binding system is how Go types are mapped to JavaScript/TypeScript types. Here's a summary of the mapping: - -| Go Type | JavaScript Type | TypeScript Type | -|---------|----------------|----------------| -| `bool` | `boolean` | `boolean` | -| `int`, `int8`, `int16`, `int32`, `int64`, `uint`, `uint8`, `uint16`, `uint32`, `uint64`, `float32`, `float64` | `number` | `number` | -| `string` | `string` | `string` | -| `[]byte` | `Uint8Array` | `Uint8Array` | -| `[]T` | `Array` | `T[]` | -| `map[K]V` | `Object` | `Record` | -| `struct` | `Object` | Custom class | -| `interface{}` | `any` | `any` | -| `*T` | `T \| null` | `T \| null` | -| `func` | Not supported | Not supported | -| `chan` | Not supported | Not supported | - -## Directives System - -The binding system supports several directives that can be used to customize the generated code. These directives are added as comments in your Go code. - -### Available Directives - -- `//wails:inject`: Injects custom JavaScript/TypeScript code into the generated bindings -- `//wails:include`: Includes additional files with the generated bindings -- `//wails:internal`: Marks a type or method as internal, preventing it from being exported to the frontend -- `//wails:ignore`: Completely ignores a method during binding generation -- `//wails:id`: Specifies a custom ID for a method, overriding the default hash-based ID - -### Directive Processing - -1. During the collection phase, the collector identifies and parses directives in the Go code -2. The directives are stored with the corresponding declarations (services, methods, models, etc.) -3. During the rendering phase, the renderer applies the directives to customize the generated code - -## Advanced Features - -### Conditional Code Generation - -The binding system supports conditional code generation using a two-character condition prefix for `include` and `inject` directives: - -``` - - - -
-

Application Report

-

Generated: {{.Timestamp}}

-
-
- - {{range .Items}} -

{{.}}

- {{end}} -
- -` - - // Write report to file - file, err := os.Create(reportPath) - if err != nil { - return err - } - defer file.Close() - - t, err := template.New("report").Parse(tmpl) - if err != nil { - return err - } - - err = t.Execute(file, data) - if err != nil { - return err - } - - // Open in browser - return app.Browser.OpenFile(reportPath) -} -``` - -### Development Tools - -Open development resources during development: - -```go -func setupDevelopmentMenu(app *application.App) { - if !app.Env.Info().Debug { - return // Only show in debug mode - } - - menu := app.Menu.New() - devMenu := menu.AddSubmenu("Development") - - devMenu.Add("Open DevTools").OnClick(func(ctx *application.Context) { - // This would open browser devtools if available - window := app.Window.Current() - if window != nil { - window.OpenDevTools() - } - }) - - devMenu.Add("View Source").OnClick(func(ctx *application.Context) { - // Open source code repository - app.Browser.OpenURL("https://github.com/youruser/yourapp") - }) - - devMenu.Add("API Documentation").OnClick(func(ctx *application.Context) { - // Open local API docs - app.Browser.OpenURL("http://localhost:8080/docs") - }) -} -``` - -## Error Handling - -### Graceful Error Handling - -Always handle potential errors when opening URLs or files: - -```go -func openURLWithFallback(app *application.App, url string, fallbackMessage string) { - err := app.Browser.OpenURL(url) - if err != nil { - app.Logger.Error("Failed to open URL", "url", url, "error", err) - - // Show fallback dialog with URL - dialog := app.Dialog.Info() - dialog.SetTitle("Unable to Open Link") - dialog.SetMessage(fmt.Sprintf("%s\n\nURL: %s", fallbackMessage, url)) - dialog.Show() - } -} - -// Usage -openURLWithFallback(app, - "https://docs.example.com", - "Please open the following URL manually in your browser:") -``` - -### User Feedback - -Provide feedback when operations succeed or fail: - -```go -func openURLWithFeedback(app *application.App, url string) { - err := app.Browser.OpenURL(url) - if err != nil { - // Show error dialog - app.Dialog.Error(). - SetTitle("Browser Error"). - SetMessage(fmt.Sprintf("Could not open URL: %s", err.Error())). - Show() - } else { - // Optionally show success notification - app.Logger.Info("URL opened successfully", "url", url) - } -} -``` - -## Platform Considerations - - - - - On macOS: - - - Uses the `open` command to launch the default browser - - Respects user's default browser setting in System Preferences - - May prompt for permission if the application is sandboxed - - Handles `file://` URLs correctly for local files - - - - - - On Windows: - - - Uses Windows Shell API to open URLs - - Respects default browser setting in Windows Settings - - Handles Windows path formats correctly - - May show security warnings for untrusted URLs - - - - - - On Linux: - - - Attempts to use `xdg-open` first, falls back to other methods - - Behavior varies by desktop environment - - Respects `BROWSER` environment variable if set - - May require additional packages in minimal installations - - - - -## Best Practices - -1. **Always Handle Errors**: Browser operations can fail for various reasons: - ```go - if err := app.Browser.OpenURL(url); err != nil { - app.Logger.Error("Failed to open browser", "error", err) - // Provide fallback or user notification - } - ``` - -2. **Validate URLs**: Ensure URLs are well-formed before opening: - ```go - func isValidHTTPURL(str string) bool { - u, err := url.Parse(str) - return err == nil && (u.Scheme == "http" || u.Scheme == "https") - } - ``` - -3. **User Confirmation**: For external links, consider asking user permission: - ```go - // Show confirmation dialog before opening external links - confirmAndOpen(app, "https://external-site.com") - ``` - -4. **Secure File Paths**: When opening files, ensure paths are safe: - ```go - func openSafeFile(app *application.App, filename string) error { - // Ensure file exists and is readable - if _, err := os.Stat(filename); err != nil { - return err - } - return app.Browser.OpenFile(filename) - } - ``` - -## Complete Example - -Here's a complete example showing various browser integration patterns: - -```go -package main - -import ( - "fmt" - "os" - "path/filepath" - "github.com/wailsapp/wails/v3/pkg/application" -) - -func main() { - app := application.New(application.Options{ - Name: "Browser Integration Demo", - }) - - // Setup menu with browser actions - setupMenu(app) - - // Create main window - window := app.Window.New() - window.SetTitle("Browser Integration") - - err := app.Run() - if err != nil { - panic(err) - } -} - -func setupMenu(app *application.App) { - menu := app.Menu.New() - - // File menu - fileMenu := menu.AddSubmenu("File") - fileMenu.Add("Generate Report").OnClick(func(ctx *application.Context) { - generateHTMLReport(app) - }) - - // Help menu - helpMenu := menu.AddSubmenu("Help") - helpMenu.Add("Documentation").OnClick(func(ctx *application.Context) { - openWithConfirmation(app, "https://docs.example.com") - }) - helpMenu.Add("Support").OnClick(func(ctx *application.Context) { - openWithConfirmation(app, "https://support.example.com") - }) - - app.Menu.Set(menu) -} - -func openWithConfirmation(app *application.App, url string) { - dialog := app.Dialog.Question() - dialog.SetTitle("Open External Link") - dialog.SetMessage(fmt.Sprintf("Open %s in your browser?", url)) - - dialog.AddButton("Open").OnClick(func() { - if err := app.Browser.OpenURL(url); err != nil { - showError(app, "Failed to open URL", err) - } - }) - - dialog.AddButton("Cancel") - dialog.Show() -} - -func generateHTMLReport(app *application.App) { - // Create temporary HTML file - tmpDir := os.TempDir() - reportPath := filepath.Join(tmpDir, "demo_report.html") - - html := ` - - - - Demo Report - - - -
-

Application Report

-

This is a sample report generated by the application.

-
-
-

Report Details

-

This report was generated to demonstrate browser integration.

-
- -` - - err := os.WriteFile(reportPath, []byte(html), 0644) - if err != nil { - showError(app, "Failed to create report", err) - return - } - - // Open in browser - err = app.Browser.OpenFile(reportPath) - if err != nil { - showError(app, "Failed to open report", err) - } -} - -func showError(app *application.App, message string, err error) { - app.Dialog.Error(). - SetTitle("Error"). - SetMessage(fmt.Sprintf("%s: %v", message, err)). - Show() -} -``` - -:::tip[Pro Tip] -Consider providing fallback mechanisms for when browser operations fail, such as copying URLs to clipboard or showing them in a dialog for manual opening. -::: - -:::danger[Warning] -Always validate URLs and file paths before opening them to prevent security issues. Be cautious about opening user-provided URLs without validation. -::: \ No newline at end of file diff --git a/docs/src/content/docs/features/clipboard/basics.mdx b/docs/src/content/docs/features/clipboard/basics.mdx deleted file mode 100644 index b75570aca..000000000 --- a/docs/src/content/docs/features/clipboard/basics.mdx +++ /dev/null @@ -1,493 +0,0 @@ ---- -title: Clipboard Operations -description: Copy and paste text with the system clipboard -sidebar: - order: 1 ---- - -import { Card, CardGrid } from "@astrojs/starlight/components"; - -## Clipboard Operations - -Wails provides a **unified clipboard API** that works across all platforms. Copy and paste text with simple, consistent methods on Windows, macOS, and Linux. - -## Quick Start - -```go -// Copy text to clipboard -app.Clipboard.SetText("Hello, World!") - -// Get text from clipboard -text, ok := app.Clipboard.Text() -if ok { - fmt.Println("Clipboard:", text) -} -``` - -**That's it!** Cross-platform clipboard access. - -## Copying Text - -### Basic Copy - -```go -success := app.Clipboard.SetText("Text to copy") -if !success { - app.Logger.Error("Failed to copy to clipboard") -} -``` - -**Returns:** `bool` - `true` if successful, `false` otherwise - -### Copy from Service - -```go -type ClipboardService struct { - app *application.Application -} - -func (c *ClipboardService) CopyToClipboard(text string) bool { - return c.app.Clipboard.SetText(text) -} -``` - -**Call from JavaScript:** - -```javascript -import { CopyToClipboard } from './bindings/myapp/clipboardservice' - -await CopyToClipboard("Text to copy") -``` - -### Copy with Feedback - -```go -func copyWithFeedback(text string) { - if app.Clipboard.SetText(text) { - app.Dialog.Info(). - SetTitle("Copied"). - SetMessage("Text copied to clipboard!"). - Show() - } else { - app.Dialog.Error(). - SetTitle("Copy Failed"). - SetMessage("Failed to copy to clipboard."). - Show() - } -} -``` - -## Pasting Text - -### Basic Paste - -```go -text, ok := app.Clipboard.Text() -if !ok { - app.Logger.Error("Failed to read clipboard") - return -} - -fmt.Println("Clipboard text:", text) -``` - -**Returns:** `(string, bool)` - Text and success flag - -### Paste from Service - -```go -func (c *ClipboardService) PasteFromClipboard() string { - text, ok := c.app.Clipboard.Text() - if !ok { - return "" - } - return text -} -``` - -**Call from JavaScript:** - -```javascript -import { PasteFromClipboard } from './bindings/myapp/clipboardservice' - -const text = await PasteFromClipboard() -console.log("Pasted:", text) -``` - -### Paste with Validation - -```go -func pasteText() (string, error) { - text, ok := app.Clipboard.Text() - if !ok { - return "", errors.New("clipboard empty or unavailable") - } - - // Validate - if len(text) == 0 { - return "", errors.New("clipboard is empty") - } - - if len(text) > 10000 { - return "", errors.New("clipboard text too large") - } - - return text, nil -} -``` - -## Complete Examples - -### Copy Button - -**Go:** - -```go -type TextService struct { - app *application.Application -} - -func (t *TextService) CopyText(text string) error { - if !t.app.Clipboard.SetText(text) { - return errors.New("failed to copy") - } - return nil -} -``` - -**JavaScript:** - -```javascript -import { CopyText } from './bindings/myapp/textservice' - -async function copyToClipboard(text) { - try { - await CopyText(text) - showNotification("Copied to clipboard!") - } catch (error) { - showError("Failed to copy: " + error) - } -} - -// Usage -document.getElementById('copy-btn').addEventListener('click', () => { - const text = document.getElementById('text').value - copyToClipboard(text) -}) -``` - -### Paste and Process - -**Go:** - -```go -type DataService struct { - app *application.Application -} - -func (d *DataService) PasteAndProcess() (string, error) { - // Get clipboard text - text, ok := d.app.Clipboard.Text() - if !ok { - return "", errors.New("clipboard unavailable") - } - - // Process text - processed := strings.TrimSpace(text) - processed = strings.ToUpper(processed) - - return processed, nil -} -``` - -**JavaScript:** - -```javascript -import { PasteAndProcess } from './bindings/myapp/dataservice' - -async function pasteAndProcess() { - try { - const result = await PasteAndProcess() - document.getElementById('output').value = result - } catch (error) { - showError("Failed to paste: " + error) - } -} -``` - -### Copy Multiple Formats - -```go -type CopyService struct { - app *application.Application -} - -func (c *CopyService) CopyAsPlainText(text string) bool { - return c.app.Clipboard.SetText(text) -} - -func (c *CopyService) CopyAsJSON(data interface{}) bool { - jsonBytes, err := json.MarshalIndent(data, "", " ") - if err != nil { - return false - } - return c.app.Clipboard.SetText(string(jsonBytes)) -} - -func (c *CopyService) CopyAsCSV(rows [][]string) bool { - var buf bytes.Buffer - writer := csv.NewWriter(&buf) - - for _, row := range rows { - if err := writer.Write(row); err != nil { - return false - } - } - - writer.Flush() - return c.app.Clipboard.SetText(buf.String()) -} -``` - -### Clipboard Monitor - -```go -type ClipboardMonitor struct { - app *application.Application - lastText string - ticker *time.Ticker - stopChan chan bool -} - -func NewClipboardMonitor(app *application.Application) *ClipboardMonitor { - return &ClipboardMonitor{ - app: app, - stopChan: make(chan bool), - } -} - -func (cm *ClipboardMonitor) Start() { - cm.ticker = time.NewTicker(1 * time.Second) - - go func() { - for { - select { - case <-cm.ticker.C: - cm.checkClipboard() - case <-cm.stopChan: - return - } - } - }() -} - -func (cm *ClipboardMonitor) Stop() { - if cm.ticker != nil { - cm.ticker.Stop() - } - cm.stopChan <- true -} - -func (cm *ClipboardMonitor) checkClipboard() { - text, ok := cm.app.Clipboard.Text() - if !ok { - return - } - - if text != cm.lastText { - cm.lastText = text - cm.app.Event.Emit("clipboard-changed", text) - } -} -``` - -### Copy with History - -```go -type ClipboardHistory struct { - app *application.Application - history []string - maxSize int -} - -func NewClipboardHistory(app *application.Application) *ClipboardHistory { - return &ClipboardHistory{ - app: app, - history: make([]string, 0), - maxSize: 10, - } -} - -func (ch *ClipboardHistory) Copy(text string) bool { - if !ch.app.Clipboard.SetText(text) { - return false - } - - // Add to history - ch.history = append([]string{text}, ch.history...) - - // Limit size - if len(ch.history) > ch.maxSize { - ch.history = ch.history[:ch.maxSize] - } - - return true -} - -func (ch *ClipboardHistory) GetHistory() []string { - return ch.history -} - -func (ch *ClipboardHistory) RestoreFromHistory(index int) bool { - if index < 0 || index >= len(ch.history) { - return false - } - - return ch.app.Clipboard.SetText(ch.history[index]) -} -``` - -## Frontend Integration - -### Using Browser Clipboard API - -For simple text, you can use the browser's clipboard API: - -```javascript -// Copy -async function copyText(text) { - try { - await navigator.clipboard.writeText(text) - console.log("Copied!") - } catch (error) { - console.error("Copy failed:", error) - } -} - -// Paste -async function pasteText() { - try { - const text = await navigator.clipboard.readText() - return text - } catch (error) { - console.error("Paste failed:", error) - return "" - } -} -``` - -**Note:** Browser clipboard API requires HTTPS or localhost, and user permission. - -### Using Wails Clipboard - -For system-wide clipboard access: - -```javascript -import { CopyToClipboard, PasteFromClipboard } from './bindings/myapp/clipboardservice' - -// Copy -async function copy(text) { - const success = await CopyToClipboard(text) - if (success) { - console.log("Copied!") - } -} - -// Paste -async function paste() { - const text = await PasteFromClipboard() - return text -} -``` - -## Best Practices - -### ✅ Do - -- **Check return values** - Handle failures gracefully -- **Provide feedback** - Let users know copy succeeded -- **Validate pasted text** - Check format and size -- **Use appropriate method** - Browser API vs Wails API -- **Handle empty clipboard** - Check before using -- **Trim whitespace** - Clean pasted text - -### ❌ Don't - -- **Don't ignore failures** - Always check success -- **Don't copy sensitive data** - Clipboard is shared -- **Don't assume format** - Validate pasted data -- **Don't poll too frequently** - If monitoring clipboard -- **Don't copy large data** - Use files instead -- **Don't forget security** - Sanitise pasted content - -## Platform Differences - -### macOS - -- Uses NSPasteboard -- Supports rich text (future) -- System-wide clipboard -- Clipboard history (system feature) - -### Windows - -- Uses Windows Clipboard API -- Supports multiple formats (future) -- System-wide clipboard -- Clipboard history (Windows 10+) - -### Linux - -- Uses X11/Wayland clipboard -- Primary and clipboard selections -- Varies by desktop environment -- May require clipboard manager - -## Limitations - -### Current Version - -- **Text only** - Images not yet supported -- **No format detection** - Plain text only -- **No clipboard events** - Must poll for changes -- **No clipboard history** - Implement yourself - -### Future Features - -- Image support -- Rich text support -- Multiple formats -- Clipboard change events -- Clipboard history API - -## Next Steps - - - - Call Go functions from JavaScript. - - [Learn More →](/features/bindings/methods) - - - - Use events for clipboard notifications. - - [Learn More →](/features/events/system) - - - - Show copy/paste feedback. - - [Learn More →](/features/dialogs/message) - - - - Organise clipboard code. - - [Learn More →](/features/bindings/services) - - - ---- - -**Questions?** Ask in [Discord](https://discord.gg/JDdSxwjhGf) or check the [clipboard examples](https://github.com/wailsapp/wails/tree/v3-alpha/v3/examples). diff --git a/docs/src/content/docs/features/dialogs/custom.mdx b/docs/src/content/docs/features/dialogs/custom.mdx deleted file mode 100644 index 591d68db2..000000000 --- a/docs/src/content/docs/features/dialogs/custom.mdx +++ /dev/null @@ -1,626 +0,0 @@ ---- -title: Custom dialogs -sidebar: - order: 4 ---- - -import { Card, CardGrid } from "@astrojs/starlight/components"; - -## Custom dialogs - -Create **custom dialog windows** using regular Wails windows with dialog-like behaviour. Build custom forms, complex input validation, branded appearance, and rich content (images, videos) whilst maintaining familiar dialog patterns. - -## Quick Start - -```go -// Create custom dialog window -dialog := app.Window.NewWithOptions(application.WebviewWindowOptions{ - Title: "Custom dialog", - Width: 400, - Height: 300, - AlwaysOnTop: true, - Frameless: true, - Hidden: true, -}) - -// Load custom UI -dialog.SetURL("http://wails.localhost/dialog.html") - -// Show as modal -dialog.Show() -dialog.SetFocus() -``` - -**That's it!** Custom UI with dialog behaviour. - -## Creating Custom dialogs - -### Basic Custom dialog - -```go -type Customdialog struct { - window *application.WebviewWindow - result chan string -} - -func NewCustomdialog(app *application.Application) *Customdialog { - dialog := &Customdialog{ - result: make(chan string, 1), - } - - dialog.window = app.Window.NewWithOptions(application.WebviewWindowOptions{ - Title: "Custom dialog", - Width: 400, - Height: 300, - AlwaysOnTop: true, - Resizable: false, - Hidden: true, - }) - - return dialog -} - -func (d *Customdialog) Show() string { - d.window.Show() - d.window.SetFocus() - - // Wait for result - return <-d.result -} - -func (d *Customdialog) Close(result string) { - d.result <- result - d.window.Close() -} -``` - -### Modal dialog - -```go -func ShowModaldialog(parent *application.WebviewWindow, title string) string { - // Create dialog - dialog := app.Window.NewWithOptions(application.WebviewWindowOptions{ - Title: title, - Width: 400, - Height: 200, - Parent: parent, - AlwaysOnTop: true, - Resizable: false, - }) - - // Disable parent - parent.SetEnabled(false) - - // Re-enable parent on close - dialog.OnClose(func() bool { - parent.SetEnabled(true) - parent.SetFocus() - return true - }) - - dialog.Show() - - return waitForResult(dialog) -} -``` - -### Form dialog - -```go -type Formdialog struct { - window *application.WebviewWindow - data map[string]interface{} - done chan bool -} - -func NewFormdialog(app *application.Application) *Formdialog { - fd := &Formdialog{ - data: make(map[string]interface{}), - done: make(chan bool, 1), - } - - fd.window = app.Window.NewWithOptions(application.WebviewWindowOptions{ - Title: "Enter Information", - Width: 500, - Height: 400, - Frameless: true, - Hidden: true, - }) - - return fd -} - -func (fd *Formdialog) Show() (map[string]interface{}, bool) { - fd.window.Show() - fd.window.SetFocus() - - ok := <-fd.done - return fd.data, ok -} - -func (fd *Formdialog) Submit(data map[string]interface{}) { - fd.data = data - fd.done <- true - fd.window.Close() -} - -func (fd *Formdialog) Cancel() { - fd.done <- false - fd.window.Close() -} -``` - -## dialog Patterns - -### Confirmation dialog - -```go -func ShowConfirmdialog(message string) bool { - dialog := app.Window.NewWithOptions(application.WebviewWindowOptions{ - Title: "Confirm", - Width: 400, - Height: 150, - AlwaysOnTop: true, - Frameless: true, - }) - - // Pass message to dialog - dialog.OnReady(func() { - dialog.EmitEvent("set-message", message) - }) - - result := make(chan bool, 1) - - // Handle responses - app.Event.On("confirm-yes", func(e *application.CustomEvent) { - result <- true - dialog.Close() - }) - - app.Event.On("confirm-no", func(e *application.CustomEvent) { - result <- false - dialog.Close() - }) - - dialog.Show() - return <-result -} -``` - -**Frontend (HTML/JS):** - -```html -
-

-
- - -
-
- - -``` - -### Input dialog - -```go -func ShowInputdialog(prompt string, defaultValue string) (string, bool) { - dialog := app.Window.NewWithOptions(application.WebviewWindowOptions{ - Title: "Input", - Width: 400, - Height: 150, - Frameless: true, - }) - - result := make(chan struct { - value string - ok bool - }, 1) - - dialog.OnReady(func() { - dialog.EmitEvent("set-prompt", map[string]string{ - "prompt": prompt, - "default": defaultValue, - }) - }) - - app.Event.On("input-submit", func(e *application.CustomEvent) { - result <- struct { - value string - ok bool - }{e.Data.(string), true} - dialog.Close() - }) - - app.Event.On("input-cancel", func(e *application.CustomEvent) { - result <- struct { - value string - ok bool - }{"", false} - dialog.Close() - }) - - dialog.Show() - r := <-result - return r.value, r.ok -} -``` - -### Progress dialog - -```go -type Progressdialog struct { - window *application.WebviewWindow -} - -func NewProgressdialog(title string) *Progressdialog { - pd := &Progressdialog{} - - pd.window = app.Window.NewWithOptions(application.WebviewWindowOptions{ - Title: title, - Width: 400, - Height: 150, - Frameless: true, - }) - - return pd -} - -func (pd *Progressdialog) Show() { - pd.window.Show() -} - -func (pd *Progressdialog) UpdateProgress(current, total int, message string) { - pd.window.EmitEvent("progress-update", map[string]interface{}{ - "current": current, - "total": total, - "message": message, - }) -} - -func (pd *Progressdialog) Close() { - pd.window.Close() -} -``` - -**Usage:** - -```go -func processFiles(files []string) { - progress := NewProgressdialog("Processing Files") - progress.Show() - - for i, file := range files { - progress.UpdateProgress(i+1, len(files), - fmt.Sprintf("Processing %s...", filepath.Base(file))) - - processFile(file) - } - - progress.Close() -} -``` - -## Complete Examples - -### Login dialog - -**Go:** - -```go -type Logindialog struct { - window *application.WebviewWindow - result chan struct { - username string - password string - ok bool - } -} - -func NewLogindialog(app *application.Application) *Logindialog { - ld := &Logindialog{ - result: make(chan struct { - username string - password string - ok bool - }, 1), - } - - ld.window = app.Window.NewWithOptions(application.WebviewWindowOptions{ - Title: "Login", - Width: 400, - Height: 250, - Frameless: true, - }) - - return ld -} - -func (ld *Logindialog) Show() (string, string, bool) { - ld.window.Show() - ld.window.SetFocus() - - r := <-ld.result - return r.username, r.password, r.ok -} - -func (ld *Logindialog) Submit(username, password string) { - ld.result <- struct { - username string - password string - ok bool - }{username, password, true} - ld.window.Close() -} - -func (ld *Logindialog) Cancel() { - ld.result <- struct { - username string - password string - ok bool - }{"", "", false} - ld.window.Close() -} -``` - -**Frontend:** - -```html - - - -``` - -### Settings dialog - -**Go:** - -```go -type Settingsdialog struct { - window *application.WebviewWindow - settings map[string]interface{} - done chan bool -} - -func NewSettingsdialog(app *application.Application, current map[string]interface{}) *Settingsdialog { - sd := &Settingsdialog{ - settings: current, - done: make(chan bool, 1), - } - - sd.window = app.Window.NewWithOptions(application.WebviewWindowOptions{ - Title: "Settings", - Width: 600, - Height: 500, - }) - - sd.window.OnReady(func() { - sd.window.EmitEvent("load-settings", current) - }) - - return sd -} - -func (sd *Settingsdialog) Show() (map[string]interface{}, bool) { - sd.window.Show() - - ok := <-sd.done - return sd.settings, ok -} - -func (sd *Settingsdialog) Save(settings map[string]interface{}) { - sd.settings = settings - sd.done <- true - sd.window.Close() -} - -func (sd *Settingsdialog) Cancel() { - sd.done <- false - sd.window.Close() -} -``` - -### Wizard dialog - -```go -type Wizarddialog struct { - window *application.WebviewWindow - currentStep int - data map[string]interface{} - done chan bool -} - -func NewWizarddialog(app *application.Application) *Wizarddialog { - wd := &Wizarddialog{ - currentStep: 0, - data: make(map[string]interface{}), - done: make(chan bool, 1), - } - - wd.window = app.Window.NewWithOptions(application.WebviewWindowOptions{ - Title: "Setup Wizard", - Width: 600, - Height: 400, - Resizable: false, - }) - - return wd -} - -func (wd *Wizarddialog) Show() (map[string]interface{}, bool) { - wd.window.Show() - - ok := <-wd.done - return wd.data, ok -} - -func (wd *Wizarddialog) NextStep(stepData map[string]interface{}) { - // Merge step data - for k, v := range stepData { - wd.data[k] = v - } - - wd.currentStep++ - wd.window.EmitEvent("next-step", wd.currentStep) -} - -func (wd *Wizarddialog) PreviousStep() { - if wd.currentStep > 0 { - wd.currentStep-- - wd.window.EmitEvent("previous-step", wd.currentStep) - } -} - -func (wd *Wizarddialog) Finish(finalData map[string]interface{}) { - for k, v := range finalData { - wd.data[k] = v - } - - wd.done <- true - wd.window.Close() -} - -func (wd *Wizarddialog) Cancel() { - wd.done <- false - wd.window.Close() -} -``` - -## Best Practices - -### ✅ Do - -- **Use appropriate window options** - AlwaysOnTop, Frameless, etc. -- **Handle cancellation** - Always provide a way to cancel -- **Validate input** - Check data before accepting -- **Provide feedback** - Loading states, errors -- **Use events for communication** - Clean separation -- **Clean up resources** - Close windows, remove listeners - -### ❌ Don't - -- **Don't block the main thread** - Use channels for results -- **Don't forget to close** - Memory leaks -- **Don't skip validation** - Always validate input -- **Don't ignore errors** - Handle all error cases -- **Don't make it too complex** - Keep dialogs simple -- **Don't forget accessibility** - Keyboard navigation - -## Styling Custom dialogs - -### Modern dialog Style - -```css -.dialog { - display: flex; - flex-direction: column; - height: 100vh; - background: white; - font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; -} - -.dialog-header { - --wails-draggable: drag; - padding: 16px; - background: #f5f5f5; - border-bottom: 1px solid #e0e0e0; -} - -.dialog-content { - flex: 1; - padding: 24px; - overflow: auto; -} - -.dialog-footer { - padding: 16px; - background: #f5f5f5; - border-top: 1px solid #e0e0e0; - display: flex; - justify-content: flex-end; - gap: 8px; -} - -button { - padding: 8px 16px; - border: none; - border-radius: 4px; - cursor: pointer; - font-size: 14px; -} - -button.primary { - background: #007aff; - color: white; -} - -button.secondary { - background: #e0e0e0; - color: #333; -} -``` - -## Next Steps - - - - Standard info, warning, error dialogs. - - [Learn More →](/features/dialogs/message) - - - - Open, save, folder selection. - - [Learn More →](/features/dialogs/file) - - - - Learn about window management. - - [Learn More →](/features/windows/basics) - - - - Use events for dialog communication. - - [Learn More →](/features/events/system) - - - ---- - -**Questions?** Ask in [Discord](https://discord.gg/JDdSxwjhGf) or check the [custom dialog examples](https://github.com/wailsapp/wails/tree/v3-alpha/v3/examples/dialogs). diff --git a/docs/src/content/docs/features/dialogs/file.mdx b/docs/src/content/docs/features/dialogs/file.mdx deleted file mode 100644 index bba6e3f03..000000000 --- a/docs/src/content/docs/features/dialogs/file.mdx +++ /dev/null @@ -1,568 +0,0 @@ ---- -title: File dialogs -description: Open, save, and folder selection dialogs -sidebar: - order: 3 ---- - -import { Card, CardGrid } from "@astrojs/starlight/components"; - -## File dialogs - -Wails provides **native file dialogs** with platform-appropriate appearance for opening files, saving files, and selecting folders. Simple API with file type filtering, multiple selection support, and default locations. - -## Creating File Dialogs - -File dialogs are accessed through the `app.Dialog` manager: - -```go -app.Dialog.OpenFile() -app.Dialog.SaveFile() -``` - -## Open File dialog - -Select files to open: - -```go -path, err := app.Dialog.OpenFile(). - SetTitle("Select Image"). - AddFilter("Images", "*.png;*.jpg;*.gif"). - AddFilter("All Files", "*.*"). - PromptForSingleSelection() - -if err != nil || path == "" { - return -} - -openFile(path) -``` - -**Use cases:** -- Open documents -- Import files -- Load images -- Select configuration files - -### Single File Selection - -```go -path, err := app.Dialog.OpenFile(). - SetTitle("Open Document"). - AddFilter("Text Files", "*.txt"). - AddFilter("All Files", "*.*"). - PromptForSingleSelection() - -if err != nil || path == "" { - // User cancelled or error occurred - return -} - -// Use selected file -data, _ := os.ReadFile(path) -``` - -### Multiple File Selection - -```go -paths, err := app.Dialog.OpenFile(). - SetTitle("Select Images"). - AddFilter("Images", "*.png;*.jpg;*.jpeg;*.gif"). - PromptForMultipleSelection() - -if err != nil { - return -} - -// Process all selected files -for _, path := range paths { - processFile(path) -} -``` - -### With Default Directory - -```go -path, err := app.Dialog.OpenFile(). - SetTitle("Open File"). - SetDirectory("/Users/me/Documents"). - PromptForSingleSelection() -``` - -## Save File dialog - -Choose where to save: - -```go -path, err := app.Dialog.SaveFile(). - SetFilename("document.txt"). - AddFilter("Text Files", "*.txt"). - AddFilter("All Files", "*.*"). - PromptForSingleSelection() - -if err != nil || path == "" { - return -} - -saveFile(path, data) -``` - -**Use cases:** -- Save documents -- Export data -- Create new files -- Save as... - -### With Default Filename - -```go -path, err := app.Dialog.SaveFile(). - SetFilename("export.csv"). - AddFilter("CSV Files", "*.csv"). - PromptForSingleSelection() -``` - -### With Default Directory - -```go -path, err := app.Dialog.SaveFile(). - SetDirectory("/Users/me/Documents"). - SetFilename("untitled.txt"). - PromptForSingleSelection() -``` - -### Overwrite Confirmation - -```go -path, err := app.Dialog.SaveFile(). - SetFilename("document.txt"). - PromptForSingleSelection() - -if err != nil || path == "" { - return -} - -// Check if file exists -if _, err := os.Stat(path); err == nil { - dialog := app.Dialog.Question(). - SetTitle("Confirm Overwrite"). - SetMessage("File already exists. Overwrite?") - - overwriteBtn := dialog.AddButton("Overwrite") - overwriteBtn.OnClick(func() { - saveFile(path, data) - }) - - cancelBtn := dialog.AddButton("Cancel") - dialog.SetDefaultButton(cancelBtn) - dialog.SetCancelButton(cancelBtn) - dialog.Show() - return -} - -saveFile(path, data) -``` - -## Select Folder dialog - -Choose a directory using the open file dialog with directory selection enabled: - -```go -path, err := app.Dialog.OpenFile(). - SetTitle("Select Output Folder"). - CanChooseDirectories(true). - CanChooseFiles(false). - PromptForSingleSelection() - -if err != nil || path == "" { - return -} - -exportToFolder(path) -``` - -**Use cases:** -- Choose output directory -- Select workspace -- Pick backup location -- Choose installation directory - -### With Default Directory - -```go -path, err := app.Dialog.OpenFile(). - SetTitle("Select Folder"). - SetDirectory("/Users/me/Documents"). - CanChooseDirectories(true). - CanChooseFiles(false). - PromptForSingleSelection() -``` - -## File Filters - -Use the `AddFilter()` method to add file type filters to dialogs. Each call adds a new filter option. - -### Basic Filters - -```go -path, _ := app.Dialog.OpenFile(). - AddFilter("Text Files", "*.txt"). - AddFilter("All Files", "*.*"). - PromptForSingleSelection() -``` - -### Multiple Extensions - -Use semicolons to specify multiple extensions in a single filter: - -```go -dialog := app.Dialog.OpenFile(). - AddFilter("Images", "*.png;*.jpg;*.jpeg;*.gif;*.bmp"). - AddFilter("Documents", "*.txt;*.doc;*.docx;*.pdf"). - AddFilter("All Files", "*.*") -``` - -### Pattern Format - -Use **semicolons** to separate multiple extensions in a single filter: - -```go -// Multiple extensions separated by semicolons -AddFilter("Images", "*.png;*.jpg;*.gif") -``` - -## Complete Examples - -### Open Image File - -```go -func openImage(app *application.App) (image.Image, error) { - path, err := app.Dialog.OpenFile(). - SetTitle("Select Image"). - AddFilter("Images", "*.png;*.jpg;*.jpeg;*.gif;*.bmp"). - PromptForSingleSelection() - - if err != nil { - return nil, err - } - - if path == "" { - return nil, errors.New("no file selected") - } - - // Open and decode image - file, err := os.Open(path) - if err != nil { - app.Dialog.Error(). - SetTitle("Open Failed"). - SetMessage(err.Error()). - Show() - return nil, err - } - defer file.Close() - - img, _, err := image.Decode(file) - if err != nil { - app.Dialog.Error(). - SetTitle("Invalid Image"). - SetMessage("Could not decode image file."). - Show() - return nil, err - } - - return img, nil -} -``` - -### Save Document with Validation - -```go -func saveDocument(app *application.App, content string) { - path, err := app.Dialog.SaveFile(). - SetFilename("document.txt"). - AddFilter("Text Files", "*.txt"). - AddFilter("Markdown Files", "*.md"). - AddFilter("All Files", "*.*"). - PromptForSingleSelection() - - if err != nil || path == "" { - return - } - - // Validate extension - ext := filepath.Ext(path) - if ext != ".txt" && ext != ".md" { - dialog := app.Dialog.Question(). - SetTitle("Confirm Extension"). - SetMessage(fmt.Sprintf("Save as %s file?", ext)) - - saveBtn := dialog.AddButton("Save") - saveBtn.OnClick(func() { - doSave(app, path, content) - }) - - cancelBtn := dialog.AddButton("Cancel") - dialog.SetDefaultButton(cancelBtn) - dialog.SetCancelButton(cancelBtn) - dialog.Show() - return - } - - doSave(app, path, content) -} - -func doSave(app *application.App, path, content string) { - if err := os.WriteFile(path, []byte(content), 0644); err != nil { - app.Dialog.Error(). - SetTitle("Save Failed"). - SetMessage(err.Error()). - Show() - return - } - - app.Dialog.Info(). - SetTitle("Saved"). - SetMessage("Document saved successfully!"). - Show() -} -``` - -### Batch File Processing - -```go -func processMultipleFiles(app *application.App) { - paths, err := app.Dialog.OpenFile(). - SetTitle("Select Files to Process"). - AddFilter("Images", "*.png;*.jpg"). - PromptForMultipleSelection() - - if err != nil || len(paths) == 0 { - return - } - - // Confirm processing - dialog := app.Dialog.Question(). - SetTitle("Confirm Processing"). - SetMessage(fmt.Sprintf("Process %d file(s)?", len(paths))) - - processBtn := dialog.AddButton("Process") - processBtn.OnClick(func() { - // Process files - var errs []error - for i, path := range paths { - if err := processFile(path); err != nil { - errs = append(errs, err) - } - - // Update progress - // app.Event.Emit("progress", map[string]interface{}{ - // "current": i + 1, - // "total": len(paths), - // }) - _ = i // suppress unused variable warning in example - } - - // Show results - if len(errs) > 0 { - app.Dialog.Warning(). - SetTitle("Processing Complete"). - SetMessage(fmt.Sprintf("Processed %d files with %d errors.", - len(paths), len(errs))). - Show() - } else { - app.Dialog.Info(). - SetTitle("Success"). - SetMessage(fmt.Sprintf("Processed %d files successfully!", len(paths))). - Show() - } - }) - - cancelBtn := dialog.AddButton("Cancel") - dialog.SetCancelButton(cancelBtn) - dialog.Show() -} -``` - -### Export with Folder Selection - -```go -func exportData(app *application.App, data []byte) { - // Select output folder - folder, err := app.Dialog.OpenFile(). - SetTitle("Select Export Folder"). - SetDirectory(getDefaultExportFolder()). - CanChooseDirectories(true). - CanChooseFiles(false). - PromptForSingleSelection() - - if err != nil || folder == "" { - return - } - - // Generate filename - filename := fmt.Sprintf("export_%s.csv", - time.Now().Format("2006-01-02_15-04-05")) - path := filepath.Join(folder, filename) - - // Save file - if err := os.WriteFile(path, data, 0644); err != nil { - app.Dialog.Error(). - SetTitle("Export Failed"). - SetMessage(err.Error()). - Show() - return - } - - // Show success with option to open folder - dialog := app.Dialog.Question(). - SetTitle("Export Complete"). - SetMessage(fmt.Sprintf("Exported to %s", filename)) - - openBtn := dialog.AddButton("Open Folder") - openBtn.OnClick(func() { - openFolder(folder) - }) - - dialog.AddButton("OK") - dialog.Show() -} -``` - -### Import with Validation - -```go -func importConfiguration(app *application.App) { - path, err := app.Dialog.OpenFile(). - SetTitle("Import Configuration"). - AddFilter("JSON Files", "*.json"). - AddFilter("YAML Files", "*.yaml;*.yml"). - PromptForSingleSelection() - - if err != nil || path == "" { - return - } - - // Read file - data, err := os.ReadFile(path) - if err != nil { - app.Dialog.Error(). - SetTitle("Read Failed"). - SetMessage(err.Error()). - Show() - return - } - - // Validate configuration - config, err := parseConfig(data) - if err != nil { - app.Dialog.Error(). - SetTitle("Invalid Configuration"). - SetMessage("File is not a valid configuration."). - Show() - return - } - - // Confirm import - dialog := app.Dialog.Question(). - SetTitle("Confirm Import"). - SetMessage("Import this configuration?") - - importBtn := dialog.AddButton("Import") - importBtn.OnClick(func() { - // Apply configuration - if err := applyConfig(config); err != nil { - app.Dialog.Error(). - SetTitle("Import Failed"). - SetMessage(err.Error()). - Show() - return - } - - app.Dialog.Info(). - SetTitle("Success"). - SetMessage("Configuration imported successfully!"). - Show() - }) - - cancelBtn := dialog.AddButton("Cancel") - dialog.SetCancelButton(cancelBtn) - dialog.Show() -} -``` - -## Best Practices - -### ✅ Do - -- **Provide file filters** - Help users find files -- **Set appropriate titles** - Clear context -- **Use default directories** - Start in logical location -- **Validate selections** - Check file types -- **Handle cancellation** - User might cancel -- **Show confirmation** - For destructive actions -- **Provide feedback** - Success/error messages - -### ❌ Don't - -- **Don't skip validation** - Check file types -- **Don't ignore errors** - Handle cancellation -- **Don't use generic filters** - Be specific -- **Don't forget "All Files"** - Always include as option -- **Don't hardcode paths** - Use user's home directory -- **Don't assume file exists** - Check before opening - -## Platform Differences - -### macOS - -- Native NSOpenPanel/NSSavePanel -- Sheet-style when attached to window -- Follows system theme -- Supports Quick Look preview -- Tags and favourites integration - -### Windows - -- Native File Open/Save dialogs -- Follows system theme -- Recent files integration -- Network location support - -### Linux - -- GTK file chooser -- Varies by desktop environment -- Follows desktop theme -- Recent files support - -## Next Steps - - - - Info, warning, and error dialogs. - - [Learn More →](/features/dialogs/message) - - - - Create custom dialog windows. - - [Learn More →](/features/dialogs/custom) - - - - Call Go functions from JavaScript. - - [Learn More →](/features/bindings/methods) - - - - Use events for progress updates. - - [Learn More →](/features/events/system) - - - ---- - -**Questions?** Ask in [Discord](https://discord.gg/JDdSxwjhGf) or check the [file dialog examples](https://github.com/wailsapp/wails/tree/v3-alpha/v3/examples/dialogs). diff --git a/docs/src/content/docs/features/dialogs/message.mdx b/docs/src/content/docs/features/dialogs/message.mdx deleted file mode 100644 index 4b718aaa6..000000000 --- a/docs/src/content/docs/features/dialogs/message.mdx +++ /dev/null @@ -1,516 +0,0 @@ ---- -title: Message dialogs -description: Display information, warnings, errors, and questions -sidebar: - order: 2 ---- - -import { Card, CardGrid } from "@astrojs/starlight/components"; - -## Message dialogs - -Wails provides **native message dialogs** with platform-appropriate appearance: info, warning, error, and question dialogs with customisable titles, messages, and buttons. Simple API, native behaviour, accessible by default. - -## Creating Dialogs - -Message dialogs are accessed through the `app.Dialog` manager: - -```go -app.Dialog.Info() -app.Dialog.Question() -app.Dialog.Warning() -app.Dialog.Error() -``` - -All methods return a `*MessageDialog` that can be configured using method chaining. - -## Information dialog - -Display informational messages: - -```go -app.Dialog.Info(). - SetTitle("Success"). - SetMessage("File saved successfully!"). - Show() -``` - -**Use cases:** -- Success confirmations -- Completion notices -- Informational messages -- Status updates - -**Example - Save confirmation:** - -```go -func saveFile(app *application.App, path string, data []byte) error { - if err := os.WriteFile(path, data, 0644); err != nil { - return err - } - - app.Dialog.Info(). - SetTitle("File Saved"). - SetMessage(fmt.Sprintf("Saved to %s", filepath.Base(path))). - Show() - - return nil -} -``` - -## Warning dialog - -Show warnings: - -```go -app.Dialog.Warning(). - SetTitle("Warning"). - SetMessage("This action cannot be undone."). - Show() -``` - -**Use cases:** -- Non-critical warnings -- Deprecation notices -- Caution messages -- Potential issues - -**Example - Disk space warning:** - -```go -func checkDiskSpace(app *application.App) { - available := getDiskSpace() - - if available < 100*1024*1024 { // Less than 100MB - app.Dialog.Warning(). - SetTitle("Low Disk Space"). - SetMessage(fmt.Sprintf("Only %d MB available.", available/(1024*1024))). - Show() - } -} -``` - -## Error dialog - -Display errors: - -```go -app.Dialog.Error(). - SetTitle("Error"). - SetMessage("Failed to connect to server."). - Show() -``` - -**Use cases:** -- Error messages -- Failure notifications -- Exception handling -- Critical issues - -**Example - Network error:** - -```go -func fetchData(app *application.App, url string) ([]byte, error) { - resp, err := http.Get(url) - if err != nil { - app.Dialog.Error(). - SetTitle("Network Error"). - SetMessage(fmt.Sprintf("Failed to connect: %v", err)). - Show() - return nil, err - } - defer resp.Body.Close() - - return io.ReadAll(resp.Body) -} -``` - -## Question dialog - -Ask users questions and handle responses via button callbacks: - -```go -dialog := app.Dialog.Question(). - SetTitle("Confirm"). - SetMessage("Save changes before closing?") - -save := dialog.AddButton("Save") -save.OnClick(func() { - saveChanges() -}) - -dontSave := dialog.AddButton("Don't Save") -dontSave.OnClick(func() { - // Continue without saving -}) - -cancel := dialog.AddButton("Cancel") -cancel.OnClick(func() { - // Don't close -}) - -dialog.SetDefaultButton(save) -dialog.SetCancelButton(cancel) -dialog.Show() -``` - -**Use cases:** -- Confirm actions -- Yes/No questions -- Multiple choice -- User decisions - -**Example - Unsaved changes:** - -```go -func closeDocument(app *application.App) { - if !hasUnsavedChanges() { - doClose() - return - } - - dialog := app.Dialog.Question(). - SetTitle("Unsaved Changes"). - SetMessage("Do you want to save your changes?") - - save := dialog.AddButton("Save") - save.OnClick(func() { - if saveDocument() { - doClose() - } - }) - - dontSave := dialog.AddButton("Don't Save") - dontSave.OnClick(func() { - doClose() - }) - - cancel := dialog.AddButton("Cancel") - // Cancel button has no callback - just closes the dialog - - dialog.SetDefaultButton(save) - dialog.SetCancelButton(cancel) - dialog.Show() -} -``` - -## dialog Options - -### Title and Message - -```go -dialog := app.Dialog.Info(). - SetTitle("Operation Complete"). - SetMessage("All files have been processed successfully.") -``` - -**Best practices:** -- **Title:** Short, descriptive (2-5 words) -- **Message:** Clear, specific, actionable -- **Avoid jargon:** Use plain language - -### Buttons - -**Single button (Info/Warning/Error):** - -Info, warning, and error dialogs display a default "OK" button: - -```go -app.Dialog.Info(). - SetMessage("Done!"). - Show() -``` - -You can also add custom buttons: - -```go -dialog := app.Dialog.Info(). - SetMessage("Done!") -ok := dialog.AddButton("Got it!") -dialog.SetDefaultButton(ok) -dialog.Show() -``` - -**Multiple buttons (Question):** - -Use `AddButton()` to add buttons, which returns a `*Button` you can configure: - -```go -dialog := app.Dialog.Question(). - SetMessage("Choose an action") - -option1 := dialog.AddButton("Option 1") -option1.OnClick(func() { - handleOption1() -}) - -option2 := dialog.AddButton("Option 2") -option2.OnClick(func() { - handleOption2() -}) - -option3 := dialog.AddButton("Option 3") -option3.OnClick(func() { - handleOption3() -}) - -dialog.Show() -``` - -**Default and Cancel buttons:** - -Use `SetDefaultButton()` to specify which button is highlighted and triggered by Enter. -Use `SetCancelButton()` to specify which button is triggered by Escape. - -```go -dialog := app.Dialog.Question(). - SetMessage("Delete file?") - -deleteBtn := dialog.AddButton("Delete") -deleteBtn.OnClick(func() { - performDelete() -}) - -cancelBtn := dialog.AddButton("Cancel") -// No callback needed - just dismisses dialog - -dialog.SetDefaultButton(cancelBtn) // Safe option as default -dialog.SetCancelButton(cancelBtn) // Escape triggers Cancel -dialog.Show() -``` - -You can also use the fluent `SetAsDefault()` and `SetAsCancel()` methods on buttons: - -```go -dialog := app.Dialog.Question(). - SetMessage("Delete file?") - -dialog.AddButton("Delete").OnClick(func() { - performDelete() -}) - -dialog.AddButton("Cancel").SetAsDefault().SetAsCancel() - -dialog.Show() -``` - -**Best practices:** -- **1-3 buttons:** Don't overwhelm users -- **Clear labels:** "Save" not "OK" -- **Safe default:** Non-destructive action -- **Order matters:** Most likely action first (except Cancel) - -### Custom Icon - -Set a custom icon for the dialog: - -```go -app.Dialog.Info(). - SetTitle("Custom Icon Example"). - SetMessage("Using a custom icon"). - SetIcon(myIconBytes). - Show() -``` - -### Window Attachment - -Attach to specific window: - -```go -dialog := app.Dialog.Question(). - SetMessage("Window-specific question"). - AttachToWindow(window) - -dialog.AddButton("OK") -dialog.Show() -``` - -**Benefits:** -- dialog appears on correct window -- Parent window disabled whilst shown -- Better multi-window UX - -## Complete Examples - -### Confirm Destructive Action - -```go -func deleteFiles(app *application.App, paths []string) { - // Confirm deletion - message := fmt.Sprintf("Delete %d file(s)?", len(paths)) - if len(paths) == 1 { - message = fmt.Sprintf("Delete %s?", filepath.Base(paths[0])) - } - - dialog := app.Dialog.Question(). - SetTitle("Confirm Delete"). - SetMessage(message) - - deleteBtn := dialog.AddButton("Delete") - deleteBtn.OnClick(func() { - // Perform deletion - var errs []error - for _, path := range paths { - if err := os.Remove(path); err != nil { - errs = append(errs, err) - } - } - - // Show result - if len(errs) > 0 { - app.Dialog.Error(). - SetTitle("Delete Failed"). - SetMessage(fmt.Sprintf("Failed to delete %d file(s)", len(errs))). - Show() - } else { - app.Dialog.Info(). - SetTitle("Delete Complete"). - SetMessage(fmt.Sprintf("Deleted %d file(s)", len(paths))). - Show() - } - }) - - cancelBtn := dialog.AddButton("Cancel") - dialog.SetDefaultButton(cancelBtn) - dialog.SetCancelButton(cancelBtn) - dialog.Show() -} -``` - -### Quit Confirmation - -```go -func confirmQuit(app *application.App) { - dialog := app.Dialog.Question(). - SetTitle("Quit"). - SetMessage("You have unsaved work. Are you sure you want to quit?") - - yes := dialog.AddButton("Yes") - yes.OnClick(func() { - app.Quit() - }) - - no := dialog.AddButton("No") - dialog.SetDefaultButton(no) - dialog.Show() -} -``` - -### Update Dialog with Download Option - -```go -func showUpdateDialog(app *application.App) { - dialog := app.Dialog.Question(). - SetTitle("Update"). - SetMessage("A new version is available. The cancel button is selected when pressing escape.") - - download := dialog.AddButton("📥 Download") - download.OnClick(func() { - app.Dialog.Info().SetMessage("Downloading...").Show() - }) - - cancel := dialog.AddButton("Cancel") - - dialog.SetDefaultButton(download) - dialog.SetCancelButton(cancel) - dialog.Show() -} -``` - -### Custom Icon Question - -```go -func showCustomIconQuestion(app *application.App, iconBytes []byte) { - dialog := app.Dialog.Question(). - SetTitle("Custom Icon Example"). - SetMessage("Using a custom icon"). - SetIcon(iconBytes) - - likeIt := dialog.AddButton("I like it!") - likeIt.OnClick(func() { - app.Dialog.Info().SetMessage("Thanks!").Show() - }) - - notKeen := dialog.AddButton("Not so keen...") - notKeen.OnClick(func() { - app.Dialog.Info().SetMessage("Too bad!").Show() - }) - - dialog.SetDefaultButton(likeIt) - dialog.Show() -} - -## Best Practices - -### ✅ Do - -- **Be specific** - "File saved to Documents" not "Success" -- **Use appropriate type** - Error for errors, Warning for warnings -- **Provide context** - Include relevant details -- **Use clear button labels** - "Delete" not "OK" -- **Set safe defaults** - Non-destructive action -- **Handle cancellation** - User might close dialog - -### ❌ Don't - -- **Don't overuse** - Interrupts workflow -- **Don't use for frequent updates** - Use notifications instead -- **Don't use generic messages** - "Error" tells nothing -- **Don't ignore errors** - Handle dialog.Show() errors -- **Don't block unnecessarily** - Consider async alternatives -- **Don't use technical jargon** - Plain language - -## Platform Differences - -### macOS - -- Sheet-style when attached to window -- Standard keyboard shortcuts (⌘. for Cancel) -- Follows system theme automatically -- Accessibility built-in - -### Windows - -- Modal dialogs -- TaskDialog appearance -- Esc for Cancel -- Follows system theme - -### Linux - -- GTK dialogs -- Varies by desktop environment -- Follows desktop theme -- Standard keyboard navigation - -## Next Steps - - - - Open, save, and folder selection. - - [Learn More →](/features/dialogs/file) - - - - Create custom dialog windows. - - [Learn More →](/features/dialogs/custom) - - - - Non-intrusive notifications. - - [Learn More →](/features/notifications) - - - - Use events for non-blocking communication. - - [Learn More →](/features/events/system) - - - ---- - -**Questions?** Ask in [Discord](https://discord.gg/JDdSxwjhGf) or check the [dialog examples](https://github.com/wailsapp/wails/tree/v3-alpha/v3/examples/dialogs). diff --git a/docs/src/content/docs/features/dialogs/overview.mdx b/docs/src/content/docs/features/dialogs/overview.mdx deleted file mode 100644 index 25dcaf901..000000000 --- a/docs/src/content/docs/features/dialogs/overview.mdx +++ /dev/null @@ -1,518 +0,0 @@ ---- -title: dialogs Overview -description: Display native system dialogs in your application -sidebar: - order: 1 ---- - -import { Tabs, TabItem, Card, CardGrid } from "@astrojs/starlight/components"; - -## Native dialogs - -Wails provides **native system dialogs** that work across all platforms: message dialogs (info, warning, error, question), file dialogs (open, save, folder), and custom dialog windows with platform-native appearance and behaviour. - -## Quick Start - -```go -// Information dialog -app.Dialog.Info(). - SetTitle("Success"). - SetMessage("File saved successfully!"). - Show() - -// Question dialog with button callbacks -dialog := app.Dialog.Question(). - SetTitle("Confirm"). - SetMessage("Delete this file?") - -deleteBtn := dialog.AddButton("Delete") -deleteBtn.OnClick(func() { - deleteFile() -}) - -cancelBtn := dialog.AddButton("Cancel") -dialog.SetDefaultButton(cancelBtn) -dialog.SetCancelButton(cancelBtn) -dialog.Show() - -// File open dialog -path, _ := app.Dialog.OpenFile(). - SetTitle("Select Image"). - AddFilter("Images", "*.png;*.jpg"). - PromptForSingleSelection() -``` - -**That's it!** Native dialogs with minimal code. - -## Accessing Dialogs - -Dialogs are accessed through the `app.Dialog` manager: - -```go -app.Dialog.Info() -app.Dialog.Question() -app.Dialog.Warning() -app.Dialog.Error() -app.Dialog.OpenFile() -app.Dialog.SaveFile() -``` - -## dialog Types - -### Information dialog - -Display simple messages: - -```go -app.Dialog.Info(). - SetTitle("Welcome"). - SetMessage("Welcome to our application!"). - Show() -``` - -**Use cases:** -- Success messages -- Informational notices -- Completion confirmations - -### Warning dialog - -Show warnings: - -```go -app.Dialog.Warning(). - SetTitle("Warning"). - SetMessage("This action cannot be undone."). - Show() -``` - -**Use cases:** -- Non-critical warnings -- Deprecation notices -- Caution messages - -### Error dialog - -Display errors: - -```go -app.Dialog.Error(). - SetTitle("Error"). - SetMessage("Failed to save file: " + err.Error()). - Show() -``` - -**Use cases:** -- Error messages -- Failure notifications -- Exception handling - -### Question dialog - -Ask users questions and handle responses via button callbacks: - -```go -dialog := app.Dialog.Question(). - SetTitle("Confirm Delete"). - SetMessage("Are you sure you want to delete this file?") - -deleteBtn := dialog.AddButton("Delete") -deleteBtn.OnClick(func() { - deleteFile() -}) - -cancelBtn := dialog.AddButton("Cancel") -dialog.SetDefaultButton(cancelBtn) -dialog.SetCancelButton(cancelBtn) -dialog.Show() -``` - -**Use cases:** -- Confirm actions -- Yes/No questions -- Multiple choice - -## File dialogs - -### Open File dialog - -Select files to open: - -```go -path, err := app.Dialog.OpenFile(). - SetTitle("Select Image"). - AddFilter("Images", "*.png;*.jpg;*.gif"). - AddFilter("All Files", "*.*"). - PromptForSingleSelection() - -if err == nil && path != "" { - openFile(path) -} -``` - -**Multiple selection:** - -```go -paths, err := app.Dialog.OpenFile(). - SetTitle("Select Images"). - AddFilter("Images", "*.png;*.jpg"). - PromptForMultipleSelection() - -if err == nil { - for _, path := range paths { - processFile(path) - } -} -``` - -### Save File dialog - -Choose where to save: - -```go -path, err := app.Dialog.SaveFile(). - SetFilename("document.txt"). - AddFilter("Text Files", "*.txt"). - AddFilter("All Files", "*.*"). - PromptForSingleSelection() - -if err == nil && path != "" { - saveFile(path) -} -``` - -### Select Folder dialog - -Choose a directory using the open file dialog with directory selection enabled: - -```go -path, err := app.Dialog.OpenFile(). - SetTitle("Select Output Folder"). - CanChooseDirectories(true). - CanChooseFiles(false). - PromptForSingleSelection() - -if err == nil && path != "" { - exportToFolder(path) -} -``` - -## dialog Options - -### Title and Message - -```go -dialog := app.Dialog.Info(). - SetTitle("Success"). - SetMessage("Operation completed successfully!") -``` - -### Buttons - -**Default button for simple dialogs:** - -Info, warning, and error dialogs display a default "OK" button: - -```go -app.Dialog.Info(). - SetMessage("Done!"). - Show() -``` - -**Custom buttons for question dialogs:** - -Use `AddButton()` to add buttons, which returns a `*Button` you can configure with callbacks: - -```go -dialog := app.Dialog.Question(). - SetMessage("Choose action") - -save := dialog.AddButton("Save") -save.OnClick(func() { - saveDocument() -}) - -dontSave := dialog.AddButton("Don't Save") -dontSave.OnClick(func() { - discardChanges() -}) - -cancel := dialog.AddButton("Cancel") -// No callback needed - just dismisses dialog - -dialog.SetDefaultButton(save) -dialog.SetCancelButton(cancel) -dialog.Show() -``` - -**Default and Cancel buttons:** - -Use `SetDefaultButton()` to specify which button is highlighted and triggered by Enter. -Use `SetCancelButton()` to specify which button is triggered by Escape. - -```go -dialog := app.Dialog.Question(). - SetMessage("Delete file?") - -deleteBtn := dialog.AddButton("Delete") -deleteBtn.OnClick(func() { - performDelete() -}) - -cancelBtn := dialog.AddButton("Cancel") -dialog.SetDefaultButton(cancelBtn) // Safe option highlighted by default -dialog.SetCancelButton(cancelBtn) // Escape triggers Cancel -dialog.Show() -``` - -### Window Attachment - -Attach dialog to specific window: - -```go -dialog := app.Dialog.Info(). - SetMessage("Window-specific message"). - AttachToWindow(window) - -dialog.Show() -``` - -**Behaviour:** -- dialog appears centred on parent window -- Parent window disabled whilst dialog shown -- dialog moves with parent window (macOS) - -## Platform Behaviour - - - - **macOS dialogs:** - - - Native NSAlert appearance - - Follow system theme (light/dark) - - Support keyboard navigation - - Standard shortcuts (⌘. for Cancel) - - Accessibility features built-in - - Sheet-style when attached to window - - **Example:** - ```go - // Appears as sheet on macOS - dialog := app.Dialog.Question(). - SetMessage("Save changes?"). - AttachToWindow(window) - dialog.AddButton("Yes") - dialog.AddButton("No") - dialog.Show() - ``` - - - - **Windows dialogs:** - - - Native TaskDialog appearance - - Follow system theme - - Support keyboard navigation - - Standard shortcuts (Esc for Cancel) - - Accessibility features built-in - - Modal to parent window - - **Example:** - ```go - // Modal dialog on Windows - app.Dialog.Error(). - SetTitle("Error"). - SetMessage("Operation failed"). - Show() - ``` - - - - **Linux dialogs:** - - - GTK dialog appearance - - Follow desktop theme - - Support keyboard navigation - - Desktop environment integration - - Varies by DE (GNOME, KDE, etc.) - - **Example:** - ```go - // GTK dialog on Linux - app.Dialog.Info(). - SetMessage("Update complete"). - Show() - ``` - - - -## Common Patterns - -### Confirm Before Destructive Action - -```go -func deleteFile(app *application.App, path string) { - dialog := app.Dialog.Question(). - SetTitle("Confirm Delete"). - SetMessage(fmt.Sprintf("Delete %s?", filepath.Base(path))) - - deleteBtn := dialog.AddButton("Delete") - deleteBtn.OnClick(func() { - if err := os.Remove(path); err != nil { - app.Dialog.Error(). - SetTitle("Delete Failed"). - SetMessage(err.Error()). - Show() - } - }) - - cancelBtn := dialog.AddButton("Cancel") - dialog.SetDefaultButton(cancelBtn) - dialog.SetCancelButton(cancelBtn) - dialog.Show() -} -``` - -### Error Handling with dialog - -```go -func saveDocument(app *application.App, path string, data []byte) { - if err := os.WriteFile(path, data, 0644); err != nil { - app.Dialog.Error(). - SetTitle("Save Failed"). - SetMessage(fmt.Sprintf("Could not save file: %v", err)). - Show() - return - } - - app.Dialog.Info(). - SetTitle("Success"). - SetMessage("File saved successfully!"). - Show() -} -``` - -### File Selection with Validation - -```go -func selectImageFile(app *application.App) (string, error) { - path, err := app.Dialog.OpenFile(). - SetTitle("Select Image"). - AddFilter("Images", "*.png;*.jpg;*.jpeg;*.gif"). - PromptForSingleSelection() - - if err != nil { - return "", err - } - - if path == "" { - return "", errors.New("no file selected") - } - - // Validate file - if !isValidImage(path) { - app.Dialog.Error(). - SetTitle("Invalid File"). - SetMessage("Selected file is not a valid image."). - Show() - return "", errors.New("invalid image") - } - - return path, nil -} -``` - -### Multi-Step dialog Flow - -```go -func exportData(app *application.App) { - // Step 1: Confirm export - dialog := app.Dialog.Question(). - SetTitle("Export Data"). - SetMessage("Export all data to CSV?") - - exportBtn := dialog.AddButton("Export") - exportBtn.OnClick(func() { - // Step 2: Select destination - path, err := app.Dialog.SaveFile(). - SetFilename("export.csv"). - AddFilter("CSV Files", "*.csv"). - PromptForSingleSelection() - - if err != nil || path == "" { - return - } - - // Step 3: Perform export - if err := performExport(path); err != nil { - app.Dialog.Error(). - SetTitle("Export Failed"). - SetMessage(err.Error()). - Show() - return - } - - // Step 4: Success - app.Dialog.Info(). - SetTitle("Export Complete"). - SetMessage("Data exported successfully!"). - Show() - }) - - cancelBtn := dialog.AddButton("Cancel") - dialog.SetCancelButton(cancelBtn) - dialog.Show() -} -``` - -## Best Practices - -### ✅ Do - -- **Use native dialogs** - Better UX than custom -- **Provide clear messages** - Be specific -- **Set appropriate titles** - Context matters -- **Use default buttons wisely** - Safe option as default -- **Handle cancellation** - User might cancel -- **Validate file selections** - Check file types - -### ❌ Don't - -- **Don't overuse dialogs** - Interrupts workflow -- **Don't use for frequent messages** - Use notifications -- **Don't forget error handling** - User might cancel -- **Don't block unnecessarily** - Consider alternatives -- **Don't use generic messages** - Be specific -- **Don't ignore platform differences** - Test on all platforms - -## Next Steps - - - - Info, warning, and error dialogs. - - [Learn More →](/features/dialogs/message) - - - - Open, save, and folder selection. - - [Learn More →](/features/dialogs/file) - - - - Create custom dialog windows. - - [Learn More →](/features/dialogs/custom) - - - - Learn about window management. - - [Learn More →](/features/windows/basics) - - - ---- - -**Questions?** Ask in [Discord](https://discord.gg/JDdSxwjhGf) or check the [dialog examples](https://github.com/wailsapp/wails/tree/v3-alpha/v3/examples/dialogs). diff --git a/docs/src/content/docs/features/drag-and-drop/files.mdx b/docs/src/content/docs/features/drag-and-drop/files.mdx deleted file mode 100644 index ffc75093a..000000000 --- a/docs/src/content/docs/features/drag-and-drop/files.mdx +++ /dev/null @@ -1,212 +0,0 @@ ---- -title: File Drop -description: Accept files dragged from the operating system into your application -sidebar: - order: 1 ---- - -Wails lets users drag files from the operating system (file manager, desktop) into your application. Unlike HTML5 drag-and-drop which only works within the browser, this gives you access to actual file paths on disk. - -## Enable File Drop - -File drop is disabled by default. To enable it, set `EnableFileDrop: true` in your window options: - -```go -window := app.Window.NewWithOptions(application.WebviewWindowOptions{ - Title: "My App", - Width: 800, - Height: 600, - EnableFileDrop: true, -}) -``` - -When `EnableFileDrop` is `false` (the default), files dragged from the OS are blocked - they won't open in the webview or trigger any events. This prevents accidental navigation when users drag files over your app. - -## Define Drop Zones - -Drop zones tell Wails which elements should accept files. Files dropped outside a drop zone are ignored. - -Add the `data-file-drop-target` attribute to any element: - -```html -
- Drop files here -
-``` - -You can have multiple drop zones. The element's `id` and CSS classes are passed to your Go code, so you can handle drops differently depending on where files land. - -## Style Drag Hover - -When files are dragged over a drop zone, Wails adds the `file-drop-target-active` class. This lets you provide visual feedback so users know where they can drop: - -```css -.drop-zone { - border: 2px dashed #ccc; - padding: 40px; - text-align: center; - transition: all 0.2s ease; -} - -.drop-zone.file-drop-target-active { - border-color: #007bff; - background-color: rgba(0, 123, 255, 0.1); -} -``` - -The class is removed automatically when files leave the zone or are dropped. - -## Detect Dropped Files - -When files are dropped on a valid drop zone, Wails fires a `WindowFilesDropped` event. The event context contains the full filesystem paths of all dropped files: - -```go -import "github.com/wailsapp/wails/v3/pkg/events" - -window.OnWindowEvent(events.Common.WindowFilesDropped, func(event *application.WindowEvent) { - files := event.Context().DroppedFiles() - - for _, file := range files { - fmt.Println("Dropped:", file) - } -}) -``` - -The paths are absolute, like `/home/user/documents/report.pdf` or `C:\Users\Name\Documents\report.pdf`. - -## Get Drop Target Info - -When you have multiple drop zones, you can find out which one received the files using `DropTargetDetails()`: - -```go -window.OnWindowEvent(events.Common.WindowFilesDropped, func(event *application.WindowEvent) { - files := event.Context().DroppedFiles() - details := event.Context().DropTargetDetails() - - fmt.Printf("Dropped on element: id=%s, classes=%v\n", - details.ElementID, details.ClassList) - fmt.Printf("Position: x=%d, y=%d\n", details.X, details.Y) -}) -``` - -This lets you route files to different handlers: - -```go -switch details.ElementID { -case "images": - handleImageUpload(files) -case "documents": - handleDocumentUpload(files) -} -``` - -## Complete Example - -**Go:** - -```go -window := app.Window.NewWithOptions(application.WebviewWindowOptions{ - Title: "File Uploader", - EnableFileDrop: true, -}) - -window.OnWindowEvent(events.Common.WindowFilesDropped, func(event *application.WindowEvent) { - files := event.Context().DroppedFiles() - details := event.Context().DropTargetDetails() - - // Send to frontend - app.Event.Emit("files-dropped", map[string]any{ - "files": files, - "target": details.ElementID, - }) -}) -``` - -**HTML:** - -```html -
- Drop images here -
- -
- Drop documents here -
- - -``` - -## Full Window Drop - -If you want files to be droppable anywhere in your app, add the attribute to the body element: - -```html - - - -``` - -You can use a CSS overlay to indicate the entire window is a drop target: - -```css -body.file-drop-target-active::after { - content: "Drop files anywhere"; - position: fixed; - inset: 0; - display: flex; - align-items: center; - justify-content: center; - font-size: 24px; - color: #007bff; - background: rgba(255, 255, 255, 0.9); - pointer-events: none; -} -``` - -## Combining with HTML Drag & Drop - -You can use both external file drops and internal HTML drag-and-drop in the same application. When `EnableFileDrop` is `true`, Wails intercepts external file drags but lets internal HTML5 drags pass through normally. - -To distinguish between them in your HTML drop zone handlers, check if the drag contains files: - -```javascript -zone.addEventListener('dragenter', (e) => { - // Skip external file drags - Wails handles these - if (e.dataTransfer?.types.includes('Files')) { - return; - } - // Handle internal HTML5 drags - zone.classList.add('drag-over'); -}); - -zone.addEventListener('drop', (e) => { - // Skip external file drops - Wails handles these - if (e.dataTransfer?.types.includes('Files')) { - return; - } - e.preventDefault(); - zone.classList.remove('drag-over'); - // Handle internal drop -}); -``` - -This ensures your HTML drop handlers only respond to internal drags (like moving list items), while Wails handles external file drops separately via the `WindowFilesDropped` event. - -## Next Steps - -- [HTML Drag & Drop](./html) - Drag elements within your app -- [Window Options](/features/windows/options) - All window configuration options diff --git a/docs/src/content/docs/features/drag-and-drop/html.mdx b/docs/src/content/docs/features/drag-and-drop/html.mdx deleted file mode 100644 index 7eeebc7be..000000000 --- a/docs/src/content/docs/features/drag-and-drop/html.mdx +++ /dev/null @@ -1,232 +0,0 @@ ---- -title: HTML Drag & Drop -description: Drag and drop elements within your application -sidebar: - order: 2 ---- - -HTML5 drag-and-drop lets users drag elements within your app's UI - for example, reordering a list or moving items between columns. This is standard web functionality that works in Wails without any special setup. - -## Make an Element Draggable - -By default, most elements can't be dragged. To make an element draggable, add `draggable="true"`: - -```html -
Drag me
-``` - -The element will now show a drag preview when the user clicks and drags it. - -## Define a Drop Zone - -Elements don't accept drops by default. To make an element accept drops, you need to cancel the default behaviour on `dragover`: - -```html -
Drop here
- - -``` - -Calling `preventDefault()` on `dragover` is required - it signals that this element accepts drops. Without it, the drop event won't fire. - -## Style Drag Hover - -To show users where they can drop, add visual feedback when dragging over a drop zone. The `dragenter` event fires when something enters the zone, and `dragleave` fires when it leaves: - -```css -.drop-zone { - border: 2px dashed #ccc; - padding: 40px; - transition: all 0.2s ease; -} - -.drop-zone.drag-over { - border-color: #007bff; - background-color: rgba(0, 123, 255, 0.1); -} -``` - -```javascript -const target = document.getElementById('target'); - -target.addEventListener('dragenter', () => { - target.classList.add('drag-over'); -}); - -target.addEventListener('dragleave', () => { - target.classList.remove('drag-over'); -}); - -target.addEventListener('drop', (e) => { - e.preventDefault(); - target.classList.remove('drag-over'); - // Handle the drop -}); -``` - -Note: `dragleave` also fires when entering a child element, which can cause flickering. The complete example below shows how to handle this. - -## Complete Example - -A task list where items can be dragged between priority columns. This tracks the dragged element in a variable, which is the simplest approach when everything is on the same page: - -```html -
-
Fix login bug
-
Update docs
-
Add dark mode
-
- -
-
-

High Priority

-
    -
    -
    -

    Low Priority

    -
      -
      -
      - - - - -``` - -## Combining with File Drop - -If your app uses both HTML drag-and-drop and [File Drop](./files), your HTML drop zones will also receive events when users drag files from the operating system. To prevent confusion, filter out file drags in your handlers: - -```javascript -zone.addEventListener('dragenter', (e) => { - // Ignore external file drags - if (e.dataTransfer?.types.includes('Files')) return; - - zone.classList.add('drag-over'); -}); - -zone.addEventListener('dragover', (e) => { - // Ignore external file drags - if (e.dataTransfer?.types.includes('Files')) return; - - e.preventDefault(); -}); - -zone.addEventListener('drop', (e) => { - // Ignore external file drags - if (e.dataTransfer?.types.includes('Files')) return; - - e.preventDefault(); - zone.classList.remove('drag-over'); - // Handle the internal drop -}); -``` - -The `dataTransfer.types` array contains `'Files'` when the user is dragging files from the OS, but contains types like `'text/plain'` for internal HTML drags. This lets you distinguish between the two. - -## Passing Data with dataTransfer - -The example above tracks the dragged element in a JavaScript variable. This works well when everything is on the same page. But if you need to drag between iframes or pass data that isn't tied to a DOM element, use the `dataTransfer` API: - -```javascript -// When drag starts, store data -item.addEventListener('dragstart', (e) => { - e.dataTransfer.setData('text/plain', item.id); -}); - -// When dropped, retrieve the data -target.addEventListener('drop', (e) => { - e.preventDefault(); - const itemId = e.dataTransfer.getData('text/plain'); - const item = document.getElementById(itemId); - // Move or copy the item -}); -``` - -The data is stored as strings, so you'll need to serialize objects with `JSON.stringify()` if needed. - -## Next Steps - -- [File Drop](./files) - Accept files from the operating system -- [MDN Drag and Drop API](https://developer.mozilla.org/en-US/docs/Web/API/HTML_Drag_and_Drop_API) - Full browser API reference diff --git a/docs/src/content/docs/features/environment/info.mdx b/docs/src/content/docs/features/environment/info.mdx deleted file mode 100644 index d03fb5f70..000000000 --- a/docs/src/content/docs/features/environment/info.mdx +++ /dev/null @@ -1,620 +0,0 @@ ---- -title: Environment -sidebar: - order: 59 ---- - -import { Tabs, TabItem } from "@astrojs/starlight/components"; - -Wails provides comprehensive environment information through the EnvironmentManager API. This allows your application to detect system properties, theme preferences, and integrate with the operating system's file manager. - -## Accessing the Environment Manager - -The environment manager is accessed through the `Env` property on your application instance: - -```go -app := application.New(application.Options{ - Name: "Environment Demo", -}) - -// Access the environment manager -env := app.Env -``` - -## System Information - -### Get Environment Information - -Retrieve comprehensive information about the runtime environment: - -```go -envInfo := app.Env.Info() - -app.Logger.Info("Environment information", - "os", envInfo.OS, // "windows", "darwin", "linux" - "arch", envInfo.Arch, // "amd64", "arm64", etc. - "debug", envInfo.Debug, // Debug mode flag -) - -// Operating system details -if envInfo.OSInfo != nil { - app.Logger.Info("OS details", - "name", envInfo.OSInfo.Name, - "version", envInfo.OSInfo.Version, - ) -} - -// Platform-specific information -for key, value := range envInfo.PlatformInfo { - app.Logger.Info("Platform info", "key", key, "value", value) -} -``` - -### Environment Structure - -The environment information includes several important fields: - -```go -type EnvironmentInfo struct { - OS string // Operating system: "windows", "darwin", "linux" - Arch string // Architecture: "amd64", "arm64", "386", etc. - Debug bool // Whether running in debug mode - OSInfo *operatingsystem.OS // Detailed OS information - PlatformInfo map[string]any // Platform-specific details -} -``` - -## Theme Detection - -### Dark Mode Detection - -Detect whether the system is using dark mode: - -```go -if app.Env.IsDarkMode() { - app.Logger.Info("System is in dark mode") - // Apply dark theme to your application - applyDarkTheme() -} else { - app.Logger.Info("System is in light mode") - // Apply light theme to your application - applyLightTheme() -} -``` - -### Theme Change Monitoring - -Listen for theme changes to update your application dynamically: - -```go -import "github.com/wailsapp/wails/v3/pkg/events" - -// Listen for theme changes -app.Event.OnApplicationEvent(events.Common.ThemeChanged, func(event *application.ApplicationEvent) { - if app.Env.IsDarkMode() { - app.Logger.Info("Switched to dark mode") - updateApplicationTheme("dark") - } else { - app.Logger.Info("Switched to light mode") - updateApplicationTheme("light") - } -}) - -func updateApplicationTheme(theme string) { - // Update your application's theme - // This could emit an event to the frontend - app.Event.Emit("theme:changed", theme) -} -``` - -## File Manager Integration - -### Open File Manager - -Open the system's file manager at a specific location: - -```go -// Open file manager at a directory -err := app.Env.OpenFileManager("/Users/username/Documents", false) -if err != nil { - app.Logger.Error("Failed to open file manager", "error", err) -} - -// Open file manager and select a specific file -err = app.Env.OpenFileManager("/Users/username/Documents/report.pdf", true) -if err != nil { - app.Logger.Error("Failed to open file manager with selection", "error", err) -} -``` - -### Common Use Cases - -Show files or folders in the file manager from your application: - -```go -func showInFileManager(app *application.App, path string) { - err := app.Env.OpenFileManager(path, true) - if err != nil { - // Fallback: try opening just the directory - dir := filepath.Dir(path) - err = app.Env.OpenFileManager(dir, false) - if err != nil { - app.Logger.Error("Could not open file manager", "path", path, "error", err) - - // Show error to user - app.Dialog.Error(). - SetTitle("File Manager Error"). - SetMessage("Could not open file manager"). - Show() - } - } -} - -// Usage examples -func setupFileMenu(app *application.App) { - menu := app.Menu.New() - fileMenu := menu.AddSubmenu("File") - - fileMenu.Add("Show Downloads Folder").OnClick(func(ctx *application.Context) { - homeDir, _ := os.UserHomeDir() - downloadsDir := filepath.Join(homeDir, "Downloads") - showInFileManager(app, downloadsDir) - }) - - fileMenu.Add("Show Application Data").OnClick(func(ctx *application.Context) { - configDir, _ := os.UserConfigDir() - appDir := filepath.Join(configDir, "MyApp") - showInFileManager(app, appDir) - }) -} -``` - -## Platform-Specific Behavior - -### Adaptive Application Behavior - -Use environment information to adapt your application's behavior: - -```go -func configureForPlatform(app *application.App) { - envInfo := app.Env.Info() - - switch envInfo.OS { - case "darwin": - configureMacOS(app) - case "windows": - configureWindows(app) - case "linux": - configureLinux(app) - } - - // Adapt to architecture - if envInfo.Arch == "arm64" { - app.Logger.Info("Running on ARM architecture") - // Potentially optimize for ARM - } -} - -func configureMacOS(app *application.App) { - app.Logger.Info("Configuring for macOS") - - // macOS-specific configuration - menu := app.Menu.New() - menu.AddRole(application.AppMenu) // Add standard macOS app menu - - // Handle dark mode - if app.Env.IsDarkMode() { - setMacOSDarkTheme() - } -} - -func configureWindows(app *application.App) { - app.Logger.Info("Configuring for Windows") - - // Windows-specific configuration - // Set up Windows-style menus, key bindings, etc. -} - -func configureLinux(app *application.App) { - app.Logger.Info("Configuring for Linux") - - // Linux-specific configuration - // Adapt to different desktop environments -} -``` - -## Debug Mode Handling - -### Development vs Production - -Use debug mode information to enable development features: - -```go -func setupApplicationMode(app *application.App) { - envInfo := app.Env.Info() - - if envInfo.Debug { - app.Logger.Info("Running in debug mode") - setupDevelopmentFeatures(app) - } else { - app.Logger.Info("Running in production mode") - setupProductionFeatures(app) - } -} - -func setupDevelopmentFeatures(app *application.App) { - // Enable development-only features - menu := app.Menu.New() - - // Add development menu - devMenu := menu.AddSubmenu("Development") - devMenu.Add("Reload Application").OnClick(func(ctx *application.Context) { - // Reload the application - window := app.Window.Current() - if window != nil { - window.Reload() - } - }) - - devMenu.Add("Open DevTools").OnClick(func(ctx *application.Context) { - window := app.Window.Current() - if window != nil { - window.OpenDevTools() - } - }) - - devMenu.Add("Show Environment").OnClick(func(ctx *application.Context) { - showEnvironmentDialog(app) - }) -} - -func setupProductionFeatures(app *application.App) { - // Production-only features - // Disable debug logging, enable analytics, etc. -} -``` - -## Environment Information Dialog - -### Display System Information - -Create a dialog showing environment information: - -```go -func showEnvironmentDialog(app *application.App) { - envInfo := app.Env.Info() - - details := fmt.Sprintf(`Environment Information: - -Operating System: %s -Architecture: %s -Debug Mode: %t - -Dark Mode: %t - -Platform Information:`, - envInfo.OS, - envInfo.Arch, - envInfo.Debug, - app.Env.IsDarkMode()) - - // Add platform-specific details - for key, value := range envInfo.PlatformInfo { - details += fmt.Sprintf("\n%s: %v", key, value) - } - - if envInfo.OSInfo != nil { - details += fmt.Sprintf("\n\nOS Details:\nName: %s\nVersion: %s", - envInfo.OSInfo.Name, - envInfo.OSInfo.Version) - } - - dialog := app.Dialog.Info() - dialog.SetTitle("Environment Information") - dialog.SetMessage(details) - dialog.Show() -} -``` - -## Platform Considerations - - - - - On macOS: - - - Dark mode detection uses system appearance settings - - File manager operations use Finder - - Platform info includes macOS version details - - Architecture may be "arm64" on Apple Silicon Macs - - ```go - if envInfo.OS == "darwin" { - // macOS-specific handling - if envInfo.Arch == "arm64" { - app.Logger.Info("Running on Apple Silicon") - } - } - ``` - - - - - - On Windows: - - - Dark mode detection uses Windows theme settings - - File manager operations use Windows Explorer - - Platform info includes Windows version details - - May include additional Windows-specific information - - ```go - if envInfo.OS == "windows" { - // Windows-specific handling - for key, value := range envInfo.PlatformInfo { - if key == "windows_version" { - app.Logger.Info("Windows version", "version", value) - } - } - } - ``` - - - - - - On Linux: - - - Dark mode detection varies by desktop environment - - File manager operations use system default file manager - - Platform info includes distribution details - - Behavior may vary between different Linux distributions - - ```go - if envInfo.OS == "linux" { - // Linux-specific handling - if distro, ok := envInfo.PlatformInfo["distribution"]; ok { - app.Logger.Info("Linux distribution", "distro", distro) - } - } - ``` - - - - -## Best Practices - -1. **Cache Environment Information**: Environment info rarely changes during runtime: - ```go - type App struct { - envInfo *application.EnvironmentInfo - } - - func (a *App) getEnvInfo() application.EnvironmentInfo { - if a.envInfo == nil { - info := a.app.Env.Info() - a.envInfo = &info - } - return *a.envInfo - } - ``` - -2. **Handle Theme Changes**: Listen for system theme changes: - ```go - app.Event.OnApplicationEvent(events.Common.ThemeChanged, func(event *application.ApplicationEvent) { - updateTheme(app.Env.IsDarkMode()) - }) - ``` - -3. **Graceful File Manager Failures**: Always handle file manager errors: - ```go - func openFileManagerSafely(app *application.App, path string) { - err := app.Env.OpenFileManager(path, false) - if err != nil { - // Provide fallback or user notification - app.Logger.Warn("Could not open file manager", "path", path) - } - } - ``` - -4. **Platform-Specific Features**: Use environment info to enable platform features: - ```go - envInfo := app.Env.Info() - if envInfo.OS == "darwin" { - // Enable macOS-specific features - } - ``` - -## Complete Example - -Here's a complete example demonstrating environment management: - -```go -package main - -import ( - "fmt" - "os" - "path/filepath" - "runtime" - "github.com/wailsapp/wails/v3/pkg/application" - "github.com/wailsapp/wails/v3/pkg/events" -) - -func main() { - app := application.New(application.Options{ - Name: "Environment Demo", - }) - - // Setup application based on environment - setupForEnvironment(app) - - // Monitor theme changes - monitorThemeChanges(app) - - // Create menu with environment features - setupEnvironmentMenu(app) - - // Create main window - window := app.Window.New() - window.SetTitle("Environment Demo") - - err := app.Run() - if err != nil { - panic(err) - } -} - -func setupForEnvironment(app *application.App) { - envInfo := app.Env.Info() - - app.Logger.Info("Application environment", - "os", envInfo.OS, - "arch", envInfo.Arch, - "debug", envInfo.Debug, - "darkMode", app.Env.IsDarkMode(), - ) - - // Configure for platform - switch envInfo.OS { - case "darwin": - app.Logger.Info("Configuring for macOS") - // macOS-specific setup - case "windows": - app.Logger.Info("Configuring for Windows") - // Windows-specific setup - case "linux": - app.Logger.Info("Configuring for Linux") - // Linux-specific setup - } - - // Apply initial theme - if app.Env.IsDarkMode() { - applyDarkTheme(app) - } else { - applyLightTheme(app) - } -} - -func monitorThemeChanges(app *application.App) { - app.Event.OnApplicationEvent(events.Common.ThemeChanged, func(event *application.ApplicationEvent) { - if app.Env.IsDarkMode() { - app.Logger.Info("System switched to dark mode") - applyDarkTheme(app) - } else { - app.Logger.Info("System switched to light mode") - applyLightTheme(app) - } - }) -} - -func setupEnvironmentMenu(app *application.App) { - menu := app.Menu.New() - - // Add platform-specific app menu - if runtime.GOOS == "darwin" { - menu.AddRole(application.AppMenu) - } - - // Tools menu - toolsMenu := menu.AddSubmenu("Tools") - - toolsMenu.Add("Show Environment Info").OnClick(func(ctx *application.Context) { - showEnvironmentInfo(app) - }) - - toolsMenu.Add("Open Downloads Folder").OnClick(func(ctx *application.Context) { - openDownloadsFolder(app) - }) - - toolsMenu.Add("Toggle Theme").OnClick(func(ctx *application.Context) { - // This would typically be handled by the system - // but shown here for demonstration - toggleTheme(app) - }) - - app.Menu.Set(menu) -} - -func showEnvironmentInfo(app *application.App) { - envInfo := app.Env.Info() - - message := fmt.Sprintf(`Environment Information: - -Operating System: %s -Architecture: %s -Debug Mode: %t -Dark Mode: %t - -Platform Details:`, - envInfo.OS, - envInfo.Arch, - envInfo.Debug, - app.Env.IsDarkMode()) - - for key, value := range envInfo.PlatformInfo { - message += fmt.Sprintf("\n%s: %v", key, value) - } - - if envInfo.OSInfo != nil { - message += fmt.Sprintf("\n\nOS Information:\nName: %s\nVersion: %s", - envInfo.OSInfo.Name, - envInfo.OSInfo.Version) - } - - dialog := app.Dialog.Info() - dialog.SetTitle("Environment Information") - dialog.SetMessage(message) - dialog.Show() -} - -func openDownloadsFolder(app *application.App) { - homeDir, err := os.UserHomeDir() - if err != nil { - app.Logger.Error("Could not get home directory", "error", err) - return - } - - downloadsDir := filepath.Join(homeDir, "Downloads") - err = app.Env.OpenFileManager(downloadsDir, false) - if err != nil { - app.Logger.Error("Could not open Downloads folder", "error", err) - - app.Dialog.Error(). - SetTitle("File Manager Error"). - SetMessage("Could not open Downloads folder"). - Show() - } -} - -func applyDarkTheme(app *application.App) { - app.Logger.Info("Applying dark theme") - // Emit theme change to frontend - app.Event.Emit("theme:apply", "dark") -} - -func applyLightTheme(app *application.App) { - app.Logger.Info("Applying light theme") - // Emit theme change to frontend - app.Event.Emit("theme:apply", "light") -} - -func toggleTheme(app *application.App) { - // This is just for demonstration - // Real theme changes should come from the system - currentlyDark := app.Env.IsDarkMode() - if currentlyDark { - applyLightTheme(app) - } else { - applyDarkTheme(app) - } -} -``` - -:::tip[Pro Tip] -Use environment information to provide platform-appropriate user experiences. For example, use Command key shortcuts on macOS and Control key shortcuts on Windows/Linux. -::: - -:::danger[Warning] -Environment information is generally stable during application runtime, but theme preferences can change. Always listen for theme change events to keep your UI synchronized. -::: \ No newline at end of file diff --git a/docs/src/content/docs/features/events/system.mdx b/docs/src/content/docs/features/events/system.mdx deleted file mode 100644 index 678abff2f..000000000 --- a/docs/src/content/docs/features/events/system.mdx +++ /dev/null @@ -1,591 +0,0 @@ ---- -title: Event System -description: Communicate between components with the event system -sidebar: - order: 1 ---- - -import { Tabs, TabItem, Card, CardGrid } from "@astrojs/starlight/components"; - -## Event System - -Wails provides a **unified event system** for pub/sub communication. Emit events from anywhere, listen from anywhere—Go to JavaScript, JavaScript to Go, window to window—enabling decoupled architecture with typed events and lifecycle hooks. - -## Quick Start - -**Go (emit):** - -```go -app.Event.Emit("user-logged-in", map[string]interface{}{ - "userId": 123, - "name": "Alice", -}) -``` - -**JavaScript (listen):** - -```javascript -import { Events } from '@wailsio/runtime' - -Events.On("user-logged-in", (event) => { - console.log(`User ${event.data.name} logged in`) -}) -``` - -**That's it!** Cross-language pub/sub. - -## Event Types - -### Custom Events - -Your application-specific events: - -```go -// Emit from Go -app.Event.Emit("order-created", order) -app.Event.Emit("payment-processed", payment) -app.Event.Emit("notification", message) -``` - -```javascript -// Listen in JavaScript -Events.On("order-created", handleOrder) -Events.On("payment-processed", handlePayment) -Events.On("notification", showNotification) -``` - -### System Events - -Built-in OS and application events: - -```go -import "github.com/wailsapp/wails/v3/pkg/events" - -// Theme changes -app.Event.OnApplicationEvent(events.Common.ThemeChanged, func(e *application.ApplicationEvent) { - if e.Context().IsDarkMode() { - app.Logger.Info("Dark mode enabled") - } -}) - -// Application lifecycle -app.Event.OnApplicationEvent(events.Common.ApplicationStarted, func(e *application.ApplicationEvent) { - app.Logger.Info("Application started") -}) -``` - -### Window Events - -Window-specific events: - -```go -window.OnWindowEvent(events.Common.WindowFocus, func(e *application.WindowEvent) { - app.Logger.Info("Window focused") -}) - -window.OnWindowEvent(events.Common.WindowClosing, func(e *application.WindowEvent) { - app.Logger.Info("Window closing") -}) -``` - -## Emitting Events - -### From Go - -**Basic emit:** - -```go -app.Event.Emit("event-name", data) -``` - -**With different data types:** - -```go -// String -app.Event.Emit("message", "Hello") - -// Number -app.Event.Emit("count", 42) - -// Struct -app.Event.Emit("user", User{ID: 1, Name: "Alice"}) - -// Map -app.Event.Emit("config", map[string]interface{}{ - "theme": "dark", - "fontSize": 14, -}) - -// Array -app.Event.Emit("items", []string{"a", "b", "c"}) -``` - -**To specific window:** - -```go -window.EmitEvent("window-specific-event", data) -``` - -### From JavaScript - -```javascript -import { Emit } from '@wailsio/runtime' - -// Emit to Go -Emit("button-clicked", { buttonId: "submit" }) - -// Emit to all windows -Emit("broadcast-message", "Hello everyone") -``` - -## Listening to Events - -### In Go - -**Application events:** - -```go -app.Event.On("custom-event", func(e *application.CustomEvent) { - data := e.Data - // Handle event -}) -``` - -**With type assertion:** - -```go -app.Event.On("user-updated", func(e *application.CustomEvent) { - user := e.Data.(User) - app.Logger.Info("User updated", "name", user.Name) -}) -``` - -**Multiple handlers:** - -```go -// All handlers will be called -app.Event.On("order-created", logOrder) -app.Event.On("order-created", sendEmail) -app.Event.On("order-created", updateInventory) -``` - -### In JavaScript - -**Basic listener:** - -```javascript -import { Events } from '@wailsio/runtime' - -Events.On("event-name", (event) => { - console.log("Event received:", event.data) -}) -``` - -**With cleanup:** - -```javascript -const unsubscribe = Events.On("event-name", handleEvent) - -// Later, stop listening -unsubscribe() -``` - -**Multiple handlers:** - -```javascript -Events.On("data-updated", updateUI) -Events.On("data-updated", saveToCache) -Events.On("data-updated", logChange) -``` - -**One Time handlers:** - -```javascript -Events.Once("data-updated", updateVariable) -``` - -## System Events - -### Application Events - -**Common events (cross-platform):** - -```go -import "github.com/wailsapp/wails/v3/pkg/events" - -// Application started -app.Event.OnApplicationEvent(events.Common.ApplicationStarted, func(e *application.ApplicationEvent) { - app.Logger.Info("App started") -}) - -// Theme changed -app.Event.OnApplicationEvent(events.Common.ThemeChanged, func(e *application.ApplicationEvent) { - isDark := e.Context().IsDarkMode() - app.Event.Emit("theme-changed", isDark) -}) - -// File opened -app.Event.OnApplicationEvent(events.Common.ApplicationOpenedWithFile, func(e *application.ApplicationEvent) { - filePath := e.Context().OpenedFile() - openFile(filePath) -}) -``` - -**Platform-specific events:** - - - - ```go - // Application became active - app.Event.OnApplicationEvent(events.Mac.ApplicationDidBecomeActive, func(e *application.ApplicationEvent) { - app.Logger.Info("App became active") - }) - - // Application will terminate - app.Event.OnApplicationEvent(events.Mac.ApplicationWillTerminate, func(e *application.ApplicationEvent) { - cleanup() - }) - ``` - - - - ```go - // Power status changed - app.Event.OnApplicationEvent(events.Windows.APMPowerStatusChange, func(e *application.ApplicationEvent) { - app.Logger.Info("Power status changed") - }) - - // System suspending - app.Event.OnApplicationEvent(events.Windows.APMSuspend, func(e *application.ApplicationEvent) { - saveState() - }) - ``` - - - - ```go - // Application startup - app.Event.OnApplicationEvent(events.Linux.ApplicationStartup, func(e *application.ApplicationEvent) { - app.Logger.Info("App starting") - }) - - // Theme changed - app.Event.OnApplicationEvent(events.Linux.SystemThemeChanged, func(e *application.ApplicationEvent) { - updateTheme() - }) - ``` - - - -### Window Events - -**Common window events:** - -```go -// Window focus -window.OnWindowEvent(events.Common.WindowFocus, func(e *application.WindowEvent) { - app.Logger.Info("Window focused") -}) - -// Window blur -window.OnWindowEvent(events.Common.WindowBlur, func(e *application.WindowEvent) { - app.Logger.Info("Window blurred") -}) - -// Window closing -window.OnWindowEvent(events.Common.WindowClosing, func(e *application.WindowEvent) { - if hasUnsavedChanges() { - e.Cancel() // Prevent close - } -}) - -// Window closed -window.OnWindowEvent(events.Common.WindowClosed, func(e *application.WindowEvent) { - cleanup() -}) -``` - -## Event Hooks - -Hooks run **before** standard listeners and can **cancel** events: - -```go -// Hook - runs first, can cancel -window.RegisterHook(events.Common.WindowClosing, func(e *application.WindowEvent) { - if hasUnsavedChanges() { - result := showConfirmdialog("Unsaved changes. Close anyway?") - if result != "yes" { - e.Cancel() // Prevent window close - } - } -}) - -// Standard listener - runs after hooks -window.OnWindowEvent(events.Common.WindowClosing, func(e *application.WindowEvent) { - app.Logger.Info("Window closing") -}) -``` - -**Key differences:** - -| Feature | Hooks | Standard Listeners | -|---------|-------|-------------------| -| Execution order | First, in registration order | After hooks, no guaranteed order | -| Blocking | Synchronous, blocks next hook | Asynchronous, non-blocking | -| Can cancel | Yes | No (already propagated) | -| Use case | Control flow, validation | Logging, side effects | - -## Event Patterns - -### Pub/Sub Pattern - -```go -// Publisher (service) -type OrderService struct { - app *application.Application -} - -func (o *OrderService) CreateOrder(items []Item) (*Order, error) { - order := &Order{Items: items} - - if err := o.saveOrder(order); err != nil { - return nil, err - } - - // Publish event - o.app.Event.Emit("order-created", order) - - return order, nil -} - -// Subscribers -app.Event.On("order-created", func(e *application.CustomEvent) { - order := e.Data.(*Order) - sendConfirmationEmail(order) -}) - -app.Event.On("order-created", func(e *application.CustomEvent) { - order := e.Data.(*Order) - updateInventory(order) -}) - -app.Event.On("order-created", func(e *application.CustomEvent) { - order := e.Data.(*Order) - logOrder(order) -}) -``` - -### Request/Response Pattern - -```go -// Frontend requests data -Emit("get-user-data", { userId: 123 }) - -// Backend responds -app.Event.On("get-user-data", func(e *application.CustomEvent) { - data := e.Data.(map[string]interface{}) - userId := int(data["userId"].(float64)) - - user := getUserFromDB(userId) - - // Send response - app.Event.Emit("user-data-response", user) -}) -``` - -```javascript -// Frontend receives response -Events.On("user-data-response", (event) => { - const user = event.data - displayUser(user) -}) -``` - -**Note:** For request/response, **bindings are better**. Use events for notifications. - -### Broadcast Pattern - -```go -// Broadcast to all windows -app.Event.Emit("global-notification", "System update available") - -// Each window handles it -Events.On("global-notification", (event) => { - const message = event.data - showNotification(message) -}) -``` - -### Event Aggregation - -```go -type EventAggregator struct { - events []Event - mu sync.Mutex -} - -func (ea *EventAggregator) Add(event Event) { - ea.mu.Lock() - defer ea.mu.Unlock() - - ea.events = append(ea.events, event) - - // Emit batch every 100 events - if len(ea.events) >= 100 { - app.Event.Emit("event-batch", ea.events) - ea.events = nil - } -} -``` - -## Complete Example - -**Go:** - -```go -package main - -import ( - "github.com/wailsapp/wails/v3/pkg/application" - "github.com/wailsapp/wails/v3/pkg/events" -) - -type NotificationService struct { - app *application.Application -} - -func (n *NotificationService) Notify(message string) { - // Emit to all windows - n.app.Event.Emit("notification", map[string]interface{}{ - "message": message, - "timestamp": time.Now(), - }) -} - -func main() { - app := application.New(application.Options{ - Name: "Event Demo", - }) - - notifService := &NotificationService{app: app} - - // System events - app.Event.OnApplicationEvent(events.Common.ThemeChanged, func(e *application.ApplicationEvent) { - isDark := e.Context().IsDarkMode() - app.Event.Emit("theme-changed", isDark) - }) - - // Custom events from frontend - app.Event.On("user-action", func(e *application.CustomEvent) { - data := e.Data.(map[string]interface{}) - action := data["action"].(string) - - app.Logger.Info("User action", "action", action) - - // Respond - notifService.Notify("Action completed: " + action) - }) - - // Window events - window := app.Window.New() - - window.OnWindowEvent(events.Common.WindowFocus, func(e *application.WindowEvent) { - app.Event.Emit("window-focused", window.Name()) - }) - - window.RegisterHook(events.Common.WindowClosing, func(e *application.WindowEvent) { - // Confirm before close - app.Event.Emit("confirm-close", nil) - e.Cancel() // Wait for confirmation - }) - - app.Run() -} -``` - -**JavaScript:** - -```javascript -import { Events, Emit } from '@wailsio/runtime' - -// Listen for notifications -Events.On("notification", (event) => { - showNotification(event.data.message) -}) - -// Listen for theme changes -Events.On("theme-changed", (event) => { - const isDark = event.data - document.body.classList.toggle('dark', isDark) -}) - -// Listen for window focus -Events.On("window-focused", (event) => { - const windowName = event.data - console.log(`Window ${windowName} focused`) -}) - -// Handle close confirmation -Events.On("confirm-close", (event) => { - if (confirm("Close window?")) { - Emit("close-confirmed", true) - } -}) - -// Emit user actions -document.getElementById('button').addEventListener('click', () => { - Emit("user-action", { action: "button-clicked" }) -}) -``` - -## Best Practices - -### ✅ Do - -- **Use events for notifications** - One-way communication -- **Use bindings for requests** - Two-way communication -- **Keep event names consistent** - Use kebab-case -- **Document event data** - What fields are included? -- **Unsubscribe when done** - Prevent memory leaks -- **Use hooks for validation** - Control event flow - -### ❌ Don't - -- **Don't use events for RPC** - Use bindings instead -- **Don't emit too frequently** - Batch if needed -- **Don't block in handlers** - Keep them fast -- **Don't forget to unsubscribe** - Memory leaks -- **Don't use events for large data** - Use bindings -- **Don't create event loops** - A emits B, B emits A - -## Next Steps - - - - Create your own event types. - - [Learn More →](/features/events/custom) - - - - Common event patterns and best practices. - - [Learn More →](/features/events/patterns) - - - - Use bindings for request/response. - - [Learn More →](/features/bindings/methods) - - - - Handle window lifecycle events. - - [Learn More →](/features/windows/events) - - - ---- - -**Questions?** Ask in [Discord](https://discord.gg/JDdSxwjhGf) or check the [event examples](https://github.com/wailsapp/wails/tree/v3-alpha/v3/examples/events). diff --git a/docs/src/content/docs/features/keyboard/shortcuts.mdx b/docs/src/content/docs/features/keyboard/shortcuts.mdx deleted file mode 100644 index ba83603f8..000000000 --- a/docs/src/content/docs/features/keyboard/shortcuts.mdx +++ /dev/null @@ -1,438 +0,0 @@ ---- -title: Keyboard Shortcuts -description: Register global keyboard shortcuts for quick access to functionality -sidebar: - order: 1 ---- - -import { Tabs, TabItem } from "@astrojs/starlight/components"; - -Wails provides a powerful key binding system that allows you to register global keyboard shortcuts that work across all windows in your application. This enables users to quickly access functionality without navigating through menus. - -## Accessing the Key Binding Manager - -The key binding manager is accessed through the `KeyBindings` property on your application instance: - -```go -app := application.New(application.Options{ - Name: "Keyboard Shortcuts Demo", -}) - -// Access the key binding manager -keyBindings := app.KeyBinding -``` - -## Adding Key Bindings - -### Basic Key Binding - -Register a simple keyboard shortcut: - -```go -app.KeyBinding.Add("Ctrl+S", func(window application.Window) { - // Handle save action - app.Logger.Info("Save shortcut triggered") - // Perform save operation... -}) -``` - -### Multiple Key Bindings - -Register multiple shortcuts for common operations: - -```go -// File operations -app.KeyBinding.Add("Ctrl+N", func(window application.Window) { - // New file - window.EmitEvent("file:new", nil) -}) - -app.KeyBinding.Add("Ctrl+O", func(window application.Window) { - // Open file - dialog := app.Dialog.OpenFile() - if file, err := dialog.PromptForSingleSelection(); err == nil { - window.EmitEvent("file:open", file) - } -}) - -app.KeyBinding.Add("Ctrl+S", func(window application.Window) { - // Save file - window.EmitEvent("file:save", nil) -}) - -// Edit operations -app.KeyBinding.Add("Ctrl+Z", func(window application.Window) { - // Undo - window.EmitEvent("edit:undo", nil) -}) - -app.KeyBinding.Add("Ctrl+Y", func(window application.Window) { - // Redo (Windows/Linux) - window.EmitEvent("edit:redo", nil) -}) - -app.KeyBinding.Add("Cmd+Shift+Z", func(window application.Window) { - // Redo (macOS) - window.EmitEvent("edit:redo", nil) -}) -``` - -## Key Binding Accelerators - -### Accelerator Format - -Key bindings use a standard accelerator format with modifiers and keys: - -```go -// Modifier keys -"Ctrl+S" // Control + S -"Cmd+S" // Command + S (macOS) -"Alt+F4" // Alt + F4 -"Shift+Ctrl+Z" // Shift + Control + Z - -// Function keys -"F1" // F1 key -"Ctrl+F5" // Control + F5 - -// Special keys -"Escape" // Escape key -"Enter" // Enter key -"Space" // Spacebar -"Tab" // Tab key -"Backspace" // Backspace key -"Delete" // Delete key - -// Arrow keys -"Up" // Up arrow -"Down" // Down arrow -"Left" // Left arrow -"Right" // Right arrow -``` - -### Platform-Specific Accelerators - -Handle platform differences for common shortcuts: - -```go -import "runtime" - -// Cross-platform save shortcut -if runtime.GOOS == "darwin" { - app.KeyBinding.Add("Cmd+S", saveHandler) -} else { - app.KeyBinding.Add("Ctrl+S", saveHandler) -} - -// Or register both -app.KeyBinding.Add("Ctrl+S", saveHandler) -app.KeyBinding.Add("Cmd+S", saveHandler) -``` - -## Managing Key Bindings - -### Removing Key Bindings - -Remove key bindings when they're no longer needed: - -```go -// Remove a specific key binding -app.KeyBinding.Remove("Ctrl+S") - -// Example: Temporary key binding for a modal -app.KeyBinding.Add("Escape", func(window application.Window) { - // Close modal - window.EmitEvent("modal:close", nil) - // Remove this temporary binding - app.KeyBinding.Remove("Escape") -}) -``` - -### Getting All Key Bindings - -Retrieve all registered key bindings: - -```go -allBindings := app.KeyBinding.GetAll() -for _, binding := range allBindings { - app.Logger.Info("Key binding", "accelerator", binding.Accelerator) -} -``` - -## Advanced Usage - -### Context-Aware Key Bindings - -Make key bindings context-aware by checking application state: - -```go -app.KeyBinding.Add("Ctrl+S", func(window application.Window) { - // Check current application state - if isEditMode() { - // Save document - saveDocument() - } else if isInSettings() { - // Save settings - saveSettings() - } else { - app.Logger.Info("Save not available in current context") - } -}) -``` - -### Window-Specific Actions - -Key bindings receive the active window, allowing window-specific behavior: - -```go -app.KeyBinding.Add("F11", func(window application.Window) { - // Toggle fullscreen for the active window - if window.Fullscreen() { - window.SetFullscreen(false) - } else { - window.SetFullscreen(true) - } -}) - -app.KeyBinding.Add("Ctrl+W", func(window application.Window) { - // Close the active window - window.Close() -}) -``` - -### Dynamic Key Binding Management - -Dynamically add and remove key bindings based on application state: - -```go -func enableEditMode() { - // Add edit-specific key bindings - app.KeyBinding.Add("Ctrl+B", func(window application.Window) { - window.EmitEvent("format:bold", nil) - }) - - app.KeyBinding.Add("Ctrl+I", func(window application.Window) { - window.EmitEvent("format:italic", nil) - }) - - app.KeyBinding.Add("Ctrl+U", func(window application.Window) { - window.EmitEvent("format:underline", nil) - }) -} - -func disableEditMode() { - // Remove edit-specific key bindings - app.KeyBinding.Remove("Ctrl+B") - app.KeyBinding.Remove("Ctrl+I") - app.KeyBinding.Remove("Ctrl+U") -} -``` - -## Platform Considerations - - - - - On macOS: - - - Use `Cmd` instead of `Ctrl` for standard shortcuts - - `Cmd+Q` is typically reserved for quitting the application - - `Cmd+H` hides the application - - `Cmd+M` minimizes windows - - Consider standard macOS keyboard shortcuts - - Common macOS patterns: - ```go - app.KeyBinding.Add("Cmd+N", newFileHandler) // New - app.KeyBinding.Add("Cmd+O", openFileHandler) // Open - app.KeyBinding.Add("Cmd+S", saveFileHandler) // Save - app.KeyBinding.Add("Cmd+Z", undoHandler) // Undo - app.KeyBinding.Add("Cmd+Shift+Z", redoHandler) // Redo - app.KeyBinding.Add("Cmd+C", copyHandler) // Copy - app.KeyBinding.Add("Cmd+V", pasteHandler) // Paste - ``` - - - - - - On Windows: - - - Use `Ctrl` for standard shortcuts - - `Alt+F4` closes applications - - `F1` typically opens help - - Consider Windows keyboard conventions - - Common Windows patterns: - ```go - app.KeyBinding.Add("Ctrl+N", newFileHandler) // New - app.KeyBinding.Add("Ctrl+O", openFileHandler) // Open - app.KeyBinding.Add("Ctrl+S", saveFileHandler) // Save - app.KeyBinding.Add("Ctrl+Z", undoHandler) // Undo - app.KeyBinding.Add("Ctrl+Y", redoHandler) // Redo - app.KeyBinding.Add("Ctrl+C", copyHandler) // Copy - app.KeyBinding.Add("Ctrl+V", pasteHandler) // Paste - app.KeyBinding.Add("F1", helpHandler) // Help - ``` - - - - - - On Linux: - - - Generally follows Windows conventions with `Ctrl` - - May vary by desktop environment - - Consider GNOME/KDE standard shortcuts - - Some desktop environments reserve certain shortcuts - - Common Linux patterns: - ```go - app.KeyBinding.Add("Ctrl+N", newFileHandler) // New - app.KeyBinding.Add("Ctrl+O", openFileHandler) // Open - app.KeyBinding.Add("Ctrl+S", saveFileHandler) // Save - app.KeyBinding.Add("Ctrl+Z", undoHandler) // Undo - app.KeyBinding.Add("Ctrl+Shift+Z", redoHandler) // Redo - app.KeyBinding.Add("Ctrl+C", copyHandler) // Copy - app.KeyBinding.Add("Ctrl+V", pasteHandler) // Paste - ``` - - - - -## Best Practices - -1. **Use Standard Shortcuts**: Follow platform conventions for common operations: - ```go - // Cross-platform save - if runtime.GOOS == "darwin" { - app.KeyBinding.Add("Cmd+S", saveHandler) - } else { - app.KeyBinding.Add("Ctrl+S", saveHandler) - } - ``` - -2. **Provide Visual Feedback**: Let users know when shortcuts are triggered: - ```go - app.KeyBinding.Add("Ctrl+S", func(window application.Window) { - saveDocument() - // Show brief notification - window.EmitEvent("notification:show", "Document saved") - }) - ``` - -3. **Handle Conflicts**: Be careful not to override important system shortcuts: - ```go - // Avoid overriding system shortcuts like: - // Ctrl+Alt+Del (Windows) - // Cmd+Space (macOS Spotlight) - // Alt+Tab (Window switching) - ``` - -4. **Document Shortcuts**: Provide help or documentation for available shortcuts: - ```go - app.KeyBinding.Add("F1", func(window application.Window) { - // Show help dialog with available shortcuts - showKeyboardShortcutsHelp() - }) - ``` - -5. **Clean Up**: Remove temporary key bindings when they're no longer needed: - ```go - func enterEditMode() { - app.KeyBinding.Add("Escape", exitEditModeHandler) - } - - func exitEditModeHandler(window application.Window) { - exitEditMode() - app.KeyBinding.Remove("Escape") // Clean up temporary binding - } - ``` - -## Complete Example - -Here's a complete example of a text editor with keyboard shortcuts: - -```go -package main - -import ( - "runtime" - "github.com/wailsapp/wails/v3/pkg/application" -) - -func main() { - app := application.New(application.Options{ - Name: "Text Editor with Shortcuts", - }) - - // File operations - if runtime.GOOS == "darwin" { - app.KeyBinding.Add("Cmd+N", func(window application.Window) { - window.EmitEvent("file:new", nil) - }) - app.KeyBinding.Add("Cmd+O", func(window application.Window) { - openFile(app, window) - }) - app.KeyBinding.Add("Cmd+S", func(window application.Window) { - window.EmitEvent("file:save", nil) - }) - } else { - app.KeyBinding.Add("Ctrl+N", func(window application.Window) { - window.EmitEvent("file:new", nil) - }) - app.KeyBinding.Add("Ctrl+O", func(window application.Window) { - openFile(app, window) - }) - app.KeyBinding.Add("Ctrl+S", func(window application.Window) { - window.EmitEvent("file:save", nil) - }) - } - - // View operations - app.KeyBinding.Add("F11", func(window application.Window) { - window.SetFullscreen(!window.Fullscreen()) - }) - - app.KeyBinding.Add("F1", func(window application.Window) { - showKeyboardShortcuts(window) - }) - - // Create main window - window := app.Window.New() - window.SetTitle("Text Editor") - - err := app.Run() - if err != nil { - panic(err) - } -} - -func openFile(app *application.App, window application.Window) { - dialog := app.Dialog.OpenFile() - dialog.AddFilter("Text Files", "*.txt;*.md") - - if file, err := dialog.PromptForSingleSelection(); err == nil { - window.EmitEvent("file:open", file) - } -} - -func showKeyboardShortcuts(window application.Window) { - shortcuts := ` -Keyboard Shortcuts: -- Ctrl/Cmd+N: New file -- Ctrl/Cmd+O: Open file -- Ctrl/Cmd+S: Save file -- F11: Toggle fullscreen -- F1: Show this help -` - window.EmitEvent("help:show", shortcuts) -} -``` - -:::tip[Pro Tip] -Test your key bindings on all target platforms to ensure they work correctly and don't conflict with system shortcuts. -::: - -:::danger[Warning] -Be careful not to override critical system shortcuts. Some key combinations are reserved by the operating system and cannot be captured by applications. -::: diff --git a/docs/src/content/docs/features/menus/application.mdx b/docs/src/content/docs/features/menus/application.mdx deleted file mode 100644 index 26b7e71a0..000000000 --- a/docs/src/content/docs/features/menus/application.mdx +++ /dev/null @@ -1,683 +0,0 @@ ---- -title: Application Menus -description: Create native menu bars for your desktop application -sidebar: - order: 1 ---- - -import { Card, CardGrid, Tabs, TabItem } from "@astrojs/starlight/components"; - -## The Problem - -Professional desktop applications need menu bars—File, Edit, View, Help. But menus work differently on each platform: -- **macOS**: Global menu bar at top of screen -- **Windows**: Menu bar in window title bar -- **Linux**: Varies by desktop environment - -Building platform-appropriate menus manually is tedious and error-prone. - -## The Wails Solution - -Wails provides a **unified API** that creates platform-native menus automatically. Write once, get native behaviour on all platforms. - -{/* VISUAL PLACEHOLDER: Menu Bar Comparison -Description: Three screenshots side-by-side showing the same Wails menu on: -1. macOS - Global menu bar at top of screen with app name -2. Windows - Menu bar in window title bar -3. Linux (GNOME) - Menu bar in window -All showing identical menu structure: File, Edit, View, Tools, Help -Style: Clean screenshots with subtle borders, labels indicating platform -*/} - -## Quick Start - -```go -package main - -import ( - "runtime" - "github.com/wailsapp/wails/v3/pkg/application" -) - -func main() { - app := application.New(application.Options{ - Name: "My App", - }) - - // Create menu - menu := app.NewMenu() - - // Add standard menus (platform-appropriate) - if runtime.GOOS == "darwin" { - menu.AddRole(application.AppMenu) // macOS only - } - menu.AddRole(application.FileMenu) - menu.AddRole(application.EditMenu) - menu.AddRole(application.WindowMenu) - menu.AddRole(application.HelpMenu) - - // Set the application menu - app.Menu.Set(menu) - - // Create window with UseApplicationMenu to inherit the menu on Windows/Linux - app.Window.NewWithOptions(application.WebviewWindowOptions{ - UseApplicationMenu: true, - }) - - app.Run() -} -``` - -**That's it!** You now have platform-native menus with standard items. The `UseApplicationMenu` option ensures Windows and Linux windows display the menu without additional code. - -## Creating Menus - -### Basic Menu Creation - -```go -// Create a new menu -menu := app.NewMenu() - -// Add a top-level menu -fileMenu := menu.AddSubmenu("File") - -// Add menu items -fileMenu.Add("New").OnClick(func(ctx *application.Context) { - // Handle New -}) - -fileMenu.Add("Open").OnClick(func(ctx *application.Context) { - // Handle Open -}) - -fileMenu.AddSeparator() - -fileMenu.Add("Quit").OnClick(func(ctx *application.Context) { - app.Quit() -}) -``` - -### Setting the Menu - -**Recommended approach** — Use `UseApplicationMenu` for cross-platform consistency: - -```go -// Set the application menu once -app.Menu.Set(menu) - -// Create windows that inherit the menu on Windows/Linux -app.Window.NewWithOptions(application.WebviewWindowOptions{ - UseApplicationMenu: true, // Window uses the app menu -}) -``` - -This approach: -- On **macOS**: The menu appears at the top of screen (standard behaviour) -- On **Windows/Linux**: Each window with `UseApplicationMenu: true` displays the app menu - -**Platform-specific details:** - - - - **Global menu bar** (one per application): - - ```go - app.Menu.Set(menu) - ``` - - The menu appears at the top of the screen and persists even when all windows are closed. The `UseApplicationMenu` option has no effect on macOS since all apps use the global menu. - - - - **Per-window menu bar**: - - ```go - // Option 1: Use application menu (recommended) - app.Menu.Set(menu) - window := app.Window.NewWithOptions(application.WebviewWindowOptions{ - UseApplicationMenu: true, - }) - - // Option 2: Set menu directly on window - window.SetMenu(menu) - ``` - - Each window can have its own menu, or inherit the application menu. The menu appears in the window's title bar. - - - - **Per-window menu bar** (usually): - - ```go - // Option 1: Use application menu (recommended) - app.Menu.Set(menu) - window := app.Window.NewWithOptions(application.WebviewWindowOptions{ - UseApplicationMenu: true, - }) - - // Option 2: Set menu directly on window - window.SetMenu(menu) - ``` - - Behaviour varies by desktop environment. Some (like Unity) support global menus. - - - -:::tip[Simplify Cross-Platform Menus] -Using `UseApplicationMenu: true` eliminates the need for platform-specific code like: -```go -// Old approach - no longer needed -if runtime.GOOS == "darwin" { - app.Menu.Set(menu) -} else { - window.SetMenu(menu) -} -``` -::: - -**Per-window custom menus:** - -If a window needs a different menu than the application menu, set it directly: - -```go -window.SetMenu(customMenu) // Overrides UseApplicationMenu -``` - -## Menu Roles - -Wails provides **predefined menu roles** that create platform-appropriate menu structures automatically. - -### Available Roles - -| Role | Description | Platform Notes | -|------|-------------|----------------| -| `AppMenu` | Application menu with About, Preferences, Quit | **macOS only** | -| `FileMenu` | File operations (New, Open, Save, etc.) | All platforms | -| `EditMenu` | Text editing (Undo, Redo, Cut, Copy, Paste) | All platforms | -| `WindowMenu` | Window management (Minimise, Zoom, etc.) | All platforms | -| `HelpMenu` | Help and information | All platforms | - -### Using Roles - -```go -menu := app.NewMenu() - -// macOS: Add application menu -if runtime.GOOS == "darwin" { - menu.AddRole(application.AppMenu) -} - -// All platforms: Add standard menus -menu.AddRole(application.FileMenu) -menu.AddRole(application.EditMenu) -menu.AddRole(application.WindowMenu) -menu.AddRole(application.HelpMenu) -``` - -**What you get:** - - - - **AppMenu** (with app name): - - About [App Name] - - Preferences... (⌘,) - - --- - - Services - - --- - - Hide [App Name] (⌘H) - - Hide Others (⌥⌘H) - - Show All - - --- - - Quit [App Name] (⌘Q) - - **FileMenu**: - - New (⌘N) - - Open... (⌘O) - - --- - - Close Window (⌘W) - - **EditMenu**: - - Undo (⌘Z) - - Redo (⇧⌘Z) - - --- - - Cut (⌘X) - - Copy (⌘C) - - Paste (⌘V) - - Select All (⌘A) - - **WindowMenu**: - - Minimise (⌘M) - - Zoom - - --- - - Bring All to Front - - **HelpMenu**: - - [App Name] Help - - - - **FileMenu**: - - New (Ctrl+N) - - Open... (Ctrl+O) - - --- - - Exit (Alt+F4) - - **EditMenu**: - - Undo (Ctrl+Z) - - Redo (Ctrl+Y) - - --- - - Cut (Ctrl+X) - - Copy (Ctrl+C) - - Paste (Ctrl+V) - - Select All (Ctrl+A) - - **WindowMenu**: - - Minimise - - Maximise - - **HelpMenu**: - - About [App Name] - - - - Similar to Windows, but keyboard shortcuts may vary by desktop environment. - - - -### Customising Role Menus - -Add items to role menus: - -```go -fileMenu := menu.AddRole(application.FileMenu) - -// Add custom items -fileMenu.Add("Import...").OnClick(handleImport) -fileMenu.Add("Export...").OnClick(handleExport) -``` - -## Custom Menus - -Create your own menus for application-specific features: - -```go -// Add a custom top-level menu -toolsMenu := menu.AddSubmenu("Tools") - -// Add items -toolsMenu.Add("Settings").OnClick(func(ctx *application.Context) { - showSettingsWindow() -}) - -toolsMenu.AddSeparator() - -// Add checkbox -toolsMenu.AddCheckbox("Dark Mode", false).OnClick(func(ctx *application.Context) { - isDark := ctx.ClickedMenuItem().Checked() - setTheme(isDark) -}) - -// Add radio group -toolsMenu.AddRadio("Small", true).OnClick(handleFontSize) -toolsMenu.AddRadio("Medium", false).OnClick(handleFontSize) -toolsMenu.AddRadio("Large", false).OnClick(handleFontSize) - -// Add submenu -advancedMenu := toolsMenu.AddSubmenu("Advanced") -advancedMenu.Add("Configure...").OnClick(showAdvancedSettings) -``` - -**For more menu item types**, see [Menu Reference](/features/menus/reference). - -## Dynamic Menus - -Update menus based on application state: - -### Enable/Disable Items - -```go -var saveMenuItem *application.MenuItem - -func createMenu() { - menu := app.NewMenu() - fileMenu := menu.AddSubmenu("File") - - saveMenuItem = fileMenu.Add("Save") - saveMenuItem.SetEnabled(false) // Initially disabled - saveMenuItem.OnClick(handleSave) - - app.SetMenu(menu) -} - -func onDocumentChanged() { - saveMenuItem.SetEnabled(hasUnsavedChanges()) - menu.Update() // Important! -} -``` - -:::caution[Always Call menu.Update()] -After changing menu state (enable/disable, label, checked), **always call `menu.Update()`**. This is especially critical on Windows where menus are reconstructed. - -See [Menu Reference](/features/menus/reference#enabled-state) for details. -::: - -### Change Labels - -```go -updateMenuItem := menu.Add("Check for Updates") - -updateMenuItem.OnClick(func(ctx *application.Context) { - updateMenuItem.SetLabel("Checking...") - menu.Update() - - checkForUpdates() - - updateMenuItem.SetLabel("Check for Updates") - menu.Update() -}) -``` - -### Rebuild Menus - -For major changes, rebuild the entire menu: - -```go -func rebuildFileMenu() { - menu := app.NewMenu() - fileMenu := menu.AddSubmenu("File") - - fileMenu.Add("New").OnClick(handleNew) - fileMenu.Add("Open").OnClick(handleOpen) - - // Add recent files dynamically - if hasRecentFiles() { - recentMenu := fileMenu.AddSubmenu("Open Recent") - for _, file := range getRecentFiles() { - filePath := file // Capture for closure - recentMenu.Add(filepath.Base(file)).OnClick(func(ctx *application.Context) { - openFile(filePath) - }) - } - recentMenu.AddSeparator() - recentMenu.Add("Clear Recent").OnClick(clearRecentFiles) - } - - fileMenu.AddSeparator() - fileMenu.Add("Quit").OnClick(func(ctx *application.Context) { - app.Quit() - }) - - app.SetMenu(menu) -} -``` - -## Window Control from Menus - -Menu items can control windows: - -```go -viewMenu := menu.AddSubmenu("View") - -// Toggle fullscreen -viewMenu.Add("Toggle Fullscreen").OnClick(func(ctx *application.Context) { - window := app.GetWindowByName("main") - window.SetFullscreen(!window.IsFullscreen()) -}) - -// Zoom controls -viewMenu.Add("Zoom In").SetAccelerator("CmdOrCtrl++").OnClick(func(ctx *application.Context) { - // Increase zoom -}) - -viewMenu.Add("Zoom Out").SetAccelerator("CmdOrCtrl+-").OnClick(func(ctx *application.Context) { - // Decrease zoom -}) - -viewMenu.Add("Reset Zoom").SetAccelerator("CmdOrCtrl+0").OnClick(func(ctx *application.Context) { - // Reset zoom -}) -``` - -**Get the active window:** - -```go -menuItem.OnClick(func(ctx *application.Context) { - window := application.ContextWindow(ctx) - // Use window -}) -``` - -## Platform-Specific Considerations - -### macOS - -**Menu bar behaviour:** -- Appears at **top of screen** (global) -- Persists when all windows closed -- First menu is **always the application menu** -- Use `menu.AddRole(application.AppMenu)` for standard items - -**Standard locations:** -- **About**: Application menu -- **Preferences**: Application menu (⌘,) -- **Quit**: Application menu (⌘Q) -- **Help**: Help menu - -**Example:** - -```go -if runtime.GOOS == "darwin" { - menu.AddRole(application.AppMenu) // Adds About, Preferences, Quit - - // Don't add Quit to File menu on macOS - // Don't add About to Help menu on macOS -} -``` - -### Windows - -**Menu bar behaviour:** -- Appears in **window title bar** -- Each window has its own menu -- No application menu - -**Standard locations:** -- **Exit**: File menu (Alt+F4) -- **Settings**: Tools or Edit menu -- **About**: Help menu - -**Example:** - -```go -if runtime.GOOS == "windows" { - fileMenu := menu.AddRole(application.FileMenu) - // Exit is added automatically - - helpMenu := menu.AddRole(application.HelpMenu) - // About is added automatically -} -``` - -### Linux - -**Menu bar behaviour:** -- Usually per-window (like Windows) -- Some DEs support global menus (Unity, GNOME with extension) -- Appearance varies by desktop environment - -**Best practice:** Follow Windows conventions, test on target DEs. - -## Complete Example - -Here's a production-ready menu structure: - -```go -package main - -import ( - "runtime" - "github.com/wailsapp/wails/v3/pkg/application" -) - -func main() { - app := application.New(application.Options{ - Name: "My Application", - }) - - // Create and set menu - createMenu(app) - - // Create main window with UseApplicationMenu for cross-platform menu support - app.Window.NewWithOptions(application.WebviewWindowOptions{ - UseApplicationMenu: true, - }) - - app.Run() -} - -func createMenu(app *application.Application) { - menu := app.NewMenu() - - // Platform-specific application menu (macOS only) - if runtime.GOOS == "darwin" { - menu.AddRole(application.AppMenu) - } - - // File menu - fileMenu := menu.AddRole(application.FileMenu) - fileMenu.Add("Import...").SetAccelerator("CmdOrCtrl+I").OnClick(handleImport) - fileMenu.Add("Export...").SetAccelerator("CmdOrCtrl+E").OnClick(handleExport) - - // Edit menu - menu.AddRole(application.EditMenu) - - // View menu - viewMenu := menu.AddSubmenu("View") - viewMenu.Add("Toggle Fullscreen").SetAccelerator("F11").OnClick(toggleFullscreen) - viewMenu.AddSeparator() - viewMenu.AddCheckbox("Show Sidebar", true).OnClick(toggleSidebar) - viewMenu.AddCheckbox("Show Toolbar", true).OnClick(toggleToolbar) - - // Tools menu - toolsMenu := menu.AddSubmenu("Tools") - - // Settings location varies by platform - if runtime.GOOS == "darwin" { - // On macOS, Preferences is in Application menu (added by AppMenu role) - } else { - toolsMenu.Add("Settings").SetAccelerator("CmdOrCtrl+,").OnClick(showSettings) - } - - toolsMenu.AddSeparator() - toolsMenu.AddCheckbox("Dark Mode", false).OnClick(toggleDarkMode) - - // Window menu - menu.AddRole(application.WindowMenu) - - // Help menu - helpMenu := menu.AddRole(application.HelpMenu) - helpMenu.Add("Documentation").OnClick(openDocumentation) - - // About location varies by platform - if runtime.GOOS == "darwin" { - // On macOS, About is in Application menu (added by AppMenu role) - } else { - helpMenu.AddSeparator() - helpMenu.Add("About").OnClick(showAbout) - } - - // Set the application menu - app.Menu.Set(menu) -} - -func handleImport(ctx *application.Context) { - // Implementation -} - -func handleExport(ctx *application.Context) { - // Implementation -} - -func toggleFullscreen(ctx *application.Context) { - window := application.ContextWindow(ctx) - window.SetFullscreen(!window.IsFullscreen()) -} - -func toggleSidebar(ctx *application.Context) { - // Implementation -} - -func toggleToolbar(ctx *application.Context) { - // Implementation -} - -func showSettings(ctx *application.Context) { - // Implementation -} - -func toggleDarkMode(ctx *application.Context) { - isDark := ctx.ClickedMenuItem().Checked() - // Apply theme -} - -func openDocumentation(ctx *application.Context) { - // Open browser -} - -func showAbout(ctx *application.Context) { - // Show about dialog -} -``` - -## Best Practices - -### ✅ Do - -- **Use menu roles** for standard menus (File, Edit, etc.) -- **Follow platform conventions** for menu structure -- **Add keyboard shortcuts** to common actions -- **Call menu.Update()** after changing menu state -- **Test on all platforms** - behaviour varies -- **Keep menus shallow** - 2-3 levels maximum -- **Use clear labels** - "Save Project" not "Save" - -### ❌ Don't - -- **Don't hardcode platform shortcuts** - Use `CmdOrCtrl` -- **Don't put Quit in File menu on macOS** - It's in Application menu -- **Don't put About in Help menu on macOS** - It's in Application menu -- **Don't forget menu.Update()** - Menus won't work properly -- **Don't nest too deeply** - Users get lost -- **Don't use jargon** - Keep labels user-friendly - -## Next Steps - - - - Complete reference for menu item types and properties. - - [Learn More →](/features/menus/reference) - - - - Create right-click context menus. - - [Learn More →](/features/menus/context) - - - - Add system tray/menu bar integration. - - [Learn More →](/features/menus/systray) - - - - Common menu patterns and best practices. - - [Learn More →](/guides/patterns/menus) - - - ---- - -**Questions?** Ask in [Discord](https://discord.gg/JDdSxwjhGf) or check the [menu example](https://github.com/wailsapp/wails/tree/v3-alpha/v3/examples/menu). diff --git a/docs/src/content/docs/features/menus/context.mdx b/docs/src/content/docs/features/menus/context.mdx deleted file mode 100644 index ab7eb630a..000000000 --- a/docs/src/content/docs/features/menus/context.mdx +++ /dev/null @@ -1,728 +0,0 @@ ---- -title: Context Menus -description: Create right-click context menus for your application -sidebar: - order: 2 ---- - -import { Card, CardGrid, Tabs, TabItem } from "@astrojs/starlight/components"; - -## The Problem - -Users expect right-click menus with context-specific actions. Different elements need different menus: -- **Text**: Cut, Copy, Paste -- **Images**: Save, Copy, Open -- **Custom elements**: Application-specific actions - -Building context menus manually means handling mouse events, positioning, and platform differences. - -## The Wails Solution - -Wails provides **declarative context menus** using CSS properties. Associate menus with HTML elements, pass data, and handle clicks—all with native platform behaviour. - -## Quick Start - -**Go code:** - -```go -// Create context menu -contextMenu := app.NewContextMenu() -contextMenu.Add("Cut").OnClick(handleCut) -contextMenu.Add("Copy").OnClick(handleCopy) -contextMenu.Add("Paste").OnClick(handlePaste) - -// Register with ID -app.RegisterContextMenu("editor-menu", contextMenu) -``` - -**HTML:** - -```html - -``` - -**That's it!** Right-clicking the textarea shows your custom menu. - -## Creating Context Menus - -### Basic Context Menu - -```go -// Create menu -contextMenu := app.NewContextMenu() - -// Add items -contextMenu.Add("Cut").SetAccelerator("CmdOrCtrl+X").OnClick(func(ctx *application.Context) { - // Handle cut -}) - -contextMenu.Add("Copy").SetAccelerator("CmdOrCtrl+C").OnClick(func(ctx *application.Context) { - // Handle copy -}) - -contextMenu.Add("Paste").SetAccelerator("CmdOrCtrl+V").OnClick(func(ctx *application.Context) { - // Handle paste -}) - -// Register with unique ID -app.RegisterContextMenu("text-menu", contextMenu) -``` - -**Menu ID:** Must be unique. Used to associate menu with HTML elements. - -### With Submenus - -```go -contextMenu := app.NewContextMenu() - -// Add regular items -contextMenu.Add("Open").OnClick(handleOpen) -contextMenu.Add("Delete").OnClick(handleDelete) - -contextMenu.AddSeparator() - -// Add submenu -exportMenu := contextMenu.AddSubmenu("Export As") -exportMenu.Add("PNG").OnClick(exportPNG) -exportMenu.Add("JPEG").OnClick(exportJPEG) -exportMenu.Add("SVG").OnClick(exportSVG) - -app.RegisterContextMenu("image-menu", contextMenu) -``` - -### With Checkboxes and Radio Groups - -```go -contextMenu := app.NewContextMenu() - -// Checkbox -contextMenu.AddCheckbox("Show Grid", true).OnClick(func(ctx *application.Context) { - showGrid := ctx.ClickedMenuItem().Checked() - // Toggle grid -}) - -contextMenu.AddSeparator() - -// Radio group -contextMenu.AddRadio("Small", false).OnClick(handleSize) -contextMenu.AddRadio("Medium", true).OnClick(handleSize) -contextMenu.AddRadio("Large", false).OnClick(handleSize) - -app.RegisterContextMenu("view-menu", contextMenu) -``` - -**For all menu item types**, see [Menu Reference](/features/menus/reference). - -## Associating with HTML Elements - -Use CSS custom properties to attach context menus: - -### Basic Association - -```html -
      - Right-click me! -
      -``` - -**CSS property:** `--custom-contextmenu: ` - -### With Context Data - -Pass data from HTML to Go: - -```html -
      - Right-click this file -
      -``` - -**Go handler:** - -```go -contextMenu := app.NewContextMenu() -contextMenu.Add("Open").OnClick(func(ctx *application.Context) { - fileID := ctx.ContextMenuData() // "file-123" - openFile(fileID) -}) - -app.RegisterContextMenu("file-menu", contextMenu) -``` - -**CSS properties:** -- `--custom-contextmenu: ` - Which menu to show -- `--custom-contextmenu-data: ` - Data to pass to handlers - -### Dynamic Data - -Generate data dynamically in JavaScript: - -```html -
      - File.txt -
      - - -``` - -### Multiple Elements, Same Menu - -```html -
      - Document.pdf -
      - -
      - Image.png -
      - -
      - Video.mp4 -
      -``` - -**One menu, different data for each element.** - -## Context Data - -### Accessing Context Data - -```go -contextMenu.Add("Process").OnClick(func(ctx *application.Context) { - data := ctx.ContextMenuData() // Get data from HTML - - // Use the data - processItem(data) -}) -``` - -**Data type:** Always `string`. Parse as needed. - -### Passing Complex Data - -Use JSON for complex data: - -```html -
      - Image.png -
      -``` - -**Go handler:** - -```go -import "encoding/json" - -type ItemData struct { - ID int `json:"id"` - Type string `json:"type"` -} - -contextMenu.Add("Process").OnClick(func(ctx *application.Context) { - dataStr := ctx.ContextMenuData() - - var data ItemData - if err := json.Unmarshal([]byte(dataStr), &data); err != nil { - log.Printf("Invalid data: %v", err) - return - } - - processItem(data.ID, data.Type) -}) -``` - -:::caution[Security] -**Always validate context data** from the frontend. Users can manipulate CSS properties, so treat data as untrusted input. -::: - -### Validation Example - -```go -contextMenu.Add("Delete").OnClick(func(ctx *application.Context) { - fileID := ctx.ContextMenuData() - - // Validate - if !isValidFileID(fileID) { - log.Printf("Invalid file ID: %s", fileID) - return - } - - // Check permissions - if !canDeleteFile(fileID) { - showError("Permission denied") - return - } - - // Safe to proceed - deleteFile(fileID) -}) -``` - -## Default Context Menu - -The WebView provides a built-in context menu for standard operations (copy, paste, inspect). Control it with `--default-contextmenu`: - -### Hide Default Menu - -```html -
      - No default menu here -
      -``` - -**Use case:** Custom UI elements where default menu doesn't make sense. - -### Show Default Menu - -```html -
      - Default menu always shown -
      -``` - -**Use case:** Text areas, input fields, editable content. - -### Auto (Smart) Mode - -```html -
      - Smart context menu -
      -``` - -**Default behaviour.** Shows default menu when: -- Text is selected -- In text input fields -- In editable content (`contenteditable`) - -Hides default menu otherwise. - -### Combining Custom and Default - -```html - - -``` - -**Behaviour:** -1. Custom menu shows first -2. If custom menu is empty or not found, default menu shows -3. Both can coexist (platform-dependent) - -## Dynamic Context Menus - -Update menus based on application state: - -### Enable/Disable Items - -```go -var cutMenuItem *application.MenuItem -var copyMenuItem *application.MenuItem - -func createContextMenu() { - contextMenu := app.NewContextMenu() - - cutMenuItem = contextMenu.Add("Cut") - cutMenuItem.SetEnabled(false) // Initially disabled - cutMenuItem.OnClick(handleCut) - - copyMenuItem = contextMenu.Add("Copy") - copyMenuItem.SetEnabled(false) - copyMenuItem.OnClick(handleCopy) - - app.RegisterContextMenu("editor-menu", contextMenu) -} - -func onSelectionChanged(hasSelection bool) { - cutMenuItem.SetEnabled(hasSelection) - copyMenuItem.SetEnabled(hasSelection) - contextMenu.Update() // Important! -} -``` - -:::caution[Always Call Update()] -After changing menu state, **call `contextMenu.Update()`**. This is critical on Windows. - -See [Menu Reference](/features/menus/reference#enabled-state) for details. -::: - -### Change Labels - -```go -playMenuItem := contextMenu.Add("Play") - -playMenuItem.OnClick(func(ctx *application.Context) { - if isPlaying { - playMenuItem.SetLabel("Pause") - } else { - playMenuItem.SetLabel("Play") - } - contextMenu.Update() -}) -``` - -### Rebuild Menus - -For major changes, rebuild the entire menu: - -```go -func rebuildContextMenu(fileType string) { - contextMenu := app.NewContextMenu() - - // Common items - contextMenu.Add("Open").OnClick(handleOpen) - contextMenu.Add("Delete").OnClick(handleDelete) - - contextMenu.AddSeparator() - - // Type-specific items - switch fileType { - case "image": - contextMenu.Add("Edit Image").OnClick(editImage) - contextMenu.Add("Set as Wallpaper").OnClick(setWallpaper) - case "video": - contextMenu.Add("Play").OnClick(playVideo) - contextMenu.Add("Extract Audio").OnClick(extractAudio) - case "document": - contextMenu.Add("Print").OnClick(printDocument) - contextMenu.Add("Export PDF").OnClick(exportPDF) - } - - app.RegisterContextMenu("file-menu", contextMenu) -} -``` - -## Platform Behaviour - -Context menus are **platform-native**: - - - - **Native macOS context menus:** - - System animations and transitions - - Right-click = Control+Click (automatic) - - Adapts to system appearance (light/dark) - - Standard text operations in default menu - - Native scrolling for long menus - - **macOS conventions:** - - Use sentence case for menu items - - Use ellipsis (...) for items that open dialogs - - Common shortcuts: ⌘C (Copy), ⌘V (Paste) - - - - **Native Windows context menus:** - - Windows native style - - Follows Windows theme - - Standard Windows operations in default menu - - Touch and pen input support - - **Windows conventions:** - - Use title case for menu items - - Use ellipsis (...) for items that open dialogs - - Common shortcuts: Ctrl+C (Copy), Ctrl+V (Paste) - - - - **Desktop environment integration:** - - Adapts to desktop theme (GTK, Qt, etc.) - - Right-click behaviour follows system settings - - Default menu content varies by environment - - Positioning follows DE conventions - - **Linux considerations:** - - Test on target desktop environments - - GTK and Qt have different behaviours - - Some DEs customise context menus - - - -## Complete Example - -**Go code:** - -```go -package main - -import ( - "encoding/json" - "log" - "github.com/wailsapp/wails/v3/pkg/application" -) - -type FileData struct { - ID string `json:"id"` - Type string `json:"type"` - Name string `json:"name"` -} - -func main() { - app := application.New(application.Options{ - Name: "Context Menu Demo", - }) - - // Create file context menu - fileMenu := createFileMenu(app) - app.RegisterContextMenu("file-menu", fileMenu) - - // Create image context menu - imageMenu := createImageMenu(app) - app.RegisterContextMenu("image-menu", imageMenu) - - // Create text context menu - textMenu := createTextMenu(app) - app.RegisterContextMenu("text-menu", textMenu) - - app.Window.New() - app.Run() -} - -func createFileMenu(app *application.Application) *application.ContextMenu { - menu := app.NewContextMenu() - - menu.Add("Open").OnClick(func(ctx *application.Context) { - data := parseFileData(ctx.ContextMenuData()) - openFile(data.ID) - }) - - menu.Add("Rename").OnClick(func(ctx *application.Context) { - data := parseFileData(ctx.ContextMenuData()) - renameFile(data.ID) - }) - - menu.AddSeparator() - - menu.Add("Delete").OnClick(func(ctx *application.Context) { - data := parseFileData(ctx.ContextMenuData()) - deleteFile(data.ID) - }) - - return menu -} - -func createImageMenu(app *application.Application) *application.ContextMenu { - menu := app.NewContextMenu() - - menu.Add("View").OnClick(func(ctx *application.Context) { - data := parseFileData(ctx.ContextMenuData()) - viewImage(data.ID) - }) - - menu.Add("Edit").OnClick(func(ctx *application.Context) { - data := parseFileData(ctx.ContextMenuData()) - editImage(data.ID) - }) - - menu.AddSeparator() - - exportMenu := menu.AddSubmenu("Export As") - exportMenu.Add("PNG").OnClick(exportPNG) - exportMenu.Add("JPEG").OnClick(exportJPEG) - exportMenu.Add("WebP").OnClick(exportWebP) - - return menu -} - -func createTextMenu(app *application.Application) *application.ContextMenu { - menu := app.NewContextMenu() - - menu.Add("Cut").SetAccelerator("CmdOrCtrl+X").OnClick(handleCut) - menu.Add("Copy").SetAccelerator("CmdOrCtrl+C").OnClick(handleCopy) - menu.Add("Paste").SetAccelerator("CmdOrCtrl+V").OnClick(handlePaste) - - return menu -} - -func parseFileData(dataStr string) FileData { - var data FileData - if err := json.Unmarshal([]byte(dataStr), &data); err != nil { - log.Printf("Invalid file data: %v", err) - } - return data -} - -// Handler implementations... -func openFile(id string) { /* ... */ } -func renameFile(id string) { /* ... */ } -func deleteFile(id string) { /* ... */ } -func viewImage(id string) { /* ... */ } -func editImage(id string) { /* ... */ } -func exportPNG(ctx *application.Context) { /* ... */ } -func exportJPEG(ctx *application.Context) { /* ... */ } -func exportWebP(ctx *application.Context) { /* ... */ } -func handleCut(ctx *application.Context) { /* ... */ } -func handleCopy(ctx *application.Context) { /* ... */ } -func handlePaste(ctx *application.Context) { /* ... */ } -``` - -**HTML:** - -```html - - - - - - -

      Files

      - - -
      - 📄 Report.pdf -
      - - -
      - 🖼️ Photo.jpg -
      - -

      Text Editor

      - - - - -

      No Context Menu

      - - -
      - Right-click here - no menu appears -
      - - -``` - -## Best Practices - -### ✅ Do - -- **Keep menus focused** - Only relevant actions for the element -- **Validate context data** - Treat as untrusted input -- **Use clear labels** - "Delete File" not "Delete" -- **Call menu.Update()** - After changing menu state -- **Test on all platforms** - Behaviour varies -- **Provide keyboard shortcuts** - For common actions -- **Group related items** - Use separators - -### ❌ Don't - -- **Don't trust context data** - Always validate -- **Don't make menus too long** - 7-10 items maximum -- **Don't forget menu.Update()** - Menus won't work properly -- **Don't nest too deeply** - 2 levels maximum -- **Don't use jargon** - Keep labels user-friendly -- **Don't block handlers** - Keep them fast - -## Troubleshooting - -### Context Menu Not Appearing - -**Possible causes:** -1. Menu ID mismatch -2. CSS property typo -3. Runtime not initialised - -**Solution:** - -```go -// Check menu is registered -app.RegisterContextMenu("my-menu", contextMenu) -``` - -```html - -
      -``` - -### Context Data Not Received - -**Possible causes:** -1. CSS property not set -2. Data contains special characters - -**Solution:** - -```html - -
      -``` - -Or use JavaScript: - -```javascript -element.style.setProperty('--custom-contextmenu-data', JSON.stringify(data)) -``` - -### Menu Items Not Responding - -**Cause:** Forgot to call `menu.Update()` after enabling - -**Solution:** - -```go -menuItem.SetEnabled(true) -contextMenu.Update() // Add this! -``` - -## Next Steps - - - - Complete reference for menu item types and properties. - - [Learn More →](/features/menus/reference) - - - - Create application menu bars. - - [Learn More →](/features/menus/application) - - - - Add system tray/menu bar integration. - - [Learn More →](/features/menus/systray) - - - - Common menu patterns and best practices. - - [Learn More →](/guides/patterns/menus) - - - ---- - -**Questions?** Ask in [Discord](https://discord.gg/JDdSxwjhGf) or check the [context menu example](https://github.com/wailsapp/wails/tree/v3-alpha/v3/examples/contextmenus). diff --git a/docs/src/content/docs/features/menus/reference.mdx b/docs/src/content/docs/features/menus/reference.mdx deleted file mode 100644 index 93cc6b45a..000000000 --- a/docs/src/content/docs/features/menus/reference.mdx +++ /dev/null @@ -1,562 +0,0 @@ ---- -title: Menu Reference -description: Complete reference for menu item types, properties, and methods -sidebar: - order: 4 ---- - -import { Tabs, TabItem } from "@astrojs/starlight/components"; - -## Menu Reference - -Complete reference for menu item types, properties, and dynamic behaviour. Build professional, responsive menus with checkboxes, radio groups, separators, and dynamic updates. - -## Menu Item Types - -### Regular Menu Items - -The most common type—displays text and triggers an action: - -```go -menuItem := menu.Add("Click Me") -menuItem.OnClick(func(ctx *application.Context) { - fmt.Println("Menu item clicked!") -}) -``` - -**Use for:** Commands, actions, opening windows - -### Checkboxes - -Toggle-able menu items with checked/unchecked state: - -```go -checkbox := menu.AddCheckbox("Enable Feature", true) // true = initially checked -checkbox.OnClick(func(ctx *application.Context) { - isChecked := ctx.ClickedMenuItem().Checked() - fmt.Printf("Feature is now: %v\n", isChecked) -}) -``` - -**Use for:** Boolean settings, feature toggles, view options - -**Important:** The checked state toggles automatically when clicked. - -### Radio Groups - -Mutually exclusive options—only one can be selected: - -```go -menu.AddRadio("Small", true) // true = initially selected -menu.AddRadio("Medium", false) -menu.AddRadio("Large", false) -``` - -**Use for:** Mutually exclusive choices (size, theme, mode) - -**How grouping works:** -- Adjacent radio items form a group automatically -- Selecting one deselects others in the group -- Separate groups with a separator or regular item - -**Example with multiple groups:** - -```go -// Group 1: Size -menu.AddRadio("Small", true) -menu.AddRadio("Medium", false) -menu.AddRadio("Large", false) - -menu.AddSeparator() - -// Group 2: Theme -menu.AddRadio("Light", true) -menu.AddRadio("Dark", false) -``` - -### Submenus - -Nested menu structures for organisation: - -```go -submenu := menu.AddSubmenu("More Options") -submenu.Add("Submenu Item 1").OnClick(func(ctx *application.Context) { - // Handle click -}) -submenu.Add("Submenu Item 2") -``` - -**Use for:** Grouping related items, reducing clutter - -**Nesting limit:** Most platforms support 2-3 levels. Avoid deeper nesting. - -### Separators - -Visual dividers between menu items: - -```go -menu.Add("Item 1") -menu.AddSeparator() -menu.Add("Item 2") -``` - -**Use for:** Grouping related items visually - -**Best practice:** Don't start or end menus with separators. - -## Menu Item Properties - -### Label - -The text displayed for the menu item: - -```go -menuItem := menu.Add("Initial Label") -menuItem.SetLabel("New Label") - -// Get current label -label := menuItem.Label() -``` - -**Dynamic labels:** - -```go -updateMenuItem := menu.Add("Check for Updates") -updateMenuItem.OnClick(func(ctx *application.Context) { - updateMenuItem.SetLabel("Checking...") - menu.Update() // Important on Windows! - - // Perform update check - checkForUpdates() - - updateMenuItem.SetLabel("Check for Updates") - menu.Update() -}) -``` - -### Enabled State - -Control whether the menu item can be interacted with: - -```go -menuItem := menu.Add("Save") -menuItem.SetEnabled(false) // Greyed out, can't click - -// Enable it later -menuItem.SetEnabled(true) -menu.Update() // Important: Call this after changing enabled state! - -// Check current state -isEnabled := menuItem.Enabled() -``` - -:::caution[Windows Menu Behaviour] -On Windows, menus need to be reconstructed when their state changes. **Always call `menu.Update()` after enabling/disabling menu items**, especially if the item was created whilst disabled. - -**Why:** Windows menus are rebuilt from scratch when updated. If you don't call `Update()`, click handlers won't fire properly. -::: - -**Example: Dynamic enable/disable** - -```go -var hasSelection bool - -cutMenuItem := menu.Add("Cut") -cutMenuItem.SetEnabled(false) // Initially disabled - -copyMenuItem := menu.Add("Copy") -copyMenuItem.SetEnabled(false) - -// When selection changes -func onSelectionChanged(selected bool) { - hasSelection = selected - cutMenuItem.SetEnabled(hasSelection) - copyMenuItem.SetEnabled(hasSelection) - menu.Update() // Critical on Windows! -} -``` - -**Common pattern: Enable on condition** - -```go -saveMenuItem := menu.Add("Save") - -func updateSaveMenuItem() { - canSave := hasUnsavedChanges() && !isSaving() - saveMenuItem.SetEnabled(canSave) - menu.Update() -} - -// Call whenever state changes -onDocumentChanged(func() { - updateSaveMenuItem() -}) -``` - -### Checked State - -For checkbox and radio items, control or query their checked state: - -```go -checkbox := menu.AddCheckbox("Feature", false) -checkbox.SetChecked(true) -menu.Update() - -// Query state -isChecked := checkbox.Checked() -``` - -**Auto-toggle:** Checkboxes toggle automatically when clicked. You don't need to call `SetChecked()` in the click handler. - -**Manual control:** - -```go -checkbox := menu.AddCheckbox("Auto-save", false) - -// Sync with external state -func syncAutoSave(enabled bool) { - checkbox.SetChecked(enabled) - menu.Update() -} -``` - -### Accelerators (Keyboard Shortcuts) - -Add keyboard shortcuts to menu items: - -```go -saveMenuItem := menu.Add("Save") -saveMenuItem.SetAccelerator("CmdOrCtrl+S") - -quitMenuItem := menu.Add("Quit") -quitMenuItem.SetAccelerator("CmdOrCtrl+Q") -``` - -**Accelerator format:** -- `CmdOrCtrl` - Cmd on macOS, Ctrl on Windows/Linux -- `Shift`, `Alt`, `Option` - Modifier keys -- `A-Z`, `0-9` - Letter/number keys -- `F1-F12` - Function keys -- `Enter`, `Space`, `Backspace`, etc. - Special keys - -**Examples:** - -```go -"CmdOrCtrl+S" // Save -"CmdOrCtrl+Shift+S" // Save As -"CmdOrCtrl+W" // Close Window -"CmdOrCtrl+Q" // Quit -"F5" // Refresh -"CmdOrCtrl+," // Preferences (macOS convention) -"Alt+F4" // Close (Windows convention) -``` - -**Platform-specific accelerators:** - -```go -if runtime.GOOS == "darwin" { - prefsMenuItem.SetAccelerator("Cmd+,") -} else { - prefsMenuItem.SetAccelerator("Ctrl+P") -} -``` - -### Tooltip - -Add hover text to menu items (platform support varies): - -```go -menuItem := menu.Add("Advanced Options") -menuItem.SetTooltip("Configure advanced settings") -``` - -**Platform support:** -- **Windows:** ✅ Supported -- **macOS:** ❌ Not supported (tooltips not standard for menus) -- **Linux:** ⚠️ Varies by desktop environment - -### Hidden State - -Hide menu items without removing them: - -```go -debugMenuItem := menu.Add("Debug Mode") -debugMenuItem.SetHidden(true) // Hidden - -// Show in debug builds -if isDebugBuild { - debugMenuItem.SetHidden(false) - menu.Update() -} -``` - -**Use for:** Debug options, feature flags, conditional features - -## Event Handling - -### OnClick Handler - -Execute code when menu item is clicked: - -```go -menuItem := menu.Add("Click Me") -menuItem.OnClick(func(ctx *application.Context) { - // Handle click - fmt.Println("Clicked!") -}) -``` - -**Context provides:** -- `ctx.ClickedMenuItem()` - The menu item that was clicked -- Window context (if from window menu) -- Application context - -**Example: Access menu item in handler** - -```go -checkbox := menu.AddCheckbox("Feature", false) -checkbox.OnClick(func(ctx *application.Context) { - item := ctx.ClickedMenuItem() - isChecked := item.Checked() - fmt.Printf("Feature is now: %v\n", isChecked) -}) -``` - -### Multiple Handlers - -You can set multiple handlers (last one wins): - -```go -menuItem := menu.Add("Action") -menuItem.OnClick(func(ctx *application.Context) { - fmt.Println("First handler") -}) - -// This replaces the first handler -menuItem.OnClick(func(ctx *application.Context) { - fmt.Println("Second handler - this one runs") -}) -``` - -**Best practice:** Set handler once, use conditional logic inside if needed. - -## Dynamic Menus - -### Updating Menu Items - -**The golden rule:** Always call `menu.Update()` after changing menu state. - -```go -// ✅ Correct -menuItem.SetEnabled(true) -menu.Update() - -// ❌ Wrong (especially on Windows) -menuItem.SetEnabled(true) -// Forgot to call Update() - click handlers may not work! -``` - -**Why this matters:** -- **Windows:** Menus are reconstructed when updated -- **macOS/Linux:** Less critical but still recommended -- **Click handlers:** Won't fire properly without Update() - -### Rebuilding Menus - -For major changes, rebuild the entire menu: - -```go -func rebuildFileMenu() { - menu := app.Menu.New() - - menu.Add("New").OnClick(handleNew) - menu.Add("Open").OnClick(handleOpen) - - if hasRecentFiles() { - recentMenu := menu.AddSubmenu("Open Recent") - for _, file := range getRecentFiles() { - recentMenu.Add(file).OnClick(func(ctx *application.Context) { - openFile(file) - }) - } - } - - menu.AddSeparator() - menu.Add("Quit").OnClick(handleQuit) - - // Set the new menu - window.SetMenu(menu) -} -``` - -**When to rebuild:** -- Recent files list changes -- Plugin menus change -- Major state transitions - -**When to update:** -- Enable/disable items -- Change labels -- Toggle checkboxes - -### Context-Sensitive Menus - -Adjust menus based on application state: - -```go -func updateEditMenu() { - cutMenuItem.SetEnabled(hasSelection()) - copyMenuItem.SetEnabled(hasSelection()) - pasteMenuItem.SetEnabled(hasClipboardContent()) - undoMenuItem.SetEnabled(canUndo()) - redoMenuItem.SetEnabled(canRedo()) - menu.Update() -} - -// Call whenever state changes -onSelectionChanged(updateEditMenu) -onClipboardChanged(updateEditMenu) -onUndoStackChanged(updateEditMenu) -``` - -## Platform Differences - -### Menu Bar Location - -| Platform | Location | Notes | -|----------|----------|-------| -| **macOS** | Top of screen | Global menu bar | -| **Windows** | Top of window | Per-window menu | -| **Linux** | Top of window | Per-window (usually) | - -### Standard Menus - -**macOS:** -- Has "Application" menu (with app name) -- "Preferences" in Application menu -- "Quit" in Application menu - -**Windows/Linux:** -- No Application menu -- "Preferences" in Edit or Tools menu -- "Exit" in File menu - -**Example: Platform-appropriate structure** - -```go -menu := app.Menu.New() - -// macOS gets Application menu -if runtime.GOOS == "darwin" { - menu.AddRole(application.AppMenu) -} - -// File menu -fileMenu := menu.AddSubmenu("File") -fileMenu.Add("New") -fileMenu.Add("Open") - -// Preferences location varies -if runtime.GOOS == "darwin" { - // On macOS, preferences are in Application menu (added by AppMenu role) -} else { - // On Windows/Linux, add to Edit or Tools menu - editMenu := menu.AddSubmenu("Edit") - editMenu.Add("Preferences") -} -``` - -### Accelerator Conventions - -**macOS:** -- `Cmd+` for most shortcuts -- `Cmd+,` for Preferences -- `Cmd+Q` for Quit - -**Windows:** -- `Ctrl+` for most shortcuts -- `Ctrl+P` or `Ctrl+,` for Preferences -- `Alt+F4` for Exit (or `Ctrl+Q`) - -**Linux:** -- Generally follows Windows conventions -- Desktop environment may override - -## Best Practices - -### ✅ Do - -- **Call menu.Update()** after changing menu state (especially on Windows) -- **Use radio groups** for mutually exclusive options -- **Use checkboxes** for toggleable features -- **Add accelerators** to common actions -- **Group related items** with separators -- **Test on all platforms** - behaviour varies - -### ❌ Don't - -- **Don't forget menu.Update()** - Click handlers won't work properly -- **Don't nest too deeply** - 2-3 levels maximum -- **Don't start/end with separators** - Looks unprofessional -- **Don't use tooltips on macOS** - Not supported -- **Don't hardcode platform shortcuts** - Use `CmdOrCtrl` - -## Troubleshooting - -### Menu Items Not Responding - -**Symptom:** Click handlers don't fire - -**Cause:** Forgot to call `menu.Update()` after enabling item - -**Solution:** - -```go -menuItem.SetEnabled(true) -menu.Update() // Add this! -``` - -### Menu Items Greyed Out - -**Symptom:** Can't click menu items - -**Cause:** Items are disabled - -**Solution:** - -```go -menuItem.SetEnabled(true) -menu.Update() -``` - -### Accelerators Not Working - -**Symptom:** Keyboard shortcuts don't trigger menu items - -**Causes:** -1. Accelerator format incorrect -2. Conflict with system shortcuts -3. Window doesn't have focus - -**Solution:** - -```go -// Check format -menuItem.SetAccelerator("CmdOrCtrl+S") // ✅ Correct -menuItem.SetAccelerator("Ctrl+S") // ❌ Wrong (macOS uses Cmd) - -// Avoid conflicts -// ❌ Cmd+H (Hide Window on macOS - system shortcut) -// ✅ Cmd+Shift+H (Custom shortcut) -``` - -## Next Steps - -- [Application Menus](/features/menus/application) - Create application menu bars -- [Context Menus](/features/menus/context) - Right-click context menus -- [System Tray Menus](/features/menus/systray) - System tray/menu bar menus -- [Menu Patterns](/guides/patterns/menus) - Common menu patterns and best practices - ---- - -**Questions?** Ask in [Discord](https://discord.gg/JDdSxwjhGf) or check the [menu examples](https://github.com/wailsapp/wails/tree/v3-alpha/v3/examples/menu). diff --git a/docs/src/content/docs/features/menus/systray.mdx b/docs/src/content/docs/features/menus/systray.mdx deleted file mode 100644 index a0c8a722b..000000000 --- a/docs/src/content/docs/features/menus/systray.mdx +++ /dev/null @@ -1,713 +0,0 @@ ---- -title: System Tray Menus -description: Add system tray (notification area) integration to your application -sidebar: - order: 3 ---- - -import { Tabs, TabItem, Card, CardGrid } from "@astrojs/starlight/components"; - -## System Tray Menus - -Wails provides **unified system tray APIs** that work across all platforms. Create tray icons with menus, attach windows, and handle clicks with native platform behaviour for background applications, services, and quick-access utilities. -{/* VISUAL PLACEHOLDER: System Tray Comparison -Description: Three screenshots showing the same Wails system tray icon on: -1. Windows - Notification area (bottom-right) -2. macOS - Menu bar (top-right) with label -3. Linux (GNOME) - Top bar -All showing the same icon and menu structure -Style: Clean screenshots with arrows pointing to tray icon, menu expanded -*/} - -## Quick Start - -```go -package main - -import ( - _ "embed" - "github.com/wailsapp/wails/v3/pkg/application" -) - -//go:embed assets/icon.png -var icon []byte - -func main() { - app := application.New(application.Options{ - Name: "Tray App", - }) - - // Create system tray - systray := app.SystemTray.New() - systray.SetIcon(icon) - systray.SetLabel("My App") - - // Add menu - menu := app.NewMenu() - menu.Add("Show").OnClick(func(ctx *application.Context) { - // Show main window - }) - menu.Add("Quit").OnClick(func(ctx *application.Context) { - app.Quit() - }) - systray.SetMenu(menu) - - // Create hidden window - window := app.Window.New() - window.Hide() - - app.Run() -} -``` - -**Result:** System tray icon with menu on all platforms. - -## Creating a System Tray - -### Basic System Tray - -```go -// Create system tray -systray := app.SystemTray.New() - -// Set icon -systray.SetIcon(iconBytes) - -// Set label (macOS) / tooltip (Windows) -systray.SetLabel("My Application") -``` - -### With Icon - -Icons should be embedded: - -```go -import _ "embed" - -//go:embed assets/icon.png -var icon []byte - -//go:embed assets/icon-dark.png -var iconDark []byte - -func main() { - app := application.New(application.Options{ - Name: "My App", - }) - - systray := app.SystemTray.New() - systray.SetIcon(icon) - systray.SetDarkModeIcon(iconDark) // macOS dark mode - - app.Run() -} -``` - -**Icon requirements:** - -| Platform | Size | Format | Notes | -|----------|------|--------|-------| -| **Windows** | 16x16 or 32x32 | PNG, ICO | Notification area | -| **macOS** | 18x18 to 22x22 | PNG | Menu bar, template recommended | -| **Linux** | 22x22 to 48x48 | PNG, SVG | Varies by DE | - -### Template Icons (macOS) - -Template icons adapt to light/dark mode automatically: - -```go -systray.SetTemplateIcon(iconBytes) -``` - -**Template icon guidelines:** -- Use black and clear (transparent) colours only -- Black becomes white in dark mode -- Name file with `Template` suffix: `iconTemplate.png` -- [Design guide](https://bjango.com/articles/designingmenubarextras/) - -## Adding Menus - -System tray menus work like application menus: - -```go -menu := app.NewMenu() - -// Add items -menu.Add("Open").OnClick(func(ctx *application.Context) { - showMainWindow() -}) - -menu.AddSeparator() - -menu.AddCheckbox("Start at Login", false).OnClick(func(ctx *application.Context) { - enabled := ctx.ClickedMenuItem().Checked() - setStartAtLogin(enabled) -}) - -menu.AddSeparator() - -menu.Add("Quit").OnClick(func(ctx *application.Context) { - app.Quit() -}) - -// Set menu -systray.SetMenu(menu) -``` - -**For all menu item types**, see [Menu Reference](/features/menus/reference). - -## Attaching Windows - -Attach a window to the tray icon for automatic show/hide: - -```go -// Create window -window := app.Window.New() - -// Attach to tray -systray.AttachWindow(window) - -// Configure behaviour -systray.SetWindowOffset(10) // Pixels from tray icon -systray.SetWindowDebounce(200 * time.Millisecond) // Click debounce -``` - -**Behaviour:** -- Window starts hidden -- **Left-click tray icon** → Toggle window visibility -- **Right-click tray icon** → Show menu (if set) -- Window positioned near tray icon - -**Example: Popup window** - -```go -window := app.Window.NewWithOptions(application.WebviewWindowOptions{ - Title: "Quick Access", - Width: 300, - Height: 400, - Frameless: true, // No title bar - AlwaysOnTop: true, // Stay on top -}) - -systray.AttachWindow(window) -systray.SetWindowOffset(5) -``` - -## Click Handlers - -Handle tray icon clicks: - -```go -systray := app.SystemTray.New() - -// Left click -systray.OnClick(func() { - fmt.Println("Tray icon clicked") -}) - -// Right click -systray.OnRightClick(func() { - fmt.Println("Tray icon right-clicked") -}) - -// Double click -systray.OnDoubleClick(func() { - fmt.Println("Tray icon double-clicked") -}) - -// Mouse enter/leave -systray.OnMouseEnter(func() { - fmt.Println("Mouse entered tray icon") -}) - -systray.OnMouseLeave(func() { - fmt.Println("Mouse left tray icon") -}) -``` - -**Platform support:** - -| Event | Windows | macOS | Linux | -|-------|---------|-------|-------| -| OnClick | ✅ | ✅ | ✅ | -| OnRightClick | ✅ | ✅ | ✅ | -| OnDoubleClick | ✅ | ✅ | ⚠️ Varies | -| OnMouseEnter | ✅ | ✅ | ⚠️ Varies | -| OnMouseLeave | ✅ | ✅ | ⚠️ Varies | - -## Dynamic Updates - -Update tray icon and menu dynamically: - -### Change Icon - -```go -var isActive bool - -func updateTrayIcon() { - if isActive { - systray.SetIcon(activeIcon) - systray.SetLabel("Active") - } else { - systray.SetIcon(inactiveIcon) - systray.SetLabel("Inactive") - } -} -``` - -### Update Menu - -```go -var isPaused bool - -pauseMenuItem := menu.Add("Pause") - -pauseMenuItem.OnClick(func(ctx *application.Context) { - isPaused = !isPaused - - if isPaused { - pauseMenuItem.SetLabel("Resume") - } else { - pauseMenuItem.SetLabel("Pause") - } - - menu.Update() // Important! -}) -``` - -:::caution[Always Call Update()] -After changing menu state, **call `menu.Update()`**. See [Menu Reference](/features/menus/reference#enabled-state). -::: - -### Rebuild Menu - -For major changes, rebuild the entire menu: - -```go -func rebuildTrayMenu(status string) { - menu := app.NewMenu() - - // Status-specific items - switch status { - case "syncing": - menu.Add("Syncing...").SetEnabled(false) - menu.Add("Pause Sync").OnClick(pauseSync) - case "synced": - menu.Add("Up to date ✓").SetEnabled(false) - menu.Add("Sync Now").OnClick(startSync) - case "error": - menu.Add("Sync Error").SetEnabled(false) - menu.Add("Retry").OnClick(retrySync) - } - - menu.AddSeparator() - menu.Add("Quit").OnClick(func(ctx *application.Context) { - app.Quit() - }) - - systray.SetMenu(menu) -} -``` - -## Platform-Specific Features - - - - **Menu bar integration:** - - ```go - // Set label (appears next to icon) - systray.SetLabel("My App") - - // Use template icon (adapts to dark mode) - systray.SetTemplateIcon(iconBytes) - - // Set icon position - systray.SetIconPosition(application.IconPositionRight) - ``` - - **Icon positions:** - - `IconPositionLeft` - Icon left of label - - `IconPositionRight` - Icon right of label - - `IconPositionOnly` - Icon only, no label - - `IconPositionNone` - Label only, no icon - - **Best practices:** - - Use template icons (black + transparent) - - Keep labels short (3-5 characters) - - 18x18 to 22x22 pixels for Retina displays - - Test in both light and dark modes - - - - **Notification area integration:** - - ```go - // Set tooltip (appears on hover) - systray.SetTooltip("My Application") - - // Or use SetLabel (same as tooltip on Windows) - systray.SetLabel("My Application") - - // Show/Hide functionality (fully functional) - systray.Show() // Show tray icon - systray.Hide() // Hide tray icon - ``` - - **Icon requirements:** - - 16x16 or 32x32 pixels - - PNG or ICO format - - Transparent background - - **Tooltip limits:** - - Maximum 127 UTF-16 characters - - Longer tooltips will be truncated - - Keep concise for best experience - - **Platform features:** - - Tray icon survives Windows Explorer restarts - - Show() and Hide() methods fully functional - - Proper lifecycle management - - **Best practices:** - - Use 32x32 for high-DPI displays - - Keep tooltips under 127 characters - - Test on different Windows versions - - Consider notification area overflow - - Use Show/Hide for conditional tray visibility - - - - **System tray integration:** - - Uses StatusNotifierItem specification (most modern DEs). - - ```go - systray.SetIcon(iconBytes) - systray.SetLabel("My App") - ``` - - **Desktop environment support:** - - **GNOME**: Top bar (with extension) - - **KDE Plasma**: System tray - - **XFCE**: Notification area - - **Others**: Varies - - **Best practices:** - - Use 22x22 or 24x24 pixels - - SVG icons scale better - - Test on target desktop environments - - Provide fallback for unsupported DEs - - - -## Complete Example - -Here's a production-ready system tray application: - -```go -package main - -import ( - _ "embed" - "fmt" - "time" - "github.com/wailsapp/wails/v3/pkg/application" -) - -//go:embed assets/icon.png -var icon []byte - -//go:embed assets/icon-active.png -var iconActive []byte - -type TrayApp struct { - app *application.Application - systray *application.SystemTray - window *application.WebviewWindow - menu *application.Menu - isActive bool -} - -func main() { - app := application.New(application.Options{ - Name: "Tray Application", - Mac: application.MacOptions{ - ApplicationShouldTerminateAfterLastWindowClosed: false, - }, - }) - - trayApp := &TrayApp{app: app} - trayApp.setup() - - app.Run() -} - -func (t *TrayApp) setup() { - // Create system tray - t.systray = t.app.SystemTray.New() - t.systray.SetIcon(icon) - t.systray.SetLabel("Inactive") - - // Create menu - t.createMenu() - - // Create window (hidden by default) - t.window = t.app.Window.NewWithOptions(application.WebviewWindowOptions{ - Title: "Tray Application", - Width: 400, - Height: 600, - Hidden: true, - }) - - // Attach window to tray - t.systray.AttachWindow(t.window) - t.systray.SetWindowOffset(10) - - // Handle tray clicks - t.systray.OnRightClick(func() { - t.systray.OpenMenu() - }) - - // Start background task - go t.backgroundTask() -} - -func (t *TrayApp) createMenu() { - t.menu = t.app.NewMenu() - - // Status item (disabled) - statusItem := t.menu.Add("Status: Inactive") - statusItem.SetEnabled(false) - - t.menu.AddSeparator() - - // Toggle active - t.menu.Add("Start").OnClick(func(ctx *application.Context) { - t.toggleActive() - }) - - // Show window - t.menu.Add("Show Window").OnClick(func(ctx *application.Context) { - t.window.Show() - t.window.SetFocus() - }) - - t.menu.AddSeparator() - - // Settings - t.menu.AddCheckbox("Start at Login", false).OnClick(func(ctx *application.Context) { - enabled := ctx.ClickedMenuItem().Checked() - t.setStartAtLogin(enabled) - }) - - t.menu.AddSeparator() - - // Quit - t.menu.Add("Quit").OnClick(func(ctx *application.Context) { - t.app.Quit() - }) - - t.systray.SetMenu(t.menu) -} - -func (t *TrayApp) toggleActive() { - t.isActive = !t.isActive - t.updateTray() -} - -func (t *TrayApp) updateTray() { - if t.isActive { - t.systray.SetIcon(iconActive) - t.systray.SetLabel("Active") - } else { - t.systray.SetIcon(icon) - t.systray.SetLabel("Inactive") - } - - // Rebuild menu with new status - t.createMenu() -} - -func (t *TrayApp) backgroundTask() { - ticker := time.NewTicker(5 * time.Second) - defer ticker.Stop() - - for range ticker.C { - if t.isActive { - fmt.Println("Background task running...") - // Do work - } - } -} - -func (t *TrayApp) setStartAtLogin(enabled bool) { - // Implementation varies by platform - fmt.Printf("Start at login: %v\n", enabled) -} -``` - -## Visibility Control - -Show/hide the tray icon dynamically: - -```go -// Hide tray icon -systray.Hide() - -// Show tray icon -systray.Show() - -// Check visibility -if systray.IsVisible() { - fmt.Println("Tray icon is visible") -} -``` - -**Platform Support:** - -| Platform | Hide() | Show() | Notes | -|----------|--------|--------|-------| -| **Windows** | ✅ | ✅ | Fully functional - icon appears/disappears from notification area | -| **macOS** | ✅ | ✅ | Menu bar item shows/hides | -| **Linux** | ✅ | ✅ | Varies by desktop environment | - -**Use cases:** -- Temporarily hide tray icon based on user preference -- Headless mode with tray icon appearing only when needed -- Toggle visibility based on application state - -**Example - Conditional Tray Visibility:** - -```go -func (t *TrayApp) setTrayVisibility(visible bool) { - if visible { - t.systray.Show() - } else { - t.systray.Hide() - } -} - -// Show tray only when updates are available -func (t *TrayApp) checkForUpdates() { - if hasUpdates { - t.systray.Show() - t.systray.SetLabel("Update Available") - } else { - t.systray.Hide() - } -} -``` - -## Cleanup - -Destroy the tray icon when done: - -```go -// In OnShutdown -app := application.New(application.Options{ - OnShutdown: func() { - if systray != nil { - systray.Destroy() - } - }, -}) -``` - -**Important:** Always destroy system tray on shutdown to release resources. - -## Best Practices - -### ✅ Do - -- **Use template icons on macOS** - Adapts to dark mode -- **Keep labels short** - 3-5 characters maximum -- **Provide tooltips on Windows** - Helps users identify your app -- **Test on all platforms** - Behaviour varies -- **Handle clicks appropriately** - Left-click for main action, right-click for menu -- **Update icon for status** - Visual feedback is important -- **Destroy on shutdown** - Release resources - -### ❌ Don't - -- **Don't use large icons** - Follow platform guidelines -- **Don't use long labels** - Gets truncated -- **Don't forget dark mode** - Test on macOS dark mode -- **Don't block click handlers** - Keep them fast -- **Don't forget menu.Update()** - After changing menu state -- **Don't assume tray support** - Some Linux DEs don't support it - -## Troubleshooting - -### Tray Icon Not Appearing - -**Possible causes:** -1. Icon format not supported -2. Icon size too large/small -3. System tray not supported (Linux) - -**Solution:** - -```go -// Check if system tray is supported -if !application.SystemTraySupported() { - fmt.Println("System tray not supported") - // Fallback to window-only mode -} -``` - -### Icon Looks Wrong on macOS - -**Cause:** Not using template icon - -**Solution:** - -```go -// Use template icon -systray.SetTemplateIcon(iconBytes) - -// Or design icon as template (black + transparent) -``` - -### Menu Not Updating - -**Cause:** Forgot to call `menu.Update()` - -**Solution:** - -```go -menuItem.SetLabel("New Label") -menu.Update() // Add this! -``` - -## Next Steps - - - - Complete reference for menu item types and properties. - - [Learn More →](/features/menus/reference) - - - - Create application menu bars. - - [Learn More →](/features/menus/application) - - - - Create right-click context menus. - - [Learn More →](/features/menus/context) - - - - Build a complete system tray application. - - [Learn More →](/tutorials/system-tray) - - - ---- - -**Questions?** Ask in [Discord](https://discord.gg/JDdSxwjhGf) or check the [system tray examples](https://github.com/wailsapp/wails/tree/v3-alpha/v3/examples/systray-basic). diff --git a/docs/src/content/docs/features/notifications/overview.mdx b/docs/src/content/docs/features/notifications/overview.mdx deleted file mode 100644 index efacdd74f..000000000 --- a/docs/src/content/docs/features/notifications/overview.mdx +++ /dev/null @@ -1,307 +0,0 @@ ---- -title: Notifications -description: Display native system notifications with action buttons and text input -sidebar: - order: 1 ---- - -import { Tabs, TabItem } from "@astrojs/starlight/components"; - -## Introduction - -Wails provides a comprehensive cross-platform notification system for desktop applications. This service allows you to display native system notifications, with support for interactive elements like action buttons and text input fields. - -## Basic Usage - -### Creating the Service - -First, initialize the notifications service: - -```go -import "github.com/wailsapp/wails/v3/pkg/application" -import "github.com/wailsapp/wails/v3/pkg/services/notifications" - -// Create a new notification service -notifier := notifications.New() - -//Register the service with the application -app := application.New(application.Options{ - Services: []application.Service{ - application.NewService(notifier), - }, -}) -``` - -## Notification Authorization - -Notifications on macOS require user authorization. Request and check authorization: - -```go -authorized, err := notifier.CheckNotificationAuthorization() -if err != nil { - // Handle authorization error -} -if authorized { - // Send notifications -} else { - // Request authorization - authorized, err = notifier.RequestNotificationAuthorization() -} -``` -On Windows and Linux this always returns `true`. - -## Notification Types - -### Basic Notifications - -Send a basic notification with a unique id, title, optional subtitle (macOS and Linux), and body text to users: - -```go -notifier.SendNotification(notifications.NotificationOptions{ - ID: "unique-id", - Title: "New Calendar Invite", - Subtitle: "From: Jane Doe", // Optional - Body: "Tap to view the event", -}) - -``` - -### Interactive Notifications -Send a notification with action buttons and text inputs. These notifications require a notification category to be resgistered first: - -```go -// Define a unique category id -categoryID := "unique-category-id" - -// Define a category with actions -category := notifications.NotificationCategory{ - ID: categoryID, - Actions: []notifications.NotificationAction{ - { - ID: "OPEN", - Title: "Open", - }, - { - ID: "ARCHIVE", - Title: "Archive", - Destructive: true, /* macOS-specific */ - }, - }, - HasReplyField: true, - ReplyPlaceholder: "message...", - ReplyButtonTitle: "Reply", -} - -// Register the category -notifier.RegisterNotificationCategory(category) - -// Send an interactive notification with the actions registered in the provided category -notifier.SendNotificationWithActions(notifications.NotificationOptions{ - ID: "unique-id", - Title: "New Message", - Subtitle: "From: Jane Doe", - Body: "Are you able to make it?", - CategoryID: categoryID, -}) -``` - -## Notification Responses - -Process user interactions with notifications: - -```go -notifier.OnNotificationResponse(func(result notifications.NotificationResult) { - response := result.Response - fmt.Printf("Notification %s was actioned with: %s\n", response.ID, response.ActionIdentifier) - - if response.ActionIdentifier == "TEXT_REPLY" { - fmt.Printf("User replied: %s\n", response.UserText) - } - - if data, ok := response.UserInfo["sender"].(string); ok { - fmt.Printf("Original sender: %s\n", data) - } - - // Emit an event to the frontend - app.Event.Emit("notification", result.Response) -}) -``` - -## Notification Customisation - -### Custom Metadata - -Basic and interactive notifications can include custom data: - -```go -notifier.SendNotification(notifications.NotificationOptions{ - ID: "unique-id", - Title: "New Calendar Invite", - Subtitle: "From: Jane Doe", // Optional - Body: "Tap to view the event", - Data: map[string]interface{}{ - "sender": "jane.doe@example.com", - "timestamp": "2025-03-10T15:30:00Z", - } -}) - -``` - -## Platform Considerations - - - - - On macOS, notifications: - - - Require user authorization - - Require the app to be notorized for distribution - - Use system-standard notification appearances - - Support `subtitle` - - Support user text input - - Support the `Destructive` action option - - Automatically handle dark/light mode - - - - - - On Windows, notifications: - - - Use Windows system toast styles - - Adapt to Windows theme settings - - Support user text input - - Support high DPI displays - - Do not support `subtitle` - - - - - - On Linux, dialog behaviour depends on the desktop environment: - - - Use native notifications when available - - Follow desktop environment theme - - Position according to desktop environment rules - - Support `subtitle` - - Do not support user text input - - - - -## Best Practices - -1. Check and request for authorization: - - macOS requires user authorization - -2. Provide clear and concise notifications: - - Use descriptive titles, subtitles, text, and action titles - -3. Handle dialog responses appropriately: - - Check for errors in notification responses - - Provide feedback for user actions - -4. Consider platform conventions: - - Follow platform-specific notification patterns - - Respect system settings - -## Examples - -Explore this example: - -- [Notifications](/examples/notifications) - -## API Reference - -### Service Management -| Method | Description | -|--------------------------------------------|-------------------------------------------------------| -| `New()` | Creates a new notifications service | - -### Notification Authorization -| Method | Description | -|----------------------------------------------|------------------------------------------------------------| -| `RequestNotificationAuthorization()` | Requests permission to display notifications (macOS) | -| `CheckNotificationAuthorization()` | Checks current notification authorization status (macOS) | - -### Sending Notifications -| Method | Description | -|------------------------------------------------------------|---------------------------------------------------| -| `SendNotification(options NotificationOptions)` | Sends a basic notification | -| `SendNotificationWithActions(options NotificationOptions)` | Sends an interactive notification with actions | - -### Notification Categories -| Method | Description | -|---------------------------------------------------------------|---------------------------------------------------| -| `RegisterNotificationCategory(category NotificationCategory)` | Registers a reusable notification category | -| `RemoveNotificationCategory(categoryID string)` | Removes a previously registered category | - -### Managing Notifications -| Method | Description | -|-------------------------------------------------|---------------------------------------------------------------------| -| `RemoveAllPendingNotifications()` | Removes all pending notifications (macOS and Linux only) | -| `RemovePendingNotification(identifier string)` | Removes a specific pending notification (macOS and Linux only) | -| `RemoveAllDeliveredNotifications()` | Removes all delivered notifications (macOS and Linux only) | -| `RemoveDeliveredNotification(identifier string)`| Removes a specific delivered notification (macOS and Linux only) | -| `RemoveNotification(identifier string)` | Removes a notification (Linux-specific) | - -### Event Handling -| Method | Description | -|--------------------------------------------------------------------|-------------------------------------------------| -| `OnNotificationResponse(callback func(result NotificationResult))` | Registers a callback for notification responses | - -### Structs and Types - -#### NotificationOptions -```go -type NotificationOptions struct { - ID string // Unique identifier for the notification - Title string // Main notification title - Subtitle string // Subtitle text (macOS and Linux only) - Body string // Main notification content - CategoryID string // Category identifier for interactive notifications - Data map[string]interface{} // Custom data to associate with the notification -} -``` - -#### NotificationCategory -```go -type NotificationCategory struct { - ID string // Unique identifier for the category - Actions []NotificationAction // Button actions for the notification - HasReplyField bool // Whether to include a text input field - ReplyPlaceholder string // Placeholder text for the input field - ReplyButtonTitle string // Text for the reply button -} -``` - -#### NotificationAction -```go -type NotificationAction struct { - ID string // Unique identifier for the action - Title string // Button text - Destructive bool // Whether the action is destructive (macOS-specific) -} -``` - -#### NotificationResponse -```go -type NotificationResponse struct { - ID string // Notification identifier - ActionIdentifier string // Action that was triggered - CategoryID string // Category of the notification - Title string // Title of the notification - Subtitle string // Subtitle of the notification - Body string // Body text of the notification - UserText string // Text entered by the user - UserInfo map[string]interface{} // Custom data from the notification -} -``` - -#### NotificationResult -```go -type NotificationResult struct { - Response NotificationResponse // Response data - Error error // Any error that occurred -} -``` \ No newline at end of file diff --git a/docs/src/content/docs/features/platform/dock.mdx b/docs/src/content/docs/features/platform/dock.mdx deleted file mode 100644 index 2638f7bf2..000000000 --- a/docs/src/content/docs/features/platform/dock.mdx +++ /dev/null @@ -1,235 +0,0 @@ ---- -title: Dock & Taskbar -description: Manage dock icon visibility and display badges on macOS and Windows -sidebar: - order: 1 ---- - -import { Tabs, TabItem } from "@astrojs/starlight/components"; - -## Introduction - -Wails provides a cross-platform Dock service for desktop applications. This service allows you to: - -- Hide and show the application icon in the macOS Dock -- Display badges on your application tile or dock/taskbar icon (macOS and Windows) - -## Basic Usage - -### Creating the Service - -First, initialize the dock service: - -```go -import "github.com/wailsapp/wails/v3/pkg/application" -import "github.com/wailsapp/wails/v3/pkg/services/dock" - -// Create a new Dock service -dockService := dock.New() - -// Register the service with the application -app := application.New(application.Options{ - Services: []application.Service{ - application.NewService(dockService), - }, -}) -``` - -### Creating the Service with Custom Badge Options (Windows Only) - -On Windows, you can customize the badge appearance with various options: - -```go -import "github.com/wailsapp/wails/v3/pkg/application" -import "github.com/wailsapp/wails/v3/pkg/services/dock" -import "image/color" - -// Create a dock service with custom badge options -options := dock.BadgeOptions{ - TextColour: color.RGBA{255, 255, 255, 255}, // White text - BackgroundColour: color.RGBA{0, 0, 255, 255}, // Blue background - FontName: "consolab.ttf", // Bold Consolas font - FontSize: 20, // Font size for single character - SmallFontSize: 14, // Font size for multiple characters -} - -dockService := dock.NewWithOptions(options) - -// Register the service with the application -app := application.New(application.Options{ - Services: []application.Service{ - application.NewService(dockService), - }, -}) -``` - -## Dock Operations - -### Hiding the dock app icon - -Hide the app icon from the macOS Dock: - -```go -// Hide the app icon -dockService.HideAppIcon() -``` - -### Showing the dock app icon - -Show the app icon in the macOS Dock: - -```go -// Show the app icon -dockService.ShowAppIcon() -``` - -## Badge Operations - -### Setting a Badge - -Set a badge on the application tile/dock icon: - -```go -// Set a default badge -dockService.SetBadge("") - -// Set a numeric badge -dockService.SetBadge("3") - -// Set a text badge -dockService.SetBadge("New") -``` - -### Setting a Custom Badge (Windows Only) - -Set a badge with one-off options applied: - -```go -options := dock.BadgeOptions{ - BackgroundColour: color.RGBA{0, 255, 255, 255}, - FontName: "arialb.ttf", // System font - FontSize: 16, - SmallFontSize: 10, - TextColour: color.RGBA{0, 0, 0, 255}, -} - -// Set a default badge -dockService.SetCustomBadge("", options) - -// Set a numeric badge -dockService.SetCustomBadge("3", options) - -// Set a text badge -dockService.SetCustomBadge("New", options) -``` - -### Removing a Badge - -Remove the badge from the application icon: - -```go -dockService.RemoveBadge() -``` - -## Platform Considerations - - - - - On macOS: - - - The dock icon can be **hidden** and **shown** - - Badges are displayed directly on the dock icon - - Badge options are **not customizable** (any options passed to `NewWithOptions`/`SetCustomBadge` are ignored) - - The standard macOS dock badge styling is used and automatically adapts to appearance - - Label overflow is handled by the system - - Providing an empty label displays a default badge of "●" - - - - - - On Windows: - - - Hiding/showing the taskbar icon is not currently supported by this service - - Badges are displayed as an overlay icon in the taskbar - - Badges support text values - - Badge appearance can be customized via `BadgeOptions` - - The application must have a window for badges to display - - A smaller font size is automatically used for multi-character labels - - Label overflow is not handled - - Customization options: - - **TextColour**: Text color (default: white) - - **BackgroundColour**: Badge background color (default: red) - - **FontName**: Font file name (default: "segoeuib.ttf") - - **FontSize**: Font size for single character (default: 18) - - **SmallFontSize**: Font size for multiple characters (default: 14) - - - - - - On Linux: - - - Dock icon visibility and badge functionality are not available - - - - -## Best Practices - -1. **When hiding the dock icon (macOS):** - - Ensure users can still access your app (e.g., via [system tray](https://v3alpha.wails.io/learn/systray/)) - - Include a "Quit" option in your alternative UI - - The app won't appear in Command+Tab switcher - - Open windows remain visible and functional - - Closing all windows may not quit the app (macOS behavior varies) - - Users lose the standard way to quit via Dock right-click - -2. **Use badges sparingly:** - - Too many badge updates can distract users - - Reserve badges for important notifications - -3. **Keep badge text short:** - - Numeric badges are most effective - - On macOS, text badges should be brief - -4. **For Windows badge customization:** - - Ensure high contrast between text and background colors - - Test with different text lengths as font size decreases with length - - Use common system fonts to ensure availability - - -## API Reference - -### Service Management -| Method | Description | -|--------------------------------------------|-------------------------------------------------------| -| `New()` | Creates a new dock service | -| `NewWithOptions(options BadgeOptions)` | Creates a new dock service with custom badge options (Windows only; options are ignored on macOS and Linux) | - -### Dock Operations -| Method | Description | -|--------------------------------|-------------------------------------------------------------| -| `HideAppIcon()` | Hides the app icon from the macOS Dock (macOS only) | -| `ShowAppIcon()` | Shows the app icon in the macOS Dock (macOS only) | - -### Badge Operations -| Method | Description | -|---------------------------------------------------|------------------------------------------------------------| -| `SetBadge(label string) error` | Sets a badge with the specified label | -| `SetCustomBadge(label string, options BadgeOptions) error` | Sets a badge with the specified label and custom styling options (Windows only) | -| `RemoveBadge() error` | Removes the badge from the application icon | - -### Structs and Types - -```go -// Options for customizing badge appearance (Windows only) -type BadgeOptions struct { - TextColour color.RGBA // Color of the badge text - BackgroundColour color.RGBA // Color of the badge background - FontName string // Font file name (e.g., "segoeuib.ttf") - FontSize int // Font size for single character - SmallFontSize int // Font size for multiple characters -} -``` diff --git a/docs/src/content/docs/features/screens/info.mdx b/docs/src/content/docs/features/screens/info.mdx deleted file mode 100644 index a1ade0a27..000000000 --- a/docs/src/content/docs/features/screens/info.mdx +++ /dev/null @@ -1,466 +0,0 @@ ---- -title: Screen Information -description: Get information about displays and monitors -sidebar: - order: 1 ---- - -import { Card, CardGrid } from "@astrojs/starlight/components"; - -## Screen Information - -Wails provides a **unified screen API** that works across all platforms. Get screen information, detect multiple monitors, query screen properties (size, position, DPI), identify the primary display, and handle DPI scaling with consistent code. - -## Quick Start - -```go -// Get all screens -screens := app.Screen.GetAll() - -for _, screen := range screens { - fmt.Printf("Screen: %s (%dx%d)\n", - screen.Name, screen.Width, screen.Height) -} - -// Get primary screen -primary := app.Screens.GetPrimary() -fmt.Printf("Primary: %s\n", primary.Name) -``` - -**That's it!** Cross-platform screen information. - -## Getting Screen Information - -### All Screens - -```go -screens := app.Screen.GetAll() - -for _, screen := range screens { - fmt.Printf("ID: %s\n", screen.ID) - fmt.Printf("Name: %s\n", screen.Name) - fmt.Printf("Size: %dx%d\n", screen.Width, screen.Height) - fmt.Printf("Position: %d,%d\n", screen.X, screen.Y) - fmt.Printf("Scale: %.2f\n", screen.ScaleFactor) - fmt.Printf("Primary: %v\n", screen.IsPrimary) - fmt.Println("---") -} -``` - -### Primary Screen - -```go -primary := app.Screens.GetPrimary() - -fmt.Printf("Primary screen: %s\n", primary.Name) -fmt.Printf("Resolution: %dx%d\n", primary.Width, primary.Height) -fmt.Printf("Scale factor: %.2f\n", primary.ScaleFactor) -``` - -### Current Screen - -Get the screen containing a window: - -```go -screen := app.Screens.GetCurrent(window) - -fmt.Printf("Window is on: %s\n", screen.Name) -``` - -### Screen by ID - -```go -screen := app.Screens.GetByID("screen-id") -if screen != nil { - fmt.Printf("Found screen: %s\n", screen.Name) -} -``` - -## Screen Properties - -### Screen Structure - -```go -type Screen struct { - ID string // Unique identifier - Name string // Display name - X int // X position - Y int // Y position - Width int // Width in pixels - Height int // Height in pixels - ScaleFactor float32 // DPI scale (1.0, 1.5, 2.0, etc.) - IsPrimary bool // Is this the primary screen? -} -``` - -### Physical vs Logical Pixels - -```go -screen := app.Screens.GetPrimary() - -// Logical pixels (what you use) -logicalWidth := screen.Width -logicalHeight := screen.Height - -// Physical pixels (actual display) -physicalWidth := int(float32(screen.Width) * screen.ScaleFactor) -physicalHeight := int(float32(screen.Height) * screen.ScaleFactor) - -fmt.Printf("Logical: %dx%d\n", logicalWidth, logicalHeight) -fmt.Printf("Physical: %dx%d\n", physicalWidth, physicalHeight) -fmt.Printf("Scale: %.2f\n", screen.ScaleFactor) -``` - -**Common scale factors:** -- `1.0` - Standard DPI (96 DPI) -- `1.25` - 125% scaling (120 DPI) -- `1.5` - 150% scaling (144 DPI) -- `2.0` - 200% scaling (192 DPI) - Retina -- `3.0` - 300% scaling (288 DPI) - 4K/5K - -## Window Positioning - -### Centre on Screen - -```go -func centreOnScreen(window *application.WebviewWindow, screen *Screen) { - windowWidth, windowHeight := window.Size() - - x := screen.X + (screen.Width-windowWidth)/2 - y := screen.Y + (screen.Height-windowHeight)/2 - - window.SetPosition(x, y) -} -``` - -### Position on Specific Screen - -```go -func moveToScreen(window *application.WebviewWindow, screenIndex int) { - screens := app.Screen.GetAll() - - if screenIndex < 0 || screenIndex >= len(screens) { - return - } - - screen := screens[screenIndex] - - // Centre on target screen - centreOnScreen(window, screen) -} -``` - -### Position Relative to Screen - -```go -// Top-left corner -func positionTopLeft(window *application.WebviewWindow, screen *Screen) { - window.SetPosition(screen.X+10, screen.Y+10) -} - -// Top-right corner -func positionTopRight(window *application.WebviewWindow, screen *Screen) { - windowWidth, _ := window.Size() - window.SetPosition(screen.X+screen.Width-windowWidth-10, screen.Y+10) -} - -// Bottom-right corner -func positionBottomRight(window *application.WebviewWindow, screen *Screen) { - windowWidth, windowHeight := window.Size() - window.SetPosition( - screen.X+screen.Width-windowWidth-10, - screen.Y+screen.Height-windowHeight-10, - ) -} -``` - -## Multi-Monitor Support - -### Detect Multiple Monitors - -```go -func hasMultipleMonitors() bool { - return len(app.Screen.GetAll()) > 1 -} - -func getMonitorCount() int { - return len(app.Screen.GetAll()) -} -``` - -### List All Monitors - -```go -func listMonitors() { - screens := app.Screen.GetAll() - - fmt.Printf("Found %d monitor(s):\n", len(screens)) - - for i, screen := range screens { - primary := "" - if screen.IsPrimary { - primary = " (Primary)" - } - - fmt.Printf("%d. %s%s\n", i+1, screen.Name, primary) - fmt.Printf(" Resolution: %dx%d\n", screen.Width, screen.Height) - fmt.Printf(" Position: %d,%d\n", screen.X, screen.Y) - fmt.Printf(" Scale: %.2fx\n", screen.ScaleFactor) - } -} -``` - -### Choose Monitor - -```go -func chooseMonitor() (*Screen, error) { - screens := app.Screen.GetAll() - - if len(screens) == 1 { - return screens[0], nil - } - - // Show dialog to choose - var options []string - for i, screen := range screens { - primary := "" - if screen.IsPrimary { - primary = " (Primary)" - } - options = append(options, - fmt.Sprintf("%d. %s%s - %dx%d", - i+1, screen.Name, primary, screen.Width, screen.Height)) - } - - // Use dialog to select - // (Implementation depends on your dialog system) - - return screens[0], nil -} -``` - -## Complete Examples - -### Multi-Monitor Window Manager - -```go -type MultiMonitorManager struct { - app *application.Application - windows map[int]*application.WebviewWindow -} - -func NewMultiMonitorManager(app *application.Application) *MultiMonitorManager { - return &MultiMonitorManager{ - app: app, - windows: make(map[int]*application.WebviewWindow), - } -} - -func (m *MultiMonitorManager) CreateWindowOnScreen(screenIndex int) error { - screens := m.app.Screen.GetAll() - - if screenIndex < 0 || screenIndex >= len(screens) { - return errors.New("invalid screen index") - } - - screen := screens[screenIndex] - - // Create window - window := m.app.Window.NewWithOptions(application.WebviewWindowOptions{ - Title: fmt.Sprintf("Window on %s", screen.Name), - Width: 800, - Height: 600, - }) - - // Centre on screen - x := screen.X + (screen.Width-800)/2 - y := screen.Y + (screen.Height-600)/2 - window.SetPosition(x, y) - - window.Show() - - m.windows[screenIndex] = window - return nil -} - -func (m *MultiMonitorManager) CreateWindowOnEachScreen() { - screens := m.app.Screen.GetAll() - - for i := range screens { - m.CreateWindowOnScreen(i) - } -} -``` - -### Screen Change Detection - -```go -type ScreenMonitor struct { - app *application.Application - lastScreens []*Screen - changeHandler func([]*Screen) -} - -func NewScreenMonitor(app *application.Application) *ScreenMonitor { - return &ScreenMonitor{ - app: app, - lastScreens: app.Screen.GetAll(), - } -} - -func (sm *ScreenMonitor) OnScreenChange(handler func([]*Screen)) { - sm.changeHandler = handler -} - -func (sm *ScreenMonitor) Start() { - ticker := time.NewTicker(2 * time.Second) - - go func() { - for range ticker.C { - sm.checkScreens() - } - }() -} - -func (sm *ScreenMonitor) checkScreens() { - current := sm.app.Screen.GetAll() - - if len(current) != len(sm.lastScreens) { - sm.lastScreens = current - if sm.changeHandler != nil { - sm.changeHandler(current) - } - } -} -``` - -### DPI-Aware Window Sizing - -```go -func createDPIAwareWindow(screen *Screen) *application.WebviewWindow { - // Base size at 1.0 scale - baseWidth := 800 - baseHeight := 600 - - // Adjust for DPI - width := int(float32(baseWidth) * screen.ScaleFactor) - height := int(float32(baseHeight) * screen.ScaleFactor) - - window := app.Window.NewWithOptions(application.WebviewWindowOptions{ - Title: "DPI-Aware Window", - Width: width, - Height: height, - }) - - // Centre on screen - x := screen.X + (screen.Width-width)/2 - y := screen.Y + (screen.Height-height)/2 - window.SetPosition(x, y) - - return window -} -``` - -### Screen Layout Visualiser - -```go -func visualiseScreenLayout() string { - screens := app.Screen.GetAll() - - var layout strings.Builder - layout.WriteString("Screen Layout:\n\n") - - for i, screen := range screens { - primary := "" - if screen.IsPrimary { - primary = " [PRIMARY]" - } - - layout.WriteString(fmt.Sprintf("Screen %d: %s%s\n", i+1, screen.Name, primary)) - layout.WriteString(fmt.Sprintf(" Position: (%d, %d)\n", screen.X, screen.Y)) - layout.WriteString(fmt.Sprintf(" Size: %dx%d\n", screen.Width, screen.Height)) - layout.WriteString(fmt.Sprintf(" Scale: %.2fx\n", screen.ScaleFactor)) - layout.WriteString(fmt.Sprintf(" Physical: %dx%d\n", - int(float32(screen.Width)*screen.ScaleFactor), - int(float32(screen.Height)*screen.ScaleFactor))) - layout.WriteString("\n") - } - - return layout.String() -} -``` - -## Best Practices - -### ✅ Do - -- **Check screen count** - Handle single and multiple monitors -- **Use logical pixels** - Wails handles DPI automatically -- **Centre windows** - Better UX than fixed positions -- **Validate positions** - Ensure windows are visible -- **Handle screen changes** - Monitors can be added/removed -- **Test on different DPI** - 100%, 125%, 150%, 200% - -### ❌ Don't - -- **Don't hardcode positions** - Use screen dimensions -- **Don't assume primary screen** - User might have multiple -- **Don't ignore scale factor** - Important for DPI awareness -- **Don't position off-screen** - Validate coordinates -- **Don't forget screen changes** - Laptops dock/undock -- **Don't use physical pixels** - Use logical pixels - -## Platform Differences - -### macOS - -- Retina displays (2x scale factor) -- Multiple displays common -- Coordinate system: (0,0) at bottom-left -- Spaces (virtual desktops) affect positioning - -### Windows - -- Various DPI scaling (100%, 125%, 150%, 200%) -- Multiple displays common -- Coordinate system: (0,0) at top-left -- Per-monitor DPI awareness - -### Linux - -- Varies by desktop environment -- X11 vs Wayland differences -- DPI scaling support varies -- Multiple displays supported - -## Next Steps - - - - Learn about window management. - - [Learn More →](/features/windows/basics) - - - - Configure window appearance. - - [Learn More →](/features/windows/options) - - - - Multi-window patterns. - - [Learn More →](/features/windows/multiple) - - - - Call Go functions from JavaScript. - - [Learn More →](/features/bindings/methods) - - - ---- - -**Questions?** Ask in [Discord](https://discord.gg/JDdSxwjhGf) or check the [screen examples](https://github.com/wailsapp/wails/tree/v3-alpha/v3/examples). diff --git a/docs/src/content/docs/features/windows/basics.mdx b/docs/src/content/docs/features/windows/basics.mdx deleted file mode 100644 index deed35602..000000000 --- a/docs/src/content/docs/features/windows/basics.mdx +++ /dev/null @@ -1,616 +0,0 @@ ---- -title: Window Basics -description: Creating and managing application windows in Wails -sidebar: - order: 1 ---- - -import { Tabs, TabItem, Card, CardGrid } from "@astrojs/starlight/components"; - -## Window Management - -Wails provides a **unified window management API** that works across all platforms. Create windows, control their behaviour, and manage multiple windows with full control over creation, appearance, behaviour, and lifecycle. - -## Quick Start - -```go -package main - -import "github.com/wailsapp/wails/v3/pkg/application" - -func main() { - app := application.New(application.Options{ - Name: "My App", - }) - - // Create a window - window := app.Window.New() - - // Configure it - window.SetTitle("Hello Wails") - window.SetSize(800, 600) - window.Center() - - // Show it - window.Show() - - app.Run() -} -``` - -**That's it!** You have a cross-platform window. - -## Creating Windows - -### Basic Window - -The simplest way to create a window: - -```go -window := app.Window.New() -``` - -**What you get:** -- Default size (800x600) -- Default title (application name) -- WebView ready for your frontend -- Platform-native appearance - -### Window with Options - -Create a window with custom configuration: - -```go -window := app.Window.NewWithOptions(application.WebviewWindowOptions{ - Title: "My Application", - Width: 1200, - Height: 800, - X: 100, // Position from left - Y: 100, // Position from top - AlwaysOnTop: false, - Frameless: false, - Hidden: false, - MinWidth: 400, - MinHeight: 300, - MaxWidth: 1920, - MaxHeight: 1080, -}) -``` - -**Common options:** - -| Option | Type | Description | -|--------|------|-------------| -| `Title` | `string` | Window title | -| `Width` | `int` | Window width in pixels | -| `Height` | `int` | Window height in pixels | -| `X` | `int` | X position (from left) | -| `Y` | `int` | Y position (from top) | -| `AlwaysOnTop` | `bool` | Keep window above others | -| `Frameless` | `bool` | Remove title bar and borders | -| `Hidden` | `bool` | Start hidden | -| `MinWidth` | `int` | Minimum width | -| `MinHeight` | `int` | Minimum height | -| `MaxWidth` | `int` | Maximum width | -| `MaxHeight` | `int` | Maximum height | - -**See [Window Options](/features/windows/options) for complete list.** - -### Named Windows - -Give windows names for easy retrieval: - -```go -window := app.Window.NewWithOptions(application.WebviewWindowOptions{ - Name: "main-window", - Title: "Main Application", -}) - -// Later, find it by name -mainWindow := app.GetWindowByName("main-window") -if mainWindow != nil { - mainWindow.Show() -} -``` - -**Use cases:** -- Multiple windows (main, settings, about) -- Finding windows from different parts of your code -- Window communication - -## Controlling Windows - -### Show and Hide - -```go -// Show window -window.Show() - -// Hide window -window.Hide() - -// Check if visible -if window.IsVisible() { - fmt.Println("Window is visible") -} -``` - -**Use cases:** -- Splash screens (show, then hide) -- Settings windows (hide when not needed) -- Popup windows (show on demand) - -### Position and Size - -```go -// Set size -window.SetSize(1024, 768) - -// Set position -window.SetPosition(100, 100) - -// Centre on screen -window.Center() - -// Get current size -width, height := window.Size() - -// Get current position -x, y := window.Position() -``` - -**Coordinate system:** -- (0, 0) is top-left of primary screen -- Positive X goes right -- Positive Y goes down - -### Window State - -```go -// Minimise -window.Minimise() - -// Maximise -window.Maximise() - -// Fullscreen -window.Fullscreen() - -// Restore to normal -window.Restore() - -// Check state -if window.IsMinimised() { - fmt.Println("Window is minimised") -} - -if window.IsMaximised() { - fmt.Println("Window is maximised") -} - -if window.IsFullscreen() { - fmt.Println("Window is fullscreen") -} -``` - -**State transitions:** - -``` -Normal ←→ Minimised -Normal ←→ Maximised -Normal ←→ Fullscreen -``` - -### Title and Appearance - -```go -// Set title -window.SetTitle("My Application - Document.txt") - -// Set background colour -window.SetBackgroundColour(0, 0, 0, 255) // RGBA - -// Set always on top -window.SetAlwaysOnTop(true) - -// Set resizable -window.SetResizable(false) -``` - -### Closing Windows - -```go -// Close window -window.Close() - -// Destroy window (force close) -window.Destroy() -``` - -**Difference:** -- `Close()` - Triggers close event, can be cancelled -- `Destroy()` - Immediate destruction, cannot be cancelled - -## Finding Windows - -### By Name - -```go -window := app.GetWindowByName("settings") -if window != nil { - window.Show() -} -``` - -### By ID - -Every window has a unique ID: - -```go -id := window.ID() -fmt.Printf("Window ID: %d\n", id) - -// Find by ID -foundWindow := app.GetWindowByID(id) -``` - -### Current Window - -Get the currently focused window: - -```go -current := app.Window.Current() -if current != nil { - current.SetTitle("Active Window") -} -``` - -### All Windows - -Get all windows: - -```go -windows := app.Window.GetAll() -fmt.Printf("Total windows: %d\n", len(windows)) - -for _, w := range windows { - fmt.Printf("Window: %s (ID: %d)\n", w.Name(), w.ID()) -} -``` - -## Window Lifecycle - -### Creation - -```go -app.OnWindowCreation(func(window *application.WebviewWindow) { - fmt.Printf("Window created: %s\n", window.Name()) - - // Configure new windows - window.SetMinSize(400, 300) -}) -``` - -### Closing - -```go -window.OnClose(func() bool { - // Return false to cancel close - // Return true to allow close - - if hasUnsavedChanges() { - result := showConfirmdialog("Unsaved changes. Close anyway?") - return result == "yes" - } - return true -}) -``` - -**Important:** `OnClose` only works for user-initiated closes (clicking X button). It doesn't prevent `window.Destroy()`. - -### Destruction - -```go -window.OnDestroy(func() { - fmt.Println("Window destroyed") - // Cleanup resources -}) -``` - -## Multiple Windows - -### Creating Multiple Windows - -```go -// Main window -mainWindow := app.Window.NewWithOptions(application.WebviewWindowOptions{ - Name: "main", - Title: "Main Application", - Width: 1200, - Height: 800, -}) - -// Settings window -settingsWindow := app.Window.NewWithOptions(application.WebviewWindowOptions{ - Name: "settings", - Title: "Settings", - Width: 600, - Height: 400, - Hidden: true, // Start hidden -}) - -// Show settings when needed -settingsWindow.Show() -``` - -### Window Communication - -Windows can communicate via events: - -```go -// In main window -app.Event.Emit("data-updated", map[string]interface{}{ - "value": 42, -}) - -// In settings window -app.Event.On("data-updated", func(event *application.WailsEvent) { - data := event.Data.(map[string]interface{}) - value := data["value"].(int) - fmt.Printf("Received: %d\n", value) -}) -``` - -**See [Events](/features/events/system) for more.** - -### Parent-Child Windows - -```go -// Create child window -childWindow := app.Window.NewWithOptions(application.WebviewWindowOptions{ - Title: "Child Window", - Parent: mainWindow, // Set parent -}) -``` - -**Behaviour:** -- Child closes when parent closes -- Child stays above parent (on some platforms) -- Child minimises with parent (on some platforms) - -**Platform support:** -- **macOS:** Full support -- **Windows:** Partial support -- **Linux:** Varies by desktop environment - -## Platform-Specific Features - - - - **Windows-specific features:** - - ```go - // Flash taskbar button - window.Flash(true) // Start flashing - window.Flash(false) // Stop flashing - - // Trigger Windows 11 Snap Assist (Win+Z) - window.SnapAssist() - - // Set window icon - window.SetIcon(iconBytes) - ``` - - **Snap Assist:** - Shows Windows 11 snap layout options for the window. - - **Taskbar flashing:** - Useful for notifications when window is minimised. - - - - **macOS-specific features:** - - ```go - // Transparent title bar - window := app.Window.NewWithOptions(application.WebviewWindowOptions{ - Mac: application.MacWindow{ - TitleBar: application.MacTitleBar{ - AppearsTransparent: true, - }, - Backdrop: application.MacBackdropTranslucent, - }, - }) - ``` - - **Backdrop types:** - - `MacBackdropNormal` - Standard window - - `MacBackdropTranslucent` - Translucent background - - `MacBackdropTransparent` - Fully transparent - - **Collection behavior:** - Control how windows behave across Spaces: - - `MacWindowCollectionBehaviorCanJoinAllSpaces` - Visible on all Spaces - - `MacWindowCollectionBehaviorFullScreenAuxiliary` - Can overlay fullscreen apps - - **Native fullscreen:** - macOS fullscreen creates a new Space (virtual desktop). - - - - **Linux-specific features:** - - ```go - // Set window icon - window := app.Window.NewWithOptions(application.WebviewWindowOptions{ - Linux: application.LinuxOptions{ - Icon: iconBytes, - }, - }) - ``` - - **Desktop environment notes:** - - GNOME: Full support - - KDE Plasma: Full support - - XFCE: Partial support - - Others: Varies - - **Tiling window managers (Hyprland, Sway, i3, etc.):** - - `Minimise()` and `Maximise()` may not work as expected - the WM controls window geometry - - `SetSize()` and `SetPosition()` requests are advisory and may be ignored - - `Fullscreen()` typically works as expected - - Some WMs don't support always-on-top - - - -## Common Patterns - -### Splash Screen - -```go -// Create splash screen -splash := app.Window.NewWithOptions(application.WebviewWindowOptions{ - Title: "Loading...", - Width: 400, - Height: 300, - Frameless: true, - AlwaysOnTop: true, -}) - -// Show splash -splash.Show() - -// Initialise application -time.Sleep(2 * time.Second) - -// Hide splash, show main window -splash.Close() -mainWindow.Show() -``` - -### Settings Window - -```go -var settingsWindow *application.WebviewWindow - -func showSettings() { - if settingsWindow == nil { - settingsWindow = app.Window.NewWithOptions(application.WebviewWindowOptions{ - Name: "settings", - Title: "Settings", - Width: 600, - Height: 400, - }) - } - - settingsWindow.Show() - settingsWindow.SetFocus() -} -``` - -### Confirm Before Close - -```go -window.OnClose(func() bool { - if hasUnsavedChanges() { - // Show dialog - result := showConfirmdialog("Unsaved changes. Close anyway?") - return result == "yes" - } - return true -}) -``` - -## Best Practices - -### ✅ Do - -- **Name important windows** - Easier to find later -- **Set minimum size** - Prevent unusable layouts -- **Centre windows** - Better UX than random position -- **Handle close events** - Prevent data loss -- **Test on all platforms** - Behaviour varies -- **Use appropriate sizes** - Consider different screen sizes - -### ❌ Don't - -- **Don't create too many windows** - Confusing for users -- **Don't forget to close windows** - Memory leaks -- **Don't hardcode positions** - Different screen sizes -- **Don't ignore platform differences** - Test thoroughly -- **Don't block the UI thread** - Use goroutines for long operations - -## Troubleshooting - -### Window Not Showing - -**Possible causes:** -1. Window created as hidden -2. Window off-screen -3. Window behind other windows - -**Solution:** - -```go -window.Show() -window.Center() -window.SetFocus() -``` - -### Window Wrong Size - -**Cause:** DPI scaling on Windows/Linux - -**Solution:** - -```go -// Wails handles DPI automatically -// Just use logical pixels -window.SetSize(800, 600) -``` - -### Window Closes Immediately - -**Cause:** Application exits when last window closes - -**Solution:** - -```go -app := application.New(application.Options{ - Mac: application.MacOptions{ - ApplicationShouldTerminateAfterLastWindowClosed: false, - }, -}) -``` - -## Next Steps - - - - Complete reference for all window options. - - [Learn More →](/features/windows/options) - - - - Patterns for multi-window applications. - - [Learn More →](/features/windows/multiple) - - - - Create custom window chrome. - - [Learn More →](/features/windows/frameless) - - - - Handle window lifecycle events. - - [Learn More →](/features/windows/events) - - - ---- - -**Questions?** Ask in [Discord](https://discord.gg/JDdSxwjhGf) or check the [window examples](https://github.com/wailsapp/wails/tree/v3-alpha/v3/examples). diff --git a/docs/src/content/docs/features/windows/events.mdx b/docs/src/content/docs/features/windows/events.mdx deleted file mode 100644 index b45c6596c..000000000 --- a/docs/src/content/docs/features/windows/events.mdx +++ /dev/null @@ -1,693 +0,0 @@ ---- -title: Window Events -description: Handle window lifecycle and state change events -sidebar: - order: 5 ---- - -import { Tabs, TabItem } from "@astrojs/starlight/components"; - -## Window Events - -Wails provides **comprehensive event hooks** for window lifecycle and state changes: creation, focus/blur, resize/move, minimise/maximise, and close events. Register callbacks, handle events, and coordinate between windows with simple, consistent APIs. - -## Lifecycle Events - -### OnCreate - -Called when a window is created: - -```go -app.OnWindowCreation(func(window *application.WebviewWindow) { - fmt.Printf("Window created: %s (ID: %d)\n", window.Name(), window.ID()) - - // Configure all new windows - window.SetMinSize(400, 300) - - // Register window-specific handlers - window.OnClose(func() bool { - return confirmClose() - }) -}) -``` - -**Use cases:** -- Configure all windows consistently -- Register event handlers -- Track window creation -- Initialise window-specific resources - -### OnClose - -Called when user attempts to close window: - -```go -window.OnClose(func() bool { - // Return false to cancel close - // Return true to allow close - - if hasUnsavedChanges() { - result := showConfirmdialog("Unsaved changes. Close anyway?") - return result == "yes" - } - return true -}) -``` - -**Important:** -- Only triggered by user actions (clicking X button) -- NOT triggered by `window.Destroy()` -- Can cancel the close by returning `false` - -**Use cases:** -- Confirm before closing -- Save state -- Prevent accidental closure -- Cleanup before close - -**Example with dialog:** - -```go -window.OnClose(func() bool { - if !hasUnsavedChanges() { - return true - } - - // Show confirmation dialog - dialog := app.Window.NewWithOptions(application.WebviewWindowOptions{ - Title: "Confirm Close", - Width: 400, - Height: 150, - Parent: window, - AlwaysOnTop: true, - }) - - // Wait for user response - result := waitFordialogResult(dialog) - - return result == "yes" -}) -``` - -### OnDestroy - -Called when window is destroyed: - -```go -window.OnDestroy(func() { - fmt.Printf("Window destroyed: %s\n", window.Name()) - - // Cleanup resources - closeDatabase() - - // Remove from tracking - removeWindowFromRegistry(window.ID()) - - // Update application state - updateWindowCount() -}) -``` - -**Important:** -- Always called when window is destroyed -- Cannot be cancelled -- Last chance to cleanup - -**Use cases:** -- Release resources -- Close connections -- Update application state -- Remove from tracking - -**Example with resource cleanup:** - -```go -type ManagedWindow struct { - window *application.WebviewWindow - db *sql.DB - listeners []func() -} - -func (mw *ManagedWindow) Setup() { - mw.window.OnDestroy(func() { - // Close database - if mw.db != nil { - mw.db.Close() - } - - // Remove event listeners - for _, listener := range mw.listeners { - listener() - } - - // Clear references - mw.db = nil - mw.listeners = nil - }) -} -``` - -## Focus Events - -### OnFocus - -Called when window gains focus: - -```go -window.OnFocus(func() { - fmt.Println("Window gained focus") - - // Update UI - updateTitleBar(true) - - // Refresh data - refreshContent() - - // Notify other windows - app.Event.Emit("window-focused", window.ID()) -}) -``` - -**Use cases:** -- Update UI appearance -- Refresh data -- Resume operations -- Coordinate with other windows - -### OnBlur - -Called when window loses focus: - -```go -window.OnBlur(func() { - fmt.Println("Window lost focus") - - // Update UI - updateTitleBar(false) - - // Pause operations - pauseAnimations() - - // Save state - saveCurrentState() -}) -``` - -**Use cases:** -- Update UI appearance -- Pause operations -- Save state -- Reduce resource usage - -**Example: Focus-aware UI:** - -```go -type FocusAwareWindow struct { - window *application.WebviewWindow - focused bool -} - -func (fw *FocusAwareWindow) Setup() { - fw.window.OnFocus(func() { - fw.focused = true - fw.updateAppearance() - }) - - fw.window.OnBlur(func() { - fw.focused = false - fw.updateAppearance() - }) -} - -func (fw *FocusAwareWindow) updateAppearance() { - if fw.focused { - fw.window.EmitEvent("update-theme", "active") - } else { - fw.window.EmitEvent("update-theme", "inactive") - } -} -``` - -## State Change Events - -### OnMinimise / OnUnMinimise - -Called when window is minimised or restored: - -```go -window.OnMinimise(func() { - fmt.Println("Window minimised") - - // Pause expensive operations - pauseRendering() - - // Save state - saveWindowState() -}) - -window.OnUnMinimise(func() { - fmt.Println("Window restored from minimised") - - // Resume operations - resumeRendering() - - // Refresh data - refreshContent() -}) -``` - -**Use cases:** -- Pause/resume operations -- Save/restore state -- Reduce resource usage -- Update UI - -### OnMaximise / OnUnMaximise - -Called when window is maximised or restored: - -```go -window.OnMaximise(func() { - fmt.Println("Window maximised") - - // Adjust layout - window.EmitEvent("layout-mode", "maximised") - - // Update button icon - updateMaximiseButton("restore") -}) - -window.OnUnMaximise(func() { - fmt.Println("Window restored from maximised") - - // Adjust layout - window.EmitEvent("layout-mode", "normal") - - // Update button icon - updateMaximiseButton("maximise") -}) -``` - -**Use cases:** -- Adjust layout -- Update UI -- Save window state -- Coordinate with other windows - -### OnFullscreen / OnUnFullscreen - -Called when window enters or exits fullscreen: - -```go -window.OnFullscreen(func() { - fmt.Println("Window entered fullscreen") - - // Hide UI chrome - window.EmitEvent("chrome-visibility", false) - - // Adjust layout - window.EmitEvent("layout-mode", "fullscreen") -}) - -window.OnUnFullscreen(func() { - fmt.Println("Window exited fullscreen") - - // Show UI chrome - window.EmitEvent("chrome-visibility", true) - - // Restore layout - window.EmitEvent("layout-mode", "normal") -}) -``` - -**Use cases:** -- Show/hide UI elements -- Adjust layout -- Update controls -- Save preferences - -## Position and Size Events - -### OnMove - -Called when window is moved: - -```go -window.OnMove(func(x, y int) { - fmt.Printf("Window moved to: %d, %d\n", x, y) - - // Save position - saveWindowPosition(x, y) - - // Update related windows - updateRelatedWindowPositions(x, y) -}) -``` - -**Use cases:** -- Save window position -- Update related windows -- Snap to edges -- Multi-monitor handling - -### OnResize - -Called when window is resized: - -```go -window.OnResize(func(width, height int) { - fmt.Printf("Window resized to: %dx%d\n", width, height) - - // Save size - saveWindowSize(width, height) - - // Adjust layout - window.EmitEvent("window-size", map[string]int{ - "width": width, - "height": height, - }) -}) -``` - -**Use cases:** -- Save window size -- Adjust layout -- Update UI -- Responsive design - -**Example: Responsive layout:** - -```go -window.OnResize(func(width, height int) { - var layout string - - if width < 600 { - layout = "compact" - } else if width < 1200 { - layout = "normal" - } else { - layout = "wide" - } - - window.EmitEvent("layout-changed", layout) -}) -``` - -## Complete Example - -Here's a production-ready window with full event handling: - -```go -package main - -import ( - "encoding/json" - "fmt" - "os" - "github.com/wailsapp/wails/v3/pkg/application" -) - -type WindowState struct { - X int `json:"x"` - Y int `json:"y"` - Width int `json:"width"` - Height int `json:"height"` - Maximised bool `json:"maximised"` - Fullscreen bool `json:"fullscreen"` -} - -type ManagedWindow struct { - app *application.Application - window *application.WebviewWindow - state WindowState - dirty bool -} - -func main() { - app := application.New(application.Options{ - Name: "Event Demo", - }) - - mw := &ManagedWindow{app: app} - mw.CreateWindow() - mw.LoadState() - mw.SetupEventHandlers() - - app.Run() -} - -func (mw *ManagedWindow) CreateWindow() { - mw.window = mw.app.Window.NewWithOptions(application.WebviewWindowOptions{ - Name: "main", - Title: "Event Demo", - Width: 800, - Height: 600, - }) -} - -func (mw *ManagedWindow) SetupEventHandlers() { - // Focus events - mw.window.OnFocus(func() { - fmt.Println("Window focused") - mw.window.EmitEvent("focus-state", true) - }) - - mw.window.OnBlur(func() { - fmt.Println("Window blurred") - mw.window.EmitEvent("focus-state", false) - }) - - // State change events - mw.window.OnMinimise(func() { - fmt.Println("Window minimised") - mw.SaveState() - }) - - mw.window.OnUnMinimise(func() { - fmt.Println("Window restored") - }) - - mw.window.OnMaximise(func() { - fmt.Println("Window maximised") - mw.state.Maximised = true - mw.dirty = true - }) - - mw.window.OnUnMaximise(func() { - fmt.Println("Window restored from maximised") - mw.state.Maximised = false - mw.dirty = true - }) - - mw.window.OnFullscreen(func() { - fmt.Println("Window fullscreen") - mw.state.Fullscreen = true - mw.dirty = true - }) - - mw.window.OnUnFullscreen(func() { - fmt.Println("Window exited fullscreen") - mw.state.Fullscreen = false - mw.dirty = true - }) - - // Position and size events - mw.window.OnMove(func(x, y int) { - mw.state.X = x - mw.state.Y = y - mw.dirty = true - }) - - mw.window.OnResize(func(width, height int) { - mw.state.Width = width - mw.state.Height = height - mw.dirty = true - }) - - // Lifecycle events - mw.window.OnClose(func() bool { - if mw.dirty { - mw.SaveState() - } - return true - }) - - mw.window.OnDestroy(func() { - fmt.Println("Window destroyed") - if mw.dirty { - mw.SaveState() - } - }) -} - -func (mw *ManagedWindow) LoadState() { - data, err := os.ReadFile("window-state.json") - if err != nil { - return - } - - if err := json.Unmarshal(data, &mw.state); err != nil { - return - } - - // Restore window state - mw.window.SetPosition(mw.state.X, mw.state.Y) - mw.window.SetSize(mw.state.Width, mw.state.Height) - - if mw.state.Maximised { - mw.window.Maximise() - } - - if mw.state.Fullscreen { - mw.window.Fullscreen() - } -} - -func (mw *ManagedWindow) SaveState() { - data, err := json.Marshal(mw.state) - if err != nil { - return - } - - os.WriteFile("window-state.json", data, 0644) - mw.dirty = false - - fmt.Println("Window state saved") -} -``` - -## Event Coordination - -### Cross-Window Events - -Coordinate between multiple windows: - -```go -// In main window -mainWindow.OnFocus(func() { - // Notify all windows - app.Event.Emit("main-window-focused", nil) -}) - -// In other windows -app.Event.On("main-window-focused", func(event *application.WailsEvent) { - // Update UI - updateRelativeToMain() -}) -``` - -### Event Chains - -Chain events together: - -```go -window.OnMaximise(func() { - // Save state - saveWindowState() - - // Update layout - window.EmitEvent("layout-changed", "maximised") - - // Notify other windows - app.Event.Emit("window-maximised", window.ID()) -}) -``` - -### Debounced Events - -Debounce frequent events: - -```go -var resizeTimer *time.Timer - -window.OnResize(func(width, height int) { - if resizeTimer != nil { - resizeTimer.Stop() - } - - resizeTimer = time.AfterFunc(500*time.Millisecond, func() { - // Save after resize stops - saveWindowSize(width, height) - }) -}) -``` - -## Best Practices - -### ✅ Do - -- **Save state on close** - Restore window position/size -- **Cleanup on destroy** - Release resources -- **Debounce frequent events** - Resize, move -- **Handle focus changes** - Update UI appropriately -- **Coordinate windows** - Use events for communication -- **Test all events** - Ensure handlers work correctly - -### ❌ Don't - -- **Don't block event handlers** - Keep them fast -- **Don't forget cleanup** - Memory leaks -- **Don't ignore errors** - Log or handle them -- **Don't save on every event** - Debounce first -- **Don't create circular events** - Infinite loops -- **Don't forget platform differences** - Test thoroughly - -## Troubleshooting - -### OnClose Not Firing - -**Cause:** Using `window.Destroy()` instead of `window.Close()` - -**Solution:** - -```go -// ✅ Triggers OnClose -window.Close() - -// ❌ Doesn't trigger OnClose -window.Destroy() -``` - -### Events Not Firing - -**Cause:** Handler registered after event occurred - -**Solution:** - -```go -// Register handlers immediately after creation -window := app.Window.New() -window.OnClose(func() bool { return true }) -``` - -### Memory Leaks - -**Cause:** Not cleaning up in OnDestroy - -**Solution:** - -```go -window.OnDestroy(func() { - // Always cleanup - closeResources() - removeReferences() -}) -``` - -## Next Steps - -**Window Basics** - Learn the fundamentals of window management -[Learn More →](/features/windows/basics) - -**Multiple Windows** - Patterns for multi-window applications -[Learn More →](/features/windows/multiple) - -**Events System** - Deep dive into the event system -[Learn More →](/features/events/system) - -**Application Lifecycle** - Understand the application lifecycle -[Learn More →](/concepts/lifecycle) - ---- - -**Questions?** Ask in [Discord](https://discord.gg/JDdSxwjhGf) or check the [examples](https://github.com/wailsapp/wails/tree/v3-alpha/v3/examples). diff --git a/docs/src/content/docs/features/windows/frameless.mdx b/docs/src/content/docs/features/windows/frameless.mdx deleted file mode 100644 index c13cb9d4d..000000000 --- a/docs/src/content/docs/features/windows/frameless.mdx +++ /dev/null @@ -1,870 +0,0 @@ ---- -title: Frameless Windows -description: Create custom window chrome with frameless windows -sidebar: - order: 4 ---- - -import { Tabs, TabItem, Card, CardGrid } from "@astrojs/starlight/components"; - -## Frameless Windows - -Wails provides **frameless window support** with CSS-based drag regions and platform-native behaviour. Remove the platform-native title bar for complete control over window chrome, custom designs, and unique user experiences whilst maintaining essential functionality like dragging, resizing, and system controls. - -## Quick Start - -```go -window := app.Window.NewWithOptions(application.WebviewWindowOptions{ - Title: "Frameless App", - Width: 800, - Height: 600, - Frameless: true, -}) -``` - -**CSS for draggable title bar:** - -```css -.titlebar { - --wails-draggable: drag; - height: 40px; - background: #333; -} - -.titlebar button { - --wails-draggable: no-drag; -} -``` - -**HTML:** - -```html -
      - My Application - -
      -``` - -**That's it!** You have a custom title bar. - -## Creating Frameless Windows - -### Basic Frameless Window - -```go -window := app.Window.NewWithOptions(application.WebviewWindowOptions{ - Frameless: true, - Width: 800, - Height: 600, -}) -``` - -**What you get:** -- No title bar -- No window borders -- No system buttons -- Transparent background (optional) - -**What you need to implement:** -- Draggable area -- Close/minimise/maximise buttons -- Resize handles (if resizable) - -### With Transparent Background - -```go -window := app.Window.NewWithOptions(application.WebviewWindowOptions{ - Frameless: true, - BackgroundType: application.BackgroundTypeTransparent, -}) -``` - -**Use cases:** -- Rounded corners -- Custom shapes -- Overlay windows -- Splash screens - -## Drag Regions - -### CSS-Based Dragging - -Use the `--wails-draggable` CSS property: - -```css -/* Draggable area */ -.titlebar { - --wails-draggable: drag; -} - -/* Non-draggable elements within draggable area */ -.titlebar button { - --wails-draggable: no-drag; -} -``` - -**Values:** -- `drag` - Area is draggable -- `no-drag` - Area is not draggable (even if parent is) - -### Complete Title Bar Example - -```html -
      -
      My Application
      -
      - - - -
      -
      -``` - -```css -.titlebar { - --wails-draggable: drag; - display: flex; - justify-content: space-between; - align-items: center; - height: 40px; - background: #2c2c2c; - color: white; - padding: 0 16px; -} - -.title { - font-size: 14px; - user-select: none; -} - -.controls { - display: flex; - gap: 8px; -} - -.controls button { - --wails-draggable: no-drag; - width: 32px; - height: 32px; - border: none; - background: transparent; - color: white; - font-size: 16px; - cursor: pointer; - border-radius: 4px; -} - -.controls button:hover { - background: rgba(255, 255, 255, 0.1); -} - -.controls .close:hover { - background: #e81123; -} -``` - -**JavaScript for buttons:** - -```javascript -import { WindowMinimise, WindowMaximise, WindowClose } from '@wailsio/runtime' - -document.querySelector('.minimize').addEventListener('click', WindowMinimise) -document.querySelector('.maximize').addEventListener('click', WindowMaximise) -document.querySelector('.close').addEventListener('click', WindowClose) -``` - -## System Buttons - -### Implementing Close/Minimise/Maximise - -**Go side:** - -```go -type WindowControls struct { - window *application.WebviewWindow -} - -func (wc *WindowControls) Minimise() { - wc.window.Minimise() -} - -func (wc *WindowControls) Maximise() { - if wc.window.IsMaximised() { - wc.window.UnMaximise() - } else { - wc.window.Maximise() - } -} - -func (wc *WindowControls) Close() { - wc.window.Close() -} -``` - -**JavaScript side:** - -```javascript -import { Minimise, Maximise, Close } from './bindings/WindowControls' - -document.querySelector('.minimize').addEventListener('click', Minimise) -document.querySelector('.maximize').addEventListener('click', Maximise) -document.querySelector('.close').addEventListener('click', Close) -``` - -**Or use runtime methods:** - -```javascript -import { - WindowMinimise, - WindowMaximise, - WindowClose -} from '@wailsio/runtime' - -document.querySelector('.minimize').addEventListener('click', WindowMinimise) -document.querySelector('.maximize').addEventListener('click', WindowMaximise) -document.querySelector('.close').addEventListener('click', WindowClose) -``` - -### Toggle Maximise State - -Track maximise state for button icon: - -```javascript -import { WindowIsMaximised, WindowMaximise, WindowUnMaximise } from '@wailsio/runtime' - -async function toggleMaximise() { - const isMaximised = await WindowIsMaximised() - - if (isMaximised) { - await WindowUnMaximise() - } else { - await WindowMaximise() - } - - updateMaximiseButton() -} - -async function updateMaximiseButton() { - const isMaximised = await WindowIsMaximised() - const button = document.querySelector('.maximize') - button.textContent = isMaximised ? '❐' : '□' -} -``` - -## Resize Handles - -### CSS-Based Resize - -Wails provides automatic resize handles for frameless windows: - -```css -/* Enable resize on all edges */ -body { - --wails-resize: all; -} - -/* Or specific edges */ -.resize-top { - --wails-resize: top; -} - -.resize-bottom { - --wails-resize: bottom; -} - -.resize-left { - --wails-resize: left; -} - -.resize-right { - --wails-resize: right; -} - -/* Corners */ -.resize-top-left { - --wails-resize: top-left; -} - -.resize-top-right { - --wails-resize: top-right; -} - -.resize-bottom-left { - --wails-resize: bottom-left; -} - -.resize-bottom-right { - --wails-resize: bottom-right; -} -``` - -**Values:** -- `all` - Resize from all edges -- `top`, `bottom`, `left`, `right` - Specific edges -- `top-left`, `top-right`, `bottom-left`, `bottom-right` - Corners -- `none` - No resize - -### Resize Handle Example - -```html -
      -
      ...
      -
      ...
      -
      -
      -``` - -```css -.resize-handle { - position: absolute; - width: 16px; - height: 16px; -} - -.resize-bottom-right { - --wails-resize: bottom-right; - bottom: 0; - right: 0; - cursor: nwse-resize; -} -``` - -## Platform-Specific Behaviour - - - - **Windows frameless windows:** - - ```go - window := app.Window.NewWithOptions(application.WebviewWindowOptions{ - Frameless: true, - Windows: application.WindowsOptions{ - DisableFramelessWindowDecorations: false, - }, - }) - ``` - - **Features:** - - Automatic drop shadow - - Snap layouts support (Windows 11) - - Aero Snap support - - DPI scaling - - **Disable decorations:** - ```go - Windows: application.WindowsOptions{ - DisableFramelessWindowDecorations: true, - }, - ``` - - **Snap Assist:** - ```go - // Trigger Windows 11 Snap Assist - window.SnapAssist() - ``` - - **Custom title bar height:** - Windows automatically detects drag regions from CSS. - - - - **macOS frameless windows:** - - ```go - window := app.Window.NewWithOptions(application.WebviewWindowOptions{ - Frameless: true, - Mac: application.MacOptions{ - TitleBarAppearsTransparent: true, - InvisibleTitleBarHeight: 40, - }, - }) - ``` - - **Features:** - - Native fullscreen support - - Traffic light buttons (optional) - - Vibrancy effects - - Transparent title bar - - **Hide traffic lights:** - ```go - Mac: application.MacOptions{ - TitleBarStyle: application.MacTitleBarStyleHidden, - }, - ``` - - **Invisible title bar:** - Allows dragging whilst hiding the title bar: - ```go - Mac: application.MacOptions{ - InvisibleTitleBarHeight: 40, - }, - ``` - - - - **Linux frameless windows:** - - ```go - window := app.Window.NewWithOptions(application.WebviewWindowOptions{ - Frameless: true, - }) - ``` - - **Features:** - - Basic frameless support - - CSS drag regions - - Varies by desktop environment - - **Desktop environment notes:** - - **GNOME:** Good support - - **KDE Plasma:** Good support - - **XFCE:** Basic support - - **Tiling WMs:** Limited support - - **Compositor required:** - Transparency requires a compositor (most modern DEs have one). - - - -## Common Patterns - -### Pattern 1: Modern Title Bar - -```html -
      -
      - App Icon -
      -
      My Application
      -
      - - - -
      -
      -``` - -```css -.modern-titlebar { - --wails-draggable: drag; - display: flex; - align-items: center; - height: 40px; - background: linear-gradient(to bottom, #3a3a3a, #2c2c2c); - border-bottom: 1px solid #1a1a1a; - padding: 0 16px; -} - -.app-icon { - --wails-draggable: no-drag; - width: 24px; - height: 24px; - margin-right: 12px; -} - -.title { - flex: 1; - font-size: 13px; - color: #e0e0e0; - user-select: none; -} - -.controls { - display: flex; - gap: 1px; -} - -.controls button { - --wails-draggable: no-drag; - width: 46px; - height: 32px; - border: none; - background: transparent; - color: #e0e0e0; - font-size: 14px; - cursor: pointer; - transition: background 0.2s; -} - -.controls button:hover { - background: rgba(255, 255, 255, 0.1); -} - -.controls .close:hover { - background: #e81123; - color: white; -} -``` - -### Pattern 2: Splash Screen - -```go -splash := app.Window.NewWithOptions(application.WebviewWindowOptions{ - Title: "Loading...", - Width: 400, - Height: 300, - Frameless: true, - AlwaysOnTop: true, - BackgroundType: application.BackgroundTypeTransparent, -}) -``` - -```css -body { - background: transparent; - display: flex; - justify-content: center; - align-items: center; -} - -.splash { - background: white; - border-radius: 12px; - box-shadow: 0 8px 32px rgba(0, 0, 0, 0.3); - padding: 40px; - text-align: center; -} -``` - -### Pattern 3: Rounded Window - -```go -window := app.Window.NewWithOptions(application.WebviewWindowOptions{ - Frameless: true, - BackgroundType: application.BackgroundTypeTransparent, -}) -``` - -```css -body { - background: transparent; - margin: 8px; -} - -.window { - background: white; - border-radius: 16px; - box-shadow: 0 4px 24px rgba(0, 0, 0, 0.15); - overflow: hidden; - height: calc(100vh - 16px); -} - -.titlebar { - --wails-draggable: drag; - background: #f5f5f5; - border-bottom: 1px solid #e0e0e0; -} -``` - -### Pattern 4: Overlay Window - -```go -overlay := app.Window.NewWithOptions(application.WebviewWindowOptions{ - Frameless: true, - AlwaysOnTop: true, - BackgroundType: application.BackgroundTypeTransparent, -}) -``` - -```css -body { - background: transparent; -} - -.overlay { - background: rgba(0, 0, 0, 0.8); - backdrop-filter: blur(10px); - border-radius: 8px; - padding: 20px; -} -``` - -## Complete Example - -Here's a production-ready frameless window: - -**Go:** - -```go -package main - -import ( - _ "embed" - "github.com/wailsapp/wails/v3/pkg/application" -) - -//go:embed frontend/dist -var assets embed.FS - -func main() { - app := application.New(application.Options{ - Name: "Frameless App", - }) - - window := app.Window.NewWithOptions(application.WebviewWindowOptions{ - Title: "Frameless Application", - Width: 1000, - Height: 700, - MinWidth: 800, - MinHeight: 600, - Frameless: true, - - Assets: application.AssetOptions{ - Handler: application.AssetFileServerFS(assets), - }, - - Mac: application.MacOptions{ - TitleBarAppearsTransparent: true, - InvisibleTitleBarHeight: 40, - }, - - Windows: application.WindowsOptions{ - DisableFramelessWindowDecorations: false, - }, - }) - - window.Center() - window.Show() - - app.Run() -} -``` - -**HTML:** - -```html - - - - - - -
      -
      -
      Frameless Application
      -
      - - - -
      -
      -
      -

      Hello from Frameless Window!

      -
      -
      - - - -``` - -**CSS:** - -```css -* { - margin: 0; - padding: 0; - box-sizing: border-box; -} - -body { - font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; - background: #f5f5f5; -} - -.window { - height: 100vh; - display: flex; - flex-direction: column; -} - -.titlebar { - --wails-draggable: drag; - display: flex; - justify-content: space-between; - align-items: center; - height: 40px; - background: #ffffff; - border-bottom: 1px solid #e0e0e0; - padding: 0 16px; -} - -.title { - font-size: 13px; - font-weight: 500; - color: #333; - user-select: none; -} - -.controls { - display: flex; - gap: 8px; -} - -.controls button { - --wails-draggable: no-drag; - width: 32px; - height: 32px; - border: none; - background: transparent; - color: #666; - font-size: 16px; - cursor: pointer; - border-radius: 4px; - display: flex; - align-items: center; - justify-content: center; - transition: all 0.2s; -} - -.controls button:hover { - background: #f0f0f0; - color: #333; -} - -.controls .close:hover { - background: #e81123; - color: white; -} - -.content { - flex: 1; - padding: 40px; - overflow: auto; -} -``` - -**JavaScript:** - -```javascript -import { - WindowMinimise, - WindowMaximise, - WindowUnMaximise, - WindowIsMaximised, - WindowClose -} from '@wailsio/runtime' - -// Minimise button -document.querySelector('.minimize').addEventListener('click', () => { - WindowMinimise() -}) - -// Maximise/restore button -const maximiseBtn = document.querySelector('.maximize') -maximiseBtn.addEventListener('click', async () => { - const isMaximised = await WindowIsMaximised() - - if (isMaximised) { - await WindowUnMaximise() - } else { - await WindowMaximise() - } - - updateMaximiseButton() -}) - -// Close button -document.querySelector('.close').addEventListener('click', () => { - WindowClose() -}) - -// Update maximise button icon -async function updateMaximiseButton() { - const isMaximised = await WindowIsMaximised() - maximiseBtn.textContent = isMaximised ? '❐' : '□' - maximiseBtn.title = isMaximised ? 'Restore' : 'Maximise' -} - -// Initial state -updateMaximiseButton() -``` - -## Best Practices - -### ✅ Do - -- **Provide draggable area** - Users need to move the window -- **Implement system buttons** - Close, minimise, maximise -- **Set minimum size** - Prevent unusable layouts -- **Test on all platforms** - Behaviour varies -- **Use CSS for drag regions** - Flexible and maintainable -- **Provide visual feedback** - Hover states on buttons - -### ❌ Don't - -- **Don't forget resize handles** - If window is resizable -- **Don't make entire window draggable** - Prevents interaction -- **Don't forget no-drag on buttons** - They won't work -- **Don't use tiny drag areas** - Hard to grab -- **Don't forget platform differences** - Test thoroughly - -## Troubleshooting - -### Window Won't Drag - -**Cause:** Missing `--wails-draggable: drag` - -**Solution:** - -```css -.titlebar { - --wails-draggable: drag; -} -``` - -### Buttons Don't Work - -**Cause:** Buttons are in draggable area - -**Solution:** - -```css -.titlebar button { - --wails-draggable: no-drag; -} -``` - -### Can't Resize Window - -**Cause:** Missing resize handles - -**Solution:** - -```css -body { - --wails-resize: all; -} -``` - -## Next Steps - - - - Learn the fundamentals of window management. - - [Learn More →](/features/windows/basics) - - - - Complete reference for window options. - - [Learn More →](/features/windows/options) - - - - Handle window lifecycle events. - - [Learn More →](/features/windows/events) - - - - Patterns for multi-window applications. - - [Learn More →](/features/windows/multiple) - - - ---- - -**Questions?** Ask in [Discord](https://discord.gg/JDdSxwjhGf) or check the [frameless example](https://github.com/wailsapp/wails/tree/v3-alpha/v3/examples/frameless). diff --git a/docs/src/content/docs/features/windows/multiple.mdx b/docs/src/content/docs/features/windows/multiple.mdx deleted file mode 100644 index 41d5a18fe..000000000 --- a/docs/src/content/docs/features/windows/multiple.mdx +++ /dev/null @@ -1,814 +0,0 @@ ---- -title: Multiple Windows -description: Patterns and best practices for multi-window applications -sidebar: - order: 3 ---- - -import { Tabs, TabItem } from "@astrojs/starlight/components"; - -## Multi-Window Applications - -Wails v3 provides **native multi-window support** for creating settings windows, document windows, tool palettes, and inspector windows. Track windows, enable communication between them, and manage their lifecycle with simple, consistent APIs. - -### Main + Settings Window - -```go -package main - -import "github.com/wailsapp/wails/v3/pkg/application" - -type App struct { - app *application.Application - mainWindow *application.WebviewWindow - settingsWindow *application.WebviewWindow -} - -func main() { - app := &App{} - - app.app = application.New(application.Options{ - Name: "Multi-Window App", - }) - - // Create main window - app.mainWindow = app.app.Window.NewWithOptions(application.WebviewWindowOptions{ - Name: "main", - Title: "Main Application", - Width: 1200, - Height: 800, - }) - - // Create settings window (hidden initially) - app.settingsWindow = app.app.Window.NewWithOptions(application.WebviewWindowOptions{ - Name: "settings", - Title: "Settings", - Width: 600, - Height: 400, - Hidden: true, - }) - - app.app.Run() -} - -// Show settings from main window -func (a *App) ShowSettings() { - if a.settingsWindow != nil { - a.settingsWindow.Show() - a.settingsWindow.SetFocus() - } -} -``` - -**Key points:** -- Main window always visible -- Settings window created but hidden -- Show settings on demand -- Reuse same window (don't create multiple) - -## Window Tracking - -### Get All Windows - -```go -windows := app.Window.GetAll() -fmt.Printf("Total windows: %d\n", len(windows)) - -for _, window := range windows { - fmt.Printf("- %s (ID: %d)\n", window.Name(), window.ID()) -} -``` - -### Find Specific Window - -```go -// By name -settings := app.GetWindowByName("settings") -if settings != nil { - settings.Show() -} - -// By ID -window := app.GetWindowByID(123) - -// Current (focused) window -current := app.Window.Current() -``` - -### Window Registry Pattern - -Track windows in your application: - -```go -type WindowManager struct { - windows map[string]*application.WebviewWindow - mu sync.RWMutex -} - -func (wm *WindowManager) Register(name string, window *application.WebviewWindow) { - wm.mu.Lock() - defer wm.mu.Unlock() - wm.windows[name] = window -} - -func (wm *WindowManager) Get(name string) *application.WebviewWindow { - wm.mu.RLock() - defer wm.mu.RUnlock() - return wm.windows[name] -} - -func (wm *WindowManager) Remove(name string) { - wm.mu.Lock() - defer wm.mu.Unlock() - delete(wm.windows, name) -} -``` - -## Window Communication - -### Using Events - -Windows communicate via the event system: - -```go -// In main window - emit event -app.Event.Emit("settings-changed", map[string]interface{}{ - "theme": "dark", - "fontSize": 14, -}) - -// In settings window - listen for event -app.Event.On("settings-changed", func(event *application.WailsEvent) { - data := event.Data.(map[string]interface{}) - theme := data["theme"].(string) - fontSize := data["fontSize"].(int) - - // Update UI - updateSettings(theme, fontSize) -}) -``` - -### Shared State Pattern - -Use a shared state manager: - -```go -type AppState struct { - theme string - fontSize int - mu sync.RWMutex -} - -var state = &AppState{ - theme: "light", - fontSize: 12, -} - -func (s *AppState) SetTheme(theme string) { - s.mu.Lock() - s.theme = theme - s.mu.Unlock() - - // Notify all windows - app.Event.Emit("theme-changed", theme) -} - -func (s *AppState) GetTheme() string { - s.mu.RLock() - defer s.mu.RUnlock() - return s.theme -} -``` - -### Window-to-Window Messages - -Send messages between specific windows: - -```go -// Get target window -targetWindow := app.GetWindowByName("preview") - -// Emit event to specific window -targetWindow.EmitEvent("update-preview", previewData) -``` - -## Common Patterns - -### Pattern 1: Singleton Windows - -Ensure only one instance of a window exists: - -```go -var settingsWindow *application.WebviewWindow - -func ShowSettings(app *application.Application) { - // Create if doesn't exist - if settingsWindow == nil { - settingsWindow = app.Window.NewWithOptions(application.WebviewWindowOptions{ - Name: "settings", - Title: "Settings", - Width: 600, - Height: 400, - }) - - // Cleanup on close - settingsWindow.OnDestroy(func() { - settingsWindow = nil - }) - } - - // Show and focus - settingsWindow.Show() - settingsWindow.SetFocus() -} -``` - -### Pattern 2: Document Windows - -Multiple instances of the same window type: - -```go -type DocumentWindow struct { - window *application.WebviewWindow - filePath string - modified bool -} - -var documents = make(map[string]*DocumentWindow) - -func OpenDocument(app *application.Application, filePath string) { - // Check if already open - if doc, exists := documents[filePath]; exists { - doc.window.Show() - doc.window.SetFocus() - return - } - - // Create new document window - window := app.Window.NewWithOptions(application.WebviewWindowOptions{ - Title: filepath.Base(filePath), - Width: 800, - Height: 600, - }) - - doc := &DocumentWindow{ - window: window, - filePath: filePath, - modified: false, - } - - documents[filePath] = doc - - // Cleanup on close - window.OnDestroy(func() { - delete(documents, filePath) - }) - - // Load document - loadDocument(window, filePath) -} -``` - -### Pattern 3: Tool Palettes - -Floating windows that stay on top: - -```go -func CreateToolPalette(app *application.Application) *application.WebviewWindow { - palette := app.Window.NewWithOptions(application.WebviewWindowOptions{ - Name: "tools", - Title: "Tools", - Width: 200, - Height: 400, - AlwaysOnTop: true, - Resizable: false, - }) - - return palette -} -``` - -### Pattern 4: Modal dialogs - -Child windows that block parent: - -```go -func ShowModaldialog(parent *application.WebviewWindow, title string) { - dialog := app.Window.NewWithOptions(application.WebviewWindowOptions{ - Title: title, - Width: 400, - Height: 200, - Parent: parent, - AlwaysOnTop: true, - Resizable: false, - }) - - // Disable parent (platform-specific) - parent.SetEnabled(false) - - // Re-enable parent on close - dialog.OnDestroy(func() { - parent.SetEnabled(true) - parent.SetFocus() - }) -} -``` - -### Pattern 5: Inspector/Preview Windows - -Linked windows that update together: - -```go -type EditorApp struct { - editor *application.WebviewWindow - preview *application.WebviewWindow -} - -func (e *EditorApp) UpdatePreview(content string) { - if e.preview != nil && e.preview.IsVisible() { - e.preview.EmitEvent("content-changed", content) - } -} - -func (e *EditorApp) TogglePreview() { - if e.preview == nil { - e.preview = app.Window.NewWithOptions(application.WebviewWindowOptions{ - Name: "preview", - Title: "Preview", - Width: 600, - Height: 800, - }) - - e.preview.OnDestroy(func() { - e.preview = nil - }) - } - - if e.preview.IsVisible() { - e.preview.Hide() - } else { - e.preview.Show() - } -} -``` - -## Parent-Child Relationships - -### Creating Child Windows - -```go -childWindow := app.Window.NewWithOptions(application.WebviewWindowOptions{ - Title: "Child Window", - Parent: parentWindow, -}) -``` - -**Behaviour:** -- Child closes when parent closes -- Child stays above parent (on some platforms) -- Child minimises with parent (on some platforms) - -**Platform support:** - -| Feature | macOS | Windows | Linux | -|---------|-------|---------|-------| -| Auto-close | ✅ | ✅ | ⚠️ Varies | -| Stay above | ✅ | ⚠️ Partial | ⚠️ Varies | -| Minimise together | ✅ | ❌ | ⚠️ Varies | - -### Modal Behaviour - -Create modal-like behaviour: - -```go -func ShowModal(parent *application.WebviewWindow) { - modal := app.Window.NewWithOptions(application.WebviewWindowOptions{ - Title: "Modal dialog", - Width: 400, - Height: 200, - Parent: parent, - AlwaysOnTop: true, - }) - - // Disable parent interaction - parent.SetEnabled(false) - - // Re-enable on close - modal.OnClose(func() bool { - parent.SetEnabled(true) - parent.SetFocus() - return true - }) -} -``` - -**Note:** True modal behaviour (blocking) varies by platform. - -## Window Lifecycle Management - -### Creation Callbacks - -Be notified when windows are created: - -```go -app.OnWindowCreation(func(window *application.WebviewWindow) { - fmt.Printf("Window created: %s\n", window.Name()) - - // Configure all new windows - window.SetMinSize(400, 300) -}) -``` - -### Destruction Callbacks - -Cleanup when windows are destroyed: - -```go -window.OnDestroy(func() { - fmt.Printf("Window %s destroyed\n", window.Name()) - - // Cleanup resources - cleanup(window.ID()) - - // Remove from tracking - removeFromRegistry(window.Name()) -}) -``` - -### Application Quit Behaviour - -Control when application quits: - -```go -app := application.New(application.Options{ - Mac: application.MacOptions{ - // Don't quit when last window closes - ApplicationShouldTerminateAfterLastWindowClosed: false, - }, -}) -``` - -**Use cases:** -- System tray applications -- Background services -- Menu bar applications (macOS) - -## Memory Management - -### Preventing Leaks - -Always clean up window references: - -```go -var windows = make(map[string]*application.WebviewWindow) - -func CreateWindow(name string) { - window := app.Window.New() - windows[name] = window - - // IMPORTANT: Clean up on destroy - window.OnDestroy(func() { - delete(windows, name) - }) -} -``` - -### Closing vs Destroying - -```go -// Close - triggers OnClose, can be cancelled -window.Close() - -// Destroy - immediate, cannot be cancelled -window.Destroy() -``` - -**Best practice:** Use `Close()` for user-initiated closes, `Destroy()` for cleanup. - -### Resource Cleanup - -```go -type ManagedWindow struct { - window *application.WebviewWindow - resources []io.Closer -} - -func (mw *ManagedWindow) Destroy() { - // Close all resources - for _, resource := range mw.resources { - resource.Close() - } - - // Destroy window - mw.window.Destroy() -} -``` - -## Advanced Patterns - -### Window Pool - -Reuse windows instead of creating new ones: - -```go -type WindowPool struct { - available []*application.WebviewWindow - inUse map[uint]*application.WebviewWindow - mu sync.Mutex -} - -func (wp *WindowPool) Acquire() *application.WebviewWindow { - wp.mu.Lock() - defer wp.mu.Unlock() - - // Reuse available window - if len(wp.available) > 0 { - window := wp.available[0] - wp.available = wp.available[1:] - wp.inUse[window.ID()] = window - return window - } - - // Create new window - window := app.Window.New() - wp.inUse[window.ID()] = window - return window -} - -func (wp *WindowPool) Release(window *application.WebviewWindow) { - wp.mu.Lock() - defer wp.mu.Unlock() - - delete(wp.inUse, window.ID()) - window.Hide() - wp.available = append(wp.available, window) -} -``` - -### Window Groups - -Manage related windows together: - -```go -type WindowGroup struct { - name string - windows []*application.WebviewWindow -} - -func (wg *WindowGroup) Add(window *application.WebviewWindow) { - wg.windows = append(wg.windows, window) -} - -func (wg *WindowGroup) ShowAll() { - for _, window := range wg.windows { - window.Show() - } -} - -func (wg *WindowGroup) HideAll() { - for _, window := range wg.windows { - window.Hide() - } -} - -func (wg *WindowGroup) CloseAll() { - for _, window := range wg.windows { - window.Close() - } -} -``` - -### Workspace Management - -Save and restore window layouts: - -```go -type WindowLayout struct { - Windows []WindowState `json:"windows"` -} - -type WindowState struct { - Name string `json:"name"` - X int `json:"x"` - Y int `json:"y"` - Width int `json:"width"` - Height int `json:"height"` -} - -func SaveLayout() *WindowLayout { - layout := &WindowLayout{} - - for _, window := range app.Window.GetAll() { - x, y := window.Position() - width, height := window.Size() - - layout.Windows = append(layout.Windows, WindowState{ - Name: window.Name(), - X: x, - Y: y, - Width: width, - Height: height, - }) - } - - return layout -} - -func RestoreLayout(layout *WindowLayout) { - for _, state := range layout.Windows { - window := app.GetWindowByName(state.Name) - if window != nil { - window.SetPosition(state.X, state.Y) - window.SetSize(state.Width, state.Height) - } - } -} -``` - -## Complete Example - -Here's a production-ready multi-window application: - -```go -package main - -import ( - "encoding/json" - "os" - "sync" - "github.com/wailsapp/wails/v3/pkg/application" -) - -type MultiWindowApp struct { - app *application.Application - windows map[string]*application.WebviewWindow - mu sync.RWMutex -} - -func main() { - mwa := &MultiWindowApp{ - windows: make(map[string]*application.WebviewWindow), - } - - mwa.app = application.New(application.Options{ - Name: "Multi-Window Application", - Mac: application.MacOptions{ - ApplicationShouldTerminateAfterLastWindowClosed: false, - }, - }) - - // Create main window - mwa.CreateMainWindow() - - // Load saved layout - mwa.LoadLayout() - - mwa.app.Run() -} - -func (mwa *MultiWindowApp) CreateMainWindow() { - window := mwa.app.Window.NewWithOptions(application.WebviewWindowOptions{ - Name: "main", - Title: "Main Application", - Width: 1200, - Height: 800, - }) - - mwa.RegisterWindow("main", window) -} - -func (mwa *MultiWindowApp) ShowSettings() { - if window := mwa.GetWindow("settings"); window != nil { - window.Show() - window.SetFocus() - return - } - - window := mwa.app.Window.NewWithOptions(application.WebviewWindowOptions{ - Name: "settings", - Title: "Settings", - Width: 600, - Height: 400, - }) - - mwa.RegisterWindow("settings", window) -} - -func (mwa *MultiWindowApp) OpenDocument(path string) { - name := "doc-" + path - - if window := mwa.GetWindow(name); window != nil { - window.Show() - window.SetFocus() - return - } - - window := mwa.app.Window.NewWithOptions(application.WebviewWindowOptions{ - Name: name, - Title: path, - Width: 800, - Height: 600, - }) - - mwa.RegisterWindow(name, window) -} - -func (mwa *MultiWindowApp) RegisterWindow(name string, window *application.WebviewWindow) { - mwa.mu.Lock() - mwa.windows[name] = window - mwa.mu.Unlock() - - window.OnDestroy(func() { - mwa.UnregisterWindow(name) - }) -} - -func (mwa *MultiWindowApp) UnregisterWindow(name string) { - mwa.mu.Lock() - delete(mwa.windows, name) - mwa.mu.Unlock() -} - -func (mwa *MultiWindowApp) GetWindow(name string) *application.WebviewWindow { - mwa.mu.RLock() - defer mwa.mu.RUnlock() - return mwa.windows[name] -} - -func (mwa *MultiWindowApp) SaveLayout() { - layout := make(map[string]WindowState) - - mwa.mu.RLock() - for name, window := range mwa.windows { - x, y := window.Position() - width, height := window.Size() - - layout[name] = WindowState{ - X: x, - Y: y, - Width: width, - Height: height, - } - } - mwa.mu.RUnlock() - - data, _ := json.Marshal(layout) - os.WriteFile("layout.json", data, 0644) -} - -func (mwa *MultiWindowApp) LoadLayout() { - data, err := os.ReadFile("layout.json") - if err != nil { - return - } - - var layout map[string]WindowState - if err := json.Unmarshal(data, &layout); err != nil { - return - } - - for name, state := range layout { - if window := mwa.GetWindow(name); window != nil { - window.SetPosition(state.X, state.Y) - window.SetSize(state.Width, state.Height) - } - } -} - -type WindowState struct { - X int `json:"x"` - Y int `json:"y"` - Width int `json:"width"` - Height int `json:"height"` -} -``` - -## Best Practices - -### ✅ Do - -- **Track windows** - Keep references for easy access -- **Clean up on destroy** - Prevent memory leaks -- **Use events for communication** - Decoupled architecture -- **Reuse windows** - Don't create duplicates -- **Save/restore layouts** - Better UX -- **Handle window close** - Confirm before closing with unsaved data - -### ❌ Don't - -- **Don't create unlimited windows** - Memory and performance issues -- **Don't forget to clean up** - Memory leaks -- **Don't use global variables carelessly** - Thread-safety issues -- **Don't block window creation** - Create asynchronously if needed -- **Don't ignore platform differences** - Test on all platforms - -## Next Steps - -- [Window Basics](/features/windows/basics) - Learn the fundamentals of window management -- [Window Events](/features/windows/events) - Handle window lifecycle events -- [Events System](/features/events/system) - Deep dive into the event system -- [Frameless Windows](/features/windows/frameless) - Create custom window chrome - ---- - -**Questions?** Ask in [Discord](https://discord.gg/JDdSxwjhGf) or check the [multi-window example](https://github.com/wailsapp/wails/tree/v3-alpha/v3/examples/multi-window). diff --git a/docs/src/content/docs/features/windows/options.mdx b/docs/src/content/docs/features/windows/options.mdx deleted file mode 100644 index 730e62045..000000000 --- a/docs/src/content/docs/features/windows/options.mdx +++ /dev/null @@ -1,1094 +0,0 @@ ---- -title: Window Options -description: Complete reference for WebviewWindowOptions -sidebar: - order: 2 ---- - -import { Tabs, TabItem } from "@astrojs/starlight/components"; - -## Window Configuration Options - -Wails provides comprehensive window configuration with dozens of options for size, position, appearance, and behaviour. This reference covers all available options across Windows, macOS, and Linux as the **complete reference** for `WebviewWindowOptions`. Every option, every platform, with examples and constraints. - -## WebviewWindowOptions Structure - -```go -type WebviewWindowOptions struct { - // Identity - Name string - Title string - - // Size and Position - Width int - Height int - X int - Y int - MinWidth int - MinHeight int - MaxWidth int - MaxHeight int - - // Initial State - Hidden bool - Frameless bool - Resizable bool - AlwaysOnTop bool - Fullscreen bool - Minimised bool - Maximised bool - WindowState WindowState - - // Appearance - BackgroundColour RGBA - BackgroundType BackgroundType - - // Content - URL string - HTML string - - // Assets - Assets application.AssetOptions - - // Security - ContentProtectionEnabled bool - - // Menu - UseApplicationMenu bool - - // Lifecycle - OnClose func() bool - OnDestroy func() - - // Platform-Specific - Mac MacOptions - Windows WindowsOptions - Linux LinuxOptions -} -``` - -## Core Options - -### Name - -**Type:** `string` -**Default:** Auto-generated UUID -**Platform:** All - -```go -Name: "main-window" -``` - -**Purpose:** Unique identifier for finding windows later. - -**Best practices:** -- Use descriptive names: `"main"`, `"settings"`, `"about"` -- Use kebab-case: `"file-browser"`, `"color-picker"` -- Keep it short and memorable - -**Example:** - -```go -window := app.Window.NewWithOptions(application.WebviewWindowOptions{ - Name: "settings-window", -}) - -// Later... -settings := app.GetWindowByName("settings-window") -``` - -### Title - -**Type:** `string` -**Default:** Application name -**Platform:** All - -```go -Title: "My Application" -``` - -**Purpose:** Text shown in title bar and taskbar. - -**Dynamic updates:** - -```go -window.SetTitle("My Application - Document.txt") -``` - -### Width / Height - -**Type:** `int` (pixels) -**Default:** 800 x 600 -**Platform:** All -**Constraints:** Must be positive - -```go -Width: 1200, -Height: 800, -``` - -**Purpose:** Initial window size in logical pixels. - -**Notes:** -- Wails handles DPI scaling automatically -- Use logical pixels, not physical pixels -- Consider minimum screen resolution (1024x768) - -**Example sizes:** - -| Use Case | Width | Height | -|----------|-------|--------| -| Small utility | 400 | 300 | -| Standard app | 1024 | 768 | -| Large app | 1440 | 900 | -| Full HD | 1920 | 1080 | - -### X / Y - -**Type:** `int` (pixels) -**Default:** Centred on screen -**Platform:** All - -```go -X: 100, // 100px from left edge -Y: 100, // 100px from top edge -``` - -**Purpose:** Initial window position. - -**Coordinate system:** -- (0, 0) is top-left of primary screen -- Positive X goes right -- Positive Y goes down - -**Example:** - -```go -settings := app.Window.NewWithOptions(application.WebviewWindowOptions{ - Name: "coordinate-window", - InitialPosition: application.WindowXY, // use coordinate system - X: 100, - Y: 100, -}) - -**Best practice:** Use `Center()` to center the window: - -```go -window := app.Window.New() -window.Center() -``` - -### MinWidth / MinHeight - -**Type:** `int` (pixels) -**Default:** 0 (no minimum) -**Platform:** All - -```go -MinWidth: 400, -MinHeight: 300, -``` - -**Purpose:** Prevent window from being too small. - -**Use cases:** -- Prevent broken layouts -- Ensure usability -- Maintain aspect ratio - -**Example:** - -```go -// Prevent window smaller than 400x300 -MinWidth: 400, -MinHeight: 300, -``` - -### MaxWidth / MaxHeight - -**Type:** `int` (pixels) -**Default:** 0 (no maximum) -**Platform:** All - -```go -MaxWidth: 1920, -MaxHeight: 1080, -``` - -**Purpose:** Prevent window from being too large. - -**Use cases:** -- Fixed-size applications -- Prevent excessive resource usage -- Maintain design constraints - -## State Options - -### Hidden - -**Type:** `bool` -**Default:** `false` -**Platform:** All - -```go -Hidden: true, -``` - -**Purpose:** Create window without showing it. - -**Use cases:** -- Background windows -- Windows shown on demand -- Splash screens (create, load, then show) -- Prevent white flash while loading content - -**Platform improvements:** -- **Windows:** Fixed white window flash - window stays invisible until `Show()` is called -- **macOS:** Full support -- **Linux:** Full support - -**Recommended pattern for smooth loading:** - -```go -// Create hidden window -window := app.Window.NewWithOptions(application.WebviewWindowOptions{ - Name: "main-window", - Hidden: true, - BackgroundColour: application.RGBA{R: 30, G: 30, B: 30, A: 255}, // Match your theme -}) - -// Load content while hidden -// ... content loads ... - -// Show when ready (no flash!) -window.Show() -``` - -**Example:** - -```go -settings := app.Window.NewWithOptions(application.WebviewWindowOptions{ - Name: "settings", - Hidden: true, -}) - -// Show when needed -settings.Show() -``` - -### Frameless - -**Type:** `bool` -**Default:** `false` -**Platform:** All - -```go -Frameless: true, -``` - -**Purpose:** Remove title bar and window borders. - -**Use cases:** -- Custom window chrome -- Splash screens -- Kiosk applications -- Custom-designed windows - -**Important:** You'll need to implement: -- Window dragging -- Close/minimise/maximise buttons -- Resize handles (if resizable) - -**See [Frameless Windows](/features/windows/frameless) for details.** - -### Resizable - -**Type:** `bool` -**Default:** `true` -**Platform:** All - -```go -Resizable: false, -``` - -**Purpose:** Allow/prevent window resizing. - -**Use cases:** -- Fixed-size applications -- Splash screens -- dialogs - -**Note:** Users can still maximise/fullscreen unless you prevent those too. - -### AlwaysOnTop - -**Type:** `bool` -**Default:** `false` -**Platform:** All - -```go -AlwaysOnTop: true, -``` - -**Purpose:** Keep window above all other windows. - -**Use cases:** -- Floating toolbars -- Notifications -- Picture-in-picture -- Timers - -**Platform notes:** -- **macOS:** Full support -- **Windows:** Full support -- **Linux:** Depends on window manager - -### Fullscreen - -**Type:** `bool` -**Default:** `false` -**Platform:** All - -```go -Fullscreen: true, -``` - -**Purpose:** Start in fullscreen mode. - -**Platform behaviour:** -- **macOS:** Creates new Space (virtual desktop) -- **Windows:** Covers taskbar -- **Linux:** Varies by desktop environment - -**Toggle at runtime:** - -```go -window.Fullscreen() -window.UnFullscreen() -``` - -### Minimised / Maximised - -**Type:** `bool` -**Default:** `false` -**Platform:** All - -```go -Minimised: true, // Start minimised -Maximised: true, // Start maximised -``` - -**Purpose:** Set initial window state. - -**Note:** Don't set both to `true` - behaviour is undefined. - -### WindowState - -**Type:** `WindowState` enum -**Default:** `WindowStateNormal` -**Platform:** All - -```go -WindowState: application.WindowStateMaximised, -``` - -**Values:** -- `WindowStateNormal` - Normal window -- `WindowStateMinimised` - Minimised -- `WindowStateMaximised` - Maximised -- `WindowStateFullscreen` - Fullscreen -- `WindowStateHidden` - Hidden - -**Preferred over individual flags:** - -```go -// ✅ Preferred -WindowState: application.WindowStateMaximised, - -// ❌ Avoid -Maximised: true, -``` - -## Appearance Options - -### BackgroundColour - -**Type:** `RGBA` struct -**Default:** White (255, 255, 255, 255) -**Platform:** All - -```go -BackgroundColour: application.RGBA{R: 0, G: 0, H: 0, A: 255}, -``` - -**Purpose:** Window background colour before content loads. - -**Use cases:** -- Match your app's theme -- Prevent white flash on dark themes -- Smooth loading experience - -**Example:** - -```go -// Dark theme -BackgroundColour: application.RGBA{R: 30, G: 30, B: 30, A: 255}, - -// Light theme -BackgroundColour: application.RGBA{R: 255, G: 255, B: 255, A: 255}, -``` - -**Helper method:** - -```go -window.SetBackgroundColour(30, 30, 30, 255) -``` - -### BackgroundType - -**Type:** `BackgroundType` enum -**Default:** `BackgroundTypeSolid` -**Platform:** macOS, Windows (partial) - -```go -BackgroundType: application.BackgroundTypeTranslucent, -``` - -**Values:** -- `BackgroundTypeSolid` - Solid colour -- `BackgroundTypeTransparent` - Fully transparent -- `BackgroundTypeTranslucent` - Semi-transparent blur - -**Platform support:** -- **macOS:** All types supported -- **Windows:** Transparent and Translucent (Windows 11+) -- **Linux:** Solid only - -**Example (macOS):** - -```go -BackgroundType: application.BackgroundTypeTranslucent, -Mac: application.MacOptions{ - Backdrop: application.MacBackdropTranslucent, -}, -``` - -## Content Options - -### URL - -**Type:** `string` -**Default:** Empty (loads from Assets) -**Platform:** All - -```go -URL: "https://example.com", -``` - -**Purpose:** Load external URL instead of embedded assets. - -**Use cases:** -- Development (load from dev server) -- Web-based applications -- Hybrid applications - -**Example:** - -```go -// Development -URL: "http://localhost:5173", - -// Production -Assets: application.AssetOptions{ - Handler: application.AssetFileServerFS(assets), -}, -``` - -### HTML - -**Type:** `string` -**Default:** Empty -**Platform:** All - -```go -HTML: "

      Hello World

      ", -``` - -**Purpose:** Load HTML string directly. - -**Use cases:** -- Simple windows -- Generated content -- Testing - -**Example:** - -```go -HTML: ` - - -Simple Window -

      Hello from Wails!

      - -`, -``` - -### Assets - -**Type:** `AssetOptions` -**Default:** Inherited from application -**Platform:** All - -```go -Assets: application.AssetOptions{ - Handler: application.AssetFileServerFS(assets), -}, -``` - -**Purpose:** Serve embedded frontend assets. - -**See [Build System](/concepts/build-system) for details.** - -### UseApplicationMenu - -**Type:** `bool` -**Default:** `false` -**Platform:** Windows, Linux (no effect on macOS) - -```go -UseApplicationMenu: true, -``` - -**Purpose:** Use the application menu (set via `app.Menu.Set()`) for this window. - -On **macOS**, this option has no effect because macOS always uses a global application menu at the top of the screen. - -On **Windows** and **Linux**, windows don't display a menu by default. Setting `UseApplicationMenu: true` tells the window to use the application-level menu, providing a simple cross-platform solution. - -**Example:** - -```go -// Set the application menu once -menu := app.NewMenu() -menu.AddRole(application.FileMenu) -menu.AddRole(application.EditMenu) -app.Menu.Set(menu) - -// All windows with UseApplicationMenu will display this menu -app.Window.NewWithOptions(application.WebviewWindowOptions{ - Title: "Main Window", - UseApplicationMenu: true, -}) - -app.Window.NewWithOptions(application.WebviewWindowOptions{ - Title: "Second Window", - UseApplicationMenu: true, // Also gets the app menu -}) -``` - -**Notes:** -- If both `UseApplicationMenu` and a window-specific menu are set, the window-specific menu takes priority -- This simplifies cross-platform code by eliminating the need for runtime OS checks -- See [Application Menus](/features/menus/application) for complete menu documentation - -## Input Options - -### EnableFileDrop - -**Type:** `bool` -**Default:** `false` -**Platform:** All - -```go -EnableFileDrop: true, -``` - -**Purpose:** Enable drag-and-drop of files from the operating system into the window. - -When enabled: -- Files dragged from file managers can be dropped into your application -- The `WindowFilesDropped` event fires with the dropped file paths -- Elements with `data-file-drop-target` attribute provide detailed drop information - -**Use cases:** -- File upload interfaces -- Document editors -- Media importers -- Any app that accepts files - -**Example:** - -```go -window := app.Window.NewWithOptions(application.WebviewWindowOptions{ - Title: "File Uploader", - EnableFileDrop: true, -}) - -// Handle dropped files -window.OnWindowEvent(events.Common.WindowFilesDropped, func(event *application.WindowEvent) { - files := event.Context().DroppedFiles() - details := event.Context().DropTargetDetails() - - for _, file := range files { - fmt.Println("Dropped:", file) - } -}) -``` - -**HTML drop zones:** - -```html - -
      - Drop files here -
      -``` - -**See [File Drop](/features/drag-and-drop/files) for complete documentation.** - -## Security Options - -### ContentProtectionEnabled - -**Type:** `bool` -**Default:** `false` -**Platform:** Windows (10+), macOS - -```go -ContentProtectionEnabled: true, -``` - -**Purpose:** Prevent screen capture of window contents. - -**Platform support:** -- **Windows:** Windows 10 build 19041+ (full), older versions (partial) -- **macOS:** Full support -- **Linux:** Not supported - -**Use cases:** -- Banking applications -- Password managers -- Medical records -- Confidential documents - -**Important notes:** -1. Doesn't prevent physical photography -2. Some tools may bypass protection -3. Part of comprehensive security, not sole protection -4. DevTools windows not protected automatically - -**Example:** - -```go -window := app.Window.NewWithOptions(application.WebviewWindowOptions{ - Title: "Secure Window", - ContentProtectionEnabled: true, -}) - -// Toggle at runtime -window.SetContentProtection(true) -``` - -## Lifecycle Options - -### OnClose - -**Type:** `func() bool` -**Default:** `nil` (always allow close) -**Platform:** All - -```go -OnClose: func() bool { - // Return false to cancel close - // Return true to allow close - return true -}, -``` - -**Purpose:** Handle window close events, optionally prevent closing. - -**Use cases:** -- Confirm before closing with unsaved changes -- Save state before closing -- Prevent accidental closure - -**Example:** - -```go -OnClose: func() bool { - if hasUnsavedChanges() { - result := showConfirmdialog("Unsaved changes. Close anyway?") - return result == "yes" - } - return true -}, -``` - -**Important:** Only triggered by user actions (clicking X), not `window.Destroy()`. - -### OnDestroy - -**Type:** `func()` -**Default:** `nil` -**Platform:** All - -```go -OnDestroy: func() { - // Cleanup code - fmt.Println("Window destroyed") -}, -``` - -**Purpose:** Cleanup when window is destroyed. - -**Use cases:** -- Release resources -- Close connections -- Update application state - -**Example:** - -```go -OnDestroy: func() { - // Close database connection - if db != nil { - db.Close() - } - - // Remove from window list - removeWindow(window.ID()) -}, -``` - -## Platform-Specific Options - -### Mac Options - -```go -Mac: application.MacWindow{ - TitleBar: application.MacTitleBar{ - AppearsTransparent: true, - Hide: false, - HideTitle: true, - FullSizeContent: true, - }, - Backdrop: application.MacBackdropTranslucent, - InvisibleTitleBarHeight: 50, - WindowLevel: application.MacWindowLevelNormal, - CollectionBehavior: application.MacWindowCollectionBehaviorDefault, -}, -``` - -**TitleBar** (`MacTitleBar`) -- `AppearsTransparent` - Makes title bar transparent, content extends into title bar area -- `Hide` - Hides the title bar completely -- `HideTitle` - Hides only the title text -- `FullSizeContent` - Extends content to full window size - -**Backdrop** (`MacBackdrop`) -- `MacBackdropNormal` - Standard opaque background -- `MacBackdropTranslucent` - Blurred translucent background -- `MacBackdropTransparent` - Fully transparent background - -**InvisibleTitleBarHeight** (`int`) -- Height of invisible title bar area (for dragging) -- Useful when title bar is hidden - -**WindowLevel** (`MacWindowLevel`) -- `MacWindowLevelNormal` - Standard window level (default) -- `MacWindowLevelFloating` - Floats above normal windows -- `MacWindowLevelTornOffMenu` - Torn-off menu level -- `MacWindowLevelModalPanel` - Modal panel level -- `MacWindowLevelMainMenu` - Main menu level -- `MacWindowLevelStatus` - Status window level -- `MacWindowLevelPopUpMenu` - Pop-up menu level -- `MacWindowLevelScreenSaver` - Screen saver level - -**CollectionBehavior** (`MacWindowCollectionBehavior`) - -Controls how the window behaves across macOS Spaces and fullscreen. These are bitmask values that can be combined using bitwise OR (`|`). - -**Space behavior:** -- `MacWindowCollectionBehaviorDefault` - Uses FullScreenPrimary (default, backwards compatible) -- `MacWindowCollectionBehaviorCanJoinAllSpaces` - Window appears on all Spaces -- `MacWindowCollectionBehaviorMoveToActiveSpace` - Moves to active Space when shown -- `MacWindowCollectionBehaviorManaged` - Default managed window behavior -- `MacWindowCollectionBehaviorTransient` - Temporary/transient window -- `MacWindowCollectionBehaviorStationary` - Stays stationary during Space switches - -**Window cycling:** -- `MacWindowCollectionBehaviorParticipatesInCycle` - Included in Cmd+` cycling -- `MacWindowCollectionBehaviorIgnoresCycle` - Excluded from Cmd+` cycling - -**Fullscreen behavior:** -- `MacWindowCollectionBehaviorFullScreenPrimary` - Can enter fullscreen mode -- `MacWindowCollectionBehaviorFullScreenAuxiliary` - Can overlay fullscreen apps -- `MacWindowCollectionBehaviorFullScreenNone` - Disables fullscreen capability -- `MacWindowCollectionBehaviorFullScreenAllowsTiling` - Allows side-by-side tiling (macOS 10.11+) -- `MacWindowCollectionBehaviorFullScreenDisallowsTiling` - Prevents tiling (macOS 10.11+) - -**Example - Spotlight-like window:** - -```go -// Window that appears on all Spaces AND can overlay fullscreen apps -Mac: application.MacWindow{ - CollectionBehavior: application.MacWindowCollectionBehaviorCanJoinAllSpaces | - application.MacWindowCollectionBehaviorFullScreenAuxiliary, - WindowLevel: application.MacWindowLevelFloating, -}, -``` - -**Example - Single behavior:** - -```go -// Window that can appear over fullscreen applications -Mac: application.MacWindow{ - CollectionBehavior: application.MacWindowCollectionBehaviorFullScreenAuxiliary, -}, -``` - -### Windows Options - -```go -Windows: application.WindowsOptions{ - DisableWindowIcon: false, - WindowBackdropType: application.WindowsBackdropTypeAuto, - CustomTheme: nil, - DisableFramelessWindowDecorations: false, -}, -``` - -**DisableWindowIcon** (`bool`) -- Remove icon from title bar -- Cleaner appearance - -**WindowBackdropType** (`WindowsBackdropType`) -- `WindowsBackdropTypeAuto` - System default -- `WindowsBackdropTypeNone` - No backdrop -- `WindowsBackdropTypeMica` - Mica material (Windows 11) -- `WindowsBackdropTypeAcrylic` - Acrylic material (Windows 11) -- `WindowsBackdropTypeTabbed` - Tabbed material (Windows 11) - -**CustomTheme** (`*WindowsTheme`) -- Custom colour theme -- Override system colours - -**DisableFramelessWindowDecorations** (`bool`) -- Disable default frameless decorations -- For custom window chrome - -**Example:** - -```go -Windows: application.WindowsOptions{ - WindowBackdropType: application.WindowsBackdropTypeMica, - DisableWindowIcon: true, -}, -``` - -### Linux Options - -```go -Linux: application.LinuxOptions{ - Icon: []byte{/* PNG data */}, - WindowIsTranslucent: false, -}, -``` - -**Icon** (`[]byte`) -- Window icon (PNG format) -- Shown in title bar and taskbar - -**WindowIsTranslucent** (`bool`) -- Enable window translucency -- Requires compositor support - -**Example:** - -```go -//go:embed icon.png -var icon []byte - -Linux: application.LinuxOptions{ - Icon: icon, -}, -``` - -## Application-Level Windows Options - -Some Windows-specific options must be configured at the application level rather than per-window. This is because WebView2 shares a single browser environment per user data path. - -### Browser Flags - -WebView2 browser flags control experimental features and behavior across **all windows** in your application. These must be set in `application.Options.Windows`: - -```go -app := application.New(application.Options{ - Name: "My App", - Windows: application.WindowsOptions{ - // Enable experimental WebView2 features - EnabledFeatures: []string{ - "msWebView2EnableDraggableRegions", - }, - - // Disable specific features - DisabledFeatures: []string{ - "msSmartScreenProtection", // Always disabled by Wails - }, - - // Additional Chromium command-line arguments - AdditionalBrowserArgs: []string{ - "--disable-gpu", - "--remote-debugging-port=9222", - }, - }, -}) -``` - -**EnabledFeatures** (`[]string`) -- List of WebView2 feature flags to enable -- See [WebView2 browser flags](https://learn.microsoft.com/en-us/microsoft-edge/webview2/concepts/webview-features-flags) for available flags -- Example: `"msWebView2EnableDraggableRegions"` - -**DisabledFeatures** (`[]string`) -- List of WebView2 feature flags to disable -- Wails automatically disables `msSmartScreenProtection` -- Example: `"msExperimentalFeature"` - -**AdditionalBrowserArgs** (`[]string`) -- Chromium command-line arguments passed to the browser process -- Must include the `--` prefix (e.g., `"--remote-debugging-port=9222"`) -- See [Chromium command line switches](https://peter.sh/experiments/chromium-command-line-switches/) for available arguments - -:::caution[Important] -These flags apply globally to ALL windows because WebView2 shares a single browser environment per user data path. You cannot have different browser flags for different windows. -::: - -**Complete Example:** - -```go -package main - -import ( - "github.com/wailsapp/wails/v3/pkg/application" -) - -func main() { - app := application.New(application.Options{ - Name: "My App", - Windows: application.WindowsOptions{ - // Enable draggable regions feature - EnabledFeatures: []string{ - "msWebView2EnableDraggableRegions", - }, - // Enable remote debugging - AdditionalBrowserArgs: []string{ - "--remote-debugging-port=9222", - }, - }, - }) - - // All windows will use the browser flags configured above - window := app.Window.NewWithOptions(application.WebviewWindowOptions{ - Title: "Main Window", - Width: 1024, - Height: 768, - }) - - window.Show() - app.Run() -} -``` - -## Complete Example - -Here's a production-ready window configuration: - -```go -package main - -import ( - _ "embed" - "github.com/wailsapp/wails/v3/pkg/application" -) - -//go:embed frontend/dist -var assets embed.FS - -//go:embed icon.png -var icon []byte - -func main() { - app := application.New(application.Options{ - Name: "My Application", - }) - - window := app.Window.NewWithOptions(application.WebviewWindowOptions{ - // Identity - Name: "main-window", - Title: "My Application", - - // Size and Position - Width: 1200, - Height: 800, - MinWidth: 800, - MinHeight: 600, - - // Initial State - WindowState: application.WindowStateNormal, - Resizable: true, - - // Appearance - BackgroundColour: application.RGBA{R: 255, G: 255, B: 255, A: 255}, - - // Content - Assets: application.AssetOptions{ - Handler: application.AssetFileServerFS(assets), - }, - - // Lifecycle - OnClose: func() bool { - if hasUnsavedChanges() { - result := showConfirmdialog("Unsaved changes. Close anyway?") - return result == "yes" - } - return true - }, - - OnDestroy: func() { - cleanup() - }, - - // Platform-Specific - Mac: application.MacOptions{ - TitleBarAppearsTransparent: true, - Backdrop: application.MacBackdropTranslucent, - }, - - Windows: application.WindowsOptions{ - WindowBackdropType: application.WindowsBackdropTypeMica, - DisableWindowIcon: false, - }, - - Linux: application.LinuxOptions{ - Icon: icon, - }, - }) - - window.Center() - window.Show() - - app.Run() -} -``` - -## Next Steps - -- [Window Basics](/features/windows/basics) - Creating and controlling windows -- [Multiple Windows](/features/windows/multiple) - Multi-window patterns -- [Frameless Windows](/features/windows/frameless) - Custom window chrome -- [Window Events](/features/windows/events) - Lifecycle events - ---- - -**Questions?** Ask in [Discord](https://discord.gg/JDdSxwjhGf) or check the [examples](https://github.com/wailsapp/wails/tree/v3-alpha/v3/examples). diff --git a/docs/src/content/docs/feedback.mdx b/docs/src/content/docs/feedback.mdx deleted file mode 100644 index afe4a8bfb..000000000 --- a/docs/src/content/docs/feedback.mdx +++ /dev/null @@ -1,86 +0,0 @@ ---- -title: v3 Alpha Feedback -sidebar: - order: 40 ---- - -import { Tabs, TabItem } from "@astrojs/starlight/components"; - -We welcome (and encourage) your feedback! Please search for existing tickets or -posts before creating new ones. Here are the different ways to provide feedback: - - - - - If you find a bug, please let us know by posting into the [v3 Alpha Feedback](https://discord.gg/bdj28QNHmT) channel on Discord. - - - The post should clearly state what the bug is and have a simple reproducible example. If the docs are unclear what *should* happen, please include that in the post. - - The post should be given the `Bug` tag. - - Please include the output of `wails doctor` in your post. - - If the bug is behavior that does not align with current documentation, e.g. a window does not resize properly, please do the following: - - Update an existing example in the `v3/example` directory or create a new example in the `v3/examples` folder that clearly shows the issue. - - Open a [PR](https://github.com/wailsapp/wails/pulls) with the title `[v3 alpha test] `. - - Please include a link to the PR in your post. - - :::caution - - _Remember_, unexpected behavior isn't necessarily a bug - it might just not do - what you expect it to do. Use `Suggestions` for this. - - ::: - - - - - - If you have a fix for a bug or an update for documentation, please do the following: - - - Open a pull request on the [Wails repository](https://github.com/wailsapp/wails). The title of the PR should start with `[v3 alpha]`. - - Create a post in the [v3 Alpha Feedback](https://discord.gg/bdj28QNHmT) channel. - - The post should be given the `PR` tag. - - Please include a link to the PR in your post. - - - - - - If you have a suggestion, please let us know by posting into the [v3 Alpha Feedback](https://discord.gg/bdj28QNHmT) channel on Discord: - - - The post should be given the `Suggestion` tag. - - Please feel free to reach out to us on [Discord](https://discord.gg/bdj28QNHmT) if you have any questions. - - - - - - - Posts can be "upvoted" by using the :thumbsup: emoji. Please apply to any posts that are a priority for you. - - Please *don't* just add comments like "+1" or "me too". - - Please feel free to comment if there is more to add to the post, such as "this bug also affect ARM builds" or "Another option would be to ....." - - - - - -There is a list of known issues & work in progress can be found -[here](https://github.com/orgs/wailsapp/projects/6). - -## Things we are looking for feedback on - -- The API - - Is it easy to use? - - Does it do what you expect? - - Is it missing anything? - - Is there anything that should be removed? - - Is it consistent between Go and JS? -- The build system - - Is it easy to use? - - Can we improve it? -- The examples - - Are they clear? - - Do they cover the basics? -- Features - - What features are missing? - - What features are not needed? -- Documentation - - What could be clearer? diff --git a/docs/src/content/docs/getting-started/installation.mdx b/docs/src/content/docs/getting-started/installation.mdx deleted file mode 100644 index 9c9d87885..000000000 --- a/docs/src/content/docs/getting-started/installation.mdx +++ /dev/null @@ -1,114 +0,0 @@ ---- -title: Installation -sidebar: - order: 10 ---- - -import { Tabs, TabItem } from "@astrojs/starlight/components"; - -## Supported Platforms - -- Windows 10/11 AMD64/ARM64 -- macOS 10.15+ AMD64 (Can deploy to macOS 10.13+) -- macOS 11.0+ ARM64 -- Ubuntu 24.04 AMD64/ARM64 (other Linux may work too!) - -## Dependencies - -Wails has a number of common dependencies that are required before installation: - - - - - Download Go from the [Go Downloads Page](https://go.dev/dl/). - - Ensure that you follow the official [Go installation instructions](https://go.dev/doc/install). You will also need to ensure that your `PATH` environment variable also includes the path to your `~/go/bin` directory. Restart your terminal and do the following checks: - - - Check Go is installed correctly: `go version` - - Check `~/go/bin` is in your PATH variable - - Mac / Linux: `echo $PATH | grep go/bin` - - Windows: `$env:PATH -split ';' | Where-Object { $_ -like '*\go\bin' }` - - - - - - Although Wails doesn't require npm to be installed, it is needed by most of the bundled templates. - - Download the latest node installer from the [Node Downloads Page](https://nodejs.org/en/download/). It is best to use the latest release as that is what we generally test against. - - Run `npm --version` to verify. - - :::note - If you prefer a different package manager to npm, feel free to use it. You will need to update the project Taskfiles to use it. - ::: - - - - - -## Platform Specific Dependencies - -You will also need to install platform specific dependencies: - - - - - Wails requires that the xcode command line tools are installed. This can be - done by running: - - ```sh - xcode-select --install - ``` - - - - - Wails requires that the [WebView2 Runtime](https://developer.microsoft.com/en-us/microsoft-edge/webview2/) is installed. Almost all Windows installations will already have this installed. You can check using the `wails doctor` command. - - - - - Linux requires the standard `gcc` build tools plus `gtk3` and `webkit2gtk`. Run wails doctor after installation to be shown how to install the dependencies. If your distro/package manager is not supported, please let us know on discord. - - - - - -## Installation - -To install the Wails CLI using Go Modules, run the following commands: - -```shell -go install -v github.com/wailsapp/wails/v3/cmd/wails3@latest -``` - -If you would like to install the latest development version, run the following -commands: - -```shell -git clone https://github.com/wailsapp/wails.git -cd wails -git checkout v3-alpha -cd v3/cmd/wails3 -go install -``` - -When using the development version, all generated projects will use Go's -[replace](https://go.dev/ref/mod#go-mod-file-replace) directive to ensure -projects use the development version of Wails. - -## System Check - -Running `wails3 doctor` will check if you have the correct dependencies -installed. If not, it will advise on what is missing and help on how to rectify -any problems. - -## The `wails3` command appears to be missing? - -If your system is reporting that the `wails3` command is missing, check the -following: - -- Make sure you have followed the above `Go installation guide` correctly and - that the `go/bin` directory is in the `PATH` environment variable. -- Close/Reopen current terminals to pick up the new `PATH` variable. diff --git a/docs/src/content/docs/getting-started/your-first-app.mdx b/docs/src/content/docs/getting-started/your-first-app.mdx deleted file mode 100644 index 143e66256..000000000 --- a/docs/src/content/docs/getting-started/your-first-app.mdx +++ /dev/null @@ -1,272 +0,0 @@ ---- -title: Your First Application -sidebar: - order: 20 ---- - -import { Tabs, TabItem } from "@astrojs/starlight/components"; -import { Badge } from '@astrojs/starlight/components'; -import { Steps } from "@astrojs/starlight/components"; -import { FileTree } from '@astrojs/starlight/components'; - -import wails_init from '../../../assets/wails_init.mp4'; -import wails_build from '../../../assets/wails_build.mp4'; -import wails_dev from '../../../assets/wails_dev.mp4'; - - -This guide shows you how to create your first Wails v3 application, covering project setup, building, and development workflow. - -
      -
      - - - -1. ## Creating a New Project - - Open your terminal and run the following command to create a new Wails - project: - - ```bash - wails3 init -n myfirstapp - ``` - - This command creates a new directory called `myfirstapp` with all the - necessary files. - - - -2. ## Exploring the Project Structure - - Navigate to the `myfirstapp` directory. You'll find several files and - folders: - - - - build/ Contains files used by the build process - - appicon.png The application icon - - config.yml Build configuration - - Taskfile.yml Build tasks - - darwin/ macOS specific build files - - Info.dev.plist Development configuration - - Info.plist Production configuration - - Taskfile.yml macOS build tasks - - icons.icns macOS application icon - - linux/ Linux specific build files - - Taskfile.yml Linux build tasks - - appimage/ AppImage packaging - - build.sh AppImage build script - - nfpm/ NFPM packaging - - nfpm.yaml Package configuration - - scripts/ Build scripts - - windows/ Windows specific build files - - Taskfile.yml Windows build tasks - - icon.ico Windows application icon - - info.json Application metadata - - wails.exe.manifest Windows manifest file - - nsis/ NSIS installer files - - project.nsi NSIS project file - - wails_tools.nsh NSIS helper scripts - - frontend/ Frontend application files - - index.html Main HTML file - - main.js Main JavaScript file - - package.json NPM package configuration - - public/ Static assets - - Inter Font License.txt Font license - - .gitignore Git ignore file - - README.md Project documentation - - Taskfile.yml Project tasks - - go.mod Go module file - - go.sum Go module checksums - - greetservice.go Greeting service - - main.go Main application code - - - Take a moment to explore these files and familiarize yourself with the - structure. - - :::note - Although Wails v3 uses [Task](https://taskfile.dev/) as its - default build system, there is nothing stopping you from using `make` or any other - alternative build system. - ::: - -3. ## Building Your Application - - To build your application, execute: - - ```bash - wails3 build - ``` - - This command compiles a debug version of your application and saves it in a - new `bin` directory. - - :::note - `wails3 build` is shorthand for `wails3 task build` and will run the `build` task in `Taskfile.yml`. - ::: - - - - - Once built, you can run this like you would any normal application: - - - - - - - ```sh - ./bin/myfirstapp - ``` - - - - - - ```sh - bin\myfirstapp.exe - ``` - - - - - - ```sh - ./bin/myfirstapp - ``` - - - - - - You'll see a simple UI, the starting point for your application. As it is - the debug version, you'll also see logs in the console window. This is - useful for debugging purposes. - -4. ## Dev Mode - - We can also run the application in development mode. This mode allows you to - make changes to your frontend code and see the changes reflected in the - running application without having to rebuild the entire application. - - 1. Open a new terminal window. - 2. Run `wails3 dev`. The application will compile and run in debug mode. - 3. Open `frontend/index.html` in your editor of choice. - 4. Edit the code and change `Please enter your name below` to - `Please enter your name below!!!`. - 5. Save the file. - - This change will reflect in your application immediately. - - Any changes to backend code will trigger a rebuild: - - 1. Open `greetservice.go`. - 2. Change the line that has `return "Hello " + name + "!"` to - `return "Hello there " + name + "!"`. - 3. Save the file. - - The application will update within a matter of seconds. - - - -5. ## Packaging Your Application - - Once your application is ready for distribution, you can create - platform-specific packages: - - - - - - To create a `.app` bundle: - - ```bash - wails3 package - ``` - - This will create a production build and package it into a `.app` bundle in the `bin` directory. - - - - - To create an NSIS installer: - - ```bash - wails3 package - ``` - - This will create a production build and package it into an NSIS installer in the `bin` directory. - - - - - Wails supports multiple package formats for Linux distribution: - - ```bash - # Create all package types (AppImage, deb, rpm, and Arch Linux) - wails3 package - - # Or create specific package types - wails3 task linux:create:appimage # AppImage format - wails3 task linux:create:deb # Debian package - wails3 task linux:create:rpm # Red Hat package - wails3 task linux:create:aur # Arch Linux package - ``` - - - - - - For more detailed information about packaging options and configuration, - check out our [Packaging Guide](/guides/packaging). - -6. ## Setting up Version Control and Module Name - - Your project is created with the placeholder module name `changeme`. It's recommended to update this to match your repository URL: - - 1. Create a new repository on GitHub (or your preferred Git host) - 2. Initialize git in your project directory: - ```bash - git init - git add . - git commit -m "Initial commit" - ``` - 3. Set your remote repository (replace with your repository URL): - ```bash - git remote add origin https://github.com/username/myfirstapp.git - ``` - 4. Update your module name in `go.mod` to match your repository URL: - ```bash - go mod edit -module github.com/username/myfirstapp - ``` - 5. Push your code: - ```bash - git push -u origin main - ``` - - This ensures your Go module name aligns with Go's module naming conventions and makes it easier to share your code. - - :::tip[Pro Tip] - You can automate all of the initialisation steps by using the `-git` flag when creating your project: - ```bash - wails3 init -n myfirstapp -git github.com/username/myfirstapp - ``` - This supports various Git URL formats: - - HTTPS: `https://github.com/username/project` - - SSH: `git@github.com:username/project` or `ssh://git@github.com/username/project` - - Git protocol: `git://github.com/username/project` - - Filesystem: `file:///path/to/project.git` - ::: - - - -## Congratulations! - -You've just created, developed and packaged your first Wails application. -This is just the beginning of what you can achieve with Wails v3. - -## Next Steps - -If you are new to Wails, we recommend reading through our Tutorials next which will be a practical guide through -the various features of Wails. The first tutorial is [Creating a Service](/tutorials/01-creating-a-service). - -If you are a more advanced user, check out our [Guides](/guides) for more detailed information on how to use Wails. diff --git a/docs/src/content/docs/guides/_category_.json b/docs/src/content/docs/guides/_category_.json deleted file mode 100644 index edc4bf6e3..000000000 --- a/docs/src/content/docs/guides/_category_.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "label": "Guides", - "position": 3, - "link": { - "type": "generated-index", - "description": "Comprehensive guides for developing Wails applications" - } -} diff --git a/docs/src/content/docs/guides/architecture.mdx b/docs/src/content/docs/guides/architecture.mdx deleted file mode 100644 index 72678befd..000000000 --- a/docs/src/content/docs/guides/architecture.mdx +++ /dev/null @@ -1,199 +0,0 @@ ---- -title: Architecture Patterns -description: Design patterns for Wails applications -sidebar: - order: 7 ---- - -## Overview - -Proven patterns for organising your Wails application. - -## Service Layer Pattern - -### Structure - -``` -app/ -├── main.go -├── services/ -│ ├── user_service.go -│ ├── data_service.go -│ └── file_service.go -└── models/ - └── user.go -``` - -### Implementation - -```go -// Service interface -type UserService interface { - Create(email, password string) (*User, error) - GetByID(id int) (*User, error) - Update(user *User) error - Delete(id int) error -} - -// Implementation -type userService struct { - app *application.Application - db *sql.DB -} - -func NewUserService(app *application.Application, db *sql.DB) UserService { - return &userService{app: app, db: db} -} -``` - -## Repository Pattern - -### Structure - -```go -// Repository interface -type UserRepository interface { - Create(user *User) error - FindByID(id int) (*User, error) - Update(user *User) error - Delete(id int) error -} - -// Service uses repository -type UserService struct { - repo UserRepository -} - -func (s *UserService) Create(email, password string) (*User, error) { - user := &User{Email: email} - return user, s.repo.Create(user) -} -``` - -## Event-Driven Architecture - -### Event Bus - -```go -type EventBus struct { - app *application.Application - listeners map[string][]func(interface{}) - mu sync.RWMutex -} - -func (eb *EventBus) Subscribe(event string, handler func(interface{})) { - eb.mu.Lock() - defer eb.mu.Unlock() - eb.listeners[event] = append(eb.listeners[event], handler) -} - -func (eb *EventBus) Publish(event string, data interface{}) { - eb.mu.RLock() - handlers := eb.listeners[event] - eb.mu.RUnlock() - - for _, handler := range handlers { - go handler(data) - } -} -``` - -### Usage - -```go -// Subscribe -eventBus.Subscribe("user.created", func(data interface{}) { - user := data.(*User) - sendWelcomeEmail(user) -}) - -// Publish -eventBus.Publish("user.created", user) -``` - -## Dependency Injection - -### Manual DI - -```go -type App struct { - userService *UserService - fileService *FileService - db *sql.DB -} - -func NewApp() *App { - db := openDatabase() - - return &App{ - db: db, - userService: NewUserService(db), - fileService: NewFileService(db), - } -} -``` - -### Using Wire - -```go -// wire.go -//go:build wireinject - -func InitializeApp() (*App, error) { - wire.Build( - openDatabase, - NewUserService, - NewFileService, - NewApp, - ) - return nil, nil -} -``` - -## State Management - -### Centralised State - -```go -type AppState struct { - currentUser *User - settings *Settings - mu sync.RWMutex -} - -func (s *AppState) SetUser(user *User) { - s.mu.Lock() - defer s.mu.Unlock() - s.currentUser = user -} - -func (s *AppState) GetUser() *User { - s.mu.RLock() - defer s.mu.RUnlock() - return s.currentUser -} -``` - -## Best Practices - -### ✅ Do - -- Separate concerns -- Use interfaces -- Inject dependencies -- Handle errors properly -- Keep services focused -- Document architecture - -### ❌ Don't - -- Don't create god objects -- Don't tightly couple components -- Don't skip error handling -- Don't ignore concurrency -- Don't over-engineer - -## Next Steps - -- [Security](/guides/security) - Security best practices -- [Best Practices](/features/bindings/best-practices) - Bindings best practices diff --git a/docs/src/content/docs/guides/build/building.mdx b/docs/src/content/docs/guides/build/building.mdx deleted file mode 100644 index 64a82b552..000000000 --- a/docs/src/content/docs/guides/build/building.mdx +++ /dev/null @@ -1,104 +0,0 @@ ---- -title: Building Applications -description: Build and package your Wails application -sidebar: - order: 1 ---- - -import { Tabs, TabItem, Aside } from "@astrojs/starlight/components"; - -Wails v3 uses [Task](https://taskfile.dev) as its build system. The `wails3 build` and `wails3 package` commands are convenient wrappers around Task. - -## Building - -Build for the current platform: - -```bash -wails3 build -``` - -Build for a specific platform: - -```bash -wails3 build GOOS=windows -wails3 build GOOS=darwin -wails3 build GOOS=linux - -# With architecture -wails3 build GOOS=darwin GOARCH=arm64 - -# Environment variable style works too -GOOS=windows wails3 build -``` - -Output goes to the `bin/` directory. - - - -## Development - -Run your application with hot reload: - -```bash -wails3 dev -``` - -This starts a file watcher that rebuilds and restarts your app on changes. The frontend dev server runs on port 9245 by default. - -```bash -# Custom port -wails3 dev -port 3000 - -# Enable HTTPS -wails3 dev -s -``` - -## Packaging - -Package your app for distribution: - -```bash -wails3 package -wails3 package GOOS=windows -wails3 package GOOS=darwin -wails3 package GOOS=linux -``` - -This creates platform-specific packages: -- **Windows**: NSIS installer — see [Windows Packaging](/guides/build/windows) -- **macOS**: Application bundle (`.app`) — see [macOS Packaging](/guides/build/macos) -- **Linux**: AppImage, deb, and rpm — see [Linux Packaging](/guides/build/linux) - -## Using Task Directly - -For more control, use Task directly: - -```bash -# List available tasks -wails3 task --list - -# Verbose output -wails3 task build -v - -# Dry run -wails3 task --dry - -# Force rebuild -wails3 task build -f - -# Pass variables -wails3 task darwin:build ARCH=amd64 -``` - -Platform-specific tasks like `linux:create:deb` or `darwin:build:universal` are only available through Task. - -## Generating Assets - -Regenerate icons or update build configuration: - -```bash -wails3 generate icons -input build/appicon.png -wails3 update build-assets -name "MyApp" -config build/config.yml -dir build -``` diff --git a/docs/src/content/docs/guides/build/cross-platform.mdx b/docs/src/content/docs/guides/build/cross-platform.mdx deleted file mode 100644 index 0685834d4..000000000 --- a/docs/src/content/docs/guides/build/cross-platform.mdx +++ /dev/null @@ -1,298 +0,0 @@ ---- -title: Cross-Platform Building -description: Build for multiple platforms from a single machine -sidebar: - order: 2 ---- - -import { Tabs, TabItem, Aside } from "@astrojs/starlight/components"; - -## Quick Start - -Wails v3 supports building for Windows, macOS, and Linux from any host operating system. The build system automatically detects your environment and chooses the right compilation method. - -**Want to cross-compile to macOS and Linux?** Run this once to set up the Docker images (~800MB download): - -```bash -wails3 task setup:docker -``` - -Then build for any platform: - -```bash -# Build for current platform (production by default) -wails3 build - -# Build for specific platforms -wails3 build GOOS=windows -wails3 build GOOS=darwin -wails3 build GOOS=linux - -# Build for ARM64 architecture -wails3 build GOOS=windows GOARCH=arm64 -wails3 build GOOS=darwin GOARCH=arm64 -wails3 build GOOS=linux GOARCH=arm64 - -# Environment variable style also works -GOOS=darwin GOARCH=arm64 wails3 build -``` - -### Windows - -Windows is the simplest cross-compilation target because it doesn't require CGO by default. - -```bash -wails3 build GOOS=windows -``` - -This works from any host OS with no additional setup. Go's built-in cross-compilation handles everything. - -**If your app requires CGO** (e.g., you're using a C library or CGO-dependent package), you'll need Docker when building from macOS or Linux: - -```bash -# One-time setup -wails3 task setup:docker - -# Build with CGO enabled -wails3 task windows:build CGO_ENABLED=1 -``` - -The Taskfile detects `CGO_ENABLED=1` on non-Windows hosts and automatically uses the Docker image. - -### macOS - -macOS builds require CGO for WebView integration, which means cross-compilation needs special tooling. - -```bash -# Build for Apple Silicon (arm64) - default -wails3 build GOOS=darwin - -# Build for Intel (amd64) -wails3 build GOOS=darwin GOARCH=amd64 - -# Build universal binary (both architectures) -wails3 task darwin:build:universal -``` - -**From Linux or Windows**, you'll need to set up Docker first: - -```bash -wails3 task setup:docker -``` - -Once the images are built, the build system detects that you're not on macOS and uses Docker automatically. You don't need to change your build commands. - -Note that cross-compiled macOS binaries are not code-signed. You'll need to sign them on macOS or in CI before distribution. - -### Linux - -Linux builds require CGO for WebView integration. - -```bash -wails3 build GOOS=linux - -# Build for specific architecture -wails3 build GOOS=linux GOARCH=amd64 -wails3 build GOOS=linux GOARCH=arm64 -``` - -**From macOS or Windows**, you'll need to set up Docker first: - -```bash -wails3 task setup:docker -``` - -The build system detects that you're not on Linux and uses Docker automatically. - -**On Linux without a C compiler**, the build system checks for `gcc` or `clang`. If neither is found, it falls back to Docker. This is useful for minimal containers or systems without build tools installed. You can either: - -1. Install a C compiler: `sudo apt install build-essential` (Debian/Ubuntu) or `sudo pacman -S base-devel` (Arch) -2. Build the Docker image and let it be used automatically - -### ARM Architecture - -All platforms support ARM64 cross-compilation using `GOARCH`: - -```bash -# Windows ARM64 (Surface Pro X, Windows on ARM) -wails3 build GOOS=windows GOARCH=arm64 - -# Linux ARM64 (Raspberry Pi 4/5, AWS Graviton) -wails3 build GOOS=linux GOARCH=arm64 - -# macOS ARM64 (Apple Silicon - this is the default on macOS) -wails3 build GOOS=darwin GOARCH=arm64 - -# macOS Intel (amd64) -wails3 build GOOS=darwin GOARCH=amd64 -``` - -The Docker image includes Zig cross-compiler targets for both amd64 and arm64 on all platforms, so ARM builds work from any host: - -| Build ARM64 for | From Windows | From macOS | From Linux | -|-----------------|--------------|------------|------------| -| **Windows ARM64** | Native Go | Native Go | Native Go | -| **macOS ARM64** | Docker | Native | Docker | -| **Linux ARM64** | Docker | Docker | Docker* | - -*Linux ARM64 from Linux x86_64 uses Docker because CGO cross-compilation requires a different toolchain. - -## How It Works - -### Cross-Compilation Matrix - -| Host → Target | Windows | macOS | Linux | -|---------------|---------|-------|-------| -| **Windows** | Native | Docker | Docker | -| **macOS** | Native Go | Native | Docker | -| **Linux** | Native Go | Docker | Native | - -- **Native** = Platform's native toolchain, no additional setup -- **Native Go** = Go's built-in cross-compilation (`CGO_ENABLED=0`) -- **Docker** = Docker image with Zig cross-compiler - -### CGO Requirements - -| Target | CGO Required | Cross-Compilation Method | -|--------|--------------|--------------------------| -| Windows | No (default) | Native Go. Docker only if `CGO_ENABLED=1` | -| macOS | Yes | Docker with macOS SDK | -| Linux | Yes | Docker, or native if C compiler available | - -### Auto-Detection - -The Taskfiles automatically choose the right build method based on your environment: - -- **Windows target:** Uses native Go cross-compilation by default. If you explicitly set `CGO_ENABLED=1` on a non-Windows host, it switches to Docker. -- **macOS target:** Uses Docker automatically when not on macOS. No manual intervention needed. -- **Linux target:** Checks for `gcc` or `clang`. Uses native compilation if found, otherwise falls back to Docker. - -### Docker Image - -Wails uses a single Docker image (`wails-cross`) that can build for all platforms. It uses [Zig](https://ziglang.org/) as the cross-compiler, which can target any platform from any host. The macOS SDK is included for darwin targets. - -```bash -wails3 task setup:docker -``` - -You can check if the image is ready by running `wails3 doctor`. - -### macOS SDK - -The Docker image downloads the macOS SDK from [joseluisq/macosx-sdks](https://github.com/joseluisq/macosx-sdks) during the image build process. This is required because macOS headers are needed for CGO compilation. - -By default, the image uses **macOS SDK 14.5** (Sonoma). To use a different version, rebuild with: - -```bash -docker build -t wails-cross \ - --build-arg MACOS_SDK_VERSION=15.0 \ - -f build/docker/Dockerfile.cross build/docker/ -``` - -See the [available SDK versions](https://github.com/joseluisq/macosx-sdks/releases) for options. - -**Important:** Wails does not distribute the macOS SDK. Users are responsible for reviewing Apple's SDK license terms before using this feature. - -## CI/CD Integration - -For production releases, we recommend using CI/CD with native runners for each platform. This avoids cross-compilation entirely and ensures you get properly signed binaries. - -```yaml -name: Build - -on: - push: - branches: [main] - -jobs: - build: - strategy: - matrix: - include: - - os: ubuntu-latest - goos: linux - - os: macos-latest - goos: darwin - - os: windows-latest - goos: windows - - runs-on: ${{ matrix.os }} - - steps: - - uses: actions/checkout@v4 - - - uses: actions/setup-go@v5 - with: - go-version: '1.24' - - - uses: actions/setup-node@v4 - with: - node-version: '20' - - - name: Install Wails CLI - run: go install github.com/wailsapp/wails/v3/cmd/wails3@latest - - - name: Install Task - uses: arduino/setup-task@v2 - - - name: Build - run: wails3 build - - - uses: actions/upload-artifact@v4 - with: - name: app-${{ matrix.goos }} - path: bin/ -``` - -## Troubleshooting - -### Docker image not found - -``` -Docker image 'wails-cross' not found. -``` - -Run `wails3 task setup:docker` to build the Docker image. You only need to do this once. - -### Docker daemon not running - -``` -Docker is required for cross-compilation. Please install Docker. -``` - -Start Docker Desktop or the Docker daemon. On Linux, you may need to run `sudo systemctl start docker`. - -### No C compiler on Linux - -If you see CGO-related errors when building on Linux, you have two options: - -1. **Install a C compiler:** - - Debian/Ubuntu: `sudo apt install build-essential` - - Arch Linux: `sudo pacman -S base-devel` - - Fedora: `sudo dnf install gcc` - -2. **Use Docker instead:** Run `wails3 task setup:docker` and the Taskfile will use it automatically when no compiler is detected. - -### macOS binaries not signed - -Cross-compiled macOS binaries are not code-signed. Apple requires code signing for distribution, so you'll need to: - -1. Sign the binary on a macOS machine, or -2. Sign in CI using a macOS runner - -See [Signing Applications](/guides/build/signing) for details. - -### Universal binary creation - -Universal binaries (arm64 + amd64 combined) can be built on any platform: - -```bash -wails3 task darwin:build:universal -``` - -On Linux and Windows, Wails uses its built-in `wails3 tool lipo` command (powered by [konoui/lipo](https://github.com/konoui/lipo)) to combine the binaries. This creates a single binary that runs natively on both Apple Silicon and Intel Macs. - -## Next Steps - -- [Building Applications](/guides/build/building) - Basic build commands and options -- [Signing Applications](/guides/build/signing) - Code signing for distribution diff --git a/docs/src/content/docs/guides/build/customization.mdx b/docs/src/content/docs/guides/build/customization.mdx deleted file mode 100644 index 993fb1ee5..000000000 --- a/docs/src/content/docs/guides/build/customization.mdx +++ /dev/null @@ -1,282 +0,0 @@ ---- -title: Build Customization -description: Customize your build process using Task and Taskfile.yml -sidebar: - order: 7 ---- - -import { FileTree } from "@astrojs/starlight/components"; - -## Overview - -The Wails build system is a flexible and powerful tool designed to streamline -the build process for your Wails applications. It leverages -[Task](https://taskfile.dev), a task runner that allows you to define and run -tasks easily. While the v3 build system is the default, Wails encourages a -"bring your own tooling" approach, allowing developers to customize their build -process as needed. - -Learn more about how to use Task in the -[official documentation](https://taskfile.dev/usage/). - -## Task: The Heart of the Build System - -[Task](https://taskfile.dev) is a modern alternative to Make, written in Go. It -uses a YAML file to define tasks and their dependencies. In the Wails build -system, [Task](https://taskfile.dev) plays a central role in orchestrating the -build process. - -The main `Taskfile.yml` is located in the project root, while platform-specific -tasks are defined in `build//Taskfile.yml` files. A common `Taskfile.yml` -file in the `build` directory contains common tasks that are shared across -platforms. - - - -- Project Root - - Taskfile.yml - - build - - windows/Taskfile.yml - - darwin/Taskfile.yml - - linux/Taskfile.yml - - Taskfile.yml - - - -## Taskfile.yml - -The `Taskfile.yml` file in the project root is the main entry point for the build system. It defines -the tasks and their dependencies. Here's the default `Taskfile.yml` file: - -```yaml -version: '3' - -includes: - common: ./build/Taskfile.yml - windows: ./build/windows/Taskfile.yml - darwin: ./build/darwin/Taskfile.yml - linux: ./build/linux/Taskfile.yml - -vars: - APP_NAME: "myproject" - BIN_DIR: "bin" - VITE_PORT: '{{.WAILS_VITE_PORT | default 9245}}' - -tasks: - build: - summary: Builds the application - cmds: - - task: "{{OS}}:build" - - package: - summary: Packages a production build of the application - cmds: - - task: "{{OS}}:package" - - run: - summary: Runs the application - cmds: - - task: "{{OS}}:run" - - dev: - summary: Runs the application in development mode - cmds: - - wails3 dev -config ./build/config.yml -port {{.VITE_PORT}} - - -``` - -## Platform-Specific Taskfiles - -Each platform has its own Taskfile, located in the platform directories beneath the `build` directory. These -files define the core tasks for that platform. Each taskfile includes common tasks from the `build/Taskfile.yml` file. - -### Windows - -Location: `build/windows/Taskfile.yml` - -The Windows-specific Taskfile includes tasks for building, packaging, and -running the application on Windows. Key features include: - -- Building with optional production flags -- Generating `.ico` icon file -- Generating Windows `.syso` file -- Creating an NSIS installer for packaging - -### Linux - -Location: `build/linux/Taskfile.yml` - -The Linux-specific Taskfile includes tasks for building, packaging, and running -the application on Linux. Key features include: - -- Building with optional production flags -- Creating an AppImage, deb, rpm, and Arch Linux packages -- Generating `.desktop` file for Linux applications - -### macOS - -Location: `build/darwin/Taskfile.yml` - -The macOS-specific Taskfile includes tasks for building, packaging, and running -the application on macOS. Key features include: - -- Building binaries for amd64, arm64 and universal (both) architectures -- Generating `.icns` icon file -- Creating an `.app` bundle for distributing -- Ad-hoc signing `.app` bundles -- Setting macOS-specific build flags and environment variables - -## Task Execution and Command Aliases - -The `wails3 task` command is an embedded version of [Taskfile](https://taskfile.dev), which executes -the tasks defined in your `Taskfile.yml`. - -The `wails3 build` and `wails3 package` commands are aliases for -`wails3 task build` and `wails3 task package` respectively. When you run these -commands, Wails internally translates them to the appropriate task execution: - -- `wails3 build` → `wails3 task build` -- `wails3 package` → `wails3 task package` - -### Passing Parameters to Tasks - -You can pass CLI variables to tasks using the `KEY=VALUE` format. These variables are forwarded through the alias commands: - -```bash -# These are equivalent: -wails3 build PLATFORM=linux CONFIG=production -wails3 task build PLATFORM=linux CONFIG=production - -# Package with custom version: -wails3 package VERSION=2.0.0 OUTPUT=myapp.pkg -``` - -In your `Taskfile.yml`, you can access these variables using Go template syntax: - -```yaml -tasks: - build: - cmds: - - echo "Building for {{.PLATFORM | default "darwin"}}" - - go build -tags {{.CONFIG | default "debug"}} -o myapp -``` - -## Common Build Process - -Across all platforms, the build process typically includes the following steps: - -1. Tidying Go modules -2. Building the frontend -3. Generating icons -4. Compiling the Go code with platform-specific flags -5. Packaging the application (platform-specific) - -## Customising the Build Process - -While the v3 build system provides a solid default configuration, you can easily -customise it to fit your project's needs. By modifying the `Taskfile.yml` and -platform-specific Taskfiles, you can: - -- Add new tasks -- Modify existing tasks -- Change the order of task execution -- Integrate with other tools and scripts - -This flexibility allows you to tailor the build process to your specific -requirements while still benefiting from the structure provided by the Wails -build system. - -:::tip[Learning Taskfile] -We highly recommend reading the [Taskfile](https://taskfile.dev) documentation to -understand how to use Taskfile effectively. -You can find out which version of Taskfile is embedded in the Wails CLI by running `wails3 task --version`. -::: - -## Development Mode - -The Wails build system includes a powerful development mode that enhances the -developer experience by providing live reloading and hot module replacement. -This mode is activated using the `wails3 dev` command. - -### How It Works - -When you run `wails3 dev`, the following process occurs: - -1. The command checks for an available port, defaulting to 9245 if not - specified. -2. It sets up the environment variables for the frontend dev server (Vite). -3. It starts the file watcher using the [refresh](https://github.com/atterpac/refresh) library. - -The [refresh](https://github.com/atterpac/refresh) library is responsible for -monitoring file changes and triggering rebuilds. It uses the configuration defined under the `dev_mode` key in the `./build/config.yaml` file. -It may be configured to ignore certain directories and files, to determine which files to watch and what actions to take when changes are detected. -The default configuration works pretty well, but feel free to customise it to your needs. - -### Configuration - -Here's an example of its structure: - -```yaml -dev_mode: - root_path: . - log_level: warn - debounce: 1000 - ignore: - dir: - - .git - - node_modules - - frontend - - bin - file: - - .DS_Store - - .gitignore - - .gitkeep - watched_extension: - - "*.go" - git_ignore: true - executes: - - cmd: wails3 task common:install:frontend:deps - type: once - - cmd: wails3 task common:dev:frontend - type: background - - cmd: go mod tidy - type: blocking - - cmd: wails3 task build - type: blocking - - cmd: wails3 task run - type: primary -``` - -This configuration file allows you to: - -- Set the root path for file watching -- Configure logging level -- Set a debounce time for file change events -- Ignore specific directories, files, or file extensions -- Define commands to execute on file changes - -### Customising Development Mode - -You can customise the development mode experience by modifying these values in the `config.yaml` file. - -Some ways to customise include: - -1. Changing the watched directories or files -2. Adjusting the debounce time to control how quickly the system responds to - changes -3. Adding or modifying the execute commands to fit your project's needs - -### Using a browser for development - -Whilst Wails v2 fully supported the use of a browser for development, it caused a lot -of confusion. Applications that would work in the browser would not necessarily -work in the desktop application, as not all browser APIs are available in webviews. - -For UI-focused development work, you still have the flexibility to use a browser -in v3, by accessing the Vite URL at `http://localhost:9245` in dev mode. This -gives you access to powerful browser dev tools while working on styling and -layout. Be aware that Go bindings *will not work* in this mode. -When you're ready to test functionality like bindings and events, simply -switch to the desktop view to ensure everything works perfectly in the -production environment. diff --git a/docs/src/content/docs/guides/build/linux.mdx b/docs/src/content/docs/guides/build/linux.mdx deleted file mode 100644 index 18666c2aa..000000000 --- a/docs/src/content/docs/guides/build/linux.mdx +++ /dev/null @@ -1,160 +0,0 @@ ---- -title: Linux Packaging -description: Package your Wails application for Linux distribution -sidebar: - order: 5 ---- - -import { Aside } from '@astrojs/starlight/components'; - -## Package Formats - -Package your app for Linux distribution: - -```bash -wails3 package GOOS=linux -``` - -This creates multiple formats in the `bin/` directory: -- **AppImage**: Portable, runs on any Linux distribution -- **DEB**: For Debian, Ubuntu, and derivatives -- **RPM**: For Fedora, RHEL, and derivatives -- **Arch**: For Arch Linux and derivatives - -### Individual Formats - -Build specific formats: - -```bash -wails3 task linux:create:appimage -wails3 task linux:create:deb -wails3 task linux:create:rpm -wails3 task linux:create:aur -``` - -## Customizing Packages - -### Desktop Entry - -The `.desktop` file controls how your app appears in application menus. It's generated from values in `build/linux/Taskfile.yml`: - -```yaml -vars: - APP_NAME: 'MyApp' - EXEC: 'MyApp' - ICON: 'MyApp' - CATEGORIES: 'Development;' -``` - -### Package Metadata - -Edit `build/linux/nfpm/nfpm.yaml` to customize DEB and RPM packages: - -```yaml -name: myapp -version: 1.0.0 -maintainer: Your Name -description: My awesome Wails application -homepage: https://example.com -license: MIT -``` - -### AppImage - -AppImage configuration is in `build/linux/appimage/`. The app icon comes from `build/appicon.png`. - -## Signing Packages - -Sign DEB and RPM packages with a PGP key: - -```bash -# Using the wrapper (auto-detects platform) -wails3 sign GOOS=linux - -# Or using tasks directly -wails3 task linux:sign:deb -wails3 task linux:sign:rpm -wails3 task linux:sign:packages # Both -``` - -Configure signing in `build/linux/Taskfile.yml`: - -```yaml -vars: - PGP_KEY: "path/to/signing-key.asc" - SIGN_ROLE: "builder" # origin, maint, archive, or builder -``` - -Store your key password: - -```bash -wails3 setup signing -``` - -See [Signing Applications](/guides/build/signing) for details. - -## Building for ARM - -```bash -wails3 build GOOS=linux GOARCH=arm64 -wails3 package GOOS=linux GOARCH=arm64 -``` - - - -## Troubleshooting - -### AppImage won't run - -Make it executable: - -```bash -chmod +x MyApp-x86_64.AppImage -``` - -### Missing dependencies - -If the app fails to start, check for missing WebKit dependencies: - -```bash -# Debian/Ubuntu -sudo apt install libwebkit2gtk-4.1-0 - -# Fedora -sudo dnf install webkit2gtk4.1 - -# Arch -sudo pacman -S webkit2gtk-4.1 -``` - -### No C compiler found - -The build system needs GCC or Clang for CGO: - -```bash -# Debian/Ubuntu -sudo apt install build-essential - -# Fedora -sudo dnf install gcc - -# Arch -sudo pacman -S base-devel -``` - -Alternatively, run `wails3 task setup:docker` and the build system will use Docker automatically. - -### AppImage strip compatibility - -On modern Linux distributions (Arch Linux, Fedora 39+, Ubuntu 24.04+), system libraries are compiled with `.relr.dyn` ELF sections for more efficient relocations. The `linuxdeploy` tool used to create AppImages bundles an older `strip` binary that cannot process these modern sections. - -Wails automatically detects this situation by checking system GTK libraries before building the AppImage. When detected, stripping is disabled (`NO_STRIP=1`) to ensure compatibility. - -**What this means:** -- AppImages will be slightly larger (~20-40%) on affected systems -- The application functionality is not affected -- This is handled automatically—no action required - -If you need smaller AppImages on modern systems, you can install a newer `strip` binary and configure `linuxdeploy` to use it instead of its bundled version. diff --git a/docs/src/content/docs/guides/build/macos.mdx b/docs/src/content/docs/guides/build/macos.mdx deleted file mode 100644 index 3271b2faa..000000000 --- a/docs/src/content/docs/guides/build/macos.mdx +++ /dev/null @@ -1,145 +0,0 @@ ---- -title: macOS Packaging -description: Package your Wails application for macOS distribution -sidebar: - order: 4 ---- - -import { Aside } from '@astrojs/starlight/components'; - -## Application Bundle - -Package your app as a standard macOS `.app` bundle: - -```bash -wails3 package GOOS=darwin -``` - -This creates `bin/.app` containing: -- The compiled binary in `Contents/MacOS/` -- App icon in `Contents/Resources/` (from `icons.icns` or, when present, from an asset catalog `Assets.car`) -- `Info.plist` with app metadata - -### Universal Binary - -Build for both Apple Silicon and Intel Macs: - -```bash -wails3 task darwin:package:universal -``` - -This creates a single `.app` that runs natively on both architectures. Universal binaries can be built on any platform — on Linux and Windows, `wails3 tool lipo` is used automatically. - -## Customizing the Bundle - -Edit `build/darwin/Info.plist` to customize: - -- Bundle identifier (`CFBundleIdentifier`) -- App name and version -- Minimum macOS version -- File associations -- URL schemes - -The app icon is generated from assets in the `build/` directory. Use the `generate:icons` task: - -```bash -wails3 task generate:icons -``` - -This uses `build/appicon.png` to produce `darwin/icons.icns` and `windows/icon.ico`. On macOS you can also provide `build/appicon.icon` (Icon Composer format): the task passes `-iconcomposerinput appicon.icon -macassetdir darwin`, which produces `Assets.car` and `darwin/icons.icns` from the `.icon` file (skipped on non-macOS platforms). When `Assets.car` is present, run the `update:build-assets` task so that `Info.plist` and `CFBundleIconName` are updated accordingly: - -```bash -wails3 task update:build-assets -``` - -To run the icon command manually from the `build/` directory: - -```bash -cd build -wails3 generate icons -input appicon.png -macfilename darwin/icons.icns -windowsfilename windows/icon.ico -iconcomposerinput appicon.icon -macassetdir darwin -``` - -## Code Signing - -Sign your app for distribution: - -```bash -# Using the wrapper (auto-detects platform) -wails3 sign GOOS=darwin - -# Or using the task directly -wails3 task darwin:sign -``` - -Configure signing in `build/darwin/Taskfile.yml`: - -```yaml -vars: - SIGN_IDENTITY: "Developer ID Application: Your Company (TEAMID)" - ENTITLEMENTS: "build/darwin/entitlements.plist" -``` - -### Notarization - -For apps distributed outside the Mac App Store, Apple requires notarization: - -```bash -wails3 task darwin:sign:notarize -``` - -First, store your credentials: - -```bash -wails3 signing credentials \ - --apple-id "you@email.com" \ - --team-id "TEAMID" \ - --password "app-specific-password" \ - --profile "my-notarize-profile" -``` - -Configure in `build/darwin/Taskfile.yml`: - -```yaml -vars: - SIGN_IDENTITY: "Developer ID Application: Your Company (TEAMID)" - KEYCHAIN_PROFILE: "my-notarize-profile" -``` - -See [Signing Applications](/guides/build/signing) for details. - -## DMG Installer - -Create a DMG disk image for distribution: - -```bash -wails3 task darwin:create:dmg -``` - - - -## Troubleshooting - -### "App is damaged and can't be opened" - -The app isn't signed. Either sign it with a Developer ID certificate, or users can bypass Gatekeeper: - -```bash -xattr -cr /path/to/YourApp.app -``` - -### Notarization fails - -Common issues: -- **Invalid credentials**: Re-run `wails3 signing credentials` -- **Hardened runtime required**: Ensure entitlements include `com.apple.security.cs.allow-unsigned-executable-memory` if needed -- **Missing timestamp**: The signing process should include a timestamp automatically - -### Cross-compiled app won't run - -Cross-compiled macOS binaries aren't signed. Transfer to a Mac and sign before testing: - -```bash -codesign --force --deep --sign - YourApp.app -``` diff --git a/docs/src/content/docs/guides/build/signing.mdx b/docs/src/content/docs/guides/build/signing.mdx deleted file mode 100644 index 3f6a03382..000000000 --- a/docs/src/content/docs/guides/build/signing.mdx +++ /dev/null @@ -1,823 +0,0 @@ ---- -title: Code Signing -description: Guide for signing your Wails applications on all platforms -sidebar: - order: 6 ---- - -import { Tabs, TabItem, Steps, Aside } from '@astrojs/starlight/components'; - -# Code Signing Your Application - -This guide covers how to sign your Wails applications for macOS, Windows, and Linux. Wails v3 provides built-in CLI tools for code signing, notarization, and PGP key management. - -- **macOS** - Sign and notarize your macOS applications -- **Windows** - Sign your Windows executables and packages -- **Linux** - Sign DEB and RPM packages with PGP keys - -## Cross-Platform Signing Matrix - -This matrix shows what you can sign from each source platform: - -| Target Format | From Windows | From macOS | From Linux | -|---------------|:------------:|:----------:|:----------:| -| Windows EXE/MSI | ✅ | ✅ | ✅ | -| macOS .app bundle | ❌ | ✅ | ❌ | -| macOS notarization | ❌ | ✅ | ❌ | -| Linux DEB | ✅ | ✅ | ✅ | -| Linux RPM | ✅ | ✅ | ✅ | - - - -### Signing Backends - -Wails automatically selects the best available signing backend: - -| Platform | Native Backend | Cross-Platform Backend | -|----------|----------------|------------------------| -| Windows | `signtool.exe` (Windows SDK) | Built-in | -| macOS | `codesign` (Xcode) | Not available | -| Linux | N/A | Built-in | - -When running on the native platform, Wails uses the native tools for maximum compatibility. When cross-compiling, it uses the built-in signing support. - -## Quick Start - -The easiest way to configure signing is using the interactive setup wizard: - -```bash -wails3 setup signing -``` - -This command: -- Walks you through configuring signing credentials for each platform -- On macOS, lists available Developer ID certificates from your keychain -- For Linux, can generate a new PGP key if you don't have one -- **Stores passwords securely in your system keychain** (not in Taskfiles) -- Updates the `vars` section in each platform's Taskfile with non-sensitive config - - - -To configure only specific platforms: - -```bash -wails3 setup signing --platform darwin -wails3 setup signing --platform windows --platform linux -``` - -### Manual Configuration - -Alternatively, you can manually edit the platform-specific Taskfiles. Edit the `vars` section at the top of each file: - - - -Edit `build/darwin/Taskfile.yml`: - -```yaml -vars: - SIGN_IDENTITY: "Developer ID Application: Your Company (TEAMID)" - KEYCHAIN_PROFILE: "my-notarize-profile" - # ENTITLEMENTS: "build/darwin/entitlements.plist" -``` - -Then run: - -```bash -wails3 task darwin:sign # Sign only -wails3 task darwin:sign:notarize # Sign and notarize -``` - - -Edit `build/windows/Taskfile.yml`: - -```yaml -vars: - SIGN_CERTIFICATE: "path/to/certificate.pfx" - # Or use thumbprint instead: - # SIGN_THUMBPRINT: "certificate-thumbprint" - # TIMESTAMP_SERVER: "http://timestamp.digicert.com" -``` - -Password is retrieved from system keychain (run `wails3 setup signing` to configure). - -Then run: - -```bash -wails3 task windows:sign # Sign executable -wails3 task windows:sign:installer # Sign NSIS installer -``` - - -Edit `build/linux/Taskfile.yml`: - -```yaml -vars: - PGP_KEY: "path/to/signing-key.asc" - # SIGN_ROLE: "builder" # Options: origin, maint, archive, builder -``` - -Password is retrieved from system keychain (run `wails3 setup signing` to configure). - -Then run: - -```bash -wails3 task linux:sign:deb # Sign DEB package -wails3 task linux:sign:rpm # Sign RPM package -wails3 task linux:sign:packages # Sign all packages -``` - - - -You can also use the CLI directly: - -```bash -# Check signing capabilities on your system -wails3 signing info - -# List available signing identities (macOS/Windows) -wails3 signing list -``` - -## macOS Code Signing - -### Prerequisites - -- Apple Developer Account ($99/year) -- Developer ID Application certificate -- Xcode Command Line Tools installed - -### Signing Identities - -Check available signing identities: - -```bash -wails3 signing list -``` - -Output: - -``` -Found 2 signing identities: - - Developer ID Application: Your Company (ABCD1234) [valid] - Hash: ABC123DEF456... - - Apple Development: your@email.com (XYZ789) [valid] - Hash: DEF789ABC123... -``` - - - -### Configuration - -Edit `build/darwin/Taskfile.yml` and set the signing variables: - -```yaml -vars: - SIGN_IDENTITY: "Developer ID Application: Your Company (TEAMID)" - KEYCHAIN_PROFILE: "my-notarize-profile" - ENTITLEMENTS: "build/darwin/entitlements.plist" -``` - -| Variable | Required | Description | -|----------|----------|-------------| -| `SIGN_IDENTITY` | Yes | Your Developer ID (e.g., "Developer ID Application: Your Company (TEAMID)") | -| `KEYCHAIN_PROFILE` | For notarization | Keychain profile name with stored credentials | -| `ENTITLEMENTS` | No | Path to entitlements file | - -Then run: - -```bash -wails3 task darwin:sign # Build, package, and sign -wails3 task darwin:sign:notarize # Build, package, sign, and notarize -``` - -### Entitlements - -Entitlements control what capabilities your app has access to. Wails apps typically need different entitlements for development vs production: - -- **Development**: Requires JIT, unsigned memory, and debugging entitlements -- **Production**: Minimal entitlements (just network access) - -Use the interactive setup wizard to generate both files: - -```bash -wails3 setup entitlements -``` - -This creates: -- `build/darwin/entitlements.dev.plist` - For development builds -- `build/darwin/entitlements.plist` - For production/signed builds - -**Presets available:** -| Preset | Description | -|--------|-------------| -| Development | JIT, unsigned memory, debugging, network | -| Production | Network only (minimal, most secure) | -| Both | Creates both dev and production files (recommended) | -| App Store | Sandbox enabled with network and file access | -| Custom | Choose individual entitlements | - - - -Then set `ENTITLEMENTS` in your Taskfile vars to point to the appropriate file. - -### Notarization - -Apple requires all distributed apps to be notarized. - - -1. **Store your credentials in the keychain** (one-time setup): - ```bash - wails3 signing credentials \ - --apple-id "your@email.com" \ - --team-id "ABCD1234" \ - --password "app-specific-password" \ - --profile "my-notarize-profile" - ``` - -2. **Set KEYCHAIN_PROFILE in your Taskfile** to match the profile name above. - -3. **Sign and notarize your app**: - ```bash - wails3 task darwin:sign:notarize - ``` - -4. **Verify notarization**: - ```bash - spctl --assess --verbose=2 bin/MyApp.app - ``` - - - - -## Windows Code Signing - -### Prerequisites - -- Code signing certificate (from DigiCert, Sectigo, etc.) -- For native signing: Windows SDK installed (for signtool.exe) -- For cross-platform: Just the certificate file - -### Configuration - -Edit `build/windows/Taskfile.yml` and set the signing variables: - -```yaml -vars: - SIGN_CERTIFICATE: "path/to/certificate.pfx" - # Or use thumbprint instead: - # SIGN_THUMBPRINT: "certificate-thumbprint" - # TIMESTAMP_SERVER: "http://timestamp.digicert.com" -``` - -| Variable | Required | Description | -|----------|----------|-------------| -| `SIGN_CERTIFICATE` | One of these | Path to .pfx/.p12 certificate file | -| `SIGN_THUMBPRINT` | One of these | Certificate thumbprint in Windows cert store | -| `TIMESTAMP_SERVER` | No | Timestamp server URL (default: http://timestamp.digicert.com) | - - - -Then run: - -```bash -wails3 task windows:sign # Build and sign executable -wails3 task windows:sign:installer # Build and sign NSIS installer -``` - -### Cross-Platform Signing - -Windows executables can be signed from any platform. The same Taskfile configuration and commands work on macOS and Linux. - -### Supported Windows Formats - -| Format | Extension | Notes | -|--------|-----------|-------| -| Executables | .exe | Standard PE signing | -| Installers | .msi | Windows Installer packages | -| App Packages | .msix, .appx | Modern Windows apps | - -## Linux Package Signing - -Linux packages (DEB and RPM) are signed using PGP/GPG keys. Unlike Windows and macOS code signing, Linux package signing proves the package came from a trusted source rather than that the code is trusted by the OS. - -### Prerequisites - -- PGP key pair (can be generated with Wails) - -### Generating a PGP Key - -If you don't have a PGP key, Wails can generate one for you: - -```bash -wails3 signing generate-key \ - --name "Your Name" \ - --email "your@email.com" \ - --comment "Package Signing Key" \ - --output-private signing-key.asc \ - --output-public signing-key.pub.asc -``` - -Options: -- `--bits`: Key size (default: 4096) -- `--expiry`: Key expiry duration (e.g., "1y", "6m", "0" for no expiry) -- `--password`: Password to protect the private key - - - -### Configuration - -Edit `build/linux/Taskfile.yml` and set the signing variables: - -```yaml -vars: - PGP_KEY: "path/to/signing-key.asc" - # SIGN_ROLE: "builder" # Options: origin, maint, archive, builder -``` - -| Variable | Required | Description | -|----------|----------|-------------| -| `PGP_KEY` | Yes | Path to PGP private key file | -| `SIGN_ROLE` | No | DEB signing role (default: builder) | - - - -Then run: - -```bash -wails3 task linux:sign:deb # Build and sign DEB package -wails3 task linux:sign:rpm # Build and sign RPM package -wails3 task linux:sign:packages # Build and sign all packages -``` - -### DEB Signing Roles - -For DEB packages, you can specify the signing role via `SIGN_ROLE`: - -- `origin`: Signature from the package origin -- `maint`: Signature from the package maintainer -- `archive`: Signature from the archive maintainer -- `builder`: Signature from the package builder (default) - -### Cross-Platform Signing - -Linux packages can be signed from any platform. The same Taskfile configuration and commands work on Windows and macOS. - -### Viewing Key Information - -```bash -wails3 signing key-info --key signing-key.asc -``` - -Output: - -``` -PGP Key Information: - Key ID: ABC123DEF456 - Fingerprint: 1234 5678 90AB CDEF ... - User IDs: Your Name - Created: 2024-01-15 - Expires: 2025-01-15 - Has Private: Yes - Encrypted: Yes -``` - -### Verifying Linux Packages - -```bash -# Verify DEB signature -dpkg-sig --verify myapp_1.0.0_amd64.deb - -# Verify RPM signature -rpm --checksig myapp-1.0.0.x86_64.rpm -``` - -### Distributing Your Public Key - -Users need your public key to verify packages: - -```bash -# Export public key for distribution -wails3 signing key-info --key signing-key.asc --export-public > myapp-signing.pub.asc - -# Users can import it: -# For DEB (apt): -sudo apt-key add myapp-signing.pub.asc -# Or for modern apt: -sudo cp myapp-signing.pub.asc /etc/apt/trusted.gpg.d/ - -# For RPM: -sudo rpm --import myapp-signing.pub.asc -``` - -## GitHub Actions Integration - -In CI environments, passwords are provided via environment variables instead of the system keychain: - -| Environment Variable | Description | -|---------------------|-------------| -| `WAILS_WINDOWS_CERT_PASSWORD` | Windows certificate password | -| `WAILS_PGP_PASSWORD` | PGP key password for Linux packages | - -You can also pass Taskfile variables directly: - -```bash -wails3 task darwin:sign SIGN_IDENTITY="$SIGN_IDENTITY" KEYCHAIN_PROFILE="$KEYCHAIN_PROFILE" -``` - -### macOS Workflow - -```yaml -name: Build and Sign macOS - -on: - push: - tags: ['v*'] - -jobs: - build: - runs-on: macos-latest - steps: - - uses: actions/checkout@v4 - - - name: Setup Go - uses: actions/setup-go@v5 - with: - go-version: '1.23' - - - name: Install Wails - run: go install github.com/wailsapp/wails/v3/cmd/wails3@latest - - - name: Import Certificate - env: - CERTIFICATE_BASE64: ${{ secrets.MACOS_CERTIFICATE }} - CERTIFICATE_PASSWORD: ${{ secrets.MACOS_CERTIFICATE_PASSWORD }} - run: | - echo $CERTIFICATE_BASE64 | base64 --decode > certificate.p12 - security create-keychain -p "" build.keychain - security default-keychain -s build.keychain - security unlock-keychain -p "" build.keychain - security import certificate.p12 -k build.keychain -P "$CERTIFICATE_PASSWORD" -T /usr/bin/codesign - security set-key-partition-list -S apple-tool:,apple:,codesign: -s -k "" build.keychain - - - name: Store Notarization Credentials - env: - APPLE_ID: ${{ secrets.APPLE_ID }} - APPLE_TEAM_ID: ${{ secrets.APPLE_TEAM_ID }} - APPLE_APP_PASSWORD: ${{ secrets.APPLE_APP_PASSWORD }} - run: | - wails3 signing credentials \ - --apple-id "$APPLE_ID" \ - --team-id "$APPLE_TEAM_ID" \ - --password "$APPLE_APP_PASSWORD" \ - --profile "notarize-profile" - - - name: Build, Sign, and Notarize - env: - SIGN_IDENTITY: ${{ secrets.MACOS_SIGN_IDENTITY }} - run: | - wails3 task darwin:sign:notarize \ - SIGN_IDENTITY="$SIGN_IDENTITY" \ - KEYCHAIN_PROFILE="notarize-profile" - - - name: Upload Artifact - uses: actions/upload-artifact@v4 - with: - name: MyApp-macOS - path: bin/*.app -``` - -### Windows Workflow - -```yaml -name: Build and Sign Windows - -on: - push: - tags: ['v*'] - -jobs: - build: - runs-on: windows-latest - steps: - - uses: actions/checkout@v4 - - - name: Setup Go - uses: actions/setup-go@v5 - with: - go-version: '1.23' - - - name: Install Wails - run: go install github.com/wailsapp/wails/v3/cmd/wails3@latest - - - name: Import Certificate - env: - CERTIFICATE_BASE64: ${{ secrets.WINDOWS_CERTIFICATE }} - run: | - $certBytes = [Convert]::FromBase64String($env:CERTIFICATE_BASE64) - [IO.File]::WriteAllBytes("certificate.pfx", $certBytes) - - - name: Build and Sign - env: - WAILS_WINDOWS_CERT_PASSWORD: ${{ secrets.WINDOWS_CERTIFICATE_PASSWORD }} - run: | - wails3 task windows:sign SIGN_CERTIFICATE=certificate.pfx - - - name: Upload Artifact - uses: actions/upload-artifact@v4 - with: - name: MyApp-Windows - path: bin/*.exe -``` - -### Cross-Platform Workflow (Linux Runner) - -Sign Windows and Linux packages from a single Linux runner: - -```yaml -name: Build and Sign (Cross-Platform) - -on: - push: - tags: ['v*'] - -jobs: - build-and-sign: - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v4 - - - name: Setup Go - uses: actions/setup-go@v5 - with: - go-version: '1.23' - - - name: Install Wails - run: go install github.com/wailsapp/wails/v3/cmd/wails3@latest - - - name: Install Build Dependencies - run: | - sudo apt-get update - sudo apt-get install -y nsis rpm - - # Import certificates - - name: Import Certificates - env: - WINDOWS_CERT_BASE64: ${{ secrets.WINDOWS_CERTIFICATE }} - PGP_KEY_BASE64: ${{ secrets.PGP_PRIVATE_KEY }} - run: | - echo "$WINDOWS_CERT_BASE64" | base64 -d > certificate.pfx - echo "$PGP_KEY_BASE64" | base64 -d > signing-key.asc - - # Build and sign Windows - - name: Build and Sign Windows - env: - WAILS_WINDOWS_CERT_PASSWORD: ${{ secrets.WINDOWS_CERTIFICATE_PASSWORD }} - run: | - wails3 task windows:sign SIGN_CERTIFICATE=certificate.pfx - - # Build and sign Linux packages - - name: Build and Sign Linux Packages - env: - WAILS_PGP_PASSWORD: ${{ secrets.PGP_PASSWORD }} - run: | - wails3 task linux:sign:packages PGP_KEY=signing-key.asc - - # Cleanup secrets - - name: Cleanup - if: always() - run: rm -f certificate.pfx signing-key.asc - - - name: Upload Artifacts - uses: actions/upload-artifact@v4 - with: - name: signed-binaries - path: | - bin/*.exe - bin/*.deb - bin/*.rpm -``` - - - -## CLI Reference - -### wails3 setup signing - -Interactive wizard to configure signing for your project. - -```bash -wails3 setup signing [flags] - -Flags: - --platform Platform(s) to configure (darwin, windows, linux) - If not specified, configures all platforms -``` - -The wizard guides you through: -- **macOS**: Selecting a Developer ID certificate, configuring notarization profile -- **Windows**: Choosing between certificate file or thumbprint, setting password and timestamp server -- **Linux**: Using an existing PGP key or generating a new one, configuring signing role - -### wails3 setup entitlements - -Interactive wizard to configure macOS entitlements. - -```bash -wails3 setup entitlements [flags] - -Flags: - --output Output directory (default: build/darwin) -``` - -**Presets:** -- **Development**: Creates `entitlements.dev.plist` with JIT, debugging, and network -- **Production**: Creates `entitlements.plist` with minimal entitlements -- **Both**: Creates both files (recommended) -- **App Store**: Creates sandboxed entitlements for Mac App Store -- **Custom**: Choose individual entitlements and target file - -### wails3 sign - -Sign binaries and packages for the current or specified platform. This is a wrapper that calls the appropriate platform-specific signing task. - -```bash -wails3 sign -wails3 sign GOOS=darwin -wails3 sign GOOS=windows -wails3 sign GOOS=linux -``` - -This runs the corresponding `:sign` task which uses the signing configuration from your Taskfile. - -### wails3 tool sign - -Low-level command to sign a specific file directly. Used internally by the Taskfiles. - -```bash -wails3 tool sign [flags] -``` - -**Common Flags:** -| Flag | Description | -|------|-------------| -| `--input` | Path to the file to sign | -| `--output` | Output path (optional, defaults to in-place) | -| `--verbose` | Enable verbose output | - -**Windows/macOS Flags:** -| Flag | Description | -|------|-------------| -| `--certificate` | Path to PKCS#12 (.pfx/.p12) certificate | -| `--password` | Certificate password | -| `--timestamp` | Timestamp server URL | - -**macOS-Specific Flags:** -| Flag | Description | -|------|-------------| -| `--identity` | Signing identity (use '-' for ad-hoc) | -| `--entitlements` | Path to entitlements plist | -| `--hardened-runtime` | Enable hardened runtime (default: true) | -| `--notarize` | Submit for notarization | -| `--keychain-profile` | Keychain profile for notarization | - -**Windows-Specific Flags:** -| Flag | Description | -|------|-------------| -| `--thumbprint` | Certificate thumbprint in Windows store | -| `--description` | Application description | -| `--url` | Application URL | - -**Linux-Specific Flags:** -| Flag | Description | -|------|-------------| -| `--pgp-key` | Path to PGP private key | -| `--pgp-password` | PGP key password | -| `--role` | DEB signing role (origin/maint/archive/builder) | - -### wails3 signing info - -Display signing capabilities on the current system. - -```bash -wails3 signing info -``` - -### wails3 signing list - -List available signing identities. - -```bash -wails3 signing list -``` - -### wails3 signing credentials - -Store notarization credentials in keychain (macOS only). - -```bash -wails3 signing credentials [flags] - -Flags: - --apple-id Apple ID email - --team-id Apple Developer Team ID - --password App-specific password - --profile Keychain profile name -``` - -### wails3 signing generate-key - -Generate a PGP key pair for Linux package signing. - -```bash -wails3 signing generate-key [flags] - -Flags: - --name Name for the key (required) - --email Email for the key (required) - --comment Comment for the key - --bits Key size in bits (default: 4096) - --expiry Key expiry (e.g., "1y", "6m", "0" for never) - --password Password to encrypt private key - --output-private Path for private key output - --output-public Path for public key output -``` - -### wails3 signing key-info - -Display information about a PGP key. - -```bash -wails3 signing key-info --key -``` - -## Troubleshooting - -### macOS Issues - -**"No Developer ID certificate found"** -- Ensure your certificate is installed in the Keychain -- Check it hasn't expired with `wails3 signing list` -- Make sure you have a "Developer ID Application" certificate (not just "Apple Development") - -**"Notarization failed"** -- Check the notarization log: `xcrun notarytool log --keychain-profile ` -- Ensure hardened runtime is enabled -- Verify your app doesn't include unsigned binaries - -**"Codesign failed"** -- Make sure the keychain is unlocked: `security unlock-keychain` -- Check file permissions on the app bundle - -### Windows Issues - -**"Certificate not found"** -- Verify the certificate path is correct -- Check the certificate password -- Ensure the certificate is valid (not expired or revoked) - -**"Timestamp server error"** -- Try a different timestamp server: - - `http://timestamp.digicert.com` - - `http://timestamp.sectigo.com` - - `http://timestamp.comodoca.com` - -### Linux Issues - -**"Invalid PGP key"** -- Ensure the key file is in ASCII-armored format -- Check the key hasn't expired with `wails3 signing key-info` -- Verify the password is correct - -**"Signature verification failed"** -- Ensure the public key is properly imported -- Check that the package wasn't modified after signing - -## Additional Resources - -### Official Documentation -- [Apple Code Signing Guide](https://developer.apple.com/support/code-signing/) -- [Apple Notarization Documentation](https://developer.apple.com/documentation/security/notarizing_macos_software_before_distribution) -- [Microsoft Code Signing](https://docs.microsoft.com/en-us/windows-hardware/drivers/dashboard/get-a-code-signing-certificate) -- [Debian Package Signing](https://wiki.debian.org/SecureApt) -- [RPM Package Signing](https://rpm-software-management.github.io/rpm/manual/signatures.html) diff --git a/docs/src/content/docs/guides/build/windows.mdx b/docs/src/content/docs/guides/build/windows.mdx deleted file mode 100644 index fe4183cb4..000000000 --- a/docs/src/content/docs/guides/build/windows.mdx +++ /dev/null @@ -1,124 +0,0 @@ ---- -title: Windows Packaging -description: Package your Wails application for Windows distribution -sidebar: - order: 3 ---- - -import { Aside } from '@astrojs/starlight/components'; - -## NSIS Installer - -The default packaging format creates an NSIS installer: - -```bash -wails3 package GOOS=windows -``` - -This runs `wails3 task windows:package` which: -1. Builds the application -2. Generates the WebView2 bootstrapper -3. Creates an NSIS installer - -Output: `build/windows/nsis/-installer.exe` - -### MSIX Package - -For Microsoft Store distribution or modern Windows deployment: - -```bash -wails3 package GOOS=windows FORMAT=msix -``` - -Output: `bin/-.msix` - - - -## Customizing the Installer - -NSIS configuration is in `build/windows/nsis/project.nsi`. Edit this file to customize: - -- Installer UI and branding -- Installation directory -- Start menu and desktop shortcuts -- File associations -- License agreement - -Application metadata comes from `build/windows/info.json`: - -```json -{ - "fixed": { - "file_version": "1.0.0" - }, - "info": { - "0000": { - "ProductVersion": "1.0.0", - "CompanyName": "My Company", - "FileDescription": "My Application", - "ProductName": "MyApp" - } - } -} -``` - -## Code Signing - -Sign your executable and installer to avoid SmartScreen warnings: - -```bash -# Using the wrapper (auto-detects platform) -wails3 sign GOOS=windows - -# Or using tasks directly -wails3 task windows:sign -wails3 task windows:sign:installer -``` - -Configure signing in `build/windows/Taskfile.yml`: - -```yaml -vars: - SIGN_CERTIFICATE: "path/to/certificate.pfx" - # Or use thumbprint for certificates in Windows store - SIGN_THUMBPRINT: "certificate-thumbprint" - TIMESTAMP_SERVER: "http://timestamp.digicert.com" -``` - -Store your certificate password securely: - -```bash -wails3 setup signing -``` - -See [Signing Applications](/guides/build/signing) for details. - -## Building for ARM - -```bash -wails3 build GOOS=windows GOARCH=arm64 -wails3 package GOOS=windows GOARCH=arm64 -``` - -## Troubleshooting - -### makensis not found - -Install NSIS: - -```bash -# Windows -winget install NSIS.NSIS - -# Or download from https://nsis.sourceforge.io/ -``` - -### SmartScreen warning - -Your executable isn't signed. See [Code Signing](#code-signing) above. - -### WebView2 missing - -The installer includes a WebView2 bootstrapper that downloads the runtime if needed. If you need offline installation, download the Evergreen Standalone Installer from Microsoft. diff --git a/docs/src/content/docs/guides/cli.mdx b/docs/src/content/docs/guides/cli.mdx deleted file mode 100644 index fb9f23969..000000000 --- a/docs/src/content/docs/guides/cli.mdx +++ /dev/null @@ -1,539 +0,0 @@ ---- -title: CLI Reference -description: Complete reference for the Wails CLI commands -sidebar: - order: 1 ---- - -The Wails CLI provides a comprehensive set of commands to help you develop, build, and maintain your Wails applications. - -## Core Commands - -Core commands are the primary commands used for project creation, development, and building. - -All CLI commands are of the following format: `wails3 `. - -### `init` -Initializes a new Wails project. During this initialization, the `go mod tidy` command is run to bring the project packages up to date. This can be bypassed by using the `-skipgomodtidy` flag with the `init` command. - -```bash -wails3 init [flags] -``` - -#### Flags -| Flag | Description | Default | -|-----------------------|----------------------|--------------------------| -| `-p` | Package name | `main` | -| `-t` | Template name or URL | `vanilla` | -| `-n` | Project name | | -| `-d` | Project directory | `.` | -| `-q` | Suppress output | `false` | -| `-l` | List templates | `false` | -| `-git` | Git repository URL | | -| `-productname` | Product name | `My Product` | -| `-productdescription` | Product description | `My Product Description` | -| `-productversion` | Product version | `0.1.0` | -| `-productcompany` | Company name | `My Company` | -| `-productcopyright` | Copyright notice | ` now, My Company` | -| `-productcomments` | File comments | `This is a comment` | -| `-productidentifier` | Product identifier | | -| `-skipgomodtidy` | Skip go mod tidy | `false` | - -The `-git` flag accepts various Git URL formats: -- HTTPS: `https://github.com/username/project` -- SSH: `git@github.com:username/project` or `ssh://git@github.com/username/project` -- Git protocol: `git://github.com/username/project` -- Filesystem: `file:///path/to/project.git` - -When provided, this flag will: -1. Initialize a git repository in the project directory -2. Set the specified URL as the remote origin -3. Update the module name in `go.mod` to match the repository URL -4. Add all files - -### `dev` -Runs the application in development mode. This will give you a live view of your frontend code, and you can make changes and see them reflected -in the running application without having to rebuild the entire application. Changes to your Go code will also be detected and the application -will automatically rebuild and relaunch. - -```bash -wails3 dev [flags] -``` - -#### Flags -| Flag | Description | Default | -|-----------|----------------------|----------------------| -| `-config` | Config file path | `./build/config.yml` | -| `-port` | Vite dev server port | `9245` | -| `-s` | Enable HTTPS | `false` | - - - :::note - This is equivalent to running `wails3 task dev` and runs the `dev` task in the project's main Taskfile. You can customise this by editing the `Taskfile.yml` file. - ::: - - -### `build` -Builds a debug version of your application. It defaults to building for the current platform and architecture. - -```bash -wails3 build [CLI variables...] -``` - -You can pass CLI variables to customize the build: -```bash -wails3 build PLATFORM=linux CONFIG=production -``` - - :::note - This is equivalent to running `wails3 task build` which runs the `build` task in the project's main Taskfile. Any CLI variables passed to `build` are forwarded to the underlying task. You can customise the build process by editing the `Taskfile.yml` file. - ::: - -### `package` - -Creates platform-specific packages for distribution. - -```bash -wails3 package [CLI variables...] -``` - -You can pass CLI variables to customize the packaging: -```bash -wails3 package VERSION=2.0.0 OUTPUT=myapp.pkg -``` - -#### Package Types - -The following package types are available for each platform: - -| Platform | Package Type | -|----------|-------------------------------------------| -| Windows | `.exe` | -| macOS | `.app`, | -| Linux | `.AppImage`, `.deb`, `.rpm`, `.archlinux` | - - :::note - This is equivalent to `wails3 task package` which runs the `package` task in the project's main Taskfile. Any CLI variables passed to `package` are forwarded to the underlying task. You can customise the packaging process by editing the `Taskfile.yml` file. - ::: - - -### `task` -Runs tasks defined in your project's Taskfile.yml. This is an embedded version of [Taskfile](https://taskfile.dev) that allows you to define and run custom build, test, and deployment tasks. - -```bash -wails3 task [taskname] [CLI variables...] [flags] -``` - -#### CLI Variables -You can pass variables to tasks in the format `KEY=VALUE`: -```bash -wails3 task build PLATFORM=linux CONFIG=production -wails3 task deploy ENV=staging VERSION=1.2.3 -``` - -These variables can be accessed in your Taskfile.yml using Go template syntax: -```yaml -tasks: - build: - cmds: - - echo "Building for {{.PLATFORM | default "darwin"}}" - - echo "Config: {{.CONFIG | default "debug"}}" -``` - -#### Flags -| Flag | Description | Default | -|--------------|-------------------------------------------|----------| -| `-h` | Shows Task usage | `false` | -| `-i` | Creates a new Taskfile.yml | `false` | -| `-list` | Lists tasks with descriptions | `false` | -| `-list-all` | Lists all tasks (with or without descriptions) | `false` | -| `-json` | Formats task list as JSON | `false` | -| `-status` | Exits with non-zero if task is not up-to-date | `false` | -| `-f` | Forces execution even when task is up-to-date | `false` | -| `-w` | Enables watch mode for the given task | `false` | -| `-v` | Enables verbose mode | `false` | -| `-version` | Prints Task version | `false` | -| `-s` | Disables echoing | `false` | -| `-p` | Executes tasks in parallel | `false` | -| `-dry` | Compiles and prints tasks without executing | `false` | -| `-summary` | Shows summary about a task | `false` | -| `-x` | Pass-through the exit code of the task | `false` | -| `-dir` | Sets directory of execution | | -| `-taskfile` | Choose which Taskfile to run | | -| `-output` | Sets output style: [interleaved|group|prefixed] | | -| `-c` | Colored output (enabled by default) | `true` | -| `-C` | Limit number of tasks to run concurrently | | -| `-interval` | Interval to watch for changes (in seconds) | | - -#### Examples -```bash -# Run the default task -wails3 task - -# Run a specific task -wails3 task test - -# Run a task with variables -wails3 task build PLATFORM=windows ARCH=amd64 - -# List all available tasks -wails3 task --list - -# Run multiple tasks in parallel -wails3 task -p task1 task2 task3 - -# Watch for changes and re-run task -wails3 task -w dev -``` - -### `doctor` -Performs a system check and displays a status report. - -```bash -wails3 doctor -``` - -## Generate Commands - -Generate commands help create various project assets like bindings, icons, and build files. All generate commands use the base command: `wails3 generate `. - -### `generate bindings` -Generates bindings and models for your Go code. - -```bash -wails3 generate bindings [flags] [patterns...] -``` - -#### Flags -| Flag | Description | Default | -|-------------|---------------------------|---------------------| -| `-f` | Additional Go build flags | | -| `-d` | Output directory | `frontend/bindings` | -| `-models` | Models filename | `models` | -| `-index` | Index filename | `index` | -| `-ts` | Generate TypeScript | `false` | -| `-i` | Use TS interfaces | `false` | -| `-b` | Use bundled runtime | `false` | -| `-names` | Use names instead of IDs | `false` | -| `-noindex` | Skip index files | `false` | -| `-dry` | Dry run | `false` | -| `-silent` | Silent mode | `false` | -| `-v` | Debug output | `false` | -| `-clean` | Clean output directory | `false` | - -### `generate build-assets` -Generates build assets for your application. - -```bash -wails3 generate build-assets [flags] -``` - -#### Flags -| Flag | Description | Default | -|----------------|---------------------|--------------------| -| `-name` | Project name | | -| `-dir` | Output directory | `build` | -| `-silent` | Suppress output | `false` | -| `-company` | Company name | | -| `-productname` | Product name | | -| `-description` | Product description | | -| `-version` | Product version | | -| `-identifier` | Product identifier | `com.wails.[name]` | -| `-copyright` | Copyright notice | | -| `-comments` | File comments | | - -### `generate icons` -Generates application icons. - -```bash -wails3 generate icons [flags] -``` - -#### Flags -| Flag | Description | Default | -|--------------------|------------------------------|-----------------------| -| `-input` | Input PNG file | Required | -| `-windowsfilename` | Windows output filename | | -| `-macfilename` | macOS output filename | | -| `-sizes` | Icon sizes (comma-separated) | `256,128,64,48,32,16` | -| `-example` | Generate example icon | `false` | - -### `generate syso` -Generates Windows .syso file. - -```bash -wails3 generate syso [flags] -``` - -#### Flags -| Flag | Description | Default | -|-------------|---------------------------|----------------------------| -| `-manifest` | Path to manifest file | Required | -| `-icon` | Path to icon file | Required | -| `-info` | Path to version info file | | -| `-arch` | Target architecture | Current GOARCH | -| `-out` | Output filename | `rsrc_windows_[arch].syso` | - -### `generate .desktop` -Generates a Linux .desktop file. - -```bash -wails3 generate .desktop [flags] -``` - -#### Flags -| Flag | Description | Default | -|------------------|---------------------------|------------------| -| `-name` | Application name | Required | -| `-exec` | Executable path | Required | -| `-icon` | Icon path | | -| `-categories` | Application categories | `Utility` | -| `-comment` | Application comment | | -| `-terminal` | Run in terminal | `false` | -| `-keywords` | Search keywords | | -| `-version` | Application version | | -| `-genericname` | Generic name | | -| `-startupnotify` | Show startup notification | `false` | -| `-mimetype` | Supported MIME types | | -| `-output` | Output filename | `[name].desktop` | - -### `generate runtime` -Generates the pre-built version of the runtime. - -```bash -wails3 generate runtime -``` - -### `generate constants` -Generates JavaScript constants from Go code. - -```bash -wails3 generate constants -``` - -### `generate appimage` -Generates a Linux AppImage. - -```bash -wails3 generate appimage [flags] -``` - -#### Flags -| Flag | Description | Default | -|-------------|-----------------------|----------------| -| `-binary` | Path to binary | Required | -| `-icon` | Path to icon file | Required | -| `-desktop` | Path to .desktop file | Required | -| `-builddir` | Build directory | Temp directory | -| `-output` | Output directory | `.` | - -Base command: `wails3 service` - -## Service Commands - -Service commands help manage Wails services. All service commands use the base command: `wails3 service `. - -### `service init` -Initializes a new service. - -```bash -wails3 service init [flags] -``` - -#### Flags -| Flag | Description | Default | -|------|---------------------|-------------------| -| `-n` | Service name | `example_service` | -| `-d` | Service description | `Example service` | -| `-p` | Package name | | -| `-o` | Output directory | `.` | -| `-q` | Suppress output | `false` | -| `-a` | Author name | | -| `-v` | Version | | -| `-w` | Website URL | | -| `-r` | Repository URL | | -| `-l` | License | | - -Base command: `wails3 tool` - -## Tool Commands - -Tool commands provide utilities for development and debugging. All tool commands use the base command: `wails3 tool `. - -### `tool checkport` -Checks if a port is open. Useful for testing if vite is running. - -```bash -wails3 tool checkport [flags] -``` - -#### Flags -| Flag | Description | Default | -|---------|---------------|-------------| -| `-port` | Port to check | `9245` | -| `-host` | Host to check | `localhost` | - -### `tool watcher` -Watches files and runs a command when they change. - -```bash -wails3 tool watcher [flags] -``` - -#### Flags -| Flag | Description | Default | -|------------|---------------------|----------------------| -| `-config` | Config file path | `./build/config.yml` | -| `-ignore` | Patterns to ignore | | -| `-include` | Patterns to include | | - -### `tool cp` -Copies files. - -```bash -wails3 tool cp -``` - -### `tool buildinfo` -Shows build information about the application. - -```bash -wails3 tool buildinfo -``` - -### `tool version` -Bumps a semantic version based on the provided flags. - -```bash -wails3 tool version [flags] -``` - -#### Flags -| Flag | Description | Default | -|---------------|--------------------------------------------------|---------| -| `-v` | Current version to bump | | -| `-major` | Bump major version | `false` | -| `-minor` | Bump minor version | `false` | -| `-patch` | Bump patch version | `false` | -| `-prerelease` | Bump prerelease version (e.g., alpha.5 to alpha.6) | `false` | - -The command follows the precedence order: major > minor > patch > prerelease. It preserves the "v" prefix if present in the input version, as well as any prerelease and metadata components. - -Example usage: -```bash -wails3 tool version -v 1.2.3 -major # Output: 2.0.0 -wails3 tool version -v v1.2.3 -minor # Output: v1.3.0 -wails3 tool version -v 1.2.3-alpha -patch # Output: 1.2.4-alpha -wails3 tool version -v v3.0.0-alpha.5 -prerelease # Output: v3.0.0-alpha.6 -``` - -### `tool package` -Generates Linux packages (deb, rpm, archlinux). - -```bash -wails3 tool package [flags] -``` - -#### Flags -| Flag | Description | Default | -|-----------|--------------------------------------|----------| -| `-format` | Package format (deb, rpm, archlinux) | `deb` | -| `-name` | Executable name | Required | -| `-config` | Config file path | Required | -| `-out` | Output directory | `.` | - -#### Flags -| Flag | Description | Default | -|-----------|--------------------------------------|---------| -| `-format` | Package format (deb, rpm, archlinux) | `deb` | -| `-name` | Executable name | `myapp` | -| `-config` | Config file path | | -| `-out` | Output directory | `.` | - -Base command: `wails3 update` - -## Update Commands - -Update commands help manage and update project assets. All update commands use the base command: `wails3 update `. - -### `update cli` -Updates the Wails CLI to a new version. - -```bash -wails3 update cli [flags] -``` - -#### Flags -| Flag | Description | Default | -|-------------|---------------------------------|---------| -| `-pre` | Update to latest pre-release | `false` | -| `-version` | Update to specific version | | -| `-nocolour` | Disable colored output | `false` | - -The update cli command allows you to update your Wails CLI installation. By default, it updates to the latest stable release. -You can use the `-pre` flag to update to the latest pre-release version, or specify a particular version using the `-version` flag. - -After updating, remember to update your project's go.mod file to use the same version: -```bash -require github.com/wailsapp/wails/v3 v3.x.x -``` - -### `update build-assets` -Updates the build assets using the given config file. - -```bash -wails3 update build-assets [flags] -``` - -#### Flags -| Flag | Description | Default | -|----------------|---------------------|---------| -| `-config` | Config file path | | -| `-dir` | Output directory | `build` | -| `-silent` | Suppress output | `false` | -| `-company` | Company name | | -| `-productname` | Product name | | -| `-description` | Product description | | -| `-version` | Product version | | -| `-identifier` | Product identifier | | -| `-copyright` | Copyright notice | | -| `-comments` | File comments | | - -Base command: `wails3` - -## Utility Commands - -Utility commands provide helpful shortcuts for common tasks. Use these commands directly with the base command: `wails3 `. - -### `docs` -Opens the Wails documentation in your default browser. - -```bash -wails3 docs -``` - -### `releasenotes` -Shows the release notes for the current or specified version. - -```bash -wails3 releasenotes [flags] -``` - -#### Flags -| Flag | Description | Default | -|------|-----------------------------------|---------| -| `-v` | Version to show release notes for | | -| `-n` | Disable colour output | `false` | - -### `version` -Prints the current version of Wails. - -```bash -wails3 version -``` - -### `sponsor` -Opens the Wails sponsorship page in your default browser. - -```bash -wails3 sponsor diff --git a/docs/src/content/docs/guides/custom-templates.mdx b/docs/src/content/docs/guides/custom-templates.mdx deleted file mode 100644 index 3da561b35..000000000 --- a/docs/src/content/docs/guides/custom-templates.mdx +++ /dev/null @@ -1,293 +0,0 @@ ---- -title: Creating Custom Templates -description: Learn how to create and customise your own Wails v3 templates -sidebar: - order: 50 ---- - -This guide will walk you through the process of creating a custom template for Wails v3. - -## Why would I make a custom template? - -Wails comes with a number of pre-configured templates that allow you to get your application up and running quickly. But if you need a more customised setup, you can create your own template to suit your needs. This can then be shared with the Wails community for others to use. - -### 1. Generating a Template - -To create a custom template, you can use the `wails generate template` command: - -```bash -wails3 generate template -name mytemplate -``` - -This will create a new directory called "mytemplate" in your current directory. - -The `wails3 generate template` command supports the following options: - -| Option | Description | Default | -|----------------|---------------------------------------------------|-------------------| -| `-name` | The name of your template (required) | - | -| `-frontend` | Path to an existing frontend directory to include | - | -| `-author` | The author of the template | - | -| `-description` | A description of the template | - | -| `-helpurl` | URL for template documentation | - | -| `-dir` | Directory to generate the template in | Current directory | -| `-version` | Template version | v0.0.1 | - -For example, to create a template with all options: - -```bash -wails3 generate template \ - -name "My Custom Template" \ - -frontend ./my-existing-frontend \ - -author "Your Name" \ - -description "A template with my preferred setup" \ - -helpurl "https://github.com/yourusername/template-docs" \ - -dir ./templates \ - -version "v1.0.0" -``` - - :::tip - Using the `-frontend` option will copy an existing web frontend project into the template. - ::: - -### 2. Configure Template Metadata - -If you didn't specify the template configuration when generating the template, you can update the `template.json` file in the template directory: - -```json5 -{ - "name": "Your Template Name", // Display name of your template - "shortname": "template-shortname", // Used when referencing your template - "author": "Your Name", // Template author - "description": "Template description", // Template description - "helpurl": "https://your-docs.com", // Documentation URL - "version": "v0.0.1", // Template version - "schema": 3 // Must be kept as 3 for Wails v3 -} -``` -:::caution -The `schema` field must remain set to `3` for compatibility with Wails v3. -::: - -### 3. Set Up Build Tasks - -In the `build` directory is `Taskfile.yml` where you can define your template's build process. -This file uses [Task](https://taskfile.dev) for build automation. The key steps are: - -```yaml -tasks: - install:frontend:deps: - summary: Install frontend dependencies - dir: frontend - sources: - - package.json - - package-lock.json - generates: - - node_modules/* - preconditions: - - sh: npm version - msg: "Looks like npm isn't installed. Npm is part of the Node installer: https://nodejs.org/en/download/" - cmds: - - npm install - - build:frontend: - summary: Build the frontend project - dir: frontend - sources: - - "**/*" - generates: - - dist/* - deps: - - task: install:frontend:deps - - task: generate:bindings - cmds: - - npm run build -q - - -``` - -### 4. Frontend Setup - -If you did not use `-frontend` when generating the template, you need to add frontend files to your template. - -There are a number of ways to set up your frontend: starting from scratch or using an existing framework. - -import { Tabs, TabItem } from '@astrojs/starlight/components'; - - - - If you want to start from scratch, you can create your frontend project just like you would for any web application. - The `frontend` directory in your template is just a regular directory where you can set up your preferred - development environment. You might want to use build tools like Vite, webpack, or even just plain HTML, CSS, and - JavaScript - it's entirely up to you! - - For example, if you're using Vite, you could navigate to the `frontend` directory and run: - - ```bash - npm create vite@latest . - ``` - - Then follow the prompts to set up your project exactly how you want it. The key thing to remember is that this is just a regular frontend project - you can use any tools, frameworks, or libraries you're familiar with. - - - For this example, we'll use [Vite](https://vitejs.dev/) to set up a React frontend project: - - ```bash - npm create vite@latest frontend -- --template react - cd frontend - npm install - ``` - - - - - -Now you have the frontend files in place, update `common/Taskfile.yml` with the appropriate commands: - ```yaml - tasks: - install:frontend:deps: - summary: Install frontend dependencies - dir: frontend - sources: - - package.json - - package-lock.json - generates: - - node_modules/* - preconditions: - - sh: npm version - msg: "Looks like npm isn't installed. Npm is part of the Node installer: https://nodejs.org/en/download/" - cmds: - - npm install - - build:frontend: - summary: Build the frontend project - dir: frontend - sources: - - "**/*" - generates: - - dist/* - deps: - - task: install:frontend:deps - - task: generate:bindings - cmds: - - npm run build -q - ``` - - :::note - For this example, the default Tasks do not need updating as they use the standard `npm install` and `npm run build` commands. - ::: - -### 5. Configure the Go Application - -The default files in the template directory are sufficient to get users started. However, you may want to provide some additional functionality to demonstrate your template's capabilities. The best way to do this is to rename `main.go.tmpl` to `main.go` and edit it like any other Go file. Once finished, ensure you rename it back to `main.go.tmpl` before committing your changes. If you do not care about having a templated `main.go` file (the default template injests the project name into the `Name` field of the application), you can skip this step. - -#### Template Variables - -Wails uses Go's templating engine to process files with the `.tmpl` extension. During template generation, several variables are available for use in your template files: - -| Variable | Description | Example | -|----------------------|----------------------------------|-----------------------------------| -| `Name` | The name of the project | `"MyApp"` | -| `BinaryName` | The name of the generated binary | `"myapp"` | -| `ProductName` | The product name | `"My Application"` | -| `ProductDescription` | Description of the product | `"An awesome application"` | -| `ProductVersion` | Version of the product | `"1.0.0"` | -| `ProductCompany` | Company name | `"My Company Ltd"` | -| `ProductCopyright` | Copyright information | `"Copyright 2024 My Company Ltd"` | -| `ProductComments` | Additional product comments | `"Built with Wails"` | -| `ProductIdentifier` | Unique product identifier | `"com.mycompany.myapp"` | -| `Typescript` | Whether TypeScript is being used | `true` or `false` | -| `WailsVersion` | The version of Wails being used | `"3.0.0"` | - -You can use these variables in your template files using Go's template syntax: - -```go -// main.go.tmpl -package main - -import ( - "github.com/wailsapp/wails/v3/pkg/application" -) - -func main() { - app := application.New(application.Options{ - Name: "{{.ProductName}}", - Description: "{{.ProductDescription}}", - }) - // ... -} -``` - - :::tip - Templating can be applied to any file in your template, even html files, so long as the filename has `.tmpl` in its name. - ::: - -### 6. Testing Your Template - -To test your template: - -1. Generate a project using your template: `wails3 init -n testproject -t path/to/your/template` -2. Run `wails3 build` to generate the production build and make sure the binary in `bin` runs correctly -3. Run `wails3 dev` to start the development server. -4. Test that changes to the frontend code are reflected in the application. -5. Test that changes to the Go code rebuild and relaunch the application - -### 7. Sharing Your Template - -Once your template is ready, you can share it with the community by hosting it on GitHub. Here's how: - -1. Create a new GitHub repository for your template -2. Push your template code to the repository -3. Tag your releases using semantic versioning (e.g., v1.0.0) - -Users can then use your template directly from GitHub using the HTTPS URL: - -```bash -wails3 init -n myapp -t https://github.com/yourusername/your-template -``` - -You can also specify a particular version using the URL format: - -```bash -# Use a specific version tag -wails3 init -n myapp -t https://github.com/yourusername/your-template/releases/tag/v1.0.0 - -# Use a specific branch -wails3 init -n myapp -t https://github.com/yourusername/your-template/tree/main -``` - -To test your template before sharing: - -1. Push your changes to GitHub -2. Create a new test project using the HTTPS URL: - ```bash - wails3 init -n testapp -t https://github.com/yourusername/your-template - ``` -3. Verify that all files are correctly generated -4. Test the build and development workflow as described in the testing section - - :::note - Make sure your repository is public if you want others to use your template. - ::: - -For more information, visit the [Wails documentation](https://wails.io) - - -## Best Practices - -Let's talk about some key practices that will help make your template more useful and maintainable. Here are the main areas to focus on: - -1. **Make Your Template Easy to Understand** - - Write a clear, helpful README.md that gets users started quickly - - Add comments in your config files to explain the "why" behind your choices - - Show examples of common customisations - users love to see real-world use cases! - -2. **Keep Dependencies Happy** - - Stay on top of your frontend package updates - - Lock down specific versions in package.json to avoid surprises - - Let users know upfront what they'll need to have installed - -3. **Love Your Template** - - Keep it fresh with regular updates - - Give it a thorough test drive before sharing - - Share it with the Wails community - we'd love to see what you create! diff --git a/docs/src/content/docs/guides/custom-transport.mdx b/docs/src/content/docs/guides/custom-transport.mdx deleted file mode 100644 index ef72302a4..000000000 --- a/docs/src/content/docs/guides/custom-transport.mdx +++ /dev/null @@ -1,172 +0,0 @@ ---- -title: Creating Custom Transport Layer -description: Learn how to create and customize your own Wails v3 custom IPC transport layer -sidebar: - order: 51 ---- - -Wails v3 allows you to provide a custom IPC transport layer while retaining all generated bindings and event communication. This enables you to replace the default HTTP fetch-based transport with WebSockets, custom protocols, or any other transport mechanism. - -## Overview - -By default, Wails uses HTTP fetch requests from the frontend to communicate with the backend via `/wails/runtime`. The custom transport API allows you to: - -- Replace the HTTP transport with WebSockets, gRPC, or any custom protocol -- Maintain full compatibility with Wails code generation -- Keep all existing bindings, events, dialogs, and other Wails features -- Implement your own connection management, authentication, and error handling - -## Architecture - -```text -┌─────────────────────────────────────────────────┐ -│ Frontend (TypeScript) │ -│ - Generated bindings still work │ -│ - Your custom client transport │ -└──────────────────┬──────────────────────────────┘ - │ - │ Your Protocol (WebSocket/etc) - │ -┌──────────────────▼──────────────────────────────┐ -│ Backend (Go) │ -│ - Your Transport implementation │ -│ - Wails MessageProcessor │ -│ - All existing Wails infrastructure │ -└─────────────────────────────────────────────────┘ -``` - -## Usage - -### 1. Implement the Transport Interface - -Create a custom transport by implementing the `Transport` interface: - -```go -package main - -import ( - "context" - "github.com/wailsapp/wails/v3/pkg/application" -) - -type MyCustomTransport struct { - // Your fields -} - -func (t *MyCustomTransport) Start(ctx context.Context, processor *application.MessageProcessor) error { - // Initialize your transport (WebSocket server, gRPC server, etc.) - // When you receive requests, call processor.HandleRuntimeCallWithIDs() - return nil -} - -func (t *MyCustomTransport) Stop() error { - // Clean up your transport - return nil -} -``` - -### 2. Configure Your Application - -Pass your custom transport to the application options: - -```go -func main() { - app := application.New(application.Options{ - Name: "My App", - Transport: &MyCustomTransport{}, - // ... other options - }) - - err := app.Run() - if err != nil { - log.Fatal(err) - } -} -``` - -### 3. Modify Frontend Runtime - -If using a custom transport, you'll need to modify the frontend runtime to use your transport instead of HTTP fetch. Implement `RuntimeTransport` interface that will be used to handle requests: - -```typescript -const { setTransport } = await import('/wails/runtime.js'); - -class MyRuntimeTransport { - call(objectID: number, method: number, windowName: string, args: any): Promise { - // TODO: implement IPC call with your transport protocol - - return resp; - } -} - -const myTransport = new MyRuntimeTransport(); -setTransport(myTransport); -``` - -## Notes - -- The default HTTP transport continues to work if no custom transport is specified -- Generated bindings remain unchanged - only the transport layer changes -- Events, dialogs, clipboard, and all other Wails features work transparently -- You're responsible for error handling, reconnection logic, and security in your custom transport -- The WebSocket example provided is for demonstration and may need hardening for production use - -## API Reference - -### Transport Interface - -```go -type Transport interface { - Start(ctx context.Context, messageProcessor *application.MessageProcessor) error - Stop() error -} -``` - -### AssetServerTransport Interface (Optional) - -For browser-based deployments or when you want to serve both assets and IPC through your custom transport, implement the `AssetServerTransport` interface: - -```go -type AssetServerTransport interface { - Transport - - // ServeAssets configures the transport to serve assets alongside IPC. - // The assetHandler is Wails' internal asset server that handles all assets, - // runtime.js, capabilities, flags, etc. - ServeAssets(assetHandler http.Handler) error -} -``` - -**When to implement this interface:** -- Running the app in a browser instead of a webview -- Serving assets over HTTP alongside your custom IPC transport -- Building network-accessible applications - -**Example implementation:** - -```go -func (t *MyTransport) ServeAssets(assetHandler http.Handler) error { - mux := http.NewServeMux() - - // Mount your IPC endpoint - mux.HandleFunc("/my/ipc/endpoint", t.handleIPC) - - // Mount Wails asset server for everything else - mux.Handle("/", assetHandler) - - // Start HTTP server - t.httpServer.Handler = mux - go t.httpServer.ListenAndServe() - - return nil -} -``` - -When `ServeAssets()` is called, the assetHandler provides: -- All static assets (HTML, CSS, JS, images, etc.) -- `/wails/runtime.js` - The Wails runtime library - -## See Also - -- `transport.go` - Core transport interfaces and types -- `messageprocessor.go` - The underlying message processor that handles all Wails IPC diff --git a/docs/src/content/docs/guides/customising-windows.mdx b/docs/src/content/docs/guides/customising-windows.mdx deleted file mode 100644 index 915439a28..000000000 --- a/docs/src/content/docs/guides/customising-windows.mdx +++ /dev/null @@ -1,129 +0,0 @@ ---- -title: Customising Windows in Wails -sidebar: - order: 10 ---- - -import {Badge} from '@astrojs/starlight/components'; - -Relevant Platforms: -
      - -Wails provides an API to control the appearance and functionality of the -controls of a window. This functionality is available on Windows and macOS, but -not on Linux. - -## Setting the Window Button States - -The button states are defined by the `ButtonState` enum: - -```go -type ButtonState int - -const ( - ButtonEnabled ButtonState = 0 - ButtonDisabled ButtonState = 1 - ButtonHidden ButtonState = 2 -) -``` - -- `ButtonEnabled`: The button is enabled and visible. -- `ButtonDisabled`: The button is visible but disabled (grayed out). -- `ButtonHidden`: The button is hidden from the titlebar. - -The button states can be set during window creation or at runtime. - -### Setting Button States During Window Creation - -When creating a new window, you can set the initial state of the buttons using -the `WebviewWindowOptions` struct: - -```go title="main.go" -package main - -import ( - "github.com/wailsapp/wails/v3/pkg/application" -) - -func main() { - app := application.New(application.Options{ - Name: "My Application", - }) - - app.Window.NewWithOptions(application.WebviewWindowOptions{ - MinimiseButtonState: application.ButtonHidden, - MaximiseButtonState: application.ButtonDisabled, - CloseButtonState: application.ButtonEnabled, - }) - - app.Run() -} -``` - -In the example above, the minimise button is hidden, the maximise button is -inactive (grayed out), and the close button is active. - -### Setting Button States at Runtime - -You can also change the button states at runtime using the following methods on -the `Window` interface: - -```go -window.SetMinimiseButtonState(wails.ButtonHidden) -window.SetMaximiseButtonState(wails.ButtonEnabled) -window.SetCloseButtonState(wails.ButtonDisabled) -``` - -### Platform Differences - -The button state functionality behaves slightly differently on Windows and -macOS: - -| | Windows | Mac | -|-----------------------|------------------------|------------------------| -| Disable Min/Max/Close | Disables Min/Max/Close | Disables Min/Max/Close | -| Hide Min | Disables Min | Hides Min button | -| Hide Max | Disables Max | Hides Max button | -| Hide Close | Hides all controls | Hides Close | - -Note: On Windows, it is not possible to hide the Min/Max buttons individually. -However, disabling both will hide both of the controls and only show the close -button. - -### Controlling Window Style (Windows) - -To control the style of the titlebar on Windows, you can use the `ExStyle` field -in the `WebviewWindowOptions` struct: - -Example: - -```go title="main.go" -package main - -import ( - "github.com/wailsapp/wails/v3/pkg/application" - "github.com/wailsapp/wails/v3/pkg/w32" -) - -func main() { - app := application.New(application.Options{ - Name: "My Application", - }) - - app.Window.NewWithOptions(application.WebviewWindowOptions{ - Windows: application.WindowsWindow{ - ExStyle: w32.WS_EX_TOOLWINDOW | w32.WS_EX_NOREDIRECTIONBITMAP | w32.WS_EX_TOPMOST, - }, - }) - - app.Run() -} -``` - -Other options that affect the Extended Style of a window will be overridden by -this setting: - -- HiddenOnTaskbar -- AlwaysOnTop -- IgnoreMouseEvents -- BackgroundType diff --git a/docs/src/content/docs/guides/distribution/auto-updates.mdx b/docs/src/content/docs/guides/distribution/auto-updates.mdx deleted file mode 100644 index 273915653..000000000 --- a/docs/src/content/docs/guides/distribution/auto-updates.mdx +++ /dev/null @@ -1,564 +0,0 @@ ---- -title: Auto-Updates -description: Implement automatic application updates with Wails v3 -sidebar: - order: 5 ---- - -import { Tabs, TabItem } from '@astrojs/starlight/components'; -import { Steps } from '@astrojs/starlight/components'; -import { Card, CardGrid } from '@astrojs/starlight/components'; -import { Aside } from '@astrojs/starlight/components'; - -# Automatic Updates - -Wails v3 provides a built-in updater system that supports automatic update checking, downloading, and installation. The updater includes support for binary delta updates (patches) for minimal download sizes. - - - - Configure periodic update checks in the background - - - Download only what changed with bsdiff patches - - - Works on macOS, Windows, and Linux - - - SHA256 checksums and optional signature verification - - - -## Quick Start - -Add the updater service to your application: - -```go title="main.go" -package main - -import ( - "github.com/wailsapp/wails/v3/pkg/application" - "time" -) - -func main() { - // Create the updater service - updater, err := application.CreateUpdaterService( - "1.0.0", // Current version - application.WithUpdateURL("https://updates.example.com/myapp/"), - application.WithCheckInterval(24 * time.Hour), - ) - if err != nil { - panic(err) - } - - app := application.New(application.Options{ - Name: "MyApp", - Services: []application.Service{ - application.NewService(updater), - }, - }) - - // ... rest of your app - app.Run() -} -``` - -Then use it from your frontend: - -```typescript title="App.tsx" -import { updater } from './bindings/myapp'; - -async function checkForUpdates() { - const update = await updater.CheckForUpdate(); - - if (update) { - console.log(`New version available: ${update.version}`); - console.log(`Release notes: ${update.releaseNotes}`); - - // Download and install - await updater.DownloadAndApply(); - } -} -``` - -## Configuration Options - -The updater supports various configuration options: - -```go -updater, err := application.CreateUpdaterService( - "1.0.0", - // Required: URL where update manifests are hosted - application.WithUpdateURL("https://updates.example.com/myapp/"), - - // Optional: Check for updates automatically every 24 hours - application.WithCheckInterval(24 * time.Hour), - - // Optional: Allow pre-release versions - application.WithAllowPrerelease(true), - - // Optional: Update channel (stable, beta, canary) - application.WithChannel("stable"), - - // Optional: Require signed updates - application.WithRequireSignature(true), - application.WithPublicKey("your-ed25519-public-key"), -) -``` - -## Update Manifest Format - -Host an `update.json` file on your server: - -```json title="update.json" -{ - "version": "1.2.0", - "release_date": "2025-01-15T00:00:00Z", - "release_notes": "## What's New\n\n- Feature A\n- Bug fix B", - "platforms": { - "macos-arm64": { - "url": "https://updates.example.com/myapp/myapp-1.2.0-macos-arm64.tar.gz", - "size": 12582912, - "checksum": "sha256:abc123...", - "patches": [ - { - "from": "1.1.0", - "url": "https://updates.example.com/myapp/patches/1.1.0-to-1.2.0-macos-arm64.patch", - "size": 14336, - "checksum": "sha256:def456..." - } - ] - }, - "macos-amd64": { - "url": "https://updates.example.com/myapp/myapp-1.2.0-macos-amd64.tar.gz", - "size": 13107200, - "checksum": "sha256:789xyz..." - }, - "windows-amd64": { - "url": "https://updates.example.com/myapp/myapp-1.2.0-windows-amd64.zip", - "size": 14680064, - "checksum": "sha256:ghi789..." - }, - "linux-amd64": { - "url": "https://updates.example.com/myapp/myapp-1.2.0-linux-amd64.tar.gz", - "size": 11534336, - "checksum": "sha256:jkl012..." - } - }, - "minimum_version": "1.0.0", - "mandatory": false -} -``` - -### Platform Keys - -| Platform | Key | -|----------|-----| -| macOS (Apple Silicon) | `macos-arm64` | -| macOS (Intel) | `macos-amd64` | -| Windows (64-bit) | `windows-amd64` | -| Linux (64-bit) | `linux-amd64` | -| Linux (ARM64) | `linux-arm64` | - -## Frontend API - -The updater exposes methods that are automatically bound to your frontend: - -### TypeScript Types - -```typescript -interface UpdateInfo { - version: string; - releaseDate: Date; - releaseNotes: string; - size: number; - patchSize?: number; - mandatory: boolean; - hasPatch: boolean; -} - -interface Updater { - // Get the current application version - GetCurrentVersion(): string; - - // Check if an update is available - CheckForUpdate(): Promise; - - // Download the update (emits progress events) - DownloadUpdate(): Promise; - - // Apply the downloaded update (restarts app) - ApplyUpdate(): Promise; - - // Download and apply in one call - DownloadAndApply(): Promise; - - // Get current state: idle, checking, available, downloading, ready, installing, error - GetState(): string; - - // Get the available update info - GetUpdateInfo(): UpdateInfo | null; - - // Get the last error message - GetLastError(): string; - - // Reset the updater state - Reset(): void; -} -``` - -### Progress Events - -Listen for download progress events: - -```typescript -import { Events } from '@wailsio/runtime'; - -Events.On('updater:progress', (data) => { - console.log(`Downloaded: ${data.downloaded} / ${data.total}`); - console.log(`Progress: ${data.percentage.toFixed(1)}%`); - console.log(`Speed: ${(data.bytesPerSecond / 1024 / 1024).toFixed(2)} MB/s`); -}); -``` - -## Complete Example - -Here's a complete example with a React component: - -```tsx title="UpdateChecker.tsx" -import { useState, useEffect } from 'react'; -import { updater } from './bindings/myapp'; -import { Events } from '@wailsio/runtime'; - -interface Progress { - downloaded: number; - total: number; - percentage: number; - bytesPerSecond: number; -} - -export function UpdateChecker() { - const [checking, setChecking] = useState(false); - const [updateInfo, setUpdateInfo] = useState(null); - const [downloading, setDownloading] = useState(false); - const [progress, setProgress] = useState(null); - const [error, setError] = useState(null); - - useEffect(() => { - // Listen for progress events - const cleanup = Events.On('updater:progress', (data: Progress) => { - setProgress(data); - }); - - // Check for updates on mount - checkForUpdates(); - - return () => cleanup(); - }, []); - - async function checkForUpdates() { - setChecking(true); - setError(null); - - try { - const info = await updater.CheckForUpdate(); - setUpdateInfo(info); - } catch (err) { - setError(err.message); - } finally { - setChecking(false); - } - } - - async function downloadAndInstall() { - setDownloading(true); - setError(null); - - try { - await updater.DownloadAndApply(); - // App will restart automatically - } catch (err) { - setError(err.message); - setDownloading(false); - } - } - - if (checking) { - return
      Checking for updates...
      ; - } - - if (error) { - return ( -
      -

      Error: {error}

      - -
      - ); - } - - if (!updateInfo) { - return ( -
      -

      You're up to date! (v{updater.GetCurrentVersion()})

      - -
      - ); - } - - if (downloading) { - return ( -
      -

      Downloading update...

      - {progress && ( -
      - -

      {progress.percentage.toFixed(1)}%

      -

      {(progress.bytesPerSecond / 1024 / 1024).toFixed(2)} MB/s

      -
      - )} -
      - ); - } - - return ( -
      -

      Update Available!

      -

      Version {updateInfo.version} is available

      -

      Size: {updateInfo.hasPatch - ? `${(updateInfo.patchSize / 1024).toFixed(0)} KB (patch)` - : `${(updateInfo.size / 1024 / 1024).toFixed(1)} MB`} -

      -
      - - -
      - ); -} -``` - -## Update Strategies - -### Check on Startup - -```go -func (a *App) OnStartup(ctx context.Context) { - // Check for updates after a short delay - go func() { - time.Sleep(5 * time.Second) - info, err := a.updater.CheckForUpdate() - if err == nil && info != nil { - // Emit event to frontend - application.Get().EmitEvent("update-available", info) - } - }() -} -``` - -### Background Checking - -Configure automatic background checks: - -```go -updater, _ := application.CreateUpdaterService( - "1.0.0", - application.WithUpdateURL("https://updates.example.com/myapp/"), - application.WithCheckInterval(6 * time.Hour), // Check every 6 hours -) -``` - -### Manual Check Menu Item - -```go -menu := application.NewMenu() -menu.Add("Check for Updates...").OnClick(func(ctx *application.Context) { - info, err := updater.CheckForUpdate() - if err != nil { - application.InfoDialog().SetMessage("Error checking for updates").Show() - return - } - if info == nil { - application.InfoDialog().SetMessage("You're up to date!").Show() - return - } - // Show update dialog... -}) -``` - -## Delta Updates (Patches) - -Delta updates (patches) allow users to download only the changes between versions, dramatically reducing download sizes. - -### How It Works - -1. When building a new version, generate patches from previous versions -2. Host patches alongside full updates on your server -3. The updater automatically downloads patches when available -4. If patching fails, it falls back to the full download - -### Generating Patches - -Patches are generated using the bsdiff algorithm. You'll need the `bsdiff` tool: - -```bash -# Install bsdiff (macOS) -brew install bsdiff - -# Install bsdiff (Ubuntu/Debian) -sudo apt-get install bsdiff - -# Generate a patch -bsdiff old-binary new-binary patch.bsdiff -``` - -### Patch File Naming - -Organize your patches in your update directory: - -``` -updates/ -├── update.json -├── myapp-1.2.0-macos-arm64.tar.gz -├── myapp-1.2.0-windows-amd64.zip -└── patches/ - ├── 1.0.0-to-1.2.0-macos-arm64.patch - ├── 1.1.0-to-1.2.0-macos-arm64.patch - ├── 1.0.0-to-1.2.0-windows-amd64.patch - └── 1.1.0-to-1.2.0-windows-amd64.patch -``` - - - -## Hosting Updates - -### Static File Hosting - -Updates can be hosted on any static file server: - -- **Amazon S3** / **Cloudflare R2** -- **Google Cloud Storage** -- **GitHub Releases** -- **Any CDN or web server** - -Example S3 bucket structure: - -``` -s3://my-updates-bucket/myapp/ -├── stable/ -│ ├── update.json -│ ├── myapp-1.2.0-macos-arm64.tar.gz -│ └── patches/ -│ └── 1.1.0-to-1.2.0-macos-arm64.patch -└── beta/ - └── update.json -``` - -### CORS Configuration - -If hosting on a different domain, configure CORS: - -```json -{ - "CORSRules": [ - { - "AllowedOrigins": ["*"], - "AllowedMethods": ["GET"], - "AllowedHeaders": ["*"] - } - ] -} -``` - -## Security - -### Checksum Verification - -All downloads are verified against SHA256 checksums in the manifest: - -```json -{ - "checksum": "sha256:e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" -} -``` - -### Signature Verification - -For additional security, enable signature verification: - - -1. **Generate a key pair**: - ```bash - # Generate Ed25519 key pair - openssl genpkey -algorithm Ed25519 -out private.pem - openssl pkey -in private.pem -pubout -out public.pem - ``` - -2. **Sign your update manifest**: - ```bash - openssl pkeyutl -sign -inkey private.pem -in update.json -out update.json.sig - ``` - -3. **Configure the updater**: - ```go - updater, _ := application.CreateUpdaterService( - "1.0.0", - application.WithUpdateURL("https://updates.example.com/myapp/"), - application.WithRequireSignature(true), - application.WithPublicKey("MCowBQYDK2VwAyEA..."), // Base64-encoded public key - ) - ``` - - -## Best Practices - -### Do - -- Test updates thoroughly before deploying -- Keep previous versions available for rollback -- Show release notes to users -- Allow users to skip non-mandatory updates -- Use HTTPS for all downloads -- Verify checksums before applying updates -- Handle errors gracefully - -### Don't - -- Force immediate restarts without warning -- Skip checksum verification -- Interrupt users during important work -- Delete the previous version immediately -- Ignore update failures - -## Troubleshooting - -### Update Not Found - -- Verify the manifest URL is correct -- Check the platform key matches (e.g., `macos-arm64`) -- Ensure the version in the manifest is newer - -### Download Fails - -- Check network connectivity -- Verify the download URL is accessible -- Check CORS configuration if cross-origin - -### Patch Fails - -- The updater automatically falls back to full download -- Ensure `bspatch` is available on the system -- Verify the patch checksum is correct - -### Application Won't Restart - -- On macOS, ensure the app is properly code-signed -- On Windows, check for file locks -- On Linux, verify file permissions - -## Next Steps - -- [Code Signing](/guides/build/signing) - Sign your updates -- [Creating Installers](/guides/installers) - Package your application -- [CI/CD Integration](/guides/ci-cd) - Automate your release process diff --git a/docs/src/content/docs/guides/distribution/custom-protocols.mdx b/docs/src/content/docs/guides/distribution/custom-protocols.mdx deleted file mode 100644 index 39a9b157c..000000000 --- a/docs/src/content/docs/guides/distribution/custom-protocols.mdx +++ /dev/null @@ -1,664 +0,0 @@ ---- -title: Custom URL Protocols -description: Register custom URL schemes to launch your application from links -sidebar: - order: 3 ---- - -import { Tabs, TabItem, Aside } from '@astrojs/starlight/components'; - -Custom URL protocols (also called URL schemes) allow your application to be launched when users click links with your custom protocol, such as `myapp://action` or `myapp://open/document`. - -## Overview - -Custom protocols enable: -- **Deep linking**: Launch your app with specific data -- **Browser integration**: Handle links from web pages -- **Email links**: Open your app from email clients -- **Inter-app communication**: Launch from other applications - -**Example**: `myapp://open/document?id=123` launches your app and opens document 123. - -## Configuration - -Define custom protocols in your application options: - -```go -package main - -import "github.com/wailsapp/wails/v3/pkg/application" - -func main() { - app := application.New(application.Options{ - Name: "My Application", - Description: "My awesome application", - Protocols: []application.Protocol{ - { - Scheme: "myapp", - Description: "My Application Protocol", - Role: "Editor", // macOS only - }, - }, - }) - - // Register handler for protocol events - app.Event.On(application.Events.ApplicationOpenedWithURL, func(event *application.ApplicationEvent) { - url := event.Context().ClickedURL() - handleCustomURL(url) - }) - - app.Run() -} - -func handleCustomURL(url string) { - // Parse and handle the custom URL - // Example: myapp://open/document?id=123 - println("Received URL:", url) -} -``` - -## Protocol Handler - -Listen for protocol events to handle incoming URLs: - -```go -app.Event.On(application.Events.ApplicationOpenedWithURL, func(event *application.ApplicationEvent) { - url := event.Context().ClickedURL() - - // Parse the URL - parsedURL, err := parseCustomURL(url) - if err != nil { - app.Logger.Error("Failed to parse URL:", err) - return - } - - // Handle different actions - switch parsedURL.Action { - case "open": - openDocument(parsedURL.DocumentID) - case "settings": - showSettings() - case "user": - showUser Profile(parsedURL.UserID) - default: - app.Logger.Warn("Unknown action:", parsedURL.Action) - } -}) -``` - -## URL Structure - -Design clear, hierarchical URL structures: - -``` -myapp://action/resource?param=value - -Examples: -myapp://open/document?id=123 -myapp://settings/theme?mode=dark -myapp://user/profile?username=john -``` - -**Best practices:** -- Use lowercase scheme names -- Keep schemes short and memorable -- Use hierarchical paths for resources -- Include query parameters for optional data -- URL-encode special characters - -## Platform Registration - -Custom protocols are registered differently on each platform. - - - - -### Windows NSIS Installer - -**Wails v3 automatically registers custom protocols** when using NSIS installers. - -#### Automatic Registration - -When you build your application with `wails3 build`, the NSIS installer: -1. Automatically registers all protocols defined in `application.Options.Protocols` -2. Associates protocols with your application executable -3. Sets up proper registry entries -4. Removes protocol associations during uninstall - -**No additional configuration required!** - -#### How It Works - -The NSIS template includes built-in macros: -- `wails.associateCustomProtocols` - Registers protocols during installation -- `wails.unassociateCustomProtocols` - Removes protocols during uninstall - -These macros are automatically called based on your `Protocols` configuration. - -#### Manual Registry (Advanced) - -If you need manual registration (outside NSIS): - -```batch -@echo off -REM Register custom protocol -REG ADD "HKEY_CURRENT_USER\SOFTWARE\Classes\myapp" /ve /d "URL:My Application Protocol" /f -REG ADD "HKEY_CURRENT_USER\SOFTWARE\Classes\myapp" /v "URL Protocol" /t REG_SZ /d "" /f -REG ADD "HKEY_CURRENT_USER\SOFTWARE\Classes\myapp\shell\open\command" /ve /d "\"%1\"" /f -``` - -#### Testing - -Test your protocol registration: - -```powershell -# Open protocol URL from PowerShell -Start-Process "myapp://test/action" - -# Or from command prompt -start myapp://test/action -``` - -### Windows MSIX Package - -Custom protocols are also automatically registered when using MSIX packaging. - -#### Automatic Registration - -When you build your application with MSIX, the manifest automatically includes protocol registrations from your `build/config.yml` protocols configuration. - -The generated manifest includes: - -```xml - - - My Application Protocol - - -``` - -#### Universal Links (Web-to-App Linking) - -Windows supports **Web-to-App linking**, which works similarly to Universal Links on macOS. When deploying your application as an MSIX package, you can enable HTTPS links to launch your app directly. - - - -To enable Web-to-App linking, follow the [Microsoft guide on web-to-app linking](https://learn.microsoft.com/en-us/windows/apps/develop/launch/web-to-app-linking). You'll need to: - -1. **Manually add App URI Handler to your MSIX manifest** (`build/windows/msix/app_manifest.xml`): - ```xml - - - - - - ``` - -2. **Configure `windows-app-web-link` on your website:** Host a `windows-app-web-link` file at `https://myawesomeapp.com/.well-known/windows-app-web-link`. This file should contain your app's package information and the paths it handles. - -When a Web-to-App link launches your application, you'll receive the same `ApplicationOpenedWithURL` event as with custom protocol schemes. - - - - - -### Info.plist Configuration - -On macOS, protocols are registered via your `Info.plist` file. - -#### Automatic Configuration - -Wails automatically generates the `Info.plist` with your protocols when you build with `wails3 build`. - -The protocols from `application.Options.Protocols` are added to: - -```xml -CFBundleURLTypes - - - CFBundleURLName - My Application Protocol - CFBundleURLSchemes - - myapp - - CFBundleTypeRole - Editor - - -``` - -#### Testing - -```bash -# Open protocol URL from terminal -open "myapp://test/action" - -# Check registered handlers -/System/Library/Frameworks/CoreServices.framework/Versions/A/Frameworks/LaunchServices.framework/Versions/A/Support/lsregister -dump | grep myapp -``` - -#### Universal Links - -In addition to custom protocol schemes, macOS also supports **Universal Links**, which allow your app to be launched by regular HTTPS links (e.g., `https://myawesomeapp.com/path`). Universal Links provide a seamless user experience between your web and desktop app. - - - -To enable Universal Links, follow the [Apple guide on supporting Universal Links in your app](https://developer.apple.com/documentation/xcode/supporting-universal-links-in-your-app). You'll need to: - -1. **Add entitlements** in your `entitlements.plist`: - ```xml - com.apple.developer.associated-domains - - applinks:myawesomeapp.com - - ``` - -2. **Add NSUserActivityTypes to Info.plist**: - ```xml - NSUserActivityTypes - - NSUserActivityTypeBrowsingWeb - - ``` - -3. **Configure `apple-app-site-association` on your website:** Host an `apple-app-site-association` file at `https://myawesomeapp.com/.well-known/apple-app-site-association`. - -When a Universal Link triggers your app, you'll receive the same `ApplicationOpenedWithURL` event, making the handling code identical to custom protocol schemes. - - - - - -### Desktop Entry - -On Linux, protocols are registered via `.desktop` files. - -#### Automatic Configuration - -Wails generates a desktop entry file with protocol handlers when you build with `wails3 build`. - -**Fixed in v3**: Linux desktop template now properly includes protocol handling. - -The generated desktop file includes: - -```ini -[Desktop Entry] -Type=Application -Name=My Application -Exec=/usr/bin/myapp %u -MimeType=x-scheme-handler/myapp; -``` - -#### Manual Registration - -If needed, manually install the desktop file: - -```bash -# Copy desktop file -cp myapp.desktop ~/.local/share/applications/ - -# Update desktop database -update-desktop-database ~/.local/share/applications/ - -# Register protocol handler -xdg-mime default myapp.desktop x-scheme-handler/myapp -``` - -#### Testing - -```bash -# Open protocol URL -xdg-open "myapp://test/action" - -# Check registered handler -xdg-mime query default x-scheme-handler/myapp -``` - - - - -## Complete Example - -Here's a complete example handling multiple protocol actions: - -```go -package main - -import ( - "fmt" - "net/url" - "strings" - "github.com/wailsapp/wails/v3/pkg/application" -) - -type App struct { - app *application.Application - window *application.WebviewWindow -} - -func main() { - app := application.New(application.Options{ - Name: "DeepLink Demo", - Description: "Custom protocol demonstration", - Protocols: []application.Protocol{ - { - Scheme: "deeplink", - Description: "DeepLink Demo Protocol", - Role: "Editor", - }, - }, - }) - - myApp := &App{app: app} - myApp.setup() - - app.Run() -} - -func (a *App) setup() { - // Create window - a.window = a.app.Window.NewWithOptions(application.WebviewWindowOptions{ - Title: "DeepLink Demo", - Width: 800, - Height: 600, - URL: "http://wails.localhost/", - }) - - // Handle custom protocol URLs - a.app.Event.On(application.Events.ApplicationOpenedWithURL, func(event *application.ApplicationEvent) { - customURL := event.Context().ClickedURL() - a.handleDeepLink(customURL) - }) -} - -func (a *App) handleDeepLink(rawURL string) { - // Parse URL - parsedURL, err := url.Parse(rawURL) - if err != nil { - a.app.Logger.Error("Failed to parse URL:", err) - return - } - - // Bring window to front - a.window.Show() - a.window.SetFocus() - - // Extract path and query - path := strings.Trim(parsedURL.Path, "/") - query := parsedURL.Query() - - // Handle different actions - parts := strings.Split(path, "/") - if len(parts) == 0 { - return - } - - action := parts[0] - - switch action { - case "open": - if len(parts) >= 2 { - resource := parts[1] - id := query.Get("id") - a.openResource(resource, id) - } - - case "settings": - section := "" - if len(parts) >= 2 { - section = parts[1] - } - a.openSettings(section) - - case "user": - if len(parts) >= 2 { - username := parts[1] - a.openUserProfile(username) - } - - default: - a.app.Logger.Warn("Unknown action:", action) - } -} - -func (a *App) openResource(resourceType, id string) { - fmt.Printf("Opening %s with ID: %s\n", resourceType, id) - // Emit event to frontend - a.app.Event.Emit("navigate", map[string]string{ - "type": resourceType, - "id": id, - }) -} - -func (a *App) openSettings(section string) { - fmt.Printf("Opening settings section: %s\n", section) - a.app.Event.Emit("navigate", map[string]string{ - "page": "settings", - "section": section, - }) -} - -func (a *App) openUserProfile(username string) { - fmt.Printf("Opening user profile: %s\n", username) - a.app.Event.Emit("navigate", map[string]string{ - "page": "user", - "user": username, - }) -} -``` - -## Frontend Integration - -Handle navigation events in your frontend: - -```javascript -import { Events } from '@wailsio/runtime' - -// Listen for navigation events from protocol handler -Events.On('navigate', (event) => { - const { type, id, page, section, user } = event.data - - if (type === 'document') { - // Open document with ID - router.push(`/document/${id}`) - } else if (page === 'settings') { - // Open settings - router.push(`/settings/${section}`) - } else if (page === 'user') { - // Open user profile - router.push(`/user/${user}`) - } -}) -``` - -## Security Considerations - -### Validate All Input - -Always validate and sanitize URLs from external sources: - -```go -func (a *App) handleDeepLink(rawURL string) { - // Parse URL - parsedURL, err := url.Parse(rawURL) - if err != nil { - a.app.Logger.Error("Invalid URL:", err) - return - } - - // Validate scheme - if parsedURL.Scheme != "myapp" { - a.app.Logger.Warn("Invalid scheme:", parsedURL.Scheme) - return - } - - // Validate path - path := strings.Trim(parsedURL.Path, "/") - if !isValidPath(path) { - a.app.Logger.Warn("Invalid path:", path) - return - } - - // Sanitize parameters - params := sanitizeQueryParams(parsedURL.Query()) - - // Process validated URL - a.processDeepLink(path, params) -} - -func isValidPath(path string) bool { - // Only allow alphanumeric and forward slashes - validPath := regexp.MustCompile(`^[a-zA-Z0-9/]+$`) - return validPath.MatchString(path) -} - -func sanitizeQueryParams(query url.Values) map[string]string { - sanitized := make(map[string]string) - for key, values := range query { - if len(values) > 0 { - // Take first value and sanitize - sanitized[key] = sanitizeString(values[0]) - } - } - return sanitized -} -``` - -### Prevent Injection Attacks - -Never execute URLs directly as code or SQL: - -```go -// ❌ DON'T: Execute URL content -func badHandler(url string) { - exec.Command("sh", "-c", url).Run() // DANGEROUS! -} - -// ✅ DO: Parse and validate -func goodHandler(url string) { - parsed, _ := url.Parse(url) - action := parsed.Query().Get("action") - - // Whitelist allowed actions - allowed := map[string]bool{ - "open": true, - "settings": true, - "help": true, - } - - if allowed[action] { - handleAction(action) - } -} -``` - -## Testing - -### Manual Testing - -Test protocol handlers during development: - -**Windows:** -```powershell -Start-Process "myapp://test/action?id=123" -``` - -**macOS:** -```bash -open "myapp://test/action?id=123" -``` - -**Linux:** -```bash -xdg-open "myapp://test/action?id=123" -``` - -### HTML Testing - -Create a test HTML page: - -```html - - - - Protocol Test - - -

      Custom Protocol Test Links

      - -
      - - -``` - -## Troubleshooting - -### Protocol Not Registered - -**Windows:** -- Check registry: `HKEY_CURRENT_USER\SOFTWARE\Classes\` -- Reinstall with NSIS installer -- Verify installer ran with proper permissions - -**macOS:** -- Rebuild application with `wails3 build` -- Check `Info.plist` in app bundle: `MyApp.app/Contents/Info.plist` -- Reset Launch Services: `/System/Library/Frameworks/CoreServices.framework/Frameworks/LaunchServices.framework/Support/lsregister -kill` - -**Linux:** -- Check desktop file: `~/.local/share/applications/myapp.desktop` -- Update database: `update-desktop-database ~/.local/share/applications/` -- Verify handler: `xdg-mime query default x-scheme-handler/myapp` - -### Application Not Launching - -**Check logs:** -```go -app := application.New(application.Options{ - Logger: application.NewLogger(application.LogLevelDebug), - // ... -}) -``` - -**Common issues:** -- Application not installed in expected location -- Executable path in registration doesn't match actual location -- Permissions issues - -## Best Practices - -### ✅ Do - -- **Use descriptive scheme names** - `mycompany-myapp` instead of `mca` -- **Validate all input** - Never trust URLs from external sources -- **Handle errors gracefully** - Log invalid URLs, don't crash -- **Provide user feedback** - Show what action was triggered -- **Test on all platforms** - Protocol handling varies -- **Document your URL structure** - Help users and integrators - -### ❌ Don't - -- **Don't use common scheme names** - Avoid `http`, `file`, `app`, etc. -- **Don't execute URLs as code** - Huge security risk -- **Don't expose sensitive operations** - Require confirmation for destructive actions -- **Don't assume protocols work everywhere** - Have fallback mechanisms -- **Don't forget URL encoding** - Handle special characters properly - -## Next Steps - -- [Windows Packaging](/guides/build/windows) - Learn about NSIS installer options -- [File Associations](/guides/distribution/file-associations) - Open files with your app -- [Single Instance](/guides/distribution/single-instance) - Prevent multiple app instances - ---- - -**Questions?** Ask in [Discord](https://discord.gg/JDdSxwjhGf) or check the [examples](https://github.com/wailsapp/wails/tree/v3-alpha/v3/examples). diff --git a/docs/src/content/docs/guides/e2e-testing.mdx b/docs/src/content/docs/guides/e2e-testing.mdx deleted file mode 100644 index f461afa2e..000000000 --- a/docs/src/content/docs/guides/e2e-testing.mdx +++ /dev/null @@ -1,173 +0,0 @@ ---- -title: End-to-End Testing -description: Test complete user workflows -sidebar: - order: 6 ---- - -## Overview - -End-to-end testing validates complete user workflows in your application. - -## Using Playwright - -### Setup - -```bash -# Install Playwright -npm install -D @playwright/test - -# Initialize -npx playwright install -``` - -### Configuration - -```javascript -// playwright.config.js -import { defineConfig } from '@playwright/test' - -export default defineConfig({ - testDir: './e2e', - use: { - baseURL: 'http://localhost:34115', // Wails dev server - }, -}) -``` - -### Writing Tests - -```javascript -// e2e/app.spec.js -import { test, expect } from '@playwright/test' - -test('create note', async ({ page }) => { - await page.goto('/') - - // Click new note button - await page.click('#new-note-btn') - - // Fill in title - await page.fill('#note-title', 'Test Note') - - // Fill in content - await page.fill('#note-content', 'Test content') - - // Verify note appears in list - await expect(page.locator('.note-item')).toContainText('Test Note') -}) - -test('delete note', async ({ page }) => { - await page.goto('/') - - // Create a note first - await page.click('#new-note-btn') - await page.fill('#note-title', 'To Delete') - - // Delete it - await page.click('#delete-btn') - - // Confirm dialog - page.on('dialog', dialog => dialog.accept()) - - // Verify it's gone - await expect(page.locator('.note-item')).not.toContainText('To Delete') -}) -``` - -## Testing dialogs - -```javascript -test('file save dialog', async ({ page }) => { - await page.goto('/') - - // Intercept file dialog - page.on('filechooser', async (fileChooser) => { - await fileChooser.setFiles('/path/to/test/file.json') - }) - - // Trigger save - await page.click('#save-btn') - - // Verify success message - await expect(page.locator('.success-message')).toBeVisible() -}) -``` - -## Testing Window Behaviour - -```javascript -test('window state', async ({ page }) => { - await page.goto('/') - - // Test window title - await expect(page).toHaveTitle('My App') - - // Test window size - const size = await page.viewportSize() - expect(size.width).toBe(800) - expect(size.height).toBe(600) -}) -``` - -## Best Practices - -### ✅ Do - -- Test critical user flows -- Use data-testid attributes -- Clean up test data -- Run tests in CI/CD -- Test error scenarios -- Keep tests independent - -### ❌ Don't - -- Don't test implementation details -- Don't write brittle selectors -- Don't skip cleanup -- Don't ignore flaky tests -- Don't test everything - -## Running E2E Tests - -```bash -# Run all tests -npx playwright test - -# Run in headed mode -npx playwright test --headed - -# Run specific test -npx playwright test e2e/app.spec.js - -# Debug mode -npx playwright test --debug -``` - -## CI/CD Integration - -```yaml -# .github/workflows/e2e.yml -name: E2E Tests - -on: [push] - -jobs: - test: - runs-on: ubuntu-latest - steps: - - uses: actions/checkout@v3 - - uses: actions/setup-node@v3 - - name: Install dependencies - run: npm ci - - name: Install Playwright - run: npx playwright install --with-deps - - name: Run tests - run: npx playwright test -``` - -## Next Steps - -- [Testing](/guides/testing) - Learn unit testing -- [Building](/guides/building) - Build your application diff --git a/docs/src/content/docs/guides/events-reference.mdx b/docs/src/content/docs/guides/events-reference.mdx deleted file mode 100644 index afa61fc3e..000000000 --- a/docs/src/content/docs/guides/events-reference.mdx +++ /dev/null @@ -1,569 +0,0 @@ ---- -title: Events Guide -description: A practical guide to using events in Wails v3 for application communication and lifecycle management ---- - -**NOTE: This guide is a work in progress** - -# Events Guide - -Events are the heartbeat of communication in Wails applications. They allow different parts of your application to talk to each other without being tightly coupled. This guide will walk you through everything you need to know about using events effectively in your Wails application. - -## Understanding Wails Events - -Think of events as messages that get broadcast throughout your application. Any part of your application can listen for these messages and react accordingly. This is particularly useful for: - -- **Responding to window changes**: Know when your window is minimized, maximized, or moved -- **Handling system events**: React to theme changes or power events -- **Custom application logic**: Create your own events for features like data updates or user actions -- **Cross-component communication**: Let different parts of your app communicate without direct dependencies - -## Event Naming Convention - -All Wails events follow a namespace pattern to clearly indicate their origin: - -- `common:` - Cross-platform events that work on Windows, macOS, and Linux -- `windows:` - Windows-specific events -- `mac:` - macOS-specific events -- `linux:` - Linux-specific events - -For example: -- `common:WindowFocus` - Window gained focus (works everywhere) -- `windows:APMSuspend` - System is suspending (Windows only) -- `mac:ApplicationDidBecomeActive` - App became active (macOS only) - -## Getting Started with Events - -### Listening to Events (Frontend) - -The most common use case is listening for events in your frontend code: - -```javascript -import { Events } from '@wailsio/runtime'; - -// Listen for when the window gains focus -Events.On('common:WindowFocus', () => { - console.log('Window is now focused!'); - // Maybe refresh some data or resume animations -}); - -// Listen for theme changes -Events.On('common:ThemeChanged', (event) => { - console.log('Theme changed:', event.data); - // Update your app's theme accordingly -}); - -// Listen for custom events from your Go backend -Events.On('my-app:data-updated', (event) => { - console.log('Data updated:', event.data); - // Update your UI with the new data -}); -``` - -### Emitting Events (Backend) - -From your Go code, you can emit events that your frontend can listen to: - -```go -package main - -import ( - "github.com/wailsapp/wails/v3/pkg/application" - "time" -) - -func (s *Service) UpdateData() { - // Do some data processing... - - // Notify the frontend - app := application.Get() - app.Event.Emit("my-app:data-updated", - map[string]interface{}{ - "timestamp": time.Now(), - "count": 42, - }, - ) -} -``` - -### Emitting Events (Frontend) - -While not as commonly used, you can also emit events from your frontend that your Go code can listen to: - -```javascript -import { Events } from '@wailsio/runtime'; - -// Event without data -Events.Emit('myapp:close-window') - -// Event with data -Events.Emit('myapp:disconnect-requested', 'id-123') -``` - -If you are using TypeScript in your frontend and [registering typed events](#typed-events-with-typecheck) in your Go code, you will get event name autocomplete/checking and data type checking. - -### Removing Event Listeners - -Always clean up your event listeners when they're no longer needed: - -```javascript -import { Events } from '@wailsio/runtime'; - -// Store the handler reference -const focusHandler = () => { - console.log('Window focused'); -}; - -// Add the listener -Events.On('common:WindowFocus', focusHandler); - -// Later, remove it when no longer needed -Events.Off('common:WindowFocus', focusHandler); - -// Or remove all listeners for an event -Events.Off('common:WindowFocus'); -``` - -## Common Use Cases - -### 1. Pause/Resume on Window Focus - -Many applications need to pause certain activities when the window loses focus: - -```javascript -import { Events } from '@wailsio/runtime'; - -let animationRunning = true; - -Events.On('common:WindowLostFocus', () => { - animationRunning = false; - pauseBackgroundTasks(); -}); - -Events.On('common:WindowFocus', () => { - animationRunning = true; - resumeBackgroundTasks(); -}); -``` - -### 2. Responding to Theme Changes - -Keep your app in sync with the system theme: - -```javascript -import { Events } from '@wailsio/runtime'; - -Events.On('common:ThemeChanged', (event) => { - const isDarkMode = event.data.isDark; - - if (isDarkMode) { - document.body.classList.add('dark-theme'); - document.body.classList.remove('light-theme'); - } else { - document.body.classList.add('light-theme'); - document.body.classList.remove('dark-theme'); - } -}); -``` - -### 3. Handling File Drops - -Make your app accept dragged files: - -```javascript -import { Events } from '@wailsio/runtime'; - -Events.On('common:WindowFilesDropped', (event) => { - const files = event.data.files; - - files.forEach(file => { - console.log('File dropped:', file); - // Process the dropped files - handleFileUpload(file); - }); -}); -``` - -### 4. Window Lifecycle Management - -Respond to window state changes: - -```javascript -import { Events } from '@wailsio/runtime'; - -Events.On('common:WindowClosing', () => { - // Save user data before closing - saveApplicationState(); - - // You could also prevent closing by returning false - // from a registered window close handler -}); - -Events.On('common:WindowMaximise', () => { - // Adjust UI for maximized view - adjustLayoutForMaximized(); -}); - -Events.On('common:WindowRestore', () => { - // Return UI to normal state - adjustLayoutForNormal(); -}); -``` - -### 5. Platform-Specific Features - -Handle platform-specific events when needed: - -```javascript -import { Events } from '@wailsio/runtime'; - -// Windows-specific power management -Events.On('windows:APMSuspend', () => { - console.log('System is going to sleep'); - saveState(); -}); - -Events.On('windows:APMResumeSuspend', () => { - console.log('System woke up'); - refreshData(); -}); - -// macOS-specific app lifecycle -Events.On('mac:ApplicationWillTerminate', () => { - console.log('App is about to quit'); - performCleanup(); -}); -``` - -## Creating Custom Events - -You can create your own events for application-specific needs. - -### Backend (Go) - -```go -// Emit a custom event when data changes - -func (s *Service) ProcessUserData(userData UserData) error { - // Process the data... - - app := application.Get() - // Notify all listeners - app.Event.Emit("user:data-processed", - map[string]interface{}{ - "userId": userData.ID, - "status": "completed", - "timestamp": time.Now(), - }, - ) - return nil -} - -// Emit periodic updates -func (s *Service) StartMonitoring() { - app := application.Get() - ticker := time.NewTicker(5 * time.Second) - go func() { - for range ticker.C { - stats := s.collectStats() - app.Event.Emit("monitor:stats-updated", stats) - } - }() -} -``` - -### Frontend (JavaScript) - -```javascript -import { Events } from '@wailsio/runtime'; - -// Listen for your custom events -Events.On('user:data-processed', (event) => { - const { userId, status, timestamp } = event.data; - - showNotification(`User ${userId} processing ${status}`); - updateUIWithNewData(); -}); - -Events.On('monitor:stats-updated', (event) => { - updateDashboard(event.data); -}); -``` - -## Typed Events with Type Safety - -Wails v3 supports typed events with full TypeScript type safety through event registration and automatic binding generation. - -### Registering Custom Events - -Call `application.RegisterEvent` at init time to register custom event names with their data types: - -```go -package main - -import "github.com/wailsapp/wails/v3/pkg/application" - -type UserLoginData struct { - UserID string - Username string - LoginTime string -} - -type MonitorStats struct { - CPUUsage float64 - MemoryUsage float64 -} - -func init() { - // Register events with their data types - application.RegisterEvent[UserLoginData]("user:login") - application.RegisterEvent[MonitorStats]("monitor:stats") - - // Register events without data (void events) - application.RegisterEvent[application.Void]("app:ready") -} -``` - -:::caution -`RegisterEvent` is meant to be called at init time and will panic if: -- Arguments are not valid -- The same event name is registered twice with different data types -::: - -:::note -It is safe to register the same event multiple times as long as the data type is always the same. This can be useful to ensure an event is registered when any of multiple packages is loaded. -::: - -### Benefits of Event Registration - -Once registered, data arguments passed to `Event.Emit` are type-checked against the specified type. On mismatch: -- An error is emitted and logged (or passed to the registered error handler) -- The offending event will not be propagated -- This ensures the data field of registered events is always assignable to the declared type - -### Strict Mode - -Use the `strictevents` build tag to enable warnings for unregistered events in development: - -```bash -go build -tags strictevents -``` - -With strict mode enabled, the runtime emits at most one warning per unregistered event name to avoid spamming logs. - -### TypeScript Binding Generation - -The binding generator outputs TypeScript definitions and glue code for transparent typed event support in the frontend. - -#### 1. Set up the Vite Plugin - -In your `vite.config.ts`: - -```typescript -import { defineConfig } from 'vite' -import wails from '@wailsio/runtime/plugins/vite' - -export default defineConfig({ - plugins: [wails()], -}) -``` - -#### 2. Generate Bindings - -Run the binding generator: - -```bash -wails3 generate bindings -``` - -This creates TypeScript files in your frontend directory with typed event creators and data interfaces. - -#### 3. Use Typed Events in Frontend - -```typescript -import { Events } from '@wailsio/runtime' -import { UserLogin, MonitorStats } from './bindings/events' - -// Type-safe event emission with autocomplete -Events.Emit(UserLogin({ - UserID: "123", - Username: "john_doe", - LoginTime: new Date().toISOString() -})) - -// Type-safe event listening -Events.On(UserLogin, (event) => { - // event.data is typed as UserLoginData - console.log(`User ${event.data.Username} logged in`) -}) - -Events.On(MonitorStats, (event) => { - // event.data is typed as MonitorStats - updateDashboard({ - cpu: event.data.CPUUsage, - memory: event.data.MemoryUsage - }) -}) -``` - -The typed events provide: -- **Autocomplete** for event names -- **Type checking** for event data -- **Compile-time errors** for mismatched data types -- **IntelliSense** documentation - -## Event Reference - -### Common Events (Cross-platform) - -These events work on all platforms: - -| Event | Description | When to Use | -|-------|-------------|-------------| -| `common:ApplicationStarted` | Application has fully started | Initialize your app, load saved state | -| `common:WindowRuntimeReady` | Wails runtime is ready | Start making Wails API calls | -| `common:ThemeChanged` | System theme changed | Update app appearance | -| `common:WindowFocus` | Window gained focus | Resume activities, refresh data | -| `common:WindowLostFocus` | Window lost focus | Pause activities, save state | -| `common:WindowMinimise` | Window was minimized | Pause rendering, reduce resource usage | -| `common:WindowMaximise` | Window was maximized | Adjust layout for full screen | -| `common:WindowRestore` | Window restored from min/max | Return to normal layout | -| `common:WindowClosing` | Window is about to close | Save data, cleanup resources | -| `common:WindowFilesDropped` | Files dropped on window | Handle file imports | -| `common:WindowDidResize` | Window was resized | Adjust layout, rerender charts | -| `common:WindowDidMove` | Window was moved | Update position-dependent features | - -### Platform-Specific Events - -#### Windows Events - -Key events for Windows applications: - -| Event | Description | Use Case | -|-------|-------------|----------| -| `windows:SystemThemeChanged` | Windows theme changed | Update app colors | -| `windows:APMSuspend` | System suspending | Save state, pause operations | -| `windows:APMResumeSuspend` | System resumed | Restore state, refresh data | -| `windows:APMPowerStatusChange` | Power status changed | Adjust performance settings | - -#### macOS Events - -Important macOS application events: - -| Event | Description | Use Case | -|-------|-------------|----------| -| `mac:ApplicationDidBecomeActive` | App became active | Resume operations | -| `mac:ApplicationDidResignActive` | App became inactive | Pause operations | -| `mac:ApplicationWillTerminate` | App will quit | Final cleanup | -| `mac:WindowDidEnterFullScreen` | Entered fullscreen | Adjust UI for fullscreen | -| `mac:WindowDidExitFullScreen` | Exited fullscreen | Restore normal UI | - -#### Linux Events - -Core Linux window events: - -| Event | Description | Use Case | -|-------|-------------|----------| -| `linux:SystemThemeChanged` | Desktop theme changed | Update app theme | -| `linux:WindowFocusIn` | Window gained focus | Resume activities | -| `linux:WindowFocusOut` | Window lost focus | Pause activities | -| `linux:WindowLoadStarted` | WebView started loading | Show loading indicator | -| `linux:WindowLoadRedirected` | WebView redirected | Track navigation redirects | -| `linux:WindowLoadCommitted` | WebView committed load | Content is being received | -| `linux:WindowLoadFinished` | WebView finished loading | Hide loading indicator, inject JS/CSS | - -## Best Practices - -### 1. Use Event Namespaces - -When creating custom events, use namespaces to avoid conflicts: - -```javascript -import { Events } from '@wailsio/runtime'; - -// Good - namespaced events -Events.Emit('myapp:user:login'); -Events.Emit('myapp:data:updated'); -Events.Emit('myapp:network:connected'); - -// Avoid - generic names that might conflict -Events.Emit('login'); -Events.Emit('update'); -``` - -### 2. Clean Up Listeners - -Always remove event listeners when components unmount: - -```javascript -import { Events } from '@wailsio/runtime'; - -// React example -useEffect(() => { - const handler = (event) => { - // Handle event - }; - - Events.On('common:WindowResize', handler); - - // Cleanup - return () => { - Events.Off('common:WindowResize', handler); - }; -}, []); -``` - -### 3. Handle Platform Differences - -Check platform availability when using platform-specific events: - -```javascript -import { Platform, Events } from '@wailsio/runtime'; - -if (Platform.isWindows) { - Events.On('windows:APMSuspend', handleSuspend); -} else if (Platform.isMac) { - Events.On('mac:ApplicationWillTerminate', handleTerminate); -} -``` - -### 4. Don't Overuse Events - -While events are powerful, don't use them for everything: - -- ✅ Use events for: System notifications, lifecycle changes, broadcast updates -- ❌ Avoid events for: Direct function returns, single component updates, synchronous operations - -## Debugging Events - -To debug event issues: - -```javascript -import { Events } from '@wailsio/runtime'; - -// Log all events (development only) -if (isDevelopment) { - const originalOn = Events.On; - Events.On = function(eventName, handler) { - console.log(`[Event Registered] ${eventName}`); - return originalOn.call(this, eventName, function(event) { - console.log(`[Event Fired] ${eventName}`, event); - return handler(event); - }); - }; -} -``` - -## Source of Truth - -The complete list of available events can be found in the Wails source code: -- Frontend events: [`v3/internal/runtime/desktop/@wailsio/runtime/src/event_types.ts`](https://github.com/wailsapp/wails/blob/main/v3/internal/runtime/desktop/@wailsio/runtime/src/event_types.ts) -- Backend events: [`v3/pkg/events/events.go`](https://github.com/wailsapp/wails/blob/main/v3/pkg/events/events.go) - -Always refer to these files for the most up-to-date event names and availability. - -## Summary - -Events in Wails provide a powerful, decoupled way to handle communication in your application. By following the patterns and practices in this guide, you can build responsive, platform-aware applications that react smoothly to system changes and user interactions. - -Remember: start with common events for cross-platform compatibility, add platform-specific events when needed, and always clean up your event listeners to prevent memory leaks. \ No newline at end of file diff --git a/docs/src/content/docs/guides/file-associations.mdx b/docs/src/content/docs/guides/file-associations.mdx deleted file mode 100644 index ba37d9f35..000000000 --- a/docs/src/content/docs/guides/file-associations.mdx +++ /dev/null @@ -1,178 +0,0 @@ ---- -title: File Associations -sidebar: - order: 20 ---- - -import { Steps } from "@astrojs/starlight/components"; -import {Badge} from '@astrojs/starlight/components'; - -Relevant Platforms: -
      - -File associations allow your application to handle specific file types when -users open them. This is particularly useful for text editors, image viewers, or -any application that works with specific file formats. This guide explains how -to implement file associations in your Wails v3 application. - -## Overview - -File association support in Wails v3 is currently available for: - -- Windows (NSIS installer packages) -- macOS (application bundles) - -## Configuration - -File associations are configured in the `config.yml` file located in your -project's `build` directory. - -### Basic Configuration - -To set up file associations: - -1. Open `build/config.yml` -2. Add your file associations under the `fileAssociations` section -3. Run `wails3 update build-assets` to update the build assets -4. Set the `FileAssociations` field in the application options -5. Package your application using `wails3 package` - -Here's an example configuration: - -```yaml -fileAssociations: - - ext: myapp - name: MyApp Document - description: MyApp Document File - iconName: myappFileIcon - role: Editor - - ext: custom - name: Custom Format - description: Custom File Format - iconName: customFileIcon - role: Editor -``` - -### Configuration Properties - -| Property | Description | Platform | -|-------------|------------------------------------------------------------------|----------| -| ext | File extension without the leading period (e.g., `txt`) | All | -| name | Display name for the file type | All | -| description | Description shown in file properties | Windows | -| iconName | Name of the icon file (without extension) in the build folder | All | -| role | Application's role for this file type (e.g., `Editor`, `Viewer`) | macOS | -| mimeType | MIME type for the file (e.g., `image/jpeg`) | macOS | - -## Listening for File Open Events - -To handle file open events in your application, you can listen for the -`events.Common.ApplicationOpenedWithFile` event: - -```go title="main.go" -package main - -import ( - "github.com/wailsapp/wails/v3/pkg/application" - "github.com/wailsapp/wails/v3/pkg/events" -) - -func main() { - app := application.New(application.Options{ - Name: "MyApp", - FileAssociations: []string{".txt", ".md"}, // Specify supported extensions - }) - - // Listen for files being used to open the application - app.Event.OnApplicationEvent(events.Common.ApplicationOpenedWithFile, func(event *application.ApplicationEvent) { - associatedFile := event.Context().Filename() - application.InfoDialog().SetMessage("Application opened with file: " + associatedFile).Show() - }) - - // Create your window and run the app... -} - -``` - -## Step-by-Step Tutorial - -Let's walk through setting up file associations for a simple text editor: - - - -1. ### Create Icons - - - Create icons for your file type (recommended sizes: 16x16, 32x32, 48x48, - 256x256) - - Save the icons in your project's `build` folder - - Name them according to your `iconName` configuration (e.g., - `textFileIcon.png`) - - :::tip - You can use `wails3 generate icons` to generate the required icons for you. - Run `wails3 generate icons --help` for more information. - ::: - - - For macOS add copy statement like `cp build/darwin/documenticon.icns {{.BIN_DIR}}/{{.APP_NAME}}.app/Contents/Resources` in the `create:app:bundle:` task. - -2. ### Configure File Associations - - Edit the `build/config.yml` file to add your file associations: - - ```yaml - # build/config.yml - fileAssociations: - - ext: txt - name: Text Document - description: Plain Text Document - iconName: textFileIcon - role: Editor - ``` - -3. ### Update Build Assets - - Run the following command to update the build assets: - - ```bash - wails3 update build-assets - ``` - -4. ### Set File Associations in the Application Options - - In your `main.go` file, set the `FileAssociations` field in the application - options: - - ```go - app := application.New(application.Options{ - Name: "MyApp", - FileAssociations: []string{".txt", ".md"}, // Specify supported extensions - }) - ``` - - :::tip[Why are file extensions required in both the application config and config.yml?] - - On Windows, when a file is opened with a file association, the application is - launched with the filename as the first argument to the application. The - application has no way of knowing if the first argument is a file or a command - line argument, so it uses the `FileAssociations` field in the application - options to determine if the first argument is an associated file or not. - - ::: - -5. ### Package Your Application - - Package your application using the following command: - - ```bash - wails3 package - ``` - - The packaged application will be created in the `bin` directory. You can then - install and test the application. - - ## Additional Notes - - - Icons should be provided in PNG format in the build folder - - Testing file associations requires installing the packaged application - - \ No newline at end of file diff --git a/docs/src/content/docs/guides/gin-routing.mdx b/docs/src/content/docs/guides/gin-routing.mdx deleted file mode 100644 index fc3ce289a..000000000 --- a/docs/src/content/docs/guides/gin-routing.mdx +++ /dev/null @@ -1,263 +0,0 @@ ---- -title: Using Gin for Routing -description: A comprehensive guide to integrating Gin web framework with Wails v3 applications ---- - -This guide demonstrates how to integrate the [Gin web framework](https://github.com/gin-gonic/gin) with Wails v3. Gin is a high-performance HTTP web framework written in Go that makes it easy to build web applications and APIs. - -## Introduction - -Wails v3 provides a flexible asset system that allows you to use any HTTP handler, including popular web frameworks like Gin. This integration enables you to: - -- Serve web content using Gin's routing and middleware -- Create RESTful APIs accessible from your Wails application -- Use Gin's features while maintaining Wails desktop integration - -## Setting Up Gin with Wails - -To integrate Gin with Wails, you need to create a Gin router and configure it as the asset handler in your Wails application. Here's a step-by-step guide: - -### 1. Install Dependencies - -First, ensure you have the Gin package installed: - -```bash -go get -u github.com/gin-gonic/gin -``` - -### 2. Create a Middleware for Gin - -Create a middleware function that will handle the integration between Wails and Gin: - -```go -// GinMiddleware creates a middleware that passes requests to Gin if they're not handled by Wails -func GinMiddleware(ginEngine *gin.Engine) application.Middleware { - return func(next http.Handler) http.Handler { - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - // Let Wails handle the `/wails` route - if strings.HasPrefix(r.URL.Path, "/wails") { - next.ServeHTTP(w, r) - return - } - // Let Gin handle everything else - ginEngine.ServeHTTP(w, r) - }) - } -} -``` - -This middleware passes all HTTP requests to the Gin router. - -### 3. Configure Your Gin Router - -Set up your Gin router with routes, middlewares, and handlers: - -```go -// Create a new Gin router -ginEngine := gin.New() // Using New() instead of Default() to add custom middleware - -// Add middlewares -ginEngine.Use(gin.Recovery()) -ginEngine.Use(LoggingMiddleware()) // Your custom middleware - -// Define routes -ginEngine.GET("/", func(c *gin.Context) { - // Serve your main page -}) - -ginEngine.GET("/api/hello", func(c *gin.Context) { - c.JSON(http.StatusOK, gin.H{ - "message": "Hello from Gin API!", - "time": time.Now().Format(time.RFC3339), - }) -}) -``` - -### 4. Integrate with Wails Application - -Configure your Wails application to use the Gin router as its asset handler: - -```go -// Create a new Wails application -app := application.New(application.Options{ - Name: "Gin Example", - Description: "A demo of using Gin with Wails", - Mac: application.MacOptions{ - ApplicationShouldTerminateAfterLastWindowClosed: true, - }, - Assets: application.AssetOptions{ - Handler: ginEngine, - Middleware: GinMiddleware(ginEngine), - }, -}) - -// Create window -app.Window.NewWithOptions(application.WebviewWindowOptions{ - Title: "Wails + Gin Example", - Width: 900, - Height: 700, - URL: "/", // This will load the route handled by Gin -}) -``` - -## Serving Static Content - -Use Go's `embed` package to embed static files into your binary: - -```go -//go:embed static -var staticFiles embed.FS - -ginEngine.StaticFS("/static", http.FS(staticFiles)) -ginEngine.GET("/", func(c *gin.Context) { - file, _ := staticFiles.ReadFile("static/index.html") - c.Data(http.StatusOK, "text/html; charset=utf-8", file) -}) -``` - -For development, serve files directly from disk using `ginEngine.Static("/static", "./static")`. - -## Custom Middleware - -Gin allows you to create custom middleware for various purposes. Here's an example of a logging middleware: - -```go -// LoggingMiddleware is a Gin middleware that logs request details -func LoggingMiddleware() gin.HandlerFunc { - return func(c *gin.Context) { - // Start timer - startTime := time.Now() - - // Process request - c.Next() - - // Calculate latency - latency := time.Since(startTime) - - // Log request details - log.Printf("[GIN] %s | %s | %s | %d | %s", - c.Request.Method, - c.Request.URL.Path, - c.ClientIP(), - c.Writer.Status(), - latency, - ) - } -} -``` - -## Handling API Requests - -Gin makes it easy to create RESTful APIs. Here's how to define API endpoints: - -```go -// GET endpoint -ginEngine.GET("/api/users", func(c *gin.Context) { - c.JSON(http.StatusOK, users) -}) - -// POST endpoint with JSON binding -ginEngine.POST("/api/users", func(c *gin.Context) { - var newUser User - if err := c.ShouldBindJSON(&newUser); err != nil { - c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) - return - } - // Process the new user... - c.JSON(http.StatusCreated, newUser) -}) - -// Path parameters -ginEngine.GET("/api/users/:id", func(c *gin.Context) { - id := c.Param("id") - // Find user by ID... - c.JSON(http.StatusOK, user) -}) - -// Query parameters -ginEngine.GET("/api/search", func(c *gin.Context) { - query := c.DefaultQuery("q", "") - limit := c.DefaultQuery("limit", "10") - // Perform search... - c.JSON(http.StatusOK, results) -}) -``` - -## Using Wails Features - -Your Gin-served web content can interact with Wails features using the `@wailsio/runtime` package. - -### Event Handling - -Register event handlers in Go: - -```go -app.Event.On("my-event", func(event *application.CustomEvent) { - log.Printf("Received event: %v", event.Data) -}) -``` - -Call from JavaScript using the runtime: - -```html - -``` - -## Advanced Configuration - -### Customising Gin's Mode - -Set Gin to release mode for production: - -```go -gin.SetMode(gin.ReleaseMode) // Use gin.DebugMode for development -ginEngine := gin.New() -``` - -### Handling WebSockets - -You can integrate WebSockets with Gin using libraries like Gorilla WebSocket: - -```go -import "github.com/gorilla/websocket" - -var upgrader = websocket.Upgrader{ - ReadBufferSize: 1024, - WriteBufferSize: 1024, - CheckOrigin: func(r *http.Request) bool { - return true // Allow all connections - }, -} - -// In your route handler: -ginEngine.GET("/ws", func(c *gin.Context) { - conn, err := upgrader.Upgrade(c.Writer, c.Request, nil) - if err != nil { - log.Println(err) - return - } - defer conn.Close() - - // Handle WebSocket connection... -}) -``` - -## Best Practices - -- **Use Go's embed Package:** Embed static files into your binary for better distribution. -- **Separate Concerns:** Keep your API logic separate from your UI logic. -- **Error Handling:** Implement proper error handling in both Gin routes and frontend code. -- **Security:** Be mindful of security considerations, especially when handling user input. -- **Performance:** Use Gin's release mode in production for better performance. -- **Testing:** Write tests for your Gin routes using Gin's testing utilities. - -## Conclusion - -Integrating Gin with Wails provides a powerful combination for building desktop applications with web technologies. Gin's performance and feature set complement Wails' desktop integration capabilities, allowing you to create sophisticated applications that use the best of both worlds. - -For more information, refer to the [Gin documentation](https://github.com/gin-gonic/gin) and the [Wails documentation](https://wails.io). diff --git a/docs/src/content/docs/guides/gin-services.mdx b/docs/src/content/docs/guides/gin-services.mdx deleted file mode 100644 index 123f876eb..000000000 --- a/docs/src/content/docs/guides/gin-services.mdx +++ /dev/null @@ -1,556 +0,0 @@ ---- -title: Using Gin for Services -description: A guide to integrating the Gin web framework with Wails v3 Services ---- - -# Using Gin for Services - -The Gin web framework is a popular choice for building HTTP services in Go. With Wails v3, you can easily integrate Gin-based services into your application, providing a powerful way to handle HTTP requests, implement RESTful APIs, and serve web content. - -This guide will walk you through creating a Gin-based service that can be mounted at a specific route in your Wails application. We'll build a complete example that demonstrates how to: - -1. Create a Gin-based service -2. Implement the Wails Service interface -3. Set up routes and middleware -4. Integrate with the Wails event system -5. Interact with the service from the frontend - -## Prerequisites - -Before you begin, make sure you have: - -- Wails v3 installed -- Basic knowledge of Go and the Gin framework -- Familiarity with HTTP concepts and RESTful APIs - -You'll need to add the Gin framework to your project: - -```bash -go get github.com/gin-gonic/gin -``` - -## Creating a Gin-Based Service - -Let's start by creating a Gin service that implements the Wails Service interface. Our service will manage a collection of users and provide API endpoints for retrieving and creating user records. - -### 1. Define Your Data Models - -First, define the data structures your service will work with: - -```go -package services - -import ( - "context" - "net/http" - "strconv" - "sync" - "time" - - "github.com/gin-gonic/gin" - "github.com/wailsapp/wails/v3/pkg/application" -) - -// User represents a user in the system -type User struct { - ID int `json:"id"` - Name string `json:"name"` - Email string `json:"email"` - CreatedAt time.Time `json:"createdAt"` -} - -// EventData represents data sent in events -type EventData struct { - Message string `json:"message"` - Timestamp string `json:"timestamp"` -} -``` - -### 2. Create Your Service Structure - -Next, define the service structure that will hold your Gin router and any state your service needs to maintain: - -```go -// GinService implements a Wails service that uses Gin for HTTP handling -type GinService struct { - ginEngine *gin.Engine - users []User - nextID int - mu sync.RWMutex - app *application.App -} - -// NewGinService creates a new GinService instance -func NewGinService() *GinService { - // Create a new Gin router - ginEngine := gin.New() - - // Add middlewares - ginEngine.Use(gin.Recovery()) - ginEngine.Use(LoggingMiddleware()) - - service := &GinService{ - ginEngine: ginEngine, - users: []User{ - {ID: 1, Name: "Alice", Email: "alice@example.com", CreatedAt: time.Now().Add(-72 * time.Hour)}, - {ID: 2, Name: "Bob", Email: "bob@example.com", CreatedAt: time.Now().Add(-48 * time.Hour)}, - {ID: 3, Name: "Charlie", Email: "charlie@example.com", CreatedAt: time.Now().Add(-24 * time.Hour)}, - }, - nextID: 4, - } - - // Define routes - service.setupRoutes() - - return service -} -``` - -### 3. Implement the Service Interface - -Implement the required methods for the Wails Service interface: - -```go -// ServiceName returns the name of the service -func (s *GinService) ServiceName() string { - return "Gin API Service" -} - -// ServiceStartup is called when the service starts -func (s *GinService) ServiceStartup(ctx context.Context, options application.ServiceOptions) error { - // Store the application instance for later use - s.app = application.Get() - - // Register an event handler that can be triggered from the frontend - s.app.Event.On("gin-api-event", func(event *application.CustomEvent) { - // Log the event data - s.app.Logger.Info("Received event from frontend", "data", event.Data) - - // Emit an event back to the frontend - s.app.Event.Emit("gin-api-response", - map[string]interface{}{ - "message": "Response from Gin API Service", - "time": time.Now().Format(time.RFC3339), - }, - ) - }) - - return nil -} - -// ServiceShutdown is called when the service shuts down -func (s *GinService) ServiceShutdown(ctx context.Context) error { - // Clean up resources if needed - return nil -} -``` - -### 3. Implement the http.Handler Interface - -To make your service mountable at a specific route, implement the `http.Handler` interface. This single method, `ServeHTTP`, is the gateway for all HTTP requests to your service. It delegates the request handling to the Gin router, allowing you to use all of Gin's powerful features for routing and middleware. - -```go -// ServeHTTP implements the http.Handler interface -func (s *GinService) ServeHTTP(w http.ResponseWriter, r *http.Request) { - // All requests go to the Gin router - s.ginEngine.ServeHTTP(w, r) -} -``` - -### 4. Set Up Your Routes - -Define your API routes in a separate method for better organisation. This approach keeps your code clean and makes it easier to understand the structure of your API. The Gin router provides a fluent API for defining routes, including support for route groups, which help organise related endpoints. - -```go -// setupRoutes configures the API routes -func (s *GinService) setupRoutes() { - // Basic info endpoint - s.ginEngine.GET("/info", func(c *gin.Context) { - c.JSON(http.StatusOK, gin.H{ - "service": "Gin API Service", - "version": "1.0.0", - "time": time.Now().Format(time.RFC3339), - }) - }) - - // Users group - users := s.ginEngine.Group("/users") - { - // Get all users - users.GET("", func(c *gin.Context) { - s.mu.RLock() - defer s.mu.RUnlock() - c.JSON(http.StatusOK, s.users) - }) - - // Get user by ID - users.GET("/:id", func(c *gin.Context) { - id, err := strconv.Atoi(c.Param("id")) - if err != nil { - c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid user ID"}) - return - } - - s.mu.RLock() - defer s.mu.RUnlock() - - for _, user := range s.users { - if user.ID == id { - c.JSON(http.StatusOK, user) - return - } - } - - c.JSON(http.StatusNotFound, gin.H{"error": "User not found"}) - }) - - // Create a new user - users.POST("", func(c *gin.Context) { - var newUser User - if err := c.ShouldBindJSON(&newUser); err != nil { - c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) - return - } - - s.mu.Lock() - defer s.mu.Unlock() - - // Set the ID and creation time - newUser.ID = s.nextID - newUser.CreatedAt = time.Now() - s.nextID++ - - // Add to the users slice - s.users = append(s.users, newUser) - - c.JSON(http.StatusCreated, newUser) - - // Emit an event to notify about the new user - s.app.Event.Emit("user-created", newUser) - }) - - // Delete a user - users.DELETE("/:id", func(c *gin.Context) { - id, err := strconv.Atoi(c.Param("id")) - if err != nil { - c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid user ID"}) - return - } - - s.mu.Lock() - defer s.mu.Unlock() - - for i, user := range s.users { - if user.ID == id { - // Remove the user from the slice - s.users = append(s.users[:i], s.users[i+1:]...) - c.JSON(http.StatusOK, gin.H{"message": "User deleted"}) - return - } - } - - c.JSON(http.StatusNotFound, gin.H{"error": "User not found"}) - }) - } -} -``` - -### 5. Create Custom Middleware - -You can create custom Gin middleware to enhance your service. Middleware functions in Gin are executed in the order they are added to the router and can perform tasks such as logging, authentication, and error handling. This example shows a simple logging middleware that records request details. - -```go -// LoggingMiddleware is a Gin middleware that logs request details -func LoggingMiddleware() gin.HandlerFunc { - return func(c *gin.Context) { - // Start timer - start := time.Now() - - // Process request - c.Next() - - // Calculate latency - latency := time.Since(start) - - // Log request details - log.Printf("[GIN] %s %s %d %s", c.Request.Method, c.Request.URL.Path, c.Writer.Status(), latency) - } -} -``` - -## Registering Your Service - -To use your Gin-based service in a Wails application, you need to register it with the application and specify the route where it should be mounted. This is done when creating the Wails application instance. The route you specify becomes the base path for all endpoints defined in your Gin router. - -```go -app := application.New(application.Options{ - Name: "Gin Service Demo", - Description: "A demo of using Gin in Wails services", - Mac: application.MacOptions{ - ApplicationShouldTerminateAfterLastWindowClosed: true, - }, - LogLevel: slog.LevelDebug, - Services: []application.Service{ - application.NewServiceWithOptions(services.NewGinService(), application.ServiceOptions{ - Route: "/api", - }), - }, - Assets: application.AssetOptions{ - Handler: application.BundledAssetFileServer(assets), - }, -}) -``` - -In this example, the Gin service is mounted at the `/api` route. This means that if your Gin router has an endpoint defined as `/info`, it will be accessible at `/api/info` in your application. This approach allows you to organise your API endpoints logically and avoid conflicts with other parts of your application. - -## Integrating with the Wails Event System - -One of the powerful features of using Gin with Wails Services is the ability to seamlessly integrate with the Wails event system. This allows for real-time communication between your backend service and the frontend. - -In your service's `ServiceStartup` method, you can register event handlers to process events from the frontend: - -```go -s.app.Event.On("gin-api-event", func(event *application.CustomEvent) { - // Log the event data - s.app.Logger.Info("Received event from frontend", "data", event.Data) - - // Emit an event back to the frontend - s.app.Event.Emit("gin-api-response", - map[string]interface{}{ - "message": "Response from Gin API Service", - "time": time.Now().Format(time.RFC3339), - }, - ) -}) -``` - -You can also emit events to the frontend from your Gin routes or other parts of your service: - -```go -// After creating a new user -s.app.Event.Emit("user-created", newUser) -``` - -## Frontend Integration - -To interact with your Gin service from the frontend, you'll need to import the Wails runtime, make HTTP requests to your API endpoints, and use the Wails event system for real-time communication. - -For production use, it's recommended to use the `@wailsio/runtime` package instead of directly importing `/wails/runtime.js`. This ensures type safety, better IDE support, version management through npm, and compatibility with modern JavaScript tooling. - -Install the package: -```bash -npm install @wailsio/runtime -``` - -Then use it in your code: -```javascript -import * as wails from '@wailsio/runtime'; - -// Event emission -wails.Events.Emit('gin-api-event', eventData); -``` - -Here's an example of how to set up frontend integration: - -```html - - - - - - Gin Service Example - - - -

      Gin Service Example

      - -
      -

      API Endpoints

      -

      Try the Gin API endpoints mounted at /api:

      - - - - - - - -
      -
      Results will appear here...
      -
      -
      - -
      -

      Event Communication

      -

      Trigger an event to communicate with the Gin service:

      - - - -
      -
      Event responses will appear here...
      -
      -
      - - - - - - -``` - -## Closing Thoughts - -Integrating the Gin web framework with Wails v3 Services provides a powerful and flexible approach to building modular, maintainable web applications. By leveraging Gin's routing and middleware capabilities alongside the Wails event system, you can create rich, interactive applications with clean separation of concerns. - -The complete example code for this guide can be found in the Wails repository under `v3/examples/gin-service`. diff --git a/docs/src/content/docs/guides/installers.mdx b/docs/src/content/docs/guides/installers.mdx deleted file mode 100644 index 170b26865..000000000 --- a/docs/src/content/docs/guides/installers.mdx +++ /dev/null @@ -1,160 +0,0 @@ ---- -title: Creating Installers -description: Package your application for distribution -sidebar: - order: 3 ---- - -import { Tabs, TabItem } from "@astrojs/starlight/components"; - -## Overview - -Create professional installers for your Wails application on all platforms. - -## Platform Installers - - - - ### NSIS Installer - - ```bash - # Install NSIS - # Download from: https://nsis.sourceforge.io/ - - # Create installer script (installer.nsi) - makensis installer.nsi - ``` - - **installer.nsi:** - ```nsis - !define APPNAME "MyApp" - !define VERSION "1.0.0" - - Name "${APPNAME}" - OutFile "MyApp-Setup.exe" - InstallDir "$PROGRAMFILES\${APPNAME}" - - Section "Install" - SetOutPath "$INSTDIR" - File "build\bin\myapp.exe" - CreateShortcut "$DESKTOP\${APPNAME}.lnk" "$INSTDIR\myapp.exe" - SectionEnd - ``` - - ### WiX Toolset - - Alternative for MSI installers. - - - - ### DMG Creation - - ```bash - # Create DMG - hdiutil create -volname "MyApp" -srcfolder build/bin/MyApp.app -ov -format UDZO MyApp.dmg - ``` - - ### Code Signing - - ```bash - # Sign application - codesign --deep --force --verify --verbose --sign "Developer ID" MyApp.app - - # Notarize - xcrun notarytool submit MyApp.dmg --apple-id "email" --password "app-password" - ``` - - ### App Store - - Use Xcode for App Store distribution. - - - - ### DEB Package - - ```bash - # Create package structure - mkdir -p myapp_1.0.0/DEBIAN - mkdir -p myapp_1.0.0/usr/bin - - # Copy binary - cp build/bin/myapp myapp_1.0.0/usr/bin/ - - # Create control file - cat > myapp_1.0.0/DEBIAN/control << EOF - Package: myapp - Version: 1.0.0 - Architecture: amd64 - Maintainer: Your Name - Description: My Application - EOF - - # Build package - dpkg-deb --build myapp_1.0.0 - ``` - - ### RPM Package - - Use `rpmbuild` for RPM-based distributions. - - ### AppImage - - ```bash - # Use appimagetool - appimagetool myapp.AppDir - ``` - - - -## Automated Packaging - -### Using GoReleaser - -```yaml -# .goreleaser.yml -project_name: myapp - -builds: - - binary: myapp - goos: - - windows - - darwin - - linux - goarch: - - amd64 - - arm64 - -archives: - - format: zip - name_template: "{{ .ProjectName }}_{{ .Version }}_{{ .Os }}_{{ .Arch }}" - -nfpms: - - formats: - - deb - - rpm - vendor: Your Company - homepage: https://example.com - description: My Application -``` - -## Best Practices - -### ✅ Do - -- Code sign on all platforms -- Include version information -- Create uninstallers -- Test installation process -- Provide clear documentation - -### ❌ Don't - -- Don't skip code signing -- Don't forget file associations -- Don't hardcode paths -- Don't skip testing - -## Next Steps - -- [Auto-Updates](/guides/auto-updates) - Implement automatic updates -- [Cross-Platform Building](/guides/cross-platform) - Build for multiple platforms diff --git a/docs/src/content/docs/guides/menus.mdx b/docs/src/content/docs/guides/menus.mdx deleted file mode 100644 index c16c40ff6..000000000 --- a/docs/src/content/docs/guides/menus.mdx +++ /dev/null @@ -1,531 +0,0 @@ ---- -title: Menus -description: A guide to creating and customising menus in Wails v3 ---- - -Wails v3 provides a powerful menu system that allows you to create both application menus and context menus. This guide will walk you through the various features and capabilities of the menu system. - -### Creating a Menu - -To create a new menu, use the `New()` method from the Menus manager: - -```go -menu := app.Menu.New() -``` - -### Adding Menu Items - -Wails supports several types of menu items, each serving a specific purpose: - -#### Regular Menu Items -Regular menu items are the basic building blocks of menus. They display text and can trigger actions when clicked: - -```go -menuItem := menu.Add("Click Me") -``` - -#### Checkboxes -Checkbox menu items provide a toggleable state, useful for enabling/disabling features or settings: - -```go -checkbox := menu.AddCheckbox("My checkbox", true) // true = initially checked -``` - -#### Radio Groups -Radio groups allow users to select one option from a set of mutually exclusive choices. They are automatically created when radio items are placed next to each other: - -```go -menu.AddRadio("Option 1", true) // true = initially selected -menu.AddRadio("Option 2", false) -menu.AddRadio("Option 3", false) -``` - -#### Separators -Separators are horizontal lines that help organise menu items into logical groups: - -```go -menu.AddSeparator() -``` - -#### Submenus -Submenus are nested menus that appear when hovering over or clicking a menu item. They're useful for organizing complex menu structures: - -```go -submenu := menu.AddSubmenu("File") -submenu.Add("Open") -submenu.Add("Save") -``` - -#### Combining menus -A menu can be added into another menu by appending or prepending it. -```go -menu := app.Menu.New() -menu.Add("First Menu") - -secondaryMenu := app.Menu.New() -secondaryMenu.Add("Second Menu") - -// insert 'secondaryMenu' after 'menu' -menu.Append(secondaryMenu) - -// insert 'secondaryMenu' before 'menu' -menu.Prepend(secondaryMenu) - -// update the menu -menu.Update() -``` - -:::note -By default, `prepend` and `append` will share state with the original menu. If you want to create a new menu with its own state, -you can call `.Clone()` on the menu. - -E.g: `menu.Append(secondaryMenu.Clone())` -::: - -#### Clearing a menu -In some cases it'll be better to construct a whole new menu if you are working with a variable amount of menu items. - -This will clear all items on an existing menu and allows you to add items again. - -```go -menu := app.Menu.New() -menu.Add("Waiting for update...") - -// after certain logic, the menu has to be updated -menu.Clear() -menu.Add("Update complete!") -menu.Update() -``` - -:::note -Clearing a menu simply clears the menu items at the top level. Whilst Submenus won't be visible, they will still occupy memory -so be sure to manage your menus carefully. -::: - -#### Destroying a menu - -If you want to clear and release a menu, use the `Destroy()` method: - -```go -menu := app.Menu.New() -menu.Add("Waiting for update...") - -// after certain logic, the menu has to be destroyed -menu.Destroy() -``` - - -### Menu Item Properties - -Menu items have several properties that can be configured: - -| Property | Method | Description | -|-------------|--------------------------|-----------------------------------------------------| -| Label | `SetLabel(string)` | Sets the display text | -| Enabled | `SetEnabled(bool)` | Enables/disables the item | -| Checked | `SetChecked(bool)` | Sets the checked state (for checkboxes/radio items) | -| Tooltip | `SetTooltip(string)` | Sets the tooltip text | -| Hidden | `SetHidden(bool)` | Shows/hides the item | -| Accelerator | `SetAccelerator(string)` | Sets the keyboard shortcut | - -### Menu Item States - -Menu items can be in different states that control their visibility and interactivity: - -#### Visibility - -Menu items can be shown or hidden dynamically using the `SetHidden()` method: - -```go -menuItem := menu.Add("Dynamic Item") - -// Hide the menu item -menuItem.SetHidden(true) - -// Show the menu item -menuItem.SetHidden(false) - -// Check current visibility -isHidden := menuItem.Hidden() -``` - -Hidden menu items are completely removed from the menu until shown again. This is useful for contextual menu items that should only appear in certain application states. - -#### Enabled State - -Menu items can be enabled or disabled using the `SetEnabled()` method: - -```go -menuItem := menu.Add("Save") - -// Disable the menu item -menuItem.SetEnabled(false) // Item appears grayed out and cannot be clicked - -// Enable the menu item -menuItem.SetEnabled(true) // Item becomes clickable again - -// Check current enabled state -isEnabled := menuItem.Enabled() -``` - -Disabled menu items remain visible but appear grayed out and cannot be clicked. This is commonly used to indicate that an action is currently unavailable, such as: -- Disabling "Save" when there are no changes to save -- Disabling "Copy" when nothing is selected -- Disabling "Undo" when there's no action to undo - -#### Dynamic State Management - -You can combine these states with event handlers to create dynamic menus: - -```go -saveMenuItem := menu.Add("Save") - -// Initially disable the Save menu item -saveMenuItem.SetEnabled(false) - -// Enable Save only when there are unsaved changes -documentChanged := func() { - saveMenuItem.SetEnabled(true) - menu.Update() // Remember to update the menu after changing states -} - -// Disable Save after saving -documentSaved := func() { - saveMenuItem.SetEnabled(false) - menu.Update() -} -``` - -### Event Handling - -Menu items can respond to click events using the `OnClick` method: - -```go -menuItem.OnClick(func(ctx *application.Context) { - // Handle the click event - println("Menu item clicked!") -}) -``` - -The context provides information about the clicked menu item: - -```go -menuItem.OnClick(func(ctx *application.Context) { - // Get the clicked menu item - clickedItem := ctx.ClickedMenuItem() - // Get its current state - isChecked := clickedItem.Checked() -}) -``` - -### Role-Based Menu Items - -Wails provides a set of predefined menu roles that automatically create menu items with standard functionality. Here are the supported menu roles: - -#### Complete Menu Structures -These roles create entire menu structures with common functionality: - -| Role | Description | Platform Notes | -|------|-------------|----------------| -| `AppMenu` | Application menu with About, Services, Hide/Show, and Quit | macOS only | -| `EditMenu` | Standard Edit menu with Undo, Redo, Cut, Copy, Paste, etc. | All platforms | -| `ViewMenu` | View menu with Reload, Zoom, and Fullscreen controls | All platforms | -| `WindowMenu` | Window controls (Minimise, Zoom, etc.) | All platforms | -| `HelpMenu` | Help menu with "Learn More" link to Wails website | All platforms | - -#### Individual Menu Items -These roles can be used to add individual menu items: - -| Role | Description | Platform Notes | -|------|-------------|----------------| -| `About` | Show application About dialog | All platforms | -| `Hide` | Hide application | macOS only | -| `HideOthers` | Hide other applications | macOS only | -| `UnHide` | Show hidden application | macOS only | -| `CloseWindow` | Close current window | All platforms | -| `Minimise` | Minimise window | All platforms | -| `Zoom` | Zoom window | macOS only | -| `Front` | Bring window to front | macOS only | -| `Quit` | Quit application | All platforms | -| `Undo` | Undo last action | All platforms | -| `Redo` | Redo last action | All platforms | -| `Cut` | Cut selection | All platforms | -| `Copy` | Copy selection | All platforms | -| `Paste` | Paste from clipboard | All platforms | -| `PasteAndMatchStyle` | Paste and match style | macOS only | -| `SelectAll` | Select all | All platforms | -| `Delete` | Delete selection | All platforms | -| `Reload` | Reload current page | All platforms | -| `ForceReload` | Force reload current page | All platforms | -| `ToggleFullscreen` | Toggle fullscreen mode | All platforms | -| `ResetZoom` | Reset zoom level | All platforms | -| `ZoomIn` | Increase zoom | All platforms | -| `ZoomOut` | Decrease zoom | All platforms | - -Here's an example showing how to use both complete menus and individual roles: - -```go -menu := app.Menu.New() - -// Add complete menu structures -menu.AddRole(application.AppMenu) // macOS only -menu.AddRole(application.EditMenu) // Common edit operations -menu.AddRole(application.ViewMenu) // View controls -menu.AddRole(application.WindowMenu) // Window controls - -// Add individual role-based items to a custom menu -fileMenu := menu.AddSubmenu("File") -fileMenu.AddRole(application.CloseWindow) -fileMenu.AddSeparator() -fileMenu.AddRole(application.Quit) -``` - -## Application Menus - -Application menus are the menus that appear at the top of your application window (Windows/Linux) or at the top of the screen (macOS). - - -### Application Menu Behaviour - -When you set an application menu using `app.Menu.Set()`, it becomes the main menu on macOS. -Menus are set on a per-window basis for Windows/Linux. - -```go -app.Window.NewWithOptions(application.WebviewWindowOptions{ - Title: "Custom Menu Window", - Windows: application.WindowsWindow{ - Menu: customMenu, // Override application menu for this window - }, -}) -``` - -Here's a complete example showing these different menu behaviours: - -```go -func main() { - app := application.New(application.Options{}) - - // Create application menu - appMenu := app.Menu.New() - fileMenu := appMenu.AddSubmenu("File") - fileMenu.Add("New").OnClick(func(ctx *application.Context) { - // This will be available in all windows unless overridden - window := app.Windows.Current() - window.SetTitle("New Window") - }) - - // Set as application menu - this is for macOS - app.Menu.Set(appMenu) - - // Window with custom menu on Windows - customMenu := app.Menu.New() - customMenu.Add("Custom Action") - app.Window.NewWithOptions(application.WebviewWindowOptions{ - Title: "Custom Menu", - Windows: application.WindowsWindow{ - Menu: customMenu, - }, - }) - - app.Run() -} -``` - -## Context Menus - -Context menus are popup menus that appear when right-clicking elements in your application. They provide quick access to relevant actions for the clicked element. - -### Default Context Menu - -The default context menu is the webview's built-in context menu that provides system-level operations such as: -- Copy, Cut, and Paste for text manipulation -- Text selection controls -- Spell checking options - -#### Controlling the Default Context Menu - -You can control when the default context menu appears using the `--default-contextmenu` CSS property: - -```html - -
      - - -
      - - -
      -
      Custom context menu only
      -
      - - -
      - -

      Select this text to see the default menu

      - -
      -``` - -:::note -This feature will only work as expected after the runtime [has been initialised](../../learn/runtime#initialisation). -::: - -#### Nested Context Menu Behavior - -When using the `--default-contextmenu` property on nested elements, the following rules apply: - -1. Child elements inherit their parent's context menu setting unless explicitly overridden -2. The most specific (closest) setting takes precedence -3. The `auto` value can be used to reset to default behaviour - -Example of nested context menu behaviour: - -```html - -
      - -

      No context menu here

      - - -
      -

      Context menu shown here

      - - - Also has context menu - - -
      -

      Shows menu only when text is selected

      -
      -
      -
      -``` - -### Custom Context Menus - -Custom context menus allow you to provide application-specific actions that are relevant to the element being clicked. They're particularly useful for: -- File operations in a document manager -- Image manipulation tools -- Custom actions in a data grid -- Component-specific operations - -#### Creating a Custom Context Menu - -When creating a custom context menu, you provide a unique identifier (name) that links the menu to HTML elements: - -```go -// Create a context menu with identifier "imageMenu" -contextMenu := application.NewContextMenu() -app.ContextMenus.Add("imageMenu", contextMenu) -``` - -The name parameter ("imageMenu" in this example) serves as a unique identifier that will be used to: -1. Link HTML elements to this specific context menu -2. Identify which menu should be shown when right-clicking -3. Allow menu updates and cleanup - -#### Context Data - -When handling context menu events, you can access both the clicked menu item and its associated context data: - -```go -contextMenu.Add("Process").OnClick(func(ctx *application.Context) { - // Get the clicked menu item - menuItem := ctx.ClickedMenuItem() - - // Get the context data as a string - contextData := ctx.ContextMenuData() - - // Check if the menu item is checked (for checkbox/radio items) - isChecked := ctx.IsChecked() - - // Use the data - if contextData != "" { - processItem(contextData) - } -}) -``` - -The context data is passed from the HTML element's `--custom-contextmenu-data` property and is available in the click handler through `ctx.ContextMenuData()`. This is particularly useful when: - -- Working with lists or grids where each item needs unique identification -- Handling operations on specific components or elements -- Passing state or metadata from the frontend to the backend - -#### Context Menu Management - -After making changes to a context menu, call the `Update()` method to apply the changes: - -```go -contextMenu.Update() -``` - -When you no longer need a context menu, you can destroy it: - -```go -contextMenu.Destroy() -``` -:::danger[Warning] -After calling `Destroy()`, using the context menu reference again will result in a panic. -::: - -### Real-World Example: Image Gallery - -Here's a complete example of implementing a custom context menu for an image gallery: - -```go -// Backend: Create the context menu -imageMenu := application.NewContextMenu() -app.ContextMenus.Add("imageMenu", imageMenu) - -// Add relevant operations -imageMenu.Add("View Full Size").OnClick(func(ctx *application.Context) { - // Get the image ID from context data - if imageID := ctx.ContextMenuData(); imageID != "" { - openFullSizeImage(imageID) - } -}) - -imageMenu.Add("Download").OnClick(func(ctx *application.Context) { - if imageID := ctx.ContextMenuData(); imageID != "" { - downloadImage(imageID) - } -}) - -imageMenu.Add("Share").OnClick(func(ctx *application.Context) { - if imageID := ctx.ContextMenuData(); imageID != "" { - showShareDialog(imageID) - } -}) -``` - -```html - - -``` - -In this example: -1. The context menu is created with the identifier "imageMenu" -2. Each image container is linked to the menu using `--custom-contextmenu: imageMenu` -3. Each container provides its image ID as context data using `--custom-contextmenu-data` -4. The backend receives the image ID in click handlers and can perform specific operations -5. The same menu is reused for all images, but the context data tells us which image to operate on - -This pattern is particularly powerful for: -- Data grids where rows need specific operations -- File managers where files need context-specific actions -- Design tools where different elements need different operations -- Any component where the same operations apply to multiple instances diff --git a/docs/src/content/docs/guides/panic-handling.mdx b/docs/src/content/docs/guides/panic-handling.mdx deleted file mode 100644 index f252f0dc3..000000000 --- a/docs/src/content/docs/guides/panic-handling.mdx +++ /dev/null @@ -1,116 +0,0 @@ ---- -title: Handling Panics -description: How to handle panics in your Wails application ---- - -In Go applications, panics can occur during runtime when something unexpected happens. This guide explains how to handle panics both in general Go code and specifically in your Wails application. - -## Understanding Panics in Go - -Before diving into Wails-specific panic handling, it's essential to understand how panics work in Go: - -1. Panics are for unrecoverable errors that shouldn't happen during normal operation -2. When a panic occurs in a goroutine, only that goroutine is affected -3. Panics can be recovered using `defer` and `recover()` - -Here's a basic example of panic handling in Go: - -```go -func doSomething() { - // Deferred functions run even when a panic occurs - defer func() { - if r := recover(); r != nil { - fmt.Printf("Recovered from panic: %v\n", r) - } - }() - - // Your code that might panic - panic("something went wrong") -} -``` - -For more detailed information about panic and recover in Go, see the [Go Blog: Defer, Panic, and Recover](https://go.dev/blog/defer-panic-and-recover). - -## Panic Handling in Wails - -Wails automatically handles panics that occur in your Service methods when they are called from the frontend. This means you don't need to add panic recovery to these methods - Wails will catch the panic and process it through your configured panic handler. - -The panic handler is specifically designed to catch: -- Panics in bound service methods called from the frontend -- Internal panics from the Wails runtime - -For other scenarios, such as background goroutines or standalone Go code, you should handle panics yourself using Go's standard panic recovery mechanisms. - -## The PanicDetails Struct - -When a panic occurs, Wails captures important information about the panic in a `PanicDetails` struct: - -```go -type PanicDetails struct { - StackTrace string // The stack trace of where the panic occurred. Potentially trimmed to provide more context - Error error // The error that caused the panic - Time time.Time // The time when the panic occurred - FullStackTrace string // The complete stack trace including runtime frames -} -``` - -This structure provides comprehensive information about the panic: -- `StackTrace`: A formatted string showing the call stack that led to the panic -- `Error`: The actual error or panic message -- `Time`: The exact time when the panic occurred -- `FullStackTrace`: The complete stack trace including runtime frames - -:::note[Panics in Service Code] - -When panics are caught in your Service code after being called from the frontend, the stack trace is trimmed to focus on exactly where in your code the panic occurred. -If you want to see the full stack trace, you can use the `FullStackTrace` field. - -::: - -## Default Panic Handler - -If you don't specify a custom panic handler, Wails will use its default handler which outputs error information in a formatted log message and then quits. -For example: - -``` -************************ FATAL ****************************** -* There has been a catastrophic failure in your application * -********************* Error Details ************************* -panic error: oh no! something went wrong deep in my service! :( -main.(*WindowService).call2 - at E:/wails/v3/examples/panic-handling/main.go:23 -main.(*WindowService).call1 - at E:/wails/v3/examples/panic-handling/main.go:19 -main.(*WindowService).GeneratePanic - at E:/wails/v3/examples/panic-handling/main.go:15 -************************************************************* -``` - -## Custom Panic Handler - -You can implement your own panic handler by setting the `PanicHandler` option when creating your application. Here's an example: - -```go -app := application.New(application.Options{ - Name: "My App", - PanicHandler: func(panicDetails *application.PanicDetails) { - fmt.Printf("*** Custom Panic Handler ***\n") - fmt.Printf("Time: %s\n", panicDetails.Time) - fmt.Printf("Error: %s\n", panicDetails.Error) - fmt.Printf("Stacktrace: %s\n", panicDetails.StackTrace) - fmt.Printf("Full Stacktrace: %s\n", panicDetails.FullStackTrace) - - // You could also: - // - Log to a file - // - Send to a crash reporting service - // - Show a user-friendly error dialog - // - Attempt to recover or restart the application - }, -}) -``` - -For a complete working example of panic handling in a Wails application, see the panic-handling example in `v3/examples/panic-handling`. - -## Final Notes - -Remember that the Wails panic handler is specifically for managing panics in bound methods and internal runtime errors. For other parts of your application, you should use Go's standard error handling patterns and panic recovery mechanisms where appropriate. As with all Go applications, it's better to prevent panics through proper error handling where possible. diff --git a/docs/src/content/docs/guides/performance.mdx b/docs/src/content/docs/guides/performance.mdx deleted file mode 100644 index 1d38a1ef4..000000000 --- a/docs/src/content/docs/guides/performance.mdx +++ /dev/null @@ -1,341 +0,0 @@ ---- -title: Performance Optimisation -description: Optimise your Wails application for maximum performance -sidebar: - order: 9 ---- - -## Overview - -Optimise your Wails application for speed, memory efficiency, and responsiveness. - -## Frontend Optimisation - -### Bundle Size - -```javascript -// vite.config.js -export default { - build: { - rollupOptions: { - output: { - manualChunks: { - vendor: ['react', 'react-dom'], - }, - }, - }, - minify: 'terser', - terserOptions: { - compress: { - drop_console: true, - }, - }, - }, -} -``` - -### Code Splitting - -```javascript -// Lazy load components -const Settings = lazy(() => import('./Settings')) - -function App() { - return ( - }> - - - ) -} -``` - -### Asset Optimisation - -```javascript -// Optimise images -import { defineConfig } from 'vite' -import imagemin from 'vite-plugin-imagemin' - -export default defineConfig({ - plugins: [ - imagemin({ - gifsicle: { optimizationLevel: 3 }, - optipng: { optimizationLevel: 7 }, - svgo: { plugins: [{ removeViewBox: false }] }, - }), - ], -}) -``` - -## Backend Optimisation - -### Efficient Bindings - -```go -// ❌ Bad: Return everything -func (s *Service) GetAllData() []Data { - return s.db.FindAll() // Could be huge -} - -// ✅ Good: Paginate -func (s *Service) GetData(page, size int) (*PagedData, error) { - return s.db.FindPaged(page, size) -} -``` - -### Caching - -```go -type CachedService struct { - cache *lru.Cache - ttl time.Duration -} - -func (s *CachedService) GetData(key string) (interface{}, error) { - // Check cache - if val, ok := s.cache.Get(key); ok { - return val, nil - } - - // Fetch and cache - data, err := s.fetchData(key) - if err != nil { - return nil, err - } - - s.cache.Add(key, data) - return data, nil -} -``` - -### Goroutines for Long Operations - -```go -func (s *Service) ProcessLargeFile(path string) error { - // Process in background - go func() { - result, err := s.process(path) - if err != nil { - s.app.Event.Emit("process-error", err.Error()) - return - } - s.app.Event.Emit("process-complete", result) - }() - - return nil -} -``` - -## Memory Optimisation - -### Avoid Memory Leaks - -```go -// ❌ Bad: Goroutine leak -func (s *Service) StartPolling() { - ticker := time.NewTicker(1 * time.Second) - go func() { - for range ticker.C { - s.poll() - } - }() - // ticker never stopped! -} - -// ✅ Good: Proper cleanup -func (s *Service) StartPolling() { - ticker := time.NewTicker(1 * time.Second) - s.stopChan = make(chan bool) - - go func() { - for { - select { - case <-ticker.C: - s.poll() - case <-s.stopChan: - ticker.Stop() - return - } - } - }() -} - -func (s *Service) StopPolling() { - close(s.stopChan) -} -``` - -### Pool Resources - -```go -var bufferPool = sync.Pool{ - New: func() interface{} { - return new(bytes.Buffer) - }, -} - -func processData(data []byte) []byte { - buf := bufferPool.Get().(*bytes.Buffer) - defer bufferPool.Put(buf) - - buf.Reset() - buf.Write(data) - // Process... - return buf.Bytes() -} -``` - -## Event Optimisation - -### Debounce Events - -```javascript -// Debounce frequent events -let debounceTimer -function handleInput(value) { - clearTimeout(debounceTimer) - debounceTimer = setTimeout(() => { - UpdateData(value) - }, 300) -} -``` - -### Batch Updates - -```go -type BatchProcessor struct { - items []Item - mu sync.Mutex - timer *time.Timer -} - -func (b *BatchProcessor) Add(item Item) { - b.mu.Lock() - defer b.mu.Unlock() - - b.items = append(b.items, item) - - if b.timer == nil { - b.timer = time.AfterFunc(100*time.Millisecond, b.flush) - } -} - -func (b *BatchProcessor) flush() { - b.mu.Lock() - items := b.items - b.items = nil - b.timer = nil - b.mu.Unlock() - - // Process batch - processBatch(items) -} -``` - -## Build Optimisation - -### Binary Size - -```bash -# Strip debug symbols -wails3 build -ldflags "-s -w" - -# Reduce binary size further -go build -ldflags="-s -w" -trimpath -``` - -### Compilation Speed - -```bash -# Use build cache -go build -buildmode=default - -# Parallel compilation -go build -p 8 -``` - -## Profiling - -### CPU Profiling - -```go -import "runtime/pprof" - -func profileCPU() { - f, _ := os.Create("cpu.prof") - defer f.Close() - - pprof.StartCPUProfile(f) - defer pprof.StopCPUProfile() - - // Code to profile -} -``` - -### Memory Profiling - -```go -import "runtime/pprof" - -func profileMemory() { - f, _ := os.Create("mem.prof") - defer f.Close() - - runtime.GC() - pprof.WriteHeapProfile(f) -} -``` - -### Analyse Profiles - -```bash -# View CPU profile -go tool pprof cpu.prof - -# View memory profile -go tool pprof mem.prof - -# Web interface -go tool pprof -http=:8080 cpu.prof -``` - -## Best Practices - -### ✅ Do - -- Profile before optimising -- Cache expensive operations -- Use pagination for large datasets -- Debounce frequent events -- Pool resources -- Clean up goroutines -- Optimise bundle size -- Use lazy loading - -### ❌ Don't - -- Don't optimise prematurely -- Don't ignore memory leaks -- Don't block the main thread -- Don't return huge datasets -- Don't skip profiling -- Don't forget cleanup - -## Performance Checklist - -- [ ] Frontend bundle optimised -- [ ] Images compressed -- [ ] Code splitting implemented -- [ ] Backend methods paginated -- [ ] Caching implemented -- [ ] Goroutines cleaned up -- [ ] Events debounced -- [ ] Binary size optimised -- [ ] Profiling done -- [ ] Memory leaks fixed - -## Next Steps - -- [Architecture](/guides/architecture) - Application architecture patterns -- [Testing](/guides/testing) - Test your application -- [Building](/guides/building) - Build optimised binaries diff --git a/docs/src/content/docs/guides/raw-messages.mdx b/docs/src/content/docs/guides/raw-messages.mdx deleted file mode 100644 index 5f2a7a653..000000000 --- a/docs/src/content/docs/guides/raw-messages.mdx +++ /dev/null @@ -1,393 +0,0 @@ ---- -title: Raw Messages -description: Implement custom frontend-to-backend communication for performance-critical applications -sidebar: - order: 10 ---- - -Raw messages provide a low-level communication channel between your frontend and backend, bypassing the standard binding system. This trades convenience for speed. - -## When to Use Raw Messages - -Raw messages are best suited for extreme edge cases: - -- **Ultra-high-frequency updates** - Thousands of messages per second where every microsecond matters -- **Custom message protocols** - When you need complete control over the wire format - -:::tip -For almost all use cases, standard [service bindings](/features/bindings/services) are recommended as they provide type safety, automatic serialization, and a better developer experience with negligible overhead. -::: - -## Backend Setup - -Configure the `RawMessageHandler` in your application options: - -```go -package main - -import ( - "encoding/json" - "fmt" - - "github.com/wailsapp/wails/v3/pkg/application" -) - -func main() { - app := application.New(application.Options{ - Name: "Raw Message Demo", - Assets: application.AssetOptions{ - Handler: application.BundledAssetFileServer(assets), - }, - RawMessageHandler: func(window application.Window, message string, originInfo *application.OriginInfo) { - fmt.Printf("Raw message from window '%s': %s (origin: %+v)\n", window.Name(), message, originInfo.Origin) - - // Process the message and respond via events - response := processMessage(message) - window.EmitEvent("raw-response", response) - }, - }) - - app.Window.NewWithOptions(application.WebviewWindowOptions{ - Title: "My App", - Name: "main", - }) - - app.Run() -} - -func processMessage(message string) map[string]any { - // Your custom message processing logic - return map[string]any{ - "received": message, - "status": "processed", - } -} -``` - -### Handler Signature - -```go -RawMessageHandler func(window Window, message string, originInfo *application.OriginInfo) -``` - -| Parameter | Type | Description | -|-----------|------|-------------| -| `window` | `Window` | The window that sent the message | -| `message` | `string` | The raw message content | -| `originInfo` | `*application.OriginInfo` | Origin information about the message source | - -#### OriginInfo Structure - -```go -type OriginInfo struct { - Origin string - TopOrigin string - IsMainFrame bool -} -``` - -| Field | Type | Description | -|-------|------|-------------| -| `Origin` | `string` | The origin URL of the document that sent the message | -| `TopOrigin` | `string` | The top-level origin URL (may differ from Origin in iframes) | -| `IsMainFrame` | `bool` | Whether the message originated from the main frame | - -#### Platform-Specific Availability - -- **macOS**: `Origin` and `IsMainFrame` are provided -- **Windows**: `Origin` and `TopOrigin` are provided -- **Linux**: Only `Origin` is provided - -### Origin Validation - -:::caution -Never assume a message is safe because it arrives in your handler. The origin information must be validated before processing sensitive operations or operations that modify state. -::: - -**Always verify the origin of incoming messages before processing them.** The `originInfo` parameter provides critical security information that must be validated to prevent unauthorized access. -Malicious content, compromised content, or unintended scripts could send raw messages. Without origin validation, you may process commands from untrusted sources. Use `originInfo` to ensure messages come from expected sources. - -### Key Validation Points - -- **Always check `Origin`** - Verify the origin matches your expected trusted sources (typically `wails://wails` or `http://wails.localhost` for local assets or your app's specific origin) -- **Validate `IsMainFrame`** (macOS) - Be aware if the message comes from an iframe, as this may indicate embedded content with different security contexts -- **Use `TopOrigin`** (Windows) - Verify the top-level origin when dealing with framed content -- **Reject unexpected origins** - Fail securely by rejecting messages from origins you don't explicitly allow - - -:::note -Messages prefixed with `wails:` are reserved for internal Wails communication and will not be passed to your handler. -::: - -## Frontend Setup - -Send raw messages using `System.invoke()`: - -```html - - - - - - - - - - -``` - -### Using the Pre-built Bundle - -If you're not using npm, access `invoke` via the global `wails` object: - -```html - - -``` - -## Structured Messages - -For complex data, serialize to JSON: - -### Frontend - -```javascript -import { System } from '@wailsio/runtime' - -const command = { - action: 'update', - payload: { - id: 123, - value: 'new value' - } -} - -System.invoke(JSON.stringify(command)) -``` - -### Backend - -```go -RawMessageHandler: func(window application.Window, message string, originInfo *application.OriginInfo) { - var cmd struct { - Action string `json:"action"` - Payload struct { - ID int `json:"id"` - Value string `json:"value"` - } `json:"payload"` - } - - if err := json.Unmarshal([]byte(message), &cmd); err != nil { - window.EmitEvent("error", err.Error()) - return - } - - switch cmd.Action { - case "update": - // Handle update - result := handleUpdate(cmd.Payload.ID, cmd.Payload.Value) - window.EmitEvent("update-complete", result) - default: - window.EmitEvent("error", "unknown action") - } -} -``` - -## Performance Comparison - -| Approach | Overhead | Type Safety | Use Case | -|----------|----------|-------------|----------| -| Service Bindings | Higher | Full | General purpose | -| Raw Messages | Minimal | Manual | High-frequency, performance-critical | - -### Benchmark Example - -Raw messages can process significantly more messages per second compared to service bindings for simple payloads: - -```go -// Raw message handler - minimal overhead -RawMessageHandler: func(window application.Window, message string, originInfo *application.OriginInfo) { - // Direct string processing, no reflection or marshaling - counter++ -} -``` - -## Complete Example - -Here's a full example implementing a simple command protocol: - -### main.go - -```go -package main - -import ( - "embed" - "encoding/json" - "fmt" - "time" - - "github.com/wailsapp/wails/v3/pkg/application" -) - -//go:embed assets -var assets embed.FS - -type Command struct { - Type string `json:"type"` - Data json.RawMessage `json:"data"` -} - -func main() { - app := application.New(application.Options{ - Name: "Raw Message Demo", - Assets: application.AssetOptions{ - Handler: application.BundledAssetFileServer(assets), - }, - Mac: application.MacOptions{ - ApplicationShouldTerminateAfterLastWindowClosed: true, - }, - RawMessageHandler: func(window application.Window, message string, originInfo *application.OriginInfo) { - var cmd Command - if err := json.Unmarshal([]byte(message), &cmd); err != nil { - window.EmitEvent("error", map[string]string{"error": err.Error()}) - return - } - - switch cmd.Type { - case "ping": - window.EmitEvent("pong", map[string]any{ - "time": time.Now().UnixMilli(), - "window": window.Name(), - }) - case "echo": - var text string - json.Unmarshal(cmd.Data, &text) - window.EmitEvent("echo", text) - default: - window.EmitEvent("error", map[string]string{ - "error": fmt.Sprintf("unknown command: %s", cmd.Type), - }) - } - }, - }) - - app.Window.NewWithOptions(application.WebviewWindowOptions{ - Title: "Raw Message Demo", - Name: "main", - Width: 400, - Height: 300, - }) - - app.Run() -} -``` - -### assets/index.html - -```html - - - - Raw Message Demo - - - -

      Raw Message Demo

      - - - - -
      Waiting for response...
      - - - - -``` - -## Best Practices - -### Do - -- Use raw messages for genuinely performance-critical paths -- Implement proper error handling in your handler -- Use events to send responses back to the frontend -- Consider JSON for structured data -- Keep message processing fast to avoid blocking - -### Don't - -- Use raw messages when service bindings would suffice -- Forget to validate incoming messages -- Block in the handler with long-running operations (use goroutines) -- Ignore the window parameter when responses need to target specific windows - -## Multi-Window Considerations - -The `window` parameter identifies which window sent the message, allowing you to: - -- Send responses to the correct window -- Implement window-specific behavior -- Track message sources for debugging - -```go -RawMessageHandler: func(window application.Window, message string, originInfo *application.OriginInfo) { - // Respond only to the sending window - window.EmitEvent("response", result) - - // Or broadcast to all windows - app.Event.Emit("broadcast", result) -} -``` - -## Next Steps - -- [Service Bindings](/features/bindings/services) - Standard approach for most applications -- [Events](/guides/events-reference) - Event system for backend-to-frontend communication -- [Performance](/guides/performance) - General performance optimization diff --git a/docs/src/content/docs/guides/security.mdx b/docs/src/content/docs/guides/security.mdx deleted file mode 100644 index 51bc21b3e..000000000 --- a/docs/src/content/docs/guides/security.mdx +++ /dev/null @@ -1,261 +0,0 @@ ---- -title: Security Best Practices -description: Secure your Wails application -sidebar: - order: 8 ---- - -## Overview - -Security is critical for desktop applications. Follow these practices to keep your application secure. - -## Input Validation - -### Always Validate - -```go -func (s *UserService) CreateUser(email, password string) (*User, error) { - // Validate email - if !isValidEmail(email) { - return nil, errors.New("invalid email") - } - - // Validate password strength - if len(password) < 8 { - return nil, errors.New("password too short") - } - - // Sanitise input - email = strings.TrimSpace(email) - email = html.EscapeString(email) - - // Continue... -} -``` - -### Sanitise HTML - -```go -import "html" - -func (s *Service) SaveComment(text string) error { - // Escape HTML - text = html.EscapeString(text) - - // Validate length - if len(text) > 1000 { - return errors.New("comment too long") - } - - return s.db.Save(text) -} -``` - -## Authentication - -### Secure Password Storage - -```go -import "golang.org/x/crypto/bcrypt" - -func hashPassword(password string) (string, error) { - hash, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost) - return string(hash), err -} - -func verifyPassword(hash, password string) bool { - err := bcrypt.CompareHashAndPassword([]byte(hash), []byte(password)) - return err == nil -} -``` - -### Session Management - -```go -type Session struct { - UserID int - Token string - ExpiresAt time.Time -} - -func (a *AuthService) CreateSession(userID int) (*Session, error) { - token := generateSecureToken() - - session := &Session{ - UserID: userID, - Token: token, - ExpiresAt: time.Now().Add(24 * time.Hour), - } - - return session, a.saveSession(session) -} -``` - -## Data Protection - -### Encrypt Sensitive Data - -```go -import "crypto/aes" -import "crypto/cipher" - -func encrypt(data []byte, key []byte) ([]byte, error) { - block, err := aes.NewCipher(key) - if err != nil { - return nil, err - } - - gcm, err := cipher.NewGCM(block) - if err != nil { - return nil, err - } - - nonce := make([]byte, gcm.NonceSize()) - return gcm.Seal(nonce, nonce, data, nil), nil -} -``` - -### Secure Storage - -```go -// Use OS keychain for sensitive data -import "github.com/zalando/go-keyring" - -func saveAPIKey(key string) error { - return keyring.Set("myapp", "api_key", key) -} - -func getAPIKey() (string, error) { - return keyring.Get("myapp", "api_key") -} -``` - -## Network Security - -### Use HTTPS - -```go -func makeAPICall(url string) (*Response, error) { - // Always use HTTPS - if !strings.HasPrefix(url, "https://") { - return nil, errors.New("only HTTPS allowed") - } - - return http.Get(url) -} -``` - -### Verify Certificates - -```go -import "crypto/tls" - -func secureClient() *http.Client { - return &http.Client{ - Transport: &http.Transport{ - TLSClientConfig: &tls.Config{ - MinVersion: tls.VersionTLS12, - }, - }, - } -} -``` - -## File Operations - -### Validate Paths - -```go -func readFile(path string) ([]byte, error) { - // Prevent path traversal - if strings.Contains(path, "..") { - return nil, errors.New("invalid path") - } - - // Check file exists in allowed directory - absPath, err := filepath.Abs(path) - if err != nil { - return nil, err - } - - if !strings.HasPrefix(absPath, allowedDir) { - return nil, errors.New("access denied") - } - - return os.ReadFile(absPath) -} -``` - -## Rate Limiting - -```go -type RateLimiter struct { - requests map[string][]time.Time - mu sync.Mutex - limit int - window time.Duration -} - -func (r *RateLimiter) Allow(key string) bool { - r.mu.Lock() - defer r.mu.Unlock() - - now := time.Now() - - // Clean old requests - var recent []time.Time - for _, t := range r.requests[key] { - if now.Sub(t) < r.window { - recent = append(recent, t) - } - } - - if len(recent) >= r.limit { - return false - } - - r.requests[key] = append(recent, now) - return true -} -``` - -## Best Practices - -### ✅ Do - -- Validate all input -- Use HTTPS for network calls -- Encrypt sensitive data -- Use secure password hashing -- Implement rate limiting -- Keep dependencies updated -- Log security events -- Use OS keychains - -### ❌ Don't - -- Don't trust user input -- Don't store passwords in plain text -- Don't hardcode secrets -- Don't skip certificate verification -- Don't expose sensitive data in logs -- Don't use weak encryption -- Don't ignore security updates - -## Security Checklist - -- [ ] All user input validated -- [ ] Passwords hashed with bcrypt -- [ ] Sensitive data encrypted -- [ ] HTTPS used for all network calls -- [ ] Rate limiting implemented -- [ ] File paths validated -- [ ] Dependencies up to date -- [ ] Security logging enabled -- [ ] Error messages don't leak info -- [ ] Code reviewed for vulnerabilities - -## Next Steps - -- [Architecture](/guides/architecture) - Application architecture patterns -- [Best Practices](/features/bindings/best-practices) - Bindings best practices diff --git a/docs/src/content/docs/guides/server-build.mdx b/docs/src/content/docs/guides/server-build.mdx deleted file mode 100644 index d0a9bcd73..000000000 --- a/docs/src/content/docs/guides/server-build.mdx +++ /dev/null @@ -1,353 +0,0 @@ ---- -title: Server Build -description: Run Wails applications as HTTP servers without a native GUI window -sidebar: - order: 52 - badge: - text: Experimental - variant: caution ---- - -import { Aside } from '@astrojs/starlight/components'; - - - -Wails v3 supports server mode, allowing you to run your application as a pure HTTP server without creating native windows or requiring GUI dependencies. This enables deploying the same Wails application to servers, containers, and web browsers. - -## Overview - -Server mode is useful for: - -- **Docker/Container deployments** - Run without X11/Wayland dependencies -- **Server-side applications** - Deploy as a web server accessible via browser -- **Web-only access** - Share the same codebase between desktop and web -- **CI/CD testing** - Run integration tests without a display server -- **Microservices** - Use Wails bindings in headless backend services - -## Quick Start - -Server mode is enabled via the `server` build tag. Your application code remains the same - you just build with the tag: - -```bash -# Using Taskfile (recommended) -wails3 task build:server -wails3 task run:server - -# Or build directly with Go -go build -tags server -o myapp-server . -``` - -Here's a minimal example: - -```go -package main - -import ( - "embed" - "log" - - "github.com/wailsapp/wails/v3/pkg/application" -) - -//go:embed frontend/dist -var assets embed.FS - -func main() { - app := application.New(application.Options{ - Name: "My App", - // Server options are used when built with -tags server - Server: application.ServerOptions{ - Host: "localhost", - Port: 8080, - }, - Services: []application.Service{ - application.NewService(&MyService{}), - }, - Assets: application.AssetOptions{ - Handler: application.AssetFileServerFS(assets), - }, - }) - - log.Println("Starting application...") - if err := app.Run(); err != nil { - log.Fatal(err) - } -} -``` - -The same code can be built for desktop (without the tag) or server mode (with `-tags server`). - -## Configuration - -### ServerOptions - -Configure the HTTP server with `ServerOptions`: - -```go -Server: application.ServerOptions{ - // Host to bind to. Default: "localhost" - // Use "0.0.0.0" to listen on all interfaces - Host: "localhost", - - // Port to listen on. Default: 8080 - Port: 8080, - - // Request read timeout. Default: 30s - ReadTimeout: 30 * time.Second, - - // Response write timeout. Default: 30s - WriteTimeout: 30 * time.Second, - - // Idle connection timeout. Default: 120s - IdleTimeout: 120 * time.Second, - - // Graceful shutdown timeout. Default: 30s - ShutdownTimeout: 30 * time.Second, - - // TLS configuration (optional) - TLS: &application.TLSOptions{ - CertFile: "/path/to/cert.pem", - KeyFile: "/path/to/key.pem", - }, -}, -``` - -## Features - -### Health Check Endpoint - -A health check endpoint is automatically available at `/health`: - -```bash -curl http://localhost:8080/health -# {"status":"ok"} -``` - -This is useful for: -- Kubernetes liveness/readiness probes -- Load balancer health checks -- Monitoring systems - -### Service Bindings - -All service bindings work identically to desktop mode: - -```go -type GreetService struct{} - -func (g *GreetService) Greet(name string) string { - return "Hello, " + name + "!" -} - -// Register in options -Services: []application.Service{ - application.NewService(&GreetService{}), -}, -``` - -The frontend can call these bindings using the standard Wails runtime: - -```javascript -const greeting = await wails.Call.ByName('main.GreetService.Greet', 'World'); -``` - -### Events - -Events work bidirectionally in server mode: - -- **Frontend to Backend**: Events emitted from the browser are sent via HTTP and received by your Go event handlers -- **Backend to Frontend**: Events emitted from Go are broadcast to all connected browsers via WebSocket - -Each browser tab is represented as a "window" with a unique name (`browser-1`, `browser-2`, etc.), accessible via `event.Sender`: - -```go -// Listen for events from browsers -app.Event.On("user-action", func(event *application.CustomEvent) { - log.Printf("Event from %s: %v", event.Sender, event.Data) - // event.Sender will be "browser-1", "browser-2", etc. -}) - -// Emit events to all connected browsers -app.Event.Emit("server-update", data) -``` - -From the frontend: - -```javascript -// Emit event to server (and all other browsers) -await wails.Events.Emit('user-action', { action: 'click' }); - -// Listen for events from server -wails.Events.On('server-update', (event) => { - console.log('Update from server:', event.data); -}); -``` - -### Graceful Shutdown - -The server handles `SIGINT` and `SIGTERM` signals gracefully: - -1. Stops accepting new connections -2. Waits for active requests to complete (up to `ShutdownTimeout`) -3. Runs `OnShutdown` hooks -4. Shuts down services in reverse order - -## Differences from Desktop Mode - -| Feature | Desktop Mode | Server Mode | -|---------|-------------|-------------| -| Native windows | Created | Browser windows (`browser-N`) | -| System tray | Available | Not available | -| Native dialogs | Available | Not available | -| Application menu | Available | Not available | -| Screen info | Available | Returns error | -| Service bindings | Works | Works | -| Events | Works | Works (via WebSocket) | -| Assets | Via webview | Via HTTP | -| CGO required | Yes | No | - -### Window API Behavior - -In server mode, window-related APIs are safely handled: - -- `app.Window.NewWithOptions()` - Logs a warning, returns nil -- `app.Hide()` / `app.Show()` - No-op -- `app.Screen.GetPrimary()` - Returns error - -This allows code that references windows to run without crashing, though window operations have no effect. - -## Building for Production - -### Using Task (Recommended) - -Projects created with `wails3 init` include a `build:server` task: - -```bash -# Build for server mode -wails3 task build:server - -# Build and run -wails3 task run:server -``` - -### Manual Build - -```bash -# Build with server mode -go build -tags server -o myapp-server . -``` - -### Docker - -Wails projects include a ready-to-use Docker setup. To build and run your application in a container: - -```bash -# Build the Docker image -wails3 task build:docker - -# Run it -wails3 task run:docker -``` - -That's it! Your application will be available at `http://localhost:8080`. - -You can customise the build with a few options: - -```bash -# Use a custom image tag -wails3 task build:docker TAG=myapp:v1.0.0 - -# Run on a different port -wails3 task run:docker PORT=3000 -``` - -The generated `Dockerfile.server` creates a minimal image based on distroless. It handles the network binding automatically, so your application will be accessible from outside the container. - -### Docker Compose - -For more complex deployments, here's a Docker Compose configuration with health checks: - -```yaml -services: - app: - build: . - ports: - - "8080:8080" - environment: - - WAILS_SERVER_HOST=0.0.0.0 - healthcheck: - test: ["CMD", "wget", "-q", "--spider", "http://localhost:8080/health"] - interval: 30s - timeout: 10s - retries: 3 -``` - -:::note -The healthcheck example uses `wget`. If you're using a distroless base image, you'll need to either include a healthcheck binary in your image or use an external health check mechanism (e.g., Docker's `curl` option or a sidecar container). -::: - -### Custom Dockerfile - -If you need more control, you can create your own Dockerfile. The key thing to remember is setting `WAILS_SERVER_HOST=0.0.0.0` so the server accepts connections from outside the container: - -```dockerfile -# Build stage -FROM golang:alpine AS builder -WORKDIR /app -RUN apk add --no-cache git -COPY . . -RUN go mod tidy -RUN go build -tags server -ldflags="-s -w" -o server . - -# Runtime stage -FROM gcr.io/distroless/static-debian12 -COPY --from=builder /app/server /server -COPY --from=builder /app/frontend/dist /frontend/dist -EXPOSE 8080 -ENV WAILS_SERVER_HOST=0.0.0.0 -ENTRYPOINT ["/server"] -``` - -## Security Considerations - -When deploying server mode applications: - -1. **Bind to localhost by default** - Only use `0.0.0.0` when needed -2. **Use TLS in production** - Configure `ServerOptions.TLS` -3. **Place behind reverse proxy** - Use nginx/traefik for additional security -4. **Validate all inputs** - Same security practices as any web application - -## Example - -A complete example is available at `v3/examples/server/`: - -```bash -cd v3/examples/server - -# Using Taskfile -task dev - -# Or run directly -go run -tags server . - -# Open http://localhost:8080 in browser -``` - -## Environment Variables - -For deployment scenarios where you need to override the server configuration without changing code, Wails recognises these environment variables: - -| Variable | Description | Default | -|----------|-------------|---------| -| `WAILS_SERVER_HOST` | Network interface to bind to | `localhost` | -| `WAILS_SERVER_PORT` | Port to listen on | `8080` | - -These take precedence over the `ServerOptions` in your code, which is why the Docker examples set `WAILS_SERVER_HOST=0.0.0.0` - it allows the container to accept external connections without requiring any changes to your application. - -## See Also - -- [Custom Transport](/docs/guides/custom-transport) - For advanced IPC customization -- [Services](/docs/concepts/services) - Service binding documentation -- [Events](/docs/guides/events-reference) - Event system documentation diff --git a/docs/src/content/docs/guides/single-instance.mdx b/docs/src/content/docs/guides/single-instance.mdx deleted file mode 100644 index 25b7fac47..000000000 --- a/docs/src/content/docs/guides/single-instance.mdx +++ /dev/null @@ -1,119 +0,0 @@ ---- -title: Single Instance -description: Limiting your app to a single running instance -sidebar: - order: 40 ---- - -import { Tabs, TabItem } from "@astrojs/starlight/components"; - -Single instance locking is a mechanism that prevents multiple instances of your app from running at the same time. -It is useful for apps that are designed to open files from the command line or from the OS file explorer. - - -## Usage - -To enable single instance functionality in your app, provide a `SingleInstanceOptions` struct when creating your application: - -```go -app := application.New(application.Options{ - // ... other options ... - SingleInstance: &application.SingleInstanceOptions{ - UniqueID: "com.myapp.unique-id", - OnSecondInstanceLaunch: func(data application.SecondInstanceData) { - log.Printf("Second instance launched with args: %v", data.Args) - log.Printf("Working directory: %s", data.WorkingDir) - log.Printf("Additional data: %v", data.AdditionalData) - }, - // Optional: Pass additional data to second instance - AdditionalData: map[string]string{ - "launchtime": time.Now().String(), - }, - }, -}) -``` - -The `SingleInstanceOptions` struct has the following fields: - -- `UniqueID`: A unique identifier for your application. This should be a unique string, typically in reverse domain notation (e.g., "com.company.appname"). -- `EncryptionKey`: Optional 32-byte array for encrypting data passed between instances using AES-256-GCM. If provided as a non-zero array, all communication between instances will be encrypted. -- `OnSecondInstanceLaunch`: A callback function that is called when a second instance of your app is launched. The callback receives a `SecondInstanceData` struct containing: - - `Args`: The command line arguments passed to the second instance - - `WorkingDir`: The working directory of the second instance - - `AdditionalData`: Any additional data passed from the second instance (if provided) -- `AdditionalData`: Optional map of string key-value pairs that will be passed to the first instance when subsequent instances are launched - -:::danger[Warning] -The Single Instance feature implements an optional encryption protocol using AES-256-GCM. Without encryption enabled, -data passed between instances is not secure. When using the single instance feature without encryption, -your app should treat any data passed to it from second instance callback as untrusted. -You should verify that args that you receive are valid and don't contain any malicious data. -::: - -### Secure Communication - -To enable secure communication between instances, provide a 32-byte encryption key. This key must be the same for all instances of your application: - -```go -// Define your encryption key (must be exactly 32 bytes) -var encryptionKey = [32]byte{ - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, - 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, -} - -// Use the key in SingleInstanceOptions -SingleInstance: &application.SingleInstanceOptions{ - UniqueID: "com.myapp.unique-id", - // Enable encryption for instance communication - EncryptionKey: encryptionKey, - // ... other options ... -} -``` - -:::tip[Security Best Practices] -- Use a unique key for your application -- Store the key securely if loading it from configuration -- Do not use the example key shown above - create your own! -::: - -### Window Management - -When handling second instance launches, you'll often want to bring your application window to the front. You can do this using the window's `Focus()` method. If your window is minimized, you may need to restore it first: - -```go - - var mainWindow *application.WebviewWindow - - SingleInstance: &application.SingleInstanceOptions{ - // Other options... - OnSecondInstanceLaunch: func(data application.SecondInstanceData) { - // Focus the window if needed - if mainWindow != nil { - mainWindow.Restore() - mainWindow.Focus() - } - }, - } -``` - -## How it works - - - - - Single instance lock using a named mutex. The mutex name is generated from the unique id that you provide. Data is passed to the first instance via [NSDistributedNotificationCenter](https://developer.apple.com/documentation/foundation/nsdistributednotificationcenter) - - - - - Single instance lock using a named mutex. The mutex name is generated from the unique id that you provide. Data is passed to the first instance via a shared window using [SendMessage](https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-sendmessage) - - - - - Single instance lock using [dbus](https://www.freedesktop.org/wiki/Software/dbus/). The dbus name is generated from the unique id that you provide. Data is passed to the first instance via [dbus](https://www.freedesktop.org/wiki/Software/dbus/) - - - diff --git a/docs/src/content/docs/guides/testing.mdx b/docs/src/content/docs/guides/testing.mdx deleted file mode 100644 index 4bd3a07b8..000000000 --- a/docs/src/content/docs/guides/testing.mdx +++ /dev/null @@ -1,175 +0,0 @@ ---- -title: Testing -description: Test your Wails application -sidebar: - order: 5 ---- - -## Overview - -Testing ensures your application works correctly and prevents regressions. - -## Unit Testing - -### Testing Services - -```go -func TestUserService_Create(t *testing.T) { - service := &UserService{ - users: make(map[string]*User), - } - - user, err := service.Create("john@example.com", "password123") - if err != nil { - t.Fatalf("unexpected error: %v", err) - } - - if user.Email != "john@example.com" { - t.Errorf("expected email john@example.com, got %s", user.Email) - } -} -``` - -### Testing with Mocks - -```go -type MockDB struct { - users map[string]*User -} - -func (m *MockDB) Create(user *User) error { - m.users[user.ID] = user - return nil -} - -func TestUserService_WithMock(t *testing.T) { - mockDB := &MockDB{users: make(map[string]*User)} - service := &UserService{db: mockDB} - - user, err := service.Create("test@example.com", "pass") - if err != nil { - t.Fatal(err) - } - - if len(mockDB.users) != 1 { - t.Error("expected 1 user in mock") - } -} -``` - -## Integration Testing - -### Testing with Real Dependencies - -```go -func TestIntegration(t *testing.T) { - // Setup test database - db, err := sql.Open("sqlite3", ":memory:") - if err != nil { - t.Fatal(err) - } - defer db.Close() - - // Create schema - _, err = db.Exec(`CREATE TABLE users (...)`) - if err != nil { - t.Fatal(err) - } - - // Test service - service := &UserService{db: db} - user, err := service.Create("test@example.com", "password") - if err != nil { - t.Fatal(err) - } - - // Verify in database - var count int - db.QueryRow("SELECT COUNT(*) FROM users").Scan(&count) - if count != 1 { - t.Errorf("expected 1 user, got %d", count) - } -} -``` - -## Frontend Testing - -### JavaScript Unit Tests - -```javascript -// Using Vitest -import { describe, it, expect } from 'vitest' -import { formatDate } from './utils' - -describe('formatDate', () => { - it('formats date correctly', () => { - const date = new Date('2024-01-01') - expect(formatDate(date)).toBe('2024-01-01') - }) -}) -``` - -### Testing Bindings - -```javascript -import { vi } from 'vitest' -import { GetUser } from './bindings/myapp/userservice' - -// Mock the binding -vi.mock('./bindings/myapp/userservice', () => ({ - GetUser: vi.fn() -})) - -describe('User Component', () => { - it('loads user data', async () => { - GetUser.mockResolvedValue({ name: 'John', email: 'john@example.com' }) - - // Test your component - const user = await GetUser(1) - expect(user.name).toBe('John') - }) -}) -``` - -## Best Practices - -### ✅ Do - -- Write tests before fixing bugs -- Test edge cases -- Use table-driven tests -- Mock external dependencies -- Test error handling -- Keep tests fast - -### ❌ Don't - -- Don't skip error cases -- Don't test implementation details -- Don't write flaky tests -- Don't ignore test failures -- Don't skip integration tests - -## Running Tests - -```bash -# Run Go tests -go test ./... - -# Run with coverage -go test -cover ./... - -# Run specific test -go test -run TestUserService - -# Run frontend tests -cd frontend && npm test - -# Run with watch mode -cd frontend && npm test -- --watch -``` - -## Next Steps - -- [End-to-End Testing](/guides/e2e-testing) - Test complete user flows -- [Best Practices](/features/bindings/best-practices) - Learn best practices diff --git a/docs/src/content/docs/guides/windows-uac.mdx b/docs/src/content/docs/guides/windows-uac.mdx deleted file mode 100644 index 5bb380179..000000000 --- a/docs/src/content/docs/guides/windows-uac.mdx +++ /dev/null @@ -1,151 +0,0 @@ ---- -title: Windows UAC Configuration -sidebar: - order: 11 ---- - -import {Badge} from '@astrojs/starlight/components'; - -Relevant Platforms: -
      - -Windows User Account Control (UAC) determines the execution privileges of your Wails application. By default, Wails v3 applications include explicit UAC configuration in their Windows manifest, ensuring consistent behavior across different machines. - -## UAC Execution Levels - -Windows applications can request different execution levels through their manifest file. Wails v3 automatically includes UAC configuration with a default execution level that you can customize based on your application's needs. - -### Available Execution Levels - -| Level | Description | Use Case | -|-------|-------------|----------| -| `asInvoker` | Runs with the same privileges as the parent process | Default for most applications | -| `highestAvailable` | Runs with the highest privileges available to the user | Applications that may need elevated access | -| `requireAdministrator` | Always requires administrator privileges | System utilities, installers | - -### Default Configuration - -Wails v3 applications include a default UAC configuration in their Windows manifest: - -```xml - - - - - - - -``` - -This configuration ensures your application: -- Runs with the same privileges as the launching process -- Does not require elevation by default -- Works consistently across different machines -- Does not trigger UAC prompts for normal users - -## Customizing UAC Configuration - -Since Wails v3 encourages users to customize their build assets, you can modify the UAC configuration by editing your Windows manifest template directly. - -### Locating the Manifest Template - -The Windows manifest template is located at: -``` -build/windows/wails.exe.manifest -``` - -### Modifying the Execution Level - -To change the execution level, edit the `level` attribute in the `requestedExecutionLevel` element: - -```xml title="build/windows/wails.exe.manifest" - - - - - - - -``` - -### Examples - -#### Standard Application (Default) -Most applications should use the default `asInvoker` level: - -```xml - -``` - -#### System Utility -Applications that need elevated access when available: - -```xml - -``` - -#### Administrative Tool -Applications that always require administrator privileges: - -```xml - -``` - -## UI Access - -The `uiAccess` attribute controls whether your application can interact with higher-privilege UI elements. In most cases, this should remain `false`. - -Set to `true` only if your application needs to: -- Send input to other applications -- Drive the UI of other applications -- Access UI elements of higher-privilege processes - -:::caution[UI Access Requirements] -Setting `uiAccess="true"` requires your application to be: -- Digitally signed with a certificate from a trusted certificate authority -- Installed in a secure location (Program Files or Windows\System32) -::: - -## Building with Custom UAC Settings - -After modifying your manifest template, build your application normally: - -```bash -wails3 build -``` - -The build process will automatically embed your custom UAC configuration into the executable. - -## Verifying UAC Configuration - -You can verify that your UAC settings are properly embedded using the `go-winres` tool: - -```bash -go-winres extract --in your-app.exe --out extracted-resources/ -``` - -Then examine the extracted manifest file to confirm your UAC configuration is present. - -:::tip[Manifest Persistence] -Unlike some other frameworks, Wails v3's UAC configuration is embedded directly into the executable during compilation, ensuring it persists when the application is copied to other machines. -::: - -## Troubleshooting - -### UAC Prompts Not Appearing -If you set `requireAdministrator` but don't see UAC prompts: -- Verify the manifest is properly embedded in your executable -- Check that you're not running from an already-elevated process -- Ensure the manifest syntax is valid XML - -### Application Not Starting -If your application fails to start after UAC changes: -- Check the manifest syntax for XML errors -- Verify the execution level value is valid -- Try reverting to `asInvoker` to isolate the issue - -### Inconsistent Behavior Across Machines -If UAC behavior differs between machines: -- Ensure the manifest is embedded in the executable (not external) -- Check that the executable wasn't modified after building -- Verify Windows UAC settings are enabled on the target machine \ No newline at end of file diff --git a/docs/src/content/docs/index.mdx b/docs/src/content/docs/index.mdx deleted file mode 100644 index c5f1c8790..000000000 --- a/docs/src/content/docs/index.mdx +++ /dev/null @@ -1,294 +0,0 @@ ---- -title: Build Desktop Apps with Go -description: "Native desktop applications using Go and web technologies" -banner: - content: | - Wails v3 is in ALPHA. v2 docs -template: splash -hero: - tagline: Build beautiful, performant desktop applications using Go and modern web technologies. One codebase. Three platforms. No browsers. - image: - dark: ../../assets/wails-logo-dark.svg - light: ../../assets/wails-logo-light.svg - alt: Wails Logo - actions: - - text: Get Started - link: /quick-start/installation - icon: right-arrow - variant: primary - - text: View Tutorial - link: /tutorials/03-notes-vanilla - icon: open-book - variant: secondary ---- -{/* Updated 2025-11-23 */} -import { Tabs, TabItem, Card, CardGrid } from "@astrojs/starlight/components"; - - - -## Quickstart - - - -```bash -# Install Wails -go install github.com/wailsapp/wails/v3/cmd/wails3@latest - -# Create your application -wails3 init -n myapp -t vanilla - -# Run with hot reload -cd myapp && wails3 dev -``` - - - -```powershell -# Install Wails -go install github.com/wailsapp/wails/v3/cmd/wails3@latest - -# Create your application -wails3 init -n myapp -t vanilla - -# Run with hot reload -cd myapp; wails3 dev -``` - - - -```bash -# Install Wails -go install github.com/wailsapp/wails/v3/cmd/wails3@latest - -# Create your application -wails3 init -n myapp -t vanilla - -# Run with hot reload -cd myapp && wails3 dev -``` - - - -**Your application is now running** with hot reload and type-safe Go-to-JS bindings. - - -## Why Wails? - - - - - ~15MB binaries vs Electron's 150MB - - ~10MB baseline memory vs 100MB+ - - <0.5s startup time vs 2-3s - - Native rendering using OS WebView - - No bundled browser overhead - - - - - One Go codebase for all platforms - - Any web framework - React, Vue, Svelte - - Hot reload during development - - Auto-generated bindings to easily call Go from Javascript - - In-memory IPC. No network ports - - - - - Multiple windows with lifecycles - - Native menus and system tray - - Platform-native file dialogs - - System integration and shortcuts - - Code signing and packaging tools - - - - - Single codebase for Windows, macOS, Linux - - Platform-specific features when needed - - No compromise on user experience - - Deploy to all platforms from one build - - Mobile coming soon... - - - - - - -## Next Steps - -Next: [Build a complete application](/tutorials/03-notes-vanilla), browse [examples](https://github.com/wailsapp/wails/tree/v3-alpha/v3/examples), or check the [API reference](/reference/application). Migrating from v2? See the [upgrade guide](/migration/v2-to-v3). - - -:::note[Production Ready] -Wails v3 is in **ALPHA**. The API is *reasonably* stable, and applications are running in production. We're refining documentation and tooling before the final release. -::: - - - Wails is free and open source, built by developers for developers. If Wails helps you build amazing applications, consider supporting its continued development. - - Your sponsorship helps maintain the project, improve documentation, and develop new features that benefit the entire community. - - [Become a Sponsor →](https://github.com/sponsors/leaanthony) - - diff --git a/docs/src/content/docs/migration/v2-to-v3.mdx b/docs/src/content/docs/migration/v2-to-v3.mdx deleted file mode 100644 index 5eb94ca67..000000000 --- a/docs/src/content/docs/migration/v2-to-v3.mdx +++ /dev/null @@ -1,727 +0,0 @@ ---- -title: Migrating from v2 to v3 -description: Complete guide to migrating your Wails v2 application to v3 -sidebar: - order: 1 ---- - -import { Card, CardGrid, Tabs, TabItem } from "@astrojs/starlight/components"; - -Wails v3 is a **complete rewrite** with significant improvements in architecture, performance, and developer experience. This guide helps you migrate your v2 application to v3. - -**Key changes:** -- New application structure -- Improved bindings system -- Enhanced window management -- Better event system -- Simplified configuration - -**Migration time:** 1-4 hours for typical applications - -## Breaking Changes - -### Application Initialisation - -In v2, application setup, window configuration, and execution were all combined into a single `wails.Run()` call. This monolithic approach made it difficult to create multiple windows, handle errors at different stages, or test individual components of your application. - -v3 separates these concerns into distinct phases: application creation, window creation, and execution. This separation gives you explicit control over each stage of your application's lifecycle and makes the code more modular and testable. - -**v2:** - -```go -err := wails.Run(&options.App{ - Title: "My App", - Width: 1024, - Height: 768, - Bind: []interface{}{ - &GreetService{}, - }, -}) -``` - -**v3:** - -```go -app := application.New(application.Options{ - Name: "My App", - Services: []application.Service{ - application.NewService(&GreetService{}), - }, -}) - -window := app.Window.NewWithOptions(application.WebviewWindowOptions{ - Title: "My App", - Width: 1024, - Height: 768, -}) - -app.Run() -``` - -**Why this is better:** - -- **Multi-window support**: You can create windows dynamically at any point, not just at startup -- **Better error handling**: Each phase can be validated separately with proper error handling -- **Clearer code**: The separation makes it obvious what's happening at each stage -- **More testable**: You can test application setup without running the event loop -- **More flexible**: Windows can be created, destroyed, and recreated throughout the application lifecycle - -### Bindings - -In v2, every bound struct required a context field and a `startup(ctx)` method to receive the runtime context. This created tight coupling between your business logic and the Wails runtime, making code harder to test and understand. - -v3 introduces the service pattern, where your structs are completely standalone and don't need to store runtime context. If a service needs access to the application instance, it explicitly receives it through dependency injection rather than implicit context threading. - -**v2:** - -```go -type App struct { - ctx context.Context -} - -func (a *App) startup(ctx context.Context) { - a.ctx = ctx -} - -func (a *App) Greet(name string) string { - return "Hello " + name -} -``` - -**v3:** - -```go -type GreetService struct{} - -func (g *GreetService) Greet(name string) string { - return "Hello " + name -} - -// Register as service -app := application.New(application.Options{ - Services: []application.Service{ - application.NewService(&GreetService{}), - }, -}) -``` - -**Why this is better:** - -- **No implicit dependencies**: Services are plain Go structs without hidden runtime dependencies -- **Easier testing**: You can test service methods without mocking a Wails context -- **Clearer code**: Dependencies are explicit (passed as constructor arguments) rather than hidden in a context field -- **Better organization**: Services can be grouped by domain rather than all living in a single `App` struct -- **Proper initialization**: Use `ServiceStartup()` method when you need initialization, making it explicit - -### Runtime - -In v2, all runtime operations required passing a context to global functions from the `runtime` package. This created tight coupling to the context object throughout your codebase and made the API feel procedural rather than object-oriented. - -v3 replaces the context-based runtime with direct method calls on application and window objects. Operations are called directly on the objects they affect, making the code more intuitive and object-oriented. - -**v2:** - -```go -import "github.com/wailsapp/wails/v2/pkg/runtime" - -runtime.WindowSetTitle(a.ctx, "New Title") -runtime.EventsEmit(a.ctx, "event-name", data) -``` - -**v3:** - -```go -// Store app reference -type MyService struct { - app *application.Application -} - -func (s *MyService) UpdateTitle() { - window := s.app.Window.Current() - window.SetTitle("New Title") -} - -func (s *MyService) EmitEvent() { - s.app.Event.Emit("event-name", data) -} -``` - -**Why this is better:** - -- **Object-oriented design**: Methods are called on the objects they affect (window, app, menu, etc.) -- **Clearer intent**: `window.SetTitle()` is more obvious than `runtime.WindowSetTitle(ctx, ...)` -- **Better IDE support**: Autocomplete works properly when methods are on objects -- **Multi-window clarity**: With multiple windows, you explicitly choose which window to operate on -- **No context threading**: You don't need to pass context through every function - -### Frontend Bindings - -In v2, bindings were organized by Go package and struct name, typically resulting in paths like `wailsjs/go/main/App`. This structure didn't reflect logical grouping and made it hard to find related functionality. - -v3 organizes bindings by service name and application module, creating a clearer logical structure. The bindings are generated into a `bindings` directory organized by your application name and service names, making it easier to understand what functionality is available. - -**v2:** - -```javascript -import { Greet } from '../wailsjs/go/main/App' - -const result = await Greet("World") -``` - -**v3:** - -```javascript -import { Greet } from './bindings/myapp/greetservice' - -const result = await Greet("World") -``` - -**Why this is better:** - -- **Logical organization**: Bindings are grouped by service name rather than Go package structure -- **Clearer imports**: The path reflects the domain logic (greetservice) not the file structure (main/App) -- **Better discoverability**: You can navigate bindings by feature rather than by technical structure -- **Consistent naming**: Service-based organization matches your backend architecture -- **Simpler paths**: No more `../wailsjs/go` prefix - just `./bindings` - -### Events - -In v2, events used variadic `interface{}` parameters and required passing context to every event function. Event handlers received untyped data that needed manual type assertions, making the event system error-prone and hard to debug. - -v3 introduces typed event objects and removes the context requirement. Event handlers receive a proper event object with typed data, making the event system more reliable and easier to use. - -**v2:** - -```go -runtime.EventsOn(ctx, "event-name", func(data ...interface{}) { - // Handle event -}) - -runtime.EventsEmit(ctx, "event-name", data) -``` - -**v3:** - -```go -app.Event.On("event-name", func(e *application.CustomEvent) { - data := e.Data - // Handle event -}) - -app.Event.Emit("event-name", data) -``` - -**Why this is better:** - -- **Type safety**: Events use proper event objects instead of `...interface{}` -- **Better debugging**: Event objects contain metadata like event name, making debugging easier -- **Clearer API**: `app.Event.On()` and `app.Event.Emit()` are more intuitive than runtime functions -- **No context needed**: Events work directly on the app object without threading context -- **Simpler handlers**: Event handlers have a clear signature instead of variadic parameters - -### Windows - -v2 supported only a single window per application. The window was created at startup and all window operations were performed through runtime functions that implicitly targeted that single window. - -v3 introduces native multi-window support as a core feature. Each window is a first-class object with its own methods and lifecycle. You can create, manage, and destroy multiple windows dynamically throughout your application's lifetime. - -**v2:** - -```go -// Single window only -runtime.WindowSetSize(ctx, 800, 600) -``` - -**v3:** - -```go -// Multiple windows supported -window1 := app.Window.New() -window1.SetSize(800, 600) - -window2 := app.Window.New() -window2.SetSize(1024, 768) -``` - -**Why this is better:** - -- **Multi-window applications**: Build apps with multiple independent windows (dashboards, preferences, tools, etc.) -- **Explicit window references**: Each window is an object you can store and manipulate directly -- **Dynamic window creation**: Create and destroy windows at any time during runtime -- **Independent window state**: Each window has its own events, properties, and lifecycle -- **Better architecture**: Window management is object-oriented rather than context-based - -## Migration Steps - -### Step 1: Update Dependencies - -**go.mod:** - -```go -module myapp - -go 1.21 - -require ( - github.com/wailsapp/wails/v3 v3.0.0-alpha.1 -) -``` - -**Update:** - -```bash -go get github.com/wailsapp/wails/v3@latest -go mod tidy -``` - -### Step 2: Update main.go - -**v2:** - -```go -package main - -import ( - "embed" - "github.com/wailsapp/wails/v2/pkg/options" - "github.com/wailsapp/wails/v2/pkg/options/assetserver" - "github.com/wailsapp/wails/v2/pkg/options/windows" -) - -//go:embed all:frontend/dist -var assets embed.FS - -func main() { - app := NewApp() - - err := wails.Run(&options.App{ - Title: "My App", - Width: 1024, - Height: 768, - AssetServer: &assetserver.Options{ - Assets: assets, - }, - Bind: []interface{}{ - app, - }, - Windows: &windows.Options{ - WebviewIsTransparent: false, - }, - }) - - if err != nil { - println("Error:", err.Error()) - } -} -``` - -**v3:** - -```go -package main - -import ( - "embed" - "github.com/wailsapp/wails/v3/pkg/application" -) - -//go:embed frontend/dist -var assets embed.FS - -func main() { - app := application.New(application.Options{ - Name: "My App", - Services: []application.Service{ - application.NewService(&MyService{}), - }, - Assets: application.AssetOptions{ - Handler: application.AssetFileServerFS(assets), - }, - }) - - app.Window.NewWithOptions(application.WebviewWindowOptions{ - Title: "My App", - Width: 1024, - Height: 768, - }) - - err := app.Run() - if err != nil { - panic(err) - } -} -``` - -### Step 3: Convert App Struct to Service - -**v2:** - -```go -type App struct { - ctx context.Context -} - -func NewApp() *App { - return &App{} -} - -func (a *App) startup(ctx context.Context) { - a.ctx = ctx - // Initialisation -} - -func (a *App) Greet(name string) string { - return "Hello " + name -} -``` - -**v3:** - -```go -type MyService struct { - app *application.Application -} - -func NewMyService(app *application.Application) *MyService { - return &MyService{app: app} -} - -func (s *MyService) ServiceStartup(ctx context.Context, options application.ServiceOptions) error { - // Initialisation - return nil -} - -func (s *MyService) Greet(name string) string { - return "Hello " + name -} - -// Register after app creation -app := application.New(application.Options{}) -app.RegisterService(application.NewService(NewMyService(app))) -``` - -### Step 4: Update Runtime Calls - -**v2:** - -```go -func (a *App) DoSomething() { - runtime.WindowSetTitle(a.ctx, "New Title") - runtime.EventsEmit(a.ctx, "update", data) - runtime.LogInfo(a.ctx, "Message") -} -``` - -**v3:** - -```go -func (s *MyService) DoSomething() { - window := s.app.Window.Current() - window.SetTitle("New Title") - - s.app.Event.Emit("update", data) - - s.app.Logger.Info("Message") -} -``` - -### Step 5: Update Frontend - -**Generate new bindings:** - -```bash -wails3 generate bindings -``` - -**Update imports:** - -```javascript -// v2 -import { Greet } from '../wailsjs/go/main/App' - -// v3 -import { Greet } from './bindings/myapp/myservice' -``` - -**Update event handling:** - -```javascript -// v2 -import { EventsOn, EventsEmit } from '../wailsjs/runtime/runtime' - -EventsOn("update", (data) => { - console.log(data) -}) - -EventsEmit("action", data) - -// v3 -import { OnEvent, Emit } from '@wailsio/runtime' - -OnEvent("update", (data) => { - console.log(data) -}) - -Emit("action", data) -``` - -### Step 6: Update Configuration - -**v2 (wails.json):** - -```json -{ - "name": "myapp", - "outputfilename": "myapp", - "frontend:install": "npm install", - "frontend:build": "npm run build", - "frontend:dev:watcher": "npm run dev", - "frontend:dev:serverUrl": "auto" -} -``` - -**v3 (wails.json):** - -```json -{ - "name": "myapp", - "frontend": { - "dir": "./frontend", - "install": "npm install", - "build": "npm run build", - "dev": "npm run dev", - "devServerUrl": "http://localhost:5173" - } -} -``` - -## Feature Mapping - -### dialogs - -**v2:** - -```go -selection, err := runtime.OpenFileDialog(ctx, runtime.OpenDialogOptions{ - Title: "Select File", -}) -``` - -**v3:** - -```go -selection, err := app.Dialog.OpenFile(application.OpenFileDialogOptions{ - Title: "Select File", -}) -``` - -### Menus - -**v2:** - -```go -menu := menu.NewMenu() -menu.Append(menu.Text("File", nil, []*menu.MenuItem{ - menu.Text("Quit", nil, func(_ *menu.CallbackData) { - runtime.Quit(ctx) - }), -})) -``` - -**v3:** - -```go -menu := app.NewMenu() -fileMenu := menu.AddSubmenu("File") -fileMenu.Add("Quit").OnClick(func(ctx *application.Context) { - app.Quit() -}) -``` - -### System Tray - -**v2:** - -```go -// Not available in v2 -``` - -**v3:** - -```go -systray := app.SystemTray.New() -systray.SetIcon(iconBytes) -systray.SetLabel("My App") - -menu := app.NewMenu() -menu.Add("Show").OnClick(showWindow) -menu.Add("Quit").OnClick(app.Quit) -systray.SetMenu(menu) -``` - -## Common Issues - -### Issue: Bindings not found - -**Problem:** Import errors after migration - -**Solution:** - -```bash -# Regenerate bindings -wails3 generate bindings - -# Check output directory -ls frontend/bindings -``` - -### Issue: Context errors - -**Problem:** `ctx` not available - -**Solution:** - -Store app reference instead: - -```go -type MyService struct { - app *application.Application -} - -func NewMyService(app *application.Application) *MyService { - return &MyService{app: app} -} -``` - -### Issue: Window methods not working - -**Problem:** `runtime.WindowSetTitle()` doesn't exist - -**Solution:** - -Use window methods directly: - -```go -window := s.app.Window.Current() -window.SetTitle("New Title") -``` - -### Issue: Events not firing - -**Problem:** Events registered but not received - -**Solution:** - -Check event names match exactly: - -```go -// Go -app.Event.Emit("my-event", data) - -// JavaScript -OnEvent("my-event", handler) // Must match exactly -``` - -## Testing Migration - -### Checklist - -- [ ] Application starts without errors -- [ ] All bindings work -- [ ] Events are sent and received -- [ ] Windows open and close correctly -- [ ] Menus work (if applicable) -- [ ] dialogs work (if applicable) -- [ ] System tray works (if applicable) -- [ ] Build process works -- [ ] Production build works - -### Test Commands - -```bash -# Development -wails3 dev - -# Build -wails3 build - -# Generate bindings -wails3 generate bindings -``` - -## Benefits of v3 - -### Performance - -- **Faster startup** - Optimised initialisation -- **Lower memory** - Efficient resource usage -- **Better bridge** - <1ms call overhead - -### Features - -- **Multi-window** - Native support -- **System tray** - Built-in -- **Better events** - Typed, simpler API -- **Services** - Better code organisation - -### Developer Experience - -- **Type safety** - Full TypeScript support -- **Better errors** - Clear error messages -- **Hot reload** - Faster development -- **Better docs** - Comprehensive guides - -## Getting Help - -### Resources - -- [Documentation](/quick-start/why-wails) -- [Discord Community](https://discord.gg/JDdSxwjhGf) -- [GitHub Issues](https://github.com/wailsapp/wails/issues) -- [Examples](https://github.com/wailsapp/wails/tree/v3-alpha/v3/examples) - -### Common Questions - -**Q: Can I run v2 and v3 side by side?** -A: Yes, they use different import paths. - -**Q: Is v3 production-ready?** -A: v3 is in alpha/beta. Test thoroughly before production. - -**Q: Will v2 be maintained?** -A: Yes, v2 will receive critical updates. - -**Q: How long does migration take?** -A: 1-4 hours for typical applications. - -## Next Steps - - - - Get started with Wails v3. - - [Learn More →](/quick-start/installation) - - - - Understand v3 architecture. - - [Learn More →](/concepts/architecture) - - - - Learn the new bindings system. - - [Learn More →](/features/bindings/methods) - - - - See complete v3 examples. - - [View Examples →](https://github.com/wailsapp/wails/tree/v3-alpha/v3/examples) - - - ---- - -**Questions?** Ask in [Discord](https://discord.gg/JDdSxwjhGf) or [open an issue](https://github.com/wailsapp/wails/issues). diff --git a/docs/src/content/docs/quick-start/first-app.mdx b/docs/src/content/docs/quick-start/first-app.mdx deleted file mode 100644 index 204fed2f8..000000000 --- a/docs/src/content/docs/quick-start/first-app.mdx +++ /dev/null @@ -1,270 +0,0 @@ ---- -title: Your First App -description: Build a working Wails application in 10 minutes -sidebar: - order: 3 ---- - -import { Tabs, TabItem, Steps } from "@astrojs/starlight/components"; - -We will build a simple greeting application that demonstrates the core Wails concepts: -- Go backend managing logic -- Frontend calling Go functions -- Type-safe bindings -- Hot reload during development - -**Time to complete:** 10 minutes - -:::tip[Performance Tip for Windows 11 Users] -Consider using [Dev Drive](https://learn.microsoft.com/en-us/windows/dev-drive/) to store your projects. Dev Drives are optimized for developer workloads and can significantly improve build times and disk access speeds by up to 30% compared to regular NTFS drives. -::: - -## Create Your Project - - - -1. **Generate the project** - - ```bash - wails3 init -n myapp - cd myapp - ``` - - This creates a new project with the default Vanilla + Vite template (plain HTML/CSS/JS with Vite bundler). - - :::tip[Other Templates] - Try `-t react`, `-t vue`, or `-t svelte` for your preferred framework. - Run `wails3 init -l` to see all available templates. - ::: - -2. **Understand the project structure** - - ``` - myapp/ - ├── main.go # Application entry point - ├── greetservice.go # Greet service - ├── frontend/ # Your UI code - │ ├── index.html # HTML entry point - │ ├── src/ - │ │ └── main.js # Frontend JavaScript - │ ├── public/ - │ │ └── style.css # Styles - │ ├── package.json # Frontend dependencies - │ └── vite.config.js # Vite bundler config - ├── build/ # Build configuration - └── Taskfile.yml # Build tasks - ``` - -3. **Run the app** - - ```bash - wails3 dev - ``` - - :::note[First Run] - The first run may take longer than expected as it installs frontend dependencies, generates bindings, etc. Subsequent runs are much faster. - ::: - - The app opens showing a greeting interface. Enter your name and click "Greet" - the Go backend processes your input and returns a greeting. - - - -## How It Works - -Let's understand the code that makes this work. - -### The Go Backend - -Open `greetservice.go`: - -```go title="greetservice.go" -package main - -import ( - "fmt" -) - -type GreetService struct{} - -func (g *GreetService) Greet(name string) string { - return fmt.Sprintf("Hello %s, It's show time!", name) -} -``` - -**Key concepts:** - -1. **Service** - A Go struct with exported methods -2. **Exported method** - `Greet` is capitalized, making it available to the frontend -3. **Simple logic** - Takes a name, returns a greeting -4. **Type safety** - Input and output types are defined - -:::tip[Understanding Services and Bindings] -**Services** are self-contained Go modules that expose functionality to your frontend. They're just regular Go structs with exported methods that you register in the `Services` field of your application config. - -**Bindings** are the auto-generated TypeScript/JavaScript SDK that lets your frontend call these services. When you run `wails3 dev` or `wails3 build`, Wails analyzes your registered services and generates type-safe bindings in `frontend/bindings/`. - -Think of services as your backend API, and bindings as the client library that talks to it. -::: - -### Registering the Service - -Open `main.go` and find the service registration: - -```go title="main.go" {4-6} -err := application.New(application.Options{ - Name: "myapp", - Services: []application.Service{ - application.NewService(&GreetService{}), - }, - // ... other options -}) -``` - -This registers your `GreetService` with Wails, making all its exported methods available to the frontend. - -### The Frontend - -Open `frontend/src/main.js`: - -```javascript title="frontend/src/main.js" -import {GreetService} from "../bindings/changeme"; - -window.greet = async () => { - const nameElement = document.getElementById('name'); - const resultElement = document.getElementById('result'); - - const name = nameElement.value; - if (!name) { - return; - } - - try { - const result = await GreetService.Greet(name); - resultElement.innerText = result; - } catch (err) { - console.error(err); - } -}; -``` - -**Key concepts:** - -1. **Auto-generated bindings** - `GreetService` is imported from generated code -2. **Type-safe calls** - Method names and signatures match your Go code -3. **Async by default** - All Go calls return Promises -4. **Error handling** - Errors from Go are caught in try/catch - -:::note[Where are the bindings?] -Generated bindings are in `frontend/bindings/`. They're created automatically when you run `wails3 dev` or `wails3 build`. - -**Never edit these files manually**—they're regenerated on every build. -::: - -## Customize Your App - -Let's add a new feature to understand the workflow. - -### Add a "Greet Many" Feature - - - -1. **Add the method to GreetService** - - Add this to `greetservice.go`: - - ```go title="greetservice.go" - func (g *GreetService) GreetMany(names []string) []string { - greetings := make([]string, len(names)) - for i, name := range names { - greetings[i] = fmt.Sprintf("Hello %s!", name) - } - return greetings - } - ``` - -2. **The app will auto-rebuild** - - Save the file and `wails3 dev` will automatically rebuild your Go code and restart the app. - - :::note[Auto-Rebuild] - Go code changes trigger an automatic rebuild and restart. Frontend changes hot-reload without restart. - ::: - -3. **Use it in the frontend** - - Add this to `frontend/src/main.js`: - - ```javascript title="frontend/src/main.js" - window.greetMany = async () => { - const names = ['Alice', 'Bob', 'Charlie']; - const greetings = await GreetService.GreetMany(names); - console.log(greetings); - }; - ``` - - Open the browser console and call `greetMany()` - you'll see the array of greetings. - - - -## Build for Production - -When you're ready to distribute your app: - -```bash -wails3 build -``` - -**What this does:** -- Compiles Go code with optimizations -- Builds frontend for production (minified) -- Creates a native executable in `build/bin/` - - - - **Output:** `build/bin/myapp.exe` - - Double-click to run. No dependencies needed (WebView2 is part of Windows). - - - - **Output:** `build/bin/myapp.app` - - Drag to Applications folder or double-click to run. - - - - **Output:** `build/bin/myapp` - - Run with `./build/bin/myapp` or create a `.desktop` file for your launcher. - - - -:::tip[Cross-Platform Builds] -Want to build for other platforms? See [Cross-Platform Builds →](/guides/build/cross-platform) -::: - -## What we've learned - -**Project Structure** -- `main.go` for Go backend -- `frontend/` for UI code -- `Taskfile.yml` for build tasks - -**Services** -- Create Go structs with exported methods -- Register with `application.NewService()` -- Methods automatically available in frontend - -**Bindings** -- Auto-generated TypeScript definitions -- Type-safe function calls -- Async by default (Promises) - -**Development Workflow** -- `wails3 dev` for hot reload -- Go changes auto-rebuild and restart -- Frontend changes hot-reload instantly - ---- - -**Questions?** Join [Discord](https://discord.gg/JDdSxwjhGf) and ask the community. diff --git a/docs/src/content/docs/quick-start/installation.mdx b/docs/src/content/docs/quick-start/installation.mdx deleted file mode 100644 index 20bdc51ba..000000000 --- a/docs/src/content/docs/quick-start/installation.mdx +++ /dev/null @@ -1,402 +0,0 @@ ---- -title: Installation -description: Get Wails installed and ready to build applications -sidebar: - order: 2 ---- - -import { Card, CardGrid, Tabs, TabItem, Steps } from "@astrojs/starlight/components"; - -## Quick Install (5 Minutes) - -:::tip[TL;DR - Experienced Developers] -```bash -# Install Go 1.25+, then: -go install github.com/wailsapp/wails/v3/cmd/wails3@latest -wails3 doctor # Verify installation -``` - -If `wails3 doctor` passes, you're done. [Skip to First App →](/quick-start/first-app) -::: - -## Step-by-Step Installation - - - -1. **Install Go (Required)** - - Wails requires Go 1.25 or later. - - - - Download the Windows installer from **[go.dev/dl](https://go.dev/dl/)** and run it. - - **Verify installation:** - ```powershell - go version # Should show 1.25 or later - ``` - - **Check PATH:** - ```powershell - $env:PATH -split ';' | Where-Object { $_ -like '*\go\bin' } - ``` - - If empty, add `C:\Users\YourName\go\bin` to your PATH. - - - - **Option 1: Official Installer** - - Download the macOS installer (.pkg file) from **[go.dev/dl](https://go.dev/dl/)** and run it. - - **Option 2: Homebrew** - ```bash - brew install go - ``` - - **Verify installation:** - ```bash - go version # Should show 1.25 or later - echo $PATH | grep go/bin # Should show ~/go/bin - ``` - - If `~/go/bin` isn't in PATH, add to `~/.zshrc` or `~/.bash_profile`: - ```bash - export PATH=$PATH:~/go/bin - ``` - - - - **Option 1: Official Tarball** - - Download the Linux tarball from **[go.dev/dl](https://go.dev/dl/)**, then: - ```bash - sudo rm -rf /usr/local/go - sudo tar -C /usr/local -xzf go1.25.linux-amd64.tar.gz - ``` - - **Option 2: Package Manager** - ```bash - # Ubuntu/Debian - sudo apt install golang-go - - # Fedora - sudo dnf install golang - - # Arch - sudo pacman -S go - ``` - - **Add to PATH** (add to `~/.bashrc` or `~/.zshrc`): - ```bash - export PATH=$PATH:/usr/local/go/bin:~/go/bin - source ~/.bashrc # Reload - ``` - - **Verify:** - ```bash - go version - echo $PATH | grep go/bin - ``` - - - -2. **Install Platform Dependencies** - - - - **WebView2 Runtime** (usually pre-installed) - - Windows 10/11 includes WebView2 by default. If missing: - - Download from [Microsoft](https://developer.microsoft.com/microsoft-edge/webview2/) - - Or run `wails3 doctor` later—it will guide you - - **That's it!** No other dependencies needed. - - :::tip[Performance Tip for Windows 11] - Consider using [Dev Drive](https://learn.microsoft.com/en-us/windows/dev-drive/) to store your projects. Dev Drives are optimized for developer workloads and can significantly improve build times and disk access speeds by up to 30%. - ::: - - - - **Xcode Command Line Tools** (required) - - ```bash - xcode-select --install - ``` - - Click "Install" in the dialog that appears. - - **Verify:** - ```bash - xcode-select -p # Should show /Library/Developer/CommandLineTools - ``` - - **That's it!** macOS includes WebKit by default. - - - - **Build tools and WebKit** - - - - ```bash - sudo apt update - sudo apt install build-essential pkg-config libgtk-3-dev libwebkit2gtk-4.0-dev - ``` - - - - ```bash - sudo dnf install gcc pkg-config gtk3-devel webkit2gtk4.0-devel - ``` - - - - ```bash - sudo pacman -S base-devel gtk3 webkit2gtk - ``` - - - - Run `wails3 doctor` after installing Wails—it will show the exact packages needed for your distribution. - - - - - -3. **Install Wails CLI** - - ```bash - go install github.com/wailsapp/wails/v3/cmd/wails3@latest - ``` - - This installs the `wails3` command to `~/go/bin` (or `%USERPROFILE%\go\bin` on Windows). - -4. **Verify Installation** - - ```bash - wails3 doctor - ``` - - **Expected output (or similar):** - ``` - Wails (v3.0.0-dev) Wails Doctor - - # System - - ┌──────────────────────────────────────────────────┐ - | Name | MacOS | - | Version | 26.0 | - | ID | 25A354 | - | Branding | MacOS 26.0 | - | Platform | darwin | - | Architecture | arm64 | - | Apple Silicon | true | - | CPU | Apple M2 Pro | - | CPU 1 | Apple M2 Pro | - | CPU 2 | Apple M2 Pro | - | GPU | 16 cores, Metal Support: Metal 4 | - | Memory | 16 GB | - └──────────────────────────────────────────────────┘ - - # Build Environment - - ┌─────────────┬─────────────────┐ - | Wails CLI | v3.0.0-alpha.40 | - | Go Version | go1.24.6 | - └─────────────┴─────────────────┘ - - # Dependencies - - ┌─────────────────┬─────────────────────────────────────────────────┐ - | npm | 11.6.2 | - | *NSIS | Not Installed. Install with `brew install...`. | - | Xcode cli tools | 2412 | - └─────────────────┴─────────────────────────────────────────────────┘ - - # Checking for issues - - SUCCESS No issues found - - # Diagnosis - - SUCCESS Your system is ready for Wails development! - ``` - - :::note[If `wails3` command not found] - Your `~/go/bin` isn't in PATH. See step 1 above to fix this, then restart your terminal. - ::: - -5. **Install npm (Optional but Recommended)** - - Most Wails templates use npm for frontend tooling. - - - - Download from [nodejs.org](https://nodejs.org/) and run the installer. - - **Verify:** - ```powershell - npm --version - ``` - - - - **Option 1: Official Installer** - Download from [nodejs.org](https://nodejs.org/) - - **Option 2: Homebrew** - ```bash - brew install node - ``` - - **Verify:** - ```bash - npm --version - ``` - - - - **Option 1: NodeSource** - ```bash - curl -fsSL https://deb.nodesource.com/setup_lts.x | sudo -E bash - - sudo apt-get install -y nodejs # Ubuntu/Debian - ``` - - **Option 2: Package Manager** - ```bash - sudo dnf install nodejs # Fedora - sudo pacman -S nodejs npm # Arch - ``` - - **Verify:** - ```bash - npm --version - ``` - - - - :::tip[Alternative Package Managers] - Prefer `pnpm`, `yarn`, or `bun`? No problem! Just update the `Taskfile.yml` in your project to use your preferred tool. - ::: - - - -## Troubleshooting - -#### `wails3` command not found - -**Cause:** `~/go/bin` (or `%USERPROFILE%\go\bin`) isn't in your PATH. - -**Solution:** - - - - 1. Open "Environment Variables" (search in Start menu) - 2. Under "User variables", find `Path` - 3. Click "Edit" → "New" - 4. Add: `C:\Users\YourName\go\bin` (replace `YourName`) - 5. Click "OK" on all dialogs - 6. **Restart your terminal** - - **Verify:** - ```powershell - $env:PATH -split ';' | Where-Object { $_ -like '*\go\bin' } - ``` - - - - Add to `~/.zshrc` (macOS) or `~/.bashrc` (Linux): - ```bash - export PATH=$PATH:~/go/bin - ``` - - Reload: - ```bash - source ~/.zshrc # or ~/.bashrc - ``` - - **Verify:** - ```bash - echo $PATH | grep go/bin - wails3 version - ``` - - ---- - -#### `wails3 doctor` reports missing dependencies - -**Linux:** The output tells you exactly which packages to install. Example: -``` -❌ webkit2gtk not found - Install with: sudo apt install libwebkit2gtk-4.0-dev -``` - -**Windows:** If WebView2 is missing: -- Download from [Microsoft](https://developer.microsoft.com/microsoft-edge/webview2/) -- Or it will be installed automatically when you run your first app - -**macOS:** If Xcode tools are missing: -```bash -xcode-select --install -``` ---- -#### Go version too old - -Wails v3 requires Go 1.25+. If you have an older version: - - - - Download the latest from [go.dev/dl](https://go.dev/dl/) and reinstall. - - - - Download the latest tarball from [go.dev/dl](https://go.dev/dl/), then: - ```bash - sudo rm -rf /usr/local/go - sudo tar -C /usr/local -xzf go1.25.linux-amd64.tar.gz - ``` - - - -## Development Version (Bleeding Edge) - -Want to use the absolute latest code from the main development branch? This gives you access to new features and fixes before they're released, but comes with the risk of bugs and breaking changes. Only recommended for contributors or those who need to test upcoming features. - -```bash -git clone https://github.com/wailsapp/wails.git -cd wails -git checkout v3 -cd v3/cmd/wails3 -go install -``` - -:::caution[Development Version] -- May have bugs or breaking changes -- Projects created will use `replace` directive to point to local Wails -- Only recommended for contributors or testing new features -::: - -## Next Steps - -**Installation Complete!** Your system is ready for Wails development. - - - Create a working application in 10 minutes. - - [First App Tutorial →](/quick-start/first-app) - - - - See what's available out of the box. - - ```bash - wails3 init -l # List templates - ``` - - ---- - -**Having issues?** Ask in [Discord](https://discord.gg/JDdSxwjhGf) or [open an issue](https://github.com/wailsapp/wails/issues). diff --git a/docs/src/content/docs/quick-start/next-steps.mdx b/docs/src/content/docs/quick-start/next-steps.mdx deleted file mode 100644 index 394d8e69a..000000000 --- a/docs/src/content/docs/quick-start/next-steps.mdx +++ /dev/null @@ -1,34 +0,0 @@ ---- -title: Next Steps -description: Where to go after building your first app -sidebar: - order: 4 ---- - -You've built your first Wails app and understand the basics. Here's where to go next. - -## Learn More - -Practice by building complete applications: - -- [TODO App](/tutorials/02-todo-vanilla) - CRUD operations, state management, modern UI -- [All Tutorials](/tutorials/overview) - Notes apps, dashboards, system tray apps, and more - -## Features - -Wails provides native desktop capabilities: - -- [Windows](/features/windows/basics) - Multiple windows, frameless windows, positioning -- [Menus](/features/menus/application) - Application menus, context menus, system tray -- [Dialogs](/features/dialogs/file) - File open/save, message dialogs -- [Events](/features/events/system) - Communication between components -- [Bindings](/features/bindings/methods) - Type-safe Go ↔ JavaScript calls -- [Clipboard](/features/clipboard) - Copy/paste operations -- [Drag & Drop](/features/drag-and-drop/files) - File drag and drop -- [Keyboard](/features/keyboard) - Global shortcuts - -## Get Help - -- [Discord](https://discord.gg/JDdSxwjhGf) - Ask questions, share projects -- [Examples](https://github.com/wailsapp/wails/tree/v3-alpha/v3/examples) - 50+ working examples -- [API Reference](/reference/overview) - Complete documentation diff --git a/docs/src/content/docs/quick-start/why-wails.mdx b/docs/src/content/docs/quick-start/why-wails.mdx deleted file mode 100644 index a99c299d2..000000000 --- a/docs/src/content/docs/quick-start/why-wails.mdx +++ /dev/null @@ -1,133 +0,0 @@ ---- -title: Why Wails? -description: Understand why Wails is the right choice for your desktop application -sidebar: - order: 1 ---- - - -Wails combines **Go's performance and simplicity** with **modern web UI flexibility**, enabling you to build beautiful, native desktop applications with the tools you already know. - -## Performance That Users Notice - -**Wails Applications:** -- **~15MB binaries** (vs Electron's 150MB) -- **~10MB baseline memory** (vs Electron's 100MB+) -- **<0.5s startup time** (vs Electron's 2-3s) -- **Native rendering** using the OS-provided WebView - -Users perceive your application as fast, lightweight, and professional. - -## Developer Experience - -**Write Once, Run Everywhere:** -- One Go codebase for Windows, macOS, and Linux -- Use any web framework (React, Vue, Svelte, vanilla JS) -- Hot reload during development -- TypeScript bindings auto-generated from Go code - -Ship faster with less code to maintain. - -## Production-Ready Features - -**Everything you need:** -- Multiple windows with independent lifecycles -- Native menus (application, context, system tray) -- File dialogs with platform-native UI -- System integration (notifications, clipboard, keyboard shortcuts) -- Code signing and packaging for all platforms - -Build professional applications, not prototypes. - -## Faster Development - -- **One codebase, three platforms** - Write once, build for Windows, macOS, and Linux -- **Use existing skills** - Go for backend, HTML/CSS/JS for UI -- **Instant feedback** - Hot reload during development, compile times measured in seconds -- **Small binaries** - 15MB apps mean faster builds, faster downloads, faster iteration - -## When to Choose Wails - -**Wails is Perfect For:** - -- **Business applications** (CRM, inventory, dashboards, admin tools) -- **Developer tools** (database clients, API testers, deployment tools) -- **Productivity apps** (note-taking, task managers, time trackers) -- **Creative tools** (image editors, video processors, design utilities) -- **Internal tools** (company-specific applications, automation tools) - -## Real-World Success Stories - -:::tip[Production Applications] -Wails powers real applications used by thousands of users: -- **Database management tools** with complex UIs -- **Financial dashboards** processing real-time data -- **Video editing tools** with native performance -- **Development utilities** used by engineering teams - -[See the showcase →](/community/showcase) -::: - -## How Wails Works - -Unlike Electron which bundles an entire browser and Node.js runtime, Wails takes a fundamentally different approach: your Go code compiles to a native binary, and your UI runs in the operating system's built-in WebView. This architecture delivers the small binaries, fast startup, and low memory usage that make Wails applications feel native. - -### Architecture - -Wails applications consist of two main parts that communicate seamlessly: a Go backend handling business logic and system operations, and a web-based frontend for your user interface. The OS-provided WebView renders your UI without bundling a browser, while the bindings layer provides type-safe communication between Go and JavaScript. - -
      -
      - -```d2 -direction: down - -Application: { -Go: "Go Backend" { - shape: rectangle - style.fill: "#00ADD8" -} -WebView: "Native WebView" { - shape: rectangle - style.fill: "#3B82F6" - - Frontend: "Your UI\n(React/Vue/etc)" { - shape: rectangle - style.fill: "#8B5CF6" - } - -} -Go <-> WebView: "Bindings & Events" -} - - - -``` - -
      -
      - -This simple architecture enables JavaScript code to call Go functions directly (through auto-generated bindings), while Go can send events and data back to the frontend. Both layers communicate through an efficient in-memory bridge with sub-millisecond overhead. - -**How Wails achieves performance:** -1. **No runtime bundled** - Uses Go's compiled binary -2. **Native WebView** - OS-provided rendering engine -3. **Direct Go ↔ JS bridge** - In-memory communication, no network overhead -4. **Compiled binary** - Instant startup, no JIT compilation - -## Next Steps - -Now that you understand what Wails provides, let's get you set up: - -1. **Install Wails** - Set up your development environment in 5 minutes - [Installation Guide →](/quick-start/installation) - -2. **Build Your First App** - Create a working application and understand the basics - [First App Tutorial →](/quick-start/first-app) - -3. **Explore Features** - Discover what Wails can do for your application - [Feature Overview →](/quick-start/next-steps) - ---- - -**Still have questions?** Join our [Discord community](https://discord.gg/JDdSxwjhGf) and ask the team directly. diff --git a/docs/src/content/docs/reference/application.mdx b/docs/src/content/docs/reference/application.mdx deleted file mode 100644 index cab3a279d..000000000 --- a/docs/src/content/docs/reference/application.mdx +++ /dev/null @@ -1,489 +0,0 @@ ---- -title: Application API -description: Complete reference for the Application API -sidebar: - order: 1 ---- - -import { Card, CardGrid } from "@astrojs/starlight/components"; - -## Overview - -The `Application` is the core of your Wails app. It manages windows, services, events, and provides access to all platform features. - -## Creating an Application - -```go -import "github.com/wailsapp/wails/v3/pkg/application" - -app := application.New(application.Options{ - Name: "My App", - Description: "My awesome application", - Services: []application.Service{ - application.NewService(&MyService{}), - }, -}) -``` - -## Core Methods - -### Run() - -Starts the application event loop. - -```go -func (a *App) Run() error -``` - -**Example:** - -```go -err := app.Run() -if err != nil { - log.Fatal(err) -} -``` - -**Returns:** Error if startup fails - -### Quit() - -Gracefully shuts down the application. - -```go -func (a *App) Quit() -``` - -**Example:** - -```go -// In a menu handler -menu.Add("Quit").OnClick(func(ctx *application.Context) { - app.Quit() -}) -``` - -### Config() - -Returns the application configuration. - -```go -func (a *App) Config() Options -``` - -**Example:** - -```go -config := app.Config() -fmt.Println("App name:", config.Name) -``` - -## Window Management - -### app.Window.New() - -Creates a new webview window with default options. - -```go -func (wm *WindowManager) New() *WebviewWindow -``` - -**Example:** - -```go -window := app.Window.New() -window.Show() -``` - -### app.Window.NewWithOptions() - -Creates a new webview window with custom options. - -```go -func (wm *WindowManager) NewWithOptions(options WebviewWindowOptions) *WebviewWindow -``` - -**Example:** - -```go -window := app.Window.NewWithOptions(application.WebviewWindowOptions{ - Title: "My Window", - Width: 800, - Height: 600, - BackgroundColour: application.NewRGB(255, 255, 255), -}) -``` - -### app.Window.GetByName() - -Gets a window by its name. - -```go -func (wm *WindowManager) GetByName(name string) Window -``` - -**Example:** - -```go -window := app.Window.GetByName("main") -if window != nil { - window.Show() -} -``` - -### app.Window.GetAll() - -Returns all application windows. - -```go -func (wm *WindowManager) GetAll() []Window -``` - -**Example:** - -```go -windows := app.Window.GetAll() -for _, window := range windows { - fmt.Println("Window:", window.Name()) -} -``` - -## Managers - -The Application provides access to various managers through properties: - -```go -app.Window // Window management -app.Menu // Menu management -app.Dialog // dialog management -app.Event // Event management -app.Clipboard // Clipboard operations -app.Screen // Screen information -app.SystemTray // System tray -app.Browser // Browser operations -app.Env // Environment variables -``` - -### Example Usage - -```go -// Create window -window := app.Window.New() - -// Show dialog -app.Dialog.Info().SetMessage("Hello!").Show() - -// Copy to clipboard -app.Clipboard.SetText("Copied text") - -// Get screens -screens := app.Screen.GetAll() -``` - -## Service Management - -### RegisterService() - -Registers a service with the application. - -```go -func (a *App) RegisterService(service Service) error -``` - -**Example:** - -```go -type MyService struct { - app *application.Application -} - -func NewMyService(app *application.Application) *MyService { - return &MyService{app: app} -} - -// Register after app creation -app.RegisterService(application.NewService(NewMyService(app))) -``` - -## Event Management - -### app.Event.Emit() - -Emits a custom event. - -```go -func (em *EventManager) Emit(name string, data ...interface{}) -``` - -**Example:** - -```go -// Emit event with data -app.Event.Emit("user-logged-in", map[string]interface{}{ - "username": "john", - "timestamp": time.Now(), -}) -``` - -### app.Event.On() - -Listens for custom events. - -```go -func (em *EventManager) On(name string, callback func(*CustomEvent)) -``` - -**Example:** - -```go -app.Event.On("user-logged-in", func(e *application.CustomEvent) { - data := e.Data.(map[string]interface{}) - username := data["username"].(string) - fmt.Println("User logged in:", username) -}) -``` - -### app.Event.OnApplicationEvent() - -Listens for application lifecycle events. - -```go -func (em *EventManager) OnApplicationEvent(eventType ApplicationEventType, callback func(*ApplicationEvent)) func() -``` - -**Example:** - -```go -// Listen for shutdown -app.Event.OnApplicationEvent(application.EventApplicationShutdown, func(e *application.ApplicationEvent) { - fmt.Println("Application shutting down") - // Cleanup -}) -``` - -## Dialog Methods - -Dialogs are accessed through the `app.Dialog` manager. See [Dialogs API](/reference/dialogs/) for complete reference. - -### Message Dialogs - -```go -// Information dialog -app.Dialog.Info(). - SetTitle("Success"). - SetMessage("Operation completed!"). - Show() - -// Error dialog -app.Dialog.Error(). - SetTitle("Error"). - SetMessage("Something went wrong."). - Show() - -// Warning dialog -app.Dialog.Warning(). - SetTitle("Warning"). - SetMessage("This action cannot be undone."). - Show() -``` - -### Question Dialogs - -Question dialogs use button callbacks to handle user responses: - -```go -dialog := app.Dialog.Question(). - SetTitle("Confirm"). - SetMessage("Continue?") - -yes := dialog.AddButton("Yes") -yes.OnClick(func() { - // Handle yes -}) - -no := dialog.AddButton("No") -no.OnClick(func() { - // Handle no -}) - -dialog.SetDefaultButton(yes) -dialog.SetCancelButton(no) -dialog.Show() -``` - -### File Dialogs - -```go -// Open file dialog -path, err := app.Dialog.OpenFile(). - SetTitle("Select File"). - AddFilter("Images", "*.png;*.jpg"). - PromptForSingleSelection() - -// Save file dialog -path, err := app.Dialog.SaveFile(). - SetTitle("Save File"). - SetFilename("document.pdf"). - AddFilter("PDF", "*.pdf"). - PromptForSingleSelection() - -// Folder selection (use OpenFile with directory options) -path, err := app.Dialog.OpenFile(). - SetTitle("Select Folder"). - CanChooseDirectories(true). - CanChooseFiles(false). - PromptForSingleSelection() -``` - -## Logger - -The application provides a structured logger: - -```go -app.Logger.Info("Message", "key", "value") -app.Logger.Error("Error occurred", "error", err) -app.Logger.Debug("Debug info") -app.Logger.Warn("Warning message") -``` - -**Example:** - -```go -func (s *MyService) ProcessData(data string) error { - s.app.Logger.Info("Processing data", "length", len(data)) - - if err := process(data); err != nil { - s.app.Logger.Error("Processing failed", "error", err) - return err - } - - s.app.Logger.Info("Processing complete") - return nil -} -``` - -## Raw Message Handling - -For applications that need direct, low-level control over frontend-to-backend communication, Wails provides the `RawMessageHandler` option. This bypasses the standard binding system. - -:::note -Raw messages should only be used as a last resort. The standard binding system is highly optimized and sufficient for almost all applications. Only use raw messages if you have profiled your application and confirmed that bindings are a bottleneck. -::: - -### RawMessageHandler - -The `RawMessageHandler` callback receives raw messages sent from the frontend using `System.invoke()`. - -```go -func (a *App) RawMessageHandler(window Window, message string) -``` - -**Example:** - -```go -app := application.New(application.Options{ - Name: "My App", - RawMessageHandler: func(window application.Window, message string) { - // Handle the raw message - fmt.Printf("Received from %s: %s\n", window.Name(), message) - - // You can respond using events - window.EmitEvent("response", processMessage(message)) - }, -}) -``` - - -For more details, see the [Raw Messages Guide](/guides/raw-messages). - -## Platform-Specific Options - -### Windows Options - -Configure Windows-specific behavior at the application level: - -```go -app := application.New(application.Options{ - Name: "My App", - Windows: application.WindowsOptions{ - // WebView2 browser flags (apply to ALL windows) - EnabledFeatures: []string{"msWebView2EnableDraggableRegions"}, - DisabledFeatures: []string{"msExperimentalFeature"}, - AdditionalBrowserArgs: []string{"--remote-debugging-port=9222"}, - - // Other Windows options - WndClass: "MyAppClass", - WebviewUserDataPath: "", // Default: %APPDATA%\[BinaryName.exe] - WebviewBrowserPath: "", // Default: system WebView2 - DisableQuitOnLastWindowClosed: false, - }, -}) -``` - -**Browser Flags:** -- `EnabledFeatures` - WebView2 feature flags to enable -- `DisabledFeatures` - WebView2 feature flags to disable -- `AdditionalBrowserArgs` - Chromium command-line arguments - -See [Window Options - Application-Level Windows Options](/features/windows/options#application-level-windows-options) for detailed documentation. - -### Mac Options - -```go -app := application.New(application.Options{ - Name: "My App", - Mac: application.MacOptions{ - ActivationPolicy: application.ActivationPolicyRegular, - ApplicationShouldTerminateAfterLastWindowClosed: true, - }, -}) -``` - -### Linux Options - -```go -app := application.New(application.Options{ - Name: "My App", - Linux: application.LinuxOptions{ - ProgramName: "my-app", - DisableQuitOnLastWindowClosed: false, - }, -}) -``` - -## Complete Application Example - -```go -package main - -import ( - "github.com/wailsapp/wails/v3/pkg/application" -) - -func main() { - app := application.New(application.Options{ - Name: "My Application", - Description: "A demo application", - Mac: application.MacOptions{ - ApplicationShouldTerminateAfterLastWindowClosed: true, - }, - }) - - // Create main window - window := app.Window.NewWithOptions(application.WebviewWindowOptions{ - Title: "My App", - Width: 1024, - Height: 768, - MinWidth: 800, - MinHeight: 600, - BackgroundColour: application.NewRGB(255, 255, 255), - URL: "http://wails.localhost/", - }) - - window.Centre() - window.Show() - - app.Run() -} -``` - diff --git a/docs/src/content/docs/reference/cli.mdx b/docs/src/content/docs/reference/cli.mdx deleted file mode 100644 index 9f37ff6bf..000000000 --- a/docs/src/content/docs/reference/cli.mdx +++ /dev/null @@ -1,28 +0,0 @@ ---- -title: CLI Reference -description: Complete reference for the Wails CLI commands -sidebar: - order: 1 ---- - -## Overview - -The Wails CLI (`wails3`) provides commands for creating, developing, building, and managing Wails applications. - -## Coming Soon - -This section is under construction. For now, use `wails3 --help` or `wails3 [command] --help` for command documentation. - -**Common commands:** - -```bash -wails3 init # Create a new project -wails3 dev # Run in development mode -wails3 build # Build for production -wails3 generate # Generate bindings or runtime -wails3 doctor # Check development environment -``` - ---- - -**Questions?** Ask in [Discord](https://discord.gg/JDdSxwjhGf) or check the [examples](https://github.com/wailsapp/wails/tree/v3-alpha/v3/examples). diff --git a/docs/src/content/docs/reference/dialogs.mdx b/docs/src/content/docs/reference/dialogs.mdx deleted file mode 100644 index 799c453b8..000000000 --- a/docs/src/content/docs/reference/dialogs.mdx +++ /dev/null @@ -1,844 +0,0 @@ ---- -title: Dialogs API -description: Complete reference for native dialog APIs -sidebar: - order: 5 ---- - -import { Card, CardGrid } from "@astrojs/starlight/components"; - -## Overview - -The Dialogs API provides methods to show native file dialogs and message dialogs. Access dialogs through the `app.Dialog` manager. - -**Dialog Types:** -- **File Dialogs** - Open and Save dialogs -- **Message Dialogs** - Info, Error, Warning, and Question dialogs - -All dialogs are **native OS dialogs** that match the platform's look and feel. - -## Accessing Dialogs - -Dialogs are accessed through the `app.Dialog` manager: - -```go -app.Dialog.OpenFile() -app.Dialog.SaveFile() -app.Dialog.Info() -app.Dialog.Question() -app.Dialog.Warning() -app.Dialog.Error() -``` - -## File Dialogs - -### OpenFile() - -Creates a file open dialog. - -```go -func (dm *DialogManager) OpenFile() *OpenFileDialogStruct -``` - -**Example:** -```go -dialog := app.Dialog.OpenFile() -``` - -### OpenFileDialogStruct Methods - -#### SetTitle() - -Sets the dialog title. - -```go -func (d *OpenFileDialogStruct) SetTitle(title string) *OpenFileDialogStruct -``` - -**Example:** -```go -dialog.SetTitle("Select Image") -``` - -#### AddFilter() - -Adds a file type filter. - -```go -func (d *OpenFileDialogStruct) AddFilter(displayName, pattern string) *OpenFileDialogStruct -``` - -**Parameters:** -- `displayName` - Filter description shown to user (e.g., "Images", "Documents") -- `pattern` - Semicolon-separated list of extensions (e.g., "*.png;*.jpg") - -**Example:** -```go -dialog.AddFilter("Images", "*.png;*.jpg;*.gif"). - AddFilter("Documents", "*.pdf;*.docx"). - AddFilter("All Files", "*.*") -``` - -#### SetDirectory() - -Sets the initial directory. - -```go -func (d *OpenFileDialogStruct) SetDirectory(directory string) *OpenFileDialogStruct -``` - -**Example:** -```go -homeDir, _ := os.UserHomeDir() -dialog.SetDirectory(homeDir) -``` - -#### CanChooseDirectories() - -Enables or disables directory selection. - -```go -func (d *OpenFileDialogStruct) CanChooseDirectories(canChooseDirectories bool) *OpenFileDialogStruct -``` - -**Example (folder selection):** -```go -// Select folders instead of files -path, err := app.Dialog.OpenFile(). - SetTitle("Select Folder"). - CanChooseDirectories(true). - CanChooseFiles(false). - PromptForSingleSelection() -``` - -#### CanChooseFiles() - -Enables or disables file selection. - -```go -func (d *OpenFileDialogStruct) CanChooseFiles(canChooseFiles bool) *OpenFileDialogStruct -``` - -#### CanCreateDirectories() - -Enables or disables creating new directories. - -```go -func (d *OpenFileDialogStruct) CanCreateDirectories(canCreateDirectories bool) *OpenFileDialogStruct -``` - -#### ShowHiddenFiles() - -Shows or hides hidden files. - -```go -func (d *OpenFileDialogStruct) ShowHiddenFiles(showHiddenFiles bool) *OpenFileDialogStruct -``` - -#### AttachToWindow() - -Attaches the dialog to a specific window. - -```go -func (d *OpenFileDialogStruct) AttachToWindow(window Window) *OpenFileDialogStruct -``` - -#### PromptForSingleSelection() - -Shows the dialog and returns the selected file. - -```go -func (d *OpenFileDialogStruct) PromptForSingleSelection() (string, error) -``` - -**Returns:** -- `string` - Selected file path (empty if cancelled) -- `error` - Error if dialog failed - -**Example:** -```go -path, err := app.Dialog.OpenFile(). - SetTitle("Select Image"). - AddFilter("Images", "*.png;*.jpg;*.gif"). - PromptForSingleSelection() - -if err != nil { - // User cancelled or error occurred - return -} - -// Use the selected file -processFile(path) -``` - -#### PromptForMultipleSelection() - -Shows the dialog and returns multiple selected files. - -```go -func (d *OpenFileDialogStruct) PromptForMultipleSelection() ([]string, error) -``` - -**Returns:** -- `[]string` - Array of selected file paths -- `error` - Error if dialog failed - -**Example:** -```go -paths, err := app.Dialog.OpenFile(). - SetTitle("Select Images"). - AddFilter("Images", "*.png;*.jpg"). - PromptForMultipleSelection() - -if err != nil { - return -} - -for _, path := range paths { - processFile(path) -} -``` - -### SaveFile() - -Creates a file save dialog. - -```go -func (dm *DialogManager) SaveFile() *SaveFileDialogStruct -``` - -**Example:** -```go -dialog := app.Dialog.SaveFile() -``` - -### SaveFileDialogStruct Methods - -#### SetTitle() - -Sets the dialog title. - -```go -func (d *SaveFileDialogStruct) SetTitle(title string) *SaveFileDialogStruct -``` - -#### SetFilename() - -Sets the default filename. - -```go -func (d *SaveFileDialogStruct) SetFilename(filename string) *SaveFileDialogStruct -``` - -**Example:** -```go -dialog.SetFilename("document.pdf") -``` - -#### AddFilter() - -Adds a file type filter. - -```go -func (d *SaveFileDialogStruct) AddFilter(displayName, pattern string) *SaveFileDialogStruct -``` - -**Example:** -```go -dialog.AddFilter("PDF Document", "*.pdf"). - AddFilter("Text Document", "*.txt") -``` - -#### SetDirectory() - -Sets the initial directory. - -```go -func (d *SaveFileDialogStruct) SetDirectory(directory string) *SaveFileDialogStruct -``` - -#### AttachToWindow() - -Attaches the dialog to a specific window. - -```go -func (d *SaveFileDialogStruct) AttachToWindow(window Window) *SaveFileDialogStruct -``` - -#### PromptForSingleSelection() - -Shows the dialog and returns the save path. - -```go -func (d *SaveFileDialogStruct) PromptForSingleSelection() (string, error) -``` - -**Example:** -```go -path, err := app.Dialog.SaveFile(). - SetTitle("Save Document"). - SetFilename("untitled.pdf"). - AddFilter("PDF Document", "*.pdf"). - PromptForSingleSelection() - -if err != nil { - // User cancelled - return -} - -// Save to the selected path -saveDocument(path) -``` - -### Folder Selection - -There is no separate `SelectFolderDialog`. Use `OpenFile()` with directory options: - -```go -path, err := app.Dialog.OpenFile(). - SetTitle("Select Output Folder"). - CanChooseDirectories(true). - CanChooseFiles(false). - PromptForSingleSelection() - -if err != nil { - // User cancelled - return -} - -// Use the selected folder -outputDir = path -``` - -## Message Dialogs - -All message dialogs return `*MessageDialog` and share the same methods. - -### Info() - -Creates an information dialog. - -```go -func (dm *DialogManager) Info() *MessageDialog -``` - -**Example:** -```go -app.Dialog.Info(). - SetTitle("Success"). - SetMessage("File saved successfully!"). - Show() -``` - -### Error() - -Creates an error dialog. - -```go -func (dm *DialogManager) Error() *MessageDialog -``` - -**Example:** -```go -app.Dialog.Error(). - SetTitle("Error"). - SetMessage("Failed to save file: " + err.Error()). - Show() -``` - -### Warning() - -Creates a warning dialog. - -```go -func (dm *DialogManager) Warning() *MessageDialog -``` - -**Example:** -```go -app.Dialog.Warning(). - SetTitle("Warning"). - SetMessage("This action cannot be undone."). - Show() -``` - -### Question() - -Creates a question dialog with custom buttons. - -```go -func (dm *DialogManager) Question() *MessageDialog -``` - -**Example:** -```go -dialog := app.Dialog.Question(). - SetTitle("Confirm"). - SetMessage("Do you want to save changes?") - -save := dialog.AddButton("Save") -save.OnClick(func() { - saveDocument() -}) - -dontSave := dialog.AddButton("Don't Save") -dontSave.OnClick(func() { - // Continue without saving -}) - -cancel := dialog.AddButton("Cancel") -cancel.OnClick(func() { - // Do nothing -}) - -dialog.SetDefaultButton(save) -dialog.SetCancelButton(cancel) -dialog.Show() -``` - -### MessageDialog Methods - -#### SetTitle() - -Sets the dialog title. - -```go -func (d *MessageDialog) SetTitle(title string) *MessageDialog -``` - -#### SetMessage() - -Sets the dialog message. - -```go -func (d *MessageDialog) SetMessage(message string) *MessageDialog -``` - -#### SetIcon() - -Sets a custom icon for the dialog. - -```go -func (d *MessageDialog) SetIcon(icon []byte) *MessageDialog -``` - -#### AddButton() - -Adds a button to the dialog and returns the button for configuration. - -```go -func (d *MessageDialog) AddButton(label string) *Button -``` - -**Returns:** `*Button` - The button instance for further configuration - -**Example:** -```go -button := dialog.AddButton("OK") -button.OnClick(func() { - // Handle click -}) -``` - -#### SetDefaultButton() - -Sets which button is the default (activated by pressing Enter). - -```go -func (d *MessageDialog) SetDefaultButton(button *Button) *MessageDialog -``` - -**Example:** -```go -yes := dialog.AddButton("Yes") -no := dialog.AddButton("No") -dialog.SetDefaultButton(yes) -``` - -#### SetCancelButton() - -Sets which button is the cancel button (activated by pressing Escape). - -```go -func (d *MessageDialog) SetCancelButton(button *Button) *MessageDialog -``` - -**Example:** -```go -ok := dialog.AddButton("OK") -cancel := dialog.AddButton("Cancel") -dialog.SetCancelButton(cancel) -``` - -#### AttachToWindow() - -Attaches the dialog to a specific window. - -```go -func (d *MessageDialog) AttachToWindow(window Window) *MessageDialog -``` - -#### Show() - -Shows the dialog. Button callbacks handle user responses. - -```go -func (d *MessageDialog) Show() -``` - -**Note:** `Show()` does not return a value. Use button callbacks to handle user responses. - -### Button Methods - -#### OnClick() - -Sets the callback function for when the button is clicked. - -```go -func (b *Button) OnClick(callback func()) *Button -``` - -#### SetAsDefault() - -Marks this button as the default button. - -```go -func (b *Button) SetAsDefault() *Button -``` - -#### SetAsCancel() - -Marks this button as the cancel button. - -```go -func (b *Button) SetAsCancel() *Button -``` - -## Complete Examples - -### File Selection Example - -```go -type FileService struct { - app *application.App -} - -func (s *FileService) OpenImage() (string, error) { - path, err := s.app.Dialog.OpenFile(). - SetTitle("Select Image"). - AddFilter("Images", "*.png;*.jpg;*.jpeg;*.gif"). - AddFilter("All Files", "*.*"). - PromptForSingleSelection() - - if err != nil { - return "", err - } - - return path, nil -} - -func (s *FileService) SaveDocument(defaultName string) (string, error) { - path, err := s.app.Dialog.SaveFile(). - SetTitle("Save Document"). - SetFilename(defaultName). - AddFilter("PDF Document", "*.pdf"). - AddFilter("Text Document", "*.txt"). - PromptForSingleSelection() - - if err != nil { - return "", err - } - - return path, nil -} - -func (s *FileService) SelectOutputFolder() (string, error) { - path, err := s.app.Dialog.OpenFile(). - SetTitle("Select Output Folder"). - CanChooseDirectories(true). - CanChooseFiles(false). - PromptForSingleSelection() - - if err != nil { - return "", err - } - - return path, nil -} -``` - -### Confirmation Dialog Example - -```go -func (s *Service) DeleteItem(app *application.App, id string) { - dialog := app.Dialog.Question(). - SetTitle("Confirm Delete"). - SetMessage("Are you sure you want to delete this item?") - - deleteBtn := dialog.AddButton("Delete") - deleteBtn.OnClick(func() { - deleteFromDatabase(id) - }) - - cancelBtn := dialog.AddButton("Cancel") - // Cancel does nothing - - dialog.SetDefaultButton(cancelBtn) // Default to Cancel for safety - dialog.SetCancelButton(cancelBtn) - dialog.Show() -} -``` - -### Save Changes Dialog - -```go -func (s *Editor) PromptSaveChanges(app *application.App) { - dialog := app.Dialog.Question(). - SetTitle("Unsaved Changes"). - SetMessage("Do you want to save your changes before closing?") - - save := dialog.AddButton("Save") - save.OnClick(func() { - s.Save() - s.Close() - }) - - dontSave := dialog.AddButton("Don't Save") - dontSave.OnClick(func() { - s.Close() - }) - - cancel := dialog.AddButton("Cancel") - // Cancel does nothing, dialog closes - - dialog.SetDefaultButton(save) - dialog.SetCancelButton(cancel) - dialog.Show() -} -``` - -### Multi-File Processing - -```go -func (s *Service) ProcessMultipleFiles(app *application.App) error { - // Select multiple files - paths, err := app.Dialog.OpenFile(). - SetTitle("Select Files to Process"). - AddFilter("Images", "*.png;*.jpg"). - PromptForMultipleSelection() - - if err != nil { - return err - } - - if len(paths) == 0 { - app.Dialog.Info(). - SetTitle("No Files Selected"). - SetMessage("Please select at least one file."). - Show() - return nil - } - - // Process files - for _, path := range paths { - err := processFile(path) - if err != nil { - app.Dialog.Error(). - SetTitle("Processing Error"). - SetMessage(fmt.Sprintf("Failed to process %s: %v", path, err)). - Show() - continue - } - } - - // Show completion - app.Dialog.Info(). - SetTitle("Complete"). - SetMessage(fmt.Sprintf("Successfully processed %d files", len(paths))). - Show() - - return nil -} -``` - -### Error Handling with Dialogs - -```go -func (s *Service) SaveFile(app *application.App, data []byte) error { - // Select save location - path, err := app.Dialog.SaveFile(). - SetTitle("Save File"). - SetFilename("data.json"). - AddFilter("JSON File", "*.json"). - PromptForSingleSelection() - - if err != nil { - // User cancelled - not an error - return nil - } - - // Attempt to save - err = os.WriteFile(path, data, 0644) - if err != nil { - // Show error dialog - app.Dialog.Error(). - SetTitle("Save Failed"). - SetMessage(fmt.Sprintf("Could not save file: %v", err)). - Show() - return err - } - - // Show success - app.Dialog.Info(). - SetTitle("Success"). - SetMessage("File saved successfully!"). - Show() - - return nil -} -``` - -### Platform-Specific Defaults - -```go -import ( - "os" - "path/filepath" - "runtime" -) - -func (s *Service) GetDefaultDirectory() string { - homeDir, _ := os.UserHomeDir() - - switch runtime.GOOS { - case "windows": - return filepath.Join(homeDir, "Documents") - case "darwin": - return filepath.Join(homeDir, "Documents") - case "linux": - return filepath.Join(homeDir, "Documents") - default: - return homeDir - } -} - -func (s *Service) OpenWithDefaults(app *application.App) (string, error) { - return app.Dialog.OpenFile(). - SetTitle("Open File"). - SetDirectory(s.GetDefaultDirectory()). - AddFilter("All Files", "*.*"). - PromptForSingleSelection() -} -``` - -## Best Practices - -### Do - -- **Use native dialogs** - They match the platform's look and feel -- **Provide clear titles** - Help users understand the purpose -- **Set appropriate filters** - Guide users to correct file types -- **Handle cancellation** - Check for errors (user may cancel) -- **Show confirmation for destructive actions** - Use Question dialogs -- **Provide feedback** - Use Info dialogs for success messages -- **Set sensible defaults** - Default directory, filename, etc. -- **Use callbacks for button actions** - Handle user responses properly - -### Don't - -- **Don't ignore errors** - User cancellation returns an error -- **Don't use ambiguous button labels** - Be specific: "Save"/"Cancel" -- **Don't overuse dialogs** - They interrupt workflow -- **Don't show errors for cancellation** - It's a normal action -- **Don't forget file filters** - Help users find the right files -- **Don't hardcode paths** - Use os.UserHomeDir() or similar - -## Dialog Types by Platform - -### macOS - -- Dialogs slide down from title bar -- "Sheet" style attached to parent window -- Native macOS appearance - -### Windows - -- Standard Windows dialogs -- Follows Windows design guidelines -- Modern Windows 10/11 appearance - -### Linux - -- GTK dialogs on GTK-based systems -- Qt dialogs on Qt-based systems -- Matches desktop environment - -#### Linux GTK4 Limitations - -On Linux with GTK4 (the default for modern distributions), file dialogs use the **xdg-desktop-portal** -for native integration. This provides better desktop integration but means some options have no effect: - -| Option | GTK3 | GTK4 | Notes | -|--------|------|------|-------| -| `ShowHiddenFiles()` | ✅ Works | ❌ No effect | User controls via dialog's UI toggle (Ctrl+H or menu) | -| `CanCreateDirectories()` | ✅ Works | ❌ No effect | Always enabled in the portal | -| `ResolvesAliases()` | ✅ Works | ❌ No effect | Portal handles symlink resolution | -| `SetButtonText()` | ✅ Works | ✅ Works | Custom accept button text works | - -**Why these limitations exist:** GTK4's portal-based dialogs delegate UI control to the desktop -environment (GNOME, KDE, etc.). This is by design - the portal provides consistent UX across -applications and respects user preferences. - -:::note -The table above shows GTK4 behavior when building with `-tags gtk4`. By default, Wails uses GTK3 -which provides full control over these dialog options. -::: - -## Common Patterns - -### "Save As" Pattern - -```go -func (s *Service) SaveAs(app *application.App, currentPath string) (string, error) { - // Extract filename from current path - filename := filepath.Base(currentPath) - - // Show save dialog - path, err := app.Dialog.SaveFile(). - SetTitle("Save As"). - SetFilename(filename). - PromptForSingleSelection() - - if err != nil { - return "", err - } - - return path, nil -} -``` - -### "Open Recent" Pattern - -```go -func (s *Service) OpenRecent(app *application.App, recentPath string) error { - // Check if file still exists - if _, err := os.Stat(recentPath); os.IsNotExist(err) { - dialog := app.Dialog.Question(). - SetTitle("File Not Found"). - SetMessage("The file no longer exists. Remove from recent files?") - - remove := dialog.AddButton("Remove") - remove.OnClick(func() { - s.removeFromRecent(recentPath) - }) - - cancel := dialog.AddButton("Cancel") - dialog.SetCancelButton(cancel) - dialog.Show() - - return err - } - - return s.openFile(recentPath) -} -``` diff --git a/docs/src/content/docs/reference/events.mdx b/docs/src/content/docs/reference/events.mdx deleted file mode 100644 index d6286018e..000000000 --- a/docs/src/content/docs/reference/events.mdx +++ /dev/null @@ -1,801 +0,0 @@ ---- -title: Events API -description: Complete reference for the Events API -sidebar: - order: 4 ---- - -import { Card, CardGrid } from "@astrojs/starlight/components"; - -## Overview - -The Events API provides methods to emit and listen to events, enabling communication between different parts of your application. - -**Event Types:** -- **Application Events** - App lifecycle events (startup, shutdown) -- **Window Events** - Window state changes (focus, blur, resize) -- **Custom Events** - User-defined events for app-specific communication - -**Communication Patterns:** -- **Go to Frontend** - Emit events from Go, listen in JavaScript -- **Frontend to Go** - Not directly (use service bindings instead) -- **Frontend to Frontend** - Via Go or local runtime events -- **Window to Window** - Target specific windows or broadcast to all - -## Event Methods (Go) - -### app.Event.Emit() - -Emits a custom event to all windows. - -```go -func (em *EventManager) Emit(name string, data ...interface{}) -``` - -**Parameters:** -- `name` - Event name -- `data` - Optional data to send with the event - -**Example:** -```go -// Emit simple event -app.Event.Emit("user-logged-in") - -// Emit with data -app.Event.Emit("data-updated", map[string]interface{}{ - "count": 42, - "status": "success", -}) - -// Emit multiple values -app.Event.Emit("progress", 75, "Processing files...") -``` - -### app.Event.On() - -Listens for custom events in Go. - -```go -func (em *EventManager) On(name string, callback func(*CustomEvent)) func() -``` - -**Parameters:** -- `name` - Event name to listen for -- `callback` - Function called when event is emitted - -**Returns:** Cleanup function to remove the event listener - -**Example:** -```go -// Listen for events -cleanup := app.Event.On("user-action", func(e *application.CustomEvent) { - data := e.Data.(map[string]interface{}) - action := data["action"].(string) - app.Logger.Info("User action", "action", action) -}) - -// Later, remove listener -cleanup() -``` - -### Window-Specific Events - -Emit events to a specific window: - -```go -// Emit to specific window -window.EmitEvent("notification", "Hello from Go!") - -// Emit to all windows -app.Event.Emit("global-update", data) -``` - -## Event Methods (Frontend) - -### On() - -Listens for events from Go. - -```javascript -import { On } from '@wailsio/runtime' - -On(eventName, callback) -``` - -**Parameters:** -- `eventName` - Name of the event to listen for -- `callback` - Function called when event is received - -**Returns:** Cleanup function - -**Example:** -```javascript -import { On } from '@wailsio/runtime' - -// Listen for events -const cleanup = On('data-updated', (data) => { - console.log('Count:', data.count) - console.log('Status:', data.status) - updateUI(data) -}) - -// Later, remove listener -cleanup() -``` - -### Once() - -Listens for a single event occurrence. - -```javascript -import { Once } from '@wailsio/runtime' - -Once(eventName, callback) -``` - -**Example:** -```javascript -import { Once } from '@wailsio/runtime' - -// Listen for first occurrence only -Once('initialization-complete', (data) => { - console.log('App initialized!', data) - // This will only fire once -}) -``` - -### Off() - -Removes an event listener. - -```javascript -import { Off } from '@wailsio/runtime' - -Off(eventName, callback) -``` - -**Example:** -```javascript -import { On, Off } from '@wailsio/runtime' - -const handler = (data) => { - console.log('Event received:', data) -} - -// Start listening -On('my-event', handler) - -// Stop listening -Off('my-event', handler) -``` - -### OffAll() - -Removes all listeners for an event. - -```javascript -import { OffAll } from '@wailsio/runtime' - -OffAll(eventName) -``` - -**Example:** -```javascript -// Remove all listeners for this event -OffAll('data-updated') -``` - -## Application Events - -### app.Event.OnApplicationEvent() - -Listens for application lifecycle events. - -```go -func (em *EventManager) OnApplicationEvent(eventType ApplicationEventType, callback func(*ApplicationEvent)) func() -``` - -**Event Types:** -- `EventApplicationStarted` - Application has started -- `EventApplicationShutdown` - Application is shutting down -- `EventApplicationDebug` - Debug event (dev mode only) - -**Example:** -```go -// Handle application startup -app.Event.OnApplicationEvent(application.EventApplicationStarted, func(e *application.ApplicationEvent) { - app.Logger.Info("Application started") - // Initialize resources -}) - -// Handle application shutdown -app.Event.OnApplicationEvent(application.EventApplicationShutdown, func(e *application.ApplicationEvent) { - app.Logger.Info("Application shutting down") - // Cleanup resources, save state - database.Close() - saveSettings() -}) -``` - -## Window Events - -### OnWindowEvent() - -Listens for window-specific events. - -```go -func (w *Window) OnWindowEvent(eventType WindowEventType, callback func(*WindowEvent)) func() -``` - -**Event Types:** -- `EventWindowFocus` - Window gained focus -- `EventWindowBlur` - Window lost focus -- `EventWindowClose` - Window is closing -- `EventWindowResize` - Window was resized -- `EventWindowMove` - Window was moved - -**Example:** -```go -// Handle window focus -window.OnWindowEvent(application.EventWindowFocus, func(e *application.WindowEvent) { - app.Logger.Info("Window focused") -}) - -// Handle window resize -window.OnWindowEvent(application.EventWindowResize, func(e *application.WindowEvent) { - width, height := window.Size() - app.Logger.Info("Window resized", "width", width, "height", height) -}) -``` - -## Common Patterns - -These patterns demonstrate proven approaches for using events in real-world applications. Each pattern solves a specific communication challenge between your Go backend and frontend, helping you build responsive, well-structured applications. - -### Request/Response Pattern - -Use this when you want to notify the frontend about the completion of backend operations, such as after data fetching, file processing, or background tasks. The service binding returns data directly, while events provide additional notifications for UI updates like showing toast messages or refreshing lists. - -**Go:** - -```go -// Service method -type DataService struct { - app *application.Application -} - -func (s *DataService) FetchData(query string) ([]Item, error) { - items := fetchFromDatabase(query) - - // Emit event when done - s.app.Event.Emit("data-fetched", map[string]interface{}{ - "query": query, - "count": len(items), - }) - - return items, nil -} -``` - -**JavaScript:** - -```javascript -import { FetchData } from './bindings/DataService' -import { On } from '@wailsio/runtime' - -// Listen for completion event -On('data-fetched', (data) => { - console.log(`Fetched ${data.count} items for query: ${data.query}`) - showNotification(`Found ${data.count} results`) -}) - -// Call service method -const items = await FetchData("search term") -displayItems(items) -``` - -### Progress Updates - -Ideal for long-running operations like file uploads, batch processing, large data imports, or video encoding. Emit progress events during the operation to update progress bars, status text, or step indicators in the UI, providing users with real-time feedback. - -**Go:** - -```go -func (s *Service) ProcessFiles(files []string) error { - total := len(files) - - for i, file := range files { - // Process file - processFile(file) - - // Emit progress event - s.app.Event.Emit("progress", map[string]interface{}{ - "current": i + 1, - "total": total, - "percent": float64(i+1) / float64(total) * 100, - "file": file, - }) - } - - s.app.Event.Emit("processing-complete") - return nil -} -``` - -**JavaScript:** - -```javascript -import { On, Once } from '@wailsio/runtime' - -// Update progress bar -On('progress', (data) => { - progressBar.style.width = `${data.percent}%` - statusText.textContent = `Processing ${data.file}... (${data.current}/${data.total})` -}) - -// Handle completion -Once('processing-complete', () => { - progressBar.style.width = '100%' - statusText.textContent = 'Complete!' - setTimeout(() => hideProgressBar(), 2000) -}) -``` - -### Multi-Window Communication - -Perfect for applications with multiple windows like settings panels, dashboards, or document viewers. Broadcast events to synchronize state across all windows (theme changes, user preferences) or send targeted events to specific windows for window-specific updates. - -**Go:** - -```go -// Broadcast to all windows -app.Event.Emit("theme-changed", "dark") - -// Send to specific window -preferencesWindow.EmitEvent("settings-updated", settings) - -// Window-specific listener -window1.OnEvent("request-data", func(e *application.CustomEvent) { - // Only this window will receive this event - window1.EmitEvent("data-response", data) -}) -``` - -**JavaScript:** - -```javascript -import { On } from '@wailsio/runtime' - -// Listen in any window -On('theme-changed', (theme) => { - document.body.className = theme -}) -``` - -### State Synchronization - -Use when you need to keep frontend and backend state in sync, such as user sessions, application configuration, or collaborative features. When state changes on the backend, emit events to update all connected frontends, ensuring consistency across your application. - -**Go:** - -```go -type StateService struct { - app *application.Application - state map[string]interface{} - mu sync.RWMutex -} - -func (s *StateService) UpdateState(key string, value interface{}) { - s.mu.Lock() - s.state[key] = value - s.mu.Unlock() - - // Notify all windows - s.app.Event.Emit("state-updated", map[string]interface{}{ - "key": key, - "value": value, - }) -} - -func (s *StateService) GetState(key string) interface{} { - s.mu.RLock() - defer s.mu.RUnlock() - return s.state[key] -} -``` - -**JavaScript:** - -```javascript -import { On } from '@wailsio/runtime' -import { GetState } from './bindings/StateService' - -// Keep local state in sync -let localState = {} - -On('state-updated', async (data) => { - localState[data.key] = data.value - updateUI(data.key, data.value) -}) - -// Initialize state -const initialState = await GetState("all") -localState = initialState -``` - -### Event-Driven Notifications - -Best for displaying user feedback like success confirmations, error alerts, or info messages. Instead of calling UI code directly from services, emit notification events that the frontend handles consistently, making it easy to change notification styles or add features like notification history. - -**Go:** - -```go -type NotificationService struct { - app *application.Application -} - -func (s *NotificationService) Success(message string) { - s.app.Event.Emit("notification", map[string]interface{}{ - "type": "success", - "message": message, - }) -} - -func (s *NotificationService) Error(message string) { - s.app.Event.Emit("notification", map[string]interface{}{ - "type": "error", - "message": message, - }) -} - -func (s *NotificationService) Info(message string) { - s.app.Event.Emit("notification", map[string]interface{}{ - "type": "info", - "message": message, - }) -} -``` - -**JavaScript:** - -```javascript -import { On } from '@wailsio/runtime' - -// Unified notification handler -On('notification', (data) => { - const toast = document.createElement('div') - toast.className = `toast toast-${data.type}` - toast.textContent = data.message - - document.body.appendChild(toast) - - setTimeout(() => { - toast.classList.add('fade-out') - setTimeout(() => toast.remove(), 300) - }, 3000) -}) -``` - -## Complete Example - -**Go:** - -```go -package main - -import ( - "sync" - "time" - "github.com/wailsapp/wails/v3/pkg/application" -) - -type EventDemoService struct { - app *application.Application - mu sync.Mutex -} - -func NewEventDemoService(app *application.Application) *EventDemoService { - service := &EventDemoService{app: app} - - // Listen for custom events - app.Event.On("user-action", func(e *application.CustomEvent) { - data := e.Data.(map[string]interface{}) - app.Logger.Info("User action received", "data", data) - }) - - return service -} - -func (s *EventDemoService) StartLongTask() { - go func() { - s.app.Event.Emit("task-started") - - for i := 1; i <= 10; i++ { - time.Sleep(500 * time.Millisecond) - - s.app.Event.Emit("task-progress", map[string]interface{}{ - "step": i, - "total": 10, - "percent": i * 10, - }) - } - - s.app.Event.Emit("task-completed", map[string]interface{}{ - "message": "Task finished successfully!", - }) - }() -} - -func (s *EventDemoService) BroadcastMessage(message string) { - s.app.Event.Emit("broadcast", message) -} - -func main() { - app := application.New(application.Options{ - Name: "Event Demo", - }) - - // Handle application lifecycle - app.Event.OnApplicationEvent(application.EventApplicationStarted, func(e *application.ApplicationEvent) { - app.Logger.Info("Application started!") - }) - - app.Event.OnApplicationEvent(application.EventApplicationShutdown, func(e *application.ApplicationEvent) { - app.Logger.Info("Application shutting down...") - }) - - // Register service - service := NewEventDemoService(app) - app.RegisterService(application.NewService(service)) - - // Create window - window := app.Window.New() - - // Handle window events - window.OnWindowEvent(events.Common.WindowFocus, func(e *application.WindowEvent) { - window.EmitEvent("window-state", "focused") - }) - - window.OnWindowEvent(events.Common.WindowLostFocus, func(e *application.WindowEvent) { - window.EmitEvent("window-state", "blurred") - }) - - window.Show() - app.Run() -} -``` - -**JavaScript:** - -```javascript -import { On, Once } from '@wailsio/runtime' -import { StartLongTask, BroadcastMessage } from './bindings/EventDemoService' - -// Task events -On('task-started', () => { - console.log('Task started...') - document.getElementById('status').textContent = 'Running...' -}) - -On('task-progress', (data) => { - const progressBar = document.getElementById('progress') - progressBar.style.width = `${data.percent}%` - console.log(`Step ${data.step} of ${data.total}`) -}) - -Once('task-completed', (data) => { - console.log('Task completed!', data.message) - document.getElementById('status').textContent = data.message -}) - -// Broadcast events -On('broadcast', (message) => { - console.log('Broadcast:', message) - alert(message) -}) - -// Window state events -On('window-state', (state) => { - console.log('Window is now:', state) - document.body.dataset.windowState = state -}) - -// Trigger long task -document.getElementById('startTask').addEventListener('click', async () => { - await StartLongTask() -}) - -// Send broadcast -document.getElementById('broadcast').addEventListener('click', async () => { - const message = document.getElementById('message').value - await BroadcastMessage(message) -}) -``` - -## Built-in Events - -Wails provides built-in system events for application and window lifecycle. These events are emitted automatically by the framework. - -### Common Events vs Platform-Native Events - -Wails provides two types of system events: - -**Common Events** (`events.Common.*`) are cross-platform abstractions that work consistently across macOS, Windows, and Linux. These are the events you should use in your application for maximum portability. - -**Platform-Native Events** (`events.Mac.*`, `events.Windows.*`, `events.Linux.*`) are the underlying OS-specific events that Common Events are mapped from. These provide access to platform-specific behaviors and edge cases. - -**How They Work:** - -```go -import "github.com/wailsapp/wails/v3/pkg/events" - -// ✅ RECOMMENDED: Use Common Events for cross-platform code -window.OnWindowEvent(events.Common.WindowClosing, func(e *application.WindowEvent) { - // This works on all platforms -}) - -// Platform-specific events for advanced use cases -window.OnWindowEvent(events.Mac.WindowWillClose, func(e *application.WindowEvent) { - // macOS-specific "will close" event (before WindowClosing) -}) - -window.OnWindowEvent(events.Windows.WindowClosing, func(e *application.WindowEvent) { - // Windows-specific close event -}) -``` - -**Event Mapping:** - -Platform-native events are automatically mapped to Common Events: - -- macOS: `events.Mac.WindowShouldClose` → `events.Common.WindowClosing` -- Windows: `events.Windows.WindowClosing` → `events.Common.WindowClosing` -- Linux: `events.Linux.WindowDeleteEvent` → `events.Common.WindowClosing` - -This mapping happens automatically in the background, so when you listen for `events.Common.WindowClosing`, you'll receive it regardless of the platform. - -**When to Use Each:** - -- **Use Common Events** for 99% of your application code - they provide consistent behavior across platforms -- **Use Platform-Native Events** only when you need platform-specific functionality that isn't available in Common Events (e.g., macOS-specific window lifecycle events, Windows power management events) - -### Application Events - -| Event | Description | When Emitted | Cancellable | -|-------|-------------|--------------|-------------| -| `ApplicationOpenedWithFile` | Application opened with a file | When app is launched with a file (e.g., from file association) | No | -| `ApplicationStarted` | Application has finished launching | After app initialization is complete and app is ready | No | -| `ApplicationLaunchedWithUrl` | Application launched with a URL | When app is launched via URL scheme | No | -| `ThemeChanged` | System theme changed | When OS theme switches between light/dark mode | No | - -**Usage:** - -```go -import "github.com/wailsapp/wails/v3/pkg/events" - -app.Event.OnApplicationEvent(events.Common.ApplicationStarted, func(e *application.ApplicationEvent) { - app.Logger.Info("Application ready!") -}) - -app.Event.OnApplicationEvent(events.Common.ThemeChanged, func(e *application.ApplicationEvent) { - // Update app theme -}) -``` - -### Window Events - -| Event | Description | When Emitted | Cancellable | -|-------|-------------|--------------|-------------| -| `WindowClosing` | Window is about to close | Before window closes (user clicked X, Close() called) | Yes | -| `WindowDidMove` | Window moved to new position | After window position changes (debounced) | No | -| `WindowDidResize` | Window was resized | After window size changes | No | -| `WindowDPIChanged` | Window DPI scaling changed | When moving between monitors with different DPI (Windows) | No | -| `WindowFilesDropped` | Files dropped via native OS drag-drop | After files are dropped from OS onto window | No | -| `WindowFocus` | Window gained focus | When window becomes active | No | -| `WindowFullscreen` | Window entered fullscreen | After Fullscreen() or user enters fullscreen | No | -| `WindowHide` | Window was hidden | After Hide() or window becomes occluded | No | -| `WindowLostFocus` | Window lost focus | When window becomes inactive | No | -| `WindowMaximise` | Window was maximized | After Maximise() or user maximizes | Yes (macOS) | -| `WindowMinimise` | Window was minimized | After Minimise() or user minimizes | Yes (macOS) | -| `WindowRestore` | Window restored from min/max state | After Restore() (Windows primarily) | No | -| `WindowRuntimeReady` | Wails runtime loaded and ready | When JavaScript runtime initialization completes | No | -| `WindowShow` | Window became visible | After Show() or window becomes visible | No | -| `WindowUnFullscreen` | Window exited fullscreen | After UnFullscreen() or user exits fullscreen | No | -| `WindowUnMaximise` | Window exited maximized state | After UnMaximise() or user unmaximizes | Yes (macOS) | -| `WindowUnMinimise` | Window exited minimized state | After UnMinimise()/Restore() or user restores | Yes (macOS) | -| `WindowZoomIn` | Window content zoom increased | After ZoomIn() called (macOS primarily) | Yes (macOS) | -| `WindowZoomOut` | Window content zoom decreased | After ZoomOut() called (macOS primarily) | Yes (macOS) | -| `WindowZoomReset` | Window content zoom reset to 100% | After ZoomReset() called (macOS primarily) | Yes (macOS) | -| `WindowDropZoneFilesDropped` | Files dropped on JS-defined drop zone | When files dropped onto element with drop zone | No | - -**Usage:** - -```go -import "github.com/wailsapp/wails/v3/pkg/events" - -// Listen for window events -window.OnWindowEvent(events.Common.WindowFocus, func(e *application.WindowEvent) { - app.Logger.Info("Window focused") -}) - -// Cancel window close -window.RegisterHook(events.Common.WindowClosing, func(e *application.WindowEvent) { - result, _ := app.Dialog.Question(). - SetMessage("Close window?"). - SetButtons("Yes", "No"). - Show() - - if result == "No" { - e.Cancel() // Prevent close - } -}) - -// Wait for runtime ready -window.OnWindowEvent(events.Common.WindowRuntimeReady, func(e *application.WindowEvent) { - app.Logger.Info("Runtime ready, safe to emit events to frontend") - window.EmitEvent("app-initialized", data) -}) -``` - -**Important Notes:** - -- **WindowRuntimeReady** is critical - wait for this event before emitting events to the frontend -- **WindowDidMove** and **WindowDidResize** are debounced (50ms default) to prevent event flooding -- **Cancellable events** can be prevented by calling `event.Cancel()` in a `RegisterHook()` handler -- **WindowFilesDropped** is for native OS file drops; **WindowDropZoneFilesDropped** is for web-based drop zones -- Some events are platform-specific (e.g., WindowDPIChanged on Windows, zoom events primarily on macOS) - -## Event Naming Conventions - -```go -// Good - descriptive and specific -app.Event.Emit("user:logged-in", user) -app.Event.Emit("data:fetch:complete", results) -app.Event.Emit("ui:theme:changed", theme) - -// Bad - vague and unclear -app.Event.Emit("event1", data) -app.Event.Emit("update", stuff) -app.Event.Emit("e", value) -``` - -## Performance Considerations - -### Debouncing High-Frequency Events - -```go -type Service struct { - app *application.Application - lastEmit time.Time - debounceWindow time.Duration -} - -func (s *Service) EmitWithDebounce(event string, data interface{}) { - now := time.Now() - if now.Sub(s.lastEmit) < s.debounceWindow { - return // Skip this emission - } - - s.app.Event.Emit(event, data) - s.lastEmit = now -} -``` - -### Throttling Events - -```javascript -import { On } from '@wailsio/runtime' - -let lastUpdate = 0 -const throttleMs = 100 - -On('high-frequency-event', (data) => { - const now = Date.now() - if (now - lastUpdate < throttleMs) { - return // Skip this update - } - - processUpdate(data) - lastUpdate = now -}) -``` diff --git a/docs/src/content/docs/reference/frontend-runtime.mdx b/docs/src/content/docs/reference/frontend-runtime.mdx deleted file mode 100644 index 4d56667fc..000000000 --- a/docs/src/content/docs/reference/frontend-runtime.mdx +++ /dev/null @@ -1,953 +0,0 @@ ---- -title: Frontend Runtime -description: The Wails JavaScript runtime package for frontend integration -sidebar: - order: 1 ---- - -The Wails frontend runtime is the standard library for Wails applications. It provides a -number of features that may be used in your applications, including: - -- Window management -- Dialogs -- Browser integration -- Clipboard -- Menus -- System information -- Events -- Context Menus -- Screens -- WML (Wails Markup Language) - -The runtime is required for integration between Go and the frontend. There are 2 -ways to integrate the runtime: - -- Using the `@wailsio/runtime` package -- Using a pre-built bundle - -## Using the npm package - -The `@wailsio/runtime` package is a JavaScript package that provides access to -the Wails runtime from the frontend. It is used by all standard templates -and is the recommended way to integrate the runtime into your application. -By using the `@wailsio/runtime` package, you will only include the parts of the runtime that you use. - -The package is available on npm and can be installed using: - -```shell -npm install --save @wailsio/runtime -``` - -## Using a pre-built bundle - -Some projects will not use a Javascript bundler and may prefer to use a -pre-built bundled version of the runtime. This version can be generated locally -using the following command: - -```shell -wails3 generate runtime -``` - -The command will output a `runtime.js` (and `runtime.debug.js`) file in the current -directory. This file is an ES module that can be imported by your application scripts -just like the npm package, but the API is also exported to the global window object, -so for simpler applications you can use it as follows: - -```html - - - - - - - -``` - -:::caution -It is important to include the `type="module"` attribute on the ` - - - ``` - - Run `wails3 dev` to start the dev server. After a few seconds, the application should open. - - Type in some text and click the "Generate QR Code" button. You should see a QR code in the center of the page: - - QR Code - -
      -
      - -7. ## Alternative Approach: HTTP Handler - - So far, we have covered the following areas: - - Creating a new Service - - Generating Bindings - - Using the Bindings in our Frontend code - - **Why use an HTTP handler?** - - Method bindings work great for data operations, but there's an alternative approach for serving files, images, or other media. Instead of converting everything to base64 and sending it through bindings, you can make your service act like a mini web server. - - This is useful when: - - You're serving images, videos, or large files - - You want to use standard HTML `` or `
      +`; +document.getElementById('logo').src = logo; + +let nameElement = document.getElementById("name"); +nameElement.focus(); +let resultElement = document.getElementById("result"); + +// Setup the greet function +window.greet = function () { + // Get name + let name = nameElement.value; + + // Check if the input is empty + if (name === "") return; + + // Call App.Greet(name) + try { + Greet(name) + .then((result) => { + // Update result with data back from App.Greet() + resultElement.innerText = result; + }) + .catch((err) => { + console.error(err); + }); + } catch (err) { + console.error(err); + } +}; + +// Auto-call Greet after 5 seconds to trigger the panic test +setTimeout(() => { + console.log("Auto-calling Greet to trigger panic test..."); + Greet("PanicTest") + .then((result) => { + resultElement.innerText = result + " (auto-called - panic will occur in 5s)"; + }) + .catch((err) => { + console.error("Error:", err); + }); +}, 5000); diff --git a/v2/examples/panic-recovery-test/frontend/src/style.css b/v2/examples/panic-recovery-test/frontend/src/style.css new file mode 100644 index 000000000..3940d6c63 --- /dev/null +++ b/v2/examples/panic-recovery-test/frontend/src/style.css @@ -0,0 +1,26 @@ +html { + background-color: rgba(27, 38, 54, 1); + text-align: center; + color: white; +} + +body { + margin: 0; + color: white; + font-family: "Nunito", -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", + "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", + sans-serif; +} + +@font-face { + font-family: "Nunito"; + font-style: normal; + font-weight: 400; + src: local(""), + url("assets/fonts/nunito-v16-latin-regular.woff2") format("woff2"); +} + +#app { + height: 100vh; + text-align: center; +} diff --git a/v2/examples/panic-recovery-test/frontend/wailsjs/go/main/App.d.ts b/v2/examples/panic-recovery-test/frontend/wailsjs/go/main/App.d.ts new file mode 100755 index 000000000..02a3bb988 --- /dev/null +++ b/v2/examples/panic-recovery-test/frontend/wailsjs/go/main/App.d.ts @@ -0,0 +1,4 @@ +// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL +// This file is automatically generated. DO NOT EDIT + +export function Greet(arg1:string):Promise; diff --git a/v2/examples/panic-recovery-test/frontend/wailsjs/go/main/App.js b/v2/examples/panic-recovery-test/frontend/wailsjs/go/main/App.js new file mode 100755 index 000000000..c71ae77cb --- /dev/null +++ b/v2/examples/panic-recovery-test/frontend/wailsjs/go/main/App.js @@ -0,0 +1,7 @@ +// @ts-check +// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL +// This file is automatically generated. DO NOT EDIT + +export function Greet(arg1) { + return window['go']['main']['App']['Greet'](arg1); +} diff --git a/v2/examples/panic-recovery-test/frontend/wailsjs/runtime/package.json b/v2/examples/panic-recovery-test/frontend/wailsjs/runtime/package.json new file mode 100644 index 000000000..1e7c8a5d7 --- /dev/null +++ b/v2/examples/panic-recovery-test/frontend/wailsjs/runtime/package.json @@ -0,0 +1,24 @@ +{ + "name": "@wailsapp/runtime", + "version": "2.0.0", + "description": "Wails Javascript runtime library", + "main": "runtime.js", + "types": "runtime.d.ts", + "scripts": { + }, + "repository": { + "type": "git", + "url": "git+https://github.com/wailsapp/wails.git" + }, + "keywords": [ + "Wails", + "Javascript", + "Go" + ], + "author": "Lea Anthony ", + "license": "MIT", + "bugs": { + "url": "https://github.com/wailsapp/wails/issues" + }, + "homepage": "https://github.com/wailsapp/wails#readme" +} diff --git a/v2/examples/panic-recovery-test/frontend/wailsjs/runtime/runtime.d.ts b/v2/examples/panic-recovery-test/frontend/wailsjs/runtime/runtime.d.ts new file mode 100644 index 000000000..4445dac21 --- /dev/null +++ b/v2/examples/panic-recovery-test/frontend/wailsjs/runtime/runtime.d.ts @@ -0,0 +1,249 @@ +/* + _ __ _ __ +| | / /___ _(_) /____ +| | /| / / __ `/ / / ___/ +| |/ |/ / /_/ / / (__ ) +|__/|__/\__,_/_/_/____/ +The electron alternative for Go +(c) Lea Anthony 2019-present +*/ + +export interface Position { + x: number; + y: number; +} + +export interface Size { + w: number; + h: number; +} + +export interface Screen { + isCurrent: boolean; + isPrimary: boolean; + width : number + height : number +} + +// Environment information such as platform, buildtype, ... +export interface EnvironmentInfo { + buildType: string; + platform: string; + arch: string; +} + +// [EventsEmit](https://wails.io/docs/reference/runtime/events#eventsemit) +// emits the given event. Optional data may be passed with the event. +// This will trigger any event listeners. +export function EventsEmit(eventName: string, ...data: any): void; + +// [EventsOn](https://wails.io/docs/reference/runtime/events#eventson) sets up a listener for the given event name. +export function EventsOn(eventName: string, callback: (...data: any) => void): () => void; + +// [EventsOnMultiple](https://wails.io/docs/reference/runtime/events#eventsonmultiple) +// sets up a listener for the given event name, but will only trigger a given number times. +export function EventsOnMultiple(eventName: string, callback: (...data: any) => void, maxCallbacks: number): () => void; + +// [EventsOnce](https://wails.io/docs/reference/runtime/events#eventsonce) +// sets up a listener for the given event name, but will only trigger once. +export function EventsOnce(eventName: string, callback: (...data: any) => void): () => void; + +// [EventsOff](https://wails.io/docs/reference/runtime/events#eventsoff) +// unregisters the listener for the given event name. +export function EventsOff(eventName: string, ...additionalEventNames: string[]): void; + +// [EventsOffAll](https://wails.io/docs/reference/runtime/events#eventsoffall) +// unregisters all listeners. +export function EventsOffAll(): void; + +// [LogPrint](https://wails.io/docs/reference/runtime/log#logprint) +// logs the given message as a raw message +export function LogPrint(message: string): void; + +// [LogTrace](https://wails.io/docs/reference/runtime/log#logtrace) +// logs the given message at the `trace` log level. +export function LogTrace(message: string): void; + +// [LogDebug](https://wails.io/docs/reference/runtime/log#logdebug) +// logs the given message at the `debug` log level. +export function LogDebug(message: string): void; + +// [LogError](https://wails.io/docs/reference/runtime/log#logerror) +// logs the given message at the `error` log level. +export function LogError(message: string): void; + +// [LogFatal](https://wails.io/docs/reference/runtime/log#logfatal) +// logs the given message at the `fatal` log level. +// The application will quit after calling this method. +export function LogFatal(message: string): void; + +// [LogInfo](https://wails.io/docs/reference/runtime/log#loginfo) +// logs the given message at the `info` log level. +export function LogInfo(message: string): void; + +// [LogWarning](https://wails.io/docs/reference/runtime/log#logwarning) +// logs the given message at the `warning` log level. +export function LogWarning(message: string): void; + +// [WindowReload](https://wails.io/docs/reference/runtime/window#windowreload) +// Forces a reload by the main application as well as connected browsers. +export function WindowReload(): void; + +// [WindowReloadApp](https://wails.io/docs/reference/runtime/window#windowreloadapp) +// Reloads the application frontend. +export function WindowReloadApp(): void; + +// [WindowSetAlwaysOnTop](https://wails.io/docs/reference/runtime/window#windowsetalwaysontop) +// Sets the window AlwaysOnTop or not on top. +export function WindowSetAlwaysOnTop(b: boolean): void; + +// [WindowSetSystemDefaultTheme](https://wails.io/docs/next/reference/runtime/window#windowsetsystemdefaulttheme) +// *Windows only* +// Sets window theme to system default (dark/light). +export function WindowSetSystemDefaultTheme(): void; + +// [WindowSetLightTheme](https://wails.io/docs/next/reference/runtime/window#windowsetlighttheme) +// *Windows only* +// Sets window to light theme. +export function WindowSetLightTheme(): void; + +// [WindowSetDarkTheme](https://wails.io/docs/next/reference/runtime/window#windowsetdarktheme) +// *Windows only* +// Sets window to dark theme. +export function WindowSetDarkTheme(): void; + +// [WindowCenter](https://wails.io/docs/reference/runtime/window#windowcenter) +// Centers the window on the monitor the window is currently on. +export function WindowCenter(): void; + +// [WindowSetTitle](https://wails.io/docs/reference/runtime/window#windowsettitle) +// Sets the text in the window title bar. +export function WindowSetTitle(title: string): void; + +// [WindowFullscreen](https://wails.io/docs/reference/runtime/window#windowfullscreen) +// Makes the window full screen. +export function WindowFullscreen(): void; + +// [WindowUnfullscreen](https://wails.io/docs/reference/runtime/window#windowunfullscreen) +// Restores the previous window dimensions and position prior to full screen. +export function WindowUnfullscreen(): void; + +// [WindowIsFullscreen](https://wails.io/docs/reference/runtime/window#windowisfullscreen) +// Returns the state of the window, i.e. whether the window is in full screen mode or not. +export function WindowIsFullscreen(): Promise; + +// [WindowSetSize](https://wails.io/docs/reference/runtime/window#windowsetsize) +// Sets the width and height of the window. +export function WindowSetSize(width: number, height: number): void; + +// [WindowGetSize](https://wails.io/docs/reference/runtime/window#windowgetsize) +// Gets the width and height of the window. +export function WindowGetSize(): Promise; + +// [WindowSetMaxSize](https://wails.io/docs/reference/runtime/window#windowsetmaxsize) +// Sets the maximum window size. Will resize the window if the window is currently larger than the given dimensions. +// Setting a size of 0,0 will disable this constraint. +export function WindowSetMaxSize(width: number, height: number): void; + +// [WindowSetMinSize](https://wails.io/docs/reference/runtime/window#windowsetminsize) +// Sets the minimum window size. Will resize the window if the window is currently smaller than the given dimensions. +// Setting a size of 0,0 will disable this constraint. +export function WindowSetMinSize(width: number, height: number): void; + +// [WindowSetPosition](https://wails.io/docs/reference/runtime/window#windowsetposition) +// Sets the window position relative to the monitor the window is currently on. +export function WindowSetPosition(x: number, y: number): void; + +// [WindowGetPosition](https://wails.io/docs/reference/runtime/window#windowgetposition) +// Gets the window position relative to the monitor the window is currently on. +export function WindowGetPosition(): Promise; + +// [WindowHide](https://wails.io/docs/reference/runtime/window#windowhide) +// Hides the window. +export function WindowHide(): void; + +// [WindowShow](https://wails.io/docs/reference/runtime/window#windowshow) +// Shows the window, if it is currently hidden. +export function WindowShow(): void; + +// [WindowMaximise](https://wails.io/docs/reference/runtime/window#windowmaximise) +// Maximises the window to fill the screen. +export function WindowMaximise(): void; + +// [WindowToggleMaximise](https://wails.io/docs/reference/runtime/window#windowtogglemaximise) +// Toggles between Maximised and UnMaximised. +export function WindowToggleMaximise(): void; + +// [WindowUnmaximise](https://wails.io/docs/reference/runtime/window#windowunmaximise) +// Restores the window to the dimensions and position prior to maximising. +export function WindowUnmaximise(): void; + +// [WindowIsMaximised](https://wails.io/docs/reference/runtime/window#windowismaximised) +// Returns the state of the window, i.e. whether the window is maximised or not. +export function WindowIsMaximised(): Promise; + +// [WindowMinimise](https://wails.io/docs/reference/runtime/window#windowminimise) +// Minimises the window. +export function WindowMinimise(): void; + +// [WindowUnminimise](https://wails.io/docs/reference/runtime/window#windowunminimise) +// Restores the window to the dimensions and position prior to minimising. +export function WindowUnminimise(): void; + +// [WindowIsMinimised](https://wails.io/docs/reference/runtime/window#windowisminimised) +// Returns the state of the window, i.e. whether the window is minimised or not. +export function WindowIsMinimised(): Promise; + +// [WindowIsNormal](https://wails.io/docs/reference/runtime/window#windowisnormal) +// Returns the state of the window, i.e. whether the window is normal or not. +export function WindowIsNormal(): Promise; + +// [WindowSetBackgroundColour](https://wails.io/docs/reference/runtime/window#windowsetbackgroundcolour) +// Sets the background colour of the window to the given RGBA colour definition. This colour will show through for all transparent pixels. +export function WindowSetBackgroundColour(R: number, G: number, B: number, A: number): void; + +// [ScreenGetAll](https://wails.io/docs/reference/runtime/window#screengetall) +// Gets the all screens. Call this anew each time you want to refresh data from the underlying windowing system. +export function ScreenGetAll(): Promise; + +// [BrowserOpenURL](https://wails.io/docs/reference/runtime/browser#browseropenurl) +// Opens the given URL in the system browser. +export function BrowserOpenURL(url: string): void; + +// [Environment](https://wails.io/docs/reference/runtime/intro#environment) +// Returns information about the environment +export function Environment(): Promise; + +// [Quit](https://wails.io/docs/reference/runtime/intro#quit) +// Quits the application. +export function Quit(): void; + +// [Hide](https://wails.io/docs/reference/runtime/intro#hide) +// Hides the application. +export function Hide(): void; + +// [Show](https://wails.io/docs/reference/runtime/intro#show) +// Shows the application. +export function Show(): void; + +// [ClipboardGetText](https://wails.io/docs/reference/runtime/clipboard#clipboardgettext) +// Returns the current text stored on clipboard +export function ClipboardGetText(): Promise; + +// [ClipboardSetText](https://wails.io/docs/reference/runtime/clipboard#clipboardsettext) +// Sets a text on the clipboard +export function ClipboardSetText(text: string): Promise; + +// [OnFileDrop](https://wails.io/docs/reference/runtime/draganddrop#onfiledrop) +// OnFileDrop listens to drag and drop events and calls the callback with the coordinates of the drop and an array of path strings. +export function OnFileDrop(callback: (x: number, y: number ,paths: string[]) => void, useDropTarget: boolean) :void + +// [OnFileDropOff](https://wails.io/docs/reference/runtime/draganddrop#dragandddropoff) +// OnFileDropOff removes the drag and drop listeners and handlers. +export function OnFileDropOff() :void + +// Check if the file path resolver is available +export function CanResolveFilePaths(): boolean; + +// Resolves file paths for an array of files +export function ResolveFilePaths(files: File[]): void \ No newline at end of file diff --git a/v2/examples/panic-recovery-test/frontend/wailsjs/runtime/runtime.js b/v2/examples/panic-recovery-test/frontend/wailsjs/runtime/runtime.js new file mode 100644 index 000000000..7cb89d750 --- /dev/null +++ b/v2/examples/panic-recovery-test/frontend/wailsjs/runtime/runtime.js @@ -0,0 +1,242 @@ +/* + _ __ _ __ +| | / /___ _(_) /____ +| | /| / / __ `/ / / ___/ +| |/ |/ / /_/ / / (__ ) +|__/|__/\__,_/_/_/____/ +The electron alternative for Go +(c) Lea Anthony 2019-present +*/ + +export function LogPrint(message) { + window.runtime.LogPrint(message); +} + +export function LogTrace(message) { + window.runtime.LogTrace(message); +} + +export function LogDebug(message) { + window.runtime.LogDebug(message); +} + +export function LogInfo(message) { + window.runtime.LogInfo(message); +} + +export function LogWarning(message) { + window.runtime.LogWarning(message); +} + +export function LogError(message) { + window.runtime.LogError(message); +} + +export function LogFatal(message) { + window.runtime.LogFatal(message); +} + +export function EventsOnMultiple(eventName, callback, maxCallbacks) { + return window.runtime.EventsOnMultiple(eventName, callback, maxCallbacks); +} + +export function EventsOn(eventName, callback) { + return EventsOnMultiple(eventName, callback, -1); +} + +export function EventsOff(eventName, ...additionalEventNames) { + return window.runtime.EventsOff(eventName, ...additionalEventNames); +} + +export function EventsOffAll() { + return window.runtime.EventsOffAll(); +} + +export function EventsOnce(eventName, callback) { + return EventsOnMultiple(eventName, callback, 1); +} + +export function EventsEmit(eventName) { + let args = [eventName].slice.call(arguments); + return window.runtime.EventsEmit.apply(null, args); +} + +export function WindowReload() { + window.runtime.WindowReload(); +} + +export function WindowReloadApp() { + window.runtime.WindowReloadApp(); +} + +export function WindowSetAlwaysOnTop(b) { + window.runtime.WindowSetAlwaysOnTop(b); +} + +export function WindowSetSystemDefaultTheme() { + window.runtime.WindowSetSystemDefaultTheme(); +} + +export function WindowSetLightTheme() { + window.runtime.WindowSetLightTheme(); +} + +export function WindowSetDarkTheme() { + window.runtime.WindowSetDarkTheme(); +} + +export function WindowCenter() { + window.runtime.WindowCenter(); +} + +export function WindowSetTitle(title) { + window.runtime.WindowSetTitle(title); +} + +export function WindowFullscreen() { + window.runtime.WindowFullscreen(); +} + +export function WindowUnfullscreen() { + window.runtime.WindowUnfullscreen(); +} + +export function WindowIsFullscreen() { + return window.runtime.WindowIsFullscreen(); +} + +export function WindowGetSize() { + return window.runtime.WindowGetSize(); +} + +export function WindowSetSize(width, height) { + window.runtime.WindowSetSize(width, height); +} + +export function WindowSetMaxSize(width, height) { + window.runtime.WindowSetMaxSize(width, height); +} + +export function WindowSetMinSize(width, height) { + window.runtime.WindowSetMinSize(width, height); +} + +export function WindowSetPosition(x, y) { + window.runtime.WindowSetPosition(x, y); +} + +export function WindowGetPosition() { + return window.runtime.WindowGetPosition(); +} + +export function WindowHide() { + window.runtime.WindowHide(); +} + +export function WindowShow() { + window.runtime.WindowShow(); +} + +export function WindowMaximise() { + window.runtime.WindowMaximise(); +} + +export function WindowToggleMaximise() { + window.runtime.WindowToggleMaximise(); +} + +export function WindowUnmaximise() { + window.runtime.WindowUnmaximise(); +} + +export function WindowIsMaximised() { + return window.runtime.WindowIsMaximised(); +} + +export function WindowMinimise() { + window.runtime.WindowMinimise(); +} + +export function WindowUnminimise() { + window.runtime.WindowUnminimise(); +} + +export function WindowSetBackgroundColour(R, G, B, A) { + window.runtime.WindowSetBackgroundColour(R, G, B, A); +} + +export function ScreenGetAll() { + return window.runtime.ScreenGetAll(); +} + +export function WindowIsMinimised() { + return window.runtime.WindowIsMinimised(); +} + +export function WindowIsNormal() { + return window.runtime.WindowIsNormal(); +} + +export function BrowserOpenURL(url) { + window.runtime.BrowserOpenURL(url); +} + +export function Environment() { + return window.runtime.Environment(); +} + +export function Quit() { + window.runtime.Quit(); +} + +export function Hide() { + window.runtime.Hide(); +} + +export function Show() { + window.runtime.Show(); +} + +export function ClipboardGetText() { + return window.runtime.ClipboardGetText(); +} + +export function ClipboardSetText(text) { + return window.runtime.ClipboardSetText(text); +} + +/** + * Callback for OnFileDrop returns a slice of file path strings when a drop is finished. + * + * @export + * @callback OnFileDropCallback + * @param {number} x - x coordinate of the drop + * @param {number} y - y coordinate of the drop + * @param {string[]} paths - A list of file paths. + */ + +/** + * OnFileDrop listens to drag and drop events and calls the callback with the coordinates of the drop and an array of path strings. + * + * @export + * @param {OnFileDropCallback} callback - Callback for OnFileDrop returns a slice of file path strings when a drop is finished. + * @param {boolean} [useDropTarget=true] - Only call the callback when the drop finished on an element that has the drop target style. (--wails-drop-target) + */ +export function OnFileDrop(callback, useDropTarget) { + return window.runtime.OnFileDrop(callback, useDropTarget); +} + +/** + * OnFileDropOff removes the drag and drop listeners and handlers. + */ +export function OnFileDropOff() { + return window.runtime.OnFileDropOff(); +} + +export function CanResolveFilePaths() { + return window.runtime.CanResolveFilePaths(); +} + +export function ResolveFilePaths(files) { + return window.runtime.ResolveFilePaths(files); +} \ No newline at end of file diff --git a/v2/examples/panic-recovery-test/go.mod b/v2/examples/panic-recovery-test/go.mod new file mode 100644 index 000000000..026042cbf --- /dev/null +++ b/v2/examples/panic-recovery-test/go.mod @@ -0,0 +1,5 @@ +module panic-recovery-test + +go 1.21 + +require github.com/wailsapp/wails/v2 v2.11.0 diff --git a/v2/examples/panic-recovery-test/main.go b/v2/examples/panic-recovery-test/main.go new file mode 100644 index 000000000..f6a38e86c --- /dev/null +++ b/v2/examples/panic-recovery-test/main.go @@ -0,0 +1,36 @@ +package main + +import ( + "embed" + + "github.com/wailsapp/wails/v2" + "github.com/wailsapp/wails/v2/pkg/options" + "github.com/wailsapp/wails/v2/pkg/options/assetserver" +) + +//go:embed all:frontend/dist +var assets embed.FS + +func main() { + // Create an instance of the app structure + app := NewApp() + + // Create application with options + err := wails.Run(&options.App{ + Title: "panic-test", + Width: 1024, + Height: 768, + AssetServer: &assetserver.Options{ + Assets: assets, + }, + BackgroundColour: &options.RGBA{R: 27, G: 38, B: 54, A: 1}, + OnStartup: app.startup, + Bind: []interface{}{ + app, + }, + }) + + if err != nil { + println("Error:", err.Error()) + } +} diff --git a/v2/examples/panic-recovery-test/wails.json b/v2/examples/panic-recovery-test/wails.json new file mode 100644 index 000000000..56770f091 --- /dev/null +++ b/v2/examples/panic-recovery-test/wails.json @@ -0,0 +1,13 @@ +{ + "$schema": "https://wails.io/schemas/config.v2.json", + "name": "panic-recovery-test", + "outputfilename": "panic-recovery-test", + "frontend:install": "npm install", + "frontend:build": "npm run build", + "frontend:dev:watcher": "npm run dev", + "frontend:dev:serverUrl": "auto", + "author": { + "name": "Lea Anthony", + "email": "lea.anthony@gmail.com" + } +} diff --git a/v2/go.mod b/v2/go.mod index 375f6ee6f..2eb753ee2 100644 --- a/v2/go.mod +++ b/v2/go.mod @@ -1,109 +1,112 @@ module github.com/wailsapp/wails/v2 -go 1.21 +go 1.22.0 require ( github.com/Masterminds/semver v1.5.0 github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d github.com/bep/debounce v1.2.1 - github.com/bitfield/script v0.19.0 - github.com/charmbracelet/glamour v0.5.0 - github.com/flytam/filenamify v1.0.0 - github.com/fsnotify/fsnotify v1.4.9 - github.com/go-git/go-git/v5 v5.11.0 - github.com/go-ole/go-ole v1.2.6 + github.com/bitfield/script v0.24.0 + github.com/charmbracelet/glamour v0.8.0 + github.com/flytam/filenamify v1.2.0 + github.com/fsnotify/fsnotify v1.9.0 + github.com/go-git/go-git/v5 v5.13.2 + github.com/go-ole/go-ole v1.3.0 github.com/godbus/dbus/v5 v5.1.0 github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 - github.com/google/uuid v1.3.0 + github.com/google/uuid v1.6.0 + github.com/gorilla/websocket v1.5.3 github.com/jackmordaunt/icns v1.0.0 - github.com/jaypipes/ghw v0.12.0 - github.com/labstack/echo/v4 v4.10.2 - github.com/labstack/gommon v0.4.0 + github.com/jaypipes/ghw v0.21.3 + github.com/labstack/echo/v4 v4.13.3 + github.com/labstack/gommon v0.4.2 github.com/leaanthony/clir v1.3.0 github.com/leaanthony/debme v1.2.1 - github.com/leaanthony/go-ansi-parser v1.6.0 - github.com/leaanthony/gosod v1.0.3 + github.com/leaanthony/go-ansi-parser v1.6.1 + github.com/leaanthony/gosod v1.0.4 github.com/leaanthony/slicer v1.6.0 - github.com/leaanthony/u v1.1.0 + github.com/leaanthony/u v1.1.1 github.com/leaanthony/winicon v1.0.0 - github.com/matryer/is v1.4.0 - github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 + github.com/matryer/is v1.4.1 + github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c github.com/pkg/errors v0.9.1 - github.com/pterm/pterm v0.12.49 + github.com/pterm/pterm v0.12.80 github.com/sabhiram/go-gitignore v0.0.0-20210923224102-525f6e181f06 - github.com/samber/lo v1.38.1 - github.com/stretchr/testify v1.8.4 - github.com/tc-hib/winres v0.2.1 - github.com/tidwall/sjson v1.1.7 - github.com/tkrajina/go-reflector v0.5.6 - github.com/wailsapp/go-webview2 v1.0.10 + github.com/samber/lo v1.49.1 + github.com/stretchr/testify v1.10.0 + github.com/tc-hib/winres v0.3.1 + github.com/tidwall/sjson v1.2.5 + github.com/tkrajina/go-reflector v0.5.8 + github.com/wailsapp/go-webview2 v1.0.22 github.com/wailsapp/mimetype v1.4.1 github.com/wzshiming/ctc v1.2.3 - golang.org/x/mod v0.14.0 - golang.org/x/net v0.25.0 - golang.org/x/sys v0.20.0 - golang.org/x/tools v0.17.0 + golang.org/x/mod v0.23.0 + golang.org/x/net v0.35.0 + golang.org/x/sys v0.30.0 + golang.org/x/tools v0.30.0 ) require ( - atomicgo.dev/cursor v0.1.1 // indirect - atomicgo.dev/keyboard v0.2.8 // indirect - bitbucket.org/creachadair/shell v0.0.7 // indirect + atomicgo.dev/cursor v0.2.0 // indirect + atomicgo.dev/keyboard v0.2.9 // indirect + atomicgo.dev/schedule v0.1.0 // indirect dario.cat/mergo v1.0.0 // indirect github.com/Microsoft/go-winio v0.6.1 // indirect - github.com/ProtonMail/go-crypto v0.0.0-20230828082145-3c4c8a2d2371 // indirect - github.com/StackExchange/wmi v1.2.1 // indirect - github.com/alecthomas/chroma v0.10.0 // indirect + github.com/ProtonMail/go-crypto v1.1.5 // indirect + github.com/alecthomas/chroma/v2 v2.14.0 // indirect + github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect github.com/aymerick/douceur v0.2.0 // indirect + github.com/charmbracelet/lipgloss v0.12.1 // indirect + github.com/charmbracelet/x/ansi v0.1.4 // indirect github.com/cloudflare/circl v1.3.7 // indirect github.com/containerd/console v1.0.3 // indirect - github.com/cyphar/filepath-securejoin v0.2.4 // indirect + github.com/cyphar/filepath-securejoin v0.3.6 // indirect github.com/davecgh/go-spew v1.1.1 // indirect - github.com/dlclark/regexp2 v1.4.0 // indirect + github.com/dlclark/regexp2 v1.11.0 // indirect github.com/emirpasic/gods v1.18.1 // indirect - github.com/ghodss/yaml v1.0.0 // indirect github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect - github.com/go-git/go-billy/v5 v5.5.0 // indirect + github.com/go-git/go-billy/v5 v5.6.2 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect - github.com/gookit/color v1.5.2 // indirect - github.com/gorilla/css v1.0.0 // indirect - github.com/jaypipes/pcidb v1.0.0 // indirect + github.com/gookit/color v1.5.4 // indirect + github.com/gorilla/css v1.0.1 // indirect + github.com/itchyny/gojq v0.12.13 // indirect + github.com/itchyny/timefmt-go v0.1.5 // indirect + github.com/jaypipes/pcidb v1.1.1 // indirect github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect github.com/jchv/go-winloader v0.0.0-20210711035445-715c2860da7e // indirect github.com/kevinburke/ssh_config v1.2.0 // indirect - github.com/lithammer/fuzzysearch v1.1.5 // indirect + github.com/lithammer/fuzzysearch v1.1.8 // indirect github.com/lucasb-eyer/go-colorful v1.2.0 // indirect github.com/mattn/go-colorable v0.1.13 // indirect - github.com/mattn/go-isatty v0.0.19 // indirect - github.com/mattn/go-runewidth v0.0.13 // indirect - github.com/microcosm-cc/bluemonday v1.0.17 // indirect - github.com/mitchellh/go-homedir v1.1.0 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect + github.com/mattn/go-runewidth v0.0.16 // indirect + github.com/microcosm-cc/bluemonday v1.0.27 // indirect github.com/muesli/reflow v0.3.0 // indirect - github.com/muesli/termenv v0.9.0 // indirect + github.com/muesli/termenv v0.15.3-0.20240618155329-98d742f6907a // indirect github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 // indirect - github.com/olekukonko/tablewriter v0.0.5 // indirect - github.com/pjbgf/sha1cd v0.3.0 // indirect + github.com/pjbgf/sha1cd v0.3.2 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/rivo/uniseg v0.4.4 // indirect - github.com/sergi/go-diff v1.2.0 // indirect - github.com/skeema/knownhosts v1.2.1 // indirect - github.com/tidwall/gjson v1.9.3 // indirect + github.com/rivo/uniseg v0.4.7 // indirect + github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 // indirect + github.com/skeema/knownhosts v1.3.0 // indirect + github.com/tidwall/gjson v1.14.2 // indirect github.com/tidwall/match v1.1.1 // indirect github.com/tidwall/pretty v1.2.0 // indirect github.com/valyala/bytebufferpool v1.0.0 // indirect github.com/valyala/fasttemplate v1.2.2 // indirect github.com/wzshiming/winseq v0.0.0-20200112104235-db357dc107ae // indirect github.com/xanzy/ssh-agent v0.3.3 // indirect - github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778 // indirect - github.com/yuin/goldmark v1.4.13 // indirect - github.com/yuin/goldmark-emoji v1.0.1 // indirect - golang.org/x/crypto v0.23.0 // indirect - golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1 // indirect + github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect + github.com/yuin/goldmark v1.7.4 // indirect + github.com/yuin/goldmark-emoji v1.0.3 // indirect + github.com/yusufpapurcu/wmi v1.2.4 // indirect + golang.org/x/crypto v0.33.0 // indirect golang.org/x/image v0.12.0 // indirect - golang.org/x/term v0.20.0 // indirect - golang.org/x/text v0.15.0 // indirect + golang.org/x/sync v0.11.0 // indirect + golang.org/x/term v0.29.0 // indirect + golang.org/x/text v0.22.0 // indirect gopkg.in/warnings.v0 v0.1.2 // indirect - gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect - howett.net/plist v1.0.0 // indirect + howett.net/plist v1.0.2-0.20250314012144-ee69052608d9 // indirect + mvdan.cc/sh/v3 v3.7.0 // indirect ) diff --git a/v2/go.sum b/v2/go.sum index 6e273e1ba..f6df3507e 100644 --- a/v2/go.sum +++ b/v2/go.sum @@ -1,9 +1,11 @@ -atomicgo.dev/cursor v0.1.1 h1:0t9sxQomCTRh5ug+hAMCs59x/UmC9QL6Ci5uosINKD4= -atomicgo.dev/cursor v0.1.1/go.mod h1:Lr4ZJB3U7DfPPOkbH7/6TOtJ4vFGHlgj1nc+n900IpU= -atomicgo.dev/keyboard v0.2.8 h1:Di09BitwZgdTV1hPyX/b9Cqxi8HVuJQwWivnZUEqlj4= -atomicgo.dev/keyboard v0.2.8/go.mod h1:BC4w9g00XkxH/f1HXhW2sXmJFOCWbKn9xrOunSFtExQ= -bitbucket.org/creachadair/shell v0.0.7 h1:Z96pB6DkSb7F3Y3BBnJeOZH2gazyMTWlvecSD4vDqfk= -bitbucket.org/creachadair/shell v0.0.7/go.mod h1:oqtXSSvSYr4624lnnabXHaBsYW6RD80caLi2b3hJk0U= +atomicgo.dev/assert v0.0.2 h1:FiKeMiZSgRrZsPo9qn/7vmr7mCsh5SZyXY4YGYiYwrg= +atomicgo.dev/assert v0.0.2/go.mod h1:ut4NcI3QDdJtlmAxQULOmA13Gz6e2DWbSAS8RUOmNYQ= +atomicgo.dev/cursor v0.2.0 h1:H6XN5alUJ52FZZUkI7AlJbUc1aW38GWZalpYRPpoPOw= +atomicgo.dev/cursor v0.2.0/go.mod h1:Lr4ZJB3U7DfPPOkbH7/6TOtJ4vFGHlgj1nc+n900IpU= +atomicgo.dev/keyboard v0.2.9 h1:tOsIid3nlPLZ3lwgG8KZMp/SFmr7P0ssEN5JUsm78K8= +atomicgo.dev/keyboard v0.2.9/go.mod h1:BC4w9g00XkxH/f1HXhW2sXmJFOCWbKn9xrOunSFtExQ= +atomicgo.dev/schedule v0.1.0 h1:nTthAbhZS5YZmgYbb2+DH8uQIZcTlIrd4eYr3UQxEjs= +atomicgo.dev/schedule v0.1.0/go.mod h1:xeUa3oAkiuHYh8bKiQBRojqAMq3PXXbJujjb0hw8pEU= dario.cat/mergo v1.0.0 h1:AGCNq9Evsj31mOgNPcLyXc+4PNABt905YmuqPYYpBWk= dario.cat/mergo v1.0.0/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= github.com/MarvinJWendt/testza v0.1.0/go.mod h1:7AxNvlfeHP7Z/hDQ5JtE3OKYT3XFUeLCDE2DQninSqs= @@ -13,94 +15,110 @@ github.com/MarvinJWendt/testza v0.2.10/go.mod h1:pd+VWsoGUiFtq+hRKSU1Bktnn+DMCSr github.com/MarvinJWendt/testza v0.2.12/go.mod h1:JOIegYyV7rX+7VZ9r77L/eH6CfJHHzXjB69adAhzZkI= github.com/MarvinJWendt/testza v0.3.0/go.mod h1:eFcL4I0idjtIx8P9C6KkAuLgATNKpX4/2oUqKc6bF2c= github.com/MarvinJWendt/testza v0.4.2/go.mod h1:mSdhXiKH8sg/gQehJ63bINcCKp7RtYewEjXsvsVUPbE= -github.com/MarvinJWendt/testza v0.4.3 h1:u2XaM4IqGp9dsdUmML8/Z791fu4yjQYzOiufOtJwTII= -github.com/MarvinJWendt/testza v0.4.3/go.mod h1:CpXaOfceNEYnLDtNIyTrPPcCpDJYqzZnu2aiA2Wp33U= +github.com/MarvinJWendt/testza v0.5.2 h1:53KDo64C1z/h/d/stCYCPY69bt/OSwjq5KpFNwi+zB4= +github.com/MarvinJWendt/testza v0.5.2/go.mod h1:xu53QFE5sCdjtMCKk8YMQ2MnymimEctc4n3EjyIYvEY= github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww= github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y= github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY= github.com/Microsoft/go-winio v0.6.1 h1:9/kr64B9VUZrLm5YYwbGtUJnMgqWVOdUAXu6Migciow= github.com/Microsoft/go-winio v0.6.1/go.mod h1:LRdKpFKfdobln8UmuiYcKPot9D2v6svN5+sAH+4kjUM= -github.com/ProtonMail/go-crypto v0.0.0-20230828082145-3c4c8a2d2371 h1:kkhsdkhsCvIsutKu5zLMgWtgh9YxGCNAw8Ad8hjwfYg= -github.com/ProtonMail/go-crypto v0.0.0-20230828082145-3c4c8a2d2371/go.mod h1:EjAoLdwvbIOoOQr3ihjnSoLZRtE8azugULFRteWMNc0= -github.com/StackExchange/wmi v1.2.1 h1:VIkavFPXSjcnS+O8yTq7NI32k0R5Aj+v39y29VYDOSA= -github.com/StackExchange/wmi v1.2.1/go.mod h1:rcmrprowKIVzvc+NUiLncP2uuArMWLCbu9SBzvHz7e8= +github.com/ProtonMail/go-crypto v1.1.5 h1:eoAQfK2dwL+tFSFpr7TbOaPNUbPiJj4fLYwwGE1FQO4= +github.com/ProtonMail/go-crypto v1.1.5/go.mod h1:rA3QumHc/FZ8pAHreoekgiAbzpNsfQAosU5td4SnOrE= github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d h1:licZJFw2RwpHMqeKTCYkitsPqHNxTmd4SNR5r94FGM8= github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d/go.mod h1:asat636LX7Bqt5lYEZ27JNDcqxfjdBQuJ/MM4CN/Lzo= -github.com/alecthomas/chroma v0.10.0 h1:7XDcGkCQopCNKjZHfYrNLraA+M7e0fMiJ/Mfikbfjek= -github.com/alecthomas/chroma v0.10.0/go.mod h1:jtJATyUxlIORhUOFNA9NZDWGAQ8wpxQQqNSB4rjA/1s= +github.com/alecthomas/assert/v2 v2.7.0 h1:QtqSACNS3tF7oasA8CU6A6sXZSBDqnm7RfpLl9bZqbE= +github.com/alecthomas/assert/v2 v2.7.0/go.mod h1:Bze95FyfUr7x34QZrjL+XP+0qgp/zg8yS+TtBj1WA3k= +github.com/alecthomas/chroma/v2 v2.14.0 h1:R3+wzpnUArGcQz7fCETQBzO5n9IMNi13iIs46aU4V9E= +github.com/alecthomas/chroma/v2 v2.14.0/go.mod h1:QolEbTfmUHIMVpBqxeDnNBj2uoeI4EbYP4i6n68SG4I= +github.com/alecthomas/repr v0.4.0 h1:GhI2A8MACjfegCPVq9f1FLvIBS+DrQ2KQBFZP1iFzXc= +github.com/alecthomas/repr v0.4.0/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4= github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8= github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= github.com/atomicgo/cursor v0.0.1/go.mod h1:cBON2QmmrysudxNBFthvMtN32r3jxVRIvzkUiF/RuIk= +github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k= +github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8= +github.com/aymanbagabas/go-udiff v0.2.0 h1:TK0fH4MteXUDspT88n8CKzvK0X9O2xu9yQjWpi6yML8= +github.com/aymanbagabas/go-udiff v0.2.0/go.mod h1:RE4Ex0qsGkTAJoQdQQCA0uG+nAzJO/pI/QwceO5fgrA= github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk= github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4= github.com/bep/debounce v1.2.1 h1:v67fRdBA9UQu2NhLFXrSg0Brw7CexQekrBwDMM8bzeY= github.com/bep/debounce v1.2.1/go.mod h1:H8yggRPQKLUhUoqrJC1bO2xNya7vanpDl7xR3ISbCJ0= -github.com/bitfield/script v0.19.0 h1:W24f+FQuPab9gXcW8bhcbo5qO8AtrXyu3XOnR4zhHN0= -github.com/bitfield/script v0.19.0/go.mod h1:ana6F8YOSZ3ImT8SauIzuYSqXgFVkSUJ6kgja+WMmIY= -github.com/bwesterb/go-ristretto v1.2.3/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0= -github.com/charmbracelet/glamour v0.5.0 h1:wu15ykPdB7X6chxugG/NNfDUbyyrCLV9XBalj5wdu3g= -github.com/charmbracelet/glamour v0.5.0/go.mod h1:9ZRtG19AUIzcTm7FGLGbq3D5WKQ5UyZBbQsMQN0XIqc= -github.com/cloudflare/circl v1.3.3/go.mod h1:5XYMA4rFBvNIrhs50XuiBJ15vF2pZn4nnUKZrLbUZFA= +github.com/bitfield/script v0.24.0 h1:ic0Tbx+2AgRtkGGIcUyr+Un60vu4WXvqFrCSumf+T7M= +github.com/bitfield/script v0.24.0/go.mod h1:fv+6x4OzVsRs6qAlc7wiGq8fq1b5orhtQdtW0dwjUHI= +github.com/charmbracelet/glamour v0.8.0 h1:tPrjL3aRcQbn++7t18wOpgLyl8wrOHUEDS7IZ68QtZs= +github.com/charmbracelet/glamour v0.8.0/go.mod h1:ViRgmKkf3u5S7uakt2czJ272WSg2ZenlYEZXT2x7Bjw= +github.com/charmbracelet/lipgloss v0.12.1 h1:/gmzszl+pedQpjCOH+wFkZr/N90Snz40J/NR7A0zQcs= +github.com/charmbracelet/lipgloss v0.12.1/go.mod h1:V2CiwIuhx9S1S1ZlADfOj9HmxeMAORuz5izHb0zGbB8= +github.com/charmbracelet/x/ansi v0.1.4 h1:IEU3D6+dWwPSgZ6HBH+v6oUuZ/nVawMiWj5831KfiLM= +github.com/charmbracelet/x/ansi v0.1.4/go.mod h1:dk73KoMTT5AX5BsX0KrqhsTqAnhZZoCBjs7dGWp4Ktw= +github.com/charmbracelet/x/exp/golden v0.0.0-20240715153702-9ba8adf781c4 h1:6KzMkQeAF56rggw2NZu1L+TH7j9+DM1/2Kmh7KUxg1I= +github.com/charmbracelet/x/exp/golden v0.0.0-20240715153702-9ba8adf781c4/go.mod h1:wDlXFlCrmJ8J+swcL/MnGUuYnqgQdW9rhSD61oNMb6U= github.com/cloudflare/circl v1.3.7 h1:qlCDlTPz2n9fu58M0Nh1J/JzcFpfgkFHHX3O35r5vcU= github.com/cloudflare/circl v1.3.7/go.mod h1:sRTcRWXGLrKw6yIGJ+l7amYJFfAXbZG0kBSc8r4zxgA= github.com/containerd/console v1.0.3 h1:lIr7SlA5PxZyMV30bDW0MGbiOPXwc63yRuCP0ARubLw= github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkXar0TQ1gf3U= -github.com/cyphar/filepath-securejoin v0.2.4 h1:Ugdm7cg7i6ZK6x3xDF1oEu1nfkyfH53EtKeQYTC3kyg= -github.com/cyphar/filepath-securejoin v0.2.4/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4= +github.com/cyphar/filepath-securejoin v0.3.6 h1:4d9N5ykBnSp5Xn2JkhocYDkOpURL/18CYMpo6xB9uWM= +github.com/cyphar/filepath-securejoin v0.3.6/go.mod h1:Sdj7gXlvMcPZsbhwhQ33GguGLDGQL7h7bg04C/+u9jI= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/dlclark/regexp2 v1.4.0 h1:F1rxgk7p4uKjwIQxBs9oAXe5CqrXlCduYEJvrF4u93E= -github.com/dlclark/regexp2 v1.4.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc= -github.com/elazarl/goproxy v0.0.0-20230808193330-2592e75ae04a h1:mATvB/9r/3gvcejNsXKSkQ6lcIaNec2nyfOdlTBR2lU= -github.com/elazarl/goproxy v0.0.0-20230808193330-2592e75ae04a/go.mod h1:Ro8st/ElPeALwNFlcTpWmkr6IoMFfkjXAvTHpevnDsM= +github.com/dlclark/regexp2 v1.11.0 h1:G/nrcoOa7ZXlpoa/91N3X7mM3r8eIlMBBJZvsz/mxKI= +github.com/dlclark/regexp2 v1.11.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= +github.com/elazarl/goproxy v1.4.0 h1:4GyuSbFa+s26+3rmYNSuUVsx+HgPrV1bk1jXI0l9wjM= +github.com/elazarl/goproxy v1.4.0/go.mod h1:X/5W/t+gzDyLfHW4DrMdpjqYjpXsURlBt9lpBDxZZZQ= github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc= github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ= -github.com/flytam/filenamify v1.0.0 h1:ewx6BY2dj7U6h2zGPJmt33q/BjkSf/YsY/woQvnUNIs= -github.com/flytam/filenamify v1.0.0/go.mod h1:Dzf9kVycwcsBlr2ATg6uxjqiFgKGH+5SKFuhdeP5zu8= -github.com/fsnotify/fsnotify v1.4.9 h1:hsms1Qyu0jgnwNXIxa+/V/PDsU6CfLf6CNO8H7IWoS4= -github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= -github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= -github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= -github.com/gliderlabs/ssh v0.3.5 h1:OcaySEmAQJgyYcArR+gGGTHCyE7nvhEMTlYY+Dp8CpY= -github.com/gliderlabs/ssh v0.3.5/go.mod h1:8XB4KraRrX39qHhT6yxPsHedjA08I/uBVwj4xC+/+z4= +github.com/flytam/filenamify v1.2.0 h1:7RiSqXYR4cJftDQ5NuvljKMfd/ubKnW/j9C6iekChgI= +github.com/flytam/filenamify v1.2.0/go.mod h1:Dzf9kVycwcsBlr2ATg6uxjqiFgKGH+5SKFuhdeP5zu8= +github.com/frankban/quicktest v1.14.5 h1:dfYrrRyLtiqT9GyKXgdh+k4inNeTvmGbuSgZ3lx3GhA= +github.com/frankban/quicktest v1.14.5/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= +github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k= +github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= +github.com/gliderlabs/ssh v0.3.8 h1:a4YXD1V7xMF9g5nTkdfnja3Sxy1PVDCj1Zg4Wb8vY6c= +github.com/gliderlabs/ssh v0.3.8/go.mod h1:xYoytBv1sV0aL3CavoDuJIQNURXkkfPA/wxQ1pL1fAU= github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI= github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmSxCcxctByoQdvwPiA7DTK7jaaFDBTtu0ic= -github.com/go-git/go-billy/v5 v5.5.0 h1:yEY4yhzCDuMGSv83oGxiBotRzhwhNr8VZyphhiu+mTU= -github.com/go-git/go-billy/v5 v5.5.0/go.mod h1:hmexnoNsr2SJU1Ju67OaNz5ASJY3+sHgFRpCtpDCKow= +github.com/go-git/go-billy/v5 v5.6.2 h1:6Q86EsPXMa7c3YZ3aLAQsMA0VlWmy43r6FHqa/UNbRM= +github.com/go-git/go-billy/v5 v5.6.2/go.mod h1:rcFC2rAsp/erv7CMz9GczHcuD0D32fWzH+MJAU+jaUU= github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399 h1:eMje31YglSBqCdIqdhKBW8lokaMrL3uTkpGYlE2OOT4= github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399/go.mod h1:1OCfN199q1Jm3HZlxleg+Dw/mwps2Wbk9frAWm+4FII= -github.com/go-git/go-git/v5 v5.11.0 h1:XIZc1p+8YzypNr34itUfSvYJcv+eYdTnTvOZ2vD3cA4= -github.com/go-git/go-git/v5 v5.11.0/go.mod h1:6GFcX2P3NM7FPBfpePbpLd21XxsgdAt+lKqXmCUiUCY= -github.com/go-ole/go-ole v1.2.5/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= -github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= +github.com/go-git/go-git/v5 v5.13.2 h1:7O7xvsK7K+rZPKW6AQR1YyNhfywkv7B8/FsP3ki6Zv0= +github.com/go-git/go-git/v5 v5.13.2/go.mod h1:hWdW5P4YZRjmpGHwRH2v3zkWcNl6HeXaXQEMGb3NJ9A= github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= +github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE= +github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78= github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk= github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= -github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.7/go.mod h1:n+brtR0CgQNWTVd5ZUFpTBC8YFBDLK/h/bpaJ8/DtOE= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= -github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= -github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= +github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/gookit/color v1.4.2/go.mod h1:fqRyamkC1W8uxl+lxCQxOT09l/vYfZ+QeiX3rKQHCoQ= github.com/gookit/color v1.5.0/go.mod h1:43aQb+Zerm/BWh2GnrgOQm7ffz7tvQXEKV6BFMl7wAo= -github.com/gookit/color v1.5.2 h1:uLnfXcaFjlrDnQDT+NCBcfhrXqYTx/rcCa6xn01Y8yI= -github.com/gookit/color v1.5.2/go.mod h1:w8h4bGiHeeBpvQVePTutdbERIUf3oJE5lZ8HM0UgXyg= -github.com/gorilla/css v1.0.0 h1:BQqNyPTi50JCFMTw/b67hByjMVXZRwGha6wxVGkeihY= -github.com/gorilla/css v1.0.0/go.mod h1:Dn721qIggHpt4+EFCcTLTU/vk5ySda2ReITrtgBl60c= +github.com/gookit/color v1.5.4 h1:FZmqs7XOyGgCAxmWyPslpiok1k05wmY3SJTytgvYFs0= +github.com/gookit/color v1.5.4/go.mod h1:pZJOeOS8DM43rXbp4AZo1n9zCU2qjpcRko0b6/QJi9w= +github.com/gorilla/css v1.0.1 h1:ntNaBIghp6JmvWnxbZKANoLyuXTPZ4cAMlo6RyhlbO8= +github.com/gorilla/css v1.0.1/go.mod h1:BvnYkspnSzMmwRK+b8/xgNPLiIuNZr6vbZBTPQ2A3b0= +github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= +github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM= +github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg= +github.com/itchyny/gojq v0.12.13 h1:IxyYlHYIlspQHHTE0f3cJF0NKDMfajxViuhBLnHd/QU= +github.com/itchyny/gojq v0.12.13/go.mod h1:JzwzAqenfhrPUuwbmEz3nu3JQmFLlQTQMUcOdnu/Sf4= +github.com/itchyny/timefmt-go v0.1.5 h1:G0INE2la8S6ru/ZI5JecgyzbbJNs5lG1RcBqa7Jm6GE= +github.com/itchyny/timefmt-go v0.1.5/go.mod h1:nEP7L+2YmAbT2kZ2HfSs1d8Xtw9LY8D2stDBckWakZ8= github.com/jackmordaunt/icns v1.0.0 h1:RYSxplerf/l/DUd09AHtITwckkv/mqjVv4DjYdPmAMQ= github.com/jackmordaunt/icns v1.0.0/go.mod h1:7TTQVEuGzVVfOPPlLNHJIkzA6CoV7aH1Dv9dW351oOo= -github.com/jaypipes/ghw v0.12.0 h1:xU2/MDJfWmBhJnujHY9qwXQLs3DBsf0/Xa9vECY0Tho= -github.com/jaypipes/ghw v0.12.0/go.mod h1:jeJGbkRB2lL3/gxYzNYzEDETV1ZJ56OKr+CSeSEym+g= -github.com/jaypipes/pcidb v1.0.0 h1:vtZIfkiCUE42oYbJS0TAq9XSfSmcsgo9IdxSm9qzYU8= -github.com/jaypipes/pcidb v1.0.0/go.mod h1:TnYUvqhPBzCKnH34KrIX22kAeEbDCSRJ9cqLRCuNDfk= +github.com/jaypipes/ghw v0.21.3 h1:v5mUHM+RN854Vqmk49Uh213jyUA4+8uqaRajlYESsh8= +github.com/jaypipes/ghw v0.21.3/go.mod h1:GPrvwbtPoxYUenr74+nAnWbardIZq600vJDD5HnPsPE= +github.com/jaypipes/pcidb v1.1.1 h1:QmPhpsbmmnCwZmHeYAATxEaoRuiMAJusKYkUncMC0ro= +github.com/jaypipes/pcidb v1.1.1/go.mod h1:x27LT2krrUgjf875KxQXKB0Ha/YXLdZRVmw6hH0G7g8= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A= github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= github.com/jchv/go-winloader v0.0.0-20210711035445-715c2860da7e h1:Q3+PugElBCf4PFpxhErSzU3/PY5sFL5Z6rfv4AbGAck= @@ -111,8 +129,8 @@ github.com/kevinburke/ssh_config v1.2.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/klauspost/cpuid/v2 v2.0.10/go.mod h1:g2LTdtYhdyuGPqyWyv7qRAmj1WBqxuObKfj5c0PQa7c= github.com/klauspost/cpuid/v2 v2.0.12/go.mod h1:g2LTdtYhdyuGPqyWyv7qRAmj1WBqxuObKfj5c0PQa7c= -github.com/klauspost/cpuid/v2 v2.1.0 h1:eyi1Ad2aNJMW95zcSbmGg7Cg6cq3ADwLpMAP96d8rF0= -github.com/klauspost/cpuid/v2 v2.1.0/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY= +github.com/klauspost/cpuid/v2 v2.2.3 h1:sxCkb+qR91z4vsqw4vGGZlDgPz3G7gjaLyK3V8y70BU= +github.com/klauspost/cpuid/v2 v2.2.3/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= @@ -120,62 +138,56 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/labstack/echo/v4 v4.10.2 h1:n1jAhnq/elIFTHr1EYpiYtyKgx4RW9ccVgkqByZaN2M= -github.com/labstack/echo/v4 v4.10.2/go.mod h1:OEyqf2//K1DFdE57vw2DRgWY0M7s65IVQO2FzvI4J5k= -github.com/labstack/gommon v0.4.0 h1:y7cvthEAEbU0yHOf4axH8ZG2NH8knB9iNSoTO8dyIk8= -github.com/labstack/gommon v0.4.0/go.mod h1:uW6kP17uPlLJsD3ijUYn3/M5bAxtlZhMI6m3MFxTMTM= +github.com/labstack/echo/v4 v4.13.3 h1:pwhpCPrTl5qry5HRdM5FwdXnhXSLSY+WE+YQSeCaafY= +github.com/labstack/echo/v4 v4.13.3/go.mod h1:o90YNEeQWjDozo584l7AwhJMHN0bOC4tAfg+Xox9q5g= +github.com/labstack/gommon v0.4.2 h1:F8qTUNXgG1+6WQmqoUWnz8WiEU60mXVVw0P4ht1WRA0= +github.com/labstack/gommon v0.4.2/go.mod h1:QlUFxVM+SNXhDL/Z7YhocGIBYOiwB0mXm1+1bAPHPyU= github.com/leaanthony/clir v1.0.4/go.mod h1:k/RBkdkFl18xkkACMCLt09bhiZnrGORoxmomeMvDpE0= github.com/leaanthony/clir v1.3.0 h1:L9nPDWrmc/qU9UWZZvRaFajWYuO0np9V5p+5gxyYno0= github.com/leaanthony/clir v1.3.0/go.mod h1:k/RBkdkFl18xkkACMCLt09bhiZnrGORoxmomeMvDpE0= github.com/leaanthony/debme v1.2.1 h1:9Tgwf+kjcrbMQ4WnPcEIUcQuIZYqdWftzZkBr+i/oOc= github.com/leaanthony/debme v1.2.1/go.mod h1:3V+sCm5tYAgQymvSOfYQ5Xx2JCr+OXiD9Jkw3otUjiA= -github.com/leaanthony/go-ansi-parser v1.6.0 h1:T8TuMhFB6TUMIUm0oRrSbgJudTFw9csT3ZK09w0t4Pg= -github.com/leaanthony/go-ansi-parser v1.6.0/go.mod h1:+vva/2y4alzVmmIEpk9QDhA7vLC5zKDTRwfZGOp3IWU= -github.com/leaanthony/gosod v1.0.3 h1:Fnt+/B6NjQOVuCWOKYRREZnjGyvg+mEhd1nkkA04aTQ= -github.com/leaanthony/gosod v1.0.3/go.mod h1:BJ2J+oHsQIyIQpnLPjnqFGTMnOZXDbvWtRCSG7jGxs4= +github.com/leaanthony/go-ansi-parser v1.6.1 h1:xd8bzARK3dErqkPFtoF9F3/HgN8UQk0ed1YDKpEz01A= +github.com/leaanthony/go-ansi-parser v1.6.1/go.mod h1:+vva/2y4alzVmmIEpk9QDhA7vLC5zKDTRwfZGOp3IWU= +github.com/leaanthony/gosod v1.0.4 h1:YLAbVyd591MRffDgxUOU1NwLhT9T1/YiwjKZpkNFeaI= +github.com/leaanthony/gosod v1.0.4/go.mod h1:GKuIL0zzPj3O1SdWQOdgURSuhkF+Urizzxh26t9f1cw= github.com/leaanthony/slicer v1.5.0/go.mod h1:FwrApmf8gOrpzEWM2J/9Lh79tyq8KTX5AzRtwV7m4AY= github.com/leaanthony/slicer v1.6.0 h1:1RFP5uiPJvT93TAHi+ipd3NACobkW53yUiBqZheE/Js= github.com/leaanthony/slicer v1.6.0/go.mod h1:o/Iz29g7LN0GqH3aMjWAe90381nyZlDNquK+mtH2Fj8= -github.com/leaanthony/u v1.1.0 h1:2n0d2BwPVXSUq5yhe8lJPHdxevE2qK5G99PMStMZMaI= -github.com/leaanthony/u v1.1.0/go.mod h1:9+o6hejoRljvZ3BzdYlVL0JYCwtnAsVuN9pVTQcaRfI= +github.com/leaanthony/u v1.1.1 h1:TUFjwDGlNX+WuwVEzDqQwC2lOv0P4uhTQw7CMFdiK7M= +github.com/leaanthony/u v1.1.1/go.mod h1:9+o6hejoRljvZ3BzdYlVL0JYCwtnAsVuN9pVTQcaRfI= github.com/leaanthony/winicon v1.0.0 h1:ZNt5U5dY71oEoKZ97UVwJRT4e+5xo5o/ieKuHuk8NqQ= github.com/leaanthony/winicon v1.0.0/go.mod h1:en5xhijl92aphrJdmRPlh4NI1L6wq3gEm0LpXAPghjU= -github.com/lithammer/fuzzysearch v1.1.5 h1:Ag7aKU08wp0R9QCfF4GoGST9HbmAIeLP7xwMrOBEp1c= -github.com/lithammer/fuzzysearch v1.1.5/go.mod h1:1R1LRNk7yKid1BaQkmuLQaHruxcC4HmAH30Dh61Ih1Q= +github.com/lithammer/fuzzysearch v1.1.8 h1:/HIuJnjHuXS8bKaiTMeeDlW2/AyIWk2brx1V8LFgLN4= +github.com/lithammer/fuzzysearch v1.1.8/go.mod h1:IdqeyBClc3FFqSzYq/MXESsS4S0FsZ5ajtkr5xPLts4= github.com/lucasb-eyer/go-colorful v1.2.0 h1:1nnpGOrhyZZuNyfu1QjKiUICQ74+3FNCN69Aj6K7nkY= github.com/lucasb-eyer/go-colorful v1.2.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= -github.com/matryer/is v1.4.0 h1:sosSmIWwkYITGrxZ25ULNDeKiMNzFSr4V/eqBQP0PeE= github.com/matryer/is v1.4.0/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwMRU= -github.com/mattn/go-colorable v0.1.11/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= +github.com/matryer/is v1.4.1 h1:55ehd8zaGABKLXQUe2awZ99BD/PTc2ls+KV/dXphgEQ= +github.com/matryer/is v1.4.1/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwMRU= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= -github.com/mattn/go-isatty v0.0.13/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= -github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= -github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= -github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= -github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= +github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= +github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-runewidth v0.0.12/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk= -github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU= github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= -github.com/microcosm-cc/bluemonday v1.0.17 h1:Z1a//hgsQ4yjC+8zEkV8IWySkXnsxmdSY642CTFQb5Y= -github.com/microcosm-cc/bluemonday v1.0.17/go.mod h1:Z0r70sCuXHig8YpBzCc5eGHAap2K7e/u082ZUpDRRqM= -github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= -github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc= +github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= +github.com/microcosm-cc/bluemonday v1.0.27 h1:MpEUotklkwCSLeH+Qdx1VJgNqLlpY2KXwXFM08ygZfk= +github.com/microcosm-cc/bluemonday v1.0.27/go.mod h1:jFi9vgW+H7c3V0lb6nR74Ib/DIB5OBs92Dimizgw2cA= github.com/muesli/reflow v0.3.0 h1:IFsN6K9NfGtjeggFP+68I4chLZV2yIKsXJFNZ+eWh6s= github.com/muesli/reflow v0.3.0/go.mod h1:pbwTDkVPibjO2kyvBQRBxTWEEGDGq0FlB1BIKtnHY/8= -github.com/muesli/termenv v0.9.0 h1:wnbOaGz+LUR3jNT0zOzinPnyDaCZUQRZj9GxK8eRVl8= -github.com/muesli/termenv v0.9.0/go.mod h1:R/LzAKf+suGs4IsO95y7+7DpFHO0KABgnZqtlyx2mBw= +github.com/muesli/termenv v0.15.3-0.20240618155329-98d742f6907a h1:2MaM6YC3mGu54x+RKAA6JiFFHlHDY1UbkxqppT7wYOg= +github.com/muesli/termenv v0.15.3-0.20240618155329-98d742f6907a/go.mod h1:hxSnBBYLK21Vtq/PHd0S2FYCxBXzBua8ov5s1RobyRQ= github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 h1:zYyBkD/k9seD2A7fsi6Oo2LfFZAehjjQMERAvZLEDnQ= github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8= -github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= -github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= -github.com/onsi/gomega v1.27.10 h1:naR28SdDFlqrG6kScpT8VWpu1xWY5nJRCF3XaYyBjhI= -github.com/onsi/gomega v1.27.10/go.mod h1:RsS8tutOdbdgzbPtzzATp12yT7kM5I5aElG3evPbQ0M= -github.com/pjbgf/sha1cd v0.3.0 h1:4D5XXmUUBUl/xQ6IjCkEAbqXskkq/4O7LmGn0AqMDs4= -github.com/pjbgf/sha1cd v0.3.0/go.mod h1:nZ1rrWOcGJ5uZgEEVL1VUM9iRQiZvWdbZjkKyFzPPsI= -github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 h1:KoWmjvw+nsYOo29YJK9vDA65RGE3NrOnUtO7a+RF9HU= -github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI= +github.com/onsi/gomega v1.34.1 h1:EUMJIKUjM8sKjYbtxQI9A4z2o+rruxnzNvpknOXie6k= +github.com/onsi/gomega v1.34.1/go.mod h1:kU1QgUvBDLXBJq618Xvm2LUX6rSAfRaFRTcdOeDLwwY= +github.com/pjbgf/sha1cd v0.3.2 h1:a9wb0bp1oC2TGwStyn0Umc/IGKQnEgF0vVaZ8QF8eo4= +github.com/pjbgf/sha1cd v0.3.2/go.mod h1:zQWigSxVmsHEZow5qaLtPYxpcKMMQpa09ixqBxuCS6A= +github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmdv1U2eRNDiU2ErMBj1gwrq8eQ= +github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c/go.mod h1:7rwL4CYBLnjLxUqIJNnCWiEdr3bn6IUYi15bNlnbCCU= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= @@ -187,55 +199,49 @@ github.com/pterm/pterm v0.12.31/go.mod h1:32ZAWZVXD7ZfG0s8qqHXePte42kdz8ECtRyEej github.com/pterm/pterm v0.12.33/go.mod h1:x+h2uL+n7CP/rel9+bImHD5lF3nM9vJj80k9ybiiTTE= github.com/pterm/pterm v0.12.36/go.mod h1:NjiL09hFhT/vWjQHSj1athJpx6H8cjpHXNAK5bUw8T8= github.com/pterm/pterm v0.12.40/go.mod h1:ffwPLwlbXxP+rxT0GsgDTzS3y3rmpAO1NMjUkGTYf8s= -github.com/pterm/pterm v0.12.49 h1:qeNm0wTWawy6WhKoY8ZKq6qTXFr0s2UtUyRW0yVztEg= -github.com/pterm/pterm v0.12.49/go.mod h1:D4OBoWNqAfXkm5QLTjIgjNiMXPHemLJHnIreGUsWzWg= +github.com/pterm/pterm v0.12.80 h1:mM55B+GnKUnLMUSqhdINe4s6tOuVQIetQ3my8JGyAIg= +github.com/pterm/pterm v0.12.80/go.mod h1:c6DeF9bSnOSeFPZlfs4ZRAFcf5SCoTwvwQ5xaKGQlHo= github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= -github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis= -github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= -github.com/rogpeppe/go-internal v1.11.0 h1:cWPaGQEPrBb5/AsnsZesgZZ9yb1OQ+GOISoDNXVBh4M= -github.com/rogpeppe/go-internal v1.11.0/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA= +github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= +github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= +github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= +github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= github.com/sabhiram/go-gitignore v0.0.0-20210923224102-525f6e181f06 h1:OkMGxebDjyw0ULyrTYWeN0UNCCkmCWfjPnIA2W6oviI= github.com/sabhiram/go-gitignore v0.0.0-20210923224102-525f6e181f06/go.mod h1:+ePHsJ1keEjQtpvf9HHw0f4ZeJ0TLRsxhunSI2hYJSs= -github.com/samber/lo v1.38.1 h1:j2XEAqXKb09Am4ebOg31SpvzUTTs6EN3VfgeLUhPdXM= -github.com/samber/lo v1.38.1/go.mod h1:+m/ZKRl6ClXCE2Lgf3MsQlWfh4bn1bz6CXEOxnEXnEA= -github.com/sergi/go-diff v1.2.0 h1:XU+rvMAioB0UC3q1MFrIQy4Vo5/4VsRDQQXHsEya6xQ= +github.com/samber/lo v1.49.1 h1:4BIFyVfuQSEpluc7Fua+j1NolZHiEHEpaSEKdsH0tew= +github.com/samber/lo v1.49.1/go.mod h1:dO6KHFzUKXgP8LDhU0oI8d2hekjXnGOu0DB8Jecxd6o= github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= +github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 h1:n661drycOFuPLCN3Uc8sB6B/s6Z4t2xvBgU1htSHuq8= +github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4= github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= -github.com/skeema/knownhosts v1.2.1 h1:SHWdIUa82uGZz+F+47k8SY4QhhI291cXCpopT1lK2AQ= -github.com/skeema/knownhosts v1.2.1/go.mod h1:xYbVRSPxqBZFrdmDyMmsOs+uX1UZC3nTN3ThzgDxUwo= +github.com/skeema/knownhosts v1.3.0 h1:AM+y0rI04VksttfwjkSTNQorvGqmwATnvnAHpSgc0LY= +github.com/skeema/knownhosts v1.3.0/go.mod h1:sPINvnADmT/qYH1kfv+ePMmOBTH6Tbl7b5LvTDjFK7M= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= -github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -github.com/tc-hib/winres v0.2.1 h1:YDE0FiP0VmtRaDn7+aaChp1KiF4owBiJa5l964l5ujA= -github.com/tc-hib/winres v0.2.1/go.mod h1:C/JaNhH3KBvhNKVbvdlDWkbMDO9H4fKKDaN7/07SSuk= -github.com/tidwall/gjson v1.8.0/go.mod h1:5/xDoumyyDNerp2U36lyolv46b3uF/9Bu6OfyQ9GImk= -github.com/tidwall/gjson v1.9.3 h1:hqzS9wAHMO+KVBBkLxYdkEeeFHuqr95GfClRLKlgK0E= -github.com/tidwall/gjson v1.9.3/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= -github.com/tidwall/match v1.0.3/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= +github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= +github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/tc-hib/winres v0.3.1 h1:CwRjEGrKdbi5CvZ4ID+iyVhgyfatxFoizjPhzez9Io4= +github.com/tc-hib/winres v0.3.1/go.mod h1:C/JaNhH3KBvhNKVbvdlDWkbMDO9H4fKKDaN7/07SSuk= +github.com/tidwall/gjson v1.14.2 h1:6BBkirS0rAHjumnjHF6qgy5d2YAJ1TLIaFE2lzfOLqo= +github.com/tidwall/gjson v1.14.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA= github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= -github.com/tidwall/pretty v1.1.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs= github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= -github.com/tidwall/sjson v1.1.7 h1:sgVPwu/yygHJ2m1pJDLgGM/h+1F5odx5Q9ljG3imRm8= -github.com/tidwall/sjson v1.1.7/go.mod h1:w/yG+ezBeTdUxiKs5NcPicO9diP38nk96QBAbIIGeFs= -github.com/tkrajina/go-reflector v0.5.6 h1:hKQ0gyocG7vgMD2M3dRlYN6WBBOmdoOzJ6njQSepKdE= -github.com/tkrajina/go-reflector v0.5.6/go.mod h1:ECbqLgccecY5kPmPmXg1MrHW585yMcDkVl6IvJe64T4= +github.com/tidwall/sjson v1.2.5 h1:kLy8mja+1c9jlljvWTlSazM7cKDRfJuR/bOJhcY5NcY= +github.com/tidwall/sjson v1.2.5/go.mod h1:Fvgq9kS/6ociJEDnK0Fk1cpYF4FIW6ZF7LAe+6jwd28= +github.com/tkrajina/go-reflector v0.5.8 h1:yPADHrwmUbMq4RGEyaOUpz2H90sRsETNVpjzo3DLVQQ= +github.com/tkrajina/go-reflector v0.5.8/go.mod h1:ECbqLgccecY5kPmPmXg1MrHW585yMcDkVl6IvJe64T4= github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= -github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ= github.com/valyala/fasttemplate v1.2.2 h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQD0Loo= github.com/valyala/fasttemplate v1.2.2/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ= -github.com/wailsapp/go-webview2 v1.0.10 h1:PP5Hug6pnQEAhfRzLCoOh2jJaPdrqeRgJKZhyYyDV/w= -github.com/wailsapp/go-webview2 v1.0.10/go.mod h1:Uk2BePfCRzttBBjFrBmqKGJd41P6QIHeV9kTgIeOZNo= +github.com/wailsapp/go-webview2 v1.0.22 h1:YT61F5lj+GGaat5OB96Aa3b4QA+mybD0Ggq6NZijQ58= +github.com/wailsapp/go-webview2 v1.0.22/go.mod h1:qJmWAmAmaniuKGZPWwne+uor3AHMB5PFhqiK0Bbj8kc= github.com/wailsapp/mimetype v1.4.1 h1:pQN9ycO7uo4vsUUuPeHEYoUkLVkaRntMnHJxVwYhwHs= github.com/wailsapp/mimetype v1.4.1/go.mod h1:9aV5k31bBOv5z6u+QP8TltzvNGJPmNJD4XlAL3U+j3o= github.com/wzshiming/ctc v1.2.3 h1:q+hW3IQNsjIlOFBTGZZZeIXTElFM4grF4spW/errh/c= @@ -244,116 +250,102 @@ github.com/wzshiming/winseq v0.0.0-20200112104235-db357dc107ae h1:tpXvBXC3hpQBDC github.com/wzshiming/winseq v0.0.0-20200112104235-db357dc107ae/go.mod h1:VTAq37rkGeV+WOybvZwjXiJOicICdpLCN8ifpISjK20= github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM= github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw= -github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778 h1:QldyIu/L63oPpyvQmHgvgickp1Yw510KJOqX7H24mg8= github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778/go.mod h1:2MuV+tbUrU1zIOPMxZ5EncGwgmMJsa+9ucAQZXxsObs= -github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= -github.com/yuin/goldmark v1.4.4/go.mod h1:rmuwmfZ0+bvzB24eSC//bk1R1Zp3hM0OXYv/G2LIilg= -github.com/yuin/goldmark v1.4.13 h1:fVcFKWvrslecOb/tg+Cc05dkeYx540o0FuFt3nUVDoE= +github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavMF/ppJZNG9ZpyihvCd0w101no= +github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e/go.mod h1:RbqR21r5mrJuqunuUZ/Dhy/avygyECGrLceyNeo4LiM= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= -github.com/yuin/goldmark-emoji v1.0.1 h1:ctuWEyzGBwiucEqxzwe0SOYDXPAucOrE9NQC18Wa1os= -github.com/yuin/goldmark-emoji v1.0.1/go.mod h1:2w1E6FEWLcDQkoTE+7HU6QF1F6SLlNGjRIBbIZQFqkQ= +github.com/yuin/goldmark v1.7.1/go.mod h1:uzxRWxtg69N339t3louHJ7+O03ezfj6PlliRlaOzY1E= +github.com/yuin/goldmark v1.7.4 h1:BDXOHExt+A7gwPCJgPIIq7ENvceR7we7rOS9TNoLZeg= +github.com/yuin/goldmark v1.7.4/go.mod h1:uzxRWxtg69N339t3louHJ7+O03ezfj6PlliRlaOzY1E= +github.com/yuin/goldmark-emoji v1.0.3 h1:aLRkLHOuBR2czCY4R8olwMjID+tENfhyFDMCRhbIQY4= +github.com/yuin/goldmark-emoji v1.0.3/go.mod h1:tTkZEbwu5wkPmgTcitqddVxY9osFZiavD+r4AzQrh1U= +github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0= +github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.3.1-0.20221117191849-2c476679df9a/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= -golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= -golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI= -golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= -golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1 h1:k/i9J1pBpvlfR+9QsetwPyERsqu1GIbi967PQMq3Ivc= -golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1/go.mod h1:V1LtkGg67GoY2N1AnLN78QLrzxkLyJw7RJb1gzOOz9w= +golang.org/x/crypto v0.33.0 h1:IOBPskki6Lysi0lo9qQvbxiQ+FvsCC/YWOecCHAixus= +golang.org/x/crypto v0.33.0/go.mod h1:bVdXmD7IV/4GdElGPozy6U7lWdRXA4qyRVGJV57uQ5M= +golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56 h1:2dVuKD2vS7b0QIHQbpyTISPd0LeHDbnYEryqj5Q1ug8= +golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56/go.mod h1:M4RDyNAINzryxdtnbRXRL/OHtkFuWGRjvuhBJpk2IlY= golang.org/x/image v0.0.0-20200430140353-33d19683fad8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/image v0.12.0 h1:w13vZbU4o5rKOFFR8y7M+c4A5jXDC0uXTdHYRP8X2DQ= golang.org/x/image v0.12.0/go.mod h1:Lu90jvHG7GfemOIcldsh9A2hS01ocl6oNO7ype5mEnk= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0= -golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.23.0 h1:Zb7khfcRGKk+kqfxFaP5tZqCnDZMjC5VtUBs87Hr6QM= +golang.org/x/mod v0.23.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210505024714-0287a6fb4125/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= -golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= -golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac= -golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= +golang.org/x/net v0.35.0 h1:T5GQRQb2y08kTAByq9L4/bz8cipCdA8FbRTXewonqY8= +golang.org/x/net v0.35.0/go.mod h1:EglIi67kWsHKlRzzVMUD93VMSWGFOMSZgxFjparz1Qk= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ= -golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.11.0 h1:GGz8+XQP4FvTTrjZPzNKTMFtSXH80RAzG+5ghFPgK9w= +golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200107162124-548cf772de50/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200810151505-1b9f1253b3ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210616045830-e2b7044e8c71/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211013075003-97ac67df715c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211103235746-7861aae1554b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y= -golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc= +golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= -golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= -golang.org/x/term v0.20.0 h1:VnkxpohqXaOBYJtBmEppKUG6mXpi+4O6purfc2+sMhw= -golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY= +golang.org/x/term v0.29.0 h1:L6pJp37ocefwRRtYPKSWOWzOtWSxVajvz2ldH/xi3iU= +golang.org/x/term v0.29.0/go.mod h1:6bl4lRlvVuDgSf3179VpIxBF0o10JUpXWOnI7nErv7s= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= -golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk= -golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM= +golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= -golang.org/x/tools v0.17.0 h1:FvmRgNOcs3kOa+T20R1uhfP9F6HgG2mfxDv1vrx1Htc= -golang.org/x/tools v0.17.0/go.mod h1:xsh6VxdV005rRVaS6SSAf9oiAqljS7UZUacMZ8Bnsps= +golang.org/x/tools v0.30.0 h1:BgcpHewrV5AUp2G9MebG4XPFI1E2W41zU1SaqVA9vJY= +golang.org/x/tools v0.30.0/go.mod h1:c347cR/OJfw5TI+GfX7RUPNMdDRRbjvYTS0jPyvsVtY= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME= gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= -gopkg.in/yaml.v1 v1.0.0-20140924161607-9f9df34309c0/go.mod h1:WDnlLJ4WF5VGsH/HVa3CI79GS0ol3YnhVnKP89i0kNg= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -howett.net/plist v1.0.0 h1:7CrbWYbPPO/PyNy38b2EB/+gYbjCe2DXBxgtOOZbSQM= -howett.net/plist v1.0.0/go.mod h1:lqaXoTrLY4hg8tnEzNru53gicrbv7rrk+2xJA/7hw9g= +howett.net/plist v1.0.2-0.20250314012144-ee69052608d9 h1:eeH1AIcPvSc0Z25ThsYF+Xoqbn0CI/YnXVYoTLFdGQw= +howett.net/plist v1.0.2-0.20250314012144-ee69052608d9/go.mod h1:fyFX5Hj5tP1Mpk8obqA9MZgXT416Q5711SDT7dQLTLk= +mvdan.cc/sh/v3 v3.7.0 h1:lSTjdP/1xsddtaKfGg7Myu7DnlHItd3/M2tomOcNNBg= +mvdan.cc/sh/v3 v3.7.0/go.mod h1:K2gwkaesF/D7av7Kxl0HbF5kGOd2ArupNTX3X44+8l8= diff --git a/v2/internal/app/app_dev.go b/v2/internal/app/app_dev.go index 58cd94ef0..6de845f96 100644 --- a/v2/internal/app/app_dev.go +++ b/v2/internal/app/app_dev.go @@ -46,7 +46,12 @@ func CreateApp(appoptions *options.App) (*App, error) { ctx = context.WithValue(ctx, "debug", true) ctx = context.WithValue(ctx, "devtoolsEnabled", true) - // Set up logger + // Set up logger if the appoptions.LogLevel is an invalid value, set it to the default log level + appoptions.LogLevel, err = pkglogger.StringToLogLevel(appoptions.LogLevel.String()) + if err != nil { + return nil, err + } + myLogger := logger.New(appoptions.Logger) myLogger.SetLogLevel(appoptions.LogLevel) @@ -74,9 +79,11 @@ func CreateApp(appoptions *options.App) (*App, error) { } loglevel := os.Getenv("loglevel") - if loglevel == "" { - loglevelFlag = devFlags.String("loglevel", "debug", "Loglevel to use - Trace, Debug, Info, Warning, Error") + appLogLevel := appoptions.LogLevel.String() + if loglevel != "" { + appLogLevel = loglevel } + loglevelFlag = devFlags.String("loglevel", appLogLevel, "Loglevel to use - Trace, Debug, Info, Warning, Error") // If we weren't given the assetdir in the environment variables if assetdir == "" { @@ -174,7 +181,10 @@ func CreateApp(appoptions *options.App) (*App, error) { if err != nil { return nil, err } - myLogger.SetLogLevel(level) + // Only set the log level if it's different from the appoptions.LogLevel + if level != appoptions.LogLevel { + myLogger.SetLogLevel(level) + } } // Attach logger to context @@ -213,7 +223,7 @@ func CreateApp(appoptions *options.App) (*App, error) { eventHandler := runtime.NewEvents(myLogger) ctx = context.WithValue(ctx, "events", eventHandler) - messageDispatcher := dispatcher.NewDispatcher(ctx, myLogger, appBindings, eventHandler, appoptions.ErrorFormatter) + messageDispatcher := dispatcher.NewDispatcher(ctx, myLogger, appBindings, eventHandler, appoptions.ErrorFormatter, appoptions.DisablePanicRecovery) // Create the frontends and register to event handler desktopFrontend := desktop.NewFrontend(ctx, appoptions, myLogger, appBindings, messageDispatcher) diff --git a/v2/internal/app/app_devtools.go b/v2/internal/app/app_devtools.go index a84e8c283..60b221094 100644 --- a/v2/internal/app/app_devtools.go +++ b/v2/internal/app/app_devtools.go @@ -1,8 +1,8 @@ -//go:build devtools - -package app - -// Note: devtools flag is also added in debug builds -func IsDevtoolsEnabled() bool { - return true -} +//go:build devtools + +package app + +// Note: devtools flag is also added in debug builds +func IsDevtoolsEnabled() bool { + return true +} diff --git a/v2/internal/app/app_production.go b/v2/internal/app/app_production.go index 4c217b17c..9eb0e5a66 100644 --- a/v2/internal/app/app_production.go +++ b/v2/internal/app/app_production.go @@ -82,7 +82,7 @@ func CreateApp(appoptions *options.App) (*App, error) { ctx = context.WithValue(ctx, "buildtype", "production") } - messageDispatcher := dispatcher.NewDispatcher(ctx, myLogger, appBindings, eventHandler, appoptions.ErrorFormatter) + messageDispatcher := dispatcher.NewDispatcher(ctx, myLogger, appBindings, eventHandler, appoptions.ErrorFormatter, appoptions.DisablePanicRecovery) appFrontend := desktop.NewFrontend(ctx, appoptions, myLogger, appBindings, messageDispatcher) eventHandler.AddFrontend(appFrontend) diff --git a/v2/internal/binding/binding.go b/v2/internal/binding/binding.go index 568e11b03..b7bf07ae0 100644 --- a/v2/internal/binding/binding.go +++ b/v2/internal/binding/binding.go @@ -14,6 +14,7 @@ import ( "github.com/wailsapp/wails/v2/internal/typescriptify" "github.com/leaanthony/slicer" + "github.com/wailsapp/wails/v2/internal/logger" ) @@ -73,13 +74,7 @@ func (b *Bindings) Add(structPtr interface{}) error { } for _, method := range methods { - splitName := strings.Split(method.Name, ".") - packageName := splitName[0] - structName := splitName[1] - methodName := splitName[2] - - // Add it as a regular method - b.db.AddMethod(packageName, structName, methodName, method) + b.db.AddMethod(method.Path.Package, method.Path.Struct, method.Path.Name, method) } return nil } @@ -128,7 +123,15 @@ func (b *Bindings) GenerateModels() ([]byte, error) { // if we have enums for this package, add them as well var enums, enumsExist = b.enumsToGenerateTS[packageName] if enumsExist { - for enumName, enum := range enums { + // Sort the enum names first to make the output deterministic + sortedEnumNames := make([]string, 0, len(enums)) + for enumName := range enums { + sortedEnumNames = append(sortedEnumNames, enumName) + } + sort.Strings(sortedEnumNames) + + for _, enumName := range sortedEnumNames { + enum := enums[enumName] fqemumname := packageName + "." + enumName if seen.Contains(fqemumname) { continue @@ -177,7 +180,7 @@ func (b *Bindings) GenerateModels() ([]byte, error) { } // Sort the package names first to make the output deterministic - sortedPackageNames := make([]string, 0) + sortedPackageNames := make([]string, 0, len(models)) for packageName := range models { sortedPackageNames = append(sortedPackageNames, packageName) } @@ -262,22 +265,19 @@ func (b *Bindings) AddStructToGenerateTS(packageName string, structName string, // Iterate this struct and add any struct field references structType := reflect.TypeOf(s) - if hasElements(structType) { + for hasElements(structType) { structType = structType.Elem() } for i := 0; i < structType.NumField(); i++ { field := structType.Field(i) - if field.Anonymous { + if field.Anonymous || !field.IsExported() { continue } kind := field.Type.Kind() if kind == reflect.Struct { - if !field.IsExported() { - continue - } fqname := field.Type.String() - sNameSplit := strings.Split(fqname, ".") + sNameSplit := strings.SplitN(fqname, ".", 2) if len(sNameSplit) < 2 { continue } @@ -288,22 +288,24 @@ func (b *Bindings) AddStructToGenerateTS(packageName string, structName string, s := reflect.Indirect(a).Interface() b.AddStructToGenerateTS(pName, sName, s) } - } else if hasElements(field.Type) && field.Type.Elem().Kind() == reflect.Struct { - if !field.IsExported() { - continue + } else { + fType := field.Type + for hasElements(fType) { + fType = fType.Elem() } - fqname := field.Type.Elem().String() - sNameSplit := strings.Split(fqname, ".") - if len(sNameSplit) < 2 { - continue - } - sName := sNameSplit[1] - pName := getPackageName(fqname) - typ := field.Type.Elem() - a := reflect.New(typ) - if b.hasExportedJSONFields(typ) { - s := reflect.Indirect(a).Interface() - b.AddStructToGenerateTS(pName, sName, s) + if fType.Kind() == reflect.Struct { + fqname := fType.String() + sNameSplit := strings.SplitN(fqname, ".", 2) + if len(sNameSplit) < 2 { + continue + } + sName := sNameSplit[1] + pName := getPackageName(fqname) + a := reflect.New(fType) + if b.hasExportedJSONFields(fType) { + s := reflect.Indirect(a).Interface() + b.AddStructToGenerateTS(pName, sName, s) + } } } } @@ -350,7 +352,18 @@ func (b *Bindings) hasExportedJSONFields(typeOf reflect.Type) bool { for i := 0; i < typeOf.NumField(); i++ { jsonFieldName := "" f := typeOf.Field(i) - jsonTag := f.Tag.Get("json") + // function, complex, and channel types cannot be json-encoded + if f.Type.Kind() == reflect.Chan || + f.Type.Kind() == reflect.Func || + f.Type.Kind() == reflect.UnsafePointer || + f.Type.Kind() == reflect.Complex128 || + f.Type.Kind() == reflect.Complex64 { + continue + } + jsonTag, hasTag := f.Tag.Lookup("json") + if !hasTag && f.IsExported() { + return true + } if len(jsonTag) == 0 { continue } diff --git a/v2/internal/binding/binding_test/binding_deepelements_test.go b/v2/internal/binding/binding_test/binding_deepelements_test.go new file mode 100644 index 000000000..034687474 --- /dev/null +++ b/v2/internal/binding/binding_test/binding_deepelements_test.go @@ -0,0 +1,126 @@ +package binding_test + +// Issues 2303, 3442, 3709 + +type DeepMessage struct { + Msg string +} + +type DeepElements struct { + Single []int + Double [][]string + FourDouble [4][]float64 + DoubleFour [][4]int64 + Triple [][][]int + + SingleMap map[string]int + SliceMap map[string][]int + DoubleSliceMap map[string][][]int + + ArrayMap map[string][4]int + DoubleArrayMap1 map[string][4][]int + DoubleArrayMap2 map[string][][4]int + DoubleArrayMap3 map[string][4][4]int + + OneStructs []*DeepMessage + TwoStructs [3][]*DeepMessage + ThreeStructs [][][]DeepMessage + MapStructs map[string][]*DeepMessage + MapTwoStructs map[string][4][]DeepMessage + MapThreeStructs map[string][][7][]*DeepMessage +} + +func (x DeepElements) Get() DeepElements { + return x +} + +var DeepElementsTest = BindingTest{ + name: "DeepElements", + structs: []interface{}{ + &DeepElements{}, + }, + exemptions: nil, + shouldError: false, + want: ` +export namespace binding_test { + + export class DeepMessage { + Msg: string; + + static createFrom(source: any = {}) { + return new DeepMessage(source); + } + + constructor(source: any = {}) { + if ('string' === typeof source) source = JSON.parse(source); + this.Msg = source["Msg"]; + } + } + export class DeepElements { + Single: number[]; + Double: string[][]; + FourDouble: number[][]; + DoubleFour: number[][]; + Triple: number[][][]; + SingleMap: Record; + SliceMap: Record>; + DoubleSliceMap: Record>>; + ArrayMap: Record>; + DoubleArrayMap1: Record>>; + DoubleArrayMap2: Record>>; + DoubleArrayMap3: Record>>; + OneStructs: DeepMessage[]; + TwoStructs: DeepMessage[][]; + ThreeStructs: DeepMessage[][][]; + MapStructs: Record>; + MapTwoStructs: Record>>; + MapThreeStructs: Record>>>; + + static createFrom(source: any = {}) { + return new DeepElements(source); + } + + constructor(source: any = {}) { + if ('string' === typeof source) source = JSON.parse(source); + this.Single = source["Single"]; + this.Double = source["Double"]; + this.FourDouble = source["FourDouble"]; + this.DoubleFour = source["DoubleFour"]; + this.Triple = source["Triple"]; + this.SingleMap = source["SingleMap"]; + this.SliceMap = source["SliceMap"]; + this.DoubleSliceMap = source["DoubleSliceMap"]; + this.ArrayMap = source["ArrayMap"]; + this.DoubleArrayMap1 = source["DoubleArrayMap1"]; + this.DoubleArrayMap2 = source["DoubleArrayMap2"]; + this.DoubleArrayMap3 = source["DoubleArrayMap3"]; + this.OneStructs = this.convertValues(source["OneStructs"], DeepMessage); + this.TwoStructs = this.convertValues(source["TwoStructs"], DeepMessage); + this.ThreeStructs = this.convertValues(source["ThreeStructs"], DeepMessage); + this.MapStructs = this.convertValues(source["MapStructs"], Array, true); + this.MapTwoStructs = this.convertValues(source["MapTwoStructs"], Array>, true); + this.MapThreeStructs = this.convertValues(source["MapThreeStructs"], Array>>, true); + } + + convertValues(a: any, classs: any, asMap: boolean = false): any { + if (!a) { + return a; + } + if (a.slice && a.map) { + return (a as any[]).map(elem => this.convertValues(elem, classs)); + } else if ("object" === typeof a) { + if (asMap) { + for (const key of Object.keys(a)) { + a[key] = new classs(a[key]); + } + return a; + } + return new classs(a); + } + return a; + } + } + + } +`, +} diff --git a/v2/internal/binding/binding_test/binding_enum_ordering_test.go b/v2/internal/binding/binding_test/binding_enum_ordering_test.go new file mode 100644 index 000000000..0939535ec --- /dev/null +++ b/v2/internal/binding/binding_test/binding_enum_ordering_test.go @@ -0,0 +1,271 @@ +package binding_test + +// Test for PR #4664: Fix generated enums ordering +// This test ensures that enum output is deterministic regardless of map iteration order + +// ZFirstEnum - named with Z prefix to test alphabetical sorting +type ZFirstEnum int + +const ( + ZFirstEnumValue1 ZFirstEnum = iota + ZFirstEnumValue2 +) + +var AllZFirstEnumValues = []struct { + Value ZFirstEnum + TSName string +}{ + {ZFirstEnumValue1, "ZValue1"}, + {ZFirstEnumValue2, "ZValue2"}, +} + +// ASecondEnum - named with A prefix to test alphabetical sorting +type ASecondEnum int + +const ( + ASecondEnumValue1 ASecondEnum = iota + ASecondEnumValue2 +) + +var AllASecondEnumValues = []struct { + Value ASecondEnum + TSName string +}{ + {ASecondEnumValue1, "AValue1"}, + {ASecondEnumValue2, "AValue2"}, +} + +// MMiddleEnum - named with M prefix to test alphabetical sorting +type MMiddleEnum int + +const ( + MMiddleEnumValue1 MMiddleEnum = iota + MMiddleEnumValue2 +) + +var AllMMiddleEnumValues = []struct { + Value MMiddleEnum + TSName string +}{ + {MMiddleEnumValue1, "MValue1"}, + {MMiddleEnumValue2, "MValue2"}, +} + +type EntityWithMultipleEnums struct { + Name string `json:"name"` + EnumZ ZFirstEnum `json:"enumZ"` + EnumA ASecondEnum `json:"enumA"` + EnumM MMiddleEnum `json:"enumM"` +} + +func (e EntityWithMultipleEnums) Get() EntityWithMultipleEnums { + return e +} + +// EnumOrderingTest tests that multiple enums in the same package are output +// in alphabetical order by enum name. Before PR #4664, the order was +// non-deterministic due to Go map iteration order. +var EnumOrderingTest = BindingTest{ + name: "EnumOrderingTest", + structs: []interface{}{ + &EntityWithMultipleEnums{}, + }, + enums: []interface{}{ + // Intentionally add enums in non-alphabetical order + AllZFirstEnumValues, + AllASecondEnumValues, + AllMMiddleEnumValues, + }, + exemptions: nil, + shouldError: false, + TsGenerationOptionsTest: TsGenerationOptionsTest{ + TsPrefix: "", + TsSuffix: "", + }, + // Expected output should have enums in alphabetical order: ASecondEnum, MMiddleEnum, ZFirstEnum + want: `export namespace binding_test { + + export enum ASecondEnum { + AValue1 = 0, + AValue2 = 1, + } + export enum MMiddleEnum { + MValue1 = 0, + MValue2 = 1, + } + export enum ZFirstEnum { + ZValue1 = 0, + ZValue2 = 1, + } + export class EntityWithMultipleEnums { + name: string; + enumZ: ZFirstEnum; + enumA: ASecondEnum; + enumM: MMiddleEnum; + + static createFrom(source: any = {}) { + return new EntityWithMultipleEnums(source); + } + + constructor(source: any = {}) { + if ('string' === typeof source) source = JSON.parse(source); + this.name = source["name"]; + this.enumZ = source["enumZ"]; + this.enumA = source["enumA"]; + this.enumM = source["enumM"]; + } + } + +} +`, +} + +// EnumElementOrderingEnum tests sorting of enum elements by TSName +type EnumElementOrderingEnum string + +const ( + EnumElementZ EnumElementOrderingEnum = "z_value" + EnumElementA EnumElementOrderingEnum = "a_value" + EnumElementM EnumElementOrderingEnum = "m_value" +) + +// AllEnumElementOrderingValues intentionally lists values out of alphabetical order +// to test that AddEnum sorts them +var AllEnumElementOrderingValues = []struct { + Value EnumElementOrderingEnum + TSName string +}{ + {EnumElementZ, "Zebra"}, + {EnumElementA, "Apple"}, + {EnumElementM, "Mango"}, +} + +type EntityWithUnorderedEnumElements struct { + Name string `json:"name"` + Enum EnumElementOrderingEnum `json:"enum"` +} + +func (e EntityWithUnorderedEnumElements) Get() EntityWithUnorderedEnumElements { + return e +} + +// EnumElementOrderingTest tests that enum elements are sorted alphabetically +// by their TSName within an enum. Before PR #4664, elements appeared in the +// order they were added, which could be arbitrary. +var EnumElementOrderingTest = BindingTest{ + name: "EnumElementOrderingTest", + structs: []interface{}{ + &EntityWithUnorderedEnumElements{}, + }, + enums: []interface{}{ + AllEnumElementOrderingValues, + }, + exemptions: nil, + shouldError: false, + TsGenerationOptionsTest: TsGenerationOptionsTest{ + TsPrefix: "", + TsSuffix: "", + }, + // Expected output should have enum elements sorted: Apple, Mango, Zebra + want: `export namespace binding_test { + + export enum EnumElementOrderingEnum { + Apple = "a_value", + Mango = "m_value", + Zebra = "z_value", + } + export class EntityWithUnorderedEnumElements { + name: string; + enum: EnumElementOrderingEnum; + + static createFrom(source: any = {}) { + return new EntityWithUnorderedEnumElements(source); + } + + constructor(source: any = {}) { + if ('string' === typeof source) source = JSON.parse(source); + this.name = source["name"]; + this.enum = source["enum"]; + } + } + +} +`, +} + +// TSNameEnumElementOrdering tests sorting with TSName() method enum +type TSNameEnumElementOrdering string + +const ( + TSNameEnumZ TSNameEnumElementOrdering = "z_value" + TSNameEnumA TSNameEnumElementOrdering = "a_value" + TSNameEnumM TSNameEnumElementOrdering = "m_value" +) + +func (v TSNameEnumElementOrdering) TSName() string { + switch v { + case TSNameEnumZ: + return "Zebra" + case TSNameEnumA: + return "Apple" + case TSNameEnumM: + return "Mango" + default: + return "Unknown" + } +} + +// AllTSNameEnumValues intentionally out of order +var AllTSNameEnumValues = []TSNameEnumElementOrdering{TSNameEnumZ, TSNameEnumA, TSNameEnumM} + +type EntityWithTSNameEnumOrdering struct { + Name string `json:"name"` + Enum TSNameEnumElementOrdering `json:"enum"` +} + +func (e EntityWithTSNameEnumOrdering) Get() EntityWithTSNameEnumOrdering { + return e +} + +// TSNameEnumElementOrderingTest tests that enums using TSName() method +// also have their elements sorted alphabetically by the TSName. +var TSNameEnumElementOrderingTest = BindingTest{ + name: "TSNameEnumElementOrderingTest", + structs: []interface{}{ + &EntityWithTSNameEnumOrdering{}, + }, + enums: []interface{}{ + AllTSNameEnumValues, + }, + exemptions: nil, + shouldError: false, + TsGenerationOptionsTest: TsGenerationOptionsTest{ + TsPrefix: "", + TsSuffix: "", + }, + // Expected output should have enum elements sorted: Apple, Mango, Zebra + want: `export namespace binding_test { + + export enum TSNameEnumElementOrdering { + Apple = "a_value", + Mango = "m_value", + Zebra = "z_value", + } + export class EntityWithTSNameEnumOrdering { + name: string; + enum: TSNameEnumElementOrdering; + + static createFrom(source: any = {}) { + return new EntityWithTSNameEnumOrdering(source); + } + + constructor(source: any = {}) { + if ('string' === typeof source) source = JSON.parse(source); + this.name = source["name"]; + this.enum = source["enum"]; + } + } + +} +`, +} diff --git a/v2/internal/binding/binding_test/binding_generics_test.go b/v2/internal/binding/binding_test/binding_generics_test.go new file mode 100644 index 000000000..920bd2a7a --- /dev/null +++ b/v2/internal/binding/binding_test/binding_generics_test.go @@ -0,0 +1,154 @@ +package binding_test + +import "github.com/wailsapp/wails/v2/internal/binding/binding_test/binding_test_import/float_package" + +// Issues 3900, 3371, 2323 (no TS generics though) + +type ListData[T interface{}] struct { + Total int64 `json:"Total"` + TotalPage int64 `json:"TotalPage"` + PageNum int `json:"PageNum"` + List []T `json:"List,omitempty"` +} + +func (x ListData[T]) Get() ListData[T] { + return x +} + +var Generics1Test = BindingTest{ + name: "Generics1", + structs: []interface{}{ + &ListData[string]{}, + }, + exemptions: nil, + shouldError: false, + want: ` +export namespace binding_test { + + export class ListData_string_ { + Total: number; + TotalPage: number; + PageNum: number; + List?: string[]; + + static createFrom(source: any = {}) { + return new ListData_string_(source); + } + + constructor(source: any = {}) { + if ('string' === typeof source) source = JSON.parse(source); + this.Total = source["Total"]; + this.TotalPage = source["TotalPage"]; + this.PageNum = source["PageNum"]; + this.List = source["List"]; + } + } + + } +`, +} + +var Generics2Test = BindingTest{ + name: "Generics2", + structs: []interface{}{ + &ListData[float_package.SomeStruct]{}, + &ListData[*float_package.SomeStruct]{}, + }, + exemptions: nil, + shouldError: false, + want: ` +export namespace binding_test { + + export class ListData__github_com_wailsapp_wails_v2_internal_binding_binding_test_binding_test_import_float_package_SomeStruct_ { + Total: number; + TotalPage: number; + PageNum: number; + List?: float_package.SomeStruct[]; + + static createFrom(source: any = {}) { + return new ListData__github_com_wailsapp_wails_v2_internal_binding_binding_test_binding_test_import_float_package_SomeStruct_(source); + } + + constructor(source: any = {}) { + if ('string' === typeof source) source = JSON.parse(source); + this.Total = source["Total"]; + this.TotalPage = source["TotalPage"]; + this.PageNum = source["PageNum"]; + this.List = this.convertValues(source["List"], float_package.SomeStruct); + } + + convertValues(a: any, classs: any, asMap: boolean = false): any { + if (!a) { + return a; + } + if (a.slice && a.map) { + return (a as any[]).map(elem => this.convertValues(elem, classs)); + } else if ("object" === typeof a) { + if (asMap) { + for (const key of Object.keys(a)) { + a[key] = new classs(a[key]); + } + return a; + } + return new classs(a); + } + return a; + } + } + export class ListData_github_com_wailsapp_wails_v2_internal_binding_binding_test_binding_test_import_float_package_SomeStruct_ { + Total: number; + TotalPage: number; + PageNum: number; + List?: float_package.SomeStruct[]; + + static createFrom(source: any = {}) { + return new ListData_github_com_wailsapp_wails_v2_internal_binding_binding_test_binding_test_import_float_package_SomeStruct_(source); + } + + constructor(source: any = {}) { + if ('string' === typeof source) source = JSON.parse(source); + this.Total = source["Total"]; + this.TotalPage = source["TotalPage"]; + this.PageNum = source["PageNum"]; + this.List = this.convertValues(source["List"], float_package.SomeStruct); + } + + convertValues(a: any, classs: any, asMap: boolean = false): any { + if (!a) { + return a; + } + if (a.slice && a.map) { + return (a as any[]).map(elem => this.convertValues(elem, classs)); + } else if ("object" === typeof a) { + if (asMap) { + for (const key of Object.keys(a)) { + a[key] = new classs(a[key]); + } + return a; + } + return new classs(a); + } + return a; + } + } + + } + + export namespace float_package { + + export class SomeStruct { + string: string; + + static createFrom(source: any = {}) { + return new SomeStruct(source); + } + + constructor(source: any = {}) { + if ('string' === typeof source) source = JSON.parse(source); + this.string = source["string"]; + } + } + + } +`, +} diff --git a/v2/internal/binding/binding_test/binding_ignored_test.go b/v2/internal/binding/binding_test/binding_ignored_test.go new file mode 100644 index 000000000..aeb6a9c3f --- /dev/null +++ b/v2/internal/binding/binding_test/binding_ignored_test.go @@ -0,0 +1,47 @@ +package binding_test + +import ( + "unsafe" +) + +// Issues 3755, 3809 + +type Ignored struct { + Valid bool + Total func() int `json:"Total"` + UnsafeP unsafe.Pointer + Complex64 complex64 `json:"Complex"` + Complex128 complex128 + StringChan chan string +} + +func (x Ignored) Get() Ignored { + return x +} + +var IgnoredTest = BindingTest{ + name: "Ignored", + structs: []interface{}{ + &Ignored{}, + }, + exemptions: nil, + shouldError: false, + want: ` +export namespace binding_test { + + export class Ignored { + Valid: boolean; + + static createFrom(source: any = {}) { + return new Ignored(source); + } + + constructor(source: any = {}) { + if ('string' === typeof source) source = JSON.parse(source); + this.Valid = source["Valid"]; + } + } + + } +`, +} diff --git a/v2/internal/binding/binding_test/binding_importedmap_test.go b/v2/internal/binding/binding_test/binding_importedmap_test.go index 7fa11d54b..4a4b2996c 100644 --- a/v2/internal/binding/binding_test/binding_importedmap_test.go +++ b/v2/internal/binding/binding_test/binding_importedmap_test.go @@ -50,7 +50,7 @@ export namespace binding_test { export namespace binding_test_import { export class AMapWrapper { - AMap: {[key: string]: binding_test_nestedimport.A}; + AMap: Record; static createFrom(source: any = {}) { return new AMapWrapper(source); } diff --git a/v2/internal/binding/binding_test/binding_nonstringmapkey_test.go b/v2/internal/binding/binding_test/binding_nonstringmapkey_test.go index 37a61dd29..9efee710f 100644 --- a/v2/internal/binding/binding_test/binding_nonstringmapkey_test.go +++ b/v2/internal/binding/binding_test/binding_nonstringmapkey_test.go @@ -18,7 +18,7 @@ var NonStringMapKeyTest = BindingTest{ want: ` export namespace binding_test { export class NonStringMapKey { - numberMap: {[key: number]: any}; + numberMap: Record; static createFrom(source: any = {}) { return new NonStringMapKey(source); } diff --git a/v2/internal/binding/binding_test/binding_notags_test.go b/v2/internal/binding/binding_test/binding_notags_test.go new file mode 100644 index 000000000..d4d9997e0 --- /dev/null +++ b/v2/internal/binding/binding_test/binding_notags_test.go @@ -0,0 +1,60 @@ +package binding_test + +type NoFieldTags struct { + Name string + Address string + Zip *string + Spouse *NoFieldTags + NoFunc func() string +} + +func (n NoFieldTags) Get() NoFieldTags { + return n +} + +var NoFieldTagsTest = BindingTest{ + name: "NoFieldTags", + structs: []interface{}{ + &NoFieldTags{}, + }, + exemptions: nil, + shouldError: false, + want: ` +export namespace binding_test { + export class NoFieldTags { + Name: string; + Address: string; + Zip?: string; + Spouse?: NoFieldTags; + static createFrom(source: any = {}) { + return new NoFieldTags(source); + } + constructor(source: any = {}) { + if ('string' === typeof source) source = JSON.parse(source); + this.Name = source["Name"]; + this.Address = source["Address"]; + this.Zip = source["Zip"]; + this.Spouse = this.convertValues(source["Spouse"], NoFieldTags); + } + + convertValues(a: any, classs: any, asMap: boolean = false): any { + if (!a) { + return a; + } + if (a.slice && a.map) { + return (a as any[]).map(elem => this.convertValues(elem, classs)); + } else if ("object" === typeof a) { + if (asMap) { + for (const key of Object.keys(a)) { + a[key] = new classs(a[key]); + } + return a; + } + return new classs(a); + } + return a; + } + } +} +`, +} diff --git a/v2/internal/binding/binding_test/binding_test.go b/v2/internal/binding/binding_test/binding_test.go index a16dde5ea..41f0618ce 100644 --- a/v2/internal/binding/binding_test/binding_test.go +++ b/v2/internal/binding/binding_test/binding_test.go @@ -50,6 +50,15 @@ func TestBindings_GenerateModels(t *testing.T) { EntityWithDiffNamespacesTest, SpecialCharacterFieldTest, WithoutFieldsTest, + NoFieldTagsTest, + Generics1Test, + Generics2Test, + IgnoredTest, + DeepElementsTest, + // PR #4664: Enum ordering tests + EnumOrderingTest, + EnumElementOrderingTest, + TSNameEnumElementOrderingTest, } testLogger := &logger.Logger{} diff --git a/v2/internal/binding/binding_test/binding_type_alias_test.go b/v2/internal/binding/binding_test/binding_type_alias_test.go index 498c5976c..90b009c5f 100644 --- a/v2/internal/binding/binding_test/binding_type_alias_test.go +++ b/v2/internal/binding/binding_test/binding_type_alias_test.go @@ -15,11 +15,11 @@ const expectedTypeAliasBindings = `// Cynhyrchwyd y ffeil hon yn awtomatig. PEID import {binding_test} from '../models'; import {int_package} from '../models'; -export function Map():Promise<{[key: string]: string}>; +export function Map():Promise>; export function MapAlias():Promise; -export function MapWithImportedStructValue():Promise<{[key: string]: int_package.SomeStruct}>; +export function MapWithImportedStructValue():Promise>; export function Slice():Promise>; diff --git a/v2/internal/binding/boundMethod.go b/v2/internal/binding/boundMethod.go index c13e2ff37..e697041b0 100644 --- a/v2/internal/binding/boundMethod.go +++ b/v2/internal/binding/boundMethod.go @@ -6,14 +6,24 @@ import ( "reflect" ) +type BoundedMethodPath struct { + Package string + Struct string + Name string +} + +func (p *BoundedMethodPath) FullName() string { + return fmt.Sprintf("%s.%s.%s", p.Package, p.Struct, p.Name) +} + // BoundMethod defines all the data related to a Go method that is // bound to the Wails application type BoundMethod struct { - Name string `json:"name"` - Inputs []*Parameter `json:"inputs,omitempty"` - Outputs []*Parameter `json:"outputs,omitempty"` - Comments string `json:"comments,omitempty"` - Method reflect.Value `json:"-"` + Path *BoundedMethodPath `json:"path"` + Inputs []*Parameter `json:"inputs,omitempty"` + Outputs []*Parameter `json:"outputs,omitempty"` + Comments string `json:"comments,omitempty"` + Method reflect.Value `json:"-"` } // InputCount returns the number of inputs this bound method has @@ -30,7 +40,7 @@ func (b *BoundMethod) OutputCount() int { func (b *BoundMethod) ParseArgs(args []json.RawMessage) ([]interface{}, error) { result := make([]interface{}, b.InputCount()) if len(args) != b.InputCount() { - return nil, fmt.Errorf("received %d arguments to method '%s', expected %d", len(args), b.Name, b.InputCount()) + return nil, fmt.Errorf("received %d arguments to method '%s', expected %d", len(args), b.Path.FullName(), b.InputCount()) } for index, arg := range args { typ := b.Inputs[index].reflectType @@ -54,7 +64,7 @@ func (b *BoundMethod) Call(args []interface{}) (interface{}, error) { expectedInputLength := len(b.Inputs) actualInputLength := len(args) if expectedInputLength != actualInputLength { - return nil, fmt.Errorf("%s takes %d inputs. Received %d", b.Name, expectedInputLength, actualInputLength) + return nil, fmt.Errorf("%s takes %d inputs. Received %d", b.Path.FullName(), expectedInputLength, actualInputLength) } /** Convert inputs to reflect values **/ diff --git a/v2/internal/binding/generate.go b/v2/internal/binding/generate.go index 02a0bd292..77edc983d 100644 --- a/v2/internal/binding/generate.go +++ b/v2/internal/binding/generate.go @@ -171,7 +171,18 @@ func fullyQualifiedName(packageName string, typeName string) string { } } +var ( + jsVariableUnsafeChars = regexp.MustCompile(`[^A-Za-z0-9_]`) +) + func arrayifyValue(valueArray string, valueType string) string { + valueType = strings.ReplaceAll(valueType, "*", "") + gidx := strings.IndexRune(valueType, '[') + if gidx > 0 { // its a generic type + rem := strings.SplitN(valueType, "[", 2) + valueType = rem[0] + "_" + jsVariableUnsafeChars.ReplaceAllLiteralString(rem[1], "_") + } + if len(valueArray) == 0 { return valueType } @@ -217,7 +228,7 @@ func goTypeToJSDocType(input string, importNamespaces *slicer.StringSlicer) stri } if len(key) > 0 { - return fmt.Sprintf("{[key: %s]: %s}", key, arrayifyValue(valueArray, value)) + return fmt.Sprintf("Record<%s, %s>", key, arrayifyValue(valueArray, value)) } return arrayifyValue(valueArray, value) diff --git a/v2/internal/binding/generate_test.go b/v2/internal/binding/generate_test.go index 8d6a833b8..26d7c70df 100644 --- a/v2/internal/binding/generate_test.go +++ b/v2/internal/binding/generate_test.go @@ -116,18 +116,28 @@ func Test_goTypeToJSDocType(t *testing.T) { { name: "map", input: "map[string]float64", - want: "{[key: string]: number}", + want: "Record", }, { name: "map", input: "map[string]map[string]float64", - want: "{[key: string]: {[key: string]: number}}", + want: "Record>", }, { name: "types", input: "main.SomeType", want: "main.SomeType", }, + { + name: "primitive_generic", + input: "main.ListData[string]", + want: "main.ListData_string_", + }, + { + name: "stdlib_generic", + input: "main.ListData[*net/http.Request]", + want: "main.ListData_net_http_Request_", + }, } var importNamespaces slicer.StringSlicer for _, tt := range tests { diff --git a/v2/internal/binding/reflect.go b/v2/internal/binding/reflect.go index 57a6335bd..c254d0f0a 100644 --- a/v2/internal/binding/reflect.go +++ b/v2/internal/binding/reflect.go @@ -24,6 +24,26 @@ func isStruct(value interface{}) bool { return reflect.ValueOf(value).Kind() == reflect.Struct } +func normalizeStructName(name string) string { + return strings.ReplaceAll( + strings.ReplaceAll( + strings.ReplaceAll( + strings.ReplaceAll( + name, + ",", + "-", + ), + "*", + "", + ), + "]", + "__", + ), + "[", + "__", + ) +} + func (b *Bindings) getMethods(value interface{}) ([]*BoundMethod, error) { // Create result placeholder var result []*BoundMethod @@ -47,14 +67,14 @@ func (b *Bindings) getMethods(value interface{}) ([]*BoundMethod, error) { // Process Struct structType := reflect.TypeOf(value) structValue := reflect.ValueOf(value) - structTypeString := structType.String() - baseName := structTypeString[1:] + structName := structType.Elem().Name() + structNameNormalized := normalizeStructName(structName) + pkgPath := strings.TrimSuffix(structType.Elem().String(), fmt.Sprintf(".%s", structName)) // Process Methods for i := 0; i < structType.NumMethod(); i++ { methodDef := structType.Method(i) methodName := methodDef.Name - fullMethodName := baseName + "." + methodName method := structValue.MethodByName(methodName) methodReflectName := runtime.FuncForPC(methodDef.Func.Pointer()).Name() @@ -64,7 +84,11 @@ func (b *Bindings) getMethods(value interface{}) ([]*BoundMethod, error) { // Create new method boundMethod := &BoundMethod{ - Name: fullMethodName, + Path: &BoundedMethodPath{ + Package: pkgPath, + Struct: structNameNormalized, + Name: methodName, + }, Inputs: nil, Outputs: nil, Comments: "", @@ -166,7 +190,7 @@ func getPackageName(in string) string { } func getSplitReturn(in string) (string, string) { - result := strings.Split(in, ".") + result := strings.SplitN(in, ".", 2) return result[0], result[1] } diff --git a/v2/internal/frontend/desktop/darwin/AppDelegate.m b/v2/internal/frontend/desktop/darwin/AppDelegate.m index 318c333d8..a73ec3ec3 100644 --- a/v2/internal/frontend/desktop/darwin/AppDelegate.m +++ b/v2/internal/frontend/desktop/darwin/AppDelegate.m @@ -9,6 +9,7 @@ #import #import "AppDelegate.h" +#import "CustomProtocol.h" #import "message.h" @implementation AppDelegate @@ -19,6 +20,17 @@ return YES; } +- (BOOL)application:(NSApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(void (^)(NSArray> * _Nullable))restorationHandler { + if ([userActivity.activityType isEqualToString:NSUserActivityTypeBrowsingWeb]) { + NSURL *url = userActivity.webpageURL; + if (url) { + HandleOpenURL((char*)[[url absoluteString] UTF8String]); + return YES; + } + } + return NO; +} + - (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)sender { return NO; } diff --git a/v2/internal/frontend/desktop/darwin/Application.h b/v2/internal/frontend/desktop/darwin/Application.h index 2582eb6e8..4d8bbd37b 100644 --- a/v2/internal/frontend/desktop/darwin/Application.h +++ b/v2/internal/frontend/desktop/darwin/Application.h @@ -17,7 +17,7 @@ #define WindowStartsMinimised 2 #define WindowStartsFullscreen 3 -WailsContext* Create(const char* title, int width, int height, int frameless, int resizable, int zoomable, int fullscreen, int fullSizeContent, int hideTitleBar, int titlebarAppearsTransparent, int hideTitle, int useToolbar, int hideToolbarSeparator, int webviewIsTransparent, int alwaysOnTop, int hideWindowOnClose, const char *appearance, int windowIsTranslucent, int devtoolsEnabled, int defaultContextMenuEnabled, int windowStartState, int startsHidden, int minWidth, int minHeight, int maxWidth, int maxHeight, bool fraudulentWebsiteWarningEnabled, struct Preferences preferences, int singleInstanceEnabled, const char* singleInstanceUniqueId, bool enableDragAndDrop, bool disableWebViewDragAndDrop); +WailsContext* Create(const char* title, int width, int height, int frameless, int resizable, int zoomable, int fullscreen, int fullSizeContent, int hideTitleBar, int titlebarAppearsTransparent, int hideTitle, int useToolbar, int hideToolbarSeparator, int webviewIsTransparent, int alwaysOnTop, int hideWindowOnClose, const char *appearance, int windowIsTranslucent, int contentProtection, int devtoolsEnabled, int defaultContextMenuEnabled, int windowStartState, int startsHidden, int minWidth, int minHeight, int maxWidth, int maxHeight, bool fraudulentWebsiteWarningEnabled, struct Preferences preferences, int singleInstanceLockEnabled, const char* singleInstanceUniqueId, bool enableDragAndDrop, bool disableWebViewDragAndDrop); void Run(void*, const char* url); void SetTitle(void* ctx, const char *title); diff --git a/v2/internal/frontend/desktop/darwin/Application.m b/v2/internal/frontend/desktop/darwin/Application.m index 941e6e922..38d349c2c 100644 --- a/v2/internal/frontend/desktop/darwin/Application.m +++ b/v2/internal/frontend/desktop/darwin/Application.m @@ -14,7 +14,7 @@ #import "WailsMenu.h" #import "WailsMenuItem.h" -WailsContext* Create(const char* title, int width, int height, int frameless, int resizable, int zoomable, int fullscreen, int fullSizeContent, int hideTitleBar, int titlebarAppearsTransparent, int hideTitle, int useToolbar, int hideToolbarSeparator, int webviewIsTransparent, int alwaysOnTop, int hideWindowOnClose, const char *appearance, int windowIsTranslucent, int devtoolsEnabled, int defaultContextMenuEnabled, int windowStartState, int startsHidden, int minWidth, int minHeight, int maxWidth, int maxHeight, bool fraudulentWebsiteWarningEnabled, struct Preferences preferences, int singleInstanceLockEnabled, const char* singleInstanceUniqueId, bool enableDragAndDrop, bool disableWebViewDragAndDrop) { +WailsContext* Create(const char* title, int width, int height, int frameless, int resizable, int zoomable, int fullscreen, int fullSizeContent, int hideTitleBar, int titlebarAppearsTransparent, int hideTitle, int useToolbar, int hideToolbarSeparator, int webviewIsTransparent, int alwaysOnTop, int hideWindowOnClose, const char *appearance, int windowIsTranslucent, int contentProtection, int devtoolsEnabled, int defaultContextMenuEnabled, int windowStartState, int startsHidden, int minWidth, int minHeight, int maxWidth, int maxHeight, bool fraudulentWebsiteWarningEnabled, struct Preferences preferences, int singleInstanceLockEnabled, const char* singleInstanceUniqueId, bool enableDragAndDrop, bool disableWebViewDragAndDrop) { [NSApplication sharedApplication]; @@ -31,6 +31,11 @@ WailsContext* Create(const char* title, int width, int height, int frameless, in [result SetTitle:safeInit(title)]; [result Center]; + if (contentProtection == 1 && + [result.mainWindow respondsToSelector:@selector(setSharingType:)]) { + [result.mainWindow setSharingType:NSWindowSharingNone]; + } + switch( windowStartState ) { case WindowStartsMaximised: [result.mainWindow zoom:nil]; diff --git a/v2/internal/frontend/desktop/darwin/CustomProtocol.h b/v2/internal/frontend/desktop/darwin/CustomProtocol.h index da0e7079f..0698a4d45 100644 --- a/v2/internal/frontend/desktop/darwin/CustomProtocol.h +++ b/v2/internal/frontend/desktop/darwin/CustomProtocol.h @@ -3,7 +3,7 @@ #import -extern void HandleCustomProtocol(char*); +extern void HandleOpenURL(char*); @interface CustomProtocolSchemeHandler : NSObject + (void)handleGetURLEvent:(NSAppleEventDescriptor *)event withReplyEvent:(NSAppleEventDescriptor *)replyEvent; diff --git a/v2/internal/frontend/desktop/darwin/CustomProtocol.m b/v2/internal/frontend/desktop/darwin/CustomProtocol.m index 7365e4f50..ebc61aa00 100644 --- a/v2/internal/frontend/desktop/darwin/CustomProtocol.m +++ b/v2/internal/frontend/desktop/darwin/CustomProtocol.m @@ -6,7 +6,7 @@ NSString *urlStr = [[event paramDescriptorForKeyword:keyDirectObject] stringValue]; - HandleCustomProtocol((char*)[[[event paramDescriptorForKeyword:keyDirectObject] stringValue] UTF8String]); + HandleOpenURL((char*)[[[event paramDescriptorForKeyword:keyDirectObject] stringValue] UTF8String]); } @end diff --git a/v2/internal/frontend/desktop/darwin/WailsContext.m b/v2/internal/frontend/desktop/darwin/WailsContext.m index 581a8c138..7c9660d54 100644 --- a/v2/internal/frontend/desktop/darwin/WailsContext.m +++ b/v2/internal/frontend/desktop/darwin/WailsContext.m @@ -215,7 +215,13 @@ typedef void (^schemeTaskCaller)(id); // Webview stuff here! WKWebViewConfiguration *config = [WKWebViewConfiguration new]; - config.suppressesIncrementalRendering = true; + // Disable suppressesIncrementalRendering on macOS 26+ to prevent WebView crashes + // during rapid UI updates. See: https://github.com/wailsapp/wails/issues/4592 + if (@available(macOS 26.0, *)) { + config.suppressesIncrementalRendering = false; + } else { + config.suppressesIncrementalRendering = true; + } config.applicationNameForUserAgent = @"wails.io"; [config setURLSchemeHandler:self forURLScheme:@"wails"]; @@ -477,6 +483,15 @@ typedef void (^schemeTaskCaller)(id); } - (void)userContentController:(nonnull WKUserContentController *)userContentController didReceiveScriptMessage:(nonnull WKScriptMessage *)message { + // Get the origin from the message's frame + NSString *origin = nil; + if (message.frameInfo && message.frameInfo.request && message.frameInfo.request.URL) { + NSURL *url = message.frameInfo.request.URL; + if (url.scheme && url.host) { + origin = [url absoluteString]; + } + } + NSString *m = message.body; // Check for drag @@ -491,11 +506,11 @@ typedef void (^schemeTaskCaller)(id); } const char *_m = [m UTF8String]; + const char *_origin = [origin UTF8String]; - processMessage(_m); + processBindingMessage(_m, _origin, message.frameInfo.isMainFrame); } - /***** Dialogs ******/ -(void) MessageDialog :(NSString*)dialogType :(NSString*)title :(NSString*)message :(NSString*)button1 :(NSString*)button2 :(NSString*)button3 :(NSString*)button4 :(NSString*)defaultButton :(NSString*)cancelButton :(void*)iconData :(int)iconDataLength { @@ -594,9 +609,8 @@ typedef void (^schemeTaskCaller)(id); } [dialog setAllowsMultipleSelection: allowMultipleSelection]; - [dialog setShowsHiddenFiles: showHiddenFiles]; - } + [dialog setShowsHiddenFiles: showHiddenFiles]; // Default Directory if( defaultDirectory != nil ) { diff --git a/v2/internal/frontend/desktop/darwin/WailsMenu.m b/v2/internal/frontend/desktop/darwin/WailsMenu.m index 7e36da99a..66e5dd399 100644 --- a/v2/internal/frontend/desktop/darwin/WailsMenu.m +++ b/v2/internal/frontend/desktop/darwin/WailsMenu.m @@ -184,16 +184,16 @@ return unicode(0x001b); } if( [key isEqualToString:@"left"] ) { - return unicode(0xf702); + return unicode(0x001c); } if( [key isEqualToString:@"right"] ) { - return unicode(0xf703); + return unicode(0x001d); } if( [key isEqualToString:@"up"] ) { - return unicode(0xf700); + return unicode(0x001e); } if( [key isEqualToString:@"down"] ) { - return unicode(0xf701); + return unicode(0x001f); } if( [key isEqualToString:@"space"] ) { return unicode(0x0020); diff --git a/v2/internal/frontend/desktop/darwin/browser.go b/v2/internal/frontend/desktop/darwin/browser.go index 12b2bc8fc..c865ab6d9 100644 --- a/v2/internal/frontend/desktop/darwin/browser.go +++ b/v2/internal/frontend/desktop/darwin/browser.go @@ -4,11 +4,19 @@ package darwin import ( + "fmt" "github.com/pkg/browser" + "github.com/wailsapp/wails/v2/internal/frontend/utils" ) // BrowserOpenURL Use the default browser to open the url -func (f *Frontend) BrowserOpenURL(url string) { +func (f *Frontend) BrowserOpenURL(rawURL string) { + url, err := utils.ValidateAndSanitizeURL(rawURL) + if err != nil { + f.logger.Error(fmt.Sprintf("Invalid URL %s", err.Error())) + return + } + // Specific method implementation if err := browser.OpenURL(url); err != nil { f.logger.Error("Unable to open default system browser") diff --git a/v2/internal/frontend/desktop/darwin/frontend.go b/v2/internal/frontend/desktop/darwin/frontend.go index ba00b02d9..6566445d5 100644 --- a/v2/internal/frontend/desktop/darwin/frontend.go +++ b/v2/internal/frontend/desktop/darwin/frontend.go @@ -31,6 +31,7 @@ import ( "github.com/wailsapp/wails/v2/internal/binding" "github.com/wailsapp/wails/v2/internal/frontend" + "github.com/wailsapp/wails/v2/internal/frontend/originvalidator" "github.com/wailsapp/wails/v2/internal/frontend/runtime" "github.com/wailsapp/wails/v2/internal/logger" "github.com/wailsapp/wails/v2/pkg/options" @@ -38,13 +39,20 @@ import ( const startURL = "wails://wails/" +type bindingsMessage struct { + message string + source string + isMainFrame bool +} + var ( - messageBuffer = make(chan string, 100) - requestBuffer = make(chan webview.Request, 100) - callbackBuffer = make(chan uint, 10) - openFilepathBuffer = make(chan string, 100) - openUrlBuffer = make(chan string, 100) - secondInstanceBuffer = make(chan options.SecondInstanceData, 1) + messageBuffer = make(chan string, 100) + bindingsMessageBuffer = make(chan *bindingsMessage, 100) + requestBuffer = make(chan webview.Request, 100) + callbackBuffer = make(chan uint, 10) + openFilepathBuffer = make(chan string, 100) + openUrlBuffer = make(chan string, 100) + secondInstanceBuffer = make(chan options.SecondInstanceData, 1) ) type Frontend struct { @@ -67,6 +75,8 @@ type Frontend struct { mainWindow *Window bindings *binding.Bindings dispatcher frontend.Dispatcher + + originValidator *originvalidator.OriginValidator } func (f *Frontend) RunMainLoop() { @@ -86,15 +96,18 @@ func NewFrontend(ctx context.Context, appoptions *options.App, myLogger *logger. ctx: ctx, } result.startURL, _ = url.Parse(startURL) + result.originValidator = originvalidator.NewOriginValidator(result.startURL, appoptions.BindingsAllowedOrigins) // this should be initialized as early as possible to handle first instance launch C.StartCustomProtocolHandler() if _starturl, _ := ctx.Value("starturl").(*url.URL); _starturl != nil { result.startURL = _starturl + result.originValidator = originvalidator.NewOriginValidator(result.startURL, appoptions.BindingsAllowedOrigins) } else { if port, _ := ctx.Value("assetserverport").(string); port != "" { result.startURL.Host = net.JoinHostPort(result.startURL.Host+".localhost", port) + result.originValidator = originvalidator.NewOriginValidator(result.startURL, appoptions.BindingsAllowedOrigins) } var bindings string @@ -119,6 +132,7 @@ func NewFrontend(ctx context.Context, appoptions *options.App, myLogger *logger. } go result.startMessageProcessor() + go result.startBindingsMessageProcessor() go result.startCallbackProcessor() go result.startFileOpenProcessor() go result.startUrlOpenProcessor() @@ -154,6 +168,30 @@ func (f *Frontend) startMessageProcessor() { } } +func (f *Frontend) startBindingsMessageProcessor() { + for msg := range bindingsMessageBuffer { + // Apple webkit doesn't provide origin of main frame. So we can't verify in case of iFrame that top level origin is allowed. + if !msg.isMainFrame { + f.logger.Error("Blocked request from not main frame") + continue + } + + origin, err := f.originValidator.GetOriginFromURL(msg.source) + if err != nil { + f.logger.Error(fmt.Sprintf("failed to get origin for URL %q: %v", msg.source, err)) + continue + } + + allowed := f.originValidator.IsOriginAllowed(origin) + if !allowed { + f.logger.Error("Blocked request from unauthorized origin: %s", origin) + continue + } + + f.processMessage(msg.message) + } +} + func (f *Frontend) startRequestProcessor() { for request := range requestBuffer { f.assets.ServeWebViewRequest(request) @@ -453,6 +491,17 @@ func processMessage(message *C.char) { messageBuffer <- goMessage } +//export processBindingMessage +func processBindingMessage(message *C.char, source *C.char, fromMainFrame bool) { + goMessage := C.GoString(message) + goSource := C.GoString(source) + bindingsMessageBuffer <- &bindingsMessage{ + message: goMessage, + source: goSource, + isMainFrame: fromMainFrame, + } +} + //export processCallback func processCallback(callbackID uint) { callbackBuffer <- callbackID @@ -469,8 +518,8 @@ func HandleOpenFile(filePath *C.char) { openFilepathBuffer <- goFilepath } -//export HandleCustomProtocol -func HandleCustomProtocol(url *C.char) { +//export HandleOpenURL +func HandleOpenURL(url *C.char) { goUrl := C.GoString(url) openUrlBuffer <- goUrl } diff --git a/v2/internal/frontend/desktop/darwin/message.h b/v2/internal/frontend/desktop/darwin/message.h index 66110841d..86506f868 100644 --- a/v2/internal/frontend/desktop/darwin/message.h +++ b/v2/internal/frontend/desktop/darwin/message.h @@ -15,6 +15,7 @@ extern "C" #endif void processMessage(const char *); +void processBindingMessage(const char *, const char *, bool); void processURLRequest(void *, void*); void processMessageDialogResponse(int); void processOpenFileDialogResponse(const char*); diff --git a/v2/internal/frontend/desktop/darwin/single_instance.go b/v2/internal/frontend/desktop/darwin/single_instance.go index 02a5c78ee..27b34045b 100644 --- a/v2/internal/frontend/desktop/darwin/single_instance.go +++ b/v2/internal/frontend/desktop/darwin/single_instance.go @@ -62,7 +62,7 @@ func HandleSecondInstanceData(secondInstanceMessage *C.char) { } } -// CreateLockFile tries to create a file with given name and acquire an +// createLockFile tries to create a file with given name and acquire an // exclusive lock on it. If the file already exists AND is still locked, it will // fail. func createLockFile(filename string) (*os.File, error) { diff --git a/v2/internal/frontend/desktop/darwin/window.go b/v2/internal/frontend/desktop/darwin/window.go index 121533a33..87d4213d9 100644 --- a/v2/internal/frontend/desktop/darwin/window.go +++ b/v2/internal/frontend/desktop/darwin/window.go @@ -32,6 +32,8 @@ func init() { type Window struct { context unsafe.Pointer + + applicationMenu *menu.Menu } func bool2Cint(value bool) C.int { @@ -61,7 +63,7 @@ func NewWindow(frontendOptions *options.App, debug bool, devtools bool) *Window singleInstanceEnabled := bool2Cint(frontendOptions.SingleInstanceLock != nil) var fullSizeContent, hideTitleBar, zoomable, hideTitle, useToolbar, webviewIsTransparent C.int - var titlebarAppearsTransparent, hideToolbarSeparator, windowIsTranslucent C.int + var titlebarAppearsTransparent, hideToolbarSeparator, windowIsTranslucent, contentProtection C.int var appearance, title *C.char var preferences C.struct_Preferences @@ -115,12 +117,13 @@ func NewWindow(frontendOptions *options.App, debug bool, devtools bool) *Window windowIsTranslucent = bool2Cint(mac.WindowIsTranslucent) webviewIsTransparent = bool2Cint(mac.WebviewIsTransparent) + contentProtection = bool2Cint(mac.ContentProtection) appearance = c.String(string(mac.Appearance)) } var context *C.WailsContext = C.Create(title, width, height, frameless, resizable, zoomable, fullscreen, fullSizeContent, hideTitleBar, titlebarAppearsTransparent, hideTitle, useToolbar, hideToolbarSeparator, webviewIsTransparent, - alwaysOnTop, hideWindowOnClose, appearance, windowIsTranslucent, devtoolsEnabled, defaultContextMenuEnabled, + alwaysOnTop, hideWindowOnClose, appearance, windowIsTranslucent, contentProtection, devtoolsEnabled, defaultContextMenuEnabled, windowStartState, startsHidden, minWidth, minHeight, maxWidth, maxHeight, enableFraudulentWebsiteWarnings, preferences, singleInstanceEnabled, singleInstanceUniqueId, enableDragAndDrop, disableWebViewDragAndDrop, ) @@ -292,12 +295,16 @@ func (w *Window) Size() (int, int) { } func (w *Window) SetApplicationMenu(inMenu *menu.Menu) { - mainMenu := NewNSMenu(w.context, "") - processMenu(mainMenu, inMenu) - C.SetAsApplicationMenu(w.context, mainMenu.nsmenu) + w.applicationMenu = inMenu + w.UpdateApplicationMenu() } func (w *Window) UpdateApplicationMenu() { + mainMenu := NewNSMenu(w.context, "") + if w.applicationMenu != nil { + processMenu(mainMenu, w.applicationMenu) + } + C.SetAsApplicationMenu(w.context, mainMenu.nsmenu) C.UpdateApplicationMenu(w.context) } diff --git a/v2/internal/frontend/desktop/linux/browser.go b/v2/internal/frontend/desktop/linux/browser.go index 30ca9620c..962e3b28a 100644 --- a/v2/internal/frontend/desktop/linux/browser.go +++ b/v2/internal/frontend/desktop/linux/browser.go @@ -3,10 +3,19 @@ package linux -import "github.com/pkg/browser" +import ( + "fmt" + "github.com/pkg/browser" + "github.com/wailsapp/wails/v2/internal/frontend/utils" +) // BrowserOpenURL Use the default browser to open the url -func (f *Frontend) BrowserOpenURL(url string) { +func (f *Frontend) BrowserOpenURL(rawURL string) { + url, err := utils.ValidateAndSanitizeURL(rawURL) + if err != nil { + f.logger.Error(fmt.Sprintf("Invalid URL %s", err.Error())) + return + } // Specific method implementation if err := browser.OpenURL(url); err != nil { f.logger.Error("Unable to open default system browser") diff --git a/v2/internal/frontend/desktop/linux/frontend.go b/v2/internal/frontend/desktop/linux/frontend.go index 3bc81649f..2942a112e 100644 --- a/v2/internal/frontend/desktop/linux/frontend.go +++ b/v2/internal/frontend/desktop/linux/frontend.go @@ -4,7 +4,7 @@ package linux /* -#cgo linux pkg-config: gtk+-3.0 +#cgo linux pkg-config: gtk+-3.0 #cgo !webkit2_41 pkg-config: webkit2gtk-4.0 #cgo webkit2_41 pkg-config: webkit2gtk-4.1 @@ -73,6 +73,16 @@ static void install_signal_handlers() #endif } +static gboolean install_signal_handlers_idle(gpointer data) { + (void)data; + install_signal_handlers(); + return G_SOURCE_REMOVE; +} + +static void fix_signal_handlers_after_gtk_init() { + g_idle_add(install_signal_handlers_idle, NULL); +} + */ import "C" import ( @@ -95,6 +105,7 @@ import ( "github.com/wailsapp/wails/v2/internal/binding" "github.com/wailsapp/wails/v2/internal/frontend" + "github.com/wailsapp/wails/v2/internal/frontend/originvalidator" wailsruntime "github.com/wailsapp/wails/v2/internal/frontend/runtime" "github.com/wailsapp/wails/v2/internal/logger" "github.com/wailsapp/wails/v2/pkg/options" @@ -124,6 +135,8 @@ type Frontend struct { mainWindow *Window bindings *binding.Bindings dispatcher frontend.Dispatcher + + originValidator *originvalidator.OriginValidator } func (f *Frontend) RunMainLoop() { @@ -156,12 +169,15 @@ func NewFrontend(ctx context.Context, appoptions *options.App, myLogger *logger. ctx: ctx, } result.startURL, _ = url.Parse(startURL) + result.originValidator = originvalidator.NewOriginValidator(result.startURL, appoptions.BindingsAllowedOrigins) if _starturl, _ := ctx.Value("starturl").(*url.URL); _starturl != nil { result.startURL = _starturl + result.originValidator = originvalidator.NewOriginValidator(result.startURL, appoptions.BindingsAllowedOrigins) } else { if port, _ := ctx.Value("assetserverport").(string); port != "" { result.startURL.Host = net.JoinHostPort(result.startURL.Host+".localhost", port) + result.originValidator = originvalidator.NewOriginValidator(result.startURL, appoptions.BindingsAllowedOrigins) } var bindings string @@ -184,6 +200,7 @@ func NewFrontend(ctx context.Context, appoptions *options.App, myLogger *logger. } go result.startMessageProcessor() + go result.startBindingsMessageProcessor() var _debug = ctx.Value("debug") var _devtoolsEnabled = ctx.Value("devtoolsEnabled") @@ -197,7 +214,7 @@ func NewFrontend(ctx context.Context, appoptions *options.App, myLogger *logger. result.mainWindow = NewWindow(appoptions, result.debug, result.devtoolsEnabled) - C.install_signal_handlers() + C.fix_signal_handlers_after_gtk_init() if appoptions.Linux != nil && appoptions.Linux.ProgramName != "" { prgname := C.CString(appoptions.Linux.ProgramName) @@ -216,6 +233,24 @@ func (f *Frontend) startMessageProcessor() { } } +func (f *Frontend) startBindingsMessageProcessor() { + for msg := range bindingsMessageBuffer { + origin, err := f.originValidator.GetOriginFromURL(msg.source) + if err != nil { + f.logger.Error(fmt.Sprintf("failed to get origin for URL %q: %v", msg.source, err)) + continue + } + + allowed := f.originValidator.IsOriginAllowed(origin) + if !allowed { + f.logger.Error("Blocked request from unauthorized origin: %s", origin) + continue + } + + f.processMessage(msg.message) + } +} + func (f *Frontend) WindowReload() { f.ExecJS("runtime.WindowReload();") } @@ -507,7 +542,13 @@ func (f *Frontend) ExecJS(js string) { f.mainWindow.ExecJS(js) } +type bindingsMessage struct { + message string + source string +} + var messageBuffer = make(chan string, 100) +var bindingsMessageBuffer = make(chan *bindingsMessage, 100) //export processMessage func processMessage(message *C.char) { @@ -515,6 +556,16 @@ func processMessage(message *C.char) { messageBuffer <- goMessage } +//export processBindingMessage +func processBindingMessage(message *C.char, source *C.char) { + goMessage := C.GoString(message) + goSource := C.GoString(source) + bindingsMessageBuffer <- &bindingsMessage{ + message: goMessage, + source: goSource, + } +} + var requestBuffer = make(chan webview.Request, 100) func (f *Frontend) startRequestProcessor() { diff --git a/v2/internal/frontend/desktop/linux/menu.go b/v2/internal/frontend/desktop/linux/menu.go index 557a24b37..a61d190bd 100644 --- a/v2/internal/frontend/desktop/linux/menu.go +++ b/v2/internal/frontend/desktop/linux/menu.go @@ -34,8 +34,11 @@ void addAccelerator(GtkWidget* menuItem, GtkAccelGroup* group, guint key, GdkMod } */ import "C" -import "github.com/wailsapp/wails/v2/pkg/menu" -import "unsafe" +import ( + "unsafe" + + "github.com/wailsapp/wails/v2/pkg/menu" +) var menuIdCounter int var menuItemToId map[*menu.MenuItem]int @@ -81,8 +84,10 @@ func (w *Window) SetApplicationMenu(inmenu *menu.Menu) { func processMenu(window *Window, menu *menu.Menu) { for _, menuItem := range menu.Items { - submenu := processSubmenu(menuItem, window.accels) - C.gtk_menu_shell_append(C.toGtkMenuShell(unsafe.Pointer(window.menubar)), submenu) + if menuItem.SubMenu != nil { + submenu := processSubmenu(menuItem, window.accels) + C.gtk_menu_shell_append(C.toGtkMenuShell(unsafe.Pointer(window.menubar)), submenu) + } } } diff --git a/v2/internal/frontend/desktop/linux/window.c b/v2/internal/frontend/desktop/linux/window.c index 0dee24f42..5441db022 100644 --- a/v2/internal/frontend/desktop/linux/window.c +++ b/v2/internal/frontend/desktop/linux/window.c @@ -14,6 +14,9 @@ static float xroot = 0.0f; static float yroot = 0.0f; static int dragTime = -1; static uint mouseButton = 0; +static int wmIsWayland = -1; +static int decoratorWidth = -1; +static int decoratorHeight = -1; // casts void ExecuteOnMainThread(void *f, gpointer jscallback) @@ -42,11 +45,17 @@ GtkBox *GTKBOX(void *pointer) } extern void processMessage(char *); +extern void processBindingMessage(char *, char *); static void sendMessageToBackend(WebKitUserContentManager *contentManager, WebKitJavascriptResult *result, void *data) { + // Retrieve webview from content manager + WebKitWebView *webview = WEBKIT_WEB_VIEW(g_object_get_data(G_OBJECT(contentManager), "webview")); + const char *current_uri = webview ? webkit_web_view_get_uri(webview) : NULL; + char *uri = current_uri ? g_strdup(current_uri) : NULL; + #if WEBKIT_MAJOR_VERSION >= 2 && WEBKIT_MINOR_VERSION >= 22 JSCValue *value = webkit_javascript_result_get_js_value(result); char *message = jsc_value_to_string(value); @@ -59,8 +68,11 @@ static void sendMessageToBackend(WebKitUserContentManager *contentManager, JSStringGetUTF8CString(js, message, messageSize); JSStringRelease(js); #endif - processMessage(message); + processBindingMessage(message, uri); g_free(message); + if (uri) { + g_free(uri); + } } static bool isNULLRectangle(GdkRectangle input) @@ -68,6 +80,29 @@ static bool isNULLRectangle(GdkRectangle input) return input.x == -1 && input.y == -1 && input.width == -1 && input.height == -1; } +static gboolean onWayland() +{ + switch (wmIsWayland) + { + case -1: + { + char *gdkBackend = getenv("XDG_SESSION_TYPE"); + if(gdkBackend != NULL && strcmp(gdkBackend, "wayland") == 0) + { + wmIsWayland = 1; + return TRUE; + } + + wmIsWayland = 0; + return FALSE; + } + case 1: + return TRUE; + default: + return FALSE; + } +} + static GdkMonitor *getCurrentMonitor(GtkWindow *window) { // Get the monitor that the window is currently on @@ -238,11 +273,34 @@ void SetMinMaxSize(GtkWindow *window, int min_width, int min_height, int max_wid { return; } + int flags = GDK_HINT_MAX_SIZE | GDK_HINT_MIN_SIZE; + size.max_height = (max_height == 0 ? monitorSize.height : max_height); size.max_width = (max_width == 0 ? monitorSize.width : max_width); size.min_height = min_height; size.min_width = min_width; + + // On Wayland window manager get the decorators and calculate the differences from the windows' size. + if(onWayland()) + { + if(decoratorWidth == -1 && decoratorHeight == -1) + { + int windowWidth, windowHeight; + gtk_window_get_size(window, &windowWidth, &windowHeight); + + GtkAllocation windowAllocation; + gtk_widget_get_allocation(GTK_WIDGET(window), &windowAllocation); + + decoratorWidth = (windowAllocation.width-windowWidth); + decoratorHeight = (windowAllocation.height-windowHeight); + } + + // Add the decorator difference to the window so fullscreen and maximise can fill the window. + size.max_height = decoratorHeight+size.max_height; + size.max_width = decoratorWidth+size.max_width; + } + gtk_window_set_geometry_hints(window, NULL, &size, flags); } @@ -500,6 +558,9 @@ static gboolean onDragDrop(GtkWidget* self, GdkDragContext* context, gint x, gin GtkWidget *SetupWebview(void *contentManager, GtkWindow *window, int hideWindowOnClose, int gpuPolicy, int disableWebViewDragAndDrop, int enableDragAndDrop) { GtkWidget *webview = webkit_web_view_new_with_user_content_manager((WebKitUserContentManager *)contentManager); + + // Store webview reference in the content manager + g_object_set_data(G_OBJECT((WebKitUserContentManager *)contentManager), "webview", webview); // gtk_container_add(GTK_CONTAINER(window), webview); WebKitWebContext *context = webkit_web_context_get_default(); webkit_web_context_register_uri_scheme(context, "wails", (WebKitURISchemeRequestCallback)processURLRequest, NULL, NULL); @@ -827,4 +888,4 @@ void InstallF12Hotkey(void *window) gtk_window_add_accel_group(GTK_WINDOW(window), accel_group); GClosure *closure = g_cclosure_new(G_CALLBACK(sendShowInspectorMessage), window, NULL); gtk_accel_group_connect(accel_group, GDK_KEY_F12, GDK_CONTROL_MASK | GDK_SHIFT_MASK, GTK_ACCEL_VISIBLE, closure); -} \ No newline at end of file +} diff --git a/v2/internal/frontend/desktop/windows/browser.go b/v2/internal/frontend/desktop/windows/browser.go index 2b058feda..13d037b14 100644 --- a/v2/internal/frontend/desktop/windows/browser.go +++ b/v2/internal/frontend/desktop/windows/browser.go @@ -4,7 +4,9 @@ package windows import ( + "fmt" "github.com/pkg/browser" + "github.com/wailsapp/wails/v2/internal/frontend/utils" "golang.org/x/sys/windows" ) @@ -16,9 +18,15 @@ var fallbackBrowserPaths = []string{ } // BrowserOpenURL Use the default browser to open the url -func (f *Frontend) BrowserOpenURL(url string) { +func (f *Frontend) BrowserOpenURL(rawURL string) { + url, err := utils.ValidateAndSanitizeURL(rawURL) + if err != nil { + f.logger.Error(fmt.Sprintf("Invalid URL %s", err.Error())) + return + } + // Specific method implementation - err := browser.OpenURL(url) + err = browser.OpenURL(url) if err == nil { return } diff --git a/v2/internal/frontend/desktop/windows/frontend.go b/v2/internal/frontend/desktop/windows/frontend.go index 71e90e8e5..5df13ed98 100644 --- a/v2/internal/frontend/desktop/windows/frontend.go +++ b/v2/internal/frontend/desktop/windows/frontend.go @@ -25,13 +25,16 @@ import ( "github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/win32" "github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/winc" "github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/winc/w32" + "github.com/wailsapp/wails/v2/internal/frontend/originvalidator" wailsruntime "github.com/wailsapp/wails/v2/internal/frontend/runtime" "github.com/wailsapp/wails/v2/internal/logger" + w32consts "github.com/wailsapp/wails/v2/internal/platform/win32" "github.com/wailsapp/wails/v2/internal/system/operatingsystem" "github.com/wailsapp/wails/v2/pkg/assetserver" "github.com/wailsapp/wails/v2/pkg/assetserver/webview" "github.com/wailsapp/wails/v2/pkg/options" "github.com/wailsapp/wails/v2/pkg/options/windows" + w "golang.org/x/sys/windows" ) const startURL = "http://wails.localhost/" @@ -62,6 +65,8 @@ type Frontend struct { hasStarted bool + originValidator *originvalidator.OriginValidator + // Windows build number versionInfo *operatingsystem.WindowsVersionInfo resizeDebouncer func(f func()) @@ -72,6 +77,13 @@ func NewFrontend(ctx context.Context, appoptions *options.App, myLogger *logger. // Get Windows build number versionInfo, _ := operatingsystem.GetWindowsVersionInfo() + // Apply DLL search path settings if specified + if appoptions.Windows != nil && appoptions.Windows.DLLSearchPaths != 0 { + w.SetDefaultDllDirectories(appoptions.Windows.DLLSearchPaths) + } + // Now initialize packages that load DLLs + w32.Init() + w32consts.Init() result := &Frontend{ frontendOptions: appoptions, logger: myLogger, @@ -89,14 +101,17 @@ func NewFrontend(ctx context.Context, appoptions *options.App, myLogger *logger. // We currently can't use wails://wails/ as other platforms do, therefore we map the assets sever onto the following url. result.startURL, _ = url.Parse(startURL) + result.originValidator = originvalidator.NewOriginValidator(result.startURL, appoptions.BindingsAllowedOrigins) if _starturl, _ := ctx.Value("starturl").(*url.URL); _starturl != nil { result.startURL = _starturl + result.originValidator = originvalidator.NewOriginValidator(result.startURL, appoptions.BindingsAllowedOrigins) return result } if port, _ := ctx.Value("assetserverport").(string); port != "" { result.startURL.Host = net.JoinHostPort(result.startURL.Host, port) + result.originValidator = originvalidator.NewOriginValidator(result.startURL, appoptions.BindingsAllowedOrigins) } var bindings string @@ -170,10 +185,21 @@ func (f *Frontend) Run(ctx context.Context) error { // depends on the content in the WebView, see https://github.com/wailsapp/wails/issues/1319 event, _ := arg.Data.(*winc.SizeEventData) if event != nil && event.Type == w32.SIZE_MINIMIZED { + // Set minimizing flag to prevent unnecessary redraws during minimize/restore for frameless windows + // 设置最小化标志以防止无边框窗口在最小化/恢复过程中的不必要重绘 + // This fixes window flickering when minimizing/restoring frameless windows + // 这修复了无边框窗口在最小化/恢复时的闪烁问题 + // Reference: https://github.com/wailsapp/wails/issues/3951 + f.mainWindow.isMinimizing = true return } } + // Clear minimizing flag for all non-minimize size events + // 对于所有非最小化的尺寸变化事件,清除最小化标志 + // Reference: https://github.com/wailsapp/wails/issues/3951 + f.mainWindow.isMinimizing = false + if f.resizeDebouncer != nil { f.resizeDebouncer(func() { f.mainWindow.Invoke(func() { @@ -669,7 +695,24 @@ var edgeMap = map[string]uintptr{ "nw-resize": w32.HTTOPLEFT, } -func (f *Frontend) processMessage(message string) { +func (f *Frontend) processMessage(message string, sender *edge.ICoreWebView2, args *edge.ICoreWebView2WebMessageReceivedEventArgs) { + topSource, err := sender.GetSource() + if err != nil { + f.logger.Error(fmt.Sprintf("Unable to get source from sender: %s", err.Error())) + return + } + + senderSource, err := args.GetSource() + if err != nil { + f.logger.Error(fmt.Sprintf("Unable to get source from args: %s", err.Error())) + return + } + + // verify both topSource and sender are allowed origins + if !f.validBindingOrigin(topSource) || !f.validBindingOrigin(senderSource) { + return + } + if message == "drag" { if !f.mainWindow.IsFullScreen() { err := f.startDrag() @@ -714,6 +757,23 @@ func (f *Frontend) processMessage(message string) { } func (f *Frontend) processMessageWithAdditionalObjects(message string, sender *edge.ICoreWebView2, args *edge.ICoreWebView2WebMessageReceivedEventArgs) { + topSource, err := sender.GetSource() + if err != nil { + f.logger.Error(fmt.Sprintf("Unable to get source from sender: %s", err.Error())) + return + } + + senderSource, err := args.GetSource() + if err != nil { + f.logger.Error(fmt.Sprintf("Unable to get source from args: %s", err.Error())) + return + } + + // verify both topSource and sender are allowed origins + if !f.validBindingOrigin(topSource) || !f.validBindingOrigin(senderSource) { + return + } + if strings.HasPrefix(message, "file:drop") { if !f.frontendOptions.DragAndDrop.EnableFileDrop { return @@ -740,6 +800,11 @@ func (f *Frontend) processMessageWithAdditionalObjects(message string, sender *e return } + if _file == nil { + f.logger.Warning("object at %d is not a file", i) + continue + } + file := (*edge.ICoreWebView2File)(unsafe.Pointer(_file)) defer file.Release() @@ -767,6 +832,20 @@ func (f *Frontend) processMessageWithAdditionalObjects(message string, sender *e } } +func (f *Frontend) validBindingOrigin(source string) bool { + origin, err := f.originValidator.GetOriginFromURL(source) + if err != nil { + f.logger.Error(fmt.Sprintf("Error parsing source URL %s: %v", source, err.Error())) + return false + } + allowed := f.originValidator.IsOriginAllowed(origin) + if !allowed { + f.logger.Error("Blocked request from unauthorized origin: %s", origin) + return false + } + return true +} + func (f *Frontend) dispatchMessage(message string) { result, err := f.dispatcher.ProcessMessage(message, f) if err != nil { diff --git a/v2/internal/frontend/desktop/windows/winc/controlbase.go b/v2/internal/frontend/desktop/windows/winc/controlbase.go index 086609aed..cdb29518c 100644 --- a/v2/internal/frontend/desktop/windows/winc/controlbase.go +++ b/v2/internal/frontend/desktop/windows/winc/controlbase.go @@ -65,7 +65,7 @@ type ControlBase struct { dispatchq []func() } -// initControl is called by controls: edit, button, treeview, listview, and so on. +// InitControl is called by controls: edit, button, treeview, listview, and so on. func (cba *ControlBase) InitControl(className string, parent Controller, exstyle, style uint) { cba.hwnd = CreateWindow(className, parent, exstyle, style) if cba.hwnd == 0 { @@ -170,6 +170,14 @@ func (cba *ControlBase) SetTranslucentBackground() { w32.SetWindowCompositionAttribute(cba.hwnd, &data) } +func (cba *ControlBase) SetContentProtection(enable bool) { + if enable { + w32.SetWindowDisplayAffinity(uintptr(cba.hwnd), w32.WDA_EXCLUDEFROMCAPTURE) + } else { + w32.SetWindowDisplayAffinity(uintptr(cba.hwnd), w32.WDA_NONE) + } +} + func min(a, b int) int { if a < b { return a diff --git a/v2/internal/frontend/desktop/windows/winc/form.go b/v2/internal/frontend/desktop/windows/winc/form.go index 8a42d63f3..c9acf7278 100644 --- a/v2/internal/frontend/desktop/windows/winc/form.go +++ b/v2/internal/frontend/desktop/windows/winc/form.go @@ -145,7 +145,7 @@ func (fm *Form) Restore() { SC_RESTORE, 0, ) - w32.ShowWindow(fm.hwnd, w32.SW_RESTORE) + w32.ShowWindow(fm.hwnd, w32.SW_SHOW) } // Public methods diff --git a/v2/internal/frontend/desktop/windows/winc/w32/user32.go b/v2/internal/frontend/desktop/windows/winc/w32/user32.go index 89ff985af..707701f5e 100644 --- a/v2/internal/frontend/desktop/windows/winc/w32/user32.go +++ b/v2/internal/frontend/desktop/windows/winc/w32/user32.go @@ -792,11 +792,9 @@ func CreateMenu() HMENU { } func SetMenu(hWnd HWND, hMenu HMENU) bool { - ret, _, _ := syscall.Syscall(setMenu, 2, + ret, _, _ := syscall.SyscallN(setMenu, uintptr(hWnd), - uintptr(hMenu), - 0) - + uintptr(hMenu)) return ret != 0 } @@ -834,11 +832,7 @@ func TrackPopupMenuEx(hMenu HMENU, fuFlags uint32, x, y int32, hWnd HWND, lptpm } func DrawMenuBar(hWnd HWND) bool { - ret, _, _ := syscall.Syscall(drawMenuBar, 1, - uintptr(hWnd), - 0, - 0) - + ret, _, _ := syscall.SyscallN(drawMenuBar, hWnd) return ret != 0 } @@ -1231,11 +1225,8 @@ func CallNextHookEx(hhk HHOOK, nCode int, wParam WPARAM, lParam LPARAM) LRESULT } func GetKeyState(nVirtKey int32) int16 { - ret, _, _ := syscall.Syscall(getKeyState, 1, - uintptr(nVirtKey), - 0, - 0) - + ret, _, _ := syscall.SyscallN(getKeyState, + uintptr(nVirtKey)) return int16(ret) } @@ -1249,17 +1240,15 @@ func DestroyMenu(hMenu HMENU) bool { } func GetWindowPlacement(hWnd HWND, lpwndpl *WINDOWPLACEMENT) bool { - ret, _, _ := syscall.Syscall(getWindowPlacement, 2, - uintptr(hWnd), - uintptr(unsafe.Pointer(lpwndpl)), - 0) - + ret, _, _ := syscall.SyscallN(getWindowPlacement, + hWnd, + uintptr(unsafe.Pointer(lpwndpl))) return ret != 0 } func SetWindowPlacement(hWnd HWND, lpwndpl *WINDOWPLACEMENT) bool { - ret, _, _ := syscall.Syscall(setWindowPlacement, 2, - uintptr(hWnd), + ret, _, _ := syscall.SyscallN(setWindowPlacement, + hWnd, uintptr(unsafe.Pointer(lpwndpl)), 0) @@ -1279,7 +1268,7 @@ func SetScrollInfo(hwnd HWND, fnBar int32, lpsi *SCROLLINFO, fRedraw bool) int32 } func GetScrollInfo(hwnd HWND, fnBar int32, lpsi *SCROLLINFO) bool { - ret, _, _ := syscall.Syscall(getScrollInfo, 3, + ret, _, _ := syscall.SyscallN(getScrollInfo, hwnd, uintptr(fnBar), uintptr(unsafe.Pointer(lpsi))) diff --git a/v2/internal/frontend/desktop/windows/winc/w32/utils.go b/v2/internal/frontend/desktop/windows/winc/w32/utils.go index 8a72d4846..4568b4849 100644 --- a/v2/internal/frontend/desktop/windows/winc/w32/utils.go +++ b/v2/internal/frontend/desktop/windows/winc/w32/utils.go @@ -75,7 +75,7 @@ func UTF16PtrToString(cstr *uint16) string { } func ComAddRef(unknown *IUnknown) int32 { - ret, _, _ := syscall.Syscall(unknown.lpVtbl.pAddRef, 1, + ret, _, _ := syscall.SyscallN(unknown.lpVtbl.pAddRef, uintptr(unsafe.Pointer(unknown)), 0, 0) @@ -83,7 +83,7 @@ func ComAddRef(unknown *IUnknown) int32 { } func ComRelease(unknown *IUnknown) int32 { - ret, _, _ := syscall.Syscall(unknown.lpVtbl.pRelease, 1, + ret, _, _ := syscall.SyscallN(unknown.lpVtbl.pRelease, uintptr(unsafe.Pointer(unknown)), 0, 0) @@ -92,7 +92,7 @@ func ComRelease(unknown *IUnknown) int32 { func ComQueryInterface(unknown *IUnknown, id *GUID) *IDispatch { var disp *IDispatch - hr, _, _ := syscall.Syscall(unknown.lpVtbl.pQueryInterface, 3, + hr, _, _ := syscall.SyscallN(unknown.lpVtbl.pQueryInterface, uintptr(unsafe.Pointer(unknown)), uintptr(unsafe.Pointer(id)), uintptr(unsafe.Pointer(&disp))) diff --git a/v2/internal/frontend/desktop/windows/winc/w32/uxtheme.go b/v2/internal/frontend/desktop/windows/winc/w32/uxtheme.go index 51ec0035f..8a14f0cb7 100644 --- a/v2/internal/frontend/desktop/windows/winc/w32/uxtheme.go +++ b/v2/internal/frontend/desktop/windows/winc/w32/uxtheme.go @@ -69,7 +69,7 @@ var ( setWindowTheme uintptr ) -func init() { +func Init() { // Library libuxtheme = MustLoadLibrary("uxtheme.dll") @@ -83,7 +83,7 @@ func init() { } func CloseThemeData(hTheme HTHEME) HRESULT { - ret, _, _ := syscall.Syscall(closeThemeData, 1, + ret, _, _ := syscall.SyscallN(closeThemeData, uintptr(hTheme), 0, 0) @@ -134,7 +134,7 @@ func GetThemeTextExtent(hTheme HTHEME, hdc HDC, iPartId, iStateId int32, pszText } func OpenThemeData(hwnd HWND, pszClassList *uint16) HTHEME { - ret, _, _ := syscall.Syscall(openThemeData, 2, + ret, _, _ := syscall.SyscallN(openThemeData, uintptr(hwnd), uintptr(unsafe.Pointer(pszClassList)), 0) @@ -143,7 +143,7 @@ func OpenThemeData(hwnd HWND, pszClassList *uint16) HTHEME { } func SetWindowTheme(hwnd HWND, pszSubAppName, pszSubIdList *uint16) HRESULT { - ret, _, _ := syscall.Syscall(setWindowTheme, 3, + ret, _, _ := syscall.SyscallN(setWindowTheme, uintptr(hwnd), uintptr(unsafe.Pointer(pszSubAppName)), uintptr(unsafe.Pointer(pszSubIdList))) diff --git a/v2/internal/frontend/desktop/windows/winc/w32/wda.go b/v2/internal/frontend/desktop/windows/winc/w32/wda.go new file mode 100644 index 000000000..3925f2805 --- /dev/null +++ b/v2/internal/frontend/desktop/windows/winc/w32/wda.go @@ -0,0 +1,47 @@ +//go:build windows + +package w32 + +import ( + "syscall" + + "github.com/wailsapp/wails/v2/internal/system/operatingsystem" +) + +var user32 = syscall.NewLazyDLL("user32.dll") +var procSetWindowDisplayAffinity = user32.NewProc("SetWindowDisplayAffinity") +var windowsVersion, _ = operatingsystem.GetWindowsVersionInfo() + +const ( + WDA_NONE = 0x00000000 + WDA_MONITOR = 0x00000001 + WDA_EXCLUDEFROMCAPTURE = 0x00000011 // windows 10 2004+ +) + +func isWindowsVersionAtLeast(major, minor, build int) bool { + if windowsVersion.Major > major { + return true + } + if windowsVersion.Major < major { + return false + } + if windowsVersion.Minor > minor { + return true + } + if windowsVersion.Minor < minor { + return false + } + return windowsVersion.Build >= build +} + +func SetWindowDisplayAffinity(hwnd uintptr, affinity uint32) bool { + if affinity == WDA_EXCLUDEFROMCAPTURE && !isWindowsVersionAtLeast(10, 0, 19041) { + // for older windows versions, use WDA_MONITOR + affinity = WDA_MONITOR + } + ret, _, _ := procSetWindowDisplayAffinity.Call( + hwnd, + uintptr(affinity), + ) + return ret != 0 +} diff --git a/v2/internal/frontend/desktop/windows/window.go b/v2/internal/frontend/desktop/windows/window.go index a513e875a..b04d61814 100644 --- a/v2/internal/frontend/desktop/windows/window.go +++ b/v2/internal/frontend/desktop/windows/window.go @@ -3,10 +3,11 @@ package windows import ( - "github.com/wailsapp/go-webview2/pkg/edge" "sync" "unsafe" + "github.com/wailsapp/go-webview2/pkg/edge" + "github.com/wailsapp/wails/v2/internal/frontend/desktop/windows/win32" "github.com/wailsapp/wails/v2/internal/system/operatingsystem" @@ -37,6 +38,13 @@ type Window struct { OnResume func() chromium *edge.Chromium + + // isMinimizing indicates whether the window is currently being minimized + // 标识窗口是否处于最小化状态,用于解决最小化/恢复时的闪屏问题 + // This flag is used to prevent unnecessary redraws during minimize/restore transitions for frameless windows + // 此标志用于防止无边框窗口在最小化/恢复过程中的不必要重绘 + // Reference: https://github.com/wailsapp/wails/issues/3951 + isMinimizing bool } func NewWindow(parent winc.Controller, appoptions *options.App, versionInfo *operatingsystem.WindowsVersionInfo, chromium *edge.Chromium) *Window { @@ -70,8 +78,13 @@ func NewWindow(parent winc.Controller, appoptions *options.App, versionInfo *ope var dwStyle = w32.WS_OVERLAPPEDWINDOW - winc.RegClassOnlyOnce("wailsWindow") - handle := winc.CreateWindow("wailsWindow", parent, uint(exStyle), uint(dwStyle)) + windowClassName := "wailsWindow" + if windowsOptions != nil && windowsOptions.WindowClassName != "" { + windowClassName = windowsOptions.WindowClassName + } + + winc.RegClassOnlyOnce(windowClassName) + handle := winc.CreateWindow(windowClassName, parent, uint(exStyle), uint(dwStyle)) result.SetHandle(handle) winc.RegMsgHandler(result) result.SetParent(parent) @@ -118,6 +131,10 @@ func NewWindow(parent winc.Controller, appoptions *options.App, versionInfo *ope } } + if windowsOptions.ContentProtection { + w32.SetWindowDisplayAffinity(result.Handle(), w32.WDA_EXCLUDEFROMCAPTURE) + } + if windowsOptions.DisableWindowIcon { result.DisableIcon() } @@ -251,7 +268,7 @@ func (w *Window) WndProc(msg uint32, wparam, lparam uintptr) uintptr { rgrc := (*w32.RECT)(unsafe.Pointer(lparam)) if w.Form.IsFullScreen() { // In Full-Screen mode we don't need to adjust anything - w.chromium.SetPadding(edge.Rect{}) + w.SetPadding(edge.Rect{}) } else if w.IsMaximised() { // If the window is maximized we must adjust the client area to the work area of the monitor. Otherwise // some content goes beyond the visible part of the monitor. @@ -282,7 +299,7 @@ func (w *Window) WndProc(msg uint32, wparam, lparam uintptr) uintptr { } } } - w.chromium.SetPadding(edge.Rect{}) + w.SetPadding(edge.Rect{}) } else { // This is needed to workaround the resize flickering in frameless mode with WindowDecorations // See: https://stackoverflow.com/a/6558508 @@ -291,7 +308,7 @@ func (w *Window) WndProc(msg uint32, wparam, lparam uintptr) uintptr { // Increasing the bottom also worksaround the flickering but we would loose 1px of the WebView content // therefore let's pad the content with 1px at the bottom. rgrc.Bottom += 1 - w.chromium.SetPadding(edge.Rect{Bottom: 1}) + w.SetPadding(edge.Rect{Bottom: 1}) } return 0 } @@ -334,3 +351,17 @@ func invokeSync[T any](cba *Window, fn func() (T, error)) (res T, err error) { wg.Wait() return res, err } + +// SetPadding is a filter that wraps chromium.SetPadding to prevent unnecessary redraws during minimize/restore +// 包装了chromium.SetPadding的过滤器,用于防止窗口最小化/恢复过程中的不必要重绘 +// This fixes window flickering when minimizing/restoring frameless windows +// 这修复了无边框窗口在最小化/恢复时的闪烁问题 +// Reference: https://github.com/wailsapp/wails/issues/3951 +func (w *Window) SetPadding(padding edge.Rect) { + // Skip SetPadding if window is being minimized to prevent flickering + // 如果窗口正在最小化,跳过设置padding以防止闪烁 + if w.isMinimizing { + return + } + w.chromium.SetPadding(padding) +} diff --git a/v2/internal/frontend/devserver/devserver.go b/v2/internal/frontend/devserver/devserver.go index 3d623ed6d..8a130890d 100644 --- a/v2/internal/frontend/devserver/devserver.go +++ b/v2/internal/frontend/devserver/devserver.go @@ -20,17 +20,23 @@ import ( "github.com/wailsapp/wails/v2/internal/frontend/runtime" + "github.com/gorilla/websocket" "github.com/labstack/echo/v4" "github.com/wailsapp/wails/v2/internal/binding" "github.com/wailsapp/wails/v2/internal/frontend" "github.com/wailsapp/wails/v2/internal/logger" "github.com/wailsapp/wails/v2/internal/menumanager" "github.com/wailsapp/wails/v2/pkg/options" - "golang.org/x/net/websocket" ) type Screen = frontend.Screen +var upgrader = websocket.Upgrader{ + ReadBufferSize: 1024, + WriteBufferSize: 1024, + CheckOrigin: func(r *http.Request) bool { return true }, +} + type DevWebServer struct { server *echo.Echo ctx context.Context @@ -155,51 +161,64 @@ func (d *DevWebServer) handleReloadApp(c echo.Context) error { } func (d *DevWebServer) handleIPCWebSocket(c echo.Context) error { - websocket.Handler(func(c *websocket.Conn) { - d.LogDebug(fmt.Sprintf("Websocket client %p connected", c)) + conn, err := upgrader.Upgrade(c.Response(), c.Request(), nil) + if err != nil { + d.logger.Error("WebSocket upgrade failed %v", err) + return err + } + d.LogDebug(fmt.Sprintf("WebSocket client %p connected", conn)) + + d.socketMutex.Lock() + d.websocketClients[conn] = &sync.Mutex{} + locker := d.websocketClients[conn] + d.socketMutex.Unlock() + + var wg sync.WaitGroup + + defer func() { + wg.Wait() d.socketMutex.Lock() - d.websocketClients[c] = &sync.Mutex{} - locker := d.websocketClients[c] + delete(d.websocketClients, conn) d.socketMutex.Unlock() + d.LogDebug(fmt.Sprintf("WebSocket client %p disconnected", conn)) + conn.Close() + }() - defer func() { - d.socketMutex.Lock() - delete(d.websocketClients, c) - d.socketMutex.Unlock() - d.LogDebug(fmt.Sprintf("Websocket client %p disconnected", c)) - }() + for { + _, msgBytes, err := conn.ReadMessage() + if err != nil { + break + } - var msg string - defer c.Close() - for { - if err := websocket.Message.Receive(c, &msg); err != nil { - break - } - // We do not support drag in browsers - if msg == "drag" { - continue + msg := string(msgBytes) + wg.Add(1) + + go func(m string) { + defer wg.Done() + + if m == "drag" { + return } - // Notify the other browsers of "EventEmit" - if len(msg) > 2 && strings.HasPrefix(string(msg), "EE") { - d.notifyExcludingSender([]byte(msg), c) + if len(m) > 2 && strings.HasPrefix(m, "EE") { + d.notifyExcludingSender([]byte(m), conn) } - // Send the message to dispatch to the frontend - result, err := d.dispatcher.ProcessMessage(string(msg), d) + result, err := d.dispatcher.ProcessMessage(m, d) if err != nil { d.logger.Error(err.Error()) } + if result != "" { locker.Lock() - if err = websocket.Message.Send(c, result); err != nil { - locker.Unlock() - break + defer locker.Unlock() + if err := conn.WriteMessage(websocket.TextMessage, []byte(result)); err != nil { + d.logger.Error("Websocket write message failed %v", err) } - locker.Unlock() } - } - }).ServeHTTP(c.Response(), c.Request()) + }(msg) + } + return nil } @@ -222,7 +241,7 @@ func (d *DevWebServer) broadcast(message string) { return } locker.Lock() - err := websocket.Message.Send(client, message) + err := client.WriteMessage(websocket.TextMessage, []byte(message)) if err != nil { locker.Unlock() d.logger.Error(err.Error()) @@ -256,7 +275,7 @@ func (d *DevWebServer) broadcastExcludingSender(message string, sender *websocke return } locker.Lock() - err := websocket.Message.Send(client, message) + err := client.WriteMessage(websocket.TextMessage, []byte(message)) if err != nil { locker.Unlock() d.logger.Error(err.Error()) diff --git a/v2/internal/frontend/dispatcher/dispatcher.go b/v2/internal/frontend/dispatcher/dispatcher.go index 97d9b32e9..24a43cfef 100644 --- a/v2/internal/frontend/dispatcher/dispatcher.go +++ b/v2/internal/frontend/dispatcher/dispatcher.go @@ -2,6 +2,7 @@ package dispatcher import ( "context" + "fmt" "github.com/pkg/errors" "github.com/wailsapp/wails/v2/internal/binding" "github.com/wailsapp/wails/v2/internal/frontend" @@ -10,26 +11,43 @@ import ( ) type Dispatcher struct { - log *logger.Logger - bindings *binding.Bindings - events frontend.Events - bindingsDB *binding.DB - ctx context.Context - errfmt options.ErrorFormatter + log *logger.Logger + bindings *binding.Bindings + events frontend.Events + bindingsDB *binding.DB + ctx context.Context + errfmt options.ErrorFormatter + disablePanicRecovery bool } -func NewDispatcher(ctx context.Context, log *logger.Logger, bindings *binding.Bindings, events frontend.Events, errfmt options.ErrorFormatter) *Dispatcher { +func NewDispatcher(ctx context.Context, log *logger.Logger, bindings *binding.Bindings, events frontend.Events, errfmt options.ErrorFormatter, disablePanicRecovery bool) *Dispatcher { return &Dispatcher{ - log: log, - bindings: bindings, - events: events, - bindingsDB: bindings.DB(), - ctx: ctx, - errfmt: errfmt, + log: log, + bindings: bindings, + events: events, + bindingsDB: bindings.DB(), + ctx: ctx, + errfmt: errfmt, + disablePanicRecovery: disablePanicRecovery, } } -func (d *Dispatcher) ProcessMessage(message string, sender frontend.Frontend) (string, error) { +func (d *Dispatcher) ProcessMessage(message string, sender frontend.Frontend) (_ string, err error) { + if !d.disablePanicRecovery { + defer func() { + if e := recover(); e != nil { + if errPanic, ok := e.(error); ok { + err = errPanic + } else { + err = fmt.Errorf("%v", e) + } + } + if err != nil { + d.log.Error("process message error: %s -> %s", message, err) + } + }() + } + if message == "" { return "", errors.New("No message to process") } diff --git a/v2/internal/frontend/originvalidator/originValidator.go b/v2/internal/frontend/originvalidator/originValidator.go new file mode 100644 index 000000000..fd416f945 --- /dev/null +++ b/v2/internal/frontend/originvalidator/originValidator.go @@ -0,0 +1,116 @@ +package originvalidator + +import ( + "fmt" + "net/url" + "regexp" + "strings" +) + +type OriginValidator struct { + allowedOrigins []string +} + +// NewOriginValidator creates a new validator from a comma-separated string of allowed origins +func NewOriginValidator(startUrl *url.URL, allowedOriginsString string) *OriginValidator { + allowedOrigins := startUrl.Scheme + "://" + startUrl.Host + if allowedOriginsString != "" { + allowedOrigins += "," + allowedOriginsString + } + validator := &OriginValidator{} + validator.parseAllowedOrigins(allowedOrigins) + return validator +} + +// parseAllowedOrigins parses the comma-separated origins string +func (v *OriginValidator) parseAllowedOrigins(originsString string) { + if originsString == "" { + v.allowedOrigins = []string{} + return + } + + origins := strings.Split(originsString, ",") + var trimmedOrigins []string + + for _, origin := range origins { + trimmed := strings.TrimSuffix(strings.TrimSpace(origin), "/") + if trimmed != "" { + trimmedOrigins = append(trimmedOrigins, trimmed) + } + } + + v.allowedOrigins = trimmedOrigins +} + +// IsOriginAllowed checks if the given origin is allowed +func (v *OriginValidator) IsOriginAllowed(origin string) bool { + if origin == "" { + return false + } + + for _, allowedOrigin := range v.allowedOrigins { + if v.matchesOriginPattern(allowedOrigin, origin) { + return true + } + } + + return false +} + +// matchesOriginPattern checks if origin matches the pattern (supports wildcards) +func (v *OriginValidator) matchesOriginPattern(pattern, origin string) bool { + // Exact match + if pattern == origin { + return true + } + + // Wildcard pattern matching + if strings.Contains(pattern, "*") { + regexPattern := v.wildcardPatternToRegex(pattern) + matched, err := regexp.MatchString(regexPattern, origin) + if err != nil { + return false + } + return matched + } + + return false +} + +// wildcardPatternToRegex converts wildcard pattern to regex +func (v *OriginValidator) wildcardPatternToRegex(wildcardPattern string) string { + // Escape special regex characters except * + specialChars := []string{"\\", ".", "+", "?", "^", "$", "{", "}", "(", ")", "|", "[", "]"} + + escaped := wildcardPattern + for _, specialChar := range specialChars { + escaped = strings.ReplaceAll(escaped, specialChar, "\\"+specialChar) + } + + // Replace * with .* (matches any characters) + escaped = strings.ReplaceAll(escaped, "*", ".*") + + // Anchor the pattern to match the entire string + return "^" + escaped + "$" +} + +// GetOriginFromURL extracts origin from URL string +func (v *OriginValidator) GetOriginFromURL(urlString string) (string, error) { + if urlString == "" { + return "", fmt.Errorf("empty URL") + } + + parsedURL, err := url.Parse(urlString) + if err != nil { + return "", fmt.Errorf("invalid URL: %v", err) + } + + if parsedURL.Scheme == "" || parsedURL.Host == "" { + return "", fmt.Errorf("URL missing scheme or host") + } + + // Build origin (scheme + host) + origin := parsedURL.Scheme + "://" + parsedURL.Host + + return origin, nil +} diff --git a/v2/internal/frontend/runtime/desktop/draganddrop.js b/v2/internal/frontend/runtime/desktop/draganddrop.js index 143b4228e..e470e4823 100644 --- a/v2/internal/frontend/runtime/desktop/draganddrop.js +++ b/v2/internal/frontend/runtime/desktop/draganddrop.js @@ -44,14 +44,27 @@ function checkStyleDropTarget(style) { /** * onDragOver is called when the dragover event is emitted. - * @param {DragEvent} e - * @returns + * @param {DragEvent} e + * @returns */ function onDragOver(e) { + // Check if this is an external file drop or internal HTML drag + // External file drops will have "Files" in the types array + // Internal HTML drags typically have "text/plain", "text/html" or custom types + const isFileDrop = e.dataTransfer.types.includes("Files"); + + // Only handle external file drops, let internal HTML5 drag-and-drop work normally + if (!isFileDrop) { + return; + } + + // ALWAYS prevent default for file drops to stop browser navigation + e.preventDefault(); + e.dataTransfer.dropEffect = 'copy'; + if (!window.wails.flags.enableWailsDragAndDrop) { return; } - e.preventDefault(); if (!flags.useDropTarget) { return; @@ -70,7 +83,7 @@ function onDragOver(e) { let currentElement = element; while (currentElement) { // check if currentElement is drop target element - if (checkStyleDropTarget(currentElement.style)) { + if (checkStyleDropTarget(getComputedStyle(currentElement))) { currentElement.classList.add(DROP_TARGET_ACTIVE); } currentElement = currentElement.parentElement; @@ -79,14 +92,24 @@ function onDragOver(e) { /** * onDragLeave is called when the dragleave event is emitted. - * @param {DragEvent} e - * @returns + * @param {DragEvent} e + * @returns */ function onDragLeave(e) { + // Check if this is an external file drop or internal HTML drag + const isFileDrop = e.dataTransfer.types.includes("Files"); + + // Only handle external file drops, let internal HTML5 drag-and-drop work normally + if (!isFileDrop) { + return; + } + + // ALWAYS prevent default for file drops to stop browser navigation + e.preventDefault(); + if (!window.wails.flags.enableWailsDragAndDrop) { return; } - e.preventDefault(); if (!flags.useDropTarget) { return; @@ -121,24 +144,24 @@ function onDragLeave(e) { /** * onDrop is called when the drop event is emitted. - * @param {DragEvent} e - * @returns + * @param {DragEvent} e + * @returns */ function onDrop(e) { + // Check if this is an external file drop or internal HTML drag + const isFileDrop = e.dataTransfer.types.includes("Files"); + + // Only handle external file drops, let internal HTML5 drag-and-drop work normally + if (!isFileDrop) { + return; + } + + // ALWAYS prevent default for file drops to stop browser navigation + e.preventDefault(); + if (!window.wails.flags.enableWailsDragAndDrop) { return; } - e.preventDefault(); - - if (!flags.useDropTarget) { - return; - } - - // Trigger debounce function to deactivate drop targets - if(flags.nextDeactivate) flags.nextDeactivate(); - - // Deactivate all drop targets - Array.from(document.getElementsByClassName(DROP_TARGET_ACTIVE)).forEach(el => el.classList.remove(DROP_TARGET_ACTIVE)); if (CanResolveFilePaths()) { // process files @@ -154,6 +177,16 @@ function onDrop(e) { } window.runtime.ResolveFilePaths(e.x, e.y, files); } + + if (!flags.useDropTarget) { + return; + } + + // Trigger debounce function to deactivate drop targets + if(flags.nextDeactivate) flags.nextDeactivate(); + + // Deactivate all drop targets + Array.from(document.getElementsByClassName(DROP_TARGET_ACTIVE)).forEach(el => el.classList.remove(DROP_TARGET_ACTIVE)); } /** diff --git a/v2/internal/frontend/runtime/desktop/events.js b/v2/internal/frontend/runtime/desktop/events.js index 9548cbc34..e665a8aff 100644 --- a/v2/internal/frontend/runtime/desktop/events.js +++ b/v2/internal/frontend/runtime/desktop/events.js @@ -90,17 +90,17 @@ function notifyListeners(eventData) { // Get the event name let eventName = eventData.name; - // Check if we have any listeners for this event - if (eventListeners[eventName]) { + // Keep a list of listener indexes to destroy + const newEventListenerList = eventListeners[eventName]?.slice() || []; - // Keep a list of listener indexes to destroy - const newEventListenerList = eventListeners[eventName].slice(); + // Check if we have any listeners for this event + if (newEventListenerList.length) { // Iterate listeners - for (let count = eventListeners[eventName].length - 1; count >= 0; count -= 1) { + for (let count = newEventListenerList.length - 1; count >= 0; count -= 1) { // Get next listener - const listener = eventListeners[eventName][count]; + const listener = newEventListenerList[count]; let data = eventData.data; @@ -190,9 +190,9 @@ export function EventsOff(eventName, ...additionalEventNames) { */ export function EventsOffAll() { const eventNames = Object.keys(eventListeners); - for (let i = 0; i !== eventNames.length; i++) { - removeListener(eventNames[i]); - } + eventNames.forEach(eventName => { + removeListener(eventName) + }) } /** @@ -202,6 +202,8 @@ export function EventsOff(eventName, ...additionalEventNames) { */ function listenerOff(listener) { const eventName = listener.eventName; + if (eventListeners[eventName] === undefined) return; + // Remove local listener eventListeners[eventName] = eventListeners[eventName].filter(l => l !== listener); diff --git a/v2/internal/frontend/runtime/desktop/main.js b/v2/internal/frontend/runtime/desktop/main.js index ae31744cc..3fda7ef36 100644 --- a/v2/internal/frontend/runtime/desktop/main.js +++ b/v2/internal/frontend/runtime/desktop/main.js @@ -9,9 +9,18 @@ The electron alternative for Go */ /* jshint esversion: 9 */ import * as Log from './log'; -import {eventListeners, EventsEmit, EventsNotify, EventsOff, EventsOn, EventsOnce, EventsOnMultiple} from './events'; -import {Call, Callback, callbacks} from './calls'; -import {SetBindings} from "./bindings"; +import { + eventListeners, + EventsEmit, + EventsNotify, + EventsOff, + EventsOffAll, + EventsOn, + EventsOnce, + EventsOnMultiple, +} from "./events"; +import { Call, Callback, callbacks } from './calls'; +import { SetBindings } from "./bindings"; import * as Window from "./window"; import * as Screen from "./screen"; import * as Browser from "./browser"; @@ -48,6 +57,7 @@ window.runtime = { EventsOnMultiple, EventsEmit, EventsOff, + EventsOffAll, Environment, Show, Hide, @@ -88,12 +98,12 @@ if (!DEBUG) { delete window.wailsbindings; } -let dragTest = function (e) { +let dragTest = function(e) { var val = window.getComputedStyle(e.target).getPropertyValue(window.wails.flags.cssDragProperty); if (val) { - val = val.trim(); + val = val.trim(); } - + if (val !== window.wails.flags.cssDragValue) { return false; } @@ -111,12 +121,12 @@ let dragTest = function (e) { return true; }; -window.wails.setCSSDragProperties = function (property, value) { +window.wails.setCSSDragProperties = function(property, value) { window.wails.flags.cssDragProperty = property; window.wails.flags.cssDragValue = value; } -window.wails.setCSSDropProperties = function (property, value) { +window.wails.setCSSDropProperties = function(property, value) { window.wails.flags.cssDropProperty = property; window.wails.flags.cssDropValue = value; } @@ -157,7 +167,7 @@ function setResize(cursor) { window.wails.flags.resizeEdge = cursor; } -window.addEventListener('mousemove', function (e) { +window.addEventListener('mousemove', function(e) { if (window.wails.flags.shouldDrag) { window.wails.flags.shouldDrag = false; let mousePressed = e.buttons !== undefined ? e.buttons : e.which; @@ -195,7 +205,7 @@ window.addEventListener('mousemove', function (e) { }); // Setup context menu hook -window.addEventListener('contextmenu', function (e) { +window.addEventListener('contextmenu', function(e) { // always show the contextmenu in debug & dev if (DEBUG) return; diff --git a/v2/internal/frontend/runtime/ipc_websocket.js b/v2/internal/frontend/runtime/ipc_websocket.js index a0d6b4a70..1ca048df1 100644 --- a/v2/internal/frontend/runtime/ipc_websocket.js +++ b/v2/internal/frontend/runtime/ipc_websocket.js @@ -1,9 +1,9 @@ (()=>{function D(t){console.log("%c wails dev %c "+t+" ","background: #aa0000; color: #fff; border-radius: 3px 0px 0px 3px; padding: 1px; font-size: 0.7rem","background: #009900; color: #fff; border-radius: 0px 3px 3px 0px; padding: 1px; font-size: 0.7rem")}function _(){}var A=t=>t;function N(t){return t()}function it(){return Object.create(null)}function b(t){t.forEach(N)}function w(t){return typeof t=="function"}function L(t,e){return t!=t?e==e:t!==e||t&&typeof t=="object"||typeof t=="function"}function ot(t){return Object.keys(t).length===0}function rt(t,...e){if(t==null)return _;let n=t.subscribe(...e);return n.unsubscribe?()=>n.unsubscribe():n}function st(t,e,n){t.$$.on_destroy.push(rt(e,n))}var ct=typeof window!="undefined",Ot=ct?()=>window.performance.now():()=>Date.now(),P=ct?t=>requestAnimationFrame(t):_;var x=new Set;function lt(t){x.forEach(e=>{e.c(t)||(x.delete(e),e.f())}),x.size!==0&&P(lt)}function Dt(t){let e;return x.size===0&&P(lt),{promise:new Promise(n=>{x.add(e={c:t,f:n})}),abort(){x.delete(e)}}}var ut=!1;function At(){ut=!0}function Lt(){ut=!1}function Bt(t,e){t.appendChild(e)}function at(t,e,n){let i=R(t);if(!i.getElementById(e)){let o=B("style");o.id=e,o.textContent=n,ft(i,o)}}function R(t){if(!t)return document;let e=t.getRootNode?t.getRootNode():t.ownerDocument;return e&&e.host?e:t.ownerDocument}function Tt(t){let e=B("style");return ft(R(t),e),e.sheet}function ft(t,e){return Bt(t.head||t,e),e.sheet}function W(t,e,n){t.insertBefore(e,n||null)}function S(t){t.parentNode.removeChild(t)}function B(t){return document.createElement(t)}function Jt(t){return document.createTextNode(t)}function dt(){return Jt("")}function ht(t,e,n){n==null?t.removeAttribute(e):t.getAttribute(e)!==n&&t.setAttribute(e,n)}function zt(t){return Array.from(t.childNodes)}function Ht(t,e,{bubbles:n=!1,cancelable:i=!1}={}){let o=document.createEvent("CustomEvent");return o.initCustomEvent(t,n,i,e),o}var T=new Map,J=0;function Gt(t){let e=5381,n=t.length;for(;n--;)e=(e<<5)-e^t.charCodeAt(n);return e>>>0}function qt(t,e){let n={stylesheet:Tt(e),rules:{}};return T.set(t,n),n}function pt(t,e,n,i,o,c,s,l=0){let f=16.666/i,r=`{ `;for(let g=0;g<=1;g+=f){let F=e+(n-e)*c(g);r+=g*100+`%{${s(F,1-F)}} `}let y=r+`100% {${s(n,1-n)}} -}`,a=`__svelte_${Gt(y)}_${l}`,u=R(t),{stylesheet:h,rules:p}=T.get(u)||qt(u,t);p[a]||(p[a]=!0,h.insertRule(`@keyframes ${a} ${y}`,h.cssRules.length));let v=t.style.animation||"";return t.style.animation=`${v?`${v}, `:""}${a} ${i}ms linear ${o}ms 1 both`,J+=1,a}function Kt(t,e){let n=(t.style.animation||"").split(", "),i=n.filter(e?c=>c.indexOf(e)<0:c=>c.indexOf("__svelte")===-1),o=n.length-i.length;o&&(t.style.animation=i.join(", "),J-=o,J||Nt())}function Nt(){P(()=>{J||(T.forEach(t=>{let{ownerNode:e}=t.stylesheet;e&&S(e)}),T.clear())})}var V;function C(t){V=t}var k=[];var _t=[],z=[],mt=[],Pt=Promise.resolve(),U=!1;function Rt(){U||(U=!0,Pt.then(yt))}function $(t){z.push(t)}var X=new Set,H=0;function yt(){let t=V;do{for(;H{E=null})),E}function Z(t,e,n){t.dispatchEvent(Ht(`${e?"intro":"outro"}${n}`))}var G=new Set,m;function gt(){m={r:0,c:[],p:m}}function bt(){m.r||b(m.c),m=m.p}function I(t,e){t&&t.i&&(G.delete(t),t.i(e))}function Q(t,e,n,i){if(t&&t.o){if(G.has(t))return;G.add(t),m.c.push(()=>{G.delete(t),i&&(n&&t.d(1),i())}),t.o(e)}else i&&i()}var Ut={duration:0};function Y(t,e,n,i){let o=e(t,n),c=i?0:1,s=null,l=null,f=null;function r(){f&&Kt(t,f)}function y(u,h){let p=u.b-c;return h*=Math.abs(p),{a:c,b:u.b,d:p,duration:h,start:u.start,end:u.start+h,group:u.group}}function a(u){let{delay:h=0,duration:p=300,easing:v=A,tick:g=_,css:F}=o||Ut,K={start:Ot()+h,b:u};u||(K.group=m,m.r+=1),s||l?l=K:(F&&(r(),f=pt(t,c,u,p,h,v,F)),u&&g(0,1),s=y(K,p),$(()=>Z(t,u,"start")),Dt(O=>{if(l&&O>l.start&&(s=y(l,p),l=null,Z(t,s.b,"start"),F&&(r(),f=pt(t,c,s.b,s.duration,0,v,o.css))),s){if(O>=s.end)g(c=s.b,1-c),Z(t,s.b,"end"),l||(s.b?r():--s.group.r||b(s.group.c)),s=null;else if(O>=s.start){let jt=O-s.start;c=s.a+s.d*v(jt/s.duration),g(c,1-c)}}return!!(s||l)}))}return{run(u){w(o)?Vt().then(()=>{o=o(),a(u)}):a(u)},end(){r(),s=l=null}}}var le=typeof window!="undefined"?window:typeof globalThis!="undefined"?globalThis:global;var ue=new Set(["allowfullscreen","allowpaymentrequest","async","autofocus","autoplay","checked","controls","default","defer","disabled","formnovalidate","hidden","inert","ismap","itemscope","loop","multiple","muted","nomodule","novalidate","open","playsinline","readonly","required","reversed","selected"]);function Xt(t,e,n,i){let{fragment:o,after_update:c}=t.$$;o&&o.m(e,n),i||$(()=>{let s=t.$$.on_mount.map(N).filter(w);t.$$.on_destroy?t.$$.on_destroy.push(...s):b(s),t.$$.on_mount=[]}),c.forEach($)}function wt(t,e){let n=t.$$;n.fragment!==null&&(b(n.on_destroy),n.fragment&&n.fragment.d(e),n.on_destroy=n.fragment=null,n.ctx=[])}function Zt(t,e){t.$$.dirty[0]===-1&&(k.push(t),Rt(),t.$$.dirty.fill(0)),t.$$.dirty[e/31|0]|=1<{let p=h.length?h[0]:u;return r.ctx&&o(r.ctx[a],r.ctx[a]=p)&&(!r.skip_bound&&r.bound[a]&&r.bound[a](p),y&&Zt(t,a)),u}):[],r.update(),y=!0,b(r.before_update),r.fragment=i?i(r.ctx):!1,e.target){if(e.hydrate){At();let a=zt(e.target);r.fragment&&r.fragment.l(a),a.forEach(S)}else r.fragment&&r.fragment.c();e.intro&&I(t.$$.fragment),Xt(t,e.target,e.anchor,e.customElement),Lt(),yt()}C(f)}var Qt;typeof HTMLElement=="function"&&(Qt=class extends HTMLElement{constructor(){super();this.attachShadow({mode:"open"})}connectedCallback(){let{on_mount:t}=this.$$;this.$$.on_disconnect=t.map(N).filter(w);for(let e in this.$$.slotted)this.appendChild(this.$$.slotted[e])}attributeChangedCallback(t,e,n){this[t]=n}disconnectedCallback(){b(this.$$.on_disconnect)}$destroy(){wt(this,1),this.$destroy=_}$on(t,e){if(!w(e))return _;let n=this.$$.callbacks[t]||(this.$$.callbacks[t]=[]);return n.push(e),()=>{let i=n.indexOf(e);i!==-1&&n.splice(i,1)}}$set(t){this.$$set&&!ot(t)&&(this.$$.skip_bound=!0,this.$$set(t),this.$$.skip_bound=!1)}});var tt=class{$destroy(){wt(this,1),this.$destroy=_}$on(e,n){if(!w(n))return _;let i=this.$$.callbacks[e]||(this.$$.callbacks[e]=[]);return i.push(n),()=>{let o=i.indexOf(n);o!==-1&&i.splice(o,1)}}$set(e){this.$$set&&!ot(e)&&(this.$$.skip_bound=!0,this.$$set(e),this.$$.skip_bound=!1)}};var M=[];function Ft(t,e=_){let n,i=new Set;function o(l){if(L(t,l)&&(t=l,n)){let f=!M.length;for(let r of i)r[1](),M.push(r,t);if(f){for(let r=0;r{i.delete(r),i.size===0&&(n(),n=null)}}return{set:o,update:c,subscribe:s}}var q=Ft(!1);function xt(){q.set(!0)}function $t(){q.set(!1)}function et(t,{delay:e=0,duration:n=400,easing:i=A}={}){let o=+getComputedStyle(t).opacity;return{delay:e,duration:n,easing:i,css:c=>`opacity: ${c*o}`}}function Yt(t){at(t,"svelte-181h7z",`.wails-reconnect-overlay.svelte-181h7z{position:fixed;top:0;left:0;width:100%;height:100%;backdrop-filter:blur(2px) saturate(0%) contrast(50%) brightness(25%);z-index:999999 - }.wails-reconnect-overlay-content.svelte-181h7z{position:relative;top:50%;transform:translateY(-50%);margin:0;background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEsAAAA7CAMAAAAEsocZAAAC91BMVEUAAACzQ0PjMjLkMjLZLS7XLS+vJCjkMjKlEx6uGyHjMDGiFx7GJyrAISjUKy3mMzPlMjLjMzOsGyDKJirkMjK6HyXmMjLgMDC6IiLcMjLULC3MJyrRKSy+IibmMzPmMjK7ISXlMjLIJimzHSLkMjKtGiHZLC7BIifgMDCpGSDFIivcLy+yHSKoGR+eFBzNKCvlMjKxHSPkMTKxHSLmMjLKJyq5ICXDJCe6ISXdLzDkMjLmMzPFJSm2HyTlMTLhMDGyHSKUEBmhFx24HyTCJCjHJijjMzOiFh7mMjJ6BhDaLDCuGyOKABjnMzPGJinJJiquHCGEChSmGB/pMzOiFh7VKy3OKCu1HiSvHCLjMTLMKCrBIyeICxWxHCLDIyjSKizBIyh+CBO9ISa6ISWDChS9Iie1HyXVLC7FJSrLKCrlMjLiMTGPDhicFRywGyKXFBuhFx1/BxO7IiXkMTGeFBx8BxLkMTGnGR/GJCi4ICWsGyGJDxXSLS2yGiHSKi3CJCfnMzPQKiyECRTKJiq6ISWUERq/Iye0HiPDJCjGJSm6ICaPDxiTEBrdLy+3HyXSKiy0HyOQEBi4ICWhFh1+CBO9IieODhfSKyzWLC2LDhh8BxHKKCq7ISWaFBzkMzPqNDTTLC3EJSiHDBacExyvGyO1HyTPKCy+IieoGSC7ISaVEhrMKCvQKyusGyG0HiKACBPIJSq/JCaABxR5BRLEJCnkMzPJJinEJimPDRZ2BRKqHx/jMjLnMzPgMDHULC3NKSvQKSzsNDTWLS7SKyy3HyTKJyrDJSjbLzDYLC6mGB/GJSnVLC61HiPLKCrHJSm/Iye8Iia6ICWzHSKxHCLaLi/PKSupGR+7ICXpMzPbLi/IJinJJSmsGyGrGiCkFx6PDheJCxaFChXBIyfAIieSDxmBCBPlMjLeLzDdLzC5HySMDRe+ISWvGyGcFBzSKSzPJyvMJyrEJCjDIyefFRyWERriMDHUKiy/ISaZExv0NjbwNTXuNDTrMzMI0c+yAAAAu3RSTlMAA8HR/gwGgAj+MEpGCsC+hGpjQjYnIxgWBfzx7urizMrFqqB1bF83KhsR/fz8+/r5+fXv7unZ1tC+t6mmopqKdW1nYVpVRjUeHhIQBPr59/b28/Hx8ODg3NvUw8O/vKeim5aNioiDgn1vZWNjX1xUU1JPTUVFPT08Mi4qJyIh/Pv7+/n4+Pf39fT08/Du7efn5uXj4uHa19XNwsG/vrq2tbSuramlnpyYkpGNiIZ+enRraGVjVVBKOzghdjzRsAAABJVJREFUWMPtllVQG1EYhTc0ASpoobS0FCulUHd3oUjd3d3d3d3d3d2b7CYhnkBCCHGDEIK7Vh56d0NpOgwkYfLQzvA9ZrLfnPvfc+8uVEst/yheBJup3Nya2MjU6pa/jWLZtxjXpZFtVB4uVNI6m5gIruNkVFebqIb5Ug2ym4TIEM/gtUOGbg613oBzjAzZFrZ+lXu/3TIiMXXS5M6HTvrNHeLpZLEh6suGNW9fzZ9zd/qVi2eOHygqi5cDE5GUrJocONgzyqo0UXNSUlKSEhMztFqtXq9vNxImAmS3g7Y6QlbjdBWVGW36jt4wDGTUXjUsafh5zJWRkdFuZGtWGnCRmg+HasiGMUClTTzW0ZuVgLlGDIPM4Lhi0IrVq+tv2hS21fNrSONQgpM9DsJ4t3fM9PkvJuKj2ZjrZwvILKvaSTgciUSirjt6dOfOpyd169bDb9rMOwF9Hj4OD100gY0YXYb299bjzMrqj9doNByJWlVXFB9DT5dmJuvy+cq83JyuS6ayEYSHulKL8dmFnBkrCeZlHKMrC5XRhXGCZB2Ty1fkleRQaMCFT2DBsEafzRFJu7/2MicbKynPhQUDLiZwMWLJZKNLzoLbJBYVcurSmbmn+rcyJ8vCMgmlmaW6gnwun/+3C96VpAUuET1ZgRR36r2xWlnYSnf3oKABA14uXDDvydxHs6cpTV1p3hlJ2rJCiUjIZCByItXg8sHJijuvT64CuMTABUYvb6NN1Jdp1PH7D7f3bo2eS5KvW4RJr7atWT5w4MBBg9zdBw9+37BS7QIoFS5WnIaj12dr1DEXFgdvr4fh4eFl+u/wz8uf3jjHic8s4DL2Dal0IANyUBeCRCcwOBJV26JsjSpGwHVuSai69jvqD+jr56OgtKy0zAAK5mLTVBKVKL5tNthGAR9JneJQ/bFsHNzy+U7IlCYROxtMpIjR0ceoQVnowracLLpAQWETqV361bPoFo3cEbz2zYLZM7t3HWXcxmiBOgttS1ycWkTXMWh4mGigdug9DFdttqCFgTN6nD0q1XEVSoCxEjyFCi2eNC6Z69MRVIImJ6JQSf5gcFVCuF+aDhCa1F6MJFDaiNBQAh2TMfWBjhmLsAxUjG/fmjs0qjJck8D0GPBcuUuZW1LS/tIsPzqmQt17PvZQknlwnf4tHDBc+7t5VV3QQCkdc+Ur8/hdrz0but0RCumWiYbiKmLJ7EVbRomj4Q7+y5wsaXvfTGFpQcHB7n2WbG4MGdniw2Tm8xl5Yhr7MrSYHQ3uampz10aWyHyuzxvqaW/6W4MjXAUD3QV2aw97ZxhGjxCohYf5TpTHMXU1BbsAuoFnkRygVieIGAbqiF7rrH4rfWpKJouBCtyHJF8ctEyGubBa+C6NsMYEUonJFITHZqWBxXUA12Dv76Tf/PgOBmeNiiLG1pcKo1HAq8jLpY4JU1yWEixVNaOgoRJAKBSZHTZTU+wJOMtUDZvlVITC6FTlksyrEBoPHXpxxbzdaqzigUtVDkJVIOtVQ9UEOR4VGUh/kHWq0edJ6CxnZ+eePXva2bnY/cF/I1RLLf8vvwDANdMSMegxcAAAAABJRU5ErkJggg==);background-repeat:no-repeat;background-position:center - }.wails-reconnect-overlay-loadingspinner.svelte-181h7z{pointer-events:none;width:2.5em;height:2.5em;border:.4em solid transparent;border-color:#f00 #eee0 #f00 #eee0;border-radius:50%;animation:svelte-181h7z-loadingspin 1s linear infinite;margin:auto;padding:2.5em +}`,a=`__svelte_${Gt(y)}_${l}`,u=R(t),{stylesheet:h,rules:p}=T.get(u)||qt(u,t);p[a]||(p[a]=!0,h.insertRule(`@keyframes ${a} ${y}`,h.cssRules.length));let v=t.style.animation||"";return t.style.animation=`${v?`${v}, `:""}${a} ${i}ms linear ${o}ms 1 both`,J+=1,a}function Kt(t,e){let n=(t.style.animation||"").split(", "),i=n.filter(e?c=>c.indexOf(e)<0:c=>c.indexOf("__svelte")===-1),o=n.length-i.length;o&&(t.style.animation=i.join(", "),J-=o,J||Nt())}function Nt(){P(()=>{J||(T.forEach(t=>{let{ownerNode:e}=t.stylesheet;e&&S(e)}),T.clear())})}var V;function C(t){V=t}var k=[];var _t=[],z=[],mt=[],Pt=Promise.resolve(),U=!1;function Rt(){U||(U=!0,Pt.then(yt))}function $(t){z.push(t)}var X=new Set,H=0;function yt(){let t=V;do{for(;H{E=null})),E}function Z(t,e,n){t.dispatchEvent(Ht(`${e?"intro":"outro"}${n}`))}var G=new Set,m;function gt(){m={r:0,c:[],p:m}}function bt(){m.r||b(m.c),m=m.p}function I(t,e){t&&t.i&&(G.delete(t),t.i(e))}function Q(t,e,n,i){if(t&&t.o){if(G.has(t))return;G.add(t),m.c.push(()=>{G.delete(t),i&&(n&&t.d(1),i())}),t.o(e)}else i&&i()}var Ut={duration:0};function Y(t,e,n,i){let o=e(t,n),c=i?0:1,s=null,l=null,f=null;function r(){f&&Kt(t,f)}function y(u,h){let p=u.b-c;return h*=Math.abs(p),{a:c,b:u.b,d:p,duration:h,start:u.start,end:u.start+h,group:u.group}}function a(u){let{delay:h=0,duration:p=300,easing:v=A,tick:g=_,css:F}=o||Ut,K={start:Ot()+h,b:u};u||(K.group=m,m.r+=1),s||l?l=K:(F&&(r(),f=pt(t,c,u,p,h,v,F)),u&&g(0,1),s=y(K,p),$(()=>Z(t,u,"start")),Dt(O=>{if(l&&O>l.start&&(s=y(l,p),l=null,Z(t,s.b,"start"),F&&(r(),f=pt(t,c,s.b,s.duration,0,v,o.css))),s){if(O>=s.end)g(c=s.b,1-c),Z(t,s.b,"end"),l||(s.b?r():--s.group.r||b(s.group.c)),s=null;else if(O>=s.start){let jt=O-s.start;c=s.a+s.d*v(jt/s.duration),g(c,1-c)}}return!!(s||l)}))}return{run(u){w(o)?Vt().then(()=>{o=o(),a(u)}):a(u)},end(){r(),s=l=null}}}var le=typeof window!="undefined"?window:typeof globalThis!="undefined"?globalThis:global;var ue=new Set(["allowfullscreen","allowpaymentrequest","async","autofocus","autoplay","checked","controls","default","defer","disabled","formnovalidate","hidden","inert","ismap","itemscope","loop","multiple","muted","nomodule","novalidate","open","playsinline","readonly","required","reversed","selected"]);function Xt(t,e,n,i){let{fragment:o,after_update:c}=t.$$;o&&o.m(e,n),i||$(()=>{let s=t.$$.on_mount.map(N).filter(w);t.$$.on_destroy?t.$$.on_destroy.push(...s):b(s),t.$$.on_mount=[]}),c.forEach($)}function wt(t,e){let n=t.$$;n.fragment!==null&&(b(n.on_destroy),n.fragment&&n.fragment.d(e),n.on_destroy=n.fragment=null,n.ctx=[])}function Zt(t,e){t.$$.dirty[0]===-1&&(k.push(t),Rt(),t.$$.dirty.fill(0)),t.$$.dirty[e/31|0]|=1<{let p=h.length?h[0]:u;return r.ctx&&o(r.ctx[a],r.ctx[a]=p)&&(!r.skip_bound&&r.bound[a]&&r.bound[a](p),y&&Zt(t,a)),u}):[],r.update(),y=!0,b(r.before_update),r.fragment=i?i(r.ctx):!1,e.target){if(e.hydrate){At();let a=zt(e.target);r.fragment&&r.fragment.l(a),a.forEach(S)}else r.fragment&&r.fragment.c();e.intro&&I(t.$$.fragment),Xt(t,e.target,e.anchor,e.customElement),Lt(),yt()}C(f)}var Qt;typeof HTMLElement=="function"&&(Qt=class extends HTMLElement{constructor(){super();this.attachShadow({mode:"open"})}connectedCallback(){let{on_mount:t}=this.$$;this.$$.on_disconnect=t.map(N).filter(w);for(let e in this.$$.slotted)this.appendChild(this.$$.slotted[e])}attributeChangedCallback(t,e,n){this[t]=n}disconnectedCallback(){b(this.$$.on_disconnect)}$destroy(){wt(this,1),this.$destroy=_}$on(t,e){if(!w(e))return _;let n=this.$$.callbacks[t]||(this.$$.callbacks[t]=[]);return n.push(e),()=>{let i=n.indexOf(e);i!==-1&&n.splice(i,1)}}$set(t){this.$$set&&!ot(t)&&(this.$$.skip_bound=!0,this.$$set(t),this.$$.skip_bound=!1)}});var tt=class{$destroy(){wt(this,1),this.$destroy=_}$on(e,n){if(!w(n))return _;let i=this.$$.callbacks[e]||(this.$$.callbacks[e]=[]);return i.push(n),()=>{let o=i.indexOf(n);o!==-1&&i.splice(o,1)}}$set(e){this.$$set&&!ot(e)&&(this.$$.skip_bound=!0,this.$$set(e),this.$$.skip_bound=!1)}};var M=[];function Ft(t,e=_){let n,i=new Set;function o(l){if(L(t,l)&&(t=l,n)){let f=!M.length;for(let r of i)r[1](),M.push(r,t);if(f){for(let r=0;r{i.delete(r),i.size===0&&(n(),n=null)}}return{set:o,update:c,subscribe:s}}var q=Ft(!1);function xt(){q.set(!0)}function $t(){q.set(!1)}function et(t,{delay:e=0,duration:n=400,easing:i=A}={}){let o=+getComputedStyle(t).opacity;return{delay:e,duration:n,easing:i,css:c=>`opacity: ${c*o}`}}function Yt(t){at(t,"svelte-181h7z",`.wails-reconnect-overlay.svelte-181h7z{position:fixed;top:0;left:0;width:100%;height:100%;backdrop-filter:blur(2px) saturate(0%) contrast(50%) brightness(25%);z-index:999999\r + }.wails-reconnect-overlay-content.svelte-181h7z{position:relative;top:50%;transform:translateY(-50%);margin:0;background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEsAAAA7CAMAAAAEsocZAAAC91BMVEUAAACzQ0PjMjLkMjLZLS7XLS+vJCjkMjKlEx6uGyHjMDGiFx7GJyrAISjUKy3mMzPlMjLjMzOsGyDKJirkMjK6HyXmMjLgMDC6IiLcMjLULC3MJyrRKSy+IibmMzPmMjK7ISXlMjLIJimzHSLkMjKtGiHZLC7BIifgMDCpGSDFIivcLy+yHSKoGR+eFBzNKCvlMjKxHSPkMTKxHSLmMjLKJyq5ICXDJCe6ISXdLzDkMjLmMzPFJSm2HyTlMTLhMDGyHSKUEBmhFx24HyTCJCjHJijjMzOiFh7mMjJ6BhDaLDCuGyOKABjnMzPGJinJJiquHCGEChSmGB/pMzOiFh7VKy3OKCu1HiSvHCLjMTLMKCrBIyeICxWxHCLDIyjSKizBIyh+CBO9ISa6ISWDChS9Iie1HyXVLC7FJSrLKCrlMjLiMTGPDhicFRywGyKXFBuhFx1/BxO7IiXkMTGeFBx8BxLkMTGnGR/GJCi4ICWsGyGJDxXSLS2yGiHSKi3CJCfnMzPQKiyECRTKJiq6ISWUERq/Iye0HiPDJCjGJSm6ICaPDxiTEBrdLy+3HyXSKiy0HyOQEBi4ICWhFh1+CBO9IieODhfSKyzWLC2LDhh8BxHKKCq7ISWaFBzkMzPqNDTTLC3EJSiHDBacExyvGyO1HyTPKCy+IieoGSC7ISaVEhrMKCvQKyusGyG0HiKACBPIJSq/JCaABxR5BRLEJCnkMzPJJinEJimPDRZ2BRKqHx/jMjLnMzPgMDHULC3NKSvQKSzsNDTWLS7SKyy3HyTKJyrDJSjbLzDYLC6mGB/GJSnVLC61HiPLKCrHJSm/Iye8Iia6ICWzHSKxHCLaLi/PKSupGR+7ICXpMzPbLi/IJinJJSmsGyGrGiCkFx6PDheJCxaFChXBIyfAIieSDxmBCBPlMjLeLzDdLzC5HySMDRe+ISWvGyGcFBzSKSzPJyvMJyrEJCjDIyefFRyWERriMDHUKiy/ISaZExv0NjbwNTXuNDTrMzMI0c+yAAAAu3RSTlMAA8HR/gwGgAj+MEpGCsC+hGpjQjYnIxgWBfzx7urizMrFqqB1bF83KhsR/fz8+/r5+fXv7unZ1tC+t6mmopqKdW1nYVpVRjUeHhIQBPr59/b28/Hx8ODg3NvUw8O/vKeim5aNioiDgn1vZWNjX1xUU1JPTUVFPT08Mi4qJyIh/Pv7+/n4+Pf39fT08/Du7efn5uXj4uHa19XNwsG/vrq2tbSuramlnpyYkpGNiIZ+enRraGVjVVBKOzghdjzRsAAABJVJREFUWMPtllVQG1EYhTc0ASpoobS0FCulUHd3oUjd3d3d3d3d3d2b7CYhnkBCCHGDEIK7Vh56d0NpOgwkYfLQzvA9ZrLfnPvfc+8uVEst/yheBJup3Nya2MjU6pa/jWLZtxjXpZFtVB4uVNI6m5gIruNkVFebqIb5Ug2ym4TIEM/gtUOGbg613oBzjAzZFrZ+lXu/3TIiMXXS5M6HTvrNHeLpZLEh6suGNW9fzZ9zd/qVi2eOHygqi5cDE5GUrJocONgzyqo0UXNSUlKSEhMztFqtXq9vNxImAmS3g7Y6QlbjdBWVGW36jt4wDGTUXjUsafh5zJWRkdFuZGtWGnCRmg+HasiGMUClTTzW0ZuVgLlGDIPM4Lhi0IrVq+tv2hS21fNrSONQgpM9DsJ4t3fM9PkvJuKj2ZjrZwvILKvaSTgciUSirjt6dOfOpyd169bDb9rMOwF9Hj4OD100gY0YXYb299bjzMrqj9doNByJWlVXFB9DT5dmJuvy+cq83JyuS6ayEYSHulKL8dmFnBkrCeZlHKMrC5XRhXGCZB2Ty1fkleRQaMCFT2DBsEafzRFJu7/2MicbKynPhQUDLiZwMWLJZKNLzoLbJBYVcurSmbmn+rcyJ8vCMgmlmaW6gnwun/+3C96VpAUuET1ZgRR36r2xWlnYSnf3oKABA14uXDDvydxHs6cpTV1p3hlJ2rJCiUjIZCByItXg8sHJijuvT64CuMTABUYvb6NN1Jdp1PH7D7f3bo2eS5KvW4RJr7atWT5w4MBBg9zdBw9+37BS7QIoFS5WnIaj12dr1DEXFgdvr4fh4eFl+u/wz8uf3jjHic8s4DL2Dal0IANyUBeCRCcwOBJV26JsjSpGwHVuSai69jvqD+jr56OgtKy0zAAK5mLTVBKVKL5tNthGAR9JneJQ/bFsHNzy+U7IlCYROxtMpIjR0ceoQVnowracLLpAQWETqV361bPoFo3cEbz2zYLZM7t3HWXcxmiBOgttS1ycWkTXMWh4mGigdug9DFdttqCFgTN6nD0q1XEVSoCxEjyFCi2eNC6Z69MRVIImJ6JQSf5gcFVCuF+aDhCa1F6MJFDaiNBQAh2TMfWBjhmLsAxUjG/fmjs0qjJck8D0GPBcuUuZW1LS/tIsPzqmQt17PvZQknlwnf4tHDBc+7t5VV3QQCkdc+Ur8/hdrz0but0RCumWiYbiKmLJ7EVbRomj4Q7+y5wsaXvfTGFpQcHB7n2WbG4MGdniw2Tm8xl5Yhr7MrSYHQ3uampz10aWyHyuzxvqaW/6W4MjXAUD3QV2aw97ZxhGjxCohYf5TpTHMXU1BbsAuoFnkRygVieIGAbqiF7rrH4rfWpKJouBCtyHJF8ctEyGubBa+C6NsMYEUonJFITHZqWBxXUA12Dv76Tf/PgOBmeNiiLG1pcKo1HAq8jLpY4JU1yWEixVNaOgoRJAKBSZHTZTU+wJOMtUDZvlVITC6FTlksyrEBoPHXpxxbzdaqzigUtVDkJVIOtVQ9UEOR4VGUh/kHWq0edJ6CxnZ+eePXva2bnY/cF/I1RLLf8vvwDANdMSMegxcAAAAABJRU5ErkJggg==);background-repeat:no-repeat;background-position:center\r + }.wails-reconnect-overlay-loadingspinner.svelte-181h7z{pointer-events:none;width:2.5em;height:2.5em;border:.4em solid transparent;border-color:#f00 #eee0 #f00 #eee0;border-radius:50%;animation:svelte-181h7z-loadingspin 1s linear infinite;margin:auto;padding:2.5em\r }@keyframes svelte-181h7z-loadingspin{100%{transform:rotate(360deg)}}`)}function Mt(t){let e,n,i;return{c(){e=B("div"),e.innerHTML='
      ',ht(e,"class","wails-reconnect-overlay svelte-181h7z")},m(o,c){W(o,e,c),i=!0},i(o){i||($(()=>{n||(n=Y(e,et,{duration:300},!0)),n.run(1)}),i=!0)},o(o){n||(n=Y(e,et,{duration:300},!1)),n.run(0),i=!1},d(o){o&&S(e),o&&n&&n.end()}}}function te(t){let e,n,i=t[0]&&Mt(t);return{c(){i&&i.c(),e=dt()},m(o,c){i&&i.m(o,c),W(o,e,c),n=!0},p(o,[c]){o[0]?i?c&1&&I(i,1):(i=Mt(o),i.c(),I(i,1),i.m(e.parentNode,e)):i&&(gt(),Q(i,1,1,()=>{i=null}),bt())},i(o){n||(I(i),n=!0)},o(o){Q(i),n=!1},d(o){i&&i.d(o),o&&S(e)}}}function ee(t,e,n){let i;return st(t,q,o=>n(0,i=o)),[i]}var St=class extends tt{constructor(e){super();vt(this,e,ee,te,L,{},Yt)}},Ct=St;var ne={},nt=null,j=[];window.WailsInvoke=t=>{if(!nt){console.log("Queueing: "+t),j.push(t);return}nt(t)};window.addEventListener("DOMContentLoaded",()=>{ne.overlay=new Ct({target:document.body,anchor:document.querySelector("#wails-spinner")})});var d=null,kt;window.onbeforeunload=function(){d&&(d.onclose=function(){},d.close(),d=null)};It();function ie(){nt=t=>{d.send(t)};for(let t=0;t= 0; count -= 1) { - const listener = eventListeners[eventName][count]; + const newEventListenerList = eventListeners[eventName]?.slice() || []; + if (newEventListenerList.length) { + for (let count = newEventListenerList.length - 1; count >= 0; count -= 1) { + const listener = newEventListenerList[count]; let data = eventData.data; const destroy = listener.Callback(data); if (destroy) { @@ -130,8 +130,16 @@ }); } } + function EventsOffAll() { + const eventNames = Object.keys(eventListeners); + eventNames.forEach((eventName) => { + removeListener(eventName); + }); + } function listenerOff(listener) { const eventName = listener.eventName; + if (eventListeners[eventName] === void 0) + return; eventListeners[eventName] = eventListeners[eventName].filter((l) => l !== listener); if (eventListeners[eventName].length === 0) { removeListener(eventName); @@ -451,10 +459,15 @@ return false; } function onDragOver(e) { - if (!window.wails.flags.enableWailsDragAndDrop) { + const isFileDrop = e.dataTransfer.types.includes("Files"); + if (!isFileDrop) { return; } e.preventDefault(); + e.dataTransfer.dropEffect = "copy"; + if (!window.wails.flags.enableWailsDragAndDrop) { + return; + } if (!flags.useDropTarget) { return; } @@ -466,17 +479,21 @@ } let currentElement = element; while (currentElement) { - if (checkStyleDropTarget(currentElement.style)) { + if (checkStyleDropTarget(getComputedStyle(currentElement))) { currentElement.classList.add(DROP_TARGET_ACTIVE); } currentElement = currentElement.parentElement; } } function onDragLeave(e) { - if (!window.wails.flags.enableWailsDragAndDrop) { + const isFileDrop = e.dataTransfer.types.includes("Files"); + if (!isFileDrop) { return; } e.preventDefault(); + if (!window.wails.flags.enableWailsDragAndDrop) { + return; + } if (!flags.useDropTarget) { return; } @@ -499,16 +516,14 @@ }, 50); } function onDrop(e) { - if (!window.wails.flags.enableWailsDragAndDrop) { + const isFileDrop = e.dataTransfer.types.includes("Files"); + if (!isFileDrop) { return; } e.preventDefault(); - if (!flags.useDropTarget) { + if (!window.wails.flags.enableWailsDragAndDrop) { return; } - if (flags.nextDeactivate) - flags.nextDeactivate(); - Array.from(document.getElementsByClassName(DROP_TARGET_ACTIVE)).forEach((el) => el.classList.remove(DROP_TARGET_ACTIVE)); if (CanResolveFilePaths()) { let files = []; if (e.dataTransfer.items) { @@ -522,6 +537,12 @@ } window.runtime.ResolveFilePaths(e.x, e.y, files); } + if (!flags.useDropTarget) { + return; + } + if (flags.nextDeactivate) + flags.nextDeactivate(); + Array.from(document.getElementsByClassName(DROP_TARGET_ACTIVE)).forEach((el) => el.classList.remove(DROP_TARGET_ACTIVE)); } function CanResolveFilePaths() { return window.chrome?.webview?.postMessageWithAdditionalObjects != null; @@ -628,6 +649,7 @@ EventsOnMultiple, EventsEmit, EventsOff, + EventsOffAll, Environment, Show, Hide, @@ -767,4 +789,4 @@ }); window.WailsInvoke("runtime:ready"); })(); -//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiZGVza3RvcC9sb2cuanMiLCAiZGVza3RvcC9ldmVudHMuanMiLCAiZGVza3RvcC9jYWxscy5qcyIsICJkZXNrdG9wL2JpbmRpbmdzLmpzIiwgImRlc2t0b3Avd2luZG93LmpzIiwgImRlc2t0b3Avc2NyZWVuLmpzIiwgImRlc2t0b3AvYnJvd3Nlci5qcyIsICJkZXNrdG9wL2NsaXBib2FyZC5qcyIsICJkZXNrdG9wL2RyYWdhbmRkcm9wLmpzIiwgImRlc2t0b3AvY29udGV4dG1lbnUuanMiLCAiZGVza3RvcC9tYWluLmpzIl0sCiAgInNvdXJjZXNDb250ZW50IjogWyIvKlxuIF8gICAgICAgX18gICAgICBfIF9fXG58IHwgICAgIC8gL19fXyBfKF8pIC9fX19fXG58IHwgL3wgLyAvIF9fIGAvIC8gLyBfX18vXG58IHwvIHwvIC8gL18vIC8gLyAoX18gIClcbnxfXy98X18vXFxfXyxfL18vXy9fX19fL1xuVGhlIGVsZWN0cm9uIGFsdGVybmF0aXZlIGZvciBHb1xuKGMpIExlYSBBbnRob255IDIwMTktcHJlc2VudFxuKi9cblxuLyoganNoaW50IGVzdmVyc2lvbjogNiAqL1xuXG4vKipcbiAqIFNlbmRzIGEgbG9nIG1lc3NhZ2UgdG8gdGhlIGJhY2tlbmQgd2l0aCB0aGUgZ2l2ZW4gbGV2ZWwgKyBtZXNzYWdlXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IGxldmVsXG4gKiBAcGFyYW0ge3N0cmluZ30gbWVzc2FnZVxuICovXG5mdW5jdGlvbiBzZW5kTG9nTWVzc2FnZShsZXZlbCwgbWVzc2FnZSkge1xuXG5cdC8vIExvZyBNZXNzYWdlIGZvcm1hdDpcblx0Ly8gbFt0eXBlXVttZXNzYWdlXVxuXHR3aW5kb3cuV2FpbHNJbnZva2UoJ0wnICsgbGV2ZWwgKyBtZXNzYWdlKTtcbn1cblxuLyoqXG4gKiBMb2cgdGhlIGdpdmVuIHRyYWNlIG1lc3NhZ2Ugd2l0aCB0aGUgYmFja2VuZFxuICpcbiAqIEBleHBvcnRcbiAqIEBwYXJhbSB7c3RyaW5nfSBtZXNzYWdlXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBMb2dUcmFjZShtZXNzYWdlKSB7XG5cdHNlbmRMb2dNZXNzYWdlKCdUJywgbWVzc2FnZSk7XG59XG5cbi8qKlxuICogTG9nIHRoZSBnaXZlbiBtZXNzYWdlIHdpdGggdGhlIGJhY2tlbmRcbiAqXG4gKiBAZXhwb3J0XG4gKiBAcGFyYW0ge3N0cmluZ30gbWVzc2FnZVxuICovXG5leHBvcnQgZnVuY3Rpb24gTG9nUHJpbnQobWVzc2FnZSkge1xuXHRzZW5kTG9nTWVzc2FnZSgnUCcsIG1lc3NhZ2UpO1xufVxuXG4vKipcbiAqIExvZyB0aGUgZ2l2ZW4gZGVidWcgbWVzc2FnZSB3aXRoIHRoZSBiYWNrZW5kXG4gKlxuICogQGV4cG9ydFxuICogQHBhcmFtIHtzdHJpbmd9IG1lc3NhZ2VcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIExvZ0RlYnVnKG1lc3NhZ2UpIHtcblx0c2VuZExvZ01lc3NhZ2UoJ0QnLCBtZXNzYWdlKTtcbn1cblxuLyoqXG4gKiBMb2cgdGhlIGdpdmVuIGluZm8gbWVzc2FnZSB3aXRoIHRoZSBiYWNrZW5kXG4gKlxuICogQGV4cG9ydFxuICogQHBhcmFtIHtzdHJpbmd9IG1lc3NhZ2VcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIExvZ0luZm8obWVzc2FnZSkge1xuXHRzZW5kTG9nTWVzc2FnZSgnSScsIG1lc3NhZ2UpO1xufVxuXG4vKipcbiAqIExvZyB0aGUgZ2l2ZW4gd2FybmluZyBtZXNzYWdlIHdpdGggdGhlIGJhY2tlbmRcbiAqXG4gKiBAZXhwb3J0XG4gKiBAcGFyYW0ge3N0cmluZ30gbWVzc2FnZVxuICovXG5leHBvcnQgZnVuY3Rpb24gTG9nV2FybmluZyhtZXNzYWdlKSB7XG5cdHNlbmRMb2dNZXNzYWdlKCdXJywgbWVzc2FnZSk7XG59XG5cbi8qKlxuICogTG9nIHRoZSBnaXZlbiBlcnJvciBtZXNzYWdlIHdpdGggdGhlIGJhY2tlbmRcbiAqXG4gKiBAZXhwb3J0XG4gKiBAcGFyYW0ge3N0cmluZ30gbWVzc2FnZVxuICovXG5leHBvcnQgZnVuY3Rpb24gTG9nRXJyb3IobWVzc2FnZSkge1xuXHRzZW5kTG9nTWVzc2FnZSgnRScsIG1lc3NhZ2UpO1xufVxuXG4vKipcbiAqIExvZyB0aGUgZ2l2ZW4gZmF0YWwgbWVzc2FnZSB3aXRoIHRoZSBiYWNrZW5kXG4gKlxuICogQGV4cG9ydFxuICogQHBhcmFtIHtzdHJpbmd9IG1lc3NhZ2VcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIExvZ0ZhdGFsKG1lc3NhZ2UpIHtcblx0c2VuZExvZ01lc3NhZ2UoJ0YnLCBtZXNzYWdlKTtcbn1cblxuLyoqXG4gKiBTZXRzIHRoZSBMb2cgbGV2ZWwgdG8gdGhlIGdpdmVuIGxvZyBsZXZlbFxuICpcbiAqIEBleHBvcnRcbiAqIEBwYXJhbSB7bnVtYmVyfSBsb2dsZXZlbFxuICovXG5leHBvcnQgZnVuY3Rpb24gU2V0TG9nTGV2ZWwobG9nbGV2ZWwpIHtcblx0c2VuZExvZ01lc3NhZ2UoJ1MnLCBsb2dsZXZlbCk7XG59XG5cbi8vIExvZyBsZXZlbHNcbmV4cG9ydCBjb25zdCBMb2dMZXZlbCA9IHtcblx0VFJBQ0U6IDEsXG5cdERFQlVHOiAyLFxuXHRJTkZPOiAzLFxuXHRXQVJOSU5HOiA0LFxuXHRFUlJPUjogNSxcbn07XG4iLCAiLypcbiBfICAgICAgIF9fICAgICAgXyBfX1xufCB8ICAgICAvIC9fX18gXyhfKSAvX19fX1xufCB8IC98IC8gLyBfXyBgLyAvIC8gX19fL1xufCB8LyB8LyAvIC9fLyAvIC8gKF9fICApXG58X18vfF9fL1xcX18sXy9fL18vX19fXy9cblRoZSBlbGVjdHJvbiBhbHRlcm5hdGl2ZSBmb3IgR29cbihjKSBMZWEgQW50aG9ueSAyMDE5LXByZXNlbnRcbiovXG4vKiBqc2hpbnQgZXN2ZXJzaW9uOiA2ICovXG5cbi8vIERlZmluZXMgYSBzaW5nbGUgbGlzdGVuZXIgd2l0aCBhIG1heGltdW0gbnVtYmVyIG9mIHRpbWVzIHRvIGNhbGxiYWNrXG5cbi8qKlxuICogVGhlIExpc3RlbmVyIGNsYXNzIGRlZmluZXMgYSBsaXN0ZW5lciEgOi0pXG4gKlxuICogQGNsYXNzIExpc3RlbmVyXG4gKi9cbmNsYXNzIExpc3RlbmVyIHtcbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGFuIGluc3RhbmNlIG9mIExpc3RlbmVyLlxuICAgICAqIEBwYXJhbSB7c3RyaW5nfSBldmVudE5hbWVcbiAgICAgKiBAcGFyYW0ge2Z1bmN0aW9ufSBjYWxsYmFja1xuICAgICAqIEBwYXJhbSB7bnVtYmVyfSBtYXhDYWxsYmFja3NcbiAgICAgKiBAbWVtYmVyb2YgTGlzdGVuZXJcbiAgICAgKi9cbiAgICBjb25zdHJ1Y3RvcihldmVudE5hbWUsIGNhbGxiYWNrLCBtYXhDYWxsYmFja3MpIHtcbiAgICAgICAgdGhpcy5ldmVudE5hbWUgPSBldmVudE5hbWU7XG4gICAgICAgIC8vIERlZmF1bHQgb2YgLTEgbWVhbnMgaW5maW5pdGVcbiAgICAgICAgdGhpcy5tYXhDYWxsYmFja3MgPSBtYXhDYWxsYmFja3MgfHwgLTE7XG4gICAgICAgIC8vIENhbGxiYWNrIGludm9rZXMgdGhlIGNhbGxiYWNrIHdpdGggdGhlIGdpdmVuIGRhdGFcbiAgICAgICAgLy8gUmV0dXJucyB0cnVlIGlmIHRoaXMgbGlzdGVuZXIgc2hvdWxkIGJlIGRlc3Ryb3llZFxuICAgICAgICB0aGlzLkNhbGxiYWNrID0gKGRhdGEpID0+IHtcbiAgICAgICAgICAgIGNhbGxiYWNrLmFwcGx5KG51bGwsIGRhdGEpO1xuICAgICAgICAgICAgLy8gSWYgbWF4Q2FsbGJhY2tzIGlzIGluZmluaXRlLCByZXR1cm4gZmFsc2UgKGRvIG5vdCBkZXN0cm95KVxuICAgICAgICAgICAgaWYgKHRoaXMubWF4Q2FsbGJhY2tzID09PSAtMSkge1xuICAgICAgICAgICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIC8vIERlY3JlbWVudCBtYXhDYWxsYmFja3MuIFJldHVybiB0cnVlIGlmIG5vdyAwLCBvdGhlcndpc2UgZmFsc2VcbiAgICAgICAgICAgIHRoaXMubWF4Q2FsbGJhY2tzIC09IDE7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy5tYXhDYWxsYmFja3MgPT09IDA7XG4gICAgICAgIH07XG4gICAgfVxufVxuXG5leHBvcnQgY29uc3QgZXZlbnRMaXN0ZW5lcnMgPSB7fTtcblxuLyoqXG4gKiBSZWdpc3RlcnMgYW4gZXZlbnQgbGlzdGVuZXIgdGhhdCB3aWxsIGJlIGludm9rZWQgYG1heENhbGxiYWNrc2AgdGltZXMgYmVmb3JlIGJlaW5nIGRlc3Ryb3llZFxuICpcbiAqIEBleHBvcnRcbiAqIEBwYXJhbSB7c3RyaW5nfSBldmVudE5hbWVcbiAqIEBwYXJhbSB7ZnVuY3Rpb259IGNhbGxiYWNrXG4gKiBAcGFyYW0ge251bWJlcn0gbWF4Q2FsbGJhY2tzXG4gKiBAcmV0dXJucyB7ZnVuY3Rpb259IEEgZnVuY3Rpb24gdG8gY2FuY2VsIHRoZSBsaXN0ZW5lclxuICovXG5leHBvcnQgZnVuY3Rpb24gRXZlbnRzT25NdWx0aXBsZShldmVudE5hbWUsIGNhbGxiYWNrLCBtYXhDYWxsYmFja3MpIHtcbiAgICBldmVudExpc3RlbmVyc1tldmVudE5hbWVdID0gZXZlbnRMaXN0ZW5lcnNbZXZlbnROYW1lXSB8fCBbXTtcbiAgICBjb25zdCB0aGlzTGlzdGVuZXIgPSBuZXcgTGlzdGVuZXIoZXZlbnROYW1lLCBjYWxsYmFjaywgbWF4Q2FsbGJhY2tzKTtcbiAgICBldmVudExpc3RlbmVyc1tldmVudE5hbWVdLnB1c2godGhpc0xpc3RlbmVyKTtcbiAgICByZXR1cm4gKCkgPT4gbGlzdGVuZXJPZmYodGhpc0xpc3RlbmVyKTtcbn1cblxuLyoqXG4gKiBSZWdpc3RlcnMgYW4gZXZlbnQgbGlzdGVuZXIgdGhhdCB3aWxsIGJlIGludm9rZWQgZXZlcnkgdGltZSB0aGUgZXZlbnQgaXMgZW1pdHRlZFxuICpcbiAqIEBleHBvcnRcbiAqIEBwYXJhbSB7c3RyaW5nfSBldmVudE5hbWVcbiAqIEBwYXJhbSB7ZnVuY3Rpb259IGNhbGxiYWNrXG4gKiBAcmV0dXJucyB7ZnVuY3Rpb259IEEgZnVuY3Rpb24gdG8gY2FuY2VsIHRoZSBsaXN0ZW5lclxuICovXG5leHBvcnQgZnVuY3Rpb24gRXZlbnRzT24oZXZlbnROYW1lLCBjYWxsYmFjaykge1xuICAgIHJldHVybiBFdmVudHNPbk11bHRpcGxlKGV2ZW50TmFtZSwgY2FsbGJhY2ssIC0xKTtcbn1cblxuLyoqXG4gKiBSZWdpc3RlcnMgYW4gZXZlbnQgbGlzdGVuZXIgdGhhdCB3aWxsIGJlIGludm9rZWQgb25jZSB0aGVuIGRlc3Ryb3llZFxuICpcbiAqIEBleHBvcnRcbiAqIEBwYXJhbSB7c3RyaW5nfSBldmVudE5hbWVcbiAqIEBwYXJhbSB7ZnVuY3Rpb259IGNhbGxiYWNrXG4gKiBAcmV0dXJucyB7ZnVuY3Rpb259IEEgZnVuY3Rpb24gdG8gY2FuY2VsIHRoZSBsaXN0ZW5lclxuICovXG5leHBvcnQgZnVuY3Rpb24gRXZlbnRzT25jZShldmVudE5hbWUsIGNhbGxiYWNrKSB7XG4gICAgcmV0dXJuIEV2ZW50c09uTXVsdGlwbGUoZXZlbnROYW1lLCBjYWxsYmFjaywgMSk7XG59XG5cbmZ1bmN0aW9uIG5vdGlmeUxpc3RlbmVycyhldmVudERhdGEpIHtcblxuICAgIC8vIEdldCB0aGUgZXZlbnQgbmFtZVxuICAgIGxldCBldmVudE5hbWUgPSBldmVudERhdGEubmFtZTtcblxuICAgIC8vIENoZWNrIGlmIHdlIGhhdmUgYW55IGxpc3RlbmVycyBmb3IgdGhpcyBldmVudFxuICAgIGlmIChldmVudExpc3RlbmVyc1tldmVudE5hbWVdKSB7XG5cbiAgICAgICAgLy8gS2VlcCBhIGxpc3Qgb2YgbGlzdGVuZXIgaW5kZXhlcyB0byBkZXN0cm95XG4gICAgICAgIGNvbnN0IG5ld0V2ZW50TGlzdGVuZXJMaXN0ID0gZXZlbnRMaXN0ZW5lcnNbZXZlbnROYW1lXS5zbGljZSgpO1xuXG4gICAgICAgIC8vIEl0ZXJhdGUgbGlzdGVuZXJzXG4gICAgICAgIGZvciAobGV0IGNvdW50ID0gZXZlbnRMaXN0ZW5lcnNbZXZlbnROYW1lXS5sZW5ndGggLSAxOyBjb3VudCA+PSAwOyBjb3VudCAtPSAxKSB7XG5cbiAgICAgICAgICAgIC8vIEdldCBuZXh0IGxpc3RlbmVyXG4gICAgICAgICAgICBjb25zdCBsaXN0ZW5lciA9IGV2ZW50TGlzdGVuZXJzW2V2ZW50TmFtZV1bY291bnRdO1xuXG4gICAgICAgICAgICBsZXQgZGF0YSA9IGV2ZW50RGF0YS5kYXRhO1xuXG4gICAgICAgICAgICAvLyBEbyB0aGUgY2FsbGJhY2tcbiAgICAgICAgICAgIGNvbnN0IGRlc3Ryb3kgPSBsaXN0ZW5lci5DYWxsYmFjayhkYXRhKTtcbiAgICAgICAgICAgIGlmIChkZXN0cm95KSB7XG4gICAgICAgICAgICAgICAgLy8gaWYgdGhlIGxpc3RlbmVyIGluZGljYXRlZCB0byBkZXN0cm95IGl0c2VsZiwgYWRkIGl0IHRvIHRoZSBkZXN0cm95IGxpc3RcbiAgICAgICAgICAgICAgICBuZXdFdmVudExpc3RlbmVyTGlzdC5zcGxpY2UoY291bnQsIDEpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgLy8gVXBkYXRlIGNhbGxiYWNrcyB3aXRoIG5ldyBsaXN0IG9mIGxpc3RlbmVyc1xuICAgICAgICBpZiAobmV3RXZlbnRMaXN0ZW5lckxpc3QubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgICByZW1vdmVMaXN0ZW5lcihldmVudE5hbWUpO1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgZXZlbnRMaXN0ZW5lcnNbZXZlbnROYW1lXSA9IG5ld0V2ZW50TGlzdGVuZXJMaXN0O1xuICAgICAgICB9XG4gICAgfVxufVxuXG4vKipcbiAqIE5vdGlmeSBpbmZvcm1zIGZyb250ZW5kIGxpc3RlbmVycyB0aGF0IGFuIGV2ZW50IHdhcyBlbWl0dGVkIHdpdGggdGhlIGdpdmVuIGRhdGFcbiAqXG4gKiBAZXhwb3J0XG4gKiBAcGFyYW0ge3N0cmluZ30gbm90aWZ5TWVzc2FnZSAtIGVuY29kZWQgbm90aWZpY2F0aW9uIG1lc3NhZ2VcblxuICovXG5leHBvcnQgZnVuY3Rpb24gRXZlbnRzTm90aWZ5KG5vdGlmeU1lc3NhZ2UpIHtcbiAgICAvLyBQYXJzZSB0aGUgbWVzc2FnZVxuICAgIGxldCBtZXNzYWdlO1xuICAgIHRyeSB7XG4gICAgICAgIG1lc3NhZ2UgPSBKU09OLnBhcnNlKG5vdGlmeU1lc3NhZ2UpO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgY29uc3QgZXJyb3IgPSAnSW52YWxpZCBKU09OIHBhc3NlZCB0byBOb3RpZnk6ICcgKyBub3RpZnlNZXNzYWdlO1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoZXJyb3IpO1xuICAgIH1cbiAgICBub3RpZnlMaXN0ZW5lcnMobWVzc2FnZSk7XG59XG5cbi8qKlxuICogRW1pdCBhbiBldmVudCB3aXRoIHRoZSBnaXZlbiBuYW1lIGFuZCBkYXRhXG4gKlxuICogQGV4cG9ydFxuICogQHBhcmFtIHtzdHJpbmd9IGV2ZW50TmFtZVxuICovXG5leHBvcnQgZnVuY3Rpb24gRXZlbnRzRW1pdChldmVudE5hbWUpIHtcblxuICAgIGNvbnN0IHBheWxvYWQgPSB7XG4gICAgICAgIG5hbWU6IGV2ZW50TmFtZSxcbiAgICAgICAgZGF0YTogW10uc2xpY2UuYXBwbHkoYXJndW1lbnRzKS5zbGljZSgxKSxcbiAgICB9O1xuXG4gICAgLy8gTm90aWZ5IEpTIGxpc3RlbmVyc1xuICAgIG5vdGlmeUxpc3RlbmVycyhwYXlsb2FkKTtcblxuICAgIC8vIE5vdGlmeSBHbyBsaXN0ZW5lcnNcbiAgICB3aW5kb3cuV2FpbHNJbnZva2UoJ0VFJyArIEpTT04uc3RyaW5naWZ5KHBheWxvYWQpKTtcbn1cblxuZnVuY3Rpb24gcmVtb3ZlTGlzdGVuZXIoZXZlbnROYW1lKSB7XG4gICAgLy8gUmVtb3ZlIGxvY2FsIGxpc3RlbmVyc1xuICAgIGRlbGV0ZSBldmVudExpc3RlbmVyc1tldmVudE5hbWVdO1xuXG4gICAgLy8gTm90aWZ5IEdvIGxpc3RlbmVyc1xuICAgIHdpbmRvdy5XYWlsc0ludm9rZSgnRVgnICsgZXZlbnROYW1lKTtcbn1cblxuLyoqXG4gKiBPZmYgdW5yZWdpc3RlcnMgYSBsaXN0ZW5lciBwcmV2aW91c2x5IHJlZ2lzdGVyZWQgd2l0aCBPbixcbiAqIG9wdGlvbmFsbHkgbXVsdGlwbGUgbGlzdGVuZXJlcyBjYW4gYmUgdW5yZWdpc3RlcmVkIHZpYSBgYWRkaXRpb25hbEV2ZW50TmFtZXNgXG4gKlxuICogQHBhcmFtIHtzdHJpbmd9IGV2ZW50TmFtZVxuICogQHBhcmFtICB7Li4uc3RyaW5nfSBhZGRpdGlvbmFsRXZlbnROYW1lc1xuICovXG5leHBvcnQgZnVuY3Rpb24gRXZlbnRzT2ZmKGV2ZW50TmFtZSwgLi4uYWRkaXRpb25hbEV2ZW50TmFtZXMpIHtcbiAgICByZW1vdmVMaXN0ZW5lcihldmVudE5hbWUpXG5cbiAgICBpZiAoYWRkaXRpb25hbEV2ZW50TmFtZXMubGVuZ3RoID4gMCkge1xuICAgICAgICBhZGRpdGlvbmFsRXZlbnROYW1lcy5mb3JFYWNoKGV2ZW50TmFtZSA9PiB7XG4gICAgICAgICAgICByZW1vdmVMaXN0ZW5lcihldmVudE5hbWUpXG4gICAgICAgIH0pXG4gICAgfVxufVxuXG4vKipcbiAqIE9mZiB1bnJlZ2lzdGVycyBhbGwgZXZlbnQgbGlzdGVuZXJzIHByZXZpb3VzbHkgcmVnaXN0ZXJlZCB3aXRoIE9uXG4gKi9cbiBleHBvcnQgZnVuY3Rpb24gRXZlbnRzT2ZmQWxsKCkge1xuICAgIGNvbnN0IGV2ZW50TmFtZXMgPSBPYmplY3Qua2V5cyhldmVudExpc3RlbmVycyk7XG4gICAgZm9yIChsZXQgaSA9IDA7IGkgIT09IGV2ZW50TmFtZXMubGVuZ3RoOyBpKyspIHtcbiAgICAgICAgcmVtb3ZlTGlzdGVuZXIoZXZlbnROYW1lc1tpXSk7XG4gICAgfVxufVxuXG4vKipcbiAqIGxpc3RlbmVyT2ZmIHVucmVnaXN0ZXJzIGEgbGlzdGVuZXIgcHJldmlvdXNseSByZWdpc3RlcmVkIHdpdGggRXZlbnRzT25cbiAqXG4gKiBAcGFyYW0ge0xpc3RlbmVyfSBsaXN0ZW5lclxuICovXG4gZnVuY3Rpb24gbGlzdGVuZXJPZmYobGlzdGVuZXIpIHtcbiAgICBjb25zdCBldmVudE5hbWUgPSBsaXN0ZW5lci5ldmVudE5hbWU7XG4gICAgLy8gUmVtb3ZlIGxvY2FsIGxpc3RlbmVyXG4gICAgZXZlbnRMaXN0ZW5lcnNbZXZlbnROYW1lXSA9IGV2ZW50TGlzdGVuZXJzW2V2ZW50TmFtZV0uZmlsdGVyKGwgPT4gbCAhPT0gbGlzdGVuZXIpO1xuXG4gICAgLy8gQ2xlYW4gdXAgaWYgdGhlcmUgYXJlIG5vIGV2ZW50IGxpc3RlbmVycyBsZWZ0XG4gICAgaWYgKGV2ZW50TGlzdGVuZXJzW2V2ZW50TmFtZV0ubGVuZ3RoID09PSAwKSB7XG4gICAgICAgIHJlbW92ZUxpc3RlbmVyKGV2ZW50TmFtZSk7XG4gICAgfVxufVxuIiwgIi8qXG4gXyAgICAgICBfXyAgICAgIF8gX19cbnwgfCAgICAgLyAvX19fIF8oXykgL19fX19cbnwgfCAvfCAvIC8gX18gYC8gLyAvIF9fXy9cbnwgfC8gfC8gLyAvXy8gLyAvIChfXyAgKVxufF9fL3xfXy9cXF9fLF8vXy9fL19fX18vXG5UaGUgZWxlY3Ryb24gYWx0ZXJuYXRpdmUgZm9yIEdvXG4oYykgTGVhIEFudGhvbnkgMjAxOS1wcmVzZW50XG4qL1xuLyoganNoaW50IGVzdmVyc2lvbjogNiAqL1xuXG5leHBvcnQgY29uc3QgY2FsbGJhY2tzID0ge307XG5cbi8qKlxuICogUmV0dXJucyBhIG51bWJlciBmcm9tIHRoZSBuYXRpdmUgYnJvd3NlciByYW5kb20gZnVuY3Rpb25cbiAqXG4gKiBAcmV0dXJucyBudW1iZXJcbiAqL1xuZnVuY3Rpb24gY3J5cHRvUmFuZG9tKCkge1xuXHR2YXIgYXJyYXkgPSBuZXcgVWludDMyQXJyYXkoMSk7XG5cdHJldHVybiB3aW5kb3cuY3J5cHRvLmdldFJhbmRvbVZhbHVlcyhhcnJheSlbMF07XG59XG5cbi8qKlxuICogUmV0dXJucyBhIG51bWJlciB1c2luZyBkYSBvbGQtc2tvb2wgTWF0aC5SYW5kb21cbiAqIEkgbGlrZXMgdG8gY2FsbCBpdCBMT0xSYW5kb21cbiAqXG4gKiBAcmV0dXJucyBudW1iZXJcbiAqL1xuZnVuY3Rpb24gYmFzaWNSYW5kb20oKSB7XG5cdHJldHVybiBNYXRoLnJhbmRvbSgpICogOTAwNzE5OTI1NDc0MDk5MTtcbn1cblxuLy8gUGljayBhIHJhbmRvbSBudW1iZXIgZnVuY3Rpb24gYmFzZWQgb24gYnJvd3NlciBjYXBhYmlsaXR5XG52YXIgcmFuZG9tRnVuYztcbmlmICh3aW5kb3cuY3J5cHRvKSB7XG5cdHJhbmRvbUZ1bmMgPSBjcnlwdG9SYW5kb207XG59IGVsc2Uge1xuXHRyYW5kb21GdW5jID0gYmFzaWNSYW5kb207XG59XG5cblxuLyoqXG4gKiBDYWxsIHNlbmRzIGEgbWVzc2FnZSB0byB0aGUgYmFja2VuZCB0byBjYWxsIHRoZSBiaW5kaW5nIHdpdGggdGhlXG4gKiBnaXZlbiBkYXRhLiBBIHByb21pc2UgaXMgcmV0dXJuZWQgYW5kIHdpbGwgYmUgY29tcGxldGVkIHdoZW4gdGhlXG4gKiBiYWNrZW5kIHJlc3BvbmRzLiBUaGlzIHdpbGwgYmUgcmVzb2x2ZWQgd2hlbiB0aGUgY2FsbCB3YXMgc3VjY2Vzc2Z1bFxuICogb3IgcmVqZWN0ZWQgaWYgYW4gZXJyb3IgaXMgcGFzc2VkIGJhY2suXG4gKiBUaGVyZSBpcyBhIHRpbWVvdXQgbWVjaGFuaXNtLiBJZiB0aGUgY2FsbCBkb2Vzbid0IHJlc3BvbmQgaW4gdGhlIGdpdmVuXG4gKiB0aW1lIChpbiBtaWxsaXNlY29uZHMpIHRoZW4gdGhlIHByb21pc2UgaXMgcmVqZWN0ZWQuXG4gKlxuICogQGV4cG9ydFxuICogQHBhcmFtIHtzdHJpbmd9IG5hbWVcbiAqIEBwYXJhbSB7YW55PX0gYXJnc1xuICogQHBhcmFtIHtudW1iZXI9fSB0aW1lb3V0XG4gKiBAcmV0dXJuc1xuICovXG5leHBvcnQgZnVuY3Rpb24gQ2FsbChuYW1lLCBhcmdzLCB0aW1lb3V0KSB7XG5cblx0Ly8gVGltZW91dCBpbmZpbml0ZSBieSBkZWZhdWx0XG5cdGlmICh0aW1lb3V0ID09IG51bGwpIHtcblx0XHR0aW1lb3V0ID0gMDtcblx0fVxuXG5cdC8vIENyZWF0ZSBhIHByb21pc2Vcblx0cmV0dXJuIG5ldyBQcm9taXNlKGZ1bmN0aW9uIChyZXNvbHZlLCByZWplY3QpIHtcblxuXHRcdC8vIENyZWF0ZSBhIHVuaXF1ZSBjYWxsYmFja0lEXG5cdFx0dmFyIGNhbGxiYWNrSUQ7XG5cdFx0ZG8ge1xuXHRcdFx0Y2FsbGJhY2tJRCA9IG5hbWUgKyAnLScgKyByYW5kb21GdW5jKCk7XG5cdFx0fSB3aGlsZSAoY2FsbGJhY2tzW2NhbGxiYWNrSURdKTtcblxuXHRcdHZhciB0aW1lb3V0SGFuZGxlO1xuXHRcdC8vIFNldCB0aW1lb3V0XG5cdFx0aWYgKHRpbWVvdXQgPiAwKSB7XG5cdFx0XHR0aW1lb3V0SGFuZGxlID0gc2V0VGltZW91dChmdW5jdGlvbiAoKSB7XG5cdFx0XHRcdHJlamVjdChFcnJvcignQ2FsbCB0byAnICsgbmFtZSArICcgdGltZWQgb3V0LiBSZXF1ZXN0IElEOiAnICsgY2FsbGJhY2tJRCkpO1xuXHRcdFx0fSwgdGltZW91dCk7XG5cdFx0fVxuXG5cdFx0Ly8gU3RvcmUgY2FsbGJhY2tcblx0XHRjYWxsYmFja3NbY2FsbGJhY2tJRF0gPSB7XG5cdFx0XHR0aW1lb3V0SGFuZGxlOiB0aW1lb3V0SGFuZGxlLFxuXHRcdFx0cmVqZWN0OiByZWplY3QsXG5cdFx0XHRyZXNvbHZlOiByZXNvbHZlXG5cdFx0fTtcblxuXHRcdHRyeSB7XG5cdFx0XHRjb25zdCBwYXlsb2FkID0ge1xuXHRcdFx0XHRuYW1lLFxuXHRcdFx0XHRhcmdzLFxuXHRcdFx0XHRjYWxsYmFja0lELFxuXHRcdFx0fTtcblxuICAgICAgICAgICAgLy8gTWFrZSB0aGUgY2FsbFxuICAgICAgICAgICAgd2luZG93LldhaWxzSW52b2tlKCdDJyArIEpTT04uc3RyaW5naWZ5KHBheWxvYWQpKTtcbiAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lXG4gICAgICAgICAgICBjb25zb2xlLmVycm9yKGUpO1xuICAgICAgICB9XG4gICAgfSk7XG59XG5cbndpbmRvdy5PYmZ1c2NhdGVkQ2FsbCA9IChpZCwgYXJncywgdGltZW91dCkgPT4ge1xuXG4gICAgLy8gVGltZW91dCBpbmZpbml0ZSBieSBkZWZhdWx0XG4gICAgaWYgKHRpbWVvdXQgPT0gbnVsbCkge1xuICAgICAgICB0aW1lb3V0ID0gMDtcbiAgICB9XG5cbiAgICAvLyBDcmVhdGUgYSBwcm9taXNlXG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKGZ1bmN0aW9uIChyZXNvbHZlLCByZWplY3QpIHtcblxuICAgICAgICAvLyBDcmVhdGUgYSB1bmlxdWUgY2FsbGJhY2tJRFxuICAgICAgICB2YXIgY2FsbGJhY2tJRDtcbiAgICAgICAgZG8ge1xuICAgICAgICAgICAgY2FsbGJhY2tJRCA9IGlkICsgJy0nICsgcmFuZG9tRnVuYygpO1xuICAgICAgICB9IHdoaWxlIChjYWxsYmFja3NbY2FsbGJhY2tJRF0pO1xuXG4gICAgICAgIHZhciB0aW1lb3V0SGFuZGxlO1xuICAgICAgICAvLyBTZXQgdGltZW91dFxuICAgICAgICBpZiAodGltZW91dCA+IDApIHtcbiAgICAgICAgICAgIHRpbWVvdXRIYW5kbGUgPSBzZXRUaW1lb3V0KGZ1bmN0aW9uICgpIHtcbiAgICAgICAgICAgICAgICByZWplY3QoRXJyb3IoJ0NhbGwgdG8gbWV0aG9kICcgKyBpZCArICcgdGltZWQgb3V0LiBSZXF1ZXN0IElEOiAnICsgY2FsbGJhY2tJRCkpO1xuICAgICAgICAgICAgfSwgdGltZW91dCk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBTdG9yZSBjYWxsYmFja1xuICAgICAgICBjYWxsYmFja3NbY2FsbGJhY2tJRF0gPSB7XG4gICAgICAgICAgICB0aW1lb3V0SGFuZGxlOiB0aW1lb3V0SGFuZGxlLFxuICAgICAgICAgICAgcmVqZWN0OiByZWplY3QsXG4gICAgICAgICAgICByZXNvbHZlOiByZXNvbHZlXG4gICAgICAgIH07XG5cbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGNvbnN0IHBheWxvYWQgPSB7XG5cdFx0XHRcdGlkLFxuXHRcdFx0XHRhcmdzLFxuXHRcdFx0XHRjYWxsYmFja0lELFxuXHRcdFx0fTtcblxuICAgICAgICAgICAgLy8gTWFrZSB0aGUgY2FsbFxuICAgICAgICAgICAgd2luZG93LldhaWxzSW52b2tlKCdjJyArIEpTT04uc3RyaW5naWZ5KHBheWxvYWQpKTtcbiAgICAgICAgfSBjYXRjaCAoZSkge1xuICAgICAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lXG4gICAgICAgICAgICBjb25zb2xlLmVycm9yKGUpO1xuICAgICAgICB9XG4gICAgfSk7XG59O1xuXG5cbi8qKlxuICogQ2FsbGVkIGJ5IHRoZSBiYWNrZW5kIHRvIHJldHVybiBkYXRhIHRvIGEgcHJldmlvdXNseSBjYWxsZWRcbiAqIGJpbmRpbmcgaW52b2NhdGlvblxuICpcbiAqIEBleHBvcnRcbiAqIEBwYXJhbSB7c3RyaW5nfSBpbmNvbWluZ01lc3NhZ2VcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIENhbGxiYWNrKGluY29taW5nTWVzc2FnZSkge1xuXHQvLyBQYXJzZSB0aGUgbWVzc2FnZVxuXHRsZXQgbWVzc2FnZTtcblx0dHJ5IHtcblx0XHRtZXNzYWdlID0gSlNPTi5wYXJzZShpbmNvbWluZ01lc3NhZ2UpO1xuXHR9IGNhdGNoIChlKSB7XG5cdFx0Y29uc3QgZXJyb3IgPSBgSW52YWxpZCBKU09OIHBhc3NlZCB0byBjYWxsYmFjazogJHtlLm1lc3NhZ2V9LiBNZXNzYWdlOiAke2luY29taW5nTWVzc2FnZX1gO1xuXHRcdHJ1bnRpbWUuTG9nRGVidWcoZXJyb3IpO1xuXHRcdHRocm93IG5ldyBFcnJvcihlcnJvcik7XG5cdH1cblx0bGV0IGNhbGxiYWNrSUQgPSBtZXNzYWdlLmNhbGxiYWNraWQ7XG5cdGxldCBjYWxsYmFja0RhdGEgPSBjYWxsYmFja3NbY2FsbGJhY2tJRF07XG5cdGlmICghY2FsbGJhY2tEYXRhKSB7XG5cdFx0Y29uc3QgZXJyb3IgPSBgQ2FsbGJhY2sgJyR7Y2FsbGJhY2tJRH0nIG5vdCByZWdpc3RlcmVkISEhYDtcblx0XHRjb25zb2xlLmVycm9yKGVycm9yKTsgLy8gZXNsaW50LWRpc2FibGUtbGluZVxuXHRcdHRocm93IG5ldyBFcnJvcihlcnJvcik7XG5cdH1cblx0Y2xlYXJUaW1lb3V0KGNhbGxiYWNrRGF0YS50aW1lb3V0SGFuZGxlKTtcblxuXHRkZWxldGUgY2FsbGJhY2tzW2NhbGxiYWNrSURdO1xuXG5cdGlmIChtZXNzYWdlLmVycm9yKSB7XG5cdFx0Y2FsbGJhY2tEYXRhLnJlamVjdChtZXNzYWdlLmVycm9yKTtcblx0fSBlbHNlIHtcblx0XHRjYWxsYmFja0RhdGEucmVzb2x2ZShtZXNzYWdlLnJlc3VsdCk7XG5cdH1cbn1cbiIsICIvKlxuIF8gICAgICAgX18gICAgICBfIF9fICAgIFxufCB8ICAgICAvIC9fX18gXyhfKSAvX19fX1xufCB8IC98IC8gLyBfXyBgLyAvIC8gX19fL1xufCB8LyB8LyAvIC9fLyAvIC8gKF9fICApIFxufF9fL3xfXy9cXF9fLF8vXy9fL19fX18vICBcblRoZSBlbGVjdHJvbiBhbHRlcm5hdGl2ZSBmb3IgR29cbihjKSBMZWEgQW50aG9ueSAyMDE5LXByZXNlbnRcbiovXG4vKiBqc2hpbnQgZXN2ZXJzaW9uOiA2ICovXG5cbmltcG9ydCB7Q2FsbH0gZnJvbSAnLi9jYWxscyc7XG5cbi8vIFRoaXMgaXMgd2hlcmUgd2UgYmluZCBnbyBtZXRob2Qgd3JhcHBlcnNcbndpbmRvdy5nbyA9IHt9O1xuXG5leHBvcnQgZnVuY3Rpb24gU2V0QmluZGluZ3MoYmluZGluZ3NNYXApIHtcblx0dHJ5IHtcblx0XHRiaW5kaW5nc01hcCA9IEpTT04ucGFyc2UoYmluZGluZ3NNYXApO1xuXHR9IGNhdGNoIChlKSB7XG5cdFx0Y29uc29sZS5lcnJvcihlKTtcblx0fVxuXG5cdC8vIEluaXRpYWxpc2UgdGhlIGJpbmRpbmdzIG1hcFxuXHR3aW5kb3cuZ28gPSB3aW5kb3cuZ28gfHwge307XG5cblx0Ly8gSXRlcmF0ZSBwYWNrYWdlIG5hbWVzXG5cdE9iamVjdC5rZXlzKGJpbmRpbmdzTWFwKS5mb3JFYWNoKChwYWNrYWdlTmFtZSkgPT4ge1xuXG5cdFx0Ly8gQ3JlYXRlIGlubmVyIG1hcCBpZiBpdCBkb2Vzbid0IGV4aXN0XG5cdFx0d2luZG93LmdvW3BhY2thZ2VOYW1lXSA9IHdpbmRvdy5nb1twYWNrYWdlTmFtZV0gfHwge307XG5cblx0XHQvLyBJdGVyYXRlIHN0cnVjdCBuYW1lc1xuXHRcdE9iamVjdC5rZXlzKGJpbmRpbmdzTWFwW3BhY2thZ2VOYW1lXSkuZm9yRWFjaCgoc3RydWN0TmFtZSkgPT4ge1xuXG5cdFx0XHQvLyBDcmVhdGUgaW5uZXIgbWFwIGlmIGl0IGRvZXNuJ3QgZXhpc3Rcblx0XHRcdHdpbmRvdy5nb1twYWNrYWdlTmFtZV1bc3RydWN0TmFtZV0gPSB3aW5kb3cuZ29bcGFja2FnZU5hbWVdW3N0cnVjdE5hbWVdIHx8IHt9O1xuXG5cdFx0XHRPYmplY3Qua2V5cyhiaW5kaW5nc01hcFtwYWNrYWdlTmFtZV1bc3RydWN0TmFtZV0pLmZvckVhY2goKG1ldGhvZE5hbWUpID0+IHtcblxuXHRcdFx0XHR3aW5kb3cuZ29bcGFja2FnZU5hbWVdW3N0cnVjdE5hbWVdW21ldGhvZE5hbWVdID0gZnVuY3Rpb24gKCkge1xuXG5cdFx0XHRcdFx0Ly8gTm8gdGltZW91dCBieSBkZWZhdWx0XG5cdFx0XHRcdFx0bGV0IHRpbWVvdXQgPSAwO1xuXG5cdFx0XHRcdFx0Ly8gQWN0dWFsIGZ1bmN0aW9uXG5cdFx0XHRcdFx0ZnVuY3Rpb24gZHluYW1pYygpIHtcblx0XHRcdFx0XHRcdGNvbnN0IGFyZ3MgPSBbXS5zbGljZS5jYWxsKGFyZ3VtZW50cyk7XG5cdFx0XHRcdFx0XHRyZXR1cm4gQ2FsbChbcGFja2FnZU5hbWUsIHN0cnVjdE5hbWUsIG1ldGhvZE5hbWVdLmpvaW4oJy4nKSwgYXJncywgdGltZW91dCk7XG5cdFx0XHRcdFx0fVxuXG5cdFx0XHRcdFx0Ly8gQWxsb3cgc2V0dGluZyB0aW1lb3V0IHRvIGZ1bmN0aW9uXG5cdFx0XHRcdFx0ZHluYW1pYy5zZXRUaW1lb3V0ID0gZnVuY3Rpb24gKG5ld1RpbWVvdXQpIHtcblx0XHRcdFx0XHRcdHRpbWVvdXQgPSBuZXdUaW1lb3V0O1xuXHRcdFx0XHRcdH07XG5cblx0XHRcdFx0XHQvLyBBbGxvdyBnZXR0aW5nIHRpbWVvdXQgdG8gZnVuY3Rpb25cblx0XHRcdFx0XHRkeW5hbWljLmdldFRpbWVvdXQgPSBmdW5jdGlvbiAoKSB7XG5cdFx0XHRcdFx0XHRyZXR1cm4gdGltZW91dDtcblx0XHRcdFx0XHR9O1xuXG5cdFx0XHRcdFx0cmV0dXJuIGR5bmFtaWM7XG5cdFx0XHRcdH0oKTtcblx0XHRcdH0pO1xuXHRcdH0pO1xuXHR9KTtcbn1cbiIsICIvKlxuIF9cdCAgIF9fXHQgIF8gX19cbnwgfFx0IC8gL19fXyBfKF8pIC9fX19fXG58IHwgL3wgLyAvIF9fIGAvIC8gLyBfX18vXG58IHwvIHwvIC8gL18vIC8gLyAoX18gIClcbnxfXy98X18vXFxfXyxfL18vXy9fX19fL1xuVGhlIGVsZWN0cm9uIGFsdGVybmF0aXZlIGZvciBHb1xuKGMpIExlYSBBbnRob255IDIwMTktcHJlc2VudFxuKi9cblxuLyoganNoaW50IGVzdmVyc2lvbjogOSAqL1xuXG5cbmltcG9ydCB7Q2FsbH0gZnJvbSBcIi4vY2FsbHNcIjtcblxuZXhwb3J0IGZ1bmN0aW9uIFdpbmRvd1JlbG9hZCgpIHtcbiAgICB3aW5kb3cubG9jYXRpb24ucmVsb2FkKCk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBXaW5kb3dSZWxvYWRBcHAoKSB7XG4gICAgd2luZG93LldhaWxzSW52b2tlKCdXUicpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gV2luZG93U2V0U3lzdGVtRGVmYXVsdFRoZW1lKCkge1xuICAgIHdpbmRvdy5XYWlsc0ludm9rZSgnV0FTRFQnKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIFdpbmRvd1NldExpZ2h0VGhlbWUoKSB7XG4gICAgd2luZG93LldhaWxzSW52b2tlKCdXQUxUJyk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBXaW5kb3dTZXREYXJrVGhlbWUoKSB7XG4gICAgd2luZG93LldhaWxzSW52b2tlKCdXQURUJyk7XG59XG5cbi8qKlxuICogUGxhY2UgdGhlIHdpbmRvdyBpbiB0aGUgY2VudGVyIG9mIHRoZSBzY3JlZW5cbiAqXG4gKiBAZXhwb3J0XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBXaW5kb3dDZW50ZXIoKSB7XG4gICAgd2luZG93LldhaWxzSW52b2tlKCdXYycpO1xufVxuXG4vKipcbiAqIFNldHMgdGhlIHdpbmRvdyB0aXRsZVxuICpcbiAqIEBwYXJhbSB7c3RyaW5nfSB0aXRsZVxuICogQGV4cG9ydFxuICovXG5leHBvcnQgZnVuY3Rpb24gV2luZG93U2V0VGl0bGUodGl0bGUpIHtcbiAgICB3aW5kb3cuV2FpbHNJbnZva2UoJ1dUJyArIHRpdGxlKTtcbn1cblxuLyoqXG4gKiBNYWtlcyB0aGUgd2luZG93IGdvIGZ1bGxzY3JlZW5cbiAqXG4gKiBAZXhwb3J0XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBXaW5kb3dGdWxsc2NyZWVuKCkge1xuICAgIHdpbmRvdy5XYWlsc0ludm9rZSgnV0YnKTtcbn1cblxuLyoqXG4gKiBSZXZlcnRzIHRoZSB3aW5kb3cgZnJvbSBmdWxsc2NyZWVuXG4gKlxuICogQGV4cG9ydFxuICovXG5leHBvcnQgZnVuY3Rpb24gV2luZG93VW5mdWxsc2NyZWVuKCkge1xuICAgIHdpbmRvdy5XYWlsc0ludm9rZSgnV2YnKTtcbn1cblxuLyoqXG4gKiBSZXR1cm5zIHRoZSBzdGF0ZSBvZiB0aGUgd2luZG93LCBpLmUuIHdoZXRoZXIgdGhlIHdpbmRvdyBpcyBpbiBmdWxsIHNjcmVlbiBtb2RlIG9yIG5vdC5cbiAqXG4gKiBAZXhwb3J0XG4gKiBAcmV0dXJuIHtQcm9taXNlPGJvb2xlYW4+fSBUaGUgc3RhdGUgb2YgdGhlIHdpbmRvd1xuICovXG5leHBvcnQgZnVuY3Rpb24gV2luZG93SXNGdWxsc2NyZWVuKCkge1xuICAgIHJldHVybiBDYWxsKFwiOndhaWxzOldpbmRvd0lzRnVsbHNjcmVlblwiKTtcbn1cblxuLyoqXG4gKiBTZXQgdGhlIFNpemUgb2YgdGhlIHdpbmRvd1xuICpcbiAqIEBleHBvcnRcbiAqIEBwYXJhbSB7bnVtYmVyfSB3aWR0aFxuICogQHBhcmFtIHtudW1iZXJ9IGhlaWdodFxuICovXG5leHBvcnQgZnVuY3Rpb24gV2luZG93U2V0U2l6ZSh3aWR0aCwgaGVpZ2h0KSB7XG4gICAgd2luZG93LldhaWxzSW52b2tlKCdXczonICsgd2lkdGggKyAnOicgKyBoZWlnaHQpO1xufVxuXG4vKipcbiAqIEdldCB0aGUgU2l6ZSBvZiB0aGUgd2luZG93XG4gKlxuICogQGV4cG9ydFxuICogQHJldHVybiB7UHJvbWlzZTx7dzogbnVtYmVyLCBoOiBudW1iZXJ9Pn0gVGhlIHNpemUgb2YgdGhlIHdpbmRvd1xuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBXaW5kb3dHZXRTaXplKCkge1xuICAgIHJldHVybiBDYWxsKFwiOndhaWxzOldpbmRvd0dldFNpemVcIik7XG59XG5cbi8qKlxuICogU2V0IHRoZSBtYXhpbXVtIHNpemUgb2YgdGhlIHdpbmRvd1xuICpcbiAqIEBleHBvcnRcbiAqIEBwYXJhbSB7bnVtYmVyfSB3aWR0aFxuICogQHBhcmFtIHtudW1iZXJ9IGhlaWdodFxuICovXG5leHBvcnQgZnVuY3Rpb24gV2luZG93U2V0TWF4U2l6ZSh3aWR0aCwgaGVpZ2h0KSB7XG4gICAgd2luZG93LldhaWxzSW52b2tlKCdXWjonICsgd2lkdGggKyAnOicgKyBoZWlnaHQpO1xufVxuXG4vKipcbiAqIFNldCB0aGUgbWluaW11bSBzaXplIG9mIHRoZSB3aW5kb3dcbiAqXG4gKiBAZXhwb3J0XG4gKiBAcGFyYW0ge251bWJlcn0gd2lkdGhcbiAqIEBwYXJhbSB7bnVtYmVyfSBoZWlnaHRcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIFdpbmRvd1NldE1pblNpemUod2lkdGgsIGhlaWdodCkge1xuICAgIHdpbmRvdy5XYWlsc0ludm9rZSgnV3o6JyArIHdpZHRoICsgJzonICsgaGVpZ2h0KTtcbn1cblxuXG5cbi8qKlxuICogU2V0IHRoZSB3aW5kb3cgQWx3YXlzT25Ub3Agb3Igbm90IG9uIHRvcFxuICpcbiAqIEBleHBvcnRcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIFdpbmRvd1NldEFsd2F5c09uVG9wKGIpIHtcblxuICAgIHdpbmRvdy5XYWlsc0ludm9rZSgnV0FUUDonICsgKGIgPyAnMScgOiAnMCcpKTtcbn1cblxuXG5cblxuLyoqXG4gKiBTZXQgdGhlIFBvc2l0aW9uIG9mIHRoZSB3aW5kb3dcbiAqXG4gKiBAZXhwb3J0XG4gKiBAcGFyYW0ge251bWJlcn0geFxuICogQHBhcmFtIHtudW1iZXJ9IHlcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIFdpbmRvd1NldFBvc2l0aW9uKHgsIHkpIHtcbiAgICB3aW5kb3cuV2FpbHNJbnZva2UoJ1dwOicgKyB4ICsgJzonICsgeSk7XG59XG5cbi8qKlxuICogR2V0IHRoZSBQb3NpdGlvbiBvZiB0aGUgd2luZG93XG4gKlxuICogQGV4cG9ydFxuICogQHJldHVybiB7UHJvbWlzZTx7eDogbnVtYmVyLCB5OiBudW1iZXJ9Pn0gVGhlIHBvc2l0aW9uIG9mIHRoZSB3aW5kb3dcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIFdpbmRvd0dldFBvc2l0aW9uKCkge1xuICAgIHJldHVybiBDYWxsKFwiOndhaWxzOldpbmRvd0dldFBvc1wiKTtcbn1cblxuLyoqXG4gKiBIaWRlIHRoZSBXaW5kb3dcbiAqXG4gKiBAZXhwb3J0XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBXaW5kb3dIaWRlKCkge1xuICAgIHdpbmRvdy5XYWlsc0ludm9rZSgnV0gnKTtcbn1cblxuLyoqXG4gKiBTaG93IHRoZSBXaW5kb3dcbiAqXG4gKiBAZXhwb3J0XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBXaW5kb3dTaG93KCkge1xuICAgIHdpbmRvdy5XYWlsc0ludm9rZSgnV1MnKTtcbn1cblxuLyoqXG4gKiBNYXhpbWlzZSB0aGUgV2luZG93XG4gKlxuICogQGV4cG9ydFxuICovXG5leHBvcnQgZnVuY3Rpb24gV2luZG93TWF4aW1pc2UoKSB7XG4gICAgd2luZG93LldhaWxzSW52b2tlKCdXTScpO1xufVxuXG4vKipcbiAqIFRvZ2dsZSB0aGUgTWF4aW1pc2Ugb2YgdGhlIFdpbmRvd1xuICpcbiAqIEBleHBvcnRcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIFdpbmRvd1RvZ2dsZU1heGltaXNlKCkge1xuICAgIHdpbmRvdy5XYWlsc0ludm9rZSgnV3QnKTtcbn1cblxuLyoqXG4gKiBVbm1heGltaXNlIHRoZSBXaW5kb3dcbiAqXG4gKiBAZXhwb3J0XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBXaW5kb3dVbm1heGltaXNlKCkge1xuICAgIHdpbmRvdy5XYWlsc0ludm9rZSgnV1UnKTtcbn1cblxuLyoqXG4gKiBSZXR1cm5zIHRoZSBzdGF0ZSBvZiB0aGUgd2luZG93LCBpLmUuIHdoZXRoZXIgdGhlIHdpbmRvdyBpcyBtYXhpbWlzZWQgb3Igbm90LlxuICpcbiAqIEBleHBvcnRcbiAqIEByZXR1cm4ge1Byb21pc2U8Ym9vbGVhbj59IFRoZSBzdGF0ZSBvZiB0aGUgd2luZG93XG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBXaW5kb3dJc01heGltaXNlZCgpIHtcbiAgICByZXR1cm4gQ2FsbChcIjp3YWlsczpXaW5kb3dJc01heGltaXNlZFwiKTtcbn1cblxuLyoqXG4gKiBNaW5pbWlzZSB0aGUgV2luZG93XG4gKlxuICogQGV4cG9ydFxuICovXG5leHBvcnQgZnVuY3Rpb24gV2luZG93TWluaW1pc2UoKSB7XG4gICAgd2luZG93LldhaWxzSW52b2tlKCdXbScpO1xufVxuXG4vKipcbiAqIFVubWluaW1pc2UgdGhlIFdpbmRvd1xuICpcbiAqIEBleHBvcnRcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIFdpbmRvd1VubWluaW1pc2UoKSB7XG4gICAgd2luZG93LldhaWxzSW52b2tlKCdXdScpO1xufVxuXG4vKipcbiAqIFJldHVybnMgdGhlIHN0YXRlIG9mIHRoZSB3aW5kb3csIGkuZS4gd2hldGhlciB0aGUgd2luZG93IGlzIG1pbmltaXNlZCBvciBub3QuXG4gKlxuICogQGV4cG9ydFxuICogQHJldHVybiB7UHJvbWlzZTxib29sZWFuPn0gVGhlIHN0YXRlIG9mIHRoZSB3aW5kb3dcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIFdpbmRvd0lzTWluaW1pc2VkKCkge1xuICAgIHJldHVybiBDYWxsKFwiOndhaWxzOldpbmRvd0lzTWluaW1pc2VkXCIpO1xufVxuXG4vKipcbiAqIFJldHVybnMgdGhlIHN0YXRlIG9mIHRoZSB3aW5kb3csIGkuZS4gd2hldGhlciB0aGUgd2luZG93IGlzIG5vcm1hbCBvciBub3QuXG4gKlxuICogQGV4cG9ydFxuICogQHJldHVybiB7UHJvbWlzZTxib29sZWFuPn0gVGhlIHN0YXRlIG9mIHRoZSB3aW5kb3dcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIFdpbmRvd0lzTm9ybWFsKCkge1xuICAgIHJldHVybiBDYWxsKFwiOndhaWxzOldpbmRvd0lzTm9ybWFsXCIpO1xufVxuXG4vKipcbiAqIFNldHMgdGhlIGJhY2tncm91bmQgY29sb3VyIG9mIHRoZSB3aW5kb3dcbiAqXG4gKiBAZXhwb3J0XG4gKiBAcGFyYW0ge251bWJlcn0gUiBSZWRcbiAqIEBwYXJhbSB7bnVtYmVyfSBHIEdyZWVuXG4gKiBAcGFyYW0ge251bWJlcn0gQiBCbHVlXG4gKiBAcGFyYW0ge251bWJlcn0gQSBBbHBoYVxuICovXG5leHBvcnQgZnVuY3Rpb24gV2luZG93U2V0QmFja2dyb3VuZENvbG91cihSLCBHLCBCLCBBKSB7XG4gICAgbGV0IHJnYmEgPSBKU09OLnN0cmluZ2lmeSh7cjogUiB8fCAwLCBnOiBHIHx8IDAsIGI6IEIgfHwgMCwgYTogQSB8fCAyNTV9KTtcbiAgICB3aW5kb3cuV2FpbHNJbnZva2UoJ1dyOicgKyByZ2JhKTtcbn1cblxuIiwgIi8qXG4gX1x0ICAgX19cdCAgXyBfX1xufCB8XHQgLyAvX19fIF8oXykgL19fX19cbnwgfCAvfCAvIC8gX18gYC8gLyAvIF9fXy9cbnwgfC8gfC8gLyAvXy8gLyAvIChfXyAgKVxufF9fL3xfXy9cXF9fLF8vXy9fL19fX18vXG5UaGUgZWxlY3Ryb24gYWx0ZXJuYXRpdmUgZm9yIEdvXG4oYykgTGVhIEFudGhvbnkgMjAxOS1wcmVzZW50XG4qL1xuXG4vKiBqc2hpbnQgZXN2ZXJzaW9uOiA5ICovXG5cblxuaW1wb3J0IHtDYWxsfSBmcm9tIFwiLi9jYWxsc1wiO1xuXG5cbi8qKlxuICogR2V0cyB0aGUgYWxsIHNjcmVlbnMuIENhbGwgdGhpcyBhbmV3IGVhY2ggdGltZSB5b3Ugd2FudCB0byByZWZyZXNoIGRhdGEgZnJvbSB0aGUgdW5kZXJseWluZyB3aW5kb3dpbmcgc3lzdGVtLlxuICogQGV4cG9ydFxuICogQHR5cGVkZWYge2ltcG9ydCgnLi4vd3JhcHBlci9ydW50aW1lJykuU2NyZWVufSBTY3JlZW5cbiAqIEByZXR1cm4ge1Byb21pc2U8e1NjcmVlbltdfT59IFRoZSBzY3JlZW5zXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBTY3JlZW5HZXRBbGwoKSB7XG4gICAgcmV0dXJuIENhbGwoXCI6d2FpbHM6U2NyZWVuR2V0QWxsXCIpO1xufVxuIiwgIi8qKlxuICogQGRlc2NyaXB0aW9uOiBVc2UgdGhlIHN5c3RlbSBkZWZhdWx0IGJyb3dzZXIgdG8gb3BlbiB0aGUgdXJsXG4gKiBAcGFyYW0ge3N0cmluZ30gdXJsIFxuICogQHJldHVybiB7dm9pZH1cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIEJyb3dzZXJPcGVuVVJMKHVybCkge1xuICB3aW5kb3cuV2FpbHNJbnZva2UoJ0JPOicgKyB1cmwpO1xufSIsICIvKlxuIF9cdCAgIF9fXHQgIF8gX19cbnwgfFx0IC8gL19fXyBfKF8pIC9fX19fXG58IHwgL3wgLyAvIF9fIGAvIC8gLyBfX18vXG58IHwvIHwvIC8gL18vIC8gLyAoX18gIClcbnxfXy98X18vXFxfXyxfL18vXy9fX19fL1xuVGhlIGVsZWN0cm9uIGFsdGVybmF0aXZlIGZvciBHb1xuKGMpIExlYSBBbnRob255IDIwMTktcHJlc2VudFxuKi9cblxuLyoganNoaW50IGVzdmVyc2lvbjogOSAqL1xuXG5pbXBvcnQge0NhbGx9IGZyb20gXCIuL2NhbGxzXCI7XG5cbi8qKlxuICogU2V0IHRoZSBTaXplIG9mIHRoZSB3aW5kb3dcbiAqXG4gKiBAZXhwb3J0XG4gKiBAcGFyYW0ge3N0cmluZ30gdGV4dFxuICovXG5leHBvcnQgZnVuY3Rpb24gQ2xpcGJvYXJkU2V0VGV4dCh0ZXh0KSB7XG4gICAgcmV0dXJuIENhbGwoXCI6d2FpbHM6Q2xpcGJvYXJkU2V0VGV4dFwiLCBbdGV4dF0pO1xufVxuXG4vKipcbiAqIEdldCB0aGUgdGV4dCBjb250ZW50IG9mIHRoZSBjbGlwYm9hcmRcbiAqXG4gKiBAZXhwb3J0XG4gKiBAcmV0dXJuIHtQcm9taXNlPHtzdHJpbmd9Pn0gVGV4dCBjb250ZW50IG9mIHRoZSBjbGlwYm9hcmRcblxuICovXG5leHBvcnQgZnVuY3Rpb24gQ2xpcGJvYXJkR2V0VGV4dCgpIHtcbiAgICByZXR1cm4gQ2FsbChcIjp3YWlsczpDbGlwYm9hcmRHZXRUZXh0XCIpO1xufSIsICIvKlxuIF9cdCAgIF9fXHQgIF8gX19cbnwgfFx0IC8gL19fXyBfKF8pIC9fX19fXG58IHwgL3wgLyAvIF9fIGAvIC8gLyBfX18vXG58IHwvIHwvIC8gL18vIC8gLyAoX18gIClcbnxfXy98X18vXFxfXyxfL18vXy9fX19fL1xuVGhlIGVsZWN0cm9uIGFsdGVybmF0aXZlIGZvciBHb1xuKGMpIExlYSBBbnRob255IDIwMTktcHJlc2VudFxuKi9cblxuLyoganNoaW50IGVzdmVyc2lvbjogOSAqL1xuXG5pbXBvcnQge0V2ZW50c09uLCBFdmVudHNPZmZ9IGZyb20gXCIuL2V2ZW50c1wiO1xuXG5jb25zdCBmbGFncyA9IHtcbiAgICByZWdpc3RlcmVkOiBmYWxzZSxcbiAgICBkZWZhdWx0VXNlRHJvcFRhcmdldDogdHJ1ZSxcbiAgICB1c2VEcm9wVGFyZ2V0OiB0cnVlLFxuICAgIG5leHREZWFjdGl2YXRlOiBudWxsLFxuICAgIG5leHREZWFjdGl2YXRlVGltZW91dDogbnVsbCxcbn07XG5cbmNvbnN0IERST1BfVEFSR0VUX0FDVElWRSA9IFwid2FpbHMtZHJvcC10YXJnZXQtYWN0aXZlXCI7XG5cbi8qKlxuICogY2hlY2tTdHlsZURyb3BUYXJnZXQgY2hlY2tzIGlmIHRoZSBzdHlsZSBoYXMgdGhlIGRyb3AgdGFyZ2V0IGF0dHJpYnV0ZVxuICogXG4gKiBAcGFyYW0ge0NTU1N0eWxlRGVjbGFyYXRpb259IHN0eWxlIFxuICogQHJldHVybnMgXG4gKi9cbmZ1bmN0aW9uIGNoZWNrU3R5bGVEcm9wVGFyZ2V0KHN0eWxlKSB7XG4gICAgY29uc3QgY3NzRHJvcFZhbHVlID0gc3R5bGUuZ2V0UHJvcGVydHlWYWx1ZSh3aW5kb3cud2FpbHMuZmxhZ3MuY3NzRHJvcFByb3BlcnR5KS50cmltKCk7XG4gICAgaWYgKGNzc0Ryb3BWYWx1ZSkge1xuICAgICAgICBpZiAoY3NzRHJvcFZhbHVlID09PSB3aW5kb3cud2FpbHMuZmxhZ3MuY3NzRHJvcFZhbHVlKSB7XG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcbiAgICAgICAgfVxuICAgICAgICAvLyBpZiB0aGUgZWxlbWVudCBoYXMgdGhlIGRyb3AgdGFyZ2V0IGF0dHJpYnV0ZSwgYnV0IFxuICAgICAgICAvLyB0aGUgdmFsdWUgaXMgbm90IGNvcnJlY3QsIHRlcm1pbmF0ZSBmaW5kaW5nIHByb2Nlc3MuXG4gICAgICAgIC8vIFRoaXMgY2FuIGJlIHVzZWZ1bCB0byBibG9jayBzb21lIGNoaWxkIGVsZW1lbnRzIGZyb20gYmVpbmcgZHJvcCB0YXJnZXRzLlxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICAgIHJldHVybiBmYWxzZTtcbn1cblxuLyoqXG4gKiBvbkRyYWdPdmVyIGlzIGNhbGxlZCB3aGVuIHRoZSBkcmFnb3ZlciBldmVudCBpcyBlbWl0dGVkLlxuICogQHBhcmFtIHtEcmFnRXZlbnR9IGUgXG4gKiBAcmV0dXJucyBcbiAqL1xuZnVuY3Rpb24gb25EcmFnT3ZlcihlKSB7XG4gICAgaWYgKCF3aW5kb3cud2FpbHMuZmxhZ3MuZW5hYmxlV2FpbHNEcmFnQW5kRHJvcCkge1xuICAgICAgICByZXR1cm47XG4gICAgfVxuICAgIGUucHJldmVudERlZmF1bHQoKTtcblxuICAgIGlmICghZmxhZ3MudXNlRHJvcFRhcmdldCkge1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgY29uc3QgZWxlbWVudCA9IGUudGFyZ2V0O1xuXG4gICAgLy8gVHJpZ2dlciBkZWJvdW5jZSBmdW5jdGlvbiB0byBkZWFjdGl2YXRlIGRyb3AgdGFyZ2V0c1xuICAgIGlmKGZsYWdzLm5leHREZWFjdGl2YXRlKSBmbGFncy5uZXh0RGVhY3RpdmF0ZSgpO1xuXG4gICAgLy8gaWYgdGhlIGVsZW1lbnQgaXMgbnVsbCBvciBlbGVtZW50IGlzIG5vdCBjaGlsZCBvZiBkcm9wIHRhcmdldCBlbGVtZW50XG4gICAgaWYgKCFlbGVtZW50IHx8ICFjaGVja1N0eWxlRHJvcFRhcmdldChnZXRDb21wdXRlZFN0eWxlKGVsZW1lbnQpKSkge1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgbGV0IGN1cnJlbnRFbGVtZW50ID0gZWxlbWVudDtcbiAgICB3aGlsZSAoY3VycmVudEVsZW1lbnQpIHtcbiAgICAgICAgLy8gY2hlY2sgaWYgY3VycmVudEVsZW1lbnQgaXMgZHJvcCB0YXJnZXQgZWxlbWVudFxuICAgICAgICBpZiAoY2hlY2tTdHlsZURyb3BUYXJnZXQoY3VycmVudEVsZW1lbnQuc3R5bGUpKSB7XG4gICAgICAgICAgICBjdXJyZW50RWxlbWVudC5jbGFzc0xpc3QuYWRkKERST1BfVEFSR0VUX0FDVElWRSk7XG4gICAgICAgIH1cbiAgICAgICAgY3VycmVudEVsZW1lbnQgPSBjdXJyZW50RWxlbWVudC5wYXJlbnRFbGVtZW50O1xuICAgIH1cbn1cblxuLyoqXG4gKiBvbkRyYWdMZWF2ZSBpcyBjYWxsZWQgd2hlbiB0aGUgZHJhZ2xlYXZlIGV2ZW50IGlzIGVtaXR0ZWQuXG4gKiBAcGFyYW0ge0RyYWdFdmVudH0gZSBcbiAqIEByZXR1cm5zIFxuICovXG5mdW5jdGlvbiBvbkRyYWdMZWF2ZShlKSB7XG4gICAgaWYgKCF3aW5kb3cud2FpbHMuZmxhZ3MuZW5hYmxlV2FpbHNEcmFnQW5kRHJvcCkge1xuICAgICAgICByZXR1cm47XG4gICAgfVxuICAgIGUucHJldmVudERlZmF1bHQoKTtcblxuICAgIGlmICghZmxhZ3MudXNlRHJvcFRhcmdldCkge1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgLy8gRmluZCB0aGUgY2xvc2UgZHJvcCB0YXJnZXQgZWxlbWVudFxuICAgIGlmICghZS50YXJnZXQgfHwgIWNoZWNrU3R5bGVEcm9wVGFyZ2V0KGdldENvbXB1dGVkU3R5bGUoZS50YXJnZXQpKSkge1xuICAgICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG5cbiAgICAvLyBUcmlnZ2VyIGRlYm91bmNlIGZ1bmN0aW9uIHRvIGRlYWN0aXZhdGUgZHJvcCB0YXJnZXRzXG4gICAgaWYoZmxhZ3MubmV4dERlYWN0aXZhdGUpIGZsYWdzLm5leHREZWFjdGl2YXRlKCk7XG4gICAgXG4gICAgLy8gVXNlIGRlYm91bmNlIHRlY2huaXF1ZSB0byB0YWNsZSBkcmFnbGVhdmUgZXZlbnRzIG9uIG92ZXJsYXBwaW5nIGVsZW1lbnRzIGFuZCBkcm9wIHRhcmdldCBlbGVtZW50c1xuICAgIGZsYWdzLm5leHREZWFjdGl2YXRlID0gKCkgPT4ge1xuICAgICAgICAvLyBEZWFjdGl2YXRlIGFsbCBkcm9wIHRhcmdldHMsIG5ldyBkcm9wIHRhcmdldCB3aWxsIGJlIGFjdGl2YXRlZCBvbiBuZXh0IGRyYWdvdmVyIGV2ZW50XG4gICAgICAgIEFycmF5LmZyb20oZG9jdW1lbnQuZ2V0RWxlbWVudHNCeUNsYXNzTmFtZShEUk9QX1RBUkdFVF9BQ1RJVkUpKS5mb3JFYWNoKGVsID0+IGVsLmNsYXNzTGlzdC5yZW1vdmUoRFJPUF9UQVJHRVRfQUNUSVZFKSk7XG4gICAgICAgIC8vIFJlc2V0IG5leHREZWFjdGl2YXRlXG4gICAgICAgIGZsYWdzLm5leHREZWFjdGl2YXRlID0gbnVsbDtcbiAgICAgICAgLy8gQ2xlYXIgdGltZW91dFxuICAgICAgICBpZiAoZmxhZ3MubmV4dERlYWN0aXZhdGVUaW1lb3V0KSB7XG4gICAgICAgICAgICBjbGVhclRpbWVvdXQoZmxhZ3MubmV4dERlYWN0aXZhdGVUaW1lb3V0KTtcbiAgICAgICAgICAgIGZsYWdzLm5leHREZWFjdGl2YXRlVGltZW91dCA9IG51bGw7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvLyBTZXQgdGltZW91dCB0byBkZWFjdGl2YXRlIGRyb3AgdGFyZ2V0cyBpZiBub3QgdHJpZ2dlcmVkIGJ5IG5leHQgZHJhZyBldmVudFxuICAgIGZsYWdzLm5leHREZWFjdGl2YXRlVGltZW91dCA9IHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgICBpZihmbGFncy5uZXh0RGVhY3RpdmF0ZSkgZmxhZ3MubmV4dERlYWN0aXZhdGUoKTtcbiAgICB9LCA1MCk7XG59XG5cbi8qKlxuICogb25Ecm9wIGlzIGNhbGxlZCB3aGVuIHRoZSBkcm9wIGV2ZW50IGlzIGVtaXR0ZWQuXG4gKiBAcGFyYW0ge0RyYWdFdmVudH0gZSBcbiAqIEByZXR1cm5zIFxuICovXG5mdW5jdGlvbiBvbkRyb3AoZSkge1xuICAgIGlmICghd2luZG93LndhaWxzLmZsYWdzLmVuYWJsZVdhaWxzRHJhZ0FuZERyb3ApIHtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBlLnByZXZlbnREZWZhdWx0KCk7XG5cbiAgICBpZiAoIWZsYWdzLnVzZURyb3BUYXJnZXQpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIC8vIFRyaWdnZXIgZGVib3VuY2UgZnVuY3Rpb24gdG8gZGVhY3RpdmF0ZSBkcm9wIHRhcmdldHNcbiAgICBpZihmbGFncy5uZXh0RGVhY3RpdmF0ZSkgZmxhZ3MubmV4dERlYWN0aXZhdGUoKTtcblxuICAgIC8vIERlYWN0aXZhdGUgYWxsIGRyb3AgdGFyZ2V0c1xuICAgIEFycmF5LmZyb20oZG9jdW1lbnQuZ2V0RWxlbWVudHNCeUNsYXNzTmFtZShEUk9QX1RBUkdFVF9BQ1RJVkUpKS5mb3JFYWNoKGVsID0+IGVsLmNsYXNzTGlzdC5yZW1vdmUoRFJPUF9UQVJHRVRfQUNUSVZFKSk7XG5cbiAgICBpZiAoQ2FuUmVzb2x2ZUZpbGVQYXRocygpKSB7XG4gICAgICAgIC8vIHByb2Nlc3MgZmlsZXNcbiAgICAgICAgbGV0IGZpbGVzID0gW107XG4gICAgICAgIGlmIChlLmRhdGFUcmFuc2Zlci5pdGVtcykge1xuICAgICAgICAgICAgZmlsZXMgPSBbLi4uZS5kYXRhVHJhbnNmZXIuaXRlbXNdLm1hcCgoaXRlbSwgaSkgPT4ge1xuICAgICAgICAgICAgICAgIGlmIChpdGVtLmtpbmQgPT09ICdmaWxlJykge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gaXRlbS5nZXRBc0ZpbGUoKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9KTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIGZpbGVzID0gWy4uLmUuZGF0YVRyYW5zZmVyLmZpbGVzXTtcbiAgICAgICAgfVxuICAgICAgICB3aW5kb3cucnVudGltZS5SZXNvbHZlRmlsZVBhdGhzKGUueCwgZS55LCBmaWxlcyk7XG4gICAgfVxufVxuXG4vKipcbiAqIHBvc3RNZXNzYWdlV2l0aEFkZGl0aW9uYWxPYmplY3RzIGNoZWNrcyB0aGUgYnJvd3NlcidzIGNhcGFiaWxpdHkgb2Ygc2VuZGluZyBwb3N0TWVzc2FnZVdpdGhBZGRpdGlvbmFsT2JqZWN0c1xuICpcbiAqIEByZXR1cm5zIHtib29sZWFufVxuICogQGNvbnN0cnVjdG9yXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBDYW5SZXNvbHZlRmlsZVBhdGhzKCkge1xuICAgIHJldHVybiB3aW5kb3cuY2hyb21lPy53ZWJ2aWV3Py5wb3N0TWVzc2FnZVdpdGhBZGRpdGlvbmFsT2JqZWN0cyAhPSBudWxsO1xufVxuXG4vKipcbiAqIFJlc29sdmVGaWxlUGF0aHMgc2VuZHMgZHJvcCBldmVudHMgdG8gdGhlIEdPIHNpZGUgdG8gcmVzb2x2ZSBmaWxlIHBhdGhzIG9uIHdpbmRvd3MuXG4gKlxuICogQHBhcmFtIHtudW1iZXJ9IHhcbiAqIEBwYXJhbSB7bnVtYmVyfSB5XG4gKiBAcGFyYW0ge2FueVtdfSBmaWxlc1xuICogQGNvbnN0cnVjdG9yXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBSZXNvbHZlRmlsZVBhdGhzKHgsIHksIGZpbGVzKSB7XG4gICAgLy8gT25seSBmb3Igd2luZG93cyB3ZWJ2aWV3MiA+PSAxLjAuMTc3NC4zMFxuICAgIC8vIGh0dHBzOi8vbGVhcm4ubWljcm9zb2Z0LmNvbS9lbi11cy9taWNyb3NvZnQtZWRnZS93ZWJ2aWV3Mi9yZWZlcmVuY2Uvd2luMzIvaWNvcmV3ZWJ2aWV3MndlYm1lc3NhZ2VyZWNlaXZlZGV2ZW50YXJnczI/dmlldz13ZWJ2aWV3Mi0xLjAuMTgyMy4zMiNhcHBsaWVzLXRvXG4gICAgaWYgKHdpbmRvdy5jaHJvbWU/LndlYnZpZXc/LnBvc3RNZXNzYWdlV2l0aEFkZGl0aW9uYWxPYmplY3RzKSB7XG4gICAgICAgIGNocm9tZS53ZWJ2aWV3LnBvc3RNZXNzYWdlV2l0aEFkZGl0aW9uYWxPYmplY3RzKGBmaWxlOmRyb3A6JHt4fToke3l9YCwgZmlsZXMpO1xuICAgIH1cbn1cblxuLyoqXG4gKiBDYWxsYmFjayBmb3IgT25GaWxlRHJvcCByZXR1cm5zIGEgc2xpY2Ugb2YgZmlsZSBwYXRoIHN0cmluZ3Mgd2hlbiBhIGRyb3AgaXMgZmluaXNoZWQuXG4gKlxuICogQGV4cG9ydFxuICogQGNhbGxiYWNrIE9uRmlsZURyb3BDYWxsYmFja1xuICogQHBhcmFtIHtudW1iZXJ9IHggLSB4IGNvb3JkaW5hdGUgb2YgdGhlIGRyb3BcbiAqIEBwYXJhbSB7bnVtYmVyfSB5IC0geSBjb29yZGluYXRlIG9mIHRoZSBkcm9wXG4gKiBAcGFyYW0ge3N0cmluZ1tdfSBwYXRocyAtIEEgbGlzdCBvZiBmaWxlIHBhdGhzLlxuICovXG5cbi8qKlxuICogT25GaWxlRHJvcCBsaXN0ZW5zIHRvIGRyYWcgYW5kIGRyb3AgZXZlbnRzIGFuZCBjYWxscyB0aGUgY2FsbGJhY2sgd2l0aCB0aGUgY29vcmRpbmF0ZXMgb2YgdGhlIGRyb3AgYW5kIGFuIGFycmF5IG9mIHBhdGggc3RyaW5ncy5cbiAqXG4gKiBAZXhwb3J0XG4gKiBAcGFyYW0ge09uRmlsZURyb3BDYWxsYmFja30gY2FsbGJhY2sgLSBDYWxsYmFjayBmb3IgT25GaWxlRHJvcCByZXR1cm5zIGEgc2xpY2Ugb2YgZmlsZSBwYXRoIHN0cmluZ3Mgd2hlbiBhIGRyb3AgaXMgZmluaXNoZWQuXG4gKiBAcGFyYW0ge2Jvb2xlYW59IFt1c2VEcm9wVGFyZ2V0PXRydWVdIC0gT25seSBjYWxsIHRoZSBjYWxsYmFjayB3aGVuIHRoZSBkcm9wIGZpbmlzaGVkIG9uIGFuIGVsZW1lbnQgdGhhdCBoYXMgdGhlIGRyb3AgdGFyZ2V0IHN0eWxlLiAoLS13YWlscy1kcm9wLXRhcmdldClcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIE9uRmlsZURyb3AoY2FsbGJhY2ssIHVzZURyb3BUYXJnZXQpIHtcbiAgICBpZiAodHlwZW9mIGNhbGxiYWNrICE9PSBcImZ1bmN0aW9uXCIpIHtcbiAgICAgICAgY29uc29sZS5lcnJvcihcIkRyYWdBbmREcm9wQ2FsbGJhY2sgaXMgbm90IGEgZnVuY3Rpb25cIik7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZiAoZmxhZ3MucmVnaXN0ZXJlZCkge1xuICAgICAgICByZXR1cm47XG4gICAgfVxuICAgIGZsYWdzLnJlZ2lzdGVyZWQgPSB0cnVlO1xuXG4gICAgY29uc3QgdURUUFQgPSB0eXBlb2YgdXNlRHJvcFRhcmdldDtcbiAgICBmbGFncy51c2VEcm9wVGFyZ2V0ID0gdURUUFQgPT09IFwidW5kZWZpbmVkXCIgfHwgdURUUFQgIT09IFwiYm9vbGVhblwiID8gZmxhZ3MuZGVmYXVsdFVzZURyb3BUYXJnZXQgOiB1c2VEcm9wVGFyZ2V0O1xuICAgIHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKCdkcmFnb3ZlcicsIG9uRHJhZ092ZXIpO1xuICAgIHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKCdkcmFnbGVhdmUnLCBvbkRyYWdMZWF2ZSk7XG4gICAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ2Ryb3AnLCBvbkRyb3ApO1xuXG4gICAgbGV0IGNiID0gY2FsbGJhY2s7XG4gICAgaWYgKGZsYWdzLnVzZURyb3BUYXJnZXQpIHtcbiAgICAgICAgY2IgPSBmdW5jdGlvbiAoeCwgeSwgcGF0aHMpIHtcbiAgICAgICAgICAgIGNvbnN0IGVsZW1lbnQgPSBkb2N1bWVudC5lbGVtZW50RnJvbVBvaW50KHgsIHkpXG4gICAgICAgICAgICAvLyBpZiB0aGUgZWxlbWVudCBpcyBudWxsIG9yIGVsZW1lbnQgaXMgbm90IGNoaWxkIG9mIGRyb3AgdGFyZ2V0IGVsZW1lbnQsIHJldHVybiBudWxsXG4gICAgICAgICAgICBpZiAoIWVsZW1lbnQgfHwgIWNoZWNrU3R5bGVEcm9wVGFyZ2V0KGdldENvbXB1dGVkU3R5bGUoZWxlbWVudCkpKSB7XG4gICAgICAgICAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICBjYWxsYmFjayh4LCB5LCBwYXRocyk7XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICBFdmVudHNPbihcIndhaWxzOmZpbGUtZHJvcFwiLCBjYik7XG59XG5cbi8qKlxuICogT25GaWxlRHJvcE9mZiByZW1vdmVzIHRoZSBkcmFnIGFuZCBkcm9wIGxpc3RlbmVycyBhbmQgaGFuZGxlcnMuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBPbkZpbGVEcm9wT2ZmKCkge1xuICAgIHdpbmRvdy5yZW1vdmVFdmVudExpc3RlbmVyKCdkcmFnb3ZlcicsIG9uRHJhZ092ZXIpO1xuICAgIHdpbmRvdy5yZW1vdmVFdmVudExpc3RlbmVyKCdkcmFnbGVhdmUnLCBvbkRyYWdMZWF2ZSk7XG4gICAgd2luZG93LnJlbW92ZUV2ZW50TGlzdGVuZXIoJ2Ryb3AnLCBvbkRyb3ApO1xuICAgIEV2ZW50c09mZihcIndhaWxzOmZpbGUtZHJvcFwiKTtcbiAgICBmbGFncy5yZWdpc3RlcmVkID0gZmFsc2U7XG59XG4iLCAiLypcbi0tZGVmYXVsdC1jb250ZXh0bWVudTogYXV0bzsgKGRlZmF1bHQpIHdpbGwgc2hvdyB0aGUgZGVmYXVsdCBjb250ZXh0IG1lbnUgaWYgY29udGVudEVkaXRhYmxlIGlzIHRydWUgT1IgdGV4dCBoYXMgYmVlbiBzZWxlY3RlZCBPUiBlbGVtZW50IGlzIGlucHV0IG9yIHRleHRhcmVhXG4tLWRlZmF1bHQtY29udGV4dG1lbnU6IHNob3c7IHdpbGwgYWx3YXlzIHNob3cgdGhlIGRlZmF1bHQgY29udGV4dCBtZW51XG4tLWRlZmF1bHQtY29udGV4dG1lbnU6IGhpZGU7IHdpbGwgYWx3YXlzIGhpZGUgdGhlIGRlZmF1bHQgY29udGV4dCBtZW51XG5cblRoaXMgcnVsZSBpcyBpbmhlcml0ZWQgbGlrZSBub3JtYWwgQ1NTIHJ1bGVzLCBzbyBuZXN0aW5nIHdvcmtzIGFzIGV4cGVjdGVkXG4qL1xuZXhwb3J0IGZ1bmN0aW9uIHByb2Nlc3NEZWZhdWx0Q29udGV4dE1lbnUoZXZlbnQpIHtcbiAgICAvLyBQcm9jZXNzIGRlZmF1bHQgY29udGV4dCBtZW51XG4gICAgY29uc3QgZWxlbWVudCA9IGV2ZW50LnRhcmdldDtcbiAgICBjb25zdCBjb21wdXRlZFN0eWxlID0gd2luZG93LmdldENvbXB1dGVkU3R5bGUoZWxlbWVudCk7XG4gICAgY29uc3QgZGVmYXVsdENvbnRleHRNZW51QWN0aW9uID0gY29tcHV0ZWRTdHlsZS5nZXRQcm9wZXJ0eVZhbHVlKFwiLS1kZWZhdWx0LWNvbnRleHRtZW51XCIpLnRyaW0oKTtcbiAgICBzd2l0Y2ggKGRlZmF1bHRDb250ZXh0TWVudUFjdGlvbikge1xuICAgICAgICBjYXNlIFwic2hvd1wiOlxuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICBjYXNlIFwiaGlkZVwiOlxuICAgICAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICAgIC8vIENoZWNrIGlmIGNvbnRlbnRFZGl0YWJsZSBpcyB0cnVlXG4gICAgICAgICAgICBpZiAoZWxlbWVudC5pc0NvbnRlbnRFZGl0YWJsZSkge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gQ2hlY2sgaWYgdGV4dCBoYXMgYmVlbiBzZWxlY3RlZCBhbmQgYWN0aW9uIGlzIG9uIHRoZSBzZWxlY3RlZCBlbGVtZW50c1xuICAgICAgICAgICAgY29uc3Qgc2VsZWN0aW9uID0gd2luZG93LmdldFNlbGVjdGlvbigpO1xuICAgICAgICAgICAgY29uc3QgaGFzU2VsZWN0aW9uID0gKHNlbGVjdGlvbi50b1N0cmluZygpLmxlbmd0aCA+IDApXG4gICAgICAgICAgICBpZiAoaGFzU2VsZWN0aW9uKSB7XG4gICAgICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBzZWxlY3Rpb24ucmFuZ2VDb3VudDsgaSsrKSB7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHJhbmdlID0gc2VsZWN0aW9uLmdldFJhbmdlQXQoaSk7XG4gICAgICAgICAgICAgICAgICAgIGNvbnN0IHJlY3RzID0gcmFuZ2UuZ2V0Q2xpZW50UmVjdHMoKTtcbiAgICAgICAgICAgICAgICAgICAgZm9yIChsZXQgaiA9IDA7IGogPCByZWN0cy5sZW5ndGg7IGorKykge1xuICAgICAgICAgICAgICAgICAgICAgICAgY29uc3QgcmVjdCA9IHJlY3RzW2pdO1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKGRvY3VtZW50LmVsZW1lbnRGcm9tUG9pbnQocmVjdC5sZWZ0LCByZWN0LnRvcCkgPT09IGVsZW1lbnQpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgICAvLyBDaGVjayBpZiB0YWduYW1lIGlzIGlucHV0IG9yIHRleHRhcmVhXG4gICAgICAgICAgICBpZiAoZWxlbWVudC50YWdOYW1lID09PSBcIklOUFVUXCIgfHwgZWxlbWVudC50YWdOYW1lID09PSBcIlRFWFRBUkVBXCIpIHtcbiAgICAgICAgICAgICAgICBpZiAoaGFzU2VsZWN0aW9uIHx8ICghZWxlbWVudC5yZWFkT25seSAmJiAhZWxlbWVudC5kaXNhYmxlZCkpIHtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgLy8gaGlkZSBkZWZhdWx0IGNvbnRleHQgbWVudVxuICAgICAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICB9XG59XG4iLCAiLypcbiBfXHQgICBfX1x0ICBfIF9fXG58IHxcdCAvIC9fX18gXyhfKSAvX19fX1xufCB8IC98IC8gLyBfXyBgLyAvIC8gX19fL1xufCB8LyB8LyAvIC9fLyAvIC8gKF9fICApXG58X18vfF9fL1xcX18sXy9fL18vX19fXy9cblRoZSBlbGVjdHJvbiBhbHRlcm5hdGl2ZSBmb3IgR29cbihjKSBMZWEgQW50aG9ueSAyMDE5LXByZXNlbnRcbiovXG4vKiBqc2hpbnQgZXN2ZXJzaW9uOiA5ICovXG5pbXBvcnQgKiBhcyBMb2cgZnJvbSAnLi9sb2cnO1xuaW1wb3J0IHtldmVudExpc3RlbmVycywgRXZlbnRzRW1pdCwgRXZlbnRzTm90aWZ5LCBFdmVudHNPZmYsIEV2ZW50c09uLCBFdmVudHNPbmNlLCBFdmVudHNPbk11bHRpcGxlfSBmcm9tICcuL2V2ZW50cyc7XG5pbXBvcnQge0NhbGwsIENhbGxiYWNrLCBjYWxsYmFja3N9IGZyb20gJy4vY2FsbHMnO1xuaW1wb3J0IHtTZXRCaW5kaW5nc30gZnJvbSBcIi4vYmluZGluZ3NcIjtcbmltcG9ydCAqIGFzIFdpbmRvdyBmcm9tIFwiLi93aW5kb3dcIjtcbmltcG9ydCAqIGFzIFNjcmVlbiBmcm9tIFwiLi9zY3JlZW5cIjtcbmltcG9ydCAqIGFzIEJyb3dzZXIgZnJvbSBcIi4vYnJvd3NlclwiO1xuaW1wb3J0ICogYXMgQ2xpcGJvYXJkIGZyb20gXCIuL2NsaXBib2FyZFwiO1xuaW1wb3J0ICogYXMgRHJhZ0FuZERyb3AgZnJvbSBcIi4vZHJhZ2FuZGRyb3BcIjtcbmltcG9ydCAqIGFzIENvbnRleHRNZW51IGZyb20gXCIuL2NvbnRleHRtZW51XCI7XG5cbmV4cG9ydCBmdW5jdGlvbiBRdWl0KCkge1xuICAgIHdpbmRvdy5XYWlsc0ludm9rZSgnUScpO1xufVxuXG5leHBvcnQgZnVuY3Rpb24gU2hvdygpIHtcbiAgICB3aW5kb3cuV2FpbHNJbnZva2UoJ1MnKTtcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIEhpZGUoKSB7XG4gICAgd2luZG93LldhaWxzSW52b2tlKCdIJyk7XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBFbnZpcm9ubWVudCgpIHtcbiAgICByZXR1cm4gQ2FsbChcIjp3YWlsczpFbnZpcm9ubWVudFwiKTtcbn1cblxuLy8gVGhlIEpTIHJ1bnRpbWVcbndpbmRvdy5ydW50aW1lID0ge1xuICAgIC4uLkxvZyxcbiAgICAuLi5XaW5kb3csXG4gICAgLi4uQnJvd3NlcixcbiAgICAuLi5TY3JlZW4sXG4gICAgLi4uQ2xpcGJvYXJkLFxuICAgIC4uLkRyYWdBbmREcm9wLFxuICAgIEV2ZW50c09uLFxuICAgIEV2ZW50c09uY2UsXG4gICAgRXZlbnRzT25NdWx0aXBsZSxcbiAgICBFdmVudHNFbWl0LFxuICAgIEV2ZW50c09mZixcbiAgICBFbnZpcm9ubWVudCxcbiAgICBTaG93LFxuICAgIEhpZGUsXG4gICAgUXVpdFxufTtcblxuLy8gSW50ZXJuYWwgd2FpbHMgZW5kcG9pbnRzXG53aW5kb3cud2FpbHMgPSB7XG4gICAgQ2FsbGJhY2ssXG4gICAgRXZlbnRzTm90aWZ5LFxuICAgIFNldEJpbmRpbmdzLFxuICAgIGV2ZW50TGlzdGVuZXJzLFxuICAgIGNhbGxiYWNrcyxcbiAgICBmbGFnczoge1xuICAgICAgICBkaXNhYmxlU2Nyb2xsYmFyRHJhZzogZmFsc2UsXG4gICAgICAgIGRpc2FibGVEZWZhdWx0Q29udGV4dE1lbnU6IGZhbHNlLFxuICAgICAgICBlbmFibGVSZXNpemU6IGZhbHNlLFxuICAgICAgICBkZWZhdWx0Q3Vyc29yOiBudWxsLFxuICAgICAgICBib3JkZXJUaGlja25lc3M6IDYsXG4gICAgICAgIHNob3VsZERyYWc6IGZhbHNlLFxuICAgICAgICBkZWZlckRyYWdUb01vdXNlTW92ZTogdHJ1ZSxcbiAgICAgICAgY3NzRHJhZ1Byb3BlcnR5OiBcIi0td2FpbHMtZHJhZ2dhYmxlXCIsXG4gICAgICAgIGNzc0RyYWdWYWx1ZTogXCJkcmFnXCIsXG4gICAgICAgIGNzc0Ryb3BQcm9wZXJ0eTogXCItLXdhaWxzLWRyb3AtdGFyZ2V0XCIsXG4gICAgICAgIGNzc0Ryb3BWYWx1ZTogXCJkcm9wXCIsXG4gICAgICAgIGVuYWJsZVdhaWxzRHJhZ0FuZERyb3A6IGZhbHNlLFxuICAgIH1cbn07XG5cbi8vIFNldCB0aGUgYmluZGluZ3NcbmlmICh3aW5kb3cud2FpbHNiaW5kaW5ncykge1xuICAgIHdpbmRvdy53YWlscy5TZXRCaW5kaW5ncyh3aW5kb3cud2FpbHNiaW5kaW5ncyk7XG4gICAgZGVsZXRlIHdpbmRvdy53YWlscy5TZXRCaW5kaW5ncztcbn1cblxuLy8gKGJvb2wpIFRoaXMgaXMgZXZhbHVhdGVkIGF0IGJ1aWxkIHRpbWUgaW4gcGFja2FnZS5qc29uXG5pZiAoIURFQlVHKSB7XG4gICAgZGVsZXRlIHdpbmRvdy53YWlsc2JpbmRpbmdzO1xufVxuXG5sZXQgZHJhZ1Rlc3QgPSBmdW5jdGlvbiAoZSkge1xuICAgIHZhciB2YWwgPSB3aW5kb3cuZ2V0Q29tcHV0ZWRTdHlsZShlLnRhcmdldCkuZ2V0UHJvcGVydHlWYWx1ZSh3aW5kb3cud2FpbHMuZmxhZ3MuY3NzRHJhZ1Byb3BlcnR5KTtcbiAgICBpZiAodmFsKSB7XG4gICAgICB2YWwgPSB2YWwudHJpbSgpO1xuICAgIH1cbiAgICBcbiAgICBpZiAodmFsICE9PSB3aW5kb3cud2FpbHMuZmxhZ3MuY3NzRHJhZ1ZhbHVlKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICBpZiAoZS5idXR0b25zICE9PSAxKSB7XG4gICAgICAgIC8vIERvIG5vdCBzdGFydCBkcmFnZ2luZyBpZiBub3QgdGhlIHByaW1hcnkgYnV0dG9uIGhhcyBiZWVuIGNsaWNrZWQuXG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICBpZiAoZS5kZXRhaWwgIT09IDEpIHtcbiAgICAgICAgLy8gRG8gbm90IHN0YXJ0IGRyYWdnaW5nIGlmIG1vcmUgdGhhbiBvbmNlIGhhcyBiZWVuIGNsaWNrZWQsIGUuZy4gd2hlbiBkb3VibGUgY2xpY2tpbmdcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIHJldHVybiB0cnVlO1xufTtcblxud2luZG93LndhaWxzLnNldENTU0RyYWdQcm9wZXJ0aWVzID0gZnVuY3Rpb24gKHByb3BlcnR5LCB2YWx1ZSkge1xuICAgIHdpbmRvdy53YWlscy5mbGFncy5jc3NEcmFnUHJvcGVydHkgPSBwcm9wZXJ0eTtcbiAgICB3aW5kb3cud2FpbHMuZmxhZ3MuY3NzRHJhZ1ZhbHVlID0gdmFsdWU7XG59XG5cbndpbmRvdy53YWlscy5zZXRDU1NEcm9wUHJvcGVydGllcyA9IGZ1bmN0aW9uIChwcm9wZXJ0eSwgdmFsdWUpIHtcbiAgICB3aW5kb3cud2FpbHMuZmxhZ3MuY3NzRHJvcFByb3BlcnR5ID0gcHJvcGVydHk7XG4gICAgd2luZG93LndhaWxzLmZsYWdzLmNzc0Ryb3BWYWx1ZSA9IHZhbHVlO1xufVxuXG53aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcignbW91c2Vkb3duJywgKGUpID0+IHtcbiAgICAvLyBDaGVjayBmb3IgcmVzaXppbmdcbiAgICBpZiAod2luZG93LndhaWxzLmZsYWdzLnJlc2l6ZUVkZ2UpIHtcbiAgICAgICAgd2luZG93LldhaWxzSW52b2tlKFwicmVzaXplOlwiICsgd2luZG93LndhaWxzLmZsYWdzLnJlc2l6ZUVkZ2UpO1xuICAgICAgICBlLnByZXZlbnREZWZhdWx0KCk7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBpZiAoZHJhZ1Rlc3QoZSkpIHtcbiAgICAgICAgaWYgKHdpbmRvdy53YWlscy5mbGFncy5kaXNhYmxlU2Nyb2xsYmFyRHJhZykge1xuICAgICAgICAgICAgLy8gVGhpcyBjaGVja3MgZm9yIGNsaWNrcyBvbiB0aGUgc2Nyb2xsIGJhclxuICAgICAgICAgICAgaWYgKGUub2Zmc2V0WCA+IGUudGFyZ2V0LmNsaWVudFdpZHRoIHx8IGUub2Zmc2V0WSA+IGUudGFyZ2V0LmNsaWVudEhlaWdodCkge1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICBpZiAod2luZG93LndhaWxzLmZsYWdzLmRlZmVyRHJhZ1RvTW91c2VNb3ZlKSB7XG4gICAgICAgICAgICB3aW5kb3cud2FpbHMuZmxhZ3Muc2hvdWxkRHJhZyA9IHRydWU7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBlLnByZXZlbnREZWZhdWx0KClcbiAgICAgICAgICAgIHdpbmRvdy5XYWlsc0ludm9rZShcImRyYWdcIik7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHdpbmRvdy53YWlscy5mbGFncy5zaG91bGREcmFnID0gZmFsc2U7XG4gICAgfVxufSk7XG5cbndpbmRvdy5hZGRFdmVudExpc3RlbmVyKCdtb3VzZXVwJywgKCkgPT4ge1xuICAgIHdpbmRvdy53YWlscy5mbGFncy5zaG91bGREcmFnID0gZmFsc2U7XG59KTtcblxuZnVuY3Rpb24gc2V0UmVzaXplKGN1cnNvcikge1xuICAgIGRvY3VtZW50LmRvY3VtZW50RWxlbWVudC5zdHlsZS5jdXJzb3IgPSBjdXJzb3IgfHwgd2luZG93LndhaWxzLmZsYWdzLmRlZmF1bHRDdXJzb3I7XG4gICAgd2luZG93LndhaWxzLmZsYWdzLnJlc2l6ZUVkZ2UgPSBjdXJzb3I7XG59XG5cbndpbmRvdy5hZGRFdmVudExpc3RlbmVyKCdtb3VzZW1vdmUnLCBmdW5jdGlvbiAoZSkge1xuICAgIGlmICh3aW5kb3cud2FpbHMuZmxhZ3Muc2hvdWxkRHJhZykge1xuICAgICAgICB3aW5kb3cud2FpbHMuZmxhZ3Muc2hvdWxkRHJhZyA9IGZhbHNlO1xuICAgICAgICBsZXQgbW91c2VQcmVzc2VkID0gZS5idXR0b25zICE9PSB1bmRlZmluZWQgPyBlLmJ1dHRvbnMgOiBlLndoaWNoO1xuICAgICAgICBpZiAobW91c2VQcmVzc2VkID4gMCkge1xuICAgICAgICAgICAgd2luZG93LldhaWxzSW52b2tlKFwiZHJhZ1wiKTtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgIH1cbiAgICBpZiAoIXdpbmRvdy53YWlscy5mbGFncy5lbmFibGVSZXNpemUpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICBpZiAod2luZG93LndhaWxzLmZsYWdzLmRlZmF1bHRDdXJzb3IgPT0gbnVsbCkge1xuICAgICAgICB3aW5kb3cud2FpbHMuZmxhZ3MuZGVmYXVsdEN1cnNvciA9IGRvY3VtZW50LmRvY3VtZW50RWxlbWVudC5zdHlsZS5jdXJzb3I7XG4gICAgfVxuICAgIGlmICh3aW5kb3cub3V0ZXJXaWR0aCAtIGUuY2xpZW50WCA8IHdpbmRvdy53YWlscy5mbGFncy5ib3JkZXJUaGlja25lc3MgJiYgd2luZG93Lm91dGVySGVpZ2h0IC0gZS5jbGllbnRZIDwgd2luZG93LndhaWxzLmZsYWdzLmJvcmRlclRoaWNrbmVzcykge1xuICAgICAgICBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQuc3R5bGUuY3Vyc29yID0gXCJzZS1yZXNpemVcIjtcbiAgICB9XG4gICAgbGV0IHJpZ2h0Qm9yZGVyID0gd2luZG93Lm91dGVyV2lkdGggLSBlLmNsaWVudFggPCB3aW5kb3cud2FpbHMuZmxhZ3MuYm9yZGVyVGhpY2tuZXNzO1xuICAgIGxldCBsZWZ0Qm9yZGVyID0gZS5jbGllbnRYIDwgd2luZG93LndhaWxzLmZsYWdzLmJvcmRlclRoaWNrbmVzcztcbiAgICBsZXQgdG9wQm9yZGVyID0gZS5jbGllbnRZIDwgd2luZG93LndhaWxzLmZsYWdzLmJvcmRlclRoaWNrbmVzcztcbiAgICBsZXQgYm90dG9tQm9yZGVyID0gd2luZG93Lm91dGVySGVpZ2h0IC0gZS5jbGllbnRZIDwgd2luZG93LndhaWxzLmZsYWdzLmJvcmRlclRoaWNrbmVzcztcblxuICAgIC8vIElmIHdlIGFyZW4ndCBvbiBhbiBlZGdlLCBidXQgd2VyZSwgcmVzZXQgdGhlIGN1cnNvciB0byBkZWZhdWx0XG4gICAgaWYgKCFsZWZ0Qm9yZGVyICYmICFyaWdodEJvcmRlciAmJiAhdG9wQm9yZGVyICYmICFib3R0b21Cb3JkZXIgJiYgd2luZG93LndhaWxzLmZsYWdzLnJlc2l6ZUVkZ2UgIT09IHVuZGVmaW5lZCkge1xuICAgICAgICBzZXRSZXNpemUoKTtcbiAgICB9IGVsc2UgaWYgKHJpZ2h0Qm9yZGVyICYmIGJvdHRvbUJvcmRlcikgc2V0UmVzaXplKFwic2UtcmVzaXplXCIpO1xuICAgIGVsc2UgaWYgKGxlZnRCb3JkZXIgJiYgYm90dG9tQm9yZGVyKSBzZXRSZXNpemUoXCJzdy1yZXNpemVcIik7XG4gICAgZWxzZSBpZiAobGVmdEJvcmRlciAmJiB0b3BCb3JkZXIpIHNldFJlc2l6ZShcIm53LXJlc2l6ZVwiKTtcbiAgICBlbHNlIGlmICh0b3BCb3JkZXIgJiYgcmlnaHRCb3JkZXIpIHNldFJlc2l6ZShcIm5lLXJlc2l6ZVwiKTtcbiAgICBlbHNlIGlmIChsZWZ0Qm9yZGVyKSBzZXRSZXNpemUoXCJ3LXJlc2l6ZVwiKTtcbiAgICBlbHNlIGlmICh0b3BCb3JkZXIpIHNldFJlc2l6ZShcIm4tcmVzaXplXCIpO1xuICAgIGVsc2UgaWYgKGJvdHRvbUJvcmRlcikgc2V0UmVzaXplKFwicy1yZXNpemVcIik7XG4gICAgZWxzZSBpZiAocmlnaHRCb3JkZXIpIHNldFJlc2l6ZShcImUtcmVzaXplXCIpO1xuXG59KTtcblxuLy8gU2V0dXAgY29udGV4dCBtZW51IGhvb2tcbndpbmRvdy5hZGRFdmVudExpc3RlbmVyKCdjb250ZXh0bWVudScsIGZ1bmN0aW9uIChlKSB7XG4gICAgLy8gYWx3YXlzIHNob3cgdGhlIGNvbnRleHRtZW51IGluIGRlYnVnICYgZGV2XG4gICAgaWYgKERFQlVHKSByZXR1cm47XG5cbiAgICBpZiAod2luZG93LndhaWxzLmZsYWdzLmRpc2FibGVEZWZhdWx0Q29udGV4dE1lbnUpIHtcbiAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIENvbnRleHRNZW51LnByb2Nlc3NEZWZhdWx0Q29udGV4dE1lbnUoZSk7XG4gICAgfVxufSk7XG5cbndpbmRvdy5XYWlsc0ludm9rZShcInJ1bnRpbWU6cmVhZHlcIik7Il0sCiAgIm1hcHBpbmdzIjogIjs7Ozs7Ozs7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFrQkEsV0FBUyxlQUFlLE9BQU8sU0FBUztBQUl2QyxXQUFPLFlBQVksTUFBTSxRQUFRLE9BQU87QUFBQSxFQUN6QztBQVFPLFdBQVMsU0FBUyxTQUFTO0FBQ2pDLG1CQUFlLEtBQUssT0FBTztBQUFBLEVBQzVCO0FBUU8sV0FBUyxTQUFTLFNBQVM7QUFDakMsbUJBQWUsS0FBSyxPQUFPO0FBQUEsRUFDNUI7QUFRTyxXQUFTLFNBQVMsU0FBUztBQUNqQyxtQkFBZSxLQUFLLE9BQU87QUFBQSxFQUM1QjtBQVFPLFdBQVMsUUFBUSxTQUFTO0FBQ2hDLG1CQUFlLEtBQUssT0FBTztBQUFBLEVBQzVCO0FBUU8sV0FBUyxXQUFXLFNBQVM7QUFDbkMsbUJBQWUsS0FBSyxPQUFPO0FBQUEsRUFDNUI7QUFRTyxXQUFTLFNBQVMsU0FBUztBQUNqQyxtQkFBZSxLQUFLLE9BQU87QUFBQSxFQUM1QjtBQVFPLFdBQVMsU0FBUyxTQUFTO0FBQ2pDLG1CQUFlLEtBQUssT0FBTztBQUFBLEVBQzVCO0FBUU8sV0FBUyxZQUFZLFVBQVU7QUFDckMsbUJBQWUsS0FBSyxRQUFRO0FBQUEsRUFDN0I7QUFHTyxNQUFNLFdBQVc7QUFBQSxJQUN2QixPQUFPO0FBQUEsSUFDUCxPQUFPO0FBQUEsSUFDUCxNQUFNO0FBQUEsSUFDTixTQUFTO0FBQUEsSUFDVCxPQUFPO0FBQUEsRUFDUjs7O0FDOUZBLE1BQU0sV0FBTixNQUFlO0FBQUEsSUFRWCxZQUFZLFdBQVcsVUFBVSxjQUFjO0FBQzNDLFdBQUssWUFBWTtBQUVqQixXQUFLLGVBQWUsZ0JBQWdCO0FBR3BDLFdBQUssV0FBVyxDQUFDLFNBQVM7QUFDdEIsaUJBQVMsTUFBTSxNQUFNLElBQUk7QUFFekIsWUFBSSxLQUFLLGlCQUFpQixJQUFJO0FBQzFCLGlCQUFPO0FBQUEsUUFDWDtBQUVBLGFBQUssZ0JBQWdCO0FBQ3JCLGVBQU8sS0FBSyxpQkFBaUI7QUFBQSxNQUNqQztBQUFBLElBQ0o7QUFBQSxFQUNKO0FBRU8sTUFBTSxpQkFBaUIsQ0FBQztBQVd4QixXQUFTLGlCQUFpQixXQUFXLFVBQVUsY0FBYztBQUNoRSxtQkFBZSxhQUFhLGVBQWUsY0FBYyxDQUFDO0FBQzFELFVBQU0sZUFBZSxJQUFJLFNBQVMsV0FBVyxVQUFVLFlBQVk7QUFDbkUsbUJBQWUsV0FBVyxLQUFLLFlBQVk7QUFDM0MsV0FBTyxNQUFNLFlBQVksWUFBWTtBQUFBLEVBQ3pDO0FBVU8sV0FBUyxTQUFTLFdBQVcsVUFBVTtBQUMxQyxXQUFPLGlCQUFpQixXQUFXLFVBQVUsRUFBRTtBQUFBLEVBQ25EO0FBVU8sV0FBUyxXQUFXLFdBQVcsVUFBVTtBQUM1QyxXQUFPLGlCQUFpQixXQUFXLFVBQVUsQ0FBQztBQUFBLEVBQ2xEO0FBRUEsV0FBUyxnQkFBZ0IsV0FBVztBQUdoQyxRQUFJLFlBQVksVUFBVTtBQUcxQixRQUFJLGVBQWUsWUFBWTtBQUczQixZQUFNLHVCQUF1QixlQUFlLFdBQVcsTUFBTTtBQUc3RCxlQUFTLFFBQVEsZUFBZSxXQUFXLFNBQVMsR0FBRyxTQUFTLEdBQUcsU0FBUyxHQUFHO0FBRzNFLGNBQU0sV0FBVyxlQUFlLFdBQVc7QUFFM0MsWUFBSSxPQUFPLFVBQVU7QUFHckIsY0FBTSxVQUFVLFNBQVMsU0FBUyxJQUFJO0FBQ3RDLFlBQUksU0FBUztBQUVULCtCQUFxQixPQUFPLE9BQU8sQ0FBQztBQUFBLFFBQ3hDO0FBQUEsTUFDSjtBQUdBLFVBQUkscUJBQXFCLFdBQVcsR0FBRztBQUNuQyx1QkFBZSxTQUFTO0FBQUEsTUFDNUIsT0FBTztBQUNILHVCQUFlLGFBQWE7QUFBQSxNQUNoQztBQUFBLElBQ0o7QUFBQSxFQUNKO0FBU08sV0FBUyxhQUFhLGVBQWU7QUFFeEMsUUFBSTtBQUNKLFFBQUk7QUFDQSxnQkFBVSxLQUFLLE1BQU0sYUFBYTtBQUFBLElBQ3RDLFNBQVMsR0FBUDtBQUNFLFlBQU0sUUFBUSxvQ0FBb0M7QUFDbEQsWUFBTSxJQUFJLE1BQU0sS0FBSztBQUFBLElBQ3pCO0FBQ0Esb0JBQWdCLE9BQU87QUFBQSxFQUMzQjtBQVFPLFdBQVMsV0FBVyxXQUFXO0FBRWxDLFVBQU0sVUFBVTtBQUFBLE1BQ1osTUFBTTtBQUFBLE1BQ04sTUFBTSxDQUFDLEVBQUUsTUFBTSxNQUFNLFNBQVMsRUFBRSxNQUFNLENBQUM7QUFBQSxJQUMzQztBQUdBLG9CQUFnQixPQUFPO0FBR3ZCLFdBQU8sWUFBWSxPQUFPLEtBQUssVUFBVSxPQUFPLENBQUM7QUFBQSxFQUNyRDtBQUVBLFdBQVMsZUFBZSxXQUFXO0FBRS9CLFdBQU8sZUFBZTtBQUd0QixXQUFPLFlBQVksT0FBTyxTQUFTO0FBQUEsRUFDdkM7QUFTTyxXQUFTLFVBQVUsY0FBYyxzQkFBc0I7QUFDMUQsbUJBQWUsU0FBUztBQUV4QixRQUFJLHFCQUFxQixTQUFTLEdBQUc7QUFDakMsMkJBQXFCLFFBQVEsQ0FBQUEsZUFBYTtBQUN0Qyx1QkFBZUEsVUFBUztBQUFBLE1BQzVCLENBQUM7QUFBQSxJQUNMO0FBQUEsRUFDSjtBQWlCQyxXQUFTLFlBQVksVUFBVTtBQUM1QixVQUFNLFlBQVksU0FBUztBQUUzQixtQkFBZSxhQUFhLGVBQWUsV0FBVyxPQUFPLE9BQUssTUFBTSxRQUFRO0FBR2hGLFFBQUksZUFBZSxXQUFXLFdBQVcsR0FBRztBQUN4QyxxQkFBZSxTQUFTO0FBQUEsSUFDNUI7QUFBQSxFQUNKOzs7QUN4TU8sTUFBTSxZQUFZLENBQUM7QUFPMUIsV0FBUyxlQUFlO0FBQ3ZCLFFBQUksUUFBUSxJQUFJLFlBQVksQ0FBQztBQUM3QixXQUFPLE9BQU8sT0FBTyxnQkFBZ0IsS0FBSyxFQUFFO0FBQUEsRUFDN0M7QUFRQSxXQUFTLGNBQWM7QUFDdEIsV0FBTyxLQUFLLE9BQU8sSUFBSTtBQUFBLEVBQ3hCO0FBR0EsTUFBSTtBQUNKLE1BQUksT0FBTyxRQUFRO0FBQ2xCLGlCQUFhO0FBQUEsRUFDZCxPQUFPO0FBQ04saUJBQWE7QUFBQSxFQUNkO0FBaUJPLFdBQVMsS0FBSyxNQUFNLE1BQU0sU0FBUztBQUd6QyxRQUFJLFdBQVcsTUFBTTtBQUNwQixnQkFBVTtBQUFBLElBQ1g7QUFHQSxXQUFPLElBQUksUUFBUSxTQUFVLFNBQVMsUUFBUTtBQUc3QyxVQUFJO0FBQ0osU0FBRztBQUNGLHFCQUFhLE9BQU8sTUFBTSxXQUFXO0FBQUEsTUFDdEMsU0FBUyxVQUFVO0FBRW5CLFVBQUk7QUFFSixVQUFJLFVBQVUsR0FBRztBQUNoQix3QkFBZ0IsV0FBVyxXQUFZO0FBQ3RDLGlCQUFPLE1BQU0sYUFBYSxPQUFPLDZCQUE2QixVQUFVLENBQUM7QUFBQSxRQUMxRSxHQUFHLE9BQU87QUFBQSxNQUNYO0FBR0EsZ0JBQVUsY0FBYztBQUFBLFFBQ3ZCO0FBQUEsUUFDQTtBQUFBLFFBQ0E7QUFBQSxNQUNEO0FBRUEsVUFBSTtBQUNILGNBQU0sVUFBVTtBQUFBLFVBQ2Y7QUFBQSxVQUNBO0FBQUEsVUFDQTtBQUFBLFFBQ0Q7QUFHUyxlQUFPLFlBQVksTUFBTSxLQUFLLFVBQVUsT0FBTyxDQUFDO0FBQUEsTUFDcEQsU0FBUyxHQUFQO0FBRUUsZ0JBQVEsTUFBTSxDQUFDO0FBQUEsTUFDbkI7QUFBQSxJQUNKLENBQUM7QUFBQSxFQUNMO0FBRUEsU0FBTyxpQkFBaUIsQ0FBQyxJQUFJLE1BQU0sWUFBWTtBQUczQyxRQUFJLFdBQVcsTUFBTTtBQUNqQixnQkFBVTtBQUFBLElBQ2Q7QUFHQSxXQUFPLElBQUksUUFBUSxTQUFVLFNBQVMsUUFBUTtBQUcxQyxVQUFJO0FBQ0osU0FBRztBQUNDLHFCQUFhLEtBQUssTUFBTSxXQUFXO0FBQUEsTUFDdkMsU0FBUyxVQUFVO0FBRW5CLFVBQUk7QUFFSixVQUFJLFVBQVUsR0FBRztBQUNiLHdCQUFnQixXQUFXLFdBQVk7QUFDbkMsaUJBQU8sTUFBTSxvQkFBb0IsS0FBSyw2QkFBNkIsVUFBVSxDQUFDO0FBQUEsUUFDbEYsR0FBRyxPQUFPO0FBQUEsTUFDZDtBQUdBLGdCQUFVLGNBQWM7QUFBQSxRQUNwQjtBQUFBLFFBQ0E7QUFBQSxRQUNBO0FBQUEsTUFDSjtBQUVBLFVBQUk7QUFDQSxjQUFNLFVBQVU7QUFBQSxVQUN4QjtBQUFBLFVBQ0E7QUFBQSxVQUNBO0FBQUEsUUFDRDtBQUdTLGVBQU8sWUFBWSxNQUFNLEtBQUssVUFBVSxPQUFPLENBQUM7QUFBQSxNQUNwRCxTQUFTLEdBQVA7QUFFRSxnQkFBUSxNQUFNLENBQUM7QUFBQSxNQUNuQjtBQUFBLElBQ0osQ0FBQztBQUFBLEVBQ0w7QUFVTyxXQUFTLFNBQVMsaUJBQWlCO0FBRXpDLFFBQUk7QUFDSixRQUFJO0FBQ0gsZ0JBQVUsS0FBSyxNQUFNLGVBQWU7QUFBQSxJQUNyQyxTQUFTLEdBQVA7QUFDRCxZQUFNLFFBQVEsb0NBQW9DLEVBQUUscUJBQXFCO0FBQ3pFLGNBQVEsU0FBUyxLQUFLO0FBQ3RCLFlBQU0sSUFBSSxNQUFNLEtBQUs7QUFBQSxJQUN0QjtBQUNBLFFBQUksYUFBYSxRQUFRO0FBQ3pCLFFBQUksZUFBZSxVQUFVO0FBQzdCLFFBQUksQ0FBQyxjQUFjO0FBQ2xCLFlBQU0sUUFBUSxhQUFhO0FBQzNCLGNBQVEsTUFBTSxLQUFLO0FBQ25CLFlBQU0sSUFBSSxNQUFNLEtBQUs7QUFBQSxJQUN0QjtBQUNBLGlCQUFhLGFBQWEsYUFBYTtBQUV2QyxXQUFPLFVBQVU7QUFFakIsUUFBSSxRQUFRLE9BQU87QUFDbEIsbUJBQWEsT0FBTyxRQUFRLEtBQUs7QUFBQSxJQUNsQyxPQUFPO0FBQ04sbUJBQWEsUUFBUSxRQUFRLE1BQU07QUFBQSxJQUNwQztBQUFBLEVBQ0Q7OztBQzFLQSxTQUFPLEtBQUssQ0FBQztBQUVOLFdBQVMsWUFBWSxhQUFhO0FBQ3hDLFFBQUk7QUFDSCxvQkFBYyxLQUFLLE1BQU0sV0FBVztBQUFBLElBQ3JDLFNBQVMsR0FBUDtBQUNELGNBQVEsTUFBTSxDQUFDO0FBQUEsSUFDaEI7QUFHQSxXQUFPLEtBQUssT0FBTyxNQUFNLENBQUM7QUFHMUIsV0FBTyxLQUFLLFdBQVcsRUFBRSxRQUFRLENBQUMsZ0JBQWdCO0FBR2pELGFBQU8sR0FBRyxlQUFlLE9BQU8sR0FBRyxnQkFBZ0IsQ0FBQztBQUdwRCxhQUFPLEtBQUssWUFBWSxZQUFZLEVBQUUsUUFBUSxDQUFDLGVBQWU7QUFHN0QsZUFBTyxHQUFHLGFBQWEsY0FBYyxPQUFPLEdBQUcsYUFBYSxlQUFlLENBQUM7QUFFNUUsZUFBTyxLQUFLLFlBQVksYUFBYSxXQUFXLEVBQUUsUUFBUSxDQUFDLGVBQWU7QUFFekUsaUJBQU8sR0FBRyxhQUFhLFlBQVksY0FBYyxXQUFZO0FBRzVELGdCQUFJLFVBQVU7QUFHZCxxQkFBUyxVQUFVO0FBQ2xCLG9CQUFNLE9BQU8sQ0FBQyxFQUFFLE1BQU0sS0FBSyxTQUFTO0FBQ3BDLHFCQUFPLEtBQUssQ0FBQyxhQUFhLFlBQVksVUFBVSxFQUFFLEtBQUssR0FBRyxHQUFHLE1BQU0sT0FBTztBQUFBLFlBQzNFO0FBR0Esb0JBQVEsYUFBYSxTQUFVLFlBQVk7QUFDMUMsd0JBQVU7QUFBQSxZQUNYO0FBR0Esb0JBQVEsYUFBYSxXQUFZO0FBQ2hDLHFCQUFPO0FBQUEsWUFDUjtBQUVBLG1CQUFPO0FBQUEsVUFDUixFQUFFO0FBQUEsUUFDSCxDQUFDO0FBQUEsTUFDRixDQUFDO0FBQUEsSUFDRixDQUFDO0FBQUEsRUFDRjs7O0FDbEVBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBZU8sV0FBUyxlQUFlO0FBQzNCLFdBQU8sU0FBUyxPQUFPO0FBQUEsRUFDM0I7QUFFTyxXQUFTLGtCQUFrQjtBQUM5QixXQUFPLFlBQVksSUFBSTtBQUFBLEVBQzNCO0FBRU8sV0FBUyw4QkFBOEI7QUFDMUMsV0FBTyxZQUFZLE9BQU87QUFBQSxFQUM5QjtBQUVPLFdBQVMsc0JBQXNCO0FBQ2xDLFdBQU8sWUFBWSxNQUFNO0FBQUEsRUFDN0I7QUFFTyxXQUFTLHFCQUFxQjtBQUNqQyxXQUFPLFlBQVksTUFBTTtBQUFBLEVBQzdCO0FBT08sV0FBUyxlQUFlO0FBQzNCLFdBQU8sWUFBWSxJQUFJO0FBQUEsRUFDM0I7QUFRTyxXQUFTLGVBQWUsT0FBTztBQUNsQyxXQUFPLFlBQVksT0FBTyxLQUFLO0FBQUEsRUFDbkM7QUFPTyxXQUFTLG1CQUFtQjtBQUMvQixXQUFPLFlBQVksSUFBSTtBQUFBLEVBQzNCO0FBT08sV0FBUyxxQkFBcUI7QUFDakMsV0FBTyxZQUFZLElBQUk7QUFBQSxFQUMzQjtBQVFPLFdBQVMscUJBQXFCO0FBQ2pDLFdBQU8sS0FBSywyQkFBMkI7QUFBQSxFQUMzQztBQVNPLFdBQVMsY0FBYyxPQUFPLFFBQVE7QUFDekMsV0FBTyxZQUFZLFFBQVEsUUFBUSxNQUFNLE1BQU07QUFBQSxFQUNuRDtBQVNPLFdBQVMsZ0JBQWdCO0FBQzVCLFdBQU8sS0FBSyxzQkFBc0I7QUFBQSxFQUN0QztBQVNPLFdBQVMsaUJBQWlCLE9BQU8sUUFBUTtBQUM1QyxXQUFPLFlBQVksUUFBUSxRQUFRLE1BQU0sTUFBTTtBQUFBLEVBQ25EO0FBU08sV0FBUyxpQkFBaUIsT0FBTyxRQUFRO0FBQzVDLFdBQU8sWUFBWSxRQUFRLFFBQVEsTUFBTSxNQUFNO0FBQUEsRUFDbkQ7QUFTTyxXQUFTLHFCQUFxQixHQUFHO0FBRXBDLFdBQU8sWUFBWSxXQUFXLElBQUksTUFBTSxJQUFJO0FBQUEsRUFDaEQ7QUFZTyxXQUFTLGtCQUFrQixHQUFHLEdBQUc7QUFDcEMsV0FBTyxZQUFZLFFBQVEsSUFBSSxNQUFNLENBQUM7QUFBQSxFQUMxQztBQVFPLFdBQVMsb0JBQW9CO0FBQ2hDLFdBQU8sS0FBSyxxQkFBcUI7QUFBQSxFQUNyQztBQU9PLFdBQVMsYUFBYTtBQUN6QixXQUFPLFlBQVksSUFBSTtBQUFBLEVBQzNCO0FBT08sV0FBUyxhQUFhO0FBQ3pCLFdBQU8sWUFBWSxJQUFJO0FBQUEsRUFDM0I7QUFPTyxXQUFTLGlCQUFpQjtBQUM3QixXQUFPLFlBQVksSUFBSTtBQUFBLEVBQzNCO0FBT08sV0FBUyx1QkFBdUI7QUFDbkMsV0FBTyxZQUFZLElBQUk7QUFBQSxFQUMzQjtBQU9PLFdBQVMsbUJBQW1CO0FBQy9CLFdBQU8sWUFBWSxJQUFJO0FBQUEsRUFDM0I7QUFRTyxXQUFTLG9CQUFvQjtBQUNoQyxXQUFPLEtBQUssMEJBQTBCO0FBQUEsRUFDMUM7QUFPTyxXQUFTLGlCQUFpQjtBQUM3QixXQUFPLFlBQVksSUFBSTtBQUFBLEVBQzNCO0FBT08sV0FBUyxtQkFBbUI7QUFDL0IsV0FBTyxZQUFZLElBQUk7QUFBQSxFQUMzQjtBQVFPLFdBQVMsb0JBQW9CO0FBQ2hDLFdBQU8sS0FBSywwQkFBMEI7QUFBQSxFQUMxQztBQVFPLFdBQVMsaUJBQWlCO0FBQzdCLFdBQU8sS0FBSyx1QkFBdUI7QUFBQSxFQUN2QztBQVdPLFdBQVMsMEJBQTBCLEdBQUcsR0FBRyxHQUFHLEdBQUc7QUFDbEQsUUFBSSxPQUFPLEtBQUssVUFBVSxFQUFDLEdBQUcsS0FBSyxHQUFHLEdBQUcsS0FBSyxHQUFHLEdBQUcsS0FBSyxHQUFHLEdBQUcsS0FBSyxJQUFHLENBQUM7QUFDeEUsV0FBTyxZQUFZLFFBQVEsSUFBSTtBQUFBLEVBQ25DOzs7QUMzUUE7QUFBQTtBQUFBO0FBQUE7QUFzQk8sV0FBUyxlQUFlO0FBQzNCLFdBQU8sS0FBSyxxQkFBcUI7QUFBQSxFQUNyQzs7O0FDeEJBO0FBQUE7QUFBQTtBQUFBO0FBS08sV0FBUyxlQUFlLEtBQUs7QUFDbEMsV0FBTyxZQUFZLFFBQVEsR0FBRztBQUFBLEVBQ2hDOzs7QUNQQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBb0JPLFdBQVMsaUJBQWlCLE1BQU07QUFDbkMsV0FBTyxLQUFLLDJCQUEyQixDQUFDLElBQUksQ0FBQztBQUFBLEVBQ2pEO0FBU08sV0FBUyxtQkFBbUI7QUFDL0IsV0FBTyxLQUFLLHlCQUF5QjtBQUFBLEVBQ3pDOzs7QUNqQ0E7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFjQSxNQUFNLFFBQVE7QUFBQSxJQUNWLFlBQVk7QUFBQSxJQUNaLHNCQUFzQjtBQUFBLElBQ3RCLGVBQWU7QUFBQSxJQUNmLGdCQUFnQjtBQUFBLElBQ2hCLHVCQUF1QjtBQUFBLEVBQzNCO0FBRUEsTUFBTSxxQkFBcUI7QUFRM0IsV0FBUyxxQkFBcUIsT0FBTztBQUNqQyxVQUFNLGVBQWUsTUFBTSxpQkFBaUIsT0FBTyxNQUFNLE1BQU0sZUFBZSxFQUFFLEtBQUs7QUFDckYsUUFBSSxjQUFjO0FBQ2QsVUFBSSxpQkFBaUIsT0FBTyxNQUFNLE1BQU0sY0FBYztBQUNsRCxlQUFPO0FBQUEsTUFDWDtBQUlBLGFBQU87QUFBQSxJQUNYO0FBQ0EsV0FBTztBQUFBLEVBQ1g7QUFPQSxXQUFTLFdBQVcsR0FBRztBQUNuQixRQUFJLENBQUMsT0FBTyxNQUFNLE1BQU0sd0JBQXdCO0FBQzVDO0FBQUEsSUFDSjtBQUNBLE1BQUUsZUFBZTtBQUVqQixRQUFJLENBQUMsTUFBTSxlQUFlO0FBQ3RCO0FBQUEsSUFDSjtBQUVBLFVBQU0sVUFBVSxFQUFFO0FBR2xCLFFBQUcsTUFBTTtBQUFnQixZQUFNLGVBQWU7QUFHOUMsUUFBSSxDQUFDLFdBQVcsQ0FBQyxxQkFBcUIsaUJBQWlCLE9BQU8sQ0FBQyxHQUFHO0FBQzlEO0FBQUEsSUFDSjtBQUVBLFFBQUksaUJBQWlCO0FBQ3JCLFdBQU8sZ0JBQWdCO0FBRW5CLFVBQUkscUJBQXFCLGVBQWUsS0FBSyxHQUFHO0FBQzVDLHVCQUFlLFVBQVUsSUFBSSxrQkFBa0I7QUFBQSxNQUNuRDtBQUNBLHVCQUFpQixlQUFlO0FBQUEsSUFDcEM7QUFBQSxFQUNKO0FBT0EsV0FBUyxZQUFZLEdBQUc7QUFDcEIsUUFBSSxDQUFDLE9BQU8sTUFBTSxNQUFNLHdCQUF3QjtBQUM1QztBQUFBLElBQ0o7QUFDQSxNQUFFLGVBQWU7QUFFakIsUUFBSSxDQUFDLE1BQU0sZUFBZTtBQUN0QjtBQUFBLElBQ0o7QUFHQSxRQUFJLENBQUMsRUFBRSxVQUFVLENBQUMscUJBQXFCLGlCQUFpQixFQUFFLE1BQU0sQ0FBQyxHQUFHO0FBQ2hFLGFBQU87QUFBQSxJQUNYO0FBR0EsUUFBRyxNQUFNO0FBQWdCLFlBQU0sZUFBZTtBQUc5QyxVQUFNLGlCQUFpQixNQUFNO0FBRXpCLFlBQU0sS0FBSyxTQUFTLHVCQUF1QixrQkFBa0IsQ0FBQyxFQUFFLFFBQVEsUUFBTSxHQUFHLFVBQVUsT0FBTyxrQkFBa0IsQ0FBQztBQUVySCxZQUFNLGlCQUFpQjtBQUV2QixVQUFJLE1BQU0sdUJBQXVCO0FBQzdCLHFCQUFhLE1BQU0scUJBQXFCO0FBQ3hDLGNBQU0sd0JBQXdCO0FBQUEsTUFDbEM7QUFBQSxJQUNKO0FBR0EsVUFBTSx3QkFBd0IsV0FBVyxNQUFNO0FBQzNDLFVBQUcsTUFBTTtBQUFnQixjQUFNLGVBQWU7QUFBQSxJQUNsRCxHQUFHLEVBQUU7QUFBQSxFQUNUO0FBT0EsV0FBUyxPQUFPLEdBQUc7QUFDZixRQUFJLENBQUMsT0FBTyxNQUFNLE1BQU0sd0JBQXdCO0FBQzVDO0FBQUEsSUFDSjtBQUNBLE1BQUUsZUFBZTtBQUVqQixRQUFJLENBQUMsTUFBTSxlQUFlO0FBQ3RCO0FBQUEsSUFDSjtBQUdBLFFBQUcsTUFBTTtBQUFnQixZQUFNLGVBQWU7QUFHOUMsVUFBTSxLQUFLLFNBQVMsdUJBQXVCLGtCQUFrQixDQUFDLEVBQUUsUUFBUSxRQUFNLEdBQUcsVUFBVSxPQUFPLGtCQUFrQixDQUFDO0FBRXJILFFBQUksb0JBQW9CLEdBQUc7QUFFdkIsVUFBSSxRQUFRLENBQUM7QUFDYixVQUFJLEVBQUUsYUFBYSxPQUFPO0FBQ3RCLGdCQUFRLENBQUMsR0FBRyxFQUFFLGFBQWEsS0FBSyxFQUFFLElBQUksQ0FBQyxNQUFNLE1BQU07QUFDL0MsY0FBSSxLQUFLLFNBQVMsUUFBUTtBQUN0QixtQkFBTyxLQUFLLFVBQVU7QUFBQSxVQUMxQjtBQUFBLFFBQ0osQ0FBQztBQUFBLE1BQ0wsT0FBTztBQUNILGdCQUFRLENBQUMsR0FBRyxFQUFFLGFBQWEsS0FBSztBQUFBLE1BQ3BDO0FBQ0EsYUFBTyxRQUFRLGlCQUFpQixFQUFFLEdBQUcsRUFBRSxHQUFHLEtBQUs7QUFBQSxJQUNuRDtBQUFBLEVBQ0o7QUFRTyxXQUFTLHNCQUFzQjtBQUNsQyxXQUFPLE9BQU8sUUFBUSxTQUFTLG9DQUFvQztBQUFBLEVBQ3ZFO0FBVU8sV0FBUyxpQkFBaUIsR0FBRyxHQUFHLE9BQU87QUFHMUMsUUFBSSxPQUFPLFFBQVEsU0FBUyxrQ0FBa0M7QUFDMUQsYUFBTyxRQUFRLGlDQUFpQyxhQUFhLEtBQUssS0FBSyxLQUFLO0FBQUEsSUFDaEY7QUFBQSxFQUNKO0FBbUJPLFdBQVMsV0FBVyxVQUFVLGVBQWU7QUFDaEQsUUFBSSxPQUFPLGFBQWEsWUFBWTtBQUNoQyxjQUFRLE1BQU0sdUNBQXVDO0FBQ3JEO0FBQUEsSUFDSjtBQUVBLFFBQUksTUFBTSxZQUFZO0FBQ2xCO0FBQUEsSUFDSjtBQUNBLFVBQU0sYUFBYTtBQUVuQixVQUFNLFFBQVEsT0FBTztBQUNyQixVQUFNLGdCQUFnQixVQUFVLGVBQWUsVUFBVSxZQUFZLE1BQU0sdUJBQXVCO0FBQ2xHLFdBQU8saUJBQWlCLFlBQVksVUFBVTtBQUM5QyxXQUFPLGlCQUFpQixhQUFhLFdBQVc7QUFDaEQsV0FBTyxpQkFBaUIsUUFBUSxNQUFNO0FBRXRDLFFBQUksS0FBSztBQUNULFFBQUksTUFBTSxlQUFlO0FBQ3JCLFdBQUssU0FBVSxHQUFHLEdBQUcsT0FBTztBQUN4QixjQUFNLFVBQVUsU0FBUyxpQkFBaUIsR0FBRyxDQUFDO0FBRTlDLFlBQUksQ0FBQyxXQUFXLENBQUMscUJBQXFCLGlCQUFpQixPQUFPLENBQUMsR0FBRztBQUM5RCxpQkFBTztBQUFBLFFBQ1g7QUFDQSxpQkFBUyxHQUFHLEdBQUcsS0FBSztBQUFBLE1BQ3hCO0FBQUEsSUFDSjtBQUVBLGFBQVMsbUJBQW1CLEVBQUU7QUFBQSxFQUNsQztBQUtPLFdBQVMsZ0JBQWdCO0FBQzVCLFdBQU8sb0JBQW9CLFlBQVksVUFBVTtBQUNqRCxXQUFPLG9CQUFvQixhQUFhLFdBQVc7QUFDbkQsV0FBTyxvQkFBb0IsUUFBUSxNQUFNO0FBQ3pDLGNBQVUsaUJBQWlCO0FBQzNCLFVBQU0sYUFBYTtBQUFBLEVBQ3ZCOzs7QUMzT08sV0FBUywwQkFBMEIsT0FBTztBQUU3QyxVQUFNLFVBQVUsTUFBTTtBQUN0QixVQUFNLGdCQUFnQixPQUFPLGlCQUFpQixPQUFPO0FBQ3JELFVBQU0sMkJBQTJCLGNBQWMsaUJBQWlCLHVCQUF1QixFQUFFLEtBQUs7QUFDOUYsWUFBUSwwQkFBMEI7QUFBQSxNQUM5QixLQUFLO0FBQ0Q7QUFBQSxNQUNKLEtBQUs7QUFDRCxjQUFNLGVBQWU7QUFDckI7QUFBQSxNQUNKO0FBRUksWUFBSSxRQUFRLG1CQUFtQjtBQUMzQjtBQUFBLFFBQ0o7QUFHQSxjQUFNLFlBQVksT0FBTyxhQUFhO0FBQ3RDLGNBQU0sZUFBZ0IsVUFBVSxTQUFTLEVBQUUsU0FBUztBQUNwRCxZQUFJLGNBQWM7QUFDZCxtQkFBUyxJQUFJLEdBQUcsSUFBSSxVQUFVLFlBQVksS0FBSztBQUMzQyxrQkFBTSxRQUFRLFVBQVUsV0FBVyxDQUFDO0FBQ3BDLGtCQUFNLFFBQVEsTUFBTSxlQUFlO0FBQ25DLHFCQUFTLElBQUksR0FBRyxJQUFJLE1BQU0sUUFBUSxLQUFLO0FBQ25DLG9CQUFNLE9BQU8sTUFBTTtBQUNuQixrQkFBSSxTQUFTLGlCQUFpQixLQUFLLE1BQU0sS0FBSyxHQUFHLE1BQU0sU0FBUztBQUM1RDtBQUFBLGNBQ0o7QUFBQSxZQUNKO0FBQUEsVUFDSjtBQUFBLFFBQ0o7QUFFQSxZQUFJLFFBQVEsWUFBWSxXQUFXLFFBQVEsWUFBWSxZQUFZO0FBQy9ELGNBQUksZ0JBQWlCLENBQUMsUUFBUSxZQUFZLENBQUMsUUFBUSxVQUFXO0FBQzFEO0FBQUEsVUFDSjtBQUFBLFFBQ0o7QUFHQSxjQUFNLGVBQWU7QUFBQSxJQUM3QjtBQUFBLEVBQ0o7OztBQzVCTyxXQUFTLE9BQU87QUFDbkIsV0FBTyxZQUFZLEdBQUc7QUFBQSxFQUMxQjtBQUVPLFdBQVMsT0FBTztBQUNuQixXQUFPLFlBQVksR0FBRztBQUFBLEVBQzFCO0FBRU8sV0FBUyxPQUFPO0FBQ25CLFdBQU8sWUFBWSxHQUFHO0FBQUEsRUFDMUI7QUFFTyxXQUFTLGNBQWM7QUFDMUIsV0FBTyxLQUFLLG9CQUFvQjtBQUFBLEVBQ3BDO0FBR0EsU0FBTyxVQUFVO0FBQUEsSUFDYixHQUFHO0FBQUEsSUFDSCxHQUFHO0FBQUEsSUFDSCxHQUFHO0FBQUEsSUFDSCxHQUFHO0FBQUEsSUFDSCxHQUFHO0FBQUEsSUFDSCxHQUFHO0FBQUEsSUFDSDtBQUFBLElBQ0E7QUFBQSxJQUNBO0FBQUEsSUFDQTtBQUFBLElBQ0E7QUFBQSxJQUNBO0FBQUEsSUFDQTtBQUFBLElBQ0E7QUFBQSxJQUNBO0FBQUEsRUFDSjtBQUdBLFNBQU8sUUFBUTtBQUFBLElBQ1g7QUFBQSxJQUNBO0FBQUEsSUFDQTtBQUFBLElBQ0E7QUFBQSxJQUNBO0FBQUEsSUFDQSxPQUFPO0FBQUEsTUFDSCxzQkFBc0I7QUFBQSxNQUN0QiwyQkFBMkI7QUFBQSxNQUMzQixjQUFjO0FBQUEsTUFDZCxlQUFlO0FBQUEsTUFDZixpQkFBaUI7QUFBQSxNQUNqQixZQUFZO0FBQUEsTUFDWixzQkFBc0I7QUFBQSxNQUN0QixpQkFBaUI7QUFBQSxNQUNqQixjQUFjO0FBQUEsTUFDZCxpQkFBaUI7QUFBQSxNQUNqQixjQUFjO0FBQUEsTUFDZCx3QkFBd0I7QUFBQSxJQUM1QjtBQUFBLEVBQ0o7QUFHQSxNQUFJLE9BQU8sZUFBZTtBQUN0QixXQUFPLE1BQU0sWUFBWSxPQUFPLGFBQWE7QUFDN0MsV0FBTyxPQUFPLE1BQU07QUFBQSxFQUN4QjtBQUdBLE1BQUksT0FBUTtBQUNSLFdBQU8sT0FBTztBQUFBLEVBQ2xCO0FBRUEsTUFBSSxXQUFXLFNBQVUsR0FBRztBQUN4QixRQUFJLE1BQU0sT0FBTyxpQkFBaUIsRUFBRSxNQUFNLEVBQUUsaUJBQWlCLE9BQU8sTUFBTSxNQUFNLGVBQWU7QUFDL0YsUUFBSSxLQUFLO0FBQ1AsWUFBTSxJQUFJLEtBQUs7QUFBQSxJQUNqQjtBQUVBLFFBQUksUUFBUSxPQUFPLE1BQU0sTUFBTSxjQUFjO0FBQ3pDLGFBQU87QUFBQSxJQUNYO0FBRUEsUUFBSSxFQUFFLFlBQVksR0FBRztBQUVqQixhQUFPO0FBQUEsSUFDWDtBQUVBLFFBQUksRUFBRSxXQUFXLEdBQUc7QUFFaEIsYUFBTztBQUFBLElBQ1g7QUFFQSxXQUFPO0FBQUEsRUFDWDtBQUVBLFNBQU8sTUFBTSx1QkFBdUIsU0FBVSxVQUFVLE9BQU87QUFDM0QsV0FBTyxNQUFNLE1BQU0sa0JBQWtCO0FBQ3JDLFdBQU8sTUFBTSxNQUFNLGVBQWU7QUFBQSxFQUN0QztBQUVBLFNBQU8sTUFBTSx1QkFBdUIsU0FBVSxVQUFVLE9BQU87QUFDM0QsV0FBTyxNQUFNLE1BQU0sa0JBQWtCO0FBQ3JDLFdBQU8sTUFBTSxNQUFNLGVBQWU7QUFBQSxFQUN0QztBQUVBLFNBQU8saUJBQWlCLGFBQWEsQ0FBQyxNQUFNO0FBRXhDLFFBQUksT0FBTyxNQUFNLE1BQU0sWUFBWTtBQUMvQixhQUFPLFlBQVksWUFBWSxPQUFPLE1BQU0sTUFBTSxVQUFVO0FBQzVELFFBQUUsZUFBZTtBQUNqQjtBQUFBLElBQ0o7QUFFQSxRQUFJLFNBQVMsQ0FBQyxHQUFHO0FBQ2IsVUFBSSxPQUFPLE1BQU0sTUFBTSxzQkFBc0I7QUFFekMsWUFBSSxFQUFFLFVBQVUsRUFBRSxPQUFPLGVBQWUsRUFBRSxVQUFVLEVBQUUsT0FBTyxjQUFjO0FBQ3ZFO0FBQUEsUUFDSjtBQUFBLE1BQ0o7QUFDQSxVQUFJLE9BQU8sTUFBTSxNQUFNLHNCQUFzQjtBQUN6QyxlQUFPLE1BQU0sTUFBTSxhQUFhO0FBQUEsTUFDcEMsT0FBTztBQUNILFVBQUUsZUFBZTtBQUNqQixlQUFPLFlBQVksTUFBTTtBQUFBLE1BQzdCO0FBQ0E7QUFBQSxJQUNKLE9BQU87QUFDSCxhQUFPLE1BQU0sTUFBTSxhQUFhO0FBQUEsSUFDcEM7QUFBQSxFQUNKLENBQUM7QUFFRCxTQUFPLGlCQUFpQixXQUFXLE1BQU07QUFDckMsV0FBTyxNQUFNLE1BQU0sYUFBYTtBQUFBLEVBQ3BDLENBQUM7QUFFRCxXQUFTLFVBQVUsUUFBUTtBQUN2QixhQUFTLGdCQUFnQixNQUFNLFNBQVMsVUFBVSxPQUFPLE1BQU0sTUFBTTtBQUNyRSxXQUFPLE1BQU0sTUFBTSxhQUFhO0FBQUEsRUFDcEM7QUFFQSxTQUFPLGlCQUFpQixhQUFhLFNBQVUsR0FBRztBQUM5QyxRQUFJLE9BQU8sTUFBTSxNQUFNLFlBQVk7QUFDL0IsYUFBTyxNQUFNLE1BQU0sYUFBYTtBQUNoQyxVQUFJLGVBQWUsRUFBRSxZQUFZLFNBQVksRUFBRSxVQUFVLEVBQUU7QUFDM0QsVUFBSSxlQUFlLEdBQUc7QUFDbEIsZUFBTyxZQUFZLE1BQU07QUFDekI7QUFBQSxNQUNKO0FBQUEsSUFDSjtBQUNBLFFBQUksQ0FBQyxPQUFPLE1BQU0sTUFBTSxjQUFjO0FBQ2xDO0FBQUEsSUFDSjtBQUNBLFFBQUksT0FBTyxNQUFNLE1BQU0saUJBQWlCLE1BQU07QUFDMUMsYUFBTyxNQUFNLE1BQU0sZ0JBQWdCLFNBQVMsZ0JBQWdCLE1BQU07QUFBQSxJQUN0RTtBQUNBLFFBQUksT0FBTyxhQUFhLEVBQUUsVUFBVSxPQUFPLE1BQU0sTUFBTSxtQkFBbUIsT0FBTyxjQUFjLEVBQUUsVUFBVSxPQUFPLE1BQU0sTUFBTSxpQkFBaUI7QUFDM0ksZUFBUyxnQkFBZ0IsTUFBTSxTQUFTO0FBQUEsSUFDNUM7QUFDQSxRQUFJLGNBQWMsT0FBTyxhQUFhLEVBQUUsVUFBVSxPQUFPLE1BQU0sTUFBTTtBQUNyRSxRQUFJLGFBQWEsRUFBRSxVQUFVLE9BQU8sTUFBTSxNQUFNO0FBQ2hELFFBQUksWUFBWSxFQUFFLFVBQVUsT0FBTyxNQUFNLE1BQU07QUFDL0MsUUFBSSxlQUFlLE9BQU8sY0FBYyxFQUFFLFVBQVUsT0FBTyxNQUFNLE1BQU07QUFHdkUsUUFBSSxDQUFDLGNBQWMsQ0FBQyxlQUFlLENBQUMsYUFBYSxDQUFDLGdCQUFnQixPQUFPLE1BQU0sTUFBTSxlQUFlLFFBQVc7QUFDM0csZ0JBQVU7QUFBQSxJQUNkLFdBQVcsZUFBZTtBQUFjLGdCQUFVLFdBQVc7QUFBQSxhQUNwRCxjQUFjO0FBQWMsZ0JBQVUsV0FBVztBQUFBLGFBQ2pELGNBQWM7QUFBVyxnQkFBVSxXQUFXO0FBQUEsYUFDOUMsYUFBYTtBQUFhLGdCQUFVLFdBQVc7QUFBQSxhQUMvQztBQUFZLGdCQUFVLFVBQVU7QUFBQSxhQUNoQztBQUFXLGdCQUFVLFVBQVU7QUFBQSxhQUMvQjtBQUFjLGdCQUFVLFVBQVU7QUFBQSxhQUNsQztBQUFhLGdCQUFVLFVBQVU7QUFBQSxFQUU5QyxDQUFDO0FBR0QsU0FBTyxpQkFBaUIsZUFBZSxTQUFVLEdBQUc7QUFFaEQsUUFBSTtBQUFPO0FBRVgsUUFBSSxPQUFPLE1BQU0sTUFBTSwyQkFBMkI7QUFDOUMsUUFBRSxlQUFlO0FBQUEsSUFDckIsT0FBTztBQUNILE1BQVksMEJBQTBCLENBQUM7QUFBQSxJQUMzQztBQUFBLEVBQ0osQ0FBQztBQUVELFNBQU8sWUFBWSxlQUFlOyIsCiAgIm5hbWVzIjogWyJldmVudE5hbWUiXQp9Cg== +//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiZGVza3RvcC9sb2cuanMiLCAiZGVza3RvcC9ldmVudHMuanMiLCAiZGVza3RvcC9jYWxscy5qcyIsICJkZXNrdG9wL2JpbmRpbmdzLmpzIiwgImRlc2t0b3Avd2luZG93LmpzIiwgImRlc2t0b3Avc2NyZWVuLmpzIiwgImRlc2t0b3AvYnJvd3Nlci5qcyIsICJkZXNrdG9wL2NsaXBib2FyZC5qcyIsICJkZXNrdG9wL2RyYWdhbmRkcm9wLmpzIiwgImRlc2t0b3AvY29udGV4dG1lbnUuanMiLCAiZGVza3RvcC9tYWluLmpzIl0sCiAgInNvdXJjZXNDb250ZW50IjogWyIvKlxyXG4gXyAgICAgICBfXyAgICAgIF8gX19cclxufCB8ICAgICAvIC9fX18gXyhfKSAvX19fX1xyXG58IHwgL3wgLyAvIF9fIGAvIC8gLyBfX18vXHJcbnwgfC8gfC8gLyAvXy8gLyAvIChfXyAgKVxyXG58X18vfF9fL1xcX18sXy9fL18vX19fXy9cclxuVGhlIGVsZWN0cm9uIGFsdGVybmF0aXZlIGZvciBHb1xyXG4oYykgTGVhIEFudGhvbnkgMjAxOS1wcmVzZW50XHJcbiovXHJcblxyXG4vKiBqc2hpbnQgZXN2ZXJzaW9uOiA2ICovXHJcblxyXG4vKipcclxuICogU2VuZHMgYSBsb2cgbWVzc2FnZSB0byB0aGUgYmFja2VuZCB3aXRoIHRoZSBnaXZlbiBsZXZlbCArIG1lc3NhZ2VcclxuICpcclxuICogQHBhcmFtIHtzdHJpbmd9IGxldmVsXHJcbiAqIEBwYXJhbSB7c3RyaW5nfSBtZXNzYWdlXHJcbiAqL1xyXG5mdW5jdGlvbiBzZW5kTG9nTWVzc2FnZShsZXZlbCwgbWVzc2FnZSkge1xyXG5cclxuXHQvLyBMb2cgTWVzc2FnZSBmb3JtYXQ6XHJcblx0Ly8gbFt0eXBlXVttZXNzYWdlXVxyXG5cdHdpbmRvdy5XYWlsc0ludm9rZSgnTCcgKyBsZXZlbCArIG1lc3NhZ2UpO1xyXG59XHJcblxyXG4vKipcclxuICogTG9nIHRoZSBnaXZlbiB0cmFjZSBtZXNzYWdlIHdpdGggdGhlIGJhY2tlbmRcclxuICpcclxuICogQGV4cG9ydFxyXG4gKiBAcGFyYW0ge3N0cmluZ30gbWVzc2FnZVxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIExvZ1RyYWNlKG1lc3NhZ2UpIHtcclxuXHRzZW5kTG9nTWVzc2FnZSgnVCcsIG1lc3NhZ2UpO1xyXG59XHJcblxyXG4vKipcclxuICogTG9nIHRoZSBnaXZlbiBtZXNzYWdlIHdpdGggdGhlIGJhY2tlbmRcclxuICpcclxuICogQGV4cG9ydFxyXG4gKiBAcGFyYW0ge3N0cmluZ30gbWVzc2FnZVxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIExvZ1ByaW50KG1lc3NhZ2UpIHtcclxuXHRzZW5kTG9nTWVzc2FnZSgnUCcsIG1lc3NhZ2UpO1xyXG59XHJcblxyXG4vKipcclxuICogTG9nIHRoZSBnaXZlbiBkZWJ1ZyBtZXNzYWdlIHdpdGggdGhlIGJhY2tlbmRcclxuICpcclxuICogQGV4cG9ydFxyXG4gKiBAcGFyYW0ge3N0cmluZ30gbWVzc2FnZVxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIExvZ0RlYnVnKG1lc3NhZ2UpIHtcclxuXHRzZW5kTG9nTWVzc2FnZSgnRCcsIG1lc3NhZ2UpO1xyXG59XHJcblxyXG4vKipcclxuICogTG9nIHRoZSBnaXZlbiBpbmZvIG1lc3NhZ2Ugd2l0aCB0aGUgYmFja2VuZFxyXG4gKlxyXG4gKiBAZXhwb3J0XHJcbiAqIEBwYXJhbSB7c3RyaW5nfSBtZXNzYWdlXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gTG9nSW5mbyhtZXNzYWdlKSB7XHJcblx0c2VuZExvZ01lc3NhZ2UoJ0knLCBtZXNzYWdlKTtcclxufVxyXG5cclxuLyoqXHJcbiAqIExvZyB0aGUgZ2l2ZW4gd2FybmluZyBtZXNzYWdlIHdpdGggdGhlIGJhY2tlbmRcclxuICpcclxuICogQGV4cG9ydFxyXG4gKiBAcGFyYW0ge3N0cmluZ30gbWVzc2FnZVxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIExvZ1dhcm5pbmcobWVzc2FnZSkge1xyXG5cdHNlbmRMb2dNZXNzYWdlKCdXJywgbWVzc2FnZSk7XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBMb2cgdGhlIGdpdmVuIGVycm9yIG1lc3NhZ2Ugd2l0aCB0aGUgYmFja2VuZFxyXG4gKlxyXG4gKiBAZXhwb3J0XHJcbiAqIEBwYXJhbSB7c3RyaW5nfSBtZXNzYWdlXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gTG9nRXJyb3IobWVzc2FnZSkge1xyXG5cdHNlbmRMb2dNZXNzYWdlKCdFJywgbWVzc2FnZSk7XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBMb2cgdGhlIGdpdmVuIGZhdGFsIG1lc3NhZ2Ugd2l0aCB0aGUgYmFja2VuZFxyXG4gKlxyXG4gKiBAZXhwb3J0XHJcbiAqIEBwYXJhbSB7c3RyaW5nfSBtZXNzYWdlXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gTG9nRmF0YWwobWVzc2FnZSkge1xyXG5cdHNlbmRMb2dNZXNzYWdlKCdGJywgbWVzc2FnZSk7XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBTZXRzIHRoZSBMb2cgbGV2ZWwgdG8gdGhlIGdpdmVuIGxvZyBsZXZlbFxyXG4gKlxyXG4gKiBAZXhwb3J0XHJcbiAqIEBwYXJhbSB7bnVtYmVyfSBsb2dsZXZlbFxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIFNldExvZ0xldmVsKGxvZ2xldmVsKSB7XHJcblx0c2VuZExvZ01lc3NhZ2UoJ1MnLCBsb2dsZXZlbCk7XHJcbn1cclxuXHJcbi8vIExvZyBsZXZlbHNcclxuZXhwb3J0IGNvbnN0IExvZ0xldmVsID0ge1xyXG5cdFRSQUNFOiAxLFxyXG5cdERFQlVHOiAyLFxyXG5cdElORk86IDMsXHJcblx0V0FSTklORzogNCxcclxuXHRFUlJPUjogNSxcclxufTtcclxuIiwgIi8qXHJcbiBfICAgICAgIF9fICAgICAgXyBfX1xyXG58IHwgICAgIC8gL19fXyBfKF8pIC9fX19fXHJcbnwgfCAvfCAvIC8gX18gYC8gLyAvIF9fXy9cclxufCB8LyB8LyAvIC9fLyAvIC8gKF9fICApXHJcbnxfXy98X18vXFxfXyxfL18vXy9fX19fL1xyXG5UaGUgZWxlY3Ryb24gYWx0ZXJuYXRpdmUgZm9yIEdvXHJcbihjKSBMZWEgQW50aG9ueSAyMDE5LXByZXNlbnRcclxuKi9cclxuLyoganNoaW50IGVzdmVyc2lvbjogNiAqL1xyXG5cclxuLy8gRGVmaW5lcyBhIHNpbmdsZSBsaXN0ZW5lciB3aXRoIGEgbWF4aW11bSBudW1iZXIgb2YgdGltZXMgdG8gY2FsbGJhY2tcclxuXHJcbi8qKlxyXG4gKiBUaGUgTGlzdGVuZXIgY2xhc3MgZGVmaW5lcyBhIGxpc3RlbmVyISA6LSlcclxuICpcclxuICogQGNsYXNzIExpc3RlbmVyXHJcbiAqL1xyXG5jbGFzcyBMaXN0ZW5lciB7XHJcbiAgICAvKipcclxuICAgICAqIENyZWF0ZXMgYW4gaW5zdGFuY2Ugb2YgTGlzdGVuZXIuXHJcbiAgICAgKiBAcGFyYW0ge3N0cmluZ30gZXZlbnROYW1lXHJcbiAgICAgKiBAcGFyYW0ge2Z1bmN0aW9ufSBjYWxsYmFja1xyXG4gICAgICogQHBhcmFtIHtudW1iZXJ9IG1heENhbGxiYWNrc1xyXG4gICAgICogQG1lbWJlcm9mIExpc3RlbmVyXHJcbiAgICAgKi9cclxuICAgIGNvbnN0cnVjdG9yKGV2ZW50TmFtZSwgY2FsbGJhY2ssIG1heENhbGxiYWNrcykge1xyXG4gICAgICAgIHRoaXMuZXZlbnROYW1lID0gZXZlbnROYW1lO1xyXG4gICAgICAgIC8vIERlZmF1bHQgb2YgLTEgbWVhbnMgaW5maW5pdGVcclxuICAgICAgICB0aGlzLm1heENhbGxiYWNrcyA9IG1heENhbGxiYWNrcyB8fCAtMTtcclxuICAgICAgICAvLyBDYWxsYmFjayBpbnZva2VzIHRoZSBjYWxsYmFjayB3aXRoIHRoZSBnaXZlbiBkYXRhXHJcbiAgICAgICAgLy8gUmV0dXJucyB0cnVlIGlmIHRoaXMgbGlzdGVuZXIgc2hvdWxkIGJlIGRlc3Ryb3llZFxyXG4gICAgICAgIHRoaXMuQ2FsbGJhY2sgPSAoZGF0YSkgPT4ge1xyXG4gICAgICAgICAgICBjYWxsYmFjay5hcHBseShudWxsLCBkYXRhKTtcclxuICAgICAgICAgICAgLy8gSWYgbWF4Q2FsbGJhY2tzIGlzIGluZmluaXRlLCByZXR1cm4gZmFsc2UgKGRvIG5vdCBkZXN0cm95KVxyXG4gICAgICAgICAgICBpZiAodGhpcy5tYXhDYWxsYmFja3MgPT09IC0xKSB7XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gZmFsc2U7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgLy8gRGVjcmVtZW50IG1heENhbGxiYWNrcy4gUmV0dXJuIHRydWUgaWYgbm93IDAsIG90aGVyd2lzZSBmYWxzZVxyXG4gICAgICAgICAgICB0aGlzLm1heENhbGxiYWNrcyAtPSAxO1xyXG4gICAgICAgICAgICByZXR1cm4gdGhpcy5tYXhDYWxsYmFja3MgPT09IDA7XHJcbiAgICAgICAgfTtcclxuICAgIH1cclxufVxyXG5cclxuZXhwb3J0IGNvbnN0IGV2ZW50TGlzdGVuZXJzID0ge307XHJcblxyXG4vKipcclxuICogUmVnaXN0ZXJzIGFuIGV2ZW50IGxpc3RlbmVyIHRoYXQgd2lsbCBiZSBpbnZva2VkIGBtYXhDYWxsYmFja3NgIHRpbWVzIGJlZm9yZSBiZWluZyBkZXN0cm95ZWRcclxuICpcclxuICogQGV4cG9ydFxyXG4gKiBAcGFyYW0ge3N0cmluZ30gZXZlbnROYW1lXHJcbiAqIEBwYXJhbSB7ZnVuY3Rpb259IGNhbGxiYWNrXHJcbiAqIEBwYXJhbSB7bnVtYmVyfSBtYXhDYWxsYmFja3NcclxuICogQHJldHVybnMge2Z1bmN0aW9ufSBBIGZ1bmN0aW9uIHRvIGNhbmNlbCB0aGUgbGlzdGVuZXJcclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBFdmVudHNPbk11bHRpcGxlKGV2ZW50TmFtZSwgY2FsbGJhY2ssIG1heENhbGxiYWNrcykge1xyXG4gICAgZXZlbnRMaXN0ZW5lcnNbZXZlbnROYW1lXSA9IGV2ZW50TGlzdGVuZXJzW2V2ZW50TmFtZV0gfHwgW107XHJcbiAgICBjb25zdCB0aGlzTGlzdGVuZXIgPSBuZXcgTGlzdGVuZXIoZXZlbnROYW1lLCBjYWxsYmFjaywgbWF4Q2FsbGJhY2tzKTtcclxuICAgIGV2ZW50TGlzdGVuZXJzW2V2ZW50TmFtZV0ucHVzaCh0aGlzTGlzdGVuZXIpO1xyXG4gICAgcmV0dXJuICgpID0+IGxpc3RlbmVyT2ZmKHRoaXNMaXN0ZW5lcik7XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBSZWdpc3RlcnMgYW4gZXZlbnQgbGlzdGVuZXIgdGhhdCB3aWxsIGJlIGludm9rZWQgZXZlcnkgdGltZSB0aGUgZXZlbnQgaXMgZW1pdHRlZFxyXG4gKlxyXG4gKiBAZXhwb3J0XHJcbiAqIEBwYXJhbSB7c3RyaW5nfSBldmVudE5hbWVcclxuICogQHBhcmFtIHtmdW5jdGlvbn0gY2FsbGJhY2tcclxuICogQHJldHVybnMge2Z1bmN0aW9ufSBBIGZ1bmN0aW9uIHRvIGNhbmNlbCB0aGUgbGlzdGVuZXJcclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBFdmVudHNPbihldmVudE5hbWUsIGNhbGxiYWNrKSB7XHJcbiAgICByZXR1cm4gRXZlbnRzT25NdWx0aXBsZShldmVudE5hbWUsIGNhbGxiYWNrLCAtMSk7XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBSZWdpc3RlcnMgYW4gZXZlbnQgbGlzdGVuZXIgdGhhdCB3aWxsIGJlIGludm9rZWQgb25jZSB0aGVuIGRlc3Ryb3llZFxyXG4gKlxyXG4gKiBAZXhwb3J0XHJcbiAqIEBwYXJhbSB7c3RyaW5nfSBldmVudE5hbWVcclxuICogQHBhcmFtIHtmdW5jdGlvbn0gY2FsbGJhY2tcclxuICogQHJldHVybnMge2Z1bmN0aW9ufSBBIGZ1bmN0aW9uIHRvIGNhbmNlbCB0aGUgbGlzdGVuZXJcclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBFdmVudHNPbmNlKGV2ZW50TmFtZSwgY2FsbGJhY2spIHtcclxuICAgIHJldHVybiBFdmVudHNPbk11bHRpcGxlKGV2ZW50TmFtZSwgY2FsbGJhY2ssIDEpO1xyXG59XHJcblxyXG5mdW5jdGlvbiBub3RpZnlMaXN0ZW5lcnMoZXZlbnREYXRhKSB7XHJcblxyXG4gICAgLy8gR2V0IHRoZSBldmVudCBuYW1lXHJcbiAgICBsZXQgZXZlbnROYW1lID0gZXZlbnREYXRhLm5hbWU7XHJcblxyXG4gICAgLy8gS2VlcCBhIGxpc3Qgb2YgbGlzdGVuZXIgaW5kZXhlcyB0byBkZXN0cm95XHJcbiAgICBjb25zdCBuZXdFdmVudExpc3RlbmVyTGlzdCA9IGV2ZW50TGlzdGVuZXJzW2V2ZW50TmFtZV0/LnNsaWNlKCkgfHwgW107XHJcblxyXG4gICAgLy8gQ2hlY2sgaWYgd2UgaGF2ZSBhbnkgbGlzdGVuZXJzIGZvciB0aGlzIGV2ZW50XHJcbiAgICBpZiAobmV3RXZlbnRMaXN0ZW5lckxpc3QubGVuZ3RoKSB7XHJcblxyXG4gICAgICAgIC8vIEl0ZXJhdGUgbGlzdGVuZXJzXHJcbiAgICAgICAgZm9yIChsZXQgY291bnQgPSBuZXdFdmVudExpc3RlbmVyTGlzdC5sZW5ndGggLSAxOyBjb3VudCA+PSAwOyBjb3VudCAtPSAxKSB7XHJcblxyXG4gICAgICAgICAgICAvLyBHZXQgbmV4dCBsaXN0ZW5lclxyXG4gICAgICAgICAgICBjb25zdCBsaXN0ZW5lciA9IG5ld0V2ZW50TGlzdGVuZXJMaXN0W2NvdW50XTtcclxuXHJcbiAgICAgICAgICAgIGxldCBkYXRhID0gZXZlbnREYXRhLmRhdGE7XHJcblxyXG4gICAgICAgICAgICAvLyBEbyB0aGUgY2FsbGJhY2tcclxuICAgICAgICAgICAgY29uc3QgZGVzdHJveSA9IGxpc3RlbmVyLkNhbGxiYWNrKGRhdGEpO1xyXG4gICAgICAgICAgICBpZiAoZGVzdHJveSkge1xyXG4gICAgICAgICAgICAgICAgLy8gaWYgdGhlIGxpc3RlbmVyIGluZGljYXRlZCB0byBkZXN0cm95IGl0c2VsZiwgYWRkIGl0IHRvIHRoZSBkZXN0cm95IGxpc3RcclxuICAgICAgICAgICAgICAgIG5ld0V2ZW50TGlzdGVuZXJMaXN0LnNwbGljZShjb3VudCwgMSk7XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIC8vIFVwZGF0ZSBjYWxsYmFja3Mgd2l0aCBuZXcgbGlzdCBvZiBsaXN0ZW5lcnNcclxuICAgICAgICBpZiAobmV3RXZlbnRMaXN0ZW5lckxpc3QubGVuZ3RoID09PSAwKSB7XHJcbiAgICAgICAgICAgIHJlbW92ZUxpc3RlbmVyKGV2ZW50TmFtZSk7XHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgZXZlbnRMaXN0ZW5lcnNbZXZlbnROYW1lXSA9IG5ld0V2ZW50TGlzdGVuZXJMaXN0O1xyXG4gICAgICAgIH1cclxuICAgIH1cclxufVxyXG5cclxuLyoqXHJcbiAqIE5vdGlmeSBpbmZvcm1zIGZyb250ZW5kIGxpc3RlbmVycyB0aGF0IGFuIGV2ZW50IHdhcyBlbWl0dGVkIHdpdGggdGhlIGdpdmVuIGRhdGFcclxuICpcclxuICogQGV4cG9ydFxyXG4gKiBAcGFyYW0ge3N0cmluZ30gbm90aWZ5TWVzc2FnZSAtIGVuY29kZWQgbm90aWZpY2F0aW9uIG1lc3NhZ2VcclxuXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gRXZlbnRzTm90aWZ5KG5vdGlmeU1lc3NhZ2UpIHtcclxuICAgIC8vIFBhcnNlIHRoZSBtZXNzYWdlXHJcbiAgICBsZXQgbWVzc2FnZTtcclxuICAgIHRyeSB7XHJcbiAgICAgICAgbWVzc2FnZSA9IEpTT04ucGFyc2Uobm90aWZ5TWVzc2FnZSk7XHJcbiAgICB9IGNhdGNoIChlKSB7XHJcbiAgICAgICAgY29uc3QgZXJyb3IgPSAnSW52YWxpZCBKU09OIHBhc3NlZCB0byBOb3RpZnk6ICcgKyBub3RpZnlNZXNzYWdlO1xyXG4gICAgICAgIHRocm93IG5ldyBFcnJvcihlcnJvcik7XHJcbiAgICB9XHJcbiAgICBub3RpZnlMaXN0ZW5lcnMobWVzc2FnZSk7XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBFbWl0IGFuIGV2ZW50IHdpdGggdGhlIGdpdmVuIG5hbWUgYW5kIGRhdGFcclxuICpcclxuICogQGV4cG9ydFxyXG4gKiBAcGFyYW0ge3N0cmluZ30gZXZlbnROYW1lXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gRXZlbnRzRW1pdChldmVudE5hbWUpIHtcclxuXHJcbiAgICBjb25zdCBwYXlsb2FkID0ge1xyXG4gICAgICAgIG5hbWU6IGV2ZW50TmFtZSxcclxuICAgICAgICBkYXRhOiBbXS5zbGljZS5hcHBseShhcmd1bWVudHMpLnNsaWNlKDEpLFxyXG4gICAgfTtcclxuXHJcbiAgICAvLyBOb3RpZnkgSlMgbGlzdGVuZXJzXHJcbiAgICBub3RpZnlMaXN0ZW5lcnMocGF5bG9hZCk7XHJcblxyXG4gICAgLy8gTm90aWZ5IEdvIGxpc3RlbmVyc1xyXG4gICAgd2luZG93LldhaWxzSW52b2tlKCdFRScgKyBKU09OLnN0cmluZ2lmeShwYXlsb2FkKSk7XHJcbn1cclxuXHJcbmZ1bmN0aW9uIHJlbW92ZUxpc3RlbmVyKGV2ZW50TmFtZSkge1xyXG4gICAgLy8gUmVtb3ZlIGxvY2FsIGxpc3RlbmVyc1xyXG4gICAgZGVsZXRlIGV2ZW50TGlzdGVuZXJzW2V2ZW50TmFtZV07XHJcblxyXG4gICAgLy8gTm90aWZ5IEdvIGxpc3RlbmVyc1xyXG4gICAgd2luZG93LldhaWxzSW52b2tlKCdFWCcgKyBldmVudE5hbWUpO1xyXG59XHJcblxyXG4vKipcclxuICogT2ZmIHVucmVnaXN0ZXJzIGEgbGlzdGVuZXIgcHJldmlvdXNseSByZWdpc3RlcmVkIHdpdGggT24sXHJcbiAqIG9wdGlvbmFsbHkgbXVsdGlwbGUgbGlzdGVuZXJlcyBjYW4gYmUgdW5yZWdpc3RlcmVkIHZpYSBgYWRkaXRpb25hbEV2ZW50TmFtZXNgXHJcbiAqXHJcbiAqIEBwYXJhbSB7c3RyaW5nfSBldmVudE5hbWVcclxuICogQHBhcmFtICB7Li4uc3RyaW5nfSBhZGRpdGlvbmFsRXZlbnROYW1lc1xyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIEV2ZW50c09mZihldmVudE5hbWUsIC4uLmFkZGl0aW9uYWxFdmVudE5hbWVzKSB7XHJcbiAgICByZW1vdmVMaXN0ZW5lcihldmVudE5hbWUpXHJcblxyXG4gICAgaWYgKGFkZGl0aW9uYWxFdmVudE5hbWVzLmxlbmd0aCA+IDApIHtcclxuICAgICAgICBhZGRpdGlvbmFsRXZlbnROYW1lcy5mb3JFYWNoKGV2ZW50TmFtZSA9PiB7XHJcbiAgICAgICAgICAgIHJlbW92ZUxpc3RlbmVyKGV2ZW50TmFtZSlcclxuICAgICAgICB9KVxyXG4gICAgfVxyXG59XHJcblxyXG4vKipcclxuICogT2ZmIHVucmVnaXN0ZXJzIGFsbCBldmVudCBsaXN0ZW5lcnMgcHJldmlvdXNseSByZWdpc3RlcmVkIHdpdGggT25cclxuICovXHJcbiBleHBvcnQgZnVuY3Rpb24gRXZlbnRzT2ZmQWxsKCkge1xyXG4gICAgY29uc3QgZXZlbnROYW1lcyA9IE9iamVjdC5rZXlzKGV2ZW50TGlzdGVuZXJzKTtcclxuICAgIGV2ZW50TmFtZXMuZm9yRWFjaChldmVudE5hbWUgPT4ge1xyXG4gICAgICAgIHJlbW92ZUxpc3RlbmVyKGV2ZW50TmFtZSlcclxuICAgIH0pXHJcbn1cclxuXHJcbi8qKlxyXG4gKiBsaXN0ZW5lck9mZiB1bnJlZ2lzdGVycyBhIGxpc3RlbmVyIHByZXZpb3VzbHkgcmVnaXN0ZXJlZCB3aXRoIEV2ZW50c09uXHJcbiAqXHJcbiAqIEBwYXJhbSB7TGlzdGVuZXJ9IGxpc3RlbmVyXHJcbiAqL1xyXG4gZnVuY3Rpb24gbGlzdGVuZXJPZmYobGlzdGVuZXIpIHtcclxuICAgIGNvbnN0IGV2ZW50TmFtZSA9IGxpc3RlbmVyLmV2ZW50TmFtZTtcclxuICAgIGlmIChldmVudExpc3RlbmVyc1tldmVudE5hbWVdID09PSB1bmRlZmluZWQpIHJldHVybjtcclxuXHJcbiAgICAvLyBSZW1vdmUgbG9jYWwgbGlzdGVuZXJcclxuICAgIGV2ZW50TGlzdGVuZXJzW2V2ZW50TmFtZV0gPSBldmVudExpc3RlbmVyc1tldmVudE5hbWVdLmZpbHRlcihsID0+IGwgIT09IGxpc3RlbmVyKTtcclxuXHJcbiAgICAvLyBDbGVhbiB1cCBpZiB0aGVyZSBhcmUgbm8gZXZlbnQgbGlzdGVuZXJzIGxlZnRcclxuICAgIGlmIChldmVudExpc3RlbmVyc1tldmVudE5hbWVdLmxlbmd0aCA9PT0gMCkge1xyXG4gICAgICAgIHJlbW92ZUxpc3RlbmVyKGV2ZW50TmFtZSk7XHJcbiAgICB9XHJcbn1cclxuIiwgIi8qXHJcbiBfICAgICAgIF9fICAgICAgXyBfX1xyXG58IHwgICAgIC8gL19fXyBfKF8pIC9fX19fXHJcbnwgfCAvfCAvIC8gX18gYC8gLyAvIF9fXy9cclxufCB8LyB8LyAvIC9fLyAvIC8gKF9fICApXHJcbnxfXy98X18vXFxfXyxfL18vXy9fX19fL1xyXG5UaGUgZWxlY3Ryb24gYWx0ZXJuYXRpdmUgZm9yIEdvXHJcbihjKSBMZWEgQW50aG9ueSAyMDE5LXByZXNlbnRcclxuKi9cclxuLyoganNoaW50IGVzdmVyc2lvbjogNiAqL1xyXG5cclxuZXhwb3J0IGNvbnN0IGNhbGxiYWNrcyA9IHt9O1xyXG5cclxuLyoqXHJcbiAqIFJldHVybnMgYSBudW1iZXIgZnJvbSB0aGUgbmF0aXZlIGJyb3dzZXIgcmFuZG9tIGZ1bmN0aW9uXHJcbiAqXHJcbiAqIEByZXR1cm5zIG51bWJlclxyXG4gKi9cclxuZnVuY3Rpb24gY3J5cHRvUmFuZG9tKCkge1xyXG5cdHZhciBhcnJheSA9IG5ldyBVaW50MzJBcnJheSgxKTtcclxuXHRyZXR1cm4gd2luZG93LmNyeXB0by5nZXRSYW5kb21WYWx1ZXMoYXJyYXkpWzBdO1xyXG59XHJcblxyXG4vKipcclxuICogUmV0dXJucyBhIG51bWJlciB1c2luZyBkYSBvbGQtc2tvb2wgTWF0aC5SYW5kb21cclxuICogSSBsaWtlcyB0byBjYWxsIGl0IExPTFJhbmRvbVxyXG4gKlxyXG4gKiBAcmV0dXJucyBudW1iZXJcclxuICovXHJcbmZ1bmN0aW9uIGJhc2ljUmFuZG9tKCkge1xyXG5cdHJldHVybiBNYXRoLnJhbmRvbSgpICogOTAwNzE5OTI1NDc0MDk5MTtcclxufVxyXG5cclxuLy8gUGljayBhIHJhbmRvbSBudW1iZXIgZnVuY3Rpb24gYmFzZWQgb24gYnJvd3NlciBjYXBhYmlsaXR5XHJcbnZhciByYW5kb21GdW5jO1xyXG5pZiAod2luZG93LmNyeXB0bykge1xyXG5cdHJhbmRvbUZ1bmMgPSBjcnlwdG9SYW5kb207XHJcbn0gZWxzZSB7XHJcblx0cmFuZG9tRnVuYyA9IGJhc2ljUmFuZG9tO1xyXG59XHJcblxyXG5cclxuLyoqXHJcbiAqIENhbGwgc2VuZHMgYSBtZXNzYWdlIHRvIHRoZSBiYWNrZW5kIHRvIGNhbGwgdGhlIGJpbmRpbmcgd2l0aCB0aGVcclxuICogZ2l2ZW4gZGF0YS4gQSBwcm9taXNlIGlzIHJldHVybmVkIGFuZCB3aWxsIGJlIGNvbXBsZXRlZCB3aGVuIHRoZVxyXG4gKiBiYWNrZW5kIHJlc3BvbmRzLiBUaGlzIHdpbGwgYmUgcmVzb2x2ZWQgd2hlbiB0aGUgY2FsbCB3YXMgc3VjY2Vzc2Z1bFxyXG4gKiBvciByZWplY3RlZCBpZiBhbiBlcnJvciBpcyBwYXNzZWQgYmFjay5cclxuICogVGhlcmUgaXMgYSB0aW1lb3V0IG1lY2hhbmlzbS4gSWYgdGhlIGNhbGwgZG9lc24ndCByZXNwb25kIGluIHRoZSBnaXZlblxyXG4gKiB0aW1lIChpbiBtaWxsaXNlY29uZHMpIHRoZW4gdGhlIHByb21pc2UgaXMgcmVqZWN0ZWQuXHJcbiAqXHJcbiAqIEBleHBvcnRcclxuICogQHBhcmFtIHtzdHJpbmd9IG5hbWVcclxuICogQHBhcmFtIHthbnk9fSBhcmdzXHJcbiAqIEBwYXJhbSB7bnVtYmVyPX0gdGltZW91dFxyXG4gKiBAcmV0dXJuc1xyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIENhbGwobmFtZSwgYXJncywgdGltZW91dCkge1xyXG5cclxuXHQvLyBUaW1lb3V0IGluZmluaXRlIGJ5IGRlZmF1bHRcclxuXHRpZiAodGltZW91dCA9PSBudWxsKSB7XHJcblx0XHR0aW1lb3V0ID0gMDtcclxuXHR9XHJcblxyXG5cdC8vIENyZWF0ZSBhIHByb21pc2VcclxuXHRyZXR1cm4gbmV3IFByb21pc2UoZnVuY3Rpb24gKHJlc29sdmUsIHJlamVjdCkge1xyXG5cclxuXHRcdC8vIENyZWF0ZSBhIHVuaXF1ZSBjYWxsYmFja0lEXHJcblx0XHR2YXIgY2FsbGJhY2tJRDtcclxuXHRcdGRvIHtcclxuXHRcdFx0Y2FsbGJhY2tJRCA9IG5hbWUgKyAnLScgKyByYW5kb21GdW5jKCk7XHJcblx0XHR9IHdoaWxlIChjYWxsYmFja3NbY2FsbGJhY2tJRF0pO1xyXG5cclxuXHRcdHZhciB0aW1lb3V0SGFuZGxlO1xyXG5cdFx0Ly8gU2V0IHRpbWVvdXRcclxuXHRcdGlmICh0aW1lb3V0ID4gMCkge1xyXG5cdFx0XHR0aW1lb3V0SGFuZGxlID0gc2V0VGltZW91dChmdW5jdGlvbiAoKSB7XHJcblx0XHRcdFx0cmVqZWN0KEVycm9yKCdDYWxsIHRvICcgKyBuYW1lICsgJyB0aW1lZCBvdXQuIFJlcXVlc3QgSUQ6ICcgKyBjYWxsYmFja0lEKSk7XHJcblx0XHRcdH0sIHRpbWVvdXQpO1xyXG5cdFx0fVxyXG5cclxuXHRcdC8vIFN0b3JlIGNhbGxiYWNrXHJcblx0XHRjYWxsYmFja3NbY2FsbGJhY2tJRF0gPSB7XHJcblx0XHRcdHRpbWVvdXRIYW5kbGU6IHRpbWVvdXRIYW5kbGUsXHJcblx0XHRcdHJlamVjdDogcmVqZWN0LFxyXG5cdFx0XHRyZXNvbHZlOiByZXNvbHZlXHJcblx0XHR9O1xyXG5cclxuXHRcdHRyeSB7XHJcblx0XHRcdGNvbnN0IHBheWxvYWQgPSB7XHJcblx0XHRcdFx0bmFtZSxcclxuXHRcdFx0XHRhcmdzLFxyXG5cdFx0XHRcdGNhbGxiYWNrSUQsXHJcblx0XHRcdH07XHJcblxyXG4gICAgICAgICAgICAvLyBNYWtlIHRoZSBjYWxsXHJcbiAgICAgICAgICAgIHdpbmRvdy5XYWlsc0ludm9rZSgnQycgKyBKU09OLnN0cmluZ2lmeShwYXlsb2FkKSk7XHJcbiAgICAgICAgfSBjYXRjaCAoZSkge1xyXG4gICAgICAgICAgICAvLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmVcclxuICAgICAgICAgICAgY29uc29sZS5lcnJvcihlKTtcclxuICAgICAgICB9XHJcbiAgICB9KTtcclxufVxyXG5cclxud2luZG93Lk9iZnVzY2F0ZWRDYWxsID0gKGlkLCBhcmdzLCB0aW1lb3V0KSA9PiB7XHJcblxyXG4gICAgLy8gVGltZW91dCBpbmZpbml0ZSBieSBkZWZhdWx0XHJcbiAgICBpZiAodGltZW91dCA9PSBudWxsKSB7XHJcbiAgICAgICAgdGltZW91dCA9IDA7XHJcbiAgICB9XHJcblxyXG4gICAgLy8gQ3JlYXRlIGEgcHJvbWlzZVxyXG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKGZ1bmN0aW9uIChyZXNvbHZlLCByZWplY3QpIHtcclxuXHJcbiAgICAgICAgLy8gQ3JlYXRlIGEgdW5pcXVlIGNhbGxiYWNrSURcclxuICAgICAgICB2YXIgY2FsbGJhY2tJRDtcclxuICAgICAgICBkbyB7XHJcbiAgICAgICAgICAgIGNhbGxiYWNrSUQgPSBpZCArICctJyArIHJhbmRvbUZ1bmMoKTtcclxuICAgICAgICB9IHdoaWxlIChjYWxsYmFja3NbY2FsbGJhY2tJRF0pO1xyXG5cclxuICAgICAgICB2YXIgdGltZW91dEhhbmRsZTtcclxuICAgICAgICAvLyBTZXQgdGltZW91dFxyXG4gICAgICAgIGlmICh0aW1lb3V0ID4gMCkge1xyXG4gICAgICAgICAgICB0aW1lb3V0SGFuZGxlID0gc2V0VGltZW91dChmdW5jdGlvbiAoKSB7XHJcbiAgICAgICAgICAgICAgICByZWplY3QoRXJyb3IoJ0NhbGwgdG8gbWV0aG9kICcgKyBpZCArICcgdGltZWQgb3V0LiBSZXF1ZXN0IElEOiAnICsgY2FsbGJhY2tJRCkpO1xyXG4gICAgICAgICAgICB9LCB0aW1lb3V0KTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIC8vIFN0b3JlIGNhbGxiYWNrXHJcbiAgICAgICAgY2FsbGJhY2tzW2NhbGxiYWNrSURdID0ge1xyXG4gICAgICAgICAgICB0aW1lb3V0SGFuZGxlOiB0aW1lb3V0SGFuZGxlLFxyXG4gICAgICAgICAgICByZWplY3Q6IHJlamVjdCxcclxuICAgICAgICAgICAgcmVzb2x2ZTogcmVzb2x2ZVxyXG4gICAgICAgIH07XHJcblxyXG4gICAgICAgIHRyeSB7XHJcbiAgICAgICAgICAgIGNvbnN0IHBheWxvYWQgPSB7XHJcblx0XHRcdFx0aWQsXHJcblx0XHRcdFx0YXJncyxcclxuXHRcdFx0XHRjYWxsYmFja0lELFxyXG5cdFx0XHR9O1xyXG5cclxuICAgICAgICAgICAgLy8gTWFrZSB0aGUgY2FsbFxyXG4gICAgICAgICAgICB3aW5kb3cuV2FpbHNJbnZva2UoJ2MnICsgSlNPTi5zdHJpbmdpZnkocGF5bG9hZCkpO1xyXG4gICAgICAgIH0gY2F0Y2ggKGUpIHtcclxuICAgICAgICAgICAgLy8gZXNsaW50LWRpc2FibGUtbmV4dC1saW5lXHJcbiAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoZSk7XHJcbiAgICAgICAgfVxyXG4gICAgfSk7XHJcbn07XHJcblxyXG5cclxuLyoqXHJcbiAqIENhbGxlZCBieSB0aGUgYmFja2VuZCB0byByZXR1cm4gZGF0YSB0byBhIHByZXZpb3VzbHkgY2FsbGVkXHJcbiAqIGJpbmRpbmcgaW52b2NhdGlvblxyXG4gKlxyXG4gKiBAZXhwb3J0XHJcbiAqIEBwYXJhbSB7c3RyaW5nfSBpbmNvbWluZ01lc3NhZ2VcclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBDYWxsYmFjayhpbmNvbWluZ01lc3NhZ2UpIHtcclxuXHQvLyBQYXJzZSB0aGUgbWVzc2FnZVxyXG5cdGxldCBtZXNzYWdlO1xyXG5cdHRyeSB7XHJcblx0XHRtZXNzYWdlID0gSlNPTi5wYXJzZShpbmNvbWluZ01lc3NhZ2UpO1xyXG5cdH0gY2F0Y2ggKGUpIHtcclxuXHRcdGNvbnN0IGVycm9yID0gYEludmFsaWQgSlNPTiBwYXNzZWQgdG8gY2FsbGJhY2s6ICR7ZS5tZXNzYWdlfS4gTWVzc2FnZTogJHtpbmNvbWluZ01lc3NhZ2V9YDtcclxuXHRcdHJ1bnRpbWUuTG9nRGVidWcoZXJyb3IpO1xyXG5cdFx0dGhyb3cgbmV3IEVycm9yKGVycm9yKTtcclxuXHR9XHJcblx0bGV0IGNhbGxiYWNrSUQgPSBtZXNzYWdlLmNhbGxiYWNraWQ7XHJcblx0bGV0IGNhbGxiYWNrRGF0YSA9IGNhbGxiYWNrc1tjYWxsYmFja0lEXTtcclxuXHRpZiAoIWNhbGxiYWNrRGF0YSkge1xyXG5cdFx0Y29uc3QgZXJyb3IgPSBgQ2FsbGJhY2sgJyR7Y2FsbGJhY2tJRH0nIG5vdCByZWdpc3RlcmVkISEhYDtcclxuXHRcdGNvbnNvbGUuZXJyb3IoZXJyb3IpOyAvLyBlc2xpbnQtZGlzYWJsZS1saW5lXHJcblx0XHR0aHJvdyBuZXcgRXJyb3IoZXJyb3IpO1xyXG5cdH1cclxuXHRjbGVhclRpbWVvdXQoY2FsbGJhY2tEYXRhLnRpbWVvdXRIYW5kbGUpO1xyXG5cclxuXHRkZWxldGUgY2FsbGJhY2tzW2NhbGxiYWNrSURdO1xyXG5cclxuXHRpZiAobWVzc2FnZS5lcnJvcikge1xyXG5cdFx0Y2FsbGJhY2tEYXRhLnJlamVjdChtZXNzYWdlLmVycm9yKTtcclxuXHR9IGVsc2Uge1xyXG5cdFx0Y2FsbGJhY2tEYXRhLnJlc29sdmUobWVzc2FnZS5yZXN1bHQpO1xyXG5cdH1cclxufVxyXG4iLCAiLypcclxuIF8gICAgICAgX18gICAgICBfIF9fICAgIFxyXG58IHwgICAgIC8gL19fXyBfKF8pIC9fX19fXHJcbnwgfCAvfCAvIC8gX18gYC8gLyAvIF9fXy9cclxufCB8LyB8LyAvIC9fLyAvIC8gKF9fICApIFxyXG58X18vfF9fL1xcX18sXy9fL18vX19fXy8gIFxyXG5UaGUgZWxlY3Ryb24gYWx0ZXJuYXRpdmUgZm9yIEdvXHJcbihjKSBMZWEgQW50aG9ueSAyMDE5LXByZXNlbnRcclxuKi9cclxuLyoganNoaW50IGVzdmVyc2lvbjogNiAqL1xyXG5cclxuaW1wb3J0IHtDYWxsfSBmcm9tICcuL2NhbGxzJztcclxuXHJcbi8vIFRoaXMgaXMgd2hlcmUgd2UgYmluZCBnbyBtZXRob2Qgd3JhcHBlcnNcclxud2luZG93LmdvID0ge307XHJcblxyXG5leHBvcnQgZnVuY3Rpb24gU2V0QmluZGluZ3MoYmluZGluZ3NNYXApIHtcclxuXHR0cnkge1xyXG5cdFx0YmluZGluZ3NNYXAgPSBKU09OLnBhcnNlKGJpbmRpbmdzTWFwKTtcclxuXHR9IGNhdGNoIChlKSB7XHJcblx0XHRjb25zb2xlLmVycm9yKGUpO1xyXG5cdH1cclxuXHJcblx0Ly8gSW5pdGlhbGlzZSB0aGUgYmluZGluZ3MgbWFwXHJcblx0d2luZG93LmdvID0gd2luZG93LmdvIHx8IHt9O1xyXG5cclxuXHQvLyBJdGVyYXRlIHBhY2thZ2UgbmFtZXNcclxuXHRPYmplY3Qua2V5cyhiaW5kaW5nc01hcCkuZm9yRWFjaCgocGFja2FnZU5hbWUpID0+IHtcclxuXHJcblx0XHQvLyBDcmVhdGUgaW5uZXIgbWFwIGlmIGl0IGRvZXNuJ3QgZXhpc3RcclxuXHRcdHdpbmRvdy5nb1twYWNrYWdlTmFtZV0gPSB3aW5kb3cuZ29bcGFja2FnZU5hbWVdIHx8IHt9O1xyXG5cclxuXHRcdC8vIEl0ZXJhdGUgc3RydWN0IG5hbWVzXHJcblx0XHRPYmplY3Qua2V5cyhiaW5kaW5nc01hcFtwYWNrYWdlTmFtZV0pLmZvckVhY2goKHN0cnVjdE5hbWUpID0+IHtcclxuXHJcblx0XHRcdC8vIENyZWF0ZSBpbm5lciBtYXAgaWYgaXQgZG9lc24ndCBleGlzdFxyXG5cdFx0XHR3aW5kb3cuZ29bcGFja2FnZU5hbWVdW3N0cnVjdE5hbWVdID0gd2luZG93LmdvW3BhY2thZ2VOYW1lXVtzdHJ1Y3ROYW1lXSB8fCB7fTtcclxuXHJcblx0XHRcdE9iamVjdC5rZXlzKGJpbmRpbmdzTWFwW3BhY2thZ2VOYW1lXVtzdHJ1Y3ROYW1lXSkuZm9yRWFjaCgobWV0aG9kTmFtZSkgPT4ge1xyXG5cclxuXHRcdFx0XHR3aW5kb3cuZ29bcGFja2FnZU5hbWVdW3N0cnVjdE5hbWVdW21ldGhvZE5hbWVdID0gZnVuY3Rpb24gKCkge1xyXG5cclxuXHRcdFx0XHRcdC8vIE5vIHRpbWVvdXQgYnkgZGVmYXVsdFxyXG5cdFx0XHRcdFx0bGV0IHRpbWVvdXQgPSAwO1xyXG5cclxuXHRcdFx0XHRcdC8vIEFjdHVhbCBmdW5jdGlvblxyXG5cdFx0XHRcdFx0ZnVuY3Rpb24gZHluYW1pYygpIHtcclxuXHRcdFx0XHRcdFx0Y29uc3QgYXJncyA9IFtdLnNsaWNlLmNhbGwoYXJndW1lbnRzKTtcclxuXHRcdFx0XHRcdFx0cmV0dXJuIENhbGwoW3BhY2thZ2VOYW1lLCBzdHJ1Y3ROYW1lLCBtZXRob2ROYW1lXS5qb2luKCcuJyksIGFyZ3MsIHRpbWVvdXQpO1xyXG5cdFx0XHRcdFx0fVxyXG5cclxuXHRcdFx0XHRcdC8vIEFsbG93IHNldHRpbmcgdGltZW91dCB0byBmdW5jdGlvblxyXG5cdFx0XHRcdFx0ZHluYW1pYy5zZXRUaW1lb3V0ID0gZnVuY3Rpb24gKG5ld1RpbWVvdXQpIHtcclxuXHRcdFx0XHRcdFx0dGltZW91dCA9IG5ld1RpbWVvdXQ7XHJcblx0XHRcdFx0XHR9O1xyXG5cclxuXHRcdFx0XHRcdC8vIEFsbG93IGdldHRpbmcgdGltZW91dCB0byBmdW5jdGlvblxyXG5cdFx0XHRcdFx0ZHluYW1pYy5nZXRUaW1lb3V0ID0gZnVuY3Rpb24gKCkge1xyXG5cdFx0XHRcdFx0XHRyZXR1cm4gdGltZW91dDtcclxuXHRcdFx0XHRcdH07XHJcblxyXG5cdFx0XHRcdFx0cmV0dXJuIGR5bmFtaWM7XHJcblx0XHRcdFx0fSgpO1xyXG5cdFx0XHR9KTtcclxuXHRcdH0pO1xyXG5cdH0pO1xyXG59XHJcbiIsICIvKlxyXG4gX1x0ICAgX19cdCAgXyBfX1xyXG58IHxcdCAvIC9fX18gXyhfKSAvX19fX1xyXG58IHwgL3wgLyAvIF9fIGAvIC8gLyBfX18vXHJcbnwgfC8gfC8gLyAvXy8gLyAvIChfXyAgKVxyXG58X18vfF9fL1xcX18sXy9fL18vX19fXy9cclxuVGhlIGVsZWN0cm9uIGFsdGVybmF0aXZlIGZvciBHb1xyXG4oYykgTGVhIEFudGhvbnkgMjAxOS1wcmVzZW50XHJcbiovXHJcblxyXG4vKiBqc2hpbnQgZXN2ZXJzaW9uOiA5ICovXHJcblxyXG5cclxuaW1wb3J0IHtDYWxsfSBmcm9tIFwiLi9jYWxsc1wiO1xyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIFdpbmRvd1JlbG9hZCgpIHtcclxuICAgIHdpbmRvdy5sb2NhdGlvbi5yZWxvYWQoKTtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIFdpbmRvd1JlbG9hZEFwcCgpIHtcclxuICAgIHdpbmRvdy5XYWlsc0ludm9rZSgnV1InKTtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIFdpbmRvd1NldFN5c3RlbURlZmF1bHRUaGVtZSgpIHtcclxuICAgIHdpbmRvdy5XYWlsc0ludm9rZSgnV0FTRFQnKTtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIFdpbmRvd1NldExpZ2h0VGhlbWUoKSB7XHJcbiAgICB3aW5kb3cuV2FpbHNJbnZva2UoJ1dBTFQnKTtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIFdpbmRvd1NldERhcmtUaGVtZSgpIHtcclxuICAgIHdpbmRvdy5XYWlsc0ludm9rZSgnV0FEVCcpO1xyXG59XHJcblxyXG4vKipcclxuICogUGxhY2UgdGhlIHdpbmRvdyBpbiB0aGUgY2VudGVyIG9mIHRoZSBzY3JlZW5cclxuICpcclxuICogQGV4cG9ydFxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIFdpbmRvd0NlbnRlcigpIHtcclxuICAgIHdpbmRvdy5XYWlsc0ludm9rZSgnV2MnKTtcclxufVxyXG5cclxuLyoqXHJcbiAqIFNldHMgdGhlIHdpbmRvdyB0aXRsZVxyXG4gKlxyXG4gKiBAcGFyYW0ge3N0cmluZ30gdGl0bGVcclxuICogQGV4cG9ydFxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIFdpbmRvd1NldFRpdGxlKHRpdGxlKSB7XHJcbiAgICB3aW5kb3cuV2FpbHNJbnZva2UoJ1dUJyArIHRpdGxlKTtcclxufVxyXG5cclxuLyoqXHJcbiAqIE1ha2VzIHRoZSB3aW5kb3cgZ28gZnVsbHNjcmVlblxyXG4gKlxyXG4gKiBAZXhwb3J0XHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gV2luZG93RnVsbHNjcmVlbigpIHtcclxuICAgIHdpbmRvdy5XYWlsc0ludm9rZSgnV0YnKTtcclxufVxyXG5cclxuLyoqXHJcbiAqIFJldmVydHMgdGhlIHdpbmRvdyBmcm9tIGZ1bGxzY3JlZW5cclxuICpcclxuICogQGV4cG9ydFxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIFdpbmRvd1VuZnVsbHNjcmVlbigpIHtcclxuICAgIHdpbmRvdy5XYWlsc0ludm9rZSgnV2YnKTtcclxufVxyXG5cclxuLyoqXHJcbiAqIFJldHVybnMgdGhlIHN0YXRlIG9mIHRoZSB3aW5kb3csIGkuZS4gd2hldGhlciB0aGUgd2luZG93IGlzIGluIGZ1bGwgc2NyZWVuIG1vZGUgb3Igbm90LlxyXG4gKlxyXG4gKiBAZXhwb3J0XHJcbiAqIEByZXR1cm4ge1Byb21pc2U8Ym9vbGVhbj59IFRoZSBzdGF0ZSBvZiB0aGUgd2luZG93XHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gV2luZG93SXNGdWxsc2NyZWVuKCkge1xyXG4gICAgcmV0dXJuIENhbGwoXCI6d2FpbHM6V2luZG93SXNGdWxsc2NyZWVuXCIpO1xyXG59XHJcblxyXG4vKipcclxuICogU2V0IHRoZSBTaXplIG9mIHRoZSB3aW5kb3dcclxuICpcclxuICogQGV4cG9ydFxyXG4gKiBAcGFyYW0ge251bWJlcn0gd2lkdGhcclxuICogQHBhcmFtIHtudW1iZXJ9IGhlaWdodFxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIFdpbmRvd1NldFNpemUod2lkdGgsIGhlaWdodCkge1xyXG4gICAgd2luZG93LldhaWxzSW52b2tlKCdXczonICsgd2lkdGggKyAnOicgKyBoZWlnaHQpO1xyXG59XHJcblxyXG4vKipcclxuICogR2V0IHRoZSBTaXplIG9mIHRoZSB3aW5kb3dcclxuICpcclxuICogQGV4cG9ydFxyXG4gKiBAcmV0dXJuIHtQcm9taXNlPHt3OiBudW1iZXIsIGg6IG51bWJlcn0+fSBUaGUgc2l6ZSBvZiB0aGUgd2luZG93XHJcblxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIFdpbmRvd0dldFNpemUoKSB7XHJcbiAgICByZXR1cm4gQ2FsbChcIjp3YWlsczpXaW5kb3dHZXRTaXplXCIpO1xyXG59XHJcblxyXG4vKipcclxuICogU2V0IHRoZSBtYXhpbXVtIHNpemUgb2YgdGhlIHdpbmRvd1xyXG4gKlxyXG4gKiBAZXhwb3J0XHJcbiAqIEBwYXJhbSB7bnVtYmVyfSB3aWR0aFxyXG4gKiBAcGFyYW0ge251bWJlcn0gaGVpZ2h0XHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gV2luZG93U2V0TWF4U2l6ZSh3aWR0aCwgaGVpZ2h0KSB7XHJcbiAgICB3aW5kb3cuV2FpbHNJbnZva2UoJ1daOicgKyB3aWR0aCArICc6JyArIGhlaWdodCk7XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBTZXQgdGhlIG1pbmltdW0gc2l6ZSBvZiB0aGUgd2luZG93XHJcbiAqXHJcbiAqIEBleHBvcnRcclxuICogQHBhcmFtIHtudW1iZXJ9IHdpZHRoXHJcbiAqIEBwYXJhbSB7bnVtYmVyfSBoZWlnaHRcclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBXaW5kb3dTZXRNaW5TaXplKHdpZHRoLCBoZWlnaHQpIHtcclxuICAgIHdpbmRvdy5XYWlsc0ludm9rZSgnV3o6JyArIHdpZHRoICsgJzonICsgaGVpZ2h0KTtcclxufVxyXG5cclxuXHJcblxyXG4vKipcclxuICogU2V0IHRoZSB3aW5kb3cgQWx3YXlzT25Ub3Agb3Igbm90IG9uIHRvcFxyXG4gKlxyXG4gKiBAZXhwb3J0XHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gV2luZG93U2V0QWx3YXlzT25Ub3AoYikge1xyXG5cclxuICAgIHdpbmRvdy5XYWlsc0ludm9rZSgnV0FUUDonICsgKGIgPyAnMScgOiAnMCcpKTtcclxufVxyXG5cclxuXHJcblxyXG5cclxuLyoqXHJcbiAqIFNldCB0aGUgUG9zaXRpb24gb2YgdGhlIHdpbmRvd1xyXG4gKlxyXG4gKiBAZXhwb3J0XHJcbiAqIEBwYXJhbSB7bnVtYmVyfSB4XHJcbiAqIEBwYXJhbSB7bnVtYmVyfSB5XHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gV2luZG93U2V0UG9zaXRpb24oeCwgeSkge1xyXG4gICAgd2luZG93LldhaWxzSW52b2tlKCdXcDonICsgeCArICc6JyArIHkpO1xyXG59XHJcblxyXG4vKipcclxuICogR2V0IHRoZSBQb3NpdGlvbiBvZiB0aGUgd2luZG93XHJcbiAqXHJcbiAqIEBleHBvcnRcclxuICogQHJldHVybiB7UHJvbWlzZTx7eDogbnVtYmVyLCB5OiBudW1iZXJ9Pn0gVGhlIHBvc2l0aW9uIG9mIHRoZSB3aW5kb3dcclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBXaW5kb3dHZXRQb3NpdGlvbigpIHtcclxuICAgIHJldHVybiBDYWxsKFwiOndhaWxzOldpbmRvd0dldFBvc1wiKTtcclxufVxyXG5cclxuLyoqXHJcbiAqIEhpZGUgdGhlIFdpbmRvd1xyXG4gKlxyXG4gKiBAZXhwb3J0XHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gV2luZG93SGlkZSgpIHtcclxuICAgIHdpbmRvdy5XYWlsc0ludm9rZSgnV0gnKTtcclxufVxyXG5cclxuLyoqXHJcbiAqIFNob3cgdGhlIFdpbmRvd1xyXG4gKlxyXG4gKiBAZXhwb3J0XHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gV2luZG93U2hvdygpIHtcclxuICAgIHdpbmRvdy5XYWlsc0ludm9rZSgnV1MnKTtcclxufVxyXG5cclxuLyoqXHJcbiAqIE1heGltaXNlIHRoZSBXaW5kb3dcclxuICpcclxuICogQGV4cG9ydFxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIFdpbmRvd01heGltaXNlKCkge1xyXG4gICAgd2luZG93LldhaWxzSW52b2tlKCdXTScpO1xyXG59XHJcblxyXG4vKipcclxuICogVG9nZ2xlIHRoZSBNYXhpbWlzZSBvZiB0aGUgV2luZG93XHJcbiAqXHJcbiAqIEBleHBvcnRcclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBXaW5kb3dUb2dnbGVNYXhpbWlzZSgpIHtcclxuICAgIHdpbmRvdy5XYWlsc0ludm9rZSgnV3QnKTtcclxufVxyXG5cclxuLyoqXHJcbiAqIFVubWF4aW1pc2UgdGhlIFdpbmRvd1xyXG4gKlxyXG4gKiBAZXhwb3J0XHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gV2luZG93VW5tYXhpbWlzZSgpIHtcclxuICAgIHdpbmRvdy5XYWlsc0ludm9rZSgnV1UnKTtcclxufVxyXG5cclxuLyoqXHJcbiAqIFJldHVybnMgdGhlIHN0YXRlIG9mIHRoZSB3aW5kb3csIGkuZS4gd2hldGhlciB0aGUgd2luZG93IGlzIG1heGltaXNlZCBvciBub3QuXHJcbiAqXHJcbiAqIEBleHBvcnRcclxuICogQHJldHVybiB7UHJvbWlzZTxib29sZWFuPn0gVGhlIHN0YXRlIG9mIHRoZSB3aW5kb3dcclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBXaW5kb3dJc01heGltaXNlZCgpIHtcclxuICAgIHJldHVybiBDYWxsKFwiOndhaWxzOldpbmRvd0lzTWF4aW1pc2VkXCIpO1xyXG59XHJcblxyXG4vKipcclxuICogTWluaW1pc2UgdGhlIFdpbmRvd1xyXG4gKlxyXG4gKiBAZXhwb3J0XHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gV2luZG93TWluaW1pc2UoKSB7XHJcbiAgICB3aW5kb3cuV2FpbHNJbnZva2UoJ1dtJyk7XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBVbm1pbmltaXNlIHRoZSBXaW5kb3dcclxuICpcclxuICogQGV4cG9ydFxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIFdpbmRvd1VubWluaW1pc2UoKSB7XHJcbiAgICB3aW5kb3cuV2FpbHNJbnZva2UoJ1d1Jyk7XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBSZXR1cm5zIHRoZSBzdGF0ZSBvZiB0aGUgd2luZG93LCBpLmUuIHdoZXRoZXIgdGhlIHdpbmRvdyBpcyBtaW5pbWlzZWQgb3Igbm90LlxyXG4gKlxyXG4gKiBAZXhwb3J0XHJcbiAqIEByZXR1cm4ge1Byb21pc2U8Ym9vbGVhbj59IFRoZSBzdGF0ZSBvZiB0aGUgd2luZG93XHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gV2luZG93SXNNaW5pbWlzZWQoKSB7XHJcbiAgICByZXR1cm4gQ2FsbChcIjp3YWlsczpXaW5kb3dJc01pbmltaXNlZFwiKTtcclxufVxyXG5cclxuLyoqXHJcbiAqIFJldHVybnMgdGhlIHN0YXRlIG9mIHRoZSB3aW5kb3csIGkuZS4gd2hldGhlciB0aGUgd2luZG93IGlzIG5vcm1hbCBvciBub3QuXHJcbiAqXHJcbiAqIEBleHBvcnRcclxuICogQHJldHVybiB7UHJvbWlzZTxib29sZWFuPn0gVGhlIHN0YXRlIG9mIHRoZSB3aW5kb3dcclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBXaW5kb3dJc05vcm1hbCgpIHtcclxuICAgIHJldHVybiBDYWxsKFwiOndhaWxzOldpbmRvd0lzTm9ybWFsXCIpO1xyXG59XHJcblxyXG4vKipcclxuICogU2V0cyB0aGUgYmFja2dyb3VuZCBjb2xvdXIgb2YgdGhlIHdpbmRvd1xyXG4gKlxyXG4gKiBAZXhwb3J0XHJcbiAqIEBwYXJhbSB7bnVtYmVyfSBSIFJlZFxyXG4gKiBAcGFyYW0ge251bWJlcn0gRyBHcmVlblxyXG4gKiBAcGFyYW0ge251bWJlcn0gQiBCbHVlXHJcbiAqIEBwYXJhbSB7bnVtYmVyfSBBIEFscGhhXHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gV2luZG93U2V0QmFja2dyb3VuZENvbG91cihSLCBHLCBCLCBBKSB7XHJcbiAgICBsZXQgcmdiYSA9IEpTT04uc3RyaW5naWZ5KHtyOiBSIHx8IDAsIGc6IEcgfHwgMCwgYjogQiB8fCAwLCBhOiBBIHx8IDI1NX0pO1xyXG4gICAgd2luZG93LldhaWxzSW52b2tlKCdXcjonICsgcmdiYSk7XHJcbn1cclxuXHJcbiIsICIvKlxyXG4gX1x0ICAgX19cdCAgXyBfX1xyXG58IHxcdCAvIC9fX18gXyhfKSAvX19fX1xyXG58IHwgL3wgLyAvIF9fIGAvIC8gLyBfX18vXHJcbnwgfC8gfC8gLyAvXy8gLyAvIChfXyAgKVxyXG58X18vfF9fL1xcX18sXy9fL18vX19fXy9cclxuVGhlIGVsZWN0cm9uIGFsdGVybmF0aXZlIGZvciBHb1xyXG4oYykgTGVhIEFudGhvbnkgMjAxOS1wcmVzZW50XHJcbiovXHJcblxyXG4vKiBqc2hpbnQgZXN2ZXJzaW9uOiA5ICovXHJcblxyXG5cclxuaW1wb3J0IHtDYWxsfSBmcm9tIFwiLi9jYWxsc1wiO1xyXG5cclxuXHJcbi8qKlxyXG4gKiBHZXRzIHRoZSBhbGwgc2NyZWVucy4gQ2FsbCB0aGlzIGFuZXcgZWFjaCB0aW1lIHlvdSB3YW50IHRvIHJlZnJlc2ggZGF0YSBmcm9tIHRoZSB1bmRlcmx5aW5nIHdpbmRvd2luZyBzeXN0ZW0uXHJcbiAqIEBleHBvcnRcclxuICogQHR5cGVkZWYge2ltcG9ydCgnLi4vd3JhcHBlci9ydW50aW1lJykuU2NyZWVufSBTY3JlZW5cclxuICogQHJldHVybiB7UHJvbWlzZTx7U2NyZWVuW119Pn0gVGhlIHNjcmVlbnNcclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBTY3JlZW5HZXRBbGwoKSB7XHJcbiAgICByZXR1cm4gQ2FsbChcIjp3YWlsczpTY3JlZW5HZXRBbGxcIik7XHJcbn1cclxuIiwgIi8qKlxyXG4gKiBAZGVzY3JpcHRpb246IFVzZSB0aGUgc3lzdGVtIGRlZmF1bHQgYnJvd3NlciB0byBvcGVuIHRoZSB1cmxcclxuICogQHBhcmFtIHtzdHJpbmd9IHVybCBcclxuICogQHJldHVybiB7dm9pZH1cclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBCcm93c2VyT3BlblVSTCh1cmwpIHtcclxuICB3aW5kb3cuV2FpbHNJbnZva2UoJ0JPOicgKyB1cmwpO1xyXG59IiwgIi8qXHJcbiBfXHQgICBfX1x0ICBfIF9fXHJcbnwgfFx0IC8gL19fXyBfKF8pIC9fX19fXHJcbnwgfCAvfCAvIC8gX18gYC8gLyAvIF9fXy9cclxufCB8LyB8LyAvIC9fLyAvIC8gKF9fICApXHJcbnxfXy98X18vXFxfXyxfL18vXy9fX19fL1xyXG5UaGUgZWxlY3Ryb24gYWx0ZXJuYXRpdmUgZm9yIEdvXHJcbihjKSBMZWEgQW50aG9ueSAyMDE5LXByZXNlbnRcclxuKi9cclxuXHJcbi8qIGpzaGludCBlc3ZlcnNpb246IDkgKi9cclxuXHJcbmltcG9ydCB7Q2FsbH0gZnJvbSBcIi4vY2FsbHNcIjtcclxuXHJcbi8qKlxyXG4gKiBTZXQgdGhlIFNpemUgb2YgdGhlIHdpbmRvd1xyXG4gKlxyXG4gKiBAZXhwb3J0XHJcbiAqIEBwYXJhbSB7c3RyaW5nfSB0ZXh0XHJcbiAqL1xyXG5leHBvcnQgZnVuY3Rpb24gQ2xpcGJvYXJkU2V0VGV4dCh0ZXh0KSB7XHJcbiAgICByZXR1cm4gQ2FsbChcIjp3YWlsczpDbGlwYm9hcmRTZXRUZXh0XCIsIFt0ZXh0XSk7XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBHZXQgdGhlIHRleHQgY29udGVudCBvZiB0aGUgY2xpcGJvYXJkXHJcbiAqXHJcbiAqIEBleHBvcnRcclxuICogQHJldHVybiB7UHJvbWlzZTx7c3RyaW5nfT59IFRleHQgY29udGVudCBvZiB0aGUgY2xpcGJvYXJkXHJcblxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIENsaXBib2FyZEdldFRleHQoKSB7XHJcbiAgICByZXR1cm4gQ2FsbChcIjp3YWlsczpDbGlwYm9hcmRHZXRUZXh0XCIpO1xyXG59IiwgIi8qXHJcbiBfXHQgICBfX1x0ICBfIF9fXHJcbnwgfFx0IC8gL19fXyBfKF8pIC9fX19fXHJcbnwgfCAvfCAvIC8gX18gYC8gLyAvIF9fXy9cclxufCB8LyB8LyAvIC9fLyAvIC8gKF9fICApXHJcbnxfXy98X18vXFxfXyxfL18vXy9fX19fL1xyXG5UaGUgZWxlY3Ryb24gYWx0ZXJuYXRpdmUgZm9yIEdvXHJcbihjKSBMZWEgQW50aG9ueSAyMDE5LXByZXNlbnRcclxuKi9cclxuXHJcbi8qIGpzaGludCBlc3ZlcnNpb246IDkgKi9cclxuXHJcbmltcG9ydCB7RXZlbnRzT24sIEV2ZW50c09mZn0gZnJvbSBcIi4vZXZlbnRzXCI7XHJcblxyXG5jb25zdCBmbGFncyA9IHtcclxuICAgIHJlZ2lzdGVyZWQ6IGZhbHNlLFxyXG4gICAgZGVmYXVsdFVzZURyb3BUYXJnZXQ6IHRydWUsXHJcbiAgICB1c2VEcm9wVGFyZ2V0OiB0cnVlLFxyXG4gICAgbmV4dERlYWN0aXZhdGU6IG51bGwsXHJcbiAgICBuZXh0RGVhY3RpdmF0ZVRpbWVvdXQ6IG51bGwsXHJcbn07XHJcblxyXG5jb25zdCBEUk9QX1RBUkdFVF9BQ1RJVkUgPSBcIndhaWxzLWRyb3AtdGFyZ2V0LWFjdGl2ZVwiO1xyXG5cclxuLyoqXHJcbiAqIGNoZWNrU3R5bGVEcm9wVGFyZ2V0IGNoZWNrcyBpZiB0aGUgc3R5bGUgaGFzIHRoZSBkcm9wIHRhcmdldCBhdHRyaWJ1dGVcclxuICogXHJcbiAqIEBwYXJhbSB7Q1NTU3R5bGVEZWNsYXJhdGlvbn0gc3R5bGUgXHJcbiAqIEByZXR1cm5zIFxyXG4gKi9cclxuZnVuY3Rpb24gY2hlY2tTdHlsZURyb3BUYXJnZXQoc3R5bGUpIHtcclxuICAgIGNvbnN0IGNzc0Ryb3BWYWx1ZSA9IHN0eWxlLmdldFByb3BlcnR5VmFsdWUod2luZG93LndhaWxzLmZsYWdzLmNzc0Ryb3BQcm9wZXJ0eSkudHJpbSgpO1xyXG4gICAgaWYgKGNzc0Ryb3BWYWx1ZSkge1xyXG4gICAgICAgIGlmIChjc3NEcm9wVmFsdWUgPT09IHdpbmRvdy53YWlscy5mbGFncy5jc3NEcm9wVmFsdWUpIHtcclxuICAgICAgICAgICAgcmV0dXJuIHRydWU7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIC8vIGlmIHRoZSBlbGVtZW50IGhhcyB0aGUgZHJvcCB0YXJnZXQgYXR0cmlidXRlLCBidXQgXHJcbiAgICAgICAgLy8gdGhlIHZhbHVlIGlzIG5vdCBjb3JyZWN0LCB0ZXJtaW5hdGUgZmluZGluZyBwcm9jZXNzLlxyXG4gICAgICAgIC8vIFRoaXMgY2FuIGJlIHVzZWZ1bCB0byBibG9jayBzb21lIGNoaWxkIGVsZW1lbnRzIGZyb20gYmVpbmcgZHJvcCB0YXJnZXRzLlxyXG4gICAgICAgIHJldHVybiBmYWxzZTtcclxuICAgIH1cclxuICAgIHJldHVybiBmYWxzZTtcclxufVxyXG5cclxuLyoqXHJcbiAqIG9uRHJhZ092ZXIgaXMgY2FsbGVkIHdoZW4gdGhlIGRyYWdvdmVyIGV2ZW50IGlzIGVtaXR0ZWQuXHJcbiAqIEBwYXJhbSB7RHJhZ0V2ZW50fSBlXHJcbiAqIEByZXR1cm5zXHJcbiAqL1xyXG5mdW5jdGlvbiBvbkRyYWdPdmVyKGUpIHtcclxuICAgIC8vIENoZWNrIGlmIHRoaXMgaXMgYW4gZXh0ZXJuYWwgZmlsZSBkcm9wIG9yIGludGVybmFsIEhUTUwgZHJhZ1xyXG4gICAgLy8gRXh0ZXJuYWwgZmlsZSBkcm9wcyB3aWxsIGhhdmUgXCJGaWxlc1wiIGluIHRoZSB0eXBlcyBhcnJheVxyXG4gICAgLy8gSW50ZXJuYWwgSFRNTCBkcmFncyB0eXBpY2FsbHkgaGF2ZSBcInRleHQvcGxhaW5cIiwgXCJ0ZXh0L2h0bWxcIiBvciBjdXN0b20gdHlwZXNcclxuICAgIGNvbnN0IGlzRmlsZURyb3AgPSBlLmRhdGFUcmFuc2Zlci50eXBlcy5pbmNsdWRlcyhcIkZpbGVzXCIpO1xyXG5cclxuICAgIC8vIE9ubHkgaGFuZGxlIGV4dGVybmFsIGZpbGUgZHJvcHMsIGxldCBpbnRlcm5hbCBIVE1MNSBkcmFnLWFuZC1kcm9wIHdvcmsgbm9ybWFsbHlcclxuICAgIGlmICghaXNGaWxlRHJvcCkge1xyXG4gICAgICAgIHJldHVybjtcclxuICAgIH1cclxuXHJcbiAgICAvLyBBTFdBWVMgcHJldmVudCBkZWZhdWx0IGZvciBmaWxlIGRyb3BzIHRvIHN0b3AgYnJvd3NlciBuYXZpZ2F0aW9uXHJcbiAgICBlLnByZXZlbnREZWZhdWx0KCk7XHJcbiAgICBlLmRhdGFUcmFuc2Zlci5kcm9wRWZmZWN0ID0gJ2NvcHknO1xyXG5cclxuICAgIGlmICghd2luZG93LndhaWxzLmZsYWdzLmVuYWJsZVdhaWxzRHJhZ0FuZERyb3ApIHtcclxuICAgICAgICByZXR1cm47XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKCFmbGFncy51c2VEcm9wVGFyZ2V0KSB7XHJcbiAgICAgICAgcmV0dXJuO1xyXG4gICAgfVxyXG5cclxuICAgIGNvbnN0IGVsZW1lbnQgPSBlLnRhcmdldDtcclxuXHJcbiAgICAvLyBUcmlnZ2VyIGRlYm91bmNlIGZ1bmN0aW9uIHRvIGRlYWN0aXZhdGUgZHJvcCB0YXJnZXRzXHJcbiAgICBpZihmbGFncy5uZXh0RGVhY3RpdmF0ZSkgZmxhZ3MubmV4dERlYWN0aXZhdGUoKTtcclxuXHJcbiAgICAvLyBpZiB0aGUgZWxlbWVudCBpcyBudWxsIG9yIGVsZW1lbnQgaXMgbm90IGNoaWxkIG9mIGRyb3AgdGFyZ2V0IGVsZW1lbnRcclxuICAgIGlmICghZWxlbWVudCB8fCAhY2hlY2tTdHlsZURyb3BUYXJnZXQoZ2V0Q29tcHV0ZWRTdHlsZShlbGVtZW50KSkpIHtcclxuICAgICAgICByZXR1cm47XHJcbiAgICB9XHJcblxyXG4gICAgbGV0IGN1cnJlbnRFbGVtZW50ID0gZWxlbWVudDtcclxuICAgIHdoaWxlIChjdXJyZW50RWxlbWVudCkge1xyXG4gICAgICAgIC8vIGNoZWNrIGlmIGN1cnJlbnRFbGVtZW50IGlzIGRyb3AgdGFyZ2V0IGVsZW1lbnRcclxuICAgICAgICBpZiAoY2hlY2tTdHlsZURyb3BUYXJnZXQoZ2V0Q29tcHV0ZWRTdHlsZShjdXJyZW50RWxlbWVudCkpKSB7XHJcbiAgICAgICAgICAgIGN1cnJlbnRFbGVtZW50LmNsYXNzTGlzdC5hZGQoRFJPUF9UQVJHRVRfQUNUSVZFKTtcclxuICAgICAgICB9XHJcbiAgICAgICAgY3VycmVudEVsZW1lbnQgPSBjdXJyZW50RWxlbWVudC5wYXJlbnRFbGVtZW50O1xyXG4gICAgfVxyXG59XHJcblxyXG4vKipcclxuICogb25EcmFnTGVhdmUgaXMgY2FsbGVkIHdoZW4gdGhlIGRyYWdsZWF2ZSBldmVudCBpcyBlbWl0dGVkLlxyXG4gKiBAcGFyYW0ge0RyYWdFdmVudH0gZVxyXG4gKiBAcmV0dXJuc1xyXG4gKi9cclxuZnVuY3Rpb24gb25EcmFnTGVhdmUoZSkge1xyXG4gICAgLy8gQ2hlY2sgaWYgdGhpcyBpcyBhbiBleHRlcm5hbCBmaWxlIGRyb3Agb3IgaW50ZXJuYWwgSFRNTCBkcmFnXHJcbiAgICBjb25zdCBpc0ZpbGVEcm9wID0gZS5kYXRhVHJhbnNmZXIudHlwZXMuaW5jbHVkZXMoXCJGaWxlc1wiKTtcclxuXHJcbiAgICAvLyBPbmx5IGhhbmRsZSBleHRlcm5hbCBmaWxlIGRyb3BzLCBsZXQgaW50ZXJuYWwgSFRNTDUgZHJhZy1hbmQtZHJvcCB3b3JrIG5vcm1hbGx5XHJcbiAgICBpZiAoIWlzRmlsZURyb3ApIHtcclxuICAgICAgICByZXR1cm47XHJcbiAgICB9XHJcblxyXG4gICAgLy8gQUxXQVlTIHByZXZlbnQgZGVmYXVsdCBmb3IgZmlsZSBkcm9wcyB0byBzdG9wIGJyb3dzZXIgbmF2aWdhdGlvblxyXG4gICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xyXG5cclxuICAgIGlmICghd2luZG93LndhaWxzLmZsYWdzLmVuYWJsZVdhaWxzRHJhZ0FuZERyb3ApIHtcclxuICAgICAgICByZXR1cm47XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKCFmbGFncy51c2VEcm9wVGFyZ2V0KSB7XHJcbiAgICAgICAgcmV0dXJuO1xyXG4gICAgfVxyXG5cclxuICAgIC8vIEZpbmQgdGhlIGNsb3NlIGRyb3AgdGFyZ2V0IGVsZW1lbnRcclxuICAgIGlmICghZS50YXJnZXQgfHwgIWNoZWNrU3R5bGVEcm9wVGFyZ2V0KGdldENvbXB1dGVkU3R5bGUoZS50YXJnZXQpKSkge1xyXG4gICAgICAgIHJldHVybiBudWxsO1xyXG4gICAgfVxyXG5cclxuICAgIC8vIFRyaWdnZXIgZGVib3VuY2UgZnVuY3Rpb24gdG8gZGVhY3RpdmF0ZSBkcm9wIHRhcmdldHNcclxuICAgIGlmKGZsYWdzLm5leHREZWFjdGl2YXRlKSBmbGFncy5uZXh0RGVhY3RpdmF0ZSgpO1xyXG4gICAgXHJcbiAgICAvLyBVc2UgZGVib3VuY2UgdGVjaG5pcXVlIHRvIHRhY2xlIGRyYWdsZWF2ZSBldmVudHMgb24gb3ZlcmxhcHBpbmcgZWxlbWVudHMgYW5kIGRyb3AgdGFyZ2V0IGVsZW1lbnRzXHJcbiAgICBmbGFncy5uZXh0RGVhY3RpdmF0ZSA9ICgpID0+IHtcclxuICAgICAgICAvLyBEZWFjdGl2YXRlIGFsbCBkcm9wIHRhcmdldHMsIG5ldyBkcm9wIHRhcmdldCB3aWxsIGJlIGFjdGl2YXRlZCBvbiBuZXh0IGRyYWdvdmVyIGV2ZW50XHJcbiAgICAgICAgQXJyYXkuZnJvbShkb2N1bWVudC5nZXRFbGVtZW50c0J5Q2xhc3NOYW1lKERST1BfVEFSR0VUX0FDVElWRSkpLmZvckVhY2goZWwgPT4gZWwuY2xhc3NMaXN0LnJlbW92ZShEUk9QX1RBUkdFVF9BQ1RJVkUpKTtcclxuICAgICAgICAvLyBSZXNldCBuZXh0RGVhY3RpdmF0ZVxyXG4gICAgICAgIGZsYWdzLm5leHREZWFjdGl2YXRlID0gbnVsbDtcclxuICAgICAgICAvLyBDbGVhciB0aW1lb3V0XHJcbiAgICAgICAgaWYgKGZsYWdzLm5leHREZWFjdGl2YXRlVGltZW91dCkge1xyXG4gICAgICAgICAgICBjbGVhclRpbWVvdXQoZmxhZ3MubmV4dERlYWN0aXZhdGVUaW1lb3V0KTtcclxuICAgICAgICAgICAgZmxhZ3MubmV4dERlYWN0aXZhdGVUaW1lb3V0ID0gbnVsbDtcclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgLy8gU2V0IHRpbWVvdXQgdG8gZGVhY3RpdmF0ZSBkcm9wIHRhcmdldHMgaWYgbm90IHRyaWdnZXJlZCBieSBuZXh0IGRyYWcgZXZlbnRcclxuICAgIGZsYWdzLm5leHREZWFjdGl2YXRlVGltZW91dCA9IHNldFRpbWVvdXQoKCkgPT4ge1xyXG4gICAgICAgIGlmKGZsYWdzLm5leHREZWFjdGl2YXRlKSBmbGFncy5uZXh0RGVhY3RpdmF0ZSgpO1xyXG4gICAgfSwgNTApO1xyXG59XHJcblxyXG4vKipcclxuICogb25Ecm9wIGlzIGNhbGxlZCB3aGVuIHRoZSBkcm9wIGV2ZW50IGlzIGVtaXR0ZWQuXHJcbiAqIEBwYXJhbSB7RHJhZ0V2ZW50fSBlXHJcbiAqIEByZXR1cm5zXHJcbiAqL1xyXG5mdW5jdGlvbiBvbkRyb3AoZSkge1xyXG4gICAgLy8gQ2hlY2sgaWYgdGhpcyBpcyBhbiBleHRlcm5hbCBmaWxlIGRyb3Agb3IgaW50ZXJuYWwgSFRNTCBkcmFnXHJcbiAgICBjb25zdCBpc0ZpbGVEcm9wID0gZS5kYXRhVHJhbnNmZXIudHlwZXMuaW5jbHVkZXMoXCJGaWxlc1wiKTtcclxuXHJcbiAgICAvLyBPbmx5IGhhbmRsZSBleHRlcm5hbCBmaWxlIGRyb3BzLCBsZXQgaW50ZXJuYWwgSFRNTDUgZHJhZy1hbmQtZHJvcCB3b3JrIG5vcm1hbGx5XHJcbiAgICBpZiAoIWlzRmlsZURyb3ApIHtcclxuICAgICAgICByZXR1cm47XHJcbiAgICB9XHJcblxyXG4gICAgLy8gQUxXQVlTIHByZXZlbnQgZGVmYXVsdCBmb3IgZmlsZSBkcm9wcyB0byBzdG9wIGJyb3dzZXIgbmF2aWdhdGlvblxyXG4gICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xyXG5cclxuICAgIGlmICghd2luZG93LndhaWxzLmZsYWdzLmVuYWJsZVdhaWxzRHJhZ0FuZERyb3ApIHtcclxuICAgICAgICByZXR1cm47XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKENhblJlc29sdmVGaWxlUGF0aHMoKSkge1xyXG4gICAgICAgIC8vIHByb2Nlc3MgZmlsZXNcclxuICAgICAgICBsZXQgZmlsZXMgPSBbXTtcclxuICAgICAgICBpZiAoZS5kYXRhVHJhbnNmZXIuaXRlbXMpIHtcclxuICAgICAgICAgICAgZmlsZXMgPSBbLi4uZS5kYXRhVHJhbnNmZXIuaXRlbXNdLm1hcCgoaXRlbSwgaSkgPT4ge1xyXG4gICAgICAgICAgICAgICAgaWYgKGl0ZW0ua2luZCA9PT0gJ2ZpbGUnKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIGl0ZW0uZ2V0QXNGaWxlKCk7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH0pO1xyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgIGZpbGVzID0gWy4uLmUuZGF0YVRyYW5zZmVyLmZpbGVzXTtcclxuICAgICAgICB9XHJcbiAgICAgICAgd2luZG93LnJ1bnRpbWUuUmVzb2x2ZUZpbGVQYXRocyhlLngsIGUueSwgZmlsZXMpO1xyXG4gICAgfVxyXG5cclxuICAgIGlmICghZmxhZ3MudXNlRHJvcFRhcmdldCkge1xyXG4gICAgICAgIHJldHVybjtcclxuICAgIH1cclxuXHJcbiAgICAvLyBUcmlnZ2VyIGRlYm91bmNlIGZ1bmN0aW9uIHRvIGRlYWN0aXZhdGUgZHJvcCB0YXJnZXRzXHJcbiAgICBpZihmbGFncy5uZXh0RGVhY3RpdmF0ZSkgZmxhZ3MubmV4dERlYWN0aXZhdGUoKTtcclxuXHJcbiAgICAvLyBEZWFjdGl2YXRlIGFsbCBkcm9wIHRhcmdldHNcclxuICAgIEFycmF5LmZyb20oZG9jdW1lbnQuZ2V0RWxlbWVudHNCeUNsYXNzTmFtZShEUk9QX1RBUkdFVF9BQ1RJVkUpKS5mb3JFYWNoKGVsID0+IGVsLmNsYXNzTGlzdC5yZW1vdmUoRFJPUF9UQVJHRVRfQUNUSVZFKSk7XHJcbn1cclxuXHJcbi8qKlxyXG4gKiBwb3N0TWVzc2FnZVdpdGhBZGRpdGlvbmFsT2JqZWN0cyBjaGVja3MgdGhlIGJyb3dzZXIncyBjYXBhYmlsaXR5IG9mIHNlbmRpbmcgcG9zdE1lc3NhZ2VXaXRoQWRkaXRpb25hbE9iamVjdHNcclxuICpcclxuICogQHJldHVybnMge2Jvb2xlYW59XHJcbiAqIEBjb25zdHJ1Y3RvclxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIENhblJlc29sdmVGaWxlUGF0aHMoKSB7XHJcbiAgICByZXR1cm4gd2luZG93LmNocm9tZT8ud2Vidmlldz8ucG9zdE1lc3NhZ2VXaXRoQWRkaXRpb25hbE9iamVjdHMgIT0gbnVsbDtcclxufVxyXG5cclxuLyoqXHJcbiAqIFJlc29sdmVGaWxlUGF0aHMgc2VuZHMgZHJvcCBldmVudHMgdG8gdGhlIEdPIHNpZGUgdG8gcmVzb2x2ZSBmaWxlIHBhdGhzIG9uIHdpbmRvd3MuXHJcbiAqXHJcbiAqIEBwYXJhbSB7bnVtYmVyfSB4XHJcbiAqIEBwYXJhbSB7bnVtYmVyfSB5XHJcbiAqIEBwYXJhbSB7YW55W119IGZpbGVzXHJcbiAqIEBjb25zdHJ1Y3RvclxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIFJlc29sdmVGaWxlUGF0aHMoeCwgeSwgZmlsZXMpIHtcclxuICAgIC8vIE9ubHkgZm9yIHdpbmRvd3Mgd2VidmlldzIgPj0gMS4wLjE3NzQuMzBcclxuICAgIC8vIGh0dHBzOi8vbGVhcm4ubWljcm9zb2Z0LmNvbS9lbi11cy9taWNyb3NvZnQtZWRnZS93ZWJ2aWV3Mi9yZWZlcmVuY2Uvd2luMzIvaWNvcmV3ZWJ2aWV3MndlYm1lc3NhZ2VyZWNlaXZlZGV2ZW50YXJnczI/dmlldz13ZWJ2aWV3Mi0xLjAuMTgyMy4zMiNhcHBsaWVzLXRvXHJcbiAgICBpZiAod2luZG93LmNocm9tZT8ud2Vidmlldz8ucG9zdE1lc3NhZ2VXaXRoQWRkaXRpb25hbE9iamVjdHMpIHtcclxuICAgICAgICBjaHJvbWUud2Vidmlldy5wb3N0TWVzc2FnZVdpdGhBZGRpdGlvbmFsT2JqZWN0cyhgZmlsZTpkcm9wOiR7eH06JHt5fWAsIGZpbGVzKTtcclxuICAgIH1cclxufVxyXG5cclxuLyoqXHJcbiAqIENhbGxiYWNrIGZvciBPbkZpbGVEcm9wIHJldHVybnMgYSBzbGljZSBvZiBmaWxlIHBhdGggc3RyaW5ncyB3aGVuIGEgZHJvcCBpcyBmaW5pc2hlZC5cclxuICpcclxuICogQGV4cG9ydFxyXG4gKiBAY2FsbGJhY2sgT25GaWxlRHJvcENhbGxiYWNrXHJcbiAqIEBwYXJhbSB7bnVtYmVyfSB4IC0geCBjb29yZGluYXRlIG9mIHRoZSBkcm9wXHJcbiAqIEBwYXJhbSB7bnVtYmVyfSB5IC0geSBjb29yZGluYXRlIG9mIHRoZSBkcm9wXHJcbiAqIEBwYXJhbSB7c3RyaW5nW119IHBhdGhzIC0gQSBsaXN0IG9mIGZpbGUgcGF0aHMuXHJcbiAqL1xyXG5cclxuLyoqXHJcbiAqIE9uRmlsZURyb3AgbGlzdGVucyB0byBkcmFnIGFuZCBkcm9wIGV2ZW50cyBhbmQgY2FsbHMgdGhlIGNhbGxiYWNrIHdpdGggdGhlIGNvb3JkaW5hdGVzIG9mIHRoZSBkcm9wIGFuZCBhbiBhcnJheSBvZiBwYXRoIHN0cmluZ3MuXHJcbiAqXHJcbiAqIEBleHBvcnRcclxuICogQHBhcmFtIHtPbkZpbGVEcm9wQ2FsbGJhY2t9IGNhbGxiYWNrIC0gQ2FsbGJhY2sgZm9yIE9uRmlsZURyb3AgcmV0dXJucyBhIHNsaWNlIG9mIGZpbGUgcGF0aCBzdHJpbmdzIHdoZW4gYSBkcm9wIGlzIGZpbmlzaGVkLlxyXG4gKiBAcGFyYW0ge2Jvb2xlYW59IFt1c2VEcm9wVGFyZ2V0PXRydWVdIC0gT25seSBjYWxsIHRoZSBjYWxsYmFjayB3aGVuIHRoZSBkcm9wIGZpbmlzaGVkIG9uIGFuIGVsZW1lbnQgdGhhdCBoYXMgdGhlIGRyb3AgdGFyZ2V0IHN0eWxlLiAoLS13YWlscy1kcm9wLXRhcmdldClcclxuICovXHJcbmV4cG9ydCBmdW5jdGlvbiBPbkZpbGVEcm9wKGNhbGxiYWNrLCB1c2VEcm9wVGFyZ2V0KSB7XHJcbiAgICBpZiAodHlwZW9mIGNhbGxiYWNrICE9PSBcImZ1bmN0aW9uXCIpIHtcclxuICAgICAgICBjb25zb2xlLmVycm9yKFwiRHJhZ0FuZERyb3BDYWxsYmFjayBpcyBub3QgYSBmdW5jdGlvblwiKTtcclxuICAgICAgICByZXR1cm47XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKGZsYWdzLnJlZ2lzdGVyZWQpIHtcclxuICAgICAgICByZXR1cm47XHJcbiAgICB9XHJcbiAgICBmbGFncy5yZWdpc3RlcmVkID0gdHJ1ZTtcclxuXHJcbiAgICBjb25zdCB1RFRQVCA9IHR5cGVvZiB1c2VEcm9wVGFyZ2V0O1xyXG4gICAgZmxhZ3MudXNlRHJvcFRhcmdldCA9IHVEVFBUID09PSBcInVuZGVmaW5lZFwiIHx8IHVEVFBUICE9PSBcImJvb2xlYW5cIiA/IGZsYWdzLmRlZmF1bHRVc2VEcm9wVGFyZ2V0IDogdXNlRHJvcFRhcmdldDtcclxuICAgIHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKCdkcmFnb3ZlcicsIG9uRHJhZ092ZXIpO1xyXG4gICAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ2RyYWdsZWF2ZScsIG9uRHJhZ0xlYXZlKTtcclxuICAgIHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKCdkcm9wJywgb25Ecm9wKTtcclxuXHJcbiAgICBsZXQgY2IgPSBjYWxsYmFjaztcclxuICAgIGlmIChmbGFncy51c2VEcm9wVGFyZ2V0KSB7XHJcbiAgICAgICAgY2IgPSBmdW5jdGlvbiAoeCwgeSwgcGF0aHMpIHtcclxuICAgICAgICAgICAgY29uc3QgZWxlbWVudCA9IGRvY3VtZW50LmVsZW1lbnRGcm9tUG9pbnQoeCwgeSlcclxuICAgICAgICAgICAgLy8gaWYgdGhlIGVsZW1lbnQgaXMgbnVsbCBvciBlbGVtZW50IGlzIG5vdCBjaGlsZCBvZiBkcm9wIHRhcmdldCBlbGVtZW50LCByZXR1cm4gbnVsbFxyXG4gICAgICAgICAgICBpZiAoIWVsZW1lbnQgfHwgIWNoZWNrU3R5bGVEcm9wVGFyZ2V0KGdldENvbXB1dGVkU3R5bGUoZWxlbWVudCkpKSB7XHJcbiAgICAgICAgICAgICAgICByZXR1cm4gbnVsbDtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgICAgICBjYWxsYmFjayh4LCB5LCBwYXRocyk7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIEV2ZW50c09uKFwid2FpbHM6ZmlsZS1kcm9wXCIsIGNiKTtcclxufVxyXG5cclxuLyoqXHJcbiAqIE9uRmlsZURyb3BPZmYgcmVtb3ZlcyB0aGUgZHJhZyBhbmQgZHJvcCBsaXN0ZW5lcnMgYW5kIGhhbmRsZXJzLlxyXG4gKi9cclxuZXhwb3J0IGZ1bmN0aW9uIE9uRmlsZURyb3BPZmYoKSB7XHJcbiAgICB3aW5kb3cucmVtb3ZlRXZlbnRMaXN0ZW5lcignZHJhZ292ZXInLCBvbkRyYWdPdmVyKTtcclxuICAgIHdpbmRvdy5yZW1vdmVFdmVudExpc3RlbmVyKCdkcmFnbGVhdmUnLCBvbkRyYWdMZWF2ZSk7XHJcbiAgICB3aW5kb3cucmVtb3ZlRXZlbnRMaXN0ZW5lcignZHJvcCcsIG9uRHJvcCk7XHJcbiAgICBFdmVudHNPZmYoXCJ3YWlsczpmaWxlLWRyb3BcIik7XHJcbiAgICBmbGFncy5yZWdpc3RlcmVkID0gZmFsc2U7XHJcbn1cclxuIiwgIi8qXHJcbi0tZGVmYXVsdC1jb250ZXh0bWVudTogYXV0bzsgKGRlZmF1bHQpIHdpbGwgc2hvdyB0aGUgZGVmYXVsdCBjb250ZXh0IG1lbnUgaWYgY29udGVudEVkaXRhYmxlIGlzIHRydWUgT1IgdGV4dCBoYXMgYmVlbiBzZWxlY3RlZCBPUiBlbGVtZW50IGlzIGlucHV0IG9yIHRleHRhcmVhXHJcbi0tZGVmYXVsdC1jb250ZXh0bWVudTogc2hvdzsgd2lsbCBhbHdheXMgc2hvdyB0aGUgZGVmYXVsdCBjb250ZXh0IG1lbnVcclxuLS1kZWZhdWx0LWNvbnRleHRtZW51OiBoaWRlOyB3aWxsIGFsd2F5cyBoaWRlIHRoZSBkZWZhdWx0IGNvbnRleHQgbWVudVxyXG5cclxuVGhpcyBydWxlIGlzIGluaGVyaXRlZCBsaWtlIG5vcm1hbCBDU1MgcnVsZXMsIHNvIG5lc3Rpbmcgd29ya3MgYXMgZXhwZWN0ZWRcclxuKi9cclxuZXhwb3J0IGZ1bmN0aW9uIHByb2Nlc3NEZWZhdWx0Q29udGV4dE1lbnUoZXZlbnQpIHtcclxuICAgIC8vIFByb2Nlc3MgZGVmYXVsdCBjb250ZXh0IG1lbnVcclxuICAgIGNvbnN0IGVsZW1lbnQgPSBldmVudC50YXJnZXQ7XHJcbiAgICBjb25zdCBjb21wdXRlZFN0eWxlID0gd2luZG93LmdldENvbXB1dGVkU3R5bGUoZWxlbWVudCk7XHJcbiAgICBjb25zdCBkZWZhdWx0Q29udGV4dE1lbnVBY3Rpb24gPSBjb21wdXRlZFN0eWxlLmdldFByb3BlcnR5VmFsdWUoXCItLWRlZmF1bHQtY29udGV4dG1lbnVcIikudHJpbSgpO1xyXG4gICAgc3dpdGNoIChkZWZhdWx0Q29udGV4dE1lbnVBY3Rpb24pIHtcclxuICAgICAgICBjYXNlIFwic2hvd1wiOlxyXG4gICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgY2FzZSBcImhpZGVcIjpcclxuICAgICAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcclxuICAgICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgIGRlZmF1bHQ6XHJcbiAgICAgICAgICAgIC8vIENoZWNrIGlmIGNvbnRlbnRFZGl0YWJsZSBpcyB0cnVlXHJcbiAgICAgICAgICAgIGlmIChlbGVtZW50LmlzQ29udGVudEVkaXRhYmxlKSB7XHJcbiAgICAgICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgICAgIH1cclxuXHJcbiAgICAgICAgICAgIC8vIENoZWNrIGlmIHRleHQgaGFzIGJlZW4gc2VsZWN0ZWQgYW5kIGFjdGlvbiBpcyBvbiB0aGUgc2VsZWN0ZWQgZWxlbWVudHNcclxuICAgICAgICAgICAgY29uc3Qgc2VsZWN0aW9uID0gd2luZG93LmdldFNlbGVjdGlvbigpO1xyXG4gICAgICAgICAgICBjb25zdCBoYXNTZWxlY3Rpb24gPSAoc2VsZWN0aW9uLnRvU3RyaW5nKCkubGVuZ3RoID4gMClcclxuICAgICAgICAgICAgaWYgKGhhc1NlbGVjdGlvbikge1xyXG4gICAgICAgICAgICAgICAgZm9yIChsZXQgaSA9IDA7IGkgPCBzZWxlY3Rpb24ucmFuZ2VDb3VudDsgaSsrKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgY29uc3QgcmFuZ2UgPSBzZWxlY3Rpb24uZ2V0UmFuZ2VBdChpKTtcclxuICAgICAgICAgICAgICAgICAgICBjb25zdCByZWN0cyA9IHJhbmdlLmdldENsaWVudFJlY3RzKCk7XHJcbiAgICAgICAgICAgICAgICAgICAgZm9yIChsZXQgaiA9IDA7IGogPCByZWN0cy5sZW5ndGg7IGorKykge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCByZWN0ID0gcmVjdHNbal07XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChkb2N1bWVudC5lbGVtZW50RnJvbVBvaW50KHJlY3QubGVmdCwgcmVjdC50b3ApID09PSBlbGVtZW50KSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgLy8gQ2hlY2sgaWYgdGFnbmFtZSBpcyBpbnB1dCBvciB0ZXh0YXJlYVxyXG4gICAgICAgICAgICBpZiAoZWxlbWVudC50YWdOYW1lID09PSBcIklOUFVUXCIgfHwgZWxlbWVudC50YWdOYW1lID09PSBcIlRFWFRBUkVBXCIpIHtcclxuICAgICAgICAgICAgICAgIGlmIChoYXNTZWxlY3Rpb24gfHwgKCFlbGVtZW50LnJlYWRPbmx5ICYmICFlbGVtZW50LmRpc2FibGVkKSkge1xyXG4gICAgICAgICAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgLy8gaGlkZSBkZWZhdWx0IGNvbnRleHQgbWVudVxyXG4gICAgICAgICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xyXG4gICAgfVxyXG59XHJcbiIsICIvKlxyXG4gX1x0ICAgX19cdCAgXyBfX1xyXG58IHxcdCAvIC9fX18gXyhfKSAvX19fX1xyXG58IHwgL3wgLyAvIF9fIGAvIC8gLyBfX18vXHJcbnwgfC8gfC8gLyAvXy8gLyAvIChfXyAgKVxyXG58X18vfF9fL1xcX18sXy9fL18vX19fXy9cclxuVGhlIGVsZWN0cm9uIGFsdGVybmF0aXZlIGZvciBHb1xyXG4oYykgTGVhIEFudGhvbnkgMjAxOS1wcmVzZW50XHJcbiovXHJcbi8qIGpzaGludCBlc3ZlcnNpb246IDkgKi9cclxuaW1wb3J0ICogYXMgTG9nIGZyb20gJy4vbG9nJztcclxuaW1wb3J0IHtcclxuICBldmVudExpc3RlbmVycyxcclxuICBFdmVudHNFbWl0LFxyXG4gIEV2ZW50c05vdGlmeSxcclxuICBFdmVudHNPZmYsXHJcbiAgRXZlbnRzT2ZmQWxsLFxyXG4gIEV2ZW50c09uLFxyXG4gIEV2ZW50c09uY2UsXHJcbiAgRXZlbnRzT25NdWx0aXBsZSxcclxufSBmcm9tIFwiLi9ldmVudHNcIjtcclxuaW1wb3J0IHsgQ2FsbCwgQ2FsbGJhY2ssIGNhbGxiYWNrcyB9IGZyb20gJy4vY2FsbHMnO1xyXG5pbXBvcnQgeyBTZXRCaW5kaW5ncyB9IGZyb20gXCIuL2JpbmRpbmdzXCI7XHJcbmltcG9ydCAqIGFzIFdpbmRvdyBmcm9tIFwiLi93aW5kb3dcIjtcclxuaW1wb3J0ICogYXMgU2NyZWVuIGZyb20gXCIuL3NjcmVlblwiO1xyXG5pbXBvcnQgKiBhcyBCcm93c2VyIGZyb20gXCIuL2Jyb3dzZXJcIjtcclxuaW1wb3J0ICogYXMgQ2xpcGJvYXJkIGZyb20gXCIuL2NsaXBib2FyZFwiO1xyXG5pbXBvcnQgKiBhcyBEcmFnQW5kRHJvcCBmcm9tIFwiLi9kcmFnYW5kZHJvcFwiO1xyXG5pbXBvcnQgKiBhcyBDb250ZXh0TWVudSBmcm9tIFwiLi9jb250ZXh0bWVudVwiO1xyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIFF1aXQoKSB7XHJcbiAgICB3aW5kb3cuV2FpbHNJbnZva2UoJ1EnKTtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIFNob3coKSB7XHJcbiAgICB3aW5kb3cuV2FpbHNJbnZva2UoJ1MnKTtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIEhpZGUoKSB7XHJcbiAgICB3aW5kb3cuV2FpbHNJbnZva2UoJ0gnKTtcclxufVxyXG5cclxuZXhwb3J0IGZ1bmN0aW9uIEVudmlyb25tZW50KCkge1xyXG4gICAgcmV0dXJuIENhbGwoXCI6d2FpbHM6RW52aXJvbm1lbnRcIik7XHJcbn1cclxuXHJcbi8vIFRoZSBKUyBydW50aW1lXHJcbndpbmRvdy5ydW50aW1lID0ge1xyXG4gICAgLi4uTG9nLFxyXG4gICAgLi4uV2luZG93LFxyXG4gICAgLi4uQnJvd3NlcixcclxuICAgIC4uLlNjcmVlbixcclxuICAgIC4uLkNsaXBib2FyZCxcclxuICAgIC4uLkRyYWdBbmREcm9wLFxyXG4gICAgRXZlbnRzT24sXHJcbiAgICBFdmVudHNPbmNlLFxyXG4gICAgRXZlbnRzT25NdWx0aXBsZSxcclxuICAgIEV2ZW50c0VtaXQsXHJcbiAgICBFdmVudHNPZmYsXHJcbiAgICBFdmVudHNPZmZBbGwsXHJcbiAgICBFbnZpcm9ubWVudCxcclxuICAgIFNob3csXHJcbiAgICBIaWRlLFxyXG4gICAgUXVpdFxyXG59O1xyXG5cclxuLy8gSW50ZXJuYWwgd2FpbHMgZW5kcG9pbnRzXHJcbndpbmRvdy53YWlscyA9IHtcclxuICAgIENhbGxiYWNrLFxyXG4gICAgRXZlbnRzTm90aWZ5LFxyXG4gICAgU2V0QmluZGluZ3MsXHJcbiAgICBldmVudExpc3RlbmVycyxcclxuICAgIGNhbGxiYWNrcyxcclxuICAgIGZsYWdzOiB7XHJcbiAgICAgICAgZGlzYWJsZVNjcm9sbGJhckRyYWc6IGZhbHNlLFxyXG4gICAgICAgIGRpc2FibGVEZWZhdWx0Q29udGV4dE1lbnU6IGZhbHNlLFxyXG4gICAgICAgIGVuYWJsZVJlc2l6ZTogZmFsc2UsXHJcbiAgICAgICAgZGVmYXVsdEN1cnNvcjogbnVsbCxcclxuICAgICAgICBib3JkZXJUaGlja25lc3M6IDYsXHJcbiAgICAgICAgc2hvdWxkRHJhZzogZmFsc2UsXHJcbiAgICAgICAgZGVmZXJEcmFnVG9Nb3VzZU1vdmU6IHRydWUsXHJcbiAgICAgICAgY3NzRHJhZ1Byb3BlcnR5OiBcIi0td2FpbHMtZHJhZ2dhYmxlXCIsXHJcbiAgICAgICAgY3NzRHJhZ1ZhbHVlOiBcImRyYWdcIixcclxuICAgICAgICBjc3NEcm9wUHJvcGVydHk6IFwiLS13YWlscy1kcm9wLXRhcmdldFwiLFxyXG4gICAgICAgIGNzc0Ryb3BWYWx1ZTogXCJkcm9wXCIsXHJcbiAgICAgICAgZW5hYmxlV2FpbHNEcmFnQW5kRHJvcDogZmFsc2UsXHJcbiAgICB9XHJcbn07XHJcblxyXG4vLyBTZXQgdGhlIGJpbmRpbmdzXHJcbmlmICh3aW5kb3cud2FpbHNiaW5kaW5ncykge1xyXG4gICAgd2luZG93LndhaWxzLlNldEJpbmRpbmdzKHdpbmRvdy53YWlsc2JpbmRpbmdzKTtcclxuICAgIGRlbGV0ZSB3aW5kb3cud2FpbHMuU2V0QmluZGluZ3M7XHJcbn1cclxuXHJcbi8vIChib29sKSBUaGlzIGlzIGV2YWx1YXRlZCBhdCBidWlsZCB0aW1lIGluIHBhY2thZ2UuanNvblxyXG5pZiAoIURFQlVHKSB7XHJcbiAgICBkZWxldGUgd2luZG93LndhaWxzYmluZGluZ3M7XHJcbn1cclxuXHJcbmxldCBkcmFnVGVzdCA9IGZ1bmN0aW9uKGUpIHtcclxuICAgIHZhciB2YWwgPSB3aW5kb3cuZ2V0Q29tcHV0ZWRTdHlsZShlLnRhcmdldCkuZ2V0UHJvcGVydHlWYWx1ZSh3aW5kb3cud2FpbHMuZmxhZ3MuY3NzRHJhZ1Byb3BlcnR5KTtcclxuICAgIGlmICh2YWwpIHtcclxuICAgICAgICB2YWwgPSB2YWwudHJpbSgpO1xyXG4gICAgfVxyXG5cclxuICAgIGlmICh2YWwgIT09IHdpbmRvdy53YWlscy5mbGFncy5jc3NEcmFnVmFsdWUpIHtcclxuICAgICAgICByZXR1cm4gZmFsc2U7XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKGUuYnV0dG9ucyAhPT0gMSkge1xyXG4gICAgICAgIC8vIERvIG5vdCBzdGFydCBkcmFnZ2luZyBpZiBub3QgdGhlIHByaW1hcnkgYnV0dG9uIGhhcyBiZWVuIGNsaWNrZWQuXHJcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xyXG4gICAgfVxyXG5cclxuICAgIGlmIChlLmRldGFpbCAhPT0gMSkge1xyXG4gICAgICAgIC8vIERvIG5vdCBzdGFydCBkcmFnZ2luZyBpZiBtb3JlIHRoYW4gb25jZSBoYXMgYmVlbiBjbGlja2VkLCBlLmcuIHdoZW4gZG91YmxlIGNsaWNraW5nXHJcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xyXG4gICAgfVxyXG5cclxuICAgIHJldHVybiB0cnVlO1xyXG59O1xyXG5cclxud2luZG93LndhaWxzLnNldENTU0RyYWdQcm9wZXJ0aWVzID0gZnVuY3Rpb24ocHJvcGVydHksIHZhbHVlKSB7XHJcbiAgICB3aW5kb3cud2FpbHMuZmxhZ3MuY3NzRHJhZ1Byb3BlcnR5ID0gcHJvcGVydHk7XHJcbiAgICB3aW5kb3cud2FpbHMuZmxhZ3MuY3NzRHJhZ1ZhbHVlID0gdmFsdWU7XHJcbn1cclxuXHJcbndpbmRvdy53YWlscy5zZXRDU1NEcm9wUHJvcGVydGllcyA9IGZ1bmN0aW9uKHByb3BlcnR5LCB2YWx1ZSkge1xyXG4gICAgd2luZG93LndhaWxzLmZsYWdzLmNzc0Ryb3BQcm9wZXJ0eSA9IHByb3BlcnR5O1xyXG4gICAgd2luZG93LndhaWxzLmZsYWdzLmNzc0Ryb3BWYWx1ZSA9IHZhbHVlO1xyXG59XHJcblxyXG53aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcignbW91c2Vkb3duJywgKGUpID0+IHtcclxuICAgIC8vIENoZWNrIGZvciByZXNpemluZ1xyXG4gICAgaWYgKHdpbmRvdy53YWlscy5mbGFncy5yZXNpemVFZGdlKSB7XHJcbiAgICAgICAgd2luZG93LldhaWxzSW52b2tlKFwicmVzaXplOlwiICsgd2luZG93LndhaWxzLmZsYWdzLnJlc2l6ZUVkZ2UpO1xyXG4gICAgICAgIGUucHJldmVudERlZmF1bHQoKTtcclxuICAgICAgICByZXR1cm47XHJcbiAgICB9XHJcblxyXG4gICAgaWYgKGRyYWdUZXN0KGUpKSB7XHJcbiAgICAgICAgaWYgKHdpbmRvdy53YWlscy5mbGFncy5kaXNhYmxlU2Nyb2xsYmFyRHJhZykge1xyXG4gICAgICAgICAgICAvLyBUaGlzIGNoZWNrcyBmb3IgY2xpY2tzIG9uIHRoZSBzY3JvbGwgYmFyXHJcbiAgICAgICAgICAgIGlmIChlLm9mZnNldFggPiBlLnRhcmdldC5jbGllbnRXaWR0aCB8fCBlLm9mZnNldFkgPiBlLnRhcmdldC5jbGllbnRIZWlnaHQpIHtcclxuICAgICAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuICAgICAgICBpZiAod2luZG93LndhaWxzLmZsYWdzLmRlZmVyRHJhZ1RvTW91c2VNb3ZlKSB7XHJcbiAgICAgICAgICAgIHdpbmRvdy53YWlscy5mbGFncy5zaG91bGREcmFnID0gdHJ1ZTtcclxuICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICBlLnByZXZlbnREZWZhdWx0KClcclxuICAgICAgICAgICAgd2luZG93LldhaWxzSW52b2tlKFwiZHJhZ1wiKTtcclxuICAgICAgICB9XHJcbiAgICAgICAgcmV0dXJuO1xyXG4gICAgfSBlbHNlIHtcclxuICAgICAgICB3aW5kb3cud2FpbHMuZmxhZ3Muc2hvdWxkRHJhZyA9IGZhbHNlO1xyXG4gICAgfVxyXG59KTtcclxuXHJcbndpbmRvdy5hZGRFdmVudExpc3RlbmVyKCdtb3VzZXVwJywgKCkgPT4ge1xyXG4gICAgd2luZG93LndhaWxzLmZsYWdzLnNob3VsZERyYWcgPSBmYWxzZTtcclxufSk7XHJcblxyXG5mdW5jdGlvbiBzZXRSZXNpemUoY3Vyc29yKSB7XHJcbiAgICBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQuc3R5bGUuY3Vyc29yID0gY3Vyc29yIHx8IHdpbmRvdy53YWlscy5mbGFncy5kZWZhdWx0Q3Vyc29yO1xyXG4gICAgd2luZG93LndhaWxzLmZsYWdzLnJlc2l6ZUVkZ2UgPSBjdXJzb3I7XHJcbn1cclxuXHJcbndpbmRvdy5hZGRFdmVudExpc3RlbmVyKCdtb3VzZW1vdmUnLCBmdW5jdGlvbihlKSB7XHJcbiAgICBpZiAod2luZG93LndhaWxzLmZsYWdzLnNob3VsZERyYWcpIHtcclxuICAgICAgICB3aW5kb3cud2FpbHMuZmxhZ3Muc2hvdWxkRHJhZyA9IGZhbHNlO1xyXG4gICAgICAgIGxldCBtb3VzZVByZXNzZWQgPSBlLmJ1dHRvbnMgIT09IHVuZGVmaW5lZCA/IGUuYnV0dG9ucyA6IGUud2hpY2g7XHJcbiAgICAgICAgaWYgKG1vdXNlUHJlc3NlZCA+IDApIHtcclxuICAgICAgICAgICAgd2luZG93LldhaWxzSW52b2tlKFwiZHJhZ1wiKTtcclxuICAgICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgIH1cclxuICAgIH1cclxuICAgIGlmICghd2luZG93LndhaWxzLmZsYWdzLmVuYWJsZVJlc2l6ZSkge1xyXG4gICAgICAgIHJldHVybjtcclxuICAgIH1cclxuICAgIGlmICh3aW5kb3cud2FpbHMuZmxhZ3MuZGVmYXVsdEN1cnNvciA9PSBudWxsKSB7XHJcbiAgICAgICAgd2luZG93LndhaWxzLmZsYWdzLmRlZmF1bHRDdXJzb3IgPSBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQuc3R5bGUuY3Vyc29yO1xyXG4gICAgfVxyXG4gICAgaWYgKHdpbmRvdy5vdXRlcldpZHRoIC0gZS5jbGllbnRYIDwgd2luZG93LndhaWxzLmZsYWdzLmJvcmRlclRoaWNrbmVzcyAmJiB3aW5kb3cub3V0ZXJIZWlnaHQgLSBlLmNsaWVudFkgPCB3aW5kb3cud2FpbHMuZmxhZ3MuYm9yZGVyVGhpY2tuZXNzKSB7XHJcbiAgICAgICAgZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50LnN0eWxlLmN1cnNvciA9IFwic2UtcmVzaXplXCI7XHJcbiAgICB9XHJcbiAgICBsZXQgcmlnaHRCb3JkZXIgPSB3aW5kb3cub3V0ZXJXaWR0aCAtIGUuY2xpZW50WCA8IHdpbmRvdy53YWlscy5mbGFncy5ib3JkZXJUaGlja25lc3M7XHJcbiAgICBsZXQgbGVmdEJvcmRlciA9IGUuY2xpZW50WCA8IHdpbmRvdy53YWlscy5mbGFncy5ib3JkZXJUaGlja25lc3M7XHJcbiAgICBsZXQgdG9wQm9yZGVyID0gZS5jbGllbnRZIDwgd2luZG93LndhaWxzLmZsYWdzLmJvcmRlclRoaWNrbmVzcztcclxuICAgIGxldCBib3R0b21Cb3JkZXIgPSB3aW5kb3cub3V0ZXJIZWlnaHQgLSBlLmNsaWVudFkgPCB3aW5kb3cud2FpbHMuZmxhZ3MuYm9yZGVyVGhpY2tuZXNzO1xyXG5cclxuICAgIC8vIElmIHdlIGFyZW4ndCBvbiBhbiBlZGdlLCBidXQgd2VyZSwgcmVzZXQgdGhlIGN1cnNvciB0byBkZWZhdWx0XHJcbiAgICBpZiAoIWxlZnRCb3JkZXIgJiYgIXJpZ2h0Qm9yZGVyICYmICF0b3BCb3JkZXIgJiYgIWJvdHRvbUJvcmRlciAmJiB3aW5kb3cud2FpbHMuZmxhZ3MucmVzaXplRWRnZSAhPT0gdW5kZWZpbmVkKSB7XHJcbiAgICAgICAgc2V0UmVzaXplKCk7XHJcbiAgICB9IGVsc2UgaWYgKHJpZ2h0Qm9yZGVyICYmIGJvdHRvbUJvcmRlcikgc2V0UmVzaXplKFwic2UtcmVzaXplXCIpO1xyXG4gICAgZWxzZSBpZiAobGVmdEJvcmRlciAmJiBib3R0b21Cb3JkZXIpIHNldFJlc2l6ZShcInN3LXJlc2l6ZVwiKTtcclxuICAgIGVsc2UgaWYgKGxlZnRCb3JkZXIgJiYgdG9wQm9yZGVyKSBzZXRSZXNpemUoXCJudy1yZXNpemVcIik7XHJcbiAgICBlbHNlIGlmICh0b3BCb3JkZXIgJiYgcmlnaHRCb3JkZXIpIHNldFJlc2l6ZShcIm5lLXJlc2l6ZVwiKTtcclxuICAgIGVsc2UgaWYgKGxlZnRCb3JkZXIpIHNldFJlc2l6ZShcInctcmVzaXplXCIpO1xyXG4gICAgZWxzZSBpZiAodG9wQm9yZGVyKSBzZXRSZXNpemUoXCJuLXJlc2l6ZVwiKTtcclxuICAgIGVsc2UgaWYgKGJvdHRvbUJvcmRlcikgc2V0UmVzaXplKFwicy1yZXNpemVcIik7XHJcbiAgICBlbHNlIGlmIChyaWdodEJvcmRlcikgc2V0UmVzaXplKFwiZS1yZXNpemVcIik7XHJcblxyXG59KTtcclxuXHJcbi8vIFNldHVwIGNvbnRleHQgbWVudSBob29rXHJcbndpbmRvdy5hZGRFdmVudExpc3RlbmVyKCdjb250ZXh0bWVudScsIGZ1bmN0aW9uKGUpIHtcclxuICAgIC8vIGFsd2F5cyBzaG93IHRoZSBjb250ZXh0bWVudSBpbiBkZWJ1ZyAmIGRldlxyXG4gICAgaWYgKERFQlVHKSByZXR1cm47XHJcblxyXG4gICAgaWYgKHdpbmRvdy53YWlscy5mbGFncy5kaXNhYmxlRGVmYXVsdENvbnRleHRNZW51KSB7XHJcbiAgICAgICAgZS5wcmV2ZW50RGVmYXVsdCgpO1xyXG4gICAgfSBlbHNlIHtcclxuICAgICAgICBDb250ZXh0TWVudS5wcm9jZXNzRGVmYXVsdENvbnRleHRNZW51KGUpO1xyXG4gICAgfVxyXG59KTtcclxuXHJcbndpbmRvdy5XYWlsc0ludm9rZShcInJ1bnRpbWU6cmVhZHlcIik7Il0sCiAgIm1hcHBpbmdzIjogIjs7Ozs7Ozs7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFrQkEsV0FBUyxlQUFlLE9BQU8sU0FBUztBQUl2QyxXQUFPLFlBQVksTUFBTSxRQUFRLE9BQU87QUFBQSxFQUN6QztBQVFPLFdBQVMsU0FBUyxTQUFTO0FBQ2pDLG1CQUFlLEtBQUssT0FBTztBQUFBLEVBQzVCO0FBUU8sV0FBUyxTQUFTLFNBQVM7QUFDakMsbUJBQWUsS0FBSyxPQUFPO0FBQUEsRUFDNUI7QUFRTyxXQUFTLFNBQVMsU0FBUztBQUNqQyxtQkFBZSxLQUFLLE9BQU87QUFBQSxFQUM1QjtBQVFPLFdBQVMsUUFBUSxTQUFTO0FBQ2hDLG1CQUFlLEtBQUssT0FBTztBQUFBLEVBQzVCO0FBUU8sV0FBUyxXQUFXLFNBQVM7QUFDbkMsbUJBQWUsS0FBSyxPQUFPO0FBQUEsRUFDNUI7QUFRTyxXQUFTLFNBQVMsU0FBUztBQUNqQyxtQkFBZSxLQUFLLE9BQU87QUFBQSxFQUM1QjtBQVFPLFdBQVMsU0FBUyxTQUFTO0FBQ2pDLG1CQUFlLEtBQUssT0FBTztBQUFBLEVBQzVCO0FBUU8sV0FBUyxZQUFZLFVBQVU7QUFDckMsbUJBQWUsS0FBSyxRQUFRO0FBQUEsRUFDN0I7QUFHTyxNQUFNLFdBQVc7QUFBQSxJQUN2QixPQUFPO0FBQUEsSUFDUCxPQUFPO0FBQUEsSUFDUCxNQUFNO0FBQUEsSUFDTixTQUFTO0FBQUEsSUFDVCxPQUFPO0FBQUEsRUFDUjs7O0FDOUZBLE1BQU0sV0FBTixNQUFlO0FBQUEsSUFRWCxZQUFZLFdBQVcsVUFBVSxjQUFjO0FBQzNDLFdBQUssWUFBWTtBQUVqQixXQUFLLGVBQWUsZ0JBQWdCO0FBR3BDLFdBQUssV0FBVyxDQUFDLFNBQVM7QUFDdEIsaUJBQVMsTUFBTSxNQUFNLElBQUk7QUFFekIsWUFBSSxLQUFLLGlCQUFpQixJQUFJO0FBQzFCLGlCQUFPO0FBQUEsUUFDWDtBQUVBLGFBQUssZ0JBQWdCO0FBQ3JCLGVBQU8sS0FBSyxpQkFBaUI7QUFBQSxNQUNqQztBQUFBLElBQ0o7QUFBQSxFQUNKO0FBRU8sTUFBTSxpQkFBaUIsQ0FBQztBQVd4QixXQUFTLGlCQUFpQixXQUFXLFVBQVUsY0FBYztBQUNoRSxtQkFBZSxhQUFhLGVBQWUsY0FBYyxDQUFDO0FBQzFELFVBQU0sZUFBZSxJQUFJLFNBQVMsV0FBVyxVQUFVLFlBQVk7QUFDbkUsbUJBQWUsV0FBVyxLQUFLLFlBQVk7QUFDM0MsV0FBTyxNQUFNLFlBQVksWUFBWTtBQUFBLEVBQ3pDO0FBVU8sV0FBUyxTQUFTLFdBQVcsVUFBVTtBQUMxQyxXQUFPLGlCQUFpQixXQUFXLFVBQVUsRUFBRTtBQUFBLEVBQ25EO0FBVU8sV0FBUyxXQUFXLFdBQVcsVUFBVTtBQUM1QyxXQUFPLGlCQUFpQixXQUFXLFVBQVUsQ0FBQztBQUFBLEVBQ2xEO0FBRUEsV0FBUyxnQkFBZ0IsV0FBVztBQUdoQyxRQUFJLFlBQVksVUFBVTtBQUcxQixVQUFNLHVCQUF1QixlQUFlLFlBQVksTUFBTSxLQUFLLENBQUM7QUFHcEUsUUFBSSxxQkFBcUIsUUFBUTtBQUc3QixlQUFTLFFBQVEscUJBQXFCLFNBQVMsR0FBRyxTQUFTLEdBQUcsU0FBUyxHQUFHO0FBR3RFLGNBQU0sV0FBVyxxQkFBcUI7QUFFdEMsWUFBSSxPQUFPLFVBQVU7QUFHckIsY0FBTSxVQUFVLFNBQVMsU0FBUyxJQUFJO0FBQ3RDLFlBQUksU0FBUztBQUVULCtCQUFxQixPQUFPLE9BQU8sQ0FBQztBQUFBLFFBQ3hDO0FBQUEsTUFDSjtBQUdBLFVBQUkscUJBQXFCLFdBQVcsR0FBRztBQUNuQyx1QkFBZSxTQUFTO0FBQUEsTUFDNUIsT0FBTztBQUNILHVCQUFlLGFBQWE7QUFBQSxNQUNoQztBQUFBLElBQ0o7QUFBQSxFQUNKO0FBU08sV0FBUyxhQUFhLGVBQWU7QUFFeEMsUUFBSTtBQUNKLFFBQUk7QUFDQSxnQkFBVSxLQUFLLE1BQU0sYUFBYTtBQUFBLElBQ3RDLFNBQVMsR0FBUDtBQUNFLFlBQU0sUUFBUSxvQ0FBb0M7QUFDbEQsWUFBTSxJQUFJLE1BQU0sS0FBSztBQUFBLElBQ3pCO0FBQ0Esb0JBQWdCLE9BQU87QUFBQSxFQUMzQjtBQVFPLFdBQVMsV0FBVyxXQUFXO0FBRWxDLFVBQU0sVUFBVTtBQUFBLE1BQ1osTUFBTTtBQUFBLE1BQ04sTUFBTSxDQUFDLEVBQUUsTUFBTSxNQUFNLFNBQVMsRUFBRSxNQUFNLENBQUM7QUFBQSxJQUMzQztBQUdBLG9CQUFnQixPQUFPO0FBR3ZCLFdBQU8sWUFBWSxPQUFPLEtBQUssVUFBVSxPQUFPLENBQUM7QUFBQSxFQUNyRDtBQUVBLFdBQVMsZUFBZSxXQUFXO0FBRS9CLFdBQU8sZUFBZTtBQUd0QixXQUFPLFlBQVksT0FBTyxTQUFTO0FBQUEsRUFDdkM7QUFTTyxXQUFTLFVBQVUsY0FBYyxzQkFBc0I7QUFDMUQsbUJBQWUsU0FBUztBQUV4QixRQUFJLHFCQUFxQixTQUFTLEdBQUc7QUFDakMsMkJBQXFCLFFBQVEsQ0FBQUEsZUFBYTtBQUN0Qyx1QkFBZUEsVUFBUztBQUFBLE1BQzVCLENBQUM7QUFBQSxJQUNMO0FBQUEsRUFDSjtBQUtRLFdBQVMsZUFBZTtBQUM1QixVQUFNLGFBQWEsT0FBTyxLQUFLLGNBQWM7QUFDN0MsZUFBVyxRQUFRLGVBQWE7QUFDNUIscUJBQWUsU0FBUztBQUFBLElBQzVCLENBQUM7QUFBQSxFQUNMO0FBT0MsV0FBUyxZQUFZLFVBQVU7QUFDNUIsVUFBTSxZQUFZLFNBQVM7QUFDM0IsUUFBSSxlQUFlLGVBQWU7QUFBVztBQUc3QyxtQkFBZSxhQUFhLGVBQWUsV0FBVyxPQUFPLE9BQUssTUFBTSxRQUFRO0FBR2hGLFFBQUksZUFBZSxXQUFXLFdBQVcsR0FBRztBQUN4QyxxQkFBZSxTQUFTO0FBQUEsSUFDNUI7QUFBQSxFQUNKOzs7QUMxTU8sTUFBTSxZQUFZLENBQUM7QUFPMUIsV0FBUyxlQUFlO0FBQ3ZCLFFBQUksUUFBUSxJQUFJLFlBQVksQ0FBQztBQUM3QixXQUFPLE9BQU8sT0FBTyxnQkFBZ0IsS0FBSyxFQUFFO0FBQUEsRUFDN0M7QUFRQSxXQUFTLGNBQWM7QUFDdEIsV0FBTyxLQUFLLE9BQU8sSUFBSTtBQUFBLEVBQ3hCO0FBR0EsTUFBSTtBQUNKLE1BQUksT0FBTyxRQUFRO0FBQ2xCLGlCQUFhO0FBQUEsRUFDZCxPQUFPO0FBQ04saUJBQWE7QUFBQSxFQUNkO0FBaUJPLFdBQVMsS0FBSyxNQUFNLE1BQU0sU0FBUztBQUd6QyxRQUFJLFdBQVcsTUFBTTtBQUNwQixnQkFBVTtBQUFBLElBQ1g7QUFHQSxXQUFPLElBQUksUUFBUSxTQUFVLFNBQVMsUUFBUTtBQUc3QyxVQUFJO0FBQ0osU0FBRztBQUNGLHFCQUFhLE9BQU8sTUFBTSxXQUFXO0FBQUEsTUFDdEMsU0FBUyxVQUFVO0FBRW5CLFVBQUk7QUFFSixVQUFJLFVBQVUsR0FBRztBQUNoQix3QkFBZ0IsV0FBVyxXQUFZO0FBQ3RDLGlCQUFPLE1BQU0sYUFBYSxPQUFPLDZCQUE2QixVQUFVLENBQUM7QUFBQSxRQUMxRSxHQUFHLE9BQU87QUFBQSxNQUNYO0FBR0EsZ0JBQVUsY0FBYztBQUFBLFFBQ3ZCO0FBQUEsUUFDQTtBQUFBLFFBQ0E7QUFBQSxNQUNEO0FBRUEsVUFBSTtBQUNILGNBQU0sVUFBVTtBQUFBLFVBQ2Y7QUFBQSxVQUNBO0FBQUEsVUFDQTtBQUFBLFFBQ0Q7QUFHUyxlQUFPLFlBQVksTUFBTSxLQUFLLFVBQVUsT0FBTyxDQUFDO0FBQUEsTUFDcEQsU0FBUyxHQUFQO0FBRUUsZ0JBQVEsTUFBTSxDQUFDO0FBQUEsTUFDbkI7QUFBQSxJQUNKLENBQUM7QUFBQSxFQUNMO0FBRUEsU0FBTyxpQkFBaUIsQ0FBQyxJQUFJLE1BQU0sWUFBWTtBQUczQyxRQUFJLFdBQVcsTUFBTTtBQUNqQixnQkFBVTtBQUFBLElBQ2Q7QUFHQSxXQUFPLElBQUksUUFBUSxTQUFVLFNBQVMsUUFBUTtBQUcxQyxVQUFJO0FBQ0osU0FBRztBQUNDLHFCQUFhLEtBQUssTUFBTSxXQUFXO0FBQUEsTUFDdkMsU0FBUyxVQUFVO0FBRW5CLFVBQUk7QUFFSixVQUFJLFVBQVUsR0FBRztBQUNiLHdCQUFnQixXQUFXLFdBQVk7QUFDbkMsaUJBQU8sTUFBTSxvQkFBb0IsS0FBSyw2QkFBNkIsVUFBVSxDQUFDO0FBQUEsUUFDbEYsR0FBRyxPQUFPO0FBQUEsTUFDZDtBQUdBLGdCQUFVLGNBQWM7QUFBQSxRQUNwQjtBQUFBLFFBQ0E7QUFBQSxRQUNBO0FBQUEsTUFDSjtBQUVBLFVBQUk7QUFDQSxjQUFNLFVBQVU7QUFBQSxVQUN4QjtBQUFBLFVBQ0E7QUFBQSxVQUNBO0FBQUEsUUFDRDtBQUdTLGVBQU8sWUFBWSxNQUFNLEtBQUssVUFBVSxPQUFPLENBQUM7QUFBQSxNQUNwRCxTQUFTLEdBQVA7QUFFRSxnQkFBUSxNQUFNLENBQUM7QUFBQSxNQUNuQjtBQUFBLElBQ0osQ0FBQztBQUFBLEVBQ0w7QUFVTyxXQUFTLFNBQVMsaUJBQWlCO0FBRXpDLFFBQUk7QUFDSixRQUFJO0FBQ0gsZ0JBQVUsS0FBSyxNQUFNLGVBQWU7QUFBQSxJQUNyQyxTQUFTLEdBQVA7QUFDRCxZQUFNLFFBQVEsb0NBQW9DLEVBQUUscUJBQXFCO0FBQ3pFLGNBQVEsU0FBUyxLQUFLO0FBQ3RCLFlBQU0sSUFBSSxNQUFNLEtBQUs7QUFBQSxJQUN0QjtBQUNBLFFBQUksYUFBYSxRQUFRO0FBQ3pCLFFBQUksZUFBZSxVQUFVO0FBQzdCLFFBQUksQ0FBQyxjQUFjO0FBQ2xCLFlBQU0sUUFBUSxhQUFhO0FBQzNCLGNBQVEsTUFBTSxLQUFLO0FBQ25CLFlBQU0sSUFBSSxNQUFNLEtBQUs7QUFBQSxJQUN0QjtBQUNBLGlCQUFhLGFBQWEsYUFBYTtBQUV2QyxXQUFPLFVBQVU7QUFFakIsUUFBSSxRQUFRLE9BQU87QUFDbEIsbUJBQWEsT0FBTyxRQUFRLEtBQUs7QUFBQSxJQUNsQyxPQUFPO0FBQ04sbUJBQWEsUUFBUSxRQUFRLE1BQU07QUFBQSxJQUNwQztBQUFBLEVBQ0Q7OztBQzFLQSxTQUFPLEtBQUssQ0FBQztBQUVOLFdBQVMsWUFBWSxhQUFhO0FBQ3hDLFFBQUk7QUFDSCxvQkFBYyxLQUFLLE1BQU0sV0FBVztBQUFBLElBQ3JDLFNBQVMsR0FBUDtBQUNELGNBQVEsTUFBTSxDQUFDO0FBQUEsSUFDaEI7QUFHQSxXQUFPLEtBQUssT0FBTyxNQUFNLENBQUM7QUFHMUIsV0FBTyxLQUFLLFdBQVcsRUFBRSxRQUFRLENBQUMsZ0JBQWdCO0FBR2pELGFBQU8sR0FBRyxlQUFlLE9BQU8sR0FBRyxnQkFBZ0IsQ0FBQztBQUdwRCxhQUFPLEtBQUssWUFBWSxZQUFZLEVBQUUsUUFBUSxDQUFDLGVBQWU7QUFHN0QsZUFBTyxHQUFHLGFBQWEsY0FBYyxPQUFPLEdBQUcsYUFBYSxlQUFlLENBQUM7QUFFNUUsZUFBTyxLQUFLLFlBQVksYUFBYSxXQUFXLEVBQUUsUUFBUSxDQUFDLGVBQWU7QUFFekUsaUJBQU8sR0FBRyxhQUFhLFlBQVksY0FBYyxXQUFZO0FBRzVELGdCQUFJLFVBQVU7QUFHZCxxQkFBUyxVQUFVO0FBQ2xCLG9CQUFNLE9BQU8sQ0FBQyxFQUFFLE1BQU0sS0FBSyxTQUFTO0FBQ3BDLHFCQUFPLEtBQUssQ0FBQyxhQUFhLFlBQVksVUFBVSxFQUFFLEtBQUssR0FBRyxHQUFHLE1BQU0sT0FBTztBQUFBLFlBQzNFO0FBR0Esb0JBQVEsYUFBYSxTQUFVLFlBQVk7QUFDMUMsd0JBQVU7QUFBQSxZQUNYO0FBR0Esb0JBQVEsYUFBYSxXQUFZO0FBQ2hDLHFCQUFPO0FBQUEsWUFDUjtBQUVBLG1CQUFPO0FBQUEsVUFDUixFQUFFO0FBQUEsUUFDSCxDQUFDO0FBQUEsTUFDRixDQUFDO0FBQUEsSUFDRixDQUFDO0FBQUEsRUFDRjs7O0FDbEVBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBZU8sV0FBUyxlQUFlO0FBQzNCLFdBQU8sU0FBUyxPQUFPO0FBQUEsRUFDM0I7QUFFTyxXQUFTLGtCQUFrQjtBQUM5QixXQUFPLFlBQVksSUFBSTtBQUFBLEVBQzNCO0FBRU8sV0FBUyw4QkFBOEI7QUFDMUMsV0FBTyxZQUFZLE9BQU87QUFBQSxFQUM5QjtBQUVPLFdBQVMsc0JBQXNCO0FBQ2xDLFdBQU8sWUFBWSxNQUFNO0FBQUEsRUFDN0I7QUFFTyxXQUFTLHFCQUFxQjtBQUNqQyxXQUFPLFlBQVksTUFBTTtBQUFBLEVBQzdCO0FBT08sV0FBUyxlQUFlO0FBQzNCLFdBQU8sWUFBWSxJQUFJO0FBQUEsRUFDM0I7QUFRTyxXQUFTLGVBQWUsT0FBTztBQUNsQyxXQUFPLFlBQVksT0FBTyxLQUFLO0FBQUEsRUFDbkM7QUFPTyxXQUFTLG1CQUFtQjtBQUMvQixXQUFPLFlBQVksSUFBSTtBQUFBLEVBQzNCO0FBT08sV0FBUyxxQkFBcUI7QUFDakMsV0FBTyxZQUFZLElBQUk7QUFBQSxFQUMzQjtBQVFPLFdBQVMscUJBQXFCO0FBQ2pDLFdBQU8sS0FBSywyQkFBMkI7QUFBQSxFQUMzQztBQVNPLFdBQVMsY0FBYyxPQUFPLFFBQVE7QUFDekMsV0FBTyxZQUFZLFFBQVEsUUFBUSxNQUFNLE1BQU07QUFBQSxFQUNuRDtBQVNPLFdBQVMsZ0JBQWdCO0FBQzVCLFdBQU8sS0FBSyxzQkFBc0I7QUFBQSxFQUN0QztBQVNPLFdBQVMsaUJBQWlCLE9BQU8sUUFBUTtBQUM1QyxXQUFPLFlBQVksUUFBUSxRQUFRLE1BQU0sTUFBTTtBQUFBLEVBQ25EO0FBU08sV0FBUyxpQkFBaUIsT0FBTyxRQUFRO0FBQzVDLFdBQU8sWUFBWSxRQUFRLFFBQVEsTUFBTSxNQUFNO0FBQUEsRUFDbkQ7QUFTTyxXQUFTLHFCQUFxQixHQUFHO0FBRXBDLFdBQU8sWUFBWSxXQUFXLElBQUksTUFBTSxJQUFJO0FBQUEsRUFDaEQ7QUFZTyxXQUFTLGtCQUFrQixHQUFHLEdBQUc7QUFDcEMsV0FBTyxZQUFZLFFBQVEsSUFBSSxNQUFNLENBQUM7QUFBQSxFQUMxQztBQVFPLFdBQVMsb0JBQW9CO0FBQ2hDLFdBQU8sS0FBSyxxQkFBcUI7QUFBQSxFQUNyQztBQU9PLFdBQVMsYUFBYTtBQUN6QixXQUFPLFlBQVksSUFBSTtBQUFBLEVBQzNCO0FBT08sV0FBUyxhQUFhO0FBQ3pCLFdBQU8sWUFBWSxJQUFJO0FBQUEsRUFDM0I7QUFPTyxXQUFTLGlCQUFpQjtBQUM3QixXQUFPLFlBQVksSUFBSTtBQUFBLEVBQzNCO0FBT08sV0FBUyx1QkFBdUI7QUFDbkMsV0FBTyxZQUFZLElBQUk7QUFBQSxFQUMzQjtBQU9PLFdBQVMsbUJBQW1CO0FBQy9CLFdBQU8sWUFBWSxJQUFJO0FBQUEsRUFDM0I7QUFRTyxXQUFTLG9CQUFvQjtBQUNoQyxXQUFPLEtBQUssMEJBQTBCO0FBQUEsRUFDMUM7QUFPTyxXQUFTLGlCQUFpQjtBQUM3QixXQUFPLFlBQVksSUFBSTtBQUFBLEVBQzNCO0FBT08sV0FBUyxtQkFBbUI7QUFDL0IsV0FBTyxZQUFZLElBQUk7QUFBQSxFQUMzQjtBQVFPLFdBQVMsb0JBQW9CO0FBQ2hDLFdBQU8sS0FBSywwQkFBMEI7QUFBQSxFQUMxQztBQVFPLFdBQVMsaUJBQWlCO0FBQzdCLFdBQU8sS0FBSyx1QkFBdUI7QUFBQSxFQUN2QztBQVdPLFdBQVMsMEJBQTBCLEdBQUcsR0FBRyxHQUFHLEdBQUc7QUFDbEQsUUFBSSxPQUFPLEtBQUssVUFBVSxFQUFDLEdBQUcsS0FBSyxHQUFHLEdBQUcsS0FBSyxHQUFHLEdBQUcsS0FBSyxHQUFHLEdBQUcsS0FBSyxJQUFHLENBQUM7QUFDeEUsV0FBTyxZQUFZLFFBQVEsSUFBSTtBQUFBLEVBQ25DOzs7QUMzUUE7QUFBQTtBQUFBO0FBQUE7QUFzQk8sV0FBUyxlQUFlO0FBQzNCLFdBQU8sS0FBSyxxQkFBcUI7QUFBQSxFQUNyQzs7O0FDeEJBO0FBQUE7QUFBQTtBQUFBO0FBS08sV0FBUyxlQUFlLEtBQUs7QUFDbEMsV0FBTyxZQUFZLFFBQVEsR0FBRztBQUFBLEVBQ2hDOzs7QUNQQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBb0JPLFdBQVMsaUJBQWlCLE1BQU07QUFDbkMsV0FBTyxLQUFLLDJCQUEyQixDQUFDLElBQUksQ0FBQztBQUFBLEVBQ2pEO0FBU08sV0FBUyxtQkFBbUI7QUFDL0IsV0FBTyxLQUFLLHlCQUF5QjtBQUFBLEVBQ3pDOzs7QUNqQ0E7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFjQSxNQUFNLFFBQVE7QUFBQSxJQUNWLFlBQVk7QUFBQSxJQUNaLHNCQUFzQjtBQUFBLElBQ3RCLGVBQWU7QUFBQSxJQUNmLGdCQUFnQjtBQUFBLElBQ2hCLHVCQUF1QjtBQUFBLEVBQzNCO0FBRUEsTUFBTSxxQkFBcUI7QUFRM0IsV0FBUyxxQkFBcUIsT0FBTztBQUNqQyxVQUFNLGVBQWUsTUFBTSxpQkFBaUIsT0FBTyxNQUFNLE1BQU0sZUFBZSxFQUFFLEtBQUs7QUFDckYsUUFBSSxjQUFjO0FBQ2QsVUFBSSxpQkFBaUIsT0FBTyxNQUFNLE1BQU0sY0FBYztBQUNsRCxlQUFPO0FBQUEsTUFDWDtBQUlBLGFBQU87QUFBQSxJQUNYO0FBQ0EsV0FBTztBQUFBLEVBQ1g7QUFPQSxXQUFTLFdBQVcsR0FBRztBQUluQixVQUFNLGFBQWEsRUFBRSxhQUFhLE1BQU0sU0FBUyxPQUFPO0FBR3hELFFBQUksQ0FBQyxZQUFZO0FBQ2I7QUFBQSxJQUNKO0FBR0EsTUFBRSxlQUFlO0FBQ2pCLE1BQUUsYUFBYSxhQUFhO0FBRTVCLFFBQUksQ0FBQyxPQUFPLE1BQU0sTUFBTSx3QkFBd0I7QUFDNUM7QUFBQSxJQUNKO0FBRUEsUUFBSSxDQUFDLE1BQU0sZUFBZTtBQUN0QjtBQUFBLElBQ0o7QUFFQSxVQUFNLFVBQVUsRUFBRTtBQUdsQixRQUFHLE1BQU07QUFBZ0IsWUFBTSxlQUFlO0FBRzlDLFFBQUksQ0FBQyxXQUFXLENBQUMscUJBQXFCLGlCQUFpQixPQUFPLENBQUMsR0FBRztBQUM5RDtBQUFBLElBQ0o7QUFFQSxRQUFJLGlCQUFpQjtBQUNyQixXQUFPLGdCQUFnQjtBQUVuQixVQUFJLHFCQUFxQixpQkFBaUIsY0FBYyxDQUFDLEdBQUc7QUFDeEQsdUJBQWUsVUFBVSxJQUFJLGtCQUFrQjtBQUFBLE1BQ25EO0FBQ0EsdUJBQWlCLGVBQWU7QUFBQSxJQUNwQztBQUFBLEVBQ0o7QUFPQSxXQUFTLFlBQVksR0FBRztBQUVwQixVQUFNLGFBQWEsRUFBRSxhQUFhLE1BQU0sU0FBUyxPQUFPO0FBR3hELFFBQUksQ0FBQyxZQUFZO0FBQ2I7QUFBQSxJQUNKO0FBR0EsTUFBRSxlQUFlO0FBRWpCLFFBQUksQ0FBQyxPQUFPLE1BQU0sTUFBTSx3QkFBd0I7QUFDNUM7QUFBQSxJQUNKO0FBRUEsUUFBSSxDQUFDLE1BQU0sZUFBZTtBQUN0QjtBQUFBLElBQ0o7QUFHQSxRQUFJLENBQUMsRUFBRSxVQUFVLENBQUMscUJBQXFCLGlCQUFpQixFQUFFLE1BQU0sQ0FBQyxHQUFHO0FBQ2hFLGFBQU87QUFBQSxJQUNYO0FBR0EsUUFBRyxNQUFNO0FBQWdCLFlBQU0sZUFBZTtBQUc5QyxVQUFNLGlCQUFpQixNQUFNO0FBRXpCLFlBQU0sS0FBSyxTQUFTLHVCQUF1QixrQkFBa0IsQ0FBQyxFQUFFLFFBQVEsUUFBTSxHQUFHLFVBQVUsT0FBTyxrQkFBa0IsQ0FBQztBQUVySCxZQUFNLGlCQUFpQjtBQUV2QixVQUFJLE1BQU0sdUJBQXVCO0FBQzdCLHFCQUFhLE1BQU0scUJBQXFCO0FBQ3hDLGNBQU0sd0JBQXdCO0FBQUEsTUFDbEM7QUFBQSxJQUNKO0FBR0EsVUFBTSx3QkFBd0IsV0FBVyxNQUFNO0FBQzNDLFVBQUcsTUFBTTtBQUFnQixjQUFNLGVBQWU7QUFBQSxJQUNsRCxHQUFHLEVBQUU7QUFBQSxFQUNUO0FBT0EsV0FBUyxPQUFPLEdBQUc7QUFFZixVQUFNLGFBQWEsRUFBRSxhQUFhLE1BQU0sU0FBUyxPQUFPO0FBR3hELFFBQUksQ0FBQyxZQUFZO0FBQ2I7QUFBQSxJQUNKO0FBR0EsTUFBRSxlQUFlO0FBRWpCLFFBQUksQ0FBQyxPQUFPLE1BQU0sTUFBTSx3QkFBd0I7QUFDNUM7QUFBQSxJQUNKO0FBRUEsUUFBSSxvQkFBb0IsR0FBRztBQUV2QixVQUFJLFFBQVEsQ0FBQztBQUNiLFVBQUksRUFBRSxhQUFhLE9BQU87QUFDdEIsZ0JBQVEsQ0FBQyxHQUFHLEVBQUUsYUFBYSxLQUFLLEVBQUUsSUFBSSxDQUFDLE1BQU0sTUFBTTtBQUMvQyxjQUFJLEtBQUssU0FBUyxRQUFRO0FBQ3RCLG1CQUFPLEtBQUssVUFBVTtBQUFBLFVBQzFCO0FBQUEsUUFDSixDQUFDO0FBQUEsTUFDTCxPQUFPO0FBQ0gsZ0JBQVEsQ0FBQyxHQUFHLEVBQUUsYUFBYSxLQUFLO0FBQUEsTUFDcEM7QUFDQSxhQUFPLFFBQVEsaUJBQWlCLEVBQUUsR0FBRyxFQUFFLEdBQUcsS0FBSztBQUFBLElBQ25EO0FBRUEsUUFBSSxDQUFDLE1BQU0sZUFBZTtBQUN0QjtBQUFBLElBQ0o7QUFHQSxRQUFHLE1BQU07QUFBZ0IsWUFBTSxlQUFlO0FBRzlDLFVBQU0sS0FBSyxTQUFTLHVCQUF1QixrQkFBa0IsQ0FBQyxFQUFFLFFBQVEsUUFBTSxHQUFHLFVBQVUsT0FBTyxrQkFBa0IsQ0FBQztBQUFBLEVBQ3pIO0FBUU8sV0FBUyxzQkFBc0I7QUFDbEMsV0FBTyxPQUFPLFFBQVEsU0FBUyxvQ0FBb0M7QUFBQSxFQUN2RTtBQVVPLFdBQVMsaUJBQWlCLEdBQUcsR0FBRyxPQUFPO0FBRzFDLFFBQUksT0FBTyxRQUFRLFNBQVMsa0NBQWtDO0FBQzFELGFBQU8sUUFBUSxpQ0FBaUMsYUFBYSxLQUFLLEtBQUssS0FBSztBQUFBLElBQ2hGO0FBQUEsRUFDSjtBQW1CTyxXQUFTLFdBQVcsVUFBVSxlQUFlO0FBQ2hELFFBQUksT0FBTyxhQUFhLFlBQVk7QUFDaEMsY0FBUSxNQUFNLHVDQUF1QztBQUNyRDtBQUFBLElBQ0o7QUFFQSxRQUFJLE1BQU0sWUFBWTtBQUNsQjtBQUFBLElBQ0o7QUFDQSxVQUFNLGFBQWE7QUFFbkIsVUFBTSxRQUFRLE9BQU87QUFDckIsVUFBTSxnQkFBZ0IsVUFBVSxlQUFlLFVBQVUsWUFBWSxNQUFNLHVCQUF1QjtBQUNsRyxXQUFPLGlCQUFpQixZQUFZLFVBQVU7QUFDOUMsV0FBTyxpQkFBaUIsYUFBYSxXQUFXO0FBQ2hELFdBQU8saUJBQWlCLFFBQVEsTUFBTTtBQUV0QyxRQUFJLEtBQUs7QUFDVCxRQUFJLE1BQU0sZUFBZTtBQUNyQixXQUFLLFNBQVUsR0FBRyxHQUFHLE9BQU87QUFDeEIsY0FBTSxVQUFVLFNBQVMsaUJBQWlCLEdBQUcsQ0FBQztBQUU5QyxZQUFJLENBQUMsV0FBVyxDQUFDLHFCQUFxQixpQkFBaUIsT0FBTyxDQUFDLEdBQUc7QUFDOUQsaUJBQU87QUFBQSxRQUNYO0FBQ0EsaUJBQVMsR0FBRyxHQUFHLEtBQUs7QUFBQSxNQUN4QjtBQUFBLElBQ0o7QUFFQSxhQUFTLG1CQUFtQixFQUFFO0FBQUEsRUFDbEM7QUFLTyxXQUFTLGdCQUFnQjtBQUM1QixXQUFPLG9CQUFvQixZQUFZLFVBQVU7QUFDakQsV0FBTyxvQkFBb0IsYUFBYSxXQUFXO0FBQ25ELFdBQU8sb0JBQW9CLFFBQVEsTUFBTTtBQUN6QyxjQUFVLGlCQUFpQjtBQUMzQixVQUFNLGFBQWE7QUFBQSxFQUN2Qjs7O0FDNVFPLFdBQVMsMEJBQTBCLE9BQU87QUFFN0MsVUFBTSxVQUFVLE1BQU07QUFDdEIsVUFBTSxnQkFBZ0IsT0FBTyxpQkFBaUIsT0FBTztBQUNyRCxVQUFNLDJCQUEyQixjQUFjLGlCQUFpQix1QkFBdUIsRUFBRSxLQUFLO0FBQzlGLFlBQVEsMEJBQTBCO0FBQUEsTUFDOUIsS0FBSztBQUNEO0FBQUEsTUFDSixLQUFLO0FBQ0QsY0FBTSxlQUFlO0FBQ3JCO0FBQUEsTUFDSjtBQUVJLFlBQUksUUFBUSxtQkFBbUI7QUFDM0I7QUFBQSxRQUNKO0FBR0EsY0FBTSxZQUFZLE9BQU8sYUFBYTtBQUN0QyxjQUFNLGVBQWdCLFVBQVUsU0FBUyxFQUFFLFNBQVM7QUFDcEQsWUFBSSxjQUFjO0FBQ2QsbUJBQVMsSUFBSSxHQUFHLElBQUksVUFBVSxZQUFZLEtBQUs7QUFDM0Msa0JBQU0sUUFBUSxVQUFVLFdBQVcsQ0FBQztBQUNwQyxrQkFBTSxRQUFRLE1BQU0sZUFBZTtBQUNuQyxxQkFBUyxJQUFJLEdBQUcsSUFBSSxNQUFNLFFBQVEsS0FBSztBQUNuQyxvQkFBTSxPQUFPLE1BQU07QUFDbkIsa0JBQUksU0FBUyxpQkFBaUIsS0FBSyxNQUFNLEtBQUssR0FBRyxNQUFNLFNBQVM7QUFDNUQ7QUFBQSxjQUNKO0FBQUEsWUFDSjtBQUFBLFVBQ0o7QUFBQSxRQUNKO0FBRUEsWUFBSSxRQUFRLFlBQVksV0FBVyxRQUFRLFlBQVksWUFBWTtBQUMvRCxjQUFJLGdCQUFpQixDQUFDLFFBQVEsWUFBWSxDQUFDLFFBQVEsVUFBVztBQUMxRDtBQUFBLFVBQ0o7QUFBQSxRQUNKO0FBR0EsY0FBTSxlQUFlO0FBQUEsSUFDN0I7QUFBQSxFQUNKOzs7QUNuQk8sV0FBUyxPQUFPO0FBQ25CLFdBQU8sWUFBWSxHQUFHO0FBQUEsRUFDMUI7QUFFTyxXQUFTLE9BQU87QUFDbkIsV0FBTyxZQUFZLEdBQUc7QUFBQSxFQUMxQjtBQUVPLFdBQVMsT0FBTztBQUNuQixXQUFPLFlBQVksR0FBRztBQUFBLEVBQzFCO0FBRU8sV0FBUyxjQUFjO0FBQzFCLFdBQU8sS0FBSyxvQkFBb0I7QUFBQSxFQUNwQztBQUdBLFNBQU8sVUFBVTtBQUFBLElBQ2IsR0FBRztBQUFBLElBQ0gsR0FBRztBQUFBLElBQ0gsR0FBRztBQUFBLElBQ0gsR0FBRztBQUFBLElBQ0gsR0FBRztBQUFBLElBQ0gsR0FBRztBQUFBLElBQ0g7QUFBQSxJQUNBO0FBQUEsSUFDQTtBQUFBLElBQ0E7QUFBQSxJQUNBO0FBQUEsSUFDQTtBQUFBLElBQ0E7QUFBQSxJQUNBO0FBQUEsSUFDQTtBQUFBLElBQ0E7QUFBQSxFQUNKO0FBR0EsU0FBTyxRQUFRO0FBQUEsSUFDWDtBQUFBLElBQ0E7QUFBQSxJQUNBO0FBQUEsSUFDQTtBQUFBLElBQ0E7QUFBQSxJQUNBLE9BQU87QUFBQSxNQUNILHNCQUFzQjtBQUFBLE1BQ3RCLDJCQUEyQjtBQUFBLE1BQzNCLGNBQWM7QUFBQSxNQUNkLGVBQWU7QUFBQSxNQUNmLGlCQUFpQjtBQUFBLE1BQ2pCLFlBQVk7QUFBQSxNQUNaLHNCQUFzQjtBQUFBLE1BQ3RCLGlCQUFpQjtBQUFBLE1BQ2pCLGNBQWM7QUFBQSxNQUNkLGlCQUFpQjtBQUFBLE1BQ2pCLGNBQWM7QUFBQSxNQUNkLHdCQUF3QjtBQUFBLElBQzVCO0FBQUEsRUFDSjtBQUdBLE1BQUksT0FBTyxlQUFlO0FBQ3RCLFdBQU8sTUFBTSxZQUFZLE9BQU8sYUFBYTtBQUM3QyxXQUFPLE9BQU8sTUFBTTtBQUFBLEVBQ3hCO0FBR0EsTUFBSSxPQUFRO0FBQ1IsV0FBTyxPQUFPO0FBQUEsRUFDbEI7QUFFQSxNQUFJLFdBQVcsU0FBUyxHQUFHO0FBQ3ZCLFFBQUksTUFBTSxPQUFPLGlCQUFpQixFQUFFLE1BQU0sRUFBRSxpQkFBaUIsT0FBTyxNQUFNLE1BQU0sZUFBZTtBQUMvRixRQUFJLEtBQUs7QUFDTCxZQUFNLElBQUksS0FBSztBQUFBLElBQ25CO0FBRUEsUUFBSSxRQUFRLE9BQU8sTUFBTSxNQUFNLGNBQWM7QUFDekMsYUFBTztBQUFBLElBQ1g7QUFFQSxRQUFJLEVBQUUsWUFBWSxHQUFHO0FBRWpCLGFBQU87QUFBQSxJQUNYO0FBRUEsUUFBSSxFQUFFLFdBQVcsR0FBRztBQUVoQixhQUFPO0FBQUEsSUFDWDtBQUVBLFdBQU87QUFBQSxFQUNYO0FBRUEsU0FBTyxNQUFNLHVCQUF1QixTQUFTLFVBQVUsT0FBTztBQUMxRCxXQUFPLE1BQU0sTUFBTSxrQkFBa0I7QUFDckMsV0FBTyxNQUFNLE1BQU0sZUFBZTtBQUFBLEVBQ3RDO0FBRUEsU0FBTyxNQUFNLHVCQUF1QixTQUFTLFVBQVUsT0FBTztBQUMxRCxXQUFPLE1BQU0sTUFBTSxrQkFBa0I7QUFDckMsV0FBTyxNQUFNLE1BQU0sZUFBZTtBQUFBLEVBQ3RDO0FBRUEsU0FBTyxpQkFBaUIsYUFBYSxDQUFDLE1BQU07QUFFeEMsUUFBSSxPQUFPLE1BQU0sTUFBTSxZQUFZO0FBQy9CLGFBQU8sWUFBWSxZQUFZLE9BQU8sTUFBTSxNQUFNLFVBQVU7QUFDNUQsUUFBRSxlQUFlO0FBQ2pCO0FBQUEsSUFDSjtBQUVBLFFBQUksU0FBUyxDQUFDLEdBQUc7QUFDYixVQUFJLE9BQU8sTUFBTSxNQUFNLHNCQUFzQjtBQUV6QyxZQUFJLEVBQUUsVUFBVSxFQUFFLE9BQU8sZUFBZSxFQUFFLFVBQVUsRUFBRSxPQUFPLGNBQWM7QUFDdkU7QUFBQSxRQUNKO0FBQUEsTUFDSjtBQUNBLFVBQUksT0FBTyxNQUFNLE1BQU0sc0JBQXNCO0FBQ3pDLGVBQU8sTUFBTSxNQUFNLGFBQWE7QUFBQSxNQUNwQyxPQUFPO0FBQ0gsVUFBRSxlQUFlO0FBQ2pCLGVBQU8sWUFBWSxNQUFNO0FBQUEsTUFDN0I7QUFDQTtBQUFBLElBQ0osT0FBTztBQUNILGFBQU8sTUFBTSxNQUFNLGFBQWE7QUFBQSxJQUNwQztBQUFBLEVBQ0osQ0FBQztBQUVELFNBQU8saUJBQWlCLFdBQVcsTUFBTTtBQUNyQyxXQUFPLE1BQU0sTUFBTSxhQUFhO0FBQUEsRUFDcEMsQ0FBQztBQUVELFdBQVMsVUFBVSxRQUFRO0FBQ3ZCLGFBQVMsZ0JBQWdCLE1BQU0sU0FBUyxVQUFVLE9BQU8sTUFBTSxNQUFNO0FBQ3JFLFdBQU8sTUFBTSxNQUFNLGFBQWE7QUFBQSxFQUNwQztBQUVBLFNBQU8saUJBQWlCLGFBQWEsU0FBUyxHQUFHO0FBQzdDLFFBQUksT0FBTyxNQUFNLE1BQU0sWUFBWTtBQUMvQixhQUFPLE1BQU0sTUFBTSxhQUFhO0FBQ2hDLFVBQUksZUFBZSxFQUFFLFlBQVksU0FBWSxFQUFFLFVBQVUsRUFBRTtBQUMzRCxVQUFJLGVBQWUsR0FBRztBQUNsQixlQUFPLFlBQVksTUFBTTtBQUN6QjtBQUFBLE1BQ0o7QUFBQSxJQUNKO0FBQ0EsUUFBSSxDQUFDLE9BQU8sTUFBTSxNQUFNLGNBQWM7QUFDbEM7QUFBQSxJQUNKO0FBQ0EsUUFBSSxPQUFPLE1BQU0sTUFBTSxpQkFBaUIsTUFBTTtBQUMxQyxhQUFPLE1BQU0sTUFBTSxnQkFBZ0IsU0FBUyxnQkFBZ0IsTUFBTTtBQUFBLElBQ3RFO0FBQ0EsUUFBSSxPQUFPLGFBQWEsRUFBRSxVQUFVLE9BQU8sTUFBTSxNQUFNLG1CQUFtQixPQUFPLGNBQWMsRUFBRSxVQUFVLE9BQU8sTUFBTSxNQUFNLGlCQUFpQjtBQUMzSSxlQUFTLGdCQUFnQixNQUFNLFNBQVM7QUFBQSxJQUM1QztBQUNBLFFBQUksY0FBYyxPQUFPLGFBQWEsRUFBRSxVQUFVLE9BQU8sTUFBTSxNQUFNO0FBQ3JFLFFBQUksYUFBYSxFQUFFLFVBQVUsT0FBTyxNQUFNLE1BQU07QUFDaEQsUUFBSSxZQUFZLEVBQUUsVUFBVSxPQUFPLE1BQU0sTUFBTTtBQUMvQyxRQUFJLGVBQWUsT0FBTyxjQUFjLEVBQUUsVUFBVSxPQUFPLE1BQU0sTUFBTTtBQUd2RSxRQUFJLENBQUMsY0FBYyxDQUFDLGVBQWUsQ0FBQyxhQUFhLENBQUMsZ0JBQWdCLE9BQU8sTUFBTSxNQUFNLGVBQWUsUUFBVztBQUMzRyxnQkFBVTtBQUFBLElBQ2QsV0FBVyxlQUFlO0FBQWMsZ0JBQVUsV0FBVztBQUFBLGFBQ3BELGNBQWM7QUFBYyxnQkFBVSxXQUFXO0FBQUEsYUFDakQsY0FBYztBQUFXLGdCQUFVLFdBQVc7QUFBQSxhQUM5QyxhQUFhO0FBQWEsZ0JBQVUsV0FBVztBQUFBLGFBQy9DO0FBQVksZ0JBQVUsVUFBVTtBQUFBLGFBQ2hDO0FBQVcsZ0JBQVUsVUFBVTtBQUFBLGFBQy9CO0FBQWMsZ0JBQVUsVUFBVTtBQUFBLGFBQ2xDO0FBQWEsZ0JBQVUsVUFBVTtBQUFBLEVBRTlDLENBQUM7QUFHRCxTQUFPLGlCQUFpQixlQUFlLFNBQVMsR0FBRztBQUUvQyxRQUFJO0FBQU87QUFFWCxRQUFJLE9BQU8sTUFBTSxNQUFNLDJCQUEyQjtBQUM5QyxRQUFFLGVBQWU7QUFBQSxJQUNyQixPQUFPO0FBQ0gsTUFBWSwwQkFBMEIsQ0FBQztBQUFBLElBQzNDO0FBQUEsRUFDSixDQUFDO0FBRUQsU0FBTyxZQUFZLGVBQWU7IiwKICAibmFtZXMiOiBbImV2ZW50TmFtZSJdCn0K diff --git a/v2/internal/frontend/runtime/runtime_prod_desktop.js b/v2/internal/frontend/runtime/runtime_prod_desktop.js index 7be603d44..3d38924f7 100644 --- a/v2/internal/frontend/runtime/runtime_prod_desktop.js +++ b/v2/internal/frontend/runtime/runtime_prod_desktop.js @@ -1 +1 @@ -(()=>{var j=Object.defineProperty;var g=(e,t)=>{for(var n in t)j(e,n,{get:t[n],enumerable:!0})};var b={};g(b,{LogDebug:()=>X,LogError:()=>q,LogFatal:()=>Q,LogInfo:()=>$,LogLevel:()=>Z,LogPrint:()=>J,LogTrace:()=>N,LogWarning:()=>Y,SetLogLevel:()=>_});function u(e,t){window.WailsInvoke("L"+e+t)}function N(e){u("T",e)}function J(e){u("P",e)}function X(e){u("D",e)}function $(e){u("I",e)}function Y(e){u("W",e)}function q(e){u("E",e)}function Q(e){u("F",e)}function _(e){u("S",e)}var Z={TRACE:1,DEBUG:2,INFO:3,WARNING:4,ERROR:5};var y=class{constructor(t,n,o){this.eventName=t,this.maxCallbacks=o||-1,this.Callback=i=>(n.apply(null,i),this.maxCallbacks===-1?!1:(this.maxCallbacks-=1,this.maxCallbacks===0))}},w={};function v(e,t,n){w[e]=w[e]||[];let o=new y(e,t,n);return w[e].push(o),()=>K(o)}function W(e,t){return v(e,t,-1)}function A(e,t){return v(e,t,1)}function P(e){let t=e.name;if(w[t]){let n=w[t].slice();for(let o=w[t].length-1;o>=0;o-=1){let i=w[t][o],r=e.data;i.Callback(r)&&n.splice(o,1)}n.length===0?m(t):w[t]=n}}function R(e){let t;try{t=JSON.parse(e)}catch{let o="Invalid JSON passed to Notify: "+e;throw new Error(o)}P(t)}function M(e){let t={name:e,data:[].slice.apply(arguments).slice(1)};P(t),window.WailsInvoke("EE"+JSON.stringify(t))}function m(e){delete w[e],window.WailsInvoke("EX"+e)}function x(e,...t){m(e),t.length>0&&t.forEach(n=>{m(n)})}function K(e){let t=e.eventName;w[t]=w[t].filter(n=>n!==e),w[t].length===0&&m(t)}var c={};function ee(){var e=new Uint32Array(1);return window.crypto.getRandomValues(e)[0]}function te(){return Math.random()*9007199254740991}var D;window.crypto?D=ee:D=te;function a(e,t,n){return n==null&&(n=0),new Promise(function(o,i){var r;do r=e+"-"+D();while(c[r]);var l;n>0&&(l=setTimeout(function(){i(Error("Call to "+e+" timed out. Request ID: "+r))},n)),c[r]={timeoutHandle:l,reject:i,resolve:o};try{let d={name:e,args:t,callbackID:r};window.WailsInvoke("C"+JSON.stringify(d))}catch(d){console.error(d)}})}window.ObfuscatedCall=(e,t,n)=>(n==null&&(n=0),new Promise(function(o,i){var r;do r=e+"-"+D();while(c[r]);var l;n>0&&(l=setTimeout(function(){i(Error("Call to method "+e+" timed out. Request ID: "+r))},n)),c[r]={timeoutHandle:l,reject:i,resolve:o};try{let d={id:e,args:t,callbackID:r};window.WailsInvoke("c"+JSON.stringify(d))}catch(d){console.error(d)}}));function z(e){let t;try{t=JSON.parse(e)}catch(i){let r=`Invalid JSON passed to callback: ${i.message}. Message: ${e}`;throw runtime.LogDebug(r),new Error(r)}let n=t.callbackid,o=c[n];if(!o){let i=`Callback '${n}' not registered!!!`;throw console.error(i),new Error(i)}clearTimeout(o.timeoutHandle),delete c[n],t.error?o.reject(t.error):o.resolve(t.result)}window.go={};function B(e){try{e=JSON.parse(e)}catch(t){console.error(t)}window.go=window.go||{},Object.keys(e).forEach(t=>{window.go[t]=window.go[t]||{},Object.keys(e[t]).forEach(n=>{window.go[t][n]=window.go[t][n]||{},Object.keys(e[t][n]).forEach(o=>{window.go[t][n][o]=function(){let i=0;function r(){let l=[].slice.call(arguments);return a([t,n,o].join("."),l,i)}return r.setTimeout=function(l){i=l},r.getTimeout=function(){return i},r}()})})})}var T={};g(T,{WindowCenter:()=>le,WindowFullscreen:()=>we,WindowGetPosition:()=>We,WindowGetSize:()=>ce,WindowHide:()=>xe,WindowIsFullscreen:()=>fe,WindowIsMaximised:()=>ye,WindowIsMinimised:()=>Se,WindowIsNormal:()=>Ie,WindowMaximise:()=>he,WindowMinimise:()=>Te,WindowReload:()=>ne,WindowReloadApp:()=>oe,WindowSetAlwaysOnTop:()=>me,WindowSetBackgroundColour:()=>Ce,WindowSetDarkTheme:()=>se,WindowSetLightTheme:()=>re,WindowSetMaxSize:()=>ge,WindowSetMinSize:()=>pe,WindowSetPosition:()=>ve,WindowSetSize:()=>ue,WindowSetSystemDefaultTheme:()=>ie,WindowSetTitle:()=>ae,WindowShow:()=>De,WindowToggleMaximise:()=>Ee,WindowUnfullscreen:()=>de,WindowUnmaximise:()=>be,WindowUnminimise:()=>ke});function ne(){window.location.reload()}function oe(){window.WailsInvoke("WR")}function ie(){window.WailsInvoke("WASDT")}function re(){window.WailsInvoke("WALT")}function se(){window.WailsInvoke("WADT")}function le(){window.WailsInvoke("Wc")}function ae(e){window.WailsInvoke("WT"+e)}function we(){window.WailsInvoke("WF")}function de(){window.WailsInvoke("Wf")}function fe(){return a(":wails:WindowIsFullscreen")}function ue(e,t){window.WailsInvoke("Ws:"+e+":"+t)}function ce(){return a(":wails:WindowGetSize")}function ge(e,t){window.WailsInvoke("WZ:"+e+":"+t)}function pe(e,t){window.WailsInvoke("Wz:"+e+":"+t)}function me(e){window.WailsInvoke("WATP:"+(e?"1":"0"))}function ve(e,t){window.WailsInvoke("Wp:"+e+":"+t)}function We(){return a(":wails:WindowGetPos")}function xe(){window.WailsInvoke("WH")}function De(){window.WailsInvoke("WS")}function he(){window.WailsInvoke("WM")}function Ee(){window.WailsInvoke("Wt")}function be(){window.WailsInvoke("WU")}function ye(){return a(":wails:WindowIsMaximised")}function Te(){window.WailsInvoke("Wm")}function ke(){window.WailsInvoke("Wu")}function Se(){return a(":wails:WindowIsMinimised")}function Ie(){return a(":wails:WindowIsNormal")}function Ce(e,t,n,o){let i=JSON.stringify({r:e||0,g:t||0,b:n||0,a:o||255});window.WailsInvoke("Wr:"+i)}var k={};g(k,{ScreenGetAll:()=>Oe});function Oe(){return a(":wails:ScreenGetAll")}var S={};g(S,{BrowserOpenURL:()=>Le});function Le(e){window.WailsInvoke("BO:"+e)}var I={};g(I,{ClipboardGetText:()=>Pe,ClipboardSetText:()=>Ae});function Ae(e){return a(":wails:ClipboardSetText",[e])}function Pe(){return a(":wails:ClipboardGetText")}var C={};g(C,{CanResolveFilePaths:()=>U,OnFileDrop:()=>Me,OnFileDropOff:()=>ze,ResolveFilePaths:()=>Re});var s={registered:!1,defaultUseDropTarget:!0,useDropTarget:!0,nextDeactivate:null,nextDeactivateTimeout:null},p="wails-drop-target-active";function h(e){let t=e.getPropertyValue(window.wails.flags.cssDropProperty).trim();return t?t===window.wails.flags.cssDropValue:!1}function F(e){if(!window.wails.flags.enableWailsDragAndDrop||(e.preventDefault(),!s.useDropTarget))return;let t=e.target;if(s.nextDeactivate&&s.nextDeactivate(),!t||!h(getComputedStyle(t)))return;let n=t;for(;n;)h(n.style)&&n.classList.add(p),n=n.parentElement}function G(e){if(!!window.wails.flags.enableWailsDragAndDrop&&(e.preventDefault(),!!s.useDropTarget)){if(!e.target||!h(getComputedStyle(e.target)))return null;s.nextDeactivate&&s.nextDeactivate(),s.nextDeactivate=()=>{Array.from(document.getElementsByClassName(p)).forEach(t=>t.classList.remove(p)),s.nextDeactivate=null,s.nextDeactivateTimeout&&(clearTimeout(s.nextDeactivateTimeout),s.nextDeactivateTimeout=null)},s.nextDeactivateTimeout=setTimeout(()=>{s.nextDeactivate&&s.nextDeactivate()},50)}}function H(e){if(!!window.wails.flags.enableWailsDragAndDrop&&(e.preventDefault(),!!s.useDropTarget&&(s.nextDeactivate&&s.nextDeactivate(),Array.from(document.getElementsByClassName(p)).forEach(t=>t.classList.remove(p)),U()))){let t=[];e.dataTransfer.items?t=[...e.dataTransfer.items].map((n,o)=>{if(n.kind==="file")return n.getAsFile()}):t=[...e.dataTransfer.files],window.runtime.ResolveFilePaths(e.x,e.y,t)}}function U(){return window.chrome?.webview?.postMessageWithAdditionalObjects!=null}function Re(e,t,n){window.chrome?.webview?.postMessageWithAdditionalObjects&&chrome.webview.postMessageWithAdditionalObjects(`file:drop:${e}:${t}`,n)}function Me(e,t){if(typeof e!="function"){console.error("DragAndDropCallback is not a function");return}if(s.registered)return;s.registered=!0;let n=typeof t;s.useDropTarget=n==="undefined"||n!=="boolean"?s.defaultUseDropTarget:t,window.addEventListener("dragover",F),window.addEventListener("dragleave",G),window.addEventListener("drop",H);let o=e;s.useDropTarget&&(o=function(i,r,l){let d=document.elementFromPoint(i,r);if(!d||!h(getComputedStyle(d)))return null;e(i,r,l)}),W("wails:file-drop",o)}function ze(){window.removeEventListener("dragover",F),window.removeEventListener("dragleave",G),window.removeEventListener("drop",H),x("wails:file-drop"),s.registered=!1}function V(e){let t=e.target;switch(window.getComputedStyle(t).getPropertyValue("--default-contextmenu").trim()){case"show":return;case"hide":e.preventDefault();return;default:if(t.isContentEditable)return;let i=window.getSelection(),r=i.toString().length>0;if(r)for(let l=0;l{if(window.wails.flags.resizeEdge){window.WailsInvoke("resize:"+window.wails.flags.resizeEdge),e.preventDefault();return}if(Ve(e)){if(window.wails.flags.disableScrollbarDrag&&(e.offsetX>e.target.clientWidth||e.offsetY>e.target.clientHeight))return;window.wails.flags.deferDragToMouseMove?window.wails.flags.shouldDrag=!0:(e.preventDefault(),window.WailsInvoke("drag"));return}else window.wails.flags.shouldDrag=!1});window.addEventListener("mouseup",()=>{window.wails.flags.shouldDrag=!1});function f(e){document.documentElement.style.cursor=e||window.wails.flags.defaultCursor,window.wails.flags.resizeEdge=e}window.addEventListener("mousemove",function(e){if(window.wails.flags.shouldDrag&&(window.wails.flags.shouldDrag=!1,(e.buttons!==void 0?e.buttons:e.which)>0)){window.WailsInvoke("drag");return}if(!window.wails.flags.enableResize)return;window.wails.flags.defaultCursor==null&&(window.wails.flags.defaultCursor=document.documentElement.style.cursor),window.outerWidth-e.clientX{var j=Object.defineProperty;var p=(e,t)=>{for(var n in t)j(e,n,{get:t[n],enumerable:!0})};var b={};p(b,{LogDebug:()=>$,LogError:()=>Q,LogFatal:()=>_,LogInfo:()=>Y,LogLevel:()=>K,LogPrint:()=>X,LogTrace:()=>J,LogWarning:()=>q,SetLogLevel:()=>Z});function u(e,t){window.WailsInvoke("L"+e+t)}function J(e){u("T",e)}function X(e){u("P",e)}function $(e){u("D",e)}function Y(e){u("I",e)}function q(e){u("W",e)}function Q(e){u("E",e)}function _(e){u("F",e)}function Z(e){u("S",e)}var K={TRACE:1,DEBUG:2,INFO:3,WARNING:4,ERROR:5};var y=class{constructor(t,n,o){this.eventName=t,this.maxCallbacks=o||-1,this.Callback=i=>(n.apply(null,i),this.maxCallbacks===-1?!1:(this.maxCallbacks-=1,this.maxCallbacks===0))}},w={};function v(e,t,n){w[e]=w[e]||[];let o=new y(e,t,n);return w[e].push(o),()=>ee(o)}function W(e,t){return v(e,t,-1)}function A(e,t){return v(e,t,1)}function P(e){let t=e.name,n=w[t]?.slice()||[];if(n.length){for(let o=n.length-1;o>=0;o-=1){let i=n[o],r=e.data;i.Callback(r)&&n.splice(o,1)}n.length===0?g(t):w[t]=n}}function F(e){let t;try{t=JSON.parse(e)}catch{let o="Invalid JSON passed to Notify: "+e;throw new Error(o)}P(t)}function R(e){let t={name:e,data:[].slice.apply(arguments).slice(1)};P(t),window.WailsInvoke("EE"+JSON.stringify(t))}function g(e){delete w[e],window.WailsInvoke("EX"+e)}function x(e,...t){g(e),t.length>0&&t.forEach(n=>{g(n)})}function M(){Object.keys(w).forEach(t=>{g(t)})}function ee(e){let t=e.eventName;w[t]!==void 0&&(w[t]=w[t].filter(n=>n!==e),w[t].length===0&&g(t))}var c={};function te(){var e=new Uint32Array(1);return window.crypto.getRandomValues(e)[0]}function ne(){return Math.random()*9007199254740991}var D;window.crypto?D=te:D=ne;function a(e,t,n){return n==null&&(n=0),new Promise(function(o,i){var r;do r=e+"-"+D();while(c[r]);var l;n>0&&(l=setTimeout(function(){i(Error("Call to "+e+" timed out. Request ID: "+r))},n)),c[r]={timeoutHandle:l,reject:i,resolve:o};try{let d={name:e,args:t,callbackID:r};window.WailsInvoke("C"+JSON.stringify(d))}catch(d){console.error(d)}})}window.ObfuscatedCall=(e,t,n)=>(n==null&&(n=0),new Promise(function(o,i){var r;do r=e+"-"+D();while(c[r]);var l;n>0&&(l=setTimeout(function(){i(Error("Call to method "+e+" timed out. Request ID: "+r))},n)),c[r]={timeoutHandle:l,reject:i,resolve:o};try{let d={id:e,args:t,callbackID:r};window.WailsInvoke("c"+JSON.stringify(d))}catch(d){console.error(d)}}));function z(e){let t;try{t=JSON.parse(e)}catch(i){let r=`Invalid JSON passed to callback: ${i.message}. Message: ${e}`;throw runtime.LogDebug(r),new Error(r)}let n=t.callbackid,o=c[n];if(!o){let i=`Callback '${n}' not registered!!!`;throw console.error(i),new Error(i)}clearTimeout(o.timeoutHandle),delete c[n],t.error?o.reject(t.error):o.resolve(t.result)}window.go={};function B(e){try{e=JSON.parse(e)}catch(t){console.error(t)}window.go=window.go||{},Object.keys(e).forEach(t=>{window.go[t]=window.go[t]||{},Object.keys(e[t]).forEach(n=>{window.go[t][n]=window.go[t][n]||{},Object.keys(e[t][n]).forEach(o=>{window.go[t][n][o]=function(){let i=0;function r(){let l=[].slice.call(arguments);return a([t,n,o].join("."),l,i)}return r.setTimeout=function(l){i=l},r.getTimeout=function(){return i},r}()})})})}var T={};p(T,{WindowCenter:()=>ae,WindowFullscreen:()=>de,WindowGetPosition:()=>xe,WindowGetSize:()=>pe,WindowHide:()=>De,WindowIsFullscreen:()=>ue,WindowIsMaximised:()=>Te,WindowIsMinimised:()=>Ce,WindowIsNormal:()=>Ie,WindowMaximise:()=>Ee,WindowMinimise:()=>Se,WindowReload:()=>oe,WindowReloadApp:()=>ie,WindowSetAlwaysOnTop:()=>ve,WindowSetBackgroundColour:()=>Oe,WindowSetDarkTheme:()=>le,WindowSetLightTheme:()=>se,WindowSetMaxSize:()=>ge,WindowSetMinSize:()=>me,WindowSetPosition:()=>We,WindowSetSize:()=>ce,WindowSetSystemDefaultTheme:()=>re,WindowSetTitle:()=>we,WindowShow:()=>he,WindowToggleMaximise:()=>be,WindowUnfullscreen:()=>fe,WindowUnmaximise:()=>ye,WindowUnminimise:()=>ke});function oe(){window.location.reload()}function ie(){window.WailsInvoke("WR")}function re(){window.WailsInvoke("WASDT")}function se(){window.WailsInvoke("WALT")}function le(){window.WailsInvoke("WADT")}function ae(){window.WailsInvoke("Wc")}function we(e){window.WailsInvoke("WT"+e)}function de(){window.WailsInvoke("WF")}function fe(){window.WailsInvoke("Wf")}function ue(){return a(":wails:WindowIsFullscreen")}function ce(e,t){window.WailsInvoke("Ws:"+e+":"+t)}function pe(){return a(":wails:WindowGetSize")}function ge(e,t){window.WailsInvoke("WZ:"+e+":"+t)}function me(e,t){window.WailsInvoke("Wz:"+e+":"+t)}function ve(e){window.WailsInvoke("WATP:"+(e?"1":"0"))}function We(e,t){window.WailsInvoke("Wp:"+e+":"+t)}function xe(){return a(":wails:WindowGetPos")}function De(){window.WailsInvoke("WH")}function he(){window.WailsInvoke("WS")}function Ee(){window.WailsInvoke("WM")}function be(){window.WailsInvoke("Wt")}function ye(){window.WailsInvoke("WU")}function Te(){return a(":wails:WindowIsMaximised")}function Se(){window.WailsInvoke("Wm")}function ke(){window.WailsInvoke("Wu")}function Ce(){return a(":wails:WindowIsMinimised")}function Ie(){return a(":wails:WindowIsNormal")}function Oe(e,t,n,o){let i=JSON.stringify({r:e||0,g:t||0,b:n||0,a:o||255});window.WailsInvoke("Wr:"+i)}var S={};p(S,{ScreenGetAll:()=>Le});function Le(){return a(":wails:ScreenGetAll")}var k={};p(k,{BrowserOpenURL:()=>Ae});function Ae(e){window.WailsInvoke("BO:"+e)}var C={};p(C,{ClipboardGetText:()=>Fe,ClipboardSetText:()=>Pe});function Pe(e){return a(":wails:ClipboardSetText",[e])}function Fe(){return a(":wails:ClipboardGetText")}var I={};p(I,{CanResolveFilePaths:()=>V,OnFileDrop:()=>Me,OnFileDropOff:()=>ze,ResolveFilePaths:()=>Re});var s={registered:!1,defaultUseDropTarget:!0,useDropTarget:!0,nextDeactivate:null,nextDeactivateTimeout:null},m="wails-drop-target-active";function h(e){let t=e.getPropertyValue(window.wails.flags.cssDropProperty).trim();return t?t===window.wails.flags.cssDropValue:!1}function G(e){if(!e.dataTransfer.types.includes("Files")||(e.preventDefault(),e.dataTransfer.dropEffect="copy",!window.wails.flags.enableWailsDragAndDrop)||!s.useDropTarget)return;let n=e.target;if(s.nextDeactivate&&s.nextDeactivate(),!n||!h(getComputedStyle(n)))return;let o=n;for(;o;)h(getComputedStyle(o))&&o.classList.add(m),o=o.parentElement}function H(e){if(!!e.dataTransfer.types.includes("Files")&&(e.preventDefault(),!!window.wails.flags.enableWailsDragAndDrop&&!!s.useDropTarget)){if(!e.target||!h(getComputedStyle(e.target)))return null;s.nextDeactivate&&s.nextDeactivate(),s.nextDeactivate=()=>{Array.from(document.getElementsByClassName(m)).forEach(n=>n.classList.remove(m)),s.nextDeactivate=null,s.nextDeactivateTimeout&&(clearTimeout(s.nextDeactivateTimeout),s.nextDeactivateTimeout=null)},s.nextDeactivateTimeout=setTimeout(()=>{s.nextDeactivate&&s.nextDeactivate()},50)}}function U(e){if(!!e.dataTransfer.types.includes("Files")&&(e.preventDefault(),!!window.wails.flags.enableWailsDragAndDrop)){if(V()){let n=[];e.dataTransfer.items?n=[...e.dataTransfer.items].map((o,i)=>{if(o.kind==="file")return o.getAsFile()}):n=[...e.dataTransfer.files],window.runtime.ResolveFilePaths(e.x,e.y,n)}!s.useDropTarget||(s.nextDeactivate&&s.nextDeactivate(),Array.from(document.getElementsByClassName(m)).forEach(n=>n.classList.remove(m)))}}function V(){return window.chrome?.webview?.postMessageWithAdditionalObjects!=null}function Re(e,t,n){window.chrome?.webview?.postMessageWithAdditionalObjects&&chrome.webview.postMessageWithAdditionalObjects(`file:drop:${e}:${t}`,n)}function Me(e,t){if(typeof e!="function"){console.error("DragAndDropCallback is not a function");return}if(s.registered)return;s.registered=!0;let n=typeof t;s.useDropTarget=n==="undefined"||n!=="boolean"?s.defaultUseDropTarget:t,window.addEventListener("dragover",G),window.addEventListener("dragleave",H),window.addEventListener("drop",U);let o=e;s.useDropTarget&&(o=function(i,r,l){let d=document.elementFromPoint(i,r);if(!d||!h(getComputedStyle(d)))return null;e(i,r,l)}),W("wails:file-drop",o)}function ze(){window.removeEventListener("dragover",G),window.removeEventListener("dragleave",H),window.removeEventListener("drop",U),x("wails:file-drop"),s.registered=!1}function N(e){let t=e.target;switch(window.getComputedStyle(t).getPropertyValue("--default-contextmenu").trim()){case"show":return;case"hide":e.preventDefault();return;default:if(t.isContentEditable)return;let i=window.getSelection(),r=i.toString().length>0;if(r)for(let l=0;l{if(window.wails.flags.resizeEdge){window.WailsInvoke("resize:"+window.wails.flags.resizeEdge),e.preventDefault();return}if(Ne(e)){if(window.wails.flags.disableScrollbarDrag&&(e.offsetX>e.target.clientWidth||e.offsetY>e.target.clientHeight))return;window.wails.flags.deferDragToMouseMove?window.wails.flags.shouldDrag=!0:(e.preventDefault(),window.WailsInvoke("drag"));return}else window.wails.flags.shouldDrag=!1});window.addEventListener("mouseup",()=>{window.wails.flags.shouldDrag=!1});function f(e){document.documentElement.style.cursor=e||window.wails.flags.defaultCursor,window.wails.flags.resizeEdge=e}window.addEventListener("mousemove",function(e){if(window.wails.flags.shouldDrag&&(window.wails.flags.shouldDrag=!1,(e.buttons!==void 0?e.buttons:e.which)>0)){window.WailsInvoke("drag");return}if(!window.wails.flags.enableResize)return;window.wails.flags.defaultCursor==null&&(window.wails.flags.defaultCursor=document.documentElement.style.cursor),window.outerWidth-e.clientX; // [WindowSetSize](https://wails.io/docs/reference/runtime/window#windowsetsize) // Sets the width and height of the window. -export function WindowSetSize(width: number, height: number): Promise; +export function WindowSetSize(width: number, height: number): void; // [WindowGetSize](https://wails.io/docs/reference/runtime/window#windowgetsize) // Gets the width and height of the window. diff --git a/v2/internal/frontend/runtime/wrapper/runtime.js b/v2/internal/frontend/runtime/wrapper/runtime.js index 623397b0b..7cb89d750 100644 --- a/v2/internal/frontend/runtime/wrapper/runtime.js +++ b/v2/internal/frontend/runtime/wrapper/runtime.js @@ -48,6 +48,10 @@ export function EventsOff(eventName, ...additionalEventNames) { return window.runtime.EventsOff(eventName, ...additionalEventNames); } +export function EventsOffAll() { + return window.runtime.EventsOffAll(); +} + export function EventsOnce(eventName, callback) { return EventsOnMultiple(eventName, callback, 1); } diff --git a/v2/internal/frontend/utils/urlValidator.go b/v2/internal/frontend/utils/urlValidator.go new file mode 100644 index 000000000..76ba216ce --- /dev/null +++ b/v2/internal/frontend/utils/urlValidator.go @@ -0,0 +1,58 @@ +package utils + +import ( + "errors" + "fmt" + "net/url" + "regexp" + "strings" +) + +func ValidateAndSanitizeURL(rawURL string) (string, error) { + // Check for null bytes (can cause truncation issues in some systems) + if strings.Contains(rawURL, "\x00") { + return "", errors.New("null bytes not allowed in URL") + } + + // Parse URL first - this handles most malformed URLs + parsedURL, err := url.Parse(rawURL) + if err != nil { + return "", fmt.Errorf("invalid URL format: %v", err) + } + + scheme := strings.ToLower(parsedURL.Scheme) + + if scheme == "javascript" || scheme == "data" || scheme == "file" || scheme == "ftp" || scheme == "" { + return "", errors.New("scheme not allowed") + } + + // Ensure there's actually a host for http/https URLs + if (scheme == "http" || scheme == "https") && parsedURL.Host == "" { + return "", fmt.Errorf("missing host for %s URL", scheme) + } + + sanitizedURL := parsedURL.String() + + // Check for control characters that might cause issues + // (but allow legitimate URL characters like &, ;, etc.) + for i, r := range sanitizedURL { + // Block control characters except tab, but allow other printable chars + if r < 32 && r != 9 { // 9 is tab, which might be legitimate + return "", fmt.Errorf("control character at position %d not allowed", i) + } + } + + // Shell metacharacter check + shellDangerous := `[;\|` + "`" + `$\\<>*{}\[\]()~! \t\n\r]` + if matched, _ := regexp.MatchString(shellDangerous, sanitizedURL); matched { + return "", errors.New("shell metacharacters not allowed") + } + + // Unicode danger check + unicodeDangerous := "[\u0000-\u001F\u007F\u00A0\u1680\u2000-\u200F\u2028-\u202F\u205F\u2060\u3000\uFEFF]" + if matched, _ := regexp.MatchString(unicodeDangerous, sanitizedURL); matched { + return "", errors.New("unicode dangerous characters not allowed") + } + + return sanitizedURL, nil +} diff --git a/v2/internal/frontend/utils/urlValidator_test.go b/v2/internal/frontend/utils/urlValidator_test.go new file mode 100644 index 000000000..b385ccec1 --- /dev/null +++ b/v2/internal/frontend/utils/urlValidator_test.go @@ -0,0 +1,207 @@ +package utils_test + +import ( + "strings" + "testing" + + "github.com/wailsapp/wails/v2/internal/frontend/utils" +) + +// Test cases for ValidateAndOpenURL +func TestValidateURL(t *testing.T) { + testCases := []struct { + name string + url string + shouldErr bool + errMsg string + expected string + }{ + // Valid URLs + { + name: "valid https URL", + url: "https://www.example.com", + shouldErr: false, + expected: "https://www.example.com", + }, + { + name: "valid http URL", + url: "http://example.com", + shouldErr: false, + expected: "http://example.com", + }, + { + name: "URL with query parameters", + url: "https://example.com/search?q=cats&dogs", + shouldErr: false, + expected: "https://example.com/search?q=cats&dogs", + }, + { + name: "URL with port", + url: "https://example.com:8080/path", + shouldErr: false, + expected: "https://example.com:8080/path", + }, + { + name: "URL with fragment", + url: "https://example.com/page#section", + shouldErr: false, + expected: "https://example.com/page#section", + }, + { + name: "urlencode params", + url: "http://google.com/ ----browser-subprocess-path=C:\\\\Users\\\\Public\\\\test.bat", + shouldErr: false, + expected: "http://google.com/%20----browser-subprocess-path=C:%5C%5CUsers%5C%5CPublic%5C%5Ctest.bat", + }, + + // Invalid schemes + { + name: "javascript scheme", + url: "javascript:alert('xss')", + shouldErr: true, + errMsg: "scheme not allowed", + }, + { + name: "data scheme", + url: "data:text/html,", + shouldErr: true, + errMsg: "scheme not allowed", + }, + { + name: "file scheme", + url: "file:///etc/passwd", + shouldErr: true, + errMsg: "scheme not allowed", + }, + { + name: "ftp scheme", + url: "ftp://files.example.com/file.txt", + shouldErr: true, + errMsg: "scheme not allowed", + }, + + // Malformed URLs + { + name: "not a URL", + url: "not-a-url", + shouldErr: true, + errMsg: "scheme not allowed", // will have empty scheme + }, + { + name: "missing scheme", + url: "example.com", + shouldErr: true, + errMsg: "scheme not allowed", + }, + { + name: "malformed URL", + url: "https://", + shouldErr: true, + errMsg: "missing host", + }, + { + name: "empty host", + url: "http:///path", + shouldErr: true, + errMsg: "missing host", + }, + + // Security issues + { + name: "null byte in URL", + url: "https://example.com\x00/hidden", + shouldErr: true, + errMsg: "null bytes not allowed", + }, + { + name: "control characters", + url: "https://example.com\n/path", + shouldErr: true, + errMsg: "control character", + }, + { + name: "carriage return", + url: "https://example.com\r/path", + shouldErr: true, + errMsg: "control character", + }, + { + name: "URL with tab character", + url: "https://example.com/path?q=hello\tworld", + shouldErr: true, + errMsg: "control character", + }, + { + name: "URL with path parameters", + url: "https://example.com/path;param=value", + shouldErr: true, + errMsg: "shell metacharacters not allowed", + }, + { + name: "URL with special characters in query", + url: "https://example.com/search?q=hello world&filter=price>100", + shouldErr: true, + errMsg: "shell metacharacters not allowed", + }, + { + name: "URL with special characters in query and params", + url: "https://example.com/search?q=hello ----browser-subprocess-path=C:\\\\Users\\\\Public\\\\test.bat", + shouldErr: true, + errMsg: "shell metacharacters not allowed", + }, + { + name: "URL with dollar sign in query", + url: "https://example.com/search?price=$100", + shouldErr: true, + errMsg: "shell metacharacters not allowed", + }, + { + name: "URL with parentheses", + url: "https://example.com/file(1).html", + shouldErr: true, + errMsg: "shell metacharacters not allowed", + }, + { + name: "URL with unicode", + url: "https://example.com/search?q=hello\u2001foo", + shouldErr: true, + errMsg: "unicode dangerous characters not allowed", + }, + + // Edge cases + { + name: "international domain", + url: "https://例え.テスト/path", + shouldErr: false, + expected: "https://%E4%BE%8B%E3%81%88.%E3%83%86%E3%82%B9%E3%83%88/path", + }, + { + name: "URL with pipe character", + url: "https://example.com/user/123|admin", + shouldErr: false, + expected: "https://example.com/user/123%7Cadmin", + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + // We'll test only the validation part to avoid actually opening URLs + sanitized, err := utils.ValidateAndSanitizeURL(tc.url) + + if tc.shouldErr { + if err == nil { + t.Errorf("expected error for URL %q, but got none", tc.url) + } else if tc.errMsg != "" && !strings.Contains(err.Error(), tc.errMsg) { + t.Errorf("expected error containing %q, got %q", tc.errMsg, err.Error()) + } + } else { + if err != nil { + t.Errorf("expected no error for URL %q, but got: %v", tc.url, err) + } + if sanitized != tc.expected { + t.Errorf("unexpected sanitized URL for %q: expected %q, got %q", tc.url, tc.expected, sanitized) + } + } + }) + } +} diff --git a/v2/internal/github/github.go b/v2/internal/github/github.go index c16e1d9dd..2aa5e1432 100644 --- a/v2/internal/github/github.go +++ b/v2/internal/github/github.go @@ -3,6 +3,7 @@ package github import ( "encoding/json" "fmt" + "github.com/charmbracelet/glamour/styles" "io" "net/http" "net/url" @@ -39,7 +40,7 @@ func GetReleaseNotes(tagVersion string, noColour bool) string { var termRendererOpts []glamour.TermRendererOption if runtime.GOOS == "windows" || noColour { - termRendererOpts = append(termRendererOpts, glamour.WithStyles(glamour.NoTTYStyleConfig)) + termRendererOpts = append(termRendererOpts, glamour.WithStyles(styles.NoTTYStyleConfig)) } else { termRendererOpts = append(termRendererOpts, glamour.WithAutoStyle()) } diff --git a/v2/internal/go-common-file-dialog/cfd/CommonFileDialog_nonWindows.go b/v2/internal/go-common-file-dialog/cfd/CommonFileDialog_nonWindows.go index 04c7cbcfe..3ab969850 100644 --- a/v2/internal/go-common-file-dialog/cfd/CommonFileDialog_nonWindows.go +++ b/v2/internal/go-common-file-dialog/cfd/CommonFileDialog_nonWindows.go @@ -5,24 +5,24 @@ package cfd import "fmt" -var errUnsupported = fmt.Errorf("common file dialogs are only available on windows") +var unsupportedError = fmt.Errorf("common file dialogs are only available on windows") // TODO doc func NewOpenFileDialog(config DialogConfig) (OpenFileDialog, error) { - return nil, errUnsupported + return nil, unsupportedError } // TODO doc func NewOpenMultipleFilesDialog(config DialogConfig) (OpenMultipleFilesDialog, error) { - return nil, errUnsupported + return nil, unsupportedError } // TODO doc func NewSelectFolderDialog(config DialogConfig) (SelectFolderDialog, error) { - return nil, errUnsupported + return nil, unsupportedError } // TODO doc func NewSaveFileDialog(config DialogConfig) (SaveFileDialog, error) { - return nil, errUnsupported + return nil, unsupportedError } diff --git a/v2/internal/go-common-file-dialog/cfd/DialogConfig.go b/v2/internal/go-common-file-dialog/cfd/DialogConfig.go index 221dbef27..9e06fb503 100644 --- a/v2/internal/go-common-file-dialog/cfd/DialogConfig.go +++ b/v2/internal/go-common-file-dialog/cfd/DialogConfig.go @@ -2,6 +2,12 @@ package cfd +import ( + "fmt" + "os" + "reflect" +) + type FileFilter struct { // The display name of the filter (That is shown to the user) DisplayName string @@ -9,6 +15,9 @@ type FileFilter struct { Pattern string } +// Never obfuscate the FileFilter type. +var _ = reflect.TypeOf(FileFilter{}) + type DialogConfig struct { // The title of the dialog Title string @@ -67,6 +76,10 @@ func (config *DialogConfig) apply(dialog Dialog) (err error) { } if config.Folder != "" { + _, err = os.Stat(config.Folder) + if err != nil { + return + } err = dialog.SetFolder(config.Folder) if err != nil { return @@ -74,6 +87,10 @@ func (config *DialogConfig) apply(dialog Dialog) (err error) { } if config.DefaultFolder != "" { + _, err = os.Stat(config.DefaultFolder) + if err != nil { + return + } err = dialog.SetDefaultFolder(config.DefaultFolder) if err != nil { return @@ -102,6 +119,10 @@ func (config *DialogConfig) apply(dialog Dialog) (err error) { } if config.SelectedFileFilterIndex != 0 { + if config.SelectedFileFilterIndex > uint(len(fileFilters)) { + err = fmt.Errorf("selected file filter index out of range") + return + } err = dialog.SetSelectedFileFilterIndex(config.SelectedFileFilterIndex) if err != nil { return diff --git a/v2/internal/go-common-file-dialog/cfd/errors.go b/v2/internal/go-common-file-dialog/cfd/errors.go index 6f21fedbf..4ca3300b9 100644 --- a/v2/internal/go-common-file-dialog/cfd/errors.go +++ b/v2/internal/go-common-file-dialog/cfd/errors.go @@ -2,4 +2,8 @@ package cfd import "errors" -var ErrCancelled = errors.New("cancelled by user") +var ( + ErrCancelled = errors.New("cancelled by user") + ErrInvalidGUID = errors.New("guid cannot be nil") + ErrEmptyFilters = errors.New("must specify at least one filter") +) diff --git a/v2/internal/go-common-file-dialog/cfd/iFileOpenDialog.go b/v2/internal/go-common-file-dialog/cfd/iFileOpenDialog.go index 4c080c916..b1be23fcf 100644 --- a/v2/internal/go-common-file-dialog/cfd/iFileOpenDialog.go +++ b/v2/internal/go-common-file-dialog/cfd/iFileOpenDialog.go @@ -5,7 +5,7 @@ package cfd import ( "github.com/go-ole/go-ole" - "github.com/wailsapp/wails/v2/internal/go-common-file-dialog/util" + "github.com/google/uuid" "syscall" "unsafe" ) @@ -106,7 +106,7 @@ func (fileOpenDialog *iFileOpenDialog) SetFileFilters(filter []FileFilter) error } func (fileOpenDialog *iFileOpenDialog) SetRole(role string) error { - return fileOpenDialog.vtbl.setClientGuid(unsafe.Pointer(fileOpenDialog), util.StringToUUID(role)) + return fileOpenDialog.vtbl.setClientGuid(unsafe.Pointer(fileOpenDialog), StringToUUID(role)) } // This should only be callable when the user asks for a multi select because @@ -164,8 +164,7 @@ func (fileOpenDialog *iFileOpenDialog) setIsMultiselect(isMultiselect bool) erro func (vtbl *iFileOpenDialogVtbl) getResults(objPtr unsafe.Pointer) (*iShellItemArray, error) { var shellItemArray *iShellItemArray - ret, _, _ := syscall.Syscall(vtbl.GetResults, - 1, + ret, _, _ := syscall.SyscallN(vtbl.GetResults, uintptr(objPtr), uintptr(unsafe.Pointer(&shellItemArray)), 0) @@ -195,3 +194,7 @@ func (vtbl *iFileOpenDialogVtbl) getResultsStrings(objPtr unsafe.Pointer) ([]str } return results, nil } + +func StringToUUID(str string) *ole.GUID { + return ole.NewGUID(uuid.NewSHA1(uuid.Nil, []byte(str)).String()) +} diff --git a/v2/internal/go-common-file-dialog/cfd/iFileSaveDialog.go b/v2/internal/go-common-file-dialog/cfd/iFileSaveDialog.go index 3effeda25..ddee7b246 100644 --- a/v2/internal/go-common-file-dialog/cfd/iFileSaveDialog.go +++ b/v2/internal/go-common-file-dialog/cfd/iFileSaveDialog.go @@ -5,7 +5,6 @@ package cfd import ( "github.com/go-ole/go-ole" - "github.com/wailsapp/wails/v2/internal/go-common-file-dialog/util" "unsafe" ) @@ -77,7 +76,7 @@ func (fileSaveDialog *iFileSaveDialog) SetFileFilters(filter []FileFilter) error } func (fileSaveDialog *iFileSaveDialog) SetRole(role string) error { - return fileSaveDialog.vtbl.setClientGuid(unsafe.Pointer(fileSaveDialog), util.StringToUUID(role)) + return fileSaveDialog.vtbl.setClientGuid(unsafe.Pointer(fileSaveDialog), StringToUUID(role)) } func (fileSaveDialog *iFileSaveDialog) SetDefaultExtension(defaultExtension string) error { diff --git a/v2/internal/go-common-file-dialog/cfd/iShellItem.go b/v2/internal/go-common-file-dialog/cfd/iShellItem.go index c97efd8bb..080115345 100644 --- a/v2/internal/go-common-file-dialog/cfd/iShellItem.go +++ b/v2/internal/go-common-file-dialog/cfd/iShellItem.go @@ -30,6 +30,10 @@ type iShellItemVtbl struct { func newIShellItem(path string) (*iShellItem, error) { var shellItem *iShellItem pathPtr := ole.SysAllocString(path) + defer func(v *int16) { + _ = ole.SysFreeString(v) + }(pathPtr) + ret, _, _ := procSHCreateItemFromParsingName.Call( uintptr(unsafe.Pointer(pathPtr)), 0, @@ -42,7 +46,7 @@ func (vtbl *iShellItemVtbl) getDisplayName(objPtr unsafe.Pointer) (string, error var ptr *uint16 ret, _, _ := syscall.SyscallN(vtbl.GetDisplayName, uintptr(objPtr), - 0x80058000, // SIGDN_FILESYSPATH + 0x80058000, // SIGDN_FILESYSPATH, uintptr(unsafe.Pointer(&ptr))) if err := hresultToError(ret); err != nil { return "", err diff --git a/v2/internal/go-common-file-dialog/cfd/iShellItemArray.go b/v2/internal/go-common-file-dialog/cfd/iShellItemArray.go index d904e72b2..c548160d1 100644 --- a/v2/internal/go-common-file-dialog/cfd/iShellItemArray.go +++ b/v2/internal/go-common-file-dialog/cfd/iShellItemArray.go @@ -38,11 +38,9 @@ type iShellItemArrayVtbl struct { func (vtbl *iShellItemArrayVtbl) getCount(objPtr unsafe.Pointer) (uintptr, error) { var count uintptr - ret, _, _ := syscall.Syscall(vtbl.GetCount, - 1, + ret, _, _ := syscall.SyscallN(vtbl.GetCount, uintptr(objPtr), - uintptr(unsafe.Pointer(&count)), - 0) + uintptr(unsafe.Pointer(&count))) if err := hresultToError(ret); err != nil { return 0, err } @@ -51,8 +49,7 @@ func (vtbl *iShellItemArrayVtbl) getCount(objPtr unsafe.Pointer) (uintptr, error func (vtbl *iShellItemArrayVtbl) getItemAt(objPtr unsafe.Pointer, index uintptr) (string, error) { var shellItem *iShellItem - ret, _, _ := syscall.Syscall(vtbl.GetItemAt, - 2, + ret, _, _ := syscall.SyscallN(vtbl.GetItemAt, uintptr(objPtr), index, uintptr(unsafe.Pointer(&shellItem))) diff --git a/v2/internal/go-common-file-dialog/cfd/vtblCommonFunc.go b/v2/internal/go-common-file-dialog/cfd/vtblCommonFunc.go index 929d5a2b7..581a7b25c 100644 --- a/v2/internal/go-common-file-dialog/cfd/vtblCommonFunc.go +++ b/v2/internal/go-common-file-dialog/cfd/vtblCommonFunc.go @@ -1,10 +1,8 @@ //go:build windows -// +build windows package cfd import ( - "fmt" "github.com/go-ole/go-ole" "strings" "syscall" @@ -19,27 +17,23 @@ func hresultToError(hr uintptr) error { } func (vtbl *iUnknownVtbl) release(objPtr unsafe.Pointer) error { - ret, _, _ := syscall.Syscall(vtbl.Release, - 0, + ret, _, _ := syscall.SyscallN(vtbl.Release, uintptr(objPtr), - 0, 0) return hresultToError(ret) } func (vtbl *iModalWindowVtbl) show(objPtr unsafe.Pointer, hwnd uintptr) error { - ret, _, _ := syscall.Syscall(vtbl.Show, - 1, + ret, _, _ := syscall.SyscallN(vtbl.Show, uintptr(objPtr), - hwnd, - 0) + hwnd) return hresultToError(ret) } func (vtbl *iFileDialogVtbl) setFileTypes(objPtr unsafe.Pointer, filters []FileFilter) error { cFileTypes := len(filters) if cFileTypes < 0 { - return fmt.Errorf("must specify at least one filter") + return ErrEmptyFilters } comDlgFilterSpecs := make([]comDlgFilterSpec, cFileTypes) for i := 0; i < cFileTypes; i++ { @@ -49,8 +43,16 @@ func (vtbl *iFileDialogVtbl) setFileTypes(objPtr unsafe.Pointer, filters []FileF pszSpec: ole.SysAllocString(filter.Pattern), } } - ret, _, _ := syscall.Syscall(vtbl.SetFileTypes, - 2, + + // Ensure memory is freed after use + defer func() { + for _, spec := range comDlgFilterSpecs { + ole.SysFreeString(spec.pszName) + ole.SysFreeString(spec.pszSpec) + } + }() + + ret, _, _ := syscall.SyscallN(vtbl.SetFileTypes, uintptr(objPtr), uintptr(cFileTypes), uintptr(unsafe.Pointer(&comDlgFilterSpecs[0]))) @@ -82,21 +84,17 @@ func (vtbl *iFileDialogVtbl) setFileTypes(objPtr unsafe.Pointer, filters []FileF // FOS_FORCEPREVIEWPANEON = 0x40000000, // FOS_SUPPORTSTREAMABLEITEMS = 0x80000000 func (vtbl *iFileDialogVtbl) setOptions(objPtr unsafe.Pointer, options uint32) error { - ret, _, _ := syscall.Syscall(vtbl.SetOptions, - 1, + ret, _, _ := syscall.SyscallN(vtbl.SetOptions, uintptr(objPtr), - uintptr(options), - 0) + uintptr(options)) return hresultToError(ret) } func (vtbl *iFileDialogVtbl) getOptions(objPtr unsafe.Pointer) (uint32, error) { var options uint32 - ret, _, _ := syscall.Syscall(vtbl.GetOptions, - 1, + ret, _, _ := syscall.SyscallN(vtbl.GetOptions, uintptr(objPtr), - uintptr(unsafe.Pointer(&options)), - 0) + uintptr(unsafe.Pointer(&options))) return options, hresultToError(ret) } @@ -122,11 +120,9 @@ func (vtbl *iFileDialogVtbl) setDefaultFolder(objPtr unsafe.Pointer, path string return err } defer shellItem.vtbl.release(unsafe.Pointer(shellItem)) - ret, _, _ := syscall.Syscall(vtbl.SetDefaultFolder, - 1, + ret, _, _ := syscall.SyscallN(vtbl.SetDefaultFolder, uintptr(objPtr), - uintptr(unsafe.Pointer(shellItem)), - 0) + uintptr(unsafe.Pointer(shellItem))) return hresultToError(ret) } @@ -136,40 +132,32 @@ func (vtbl *iFileDialogVtbl) setFolder(objPtr unsafe.Pointer, path string) error return err } defer shellItem.vtbl.release(unsafe.Pointer(shellItem)) - ret, _, _ := syscall.Syscall(vtbl.SetFolder, - 1, + ret, _, _ := syscall.SyscallN(vtbl.SetFolder, uintptr(objPtr), - uintptr(unsafe.Pointer(shellItem)), - 0) + uintptr(unsafe.Pointer(shellItem))) return hresultToError(ret) } func (vtbl *iFileDialogVtbl) setTitle(objPtr unsafe.Pointer, title string) error { titlePtr := ole.SysAllocString(title) - ret, _, _ := syscall.Syscall(vtbl.SetTitle, - 1, + defer ole.SysFreeString(titlePtr) // Ensure the string is freed + ret, _, _ := syscall.SyscallN(vtbl.SetTitle, uintptr(objPtr), - uintptr(unsafe.Pointer(titlePtr)), - 0) + uintptr(unsafe.Pointer(titlePtr))) return hresultToError(ret) } func (vtbl *iFileDialogVtbl) close(objPtr unsafe.Pointer) error { - ret, _, _ := syscall.Syscall(vtbl.Close, - 1, - uintptr(objPtr), - 0, - 0) + ret, _, _ := syscall.SyscallN(vtbl.Close, + uintptr(objPtr)) return hresultToError(ret) } func (vtbl *iFileDialogVtbl) getResult(objPtr unsafe.Pointer) (*iShellItem, error) { var shellItem *iShellItem - ret, _, _ := syscall.Syscall(vtbl.GetResult, - 1, + ret, _, _ := syscall.SyscallN(vtbl.GetResult, uintptr(objPtr), - uintptr(unsafe.Pointer(&shellItem)), - 0) + uintptr(unsafe.Pointer(&shellItem))) return shellItem, hresultToError(ret) } @@ -186,42 +174,51 @@ func (vtbl *iFileDialogVtbl) getResultString(objPtr unsafe.Pointer) (string, err } func (vtbl *iFileDialogVtbl) setClientGuid(objPtr unsafe.Pointer, guid *ole.GUID) error { - ret, _, _ := syscall.Syscall(vtbl.SetClientGuid, - 1, + // Ensure the GUID is not nil + if guid == nil { + return ErrInvalidGUID + } + + // Call the SetClientGuid method + ret, _, _ := syscall.SyscallN(vtbl.SetClientGuid, uintptr(objPtr), - uintptr(unsafe.Pointer(guid)), - 0) + uintptr(unsafe.Pointer(guid))) + + // Convert the HRESULT to a Go error return hresultToError(ret) } func (vtbl *iFileDialogVtbl) setDefaultExtension(objPtr unsafe.Pointer, defaultExtension string) error { - if defaultExtension[0] == '.' { + // Ensure the string is not empty before accessing the first character + if len(defaultExtension) > 0 && defaultExtension[0] == '.' { defaultExtension = strings.TrimPrefix(defaultExtension, ".") } + + // Allocate memory for the default extension string defaultExtensionPtr := ole.SysAllocString(defaultExtension) - ret, _, _ := syscall.Syscall(vtbl.SetDefaultExtension, - 1, + defer ole.SysFreeString(defaultExtensionPtr) // Ensure the string is freed + + // Call the SetDefaultExtension method + ret, _, _ := syscall.SyscallN(vtbl.SetDefaultExtension, uintptr(objPtr), - uintptr(unsafe.Pointer(defaultExtensionPtr)), - 0) + uintptr(unsafe.Pointer(defaultExtensionPtr))) + + // Convert the HRESULT to a Go error return hresultToError(ret) } func (vtbl *iFileDialogVtbl) setFileName(objPtr unsafe.Pointer, fileName string) error { fileNamePtr := ole.SysAllocString(fileName) - ret, _, _ := syscall.Syscall(vtbl.SetFileName, - 1, + defer ole.SysFreeString(fileNamePtr) // Ensure the string is freed + ret, _, _ := syscall.SyscallN(vtbl.SetFileName, uintptr(objPtr), - uintptr(unsafe.Pointer(fileNamePtr)), - 0) + uintptr(unsafe.Pointer(fileNamePtr))) return hresultToError(ret) } func (vtbl *iFileDialogVtbl) setSelectedFileFilterIndex(objPtr unsafe.Pointer, index uint) error { - ret, _, _ := syscall.Syscall(vtbl.SetFileTypeIndex, - 1, + ret, _, _ := syscall.SyscallN(vtbl.SetFileTypeIndex, uintptr(objPtr), - uintptr(index+1), // SetFileTypeIndex counts from 1 - 0) + uintptr(index+1)) // SetFileTypeIndex counts from 1 return hresultToError(ret) } diff --git a/v2/internal/go-common-file-dialog/cfdutil/CFDUtil.go b/v2/internal/go-common-file-dialog/cfdutil/CFDUtil.go index 655266bc3..bde52d743 100644 --- a/v2/internal/go-common-file-dialog/cfdutil/CFDUtil.go +++ b/v2/internal/go-common-file-dialog/cfdutil/CFDUtil.go @@ -10,9 +10,7 @@ func ShowOpenFileDialog(config cfd.DialogConfig) (string, error) { if err != nil { return "", err } - defer func() { - _ = dialog.Release() - }() + defer dialog.Release() return dialog.ShowAndGetResult() } @@ -22,9 +20,7 @@ func ShowOpenMultipleFilesDialog(config cfd.DialogConfig) ([]string, error) { if err != nil { return nil, err } - defer func() { - _ = dialog.Release() - }() + defer dialog.Release() return dialog.ShowAndGetResults() } @@ -34,9 +30,7 @@ func ShowPickFolderDialog(config cfd.DialogConfig) (string, error) { if err != nil { return "", err } - defer func() { - _ = dialog.Release() - }() + defer dialog.Release() return dialog.ShowAndGetResult() } @@ -46,8 +40,6 @@ func ShowSaveFileDialog(config cfd.DialogConfig) (string, error) { if err != nil { return "", err } - defer func() { - _ = dialog.Release() - }() + defer dialog.Release() return dialog.ShowAndGetResult() } diff --git a/v2/internal/menumanager/processedMenu.go b/v2/internal/menumanager/processedMenu.go index 0f2351846..c87646ccb 100644 --- a/v2/internal/menumanager/processedMenu.go +++ b/v2/internal/menumanager/processedMenu.go @@ -23,7 +23,7 @@ type ProcessedMenuItem struct { Hidden bool `json:",omitempty"` // Checked indicates if the item is selected (used by Checkbox and Radio types only) Checked bool `json:",omitempty"` - // Submenu contains a list of menu items that will be shown as a submenu + // SubMenu contains a list of menu items that will be shown as a submenu // SubMenu []*MenuItem `json:"SubMenu,omitempty"` SubMenu *ProcessedMenu `json:",omitempty"` /* diff --git a/v2/internal/platform/win32/consts.go b/v2/internal/platform/win32/consts.go index 03f42b1a6..43149b036 100644 --- a/v2/internal/platform/win32/consts.go +++ b/v2/internal/platform/win32/consts.go @@ -80,7 +80,7 @@ ShouldSystemUseDarkMode = bool () // ordinal 138 SetPreferredAppMode = PreferredAppMode (PreferredAppMode appMode) // ordinal 135, since 18334 IsDarkModeAllowedForApp = bool () // ordinal 139 */ -func init() { +func Init() { if IsWindowsVersionAtLeast(10, 0, 18334) { // AllowDarkModeForWindow is only available on Windows 10+ diff --git a/v2/internal/project/project.go b/v2/internal/project/project.go index a1de1b943..2df99bdfa 100644 --- a/v2/internal/project/project.go +++ b/v2/internal/project/project.go @@ -42,6 +42,9 @@ type Project struct { // Build directory BuildDir string `json:"build:dir"` + // BuildTags Extra tags to process during build + BuildTags string `json:"build:tags"` + // The output filename OutputFilename string `json:"outputfilename"` @@ -93,6 +96,9 @@ type Project struct { // Frontend directory FrontendDir string `json:"frontend:dir"` + // The timeout in seconds for Vite server detection. Default 10 + ViteServerTimeout int `json:"viteServerTimeout"` + Bindings Bindings `json:"bindings"` } @@ -175,6 +181,9 @@ func (p *Project) setDefaults() { if p.DevServer == "" { p.DevServer = "localhost:34115" } + if p.ViteServerTimeout == 0 { + p.ViteServerTimeout = 10 + } if p.NSISType == "" { p.NSISType = "multiple" } diff --git a/v2/internal/s/s.go b/v2/internal/s/s.go index 5ba0d2eaa..adb304178 100644 --- a/v2/internal/s/s.go +++ b/v2/internal/s/s.go @@ -5,7 +5,6 @@ import ( "encoding/hex" "fmt" "io" - "io/ioutil" "os" "path/filepath" "strings" @@ -29,7 +28,7 @@ func checkError(err error) { func mute() { originalOutput = Output - Output = ioutil.Discard + Output = io.Discard } func unmute() { diff --git a/v2/internal/staticanalysis/test/standard/go.mod b/v2/internal/staticanalysis/test/standard/go.mod index ae0c84abe..c9fe1fb52 100644 --- a/v2/internal/staticanalysis/test/standard/go.mod +++ b/v2/internal/staticanalysis/test/standard/go.mod @@ -1,8 +1,8 @@ module changeme -go 1.22 +go 1.18 -require github.com/wailsapp/wails/v2 v2.8.0 +require github.com/wailsapp/wails/v2 v2.3.1 require ( github.com/bep/debounce v1.2.1 // indirect @@ -10,25 +10,25 @@ require ( github.com/google/uuid v1.3.0 // indirect github.com/imdario/mergo v0.3.13 // indirect github.com/jchv/go-winloader v0.0.0-20210711035445-715c2860da7e // indirect - github.com/labstack/echo/v4 v4.10.2 // indirect + github.com/labstack/echo/v4 v4.9.1 // indirect github.com/labstack/gommon v0.4.0 // indirect github.com/leaanthony/go-ansi-parser v1.6.0 // indirect github.com/leaanthony/gosod v1.0.3 // indirect github.com/leaanthony/slicer v1.6.0 // indirect github.com/mattn/go-colorable v0.1.13 // indirect - github.com/mattn/go-isatty v0.0.19 // indirect + github.com/mattn/go-isatty v0.0.16 // indirect github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 // indirect github.com/pkg/errors v0.9.1 // indirect - github.com/rivo/uniseg v0.4.4 // indirect - github.com/samber/lo v1.38.1 // indirect + github.com/rivo/uniseg v0.4.2 // indirect + github.com/samber/lo v1.27.1 // indirect github.com/tkrajina/go-reflector v0.5.6 // indirect github.com/valyala/bytebufferpool v1.0.0 // indirect - github.com/valyala/fasttemplate v1.2.2 // indirect + github.com/valyala/fasttemplate v1.2.1 // indirect github.com/wailsapp/mimetype v1.4.1 // indirect - golang.org/x/crypto v0.18.0 // indirect - golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1 // indirect - golang.org/x/net v0.20.0 // indirect - golang.org/x/sys v0.16.0 // indirect + golang.org/x/crypto v0.21.0 // indirect + golang.org/x/exp v0.0.0-20220303212507-bbda1eaf7a17 // indirect + golang.org/x/net v0.23.0 // indirect + golang.org/x/sys v0.18.0 // indirect golang.org/x/text v0.14.0 // indirect ) diff --git a/v2/internal/staticanalysis/test/standard/go.sum b/v2/internal/staticanalysis/test/standard/go.sum index 96e20126c..2cd0cf773 100644 --- a/v2/internal/staticanalysis/test/standard/go.sum +++ b/v2/internal/staticanalysis/test/standard/go.sum @@ -13,7 +13,6 @@ github.com/jchv/go-winloader v0.0.0-20210711035445-715c2860da7e h1:Q3+PugElBCf4P github.com/jchv/go-winloader v0.0.0-20210711035445-715c2860da7e/go.mod h1:alcuEEnZsY1WQsagKhZDsoPCRoOijYqhZvPwLG0kzVs= github.com/labstack/echo/v4 v4.9.1 h1:GliPYSpzGKlyOhqIbG8nmHBo3i1saKWFOgh41AN3b+Y= github.com/labstack/echo/v4 v4.9.1/go.mod h1:Pop5HLc+xoc4qhTZ1ip6C0RtP7Z+4VzRLWZZFKqbbjo= -github.com/labstack/echo/v4 v4.10.2/go.mod h1:OEyqf2//K1DFdE57vw2DRgWY0M7s65IVQO2FzvI4J5k= github.com/labstack/gommon v0.4.0 h1:y7cvthEAEbU0yHOf4axH8ZG2NH8knB9iNSoTO8dyIk8= github.com/labstack/gommon v0.4.0/go.mod h1:uW6kP17uPlLJsD3ijUYn3/M5bAxtlZhMI6m3MFxTMTM= github.com/leaanthony/debme v1.2.1 h1:9Tgwf+kjcrbMQ4WnPcEIUcQuIZYqdWftzZkBr+i/oOc= @@ -33,7 +32,6 @@ github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovk github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= -github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 h1:KoWmjvw+nsYOo29YJK9vDA65RGE3NrOnUtO7a+RF9HU= github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8/go.mod h1:HKlIX3XHQyzLZPlr7++PzdhaXEj94dEiJgZDTsxEqUI= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= @@ -43,10 +41,8 @@ github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZN github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rivo/uniseg v0.4.2 h1:YwD0ulJSJytLpiaWua0sBDusfsCZohxjxzVTYjwxfV8= github.com/rivo/uniseg v0.4.2/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= -github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/samber/lo v1.27.1 h1:sTXwkRiIFIQG+G0HeAvOEnGjqWeWtI9cg5/n51KrxPg= github.com/samber/lo v1.27.1/go.mod h1:it33p9UtPMS7z72fP4gw/EIfQB2eI8ke7GR2wc6+Rhg= -github.com/samber/lo v1.38.1/go.mod h1:+m/ZKRl6ClXCE2Lgf3MsQlWfh4bn1bz6CXEOxnEXnEA= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk= @@ -57,22 +53,17 @@ github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6Kllzaw github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= github.com/valyala/fasttemplate v1.2.1 h1:TVEnxayobAdVkhQfrfes2IzOB6o+z4roRkPF52WA1u4= github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ= -github.com/valyala/fasttemplate v1.2.2/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ= github.com/wailsapp/mimetype v1.4.1 h1:pQN9ycO7uo4vsUUuPeHEYoUkLVkaRntMnHJxVwYhwHs= github.com/wailsapp/mimetype v1.4.1/go.mod h1:9aV5k31bBOv5z6u+QP8TltzvNGJPmNJD4XlAL3U+j3o= github.com/wailsapp/wails/v2 v2.3.1 h1:ZJz+pyIBKyASkgO8JO31NuHO1gTTHmvwiHYHwei1CqM= github.com/wailsapp/wails/v2 v2.3.1/go.mod h1:zlNLI0E2c2qA6miiuAHtp0Bac8FaGH0tlhA19OssR/8= -github.com/wailsapp/wails/v2 v2.8.0/go.mod h1:EFUGWkUX3KofO4fmKR/GmsLy3HhPH7NbyOEaMt8lBF0= -golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k= -golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4= -golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= +golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA= +golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= golang.org/x/exp v0.0.0-20220303212507-bbda1eaf7a17 h1:3MTrJm4PyNL9NBqvYDSj3DHl46qQakyfqfWo4jgfaEM= golang.org/x/exp v0.0.0-20220303212507-bbda1eaf7a17/go.mod h1:lgLbSvA5ygNOMpwM/9anMpWVlVJ7Z+cHWq/eFuinpGE= -golang.org/x/exp v0.0.0-20230522175609-2e198f4a06a1/go.mod h1:V1LtkGg67GoY2N1AnLN78QLrzxkLyJw7RJb1gzOOz9w= golang.org/x/net v0.0.0-20210505024714-0287a6fb4125/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= -golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= -golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= +golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs= +golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200810151505-1b9f1253b3ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -82,10 +73,8 @@ golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211103235746-7861aae1554b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc= -golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= +golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= diff --git a/v2/internal/system/operatingsystem/os.go b/v2/internal/system/operatingsystem/os.go index 39f1de8e0..028a97b2e 100644 --- a/v2/internal/system/operatingsystem/os.go +++ b/v2/internal/system/operatingsystem/os.go @@ -2,9 +2,10 @@ package operatingsystem // OS contains information about the operating system type OS struct { - ID string - Name string - Version string + ID string + Name string + Version string + Branding string } // Info retrieves information about the current platform diff --git a/v2/internal/system/operatingsystem/os_windows.go b/v2/internal/system/operatingsystem/os_windows.go index 38ea43a12..a9aa05a92 100644 --- a/v2/internal/system/operatingsystem/os_windows.go +++ b/v2/internal/system/operatingsystem/os_windows.go @@ -4,10 +4,44 @@ package operatingsystem import ( "fmt" + "strings" + "syscall" + "unsafe" + "golang.org/x/sys/windows" "golang.org/x/sys/windows/registry" ) +func stripNulls(str string) string { + // Split the string into substrings at each null character + substrings := strings.Split(str, "\x00") + + // Join the substrings back into a single string + strippedStr := strings.Join(substrings, "") + + return strippedStr +} + +func mustStringToUTF16Ptr(input string) *uint16 { + input = stripNulls(input) + result, err := syscall.UTF16PtrFromString(input) + if err != nil { + panic(err) + } + return result +} + +func getBranding() string { + var modBranding = syscall.NewLazyDLL("winbrand.dll") + var brandingFormatString = modBranding.NewProc("BrandingFormatString") + + windowsLong := mustStringToUTF16Ptr("%WINDOWS_LONG%\x00") + ret, _, _ := brandingFormatString.Call( + uintptr(unsafe.Pointer(windowsLong)), + ) + return windows.UTF16PtrToString((*uint16)(unsafe.Pointer(ret))) +} + func platformInfo() (*OS, error) { // Default value var result OS @@ -27,6 +61,7 @@ func platformInfo() (*OS, error) { result.Name = productName result.Version = fmt.Sprintf("%s (Build: %s)", releaseId, currentBuild) result.ID = displayVersion + result.Branding = getBranding() return &result, key.Close() } diff --git a/v2/internal/system/packagemanager/eopkg.go b/v2/internal/system/packagemanager/eopkg.go index dbeab96de..936127eac 100644 --- a/v2/internal/system/packagemanager/eopkg.go +++ b/v2/internal/system/packagemanager/eopkg.go @@ -40,7 +40,7 @@ func (e *Eopkg) Packages() packagemap { {Name: "gcc", SystemPackage: true}, }, "pkg-config": []*Package{ - {Name: "pkg-config", SystemPackage: true}, + {Name: "pkgconf", SystemPackage: true}, }, "npm": []*Package{ {Name: "nodejs", SystemPackage: true}, diff --git a/v2/internal/typescriptify/typescriptify.go b/v2/internal/typescriptify/typescriptify.go index 85fea9c42..e732c5976 100644 --- a/v2/internal/typescriptify/typescriptify.go +++ b/v2/internal/typescriptify/typescriptify.go @@ -2,6 +2,7 @@ package typescriptify import ( "bufio" + "cmp" "fmt" "io" "log" @@ -9,6 +10,7 @@ import ( "path" "reflect" "regexp" + "slices" "strings" "time" @@ -40,6 +42,18 @@ const ( jsVariableNameRegex = `^([A-Z]|[a-z]|\$|_)([A-Z]|[a-z]|[0-9]|\$|_)*$` ) +var jsVariableUnsafeChars = regexp.MustCompile(`[^A-Za-z0-9_]`) + +func nameTypeOf(typeOf reflect.Type) string { + tname := typeOf.Name() + gidx := strings.IndexRune(tname, '[') + if gidx > 0 { // its a generic type + rem := strings.SplitN(tname, "[", 2) + tname = rem[0] + "_" + jsVariableUnsafeChars.ReplaceAllLiteralString(rem[1], "_") + } + return tname +} + // TypeOptions overrides options set by `ts_*` tags. type TypeOptions struct { TSType string @@ -261,15 +275,34 @@ func (t *TypeScriptify) AddType(typeOf reflect.Type) *TypeScriptify { func (t *typeScriptClassBuilder) AddMapField(fieldName string, field reflect.StructField) { keyType := field.Type.Key() valueType := field.Type.Elem() - valueTypeName := valueType.Name() + valueTypeName := nameTypeOf(valueType) + valueTypeSuffix := "" + valueTypePrefix := "" + if valueType.Kind() == reflect.Ptr { + valueType = valueType.Elem() + valueTypeName = nameTypeOf(valueType) + } + if valueType.Kind() == reflect.Array || valueType.Kind() == reflect.Slice { + arrayDepth := 1 + for valueType.Elem().Kind() == reflect.Array || valueType.Elem().Kind() == reflect.Slice { + valueType = valueType.Elem() + arrayDepth++ + } + valueType = valueType.Elem() + valueTypeName = nameTypeOf(valueType) + valueTypeSuffix = strings.Repeat(">", arrayDepth) + valueTypePrefix = strings.Repeat("Array<", arrayDepth) + } + if valueType.Kind() == reflect.Ptr { + valueType = valueType.Elem() + valueTypeName = nameTypeOf(valueType) + } if name, ok := t.types[valueType.Kind()]; ok { valueTypeName = name } - if valueType.Kind() == reflect.Array || valueType.Kind() == reflect.Slice { - valueTypeName = valueType.Elem().Name() + "[]" - } - if valueType.Kind() == reflect.Ptr { - valueTypeName = valueType.Elem().Name() + if valueType.Kind() == reflect.Map { + // TODO: support nested maps + valueTypeName = "any" // valueType.Elem().Name() } if valueType.Kind() == reflect.Struct && differentNamespaces(t.namespace, valueType) { valueTypeName = valueType.String() @@ -294,11 +327,13 @@ func (t *typeScriptClassBuilder) AddMapField(fieldName string, field reflect.Str fieldName = fmt.Sprintf(`"%s"?`, strippedFieldName) } } - t.fields = append(t.fields, fmt.Sprintf("%s%s: {[key: %s]: %s};", t.indent, fieldName, keyTypeStr, valueTypeName)) + t.fields = append(t.fields, fmt.Sprintf("%s%s: Record<%s, %s>;", t.indent, fieldName, keyTypeStr, valueTypePrefix+valueTypeName+valueTypeSuffix)) if valueType.Kind() == reflect.Struct { - t.constructorBody = append(t.constructorBody, fmt.Sprintf("%s%sthis%s = this.convertValues(source[\"%s\"], %s, true);", t.indent, t.indent, dotField, strippedFieldName, t.prefix+valueTypeName+t.suffix)) + t.constructorBody = append(t.constructorBody, fmt.Sprintf("%s%sthis%s = this.convertValues(source[\"%s\"], %s, true);", + t.indent, t.indent, dotField, strippedFieldName, t.prefix+valueTypePrefix+valueTypeName+valueTypeSuffix+t.suffix)) } else { - t.constructorBody = append(t.constructorBody, fmt.Sprintf("%s%sthis%s = source[\"%s\"];", t.indent, t.indent, dotField, strippedFieldName)) + t.constructorBody = append(t.constructorBody, fmt.Sprintf("%s%sthis%s = source[\"%s\"];", + t.indent, t.indent, dotField, strippedFieldName)) } } @@ -339,6 +374,9 @@ func (t *TypeScriptify) AddEnum(values interface{}) *TypeScriptify { elements = append(elements, el) } + slices.SortFunc(elements, func(a, b enumElement) int { + return cmp.Compare(a.name, b.name) + }) ty := reflect.TypeOf(elements[0].value) t.enums[ty] = elements t.enumTypes = append(t.enumTypes, EnumType{Type: ty}) @@ -483,9 +521,6 @@ func (t TypeScriptify) ConvertToFile(fileName string, packageName string) error if _, err := f.WriteString(converted); err != nil { return err } - if err != nil { - return err - } return nil } @@ -501,7 +536,7 @@ func (t *TypeScriptify) convertEnum(depth int, typeOf reflect.Type, elements []e } t.alreadyConverted[typeOf.String()] = true - entityName := t.Prefix + typeOf.Name() + t.Suffix + entityName := t.Prefix + nameTypeOf(typeOf) + t.Suffix result := "enum " + entityName + " {\n" for _, val := range elements { @@ -553,7 +588,21 @@ func (t *TypeScriptify) getFieldOptions(structType reflect.Type, field reflect.S func (t *TypeScriptify) getJSONFieldName(field reflect.StructField, isPtr bool) string { jsonFieldName := "" - jsonTag := field.Tag.Get("json") + // function, complex, and channel types cannot be json-encoded + if field.Type.Kind() == reflect.Chan || + field.Type.Kind() == reflect.Func || + field.Type.Kind() == reflect.UnsafePointer || + field.Type.Kind() == reflect.Complex128 || + field.Type.Kind() == reflect.Complex64 { + return "" + } + jsonTag, hasTag := field.Tag.Lookup("json") + if !hasTag && field.IsExported() { + jsonFieldName = field.Name + if isPtr { + jsonFieldName += "?" + } + } if len(jsonTag) > 0 { jsonTagParts := strings.Split(jsonTag, ",") if len(jsonTagParts) > 0 { @@ -593,7 +642,7 @@ func (t *TypeScriptify) convertType(depth int, typeOf reflect.Type, customCode m t.alreadyConverted[typeOf.String()] = true - entityName := t.Prefix + typeOf.Name() + t.Suffix + entityName := t.Prefix + nameTypeOf(typeOf) + t.Suffix if typeClashWithReservedKeyword(entityName) { warnAboutTypesClash(entityName) @@ -653,8 +702,10 @@ func (t *TypeScriptify) convertType(depth int, typeOf reflect.Type, customCode m } isKnownType := t.KnownStructs.Contains(getStructFQN(field.Type.String())) - println("KnownStructs:", t.KnownStructs.Join("\t")) - println(getStructFQN(field.Type.String())) + if !isKnownType { + println("KnownStructs:", t.KnownStructs.Join("\t")) + println("Not found:", getStructFQN(field.Type.String())) + } builder.AddStructField(jsonFieldName, field, !isKnownType) } else if field.Type.Kind() == reflect.Map { t.logf(depth, "- map field %s.%s", typeOf.Name(), field.Name) @@ -700,11 +751,15 @@ func (t *TypeScriptify) convertType(depth int, typeOf reflect.Type, customCode m } arrayDepth := 1 - for field.Type.Elem().Kind() == reflect.Slice { // Slice of slices: + for field.Type.Elem().Kind() == reflect.Slice || field.Type.Elem().Kind() == reflect.Array { // Slice of slices: field.Type = field.Type.Elem() arrayDepth++ } + if field.Type.Elem().Kind() == reflect.Ptr { // extract ptr type + field.Type = field.Type.Elem() + } + if field.Type.Elem().Kind() == reflect.Struct { // Slice of structs: t.logf(depth, "- struct slice %s.%s (%s)", typeOf.Name(), field.Name, field.Type.String()) typeScriptChunk, err := t.convertType(depth+1, field.Type.Elem(), customCode) @@ -794,8 +849,12 @@ type typeScriptClassBuilder struct { } func (t *typeScriptClassBuilder) AddSimpleArrayField(fieldName string, field reflect.StructField, arrayDepth int, opts TypeOptions) error { - fieldType, kind := field.Type.Elem().Name(), field.Type.Elem().Kind() - typeScriptType := t.types[kind] + fieldType := nameTypeOf(field.Type.Elem()) + kind := field.Type.Elem().Kind() + typeScriptType, ok := t.types[kind] + if !ok { + typeScriptType = "any" + } if len(fieldName) > 0 { strippedFieldName := strings.ReplaceAll(fieldName, "?", "") @@ -814,9 +873,14 @@ func (t *typeScriptClassBuilder) AddSimpleArrayField(fieldName string, field ref } func (t *typeScriptClassBuilder) AddSimpleField(fieldName string, field reflect.StructField, opts TypeOptions) error { - fieldType, kind := field.Type.Name(), field.Type.Kind() + fieldType := nameTypeOf(field.Type) + kind := field.Type.Kind() + + typeScriptType, ok := t.types[kind] + if !ok { + typeScriptType = "any" + } - typeScriptType := t.types[kind] if len(opts.TSType) > 0 { typeScriptType = opts.TSType } @@ -838,7 +902,7 @@ func (t *typeScriptClassBuilder) AddSimpleField(fieldName string, field reflect. } func (t *typeScriptClassBuilder) AddEnumField(fieldName string, field reflect.StructField) { - fieldType := field.Type.Name() + fieldType := nameTypeOf(field.Type) t.addField(fieldName, t.prefix+fieldType+t.suffix, false) strippedFieldName := strings.ReplaceAll(fieldName, "?", "") t.addInitializerFieldLine(strippedFieldName, fmt.Sprintf("source[\"%s\"]", strippedFieldName)) @@ -848,7 +912,7 @@ func (t *typeScriptClassBuilder) AddStructField(fieldName string, field reflect. strippedFieldName := strings.ReplaceAll(fieldName, "?", "") classname := "null" namespace := strings.Split(field.Type.String(), ".")[0] - fqname := t.prefix + field.Type.Name() + t.suffix + fqname := t.prefix + nameTypeOf(field.Type) + t.suffix if namespace != t.namespace { fqname = namespace + "." + fqname } @@ -867,7 +931,7 @@ func (t *typeScriptClassBuilder) AddStructField(fieldName string, field reflect. } func (t *typeScriptClassBuilder) AddArrayOfStructsField(fieldName string, field reflect.StructField, arrayDepth int) { - fieldType := field.Type.Elem().Name() + fieldType := nameTypeOf(field.Type.Elem()) if differentNamespaces(t.namespace, field.Type.Elem()) { fieldType = field.Type.Elem().String() } diff --git a/v2/pkg/assetserver/assethandler.go b/v2/pkg/assetserver/assethandler.go index b56a5d033..b8e2df076 100644 --- a/v2/pkg/assetserver/assethandler.go +++ b/v2/pkg/assetserver/assethandler.go @@ -21,6 +21,9 @@ type Logger interface { Error(message string, args ...interface{}) } +//go:embed defaultindex.html +var defaultHTML []byte + const ( indexHTML = "index.html" ) @@ -117,9 +120,7 @@ func (d *assetHandler) serveFSFile(rw http.ResponseWriter, req *http.Request, fi if err != nil { return err } - defer func() { - _ = file.Close() - }() + defer file.Close() statInfo, err := file.Stat() if err != nil { @@ -142,9 +143,7 @@ func (d *assetHandler) serveFSFile(rw http.ResponseWriter, req *http.Request, fi if err != nil { return err } - defer func() { - _ = file.Close() - }() + defer file.Close() statInfo, err = file.Stat() if err != nil { diff --git a/v2/pkg/assetserver/webview/responsewriter_darwin.go b/v2/pkg/assetserver/webview/responsewriter_darwin.go index 77de3c455..a3c73b6f1 100644 --- a/v2/pkg/assetserver/webview/responsewriter_darwin.go +++ b/v2/pkg/assetserver/webview/responsewriter_darwin.go @@ -69,6 +69,7 @@ import "C" import ( "encoding/json" + "fmt" "net/http" "unsafe" ) @@ -98,16 +99,31 @@ func (rw *responseWriter) Write(buf []byte) (int, error) { rw.WriteHeader(http.StatusOK) - var content unsafe.Pointer var contentLen int if buf != nil { - content = unsafe.Pointer(&buf[0]) contentLen = len(buf) } - if !C.URLSchemeTaskDidReceiveData(rw.r.task, content, C.int(contentLen)) { - return 0, errRequestStopped + if contentLen > 0 { + // Create a C array to hold the data + cBuf := C.malloc(C.size_t(contentLen)) + if cBuf == nil { + return 0, fmt.Errorf("memory allocation failed for %d bytes", contentLen) + } + defer C.free(cBuf) + + // Copy the Go slice to the C array + C.memcpy(cBuf, unsafe.Pointer(&buf[0]), C.size_t(contentLen)) + + if !C.URLSchemeTaskDidReceiveData(rw.r.task, cBuf, C.int(contentLen)) { + return 0, errRequestStopped + } + } else { + if !C.URLSchemeTaskDidReceiveData(rw.r.task, nil, 0) { + return 0, errRequestStopped + } } + return contentLen, nil } diff --git a/v2/pkg/buildassets/build/darwin/Info.dev.plist b/v2/pkg/buildassets/build/darwin/Info.dev.plist index 04727c23f..14121ef7c 100644 --- a/v2/pkg/buildassets/build/darwin/Info.dev.plist +++ b/v2/pkg/buildassets/build/darwin/Info.dev.plist @@ -6,7 +6,7 @@ CFBundleName {{.Info.ProductName}} CFBundleExecutable - {{.Name}} + {{.OutputFilename}} CFBundleIdentifier com.wails.{{.Name}} CFBundleVersion diff --git a/v2/pkg/buildassets/build/darwin/Info.plist b/v2/pkg/buildassets/build/darwin/Info.plist index 19cc9370c..d17a7475c 100644 --- a/v2/pkg/buildassets/build/darwin/Info.plist +++ b/v2/pkg/buildassets/build/darwin/Info.plist @@ -6,7 +6,7 @@ CFBundleName {{.Info.ProductName}} CFBundleExecutable - {{.Name}} + {{.OutputFilename}} CFBundleIdentifier com.wails.{{.Name}} CFBundleVersion diff --git a/v2/pkg/buildassets/build/windows/installer/wails_tools.nsh b/v2/pkg/buildassets/build/windows/installer/wails_tools.nsh index f9c0f8852..2f6d32195 100644 --- a/v2/pkg/buildassets/build/windows/installer/wails_tools.nsh +++ b/v2/pkg/buildassets/build/windows/installer/wails_tools.nsh @@ -158,7 +158,7 @@ RequestExecutionLevel "${REQUEST_EXECUTION_LEVEL}" ${If} ${REQUEST_EXECUTION_LEVEL} == "user" # If the installer is run in user level, check the user specific key exists and is not empty then webview2 is already installed - ReadRegStr $0 HKCU "Software\Microsoft\EdgeUpdate\Clients{F3017226-FE2A-4295-8BDF-00C3A9A7E4C5}" "pv" + ReadRegStr $0 HKCU "Software\Microsoft\EdgeUpdate\Clients\{F3017226-FE2A-4295-8BDF-00C3A9A7E4C5}" "pv" ${If} $0 != "" Goto ok ${EndIf} diff --git a/v2/pkg/buildassets/buildassets.go b/v2/pkg/buildassets/buildassets.go index 778d97fbf..6934b98bd 100644 --- a/v2/pkg/buildassets/buildassets.go +++ b/v2/pkg/buildassets/buildassets.go @@ -102,8 +102,9 @@ func ReadOriginalFileWithProjectDataAndSave(projectData *project.Project, file s } type assetData struct { - Name string - Info project.Info + Name string + Info project.Info + OutputFilename string } func resolveProjectData(content []byte, projectData *project.Project) ([]byte, error) { @@ -113,8 +114,9 @@ func resolveProjectData(content []byte, projectData *project.Project) ([]byte, e } data := &assetData{ - Name: projectData.Name, - Info: projectData.Info, + Name: projectData.Name, + Info: projectData.Info, + OutputFilename: projectData.OutputFilename, } var out bytes.Buffer diff --git a/v2/pkg/commands/bindings/bindings.go b/v2/pkg/commands/bindings/bindings.go index a4a84e1be..82ce0d58f 100644 --- a/v2/pkg/commands/bindings/bindings.go +++ b/v2/pkg/commands/bindings/bindings.go @@ -53,7 +53,14 @@ func GenerateBindings(options Options) (string, error) { } } - stdout, stderr, err = shell.RunCommand(workingDirectory, options.Compiler, "build", "-tags", tagString, "-o", filename) + envBuild := os.Environ() + envBuild = shell.SetEnv(envBuild, "GOOS", runtime.GOOS) + envBuild = shell.SetEnv(envBuild, "GOARCH", runtime.GOARCH) + // wailsbindings is executed on the build machine. + // So, use the default C compiler, not the one set for cross compiling. + envBuild = shell.RemoveEnv(envBuild, "CC") + + stdout, stderr, err = shell.RunCommandWithEnv(envBuild, workingDirectory, options.Compiler, "build", "-buildvcs=false", "-tags", tagString, "-o", filename) if err != nil { return stdout, fmt.Errorf("%s\n%s\n%s", stdout, stderr, err) } diff --git a/v2/pkg/commands/build/base.go b/v2/pkg/commands/build/base.go index 6595aff0f..239932ce8 100644 --- a/v2/pkg/commands/build/base.go +++ b/v2/pkg/commands/build/base.go @@ -193,6 +193,8 @@ func (b *BaseBuilder) CompileProject(options *Options) error { // Default go build command commands.Add("build") + commands.Add("-buildvcs=false") + // Add better debugging flags if options.Mode == Dev || options.Mode == Debug { commands.Add("-gcflags") @@ -307,7 +309,9 @@ func (b *BaseBuilder) CompileProject(options *Options) error { if v != "" { v += " " } - v += "-mmacosx-version-min=10.13" + if !strings.Contains(v, "-mmacosx-version-min") { + v += "-mmacosx-version-min=10.13" + } } return v }) @@ -344,7 +348,9 @@ func (b *BaseBuilder) CompileProject(options *Options) error { if addUTIFramework { v += "-framework UniformTypeIdentifiers " } - v += "-mmacosx-version-min=10.13" + if !strings.Contains(v, "-mmacosx-version-min") { + v += "-mmacosx-version-min=10.13" + } return v }) diff --git a/v2/pkg/commands/build/build.go b/v2/pkg/commands/build/build.go index 261f4c6d7..7263f63ae 100644 --- a/v2/pkg/commands/build/build.go +++ b/v2/pkg/commands/build/build.go @@ -69,6 +69,7 @@ type Options struct { Obfuscated bool // Indicates that bound methods should be obfuscated GarbleArgs string // The arguments for Garble SkipBindings bool // Skip binding generation + SkipEmbedCreate bool // Skip creation of embed files } // Build the project! @@ -120,8 +121,10 @@ func Build(options *Options) (string, error) { } // Create embed directories if they don't exist - if err := CreateEmbedDirectories(cwd, options); err != nil { - return "", err + if !options.SkipEmbedCreate { + if err := CreateEmbedDirectories(cwd, options); err != nil { + return "", err + } } // Generate bindings diff --git a/v2/pkg/commands/build/packager.go b/v2/pkg/commands/build/packager.go index b58cbbdf3..d406256f9 100644 --- a/v2/pkg/commands/build/packager.go +++ b/v2/pkg/commands/build/packager.go @@ -83,10 +83,10 @@ func packageApplicationForDarwin(options *Options) error { return err } // Copy binary - packedBinaryPath := filepath.Join(exeDir, options.ProjectData.Name) + packedBinaryPath := filepath.Join(exeDir, options.ProjectData.OutputFilename) err = fs.MoveFile(options.CompiledBinary, packedBinaryPath) if err != nil { - return errors.Wrap(err, "Cannot move file: "+options.ProjectData.OutputFilename) + return errors.Wrap(err, "Cannot move file: "+options.CompiledBinary) } // Generate Info.plist diff --git a/v2/pkg/commands/buildtags/buildtags.go b/v2/pkg/commands/buildtags/buildtags.go index 70820d03d..5cca16acf 100644 --- a/v2/pkg/commands/buildtags/buildtags.go +++ b/v2/pkg/commands/buildtags/buildtags.go @@ -8,7 +8,7 @@ import ( ) // Parse parses the given tags string and returns -// a cleaned slice of strings. Both comma and space delimeted +// a cleaned slice of strings. Both comma and space delimited // tags are supported but not mixed. If mixed, an error is returned. func Parse(tags string) ([]string, error) { if tags == "" { diff --git a/v2/pkg/git/git.go b/v2/pkg/git/git.go index 319c5672b..a0ac68ca9 100644 --- a/v2/pkg/git/git.go +++ b/v2/pkg/git/git.go @@ -1,7 +1,8 @@ package git import ( - "html/template" + "encoding/json" + "fmt" "runtime" "strings" @@ -30,9 +31,31 @@ func Email() (string, error) { // Name tries to retrieve the func Name() (string, error) { + errMsg := "failed to retrieve git user name: %w" stdout, _, err := shell.RunCommand(".", gitcommand(), "config", "user.name") - name := template.JSEscapeString(strings.TrimSpace(stdout)) - return name, err + if err != nil { + return "", fmt.Errorf(errMsg, err) + } + name := strings.TrimSpace(stdout) + return EscapeName(name) +} + +func EscapeName(str string) (string, error) { + b, err := json.Marshal(str) + if err != nil { + return "", err + } + // Remove the surrounding quotes + escaped := string(b[1 : len(b)-1]) + + // Check if username is JSON compliant + var js json.RawMessage + jsonVal := fmt.Sprintf(`{"name": "%s"}`, escaped) + err = json.Unmarshal([]byte(jsonVal), &js) + if err != nil { + return "", fmt.Errorf("failed to retrieve git user name: %w", err) + } + return escaped, nil } func InitRepo(projectDir string) error { diff --git a/v2/pkg/git/git_test.go b/v2/pkg/git/git_test.go new file mode 100644 index 000000000..238008ec3 --- /dev/null +++ b/v2/pkg/git/git_test.go @@ -0,0 +1,44 @@ +package git + +import ( + "testing" +) + +func TestEscapeName1(t *testing.T) { + type args struct { + str string + } + tests := []struct { + name string + args args + want string + wantErr bool + }{ + { + name: "Escape Apostrophe", + args: args{ + str: `John O'Keefe`, + }, + want: `John O'Keefe`, + }, + { + name: "Escape backslash", + args: args{ + str: `MYDOMAIN\USER`, + }, + want: `MYDOMAIN\\USER`, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := EscapeName(tt.args.str) + if (err != nil) != tt.wantErr { + t.Errorf("EscapeName() error = %v, wantErr %v", err, tt.wantErr) + return + } + if got != tt.want { + t.Errorf("EscapeName() got = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/v2/pkg/logger/logger.go b/v2/pkg/logger/logger.go index abc288265..990dffe75 100644 --- a/v2/pkg/logger/logger.go +++ b/v2/pkg/logger/logger.go @@ -41,6 +41,24 @@ func StringToLogLevel(input string) (LogLevel, error) { return result, nil } +// String returns the string representation of the LogLevel +func (l LogLevel) String() string { + switch l { + case TRACE: + return "trace" + case DEBUG: + return "debug" + case INFO: + return "info" + case WARNING: + return "warning" + case ERROR: + return "error" + default: + return "debug" + } +} + // Logger specifies the methods required to attach // a logger to a Wails application type Logger interface { diff --git a/v2/pkg/menu/menuitem.go b/v2/pkg/menu/menuitem.go index 264b2ebd4..bffc522d8 100644 --- a/v2/pkg/menu/menuitem.go +++ b/v2/pkg/menu/menuitem.go @@ -22,7 +22,7 @@ type MenuItem struct { Hidden bool // Checked indicates if the item is selected (used by Checkbox and Radio types only) Checked bool - // Submenu contains a list of menu items that will be shown as a submenu + // SubMenu contains a list of menu items that will be shown as a submenu // SubMenu []*MenuItem `json:"SubMenu,omitempty"` SubMenu *Menu diff --git a/v2/pkg/options/linux/linux.go b/v2/pkg/options/linux/linux.go index 1287f1da2..797450c27 100644 --- a/v2/pkg/options/linux/linux.go +++ b/v2/pkg/options/linux/linux.go @@ -4,10 +4,10 @@ package linux type WebviewGpuPolicy int const ( - // WebviewGpuPolicyOnDemand Hardware acceleration is enabled/disabled as request by web contents. - WebviewGpuPolicyOnDemand WebviewGpuPolicy = iota // WebviewGpuPolicyAlways Hardware acceleration is always enabled. - WebviewGpuPolicyAlways + WebviewGpuPolicyAlways WebviewGpuPolicy = iota + // WebviewGpuPolicyOnDemand Hardware acceleration is enabled/disabled as request by web contents. + WebviewGpuPolicyOnDemand // WebviewGpuPolicyNever Hardware acceleration is always disabled. WebviewGpuPolicyNever ) diff --git a/v2/pkg/options/mac/mac.go b/v2/pkg/options/mac/mac.go index 85e52755b..152145114 100644 --- a/v2/pkg/options/mac/mac.go +++ b/v2/pkg/options/mac/mac.go @@ -18,6 +18,7 @@ type AboutInfo struct { type Options struct { TitleBar *TitleBar Appearance AppearanceType + ContentProtection bool WebviewIsTransparent bool WindowIsTranslucent bool Preferences *Preferences diff --git a/v2/pkg/options/options.go b/v2/pkg/options/options.go index 282a25691..0f62d5e4b 100644 --- a/v2/pkg/options/options.go +++ b/v2/pkg/options/options.go @@ -98,6 +98,12 @@ type App struct { // DragAndDrop options for drag and drop behavior DragAndDrop *DragAndDrop + + // DisablePanicRecovery disables the panic recovery system in messages processing + DisablePanicRecovery bool + + // List of additional allowed origins for bindings in format "https://*.myapp.com,https://example.com" + BindingsAllowedOrigins string } type ErrorFormatter func(error) any diff --git a/v2/pkg/options/windows/windows.go b/v2/pkg/options/windows/windows.go index 39b91ee8d..1fe351455 100644 --- a/v2/pkg/options/windows/windows.go +++ b/v2/pkg/options/windows/windows.go @@ -35,6 +35,27 @@ const ( Tabbed BackdropType = 4 ) +const ( + // Default is 0, which means no changes to the default Windows DLL search behavior + DLLSearchDefault uint32 = 0 + // LoadLibrary flags for determining from where to search for a DLL + DLLSearchDontResolveDllReferences uint32 = 0x1 // windows.DONT_RESOLVE_DLL_REFERENCES + DLLSearchAsDataFile uint32 = 0x2 // windows.LOAD_LIBRARY_AS_DATAFILE + DLLSearchWithAlteredPath uint32 = 0x8 // windows.LOAD_WITH_ALTERED_SEARCH_PATH + DLLSearchIgnoreCodeAuthzLevel uint32 = 0x10 // windows.LOAD_IGNORE_CODE_AUTHZ_LEVEL + DLLSearchAsImageResource uint32 = 0x20 // windows.LOAD_LIBRARY_AS_IMAGE_RESOURCE + DLLSearchAsDataFileExclusive uint32 = 0x40 // windows.LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE + DLLSearchRequireSignedTarget uint32 = 0x80 // windows.LOAD_LIBRARY_REQUIRE_SIGNED_TARGET + DLLSearchDllLoadDir uint32 = 0x100 // windows.LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR + DLLSearchApplicationDir uint32 = 0x200 // windows.LOAD_LIBRARY_SEARCH_APPLICATION_DIR + DLLSearchUserDirs uint32 = 0x400 // windows.LOAD_LIBRARY_SEARCH_USER_DIRS + DLLSearchSystem32 uint32 = 0x800 // windows.LOAD_LIBRARY_SEARCH_SYSTEM32 + DLLSearchDefaultDirs uint32 = 0x1000 // windows.LOAD_LIBRARY_SEARCH_DEFAULT_DIRS + DLLSearchSafeCurrentDirs uint32 = 0x2000 // windows.LOAD_LIBRARY_SAFE_CURRENT_DIRS + DLLSearchSystem32NoForwarder uint32 = 0x4000 // windows.LOAD_LIBRARY_SEARCH_SYSTEM32_NO_FORWARDER + DLLSearchOsIntegrityContinuity uint32 = 0x8000 // windows.LOAD_LIBRARY_OS_INTEGRITY_CONTINUITY +) + func RGB(r, g, b uint8) int32 { col := int32(b) col = col<<8 | int32(g) @@ -61,6 +82,7 @@ type ThemeSettings struct { // Options are options specific to Windows type Options struct { + ContentProtection bool WebviewIsTransparent bool WindowIsTranslucent bool DisableWindowIcon bool @@ -118,6 +140,14 @@ type Options struct { // Configure whether swipe gestures should be enabled EnableSwipeGestures bool + + // Class name for the window. If empty, 'wailsWindow' will be used. + WindowClassName string + + // DLLSearchPaths controls which directories are searched when loading DLLs + // Set to 0 for default behavior, or combine multiple flags with bitwise OR + // Example: DLLSearchApplicationDir | DLLSearchSystem32 + DLLSearchPaths uint32 } func DefaultMessages() *Messages { diff --git a/v2/pkg/runtime/signal_linux.go b/v2/pkg/runtime/signal_linux.go new file mode 100644 index 000000000..6a7ed5db3 --- /dev/null +++ b/v2/pkg/runtime/signal_linux.go @@ -0,0 +1,65 @@ +//go:build linux + +package runtime + +/* +#include +#include +#include +#include + +static void fix_signal(int signum) +{ + struct sigaction st; + + if (sigaction(signum, NULL, &st) < 0) { + return; + } + st.sa_flags |= SA_ONSTACK; + sigaction(signum, &st, NULL); +} + +static void fix_all_signals() +{ +#if defined(SIGSEGV) + fix_signal(SIGSEGV); +#endif +#if defined(SIGBUS) + fix_signal(SIGBUS); +#endif +#if defined(SIGFPE) + fix_signal(SIGFPE); +#endif +#if defined(SIGABRT) + fix_signal(SIGABRT); +#endif +} +*/ +import "C" + +// ResetSignalHandlers resets signal handlers to allow panic recovery. +// +// On Linux, WebKit (used for the webview) may install signal handlers without +// the SA_ONSTACK flag, which prevents Go from properly recovering from panics +// caused by nil pointer dereferences or other memory access violations. +// +// Call this function immediately before code that might panic to ensure +// the signal handlers are properly configured for Go's panic recovery mechanism. +// +// Example usage: +// +// go func() { +// defer func() { +// if err := recover(); err != nil { +// log.Printf("Recovered from panic: %v", err) +// } +// }() +// runtime.ResetSignalHandlers() +// // Code that might panic... +// }() +// +// Note: This function only has an effect on Linux. On other platforms, +// it is a no-op. +func ResetSignalHandlers() { + C.fix_all_signals() +} diff --git a/v2/pkg/runtime/signal_other.go b/v2/pkg/runtime/signal_other.go new file mode 100644 index 000000000..3171a700c --- /dev/null +++ b/v2/pkg/runtime/signal_other.go @@ -0,0 +1,18 @@ +//go:build !linux + +package runtime + +// ResetSignalHandlers resets signal handlers to allow panic recovery. +// +// On Linux, WebKit (used for the webview) may install signal handlers without +// the SA_ONSTACK flag, which prevents Go from properly recovering from panics +// caused by nil pointer dereferences or other memory access violations. +// +// Call this function immediately before code that might panic to ensure +// the signal handlers are properly configured for Go's panic recovery mechanism. +// +// Note: This function only has an effect on Linux. On other platforms, +// it is a no-op. +func ResetSignalHandlers() { + // No-op on non-Linux platforms +} diff --git a/v2/pkg/templates/base/go.mod.tmpl b/v2/pkg/templates/base/go.mod.tmpl index dd7184879..4b34d1668 100644 --- a/v2/pkg/templates/base/go.mod.tmpl +++ b/v2/pkg/templates/base/go.mod.tmpl @@ -1,6 +1,6 @@ module changeme -go 1.18 +go 1.23.0 require github.com/wailsapp/wails/v2 {{.WailsVersion}} diff --git a/v2/pkg/templates/generate/assets/common/frontend/wailsjs/runtime/runtime.d.ts b/v2/pkg/templates/generate/assets/common/frontend/wailsjs/runtime/runtime.d.ts index e0d662b38..336fb07aa 100644 --- a/v2/pkg/templates/generate/assets/common/frontend/wailsjs/runtime/runtime.d.ts +++ b/v2/pkg/templates/generate/assets/common/frontend/wailsjs/runtime/runtime.d.ts @@ -52,6 +52,10 @@ export function EventsOnce(eventName: string, callback: (...data: any) => void): // unregisters the listener for the given event name. export function EventsOff(eventName: string): void; +// [EventsOffAll](https://wails.io/docs/reference/runtime/events#eventsoffall) +// unregisters all event listeners. +export function EventsOffAll(): void; + // [LogPrint](https://wails.io/docs/reference/runtime/log#logprint) // logs the given message as a raw message export function LogPrint(message: string): void; @@ -126,7 +130,7 @@ export function WindowUnfullscreen(): void; // [WindowSetSize](https://wails.io/docs/reference/runtime/window#windowsetsize) // Sets the width and height of the window. -export function WindowSetSize(width: number, height: number): Promise; +export function WindowSetSize(width: number, height: number): void; // [WindowGetSize](https://wails.io/docs/reference/runtime/window#windowgetsize) // Gets the width and height of the window. diff --git a/v2/pkg/templates/generate/assets/common/frontend/wailsjs/runtime/runtime.js b/v2/pkg/templates/generate/assets/common/frontend/wailsjs/runtime/runtime.js index 2c3dafcc3..b5ae16d56 100644 --- a/v2/pkg/templates/generate/assets/common/frontend/wailsjs/runtime/runtime.js +++ b/v2/pkg/templates/generate/assets/common/frontend/wailsjs/runtime/runtime.js @@ -48,6 +48,10 @@ export function EventsOff(eventName) { return window.runtime.EventsOff(eventName); } +export function EventsOffAll() { + return window.runtime.EventsOffAll(); +} + export function EventsOnce(eventName, callback) { EventsOnMultiple(eventName, callback, 1); } diff --git a/v2/pkg/templates/generate/assets/vue-ts/frontend/READ-THIS.md b/v2/pkg/templates/generate/assets/vue-ts/frontend/READ-THIS.md deleted file mode 100644 index 15b2483d9..000000000 --- a/v2/pkg/templates/generate/assets/vue-ts/frontend/READ-THIS.md +++ /dev/null @@ -1,4 +0,0 @@ -This template uses a work around as the default template does not compile due to this issue: -https://github.com/vuejs/core/issues/1228 - -In `tsconfig.json`, `isolatedModules` is set to `false` rather than `true` to work around the issue. \ No newline at end of file diff --git a/v2/pkg/templates/generate/plain/go.mod.tmpl b/v2/pkg/templates/generate/plain/go.mod.tmpl index e01fbe9e7..f6d0daec4 100644 --- a/v2/pkg/templates/generate/plain/go.mod.tmpl +++ b/v2/pkg/templates/generate/plain/go.mod.tmpl @@ -1,6 +1,6 @@ module changeme -go 1.18 +go 1.23.0 require github.com/wailsapp/wails/v2 {{.WailsVersion}} diff --git a/v2/pkg/templates/templates.go b/v2/pkg/templates/templates.go index 9b42ef365..e18185520 100644 --- a/v2/pkg/templates/templates.go +++ b/v2/pkg/templates/templates.go @@ -186,7 +186,16 @@ func Install(options *Options) (bool, *Template, error) { return false, nil, err } options.TargetDir = targetDir - if !fs.DirExists(options.TargetDir) { + if fs.DirExists(options.TargetDir) { + // Check if directory is non-empty + entries, err := os.ReadDir(options.TargetDir) + if err != nil { + return false, nil, err + } + if len(entries) > 0 { + return false, nil, fmt.Errorf("cannot initialise project in non-empty directory: %s", options.TargetDir) + } + } else { err := fs.Mkdir(options.TargetDir) if err != nil { return false, nil, err diff --git a/v2/pkg/templates/templates/lit-ts/frontend/wailsjs/runtime/runtime.d.ts b/v2/pkg/templates/templates/lit-ts/frontend/wailsjs/runtime/runtime.d.ts index e0d662b38..336fb07aa 100644 --- a/v2/pkg/templates/templates/lit-ts/frontend/wailsjs/runtime/runtime.d.ts +++ b/v2/pkg/templates/templates/lit-ts/frontend/wailsjs/runtime/runtime.d.ts @@ -52,6 +52,10 @@ export function EventsOnce(eventName: string, callback: (...data: any) => void): // unregisters the listener for the given event name. export function EventsOff(eventName: string): void; +// [EventsOffAll](https://wails.io/docs/reference/runtime/events#eventsoffall) +// unregisters all event listeners. +export function EventsOffAll(): void; + // [LogPrint](https://wails.io/docs/reference/runtime/log#logprint) // logs the given message as a raw message export function LogPrint(message: string): void; @@ -126,7 +130,7 @@ export function WindowUnfullscreen(): void; // [WindowSetSize](https://wails.io/docs/reference/runtime/window#windowsetsize) // Sets the width and height of the window. -export function WindowSetSize(width: number, height: number): Promise; +export function WindowSetSize(width: number, height: number): void; // [WindowGetSize](https://wails.io/docs/reference/runtime/window#windowgetsize) // Gets the width and height of the window. diff --git a/v2/pkg/templates/templates/lit-ts/frontend/wailsjs/runtime/runtime.js b/v2/pkg/templates/templates/lit-ts/frontend/wailsjs/runtime/runtime.js index 2c3dafcc3..b5ae16d56 100644 --- a/v2/pkg/templates/templates/lit-ts/frontend/wailsjs/runtime/runtime.js +++ b/v2/pkg/templates/templates/lit-ts/frontend/wailsjs/runtime/runtime.js @@ -48,6 +48,10 @@ export function EventsOff(eventName) { return window.runtime.EventsOff(eventName); } +export function EventsOffAll() { + return window.runtime.EventsOffAll(); +} + export function EventsOnce(eventName, callback) { EventsOnMultiple(eventName, callback, 1); } diff --git a/v2/pkg/templates/templates/lit-ts/go.mod.tmpl b/v2/pkg/templates/templates/lit-ts/go.mod.tmpl index dd7184879..4b34d1668 100644 --- a/v2/pkg/templates/templates/lit-ts/go.mod.tmpl +++ b/v2/pkg/templates/templates/lit-ts/go.mod.tmpl @@ -1,6 +1,6 @@ module changeme -go 1.18 +go 1.23.0 require github.com/wailsapp/wails/v2 {{.WailsVersion}} diff --git a/v2/pkg/templates/templates/lit/frontend/wailsjs/runtime/runtime.d.ts b/v2/pkg/templates/templates/lit/frontend/wailsjs/runtime/runtime.d.ts index e0d662b38..336fb07aa 100644 --- a/v2/pkg/templates/templates/lit/frontend/wailsjs/runtime/runtime.d.ts +++ b/v2/pkg/templates/templates/lit/frontend/wailsjs/runtime/runtime.d.ts @@ -52,6 +52,10 @@ export function EventsOnce(eventName: string, callback: (...data: any) => void): // unregisters the listener for the given event name. export function EventsOff(eventName: string): void; +// [EventsOffAll](https://wails.io/docs/reference/runtime/events#eventsoffall) +// unregisters all event listeners. +export function EventsOffAll(): void; + // [LogPrint](https://wails.io/docs/reference/runtime/log#logprint) // logs the given message as a raw message export function LogPrint(message: string): void; @@ -126,7 +130,7 @@ export function WindowUnfullscreen(): void; // [WindowSetSize](https://wails.io/docs/reference/runtime/window#windowsetsize) // Sets the width and height of the window. -export function WindowSetSize(width: number, height: number): Promise; +export function WindowSetSize(width: number, height: number): void; // [WindowGetSize](https://wails.io/docs/reference/runtime/window#windowgetsize) // Gets the width and height of the window. diff --git a/v2/pkg/templates/templates/lit/frontend/wailsjs/runtime/runtime.js b/v2/pkg/templates/templates/lit/frontend/wailsjs/runtime/runtime.js index 2c3dafcc3..b5ae16d56 100644 --- a/v2/pkg/templates/templates/lit/frontend/wailsjs/runtime/runtime.js +++ b/v2/pkg/templates/templates/lit/frontend/wailsjs/runtime/runtime.js @@ -48,6 +48,10 @@ export function EventsOff(eventName) { return window.runtime.EventsOff(eventName); } +export function EventsOffAll() { + return window.runtime.EventsOffAll(); +} + export function EventsOnce(eventName, callback) { EventsOnMultiple(eventName, callback, 1); } diff --git a/v2/pkg/templates/templates/lit/go.mod.tmpl b/v2/pkg/templates/templates/lit/go.mod.tmpl index dd7184879..4b34d1668 100644 --- a/v2/pkg/templates/templates/lit/go.mod.tmpl +++ b/v2/pkg/templates/templates/lit/go.mod.tmpl @@ -1,6 +1,6 @@ module changeme -go 1.18 +go 1.23.0 require github.com/wailsapp/wails/v2 {{.WailsVersion}} diff --git a/v2/pkg/templates/templates/plain/go.mod.tmpl b/v2/pkg/templates/templates/plain/go.mod.tmpl index dd7184879..4b34d1668 100644 --- a/v2/pkg/templates/templates/plain/go.mod.tmpl +++ b/v2/pkg/templates/templates/plain/go.mod.tmpl @@ -1,6 +1,6 @@ module changeme -go 1.18 +go 1.23.0 require github.com/wailsapp/wails/v2 {{.WailsVersion}} diff --git a/v2/pkg/templates/templates/preact-ts/frontend/wailsjs/runtime/runtime.d.ts b/v2/pkg/templates/templates/preact-ts/frontend/wailsjs/runtime/runtime.d.ts index e0d662b38..336fb07aa 100644 --- a/v2/pkg/templates/templates/preact-ts/frontend/wailsjs/runtime/runtime.d.ts +++ b/v2/pkg/templates/templates/preact-ts/frontend/wailsjs/runtime/runtime.d.ts @@ -52,6 +52,10 @@ export function EventsOnce(eventName: string, callback: (...data: any) => void): // unregisters the listener for the given event name. export function EventsOff(eventName: string): void; +// [EventsOffAll](https://wails.io/docs/reference/runtime/events#eventsoffall) +// unregisters all event listeners. +export function EventsOffAll(): void; + // [LogPrint](https://wails.io/docs/reference/runtime/log#logprint) // logs the given message as a raw message export function LogPrint(message: string): void; @@ -126,7 +130,7 @@ export function WindowUnfullscreen(): void; // [WindowSetSize](https://wails.io/docs/reference/runtime/window#windowsetsize) // Sets the width and height of the window. -export function WindowSetSize(width: number, height: number): Promise; +export function WindowSetSize(width: number, height: number): void; // [WindowGetSize](https://wails.io/docs/reference/runtime/window#windowgetsize) // Gets the width and height of the window. diff --git a/v2/pkg/templates/templates/preact-ts/frontend/wailsjs/runtime/runtime.js b/v2/pkg/templates/templates/preact-ts/frontend/wailsjs/runtime/runtime.js index 2c3dafcc3..b5ae16d56 100644 --- a/v2/pkg/templates/templates/preact-ts/frontend/wailsjs/runtime/runtime.js +++ b/v2/pkg/templates/templates/preact-ts/frontend/wailsjs/runtime/runtime.js @@ -48,6 +48,10 @@ export function EventsOff(eventName) { return window.runtime.EventsOff(eventName); } +export function EventsOffAll() { + return window.runtime.EventsOffAll(); +} + export function EventsOnce(eventName, callback) { EventsOnMultiple(eventName, callback, 1); } diff --git a/v2/pkg/templates/templates/preact-ts/go.mod.tmpl b/v2/pkg/templates/templates/preact-ts/go.mod.tmpl index dd7184879..4b34d1668 100644 --- a/v2/pkg/templates/templates/preact-ts/go.mod.tmpl +++ b/v2/pkg/templates/templates/preact-ts/go.mod.tmpl @@ -1,6 +1,6 @@ module changeme -go 1.18 +go 1.23.0 require github.com/wailsapp/wails/v2 {{.WailsVersion}} diff --git a/v2/pkg/templates/templates/preact/frontend/wailsjs/runtime/runtime.d.ts b/v2/pkg/templates/templates/preact/frontend/wailsjs/runtime/runtime.d.ts index e0d662b38..336fb07aa 100644 --- a/v2/pkg/templates/templates/preact/frontend/wailsjs/runtime/runtime.d.ts +++ b/v2/pkg/templates/templates/preact/frontend/wailsjs/runtime/runtime.d.ts @@ -52,6 +52,10 @@ export function EventsOnce(eventName: string, callback: (...data: any) => void): // unregisters the listener for the given event name. export function EventsOff(eventName: string): void; +// [EventsOffAll](https://wails.io/docs/reference/runtime/events#eventsoffall) +// unregisters all event listeners. +export function EventsOffAll(): void; + // [LogPrint](https://wails.io/docs/reference/runtime/log#logprint) // logs the given message as a raw message export function LogPrint(message: string): void; @@ -126,7 +130,7 @@ export function WindowUnfullscreen(): void; // [WindowSetSize](https://wails.io/docs/reference/runtime/window#windowsetsize) // Sets the width and height of the window. -export function WindowSetSize(width: number, height: number): Promise; +export function WindowSetSize(width: number, height: number): void; // [WindowGetSize](https://wails.io/docs/reference/runtime/window#windowgetsize) // Gets the width and height of the window. diff --git a/v2/pkg/templates/templates/preact/frontend/wailsjs/runtime/runtime.js b/v2/pkg/templates/templates/preact/frontend/wailsjs/runtime/runtime.js index 2c3dafcc3..b5ae16d56 100644 --- a/v2/pkg/templates/templates/preact/frontend/wailsjs/runtime/runtime.js +++ b/v2/pkg/templates/templates/preact/frontend/wailsjs/runtime/runtime.js @@ -48,6 +48,10 @@ export function EventsOff(eventName) { return window.runtime.EventsOff(eventName); } +export function EventsOffAll() { + return window.runtime.EventsOffAll(); +} + export function EventsOnce(eventName, callback) { EventsOnMultiple(eventName, callback, 1); } diff --git a/v2/pkg/templates/templates/preact/go.mod.tmpl b/v2/pkg/templates/templates/preact/go.mod.tmpl index dd7184879..4b34d1668 100644 --- a/v2/pkg/templates/templates/preact/go.mod.tmpl +++ b/v2/pkg/templates/templates/preact/go.mod.tmpl @@ -1,6 +1,6 @@ module changeme -go 1.18 +go 1.23.0 require github.com/wailsapp/wails/v2 {{.WailsVersion}} diff --git a/v2/pkg/templates/templates/react-ts/frontend/wailsjs/runtime/runtime.d.ts b/v2/pkg/templates/templates/react-ts/frontend/wailsjs/runtime/runtime.d.ts index e0d662b38..336fb07aa 100644 --- a/v2/pkg/templates/templates/react-ts/frontend/wailsjs/runtime/runtime.d.ts +++ b/v2/pkg/templates/templates/react-ts/frontend/wailsjs/runtime/runtime.d.ts @@ -52,6 +52,10 @@ export function EventsOnce(eventName: string, callback: (...data: any) => void): // unregisters the listener for the given event name. export function EventsOff(eventName: string): void; +// [EventsOffAll](https://wails.io/docs/reference/runtime/events#eventsoffall) +// unregisters all event listeners. +export function EventsOffAll(): void; + // [LogPrint](https://wails.io/docs/reference/runtime/log#logprint) // logs the given message as a raw message export function LogPrint(message: string): void; @@ -126,7 +130,7 @@ export function WindowUnfullscreen(): void; // [WindowSetSize](https://wails.io/docs/reference/runtime/window#windowsetsize) // Sets the width and height of the window. -export function WindowSetSize(width: number, height: number): Promise; +export function WindowSetSize(width: number, height: number): void; // [WindowGetSize](https://wails.io/docs/reference/runtime/window#windowgetsize) // Gets the width and height of the window. diff --git a/v2/pkg/templates/templates/react-ts/frontend/wailsjs/runtime/runtime.js b/v2/pkg/templates/templates/react-ts/frontend/wailsjs/runtime/runtime.js index 2c3dafcc3..b5ae16d56 100644 --- a/v2/pkg/templates/templates/react-ts/frontend/wailsjs/runtime/runtime.js +++ b/v2/pkg/templates/templates/react-ts/frontend/wailsjs/runtime/runtime.js @@ -48,6 +48,10 @@ export function EventsOff(eventName) { return window.runtime.EventsOff(eventName); } +export function EventsOffAll() { + return window.runtime.EventsOffAll(); +} + export function EventsOnce(eventName, callback) { EventsOnMultiple(eventName, callback, 1); } diff --git a/v2/pkg/templates/templates/react-ts/go.mod.tmpl b/v2/pkg/templates/templates/react-ts/go.mod.tmpl index dd7184879..4b34d1668 100644 --- a/v2/pkg/templates/templates/react-ts/go.mod.tmpl +++ b/v2/pkg/templates/templates/react-ts/go.mod.tmpl @@ -1,6 +1,6 @@ module changeme -go 1.18 +go 1.23.0 require github.com/wailsapp/wails/v2 {{.WailsVersion}} diff --git a/v2/pkg/templates/templates/react/frontend/wailsjs/runtime/runtime.d.ts b/v2/pkg/templates/templates/react/frontend/wailsjs/runtime/runtime.d.ts index e0d662b38..336fb07aa 100644 --- a/v2/pkg/templates/templates/react/frontend/wailsjs/runtime/runtime.d.ts +++ b/v2/pkg/templates/templates/react/frontend/wailsjs/runtime/runtime.d.ts @@ -52,6 +52,10 @@ export function EventsOnce(eventName: string, callback: (...data: any) => void): // unregisters the listener for the given event name. export function EventsOff(eventName: string): void; +// [EventsOffAll](https://wails.io/docs/reference/runtime/events#eventsoffall) +// unregisters all event listeners. +export function EventsOffAll(): void; + // [LogPrint](https://wails.io/docs/reference/runtime/log#logprint) // logs the given message as a raw message export function LogPrint(message: string): void; @@ -126,7 +130,7 @@ export function WindowUnfullscreen(): void; // [WindowSetSize](https://wails.io/docs/reference/runtime/window#windowsetsize) // Sets the width and height of the window. -export function WindowSetSize(width: number, height: number): Promise; +export function WindowSetSize(width: number, height: number): void; // [WindowGetSize](https://wails.io/docs/reference/runtime/window#windowgetsize) // Gets the width and height of the window. diff --git a/v2/pkg/templates/templates/react/frontend/wailsjs/runtime/runtime.js b/v2/pkg/templates/templates/react/frontend/wailsjs/runtime/runtime.js index 2c3dafcc3..b5ae16d56 100644 --- a/v2/pkg/templates/templates/react/frontend/wailsjs/runtime/runtime.js +++ b/v2/pkg/templates/templates/react/frontend/wailsjs/runtime/runtime.js @@ -48,6 +48,10 @@ export function EventsOff(eventName) { return window.runtime.EventsOff(eventName); } +export function EventsOffAll() { + return window.runtime.EventsOffAll(); +} + export function EventsOnce(eventName, callback) { EventsOnMultiple(eventName, callback, 1); } diff --git a/v2/pkg/templates/templates/react/go.mod.tmpl b/v2/pkg/templates/templates/react/go.mod.tmpl index dd7184879..4b34d1668 100644 --- a/v2/pkg/templates/templates/react/go.mod.tmpl +++ b/v2/pkg/templates/templates/react/go.mod.tmpl @@ -1,6 +1,6 @@ module changeme -go 1.18 +go 1.23.0 require github.com/wailsapp/wails/v2 {{.WailsVersion}} diff --git a/v2/pkg/templates/templates/svelte-ts/frontend/wailsjs/runtime/runtime.d.ts b/v2/pkg/templates/templates/svelte-ts/frontend/wailsjs/runtime/runtime.d.ts index e0d662b38..336fb07aa 100644 --- a/v2/pkg/templates/templates/svelte-ts/frontend/wailsjs/runtime/runtime.d.ts +++ b/v2/pkg/templates/templates/svelte-ts/frontend/wailsjs/runtime/runtime.d.ts @@ -52,6 +52,10 @@ export function EventsOnce(eventName: string, callback: (...data: any) => void): // unregisters the listener for the given event name. export function EventsOff(eventName: string): void; +// [EventsOffAll](https://wails.io/docs/reference/runtime/events#eventsoffall) +// unregisters all event listeners. +export function EventsOffAll(): void; + // [LogPrint](https://wails.io/docs/reference/runtime/log#logprint) // logs the given message as a raw message export function LogPrint(message: string): void; @@ -126,7 +130,7 @@ export function WindowUnfullscreen(): void; // [WindowSetSize](https://wails.io/docs/reference/runtime/window#windowsetsize) // Sets the width and height of the window. -export function WindowSetSize(width: number, height: number): Promise; +export function WindowSetSize(width: number, height: number): void; // [WindowGetSize](https://wails.io/docs/reference/runtime/window#windowgetsize) // Gets the width and height of the window. diff --git a/v2/pkg/templates/templates/svelte-ts/frontend/wailsjs/runtime/runtime.js b/v2/pkg/templates/templates/svelte-ts/frontend/wailsjs/runtime/runtime.js index 2c3dafcc3..b5ae16d56 100644 --- a/v2/pkg/templates/templates/svelte-ts/frontend/wailsjs/runtime/runtime.js +++ b/v2/pkg/templates/templates/svelte-ts/frontend/wailsjs/runtime/runtime.js @@ -48,6 +48,10 @@ export function EventsOff(eventName) { return window.runtime.EventsOff(eventName); } +export function EventsOffAll() { + return window.runtime.EventsOffAll(); +} + export function EventsOnce(eventName, callback) { EventsOnMultiple(eventName, callback, 1); } diff --git a/v2/pkg/templates/templates/svelte-ts/go.mod.tmpl b/v2/pkg/templates/templates/svelte-ts/go.mod.tmpl index dd7184879..4b34d1668 100644 --- a/v2/pkg/templates/templates/svelte-ts/go.mod.tmpl +++ b/v2/pkg/templates/templates/svelte-ts/go.mod.tmpl @@ -1,6 +1,6 @@ module changeme -go 1.18 +go 1.23.0 require github.com/wailsapp/wails/v2 {{.WailsVersion}} diff --git a/v2/pkg/templates/templates/svelte/frontend/wailsjs/runtime/runtime.d.ts b/v2/pkg/templates/templates/svelte/frontend/wailsjs/runtime/runtime.d.ts index e0d662b38..336fb07aa 100644 --- a/v2/pkg/templates/templates/svelte/frontend/wailsjs/runtime/runtime.d.ts +++ b/v2/pkg/templates/templates/svelte/frontend/wailsjs/runtime/runtime.d.ts @@ -52,6 +52,10 @@ export function EventsOnce(eventName: string, callback: (...data: any) => void): // unregisters the listener for the given event name. export function EventsOff(eventName: string): void; +// [EventsOffAll](https://wails.io/docs/reference/runtime/events#eventsoffall) +// unregisters all event listeners. +export function EventsOffAll(): void; + // [LogPrint](https://wails.io/docs/reference/runtime/log#logprint) // logs the given message as a raw message export function LogPrint(message: string): void; @@ -126,7 +130,7 @@ export function WindowUnfullscreen(): void; // [WindowSetSize](https://wails.io/docs/reference/runtime/window#windowsetsize) // Sets the width and height of the window. -export function WindowSetSize(width: number, height: number): Promise; +export function WindowSetSize(width: number, height: number): void; // [WindowGetSize](https://wails.io/docs/reference/runtime/window#windowgetsize) // Gets the width and height of the window. diff --git a/v2/pkg/templates/templates/svelte/frontend/wailsjs/runtime/runtime.js b/v2/pkg/templates/templates/svelte/frontend/wailsjs/runtime/runtime.js index 2c3dafcc3..b5ae16d56 100644 --- a/v2/pkg/templates/templates/svelte/frontend/wailsjs/runtime/runtime.js +++ b/v2/pkg/templates/templates/svelte/frontend/wailsjs/runtime/runtime.js @@ -48,6 +48,10 @@ export function EventsOff(eventName) { return window.runtime.EventsOff(eventName); } +export function EventsOffAll() { + return window.runtime.EventsOffAll(); +} + export function EventsOnce(eventName, callback) { EventsOnMultiple(eventName, callback, 1); } diff --git a/v2/pkg/templates/templates/svelte/go.mod.tmpl b/v2/pkg/templates/templates/svelte/go.mod.tmpl index dd7184879..4b34d1668 100644 --- a/v2/pkg/templates/templates/svelte/go.mod.tmpl +++ b/v2/pkg/templates/templates/svelte/go.mod.tmpl @@ -1,6 +1,6 @@ module changeme -go 1.18 +go 1.23.0 require github.com/wailsapp/wails/v2 {{.WailsVersion}} diff --git a/v2/pkg/templates/templates/vanilla-ts/frontend/wailsjs/runtime/runtime.d.ts b/v2/pkg/templates/templates/vanilla-ts/frontend/wailsjs/runtime/runtime.d.ts index e0d662b38..336fb07aa 100644 --- a/v2/pkg/templates/templates/vanilla-ts/frontend/wailsjs/runtime/runtime.d.ts +++ b/v2/pkg/templates/templates/vanilla-ts/frontend/wailsjs/runtime/runtime.d.ts @@ -52,6 +52,10 @@ export function EventsOnce(eventName: string, callback: (...data: any) => void): // unregisters the listener for the given event name. export function EventsOff(eventName: string): void; +// [EventsOffAll](https://wails.io/docs/reference/runtime/events#eventsoffall) +// unregisters all event listeners. +export function EventsOffAll(): void; + // [LogPrint](https://wails.io/docs/reference/runtime/log#logprint) // logs the given message as a raw message export function LogPrint(message: string): void; @@ -126,7 +130,7 @@ export function WindowUnfullscreen(): void; // [WindowSetSize](https://wails.io/docs/reference/runtime/window#windowsetsize) // Sets the width and height of the window. -export function WindowSetSize(width: number, height: number): Promise; +export function WindowSetSize(width: number, height: number): void; // [WindowGetSize](https://wails.io/docs/reference/runtime/window#windowgetsize) // Gets the width and height of the window. diff --git a/v2/pkg/templates/templates/vanilla-ts/frontend/wailsjs/runtime/runtime.js b/v2/pkg/templates/templates/vanilla-ts/frontend/wailsjs/runtime/runtime.js index 2c3dafcc3..b5ae16d56 100644 --- a/v2/pkg/templates/templates/vanilla-ts/frontend/wailsjs/runtime/runtime.js +++ b/v2/pkg/templates/templates/vanilla-ts/frontend/wailsjs/runtime/runtime.js @@ -48,6 +48,10 @@ export function EventsOff(eventName) { return window.runtime.EventsOff(eventName); } +export function EventsOffAll() { + return window.runtime.EventsOffAll(); +} + export function EventsOnce(eventName, callback) { EventsOnMultiple(eventName, callback, 1); } diff --git a/v2/pkg/templates/templates/vanilla-ts/go.mod.tmpl b/v2/pkg/templates/templates/vanilla-ts/go.mod.tmpl index dd7184879..4b34d1668 100644 --- a/v2/pkg/templates/templates/vanilla-ts/go.mod.tmpl +++ b/v2/pkg/templates/templates/vanilla-ts/go.mod.tmpl @@ -1,6 +1,6 @@ module changeme -go 1.18 +go 1.23.0 require github.com/wailsapp/wails/v2 {{.WailsVersion}} diff --git a/v2/pkg/templates/templates/vanilla/frontend/wailsjs/runtime/runtime.d.ts b/v2/pkg/templates/templates/vanilla/frontend/wailsjs/runtime/runtime.d.ts index e0d662b38..336fb07aa 100644 --- a/v2/pkg/templates/templates/vanilla/frontend/wailsjs/runtime/runtime.d.ts +++ b/v2/pkg/templates/templates/vanilla/frontend/wailsjs/runtime/runtime.d.ts @@ -52,6 +52,10 @@ export function EventsOnce(eventName: string, callback: (...data: any) => void): // unregisters the listener for the given event name. export function EventsOff(eventName: string): void; +// [EventsOffAll](https://wails.io/docs/reference/runtime/events#eventsoffall) +// unregisters all event listeners. +export function EventsOffAll(): void; + // [LogPrint](https://wails.io/docs/reference/runtime/log#logprint) // logs the given message as a raw message export function LogPrint(message: string): void; @@ -126,7 +130,7 @@ export function WindowUnfullscreen(): void; // [WindowSetSize](https://wails.io/docs/reference/runtime/window#windowsetsize) // Sets the width and height of the window. -export function WindowSetSize(width: number, height: number): Promise; +export function WindowSetSize(width: number, height: number): void; // [WindowGetSize](https://wails.io/docs/reference/runtime/window#windowgetsize) // Gets the width and height of the window. diff --git a/v2/pkg/templates/templates/vanilla/frontend/wailsjs/runtime/runtime.js b/v2/pkg/templates/templates/vanilla/frontend/wailsjs/runtime/runtime.js index 2c3dafcc3..b5ae16d56 100644 --- a/v2/pkg/templates/templates/vanilla/frontend/wailsjs/runtime/runtime.js +++ b/v2/pkg/templates/templates/vanilla/frontend/wailsjs/runtime/runtime.js @@ -48,6 +48,10 @@ export function EventsOff(eventName) { return window.runtime.EventsOff(eventName); } +export function EventsOffAll() { + return window.runtime.EventsOffAll(); +} + export function EventsOnce(eventName, callback) { EventsOnMultiple(eventName, callback, 1); } diff --git a/v2/pkg/templates/templates/vanilla/go.mod.tmpl b/v2/pkg/templates/templates/vanilla/go.mod.tmpl index dd7184879..4b34d1668 100644 --- a/v2/pkg/templates/templates/vanilla/go.mod.tmpl +++ b/v2/pkg/templates/templates/vanilla/go.mod.tmpl @@ -1,6 +1,6 @@ module changeme -go 1.18 +go 1.23.0 require github.com/wailsapp/wails/v2 {{.WailsVersion}} diff --git a/v2/pkg/templates/templates/vue-ts/frontend/READ-THIS.md b/v2/pkg/templates/templates/vue-ts/frontend/READ-THIS.md deleted file mode 100644 index 15b2483d9..000000000 --- a/v2/pkg/templates/templates/vue-ts/frontend/READ-THIS.md +++ /dev/null @@ -1,4 +0,0 @@ -This template uses a work around as the default template does not compile due to this issue: -https://github.com/vuejs/core/issues/1228 - -In `tsconfig.json`, `isolatedModules` is set to `false` rather than `true` to work around the issue. \ No newline at end of file diff --git a/v2/pkg/templates/templates/vue-ts/frontend/wailsjs/runtime/runtime.d.ts b/v2/pkg/templates/templates/vue-ts/frontend/wailsjs/runtime/runtime.d.ts index e0d662b38..336fb07aa 100644 --- a/v2/pkg/templates/templates/vue-ts/frontend/wailsjs/runtime/runtime.d.ts +++ b/v2/pkg/templates/templates/vue-ts/frontend/wailsjs/runtime/runtime.d.ts @@ -52,6 +52,10 @@ export function EventsOnce(eventName: string, callback: (...data: any) => void): // unregisters the listener for the given event name. export function EventsOff(eventName: string): void; +// [EventsOffAll](https://wails.io/docs/reference/runtime/events#eventsoffall) +// unregisters all event listeners. +export function EventsOffAll(): void; + // [LogPrint](https://wails.io/docs/reference/runtime/log#logprint) // logs the given message as a raw message export function LogPrint(message: string): void; @@ -126,7 +130,7 @@ export function WindowUnfullscreen(): void; // [WindowSetSize](https://wails.io/docs/reference/runtime/window#windowsetsize) // Sets the width and height of the window. -export function WindowSetSize(width: number, height: number): Promise; +export function WindowSetSize(width: number, height: number): void; // [WindowGetSize](https://wails.io/docs/reference/runtime/window#windowgetsize) // Gets the width and height of the window. diff --git a/v2/pkg/templates/templates/vue-ts/frontend/wailsjs/runtime/runtime.js b/v2/pkg/templates/templates/vue-ts/frontend/wailsjs/runtime/runtime.js index 2c3dafcc3..b5ae16d56 100644 --- a/v2/pkg/templates/templates/vue-ts/frontend/wailsjs/runtime/runtime.js +++ b/v2/pkg/templates/templates/vue-ts/frontend/wailsjs/runtime/runtime.js @@ -48,6 +48,10 @@ export function EventsOff(eventName) { return window.runtime.EventsOff(eventName); } +export function EventsOffAll() { + return window.runtime.EventsOffAll(); +} + export function EventsOnce(eventName, callback) { EventsOnMultiple(eventName, callback, 1); } diff --git a/v2/pkg/templates/templates/vue-ts/go.mod.tmpl b/v2/pkg/templates/templates/vue-ts/go.mod.tmpl index dd7184879..4b34d1668 100644 --- a/v2/pkg/templates/templates/vue-ts/go.mod.tmpl +++ b/v2/pkg/templates/templates/vue-ts/go.mod.tmpl @@ -1,6 +1,6 @@ module changeme -go 1.18 +go 1.23.0 require github.com/wailsapp/wails/v2 {{.WailsVersion}} diff --git a/v2/pkg/templates/templates/vue/frontend/wailsjs/runtime/runtime.d.ts b/v2/pkg/templates/templates/vue/frontend/wailsjs/runtime/runtime.d.ts index e0d662b38..336fb07aa 100644 --- a/v2/pkg/templates/templates/vue/frontend/wailsjs/runtime/runtime.d.ts +++ b/v2/pkg/templates/templates/vue/frontend/wailsjs/runtime/runtime.d.ts @@ -52,6 +52,10 @@ export function EventsOnce(eventName: string, callback: (...data: any) => void): // unregisters the listener for the given event name. export function EventsOff(eventName: string): void; +// [EventsOffAll](https://wails.io/docs/reference/runtime/events#eventsoffall) +// unregisters all event listeners. +export function EventsOffAll(): void; + // [LogPrint](https://wails.io/docs/reference/runtime/log#logprint) // logs the given message as a raw message export function LogPrint(message: string): void; @@ -126,7 +130,7 @@ export function WindowUnfullscreen(): void; // [WindowSetSize](https://wails.io/docs/reference/runtime/window#windowsetsize) // Sets the width and height of the window. -export function WindowSetSize(width: number, height: number): Promise; +export function WindowSetSize(width: number, height: number): void; // [WindowGetSize](https://wails.io/docs/reference/runtime/window#windowgetsize) // Gets the width and height of the window. diff --git a/v2/pkg/templates/templates/vue/frontend/wailsjs/runtime/runtime.js b/v2/pkg/templates/templates/vue/frontend/wailsjs/runtime/runtime.js index 2c3dafcc3..b5ae16d56 100644 --- a/v2/pkg/templates/templates/vue/frontend/wailsjs/runtime/runtime.js +++ b/v2/pkg/templates/templates/vue/frontend/wailsjs/runtime/runtime.js @@ -48,6 +48,10 @@ export function EventsOff(eventName) { return window.runtime.EventsOff(eventName); } +export function EventsOffAll() { + return window.runtime.EventsOffAll(); +} + export function EventsOnce(eventName, callback) { EventsOnMultiple(eventName, callback, 1); } diff --git a/v2/pkg/templates/templates/vue/go.mod.tmpl b/v2/pkg/templates/templates/vue/go.mod.tmpl index dd7184879..4b34d1668 100644 --- a/v2/pkg/templates/templates/vue/go.mod.tmpl +++ b/v2/pkg/templates/templates/vue/go.mod.tmpl @@ -1,6 +1,6 @@ module changeme -go 1.18 +go 1.23.0 require github.com/wailsapp/wails/v2 {{.WailsVersion}} diff --git a/v2/pkg/templates/templates_test.go b/v2/pkg/templates/templates_test.go index 3b906601a..658ecadb6 100644 --- a/v2/pkg/templates/templates_test.go +++ b/v2/pkg/templates/templates_test.go @@ -52,3 +52,48 @@ func TestInstall(t *testing.T) { is2.NoErr(err) } + +func TestInstallFailsInNonEmptyDirectory(t *testing.T) { + is2 := is.New(t) + + // Create a temp directory with a file in it + tempDir, err := os.MkdirTemp("", "wails-test-nonempty-*") + is2.NoErr(err) + defer func() { + _ = os.RemoveAll(tempDir) + }() + + // Create a file in the directory to make it non-empty + err = os.WriteFile(filepath.Join(tempDir, "existing-file.txt"), []byte("test"), 0644) + is2.NoErr(err) + + options := &Options{ + ProjectName: "test", + TemplateName: "vanilla", + TargetDir: tempDir, + } + + _, _, err = Install(options) + is2.True(err != nil) // Should fail + is2.True(err.Error() == "cannot initialise project in non-empty directory: "+tempDir) +} + +func TestInstallSucceedsInEmptyDirectory(t *testing.T) { + is2 := is.New(t) + + // Create an empty temp directory + tempDir, err := os.MkdirTemp("", "wails-test-empty-*") + is2.NoErr(err) + defer func() { + _ = os.RemoveAll(tempDir) + }() + + options := &Options{ + ProjectName: "test", + TemplateName: "vanilla", + TargetDir: tempDir, + } + + _, _, err = Install(options) + is2.NoErr(err) // Should succeed in empty directory +} diff --git a/v3/.gitignore b/v3/.gitignore deleted file mode 100644 index 953237fcd..000000000 --- a/v3/.gitignore +++ /dev/null @@ -1,13 +0,0 @@ -examples/kitchensink/kitchensink -cmd/wails3/wails -/examples/systray-menu/systray -/examples/window/window -/examples/dialogs/dialogs -/examples/menu/menu -/examples/clipboard/clipboard -/examples/plain/plain -/cmd/wails3/ui/.task/ -!internal/commands/webview2/MicrosoftEdgeWebview2Setup.exe -internal/commands/appimage_testfiles/appimage_testfiles -testiosapp/ -test/manual/systray/bin/ \ No newline at end of file diff --git a/v3/.prettierignore b/v3/.prettierignore deleted file mode 100644 index 94c6af38e..000000000 --- a/v3/.prettierignore +++ /dev/null @@ -1 +0,0 @@ -website \ No newline at end of file diff --git a/v3/.prettierrc.yml b/v3/.prettierrc.yml deleted file mode 100644 index 685d8b6e7..000000000 --- a/v3/.prettierrc.yml +++ /dev/null @@ -1,6 +0,0 @@ -overrides: - - files: - - "**/*.md" - options: - printWidth: 80 - proseWrap: always diff --git a/v3/ANDROID_ARCHITECTURE.md b/v3/ANDROID_ARCHITECTURE.md deleted file mode 100644 index d3a589488..000000000 --- a/v3/ANDROID_ARCHITECTURE.md +++ /dev/null @@ -1,1025 +0,0 @@ -# Wails v3 Android Architecture - -## Executive Summary - -This document provides a comprehensive technical architecture for Android support in Wails v3. The implementation enables Go applications to run natively on Android with an Android WebView frontend, maintaining the Wails philosophy of using web technologies for UI while leveraging Go for business logic. - -Unlike iOS which uses CGO with Objective-C, Android uses JNI (Java Native Interface) to bridge between Java/Kotlin and Go. The Go code is compiled as a shared library (`.so`) that is loaded by the Android application at runtime. - -## Table of Contents - -1. [Architecture Overview](#architecture-overview) -2. [Core Components](#core-components) -3. [Layer Architecture](#layer-architecture) -4. [File Structure](#file-structure) -5. [Implementation Details](#implementation-details) -6. [Build System](#build-system) -7. [JNI Bridge Details](#jni-bridge-details) -8. [Asset Serving](#asset-serving) -9. [JavaScript Bridge](#javascript-bridge) -10. [Security Considerations](#security-considerations) -11. [Configuration Options](#configuration-options) -12. [Debugging](#debugging) -13. [API Reference](#api-reference) -14. [Troubleshooting](#troubleshooting) -15. [Future Enhancements](#future-enhancements) - -## Architecture Overview - -### Design Principles - -1. **Battery Efficiency First**: All architectural decisions prioritize battery life -2. **No Network Ports**: Asset serving happens in-process via `WebViewAssetLoader` -3. **JNI Bridge Pattern**: Java Activity hosts WebView, Go provides business logic -4. **Wails v3 Compatibility**: Maintain API compatibility with existing Wails v3 applications -5. **Follow Fyne's gomobile pattern**: Use `-buildmode=c-shared` for native library - -### High-Level Architecture - -``` -┌─────────────────────────────────────────────────────────────┐ -│ Android Application │ -├─────────────────────────────────────────────────────────────┤ -│ Java/Android Layer │ -│ ┌─────────────────────────────────────────────────────┐ │ -│ │ MainActivity (Activity) │ │ -│ │ ┌───────────────────────────────────────────────┐ │ │ -│ │ │ Android WebView │ │ │ -│ │ │ ┌─────────────────────────────────────────┐ │ │ │ -│ │ │ │ Web Application (HTML/JS) │ │ │ │ -│ │ │ └─────────────────────────────────────────┘ │ │ │ -│ │ └───────────────────────────────────────────────┘ │ │ -│ │ │ │ -│ │ WailsBridge WailsPathHandler WailsJSBridge│ │ -│ └─────────────────────────────────────────────────────┘ │ -├─────────────────────────────────────────────────────────────┤ -│ JNI Bridge Layer │ -│ System.loadLibrary("wails") │ -├─────────────────────────────────────────────────────────────┤ -│ Go Runtime (libwails.so) │ -│ ┌──────────────────────────────────────────────────────┐ │ -│ │ Wails Application │ │ -│ │ ┌──────────┐ ┌──────────┐ ┌──────────────────┐ │ │ -│ │ │App Logic │ │Services │ │Asset Server │ │ │ -│ │ └──────────┘ └──────────┘ └──────────────────┘ │ │ -│ └──────────────────────────────────────────────────────┘ │ -└─────────────────────────────────────────────────────────────┘ -``` - -### Comparison with iOS Architecture - -| Aspect | iOS | Android | -|--------|-----|---------| -| Native Language | Objective-C | Java | -| Bridge Technology | CGO (C headers) | JNI | -| Build Mode | `-buildmode=c-archive` (.a) | `-buildmode=c-shared` (.so) | -| Entry Point | `main.m` calls `WailsIOSMain()` | `MainActivity` loads `libwails.so` | -| WebView | WKWebView | Android WebView | -| URL Scheme | `wails://localhost` | `https://wails.localhost` | -| Asset Interception | `WKURLSchemeHandler` | `WebViewAssetLoader` + `PathHandler` | -| JS → Native | `WKScriptMessageHandler` | `@JavascriptInterface` | -| Native → JS | `evaluateJavaScript:` | `evaluateJavascript()` | -| App Lifecycle | `UIApplicationDelegate` | `Activity` lifecycle methods | - -## Core Components - -### 1. Java Components - -#### MainActivity (`MainActivity.java`) - -**Purpose**: Android Activity that hosts the WebView and manages app lifecycle. - -**Location**: `build/android/app/src/main/java/com/wails/app/MainActivity.java` - -**Key Responsibilities**: -- Initialize the native Go library via `WailsBridge` -- Configure and manage the Android WebView -- Set up asset loading via `WebViewAssetLoader` -- Handle Android lifecycle events (onCreate, onResume, onPause, onDestroy) -- Execute JavaScript in the WebView when requested by Go - -**Key Methods**: -```java -onCreate(Bundle) // Initialize bridge, setup WebView -setupWebView() // Configure WebView settings and handlers -loadApplication() // Load initial URL (https://wails.localhost/) -executeJavaScript(String) // Run JS code (called from Go via JNI) -onResume() / onPause() // Lifecycle events forwarded to Go -onDestroy() // Cleanup resources -onBackPressed() // Handle back navigation -``` - -#### WailsBridge (`WailsBridge.java`) - -**Purpose**: Manages the JNI connection between Java and Go. - -**Location**: `build/android/app/src/main/java/com/wails/app/WailsBridge.java` - -**Key Responsibilities**: -- Load the native library (`System.loadLibrary("wails")`) -- Declare and call native methods -- Manage callbacks for async operations -- Forward lifecycle events to Go - -**Native Method Declarations**: -```java -private static native void nativeInit(WailsBridge bridge); -private static native void nativeShutdown(); -private static native void nativeOnResume(); -private static native void nativeOnPause(); -private static native byte[] nativeServeAsset(String path, String method, String headers); -private static native String nativeHandleMessage(String message); -private static native String nativeGetAssetMimeType(String path); -``` - -**Key Methods**: -```java -initialize() // Call nativeInit, set up Go runtime -shutdown() // Call nativeShutdown, cleanup -serveAsset(path, method, headers) // Get asset data from Go -handleMessage(message) // Send message to Go, get response -getAssetMimeType(path) // Get MIME type for asset -executeJavaScript(js) // Execute JS (callable from Go) -emitEvent(name, data) // Emit event to frontend -``` - -#### WailsPathHandler (`WailsPathHandler.java`) - -**Purpose**: Implements `WebViewAssetLoader.PathHandler` to serve assets from Go. - -**Location**: `build/android/app/src/main/java/com/wails/app/WailsPathHandler.java` - -**Key Responsibilities**: -- Intercept all requests to `https://wails.localhost/*` -- Forward requests to Go's asset server via `WailsBridge` -- Return `WebResourceResponse` with asset data - -**Key Method**: -```java -@Nullable -public WebResourceResponse handle(@NonNull String path) { - // Normalize path (/ -> /index.html) - // Call bridge.serveAsset(path, "GET", "{}") - // Get MIME type via bridge.getAssetMimeType(path) - // Return WebResourceResponse with data -} -``` - -#### WailsJSBridge (`WailsJSBridge.java`) - -**Purpose**: JavaScript interface exposed to the WebView for Go communication. - -**Location**: `build/android/app/src/main/java/com/wails/app/WailsJSBridge.java` - -**Key Responsibilities**: -- Expose methods to JavaScript via `@JavascriptInterface` -- Forward messages from JavaScript to Go -- Support both sync and async message patterns - -**JavaScript Interface Methods**: -```java -@JavascriptInterface -public String invoke(String message) // Sync call to Go - -@JavascriptInterface -public void invokeAsync(String callbackId, String message) // Async call - -@JavascriptInterface -public void log(String level, String message) // Log to Android logcat - -@JavascriptInterface -public String platform() // Returns "android" - -@JavascriptInterface -public boolean isDebug() // Returns BuildConfig.DEBUG -``` - -**Usage from JavaScript**: -```javascript -// Synchronous call -const result = wails.invoke(JSON.stringify({type: 'call', ...})); - -// Asynchronous call -wails.invokeAsync('callback-123', JSON.stringify({type: 'call', ...})); - -// Logging -wails.log('info', 'Hello from JavaScript'); - -// Platform detection -if (wails.platform() === 'android') { ... } -``` - -### 2. Go Components - -#### Application Layer (`application_android.go`) - -**Purpose**: Main Go implementation for Android platform. - -**Location**: `v3/pkg/application/application_android.go` - -**Build Tag**: `//go:build android` - -**Key Responsibilities**: -- Export JNI functions for Java to call -- Manage global application state -- Handle lifecycle events from Android -- Serve assets and process messages - -**JNI Exports**: -```go -//export Java_com_wails_app_WailsBridge_nativeInit -func Java_com_wails_app_WailsBridge_nativeInit(env *C.JNIEnv, obj C.jobject, bridge C.jobject) - -//export Java_com_wails_app_WailsBridge_nativeShutdown -func Java_com_wails_app_WailsBridge_nativeShutdown(env *C.JNIEnv, obj C.jobject) - -//export Java_com_wails_app_WailsBridge_nativeOnResume -func Java_com_wails_app_WailsBridge_nativeOnResume(env *C.JNIEnv, obj C.jobject) - -//export Java_com_wails_app_WailsBridge_nativeOnPause -func Java_com_wails_app_WailsBridge_nativeOnPause(env *C.JNIEnv, obj C.jobject) - -//export Java_com_wails_app_WailsBridge_nativeServeAsset -func Java_com_wails_app_WailsBridge_nativeServeAsset(env *C.JNIEnv, obj C.jobject, path, method, headers *C.char) *C.char - -//export Java_com_wails_app_WailsBridge_nativeHandleMessage -func Java_com_wails_app_WailsBridge_nativeHandleMessage(env *C.JNIEnv, obj C.jobject, message *C.char) *C.char - -//export Java_com_wails_app_WailsBridge_nativeGetAssetMimeType -func Java_com_wails_app_WailsBridge_nativeGetAssetMimeType(env *C.JNIEnv, obj C.jobject, path *C.char) *C.char -``` - -**Platform Functions**: -```go -func (a *App) platformRun() // Block forever, Android manages lifecycle -func (a *App) platformQuit() // Signal quit -func (a *App) isDarkMode() bool // Query Android dark mode -``` - -#### WebView Window (`webview_window_android.go`) - -**Purpose**: Implements `webviewWindowImpl` interface for Android. - -**Location**: `v3/pkg/application/webview_window_android.go` - -**Build Tag**: `//go:build android` - -**Key Methods**: Most methods are no-ops or return defaults since Android has a single fullscreen window. - -```go -func (w *androidWebviewWindow) execJS(js string) // Execute JavaScript -func (w *androidWebviewWindow) isFullscreen() bool // Always true -func (w *androidWebviewWindow) size() (int, int) // Device dimensions -func (w *androidWebviewWindow) setBackgroundColour(col RGBA) // Set WebView bg -``` - -#### Asset Server (`assetserver_android.go`) - -**Purpose**: Configure base URL for Android asset serving. - -**Location**: `v3/internal/assetserver/assetserver_android.go` - -**Build Tag**: `//go:build android` - -```go -var baseURL = url.URL{ - Scheme: "https", - Host: "wails.localhost", -} -``` - -#### Other Platform Files - -All these files have the `//go:build android` tag: - -| File | Purpose | -|------|---------| -| `init_android.go` | Initialization (no `runtime.LockOSThread`) | -| `clipboard_android.go` | Clipboard operations (stub) | -| `dialogs_android.go` | File/message dialogs (stub) | -| `menu_android.go` | Menu handling (no-op) | -| `menuitem_android.go` | Menu items (no-op) | -| `screen_android.go` | Screen information | -| `mainthread_android.go` | Main thread dispatch | -| `signal_handler_android.go` | Signal handling (no-op) | -| `single_instance_android.go` | Single instance (via manifest) | -| `systemtray_android.go` | System tray (no-op) | -| `keys_android.go` | Keyboard handling (stub) | -| `events_common_android.go` | Event mapping | -| `messageprocessor_android.go` | Android-specific runtime methods | - -## File Structure - -``` -v3/ -├── ANDROID_ARCHITECTURE.md # This document -├── pkg/ -│ ├── application/ -│ │ ├── application_android.go # Main Android implementation -│ │ ├── application_options.go # Contains AndroidOptions struct -│ │ ├── webview_window_android.go -│ │ ├── clipboard_android.go -│ │ ├── dialogs_android.go -│ │ ├── events_common_android.go -│ │ ├── init_android.go -│ │ ├── keys_android.go -│ │ ├── mainthread_android.go -│ │ ├── menu_android.go -│ │ ├── menuitem_android.go -│ │ ├── messageprocessor_android.go -│ │ ├── messageprocessor_mobile_stub.go # Stub for non-mobile -│ │ ├── screen_android.go -│ │ ├── signal_handler_android.go -│ │ ├── signal_handler_types_android.go -│ │ ├── single_instance_android.go -│ │ └── systemtray_android.go -│ └── events/ -│ └── events_android.go -├── internal/ -│ └── assetserver/ -│ ├── assetserver_android.go -│ └── webview/ -│ └── request_android.go -└── examples/ - └── android/ - ├── main.go # Application entry point - ├── greetservice.go # Example service - ├── go.mod - ├── go.sum - ├── Taskfile.yml # Build orchestration - ├── .gitignore - ├── frontend/ # Web frontend (same as other platforms) - │ ├── index.html - │ ├── main.js - │ ├── package.json - │ └── ... - └── build/ - ├── config.yml # Build configuration - ├── Taskfile.yml # Common build tasks - ├── android/ - │ ├── Taskfile.yml # Android-specific tasks - │ ├── build.gradle # Root Gradle build - │ ├── settings.gradle - │ ├── gradle.properties - │ ├── gradlew # Gradle wrapper script - │ ├── gradle/ - │ │ └── wrapper/ - │ │ └── gradle-wrapper.properties - │ ├── scripts/ - │ │ └── deps/ - │ │ └── install_deps.go # Dependency checker - │ └── app/ - │ ├── build.gradle # App Gradle build - │ ├── proguard-rules.pro - │ └── src/ - │ └── main/ - │ ├── AndroidManifest.xml - │ ├── java/ - │ │ └── com/ - │ │ └── wails/ - │ │ └── app/ - │ │ ├── MainActivity.java - │ │ ├── WailsBridge.java - │ │ ├── WailsPathHandler.java - │ │ └── WailsJSBridge.java - │ ├── res/ - │ │ ├── layout/ - │ │ │ └── activity_main.xml - │ │ ├── values/ - │ │ │ ├── strings.xml - │ │ │ ├── colors.xml - │ │ │ └── themes.xml - │ │ └── mipmap-*/ # App icons - │ ├── assets/ # Frontend assets (copied) - │ └── jniLibs/ - │ ├── arm64-v8a/ - │ │ └── libwails.so # Generated - │ └── x86_64/ - │ └── libwails.so # Generated - ├── darwin/ # macOS build files - ├── linux/ # Linux build files - └── windows/ # Windows build files -``` - -## Implementation Details - -### Application Startup Flow - -``` -1. Android OS launches MainActivity - │ -2. MainActivity.onCreate() - │ - ├─> WailsBridge.initialize() - │ │ - │ └─> System.loadLibrary("wails") - │ │ - │ └─> Go runtime starts - │ │ - │ └─> nativeInit() called - │ │ - │ └─> globalApp = app (store reference) - │ - ├─> setupWebView() - │ │ - │ ├─> Configure WebSettings - │ ├─> Create WebViewAssetLoader with WailsPathHandler - │ ├─> Set WebViewClient for request interception - │ └─> Add WailsJSBridge via addJavascriptInterface - │ - └─> loadApplication() - │ - └─> webView.loadUrl("https://wails.localhost/") - │ - └─> WailsPathHandler.handle("/") - │ - └─> WailsBridge.serveAsset("/index.html", ...) - │ - └─> nativeServeAsset() (JNI to Go) - │ - └─> Go AssetServer returns HTML -``` - -### Asset Request Flow - -``` -WebView requests: https://wails.localhost/main.js - │ - ▼ -WebViewClient.shouldInterceptRequest() - │ - ▼ -WebViewAssetLoader.shouldInterceptRequest() - │ - ▼ -WailsPathHandler.handle("/main.js") - │ - ▼ -WailsBridge.serveAsset("/main.js", "GET", "{}") - │ - ▼ -JNI call: nativeServeAsset(path, method, headers) - │ - ▼ -Go: serveAssetForAndroid(app, "/main.js") - │ - ▼ -Go: AssetServer reads from embed.FS - │ - ▼ -Return: byte[] data - │ - ▼ -WailsPathHandler creates WebResourceResponse - │ - ▼ -WebView renders content -``` - -### JavaScript to Go Message Flow - -``` -JavaScript: wails.invoke('{"type":"call","method":"Greet","args":["World"]}') - │ - ▼ -WailsJSBridge.invoke(message) [@JavascriptInterface] - │ - ▼ -WailsBridge.handleMessage(message) - │ - ▼ -JNI call: nativeHandleMessage(message) - │ - ▼ -Go: handleMessageForAndroid(app, message) - │ - ▼ -Go: Parse JSON, route to service method - │ - ▼ -Go: Execute GreetService.Greet("World") - │ - ▼ -Return: '{"result":"Hello, World!"}' - │ - ▼ -JavaScript receives result -``` - -### Go to JavaScript Event Flow - -``` -Go: app.Event.Emit("time", "Mon, 01 Jan 2024 12:00:00") - │ - ▼ -Go: Call Java executeJavaScript via JNI callback - │ - ▼ -WailsBridge.emitEvent("time", "\"Mon, 01 Jan 2024 12:00:00\"") - │ - ▼ -JavaScript: window.wails._emit('time', "Mon, 01 Jan 2024 12:00:00") - │ - ▼ -Frontend event listeners notified -``` - -## Build System - -### Prerequisites - -1. **Go 1.21+** with CGO support -2. **Android SDK** with: - - Platform Tools (adb) - - Build Tools - - Android Emulator -3. **Android NDK r19c+** (r26d recommended) -4. **Java JDK 11+** - -### Environment Variables - -```bash -# Required -export ANDROID_HOME=$HOME/Library/Android/sdk # macOS -export ANDROID_HOME=$HOME/Android/Sdk # Linux - -# Optional (auto-detected if not set) -export ANDROID_NDK_HOME=$ANDROID_HOME/ndk/26.1.10909125 - -# Path additions -export PATH=$PATH:$ANDROID_HOME/platform-tools -export PATH=$PATH:$ANDROID_HOME/emulator -``` - -### Taskfile Commands - -```bash -# Check/install dependencies -task android:install:deps - -# Build Go shared library (default: arm64 for device) -task android:build - -# Build for emulator (x86_64) -task android:build ARCH=x86_64 - -# Build for all architectures (fat APK) -task android:compile:go:all-archs - -# Package into APK -task android:package - -# Run on emulator -task android:run - -# View logs -task android:logs - -# Clean build artifacts -task android:clean -``` - -### Build Process Details - -#### 1. Go Compilation - -```bash -# Environment for arm64 (device) -export GOOS=android -export GOARCH=arm64 -export CGO_ENABLED=1 -export CC=$NDK/toolchains/llvm/prebuilt/$HOST/bin/aarch64-linux-android21-clang - -# Build command -go build -buildmode=c-shared \ - -tags android \ - -o build/android/app/src/main/jniLibs/arm64-v8a/libwails.so -``` - -#### 2. Gradle Build - -```bash -cd build/android -./gradlew assembleDebug -# Output: app/build/outputs/apk/debug/app-debug.apk -``` - -#### 3. Installation - -```bash -adb install app-debug.apk -adb shell am start -n com.wails.app/.MainActivity -``` - -### Architecture Support - -| Architecture | GOARCH | JNI Directory | Use Case | -|--------------|--------|---------------|----------| -| arm64-v8a | arm64 | `jniLibs/arm64-v8a/` | Physical devices (most common) | -| x86_64 | amd64 | `jniLibs/x86_64/` | Emulator | -| armeabi-v7a | arm | `jniLibs/armeabi-v7a/` | Older devices (optional) | -| x86 | 386 | `jniLibs/x86/` | Older emulators (optional) | - -### Minimum SDK Configuration - -```gradle -// build/android/app/build.gradle -android { - defaultConfig { - minSdk 21 // Android 5.0 (Lollipop) - 99%+ coverage - targetSdk 34 // Android 14 - Required for Play Store - } -} -``` - -## JNI Bridge Details - -### JNI Function Naming Convention - -JNI functions must follow this naming pattern: -``` -Java___ -``` - -Example: -```go -//export Java_com_wails_app_WailsBridge_nativeInit -func Java_com_wails_app_WailsBridge_nativeInit(env *C.JNIEnv, obj C.jobject, bridge C.jobject) -``` - -Corresponds to Java: -```java -package com.wails.app; -class WailsBridge { - private static native void nativeInit(WailsBridge bridge); -} -``` - -### JNI Type Mappings - -| Java Type | JNI Type | Go CGO Type | -|-----------|----------|-------------| -| void | void | - | -| boolean | jboolean | C.jboolean | -| int | jint | C.jint | -| long | jlong | C.jlong | -| String | jstring | *C.char (via conversion) | -| byte[] | jbyteArray | *C.char (via conversion) | -| Object | jobject | C.jobject | - -### String Conversion - -```go -// Java String → Go string -goString := C.GoString((*C.char)(unsafe.Pointer(javaString))) - -// Go string → Java String (return) -return C.CString(goString) // Must be freed by Java -``` - -### Thread Safety - -- JNI calls must be made from the thread that owns the JNI environment -- Go goroutines cannot directly call JNI methods -- Use channels or callbacks to communicate between goroutines and JNI thread - -## Asset Serving - -### WebViewAssetLoader Configuration - -```java -assetLoader = new WebViewAssetLoader.Builder() - .setDomain("wails.localhost") // Custom domain - .addPathHandler("/", new WailsPathHandler(bridge)) // All paths - .build(); -``` - -### URL Scheme - -- **Base URL**: `https://wails.localhost/` -- **Why HTTPS**: Android's `WebViewAssetLoader` requires HTTPS for security -- **Domain**: `wails.localhost` is arbitrary but consistent with Wails conventions - -### Path Normalization - -```java -// In WailsPathHandler.handle() -if (path.isEmpty() || path.equals("/")) { - path = "/index.html"; -} -``` - -### MIME Type Detection - -MIME types are determined by Go based on file extension. Fallback mapping in Java: - -```java -private String getMimeType(String path) { - if (path.endsWith(".html")) return "text/html"; - if (path.endsWith(".js")) return "application/javascript"; - if (path.endsWith(".css")) return "text/css"; - // ... etc - return "application/octet-stream"; -} -``` - -## JavaScript Bridge - -### Exposed Interface - -The `WailsJSBridge` is added to the WebView as: -```java -webView.addJavascriptInterface(new WailsJSBridge(bridge, webView), "wails"); -``` - -This makes `window.wails` available in JavaScript. - -### Security Considerations - -1. **@JavascriptInterface annotation** is required for all exposed methods (Android 4.2+) -2. Only specific methods are exposed, not the entire object -3. Input validation should be performed on all received data - -### Async Pattern - -For non-blocking calls: - -```javascript -// JavaScript side -const callbackId = 'cb_' + Date.now(); -window.wails._callbacks[callbackId] = (result, error) => { - if (error) reject(error); - else resolve(result); -}; -wails.invokeAsync(callbackId, message); - -// Java side sends response via: -webView.evaluateJavascript( - "window.wails._callback('" + callbackId + "', " + result + ", null);", - null -); -``` - -## Security Considerations - -### WebView Security - -```java -WebSettings settings = webView.getSettings(); -settings.setAllowFileAccess(false); // No file:// access -settings.setAllowContentAccess(false); // No content:// access -settings.setMixedContentMode(MIXED_CONTENT_NEVER_ALLOW); // HTTPS only -``` - -### JNI Security - -1. **No arbitrary code execution**: JNI methods have fixed signatures -2. **Input validation**: All strings from Java are validated in Go -3. **Memory safety**: Go's memory management prevents buffer overflows - -### Asset Security - -1. **Same-origin policy**: Assets only served from `wails.localhost` -2. **No external network**: All assets embedded, no remote fetching -3. **Content Security Policy**: Can be set via HTML headers - -## Configuration Options - -### AndroidOptions Struct - -```go -type AndroidOptions struct { - // DisableScroll disables scrolling in the WebView - DisableScroll bool - - // DisableOverscroll disables the overscroll bounce effect - DisableOverscroll bool - - // EnableZoom allows pinch-to-zoom in the WebView (default: false) - EnableZoom bool - - // UserAgent sets a custom user agent string - UserAgent string - - // BackgroundColour sets the background colour of the WebView - BackgroundColour RGBA - - // DisableHardwareAcceleration disables hardware acceleration - DisableHardwareAcceleration bool -} -``` - -### Usage - -```go -app := application.New(application.Options{ - Name: "My App", - Android: application.AndroidOptions{ - DisableOverscroll: true, - BackgroundColour: application.NewRGB(27, 38, 54), - }, -}) -``` - -### AndroidManifest.xml Configuration - -```xml - - - - - android:hardwareAccelerated="true"> - - - - - -``` - -## Debugging - -### Logcat Filtering - -```bash -# All Wails logs -adb logcat -v time | grep -E "(Wails|WailsBridge|WailsActivity)" - -# Using task -task android:logs -``` - -### WebView Debugging - -Enable in debug builds: -```java -if (BuildConfig.DEBUG) { - WebView.setWebContentsDebuggingEnabled(true); -} -``` - -Then in Chrome: `chrome://inspect/#devices` - -### Go Debugging - -```go -func androidLogf(level string, format string, a ...interface{}) { - msg := fmt.Sprintf(format, a...) - println(fmt.Sprintf("[Android/%s] %s", level, msg)) -} -``` - -### Common Issues - -1. **"UnsatisfiedLinkError"**: Library not found or wrong architecture -2. **"No implementation found"**: JNI function name mismatch -3. **Blank WebView**: Asset serving not working, check logcat - -## API Reference - -### Go API (Same as Desktop) - -```go -// Create application -app := application.New(application.Options{ - Name: "App Name", - Assets: application.AssetOptions{ - Handler: application.AssetFileServerFS(assets), - }, - Services: []application.Service{ - application.NewService(&MyService{}), - }, - Android: application.AndroidOptions{...}, -}) - -// Run (blocks on Android) -app.Run() - -// Emit events -app.Event.Emit("eventName", data) -``` - -### JavaScript API - -```javascript -// Call Go service method -const result = await window.wails.Call.ByName('MyService.Greet', 'World'); - -// Platform detection -if (window.wails.System.Platform() === 'android') { ... } - -// Events -window.wails.Events.On('eventName', (data) => { ... }); -``` - -### Android-Specific Runtime Methods - -```javascript -// Vibrate (haptic feedback) -window.wails.Call.ByName('Android.Haptics.Vibrate', {duration: 100}); - -// Show toast -window.wails.Call.ByName('Android.Toast.Show', {message: 'Hello!'}); - -// Get device info -const info = await window.wails.Call.ByName('Android.Device.Info'); -``` - -## Troubleshooting - -### Build Errors - -**"NDK not found"** -```bash -# Set NDK path explicitly -export ANDROID_NDK_HOME=$ANDROID_HOME/ndk/26.1.10909125 -``` - -**"undefined reference to JNI function"** -- Check function name matches exactly (case-sensitive) -- Ensure `//export` comment is directly above function - -**"cannot find package"** -```bash -cd examples/android && go mod tidy -``` - -### Runtime Errors - -**App crashes on startup** -1. Check logcat for stack trace -2. Verify library is in correct jniLibs directory -3. Check architecture matches device/emulator - -**WebView shows blank** -1. Enable WebView debugging -2. Check Chrome DevTools for errors -3. Verify `https://wails.localhost/` resolves - -**JavaScript bridge not working** -1. Check `wails` object exists: `console.log(window.wails)` -2. Verify `@JavascriptInterface` annotations present -3. Check for JavaScript errors in console - -## Future Enhancements - -### Phase 1: Core Stability -- [ ] Complete JNI callback implementation for Go → Java -- [ ] Full asset server integration -- [ ] Error handling and recovery -- [ ] Unit and integration tests - -### Phase 2: Feature Parity -- [ ] Clipboard support -- [ ] File dialogs (via Storage Access Framework) -- [ ] Notifications -- [ ] Deep linking - -### Phase 3: Android-Specific Features -- [ ] Material Design 3 theming integration -- [ ] Edge-to-edge display support -- [ ] Predictive back gesture -- [ ] Picture-in-Picture mode -- [ ] Widgets - -### Phase 4: Advanced Features -- [ ] Background services -- [ ] Push notifications (FCM) -- [ ] Biometric authentication -- [ ] App Shortcuts -- [ ] Wear OS companion - -## Conclusion - -This architecture provides a solid foundation for Android support in Wails v3. The design prioritizes: - -1. **Compatibility**: Same Go code runs on all platforms -2. **Performance**: No network overhead, native rendering -3. **Security**: Sandboxed WebView, validated inputs -4. **Maintainability**: Clear separation of concerns - -The implementation follows Android best practices while maintaining the simplicity that Wails developers expect. The JNI bridge pattern, while more complex than iOS's CGO approach, provides robust interoperability between Java and Go. - -### Key Implementation Status - -| Component | Status | Notes | -|-----------|--------|-------| -| Java Activity | ✅ Complete | MainActivity with WebView | -| JNI Bridge | ✅ Complete | WailsBridge with native methods | -| Asset Handler | ✅ Complete | WailsPathHandler | -| JS Bridge | ✅ Complete | WailsJSBridge | -| Go Platform Files | ✅ Complete | All *_android.go files | -| Taskfile | ✅ Complete | Build orchestration | -| Gradle Project | ✅ Complete | App structure | -| JNI Implementation | 🔄 Partial | Needs Go → Java callbacks | -| Asset Server Integration | 🔄 Partial | Needs full wiring | -| Testing | ❌ Pending | Needs emulator testing | - ---- - -*Document Version: 1.0* -*Last Updated: November 2024* -*Wails Version: v3-alpha* diff --git a/v3/IOS_ARCHITECTURE.md b/v3/IOS_ARCHITECTURE.md deleted file mode 100644 index 2e07f4f0c..000000000 --- a/v3/IOS_ARCHITECTURE.md +++ /dev/null @@ -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 -``` -- 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 -``` -- 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. \ No newline at end of file diff --git a/v3/IOS_FEATURES_TODO.md b/v3/IOS_FEATURES_TODO.md deleted file mode 100644 index cd3bc0edd..000000000 --- a/v3/IOS_FEATURES_TODO.md +++ /dev/null @@ -1,100 +0,0 @@ -# iOS Features TODO (Prioritized) - -This document lists potential iOS features and platform options to enhance the Wails v3 iOS runtime. Items are ordered by importance for typical app development workflows. - -## Top Priority (Implement first) - -1) Input accessory bar control -- Status: Implemented as `IOSOptions.DisableInputAccessoryView` (default false = shown). Native toggle + WKWebView subclass. - -2) Scrolling and bounce behavior -- Options: - - `DisableScroll` (default true in current runtime to preserve no-scroll template behavior) - - `DisableBounce` (default true in current runtime) - - `HideScrollIndicators` (default true in current runtime) -- Purpose: control elastic bounce, page scrolling, and indicators. - -3) Web Inspector / Debug -- Options: - - `DisableInspectable` (default false; inspector enabled by default in dev) -- Purpose: enable/disable WKWebView inspector. - -4) Back/forward navigation gestures -- Options: - - `AllowsBackForwardNavigationGestures` (default false) -- Purpose: enable iOS edge-swipe navigation. - -5) Link previews -- Options: - - `DisableLinkPreview` (default false) -- Purpose: allow long-press link previews. - -6) Media autoplay and inline playback -- Options: - - `DisableInlineMediaPlayback` (default false) - - `RequireUserActionForMediaPlayback` (default false) -- Purpose: control media playback UX. - -7) User agent customization -- Options: - - `UserAgent` (string) - - `ApplicationNameForUserAgent` (string; default "wails.io") -- Purpose: customize UA / identify app. - -8) Keyboard behavior -- Options: - - Already: `DisableInputAccessoryView` - - Future: `KeyboardDismissMode` (none | onDrag | interactive) -- Purpose: refine keyboard UX. - -9) Safe-area and content inset behavior -- Options (future): - - `ContentInsetAdjustment` (automatic | never | always) - - `UseSafeArea` (bool) -- Purpose: fine-tune layout under notch/home indicator. - -10) Data detectors (future feasibility) -- Options: `DataDetectorTypes []string` (phoneNumber, link, address) -- Note: Not all are directly available on WKWebView; feasibility TBD. - -## Medium Priority - -11) Pull-to-refresh (custom) -12) File picker / photo access bridges -13) Haptics feedback helpers -14) Clipboard read/write helpers (partially present) -15) Share sheet / activity view bridges -16) Background audio / PiP controls -17) App lifecycle event hooks (background/foreground) -18) Permissions prompts helpers (camera, mic, photos) -19) Open in external browser vs in-app policy -20) Cookie / storage policy helpers - -## Low Priority - -21) Theme/dynamic color helpers bridging to CSS vars -22) Orientation lock helpers per window -23) Status bar style control from Go -24) Network reachability events bridge -25) Push notifications - ---- - -# Implementation Plan (Top 10) - -Implement the following immediately: -- DisableScroll, DisableBounce, HideScrollIndicators -- AllowsBackForwardNavigationGestures -- DisableLinkPreview -- DisableInlineMediaPlayback -- RequireUserActionForMediaPlayback -- DisableInspectable -- UserAgent -- ApplicationNameForUserAgent - -Approach: -- Extend `IOSOptions` in `pkg/application/application_options.go` with these fields. -- Add native globals + C setters in `pkg/application/application_ios.h/.m`. -- Apply options in `pkg/application/webview_window_ios.m` during WKWebView configuration and on the scrollView. -- Wire from Go in `pkg/application/application_ios.go`. -- Maintain current template behavior as defaults (no scroll/bounce/indicators) to avoid regressions in existing tests. diff --git a/v3/IOS_RUNTIME.md b/v3/IOS_RUNTIME.md deleted file mode 100644 index 22aaa320a..000000000 --- a/v3/IOS_RUNTIME.md +++ /dev/null @@ -1,53 +0,0 @@ -# iOS Runtime Feature Plan - -This document outlines proposed iOS-only runtime features for Wails v3, the initial milestones, and method shapes exposed to the frontend runtime as `IOS.*`. - -## Goals -- Provide a first-class iOS runtime namespace: `IOS`. -- Expose UX-critical features with a small, well-defined, promise-based API. -- Follow the existing runtime pattern: JS -> /wails/runtime -> Go -> ObjC. - -## Object: IOS -- Object ID: 11 (reserved in runtime objectNames) - -## Milestone 1 (MVP) -- Haptics - - `IOS.Haptics.Impact(style: "light"|"medium"|"heavy"|"soft"|"rigid"): Promise` -- Device - - `IOS.Device.Info(): Promise<{ model: string; systemName: string; systemVersion: string; isSimulator: boolean }>` - -## Milestone 2 -- Permissions - - `IOS.Permissions.Request("camera"|"microphone"|"photos"|"notifications"): Promise<"granted"|"denied"|"limited">` - - `IOS.Permissions.Status(kind): Promise<"granted"|"denied"|"limited"|"restricted"|"not_determined">` -- Camera - - `IOS.Camera.PickPhoto(options?): Promise<{ uri: string }>` - - `IOS.Camera.PickVideo(options?): Promise<{ uri: string, duration?: number }>` -- Photos - - `IOS.Photos.SaveImage(dataURL|blob, options?): Promise` - - `IOS.Photos.SaveVideo(fileURI, options?): Promise` - -## Milestone 3 -- Share - - `IOS.Share.Sheet({ text?, url?, imageDataURL? }): Promise` -- Files - - `IOS.Files.Pick({ types?, multiple? }): Promise>` -- Biometric - - `IOS.Biometric.CanAuthenticate(): Promise` - - `IOS.Biometric.Authenticate(reason: string): Promise` -- Notifications - - `IOS.Notifications.RequestPermission(): Promise` - - `IOS.Notifications.Schedule(localNotification): Promise` - -## Notes -- All APIs should be safe no-ops on other platforms (reject with a meaningful error) or be tree-shaken by frontend bundlers. -- UI-affecting APIs must ensure main-thread execution in ObjC. -- File/Photo APIs will use security-scoped bookmarks where relevant. - -## Implementation Status -- [x] Define plan (this document) -- [ ] JS runtime: add IOS object ID + IOS module exports -- [ ] Go: message dispatcher for IOS object -- [ ] iOS: Haptics.Impact(style) native bridge -- [ ] JS->Go->ObjC wiring for Haptics -- [ ] Device.Info() basic implementation diff --git a/v3/README.md b/v3/README.md deleted file mode 100644 index 2d0c36a0b..000000000 --- a/v3/README.md +++ /dev/null @@ -1,9 +0,0 @@ -# v3 Alpha - -Thanks for wanting to help out with testing/developing Wails v3! This guide will help you get started. - -## Getting Started - -All the instructions for getting started are in the v3 documentation directory: `mkdocs-website`. -Please read the README.md file in that directory for more information. - diff --git a/v3/TESTING.md b/v3/TESTING.md deleted file mode 100644 index 2e1486dc5..000000000 --- a/v3/TESTING.md +++ /dev/null @@ -1,452 +0,0 @@ -# Cross-Platform Testing Guide for Wails v3 - -This document describes the comprehensive cross-platform testing system for Wails v3 examples, supporting Mac, Linux, and Windows compilation. - -## Overview - -The testing system ensures all Wails v3 examples build successfully across all supported platforms: -- **macOS (Darwin)** - Native compilation -- **Windows** - Cross-compilation from any platform -- **Linux** - Multi-architecture Docker compilation (ARM64 + x86_64) - -## Test Directory Structure - -The testing infrastructure is organized in a dedicated test directory: - -```bash -v3/ -├── test/ -│ └── docker/ -│ ├── Dockerfile.linux-arm64 # ARM64 native compilation -│ └── Dockerfile.linux-x86_64 # x86_64 native compilation -├── Taskfile.yaml # Build task definitions -└── TESTING.md # This documentation -``` - -**Benefits of the organized structure:** -- **Separation of Concerns**: Testing files are isolated from application code -- **Clear Organization**: All Docker-related files in one location -- **Easier Maintenance**: Centralized testing infrastructure -- **Better Git Management**: Clean separation for .gitignore patterns - -## Available Commands - -### 🚀 Complete Cross-Platform Testing -```bash -# Build all examples for ALL platforms (macOS + Windows + Linux) -task test:examples:all -``` -**Total: 129 builds** (43 examples × 3 platforms) + CLI code testing - -### All Examples (No DIR Parameter Needed) -```bash -# Current platform only (all 43 examples + CLI code) -task test:examples - -# All examples for specific Linux architectures -task test:examples:linux:docker # Auto-detect architecture -task test:examples:linux:docker:arm64 # ARM64 native -task test:examples:linux:docker:x86_64 # x86_64 native - -# CLI code testing only -task test:cli -``` - -### Single Example Builds (Requires DIR=example) -```bash -# macOS/Darwin single example -task test:example:darwin DIR=badge - -# Windows cross-compilation single example -task test:example:windows DIR=badge - -# Linux native builds (on Linux systems) -task test:example:linux DIR=badge - -# Linux Docker builds (multi-architecture) -task test:example:linux:docker DIR=badge # Auto-detect architecture -task test:example:linux:docker:arm64 DIR=badge # ARM64 native -task test:example:linux:docker:x86_64 DIR=badge # x86_64 native -``` - -## Build Artifacts - -All builds generate platform-specific binaries with clear naming: -- **macOS**: `testbuild-{example}-darwin` -- **Windows**: `testbuild-{example}-windows.exe` -- **Linux**: `testbuild-{example}-linux` -- **Linux ARM64**: `testbuild-{example}-linux-arm64` (Docker) -- **Linux x86_64**: `testbuild-{example}-linux-x86_64` (Docker) - -Example outputs: -```text -examples/badge/testbuild-badge-darwin -examples/badge/testbuild-badge-windows.exe -examples/badge/testbuild-badge-linux-arm64 -examples/badge/testbuild-badge-linux-x86_64 -``` - -## Validation Status - -### ✅ **Production Ready (v3.0.0-alpha)** -- **Total Examples**: 43 examples fully tested -- **macOS**: ✅ All examples compile successfully (100%) -- **Windows**: ✅ All examples cross-compile successfully (100%) -- **Linux**: ✅ Multi-architecture Docker compilation (ARM64 + x86_64) -- **Build System**: Comprehensive Taskfile.yaml integration -- **Git Integration**: Complete .gitignore patterns for build artifacts -- **Total Build Capacity**: 129 cross-platform builds per test cycle - -## Supported Examples - -The system builds all 43 Wails v3 examples: -- badge, badge-custom, binding, build -- cancel-async, cancel-chaining, clipboard, contextmenus -- dev, dialogs, dialogs-basic, drag-n-drop -- environment, events, events-bug, file-association -- frameless, gin-example, gin-routing, gin-service -- hide-window, html-dnd-api, ignore-mouse, keybindings -- menu, notifications, panic-handling, plain -- raw-message, screen, services, show-macos-toolbar -- single-instance, systray-basic, systray-custom, systray-menu -- video, window, window-api, window-call -- window-menu, wml - -**Recently Added (v3.0.0-alpha):** -- dev, events-bug, gin-example, gin-routing, gin-service -- html-dnd-api, notifications - -## Platform Requirements - -### macOS (Darwin) -- Go 1.23+ -- Xcode Command Line Tools -- No additional dependencies required - -**Environment Variables:** -```bash -CGO_LDFLAGS="-framework UniformTypeIdentifiers -mmacosx-version-min=10.13" -CGO_CFLAGS="-mmacosx-version-min=10.13" -``` - -### Windows (Cross-compilation) -- Go 1.23+ -- No additional dependencies for cross-compilation - -**Environment Variables:** -```bash -GOOS=windows -GOARCH=amd64 -``` - -### Linux (Docker) - ✅ Multi-Architecture Support -Uses Ubuntu 24.04 base image with full GTK development environment: - -**Current Status:** Complete multi-architecture Docker compilation system -- ✅ ARM64 native compilation (Ubuntu 24.04) -- ✅ x86_64 native compilation (Ubuntu 24.04) -- ✅ Automatic architecture detection -- ✅ All dependencies install correctly (GTK + WebKit) -- ✅ Go 1.24 environment configured for each architecture -- ✅ Native compilation eliminates cross-compilation CGO issues - -**Architecture Support:** -- **ARM64**: Native compilation using `Dockerfile.linux-arm64` -- **x86_64**: Native compilation using `Dockerfile.linux-x86_64` with `--platform=linux/amd64` -- **Auto-detect**: Taskfile automatically selects appropriate architecture - -**Core Dependencies:** -- `build-essential` - GCC compiler toolchain (architecture-specific) -- `pkg-config` - Package configuration tool -- `libgtk-3-dev` - GTK+ 3.x development files -- `libwebkit2gtk-4.1-dev` - WebKit2GTK development files -- `git` - Version control (for go mod operations) -- `ca-certificates` - HTTPS support - -**Docker Images:** -- `wails-v3-linux-arm64` - Ubuntu 24.04 ARM64 native compilation (built from `test/docker/Dockerfile.linux-arm64`) -- `wails-v3-linux-x86_64` - Ubuntu 24.04 x86_64 native compilation (built from `test/docker/Dockerfile.linux-x86_64`) -- `wails-v3-linux-fixed` - Legacy unified image (deprecated) - -## Docker Configuration - -### Multi-Architecture Build System - -#### ARM64 Native Build Environment (`test/docker/Dockerfile.linux-arm64`) -```dockerfile -FROM ubuntu:24.04 -# ARM64 native compilation environment -# Go 1.24.0 ARM64 binary (go1.24.0.linux-arm64.tar.gz) -# Native GCC toolchain for ARM64 -# All GTK/WebKit dependencies for ARM64 -# Build script: /build/build-linux-arm64.sh -# Output: testbuild-{example}-linux-arm64 -``` - -#### x86_64 Native Build Environment (`test/docker/Dockerfile.linux-x86_64`) -```dockerfile -FROM --platform=linux/amd64 ubuntu:24.04 -# x86_64 native compilation environment -# Go 1.24.0 x86_64 binary (go1.24.0.linux-amd64.tar.gz) -# Native GCC toolchain for x86_64 -# All GTK/WebKit dependencies for x86_64 -# Build script: /build/build-linux-x86_64.sh -# Output: testbuild-{example}-linux-x86_64 -``` - -### Available Docker Tasks - -#### Architecture-Specific Tasks -```bash -# ARM64 builds -task test:example:linux:docker:arm64 DIR=badge -task test:examples:linux:docker:arm64 - -# x86_64 builds -task test:example:linux:docker:x86_64 DIR=badge -task test:examples:linux:docker:x86_64 -``` - -#### Auto-Detection Tasks (Recommended) -```bash -# Single example (auto-detects host architecture) -task test:example:linux:docker DIR=badge - -# All examples (auto-detects host architecture) -task test:examples:linux:docker -``` - -## Implementation Details - -### Key Fixes Applied in v3.0.0-alpha - -#### 1. **Complete Example Coverage** -- **Before**: 35 examples tested -- **After**: 43 examples tested (100% coverage) -- **Added**: dev, events-bug, gin-example, gin-routing, gin-service, html-dnd-api, notifications - -#### 2. **Go Module Resolution** -- **Issue**: Inconsistent replace directives across examples -- **Fix**: Standardized all examples to use `replace github.com/wailsapp/wails/v3 => ../..` -- **Examples Fixed**: gin-example, gin-routing, notifications - -#### 3. **Frontend Asset Embedding** -- **Issue**: Some examples referenced missing `frontend/dist` directories -- **Fix**: Updated embed paths from `//go:embed all:frontend/dist` to `//go:embed all:frontend` -- **Examples Fixed**: file-association, notifications - -#### 4. **Manager API Migration** -- **Issue**: Windows badge service using deprecated API -- **Fix**: Updated `app.CurrentWindow()` → `app.Windows.Current()` -- **Files Fixed**: pkg/services/badge/badge_windows.go - -#### 5. **File Association Example** -- **Issue**: Undefined window variable -- **Fix**: Added proper window assignment from `app.Windows.NewWithOptions()` -- **Files Fixed**: examples/file-association/main.go - -### Build Performance -- **macOS**: ~2-3 minutes for all 43 examples -- **Windows Cross-Compile**: ~2-3 minutes for all 43 examples -- **Linux Docker**: ~5-10 minutes for all 43 examples (includes image build) -- **Total Build Time**: ~10-15 minutes for complete cross-platform validation (129 builds) - -## Usage Examples - -### Single Example Testing (Requires DIR Parameter) -```bash -# Test the badge example on all platforms -task test:example:darwin DIR=badge # macOS native -task test:example:windows DIR=badge # Windows cross-compile -task test:example:linux:docker DIR=badge # Linux Docker (auto-detect arch) -``` - -### All Examples Testing (No DIR Parameter) -```bash -# Test everything - all 43 examples, all platforms -task test:examples:all - -# This runs: -# 1. All Darwin builds (43 examples) -# 2. All Windows cross-compilation (43 examples) -# 3. All Linux Docker builds (43 examples, auto-architecture) - -# Platform-specific all examples -task test:examples # Current platform (43 examples) -task test:examples:linux:docker:arm64 # ARM64 builds (43 examples) -task test:examples:linux:docker:x86_64 # x86_64 builds (43 examples) -``` - -### Continuous Integration -```bash -# For CI/CD pipelines -task test:examples:all # Complete cross-platform (129 builds) -task test:examples # Current platform only (43 builds) -``` - -## Build Process Details - -### macOS Builds -1. Sets macOS-specific CGO flags for compatibility -2. Runs `go mod tidy` in each example directory -3. Compiles with `go build -o testbuild-{example}-darwin` -4. Links against UniformTypeIdentifiers framework - -### Windows Cross-Compilation -1. Sets `GOOS=windows GOARCH=amd64` environment -2. Runs `go mod tidy` in each example directory -3. Cross-compiles with `go build -o testbuild-{example}-windows.exe` -4. No CGO dependencies required (uses Windows APIs) - -### Linux Docker Builds -1. **Auto-Detection**: Detects host architecture (ARM64 or x86_64) -2. **Image Selection**: Uses appropriate Ubuntu 24.04 image for target architecture -3. **Native Compilation**: Eliminates cross-compilation CGO issues -4. **Environment Setup**: Full GTK/WebKit development environment -5. **Build Process**: Runs `go mod tidy && go build` with native toolchain -6. **Output**: Architecture-specific binaries (`-linux-arm64` or `-linux-x86_64`) - -## Troubleshooting - -### Common Issues (All Resolved in v3.0.0-alpha) - -#### **Go Module Resolution Errors** -```bash -Error: replacement directory ../wails/v3 does not exist -``` -**Solution**: All examples now use standardized `replace github.com/wailsapp/wails/v3 => ../..` - -#### **Frontend Asset Embedding Errors** -```bash -Error: pattern frontend/dist: no matching files found -``` -**Solution**: Updated to `//go:embed all:frontend` for examples without dist directories - -#### **Manager API Errors** -```bash -Error: app.CurrentWindow undefined -``` -**Solution**: Updated to use new manager pattern `app.Windows.Current()` - -#### **Build Warnings** -Some examples may show compatibility warnings (e.g., notifications using macOS 10.14+ APIs with 10.13 target). These are non-blocking warnings that can be addressed separately. - -### Performance Optimization - -#### **Parallel Builds** -```bash -# The task system automatically runs builds in parallel where possible -task v3:test:examples:all # Optimized for maximum throughput -``` - -#### **Selective Testing** -```bash -# Test specific examples to debug issues -task v3:test:example:darwin DIR=badge -task v3:test:example:windows DIR=contextmenus -``` - -### Performance Tips - -**Parallel Builds:** -```bash -# Build multiple examples simultaneously -task v3:test:example:darwin DIR=badge & -task v3:test:example:darwin DIR=binding & -task v3:test:example:darwin DIR=build & -wait -``` - -**Docker Image Caching:** -```bash -# Pre-build Docker images -docker build -f Dockerfile.linux -t wails-v3-linux-builder . -docker build -f Dockerfile.linux-simple -t wails-v3-linux-simple . -``` - -## Integration with Git - -### Ignored Files -All build artifacts are automatically ignored via `.gitignore`: -```gitignore -/v3/examples/*/testbuild-* -``` - -### Clean Build Environment -```bash -# Remove all test build artifacts -find v3/examples -name "testbuild-*" -delete -``` - -## Validation Results - -### Current Status (as of implementation): -- ✅ **macOS**: All 43 examples compile successfully -- ✅ **Windows**: All 43 examples cross-compile successfully -- ✅ **Linux**: Multi-architecture Docker system fully functional - -### Build Time Estimates: -- **macOS**: ~2-3 minutes for all examples -- **Windows**: ~2-3 minutes for all examples (cross-compile) -- **Linux Docker**: ~5-10 minutes for all examples (includes image build and compilation) -- **Complete Cross-Platform**: ~10-15 minutes for 129 total builds - -## Future Enhancements - -### Planned Improvements: -1. **Automated Testing**: Add runtime testing in addition to compilation -2. **Multi-Architecture**: Support ARM64 builds for Apple Silicon and Windows ARM -3. **Build Caching**: Implement Go build cache for faster repeated builds -4. **Parallel Docker**: Multi-stage Docker builds for faster Linux compilation -5. **Platform Matrix**: GitHub Actions integration for automated CI/CD - -### Platform Extensions: -- **FreeBSD**: Add BSD build support -- **Android/iOS**: Mobile platform compilation (when supported) -- **WebAssembly**: WASM target compilation - -## Changelog - -### v3.0.0-alpha (2025-06-20) -#### 🎯 Complete Cross-Platform Testing System - -#### **✨ New Features** -- **Complete Example Coverage**: All 43 examples now tested (was 35) -- **Cross-Platform Validation**: Mac + Windows builds for all examples -- **Standardized Build Artifacts**: Consistent platform-specific naming -- **Enhanced Git Integration**: Complete .gitignore patterns for build artifacts - -#### **🐛 Major Fixes** -- **Go Module Resolution**: Standardized replace directives across all examples -- **Frontend Asset Embedding**: Fixed missing frontend/dist directory references -- **Manager API Migration**: Updated deprecated Windows badge service calls -- **File Association**: Fixed undefined window variable -- **Build Completeness**: Added 8 missing examples to test suite - -#### **🔧 Infrastructure Improvements** -- **Taskfile Integration**: Comprehensive cross-platform build tasks -- **Performance Optimization**: Parallel builds where possible -- **Error Handling**: Clear build failure reporting and debugging -- **Documentation**: Complete testing guide with troubleshooting - -#### **📊 Validation Results** -- **macOS**: ✅ 43/43 examples compile successfully -- **Windows**: ✅ 43/43 examples cross-compile successfully -- **Build Time**: ~5-6 minutes for complete cross-platform validation -- **Reliability**: 100% success rate with proper error handling - -## Support - -For issues with cross-platform builds: -1. Check platform-specific requirements above -2. Review the troubleshooting section for resolved issues -3. Verify Go 1.24+ is installed -4. Check build logs for specific error messages -5. Use selective testing to isolate problems - -## References - -- [Wails v3 Documentation](https://wails.io/docs/) -- [Go Cross Compilation](https://golang.org/doc/install/cross) -- [GTK Development Libraries](https://www.gtk.org/docs/installations/linux) -- [Task Runner Documentation](https://taskfile.dev/) \ No newline at end of file diff --git a/v3/Taskfile.yaml b/v3/Taskfile.yaml deleted file mode 100644 index 171853e14..000000000 --- a/v3/Taskfile.yaml +++ /dev/null @@ -1,460 +0,0 @@ -# https://taskfile.dev - -version: "3" - -includes: - generator: - taskfile: ./internal/generator - dir: ./internal/generator - - runtime: - taskfile: ./internal/runtime - dir: ./internal/runtime - - website: - taskfile: ./website - dir: ./website - optional: true - - docs: - taskfile: ../docs - dir: ../docs - optional: true - -tasks: - recreate-template-dir: - dir: internal/templates - internal: true - silent: true - cmds: - - rm -rf {{.TEMPLATE_DIR}} - - mkdir -p {{.TEMPLATE_DIR}} - - install: - dir: cmd/wails3 - silent: true - cmds: - - go install - - echo "Installed wails CLI" - - release: - summary: Release a new version of Wails. Call with `task v3:release -- ` - dir: tasks/release - cmds: - - go run release.go {{.CLI_ARGS}} - - taskfile:upgrade: - cmds: - - go get -u github.com/go-task/task/v3 - - reinstall-cli: - dir: cmd/wails3 - internal: true - silent: true - cmds: - - go install - - echo "Reinstalled wails CLI" - - generate:events: - dir: tasks/events - cmds: - - go run generate.go - - go fmt ../../pkg/events/events.go - - precommit: - cmds: - - go test ./... - - task: format -# - task: docs:update:api - - test:example:darwin: - dir: 'examples/{{.DIR}}' - platforms: - - darwin - cmds: - - echo "Building example {{.DIR}} for Darwin" - - go mod tidy - - go build -o "testbuild-{{.DIR}}-darwin{{exeExt}}" - env: - CGO_LDFLAGS: -framework UniformTypeIdentifiers -mmacosx-version-min=10.13 - CGO_CFLAGS: -mmacosx-version-min=10.13 - - test:example:windows: - dir: 'examples/{{.DIR}}' - platforms: - - windows - cmds: - - echo "Building example {{.DIR}} for Windows" - - go mod tidy - - go build -o "testbuild-{{.DIR}}-windows.exe" - env: - GOOS: windows - GOARCH: amd64 - - test:example:linux: - summary: Build example for Linux with GTK3 (default) - dir: 'examples/{{.DIR}}' - platforms: - - linux - cmds: - - echo "Building example {{.DIR}} for Linux (GTK3)" - - go mod tidy - - go build -o "testbuild-{{.DIR}}-linux" - - test:example:linux:gtk4: - summary: Build example for Linux with GTK4 (experimental, opt-in via -tags gtk4) - dir: 'examples/{{.DIR}}' - platforms: - - linux - cmds: - - echo "Building example {{.DIR}} for Linux (GTK4 experimental)" - - go mod tidy - - go build -tags gtk4 -o "testbuild-{{.DIR}}-linux-gtk4" - - test:example:linux:docker:arm64: - summary: Build a single example for Linux ARM64 using Docker (Ubuntu 24.04) - cmds: - - echo "Building example {{.DIR}} for Linux ARM64 using Docker" - - docker build --pull -f test/docker/Dockerfile.linux-arm64 -t wails-v3-linux-arm64 . - - docker run --rm wails-v3-linux-arm64 /build/build-linux-arm64.sh {{.DIR}} - - test:example:linux:docker:x86_64: - summary: Build a single example for Linux x86_64 using Docker (Ubuntu 24.04) - cmds: - - echo "Building example {{.DIR}} for Linux x86_64 using Docker" - - docker build --pull -f test/docker/Dockerfile.linux-x86_64 -t wails-v3-linux-x86_64 . - - docker run --rm wails-v3-linux-x86_64 /build/build-linux-x86_64.sh {{.DIR}} - - test:examples:linux:docker:arm64: - summary: Build all examples for Linux ARM64 using Docker (Ubuntu 24.04, GTK4) - cmds: - - echo "Building Docker image for Linux ARM64 compilation..." - - docker build --pull -f test/docker/Dockerfile.linux-arm64 -t wails-v3-linux-arm64 . - - echo "Running Linux ARM64 compilation in Docker container (GTK4)..." - - docker run --rm wails-v3-linux-arm64 - - test:examples:linux:docker:x86_64: - summary: Build all examples for Linux x86_64 using Docker (Ubuntu 24.04, GTK4) - cmds: - - echo "Building Docker image for Linux x86_64 compilation..." - - docker build --pull -f test/docker/Dockerfile.linux-x86_64 -t wails-v3-linux-x86_64 . - - echo "Running Linux x86_64 compilation in Docker container (GTK4)..." - - docker run --rm wails-v3-linux-x86_64 - - test:examples:linux:docker:x86_64:gtk3: - summary: Build all examples for Linux x86_64 using Docker with GTK3 (legacy) - cmds: - - echo "Building Docker image for Linux x86_64 compilation..." - - docker build --pull -f test/docker/Dockerfile.linux-x86_64 -t wails-v3-linux-x86_64 . - - echo "Running Linux x86_64 compilation in Docker container (GTK3 legacy)..." - - docker run --rm -e BUILD_TAGS=gtk3 wails-v3-linux-x86_64 - - test:examples:linux:docker:arm64:gtk3: - summary: Build all examples for Linux ARM64 using Docker with GTK3 (legacy) - cmds: - - echo "Building Docker image for Linux ARM64 compilation..." - - docker build --pull -f test/docker/Dockerfile.linux-arm64 -t wails-v3-linux-arm64 . - - echo "Running Linux ARM64 compilation in Docker container (GTK3 legacy)..." - - docker run --rm -e BUILD_TAGS=gtk3 wails-v3-linux-arm64 - - test:example:linux:docker: - summary: Build a single example for Linux using Docker (auto-detect architecture) - cmds: - - echo "Auto-detecting architecture for Linux Docker build..." - - | - if [ "$(uname -m)" = "arm64" ] || [ "$(uname -m)" = "aarch64" ]; then - echo "Detected ARM64, using ARM64 Docker image" - task test:example:linux:docker:arm64 DIR={{.DIR}} - else - echo "Detected x86_64, using x86_64 Docker image" - task test:example:linux:docker:x86_64 DIR={{.DIR}} - fi - - test:examples:linux:docker: - summary: Build all examples for Linux using Docker (auto-detect architecture) - cmds: - - echo "Auto-detecting architecture for Linux Docker build..." - - | - if [ "$(uname -m)" = "arm64" ] || [ "$(uname -m)" = "aarch64" ]; then - echo "Detected ARM64, using ARM64 Docker image" - task test:examples:linux:docker:arm64 - else - echo "Detected x86_64, using x86_64 Docker image" - task test:examples:linux:docker:x86_64 - fi - - test:examples:all: - summary: Builds all examples for all platforms (Mac + Windows + Linux via Docker) - vars: - EXAMPLEDIRS: | - badge - badge-custom - binding - build - cancel-async - cancel-chaining - clipboard - contextmenus - dev - dialogs - dialogs-basic - drag-n-drop - environment - events - events-bug - file-association - frameless - gin-example - gin-routing - gin-service - hide-window - ignore-mouse - keybindings - liquid-glass - menu - notifications - panic-handling - plain - raw-message - screen - services - show-macos-toolbar - single-instance - systray-basic - systray-custom - systray-menu - video - window - window-api - window-call - window-menu - wml - cmds: - - echo "Building all examples for all platforms..." - - echo "=== Building for Darwin ===" - - for: { var: EXAMPLEDIRS } - task: test:example:darwin - vars: - DIR: "{{.ITEM}}" - - echo "=== Building for Windows (cross-compile) ===" - - for: { var: EXAMPLEDIRS } - task: test:example:windows - vars: - DIR: "{{.ITEM}}" - - echo "=== Building for Linux (Docker) ===" - - task: test:examples:linux:docker - - echo "=== Testing CLI Code ===" - - task: test:cli - - echo "=== Cleaning Up Test Binaries ===" - - task: clean:test:binaries - - test:cli: - summary: Test CLI-related code compilation - cmds: - - echo "Testing CLI appimage testfiles compilation..." - - cd internal/commands/appimage_testfiles && go mod tidy && go build - - echo "✅ CLI appimage testfiles compile successfully" - - test:cli:all: - summary: Test all CLI components and critical test files - cmds: - - echo "Testing CLI appimage testfiles..." - - cd internal/commands/appimage_testfiles && go mod tidy && go build - - echo "Testing window visibility test..." - - cd tests/window-visibility-test && go mod tidy && go build - - echo "Testing service implementations..." - - cd pkg/services/badge && go build - - echo "✅ All CLI components compile successfully" - - test:generator: - summary: Test code generator test cases compilation - cmds: - - echo "Testing generator test cases (sample)..." - - cd internal/generator/testcases/function_single && go mod tidy && go build - - cd internal/generator/testcases/complex_method && go mod tidy && go build - - cd internal/generator/testcases/struct_literal_single && go mod tidy && go build - - echo "✅ Generator test cases compile successfully" - - test:templates: - summary: Test template generation for core templates - cmds: - - echo "Testing template generation (core templates)..." - - task: install - - echo "Testing lit template generation..." - - rm -rf ./test-template-lit && wails3 init -n test-template-lit -t lit - - mkdir -p ./test-template-lit/frontend/dist && touch ./test-template-lit/frontend/dist/.keep - - cd ./test-template-lit && go mod tidy && go build - - rm -rf ./test-template-lit - - echo "Testing react template generation..." - - rm -rf ./test-template-react && wails3 init -n test-template-react -t react - - mkdir -p ./test-template-react/frontend/dist && touch ./test-template-react/frontend/dist/.keep - - cd ./test-template-react && go mod tidy && go build - - rm -rf ./test-template-react - - echo "✅ Template generation tests completed successfully" - - test:infrastructure: - summary: Test critical infrastructure components - cmds: - - echo "=== Testing CLI Components ===" - - task: test:cli:all - - echo "=== Testing Generator ===" - - task: test:generator - - echo "=== Testing Templates ===" - - task: test:templates - - echo "=== Testing pkg/application ===" - - cd pkg/application && go test -c -o /dev/null ./... - - echo "=== Cleaning Up Test Binaries ===" - - task: clean:test:binaries - - echo "✅ All infrastructure components test successfully" - - test:examples: - summary: Builds the examples for current platform only - vars: - EXAMPLEDIRS: | - badge - badge-custom - binding - build - cancel-async - cancel-chaining - clipboard - contextmenus - dev - dialogs - dialogs-basic - drag-n-drop - environment - events - events-bug - file-association - frameless - gin-example - gin-routing - gin-service - hide-window - ignore-mouse - keybindings - liquid-glass - menu - notifications - panic-handling - plain - raw-message - screen - services - show-macos-toolbar - single-instance - systray-basic - systray-custom - systray-menu - video - window - window-api - window-call - window-menu - wml - cmds: - - echo "Testing examples compilation..." - - for: { var: EXAMPLEDIRS } - task: test:example:darwin - vars: - DIR: "{{.ITEM}}" - platforms: [darwin] - - for: { var: EXAMPLEDIRS } - task: test:example:linux - vars: - DIR: "{{.ITEM}}" - platforms: [linux] - # GTK4 tests are run separately via Docker tasks since CI doesn't have GTK4 deps - # - for: { var: EXAMPLEDIRS } - # task: test:example:linux:gtk4 - # vars: - # DIR: "{{.ITEM}}" - # platforms: [linux] - - for: { var: EXAMPLEDIRS } - task: test:example:windows - vars: - DIR: "{{.ITEM}}" - platforms: [windows] - - echo "Testing CLI code..." - - task: test:cli - - echo "=== Cleaning Up Test Binaries ===" - - task: clean:test:binaries - - clean:test:binaries: - summary: Clean up all test-generated binary files and directories (cross-platform) - cmds: - - echo "🧹 Cleaning up test binaries..." - - go run tasks/cleanup/cleanup.go - - echo "✅ Test binaries cleaned up" - - test:all: - summary: Run all tests including examples, infrastructure, and Go unit tests - cmds: - - echo "=== Running Go Unit Tests ===" - - go test ./... - - echo "=== Testing Examples (Current Platform) ===" - - task: test:examples - - echo "=== Testing Infrastructure Components ===" - - task: test:infrastructure - - echo "=== Cleaning Up Test Binaries ===" - - task: clean:test:binaries - - echo "✅ All tests completed successfully" - - sanity: - summary: Quick compilation sanity check for key examples (GTK3 default + GTK4 opt-in) - platforms: - - linux - cmds: - - echo "🔍 Running quick sanity check (GTK3 - default)..." - - cd examples/menu && go build -o /dev/null . - - cd examples/window && go build -o /dev/null . - - cd examples/events && go build -o /dev/null . - - cd examples/plain && go build -o /dev/null . - - cd examples/dialogs-basic && go build -o /dev/null . - - echo "✅ GTK3 sanity check passed" - - task: sanity:gtk4 - - sanity:gtk4: - summary: Quick compilation sanity check for GTK4 (experimental, opt-in via -tags gtk4) - platforms: - - linux - cmds: - - echo "🔍 Running GTK4 sanity check..." - - cd examples/menu && go build -tags gtk4 -o /dev/null . - - cd examples/window && go build -tags gtk4 -o /dev/null . - - cd examples/events && go build -tags gtk4 -o /dev/null . - - cd examples/plain && go build -tags gtk4 -o /dev/null . - - echo "✅ GTK4 sanity check passed" - - build:server: - summary: Build an application in server mode (no GUI, HTTP server only) - desc: | - Builds a Wails application in server mode using the -tags server build tag. - Server mode enables running the application as a pure HTTP server without - native GUI dependencies. - - Usage: task build:server DIR=examples/server - dir: '{{.DIR | default "."}}' - cmds: - - echo "Building {{.DIR | default `.`}} in server mode..." - - go build -tags server -o '{{.OUTPUT | default "server-app"}}' . - - echo "Server mode build complete" - - test:example:server: - summary: Build and test the server mode example - dir: 'examples/server' - cmds: - - echo "Building server example with -tags server..." - - go mod tidy - - go build -tags server -o "testbuild-server" - - echo "✅ Server example builds successfully" - - rm -f testbuild-server - - test:server: - summary: Run server mode unit tests - dir: 'pkg/application' - cmds: - - echo "Running server mode tests..." - - go test -tags server -v -run TestServerMode . - - echo "✅ Server mode tests passed" diff --git a/v3/UNRELEASED_CHANGELOG.md b/v3/UNRELEASED_CHANGELOG.md deleted file mode 100644 index 8e4648038..000000000 --- a/v3/UNRELEASED_CHANGELOG.md +++ /dev/null @@ -1,53 +0,0 @@ -# Unreleased Changes - - - -## Added - - -## Changed - - -## Fixed - - -## Deprecated - - -## Removed - - -## Security - - ---- - -### Example Entries: - -**Added:** -- Add support for custom window icons in application options -- Add new `SetWindowIcon()` method to runtime API (#1234) - -**Changed:** -- Update minimum Go version requirement to 1.21 -- Improve error messages for invalid configuration files - -**Fixed:** -- Fix memory leak in event system during window close operations (#5678) -- Fix crash when using context menus on Linux with Wayland - -**Security:** -- Update dependencies to address CVE-2024-12345 in third-party library diff --git a/v3/build_ios.sh b/v3/build_ios.sh deleted file mode 100755 index b20f5dfcb..000000000 --- a/v3/build_ios.sh +++ /dev/null @@ -1,233 +0,0 @@ -#!/bin/bash - -# Wails v3 iOS Build Script -# This script builds a Wails application for iOS Simulator - -set -e - -# Colors for output -RED='\033[0;31m' -GREEN='\033[0;32m' -YELLOW='\033[1;33m' -NC='\033[0m' # No Color - -echo -e "${GREEN}Wails v3 iOS Build Script${NC}" -echo "===============================" - -# Check for required tools -check_command() { - if ! command -v $1 &> /dev/null; then - echo -e "${RED}Error: $1 is not installed${NC}" - exit 1 - fi -} - -echo "Checking dependencies..." -check_command go -check_command xcodebuild -check_command xcrun - -# Configuration -APP_NAME="${APP_NAME:-WailsIOSDemo}" -BUNDLE_ID="${BUNDLE_ID:-com.wails.iosdemo}" -BUILD_DIR="build/ios" -SIMULATOR_SDK="iphonesimulator" -MIN_IOS_VERSION="13.0" - -# Clean build directory -echo "Cleaning build directory..." -rm -rf $BUILD_DIR -mkdir -p $BUILD_DIR - -# Create the iOS app structure -echo "Creating iOS app structure..." -APP_DIR="$BUILD_DIR/$APP_NAME.app" -mkdir -p "$APP_DIR" - -# Create Info.plist -echo "Creating Info.plist..." -cat > "$BUILD_DIR/Info.plist" << EOF - - - - - CFBundleDevelopmentRegion - en - CFBundleExecutable - $APP_NAME - CFBundleIdentifier - $BUNDLE_ID - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $APP_NAME - CFBundlePackageType - APPL - CFBundleShortVersionString - 1.0 - CFBundleVersion - 1 - LSRequiresIPhoneOS - - MinimumOSVersion - $MIN_IOS_VERSION - UILaunchStoryboardName - LaunchScreen - UIRequiredDeviceCapabilities - - arm64 - - UISupportedInterfaceOrientations - - UIInterfaceOrientationPortrait - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - UISupportedInterfaceOrientations~ipad - - UIInterfaceOrientationPortrait - UIInterfaceOrientationPortraitUpsideDown - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - NSAppTransportSecurity - - NSAllowsArbitraryLoads - - - - -EOF - -cp "$BUILD_DIR/Info.plist" "$APP_DIR/" - -# Build the Go application for iOS Simulator -echo -e "${YELLOW}Building Go application for iOS Simulator...${NC}" - -# Set up environment for iOS cross-compilation -export CGO_ENABLED=1 -export GOOS=ios -export GOARCH=arm64 -export SDK_PATH=$(xcrun --sdk $SIMULATOR_SDK --show-sdk-path) -export CGO_CFLAGS="-isysroot $SDK_PATH -mios-simulator-version-min=$MIN_IOS_VERSION -arch arm64 -fembed-bitcode" -export CGO_LDFLAGS="-isysroot $SDK_PATH -mios-simulator-version-min=$MIN_IOS_VERSION -arch arm64" - -# Find clang for the simulator -export CC=$(xcrun --sdk $SIMULATOR_SDK --find clang) -export CXX=$(xcrun --sdk $SIMULATOR_SDK --find clang++) - -echo "SDK Path: $SDK_PATH" -echo "CC: $CC" - -# Build the demo app using the example -echo "Building demo application..." - -# Create a simplified main.go that uses local packages -cat > "$BUILD_DIR/main.go" << 'EOF' -//go:build ios - -package main - -import ( - "fmt" - "log" -) - -// Since we're building a proof of concept, we'll create a minimal app -// that demonstrates the iOS integration - -func main() { - fmt.Println("Wails iOS Demo Starting...") - - // For the PoC, we'll import the iOS platform code directly - // In production, this would use the full Wails v3 application package - - log.Println("iOS application would start here") - // The actual iOS app initialization happens in the Objective-C layer - // This is just a placeholder for the build process -} -EOF - -# Try to build the binary -cd "$BUILD_DIR" -echo "Attempting to build iOS binary..." - -# For now, let's create a simple test binary to verify the build toolchain -go build -tags ios -o "$APP_NAME" main.go 2>&1 || { - echo -e "${YELLOW}Note: Full iOS build requires gomobile or additional setup${NC}" - echo "Creating placeholder binary for demonstration..." - - # Create a placeholder executable - cat > "$APP_NAME.c" << 'EOF' -#include -int main() { - printf("Wails iOS Demo Placeholder\n"); - return 0; -} -EOF - - $CC -isysroot $SDK_PATH -arch arm64 -mios-simulator-version-min=$MIN_IOS_VERSION \ - -o "$APP_NAME" "$APP_NAME.c" -} - -# Sign the app for simulator (no actual certificate needed) -echo "Preparing app for simulator..." -codesign --force --sign - "$APP_NAME" 2>/dev/null || true -mv "$APP_NAME" "$APP_DIR/" - -# Create a simple launch script -echo "Creating launch script..." -cd - > /dev/null -cat > "$BUILD_DIR/run_simulator.sh" << 'EOF' -#!/bin/bash - -echo "iOS Simulator Launch Script" -echo "============================" - -# Check if Simulator is available -if ! command -v open &> /dev/null; then - echo "Error: Cannot open Simulator" - exit 1 -fi - -# Open Xcode Simulator -echo "Opening iOS Simulator..." -open -a Simulator 2>/dev/null || { - echo "Error: Could not open Simulator. Make sure Xcode is installed." - exit 1 -} - -echo "" -echo "Simulator should now be opening..." -echo "" -echo "Note: This is a proof of concept demonstrating:" -echo " 1. ✅ WebView creation (application_ios.m)" -echo " 2. ✅ Request interception via WKURLSchemeHandler" -echo " 3. ✅ JavaScript execution bridge" -echo " 4. ✅ iOS Simulator build support" -echo "" -echo "The full implementation would require:" -echo " - gomobile for proper Go/iOS integration" -echo " - Proper Xcode project generation" -echo " - Full CGO bindings compilation" -echo "" -echo "See IOS_ARCHITECTURE.md for complete technical details." -EOF - -chmod +x "$BUILD_DIR/run_simulator.sh" - -echo -e "${GREEN}Build complete!${NC}" -echo "" -echo "Build artifacts created in: $BUILD_DIR" -echo "" -echo "To open the iOS Simulator:" -echo " cd $BUILD_DIR && ./run_simulator.sh" -echo "" -echo "The proof of concept demonstrates:" -echo " 1. ✅ WebView creation code (pkg/application/application_ios.m)" -echo " 2. ✅ Request interception (WKURLSchemeHandler implementation)" -echo " 3. ✅ JavaScript execution (bidirectional bridge)" -echo " 4. ✅ iOS build configuration and simulator support" -echo "" -echo "Full implementation requires gomobile integration." -echo "See IOS_ARCHITECTURE.md for complete technical documentation." \ No newline at end of file diff --git a/v3/cmd/wails3/README.md b/v3/cmd/wails3/README.md deleted file mode 100644 index 8924153dd..000000000 --- a/v3/cmd/wails3/README.md +++ /dev/null @@ -1,83 +0,0 @@ -# The Wails CLI - -The Wails CLI is a command line tool that allows you to create, build and run Wails applications. -There are a number of commands related to tooling, such as icon generation and asset bundling. - -## Commands - -### task - -The `task` command is for running tasks defined in `Taskfile.yml`. It is a wrapper around [Task](https://taskfile.dev). - -### generate - -The `generate` command is used to generate resources and assets for your Wails project. -It can be used to generate many things including: - - application icons, - - resource files for Windows applications - - Info.plist files for macOS deployments - -#### icon - -The `icon` command generates icons for your project. - -| Flag | Type | Description | Default | -|--------------------|--------|------------------------------------------------------|----------------------| -| `-example` | bool | Generates example icon file (appicon.png) | | -| `-input` | string | The input image file | | -| `-sizes` | string | The sizes to generate in .ico file (comma separated) | "256,128,64,48,32,16" | -| `-windowsFilename` | string | The output filename for the Windows icon | icon.ico | -| `-macFilename` | string | The output filename for the Mac icon bundle | icons.icns | - -```bash -wails3 generate icon -input myicon.png -sizes "32,64,128" -windowsFilename myicon.ico -macFilename myicon.icns -``` - -This will generate icons for mac and windows and save them in the current directory as `myicon.ico` -and `myicons.icns`. - -#### syso - -The `syso` command generates a Windows resource file (aka `.syso`). - -```bash -wails3 generate syso -``` - -| Flag | Type | Description | Default | -|-------------|--------|--------------------------------------------|------------------| -| `-example` | bool | Generates example manifest & info files | | -| `-manifest` | string | The manifest file | | -| `-info` | string | The info.json file | | -| `-icon` | string | The icon file | | -| `-out` | string | The output filename for the syso file | `wails.exe.syso` | -| `-arch` | string | The target architecture (amd64,arm64,386) | `runtime.GOOS` | - -If `-example` is provided, the command will generate example manifest and info files -in the current directory and exit. - -If `-manifest` is provided, the command will use the provided manifest file to generate -the syso file. - -If `-info` is provided, the command will use the provided info.json file to set the version -information in the syso file. - -NOTE: We use [winres](https://github.com/tc-hib/winres) to generate the syso file. Please -refer to the winres documentation for more information. - -NOTE: Whilst the tool will work for 32-bit Windows, it is not supported. Please use 64-bit. - -#### defaults - -```bash -wails3 generate defaults -``` -This will generate all the default assets and resources in the current directory. - -#### bindings - -```bash -wails3 generate bindings -``` - -Generates bindings and models for your bound Go methods and structs. \ No newline at end of file diff --git a/v3/cmd/wails3/main.go b/v3/cmd/wails3/main.go deleted file mode 100644 index 8e67ac0f5..000000000 --- a/v3/cmd/wails3/main.go +++ /dev/null @@ -1,176 +0,0 @@ -package main - -import ( - "os" - "runtime/debug" - - "github.com/pkg/browser" - - "github.com/pterm/pterm" - "github.com/samber/lo" - - "github.com/leaanthony/clir" - "github.com/wailsapp/wails/v3/internal/commands" - "github.com/wailsapp/wails/v3/internal/flags" - "github.com/wailsapp/wails/v3/internal/term" -) - -func init() { - buildInfo, ok := debug.ReadBuildInfo() - if !ok { - return - } - commands.BuildSettings = lo.Associate(buildInfo.Settings, func(setting debug.BuildSetting) (string, string) { - return setting.Key, setting.Value - }) - // Iterate over the Deps and add them to the build settings using a prefix of "mod." - for _, dep := range buildInfo.Deps { - commands.BuildSettings["mod."+dep.Path] = dep.Version - } -} - -func main() { - app := clir.NewCli("wails", "The Wails3 CLI", "v3") - app.NewSubCommand("docs", "Open the docs").Action(openDocs) - app.NewSubCommandFunction("init", "Initialise a new project", commands.Init) - - build := app.NewSubCommand("build", "Build the project") - var buildFlags flags.Build - build.AddFlags(&buildFlags) - build.Action(func() error { - return commands.Build(&buildFlags, build.OtherArgs()) - }) - - app.NewSubCommandFunction("dev", "Run in Dev mode", commands.Dev) - - pkg := app.NewSubCommand("package", "Package application") - var pkgFlags flags.Package - pkg.AddFlags(&pkgFlags) - pkg.Action(func() error { - return commands.Package(&pkgFlags, pkg.OtherArgs()) - }) - app.NewSubCommandFunction("doctor", "System status report", commands.Doctor) - app.NewSubCommandFunction("doctor-ng", "System status report (new TUI)", commands.DoctorNg) - app.NewSubCommandFunction("releasenotes", "Show release notes", commands.ReleaseNotes) - - task := app.NewSubCommand("task", "Run and list tasks") - var taskFlags commands.RunTaskOptions - task.AddFlags(&taskFlags) - task.Action(func() error { - return commands.RunTask(&taskFlags, task.OtherArgs()) - }) - task.LongDescription("\nUsage: wails3 task [taskname] [flags]\n\nTasks are defined in the `Taskfile.yaml` file. See https://taskfile.dev for more information.") - - generate := app.NewSubCommand("generate", "Generation tools") - generate.NewSubCommandFunction("build-assets", "Generate build assets", commands.GenerateBuildAssets) - generate.NewSubCommandFunction("icons", "Generate icons", commands.GenerateIcons) - generate.NewSubCommandFunction("syso", "Generate Windows .syso file", commands.GenerateSyso) - generate.NewSubCommandFunction("runtime", "Generate the pre-built version of the runtime", commands.GenerateRuntime) - generate.NewSubCommandFunction("webview2bootstrapper", "Generate WebView2 bootstrapper", commands.GenerateWebView2Bootstrapper) - generate.NewSubCommandFunction("template", "Generate a new template", commands.GenerateTemplate) - - update := app.NewSubCommand("update", "Update tools") - update.NewSubCommandFunction("build-assets", "Updates the build assets using the given config file", commands.UpdateBuildAssets) - update.NewSubCommandFunction("cli", "Updates the Wails CLI", commands.UpdateCLI) - - bindgen := generate.NewSubCommand("bindings", "Generate bindings + models") - var bindgenFlags flags.GenerateBindingsOptions - bindgen.AddFlags(&bindgenFlags) - bindgen.Action(func() error { - return commands.GenerateBindings(&bindgenFlags, bindgen.OtherArgs()) - }) - bindgen.LongDescription("\nUsage: wails3 generate bindings [flags] [patterns...]\n\nPatterns match packages to scan for bound types.\nPattern format is analogous to that of the Go build tool,\ne.g. './...' matches packages in the current directory and all descendants.\nIf no pattern is given, the tool will fall back to the current directory.") - generate.NewSubCommandFunction("constants", "Generate JS constants from Go", commands.GenerateConstants) - generate.NewSubCommandFunction(".desktop", "Generate .desktop file", commands.GenerateDotDesktop) - generate.NewSubCommandFunction("appimage", "Generate Linux AppImage", commands.GenerateAppImage) - - plugin := app.NewSubCommand("service", "Service tools") - plugin.NewSubCommandFunction("init", "Initialise a new service", commands.ServiceInit) - - tool := app.NewSubCommand("tool", "Various tools") - tool.NewSubCommandFunction("checkport", "Checks if a port is open. Useful for testing if vite is running.", commands.ToolCheckPort) - tool.NewSubCommandFunction("watcher", "Watches files and runs a command when they change", commands.Watcher) - tool.NewSubCommandFunction("cp", "Copy files", commands.Cp) - tool.NewSubCommandFunction("buildinfo", "Show Build Info", commands.BuildInfo) - tool.NewSubCommandFunction("package", "Generate Linux packages (deb, rpm, archlinux)", commands.ToolPackage) - tool.NewSubCommandFunction("version", "Bump semantic version", commands.ToolVersion) - tool.NewSubCommandFunction("lipo", "Create macOS universal binary from multiple architectures", commands.ToolLipo) - tool.NewSubCommandFunction("capabilities", "Check system build capabilities (GTK4/GTK3 availability)", commands.ToolCapabilities) - - // Low-level sign tool (used by Taskfiles) - toolSign := tool.NewSubCommand("sign", "Sign a binary or package directly") - var toolSignFlags flags.Sign - toolSign.AddFlags(&toolSignFlags) - toolSign.Action(func() error { - return commands.Sign(&toolSignFlags) - }) - - // Setup commands - setup := app.NewSubCommand("setup", "Project setup wizards") - setupSigning := setup.NewSubCommand("signing", "Configure code signing") - var setupSigningFlags flags.SigningSetup - setupSigning.AddFlags(&setupSigningFlags) - setupSigning.Action(func() error { - return commands.SigningSetup(&setupSigningFlags) - }) - - setupEntitlements := setup.NewSubCommand("entitlements", "Configure macOS entitlements") - var setupEntitlementsFlags flags.EntitlementsSetup - setupEntitlements.AddFlags(&setupEntitlementsFlags) - setupEntitlements.Action(func() error { - return commands.EntitlementsSetup(&setupEntitlementsFlags) - }) - - // Sign command (wrapper that calls platform-specific tasks) - sign := app.NewSubCommand("sign", "Sign binaries and packages for current or specified platform") - var signWrapperFlags flags.SignWrapper - sign.AddFlags(&signWrapperFlags) - sign.Action(func() error { - return commands.SignWrapper(&signWrapperFlags, sign.OtherArgs()) - }) - - // iOS tools - ios := app.NewSubCommand("ios", "iOS tooling") - ios.NewSubCommandFunction("overlay:gen", "Generate Go overlay for iOS bridge shim", commands.IOSOverlayGen) - ios.NewSubCommandFunction("xcode:gen", "Generate Xcode project in output directory", commands.IOSXcodeGen) - - app.NewSubCommandFunction("version", "Print the version", commands.Version) - app.NewSubCommand("sponsor", "Sponsor the project").Action(openSponsor) - - defer printFooter() - - err := app.Run() - if err != nil { - pterm.Error.Println(err) - os.Exit(1) - } -} - -func printFooter() { - if !commands.DisableFooter { - docsLink := term.Hyperlink("https://v3.wails.io/getting-started/your-first-app/", "wails3 docs") - - pterm.Println(pterm.LightGreen("\nNeed documentation? Run: ") + pterm.LightBlue(docsLink)) - // Check if we're in a teminal - printer := pterm.PrefixPrinter{ - MessageStyle: pterm.NewStyle(pterm.FgLightGreen), - Prefix: pterm.Prefix{ - Style: pterm.NewStyle(pterm.FgRed, pterm.BgLightWhite), - Text: "♥ ", - }, - } - - linkText := term.Hyperlink("https://github.com/sponsors/leaanthony", "wails3 sponsor") - printer.Println("If Wails is useful to you or your company, please consider sponsoring the project: " + pterm.LightBlue(linkText)) - } -} - -func openDocs() error { - commands.DisableFooter = true - return browser.OpenURL("https://v3.wails.io/getting-started/your-first-app/") -} - -func openSponsor() error { - commands.DisableFooter = true - return browser.OpenURL("https://github.com/sponsors/leaanthony") -} diff --git a/v3/examples/README.md b/v3/examples/README.md deleted file mode 100644 index 753ec5138..000000000 --- a/v3/examples/README.md +++ /dev/null @@ -1,17 +0,0 @@ -# v3 - -*NOTE*: The examples in this directory may or may not compile / run at any given time during alpha development. - - -## Running the examples - - cd v3/examples/ - go mod tidy - go run . - -## Compiling the examples - - cd v3/examples/ - go mod tidy - go build - ./ diff --git a/v3/examples/android/.gitignore b/v3/examples/android/.gitignore deleted file mode 100644 index edb05e60a..000000000 --- a/v3/examples/android/.gitignore +++ /dev/null @@ -1,24 +0,0 @@ -# Build outputs -bin/ -*.apk -*.aab - -# Android build artifacts -build/android/.gradle/ -build/android/app/build/ -build/android/local.properties - -# JNI libraries (generated during build) -build/android/app/src/main/jniLibs/*/libwails.so - -# IDE -.idea/ -*.iml - -# OS -.DS_Store -Thumbs.db - -# Frontend build -frontend/dist/ -frontend/node_modules/ diff --git a/v3/examples/android/.task/checksum/android-common-generate-icons b/v3/examples/android/.task/checksum/android-common-generate-icons deleted file mode 100644 index 4534dd92e..000000000 --- a/v3/examples/android/.task/checksum/android-common-generate-icons +++ /dev/null @@ -1 +0,0 @@ -a40fe27d90a25e84deeed985e4075cfa diff --git a/v3/examples/android/.task/checksum/android-common-install-frontend-deps b/v3/examples/android/.task/checksum/android-common-install-frontend-deps deleted file mode 100644 index 997225071..000000000 --- a/v3/examples/android/.task/checksum/android-common-install-frontend-deps +++ /dev/null @@ -1 +0,0 @@ -82dedd4f821c351be61d8e1dbb6eefa diff --git a/v3/examples/android/.task/checksum/android-generate-android-bindings b/v3/examples/android/.task/checksum/android-generate-android-bindings deleted file mode 100644 index ad9ec9f0b..000000000 --- a/v3/examples/android/.task/checksum/android-generate-android-bindings +++ /dev/null @@ -1 +0,0 @@ -7bfce68482b8f82eb3495774fb52ddca diff --git a/v3/examples/android/.task/checksum/build-frontend--PRODUCTION-- b/v3/examples/android/.task/checksum/build-frontend--PRODUCTION-- deleted file mode 100644 index 4a8874ebd..000000000 --- a/v3/examples/android/.task/checksum/build-frontend--PRODUCTION-- +++ /dev/null @@ -1 +0,0 @@ -aef25acb8df5f0f69361a3df9b49b2e diff --git a/v3/examples/android/.task/checksum/generate-bindings--BUILD_FLAGS--tags-android-debug--buildvcs-false--gcflags-all---l-- b/v3/examples/android/.task/checksum/generate-bindings--BUILD_FLAGS--tags-android-debug--buildvcs-false--gcflags-all---l-- deleted file mode 100644 index 52597e299..000000000 --- a/v3/examples/android/.task/checksum/generate-bindings--BUILD_FLAGS--tags-android-debug--buildvcs-false--gcflags-all---l-- +++ /dev/null @@ -1 +0,0 @@ -3eaf69fc9c4a0eeef54a9ebcc9b25cf7 diff --git a/v3/examples/android/Taskfile.yml b/v3/examples/android/Taskfile.yml deleted file mode 100644 index 4940aab8e..000000000 --- a/v3/examples/android/Taskfile.yml +++ /dev/null @@ -1,34 +0,0 @@ -version: '3' - -includes: - common: ./build/Taskfile.yml - windows: ./build/windows/Taskfile.yml - darwin: ./build/darwin/Taskfile.yml - linux: ./build/linux/Taskfile.yml - android: ./build/android/Taskfile.yml - -vars: - APP_NAME: "android" - BIN_DIR: "bin" - VITE_PORT: '{{.WAILS_VITE_PORT | default 9245}}' - -tasks: - build: - summary: Builds the application - cmds: - - task: "{{OS}}:build" - - package: - summary: Packages a production build of the application - cmds: - - task: "{{OS}}:package" - - run: - summary: Runs the application - cmds: - - task: "{{OS}}:run" - - dev: - summary: Runs the application in development mode - cmds: - - wails3 dev -config ./build/config.yml -port {{.VITE_PORT}} diff --git a/v3/examples/android/build/Taskfile.yml b/v3/examples/android/build/Taskfile.yml deleted file mode 100644 index 209793bfd..000000000 --- a/v3/examples/android/build/Taskfile.yml +++ /dev/null @@ -1,174 +0,0 @@ -version: '3' - -tasks: - go:mod:tidy: - summary: Runs `go mod tidy` - internal: true - cmds: - - go mod tidy - - install:frontend:deps: - summary: Install frontend dependencies - dir: frontend - sources: - - package.json - - package-lock.json - generates: - - node_modules/* - preconditions: - - sh: npm version - msg: "Looks like npm isn't installed. Npm is part of the Node installer: https://nodejs.org/en/download/" - cmds: - - npm install - - build:frontend: - label: build:frontend (PRODUCTION={{.PRODUCTION}}) - summary: Build the frontend project - dir: frontend - sources: - - "**/*" - generates: - - dist/**/* - deps: - - task: install:frontend:deps - - task: generate:bindings - vars: - BUILD_FLAGS: - ref: .BUILD_FLAGS - cmds: - - npm run {{.BUILD_COMMAND}} -q - env: - PRODUCTION: '{{.PRODUCTION | default "false"}}' - vars: - BUILD_COMMAND: '{{if eq .PRODUCTION "true"}}build{{else}}build:dev{{end}}' - - - frontend:vendor:puppertino: - summary: Fetches Puppertino CSS into frontend/public for consistent mobile styling - sources: - - frontend/public/puppertino/puppertino.css - generates: - - frontend/public/puppertino/puppertino.css - cmds: - - | - set -euo pipefail - mkdir -p frontend/public/puppertino - # Fetch Puppertino full.css and LICENSE from GitHub main branch - curl -fsSL https://raw.githubusercontent.com/codedgar/Puppertino/main/dist/css/full.css -o frontend/public/puppertino/puppertino.css - curl -fsSL https://raw.githubusercontent.com/codedgar/Puppertino/main/LICENSE -o frontend/public/puppertino/LICENSE - echo "Puppertino CSS updated at frontend/public/puppertino/puppertino.css" - # Ensure index.html includes Puppertino CSS and button classes - INDEX_HTML=frontend/index.html - if [ -f "$INDEX_HTML" ]; then - if ! grep -q 'href="/puppertino/puppertino.css"' "$INDEX_HTML"; then - # Insert Puppertino link tag after style.css link - awk ' - /href="\/style.css"\/?/ && !x { print; print " "; x=1; next }1 - ' "$INDEX_HTML" > "$INDEX_HTML.tmp" && mv "$INDEX_HTML.tmp" "$INDEX_HTML" - fi - # Replace default .btn with Puppertino primary button classes if present - sed -E -i'' 's/class=\"btn\"/class=\"p-btn p-prim-col\"/g' "$INDEX_HTML" || true - fi - - generate:bindings: - label: generate:bindings (BUILD_FLAGS={{.BUILD_FLAGS}}) - summary: Generates bindings for the frontend - deps: - - task: go:mod:tidy - sources: - - "**/*.[jt]s" - - exclude: frontend/**/* - - frontend/bindings/**/* # Rerun when switching between dev/production mode causes changes in output - - "**/*.go" - - go.mod - - go.sum - generates: - - frontend/bindings/**/* - cmds: - - wails3 generate bindings -f '{{.BUILD_FLAGS}}' -clean=true - - generate:icons: - summary: Generates Windows `.ico` and Mac `.icns` files from an image - dir: build - sources: - - "appicon.png" - generates: - - "darwin/icons.icns" - - "windows/icon.ico" - cmds: - - wails3 generate icons -input appicon.png -macfilename darwin/icons.icns -windowsfilename windows/icon.ico - - dev:frontend: - summary: Runs the frontend in development mode - dir: frontend - deps: - - task: install:frontend:deps - cmds: - - npm run dev -- --port {{.VITE_PORT}} --strictPort - - update:build-assets: - summary: Updates the build assets - dir: build - cmds: - - wails3 update build-assets -name "{{.APP_NAME}}" -binaryname "{{.APP_NAME}}" -config config.yml -dir . - - - ios:device:list: - summary: Lists connected iOS devices (UDIDs) - cmds: - - xcrun xcdevice list - - ios:run:device: - summary: Build, install, and launch on a physical iPhone using Apple tools (xcodebuild/devicectl) - vars: - PROJECT: '{{.PROJECT}}' # e.g., build/ios/xcode/.xcodeproj - SCHEME: '{{.SCHEME}}' # e.g., ios.dev - CONFIG: '{{.CONFIG | default "Debug"}}' - DERIVED: '{{.DERIVED | default "build/ios/DerivedData"}}' - UDID: '{{.UDID}}' # from `task ios:device:list` - BUNDLE_ID: '{{.BUNDLE_ID}}' # e.g., com.yourco.wails.ios.dev - TEAM_ID: '{{.TEAM_ID}}' # optional, if your project is not already set up for signing - preconditions: - - sh: xcrun -f xcodebuild - msg: "xcodebuild not found. Please install Xcode." - - sh: xcrun -f devicectl - msg: "devicectl not found. Please update to Xcode 15+ (which includes devicectl)." - - sh: test -n "{{.PROJECT}}" - msg: "Set PROJECT to your .xcodeproj path (e.g., PROJECT=build/ios/xcode/App.xcodeproj)." - - sh: test -n "{{.SCHEME}}" - msg: "Set SCHEME to your app scheme (e.g., SCHEME=ios.dev)." - - sh: test -n "{{.UDID}}" - msg: "Set UDID to your device UDID (see: task ios:device:list)." - - sh: test -n "{{.BUNDLE_ID}}" - msg: "Set BUNDLE_ID to your app's bundle identifier (e.g., com.yourco.wails.ios.dev)." - cmds: - - | - set -euo pipefail - echo "Building for device: UDID={{.UDID}} SCHEME={{.SCHEME}} PROJECT={{.PROJECT}}" - XCB_ARGS=( - -project "{{.PROJECT}}" - -scheme "{{.SCHEME}}" - -configuration "{{.CONFIG}}" - -destination "id={{.UDID}}" - -derivedDataPath "{{.DERIVED}}" - -allowProvisioningUpdates - -allowProvisioningDeviceRegistration - ) - # Optionally inject signing identifiers if provided - if [ -n "{{.TEAM_ID}}" ]; then XCB_ARGS+=(DEVELOPMENT_TEAM={{.TEAM_ID}}); fi - if [ -n "{{.BUNDLE_ID}}" ]; then XCB_ARGS+=(PRODUCT_BUNDLE_IDENTIFIER={{.BUNDLE_ID}}); fi - xcodebuild "${XCB_ARGS[@]}" build | xcpretty || true - # If xcpretty isn't installed, run without it - if [ "${PIPESTATUS[0]}" -ne 0 ]; then - xcodebuild "${XCB_ARGS[@]}" build - fi - # Find built .app - APP_PATH=$(find "{{.DERIVED}}/Build/Products" -type d -name "*.app" -maxdepth 3 | head -n 1) - if [ -z "$APP_PATH" ]; then - echo "Could not locate built .app under {{.DERIVED}}/Build/Products" >&2 - exit 1 - fi - echo "Installing: $APP_PATH" - xcrun devicectl device install app --device "{{.UDID}}" "$APP_PATH" - echo "Launching: {{.BUNDLE_ID}}" - xcrun devicectl device process launch --device "{{.UDID}}" --stderr console --stdout console "{{.BUNDLE_ID}}" diff --git a/v3/examples/android/build/android/Taskfile.yml b/v3/examples/android/build/android/Taskfile.yml deleted file mode 100644 index 5005f9f4e..000000000 --- a/v3/examples/android/build/android/Taskfile.yml +++ /dev/null @@ -1,237 +0,0 @@ -version: '3' - -includes: - common: ../Taskfile.yml - -vars: - APP_ID: '{{.APP_ID | default "com.wails.app"}}' - MIN_SDK: '21' - TARGET_SDK: '34' - NDK_VERSION: 'r26d' - -tasks: - install:deps: - summary: Check and install Android development dependencies - cmds: - - go run build/android/scripts/deps/install_deps.go - env: - TASK_FORCE_YES: '{{if .YES}}true{{else}}false{{end}}' - prompt: This will check and install Android development dependencies. Continue? - - build: - summary: Creates a build of the application for Android - deps: - - task: common:go:mod:tidy - - task: generate:android:bindings - vars: - BUILD_FLAGS: - ref: .BUILD_FLAGS - - task: common:build:frontend - vars: - BUILD_FLAGS: - ref: .BUILD_FLAGS - PRODUCTION: - ref: .PRODUCTION - - task: common:generate:icons - cmds: - - echo "Building Android app {{.APP_NAME}}..." - - task: compile:go:shared - vars: - ARCH: '{{.ARCH | default "arm64"}}' - vars: - BUILD_FLAGS: '{{if eq .PRODUCTION "true"}}-tags production,android -trimpath -buildvcs=false -ldflags="-w -s"{{else}}-tags android,debug -buildvcs=false -gcflags=all="-l"{{end}}' - env: - PRODUCTION: '{{.PRODUCTION | default "false"}}' - - compile:go:shared: - summary: Compile Go code to shared library (.so) - cmds: - - | - NDK_ROOT="${ANDROID_NDK_HOME:-$ANDROID_HOME/ndk/{{.NDK_VERSION}}}" - if [ ! -d "$NDK_ROOT" ]; then - echo "Error: Android NDK not found at $NDK_ROOT" - echo "Please set ANDROID_NDK_HOME or install NDK {{.NDK_VERSION}} via Android Studio" - exit 1 - fi - - # Determine toolchain based on host OS - case "$(uname -s)" in - Darwin) HOST_TAG="darwin-x86_64" ;; - Linux) HOST_TAG="linux-x86_64" ;; - *) echo "Unsupported host OS"; exit 1 ;; - esac - - TOOLCHAIN="$NDK_ROOT/toolchains/llvm/prebuilt/$HOST_TAG" - - # Set compiler based on architecture - case "{{.ARCH}}" in - arm64) - export CC="$TOOLCHAIN/bin/aarch64-linux-android{{.MIN_SDK}}-clang" - export CXX="$TOOLCHAIN/bin/aarch64-linux-android{{.MIN_SDK}}-clang++" - export GOARCH=arm64 - JNI_DIR="arm64-v8a" - ;; - amd64|x86_64) - export CC="$TOOLCHAIN/bin/x86_64-linux-android{{.MIN_SDK}}-clang" - export CXX="$TOOLCHAIN/bin/x86_64-linux-android{{.MIN_SDK}}-clang++" - export GOARCH=amd64 - JNI_DIR="x86_64" - ;; - *) - echo "Unsupported architecture: {{.ARCH}}" - exit 1 - ;; - esac - - export CGO_ENABLED=1 - export GOOS=android - - mkdir -p {{.BIN_DIR}} - mkdir -p build/android/app/src/main/jniLibs/$JNI_DIR - - go build -buildmode=c-shared {{.BUILD_FLAGS}} \ - -o build/android/app/src/main/jniLibs/$JNI_DIR/libwails.so - vars: - BUILD_FLAGS: '{{if eq .PRODUCTION "true"}}-tags production,android -trimpath -buildvcs=false -ldflags="-w -s"{{else}}-tags android,debug -buildvcs=false -gcflags=all="-l"{{end}}' - - compile:go:all-archs: - summary: Compile Go code for all Android architectures (fat APK) - cmds: - - task: compile:go:shared - vars: - ARCH: arm64 - - task: compile:go:shared - vars: - ARCH: amd64 - - package: - summary: Packages a production build of the application into an APK - deps: - - task: build - vars: - PRODUCTION: "true" - cmds: - - task: assemble:apk - - package:fat: - summary: Packages a production build for all architectures (fat APK) - cmds: - - task: compile:go:all-archs - - task: assemble:apk - - assemble:apk: - summary: Assembles the APK using Gradle - cmds: - - | - cd build/android - ./gradlew assembleDebug - cp app/build/outputs/apk/debug/app-debug.apk ../../{{.BIN_DIR}}/{{.APP_NAME}}.apk - echo "APK created: {{.BIN_DIR}}/{{.APP_NAME}}.apk" - - assemble:apk:release: - summary: Assembles a release APK using Gradle - cmds: - - | - cd build/android - ./gradlew assembleRelease - cp app/build/outputs/apk/release/app-release-unsigned.apk ../../{{.BIN_DIR}}/{{.APP_NAME}}-release.apk - echo "Release APK created: {{.BIN_DIR}}/{{.APP_NAME}}-release.apk" - - generate:android:bindings: - internal: true - summary: Generates bindings for Android - sources: - - "**/*.go" - - go.mod - - go.sum - generates: - - frontend/bindings/**/* - cmds: - - wails3 generate bindings -f '{{.BUILD_FLAGS}}' -clean=true - env: - GOOS: android - CGO_ENABLED: 1 - GOARCH: '{{.ARCH | default "arm64"}}' - - ensure-emulator: - internal: true - summary: Ensure Android Emulator is running - silent: true - cmds: - - | - # Check if an emulator is already running - if adb devices | grep -q "emulator"; then - echo "Emulator already running" - exit 0 - fi - - # Get first available AVD - AVD_NAME=$(emulator -list-avds | head -1) - if [ -z "$AVD_NAME" ]; then - echo "No Android Virtual Devices found." - echo "Create one using: Android Studio > Tools > Device Manager" - exit 1 - fi - - echo "Starting emulator: $AVD_NAME" - emulator -avd "$AVD_NAME" -no-snapshot-load & - - # Wait for emulator to boot (max 60 seconds) - echo "Waiting for emulator to boot..." - adb wait-for-device - - for i in {1..60}; do - BOOT_COMPLETED=$(adb shell getprop sys.boot_completed 2>/dev/null | tr -d '\r') - if [ "$BOOT_COMPLETED" = "1" ]; then - echo "Emulator booted successfully" - exit 0 - fi - sleep 1 - done - - echo "Emulator boot timeout" - exit 1 - preconditions: - - sh: command -v adb - msg: "adb not found. Please install Android SDK and add platform-tools to PATH" - - sh: command -v emulator - msg: "emulator not found. Please install Android SDK and add emulator to PATH" - - deploy-emulator: - summary: Deploy to Android Emulator - deps: [package] - cmds: - - adb uninstall {{.APP_ID}} 2>/dev/null || true - - adb install {{.BIN_DIR}}/{{.APP_NAME}}.apk - - adb shell am start -n {{.APP_ID}}/.MainActivity - - run: - summary: Run the application in Android Emulator - deps: - - task: ensure-emulator - - task: build - vars: - ARCH: x86_64 - cmds: - - task: assemble:apk - - adb uninstall {{.APP_ID}} 2>/dev/null || true - - adb install {{.BIN_DIR}}/{{.APP_NAME}}.apk - - adb shell am start -n {{.APP_ID}}/.MainActivity - - logs: - summary: Stream Android logcat filtered to this app - cmds: - - adb logcat -v time | grep -E "(Wails|{{.APP_NAME}})" - - logs:all: - summary: Stream all Android logcat (verbose) - cmds: - - adb logcat -v time - - clean: - summary: Clean build artifacts - cmds: - - rm -rf {{.BIN_DIR}} - - rm -rf build/android/app/build - - rm -rf build/android/app/src/main/jniLibs/*/libwails.so - - rm -rf build/android/.gradle diff --git a/v3/examples/android/build/android/app/build.gradle b/v3/examples/android/build/android/app/build.gradle deleted file mode 100644 index 78fdbf7d9..000000000 --- a/v3/examples/android/build/android/app/build.gradle +++ /dev/null @@ -1,63 +0,0 @@ -plugins { - id 'com.android.application' -} - -android { - namespace 'com.wails.app' - compileSdk 34 - - buildFeatures { - buildConfig = true - } - - defaultConfig { - applicationId "com.wails.app" - minSdk 21 - targetSdk 34 - versionCode 1 - versionName "1.0" - - // Configure supported ABIs - ndk { - abiFilters 'arm64-v8a', 'x86_64' - } - } - - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro' - } - debug { - debuggable true - } - } - - compileOptions { - sourceCompatibility JavaVersion.VERSION_11 - targetCompatibility JavaVersion.VERSION_11 - } - - // Source sets configuration - sourceSets { - main { - // JNI libraries are in jniLibs folder - jniLibs.srcDirs = ['src/main/jniLibs'] - // Assets for the WebView - assets.srcDirs = ['src/main/assets'] - } - } - - // Packaging options - packagingOptions { - // Don't strip Go symbols in debug builds - doNotStrip '*/arm64-v8a/libwails.so' - doNotStrip '*/x86_64/libwails.so' - } -} - -dependencies { - implementation 'androidx.appcompat:appcompat:1.6.1' - implementation 'androidx.webkit:webkit:1.9.0' - implementation 'com.google.android.material:material:1.11.0' -} diff --git a/v3/examples/android/build/android/app/proguard-rules.pro b/v3/examples/android/build/android/app/proguard-rules.pro deleted file mode 100644 index 8b88c3dfd..000000000 --- a/v3/examples/android/build/android/app/proguard-rules.pro +++ /dev/null @@ -1,12 +0,0 @@ -# Add project specific ProGuard rules here. -# You can control the set of applied configuration files using the -# proguardFiles setting in build.gradle. - -# Keep native methods --keepclasseswithmembernames class * { - native ; -} - -# Keep Wails bridge classes --keep class com.wails.app.WailsBridge { *; } --keep class com.wails.app.WailsJSBridge { *; } diff --git a/v3/examples/android/build/android/app/src/main/AndroidManifest.xml b/v3/examples/android/build/android/app/src/main/AndroidManifest.xml deleted file mode 100644 index 6c7982af1..000000000 --- a/v3/examples/android/build/android/app/src/main/AndroidManifest.xml +++ /dev/null @@ -1,30 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/v3/examples/android/build/android/app/src/main/java/com/wails/app/MainActivity.java b/v3/examples/android/build/android/app/src/main/java/com/wails/app/MainActivity.java deleted file mode 100644 index 3067fee09..000000000 --- a/v3/examples/android/build/android/app/src/main/java/com/wails/app/MainActivity.java +++ /dev/null @@ -1,198 +0,0 @@ -package com.wails.app; - -import android.annotation.SuppressLint; -import android.os.Bundle; -import android.util.Log; -import android.webkit.WebResourceRequest; -import android.webkit.WebResourceResponse; -import android.webkit.WebSettings; -import android.webkit.WebView; -import android.webkit.WebViewClient; - -import androidx.annotation.Nullable; -import androidx.appcompat.app.AppCompatActivity; -import androidx.webkit.WebViewAssetLoader; -import com.wails.app.BuildConfig; - -/** - * MainActivity hosts the WebView and manages the Wails application lifecycle. - * It uses WebViewAssetLoader to serve assets from the Go library without - * requiring a network server. - */ -public class MainActivity extends AppCompatActivity { - private static final String TAG = "WailsActivity"; - private static final String WAILS_SCHEME = "https"; - private static final String WAILS_HOST = "wails.localhost"; - - private WebView webView; - private WailsBridge bridge; - private WebViewAssetLoader assetLoader; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.activity_main); - - // Initialize the native Go library - bridge = new WailsBridge(this); - bridge.initialize(); - - // Set up WebView - setupWebView(); - - // Load the application - loadApplication(); - } - - @SuppressLint("SetJavaScriptEnabled") - private void setupWebView() { - webView = findViewById(R.id.webview); - - // Configure WebView settings - WebSettings settings = webView.getSettings(); - settings.setJavaScriptEnabled(true); - settings.setDomStorageEnabled(true); - settings.setDatabaseEnabled(true); - settings.setAllowFileAccess(false); - settings.setAllowContentAccess(false); - settings.setMediaPlaybackRequiresUserGesture(false); - settings.setMixedContentMode(WebSettings.MIXED_CONTENT_NEVER_ALLOW); - - // Enable debugging in debug builds - if (BuildConfig.DEBUG) { - WebView.setWebContentsDebuggingEnabled(true); - } - - // Set up asset loader for serving local assets - assetLoader = new WebViewAssetLoader.Builder() - .setDomain(WAILS_HOST) - .addPathHandler("/", new WailsPathHandler(bridge)) - .build(); - - // Set up WebView client to intercept requests - webView.setWebViewClient(new WebViewClient() { - @Nullable - @Override - public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) { - String url = request.getUrl().toString(); - Log.d(TAG, "Intercepting request: " + url); - - // Handle wails.localhost requests - if (request.getUrl().getHost() != null && - request.getUrl().getHost().equals(WAILS_HOST)) { - - // For wails API calls (runtime, capabilities, etc.), we need to pass the full URL - // including query string because WebViewAssetLoader.PathHandler strips query params - String path = request.getUrl().getPath(); - if (path != null && path.startsWith("/wails/")) { - // Get full path with query string for runtime calls - String fullPath = path; - String query = request.getUrl().getQuery(); - if (query != null && !query.isEmpty()) { - fullPath = path + "?" + query; - } - Log.d(TAG, "Wails API call detected, full path: " + fullPath); - - // Call bridge directly with full path - byte[] data = bridge.serveAsset(fullPath, request.getMethod(), "{}"); - if (data != null && data.length > 0) { - java.io.InputStream inputStream = new java.io.ByteArrayInputStream(data); - java.util.Map headers = new java.util.HashMap<>(); - headers.put("Access-Control-Allow-Origin", "*"); - headers.put("Cache-Control", "no-cache"); - headers.put("Content-Type", "application/json"); - - return new WebResourceResponse( - "application/json", - "UTF-8", - 200, - "OK", - headers, - inputStream - ); - } - // Return error response if data is null - return new WebResourceResponse( - "application/json", - "UTF-8", - 500, - "Internal Error", - new java.util.HashMap<>(), - new java.io.ByteArrayInputStream("{}".getBytes()) - ); - } - - // For regular assets, use the asset loader - return assetLoader.shouldInterceptRequest(request.getUrl()); - } - - return super.shouldInterceptRequest(view, request); - } - - @Override - public void onPageFinished(WebView view, String url) { - super.onPageFinished(view, url); - Log.d(TAG, "Page loaded: " + url); - // Inject Wails runtime - bridge.injectRuntime(webView, url); - } - }); - - // Add JavaScript interface for Go communication - webView.addJavascriptInterface(new WailsJSBridge(bridge, webView), "wails"); - } - - private void loadApplication() { - // Load the main page from the asset server - String url = WAILS_SCHEME + "://" + WAILS_HOST + "/"; - Log.d(TAG, "Loading URL: " + url); - webView.loadUrl(url); - } - - /** - * Execute JavaScript in the WebView from the Go side - */ - public void executeJavaScript(final String js) { - runOnUiThread(() -> { - if (webView != null) { - webView.evaluateJavascript(js, null); - } - }); - } - - @Override - protected void onResume() { - super.onResume(); - if (bridge != null) { - bridge.onResume(); - } - } - - @Override - protected void onPause() { - super.onPause(); - if (bridge != null) { - bridge.onPause(); - } - } - - @Override - protected void onDestroy() { - super.onDestroy(); - if (bridge != null) { - bridge.shutdown(); - } - if (webView != null) { - webView.destroy(); - } - } - - @Override - public void onBackPressed() { - if (webView != null && webView.canGoBack()) { - webView.goBack(); - } else { - super.onBackPressed(); - } - } -} diff --git a/v3/examples/android/build/android/app/src/main/java/com/wails/app/WailsBridge.java b/v3/examples/android/build/android/app/src/main/java/com/wails/app/WailsBridge.java deleted file mode 100644 index 3dab65247..000000000 --- a/v3/examples/android/build/android/app/src/main/java/com/wails/app/WailsBridge.java +++ /dev/null @@ -1,214 +0,0 @@ -package com.wails.app; - -import android.content.Context; -import android.util.Log; -import android.webkit.WebView; - -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.atomic.AtomicInteger; - -/** - * WailsBridge manages the connection between the Java/Android side and the Go native library. - * It handles: - * - Loading and initializing the native Go library - * - Serving asset requests from Go - * - Passing messages between JavaScript and Go - * - Managing callbacks for async operations - */ -public class WailsBridge { - private static final String TAG = "WailsBridge"; - - static { - // Load the native Go library - System.loadLibrary("wails"); - } - - private final Context context; - private final AtomicInteger callbackIdGenerator = new AtomicInteger(0); - private final ConcurrentHashMap pendingAssetCallbacks = new ConcurrentHashMap<>(); - private final ConcurrentHashMap pendingMessageCallbacks = new ConcurrentHashMap<>(); - private WebView webView; - private volatile boolean initialized = false; - - // Native methods - implemented in Go - private static native void nativeInit(WailsBridge bridge); - private static native void nativeShutdown(); - private static native void nativeOnResume(); - private static native void nativeOnPause(); - private static native void nativeOnPageFinished(String url); - private static native byte[] nativeServeAsset(String path, String method, String headers); - private static native String nativeHandleMessage(String message); - private static native String nativeGetAssetMimeType(String path); - - public WailsBridge(Context context) { - this.context = context; - } - - /** - * Initialize the native Go library - */ - public void initialize() { - if (initialized) { - return; - } - - Log.i(TAG, "Initializing Wails bridge..."); - try { - nativeInit(this); - initialized = true; - Log.i(TAG, "Wails bridge initialized successfully"); - } catch (Exception e) { - Log.e(TAG, "Failed to initialize Wails bridge", e); - } - } - - /** - * Shutdown the native Go library - */ - public void shutdown() { - if (!initialized) { - return; - } - - Log.i(TAG, "Shutting down Wails bridge..."); - try { - nativeShutdown(); - initialized = false; - } catch (Exception e) { - Log.e(TAG, "Error during shutdown", e); - } - } - - /** - * Called when the activity resumes - */ - public void onResume() { - if (initialized) { - nativeOnResume(); - } - } - - /** - * Called when the activity pauses - */ - public void onPause() { - if (initialized) { - nativeOnPause(); - } - } - - /** - * Serve an asset from the Go asset server - * @param path The URL path requested - * @param method The HTTP method - * @param headers The request headers as JSON - * @return The asset data, or null if not found - */ - public byte[] serveAsset(String path, String method, String headers) { - if (!initialized) { - Log.w(TAG, "Bridge not initialized, cannot serve asset: " + path); - return null; - } - - Log.d(TAG, "Serving asset: " + path); - try { - return nativeServeAsset(path, method, headers); - } catch (Exception e) { - Log.e(TAG, "Error serving asset: " + path, e); - return null; - } - } - - /** - * Get the MIME type for an asset - * @param path The asset path - * @return The MIME type string - */ - public String getAssetMimeType(String path) { - if (!initialized) { - return "application/octet-stream"; - } - - try { - String mimeType = nativeGetAssetMimeType(path); - return mimeType != null ? mimeType : "application/octet-stream"; - } catch (Exception e) { - Log.e(TAG, "Error getting MIME type for: " + path, e); - return "application/octet-stream"; - } - } - - /** - * Handle a message from JavaScript - * @param message The message from JavaScript (JSON) - * @return The response to send back to JavaScript (JSON) - */ - public String handleMessage(String message) { - if (!initialized) { - Log.w(TAG, "Bridge not initialized, cannot handle message"); - return "{\"error\":\"Bridge not initialized\"}"; - } - - Log.d(TAG, "Handling message from JS: " + message); - try { - return nativeHandleMessage(message); - } catch (Exception e) { - Log.e(TAG, "Error handling message", e); - return "{\"error\":\"" + e.getMessage() + "\"}"; - } - } - - /** - * Inject the Wails runtime JavaScript into the WebView. - * Called when the page finishes loading. - * @param webView The WebView to inject into - * @param url The URL that finished loading - */ - public void injectRuntime(WebView webView, String url) { - this.webView = webView; - // Notify Go side that page has finished loading so it can inject the runtime - Log.d(TAG, "Page finished loading: " + url + ", notifying Go side"); - if (initialized) { - nativeOnPageFinished(url); - } - } - - /** - * Execute JavaScript in the WebView (called from Go side) - * @param js The JavaScript code to execute - */ - public void executeJavaScript(String js) { - if (webView != null) { - webView.post(() -> webView.evaluateJavascript(js, null)); - } - } - - /** - * Called from Go when an event needs to be emitted to JavaScript - * @param eventName The event name - * @param eventData The event data (JSON) - */ - public void emitEvent(String eventName, String eventData) { - String js = String.format("window.wails && window.wails._emit('%s', %s);", - escapeJsString(eventName), eventData); - executeJavaScript(js); - } - - private String escapeJsString(String str) { - return str.replace("\\", "\\\\") - .replace("'", "\\'") - .replace("\n", "\\n") - .replace("\r", "\\r"); - } - - // Callback interfaces - public interface AssetCallback { - void onAssetReady(byte[] data, String mimeType); - void onAssetError(String error); - } - - public interface MessageCallback { - void onResponse(String response); - void onError(String error); - } -} diff --git a/v3/examples/android/build/android/app/src/main/java/com/wails/app/WailsJSBridge.java b/v3/examples/android/build/android/app/src/main/java/com/wails/app/WailsJSBridge.java deleted file mode 100644 index 98ae5b247..000000000 --- a/v3/examples/android/build/android/app/src/main/java/com/wails/app/WailsJSBridge.java +++ /dev/null @@ -1,142 +0,0 @@ -package com.wails.app; - -import android.util.Log; -import android.webkit.JavascriptInterface; -import android.webkit.WebView; -import com.wails.app.BuildConfig; - -/** - * WailsJSBridge provides the JavaScript interface that allows the web frontend - * to communicate with the Go backend. This is exposed to JavaScript as the - * `window.wails` object. - * - * Similar to iOS's WKScriptMessageHandler but using Android's addJavascriptInterface. - */ -public class WailsJSBridge { - private static final String TAG = "WailsJSBridge"; - - private final WailsBridge bridge; - private final WebView webView; - - public WailsJSBridge(WailsBridge bridge, WebView webView) { - this.bridge = bridge; - this.webView = webView; - } - - /** - * Send a message to Go and return the response synchronously. - * Called from JavaScript: wails.invoke(message) - * - * @param message The message to send (JSON string) - * @return The response from Go (JSON string) - */ - @JavascriptInterface - public String invoke(String message) { - Log.d(TAG, "Invoke called: " + message); - return bridge.handleMessage(message); - } - - /** - * Send a message to Go asynchronously. - * The response will be sent back via a callback. - * Called from JavaScript: wails.invokeAsync(callbackId, message) - * - * @param callbackId The callback ID to use for the response - * @param message The message to send (JSON string) - */ - @JavascriptInterface - public void invokeAsync(final String callbackId, final String message) { - Log.d(TAG, "InvokeAsync called: " + message); - - // Handle in background thread to not block JavaScript - new Thread(() -> { - try { - String response = bridge.handleMessage(message); - sendCallback(callbackId, response, null); - } catch (Exception e) { - Log.e(TAG, "Error in async invoke", e); - sendCallback(callbackId, null, e.getMessage()); - } - }).start(); - } - - /** - * Log a message from JavaScript to Android's logcat - * Called from JavaScript: wails.log(level, message) - * - * @param level The log level (debug, info, warn, error) - * @param message The message to log - */ - @JavascriptInterface - public void log(String level, String message) { - switch (level.toLowerCase()) { - case "debug": - Log.d(TAG + "/JS", message); - break; - case "info": - Log.i(TAG + "/JS", message); - break; - case "warn": - Log.w(TAG + "/JS", message); - break; - case "error": - Log.e(TAG + "/JS", message); - break; - default: - Log.v(TAG + "/JS", message); - break; - } - } - - /** - * Get the platform name - * Called from JavaScript: wails.platform() - * - * @return "android" - */ - @JavascriptInterface - public String platform() { - return "android"; - } - - /** - * Check if we're running in debug mode - * Called from JavaScript: wails.isDebug() - * - * @return true if debug build, false otherwise - */ - @JavascriptInterface - public boolean isDebug() { - return BuildConfig.DEBUG; - } - - /** - * Send a callback response to JavaScript - */ - private void sendCallback(String callbackId, String result, String error) { - final String js; - if (error != null) { - js = String.format( - "window.wails && window.wails._callback('%s', null, '%s');", - escapeJsString(callbackId), - escapeJsString(error) - ); - } else { - js = String.format( - "window.wails && window.wails._callback('%s', %s, null);", - escapeJsString(callbackId), - result != null ? result : "null" - ); - } - - webView.post(() -> webView.evaluateJavascript(js, null)); - } - - private String escapeJsString(String str) { - if (str == null) return ""; - return str.replace("\\", "\\\\") - .replace("'", "\\'") - .replace("\n", "\\n") - .replace("\r", "\\r"); - } -} diff --git a/v3/examples/android/build/android/app/src/main/java/com/wails/app/WailsPathHandler.java b/v3/examples/android/build/android/app/src/main/java/com/wails/app/WailsPathHandler.java deleted file mode 100644 index 326fa9b4d..000000000 --- a/v3/examples/android/build/android/app/src/main/java/com/wails/app/WailsPathHandler.java +++ /dev/null @@ -1,118 +0,0 @@ -package com.wails.app; - -import android.net.Uri; -import android.util.Log; -import android.webkit.WebResourceResponse; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.webkit.WebViewAssetLoader; - -import java.io.ByteArrayInputStream; -import java.io.InputStream; -import java.util.HashMap; -import java.util.Map; - -/** - * WailsPathHandler implements WebViewAssetLoader.PathHandler to serve assets - * from the Go asset server. This allows the WebView to load assets without - * using a network server, similar to iOS's WKURLSchemeHandler. - */ -public class WailsPathHandler implements WebViewAssetLoader.PathHandler { - private static final String TAG = "WailsPathHandler"; - - private final WailsBridge bridge; - - public WailsPathHandler(WailsBridge bridge) { - this.bridge = bridge; - } - - @Nullable - @Override - public WebResourceResponse handle(@NonNull String path) { - Log.d(TAG, "Handling path: " + path); - - // Normalize path - if (path.isEmpty() || path.equals("/")) { - path = "/index.html"; - } - - // Get asset from Go - byte[] data = bridge.serveAsset(path, "GET", "{}"); - - if (data == null || data.length == 0) { - Log.w(TAG, "Asset not found: " + path); - return null; // Return null to let WebView handle 404 - } - - // Determine MIME type - String mimeType = bridge.getAssetMimeType(path); - Log.d(TAG, "Serving " + path + " with type " + mimeType + " (" + data.length + " bytes)"); - - // Create response - InputStream inputStream = new ByteArrayInputStream(data); - Map headers = new HashMap<>(); - headers.put("Access-Control-Allow-Origin", "*"); - headers.put("Cache-Control", "no-cache"); - - return new WebResourceResponse( - mimeType, - "UTF-8", - 200, - "OK", - headers, - inputStream - ); - } - - /** - * Determine MIME type from file extension - */ - private String getMimeType(String path) { - String lowerPath = path.toLowerCase(); - - if (lowerPath.endsWith(".html") || lowerPath.endsWith(".htm")) { - return "text/html"; - } else if (lowerPath.endsWith(".js") || lowerPath.endsWith(".mjs")) { - return "application/javascript"; - } else if (lowerPath.endsWith(".css")) { - return "text/css"; - } else if (lowerPath.endsWith(".json")) { - return "application/json"; - } else if (lowerPath.endsWith(".png")) { - return "image/png"; - } else if (lowerPath.endsWith(".jpg") || lowerPath.endsWith(".jpeg")) { - return "image/jpeg"; - } else if (lowerPath.endsWith(".gif")) { - return "image/gif"; - } else if (lowerPath.endsWith(".svg")) { - return "image/svg+xml"; - } else if (lowerPath.endsWith(".ico")) { - return "image/x-icon"; - } else if (lowerPath.endsWith(".woff")) { - return "font/woff"; - } else if (lowerPath.endsWith(".woff2")) { - return "font/woff2"; - } else if (lowerPath.endsWith(".ttf")) { - return "font/ttf"; - } else if (lowerPath.endsWith(".eot")) { - return "application/vnd.ms-fontobject"; - } else if (lowerPath.endsWith(".xml")) { - return "application/xml"; - } else if (lowerPath.endsWith(".txt")) { - return "text/plain"; - } else if (lowerPath.endsWith(".wasm")) { - return "application/wasm"; - } else if (lowerPath.endsWith(".mp3")) { - return "audio/mpeg"; - } else if (lowerPath.endsWith(".mp4")) { - return "video/mp4"; - } else if (lowerPath.endsWith(".webm")) { - return "video/webm"; - } else if (lowerPath.endsWith(".webp")) { - return "image/webp"; - } - - return "application/octet-stream"; - } -} diff --git a/v3/examples/android/build/android/app/src/main/res/layout/activity_main.xml b/v3/examples/android/build/android/app/src/main/res/layout/activity_main.xml deleted file mode 100644 index f278384c7..000000000 --- a/v3/examples/android/build/android/app/src/main/res/layout/activity_main.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - diff --git a/v3/examples/android/build/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/v3/examples/android/build/android/app/src/main/res/mipmap-hdpi/ic_launcher.png deleted file mode 100644 index 9409abebe..000000000 Binary files a/v3/examples/android/build/android/app/src/main/res/mipmap-hdpi/ic_launcher.png and /dev/null differ diff --git a/v3/examples/android/build/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png b/v3/examples/android/build/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png deleted file mode 100644 index 9409abebe..000000000 Binary files a/v3/examples/android/build/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png and /dev/null differ diff --git a/v3/examples/android/build/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/v3/examples/android/build/android/app/src/main/res/mipmap-mdpi/ic_launcher.png deleted file mode 100644 index 5b6acc048..000000000 Binary files a/v3/examples/android/build/android/app/src/main/res/mipmap-mdpi/ic_launcher.png and /dev/null differ diff --git a/v3/examples/android/build/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png b/v3/examples/android/build/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png deleted file mode 100644 index 5b6acc048..000000000 Binary files a/v3/examples/android/build/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png and /dev/null differ diff --git a/v3/examples/android/build/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/v3/examples/android/build/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png deleted file mode 100644 index 1c2c66452..000000000 Binary files a/v3/examples/android/build/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png and /dev/null differ diff --git a/v3/examples/android/build/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/v3/examples/android/build/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png deleted file mode 100644 index 1c2c66452..000000000 Binary files a/v3/examples/android/build/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png and /dev/null differ diff --git a/v3/examples/android/build/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/v3/examples/android/build/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png deleted file mode 100644 index be557d897..000000000 Binary files a/v3/examples/android/build/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png and /dev/null differ diff --git a/v3/examples/android/build/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/v3/examples/android/build/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png deleted file mode 100644 index be557d897..000000000 Binary files a/v3/examples/android/build/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png and /dev/null differ diff --git a/v3/examples/android/build/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/v3/examples/android/build/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png deleted file mode 100644 index 4507f32a5..000000000 Binary files a/v3/examples/android/build/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png and /dev/null differ diff --git a/v3/examples/android/build/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/v3/examples/android/build/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png deleted file mode 100644 index 4507f32a5..000000000 Binary files a/v3/examples/android/build/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png and /dev/null differ diff --git a/v3/examples/android/build/android/app/src/main/res/values/colors.xml b/v3/examples/android/build/android/app/src/main/res/values/colors.xml deleted file mode 100644 index dd33f3b7d..000000000 --- a/v3/examples/android/build/android/app/src/main/res/values/colors.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - #3574D4 - #2C5FB8 - #1B2636 - #FFFFFFFF - #FF000000 - diff --git a/v3/examples/android/build/android/app/src/main/res/values/strings.xml b/v3/examples/android/build/android/app/src/main/res/values/strings.xml deleted file mode 100644 index 3ed9e4717..000000000 --- a/v3/examples/android/build/android/app/src/main/res/values/strings.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - Wails App - diff --git a/v3/examples/android/build/android/app/src/main/res/values/themes.xml b/v3/examples/android/build/android/app/src/main/res/values/themes.xml deleted file mode 100644 index be8a282b2..000000000 --- a/v3/examples/android/build/android/app/src/main/res/values/themes.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - diff --git a/v3/examples/android/build/android/build.gradle b/v3/examples/android/build/android/build.gradle deleted file mode 100644 index d7fbab39a..000000000 --- a/v3/examples/android/build/android/build.gradle +++ /dev/null @@ -1,4 +0,0 @@ -// Top-level build file where you can add configuration options common to all sub-projects/modules. -plugins { - id 'com.android.application' version '8.7.3' apply false -} diff --git a/v3/examples/android/build/android/build/reports/problems/problems-report.html b/v3/examples/android/build/android/build/reports/problems/problems-report.html deleted file mode 100644 index 2f0196fac..000000000 --- a/v3/examples/android/build/android/build/reports/problems/problems-report.html +++ /dev/null @@ -1,659 +0,0 @@ - - - - - - - - - - - - - Gradle Configuration Cache - - - -
      - -
      - Loading... -
      - - - - - - diff --git a/v3/examples/android/build/android/gradle.properties b/v3/examples/android/build/android/gradle.properties deleted file mode 100644 index b9d4426d5..000000000 --- a/v3/examples/android/build/android/gradle.properties +++ /dev/null @@ -1,26 +0,0 @@ -# Project-wide Gradle settings. -# IDE (e.g. Android Studio) users: -# Gradle settings configured through the IDE *will override* -# any settings specified in this file. - -# For more details on how to configure your build environment visit -# http://www.gradle.org/docs/current/userguide/build_environment.html - -# Specifies the JVM arguments used for the daemon process. -# The setting is particularly useful for tweaking memory settings. -org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8 - -# When configured, Gradle will run in incubating parallel mode. -# This option should only be used with decoupled projects. For more details, visit -# https://developer.android.com/build/optimize-your-build#parallel -# org.gradle.parallel=true - -# AndroidX package structure to make it clearer which packages are bundled with the -# Android operating system, and which are packaged with your app's APK -# https://developer.android.com/topic/libraries/support-library/androidx-rn -android.useAndroidX=true - -# Enables namespacing of each library's R class so that its R class includes only the -# resources declared in the library itself and none from the library's dependencies, -# thereby reducing the size of the R class for that library -android.nonTransitiveRClass=true diff --git a/v3/examples/android/build/android/gradle/wrapper/gradle-wrapper.jar b/v3/examples/android/build/android/gradle/wrapper/gradle-wrapper.jar deleted file mode 100644 index f8e1ee312..000000000 Binary files a/v3/examples/android/build/android/gradle/wrapper/gradle-wrapper.jar and /dev/null differ diff --git a/v3/examples/android/build/android/gradle/wrapper/gradle-wrapper.properties b/v3/examples/android/build/android/gradle/wrapper/gradle-wrapper.properties deleted file mode 100644 index 23449a2b5..000000000 --- a/v3/examples/android/build/android/gradle/wrapper/gradle-wrapper.properties +++ /dev/null @@ -1,7 +0,0 @@ -distributionBase=GRADLE_USER_HOME -distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-9.2.1-bin.zip -networkTimeout=10000 -validateDistributionUrl=true -zipStoreBase=GRADLE_USER_HOME -zipStorePath=wrapper/dists diff --git a/v3/examples/android/build/android/gradlew b/v3/examples/android/build/android/gradlew deleted file mode 100755 index adff685a0..000000000 --- a/v3/examples/android/build/android/gradlew +++ /dev/null @@ -1,248 +0,0 @@ -#!/bin/sh - -# -# Copyright © 2015 the original authors. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -# SPDX-License-Identifier: Apache-2.0 -# - -############################################################################## -# -# Gradle start up script for POSIX generated by Gradle. -# -# Important for running: -# -# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is -# noncompliant, but you have some other compliant shell such as ksh or -# bash, then to run this script, type that shell name before the whole -# command line, like: -# -# ksh Gradle -# -# Busybox and similar reduced shells will NOT work, because this script -# requires all of these POSIX shell features: -# * functions; -# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», -# «${var#prefix}», «${var%suffix}», and «$( cmd )»; -# * compound commands having a testable exit status, especially «case»; -# * various built-in commands including «command», «set», and «ulimit». -# -# Important for patching: -# -# (2) This script targets any POSIX shell, so it avoids extensions provided -# by Bash, Ksh, etc; in particular arrays are avoided. -# -# The "traditional" practice of packing multiple parameters into a -# space-separated string is a well documented source of bugs and security -# problems, so this is (mostly) avoided, by progressively accumulating -# options in "$@", and eventually passing that to Java. -# -# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, -# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; -# see the in-line comments for details. -# -# There are tweaks for specific operating systems such as AIX, CygWin, -# Darwin, MinGW, and NonStop. -# -# (3) This script is generated from the Groovy template -# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt -# within the Gradle project. -# -# You can find Gradle at https://github.com/gradle/gradle/. -# -############################################################################## - -# Attempt to set APP_HOME - -# Resolve links: $0 may be a link -app_path=$0 - -# Need this for daisy-chained symlinks. -while - APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path - [ -h "$app_path" ] -do - ls=$( ls -ld "$app_path" ) - link=${ls#*' -> '} - case $link in #( - /*) app_path=$link ;; #( - *) app_path=$APP_HOME$link ;; - esac -done - -# This is normally unused -# shellcheck disable=SC2034 -APP_BASE_NAME=${0##*/} -# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) -APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit - -# Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD=maximum - -warn () { - echo "$*" -} >&2 - -die () { - echo - echo "$*" - echo - exit 1 -} >&2 - -# OS specific support (must be 'true' or 'false'). -cygwin=false -msys=false -darwin=false -nonstop=false -case "$( uname )" in #( - CYGWIN* ) cygwin=true ;; #( - Darwin* ) darwin=true ;; #( - MSYS* | MINGW* ) msys=true ;; #( - NONSTOP* ) nonstop=true ;; -esac - - - -# Determine the Java command to use to start the JVM. -if [ -n "$JAVA_HOME" ] ; then - if [ -x "$JAVA_HOME/jre/sh/java" ] ; then - # IBM's JDK on AIX uses strange locations for the executables - JAVACMD=$JAVA_HOME/jre/sh/java - else - JAVACMD=$JAVA_HOME/bin/java - fi - if [ ! -x "$JAVACMD" ] ; then - die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." - fi -else - JAVACMD=java - if ! command -v java >/dev/null 2>&1 - then - die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." - fi -fi - -# Increase the maximum file descriptors if we can. -if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then - case $MAX_FD in #( - max*) - # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC2039,SC3045 - MAX_FD=$( ulimit -H -n ) || - warn "Could not query maximum file descriptor limit" - esac - case $MAX_FD in #( - '' | soft) :;; #( - *) - # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC2039,SC3045 - ulimit -n "$MAX_FD" || - warn "Could not set maximum file descriptor limit to $MAX_FD" - esac -fi - -# Collect all arguments for the java command, stacking in reverse order: -# * args from the command line -# * the main class name -# * -classpath -# * -D...appname settings -# * --module-path (only if needed) -# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. - -# For Cygwin or MSYS, switch paths to Windows format before running java -if "$cygwin" || "$msys" ; then - APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) - - JAVACMD=$( cygpath --unix "$JAVACMD" ) - - # Now convert the arguments - kludge to limit ourselves to /bin/sh - for arg do - if - case $arg in #( - -*) false ;; # don't mess with options #( - /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath - [ -e "$t" ] ;; #( - *) false ;; - esac - then - arg=$( cygpath --path --ignore --mixed "$arg" ) - fi - # Roll the args list around exactly as many times as the number of - # args, so each arg winds up back in the position where it started, but - # possibly modified. - # - # NB: a `for` loop captures its iteration list before it begins, so - # changing the positional parameters here affects neither the number of - # iterations, nor the values presented in `arg`. - shift # remove old arg - set -- "$@" "$arg" # push replacement arg - done -fi - - -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' - -# Collect all arguments for the java command: -# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, -# and any embedded shellness will be escaped. -# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be -# treated as '${Hostname}' itself on the command line. - -set -- \ - "-Dorg.gradle.appname=$APP_BASE_NAME" \ - -jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \ - "$@" - -# Stop when "xargs" is not available. -if ! command -v xargs >/dev/null 2>&1 -then - die "xargs is not available" -fi - -# Use "xargs" to parse quoted args. -# -# With -n1 it outputs one arg per line, with the quotes and backslashes removed. -# -# In Bash we could simply go: -# -# readarray ARGS < <( xargs -n1 <<<"$var" ) && -# set -- "${ARGS[@]}" "$@" -# -# but POSIX shell has neither arrays nor command substitution, so instead we -# post-process each arg (as a line of input to sed) to backslash-escape any -# character that might be a shell metacharacter, then use eval to reverse -# that process (while maintaining the separation between arguments), and wrap -# the whole thing up as a single "set" statement. -# -# This will of course break if any of these variables contains a newline or -# an unmatched quote. -# - -eval "set -- $( - printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | - xargs -n1 | - sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | - tr '\n' ' ' - )" '"$@"' - -exec "$JAVACMD" "$@" diff --git a/v3/examples/android/build/android/gradlew.bat b/v3/examples/android/build/android/gradlew.bat deleted file mode 100644 index e509b2dd8..000000000 --- a/v3/examples/android/build/android/gradlew.bat +++ /dev/null @@ -1,93 +0,0 @@ -@rem -@rem Copyright 2015 the original author or authors. -@rem -@rem Licensed under the Apache License, Version 2.0 (the "License"); -@rem you may not use this file except in compliance with the License. -@rem You may obtain a copy of the License at -@rem -@rem https://www.apache.org/licenses/LICENSE-2.0 -@rem -@rem Unless required by applicable law or agreed to in writing, software -@rem distributed under the License is distributed on an "AS IS" BASIS, -@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -@rem See the License for the specific language governing permissions and -@rem limitations under the License. -@rem -@rem SPDX-License-Identifier: Apache-2.0 -@rem - -@if "%DEBUG%"=="" @echo off -@rem ########################################################################## -@rem -@rem Gradle startup script for Windows -@rem -@rem ########################################################################## - -@rem Set local scope for the variables with windows NT shell -if "%OS%"=="Windows_NT" setlocal - -set DIRNAME=%~dp0 -if "%DIRNAME%"=="" set DIRNAME=. -@rem This is normally unused -set APP_BASE_NAME=%~n0 -set APP_HOME=%DIRNAME% - -@rem Resolve any "." and ".." in APP_HOME to make it shorter. -for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi - -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" - -@rem Find java.exe -if defined JAVA_HOME goto findJavaFromJavaHome - -set JAVA_EXE=java.exe -%JAVA_EXE% -version >NUL 2>&1 -if %ERRORLEVEL% equ 0 goto execute - -echo. 1>&2 -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 -echo. 1>&2 -echo Please set the JAVA_HOME variable in your environment to match the 1>&2 -echo location of your Java installation. 1>&2 - -goto fail - -:findJavaFromJavaHome -set JAVA_HOME=%JAVA_HOME:"=% -set JAVA_EXE=%JAVA_HOME%/bin/java.exe - -if exist "%JAVA_EXE%" goto execute - -echo. 1>&2 -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 -echo. 1>&2 -echo Please set the JAVA_HOME variable in your environment to match the 1>&2 -echo location of your Java installation. 1>&2 - -goto fail - -:execute -@rem Setup the command line - - - -@rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* - -:end -@rem End local scope for the variables with windows NT shell -if %ERRORLEVEL% equ 0 goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -set EXIT_CODE=%ERRORLEVEL% -if %EXIT_CODE% equ 0 set EXIT_CODE=1 -if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% -exit /b %EXIT_CODE% - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega diff --git a/v3/examples/android/build/android/scripts/deps/install_deps.go b/v3/examples/android/build/android/scripts/deps/install_deps.go deleted file mode 100644 index d9dfedf80..000000000 --- a/v3/examples/android/build/android/scripts/deps/install_deps.go +++ /dev/null @@ -1,151 +0,0 @@ -package main - -import ( - "fmt" - "os" - "os/exec" - "path/filepath" - "runtime" - "strings" -) - -func main() { - fmt.Println("Checking Android development dependencies...") - fmt.Println() - - errors := []string{} - - // Check Go - if !checkCommand("go", "version") { - errors = append(errors, "Go is not installed. Install from https://go.dev/dl/") - } else { - fmt.Println("✓ Go is installed") - } - - // Check ANDROID_HOME - androidHome := os.Getenv("ANDROID_HOME") - if androidHome == "" { - androidHome = os.Getenv("ANDROID_SDK_ROOT") - } - if androidHome == "" { - // Try common default locations - home, _ := os.UserHomeDir() - possiblePaths := []string{ - filepath.Join(home, "Android", "Sdk"), - filepath.Join(home, "Library", "Android", "sdk"), - "/usr/local/share/android-sdk", - } - for _, p := range possiblePaths { - if _, err := os.Stat(p); err == nil { - androidHome = p - break - } - } - } - - if androidHome == "" { - errors = append(errors, "ANDROID_HOME not set. Install Android Studio and set ANDROID_HOME environment variable") - } else { - fmt.Printf("✓ ANDROID_HOME: %s\n", androidHome) - } - - // Check adb - if !checkCommand("adb", "version") { - if androidHome != "" { - platformTools := filepath.Join(androidHome, "platform-tools") - errors = append(errors, fmt.Sprintf("adb not found. Add %s to PATH", platformTools)) - } else { - errors = append(errors, "adb not found. Install Android SDK Platform-Tools") - } - } else { - fmt.Println("✓ adb is installed") - } - - // Check emulator - if !checkCommand("emulator", "-list-avds") { - if androidHome != "" { - emulatorPath := filepath.Join(androidHome, "emulator") - errors = append(errors, fmt.Sprintf("emulator not found. Add %s to PATH", emulatorPath)) - } else { - errors = append(errors, "emulator not found. Install Android Emulator via SDK Manager") - } - } else { - fmt.Println("✓ Android Emulator is installed") - } - - // Check NDK - ndkHome := os.Getenv("ANDROID_NDK_HOME") - if ndkHome == "" && androidHome != "" { - // Look for NDK in default location - ndkDir := filepath.Join(androidHome, "ndk") - if entries, err := os.ReadDir(ndkDir); err == nil { - for _, entry := range entries { - if entry.IsDir() { - ndkHome = filepath.Join(ndkDir, entry.Name()) - break - } - } - } - } - - if ndkHome == "" { - errors = append(errors, "Android NDK not found. Install NDK via Android Studio > SDK Manager > SDK Tools > NDK (Side by side)") - } else { - fmt.Printf("✓ Android NDK: %s\n", ndkHome) - } - - // Check Java - if !checkCommand("java", "-version") { - errors = append(errors, "Java not found. Install JDK 11+ (OpenJDK recommended)") - } else { - fmt.Println("✓ Java is installed") - } - - // Check for AVD (Android Virtual Device) - if checkCommand("emulator", "-list-avds") { - cmd := exec.Command("emulator", "-list-avds") - output, err := cmd.Output() - if err == nil && len(strings.TrimSpace(string(output))) > 0 { - avds := strings.Split(strings.TrimSpace(string(output)), "\n") - fmt.Printf("✓ Found %d Android Virtual Device(s)\n", len(avds)) - } else { - fmt.Println("⚠ No Android Virtual Devices found. Create one via Android Studio > Tools > Device Manager") - } - } - - fmt.Println() - - if len(errors) > 0 { - fmt.Println("❌ Missing dependencies:") - for _, err := range errors { - fmt.Printf(" - %s\n", err) - } - fmt.Println() - fmt.Println("Setup instructions:") - fmt.Println("1. Install Android Studio: https://developer.android.com/studio") - fmt.Println("2. Open SDK Manager and install:") - fmt.Println(" - Android SDK Platform (API 34)") - fmt.Println(" - Android SDK Build-Tools") - fmt.Println(" - Android SDK Platform-Tools") - fmt.Println(" - Android Emulator") - fmt.Println(" - NDK (Side by side)") - fmt.Println("3. Set environment variables:") - if runtime.GOOS == "darwin" { - fmt.Println(" export ANDROID_HOME=$HOME/Library/Android/sdk") - } else { - fmt.Println(" export ANDROID_HOME=$HOME/Android/Sdk") - } - fmt.Println(" export PATH=$PATH:$ANDROID_HOME/platform-tools:$ANDROID_HOME/emulator") - fmt.Println("4. Create an AVD via Android Studio > Tools > Device Manager") - os.Exit(1) - } - - fmt.Println("✓ All Android development dependencies are installed!") -} - -func checkCommand(name string, args ...string) bool { - cmd := exec.Command(name, args...) - cmd.Stdout = nil - cmd.Stderr = nil - return cmd.Run() == nil -} diff --git a/v3/examples/android/build/android/settings.gradle b/v3/examples/android/build/android/settings.gradle deleted file mode 100644 index a3f3ec3d4..000000000 --- a/v3/examples/android/build/android/settings.gradle +++ /dev/null @@ -1,18 +0,0 @@ -pluginManagement { - repositories { - google() - mavenCentral() - gradlePluginPortal() - } -} - -dependencyResolutionManagement { - repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) - repositories { - google() - mavenCentral() - } -} - -rootProject.name = "WailsApp" -include ':app' diff --git a/v3/examples/android/build/config.yml b/v3/examples/android/build/config.yml deleted file mode 100644 index c8adba60d..000000000 --- a/v3/examples/android/build/config.yml +++ /dev/null @@ -1,75 +0,0 @@ -# This file contains the configuration for this project. -# When you update `info` or `fileAssociations`, run `wails3 task common:update:build-assets` to update the assets. -# Note that this will overwrite any changes you have made to the assets. -version: '3' - -# This information is used to generate the build assets. -info: - companyName: "My Company" # The name of the company - productName: "My Product" # The name of the application - productIdentifier: "com.mycompany.myproduct" # The unique product identifier - description: "A program that does X" # The application description - copyright: "(c) 2025, My Company" # Copyright text - comments: "Some Product Comments" # Comments - version: "0.0.1" # The application version - -# Android build configuration (uncomment to customise Android project generation) -# Note: Keys under `android` OVERRIDE values under `info` when set. -# android: -# # The Android application ID used in the generated project (applicationId) -# applicationId: "com.mycompany.myproduct" -# # The display name shown under the app icon -# displayName: "My Product" -# # The app version code (integer, must increment for each release) -# versionCode: 1 -# # The app version name (displayed to users) -# versionName: "0.0.1" -# # Minimum SDK version (API level) -# minSdkVersion: 21 -# # Target SDK version (API level) -# targetSdkVersion: 34 -# # The company/organisation name for templates and project settings -# company: "My Company" - -# Dev mode configuration -dev_mode: - root_path: . - log_level: warn - debounce: 1000 - ignore: - dir: - - .git - - node_modules - - frontend - - bin - file: - - .DS_Store - - .gitignore - - .gitkeep - watched_extension: - - "*.go" - git_ignore: true - executes: - - cmd: wails3 task common:install:frontend:deps - type: once - - cmd: wails3 task common:dev:frontend - type: background - - cmd: go mod tidy - type: blocking - - cmd: wails3 task build - type: blocking - - cmd: wails3 task run - type: primary - -# File Associations -# More information at: https://v3.wails.io/noit/done/yet -fileAssociations: -# - ext: wails -# name: Wails -# description: Wails Application File -# iconName: wailsFileIcon -# role: Editor - -# Other data -other: - - name: My Other Data diff --git a/v3/examples/android/build/darwin/Info.dev.plist b/v3/examples/android/build/darwin/Info.dev.plist deleted file mode 100644 index bd6a537fa..000000000 --- a/v3/examples/android/build/darwin/Info.dev.plist +++ /dev/null @@ -1,32 +0,0 @@ - - - - CFBundlePackageType - APPL - CFBundleName - My Product - CFBundleExecutable - ios - CFBundleIdentifier - com.wails.ios - CFBundleVersion - 0.1.0 - CFBundleGetInfoString - This is a comment - CFBundleShortVersionString - 0.1.0 - CFBundleIconFile - icons - LSMinimumSystemVersion - 10.15.0 - NSHighResolutionCapable - true - NSHumanReadableCopyright - © now, My Company - NSAppTransportSecurity - - NSAllowsLocalNetworking - - - - \ No newline at end of file diff --git a/v3/examples/android/build/darwin/Info.plist b/v3/examples/android/build/darwin/Info.plist deleted file mode 100644 index fb52df715..000000000 --- a/v3/examples/android/build/darwin/Info.plist +++ /dev/null @@ -1,27 +0,0 @@ - - - - CFBundlePackageType - APPL - CFBundleName - My Product - CFBundleExecutable - ios - CFBundleIdentifier - com.wails.ios - CFBundleVersion - 0.1.0 - CFBundleGetInfoString - This is a comment - CFBundleShortVersionString - 0.1.0 - CFBundleIconFile - icons - LSMinimumSystemVersion - 10.15.0 - NSHighResolutionCapable - true - NSHumanReadableCopyright - © now, My Company - - \ No newline at end of file diff --git a/v3/examples/android/build/darwin/Taskfile.yml b/v3/examples/android/build/darwin/Taskfile.yml deleted file mode 100644 index f0791fea9..000000000 --- a/v3/examples/android/build/darwin/Taskfile.yml +++ /dev/null @@ -1,81 +0,0 @@ -version: '3' - -includes: - common: ../Taskfile.yml - -tasks: - build: - summary: Creates a production build of the application - deps: - - task: common:go:mod:tidy - - task: common:build:frontend - vars: - BUILD_FLAGS: - ref: .BUILD_FLAGS - PRODUCTION: - ref: .PRODUCTION - - task: common:generate:icons - cmds: - - go build {{.BUILD_FLAGS}} -o {{.OUTPUT}} - vars: - BUILD_FLAGS: '{{if eq .PRODUCTION "true"}}-tags production -trimpath -buildvcs=false -ldflags="-w -s"{{else}}-buildvcs=false -gcflags=all="-l"{{end}}' - DEFAULT_OUTPUT: '{{.BIN_DIR}}/{{.APP_NAME}}' - OUTPUT: '{{ .OUTPUT | default .DEFAULT_OUTPUT }}' - env: - GOOS: darwin - CGO_ENABLED: 1 - GOARCH: '{{.ARCH | default ARCH}}' - CGO_CFLAGS: "-mmacosx-version-min=10.15" - CGO_LDFLAGS: "-mmacosx-version-min=10.15" - MACOSX_DEPLOYMENT_TARGET: "10.15" - PRODUCTION: '{{.PRODUCTION | default "false"}}' - - build:universal: - summary: Builds darwin universal binary (arm64 + amd64) - deps: - - task: build - vars: - ARCH: amd64 - OUTPUT: "{{.BIN_DIR}}/{{.APP_NAME}}-amd64" - - task: build - vars: - ARCH: arm64 - OUTPUT: "{{.BIN_DIR}}/{{.APP_NAME}}-arm64" - cmds: - - lipo -create -output "{{.BIN_DIR}}/{{.APP_NAME}}" "{{.BIN_DIR}}/{{.APP_NAME}}-amd64" "{{.BIN_DIR}}/{{.APP_NAME}}-arm64" - - rm "{{.BIN_DIR}}/{{.APP_NAME}}-amd64" "{{.BIN_DIR}}/{{.APP_NAME}}-arm64" - - package: - summary: Packages a production build of the application into a `.app` bundle - deps: - - task: build - vars: - PRODUCTION: "true" - cmds: - - task: create:app:bundle - - package:universal: - summary: Packages darwin universal binary (arm64 + amd64) - deps: - - task: build:universal - cmds: - - task: create:app:bundle - - - create:app:bundle: - summary: Creates an `.app` bundle - cmds: - - mkdir -p {{.BIN_DIR}}/{{.APP_NAME}}.app/Contents/{MacOS,Resources} - - cp build/darwin/icons.icns {{.BIN_DIR}}/{{.APP_NAME}}.app/Contents/Resources - - cp {{.BIN_DIR}}/{{.APP_NAME}} {{.BIN_DIR}}/{{.APP_NAME}}.app/Contents/MacOS - - cp build/darwin/Info.plist {{.BIN_DIR}}/{{.APP_NAME}}.app/Contents - - codesign --force --deep --sign - {{.BIN_DIR}}/{{.APP_NAME}}.app - - run: - cmds: - - mkdir -p {{.BIN_DIR}}/{{.APP_NAME}}.dev.app/Contents/{MacOS,Resources} - - cp build/darwin/icons.icns {{.BIN_DIR}}/{{.APP_NAME}}.dev.app/Contents/Resources - - cp {{.BIN_DIR}}/{{.APP_NAME}} {{.BIN_DIR}}/{{.APP_NAME}}.dev.app/Contents/MacOS - - cp build/darwin/Info.dev.plist {{.BIN_DIR}}/{{.APP_NAME}}.dev.app/Contents/Info.plist - - codesign --force --deep --sign - {{.BIN_DIR}}/{{.APP_NAME}}.dev.app - - '{{.BIN_DIR}}/{{.APP_NAME}}.dev.app/Contents/MacOS/{{.APP_NAME}}' diff --git a/v3/examples/android/build/darwin/icons.icns b/v3/examples/android/build/darwin/icons.icns deleted file mode 100644 index 1b5bd4c86..000000000 Binary files a/v3/examples/android/build/darwin/icons.icns and /dev/null differ diff --git a/v3/examples/android/build/linux/Taskfile.yml b/v3/examples/android/build/linux/Taskfile.yml deleted file mode 100644 index 87fd599cc..000000000 --- a/v3/examples/android/build/linux/Taskfile.yml +++ /dev/null @@ -1,119 +0,0 @@ -version: '3' - -includes: - common: ../Taskfile.yml - -tasks: - build: - summary: Builds the application for Linux - deps: - - task: common:go:mod:tidy - - task: common:build:frontend - vars: - BUILD_FLAGS: - ref: .BUILD_FLAGS - PRODUCTION: - ref: .PRODUCTION - - task: common:generate:icons - cmds: - - go build {{.BUILD_FLAGS}} -o {{.BIN_DIR}}/{{.APP_NAME}} - vars: - BUILD_FLAGS: '{{if eq .PRODUCTION "true"}}-tags production -trimpath -buildvcs=false -ldflags="-w -s"{{else}}-buildvcs=false -gcflags=all="-l"{{end}}' - env: - GOOS: linux - CGO_ENABLED: 1 - GOARCH: '{{.ARCH | default ARCH}}' - PRODUCTION: '{{.PRODUCTION | default "false"}}' - - package: - summary: Packages a production build of the application for Linux - deps: - - task: build - vars: - PRODUCTION: "true" - cmds: - - task: create:appimage - - task: create:deb - - task: create:rpm - - task: create:aur - - create:appimage: - summary: Creates an AppImage - dir: build/linux/appimage - deps: - - task: build - vars: - PRODUCTION: "true" - - task: generate:dotdesktop - cmds: - - cp {{.APP_BINARY}} {{.APP_NAME}} - - cp ../../appicon.png appicon.png - - wails3 generate appimage -binary {{.APP_NAME}} -icon {{.ICON}} -desktopfile {{.DESKTOP_FILE}} -outputdir {{.OUTPUT_DIR}} -builddir {{.ROOT_DIR}}/build/linux/appimage/build - vars: - APP_NAME: '{{.APP_NAME}}' - APP_BINARY: '../../../bin/{{.APP_NAME}}' - ICON: '../../appicon.png' - DESKTOP_FILE: '../{{.APP_NAME}}.desktop' - OUTPUT_DIR: '../../../bin' - - create:deb: - summary: Creates a deb package - deps: - - task: build - vars: - PRODUCTION: "true" - cmds: - - task: generate:dotdesktop - - task: generate:deb - - create:rpm: - summary: Creates a rpm package - deps: - - task: build - vars: - PRODUCTION: "true" - cmds: - - task: generate:dotdesktop - - task: generate:rpm - - create:aur: - summary: Creates a arch linux packager package - deps: - - task: build - vars: - PRODUCTION: "true" - cmds: - - task: generate:dotdesktop - - task: generate:aur - - generate:deb: - summary: Creates a deb package - cmds: - - wails3 tool package -name {{.APP_NAME}} -format deb -config ./build/linux/nfpm/nfpm.yaml -out {{.ROOT_DIR}}/bin - - generate:rpm: - summary: Creates a rpm package - cmds: - - wails3 tool package -name {{.APP_NAME}} -format rpm -config ./build/linux/nfpm/nfpm.yaml -out {{.ROOT_DIR}}/bin - - generate:aur: - summary: Creates a arch linux packager package - cmds: - - wails3 tool package -name {{.APP_NAME}} -format archlinux -config ./build/linux/nfpm/nfpm.yaml -out {{.ROOT_DIR}}/bin - - generate:dotdesktop: - summary: Generates a `.desktop` file - dir: build - cmds: - - mkdir -p {{.ROOT_DIR}}/build/linux/appimage - - wails3 generate .desktop -name "{{.APP_NAME}}" -exec "{{.EXEC}}" -icon "{{.ICON}}" -outputfile {{.ROOT_DIR}}/build/linux/{{.APP_NAME}}.desktop -categories "{{.CATEGORIES}}" - vars: - APP_NAME: '{{.APP_NAME}}' - EXEC: '{{.APP_NAME}}' - ICON: '{{.APP_NAME}}' - CATEGORIES: 'Development;' - OUTPUTFILE: '{{.ROOT_DIR}}/build/linux/{{.APP_NAME}}.desktop' - - run: - cmds: - - '{{.BIN_DIR}}/{{.APP_NAME}}' diff --git a/v3/examples/android/build/linux/appimage/build.sh b/v3/examples/android/build/linux/appimage/build.sh deleted file mode 100644 index 858f091ab..000000000 --- a/v3/examples/android/build/linux/appimage/build.sh +++ /dev/null @@ -1,34 +0,0 @@ -#!/usr/bin/env bash -# Copyright (c) 2018-Present Lea Anthony -# SPDX-License-Identifier: MIT - -# Fail script on any error -set -euxo pipefail - -# Define variables -APP_DIR="${APP_NAME}.AppDir" - -# Create AppDir structure -mkdir -p "${APP_DIR}/usr/bin" -cp -r "${APP_BINARY}" "${APP_DIR}/usr/bin/" -cp "${ICON_PATH}" "${APP_DIR}/" -cp "${DESKTOP_FILE}" "${APP_DIR}/" - -if [[ $(uname -m) == *x86_64* ]]; then - # Download linuxdeploy and make it executable - wget -q -4 -N https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-x86_64.AppImage - chmod +x linuxdeploy-x86_64.AppImage - - # Run linuxdeploy to bundle the application - ./linuxdeploy-x86_64.AppImage --appdir "${APP_DIR}" --output appimage -else - # Download linuxdeploy and make it executable (arm64) - wget -q -4 -N https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-aarch64.AppImage - chmod +x linuxdeploy-aarch64.AppImage - - # Run linuxdeploy to bundle the application (arm64) - ./linuxdeploy-aarch64.AppImage --appdir "${APP_DIR}" --output appimage -fi - -# Rename the generated AppImage -mv "${APP_NAME}*.AppImage" "${APP_NAME}.AppImage" diff --git a/v3/examples/android/build/linux/desktop b/v3/examples/android/build/linux/desktop deleted file mode 100644 index e9b30cf39..000000000 --- a/v3/examples/android/build/linux/desktop +++ /dev/null @@ -1,11 +0,0 @@ -[Desktop Entry] -Version=1.0 -Name=My Product -Comment=My Product Description -# The Exec line includes %u to pass the URL to the application -Exec=/usr/local/bin/ios %u -Terminal=false -Type=Application -Icon=ios -Categories=Utility; -StartupWMClass=ios diff --git a/v3/examples/android/build/linux/nfpm/nfpm.yaml b/v3/examples/android/build/linux/nfpm/nfpm.yaml deleted file mode 100644 index 7b78433f4..000000000 --- a/v3/examples/android/build/linux/nfpm/nfpm.yaml +++ /dev/null @@ -1,67 +0,0 @@ -# Feel free to remove those if you don't want/need to use them. -# Make sure to check the documentation at https://nfpm.goreleaser.com -# -# The lines below are called `modelines`. See `:help modeline` - -name: "ios" -arch: ${GOARCH} -platform: "linux" -version: "0.1.0" -section: "default" -priority: "extra" -maintainer: ${GIT_COMMITTER_NAME} <${GIT_COMMITTER_EMAIL}> -description: "My Product Description" -vendor: "My Company" -homepage: "https://wails.io" -license: "MIT" -release: "1" - -contents: - - src: "./bin/ios" - dst: "/usr/local/bin/ios" - - src: "./build/appicon.png" - dst: "/usr/share/icons/hicolor/128x128/apps/ios.png" - - src: "./build/linux/ios.desktop" - dst: "/usr/share/applications/ios.desktop" - -# Default dependencies for Debian 12/Ubuntu 22.04+ with WebKit 4.1 -depends: - - libgtk-3-0 - - libwebkit2gtk-4.1-0 - -# Distribution-specific overrides for different package formats and WebKit versions -overrides: - # RPM packages for RHEL/CentOS/AlmaLinux/Rocky Linux (WebKit 4.0) - rpm: - depends: - - gtk3 - - webkit2gtk4.1 - - # Arch Linux packages (WebKit 4.1) - archlinux: - depends: - - gtk3 - - webkit2gtk-4.1 - -# scripts section to ensure desktop database is updated after install -scripts: - postinstall: "./build/linux/nfpm/scripts/postinstall.sh" - # You can also add preremove, postremove if needed - # preremove: "./build/linux/nfpm/scripts/preremove.sh" - # postremove: "./build/linux/nfpm/scripts/postremove.sh" - -# replaces: -# - foobar -# provides: -# - bar -# depends: -# - gtk3 -# - libwebkit2gtk -# recommends: -# - whatever -# suggests: -# - something-else -# conflicts: -# - not-foo -# - not-bar -# changelog: "changelog.yaml" diff --git a/v3/examples/android/build/linux/nfpm/scripts/postinstall.sh b/v3/examples/android/build/linux/nfpm/scripts/postinstall.sh deleted file mode 100644 index 4bbb815a3..000000000 --- a/v3/examples/android/build/linux/nfpm/scripts/postinstall.sh +++ /dev/null @@ -1,21 +0,0 @@ -#!/bin/sh - -# Update desktop database for .desktop file changes -# This makes the application appear in application menus and registers its capabilities. -if command -v update-desktop-database >/dev/null 2>&1; then - echo "Updating desktop database..." - update-desktop-database -q /usr/share/applications -else - echo "Warning: update-desktop-database command not found. Desktop file may not be immediately recognized." >&2 -fi - -# Update MIME database for custom URL schemes (x-scheme-handler) -# This ensures the system knows how to handle your custom protocols. -if command -v update-mime-database >/dev/null 2>&1; then - echo "Updating MIME database..." - update-mime-database -n /usr/share/mime -else - echo "Warning: update-mime-database command not found. Custom URL schemes may not be immediately recognized." >&2 -fi - -exit 0 diff --git a/v3/examples/android/build/linux/nfpm/scripts/postremove.sh b/v3/examples/android/build/linux/nfpm/scripts/postremove.sh deleted file mode 100644 index a9bf588e2..000000000 --- a/v3/examples/android/build/linux/nfpm/scripts/postremove.sh +++ /dev/null @@ -1 +0,0 @@ -#!/bin/bash diff --git a/v3/examples/android/build/linux/nfpm/scripts/preinstall.sh b/v3/examples/android/build/linux/nfpm/scripts/preinstall.sh deleted file mode 100644 index a9bf588e2..000000000 --- a/v3/examples/android/build/linux/nfpm/scripts/preinstall.sh +++ /dev/null @@ -1 +0,0 @@ -#!/bin/bash diff --git a/v3/examples/android/build/linux/nfpm/scripts/preremove.sh b/v3/examples/android/build/linux/nfpm/scripts/preremove.sh deleted file mode 100644 index a9bf588e2..000000000 --- a/v3/examples/android/build/linux/nfpm/scripts/preremove.sh +++ /dev/null @@ -1 +0,0 @@ -#!/bin/bash diff --git a/v3/examples/android/build/windows/Taskfile.yml b/v3/examples/android/build/windows/Taskfile.yml deleted file mode 100644 index 19f137616..000000000 --- a/v3/examples/android/build/windows/Taskfile.yml +++ /dev/null @@ -1,98 +0,0 @@ -version: '3' - -includes: - common: ../Taskfile.yml - -tasks: - build: - summary: Builds the application for Windows - deps: - - task: common:go:mod:tidy - - task: common:build:frontend - vars: - BUILD_FLAGS: - ref: .BUILD_FLAGS - PRODUCTION: - ref: .PRODUCTION - - task: common:generate:icons - cmds: - - task: generate:syso - - go build {{.BUILD_FLAGS}} -o {{.BIN_DIR}}/{{.APP_NAME}}.exe - - cmd: powershell Remove-item *.syso - platforms: [windows] - - cmd: rm -f *.syso - platforms: [linux, darwin] - vars: - BUILD_FLAGS: '{{if eq .PRODUCTION "true"}}-tags production -trimpath -buildvcs=false -ldflags="-w -s -H windowsgui"{{else}}-buildvcs=false -gcflags=all="-l"{{end}}' - env: - GOOS: windows - CGO_ENABLED: 0 - GOARCH: '{{.ARCH | default ARCH}}' - PRODUCTION: '{{.PRODUCTION | default "false"}}' - - package: - summary: Packages a production build of the application - cmds: - - |- - if [ "{{.FORMAT | default "nsis"}}" = "msix" ]; then - task: create:msix:package - else - task: create:nsis:installer - fi - vars: - FORMAT: '{{.FORMAT | default "nsis"}}' - - generate:syso: - summary: Generates Windows `.syso` file - dir: build - cmds: - - wails3 generate syso -arch {{.ARCH}} -icon windows/icon.ico -manifest windows/wails.exe.manifest -info windows/info.json -out ../wails_windows_{{.ARCH}}.syso - vars: - ARCH: '{{.ARCH | default ARCH}}' - - create:nsis:installer: - summary: Creates an NSIS installer - dir: build/windows/nsis - deps: - - task: build - vars: - PRODUCTION: "true" - cmds: - # Create the Microsoft WebView2 bootstrapper if it doesn't exist - - wails3 generate webview2bootstrapper -dir "{{.ROOT_DIR}}/build/windows/nsis" - - makensis -DARG_WAILS_{{.ARG_FLAG}}_BINARY="{{.ROOT_DIR}}/{{.BIN_DIR}}/{{.APP_NAME}}.exe" project.nsi - vars: - ARCH: '{{.ARCH | default ARCH}}' - ARG_FLAG: '{{if eq .ARCH "amd64"}}AMD64{{else}}ARM64{{end}}' - - create:msix:package: - summary: Creates an MSIX package - deps: - - task: build - vars: - PRODUCTION: "true" - cmds: - - |- - wails3 tool msix \ - --config "{{.ROOT_DIR}}/wails.json" \ - --name "{{.APP_NAME}}" \ - --executable "{{.ROOT_DIR}}/{{.BIN_DIR}}/{{.APP_NAME}}.exe" \ - --arch "{{.ARCH}}" \ - --out "{{.ROOT_DIR}}/{{.BIN_DIR}}/{{.APP_NAME}}-{{.ARCH}}.msix" \ - {{if .CERT_PATH}}--cert "{{.CERT_PATH}}"{{end}} \ - {{if .PUBLISHER}}--publisher "{{.PUBLISHER}}"{{end}} \ - {{if .USE_MSIX_TOOL}}--use-msix-tool{{else}}--use-makeappx{{end}} - vars: - ARCH: '{{.ARCH | default ARCH}}' - CERT_PATH: '{{.CERT_PATH | default ""}}' - PUBLISHER: '{{.PUBLISHER | default ""}}' - USE_MSIX_TOOL: '{{.USE_MSIX_TOOL | default "false"}}' - - install:msix:tools: - summary: Installs tools required for MSIX packaging - cmds: - - wails3 tool msix-install-tools - - run: - cmds: - - '{{.BIN_DIR}}/{{.APP_NAME}}.exe' diff --git a/v3/examples/android/build/windows/icon.ico b/v3/examples/android/build/windows/icon.ico deleted file mode 100644 index bfa0690b7..000000000 Binary files a/v3/examples/android/build/windows/icon.ico and /dev/null differ diff --git a/v3/examples/android/build/windows/info.json b/v3/examples/android/build/windows/info.json deleted file mode 100644 index 850b2b5b0..000000000 --- a/v3/examples/android/build/windows/info.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "fixed": { - "file_version": "0.1.0" - }, - "info": { - "0000": { - "ProductVersion": "0.1.0", - "CompanyName": "My Company", - "FileDescription": "My Product Description", - "LegalCopyright": "© now, My Company", - "ProductName": "My Product", - "Comments": "This is a comment" - } - } -} \ No newline at end of file diff --git a/v3/examples/android/build/windows/msix/app_manifest.xml b/v3/examples/android/build/windows/msix/app_manifest.xml deleted file mode 100644 index ecf2506b3..000000000 --- a/v3/examples/android/build/windows/msix/app_manifest.xml +++ /dev/null @@ -1,52 +0,0 @@ - - - - - - - My Product - My Company - My Product Description - Assets\StoreLogo.png - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/v3/examples/android/build/windows/msix/template.xml b/v3/examples/android/build/windows/msix/template.xml deleted file mode 100644 index cab2f31e0..000000000 --- a/v3/examples/android/build/windows/msix/template.xml +++ /dev/null @@ -1,54 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - false - My Product - My Company - My Product Description - Assets\AppIcon.png - - - - - - - diff --git a/v3/examples/android/build/windows/nsis/project.nsi b/v3/examples/android/build/windows/nsis/project.nsi deleted file mode 100644 index 74b8d6ad0..000000000 --- a/v3/examples/android/build/windows/nsis/project.nsi +++ /dev/null @@ -1,112 +0,0 @@ -Unicode true - -#### -## Please note: Template replacements don't work in this file. They are provided with default defines like -## mentioned underneath. -## If the keyword is not defined, "wails_tools.nsh" will populate them. -## If they are defined here, "wails_tools.nsh" will not touch them. This allows you to use this project.nsi manually -## from outside of Wails for debugging and development of the installer. -## -## For development first make a wails nsis build to populate the "wails_tools.nsh": -## > wails build --target windows/amd64 --nsis -## Then you can call makensis on this file with specifying the path to your binary: -## For a AMD64 only installer: -## > makensis -DARG_WAILS_AMD64_BINARY=..\..\bin\app.exe -## For a ARM64 only installer: -## > makensis -DARG_WAILS_ARM64_BINARY=..\..\bin\app.exe -## For a installer with both architectures: -## > makensis -DARG_WAILS_AMD64_BINARY=..\..\bin\app-amd64.exe -DARG_WAILS_ARM64_BINARY=..\..\bin\app-arm64.exe -#### -## The following information is taken from the wails_tools.nsh file, but they can be overwritten here. -#### -## !define INFO_PROJECTNAME "my-project" # Default "ios" -## !define INFO_COMPANYNAME "My Company" # Default "My Company" -## !define INFO_PRODUCTNAME "My Product Name" # Default "My Product" -## !define INFO_PRODUCTVERSION "1.0.0" # Default "0.1.0" -## !define INFO_COPYRIGHT "(c) Now, My Company" # Default "© now, My Company" -### -## !define PRODUCT_EXECUTABLE "Application.exe" # Default "${INFO_PROJECTNAME}.exe" -## !define UNINST_KEY_NAME "UninstKeyInRegistry" # Default "${INFO_COMPANYNAME}${INFO_PRODUCTNAME}" -#### -## !define REQUEST_EXECUTION_LEVEL "admin" # Default "admin" see also https://nsis.sourceforge.io/Docs/Chapter4.html -#### -## Include the wails tools -#### -!include "wails_tools.nsh" - -# The version information for this two must consist of 4 parts -VIProductVersion "${INFO_PRODUCTVERSION}.0" -VIFileVersion "${INFO_PRODUCTVERSION}.0" - -VIAddVersionKey "CompanyName" "${INFO_COMPANYNAME}" -VIAddVersionKey "FileDescription" "${INFO_PRODUCTNAME} Installer" -VIAddVersionKey "ProductVersion" "${INFO_PRODUCTVERSION}" -VIAddVersionKey "FileVersion" "${INFO_PRODUCTVERSION}" -VIAddVersionKey "LegalCopyright" "${INFO_COPYRIGHT}" -VIAddVersionKey "ProductName" "${INFO_PRODUCTNAME}" - -# Enable HiDPI support. https://nsis.sourceforge.io/Reference/ManifestDPIAware -ManifestDPIAware true - -!include "MUI.nsh" - -!define MUI_ICON "..\icon.ico" -!define MUI_UNICON "..\icon.ico" -# !define MUI_WELCOMEFINISHPAGE_BITMAP "resources\leftimage.bmp" #Include this to add a bitmap on the left side of the Welcome Page. Must be a size of 164x314 -!define MUI_FINISHPAGE_NOAUTOCLOSE # Wait on the INSTFILES page so the user can take a look into the details of the installation steps -!define MUI_ABORTWARNING # This will warn the user if they exit from the installer. - -!insertmacro MUI_PAGE_WELCOME # Welcome to the installer page. -# !insertmacro MUI_PAGE_LICENSE "resources\eula.txt" # Adds a EULA page to the installer -!insertmacro MUI_PAGE_DIRECTORY # In which folder install page. -!insertmacro MUI_PAGE_INSTFILES # Installing page. -!insertmacro MUI_PAGE_FINISH # Finished installation page. - -!insertmacro MUI_UNPAGE_INSTFILES # Uninstalling page - -!insertmacro MUI_LANGUAGE "English" # Set the Language of the installer - -## The following two statements can be used to sign the installer and the uninstaller. The path to the binaries are provided in %1 -#!uninstfinalize 'signtool --file "%1"' -#!finalize 'signtool --file "%1"' - -Name "${INFO_PRODUCTNAME}" -OutFile "..\..\..\bin\${INFO_PROJECTNAME}-${ARCH}-installer.exe" # Name of the installer's file. -InstallDir "$PROGRAMFILES64\${INFO_COMPANYNAME}\${INFO_PRODUCTNAME}" # Default installing folder ($PROGRAMFILES is Program Files folder). -ShowInstDetails show # This will always show the installation details. - -Function .onInit - !insertmacro wails.checkArchitecture -FunctionEnd - -Section - !insertmacro wails.setShellContext - - !insertmacro wails.webview2runtime - - SetOutPath $INSTDIR - - !insertmacro wails.files - - CreateShortcut "$SMPROGRAMS\${INFO_PRODUCTNAME}.lnk" "$INSTDIR\${PRODUCT_EXECUTABLE}" - CreateShortCut "$DESKTOP\${INFO_PRODUCTNAME}.lnk" "$INSTDIR\${PRODUCT_EXECUTABLE}" - - !insertmacro wails.associateFiles - - !insertmacro wails.writeUninstaller -SectionEnd - -Section "uninstall" - !insertmacro wails.setShellContext - - RMDir /r "$AppData\${PRODUCT_EXECUTABLE}" # Remove the WebView2 DataPath - - RMDir /r $INSTDIR - - Delete "$SMPROGRAMS\${INFO_PRODUCTNAME}.lnk" - Delete "$DESKTOP\${INFO_PRODUCTNAME}.lnk" - - !insertmacro wails.unassociateFiles - - !insertmacro wails.deleteUninstaller -SectionEnd diff --git a/v3/examples/android/build/windows/nsis/wails_tools.nsh b/v3/examples/android/build/windows/nsis/wails_tools.nsh deleted file mode 100644 index dc9aebc17..000000000 --- a/v3/examples/android/build/windows/nsis/wails_tools.nsh +++ /dev/null @@ -1,212 +0,0 @@ -# DO NOT EDIT - Generated automatically by `wails build` - -!include "x64.nsh" -!include "WinVer.nsh" -!include "FileFunc.nsh" - -!ifndef INFO_PROJECTNAME - !define INFO_PROJECTNAME "ios" -!endif -!ifndef INFO_COMPANYNAME - !define INFO_COMPANYNAME "My Company" -!endif -!ifndef INFO_PRODUCTNAME - !define INFO_PRODUCTNAME "My Product" -!endif -!ifndef INFO_PRODUCTVERSION - !define INFO_PRODUCTVERSION "0.1.0" -!endif -!ifndef INFO_COPYRIGHT - !define INFO_COPYRIGHT "© now, My Company" -!endif -!ifndef PRODUCT_EXECUTABLE - !define PRODUCT_EXECUTABLE "${INFO_PROJECTNAME}.exe" -!endif -!ifndef UNINST_KEY_NAME - !define UNINST_KEY_NAME "${INFO_COMPANYNAME}${INFO_PRODUCTNAME}" -!endif -!define UNINST_KEY "Software\Microsoft\Windows\CurrentVersion\Uninstall\${UNINST_KEY_NAME}" - -!ifndef REQUEST_EXECUTION_LEVEL - !define REQUEST_EXECUTION_LEVEL "admin" -!endif - -RequestExecutionLevel "${REQUEST_EXECUTION_LEVEL}" - -!ifdef ARG_WAILS_AMD64_BINARY - !define SUPPORTS_AMD64 -!endif - -!ifdef ARG_WAILS_ARM64_BINARY - !define SUPPORTS_ARM64 -!endif - -!ifdef SUPPORTS_AMD64 - !ifdef SUPPORTS_ARM64 - !define ARCH "amd64_arm64" - !else - !define ARCH "amd64" - !endif -!else - !ifdef SUPPORTS_ARM64 - !define ARCH "arm64" - !else - !error "Wails: Undefined ARCH, please provide at least one of ARG_WAILS_AMD64_BINARY or ARG_WAILS_ARM64_BINARY" - !endif -!endif - -!macro wails.checkArchitecture - !ifndef WAILS_WIN10_REQUIRED - !define WAILS_WIN10_REQUIRED "This product is only supported on Windows 10 (Server 2016) and later." - !endif - - !ifndef WAILS_ARCHITECTURE_NOT_SUPPORTED - !define WAILS_ARCHITECTURE_NOT_SUPPORTED "This product can't be installed on the current Windows architecture. Supports: ${ARCH}" - !endif - - ${If} ${AtLeastWin10} - !ifdef SUPPORTS_AMD64 - ${if} ${IsNativeAMD64} - Goto ok - ${EndIf} - !endif - - !ifdef SUPPORTS_ARM64 - ${if} ${IsNativeARM64} - Goto ok - ${EndIf} - !endif - - IfSilent silentArch notSilentArch - silentArch: - SetErrorLevel 65 - Abort - notSilentArch: - MessageBox MB_OK "${WAILS_ARCHITECTURE_NOT_SUPPORTED}" - Quit - ${else} - IfSilent silentWin notSilentWin - silentWin: - SetErrorLevel 64 - Abort - notSilentWin: - MessageBox MB_OK "${WAILS_WIN10_REQUIRED}" - Quit - ${EndIf} - - ok: -!macroend - -!macro wails.files - !ifdef SUPPORTS_AMD64 - ${if} ${IsNativeAMD64} - File "/oname=${PRODUCT_EXECUTABLE}" "${ARG_WAILS_AMD64_BINARY}" - ${EndIf} - !endif - - !ifdef SUPPORTS_ARM64 - ${if} ${IsNativeARM64} - File "/oname=${PRODUCT_EXECUTABLE}" "${ARG_WAILS_ARM64_BINARY}" - ${EndIf} - !endif -!macroend - -!macro wails.writeUninstaller - WriteUninstaller "$INSTDIR\uninstall.exe" - - SetRegView 64 - WriteRegStr HKLM "${UNINST_KEY}" "Publisher" "${INFO_COMPANYNAME}" - WriteRegStr HKLM "${UNINST_KEY}" "DisplayName" "${INFO_PRODUCTNAME}" - WriteRegStr HKLM "${UNINST_KEY}" "DisplayVersion" "${INFO_PRODUCTVERSION}" - WriteRegStr HKLM "${UNINST_KEY}" "DisplayIcon" "$INSTDIR\${PRODUCT_EXECUTABLE}" - WriteRegStr HKLM "${UNINST_KEY}" "UninstallString" "$\"$INSTDIR\uninstall.exe$\"" - WriteRegStr HKLM "${UNINST_KEY}" "QuietUninstallString" "$\"$INSTDIR\uninstall.exe$\" /S" - - ${GetSize} "$INSTDIR" "/S=0K" $0 $1 $2 - IntFmt $0 "0x%08X" $0 - WriteRegDWORD HKLM "${UNINST_KEY}" "EstimatedSize" "$0" -!macroend - -!macro wails.deleteUninstaller - Delete "$INSTDIR\uninstall.exe" - - SetRegView 64 - DeleteRegKey HKLM "${UNINST_KEY}" -!macroend - -!macro wails.setShellContext - ${If} ${REQUEST_EXECUTION_LEVEL} == "admin" - SetShellVarContext all - ${else} - SetShellVarContext current - ${EndIf} -!macroend - -# Install webview2 by launching the bootstrapper -# See https://docs.microsoft.com/en-us/microsoft-edge/webview2/concepts/distribution#online-only-deployment -!macro wails.webview2runtime - !ifndef WAILS_INSTALL_WEBVIEW_DETAILPRINT - !define WAILS_INSTALL_WEBVIEW_DETAILPRINT "Installing: WebView2 Runtime" - !endif - - SetRegView 64 - # If the admin key exists and is not empty then webview2 is already installed - ReadRegStr $0 HKLM "SOFTWARE\WOW6432Node\Microsoft\EdgeUpdate\Clients\{F3017226-FE2A-4295-8BDF-00C3A9A7E4C5}" "pv" - ${If} $0 != "" - Goto ok - ${EndIf} - - ${If} ${REQUEST_EXECUTION_LEVEL} == "user" - # If the installer is run in user level, check the user specific key exists and is not empty then webview2 is already installed - ReadRegStr $0 HKCU "Software\Microsoft\EdgeUpdate\Clients\{F3017226-FE2A-4295-8BDF-00C3A9A7E4C5}" "pv" - ${If} $0 != "" - Goto ok - ${EndIf} - ${EndIf} - - SetDetailsPrint both - DetailPrint "${WAILS_INSTALL_WEBVIEW_DETAILPRINT}" - SetDetailsPrint listonly - - InitPluginsDir - CreateDirectory "$pluginsdir\webview2bootstrapper" - SetOutPath "$pluginsdir\webview2bootstrapper" - File "MicrosoftEdgeWebview2Setup.exe" - ExecWait '"$pluginsdir\webview2bootstrapper\MicrosoftEdgeWebview2Setup.exe" /silent /install' - - SetDetailsPrint both - ok: -!macroend - -# Copy of APP_ASSOCIATE and APP_UNASSOCIATE macros from here https://gist.github.com/nikku/281d0ef126dbc215dd58bfd5b3a5cd5b -!macro APP_ASSOCIATE EXT FILECLASS DESCRIPTION ICON COMMANDTEXT COMMAND - ; Backup the previously associated file class - ReadRegStr $R0 SHELL_CONTEXT "Software\Classes\.${EXT}" "" - WriteRegStr SHELL_CONTEXT "Software\Classes\.${EXT}" "${FILECLASS}_backup" "$R0" - - WriteRegStr SHELL_CONTEXT "Software\Classes\.${EXT}" "" "${FILECLASS}" - - WriteRegStr SHELL_CONTEXT "Software\Classes\${FILECLASS}" "" `${DESCRIPTION}` - WriteRegStr SHELL_CONTEXT "Software\Classes\${FILECLASS}\DefaultIcon" "" `${ICON}` - WriteRegStr SHELL_CONTEXT "Software\Classes\${FILECLASS}\shell" "" "open" - WriteRegStr SHELL_CONTEXT "Software\Classes\${FILECLASS}\shell\open" "" `${COMMANDTEXT}` - WriteRegStr SHELL_CONTEXT "Software\Classes\${FILECLASS}\shell\open\command" "" `${COMMAND}` -!macroend - -!macro APP_UNASSOCIATE EXT FILECLASS - ; Backup the previously associated file class - ReadRegStr $R0 SHELL_CONTEXT "Software\Classes\.${EXT}" `${FILECLASS}_backup` - WriteRegStr SHELL_CONTEXT "Software\Classes\.${EXT}" "" "$R0" - - DeleteRegKey SHELL_CONTEXT `Software\Classes\${FILECLASS}` -!macroend - -!macro wails.associateFiles - ; Create file associations - -!macroend - -!macro wails.unassociateFiles - ; Delete app associations - -!macroend \ No newline at end of file diff --git a/v3/examples/android/build/windows/wails.exe.manifest b/v3/examples/android/build/windows/wails.exe.manifest deleted file mode 100644 index 025555a69..000000000 --- a/v3/examples/android/build/windows/wails.exe.manifest +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - - - - - true/pm - permonitorv2,permonitor - - - - - - - - - - \ No newline at end of file diff --git a/v3/examples/android/frontend/Inter Font License.txt b/v3/examples/android/frontend/Inter Font License.txt deleted file mode 100644 index 00287df15..000000000 --- a/v3/examples/android/frontend/Inter Font License.txt +++ /dev/null @@ -1,93 +0,0 @@ -Copyright 2020 The Inter Project Authors (https://github.com/rsms/inter) - -This Font Software is licensed under the SIL Open Font License, Version 1.1. -This license is copied below, and is also available with a FAQ at: -http://scripts.sil.org/OFL - - ------------------------------------------------------------ -SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 ------------------------------------------------------------ - -PREAMBLE -The goals of the Open Font License (OFL) are to stimulate worldwide -development of collaborative font projects, to support the font creation -efforts of academic and linguistic communities, and to provide a free and -open framework in which fonts may be shared and improved in partnership -with others. - -The OFL allows the licensed fonts to be used, studied, modified and -redistributed freely as long as they are not sold by themselves. The -fonts, including any derivative works, can be bundled, embedded, -redistributed and/or sold with any software provided that any reserved -names are not used by derivative works. The fonts and derivatives, -however, cannot be released under any other type of license. The -requirement for fonts to remain under this license does not apply -to any document created using the fonts or their derivatives. - -DEFINITIONS -"Font Software" refers to the set of files released by the Copyright -Holder(s) under this license and clearly marked as such. This may -include source files, build scripts and documentation. - -"Reserved Font Name" refers to any names specified as such after the -copyright statement(s). - -"Original Version" refers to the collection of Font Software components as -distributed by the Copyright Holder(s). - -"Modified Version" refers to any derivative made by adding to, deleting, -or substituting -- in part or in whole -- any of the components of the -Original Version, by changing formats or by porting the Font Software to a -new environment. - -"Author" refers to any designer, engineer, programmer, technical -writer or other person who contributed to the Font Software. - -PERMISSION & CONDITIONS -Permission is hereby granted, free of charge, to any person obtaining -a copy of the Font Software, to use, study, copy, merge, embed, modify, -redistribute, and sell modified and unmodified copies of the Font -Software, subject to the following conditions: - -1) Neither the Font Software nor any of its individual components, -in Original or Modified Versions, may be sold by itself. - -2) Original or Modified Versions of the Font Software may be bundled, -redistributed and/or sold with any software, provided that each copy -contains the above copyright notice and this license. These can be -included either as stand-alone text files, human-readable headers or -in the appropriate machine-readable metadata fields within text or -binary files as long as those fields can be easily viewed by the user. - -3) No Modified Version of the Font Software may use the Reserved Font -Name(s) unless explicit written permission is granted by the corresponding -Copyright Holder. This restriction only applies to the primary font name as -presented to the users. - -4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font -Software shall not be used to promote, endorse or advertise any -Modified Version, except to acknowledge the contribution(s) of the -Copyright Holder(s) and the Author(s) or with their explicit written -permission. - -5) The Font Software, modified or unmodified, in part or in whole, -must be distributed entirely under this license, and must not be -distributed under any other license. The requirement for fonts to -remain under this license does not apply to any document created -using the Font Software. - -TERMINATION -This license becomes null and void if any of the above conditions are -not met. - -DISCLAIMER -THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT -OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE -COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL -DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM -OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/v3/examples/android/frontend/bindings/changeme/greetservice.js b/v3/examples/android/frontend/bindings/changeme/greetservice.js deleted file mode 100644 index 0b93e6d75..000000000 --- a/v3/examples/android/frontend/bindings/changeme/greetservice.js +++ /dev/null @@ -1,15 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "@wailsio/runtime"; - -/** - * @param {string} name - * @returns {$CancellablePromise} - */ -export function Greet(name) { - return $Call.ByID(1411160069, name); -} diff --git a/v3/examples/android/frontend/bindings/changeme/index.js b/v3/examples/android/frontend/bindings/changeme/index.js deleted file mode 100644 index fdf1ff435..000000000 --- a/v3/examples/android/frontend/bindings/changeme/index.js +++ /dev/null @@ -1,8 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; diff --git a/v3/examples/android/frontend/bindings/github.com/wailsapp/wails/v3/internal/eventcreate.js b/v3/examples/android/frontend/bindings/github.com/wailsapp/wails/v3/internal/eventcreate.js deleted file mode 100644 index 1ea105857..000000000 --- a/v3/examples/android/frontend/bindings/github.com/wailsapp/wails/v3/internal/eventcreate.js +++ /dev/null @@ -1,9 +0,0 @@ -//@ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Create as $Create } from "@wailsio/runtime"; - -Object.freeze($Create.Events); diff --git a/v3/examples/android/frontend/bindings/github.com/wailsapp/wails/v3/internal/eventdata.d.ts b/v3/examples/android/frontend/bindings/github.com/wailsapp/wails/v3/internal/eventdata.d.ts deleted file mode 100644 index 3dd1807bd..000000000 --- a/v3/examples/android/frontend/bindings/github.com/wailsapp/wails/v3/internal/eventdata.d.ts +++ /dev/null @@ -1,2 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT diff --git a/v3/examples/android/frontend/index.html b/v3/examples/android/frontend/index.html deleted file mode 100644 index f7c8de065..000000000 --- a/v3/examples/android/frontend/index.html +++ /dev/null @@ -1,110 +0,0 @@ - - - - - - - - - Wails App - - - - -
      - -

      Wails + Javascript

      -
      -
      Demo Screens
      -
      - -
      -
      Please enter your name below 👇
      -
      - - -
      -
      - - -
      -
      - -
      -
      - -
      -
      - -
      -
      - -
      -
      - -
      -
      - - -
      -
      - - -
      -
      - - - - -
      -
      - -
      -
      - -
      -
      - -
      -
      - -
      -
      - -
      -
      - - -
      -
      
      -          
      - -
      -
      - -
      - - - diff --git a/v3/examples/android/frontend/main.js b/v3/examples/android/frontend/main.js deleted file mode 100644 index ad8064576..000000000 --- a/v3/examples/android/frontend/main.js +++ /dev/null @@ -1,113 +0,0 @@ -import {GreetService} from "./bindings/changeme"; -import * as Runtime from "@wailsio/runtime"; - -const resultElement = document.getElementById('result'); -const timeElement = document.getElementById('time'); -const deviceInfoElement = document.getElementById('deviceInfo'); -const Events = Runtime.Events; -const IOS = Runtime.IOS; // May be undefined in published package; we guard usages below. - -window.doGreet = () => { - let name = document.getElementById('name').value; - if (!name) { - name = 'anonymous'; - } - GreetService.Greet(name).then((result) => { - resultElement.innerText = result; - }).catch((err) => { - console.log(err); - }); -} - -window.doHaptic = (style) => { - if (!IOS || !IOS.Haptics?.Impact) { - console.warn('IOS runtime not available in @wailsio/runtime. Skipping haptic call.'); - return; - } - IOS.Haptics.Impact(style).catch((err) => { - console.error('Haptics error:', err); - }); -} - -window.getDeviceInfo = async () => { - if (!IOS || !IOS.Device?.Info) { - deviceInfoElement.innerText = 'iOS runtime not available; cannot fetch device info.'; - return; - } - try { - const info = await IOS.Device.Info(); - deviceInfoElement.innerText = JSON.stringify(info, null, 2); - } catch (e) { - deviceInfoElement.innerText = `Error: ${e?.message || e}`; - } -} - -// Generic caller for IOS..(args) -window.iosJsSet = async (methodPath, args) => { - if (!IOS) { - console.warn('IOS runtime not available in @wailsio/runtime.'); - return; - } - try { - const [group, method] = methodPath.split('.'); - const target = IOS?.[group]; - const fn = target?.[method]; - if (typeof fn !== 'function') { - console.warn('IOS method not found:', methodPath); - return; - } - await fn(args); - } catch (e) { - console.error('iosJsSet error for', methodPath, e); - } -} - -// Emit events for Go handlers -window.emitGo = (eventName, data) => { - try { - Events.Emit(eventName, data); - } catch (e) { - console.error('emitGo error:', e); - } -} - -// Toggle helpers for UI switches -window.setGoToggle = (eventName, enabled) => { - emitGo(eventName, { enabled: !!enabled }); -} - -window.setJsToggle = (methodPath, enabled) => { - iosJsSet(methodPath, { enabled: !!enabled }); -} - -Events.On('time', (payload) => { - // payload may be a plain value or an object with a `data` field depending on emitter/runtime - const value = (payload && typeof payload === 'object' && 'data' in payload) ? payload.data : payload; - console.log('[frontend] time event:', payload, '->', value); - timeElement.innerText = value; -}); - -// Simple pane switcher responding to native UITabBar -function showPaneByIndex(index) { - const panes = [ - document.getElementById('screen-bindings'), - document.getElementById('screen-go'), - document.getElementById('screen-js'), - ]; - panes.forEach((el, i) => { - if (!el) return; - if (i === index) el.classList.add('active'); - else el.classList.remove('active'); - }); -} - -// Listen for native tab selection events posted by the iOS layer -window.addEventListener('nativeTabSelected', (e) => { - const idx = (e && e.detail && typeof e.detail.index === 'number') ? e.detail.index : 0; - showPaneByIndex(idx); -}); - -// Ensure default pane is visible on load (index 0) -window.addEventListener('DOMContentLoaded', () => { - showPaneByIndex(0); -}); diff --git a/v3/examples/android/frontend/package-lock.json b/v3/examples/android/frontend/package-lock.json deleted file mode 100644 index b0b7dc68f..000000000 --- a/v3/examples/android/frontend/package-lock.json +++ /dev/null @@ -1,936 +0,0 @@ -{ - "name": "frontend", - "version": "0.0.0", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "frontend", - "version": "0.0.0", - "dependencies": { - "@wailsio/runtime": "latest" - }, - "devDependencies": { - "vite": "^5.0.0" - } - }, - "node_modules/@esbuild/aix-ppc64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", - "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "aix" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/android-arm": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz", - "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/android-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz", - "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/android-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz", - "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/darwin-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz", - "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/darwin-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz", - "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/freebsd-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz", - "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/freebsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz", - "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-arm": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz", - "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz", - "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-ia32": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz", - "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-loong64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz", - "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==", - "cpu": [ - "loong64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-mips64el": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz", - "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==", - "cpu": [ - "mips64el" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-ppc64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz", - "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-riscv64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz", - "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-s390x": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz", - "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==", - "cpu": [ - "s390x" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz", - "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/netbsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz", - "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/openbsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz", - "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/sunos-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz", - "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/win32-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz", - "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/win32-ia32": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz", - "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/win32-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz", - "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.50.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.50.0.tgz", - "integrity": "sha512-lVgpeQyy4fWN5QYebtW4buT/4kn4p4IJ+kDNB4uYNT5b8c8DLJDg6titg20NIg7E8RWwdWZORW6vUFfrLyG3KQ==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/@rollup/rollup-android-arm64": { - "version": "4.50.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.50.0.tgz", - "integrity": "sha512-2O73dR4Dc9bp+wSYhviP6sDziurB5/HCym7xILKifWdE9UsOe2FtNcM+I4xZjKrfLJnq5UR8k9riB87gauiQtw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.50.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.50.0.tgz", - "integrity": "sha512-vwSXQN8T4sKf1RHr1F0s98Pf8UPz7pS6P3LG9NSmuw0TVh7EmaE+5Ny7hJOZ0M2yuTctEsHHRTMi2wuHkdS6Hg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.50.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.50.0.tgz", - "integrity": "sha512-cQp/WG8HE7BCGyFVuzUg0FNmupxC+EPZEwWu2FCGGw5WDT1o2/YlENbm5e9SMvfDFR6FRhVCBePLqj0o8MN7Vw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.50.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.50.0.tgz", - "integrity": "sha512-UR1uTJFU/p801DvvBbtDD7z9mQL8J80xB0bR7DqW7UGQHRm/OaKzp4is7sQSdbt2pjjSS72eAtRh43hNduTnnQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ] - }, - "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.50.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.50.0.tgz", - "integrity": "sha512-G/DKyS6PK0dD0+VEzH/6n/hWDNPDZSMBmqsElWnCRGrYOb2jC0VSupp7UAHHQ4+QILwkxSMaYIbQ72dktp8pKA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ] - }, - "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.50.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.50.0.tgz", - "integrity": "sha512-u72Mzc6jyJwKjJbZZcIYmd9bumJu7KNmHYdue43vT1rXPm2rITwmPWF0mmPzLm9/vJWxIRbao/jrQmxTO0Sm9w==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.50.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.50.0.tgz", - "integrity": "sha512-S4UefYdV0tnynDJV1mdkNawp0E5Qm2MtSs330IyHgaccOFrwqsvgigUD29uT+B/70PDY1eQ3t40+xf6wIvXJyg==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.50.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.50.0.tgz", - "integrity": "sha512-1EhkSvUQXJsIhk4msxP5nNAUWoB4MFDHhtc4gAYvnqoHlaL9V3F37pNHabndawsfy/Tp7BPiy/aSa6XBYbaD1g==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.50.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.50.0.tgz", - "integrity": "sha512-EtBDIZuDtVg75xIPIK1l5vCXNNCIRM0OBPUG+tbApDuJAy9mKago6QxX+tfMzbCI6tXEhMuZuN1+CU8iDW+0UQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-loongarch64-gnu": { - "version": "4.50.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.50.0.tgz", - "integrity": "sha512-BGYSwJdMP0hT5CCmljuSNx7+k+0upweM2M4YGfFBjnFSZMHOLYR0gEEj/dxyYJ6Zc6AiSeaBY8dWOa11GF/ppQ==", - "cpu": [ - "loong64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-ppc64-gnu": { - "version": "4.50.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.50.0.tgz", - "integrity": "sha512-I1gSMzkVe1KzAxKAroCJL30hA4DqSi+wGc5gviD0y3IL/VkvcnAqwBf4RHXHyvH66YVHxpKO8ojrgc4SrWAnLg==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.50.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.50.0.tgz", - "integrity": "sha512-bSbWlY3jZo7molh4tc5dKfeSxkqnf48UsLqYbUhnkdnfgZjgufLS/NTA8PcP/dnvct5CCdNkABJ56CbclMRYCA==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-riscv64-musl": { - "version": "4.50.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.50.0.tgz", - "integrity": "sha512-LSXSGumSURzEQLT2e4sFqFOv3LWZsEF8FK7AAv9zHZNDdMnUPYH3t8ZlaeYYZyTXnsob3htwTKeWtBIkPV27iQ==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.50.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.50.0.tgz", - "integrity": "sha512-CxRKyakfDrsLXiCyucVfVWVoaPA4oFSpPpDwlMcDFQvrv3XY6KEzMtMZrA+e/goC8xxp2WSOxHQubP8fPmmjOQ==", - "cpu": [ - "s390x" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.50.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.50.0.tgz", - "integrity": "sha512-8PrJJA7/VU8ToHVEPu14FzuSAqVKyo5gg/J8xUerMbyNkWkO9j2ExBho/68RnJsMGNJq4zH114iAttgm7BZVkA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.50.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.50.0.tgz", - "integrity": "sha512-SkE6YQp+CzpyOrbw7Oc4MgXFvTw2UIBElvAvLCo230pyxOLmYwRPwZ/L5lBe/VW/qT1ZgND9wJfOsdy0XptRvw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-openharmony-arm64": { - "version": "4.50.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.50.0.tgz", - "integrity": "sha512-PZkNLPfvXeIOgJWA804zjSFH7fARBBCpCXxgkGDRjjAhRLOR8o0IGS01ykh5GYfod4c2yiiREuDM8iZ+pVsT+Q==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openharmony" - ] - }, - "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.50.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.50.0.tgz", - "integrity": "sha512-q7cIIdFvWQoaCbLDUyUc8YfR3Jh2xx3unO8Dn6/TTogKjfwrax9SyfmGGK6cQhKtjePI7jRfd7iRYcxYs93esg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.50.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.50.0.tgz", - "integrity": "sha512-XzNOVg/YnDOmFdDKcxxK410PrcbcqZkBmz+0FicpW5jtjKQxcW1BZJEQOF0NJa6JO7CZhett8GEtRN/wYLYJuw==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.50.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.50.0.tgz", - "integrity": "sha512-xMmiWRR8sp72Zqwjgtf3QbZfF1wdh8X2ABu3EaozvZcyHJeU0r+XAnXdKgs4cCAp6ORoYoCygipYP1mjmbjrsg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@types/estree": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", - "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", - "dev": true, - "license": "MIT" - }, - "node_modules/@wailsio/runtime": { - "version": "3.0.0-alpha.66", - "resolved": "https://registry.npmjs.org/@wailsio/runtime/-/runtime-3.0.0-alpha.66.tgz", - "integrity": "sha512-ENLu8rn1griL1gFHJqkq1i+BVxrrA0JPJHYneUJYuf/s54kjuQViW0RKDEe/WTDo56ABpfykrd/T8OYpPUyXUw==", - "license": "MIT" - }, - "node_modules/esbuild": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", - "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=12" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.21.5", - "@esbuild/android-arm": "0.21.5", - "@esbuild/android-arm64": "0.21.5", - "@esbuild/android-x64": "0.21.5", - "@esbuild/darwin-arm64": "0.21.5", - "@esbuild/darwin-x64": "0.21.5", - "@esbuild/freebsd-arm64": "0.21.5", - "@esbuild/freebsd-x64": "0.21.5", - "@esbuild/linux-arm": "0.21.5", - "@esbuild/linux-arm64": "0.21.5", - "@esbuild/linux-ia32": "0.21.5", - "@esbuild/linux-loong64": "0.21.5", - "@esbuild/linux-mips64el": "0.21.5", - "@esbuild/linux-ppc64": "0.21.5", - "@esbuild/linux-riscv64": "0.21.5", - "@esbuild/linux-s390x": "0.21.5", - "@esbuild/linux-x64": "0.21.5", - "@esbuild/netbsd-x64": "0.21.5", - "@esbuild/openbsd-x64": "0.21.5", - "@esbuild/sunos-x64": "0.21.5", - "@esbuild/win32-arm64": "0.21.5", - "@esbuild/win32-ia32": "0.21.5", - "@esbuild/win32-x64": "0.21.5" - } - }, - "node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/nanoid": { - "version": "3.3.11", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", - "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "bin": { - "nanoid": "bin/nanoid.cjs" - }, - "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" - } - }, - "node_modules/picocolors": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", - "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", - "dev": true, - "license": "ISC" - }, - "node_modules/postcss": { - "version": "8.5.6", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", - "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "nanoid": "^3.3.11", - "picocolors": "^1.1.1", - "source-map-js": "^1.2.1" - }, - "engines": { - "node": "^10 || ^12 || >=14" - } - }, - "node_modules/rollup": { - "version": "4.50.0", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.50.0.tgz", - "integrity": "sha512-/Zl4D8zPifNmyGzJS+3kVoyXeDeT/GrsJM94sACNg9RtUE0hrHa1bNPtRSrfHTMH5HjRzce6K7rlTh3Khiw+pw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/estree": "1.0.8" - }, - "bin": { - "rollup": "dist/bin/rollup" - }, - "engines": { - "node": ">=18.0.0", - "npm": ">=8.0.0" - }, - "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.50.0", - "@rollup/rollup-android-arm64": "4.50.0", - "@rollup/rollup-darwin-arm64": "4.50.0", - "@rollup/rollup-darwin-x64": "4.50.0", - "@rollup/rollup-freebsd-arm64": "4.50.0", - "@rollup/rollup-freebsd-x64": "4.50.0", - "@rollup/rollup-linux-arm-gnueabihf": "4.50.0", - "@rollup/rollup-linux-arm-musleabihf": "4.50.0", - "@rollup/rollup-linux-arm64-gnu": "4.50.0", - "@rollup/rollup-linux-arm64-musl": "4.50.0", - "@rollup/rollup-linux-loongarch64-gnu": "4.50.0", - "@rollup/rollup-linux-ppc64-gnu": "4.50.0", - "@rollup/rollup-linux-riscv64-gnu": "4.50.0", - "@rollup/rollup-linux-riscv64-musl": "4.50.0", - "@rollup/rollup-linux-s390x-gnu": "4.50.0", - "@rollup/rollup-linux-x64-gnu": "4.50.0", - "@rollup/rollup-linux-x64-musl": "4.50.0", - "@rollup/rollup-openharmony-arm64": "4.50.0", - "@rollup/rollup-win32-arm64-msvc": "4.50.0", - "@rollup/rollup-win32-ia32-msvc": "4.50.0", - "@rollup/rollup-win32-x64-msvc": "4.50.0", - "fsevents": "~2.3.2" - } - }, - "node_modules/source-map-js": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", - "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/vite": { - "version": "5.4.19", - "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.19.tgz", - "integrity": "sha512-qO3aKv3HoQC8QKiNSTuUM1l9o/XX3+c+VTgLHbJWHZGeTPVAg2XwazI9UWzoxjIJCGCV2zU60uqMzjeLZuULqA==", - "dev": true, - "license": "MIT", - "dependencies": { - "esbuild": "^0.21.3", - "postcss": "^8.4.43", - "rollup": "^4.20.0" - }, - "bin": { - "vite": "bin/vite.js" - }, - "engines": { - "node": "^18.0.0 || >=20.0.0" - }, - "funding": { - "url": "https://github.com/vitejs/vite?sponsor=1" - }, - "optionalDependencies": { - "fsevents": "~2.3.3" - }, - "peerDependencies": { - "@types/node": "^18.0.0 || >=20.0.0", - "less": "*", - "lightningcss": "^1.21.0", - "sass": "*", - "sass-embedded": "*", - "stylus": "*", - "sugarss": "*", - "terser": "^5.4.0" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - }, - "less": { - "optional": true - }, - "lightningcss": { - "optional": true - }, - "sass": { - "optional": true - }, - "sass-embedded": { - "optional": true - }, - "stylus": { - "optional": true - }, - "sugarss": { - "optional": true - }, - "terser": { - "optional": true - } - } - } - } -} diff --git a/v3/examples/android/frontend/package.json b/v3/examples/android/frontend/package.json deleted file mode 100644 index 0a118e984..000000000 --- a/v3/examples/android/frontend/package.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "name": "frontend", - "private": true, - "version": "0.0.0", - "type": "module", - "scripts": { - "dev": "vite", - "build:dev": "vite build --minify false --mode development", - "build": "vite build --mode production", - "preview": "vite preview" - }, - "dependencies": { - "@wailsio/runtime": "latest" - }, - "devDependencies": { - "vite": "^5.0.0" - } -} diff --git a/v3/examples/android/frontend/public/Inter-Medium.ttf b/v3/examples/android/frontend/public/Inter-Medium.ttf deleted file mode 100644 index a01f3777a..000000000 Binary files a/v3/examples/android/frontend/public/Inter-Medium.ttf and /dev/null differ diff --git a/v3/examples/android/frontend/public/javascript.svg b/v3/examples/android/frontend/public/javascript.svg deleted file mode 100644 index f9abb2b72..000000000 --- a/v3/examples/android/frontend/public/javascript.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/v3/examples/android/frontend/public/puppertino/LICENSE b/v3/examples/android/frontend/public/puppertino/LICENSE deleted file mode 100644 index ed9065e06..000000000 --- a/v3/examples/android/frontend/public/puppertino/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2019 Edgar Pérez - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/v3/examples/android/frontend/public/puppertino/css/actions.css b/v3/examples/android/frontend/public/puppertino/css/actions.css deleted file mode 100644 index 22a9d5a13..000000000 --- a/v3/examples/android/frontend/public/puppertino/css/actions.css +++ /dev/null @@ -1,149 +0,0 @@ -:root { - --font: -apple-system, "Inter", sans-serif; - --primary-col-ac: #0f75f5; - --p-modal-bg: rgba(255, 255, 255, 0.8); - --p-modal-bd-color: rgba(0,0,0,.1); - --p-modal-fallback-color: rgba(255,255,255,.95); - --p-actions-static-color: #555761; -} - -.p-modal-opened { - overflow: hidden; -} - -.p-action-background{ - background: rgba(0, 0, 0, 0.7); - height: 100vh; - left: 0; - opacity: 0; - pointer-events: none; - position: fixed; - top: 0; - transition: 0.3s; - width: 100vw; - z-index: 5; -} - -.p-action-background.nowactive { - opacity: 1; - pointer-events: auto; -} - - -.p-action-big-container{ - position:fixed; - width: 100%; - box-sizing: border-box; - padding: 1rem 5vw; - bottom:0; -} - -.p-action-container{ - background: var(--p-modal-bg); - display:block; - margin:auto; - margin-bottom: 10px; - border-radius: 10px; - max-width: 700px; -} - -.p-action-big-container .p-action-container:first-child{ - margin-bottom:10px; -} - -.p-action--intern{ - width: 100%; - display:block; - margin:auto; - font-size: 1rem; - font-weight: 600; - text-align:center; - padding: 15px 0; - border: 0; - border-bottom: 1px solid #bfbfbf; - color: #0f75f5; - text-decoration:none; - background-color: transparent; -} - -.p-action-destructive{ - color: #c6262e; -} - -.p-action-neutral{ - color: var(--p-actions-static-color); -} - -.p-action-cancel, .p-action-container a:last-child{ - border-bottom:none; -} - -.p-action-cancel{ - font-weight:bold; -} - -.p-action-icon{ - position:relative; -} -.p-action-icon svg, .p-action-icon img{ - position:absolute; - left:5%; - top:50%; - transform:translateY(-50%); -} - -.p-action-icon-inline{ - text-align: left; - display: flex; - align-items: center; -} - -.p-action-icon-inline svg, .p-action-icon-inline img{ - margin-left: 5%; - margin-right: 3%; -} - -.p-action-title{ - padding: 30px 15px; - border-bottom: 1px solid #bfbfbf; -} - -.p-action-title--intern,.p-action-text{ - margin:0; - color:var(--p-actions-static-color); -} - -.p-action-title--intern{ - margin-bottom: .3rem; -} - -@supports not (backdrop-filter: blur(10px)) { - .p-action-container { - background: var(--p-modal-fallback-color); - } -} - -.p-action-big-container{ - -webkit-transform: translateY(30%); - transform: translateY(30%); - opacity: 0; - transition: opacity 0.4s, transform 0.4s; - transition-timing-function: ease; - pointer-events: none; -} - -.p-action-big-container.active { - -webkit-transform: translateY(0); - transform: translateY(0); - opacity: 1; - pointer-events: all; -} - - -.p-action-big-container.active .p-action-container { - backdrop-filter: saturate(180%) blur(10px); -} - -.p-action-big-container[aria-hidden="true"] .p-action--intern { - display: none; -} diff --git a/v3/examples/android/frontend/public/puppertino/css/buttons.css b/v3/examples/android/frontend/public/puppertino/css/buttons.css deleted file mode 100644 index 4950b0053..000000000 --- a/v3/examples/android/frontend/public/puppertino/css/buttons.css +++ /dev/null @@ -1,158 +0,0 @@ -@charset "UTF-8"; -:root{ - --p-btn-border: #cacaca; - --p-btn-def-bg: #FFFFFF; - --p-btn-def-col: #000000; - --p-btn-dir-col: #242424; - --p-prim-text-col: #f5f5f5; - --p-btn-scope-unactive: #212136; - --p-btn-scope-action: #212136; -} - -.p-btn { - background: var(--p-btn-def-bg); - border: 1px solid var(--p-btn-border); - border-radius: 10px; - color: var(--p-btn-def-col); - display: inline-block; - font-family: -apple-system, "Inter", sans-serif; - font-size: 1.1rem; - margin: .7rem; - padding: .4rem 1.2rem; - text-decoration: none; - text-align: center; - box-shadow: 0 1px 0.375px rgba(0, 0, 0, 0.05), 0 0.25px 0.375px rgba(0, 0, 0, 0.15); - user-select: none; - cursor: pointer; -} -.p-btn:focus{ - outline: 2px solid #64baff; -} -.p-btn.p-btn-block{ - display: block; -} -.p-btn.p-btn-sm { - padding: .3rem 1.1rem; - font-size: 1rem; -} -.p-btn.p-btn-md { - padding: .8rem 2.4rem; - font-size: 1.6rem; -} -.p-btn.p-btn-lg { - padding: 1.2rem 2.8rem; - font-size: 1.8rem; -} -.p-btn-destructive{ - color: #FF3B30; -} -.p-btn-mob{ - padding: 10px 40px; - background: #227bec; - color: #fff; - border: 0; - box-shadow: inset 0 1px 1px rgb(255 255 255 / 41%), 0px 2px 3px -2px rgba(0,0,0,.3); -} -.p-btn[disabled], -.p-btn:disabled, -.p-btn-disabled{ - filter:contrast(0.5) grayscale(.5) opacity(.8); - cursor: not-allowed; - box-shadow: none; - pointer-events: none; -} - -.p-prim-col { - position: relative; - background: #007AFF; - border: none; - box-shadow: inset 0 1px 1px rgba(255, 255, 255, 0.41), 0px 2px 3px -2px rgba(0, 0, 0, 0.3); - color: var(--p-prim-text-col); - overflow: hidden; /* Ensure the ::before element doesn't overflow */ -} - -.p-prim-col:before { - content: ''; - position: absolute; - top: 0; - left: 0; - width: 100%; - height: 100%; - background: linear-gradient(180deg, rgba(255, 255, 255, 1) 0%, rgba(255, 255, 255, 0) 100%); - opacity: 0.17; - pointer-events: none; -} - -.p-btn.p-prim-col:active { - background: #0f75f5; -} - -.p-btn-more::after { - content: "..."; -} - -.p-btn-round { - border: 0; - border-radius: 50px; - box-shadow: inset 0 1px 1px rgb(255 255 255 / 41%); - padding: 10px 30px; -} - -.p-btn-icon { - align-items: center; - background: var(--p-btn-def-bg); - border: 2px solid currentColor; - border-radius: 50%; - color: #0f75f5; - display: inline-flex; - font-weight: 900; - height: 40px; - width: 40px; - justify-content: center; - margin: 5px; - text-align: center; - text-decoration: none; - box-sizing: border-box; - user-select: none; - vertical-align: bottom; -} - -.p-btn-icon.p-btn-icon-no-border{ - border: 0px; -} - -.p-btn-scope { - background: #8e8e8e; - color: #fff; - margin: 5px; - padding: 2px 20px; - box-shadow: none; -} -.p-btn-scope-unactive { - background: transparent; - border-color: transparent; - color: var(--p-btn-scope-unactive); - transition: border-color 0.2s; -} -.p-btn-scope-unactive:hover { - border-color: var(--p-btn-border); -} - -.p-btn-scope-outline { - background: transparent; - color: var(--p-btn-scope-action); - box-shadow: none; -} - -.p-btn-outline { - background: none; - border-color: currentColor; - box-shadow: none; -} - -.p-btn-outline-dash { - background: none; - border-color: currentColor; - border-style: dashed; - box-shadow: none; -} diff --git a/v3/examples/android/frontend/public/puppertino/css/cards.css b/v3/examples/android/frontend/public/puppertino/css/cards.css deleted file mode 100644 index b4fa2e397..000000000 --- a/v3/examples/android/frontend/public/puppertino/css/cards.css +++ /dev/null @@ -1,55 +0,0 @@ -:root{ - --p-color-card: #1a1a1a; - --p-bg-card: #fff; - --p-bd-card: #c5c5c55e; -} -.p-card { - background: var(--p-bg-card); - border: 1px solid var(--p-bd-card); - color: var(--p-color-card); - display: block; - margin: 15px; - margin-left:7.5px; - margin-right:7.5px; - text-decoration: none; - border-radius: 25px; - padding: 20px 0px; - transition: .3s ease; - box-shadow: 0 0.5px 1px rgba(0, 0, 0, 0.1); -} -.p-card-image > img { - border-bottom: 3px solid var(--accent-article); - display: block; - margin: auto; - width: 100%; -} -.p-card-tags { - display: flex; - overflow: hidden; - position: relative; - width: 100%; -} -.p-card-tags::before { - background: linear-gradient(to right, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0) 75%, white 100%); - content: ""; - height: 100%; - position: absolute; - right: 0; - top: 0; - width: 30%; -} -.p-card-title { - font-size: 2rem; - margin-bottom: 15px; - margin-top: 15px; -} -.p-card-content { - padding: 15px; - padding-top: 15px; -} -.p-card-text { - font-size: 17px; - margin-bottom: 10px; - margin-left: 10px; - margin-top: 0; -} diff --git a/v3/examples/android/frontend/public/puppertino/css/color_palette.css b/v3/examples/android/frontend/public/puppertino/css/color_palette.css deleted file mode 100644 index 33a66b91c..000000000 --- a/v3/examples/android/frontend/public/puppertino/css/color_palette.css +++ /dev/null @@ -1,917 +0,0 @@ -:root{ ---p-strawberry: #c6262e; ---p-strawberry-100: #ff8c82; ---p-strawberry-300: #ed5353; ---p-strawberry-500: #c6262e; ---p-strawberry-700: #a10705; ---p-strawberry-900: #7a0000; - ---p-orange: #f37329; ---p-orange-100: #ffc27d; ---p-orange-300: #ffa154; ---p-orange-500: #f37329; ---p-orange-700: #cc3b02; ---p-orange-900: #a62100; - - ---p-banana: #f9c440; ---p-banana-100: #fff394; ---p-banana-300: #ffe16b; ---p-banana-500: #f9c440; ---p-banana-700: #d48e15; ---p-banana-900: #ad5f00; - ---p-lime: #68b723; ---p-lime-100: #d1ff82; ---p-lime-300: #9bdb4d; ---p-lime-500: #68b723; ---p-lime-700: #3a9104; ---p-lime-900: #206b00; - ---p-mint: #28bca3; ---p-mint-100: #89ffdd; ---p-mint-300: #43d6b5; ---p-mint-500: #28bca3; ---p-mint-700: #0e9a83; ---p-mint-900: #007367; - - ---p-blueberry: #3689e6; ---p-blueberry-100: #8cd5ff; ---p-blueberry-300: #64baff; ---p-blueberry-500: #3689e6; ---p-blueberry-700: #0d52bf; ---p-blueberry-900: #002e99; - ---p-grape: #a56de2; ---p-grape-100: #e4c6fa; ---p-grape-300: #cd9ef7; ---p-grape-500: #a56de2; ---p-grape-700: #7239b3; ---p-grape-900: #452981; - ---p-bubblegum: #de3e80; ---p-bubblegum-100: #fe9ab8; ---p-bubblegum-300: #f4679d; ---p-bubblegum-500: #de3e80; ---p-bubblegum-700: #bc245d; ---p-bubblegum-900: #910e38; - - ---p-cocoa: #715344; ---p-cocoa-100: #a3907c; ---p-cocoa-300: #8a715e; ---p-cocoa-500: #715344; ---p-cocoa-700: #57392d; ---p-cocoa-900: #3d211b; - ---p-silver: #abacae; ---p-silver-100: #fafafa; ---p-silver-300: #d4d4d4; ---p-silver-500: #abacae; ---p-silver-700: #7e8087; ---p-silver-900: #555761; - ---p-slate: #485a6c; ---p-slate-100: #95a3ab; ---p-slate-300: #667885; ---p-slate-500: #485a6c; ---p-slate-700: #273445; ---p-slate-900: #0e141f; - - ---p-dark: #333; ---p-dark-100: #666; ---p-dark-300: #4d4d4d; ---p-dark-500: #333; ---p-dark-700: #1a1a1a; ---p-dark-900: #000; - - ---p-apple-red: rgb(255, 59 , 48); ---p-apple-red-dark: rgb(255, 69 , 58); ---p-apple-orange: rgb(255,149,0); ---p-apple-orange-dark: rgb(255,159,10); ---p-apple-yellow: rgb(255,204,0); ---p-apple-yellow-dark: rgb(255,214,10); ---p-apple-green: rgb(40,205,65); ---p-apple-green-dark: rgb(40,215,75); ---p-apple-mint: rgb(0,199,190); ---p-apple-mint-dark: rgb(102,212,207); ---p-apple-teal: rgb(89, 173, 196); ---p-apple-teal-dark: rgb(106, 196, 220); ---p-apple-cyan: rgb(85,190,240); ---p-apple-cyan-dark: rgb(90,200,245); ---p-apple-blue: rgb(0, 122, 255); ---p-apple-blue-dark: rgb(10, 132, 255); ---p-apple-indigo: rgb(88, 86, 214); ---p-apple-indigo-dark: rgb(94, 92, 230); ---p-apple-purple: rgb(175, 82, 222); ---p-apple-purple-dark: rgb(191, 90, 242); ---p-apple-pink: rgb(255, 45, 85); ---p-apple-pink-dark: rgb(255, 55, 95); ---p-apple-brown: rgb(162, 132, 94); ---p-apple-brown-dark: rgb(172, 142, 104); ---p-apple-gray: rgb(142, 142, 147); ---p-apple-gray-dark: rgb(152, 152, 157); - -} - - -/* -APPLE OFFICIAL COLORS -*/ - -.p-apple-red{ - background: rgb(255, 59 , 48); -} - -.p-apple-red-dark{ - background: rgb(255, 69 , 58); -} - -.p-apple-orange{ - background: rgb(255,149,0); -} - -.p-apple-orange-dark{ - background: rgb(255,159,10); -} - -.p-apple-yellow{ - background: rgb(255,204,0); -} - -.p-apple-yellow-dark{ - background: rgb(255,214,10); -} - -.p-apple-green{ - background: rgb(40,205,65); -} - -.p-apple-green-dark{ - background: rgb(40,215,75); -} - -.p-apple-mint{ - background: rgb(0,199,190); -} - -.p-apple-mint-dark{ - background: rgb(102,212,207); -} - -.p-apple-teal{ - background: rgb(89, 173, 196); -} - -.p-apple-teal-dark{ - background: rgb(106, 196, 220); -} - -.p-apple-cyan{ - background: rgb(85,190,240); -} - -.p-apple-cyan-dark{ - background: rgb(90,200,245); -} - -.p-apple-blue{ - background: rgb(0, 122, 255); -} - -.p-apple-blue-dark{ - background: rgb(10, 132, 255); -} - -.p-apple-indigo{ - background: rgb(88, 86, 214); -} - -.p-apple-indigo-dark{ - background: rgb(94, 92, 230); -} - -.p-apple-purple{ - background: rgb(175, 82, 222); -} - -.p-apple-purple-dark{ - background: rgb(191, 90, 242); -} - -.p-apple-pink{ - background: rgb(255, 45, 85); -} - -.p-apple-pink-dark{ - background: rgb(255, 55, 95); -} - -.p-apple-brown{ - background: rgb(162, 132, 94); -} - -.p-apple-brown-dark{ - background: rgb(172, 142, 104); -} - -.p-apple-gray{ - background: rgb(142, 142, 147); -} - -.p-apple-gray-dark{ - background: rgb(152, 152, 157); -} - -.p-apple-red-color{ - color: rgb(255, 59 , 48); -} - -.p-apple-red-dark-color{ - color: rgb(255, 69 , 58); -} - -.p-apple-orange-color{ - color: rgb(255,149,0); -} - -.p-apple-orange-dark-color{ - color: rgb(255,159,10); -} - -.p-apple-yellow-color{ - color: rgb(255,204,0); -} - -.p-apple-yellow-dark-color{ - color: rgb(255,214,10); -} - -.p-apple-green-color{ - color: rgb(40,205,65); -} - -.p-apple-green-dark-color{ - color: rgb(40,215,75); -} - -.p-apple-mint-color{ - color: rgb(0,199,190); -} - -.p-apple-mint-dark-color{ - color: rgb(102,212,207); -} - -.p-apple-teal-color{ - color: rgb(89, 173, 196); -} - -.p-apple-teal-dark-color{ - color: rgb(106, 196, 220); -} - -.p-apple-cyan-color{ - color: rgb(85,190,240); -} - -.p-apple-cyan-dark-color{ - color: rgb(90,200,245); -} - -.p-apple-blue-color{ - color: rgb(0, 122, 255); -} - -.p-apple-blue-dark-color{ - color: rgb(10, 132, 255); -} - -.p-apple-indigo-color{ - color: rgb(88, 86, 214); -} - -.p-apple-indigo-dark-color{ - color: rgb(94, 92, 230); -} - -.p-apple-purple-color{ - color: rgb(175, 82, 222); -} - -.p-apple-purple-dark-color{ - color: rgb(191, 90, 242); -} - -.p-apple-pink-color{ - color: rgb(255, 45, 85); -} - -.p-apple-pink-dark-color{ - color: rgb(255, 55, 95); -} - -.p-apple-brown-color{ - color: rgb(162, 132, 94); -} - -.p-apple-brown-dark-color{ - color: rgb(172, 142, 104); -} - -.p-apple-gray-color{ - color: rgb(142, 142, 147); -} - -.p-apple-gray-dark-color{ - color: rgb(152, 152, 157); -} - -.p-strawberry { - background: #c6262e; -} - -.p-strawberry-100 { - background: #ff8c82; -} - -.p-strawberry-300 { - background: #ed5353; -} - -.p-strawberry-500 { - background: #c6262e; -} - -.p-strawberry-700 { - background: #a10705; -} - -.p-strawberry-900 { - background: #7a0000; -} - -.p-orange { - background: #f37329; -} - -.p-orange-100 { - background: #ffc27d; -} - -.p-orange-300 { - background: #ffa154; -} - -.p-orange-500 { - background: #f37329; -} - -.p-orange-700 { - background: #cc3b02; -} - -.p-orange-900 { - background: #a62100; -} - -.p-banana { - background: #f9c440; -} - -.p-banana-100 { - background: #fff394; -} - -.p-banana-300 { - background: #ffe16b; -} - -.p-banana-500 { - background: #f9c440; -} - -.p-banana-700 { - background: #d48e15; -} - -.p-banana-900 { - background: #ad5f00; -} - -.p-lime { - background: #68b723; -} - -.p-lime-100 { - background: #d1ff82; -} - -.p-lime-300 { - background: #9bdb4d; -} - -.p-lime-500 { - background: #68b723; -} - -.p-lime-700 { - background: #3a9104; -} - -.p-lime-900 { - background: #206b00; -} - -.p-mint { - background: #28bca3; -} - -.p-mint-100 { - background: #89ffdd; -} - -.p-mint-300 { - background: #43d6b5; -} - -.p-mint-500 { - background: #28bca3; -} - -.p-mint-700 { - background: #0e9a83; -} - -.p-mint-900 { - background: #007367; -} - -.p-blueberry { - background: #3689e6; -} - -.p-blueberry-100 { - background: #8cd5ff; -} - -.p-blueberry-300 { - background: #64baff; -} - -.p-blueberry-500 { - background: #3689e6; -} - -.p-blueberry-700 { - background: #0d52bf; -} - -.p-blueberry-900 { - background: #002e99; -} - -.p-grape { - background: #a56de2; -} - -.p-grape-100 { - background: #e4c6fa; -} - -.p-grape-300 { - background: #cd9ef7; -} - -.p-grape-500 { - background: #a56de2; -} - -.p-grape-700 { - background: #7239b3; -} - -.p-grape-900 { - background: #452981; -} - -.p-bubblegum { - background: #de3e80; -} - -.p-bubblegum-100 { - background: #fe9ab8; -} - -.p-bubblegum-300 { - background: #f4679d; -} - -.p-bubblegum-500 { - background: #de3e80; -} - -.p-bubblegum-700 { - background: #bc245d; -} - -.p-bubblegum-900 { - background: #910e38; -} - -.p-cocoa { - background: #715344; -} - -.p-cocoa-100 { - background: #a3907c; -} - -.p-cocoa-300 { - background: #8a715e; -} - -.p-cocoa-500 { - background: #715344; -} - -.p-cocoa-700 { - background: #57392d; -} - -.p-cocoa-900 { - background: #3d211b; -} - -.p-silver { - background: #abacae; -} - -.p-silver-100 { - background: #fafafa; -} - -.p-silver-300 { - background: #d4d4d4; -} - -.p-silver-500 { - background: #abacae; -} - -.p-silver-700 { - background: #7e8087; -} - -.p-silver-900 { - background: #555761; -} - -.p-slate { - background: #485a6c; -} - -.p-slate-100 { - background: #95a3ab; -} - -.p-slate-300 { - background: #667885; -} - -.p-slate-500 { - background: #485a6c; -} - -.p-slate-700 { - background: #273445; -} - -.p-slate-900 { - background: #0e141f; -} - -.p-dark { - background: #333; -} - -.p-dark-100 { - background: #666; - /* hehe */ -} - -.p-dark-300 { - background: #4d4d4d; -} - -.p-dark-500 { - background: #333; -} - -.p-dark-700 { - background: #1a1a1a; -} - -.p-dark-900 { - background: #000; -} - -.p-white{ - background: #fff; -} - -.p-strawberry-color { - color: #c6262e; -} - -.p-strawberry-100-color { - color: #ff8c82; -} - -.p-strawberry-300-color { - color: #ed5353; -} - -.p-strawberry-500-color { - color: #c6262e; -} - -.p-strawberry-700-color { - color: #a10705; -} - -.p-strawberry-900-color { - color: #7a0000; -} - -.p-orange-color { - color: #f37329; -} - -.p-orange-100-color { - color: #ffc27d; -} - -.p-orange-300-color { - color: #ffa154; -} - -.p-orange-500-color { - color: #f37329; -} - -.p-orange-700-color { - color: #cc3b02; -} - -.p-orange-900-color { - color: #a62100; -} - -.p-banana-color { - color: #f9c440; -} - -.p-banana-100-color { - color: #fff394; -} - -.p-banana-300-color { - color: #ffe16b; -} - -.p-banana-500-color { - color: #f9c440; -} - -.p-banana-700-color { - color: #d48e15; -} - -.p-banana-900-color { - color: #ad5f00; -} - -.p-lime-color { - color: #68b723; -} - -.p-lime-100-color { - color: #d1ff82; -} - -.p-lime-300-color { - color: #9bdb4d; -} - -.p-lime-500-color { - color: #68b723; -} - -.p-lime-700-color { - color: #3a9104; -} - -.p-lime-900-color { - color: #206b00; -} - -.p-mint-color { - color: #28bca3; -} - -.p-mint-100-color { - color: #89ffdd; -} - -.p-mint-300-color { - color: #43d6b5; -} - -.p-mint-500-color { - color: #28bca3; -} - -.p-mint-700-color { - color: #0e9a83; -} - -.p-mint-900-color { - color: #007367; -} - -.p-blueberry-color { - color: #3689e6; -} - -.p-blueberry-100-color { - color: #8cd5ff; -} - -.p-blueberry-300-color { - color: #64baff; -} - -.p-blueberry-500-color { - color: #3689e6; -} - -.p-blueberry-700-color { - color: #0d52bf; -} - -.p-blueberry-900-color { - color: #002e99; -} - -.p-grape-color { - color: #a56de2; -} - -.p-grape-100-color { - color: #e4c6fa; -} - -.p-grape-300-color { - color: #cd9ef7; -} - -.p-grape-500-color { - color: #a56de2; -} - -.p-grape-700-color { - color: #7239b3; -} - -.p-grape-900-color { - color: #452981; -} - -.p-bubblegum-color { - color: #de3e80; -} - -.p-bubblegum-100-color { - color: #fe9ab8; -} - -.p-bubblegum-300-color { - color: #f4679d; -} - -.p-bubblegum-500-color { - color: #de3e80; -} - -.p-bubblegum-700-color { - color: #bc245d; -} - -.p-bubblegum-900-color { - color: #910e38; -} - -.p-cocoa-color { - color: #715344; -} - -.p-cocoa-100-color { - color: #a3907c; -} - -.p-cocoa-300-color { - color: #8a715e; -} - -.p-cocoa-500-color { - color: #715344; -} - -.p-cocoa-700-color { - color: #57392d; -} - -.p-cocoa-900-color { - color: #3d211b; -} - -.p-silver-color { - color: #abacae; -} - -.p-silver-100-color { - color: #fafafa; -} - -.p-silver-300-color { - color: #d4d4d4; -} - -.p-silver-500-color { - color: #abacae; -} - -.p-silver-700-color { - color: #7e8087; -} - -.p-silver-900-color { - color: #555761; -} - -.p-slate-color { - color: #485a6c; -} - -.p-slate-100-color { - color: #95a3ab; -} - -.p-slate-300-color { - color: #667885; -} - -.p-slate-500-color { - color: #485a6c; -} - -.p-slate-700-color { - color: #273445; -} - -.p-slate-900-color { - color: #0e141f; -} - -.p-dark-color { - color: #333; -} - -.p-dark-100-color { - color: #666; - /* hehe */ -} - -.p-dark-300-color { - color: #4d4d4d; -} - -.p-dark-500-color { - color: #333; -} - -.p-dark-700-color { - color: #1a1a1a; -} - -.p-dark-900-color { - color: #000; -} - -.p-white-color{ - color: #fff; -} diff --git a/v3/examples/android/frontend/public/puppertino/css/dark_mode.css b/v3/examples/android/frontend/public/puppertino/css/dark_mode.css deleted file mode 100644 index 3c5a03e80..000000000 --- a/v3/examples/android/frontend/public/puppertino/css/dark_mode.css +++ /dev/null @@ -1 +0,0 @@ -/* Puppertino dark_mode placeholder - local vendored */ diff --git a/v3/examples/android/frontend/public/puppertino/css/forms.css b/v3/examples/android/frontend/public/puppertino/css/forms.css deleted file mode 100644 index f2320ab1b..000000000 --- a/v3/examples/android/frontend/public/puppertino/css/forms.css +++ /dev/null @@ -1,509 +0,0 @@ -:root { - --primary-col:linear-gradient(to bottom, #4fc5fa 0%,#0f75f5 100%); - --primary-col-ac:#0f75f5; - --bg-color-input:#fff; - - --p-checkbox-gradient: linear-gradient(180deg, #4B91F7 0%, #367AF6 100%); - --p-checkbox-border: rgba(0, 0, 0, 0.2); - --p-checkbox-border-active: rgba(0, 0, 0, 0.12); - --p-checkbox-bg: transparent; - --p-checkbox-shadow: inset 0px 1px 2px rgba(0, 0, 0, 0.15), inset 0px 0px 2px rgba(0, 0, 0, 0.10); - - --p-input-bg:#fff; - --p-input-color: rgba(0,0,0,.85); - --p-input-color-plac:rgba(0,0,0,0.25); - - --p-input-color:#808080; - --p-input-bd:rgba(0,0,0,0.15); - --bg-hover-color:#f9f9f9; - --bg-front-col:#000; - --invalid-color:#d6513c; - --valid-color:#94d63c; -} - -.p-dark-mode{ - --p-checkbox-bg: linear-gradient(180deg, rgba(255, 255, 255, 0.1) 0%, rgba(255, 255, 255, 0.13) 100%); - --p-checkbox-shadow: 0px 0px 1px rgba(0, 0, 0, 0.25), inset 0px 0.5px 0px rgba(255, 255, 255, 0.15); - --p-checkbox-border: rgba(0, 0, 0, 0); - - --p-checkbox-gradient: linear-gradient(180deg, #3168DD 0%, #2C5FC8 100%); - --p-checkbox-border-active: rgba(0, 0, 0, 0); -} - -.p-form-select { - border-radius: 5px; - display: inline-block; - font-family: -apple-system, "Inter", sans-serif; - margin: 10px; - position: relative; -} - -.p-form-select > select:focus{ - outline: 2px solid #64baff; -} - -.p-form-select::after { - background: url("data:image/svg+xml,%3Csvg fill='none' xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 12'%3E%3Cpath d='M.288 4.117 3.16 1.18c.168-.168.336-.246.54-.246a.731.731 0 0 1 .538.246L7.108 4.12c.125.121.184.27.184.45 0 .359-.293.656-.648.656a.655.655 0 0 1-.48-.211L3.701 2.465l-2.469 2.55a.664.664 0 0 1-.48.212.656.656 0 0 1-.465-1.11Zm3.41 7.324a.73.73 0 0 0 .54-.246l2.87-2.941a.601.601 0 0 0 .184-.45.656.656 0 0 0-.648-.656.677.677 0 0 0-.48.211L3.701 9.91 1.233 7.36a.68.68 0 0 0-.48-.212.656.656 0 0 0-.465 1.11l2.871 2.937c.172.168.336.246.54.246Z' fill='white' style='mix-blend-mode:luminosity'/%3E%3C/svg%3E"), #017AFF; - background-size: 100% 75%; - background-position: center; - background-repeat: no-repeat; - border-radius: 5px; - bottom: 0; - content: ""; - display: block; - height: 80%; - pointer-events: none; - position: absolute; - right: 3%; - top: 10%; - width: 20px; -} - -.p-form-select > select { - -webkit-appearance: none; - appearance: none; - background: var(--p-input-bg); - border: 1px solid var(--p-input-bd); - border-radius: 5px; - font-size: 14px; - margin: 0; - outline: none; - padding: 5px 35px 5px 10px; - position: relative; - width: 100%; - color: var(--p-input-color); -} - -.p-form-text:invalid, -.p-form-text-alt:invalid{ - border-color: var(--invalid-color); -} - -.p-form-text:valid, -.p-form-text-alt:valid{ - border-color: var(--valid-color); -} - -.p-form-text:placeholder-shown, -.p-form-text-alt:placeholder-shown{ - border-color: var(--p-input-bd); -} - -.p-form-text { - color: var(--p-input-color); - -webkit-appearance: none; - appearance: none; - background: var(--p-input-bg); - border: 1px solid var(--p-input-bd); - border-radius: 5px; - font-family: -apple-system, "Inter", sans-serif; - font-size: 13px; - margin: 10px; - outline: 0; - padding: 3px 7px; - resize: none; - transition: border-color 200ms; - box-shadow: 0px 0.5px 2.5px rgba(0,0,0,.3), 0px 0px 0px rgba(0,0,0,.1); -} - -.p-form-text-alt { - color: var(--p-input-color); - -webkit-appearance: none; - appearance: none; - box-shadow: none; - background: var(--p-input-bg); - border: 0px; - border-bottom: 2px solid var(--p-input-bd); - padding: 10px; - border-top-left-radius: 3px; - border-top-right-radius: 3px; - margin: 10px; -} - - - -.p-form-text-alt::placeholder, -.p-form-text::placeholder -{ - color: var(--p-input-color-plac); -} - -.p-form-text:active, -.p-form-text:focus -{ - outline: 3px solid rgb(0 122 255 / 50%); -} - -.p-form-text-alt:focus { - outline: 0; - outline: 3px solid rgb(0 122 255 / 50%); - border-color: #3689e6; -} - -.p-form-no-validate:valid, -.p-form-no-validate:invalid{ - border-color: var(--p-input-bd); - color: var(--p-input-color)!important; -} - -.p-form-text:focus { - border-color: rgb(0 122 255); -} - -textarea.p-form-text { - -webkit-appearance: none; - appearance: none; - height: 100px; -} - -.p-form-truncated { - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; -} - -.p-form-text[type=password] { - font-family: caption; -} - -.p-form-label, -.p-form-radio-cont, -.p-form-checkbox-cont, -.p-form-label-inline { - font-family: -apple-system, "Inter", sans-serif; -} - -.p-form-label, .p-form-label-inline { - display: inline-block; -} - -.p-form-label{ - font-size: 11px; -} - -.p-form-label-inline { - background: var(--p-input-bg); - padding: 5px; - border-bottom: 2px solid var(--p-input-bd); - color: #656565; - font-weight: 500; - transition: .3s; -} - -.p-form-label-inline:focus-within { - color: #3689e6; - border-color: #3689e6; -} - -.p-form-label-inline > .p-form-text-alt { - border-bottom: 0px; - padding: 0; - outline: 0; - background: var(--p-input-bg); - -} - -.p-form-label-inline > .p-form-text-alt:-webkit-autofill{ - background: var(--p-input-bg); - -webkit-box-shadow: 0 0 0 30px rgba(0,0,0,0) inset !important; -} - -.p-form-label-inline > .p-form-text-alt:invalid { - color: var(--invalid-color); -} - -.p-form-label-inline > .p-form-text-alt:valid { - color: #3689e6; -} - -.p-form-label-inline > .p-form-text-alt:focus{ - color: var(--p-input-color); -} - -.p-form-radio-cont, -.p-form-checkbox-cont { - align-items: center; - display: inline-flex; - cursor: pointer; - margin: 0 10px; - user-select: none; -} - -.p-form-radio-cont > input + span, -.p-form-checkbox-cont > input + span { - background: var(--p-input-bg); - border: 1px solid var(--p-input-bd); - border-radius: 50%; - display: inline-block; - height: 20px; - margin-right: 5px; - position: relative; - transition: 0.2s; - width: 20px; -} - -.p-form-radio-cont > input + span{ - box-shadow: inset 0px 1px 2px rgba(0,0,0,0.10), inset 0px 0px 2px rgba(0,0,0,0.10); -} - -.p-form-radio-cont > input:focus + span, -.p-form-checkbox-cont > input:focus + span{ - outline: 3px solid rgb(0 122 255 / 50%); -} - -.p-form-radio-cont:hover > input + span{ - background: #f9f9f9; -} - -.p-form-radio-cont > input, -.p-form-checkbox-cont > input { - opacity: 0; - pointer-events: none; - position: absolute; -} - -.p-form-radio-cont > input + span::after { - background: #fff; - border-radius: 50%; - content: ""; - display: block; - height: 30%; - left: calc(50% - 15%); - opacity: 0; - position: absolute; - top: calc(50% - 15%); - transform: scale(2); - transition: opacity 0.2s, transform 0.3s; - width: 30%; -} - -.p-form-radio-cont > input:checked + span { - background: #0f75f5; - box-shadow: 0px 1px 2.5px 1px rgba(0, 122, 255, 0.24), inset 0px 0px 0px 0.5px rgba(0, 122, 255, 0.12); -} - -.p-form-radio-cont > input:checked + span::after { - opacity: 1; - transform: scale(1); -} - -.p-form-checkbox-cont > input + span { - border-radius: 5px; - box-shadow: var(--p-checkbox-shadow); - border: 0.5px solid var(--p-checkbox-border); - background: var(--p-checkbox-bg) -} - -.p-form-checkbox-cont > input:checked + span { - background: var(--p-checkbox-gradient); - border: 0.5px solid var(--p-checkbox-border-active); - box-shadow: 0px 1px 2.5px rgba(0, 122, 255, 0.24), 0px 0px 0px 0.5px rgba(0, 122, 255, 0.12); -} - -.p-form-checkbox-cont > input + span::before{ - content: ""; - display: block; - height: 100%; - width: 100%; - position: absolute; - left: 0%; - top: 0%; - opacity: 0; - transition: opacity 0.2s; - background-image: url("data:image/svg+xml,%3Csvg width='10' height='8' viewBox='0 0 10 8' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M4.10791 7.81299C3.83545 7.81299 3.6084 7.70459 3.42676 7.48779L1.15918 4.74121C1.08008 4.65039 1.02441 4.5625 0.992188 4.47754C0.959961 4.39258 0.943848 4.30469 0.943848 4.21387C0.943848 4.00586 1.0127 3.83447 1.15039 3.69971C1.29102 3.56201 1.4668 3.49316 1.67773 3.49316C1.91211 3.49316 2.10693 3.58838 2.26221 3.77881L4.10791 6.04297L7.68066 0.368652C7.77148 0.230957 7.86523 0.134277 7.96191 0.0786133C8.06152 0.0200195 8.18311 -0.00927734 8.32666 -0.00927734C8.5376 -0.00927734 8.71191 0.0581055 8.84961 0.192871C8.9873 0.327637 9.05615 0.497559 9.05615 0.702637C9.05615 0.778809 9.04297 0.85791 9.0166 0.939941C8.99023 1.02197 8.94922 1.10693 8.89355 1.19482L4.80225 7.45703C4.64111 7.69434 4.40967 7.81299 4.10791 7.81299Z' fill='white'/%3E%3C/svg%3E%0A"); - background-size: 70%; - background-position: center; - background-repeat: no-repeat; -} - -.p-form-checkbox-cont > input + span::after{ - content: ''; - width: 100%; - height: 100%; - position: absolute; - top: 0; - left: 0; - z-index: 9; -} - -.p-form-checkbox-cont > input + span:active::after{ - border-radius: 5px; - backdrop-filter: brightness(1.2); -} - -.p-form-checkbox-cont > input:checked + span::before{ - opacity: 1; -} - - -.p-form-checkbox-cont > input[disabled] + span, -.p-form-radio-cont > input[disabled] ~ span -{ - opacity: .7; - cursor: not-allowed; -} - -.p-form-button { - -webkit-appearance: none; - appearance: none; - background: #fff; - border: 1px solid var(--p-input-bd); - border-radius: 5px; - color: #333230; - display: inline-block; - font-size: 17px; - margin: 10px; - padding: 5px 20px; - text-decoration: none; -} - -.p-form-send { - background: linear-gradient(to bottom, #4fc5fa 0%, #0f75f5 100%); - border: 0; - color: #fff; -} - -.p-form-send:active { - background: #0f75f5; -} - -.p-form-invalid, -.p-form-invalid:placeholder-shown, -.p-form-invalid:valid, -.p-form-invalid:invalid { - border-color: var(--invalid-color); -} - -.p-form-valid, -.p-form-valid:placeholder-shown, -.p-form-valid:valid, -.p-form-valid:invalid { - border-color: var(--valid-color); -} - -.p-form-switch { - --width: 80px; - cursor: pointer; - display: inline-block; -} - -.p-form-switch > input:checked + span::after { - left: calc(100% - calc(var(--width) / 1.8)); -} - -.p-form-switch > input:checked + span { - background: #60c35b; -} - -.p-form-switch > span { - background: #e0e0e0; - border: 1px solid #d3d3d3; - border-radius: 500px; - display: block; - height: calc(var(--width) / 1.6); - position: relative; - transition: all 0.2s; - width: var(--width); -} - -.p-form-switch > span::after { - background: #f9f9f9; - border-radius: 50%; - border: 0.5px solid rgba(0, 0, 0, 0.101987); - box-shadow: 0px 3px 1px rgba(0, 0, 0, 0.1), 0px 1px 1px rgba(0, 0, 0, 0.16), 0px 3px 8px rgba(0, 0, 0, 0.15); - box-sizing: border-box; - content: ""; - height: 84%; - left: 3%; - position: absolute; - top: 6.5%; - transition: all 0.2s; - width: 52.5%; -} - -.p-form-switch > input { - display: none; -} - -.p-chip input{ - opacity: 0; - pointer-events: none; - position: absolute; -} - -.p-chip span{ - padding: .8rem 1rem; - border-radius: 1.6rem; - display:inline-block; - margin:10px; - background: #e4e4e4ca; - color: #3689e6; - transition: .3s; - user-select: none; - cursor:pointer; - font-family: -apple-system, "Inter", sans-serif; - font-size: 1rem; - -webkit-tap-highlight-color: rgba(0, 0, 0, 0); - -moz-tap-highlight-color: rgba(0, 0, 0, 0); - text-align:center; -} - -.p-chip:focus-within span{ - outline: 2px solid #64baff; -} - -.p-chip svg{ - display:block; - margin:auto; -} - - -.p-chip input:checked + span{ - background: #3689e6; - color:#fff; -} - -.p-chip-outline span, .p-chip-outline-to-bg span{ - background: transparent; - color: #3e3e3e; - border: 1px solid currentColor; -} - -.p-chip-outline input:checked + span{ - background: transparent; - color: #3689e6; -} - -.p-chip-radius-b span{ - border-radius: 5px; -} - -.p-chip-dark span{ - color: #3e3e3e; -} - -.p-chip-dark input:checked + span{ - background: #3e3e3e; -} - -.p-chip input:disabled + span, -.p-chip input[disabled] + span{ - opacity: .5; - cursor: not-allowed; -} - -.p-chip-big span{ - font-size: 1.3rem; - padding: 1.5rem; - min-width: 80px; -} - -.p-form-checkbox-cont[disabled], -.p-form-label[disabled], -.p-form-text[disabled], -.p-form-text-alt[disabled], -.p-form-select[disabled], -.p-form-radio-cont[disabled]{ - filter: grayscale(1) opacity(.3); - pointer-events: none; -} diff --git a/v3/examples/android/frontend/public/puppertino/css/layout.css b/v3/examples/android/frontend/public/puppertino/css/layout.css deleted file mode 100644 index 1f9b36845..000000000 --- a/v3/examples/android/frontend/public/puppertino/css/layout.css +++ /dev/null @@ -1,45 +0,0 @@ -.p-large-title{ - font-size: 2.75rem; -} - -.p-layout h1 { - font-size: 2.25rem; -} - -.p-layout h2 { - font-size: 1.75rem; -} - -.p-layout h3 { - font-size: 1.58rem; -} - -.p-headline { - font-size: 1.34rem; - font-weight: bold; -} - -.p-layout p { - font-size: 1.15rem; -} - -.p-layout .link, -.p-layout input { - font-size: 0.813rem; -} - -.p-callout { - font-size: 1.14rem; -} - -.p-subhead { - font-size: 1.167rem; -} - -.p-footnote { - font-size: 1.07rem; -} - -.p-caption { - font-size: 0.91rem; -} diff --git a/v3/examples/android/frontend/public/puppertino/css/modals.css b/v3/examples/android/frontend/public/puppertino/css/modals.css deleted file mode 100644 index 4d718c4f7..000000000 --- a/v3/examples/android/frontend/public/puppertino/css/modals.css +++ /dev/null @@ -1 +0,0 @@ -/* Puppertino modals placeholder - local vendored */ diff --git a/v3/examples/android/frontend/public/puppertino/css/newfull.css b/v3/examples/android/frontend/public/puppertino/css/newfull.css deleted file mode 100644 index 622a2f364..000000000 --- a/v3/examples/android/frontend/public/puppertino/css/newfull.css +++ /dev/null @@ -1,11 +0,0 @@ -@import url('actions.css'); -@import url('buttons.css'); -@import url('layout.css'); -@import url('cards.css'); -@import url('color_palette.css'); -@import url('forms.css'); -@import url('modals.css'); -@import url('segmented-controls.css'); -@import url('shadows.css'); -@import url('tabs.css'); -@import url('dark_mode.css'); diff --git a/v3/examples/android/frontend/public/puppertino/css/segmented-controls.css b/v3/examples/android/frontend/public/puppertino/css/segmented-controls.css deleted file mode 100644 index 22819fd5f..000000000 --- a/v3/examples/android/frontend/public/puppertino/css/segmented-controls.css +++ /dev/null @@ -1 +0,0 @@ -/* Puppertino segmented-controls placeholder - local vendored */ diff --git a/v3/examples/android/frontend/public/puppertino/css/shadows.css b/v3/examples/android/frontend/public/puppertino/css/shadows.css deleted file mode 100644 index 060a61658..000000000 --- a/v3/examples/android/frontend/public/puppertino/css/shadows.css +++ /dev/null @@ -1 +0,0 @@ -/* Puppertino shadows placeholder - local vendored */ diff --git a/v3/examples/android/frontend/public/puppertino/css/tabs.css b/v3/examples/android/frontend/public/puppertino/css/tabs.css deleted file mode 100644 index 61d1487ca..000000000 --- a/v3/examples/android/frontend/public/puppertino/css/tabs.css +++ /dev/null @@ -1 +0,0 @@ -/* Puppertino tabs placeholder - local vendored */ diff --git a/v3/examples/android/frontend/public/puppertino/puppertino.css b/v3/examples/android/frontend/public/puppertino/puppertino.css deleted file mode 100644 index 905da220e..000000000 --- a/v3/examples/android/frontend/public/puppertino/puppertino.css +++ /dev/null @@ -1,1774 +0,0 @@ -@charset "UTF-8"; -.p-btn { - background: #fff; - border: 1px solid #cacaca; - border-radius: 5px; - color: #333230; - display: inline-block; - font-family: -apple-system, "Inter", sans-serif; - font-size: 17px; - margin: 10px; - padding: 5px 20px; - text-decoration: none; - /* text-shadow: 0 1px 1px rgba(0, 0, 0, 0.25); */ -} -.p-btn-mob{ - padding: 10px 40px; - background: #0f75f5; - color: #fff; -} -.p-btn[disabled] { - background: #d3d3d3; - color: #555; - cursor: not-allowed; -} -.p-btn:disabled { - background: #d3d3d3; - color: #555; - cursor: not-allowed; -} -.p-btn-disabled { - background: #d3d3d3; - color: #555; - cursor: not-allowed; -} - -.p-prim-col { - background: linear-gradient(to bottom, #4fc5fa 0%, #0f75f5 100%); - border: 0; - color: #fff; -} - -.p-btn.p-prim-col:active { - background: #0f75f5; -} - -.p-btn-more::after { - content: "..."; -} - -.p-btn-round { - border: 0; - border-radius: 50px; - padding: 10px 30px; -} - -.p-btn-icon { - align-items: center; - background: #fff; - border: 2px solid currentColor; - border-radius: 50%; - box-shadow: 0 3px 10px -8px #000; - color: #0f75f5; - display: inline-flex; - font-weight: 900; - height: 36px; - justify-content: center; - margin: 5px; - text-align: center; - text-decoration: none; - width: 36px; -} - -.p-btn-scope { - background: #8e8e8e; - color: #fff; - margin: 5px; - padding: 2px 20px; -} -.p-btn-scope-unactive { - background: transparent; - border-color: transparent; - color: #212136; - transition: border-color 0.2s; -} -.p-btn-scope-unactive:hover { - border-color: #cacaca; -} -.p-btn-scope-disabled { - background: transparent; - color: #8e8e8e; - cursor: not-allowed; -} -.p-btn-scope-outline { - background: transparent; - color: #212136; -} - -.p-btn-scope-outline { - background: transparent; - color: #212136; -} - -.p-btn-outline { - background: none; - border-color: currentColor; -} - -.p-btn-outline-dash { - background: none; - border-color: currentColor; - border-style: dashed; -} - -.p-btn-direction { - color: #212136; - padding: 5px; - text-decoration: none; -} - -.p-btn-direction.p-btn-d-back::before { - content: "❬"; -} - -.p-btn-direction.p-btn-d-next::after { - content: "❭"; -} - -@media (max-width: 576px) { - .p-btn-big-sm { - border: 0; - border-radius: 0%; - bottom: 0; - font-size: 50px; - left: 0; - margin: 0; - padding: 10px 0; - position: fixed; - text-align: center; - width: 100%; - } -} - -/*END OF BUTTONS*/ - -.p-card { - background: rgba(255, 255, 255, 0.3); - border: 1px solid rgba(0, 0, 0, 0.1); - border-radius: 3px; - box-shadow: 0 8px 10px -8px rgba(0, 0, 0, 0.1); - color: #000; - display: block; - margin-top: 30px; - text-decoration: none; -} -.p-card-image > img { - border-bottom: 3px solid var(--accent-article); - display: block; - margin: auto; - width: 100%; -} -.p-card-tags { - display: flex; - overflow: hidden; - position: relative; - width: 100%; -} -.p-card-tags::before { - background: linear-gradient(to right, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0) 75%, white 100%); - content: ""; - height: 100%; - position: absolute; - right: 0; - top: 0; - width: 30%; -} -.p-card-tags span, -.p-card-tags a { - border: 1px solid #252525; - border-radius: 50px; - color: #252525; - margin: 5px; - padding: 5px 15px; - text-decoration: none; - transition: all 0.2s; -} -.p-card-tags a:hover { - background: #252525; - color: #000; -} -.p-card-title { - font-size: 2rem; - margin-bottom: 15px; - margin-top: 10px; -} -.p-card-content { - padding: 15px; - padding-top: 5px; -} -.p-card-text { - font-size: 17px; - margin-bottom: 10px; - margin-left: 10px; - margin-top: 0; -} - - -/* END OF CARDS*/ - -.p-strawberry { - background: #c6262e; -} - -.p-strawberry-100 { - background: #ff8c82; -} - -.p-strawberry-300 { - background: #ed5353; -} - -.p-strawberry-500 { - background: #c6262e; -} - -.p-strawberry-700 { - background: #a10705; -} - -.p-strawberry-900 { - background: #7a0000; -} - -.p-orange { - background: #f37329; -} - -.p-orange-100 { - background: #ffc27d; -} - -.p-orange-300 { - background: #ffa154; -} - -.p-orange-500 { - background: #f37329; -} - -.p-orange-700 { - background: #cc3b02; -} - -.p-orange-900 { - background: #a62100; -} - -.p-banana { - background: #f9c440; -} - -.p-banana-100 { - background: #fff394; -} - -.p-banana-300 { - background: #ffe16b; -} - -.p-banana-500 { - background: #f9c440; -} - -.p-banana-700 { - background: #d48e15; -} - -.p-banana-900 { - background: #ad5f00; -} - -.p-lime { - background: #68b723; -} - -.p-lime-100 { - background: #d1ff82; -} - -.p-lime-300 { - background: #9bdb4d; -} - -.p-lime-500 { - background: #68b723; -} - -.p-lime-700 { - background: #3a9104; -} - -.p-lime-900 { - background: #206b00; -} - -.p-mint { - background: #28bca3; -} - -.p-mint-100 { - background: #89ffdd; -} - -.p-mint-300 { - background: #43d6b5; -} - -.p-mint-500 { - background: #28bca3; -} - -.p-mint-700 { - background: #0e9a83; -} - -.p-mint-900 { - background: #007367; -} - -.p-blueberry { - background: #3689e6; -} - -.p-blueberry-100 { - background: #8cd5ff; -} - -.p-blueberry-300 { - background: #64baff; -} - -.p-blueberry-500 { - background: #3689e6; -} - -.p-blueberry-700 { - background: #0d52bf; -} - -.p-blueberry-900 { - background: #002e99; -} - -.p-grape { - background: #a56de2; -} - -.p-grape-100 { - background: #e4c6fa; -} - -.p-grape-300 { - background: #cd9ef7; -} - -.p-grape-500 { - background: #a56de2; -} - -.p-grape-700 { - background: #7239b3; -} - -.p-grape-900 { - background: #452981; -} - -.p-bubblegum { - background: #de3e80; -} - -.p-bubblegum-100 { - background: #fe9ab8; -} - -.p-bubblegum-300 { - background: #f4679d; -} - -.p-bubblegum-500 { - background: #de3e80; -} - -.p-bubblegum-700 { - background: #bc245d; -} - -.p-bubblegum-900 { - background: #910e38; -} - -.p-cocoa { - background: #715344; -} - -.p-cocoa-100 { - background: #a3907c; -} - -.p-cocoa-300 { - background: #8a715e; -} - -.p-cocoa-500 { - background: #715344; -} - -.p-cocoa-700 { - background: #57392d; -} - -.p-cocoa-900 { - background: #3d211b; -} - -.p-silver { - background: #abacae; -} - -.p-silver-100 { - background: #fafafa; -} - -.p-silver-300 { - background: #d4d4d4; -} - -.p-silver-500 { - background: #abacae; -} - -.p-silver-700 { - background: #7e8087; -} - -.p-silver-900 { - background: #555761; -} - -.p-slate { - background: #485a6c; -} - -.p-slate-100 { - background: #95a3ab; -} - -.p-slate-300 { - background: #667885; -} - -.p-slate-500 { - background: #485a6c; -} - -.p-slate-700 { - background: #273445; -} - -.p-slate-900 { - background: #0e141f; -} - -.p-dark { - background: #333; -} - -.p-dark-100 { - background: #666; - /* hehe */ -} - -.p-dark-300 { - background: #4d4d4d; -} - -.p-dark-500 { - background: #333; -} - -.p-dark-700 { - background: #1a1a1a; -} - -.p-dark-900 { - background: #000; -} - -.p-strawberry-color { - color: #c6262e; -} - -.p-strawberry-100-color { - color: #ff8c82; -} - -.p-strawberry-300-color { - color: #ed5353; -} - -.p-strawberry-500-color { - color: #c6262e; -} - -.p-strawberry-700-color { - color: #a10705; -} - -.p-strawberry-900-color { - color: #7a0000; -} - -.p-orange-color { - color: #f37329; -} - -.p-orange-100-color { - color: #ffc27d; -} - -.p-orange-300-color { - color: #ffa154; -} - -.p-orange-500-color { - color: #f37329; -} - -.p-orange-700-color { - color: #cc3b02; -} - -.p-orange-900-color { - color: #a62100; -} - -.p-banana-color { - color: #f9c440; -} - -.p-banana-100-color { - color: #fff394; -} - -.p-banana-300-color { - color: #ffe16b; -} - -.p-banana-500-color { - color: #f9c440; -} - -.p-banana-700-color { - color: #d48e15; -} - -.p-banana-900-color { - color: #ad5f00; -} - -.p-lime-color { - color: #68b723; -} - -.p-lime-100-color { - color: #d1ff82; -} - -.p-lime-300-color { - color: #9bdb4d; -} - -.p-lime-500-color { - color: #68b723; -} - -.p-lime-700-color { - color: #3a9104; -} - -.p-lime-900-color { - color: #206b00; -} - -.p-mint-color { - color: #28bca3; -} - -.p-mint-100-color { - color: #89ffdd; -} - -.p-mint-300-color { - color: #43d6b5; -} - -.p-mint-500-color { - color: #28bca3; -} - -.p-mint-700-color { - color: #0e9a83; -} - -.p-mint-900-color { - color: #007367; -} - -.p-blueberry-color { - color: #3689e6; -} - -.p-blueberry-100-color { - color: #8cd5ff; -} - -.p-blueberry-300-color { - color: #64baff; -} - -.p-blueberry-500-color { - color: #3689e6; -} - -.p-blueberry-700-color { - color: #0d52bf; -} - -.p-blueberry-900-color { - color: #002e99; -} - -.p-grape-color { - color: #a56de2; -} - -.p-grape-100-color { - color: #e4c6fa; -} - -.p-grape-300-color { - color: #cd9ef7; -} - -.p-grape-500-color { - color: #a56de2; -} - -.p-grape-700-color { - color: #7239b3; -} - -.p-grape-900-color { - color: #452981; -} - -.p-bubblegum-color { - color: #de3e80; -} - -.p-bubblegum-100-color { - color: #fe9ab8; -} - -.p-bubblegum-300-color { - color: #f4679d; -} - -.p-bubblegum-500-color { - color: #de3e80; -} - -.p-bubblegum-700-color { - color: #bc245d; -} - -.p-bubblegum-900-color { - color: #910e38; -} - -.p-cocoa-color { - color: #715344; -} - -.p-cocoa-100-color { - color: #a3907c; -} - -.p-cocoa-300-color { - color: #8a715e; -} - -.p-cocoa-500-color { - color: #715344; -} - -.p-cocoa-700-color { - color: #57392d; -} - -.p-cocoa-900-color { - color: #3d211b; -} - -.p-silver-color { - color: #abacae; -} - -.p-silver-100-color { - color: #fafafa; -} - -.p-silver-300-color { - color: #d4d4d4; -} - -.p-silver-500-color { - color: #abacae; -} - -.p-silver-700-color { - color: #7e8087; -} - -.p-silver-900-color { - color: #555761; -} - -.p-slate-color { - color: #485a6c; -} - -.p-slate-100-color { - color: #95a3ab; -} - -.p-slate-300-color { - color: #667885; -} - -.p-slate-500-color { - color: #485a6c; -} - -.p-slate-700-color { - color: #273445; -} - -.p-slate-900-color { - color: #0e141f; -} - -.p-dark-color { - color: #333; -} - -.p-dark-100-color { - color: #666; - /* hehe */ -} - -.p-dark-300-color { - color: #4d4d4d; -} - -.p-dark-500-color { - color: #333; -} - -.p-dark-700-color { - color: #1a1a1a; -} - -.p-dark-900-color { - color: #000; -} - -/* END OF COLORS */ - -:root { - --primary-col:linear-gradient(to bottom, #4fc5fa 0%,#0f75f5 100%); - --primary-col-ac:#0f75f5; - --bg-color:#fff; - --bg-hover-color:#f9f9f9; - --bg-front-col:#000; - --invalid-color:#d6513c; - --valid-color:#94d63c; -} - -.p-form-select { - border-radius: 5px; - display: inline-block; - font-family: -apple-system, "Inter", sans-serif; - margin: 10px; - position: relative; -} - -.p-form-select::before { - border-color: #fff transparent transparent; - border-style: solid; - border-width: 5px; - content: ""; - pointer-events: none; - position: absolute; - right: 5px; - top: calc(50% - 3px); - z-index: 3; -} - -.p-form-select::after { - background: linear-gradient(to bottom, #4fc5fa 0%, #0f75f5 100%); - border-bottom-right-radius: 5px; - border-top-right-radius: 5px; - bottom: 0; - content: ""; - display: block; - height: 100%; - pointer-events: none; - position: absolute; - right: 0; - top: 0; - width: 20px; -} - -.p-form-select > select { - -webkit-appearance: none; - background: #fff; - border: 1px solid #cacaca; - border-radius: 5px; - font-size: 14px; - margin: 0; - outline: none; - padding: 5px 30px 5px 10px; - position: relative; - width: 100%; -} - -.p-form-text:invalid, -.p-form-text-alt:invalid, -.p-form-select > select:invalid { - border-color: var(--invalid-color); -} - -.p-form-text:valid, -.p-form-text-alt:valid, -.p-form-select > select:valid { - border-color: var(--valid-color); -} - -.p-form-text:placeholder-shown, -.p-form-text-alt:placeholder-shown, -.p-form-select > select:placeholder-shown { - border-color: #cacaca; -} - -.p-form-text { - -webkit-appearance: none; - box-shadow: none; - background: #fff; - border: 1px solid #cacaca; - border-radius: 5px; - font-family: -apple-system, "Inter", sans-serif; - margin: 10px; - outline: 0; - padding: 5px; - resize: none; - transition: border-color 200ms; -} - -.p-form-text-alt { - -webkit-appearance: none; - box-shadow: none; - background: #fff; - border: 0px; - border-bottom: 2px solid #cacaca; - padding: 10px; - border-top-left-radius: 5px; - border-top-right-radius: 5px; - margin: 10px; -} - -.p-form-text-alt::placeholder { - color: #cacaca; -} - -.p-form-text-alt:focus { - outline: 3px solid #bed8f9; -} - -.p-form-no-validate:valid, -.p-form-no-validate:invalid, -.p-form-no-validate > select:valid, -.p-form-no-validate > select:invalid { - border-color: #cacaca; -} - -.p-form-text:focus { - border-color: #0f75f5; -} - -textarea.p-form-text { - -webkit-appearance: none; - height: 100px; -} - -.p-form-truncated { - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; -} - -.p-form-text[type=password] { - font-family: caption; -} - -.p-form-label, -.p-form-radio-cont, -.p-form-checkbox-cont { - font-family: -apple-system, "Inter", sans-serif; -} - -.p-form-label { - display: block; -} - -.p-form-radio-cont, -.p-form-checkbox-cont { - align-items: center; - display: inline-flex; - margin: 0 10px; -} - -.p-form-radio-cont > input + span, -.p-form-checkbox-cont > input + span { - background: #fff; - border: 1px solid #cacaca; - border-radius: 50%; - cursor: pointer; - display: inline-block; - height: 20px; - margin-right: 5px; - position: relative; - transition: background 0.2s; - width: 20px; -} - -.p-form-radio-cont > input + span:hover { - background: #f9f9f9; -} - -.p-form-radio-cont > input, -.p-form-checkbox-cont > input { - opacity: 0; - pointer-events: none; - position: absolute; -} - -.p-form-radio-cont > input + span::after { - background: #fff; - border-radius: 50%; - box-shadow: 0 1px 2px rgba(0, 0, 0, 0.3); - content: ""; - display: block; - height: 30%; - left: calc(50% - 15%); - opacity: 0; - position: absolute; - top: calc(50% - 15%); - transform: scale(2); - transition: opacity 0.2s, transform 0.3s; - width: 30%; -} - -.p-form-radio-cont > input:checked + span { - background: #0f75f5; -} - -.p-form-radio-cont > input:checked + span::after { - opacity: 1; - transform: scale(1); -} - -.p-form-checkbox-cont > input + span { - border-radius: 5px; -} - -.p-form-checkbox-cont > input:checked + span { - background: #0f75f5; -} - -.p-form-checkbox-cont > input + span::before, -.p-form-checkbox-cont > input + span::after { - background: #fff; - border-radius: 20px; - content: ""; - display: block; - height: 8%; - position: absolute; -} - -.p-form-checkbox-cont > input + span::before { - right: 30%; - top: 15%; - transform: rotate(-65deg); - transform-origin: top right; - width: 70%; -} - -.p-form-checkbox-cont > input + span::after { - left: 30%; - top: 43%; - transform: rotate(60deg); - transform-origin: top left; - width: 40%; -} - -.p-form-button { - -webkit-appearance: none; - background: #fff; - border: 1px solid #cacaca; - border-radius: 5px; - color: #333230; - display: inline-block; - font-size: 17px; - margin: 10px; - padding: 5px 20px; - text-decoration: none; - /* text-shadow: 0 1px 1px rgba(0, 0, 0, 0.25); */ -} - -.p-form-send { - background: linear-gradient(to bottom, #4fc5fa 0%, #0f75f5 100%); - border: 0; - color: #fff; -} - -.p-form-send:active { - background: #0f75f5; -} - -.p-form-invalid, -.p-form-invalid:placeholder-shown, -.p-form-invalid:valid, -.p-form-invalid:invalid { - border-color: var(--invalid-color); -} - -.p-form-valid, -.p-form-valid:placeholder-shown, -.p-form-valid:valid, -.p-form-valid:invalid { - border-color: var(--valid-color); -} - -.p-form-switch { - --width: 80px; - cursor: pointer; - display: inline-block; -} - -.p-form-switch > input:checked + span::after { - left: calc(100% - calc(var(--width) / 2.1)); -} - -.p-form-switch > input:checked + span { - background: #60c35b; -} - -.p-form-switch > span { - background: #e0e0e0; - border: 1px solid #d3d3d3; - border-radius: 500px; - display: block; - height: calc(var(--width) / 2); - overflow: hidden; - position: relative; - transition: all 0.2s; - width: var(--width); -} - -.p-form-switch > span::after { - background: #f9f9f9; - border-radius: 50%; - box-shadow: 0px 3px 1px rgba(0, 0, 0, 0.1), 0px 1px 1px rgba(0, 0, 0, 0.16), 0px 3px 8px rgba(0, 0, 0, 0.15); - content: ""; - height: 90%; - left: 3%; - position: absolute; - top: 4.5%; - transition: all 0.2s; - width: 45%; -} - -.p-form-switch > input { - display: none; -} - -input[type=range].p-form-range { - width: 100%; - margin: 11.5px 0; - background-color: transparent; - -webkit-appearance: none; -} -input[type=range].p-form-range:focus { - outline: none; -} -input[type=range].p-form-range::-webkit-slider-runnable-track { - background: #cacaca; - border: 0; - width: 100%; - height: 2px; - cursor: pointer; -} -input[type=range].p-form-range::-webkit-slider-thumb { - margin-top: -11.5px; - width: 25px; - height: 25px; - background: #ffffff; - border: 1px solid rgba(115, 115, 115, 0.6); - border-radius: 30px; - cursor: pointer; - box-shadow: 0 3px 1px rgba(0, 0, 0, 0.1), 0 1px 1px rgba(0, 0, 0, 0.16), 0 3px 8px rgba(0, 0, 0, 0.15); - -webkit-appearance: none; -} -input[type=range].p-form-range:focus::-webkit-slider-runnable-track { - background: #d7d7d7; -} -input[type=range].p-form-range::-moz-range-track { - background: #cacaca; - border: 0; - width: 100%; - height: 2px; - cursor: pointer; -} -input[type=range].p-form-range::-moz-range-thumb { - width: 25px; - height: 25px; - background: #ffffff; - border: 1px solid rgba(115, 115, 115, 0.6); - border-radius: 30px; - box-shadow: 0 3px 1px rgba(0, 0, 0, 0.1), 0 1px 1px rgba(0, 0, 0, 0.16), 0 3px 8px rgba(0, 0, 0, 0.15); - cursor: pointer; -} -input[type=range].p-form-range::-ms-track { - background: transparent; - border-color: transparent; - border-width: 26.5px 0; - color: transparent; - width: 100%; - height: 2px; - cursor: pointer; -} -input[type=range].p-form-range::-ms-fill-lower { - background: #bdbdbd; - border: 0; -} -input[type=range].p-form-range::-ms-fill-upper { - background: #cacaca; - border: 0; -} -input[type=range].p-form-range::-ms-thumb { - width: 25px; - height: 25px; - background: #ffffff; - border: 1px solid rgba(115, 115, 115, 0.6); - border-radius: 30px; - cursor: pointer; - box-shadow: 0 3px 1px rgba(0, 0, 0, 0.1), 0 1px 1px rgba(0, 0, 0, 0.16), 0 3px 8px rgba(0, 0, 0, 0.15); - margin-top: 0px; - /*Needed to keep the Edge thumb centred*/ -} -input[type=range].p-form-range:focus::-ms-fill-lower { - background: #cacaca; -} -input[type=range].p-form-range:focus::-ms-fill-upper { - background: #d7d7d7; -} -/*TODO: Use one of the selectors from https://stackoverflow.com/a/20541859/7077589 and figure out -how to remove the virtical space around the range input in IE*/ -@supports (-ms-ime-align:auto) { - /* Pre-Chromium Edge only styles, selector taken from hhttps://stackoverflow.com/a/32202953/7077589 */ - input[type=range].p-form-range { - margin: 0; - /*Edge starts the margin from the thumb, not the track as other browsers do*/ - } -} - - -/* END OF FORMS */ - -.p-layout .p-large-title { - font-size: 2.75rem; -} - -.p-layout h1 { - font-size: 2.25rem; -} - -.p-layout h2 { - font-size: 1.75rem; -} - -.p-layout h3 { - font-size: 1.58rem; -} - -.p-layout .p-headline { - font-size: 1.34rem; - font-weight: bold; -} - -.p-layout p { - font-size: 1.15rem; -} - -.p-layout a, -.p-layout input { - font-size: 1.14rem; -} - -.p-layout .p-callout { - font-size: 1.14rem; -} - -.p-layout .p-subhead { - font-size: 1.167rem; -} - -.p-layout .p-footnote { - font-size: 1.07rem; -} - -.p-layout .p-caption { - font-size: 0.91rem; -} - -/* END OF LAYOUT */ - -:root { - --font: -apple-system, "Inter", sans-serif; - --bg-hover-color: #f9f9f9; - --primary-col-ac: #0f75f5; -} - -.p-modal-opened { - overflow: hidden; -} - -.p-modal-background { - background: rgba(0, 0, 0, 0.3); - height: 100vh; - left: 0; - opacity: 0; - pointer-events: none; - position: fixed; - top: 0; - transition: all 0.3s; - width: 100vw; - z-index: 5; -} - -.p-modal { - background: rgba(255, 255, 255, 0.85); - border-radius: 20px; - top: calc(50% - 20vh); - bottom: unset; - box-shadow: 0 10px 20px -15px; - font-family: var(--font); - left: calc(50% - 20vw); - opacity: 0; - overflow: hidden; - pointer-events: none; - position: fixed; - text-align: center; - transform: scale(1.5); - transition: opacity 0.3s, transform 0.3s; - width: 40vw; - z-index: 9; -} - -.p-modal.active { - backdrop-filter: saturate(180%) blur(10px); - opacity: 1; - pointer-events: auto; - transform: scale(1); -} - -.p-modal-button-container { - border-radius: 20px; - display: flex; -} - -.p-modal-button-container > a { - border-top: 1px solid rgba(0, 0, 0, 0.1); - color: var(--primary-col-ac); - padding: 30px 0%; - text-decoration: none; - width: 100%; -} - -.p-modal-button-container > a:nth-child(2), -.p-modal-button-container > a:nth-child(3) { - border-left: 1px solid rgba(0, 0, 0, 0.1); -} - -.nowactive { - opacity: 1; - pointer-events: auto; -} - -.p-modal p { - padding: 0% 5%; -} - -@supports not (backdrop-filter: blur(5px)) { - .p-modal { - background: #fff; - } -} -@media (max-width: 568px) { - .p-modal { - bottom: 20%; - left: 15%; - top: unset; - width: 70vw; - } - - .p-modal p { - font-size: 15px; - padding: 0% 10%; - } - - .p-modal-button-container { - display: block; - } - - .p-modal-button-container > a { - border-left: 0 !important; - display: block; - padding: 2vh 0%; - } -} - -/* END OF MODALS */ - -.p-segmented-controls { - --color-segmented: #3689e6; - --color-lighter-segment: #d2e3f9; - background: #fff; - border: 1px solid var(--color-segmented); - border-radius: 5px; - display: flex; - flex-wrap: wrap; - font-family: -apple-system, "Inter", sans-serif; - margin-top: 10px; - overflow: hidden; - width: 100%; -} -.p-segmented-controls a { - color: var(--color-segmented); - flex: auto; - padding: 10px; - text-align: center; - text-decoration: none; - transition: all 0.5s; -} -.p-segmented-controls a.active { - background: var(--color-segmented); - color: #fff; -} -.p-segmented-controls a:not(:first-child) { - border-left: 1px solid currentColor; -} - -.p-segmented-radius { - border-radius: 30px; -} - -.p-segmented-internal-radius a, -.p-segmented-internal-radius a:not(:first-child) { - border: 0; - border-radius: 30px; -} - -.p-segmented-controls-alt a:not(:first-child) { - border: 0; -} -.p-segmented-controls-alt a:not(:first-child).active { - background: var(--color-lighter-segment); - color: var(--color-segmented); - font-weight: bold; -} - -.p-segmented-outline { - border: 2px solid var(--color-segmented); -} -.p-segmented-outline a:not(:first-child) { - border-left: 2px solid var(--color-segmented); -} - -.p-segmented-controls-outline-alt a:not(:first-child) { - border: 2px solid transparent; -} - -.p-segmented-controls-outline-alt { - border-radius: 30px; -} -.p-segmented-controls-outline-alt a { - border: 2px solid transparent; - border-radius: 30px; -} -.p-segmented-controls-outline-alt a.active { - background: #fff; - border-color: var(--color-segmented); - border-radius: 30px; - color: var(--color-segmented); - font-weight: bold; -} - -.p-segmented-grey { - --color-segmented: #555761; - --color-lighter-segment: #d4d4d4; -} - -/* END OF SEGMENTED CONTROLS */ - -.p-shadow-1 { - box-shadow: 0 3px 10px rgba(0, 0, 0, 0.1); -} - -.p-shadow-2 { - box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); -} - -.p-shadow-3 { - box-shadow: 0 10px 18px rgba(0, 0, 0, 0.3); -} - -.p-shadow-4 { - box-shadow: 0 25px 30px rgba(0, 0, 0, 0.2); -} - -.p-to-shadow-4, -.p-to-shadow-3, -.p-to-shadow-2, -.p-to-shadow-1 { - transition-timing-function: ease; - transition: box-shadow 0.5s; -} - -.p-to-shadow-1:hover { - box-shadow: 0 3px 10px rgba(0, 0, 0, 0.1);> -} - -.p-to-shadow-2:hover { - box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); -} - -.p-to-shadow-3:hover { - box-shadow: 0 10px 18px rgba(0, 0, 0, 0.3); -} - -.p-to-shadow-4:hover { - box-shadow: 0 25px 30px rgba(0, 0, 0, 0.2); -} - - -/* END OF SHADOWS */ - -.p-tabs-container { - background: #e3e3e3; - border: 1px solid #e0e0e0; - padding: 1em; -} - -.p-tabs-container.p-light { - background: none; - border: none; -} - -.p-tabs-container.p-light .p-panels { - margin-top: 0; - border-radius: 0; - padding: 0; -} - -.p-tabs { - display: flex; - justify-content: center; -} - -.p-tabs > :nth-of-type(1) { - border-radius: 5px 0 0 5px; -} - -.p-tabs > :last-child { - border-radius: 0 5px 5px 0; -} - -.p-tab { - margin: 0; - padding: 5px 35px; - background: #fff; - color: #333230; - text-decoration: none; - /* text-shadow: 0 1px 1px rgba(0, 0, 0, 0.25); */ - border: 1px solid #cacaca; - display: inline-block; - font-size: 17px; - font-family: -apple-system, "Inter", sans-serif; - cursor: pointer; -} - -.p-tab:focus { - outline: 0; -} - -.p-is-active { - background: linear-gradient(to bottom, #4fc5fa 0%, #0f75f5 100%); - border: 0; - color: #fff; -} - -.p-panels { - margin-top: 1em; - background: #fff; - border-radius: 3px; - position: relative; - padding: 0.8em; - overflow: hidden; -} - -.p-panel.p-is-active { - opacity: 1; - pointer-events: all; - background: none; - color: inherit; - position: static; -} - -.p-panel { - position: absolute; - opacity: 0; - pointer-events: none; -} - -@media (max-width: 768px) { - .p-tabs { - overflow: auto; - } - .p-tab { - font-size: 0.8em; - padding: 5px 28px; - } - .p-tabs-container { - padding: 0.8em; - } - - .p-panels { - padding: 0.8em; - } -} - -@media screen and (max-width: 496px) { - .p-tab { - text-align: center; - padding: 5px 18px; - } - .p-tabs-container { - padding: 0.5em; - } - - .p-panels { - padding: 0.5em; - margin-top: 0.5em; - } -} - -@media screen and (max-width: 378px) { - .p-tab { - text-align: center; - padding: 5px 10px; - } - .p-tabs-container { - padding: 0.5em; - } - - .p-panels { - padding: 0.5em; - margin-top: 0.5; - } -} - -.p-mobile-tabs { - position: fixed; - bottom: 0; - left: 0; - width: 100%; - padding: 15px 0px; - border-top: 1px solid #949494; - background: rgba(202, 202, 202, 0.8); - backdrop-filter: blur(10px); - display: flex; - font-family: -apple-system, "Inter", sans-serif; -} - -.p-mobile-tabs > div { - flex: auto; - text-align: center; -} - -.p-mobile-tabs a { - text-decoration: none; - color: #555; - transition: color 0.5s; - display: inline-block; - font-size: 0.8rem; -} - -.p-mobile-tabs a.active { - color: #0f75f5; - font-weight: 600; -} - -.p-mobile-tabs svg { - display: block; - margin: auto; - margin-bottom: 0.2rem; -} - -.p-mobile-tabs--content { - display: none; -} - -.p-mobile-tabs--content.active { - display: block; -} - -/* END OF TABS */ - - -.p-action-background{ - background: rgba(0, 0, 0, 0.3); - height: 100vh; - left: 0; - opacity: 0; - pointer-events: none; - position: fixed; - top: 0; - transition: all 0.3s; - width: 100vw; - z-index: 5; -} - -.p-action-background.nowactive { - opacity: 1; - pointer-events: auto; -} - - -.p-action-big-container{ - position:fixed; - width: 100%; - box-sizing: border-box; - padding: 1rem 5vw; - bottom:0; -} - -.p-action-container{ - background: rgba(255, 255, 255, 0.8); - backdrop-filter: blur(10px); - display:block; - margin:auto; - margin-bottom: 10px; - border-radius: 10px; -} - -.p-action-big-container .p-action-container:first-child{ - margin-bottom:10px; -} - -.p-action--intern{ - display:block; - margin:auto; - text-align:center; - padding: 15px 0; - border-bottom: 1px solid #bfbfbf; - font-weight: 500; - color: #0f75f5; - text-decoration:none; -} - -.p-action-destructive{ - color: #c6262e; -} - -.p-action-neutral{ - color: #555761; -} - -.p-action-cancel, .p-action-container a:last-child{ - border-bottom:none; -} - -.p-action-cancel{ - font-weight:bold; -} - -.p-action-icon{ - position:relative; -} -.p-action-icon svg, .p-action-icon img{ - position:absolute; - left:5%; - top:50%; - transform:translateY(-50%); -} - -.p-action-icon-inline{ - text-align: left; - display: flex; - align-items: center; -} - -.p-action-icon-inline svg, .p-action-icon-inline img{ - margin-left: 5%; - margin-right: 3%; -} - -.p-action-title{ - padding: 30px 15px; - border-bottom: 1px solid #bfbfbf; -} - -.p-action-title--intern,.p-action-text{ - margin:0; - color:#555761; -} - -.p-action-title--intern{ - margin-bottom: .3rem; -} - -@supports not (backdrop-filter: blur(10px)) { - .p-action-container { - background: rgba(255,255,255,.95); - } -} - -.p-action-big-container{ - -webkit-transform: translateY(30%); - transform: translateY(30%); - opacity: 0; - transition: opacity 0.4s, transform 0.4s; - transition-timing-function: ease-in-out; -} - -.p-action-big-container.active { --webkit-transform: translateY(0); - transform: translateY(0); - opacity: 1; -} - - -/* END OF ACTIONS */ diff --git a/v3/examples/android/frontend/public/style.css b/v3/examples/android/frontend/public/style.css deleted file mode 100644 index 8e4ccbd00..000000000 --- a/v3/examples/android/frontend/public/style.css +++ /dev/null @@ -1,328 +0,0 @@ -:root { - font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, - sans-serif, "Apple Color Emoji", "Segoe UI Emoji"; - font-size: 16px; - line-height: 24px; - font-weight: 400; - color-scheme: light dark; - /* Desktop defaults (mobile overrides below) */ - --bg: #ffffff; - --fg: #213547; - font-synthesis: none; - text-rendering: optimizeLegibility; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - -webkit-text-size-adjust: 100%; - user-select: none; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; -} - -/* Mobile bottom tabs layout (works on all themes) */ -.mobile-pane { - display: flex; - flex-direction: column; - width: 100%; - max-width: 520px; - height: 70vh; /* fixed-height main screen */ - border-radius: 12px; -} -.mobile-pane .p-mobile-tabs-content { - position: relative; - flex: 1 1 auto; - overflow: hidden; /* contain panels */ - display: flex; - flex-direction: column; -} -.p-mobile-tabs-content .p-mobile-tabs--content { - display: none; - overflow: auto; /* scroll inside content area */ - -webkit-overflow-scrolling: touch; - padding: 8px 8px 16px; -} -.p-mobile-tabs-content .p-mobile-tabs--content.active { display: block; } - -*, *::before, *::after { - box-sizing: border-box; -} - -/* Prefer system fonts on mobile; remove custom font to reduce bundle size */ - -h3 { - font-size: 3em; - line-height: 1.1; -} - -a { - font-weight: 500; - color: #646cff; - text-decoration: inherit; -} - -a:hover { - color: #535bf2; -} - -/* Remove generic button styling to allow Puppertino .btn to control buttons */ - -.result { - height: 20px; - line-height: 20px; -} - -html, -body { - height: 100%; - width: 100%; - overflow-x: hidden; /* prevent horizontal overflow */ - overflow-y: auto; /* allow vertical scroll if needed */ -} - -body { - margin: 0; - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - min-width: 320px; - /* Use small viewport units to avoid iOS Safari URL bar issues */ - min-height: 100svh; - height: auto; /* avoid forcing overflow */ - /* Equal responsive spacing top & bottom */ - padding-block: clamp(8px, 4vh, 48px); - color: var(--fg); - background-color: var(--bg); -} - -.container { - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - /* Responsive spacing between elements */ - gap: clamp(8px, 2vh, 24px); - width: 100%; - max-width: 480px; - padding-inline: 16px; -} - -h1 { - /* Responsive heading size */ - font-size: clamp(1.6rem, 6vw, 3.2rem); - line-height: 1.1; -} - -#app { - max-width: 1280px; - margin: 0 auto; - /* Responsive inner padding: horizontal only, no extra top/bottom */ - padding: 0 clamp(12px, 4vw, 32px); - text-align: center; -} - -.logo { - /* Consistent visual size across images: fix height, auto width */ - height: clamp(80px, 18vh, 140px); - width: auto; - max-width: 80vw; - padding: 0.5em; - will-change: filter; -} - -.logo:hover { - filter: drop-shadow(0 0 2em #e80000aa); -} - -.logo.vanilla:hover { - filter: drop-shadow(0 0 2em #f7df1eaa); -} - -.result { - height: 20px; - line-height: 20px; - margin: 1.5rem auto; - text-align: center; -} - -.footer { - margin-top: 1rem; - align-content: center; - text-align: center; -} - -/* Tabs: default hide panels, show one matching the checked radio */ -.tabs .tabs-content .tab-panel { display: none; } -.tabs input#tab-js:checked ~ .tabs-content [data-tab="tab-js"] { display: block; } -.tabs input#tab-go:checked ~ .tabs-content [data-tab="tab-go"] { display: block; } - -/* Sticky tabs header */ -.tabs .tabs-header { - position: sticky; - top: env(safe-area-inset-top); - z-index: 5; - display: grid; - grid-template-columns: 1fr 1fr; - gap: 8px; - padding: 8px 0; - background: var(--bg); - backdrop-filter: saturate(1.2) blur(4px); -} - -/* Subtle divider under sticky header */ -.tabs .tabs-header::after { - content: ""; - grid-column: 1 / -1; - height: 1px; - background: rgba(0,0,0,0.08); - margin-top: 8px; -} - -/* Mobile-specific light mode */ -@media (max-width: 768px) and (prefers-color-scheme: light) { - :root { - --fg: #213547; - --bg: #ffffff; - } - - a:hover { - color: #747bff; - } - - /* allow Puppertino to style .btn */ - - .input-box .input { - color: #111827; - background-color: #f3f4f6; - border: 1px solid #e5e7eb; /* show border in light mode */ - border-radius: 8px; - } - - button:hover { - border-color: #d1d5db; /* slate-300 */ - } - - .input-box .input:focus { - border-color: #9ca3af; /* gray-400 */ - box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.15); /* subtle focus ring */ - } -} - -/* let Puppertino handle .btn hover */ - -.input-box .input { - border: 1px solid transparent; /* default; themed in media queries */ - border-radius: 8px; - outline: none; - height: 30px; - line-height: 30px; - padding: 0 10px; - color: black; - background-color: rgba(240, 240, 240, 1); - -webkit-font-smoothing: antialiased; -} - -.input-box .input:hover { - background-color: rgba(255, 255, 255, 1); -} - -.input-box .input:focus { - background-color: rgba(255, 255, 255, 1); - outline: 2px solid transparent; - outline-offset: 2px; -} - -/* Mobile-specific dark mode */ -@media (max-width: 768px) and (prefers-color-scheme: dark) { - :root { - color: rgba(255, 255, 255, 0.88); - --fg: rgba(255, 255, 255, 0.88); - --bg: #0f1115; /* deep dark background */ - } - - a { - color: #8ea2ff; - } - - a:hover { - color: #aab6ff; - } - - /* allow Puppertino to style .btn in dark mode */ - - .input-box .input { - background-color: #111827; /* gray-900 */ - color: #e5e7eb; - caret-color: #ffffff; - border: 1px solid #374151; /* slate-700 */ - } - - .input-box .input:hover, - .input-box .input:focus { - background-color: #0b1220; - border-color: #4b5563; /* slate-600 */ - } - - /* allow Puppertino to handle active state */ -} - -/* Mobile baseline overrides (apply to both light and dark) */ -@media (max-width: 768px) { - /* Prevent iOS zoom on focus */ - input, textarea, select, button { font-size: 16px; } - - /* Make layout vertical and scrollable */ - html, body { - height: auto; - min-height: 100svh; - overflow-x: hidden; - overflow-y: auto; - -webkit-overflow-scrolling: touch; - } - - body { - padding-top: env(safe-area-inset-top); - padding-bottom: env(safe-area-inset-bottom); - position: static; - } - - .container { - width: 100%; - max-width: 520px; /* allow a bit wider on phones */ - align-items: center; /* keep content centered on mobile */ - text-align: center; - } - - /* Stack controls vertically with full-width tap targets */ - .input-box { - display: flex; - flex-direction: column; - align-items: stretch; - gap: 10px; - } - - .input-box .input, - .input, - button, - .p-btn { - width: 100%; - min-height: 44px; /* comfortable touch target */ - } - - /* Tabs vertical and full-width */ - .tabs { - display: grid; - grid-template-columns: 1fr; - gap: 8px; - } - .tabs .p-btn { width: 100%; } - - /* Cap device info height for readability */ - #deviceInfo { - max-height: 30vh; - overflow: auto; - padding: 8px; - border-radius: 8px; - background: rgba(0,0,0,0.04); - } -} \ No newline at end of file diff --git a/v3/examples/android/frontend/public/wails.png b/v3/examples/android/frontend/public/wails.png deleted file mode 100644 index 8bdf42483..000000000 Binary files a/v3/examples/android/frontend/public/wails.png and /dev/null differ diff --git a/v3/examples/android/frontend/vite.config.js b/v3/examples/android/frontend/vite.config.js deleted file mode 100644 index 87b093bc3..000000000 --- a/v3/examples/android/frontend/vite.config.js +++ /dev/null @@ -1,11 +0,0 @@ -import { defineConfig } from 'vite'; -import path from 'path'; - -export default defineConfig({ - resolve: { - alias: { - // Use the local repo runtime sources instead of the published package - '@wailsio/runtime': path.resolve(__dirname, '../../../internal/runtime/desktop/@wailsio/runtime/src/index.ts'), - }, - }, -}); diff --git a/v3/examples/android/go.mod b/v3/examples/android/go.mod deleted file mode 100644 index ebca95414..000000000 --- a/v3/examples/android/go.mod +++ /dev/null @@ -1,49 +0,0 @@ -module changeme - -go 1.25 - -require github.com/wailsapp/wails/v3 v3.0.0-dev - -require ( - dario.cat/mergo v1.0.2 // indirect - github.com/Microsoft/go-winio v0.6.2 // indirect - github.com/ProtonMail/go-crypto v1.3.0 // indirect - github.com/adrg/xdg v0.5.3 // indirect - github.com/bep/debounce v1.2.1 // indirect - github.com/cloudflare/circl v1.6.3 // indirect - github.com/coder/websocket v1.8.14 // indirect - github.com/cyphar/filepath-securejoin v0.6.1 // indirect - github.com/ebitengine/purego v0.9.1 // indirect - github.com/emirpasic/gods v1.18.1 // indirect - github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect - github.com/go-git/go-billy/v5 v5.7.0 // indirect - github.com/go-git/go-git/v5 v5.16.4 // indirect - github.com/go-ole/go-ole v1.3.0 // indirect - github.com/godbus/dbus/v5 v5.2.2 // indirect - github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect - github.com/google/uuid v1.6.0 // indirect - github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect - github.com/jchv/go-winloader v0.0.0-20250406163304-c1995be93bd1 // indirect - github.com/kevinburke/ssh_config v1.4.0 // indirect - github.com/klauspost/cpuid/v2 v2.3.0 // indirect - github.com/leaanthony/go-ansi-parser v1.6.1 // indirect - github.com/leaanthony/u v1.1.1 // indirect - github.com/lmittmann/tint v1.1.2 // indirect - github.com/mattn/go-colorable v0.1.14 // indirect - github.com/mattn/go-isatty v0.0.20 // indirect - github.com/pjbgf/sha1cd v0.5.0 // indirect - github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c // indirect - github.com/rivo/uniseg v0.4.7 // indirect - github.com/samber/lo v1.52.0 // indirect - github.com/sergi/go-diff v1.4.0 // indirect - github.com/skeema/knownhosts v1.3.2 // indirect - github.com/wailsapp/go-webview2 v1.0.23 // indirect - github.com/xanzy/ssh-agent v0.3.3 // indirect - golang.org/x/crypto v0.47.0 // indirect - golang.org/x/net v0.49.0 // indirect - golang.org/x/sys v0.40.0 // indirect - golang.org/x/text v0.33.0 // indirect - gopkg.in/warnings.v0 v0.1.2 // indirect -) - -replace github.com/wailsapp/wails/v3 => ../../ diff --git a/v3/examples/android/go.sum b/v3/examples/android/go.sum deleted file mode 100644 index 56f1153ea..000000000 --- a/v3/examples/android/go.sum +++ /dev/null @@ -1,147 +0,0 @@ -dario.cat/mergo v1.0.2 h1:85+piFYR1tMbRrLcDwR18y4UKJ3aH1Tbzi24VRW1TK8= -dario.cat/mergo v1.0.2/go.mod h1:E/hbnu0NxMFBjpMIE34DRGLWqDy0g5FuKDhCb31ngxA= -github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY= -github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= -github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= -github.com/ProtonMail/go-crypto v1.3.0 h1:ILq8+Sf5If5DCpHQp4PbZdS1J7HDFRXz/+xKBiRGFrw= -github.com/ProtonMail/go-crypto v1.3.0/go.mod h1:9whxjD8Rbs29b4XWbB8irEcE8KHMqaR2e7GWU1R+/PE= -github.com/adrg/xdg v0.5.3 h1:xRnxJXne7+oWDatRhR1JLnvuccuIeCoBu2rtuLqQB78= -github.com/adrg/xdg v0.5.3/go.mod h1:nlTsY+NNiCBGCK2tpm09vRqfVzrc2fLmXGpBLF0zlTQ= -github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8= -github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4= -github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= -github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= -github.com/bep/debounce v1.2.1 h1:v67fRdBA9UQu2NhLFXrSg0Brw7CexQekrBwDMM8bzeY= -github.com/bep/debounce v1.2.1/go.mod h1:H8yggRPQKLUhUoqrJC1bO2xNya7vanpDl7xR3ISbCJ0= -github.com/cloudflare/circl v1.6.3 h1:9GPOhQGF9MCYUeXyMYlqTR6a5gTrgR/fBLXvUgtVcg8= -github.com/cloudflare/circl v1.6.3/go.mod h1:2eXP6Qfat4O/Yhh8BznvKnJ+uzEoTQ6jVKJRn81BiS4= -github.com/coder/websocket v1.8.14 h1:9L0p0iKiNOibykf283eHkKUHHrpG7f65OE3BhhO7v9g= -github.com/coder/websocket v1.8.14/go.mod h1:NX3SzP+inril6yawo5CQXx8+fk145lPDC6pumgx0mVg= -github.com/cyphar/filepath-securejoin v0.6.1 h1:5CeZ1jPXEiYt3+Z6zqprSAgSWiggmpVyciv8syjIpVE= -github.com/cyphar/filepath-securejoin v0.6.1/go.mod h1:A8hd4EnAeyujCJRrICiOWqjS1AX0a9kM5XL+NwKoYSc= -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= -github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/ebitengine/purego v0.9.1 h1:a/k2f2HQU3Pi399RPW1MOaZyhKJL9w/xFpKAg4q1s0A= -github.com/ebitengine/purego v0.9.1/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ= -github.com/elazarl/goproxy v1.7.2 h1:Y2o6urb7Eule09PjlhQRGNsqRfPmYI3KKQLFpCAV3+o= -github.com/elazarl/goproxy v1.7.2/go.mod h1:82vkLNir0ALaW14Rc399OTTjyNREgmdL2cVoIbS6XaE= -github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc= -github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ= -github.com/gliderlabs/ssh v0.3.8 h1:a4YXD1V7xMF9g5nTkdfnja3Sxy1PVDCj1Zg4Wb8vY6c= -github.com/gliderlabs/ssh v0.3.8/go.mod h1:xYoytBv1sV0aL3CavoDuJIQNURXkkfPA/wxQ1pL1fAU= -github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI= -github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmSxCcxctByoQdvwPiA7DTK7jaaFDBTtu0ic= -github.com/go-git/go-billy/v5 v5.7.0 h1:83lBUJhGWhYp0ngzCMSgllhUSuoHP1iEWYjsPl9nwqM= -github.com/go-git/go-billy/v5 v5.7.0/go.mod h1:/1IUejTKH8xipsAcdfcSAlUlo2J7lkYV8GTKxAT/L3E= -github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399 h1:eMje31YglSBqCdIqdhKBW8lokaMrL3uTkpGYlE2OOT4= -github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399/go.mod h1:1OCfN199q1Jm3HZlxleg+Dw/mwps2Wbk9frAWm+4FII= -github.com/go-git/go-git/v5 v5.16.4 h1:7ajIEZHZJULcyJebDLo99bGgS0jRrOxzZG4uCk2Yb2Y= -github.com/go-git/go-git/v5 v5.16.4/go.mod h1:4Ge4alE/5gPs30F2H1esi2gPd69R0C39lolkucHBOp8= -github.com/go-json-experiment/json v0.0.0-20251027170946-4849db3c2f7e h1:Lf/gRkoycfOBPa42vU2bbgPurFong6zXeFtPoxholzU= -github.com/go-json-experiment/json v0.0.0-20251027170946-4849db3c2f7e/go.mod h1:uNVvRXArCGbZ508SxYYTC5v1JWoz2voff5pm25jU1Ok= -github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE= -github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78= -github.com/godbus/dbus/v5 v5.2.2 h1:TUR3TgtSVDmjiXOgAAyaZbYmIeP3DPkld3jgKGV8mXQ= -github.com/godbus/dbus/v5 v5.2.2/go.mod h1:3AAv2+hPq5rdnr5txxxRwiGjPXamgoIHgz9FPBfOp3c= -github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 h1:f+oWsMOmNPc8JmEHVZIycC7hBoQxHH9pNKQORJNozsQ= -github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8/go.mod h1:wcDNUvekVysuuOpQKo3191zZyTpiI6se1N1ULghS0sw= -github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= -github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= -github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= -github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A= -github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= -github.com/jchv/go-winloader v0.0.0-20250406163304-c1995be93bd1 h1:njuLRcjAuMKr7kI3D85AXWkw6/+v9PwtV6M6o11sWHQ= -github.com/jchv/go-winloader v0.0.0-20250406163304-c1995be93bd1/go.mod h1:alcuEEnZsY1WQsagKhZDsoPCRoOijYqhZvPwLG0kzVs= -github.com/kevinburke/ssh_config v1.4.0 h1:6xxtP5bZ2E4NF5tuQulISpTO2z8XbtH8cg1PWkxoFkQ= -github.com/kevinburke/ssh_config v1.4.0/go.mod h1:q2RIzfka+BXARoNexmF9gkxEX7DmvbW9P4hIVx2Kg4M= -github.com/klauspost/cpuid/v2 v2.3.0 h1:S4CRMLnYUhGeDFDqkGriYKdfoFlDnMtqTiI/sFzhA9Y= -github.com/klauspost/cpuid/v2 v2.3.0/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0= -github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= -github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= -github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= -github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= -github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/leaanthony/go-ansi-parser v1.6.1 h1:xd8bzARK3dErqkPFtoF9F3/HgN8UQk0ed1YDKpEz01A= -github.com/leaanthony/go-ansi-parser v1.6.1/go.mod h1:+vva/2y4alzVmmIEpk9QDhA7vLC5zKDTRwfZGOp3IWU= -github.com/leaanthony/u v1.1.1 h1:TUFjwDGlNX+WuwVEzDqQwC2lOv0P4uhTQw7CMFdiK7M= -github.com/leaanthony/u v1.1.1/go.mod h1:9+o6hejoRljvZ3BzdYlVL0JYCwtnAsVuN9pVTQcaRfI= -github.com/lmittmann/tint v1.1.2 h1:2CQzrL6rslrsyjqLDwD11bZ5OpLBPU+g3G/r5LSfS8w= -github.com/lmittmann/tint v1.1.2/go.mod h1:HIS3gSy7qNwGCj+5oRjAutErFBl4BzdQP6cJZ0NfMwE= -github.com/matryer/is v1.4.0/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwMRU= -github.com/matryer/is v1.4.1 h1:55ehd8zaGABKLXQUe2awZ99BD/PTc2ls+KV/dXphgEQ= -github.com/matryer/is v1.4.1/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwMRU= -github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE= -github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8= -github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= -github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= -github.com/onsi/gomega v1.34.1 h1:EUMJIKUjM8sKjYbtxQI9A4z2o+rruxnzNvpknOXie6k= -github.com/onsi/gomega v1.34.1/go.mod h1:kU1QgUvBDLXBJq618Xvm2LUX6rSAfRaFRTcdOeDLwwY= -github.com/pjbgf/sha1cd v0.5.0 h1:a+UkboSi1znleCDUNT3M5YxjOnN1fz2FhN48FlwCxs0= -github.com/pjbgf/sha1cd v0.5.0/go.mod h1:lhpGlyHLpQZoxMv8HcgXvZEhcGs0PG/vsZnEJ7H0iCM= -github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmdv1U2eRNDiU2ErMBj1gwrq8eQ= -github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c/go.mod h1:7rwL4CYBLnjLxUqIJNnCWiEdr3bn6IUYi15bNlnbCCU= -github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= -github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= -github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= -github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= -github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= -github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= -github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= -github.com/samber/lo v1.52.0 h1:Rvi+3BFHES3A8meP33VPAxiBZX/Aws5RxrschYGjomw= -github.com/samber/lo v1.52.0/go.mod h1:4+MXEGsJzbKGaUEQFKBq2xtfuznW9oz/WrgyzMzRoM0= -github.com/sergi/go-diff v1.4.0 h1:n/SP9D5ad1fORl+llWyN+D6qoUETXNZARKjyY2/KVCw= -github.com/sergi/go-diff v1.4.0/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4= -github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= -github.com/skeema/knownhosts v1.3.2 h1:EDL9mgf4NzwMXCTfaxSD/o/a5fxDw/xL9nkU28JjdBg= -github.com/skeema/knownhosts v1.3.2/go.mod h1:bEg3iQAuw+jyiw+484wwFJoKSLwcfd7fqRy+N0QTiow= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= -github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= -github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= -github.com/wailsapp/go-webview2 v1.0.23 h1:jmv8qhz1lHibCc79bMM/a/FqOnnzOGEisLav+a0b9P0= -github.com/wailsapp/go-webview2 v1.0.23/go.mod h1:qJmWAmAmaniuKGZPWwne+uor3AHMB5PFhqiK0Bbj8kc= -github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM= -github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw= -golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.47.0 h1:V6e3FRj+n4dbpw86FJ8Fv7XVOql7TEwpHapKoMJ/GO8= -golang.org/x/crypto v0.47.0/go.mod h1:ff3Y9VzzKbwSSEzWqJsJVBnWmRwRSHt/6Op5n9bQc4A= -golang.org/x/exp v0.0.0-20260112195511-716be5621a96 h1:Z/6YuSHTLOHfNFdb8zVZomZr7cqNgTJvA8+Qz75D8gU= -golang.org/x/exp v0.0.0-20260112195511-716be5621a96/go.mod h1:nzimsREAkjBCIEFtHiYkrJyT+2uy9YZJB7H1k68CXZU= -golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.49.0 h1:eeHFmOGUTtaaPSGNmjBKpbng9MulQsJURQUAfUwY++o= -golang.org/x/net v0.49.0/go.mod h1:/ysNB2EvaqvesRkuLAyjI1ycPZlQHM3q01F02UY/MV8= -golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200810151505-1b9f1253b3ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.40.0 h1:DBZZqJ2Rkml6QMQsZywtnjnnGvHza6BTfYFWY9kjEWQ= -golang.org/x/sys v0.40.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= -golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.39.0 h1:RclSuaJf32jOqZz74CkPA9qFuVTX7vhLlpfj/IGWlqY= -golang.org/x/term v0.39.0/go.mod h1:yxzUCTP/U+FzoxfdKmLaA0RV1WgE0VY7hXBwKtY/4ww= -golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.33.0 h1:B3njUFyqtHDUI5jMn1YIr5B0IE2U0qck04r6d4KPAxE= -golang.org/x/text v0.33.0/go.mod h1:LuMebE6+rBincTi9+xWTY8TztLzKHc/9C1uBCG27+q8= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= -gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME= -gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= -gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= -gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= -gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/v3/examples/android/greetservice.go b/v3/examples/android/greetservice.go deleted file mode 100644 index 8972c39cd..000000000 --- a/v3/examples/android/greetservice.go +++ /dev/null @@ -1,7 +0,0 @@ -package main - -type GreetService struct{} - -func (g *GreetService) Greet(name string) string { - return "Hello " + name + "!" -} diff --git a/v3/examples/android/main.go b/v3/examples/android/main.go deleted file mode 100644 index ba20103da..000000000 --- a/v3/examples/android/main.go +++ /dev/null @@ -1,73 +0,0 @@ -package main - -import ( - "embed" - _ "embed" - "log" - "time" - - "github.com/wailsapp/wails/v3/pkg/application" -) - -// Wails uses Go's `embed` package to embed the frontend files into the binary. -// Any files in the frontend/dist folder will be embedded into the binary and -// made available to the frontend. -// See https://pkg.go.dev/embed for more information. - -//go:embed all:frontend/dist -var assets embed.FS - -// main function serves as the application's entry point. It initializes the application, creates a window, -// and starts a goroutine that emits a time-based event every second. It subsequently runs the application and -// logs any error that might occur. -func main() { - - // Create a new Wails application by providing the necessary options. - // Variables 'Name' and 'Description' are for application metadata. - // 'Assets' configures the asset server with the 'FS' variable pointing to the frontend files. - // 'Bind' is a list of Go struct instances. The frontend has access to the methods of these instances. - app := application.New(application.Options{ - Name: "android", - Description: "A demo of using raw HTML & CSS", - Services: []application.Service{ - application.NewService(&GreetService{}), - }, - Assets: application.AssetOptions{ - Handler: application.AssetFileServerFS(assets), - }, - Mac: application.MacOptions{ - ApplicationShouldTerminateAfterLastWindowClosed: true, - }, - Android: application.AndroidOptions{ - // Android-specific options will go here - }, - }) - - // Create a new window with the necessary options. - // 'Title' is the title of the window. - // 'BackgroundColour' is the background colour of the window. - // 'URL' is the URL that will be loaded into the webview. - app.Window.NewWithOptions(application.WebviewWindowOptions{ - Title: "Window 1", - BackgroundColour: application.NewRGB(27, 38, 54), - URL: "/", - }) - - // Create a goroutine that emits an event containing the current time every second. - // The frontend can listen to this event and update the UI accordingly. - go func() { - for { - now := time.Now().Format(time.RFC1123) - app.Event.Emit("time", now) - time.Sleep(time.Second) - } - }() - - // Run the application. This blocks until the application has been exited. - err := app.Run() - - // If an error occurred while running the application, log it and exit. - if err != nil { - log.Fatal(err) - } -} diff --git a/v3/examples/android/main_android.go b/v3/examples/android/main_android.go deleted file mode 100644 index 70a716473..000000000 --- a/v3/examples/android/main_android.go +++ /dev/null @@ -1,11 +0,0 @@ -//go:build android - -package main - -import "github.com/wailsapp/wails/v3/pkg/application" - -func init() { - // Register main function to be called when the Android app initializes - // This is necessary because in c-shared build mode, main() is not automatically called - application.RegisterAndroidMain(main) -} diff --git a/v3/examples/badge-custom/README.md b/v3/examples/badge-custom/README.md deleted file mode 100644 index ab4c5a3fb..000000000 --- a/v3/examples/badge-custom/README.md +++ /dev/null @@ -1,128 +0,0 @@ -# Welcome to Your New Wails3 Project! -Now that you have your project set up, it's time to explore the custom badge features that Wails3 offers on **Windows**. - -## Exploring Custom Badge Features - -### Creating the Service with Custom Options (Windows Only) - -On Windows, you can customize the badge appearance with various options: - -```go -import "github.com/wailsapp/wails/v3/pkg/application" -import "github.com/wailsapp/wails/v3/pkg/services/badge" -import "image/color" - -// Create a badge service with custom options -options := badge.Options{ - TextColour: color.RGBA{255, 255, 255, 255}, // White text - BackgroundColour: color.RGBA{0, 0, 255, 255}, // Green background - FontName: "consolab.ttf", // Bold Consolas font - FontSize: 20, // Font size for single character - SmallFontSize: 14, // Font size for multiple characters -} - -badgeService := badge.NewWithOptions(options) - -// Register the service with the application -app := application.New(application.Options{ - Services: []application.Service{ - application.NewService(badgeService), - }, -}) -``` - -## Badge Operations - -### Setting a Badge - -Set a badge on the application tile/dock icon with the global options applied: - -#### Go -```go -// Set a default badge -badgeService.SetBadge("") - -// Set a numeric badge -badgeService.SetBadge("3") - -// Set a text badge -badgeService.SetBadge("New") -``` - -#### JS -```js -import {SetBadge} from "../bindings/github.com/wailsapp/wails/v3/pkg/services/badge/service"; - -// Set a default badge -SetBadge("") - -// Set a numeric badge -SetBadge("3") - -// Set a text badge -SetBadge("New") -``` - -### Setting a Custom Badge - -Set a badge on the application tile/dock icon with one-off options applied: - -#### Go -```go -// Set a default badge -badgeService.SetCustomBadge("") - -// Set a numeric badge -badgeService.SetCustomBadge("3") - -// Set a text badge -badgeService.SetCustomBadge("New") -``` - -#### JS -```js -import {SetCustomBadge} from "../bindings/github.com/wailsapp/wails/v3/pkg/services/badge/service"; - -const options = { - BackgroundColour: RGBA.createFrom({ - R: 0, - G: 255, - B: 255, - A: 255, - }), - FontName: "arialb.ttf", // System font - FontSize: 16, - SmallFontSize: 10, - TextColour: RGBA.createFrom({ - R: 0, - G: 0, - B: 0, - A: 255, - }), -} - -// Set a default badge -SetCustomBadge("", options) - -// Set a numeric badge -SetCustomBadge("3", options) - -// Set a text badge -SetCustomBadge("New", options) -``` - -### Removing a Badge - -Remove the badge from the application icon: - -#### Go -```go -badgeService.RemoveBadge() -``` - -#### JS -```js -import {RemoveBadge} from "../bindings/github.com/wailsapp/wails/v3/pkg/services/badge/service"; - -RemoveBadge() -``` \ No newline at end of file diff --git a/v3/examples/badge-custom/Taskfile.yml b/v3/examples/badge-custom/Taskfile.yml deleted file mode 100644 index d1bcfaacf..000000000 --- a/v3/examples/badge-custom/Taskfile.yml +++ /dev/null @@ -1,34 +0,0 @@ -version: '3' - -includes: - common: ./build/Taskfile.yml - windows: ./build/windows/Taskfile.yml - darwin: ./build/darwin/Taskfile.yml - linux: ./build/linux/Taskfile.yml - -vars: - APP_NAME: "badge" - BIN_DIR: "bin" - VITE_PORT: '{{.WAILS_VITE_PORT | default 9245}}' - -tasks: - build: - summary: Builds the application - cmds: - - task: "{{OS}}:build" - - package: - summary: Packages a production build of the application - cmds: - - task: "{{OS}}:package" - - run: - summary: Runs the application - cmds: - - task: "{{OS}}:run" - - dev: - summary: Runs the application in development mode - cmds: - - wails3 dev -config ./build/config.yml -port {{.VITE_PORT}} - diff --git a/v3/examples/badge-custom/build/Taskfile.yml b/v3/examples/badge-custom/build/Taskfile.yml deleted file mode 100644 index 5f3517efc..000000000 --- a/v3/examples/badge-custom/build/Taskfile.yml +++ /dev/null @@ -1,86 +0,0 @@ -version: '3' - -tasks: - go:mod:tidy: - summary: Runs `go mod tidy` - internal: true - cmds: - - go mod tidy - - install:frontend:deps: - summary: Install frontend dependencies - dir: frontend - sources: - - package.json - - package-lock.json - generates: - - node_modules/* - preconditions: - - sh: npm version - msg: "Looks like npm isn't installed. Npm is part of the Node installer: https://nodejs.org/en/download/" - cmds: - - npm install - - build:frontend: - label: build:frontend (PRODUCTION={{.PRODUCTION}}) - summary: Build the frontend project - dir: frontend - sources: - - "**/*" - generates: - - dist/**/* - deps: - - task: install:frontend:deps - - task: generate:bindings - vars: - BUILD_FLAGS: - ref: .BUILD_FLAGS - cmds: - - npm run {{.BUILD_COMMAND}} -q - env: - PRODUCTION: '{{.PRODUCTION | default "false"}}' - vars: - BUILD_COMMAND: '{{if eq .PRODUCTION "true"}}build{{else}}build:dev{{end}}' - - - generate:bindings: - label: generate:bindings (BUILD_FLAGS={{.BUILD_FLAGS}}) - summary: Generates bindings for the frontend - deps: - - task: go:mod:tidy - sources: - - "**/*.[jt]s" - - exclude: frontend/**/* - - frontend/bindings/**/* # Rerun when switching between dev/production mode causes changes in output - - "**/*.go" - - go.mod - - go.sum - generates: - - frontend/bindings/**/* - cmds: - - wails3 generate bindings -f '{{.BUILD_FLAGS}}' -clean=true -ts - - generate:icons: - summary: Generates Windows `.ico` and Mac `.icns` files from an image - dir: build - sources: - - "appicon.png" - generates: - - "darwin/icons.icns" - - "windows/icon.ico" - cmds: - - wails3 generate icons -input appicon.png -macfilename darwin/icons.icns -windowsfilename windows/icon.ico - - dev:frontend: - summary: Runs the frontend in development mode - dir: frontend - deps: - - task: install:frontend:deps - cmds: - - npm run dev -- --port {{.VITE_PORT}} --strictPort - - update:build-assets: - summary: Updates the build assets - dir: build - cmds: - - wails3 update build-assets -name "{{.APP_NAME}}" -binaryname "{{.APP_NAME}}" -config config.yml -dir . diff --git a/v3/examples/badge-custom/build/appicon.png b/v3/examples/badge-custom/build/appicon.png deleted file mode 100644 index 63617fe4f..000000000 Binary files a/v3/examples/badge-custom/build/appicon.png and /dev/null differ diff --git a/v3/examples/badge-custom/build/config.yml b/v3/examples/badge-custom/build/config.yml deleted file mode 100644 index aaa3240fb..000000000 --- a/v3/examples/badge-custom/build/config.yml +++ /dev/null @@ -1,63 +0,0 @@ -# This file contains the configuration for this project. -# When you update `info` or `fileAssociations`, run `wails3 task common:update:build-assets` to update the assets. -# Note that this will overwrite any changes you have made to the assets. -version: '3' - -# This information is used to generate the build assets. -info: - companyName: "My Company" # The name of the company - productName: "My Product" # The name of the application - productIdentifier: "com.mycompany.myproduct" # The unique product identifier - description: "A program that does X" # The application description - copyright: "(c) 2025, My Company" # Copyright text - comments: "Some Product Comments" # Comments - version: "0.0.1" # The application version - -# Dev mode configuration -dev_mode: - root_path: . - log_level: warn - debounce: 1000 - ignore: - dir: - - .git - - node_modules - - frontend - - bin - file: - - .DS_Store - - .gitignore - - .gitkeep - watched_extension: - - "*.go" - git_ignore: true - executes: - - cmd: wails3 task common:install:frontend:deps - type: once - - cmd: wails3 task common:dev:frontend - type: background - - cmd: go mod tidy - type: blocking - - cmd: wails3 task build - type: blocking - - cmd: wails3 task run - type: primary - -# File Associations -# More information at: https://v3.wails.io/noit/done/yet -fileAssociations: -# - ext: wails -# name: Wails -# description: Wails Application File -# iconName: wailsFileIcon -# role: Editor -# - ext: jpg -# name: JPEG -# description: Image File -# iconName: jpegFileIcon -# role: Editor -# mimeType: image/jpeg # (optional) - -# Other data -other: - - name: My Other Data \ No newline at end of file diff --git a/v3/examples/badge-custom/build/darwin/Info.dev.plist b/v3/examples/badge-custom/build/darwin/Info.dev.plist deleted file mode 100644 index 4caddf720..000000000 --- a/v3/examples/badge-custom/build/darwin/Info.dev.plist +++ /dev/null @@ -1,32 +0,0 @@ - - - - CFBundlePackageType - APPL - CFBundleName - My Product - CFBundleExecutable - badge - CFBundleIdentifier - com.wails.badge - CFBundleVersion - 0.1.0 - CFBundleGetInfoString - This is a comment - CFBundleShortVersionString - 0.1.0 - CFBundleIconFile - icons - LSMinimumSystemVersion - 10.15.0 - NSHighResolutionCapable - true - NSHumanReadableCopyright - © now, My Company - NSAppTransportSecurity - - NSAllowsLocalNetworking - - - - \ No newline at end of file diff --git a/v3/examples/badge-custom/build/darwin/Info.plist b/v3/examples/badge-custom/build/darwin/Info.plist deleted file mode 100644 index 0dc90b2e7..000000000 --- a/v3/examples/badge-custom/build/darwin/Info.plist +++ /dev/null @@ -1,27 +0,0 @@ - - - - CFBundlePackageType - APPL - CFBundleName - My Product - CFBundleExecutable - badge - CFBundleIdentifier - com.wails.badge - CFBundleVersion - 0.1.0 - CFBundleGetInfoString - This is a comment - CFBundleShortVersionString - 0.1.0 - CFBundleIconFile - icons - LSMinimumSystemVersion - 10.15.0 - NSHighResolutionCapable - true - NSHumanReadableCopyright - © now, My Company - - \ No newline at end of file diff --git a/v3/examples/badge-custom/build/darwin/Taskfile.yml b/v3/examples/badge-custom/build/darwin/Taskfile.yml deleted file mode 100644 index f0791fea9..000000000 --- a/v3/examples/badge-custom/build/darwin/Taskfile.yml +++ /dev/null @@ -1,81 +0,0 @@ -version: '3' - -includes: - common: ../Taskfile.yml - -tasks: - build: - summary: Creates a production build of the application - deps: - - task: common:go:mod:tidy - - task: common:build:frontend - vars: - BUILD_FLAGS: - ref: .BUILD_FLAGS - PRODUCTION: - ref: .PRODUCTION - - task: common:generate:icons - cmds: - - go build {{.BUILD_FLAGS}} -o {{.OUTPUT}} - vars: - BUILD_FLAGS: '{{if eq .PRODUCTION "true"}}-tags production -trimpath -buildvcs=false -ldflags="-w -s"{{else}}-buildvcs=false -gcflags=all="-l"{{end}}' - DEFAULT_OUTPUT: '{{.BIN_DIR}}/{{.APP_NAME}}' - OUTPUT: '{{ .OUTPUT | default .DEFAULT_OUTPUT }}' - env: - GOOS: darwin - CGO_ENABLED: 1 - GOARCH: '{{.ARCH | default ARCH}}' - CGO_CFLAGS: "-mmacosx-version-min=10.15" - CGO_LDFLAGS: "-mmacosx-version-min=10.15" - MACOSX_DEPLOYMENT_TARGET: "10.15" - PRODUCTION: '{{.PRODUCTION | default "false"}}' - - build:universal: - summary: Builds darwin universal binary (arm64 + amd64) - deps: - - task: build - vars: - ARCH: amd64 - OUTPUT: "{{.BIN_DIR}}/{{.APP_NAME}}-amd64" - - task: build - vars: - ARCH: arm64 - OUTPUT: "{{.BIN_DIR}}/{{.APP_NAME}}-arm64" - cmds: - - lipo -create -output "{{.BIN_DIR}}/{{.APP_NAME}}" "{{.BIN_DIR}}/{{.APP_NAME}}-amd64" "{{.BIN_DIR}}/{{.APP_NAME}}-arm64" - - rm "{{.BIN_DIR}}/{{.APP_NAME}}-amd64" "{{.BIN_DIR}}/{{.APP_NAME}}-arm64" - - package: - summary: Packages a production build of the application into a `.app` bundle - deps: - - task: build - vars: - PRODUCTION: "true" - cmds: - - task: create:app:bundle - - package:universal: - summary: Packages darwin universal binary (arm64 + amd64) - deps: - - task: build:universal - cmds: - - task: create:app:bundle - - - create:app:bundle: - summary: Creates an `.app` bundle - cmds: - - mkdir -p {{.BIN_DIR}}/{{.APP_NAME}}.app/Contents/{MacOS,Resources} - - cp build/darwin/icons.icns {{.BIN_DIR}}/{{.APP_NAME}}.app/Contents/Resources - - cp {{.BIN_DIR}}/{{.APP_NAME}} {{.BIN_DIR}}/{{.APP_NAME}}.app/Contents/MacOS - - cp build/darwin/Info.plist {{.BIN_DIR}}/{{.APP_NAME}}.app/Contents - - codesign --force --deep --sign - {{.BIN_DIR}}/{{.APP_NAME}}.app - - run: - cmds: - - mkdir -p {{.BIN_DIR}}/{{.APP_NAME}}.dev.app/Contents/{MacOS,Resources} - - cp build/darwin/icons.icns {{.BIN_DIR}}/{{.APP_NAME}}.dev.app/Contents/Resources - - cp {{.BIN_DIR}}/{{.APP_NAME}} {{.BIN_DIR}}/{{.APP_NAME}}.dev.app/Contents/MacOS - - cp build/darwin/Info.dev.plist {{.BIN_DIR}}/{{.APP_NAME}}.dev.app/Contents/Info.plist - - codesign --force --deep --sign - {{.BIN_DIR}}/{{.APP_NAME}}.dev.app - - '{{.BIN_DIR}}/{{.APP_NAME}}.dev.app/Contents/MacOS/{{.APP_NAME}}' diff --git a/v3/examples/badge-custom/build/darwin/icons.icns b/v3/examples/badge-custom/build/darwin/icons.icns deleted file mode 100644 index 1b5bd4c86..000000000 Binary files a/v3/examples/badge-custom/build/darwin/icons.icns and /dev/null differ diff --git a/v3/examples/badge-custom/build/linux/Taskfile.yml b/v3/examples/badge-custom/build/linux/Taskfile.yml deleted file mode 100644 index 560cc9c92..000000000 --- a/v3/examples/badge-custom/build/linux/Taskfile.yml +++ /dev/null @@ -1,119 +0,0 @@ -version: '3' - -includes: - common: ../Taskfile.yml - -tasks: - build: - summary: Builds the application for Linux - deps: - - task: common:go:mod:tidy - - task: common:build:frontend - vars: - BUILD_FLAGS: - ref: .BUILD_FLAGS - PRODUCTION: - ref: .PRODUCTION - - task: common:generate:icons - cmds: - - go build {{.BUILD_FLAGS}} -o {{.BIN_DIR}}/{{.APP_NAME}} - vars: - BUILD_FLAGS: '{{if eq .PRODUCTION "true"}}-tags production -trimpath -buildvcs=false -ldflags="-w -s"{{else}}-buildvcs=false -gcflags=all="-l"{{end}}' - env: - GOOS: linux - CGO_ENABLED: 1 - GOARCH: '{{.ARCH | default ARCH}}' - PRODUCTION: '{{.PRODUCTION | default "false"}}' - - package: - summary: Packages a production build of the application for Linux - deps: - - task: build - vars: - PRODUCTION: "true" - cmds: - - task: create:appimage - - task: create:deb - - task: create:rpm - - task: create:aur - - create:appimage: - summary: Creates an AppImage - dir: build/linux/appimage - deps: - - task: build - vars: - PRODUCTION: "true" - - task: generate:dotdesktop - cmds: - - cp {{.APP_BINARY}} {{.APP_NAME}} - - cp ../../appicon.png appicon.png - - wails3 generate appimage -binary {{.APP_NAME}} -icon {{.ICON}} -desktopfile {{.DESKTOP_FILE}} -outputdir {{.OUTPUT_DIR}} -builddir {{.ROOT_DIR}}/build/linux/appimage/build - vars: - APP_NAME: '{{.APP_NAME}}' - APP_BINARY: '../../../bin/{{.APP_NAME}}' - ICON: '../../appicon.png' - DESKTOP_FILE: '../{{.APP_NAME}}.desktop' - OUTPUT_DIR: '../../../bin' - - create:deb: - summary: Creates a deb package - deps: - - task: build - vars: - PRODUCTION: "true" - cmds: - - task: generate:dotdesktop - - task: generate:deb - - create:rpm: - summary: Creates a rpm package - deps: - - task: build - vars: - PRODUCTION: "true" - cmds: - - task: generate:dotdesktop - - task: generate:rpm - - create:aur: - summary: Creates a arch linux packager package - deps: - - task: build - vars: - PRODUCTION: "true" - cmds: - - task: generate:dotdesktop - - task: generate:aur - - generate:deb: - summary: Creates a deb package - cmds: - - wails3 tool package -name {{.APP_NAME}} -format deb -config ./build/linux/nfpm/nfpm.yaml -out {{.ROOT_DIR}}/bin - - generate:rpm: - summary: Creates a rpm package - cmds: - - wails3 tool package -name {{.APP_NAME}} -format rpm -config ./build/linux/nfpm/nfpm.yaml -out {{.ROOT_DIR}}/bin - - generate:aur: - summary: Creates a arch linux packager package - cmds: - - wails3 tool package -name {{.APP_NAME}} -format archlinux -config ./build/linux/nfpm/nfpm.yaml -out {{.ROOT_DIR}}/bin - - generate:dotdesktop: - summary: Generates a `.desktop` file - dir: build - cmds: - - mkdir -p {{.ROOT_DIR}}/build/linux/appimage - - wails3 generate .desktop -name "{{.APP_NAME}}" -exec "{{.EXEC}}" -icon "{{.ICON}}" -outputfile {{.ROOT_DIR}}/build/linux/{{.APP_NAME}}.desktop -categories "{{.CATEGORIES}}" - vars: - APP_NAME: '{{.APP_NAME}}' - EXEC: '{{.APP_NAME}}' - ICON: 'appicon' - CATEGORIES: 'Development;' - OUTPUTFILE: '{{.ROOT_DIR}}/build/linux/{{.APP_NAME}}.desktop' - - run: - cmds: - - '{{.BIN_DIR}}/{{.APP_NAME}}' diff --git a/v3/examples/badge-custom/build/linux/appimage/build.sh b/v3/examples/badge-custom/build/linux/appimage/build.sh deleted file mode 100644 index 85901c34e..000000000 --- a/v3/examples/badge-custom/build/linux/appimage/build.sh +++ /dev/null @@ -1,35 +0,0 @@ -#!/usr/bin/env bash -# Copyright (c) 2018-Present Lea Anthony -# SPDX-License-Identifier: MIT - -# Fail script on any error -set -euxo pipefail - -# Define variables -APP_DIR="${APP_NAME}.AppDir" - -# Create AppDir structure -mkdir -p "${APP_DIR}/usr/bin" -cp -r "${APP_BINARY}" "${APP_DIR}/usr/bin/" -cp "${ICON_PATH}" "${APP_DIR}/" -cp "${DESKTOP_FILE}" "${APP_DIR}/" - -if [[ $(uname -m) == *x86_64* ]]; then - # Download linuxdeploy and make it executable - wget -q -4 -N https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-x86_64.AppImage - chmod +x linuxdeploy-x86_64.AppImage - - # Run linuxdeploy to bundle the application - ./linuxdeploy-x86_64.AppImage --appdir "${APP_DIR}" --output appimage -else - # Download linuxdeploy and make it executable (arm64) - wget -q -4 -N https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-aarch64.AppImage - chmod +x linuxdeploy-aarch64.AppImage - - # Run linuxdeploy to bundle the application (arm64) - ./linuxdeploy-aarch64.AppImage --appdir "${APP_DIR}" --output appimage -fi - -# Rename the generated AppImage -mv "${APP_NAME}*.AppImage" "${APP_NAME}.AppImage" - diff --git a/v3/examples/badge-custom/build/linux/nfpm/nfpm.yaml b/v3/examples/badge-custom/build/linux/nfpm/nfpm.yaml deleted file mode 100644 index 5b7ea9d02..000000000 --- a/v3/examples/badge-custom/build/linux/nfpm/nfpm.yaml +++ /dev/null @@ -1,50 +0,0 @@ -# Feel free to remove those if you don't want/need to use them. -# Make sure to check the documentation at https://nfpm.goreleaser.com -# -# The lines below are called `modelines`. See `:help modeline` - -name: "badge" -arch: ${GOARCH} -platform: "linux" -version: "0.1.0" -section: "default" -priority: "extra" -maintainer: ${GIT_COMMITTER_NAME} <${GIT_COMMITTER_EMAIL}> -description: "My Product Description" -vendor: "My Company" -homepage: "https://wails.io" -license: "MIT" -release: "1" - -contents: - - src: "./bin/badge" - dst: "/usr/local/bin/badge" - - src: "./build/appicon.png" - dst: "/usr/share/icons/hicolor/128x128/apps/badge.png" - - src: "./build/linux/badge.desktop" - dst: "/usr/share/applications/badge.desktop" - -depends: - - gtk3 - - libwebkit2gtk - -# replaces: -# - foobar -# provides: -# - bar -# depends: -# - gtk3 -# - libwebkit2gtk -# recommends: -# - whatever -# suggests: -# - something-else -# conflicts: -# - not-foo -# - not-bar -# changelog: "changelog.yaml" -# scripts: -# preinstall: ./build/linux/nfpm/scripts/preinstall.sh -# postinstall: ./build/linux/nfpm/scripts/postinstall.sh -# preremove: ./build/linux/nfpm/scripts/preremove.sh -# postremove: ./build/linux/nfpm/scripts/postremove.sh diff --git a/v3/examples/badge-custom/build/linux/nfpm/scripts/postinstall.sh b/v3/examples/badge-custom/build/linux/nfpm/scripts/postinstall.sh deleted file mode 100644 index a9bf588e2..000000000 --- a/v3/examples/badge-custom/build/linux/nfpm/scripts/postinstall.sh +++ /dev/null @@ -1 +0,0 @@ -#!/bin/bash diff --git a/v3/examples/badge-custom/build/linux/nfpm/scripts/postremove.sh b/v3/examples/badge-custom/build/linux/nfpm/scripts/postremove.sh deleted file mode 100644 index a9bf588e2..000000000 --- a/v3/examples/badge-custom/build/linux/nfpm/scripts/postremove.sh +++ /dev/null @@ -1 +0,0 @@ -#!/bin/bash diff --git a/v3/examples/badge-custom/build/linux/nfpm/scripts/preinstall.sh b/v3/examples/badge-custom/build/linux/nfpm/scripts/preinstall.sh deleted file mode 100644 index a9bf588e2..000000000 --- a/v3/examples/badge-custom/build/linux/nfpm/scripts/preinstall.sh +++ /dev/null @@ -1 +0,0 @@ -#!/bin/bash diff --git a/v3/examples/badge-custom/build/linux/nfpm/scripts/preremove.sh b/v3/examples/badge-custom/build/linux/nfpm/scripts/preremove.sh deleted file mode 100644 index a9bf588e2..000000000 --- a/v3/examples/badge-custom/build/linux/nfpm/scripts/preremove.sh +++ /dev/null @@ -1 +0,0 @@ -#!/bin/bash diff --git a/v3/examples/badge-custom/build/windows/Taskfile.yml b/v3/examples/badge-custom/build/windows/Taskfile.yml deleted file mode 100644 index 534f4fb31..000000000 --- a/v3/examples/badge-custom/build/windows/Taskfile.yml +++ /dev/null @@ -1,63 +0,0 @@ -version: '3' - -includes: - common: ../Taskfile.yml - -tasks: - build: - summary: Builds the application for Windows - deps: - - task: common:go:mod:tidy - - task: common:build:frontend - vars: - BUILD_FLAGS: - ref: .BUILD_FLAGS - PRODUCTION: - ref: .PRODUCTION - - task: common:generate:icons - cmds: - - task: generate:syso - - go build {{.BUILD_FLAGS}} -o {{.BIN_DIR}}/{{.APP_NAME}}.exe - - cmd: powershell Remove-item *.syso - platforms: [windows] - - cmd: rm -f *.syso - platforms: [linux, darwin] - vars: - BUILD_FLAGS: '{{if eq .PRODUCTION "true"}}-tags production -trimpath -buildvcs=false -ldflags="-w -s -H windowsgui"{{else}}-buildvcs=false -gcflags=all="-l"{{end}}' - env: - GOOS: windows - CGO_ENABLED: 0 - GOARCH: '{{.ARCH | default ARCH}}' - PRODUCTION: '{{.PRODUCTION | default "false"}}' - - package: - summary: Packages a production build of the application into a `.exe` bundle - cmds: - - task: create:nsis:installer - - generate:syso: - summary: Generates Windows `.syso` file - dir: build - cmds: - - wails3 generate syso -arch {{.ARCH}} -icon windows/icon.ico -manifest windows/wails.exe.manifest -info windows/info.json -out ../wails_windows_{{.ARCH}}.syso - vars: - ARCH: '{{.ARCH | default ARCH}}' - - create:nsis:installer: - summary: Creates an NSIS installer - dir: build/windows/nsis - deps: - - task: build - vars: - PRODUCTION: "true" - cmds: - # Create the Microsoft WebView2 bootstrapper if it doesn't exist - - wails3 generate webview2bootstrapper -dir "{{.ROOT_DIR}}/build/windows/nsis" - - makensis -DARG_WAILS_{{.ARG_FLAG}}_BINARY="{{.ROOT_DIR}}/{{.BIN_DIR}}/{{.APP_NAME}}.exe" project.nsi - vars: - ARCH: '{{.ARCH | default ARCH}}' - ARG_FLAG: '{{if eq .ARCH "amd64"}}AMD64{{else}}ARM64{{end}}' - - run: - cmds: - - '{{.BIN_DIR}}/{{.APP_NAME}}.exe' diff --git a/v3/examples/badge-custom/build/windows/icon.ico b/v3/examples/badge-custom/build/windows/icon.ico deleted file mode 100644 index bfa0690b7..000000000 Binary files a/v3/examples/badge-custom/build/windows/icon.ico and /dev/null differ diff --git a/v3/examples/badge-custom/build/windows/info.json b/v3/examples/badge-custom/build/windows/info.json deleted file mode 100644 index 850b2b5b0..000000000 --- a/v3/examples/badge-custom/build/windows/info.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "fixed": { - "file_version": "0.1.0" - }, - "info": { - "0000": { - "ProductVersion": "0.1.0", - "CompanyName": "My Company", - "FileDescription": "My Product Description", - "LegalCopyright": "© now, My Company", - "ProductName": "My Product", - "Comments": "This is a comment" - } - } -} \ No newline at end of file diff --git a/v3/examples/badge-custom/build/windows/nsis/project.nsi b/v3/examples/badge-custom/build/windows/nsis/project.nsi deleted file mode 100644 index 985b8e207..000000000 --- a/v3/examples/badge-custom/build/windows/nsis/project.nsi +++ /dev/null @@ -1,112 +0,0 @@ -Unicode true - -#### -## Please note: Template replacements don't work in this file. They are provided with default defines like -## mentioned underneath. -## If the keyword is not defined, "wails_tools.nsh" will populate them. -## If they are defined here, "wails_tools.nsh" will not touch them. This allows you to use this project.nsi manually -## from outside of Wails for debugging and development of the installer. -## -## For development first make a wails nsis build to populate the "wails_tools.nsh": -## > wails build --target windows/amd64 --nsis -## Then you can call makensis on this file with specifying the path to your binary: -## For a AMD64 only installer: -## > makensis -DARG_WAILS_AMD64_BINARY=..\..\bin\app.exe -## For a ARM64 only installer: -## > makensis -DARG_WAILS_ARM64_BINARY=..\..\bin\app.exe -## For a installer with both architectures: -## > makensis -DARG_WAILS_AMD64_BINARY=..\..\bin\app-amd64.exe -DARG_WAILS_ARM64_BINARY=..\..\bin\app-arm64.exe -#### -## The following information is taken from the wails_tools.nsh file, but they can be overwritten here. -#### -## !define INFO_PROJECTNAME "my-project" # Default "badge" -## !define INFO_COMPANYNAME "My Company" # Default "My Company" -## !define INFO_PRODUCTNAME "My Product Name" # Default "My Product" -## !define INFO_PRODUCTVERSION "1.0.0" # Default "0.1.0" -## !define INFO_COPYRIGHT "(c) Now, My Company" # Default "© now, My Company" -### -## !define PRODUCT_EXECUTABLE "Application.exe" # Default "${INFO_PROJECTNAME}.exe" -## !define UNINST_KEY_NAME "UninstKeyInRegistry" # Default "${INFO_COMPANYNAME}${INFO_PRODUCTNAME}" -#### -## !define REQUEST_EXECUTION_LEVEL "admin" # Default "admin" see also https://nsis.sourceforge.io/Docs/Chapter4.html -#### -## Include the wails tools -#### -!include "wails_tools.nsh" - -# The version information for this two must consist of 4 parts -VIProductVersion "${INFO_PRODUCTVERSION}.0" -VIFileVersion "${INFO_PRODUCTVERSION}.0" - -VIAddVersionKey "CompanyName" "${INFO_COMPANYNAME}" -VIAddVersionKey "FileDescription" "${INFO_PRODUCTNAME} Installer" -VIAddVersionKey "ProductVersion" "${INFO_PRODUCTVERSION}" -VIAddVersionKey "FileVersion" "${INFO_PRODUCTVERSION}" -VIAddVersionKey "LegalCopyright" "${INFO_COPYRIGHT}" -VIAddVersionKey "ProductName" "${INFO_PRODUCTNAME}" - -# Enable HiDPI support. https://nsis.sourceforge.io/Reference/ManifestDPIAware -ManifestDPIAware true - -!include "MUI.nsh" - -!define MUI_ICON "..\icon.ico" -!define MUI_UNICON "..\icon.ico" -# !define MUI_WELCOMEFINISHPAGE_BITMAP "resources\leftimage.bmp" #Include this to add a bitmap on the left side of the Welcome Page. Must be a size of 164x314 -!define MUI_FINISHPAGE_NOAUTOCLOSE # Wait on the INSTFILES page so the user can take a look into the details of the installation steps -!define MUI_ABORTWARNING # This will warn the user if they exit from the installer. - -!insertmacro MUI_PAGE_WELCOME # Welcome to the installer page. -# !insertmacro MUI_PAGE_LICENSE "resources\eula.txt" # Adds a EULA page to the installer -!insertmacro MUI_PAGE_DIRECTORY # In which folder install page. -!insertmacro MUI_PAGE_INSTFILES # Installing page. -!insertmacro MUI_PAGE_FINISH # Finished installation page. - -!insertmacro MUI_UNPAGE_INSTFILES # Uninstalling page - -!insertmacro MUI_LANGUAGE "English" # Set the Language of the installer - -## The following two statements can be used to sign the installer and the uninstaller. The path to the binaries are provided in %1 -#!uninstfinalize 'signtool --file "%1"' -#!finalize 'signtool --file "%1"' - -Name "${INFO_PRODUCTNAME}" -OutFile "..\..\..\bin\${INFO_PROJECTNAME}-${ARCH}-installer.exe" # Name of the installer's file. -InstallDir "$PROGRAMFILES64\${INFO_COMPANYNAME}\${INFO_PRODUCTNAME}" # Default installing folder ($PROGRAMFILES is Program Files folder). -ShowInstDetails show # This will always show the installation details. - -Function .onInit - !insertmacro wails.checkArchitecture -FunctionEnd - -Section - !insertmacro wails.setShellContext - - !insertmacro wails.webview2runtime - - SetOutPath $INSTDIR - - !insertmacro wails.files - - CreateShortcut "$SMPROGRAMS\${INFO_PRODUCTNAME}.lnk" "$INSTDIR\${PRODUCT_EXECUTABLE}" - CreateShortCut "$DESKTOP\${INFO_PRODUCTNAME}.lnk" "$INSTDIR\${PRODUCT_EXECUTABLE}" - - !insertmacro wails.associateFiles - - !insertmacro wails.writeUninstaller -SectionEnd - -Section "uninstall" - !insertmacro wails.setShellContext - - RMDir /r "$AppData\${PRODUCT_EXECUTABLE}" # Remove the WebView2 DataPath - - RMDir /r $INSTDIR - - Delete "$SMPROGRAMS\${INFO_PRODUCTNAME}.lnk" - Delete "$DESKTOP\${INFO_PRODUCTNAME}.lnk" - - !insertmacro wails.unassociateFiles - - !insertmacro wails.deleteUninstaller -SectionEnd diff --git a/v3/examples/badge-custom/build/windows/nsis/wails_tools.nsh b/v3/examples/badge-custom/build/windows/nsis/wails_tools.nsh deleted file mode 100644 index 6fc10ab79..000000000 --- a/v3/examples/badge-custom/build/windows/nsis/wails_tools.nsh +++ /dev/null @@ -1,212 +0,0 @@ -# DO NOT EDIT - Generated automatically by `wails build` - -!include "x64.nsh" -!include "WinVer.nsh" -!include "FileFunc.nsh" - -!ifndef INFO_PROJECTNAME - !define INFO_PROJECTNAME "badge" -!endif -!ifndef INFO_COMPANYNAME - !define INFO_COMPANYNAME "My Company" -!endif -!ifndef INFO_PRODUCTNAME - !define INFO_PRODUCTNAME "My Product" -!endif -!ifndef INFO_PRODUCTVERSION - !define INFO_PRODUCTVERSION "0.1.0" -!endif -!ifndef INFO_COPYRIGHT - !define INFO_COPYRIGHT "© now, My Company" -!endif -!ifndef PRODUCT_EXECUTABLE - !define PRODUCT_EXECUTABLE "${INFO_PROJECTNAME}.exe" -!endif -!ifndef UNINST_KEY_NAME - !define UNINST_KEY_NAME "${INFO_COMPANYNAME}${INFO_PRODUCTNAME}" -!endif -!define UNINST_KEY "Software\Microsoft\Windows\CurrentVersion\Uninstall\${UNINST_KEY_NAME}" - -!ifndef REQUEST_EXECUTION_LEVEL - !define REQUEST_EXECUTION_LEVEL "admin" -!endif - -RequestExecutionLevel "${REQUEST_EXECUTION_LEVEL}" - -!ifdef ARG_WAILS_AMD64_BINARY - !define SUPPORTS_AMD64 -!endif - -!ifdef ARG_WAILS_ARM64_BINARY - !define SUPPORTS_ARM64 -!endif - -!ifdef SUPPORTS_AMD64 - !ifdef SUPPORTS_ARM64 - !define ARCH "amd64_arm64" - !else - !define ARCH "amd64" - !endif -!else - !ifdef SUPPORTS_ARM64 - !define ARCH "arm64" - !else - !error "Wails: Undefined ARCH, please provide at least one of ARG_WAILS_AMD64_BINARY or ARG_WAILS_ARM64_BINARY" - !endif -!endif - -!macro wails.checkArchitecture - !ifndef WAILS_WIN10_REQUIRED - !define WAILS_WIN10_REQUIRED "This product is only supported on Windows 10 (Server 2016) and later." - !endif - - !ifndef WAILS_ARCHITECTURE_NOT_SUPPORTED - !define WAILS_ARCHITECTURE_NOT_SUPPORTED "This product can't be installed on the current Windows architecture. Supports: ${ARCH}" - !endif - - ${If} ${AtLeastWin10} - !ifdef SUPPORTS_AMD64 - ${if} ${IsNativeAMD64} - Goto ok - ${EndIf} - !endif - - !ifdef SUPPORTS_ARM64 - ${if} ${IsNativeARM64} - Goto ok - ${EndIf} - !endif - - IfSilent silentArch notSilentArch - silentArch: - SetErrorLevel 65 - Abort - notSilentArch: - MessageBox MB_OK "${WAILS_ARCHITECTURE_NOT_SUPPORTED}" - Quit - ${else} - IfSilent silentWin notSilentWin - silentWin: - SetErrorLevel 64 - Abort - notSilentWin: - MessageBox MB_OK "${WAILS_WIN10_REQUIRED}" - Quit - ${EndIf} - - ok: -!macroend - -!macro wails.files - !ifdef SUPPORTS_AMD64 - ${if} ${IsNativeAMD64} - File "/oname=${PRODUCT_EXECUTABLE}" "${ARG_WAILS_AMD64_BINARY}" - ${EndIf} - !endif - - !ifdef SUPPORTS_ARM64 - ${if} ${IsNativeARM64} - File "/oname=${PRODUCT_EXECUTABLE}" "${ARG_WAILS_ARM64_BINARY}" - ${EndIf} - !endif -!macroend - -!macro wails.writeUninstaller - WriteUninstaller "$INSTDIR\uninstall.exe" - - SetRegView 64 - WriteRegStr HKLM "${UNINST_KEY}" "Publisher" "${INFO_COMPANYNAME}" - WriteRegStr HKLM "${UNINST_KEY}" "DisplayName" "${INFO_PRODUCTNAME}" - WriteRegStr HKLM "${UNINST_KEY}" "DisplayVersion" "${INFO_PRODUCTVERSION}" - WriteRegStr HKLM "${UNINST_KEY}" "DisplayIcon" "$INSTDIR\${PRODUCT_EXECUTABLE}" - WriteRegStr HKLM "${UNINST_KEY}" "UninstallString" "$\"$INSTDIR\uninstall.exe$\"" - WriteRegStr HKLM "${UNINST_KEY}" "QuietUninstallString" "$\"$INSTDIR\uninstall.exe$\" /S" - - ${GetSize} "$INSTDIR" "/S=0K" $0 $1 $2 - IntFmt $0 "0x%08X" $0 - WriteRegDWORD HKLM "${UNINST_KEY}" "EstimatedSize" "$0" -!macroend - -!macro wails.deleteUninstaller - Delete "$INSTDIR\uninstall.exe" - - SetRegView 64 - DeleteRegKey HKLM "${UNINST_KEY}" -!macroend - -!macro wails.setShellContext - ${If} ${REQUEST_EXECUTION_LEVEL} == "admin" - SetShellVarContext all - ${else} - SetShellVarContext current - ${EndIf} -!macroend - -# Install webview2 by launching the bootstrapper -# See https://docs.microsoft.com/en-us/microsoft-edge/webview2/concepts/distribution#online-only-deployment -!macro wails.webview2runtime - !ifndef WAILS_INSTALL_WEBVIEW_DETAILPRINT - !define WAILS_INSTALL_WEBVIEW_DETAILPRINT "Installing: WebView2 Runtime" - !endif - - SetRegView 64 - # If the admin key exists and is not empty then webview2 is already installed - ReadRegStr $0 HKLM "SOFTWARE\WOW6432Node\Microsoft\EdgeUpdate\Clients\{F3017226-FE2A-4295-8BDF-00C3A9A7E4C5}" "pv" - ${If} $0 != "" - Goto ok - ${EndIf} - - ${If} ${REQUEST_EXECUTION_LEVEL} == "user" - # If the installer is run in user level, check the user specific key exists and is not empty then webview2 is already installed - ReadRegStr $0 HKCU "Software\Microsoft\EdgeUpdate\Clients\{F3017226-FE2A-4295-8BDF-00C3A9A7E4C5}" "pv" - ${If} $0 != "" - Goto ok - ${EndIf} - ${EndIf} - - SetDetailsPrint both - DetailPrint "${WAILS_INSTALL_WEBVIEW_DETAILPRINT}" - SetDetailsPrint listonly - - InitPluginsDir - CreateDirectory "$pluginsdir\webview2bootstrapper" - SetOutPath "$pluginsdir\webview2bootstrapper" - File "MicrosoftEdgeWebview2Setup.exe" - ExecWait '"$pluginsdir\webview2bootstrapper\MicrosoftEdgeWebview2Setup.exe" /silent /install' - - SetDetailsPrint both - ok: -!macroend - -# Copy of APP_ASSOCIATE and APP_UNASSOCIATE macros from here https://gist.github.com/nikku/281d0ef126dbc215dd58bfd5b3a5cd5b -!macro APP_ASSOCIATE EXT FILECLASS DESCRIPTION ICON COMMANDTEXT COMMAND - ; Backup the previously associated file class - ReadRegStr $R0 SHELL_CONTEXT "Software\Classes\.${EXT}" "" - WriteRegStr SHELL_CONTEXT "Software\Classes\.${EXT}" "${FILECLASS}_backup" "$R0" - - WriteRegStr SHELL_CONTEXT "Software\Classes\.${EXT}" "" "${FILECLASS}" - - WriteRegStr SHELL_CONTEXT "Software\Classes\${FILECLASS}" "" `${DESCRIPTION}` - WriteRegStr SHELL_CONTEXT "Software\Classes\${FILECLASS}\DefaultIcon" "" `${ICON}` - WriteRegStr SHELL_CONTEXT "Software\Classes\${FILECLASS}\shell" "" "open" - WriteRegStr SHELL_CONTEXT "Software\Classes\${FILECLASS}\shell\open" "" `${COMMANDTEXT}` - WriteRegStr SHELL_CONTEXT "Software\Classes\${FILECLASS}\shell\open\command" "" `${COMMAND}` -!macroend - -!macro APP_UNASSOCIATE EXT FILECLASS - ; Backup the previously associated file class - ReadRegStr $R0 SHELL_CONTEXT "Software\Classes\.${EXT}" `${FILECLASS}_backup` - WriteRegStr SHELL_CONTEXT "Software\Classes\.${EXT}" "" "$R0" - - DeleteRegKey SHELL_CONTEXT `Software\Classes\${FILECLASS}` -!macroend - -!macro wails.associateFiles - ; Create file associations - -!macroend - -!macro wails.unassociateFiles - ; Delete app associations - -!macroend \ No newline at end of file diff --git a/v3/examples/badge-custom/build/windows/wails.exe.manifest b/v3/examples/badge-custom/build/windows/wails.exe.manifest deleted file mode 100644 index 1d8992a3d..000000000 --- a/v3/examples/badge-custom/build/windows/wails.exe.manifest +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - true/pm - permonitorv2,permonitor - - - \ No newline at end of file diff --git a/v3/examples/badge-custom/frontend/Inter Font License.txt b/v3/examples/badge-custom/frontend/Inter Font License.txt deleted file mode 100644 index b525cbf3a..000000000 --- a/v3/examples/badge-custom/frontend/Inter Font License.txt +++ /dev/null @@ -1,93 +0,0 @@ -Copyright 2020 The Inter Project Authors (https://github.com/rsms/inter) - -This Font Software is licensed under the SIL Open Font License, Version 1.1. -This license is copied below, and is also available with a FAQ at: -http://scripts.sil.org/OFL - - ------------------------------------------------------------ -SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 ------------------------------------------------------------ - -PREAMBLE -The goals of the Open Font License (OFL) are to stimulate worldwide -development of collaborative font projects, to support the font creation -efforts of academic and linguistic communities, and to provide a free and -open framework in which fonts may be shared and improved in partnership -with others. - -The OFL allows the licensed fonts to be used, studied, modified and -redistributed freely as long as they are not sold by themselves. The -fonts, including any derivative works, can be bundled, embedded, -redistributed and/or sold with any software provided that any reserved -names are not used by derivative works. The fonts and derivatives, -however, cannot be released under any other type of license. The -requirement for fonts to remain under this license does not apply -to any document created using the fonts or their derivatives. - -DEFINITIONS -"Font Software" refers to the set of files released by the Copyright -Holder(s) under this license and clearly marked as such. This may -include source files, build scripts and documentation. - -"Reserved Font Name" refers to any names specified as such after the -copyright statement(s). - -"Original Version" refers to the collection of Font Software components as -distributed by the Copyright Holder(s). - -"Modified Version" refers to any derivative made by adding to, deleting, -or substituting -- in part or in whole -- any of the components of the -Original Version, by changing formats or by porting the Font Software to a -new environment. - -"Author" refers to any designer, engineer, programmer, technical -writer or other person who contributed to the Font Software. - -PERMISSION & CONDITIONS -Permission is hereby granted, free of charge, to any person obtaining -a copy of the Font Software, to use, study, copy, merge, embed, modify, -redistribute, and sell modified and unmodified copies of the Font -Software, subject to the following conditions: - -1) Neither the Font Software nor any of its individual components, -in Original or Modified Versions, may be sold by itself. - -2) Original or Modified Versions of the Font Software may be bundled, -redistributed and/or sold with any software, provided that each copy -contains the above copyright notice and this license. These can be -included either as stand-alone text files, human-readable headers or -in the appropriate machine-readable metadata fields within text or -binary files as long as those fields can be easily viewed by the user. - -3) No Modified Version of the Font Software may use the Reserved Font -Name(s) unless explicit written permission is granted by the corresponding -Copyright Holder. This restriction only applies to the primary font name as -presented to the users. - -4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font -Software shall not be used to promote, endorse or advertise any -Modified Version, except to acknowledge the contribution(s) of the -Copyright Holder(s) and the Author(s) or with their explicit written -permission. - -5) The Font Software, modified or unmodified, in part or in whole, -must be distributed entirely under this license, and must not be -distributed under any other license. The requirement for fonts to -remain under this license does not apply to any document created -using the Font Software. - -TERMINATION -This license becomes null and void if any of the above conditions are -not met. - -DISCLAIMER -THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT -OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE -COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL -DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM -OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/v3/examples/badge-custom/frontend/bindings/github.com/wailsapp/wails/v3/pkg/services/dock/dockservice.ts b/v3/examples/badge-custom/frontend/bindings/github.com/wailsapp/wails/v3/pkg/services/dock/dockservice.ts deleted file mode 100644 index abf1f22e4..000000000 --- a/v3/examples/badge-custom/frontend/bindings/github.com/wailsapp/wails/v3/pkg/services/dock/dockservice.ts +++ /dev/null @@ -1,53 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * Service represents the dock service - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "@wailsio/runtime"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * HideAppIcon hides the app icon in the dock/taskbar. - */ -export function HideAppIcon(): $CancellablePromise { - return $Call.ByID(3413658144); -} - -/** - * RemoveBadge removes the badge label from the application icon. - * This method ensures the badge call is made on the main thread to avoid crashes. - */ -export function RemoveBadge(): $CancellablePromise { - return $Call.ByID(2752757297); -} - -/** - * SetBadge sets the badge label on the application icon. - * This method ensures the badge call is made on the main thread to avoid crashes. - */ -export function SetBadge(label: string): $CancellablePromise { - return $Call.ByID(1717705661, label); -} - -/** - * SetCustomBadge sets the badge label on the application icon with custom options. - * This method ensures the badge call is made on the main thread to avoid crashes. - */ -export function SetCustomBadge(label: string, options: $models.BadgeOptions): $CancellablePromise { - return $Call.ByID(2730169760, label, options); -} - -/** - * ShowAppIcon shows the app icon in the dock/taskbar. - */ -export function ShowAppIcon(): $CancellablePromise { - return $Call.ByID(3409697379); -} diff --git a/v3/examples/badge-custom/frontend/bindings/github.com/wailsapp/wails/v3/pkg/services/dock/index.ts b/v3/examples/badge-custom/frontend/bindings/github.com/wailsapp/wails/v3/pkg/services/dock/index.ts deleted file mode 100644 index fbdaf19f3..000000000 --- a/v3/examples/badge-custom/frontend/bindings/github.com/wailsapp/wails/v3/pkg/services/dock/index.ts +++ /dev/null @@ -1,11 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as DockService from "./dockservice.js"; -export { - DockService -}; - -export { - BadgeOptions -} from "./models.js"; diff --git a/v3/examples/badge-custom/frontend/bindings/github.com/wailsapp/wails/v3/pkg/services/dock/models.ts b/v3/examples/badge-custom/frontend/bindings/github.com/wailsapp/wails/v3/pkg/services/dock/models.ts deleted file mode 100644 index f97c8a4c6..000000000 --- a/v3/examples/badge-custom/frontend/bindings/github.com/wailsapp/wails/v3/pkg/services/dock/models.ts +++ /dev/null @@ -1,61 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Create as $Create } from "@wailsio/runtime"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as color$0 from "../../../../../../../image/color/models.js"; - -/** - * BadgeOptions represents options for customizing badge appearance - */ -export class BadgeOptions { - "TextColour": color$0.RGBA; - "BackgroundColour": color$0.RGBA; - "FontName": string; - "FontSize": number; - "SmallFontSize": number; - - /** Creates a new BadgeOptions instance. */ - constructor($$source: Partial = {}) { - if (!("TextColour" in $$source)) { - this["TextColour"] = (new color$0.RGBA()); - } - if (!("BackgroundColour" in $$source)) { - this["BackgroundColour"] = (new color$0.RGBA()); - } - if (!("FontName" in $$source)) { - this["FontName"] = ""; - } - if (!("FontSize" in $$source)) { - this["FontSize"] = 0; - } - if (!("SmallFontSize" in $$source)) { - this["SmallFontSize"] = 0; - } - - Object.assign(this, $$source); - } - - /** - * Creates a new BadgeOptions instance from a string or object. - */ - static createFrom($$source: any = {}): BadgeOptions { - const $$createField0_0 = $$createType0; - const $$createField1_0 = $$createType0; - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - if ("TextColour" in $$parsedSource) { - $$parsedSource["TextColour"] = $$createField0_0($$parsedSource["TextColour"]); - } - if ("BackgroundColour" in $$parsedSource) { - $$parsedSource["BackgroundColour"] = $$createField1_0($$parsedSource["BackgroundColour"]); - } - return new BadgeOptions($$parsedSource as Partial); - } -} - -// Private type creation functions -const $$createType0 = color$0.RGBA.createFrom; diff --git a/v3/examples/badge-custom/frontend/bindings/image/color/index.ts b/v3/examples/badge-custom/frontend/bindings/image/color/index.ts deleted file mode 100644 index 97b507b08..000000000 --- a/v3/examples/badge-custom/frontend/bindings/image/color/index.ts +++ /dev/null @@ -1,6 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -export { - RGBA -} from "./models.js"; diff --git a/v3/examples/badge-custom/frontend/bindings/image/color/models.ts b/v3/examples/badge-custom/frontend/bindings/image/color/models.ts deleted file mode 100644 index 0d4eab56d..000000000 --- a/v3/examples/badge-custom/frontend/bindings/image/color/models.ts +++ /dev/null @@ -1,46 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Create as $Create } from "@wailsio/runtime"; - -/** - * RGBA represents a traditional 32-bit alpha-premultiplied color, having 8 - * bits for each of red, green, blue and alpha. - * - * An alpha-premultiplied color component C has been scaled by alpha (A), so - * has valid values 0 <= C <= A. - */ -export class RGBA { - "R": number; - "G": number; - "B": number; - "A": number; - - /** Creates a new RGBA instance. */ - constructor($$source: Partial = {}) { - if (!("R" in $$source)) { - this["R"] = 0; - } - if (!("G" in $$source)) { - this["G"] = 0; - } - if (!("B" in $$source)) { - this["B"] = 0; - } - if (!("A" in $$source)) { - this["A"] = 0; - } - - Object.assign(this, $$source); - } - - /** - * Creates a new RGBA instance from a string or object. - */ - static createFrom($$source: any = {}): RGBA { - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - return new RGBA($$parsedSource as Partial); - } -} diff --git a/v3/examples/badge-custom/frontend/dist/Inter-Medium.ttf b/v3/examples/badge-custom/frontend/dist/Inter-Medium.ttf deleted file mode 100644 index a01f3777a..000000000 Binary files a/v3/examples/badge-custom/frontend/dist/Inter-Medium.ttf and /dev/null differ diff --git a/v3/examples/badge-custom/frontend/dist/assets/index-DOJs-2ns.js b/v3/examples/badge-custom/frontend/dist/assets/index-DOJs-2ns.js deleted file mode 100644 index 780f115b6..000000000 --- a/v3/examples/badge-custom/frontend/dist/assets/index-DOJs-2ns.js +++ /dev/null @@ -1,1415 +0,0 @@ -var __defProp = Object.defineProperty; -var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; -var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value); -(function polyfill() { - const relList = document.createElement("link").relList; - if (relList && relList.supports && relList.supports("modulepreload")) { - return; - } - for (const link of document.querySelectorAll('link[rel="modulepreload"]')) { - processPreload(link); - } - new MutationObserver((mutations) => { - for (const mutation of mutations) { - if (mutation.type !== "childList") { - continue; - } - for (const node of mutation.addedNodes) { - if (node.tagName === "LINK" && node.rel === "modulepreload") - processPreload(node); - } - } - }).observe(document, { childList: true, subtree: true }); - function getFetchOpts(link) { - const fetchOpts = {}; - if (link.integrity) fetchOpts.integrity = link.integrity; - if (link.referrerPolicy) fetchOpts.referrerPolicy = link.referrerPolicy; - if (link.crossOrigin === "use-credentials") - fetchOpts.credentials = "include"; - else if (link.crossOrigin === "anonymous") fetchOpts.credentials = "omit"; - else fetchOpts.credentials = "same-origin"; - return fetchOpts; - } - function processPreload(link) { - if (link.ep) - return; - link.ep = true; - const fetchOpts = getFetchOpts(link); - fetch(link.href, fetchOpts); - } -})(); -const urlAlphabet = "useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict"; -function nanoid(size = 21) { - let id = ""; - let i = size | 0; - while (i--) { - id += urlAlphabet[Math.random() * 64 | 0]; - } - return id; -} -const runtimeURL = window.location.origin + "/wails/runtime"; -const objectNames = Object.freeze({ - Call: 0, - Clipboard: 1, - Application: 2, - Events: 3, - ContextMenu: 4, - Dialog: 5, - Window: 6, - Screens: 7, - System: 8, - Browser: 9, - CancelCall: 10 -}); -let clientId = nanoid(); -function newRuntimeCaller(object, windowName = "") { - return function(method, args = null) { - return runtimeCallWithID(object, method, windowName, args); - }; -} -async function runtimeCallWithID(objectID, method, windowName, args) { - var _a2, _b; - let url = new URL(runtimeURL); - url.searchParams.append("object", objectID.toString()); - url.searchParams.append("method", method.toString()); - if (args) { - url.searchParams.append("args", JSON.stringify(args)); - } - let headers = { - ["x-wails-client-id"]: clientId - }; - if (windowName) { - headers["x-wails-window-name"] = windowName; - } - let response = await fetch(url, { headers }); - if (!response.ok) { - throw new Error(await response.text()); - } - if (((_b = (_a2 = response.headers.get("Content-Type")) === null || _a2 === void 0 ? void 0 : _a2.indexOf("application/json")) !== null && _b !== void 0 ? _b : -1) !== -1) { - return response.json(); - } else { - return response.text(); - } -} -newRuntimeCaller(objectNames.System); -const _invoke = function() { - var _a2, _b, _c, _d, _e; - try { - if ((_b = (_a2 = window.chrome) === null || _a2 === void 0 ? void 0 : _a2.webview) === null || _b === void 0 ? void 0 : _b.postMessage) { - return window.chrome.webview.postMessage.bind(window.chrome.webview); - } else if ((_e = (_d = (_c = window.webkit) === null || _c === void 0 ? void 0 : _c.messageHandlers) === null || _d === void 0 ? void 0 : _d["external"]) === null || _e === void 0 ? void 0 : _e.postMessage) { - return window.webkit.messageHandlers["external"].postMessage.bind(window.webkit.messageHandlers["external"]); - } - } catch (e) { - } - console.warn("\n%c⚠️ Browser Environment Detected %c\n\n%cOnly UI previews are available in the browser. For full functionality, please run the application in desktop mode.\nMore information at: https://v3.wails.io/learn/build/#using-a-browser-for-development\n", "background: #ffffff; color: #000000; font-weight: bold; padding: 4px 8px; border-radius: 4px; border: 2px solid #000000;", "background: transparent;", "color: #ffffff; font-style: italic; font-weight: bold;"); - return null; -}(); -function invoke(msg) { - _invoke === null || _invoke === void 0 ? void 0 : _invoke(msg); -} -function IsWindows() { - return window._wails.environment.OS === "windows"; -} -function IsDebug() { - return Boolean(window._wails.environment.Debug); -} -function canTrackButtons() { - return new MouseEvent("mousedown").buttons === 0; -} -function eventTarget(event) { - var _a2; - if (event.target instanceof HTMLElement) { - return event.target; - } else if (!(event.target instanceof HTMLElement) && event.target instanceof Node) { - return (_a2 = event.target.parentElement) !== null && _a2 !== void 0 ? _a2 : document.body; - } else { - return document.body; - } -} -document.addEventListener("DOMContentLoaded", () => { -}); -window.addEventListener("contextmenu", contextMenuHandler); -const call$2 = newRuntimeCaller(objectNames.ContextMenu); -const ContextMenuOpen = 0; -function openContextMenu(id, x, y, data) { - void call$2(ContextMenuOpen, { id, x, y, data }); -} -function contextMenuHandler(event) { - const target = eventTarget(event); - const customContextMenu = window.getComputedStyle(target).getPropertyValue("--custom-contextmenu").trim(); - if (customContextMenu) { - event.preventDefault(); - const data = window.getComputedStyle(target).getPropertyValue("--custom-contextmenu-data"); - openContextMenu(customContextMenu, event.clientX, event.clientY, data); - } else { - processDefaultContextMenu(event, target); - } -} -function processDefaultContextMenu(event, target) { - if (IsDebug()) { - return; - } - switch (window.getComputedStyle(target).getPropertyValue("--default-contextmenu").trim()) { - case "show": - return; - case "hide": - event.preventDefault(); - return; - } - if (target.isContentEditable) { - return; - } - const selection = window.getSelection(); - const hasSelection = selection && selection.toString().length > 0; - if (hasSelection) { - for (let i = 0; i < selection.rangeCount; i++) { - const range = selection.getRangeAt(i); - const rects = range.getClientRects(); - for (let j = 0; j < rects.length; j++) { - const rect = rects[j]; - if (document.elementFromPoint(rect.left, rect.top) === target) { - return; - } - } - } - } - if (target instanceof HTMLInputElement || target instanceof HTMLTextAreaElement) { - if (hasSelection || !target.readOnly && !target.disabled) { - return; - } - } - event.preventDefault(); -} -function GetFlag(key) { - try { - return window._wails.flags[key]; - } catch (e) { - throw new Error("Unable to retrieve flag '" + key + "': " + e, { cause: e }); - } -} -let canDrag = false; -let dragging = false; -let resizable = false; -let canResize = false; -let resizing = false; -let resizeEdge = ""; -let defaultCursor = "auto"; -let buttons = 0; -const buttonsTracked = canTrackButtons(); -window._wails = window._wails || {}; -window._wails.setResizable = (value) => { - resizable = value; - if (!resizable) { - canResize = resizing = false; - setResize(); - } -}; -window.addEventListener("mousedown", update, { capture: true }); -window.addEventListener("mousemove", update, { capture: true }); -window.addEventListener("mouseup", update, { capture: true }); -for (const ev of ["click", "contextmenu", "dblclick"]) { - window.addEventListener(ev, suppressEvent, { capture: true }); -} -function suppressEvent(event) { - if (dragging || resizing) { - event.stopImmediatePropagation(); - event.stopPropagation(); - event.preventDefault(); - } -} -const MouseDown = 0; -const MouseUp = 1; -const MouseMove = 2; -function update(event) { - let eventType, eventButtons = event.buttons; - switch (event.type) { - case "mousedown": - eventType = MouseDown; - if (!buttonsTracked) { - eventButtons = buttons | 1 << event.button; - } - break; - case "mouseup": - eventType = MouseUp; - if (!buttonsTracked) { - eventButtons = buttons & ~(1 << event.button); - } - break; - default: - eventType = MouseMove; - if (!buttonsTracked) { - eventButtons = buttons; - } - break; - } - let released = buttons & ~eventButtons; - let pressed = eventButtons & ~buttons; - buttons = eventButtons; - if (eventType === MouseDown && !(pressed & event.button)) { - released |= 1 << event.button; - pressed |= 1 << event.button; - } - if (eventType !== MouseMove && resizing || dragging && (eventType === MouseDown || event.button !== 0)) { - event.stopImmediatePropagation(); - event.stopPropagation(); - event.preventDefault(); - } - if (released & 1) { - primaryUp(); - } - if (pressed & 1) { - primaryDown(event); - } - if (eventType === MouseMove) { - onMouseMove(event); - } -} -function primaryDown(event) { - canDrag = false; - canResize = false; - if (!IsWindows()) { - if (event.type === "mousedown" && event.button === 0 && event.detail !== 1) { - return; - } - } - if (resizeEdge) { - canResize = true; - return; - } - const target = eventTarget(event); - const style = window.getComputedStyle(target); - canDrag = style.getPropertyValue("--wails-draggable").trim() === "drag" && (event.offsetX - parseFloat(style.paddingLeft) < target.clientWidth && event.offsetY - parseFloat(style.paddingTop) < target.clientHeight); -} -function primaryUp(event) { - canDrag = false; - dragging = false; - canResize = false; - resizing = false; -} -const cursorForEdge = Object.freeze({ - "se-resize": "nwse-resize", - "sw-resize": "nesw-resize", - "nw-resize": "nwse-resize", - "ne-resize": "nesw-resize", - "w-resize": "ew-resize", - "n-resize": "ns-resize", - "s-resize": "ns-resize", - "e-resize": "ew-resize" -}); -function setResize(edge) { - if (edge) { - if (!resizeEdge) { - defaultCursor = document.body.style.cursor; - } - document.body.style.cursor = cursorForEdge[edge]; - } else if (!edge && resizeEdge) { - document.body.style.cursor = defaultCursor; - } - resizeEdge = edge || ""; -} -function onMouseMove(event) { - if (canResize && resizeEdge) { - resizing = true; - invoke("wails:resize:" + resizeEdge); - } else if (canDrag) { - dragging = true; - invoke("wails:drag"); - } - if (dragging || resizing) { - canDrag = canResize = false; - return; - } - if (!resizable || !IsWindows()) { - if (resizeEdge) { - setResize(); - } - return; - } - const resizeHandleHeight = GetFlag("system.resizeHandleHeight") || 5; - const resizeHandleWidth = GetFlag("system.resizeHandleWidth") || 5; - const cornerExtra = GetFlag("resizeCornerExtra") || 10; - const rightBorder = window.outerWidth - event.clientX < resizeHandleWidth; - const leftBorder = event.clientX < resizeHandleWidth; - const topBorder = event.clientY < resizeHandleHeight; - const bottomBorder = window.outerHeight - event.clientY < resizeHandleHeight; - const rightCorner = window.outerWidth - event.clientX < resizeHandleWidth + cornerExtra; - const leftCorner = event.clientX < resizeHandleWidth + cornerExtra; - const topCorner = event.clientY < resizeHandleHeight + cornerExtra; - const bottomCorner = window.outerHeight - event.clientY < resizeHandleHeight + cornerExtra; - if (!leftCorner && !topCorner && !bottomCorner && !rightCorner) { - setResize(); - } else if (rightCorner && bottomCorner) - setResize("se-resize"); - else if (leftCorner && bottomCorner) - setResize("sw-resize"); - else if (leftCorner && topCorner) - setResize("nw-resize"); - else if (topCorner && rightCorner) - setResize("ne-resize"); - else if (leftBorder) - setResize("w-resize"); - else if (topBorder) - setResize("n-resize"); - else if (bottomBorder) - setResize("s-resize"); - else if (rightBorder) - setResize("e-resize"); - else - setResize(); -} -var fnToStr = Function.prototype.toString; -var reflectApply = typeof Reflect === "object" && Reflect !== null && Reflect.apply; -var badArrayLike; -var isCallableMarker; -if (typeof reflectApply === "function" && typeof Object.defineProperty === "function") { - try { - badArrayLike = Object.defineProperty({}, "length", { - get: function() { - throw isCallableMarker; - } - }); - isCallableMarker = {}; - reflectApply(function() { - throw 42; - }, null, badArrayLike); - } catch (_) { - if (_ !== isCallableMarker) { - reflectApply = null; - } - } -} else { - reflectApply = null; -} -var constructorRegex = /^\s*class\b/; -var isES6ClassFn = function isES6ClassFunction(value) { - try { - var fnStr = fnToStr.call(value); - return constructorRegex.test(fnStr); - } catch (e) { - return false; - } -}; -var tryFunctionObject = function tryFunctionToStr(value) { - try { - if (isES6ClassFn(value)) { - return false; - } - fnToStr.call(value); - return true; - } catch (e) { - return false; - } -}; -var toStr = Object.prototype.toString; -var objectClass = "[object Object]"; -var fnClass = "[object Function]"; -var genClass = "[object GeneratorFunction]"; -var ddaClass = "[object HTMLAllCollection]"; -var ddaClass2 = "[object HTML document.all class]"; -var ddaClass3 = "[object HTMLCollection]"; -var hasToStringTag = typeof Symbol === "function" && !!Symbol.toStringTag; -var isIE68 = !(0 in [,]); -var isDDA = function isDocumentDotAll() { - return false; -}; -if (typeof document === "object") { - var all = document.all; - if (toStr.call(all) === toStr.call(document.all)) { - isDDA = function isDocumentDotAll2(value) { - if ((isIE68 || !value) && (typeof value === "undefined" || typeof value === "object")) { - try { - var str = toStr.call(value); - return (str === ddaClass || str === ddaClass2 || str === ddaClass3 || str === objectClass) && value("") == null; - } catch (e) { - } - } - return false; - }; - } -} -function isCallableRefApply(value) { - if (isDDA(value)) { - return true; - } - if (!value) { - return false; - } - if (typeof value !== "function" && typeof value !== "object") { - return false; - } - try { - reflectApply(value, null, badArrayLike); - } catch (e) { - if (e !== isCallableMarker) { - return false; - } - } - return !isES6ClassFn(value) && tryFunctionObject(value); -} -function isCallableNoRefApply(value) { - if (isDDA(value)) { - return true; - } - if (!value) { - return false; - } - if (typeof value !== "function" && typeof value !== "object") { - return false; - } - if (hasToStringTag) { - return tryFunctionObject(value); - } - if (isES6ClassFn(value)) { - return false; - } - var strClass = toStr.call(value); - if (strClass !== fnClass && strClass !== genClass && !/^\[object HTML/.test(strClass)) { - return false; - } - return tryFunctionObject(value); -} -const isCallable = reflectApply ? isCallableRefApply : isCallableNoRefApply; -var _a; -class CancelError extends Error { - /** - * Constructs a new `CancelError` instance. - * @param message - The error message. - * @param options - Options to be forwarded to the Error constructor. - */ - constructor(message, options) { - super(message, options); - this.name = "CancelError"; - } -} -class CancelledRejectionError extends Error { - /** - * Constructs a new `CancelledRejectionError` instance. - * @param promise - The promise that caused the error originally. - * @param reason - The rejection reason. - * @param info - An optional informative message specifying the circumstances in which the error was thrown. - * Defaults to the string `"Unhandled rejection in cancelled promise."`. - */ - constructor(promise, reason, info) { - super((info !== null && info !== void 0 ? info : "Unhandled rejection in cancelled promise.") + " Reason: " + errorMessage(reason), { cause: reason }); - this.promise = promise; - this.name = "CancelledRejectionError"; - } -} -const barrierSym = Symbol("barrier"); -const cancelImplSym = Symbol("cancelImpl"); -const species = (_a = Symbol.species) !== null && _a !== void 0 ? _a : Symbol("speciesPolyfill"); -class CancellablePromise extends Promise { - /** - * Creates a new `CancellablePromise`. - * - * @param executor - A callback used to initialize the promise. This callback is passed two arguments: - * a `resolve` callback used to resolve the promise with a value - * or the result of another promise (possibly cancellable), - * and a `reject` callback used to reject the promise with a provided reason or error. - * If the value provided to the `resolve` callback is a thenable _and_ cancellable object - * (it has a `then` _and_ a `cancel` method), - * cancellation requests will be forwarded to that object and the oncancelled will not be invoked anymore. - * If any one of the two callbacks is called _after_ the promise has been cancelled, - * the provided values will be cancelled and resolved as usual, - * but their results will be discarded. - * However, if the resolution process ultimately ends up in a rejection - * that is not due to cancellation, the rejection reason - * will be wrapped in a {@link CancelledRejectionError} - * and bubbled up as an unhandled rejection. - * @param oncancelled - It is the caller's responsibility to ensure that any operation - * started by the executor is properly halted upon cancellation. - * This optional callback can be used to that purpose. - * It will be called _synchronously_ with a cancellation cause - * when cancellation is requested, _after_ the promise has already rejected - * with a {@link CancelError}, but _before_ - * any {@link then}/{@link catch}/{@link finally} callback runs. - * If the callback returns a thenable, the promise returned from {@link cancel} - * will only fulfill after the former has settled. - * Unhandled exceptions or rejections from the callback will be wrapped - * in a {@link CancelledRejectionError} and bubbled up as unhandled rejections. - * If the `resolve` callback is called before cancellation with a cancellable promise, - * cancellation requests on this promise will be diverted to that promise, - * and the original `oncancelled` callback will be discarded. - */ - constructor(executor, oncancelled) { - let resolve; - let reject; - super((res, rej) => { - resolve = res; - reject = rej; - }); - if (this.constructor[species] !== Promise) { - throw new TypeError("CancellablePromise does not support transparent subclassing. Please refrain from overriding the [Symbol.species] static property."); - } - let promise = { - promise: this, - resolve, - reject, - get oncancelled() { - return oncancelled !== null && oncancelled !== void 0 ? oncancelled : null; - }, - set oncancelled(cb) { - oncancelled = cb !== null && cb !== void 0 ? cb : void 0; - } - }; - const state = { - get root() { - return state; - }, - resolving: false, - settled: false - }; - void Object.defineProperties(this, { - [barrierSym]: { - configurable: false, - enumerable: false, - writable: true, - value: null - }, - [cancelImplSym]: { - configurable: false, - enumerable: false, - writable: false, - value: cancellerFor(promise, state) - } - }); - const rejector = rejectorFor(promise, state); - try { - executor(resolverFor(promise, state), rejector); - } catch (err) { - if (state.resolving) { - console.log("Unhandled exception in CancellablePromise executor.", err); - } else { - rejector(err); - } - } - } - /** - * Cancels immediately the execution of the operation associated with this promise. - * The promise rejects with a {@link CancelError} instance as reason, - * with the {@link CancelError#cause} property set to the given argument, if any. - * - * Has no effect if called after the promise has already settled; - * repeated calls in particular are safe, but only the first one - * will set the cancellation cause. - * - * The `CancelError` exception _need not_ be handled explicitly _on the promises that are being cancelled:_ - * cancelling a promise with no attached rejection handler does not trigger an unhandled rejection event. - * Therefore, the following idioms are all equally correct: - * ```ts - * new CancellablePromise((resolve, reject) => { ... }).cancel(); - * new CancellablePromise((resolve, reject) => { ... }).then(...).cancel(); - * new CancellablePromise((resolve, reject) => { ... }).then(...).catch(...).cancel(); - * ``` - * Whenever some cancelled promise in a chain rejects with a `CancelError` - * with the same cancellation cause as itself, the error will be discarded silently. - * However, the `CancelError` _will still be delivered_ to all attached rejection handlers - * added by {@link then} and related methods: - * ```ts - * let cancellable = new CancellablePromise((resolve, reject) => { ... }); - * cancellable.then(() => { ... }).catch(console.log); - * cancellable.cancel(); // A CancelError is printed to the console. - * ``` - * If the `CancelError` is not handled downstream by the time it reaches - * a _non-cancelled_ promise, it _will_ trigger an unhandled rejection event, - * just like normal rejections would: - * ```ts - * let cancellable = new CancellablePromise((resolve, reject) => { ... }); - * let chained = cancellable.then(() => { ... }).then(() => { ... }); // No catch... - * cancellable.cancel(); // Unhandled rejection event on chained! - * ``` - * Therefore, it is important to either cancel whole promise chains from their tail, - * as shown in the correct idioms above, or take care of handling errors everywhere. - * - * @returns A cancellable promise that _fulfills_ after the cancel callback (if any) - * and all handlers attached up to the call to cancel have run. - * If the cancel callback returns a thenable, the promise returned by `cancel` - * will also wait for that thenable to settle. - * This enables callers to wait for the cancelled operation to terminate - * without being forced to handle potential errors at the call site. - * ```ts - * cancellable.cancel().then(() => { - * // Cleanup finished, it's safe to do something else. - * }, (err) => { - * // Unreachable: the promise returned from cancel will never reject. - * }); - * ``` - * Note that the returned promise will _not_ handle implicitly any rejection - * that might have occurred already in the cancelled chain. - * It will just track whether registered handlers have been executed or not. - * Therefore, unhandled rejections will never be silently handled by calling cancel. - */ - cancel(cause) { - return new CancellablePromise((resolve) => { - Promise.all([ - this[cancelImplSym](new CancelError("Promise cancelled.", { cause })), - currentBarrier(this) - ]).then(() => resolve(), () => resolve()); - }); - } - /** - * Binds promise cancellation to the abort event of the given {@link AbortSignal}. - * If the signal has already aborted, the promise will be cancelled immediately. - * When either condition is verified, the cancellation cause will be set - * to the signal's abort reason (see {@link AbortSignal#reason}). - * - * Has no effect if called (or if the signal aborts) _after_ the promise has already settled. - * Only the first signal to abort will set the cancellation cause. - * - * For more details about the cancellation process, - * see {@link cancel} and the `CancellablePromise` constructor. - * - * This method enables `await`ing cancellable promises without having - * to store them for future cancellation, e.g.: - * ```ts - * await longRunningOperation().cancelOn(signal); - * ``` - * instead of: - * ```ts - * let promiseToBeCancelled = longRunningOperation(); - * await promiseToBeCancelled; - * ``` - * - * @returns This promise, for method chaining. - */ - cancelOn(signal) { - if (signal.aborted) { - void this.cancel(signal.reason); - } else { - signal.addEventListener("abort", () => void this.cancel(signal.reason), { capture: true }); - } - return this; - } - /** - * Attaches callbacks for the resolution and/or rejection of the `CancellablePromise`. - * - * The optional `oncancelled` argument will be invoked when the returned promise is cancelled, - * with the same semantics as the `oncancelled` argument of the constructor. - * When the parent promise rejects or is cancelled, the `onrejected` callback will run, - * _even after the returned promise has been cancelled:_ - * in that case, should it reject or throw, the reason will be wrapped - * in a {@link CancelledRejectionError} and bubbled up as an unhandled rejection. - * - * @param onfulfilled The callback to execute when the Promise is resolved. - * @param onrejected The callback to execute when the Promise is rejected. - * @returns A `CancellablePromise` for the completion of whichever callback is executed. - * The returned promise is hooked up to propagate cancellation requests up the chain, but not down: - * - * - if the parent promise is cancelled, the `onrejected` handler will be invoked with a `CancelError` - * and the returned promise _will resolve regularly_ with its result; - * - conversely, if the returned promise is cancelled, _the parent promise is cancelled too;_ - * the `onrejected` handler will still be invoked with the parent's `CancelError`, - * but its result will be discarded - * and the returned promise will reject with a `CancelError` as well. - * - * The promise returned from {@link cancel} will fulfill only after all attached handlers - * up the entire promise chain have been run. - * - * If either callback returns a cancellable promise, - * cancellation requests will be diverted to it, - * and the specified `oncancelled` callback will be discarded. - */ - then(onfulfilled, onrejected, oncancelled) { - if (!(this instanceof CancellablePromise)) { - throw new TypeError("CancellablePromise.prototype.then called on an invalid object."); - } - if (!isCallable(onfulfilled)) { - onfulfilled = identity; - } - if (!isCallable(onrejected)) { - onrejected = thrower; - } - if (onfulfilled === identity && onrejected == thrower) { - return new CancellablePromise((resolve) => resolve(this)); - } - const barrier = {}; - this[barrierSym] = barrier; - return new CancellablePromise((resolve, reject) => { - void super.then((value) => { - var _a2; - if (this[barrierSym] === barrier) { - this[barrierSym] = null; - } - (_a2 = barrier.resolve) === null || _a2 === void 0 ? void 0 : _a2.call(barrier); - try { - resolve(onfulfilled(value)); - } catch (err) { - reject(err); - } - }, (reason) => { - var _a2; - if (this[barrierSym] === barrier) { - this[barrierSym] = null; - } - (_a2 = barrier.resolve) === null || _a2 === void 0 ? void 0 : _a2.call(barrier); - try { - resolve(onrejected(reason)); - } catch (err) { - reject(err); - } - }); - }, async (cause) => { - try { - return oncancelled === null || oncancelled === void 0 ? void 0 : oncancelled(cause); - } finally { - await this.cancel(cause); - } - }); - } - /** - * Attaches a callback for only the rejection of the Promise. - * - * The optional `oncancelled` argument will be invoked when the returned promise is cancelled, - * with the same semantics as the `oncancelled` argument of the constructor. - * When the parent promise rejects or is cancelled, the `onrejected` callback will run, - * _even after the returned promise has been cancelled:_ - * in that case, should it reject or throw, the reason will be wrapped - * in a {@link CancelledRejectionError} and bubbled up as an unhandled rejection. - * - * It is equivalent to - * ```ts - * cancellablePromise.then(undefined, onrejected, oncancelled); - * ``` - * and the same caveats apply. - * - * @returns A Promise for the completion of the callback. - * Cancellation requests on the returned promise - * will propagate up the chain to the parent promise, - * but not in the other direction. - * - * The promise returned from {@link cancel} will fulfill only after all attached handlers - * up the entire promise chain have been run. - * - * If `onrejected` returns a cancellable promise, - * cancellation requests will be diverted to it, - * and the specified `oncancelled` callback will be discarded. - * See {@link then} for more details. - */ - catch(onrejected, oncancelled) { - return this.then(void 0, onrejected, oncancelled); - } - /** - * Attaches a callback that is invoked when the CancellablePromise is settled (fulfilled or rejected). The - * resolved value cannot be accessed or modified from the callback. - * The returned promise will settle in the same state as the original one - * after the provided callback has completed execution, - * unless the callback throws or returns a rejecting promise, - * in which case the returned promise will reject as well. - * - * The optional `oncancelled` argument will be invoked when the returned promise is cancelled, - * with the same semantics as the `oncancelled` argument of the constructor. - * Once the parent promise settles, the `onfinally` callback will run, - * _even after the returned promise has been cancelled:_ - * in that case, should it reject or throw, the reason will be wrapped - * in a {@link CancelledRejectionError} and bubbled up as an unhandled rejection. - * - * This method is implemented in terms of {@link then} and the same caveats apply. - * It is polyfilled, hence available in every OS/webview version. - * - * @returns A Promise for the completion of the callback. - * Cancellation requests on the returned promise - * will propagate up the chain to the parent promise, - * but not in the other direction. - * - * The promise returned from {@link cancel} will fulfill only after all attached handlers - * up the entire promise chain have been run. - * - * If `onfinally` returns a cancellable promise, - * cancellation requests will be diverted to it, - * and the specified `oncancelled` callback will be discarded. - * See {@link then} for more details. - */ - finally(onfinally, oncancelled) { - if (!(this instanceof CancellablePromise)) { - throw new TypeError("CancellablePromise.prototype.finally called on an invalid object."); - } - if (!isCallable(onfinally)) { - return this.then(onfinally, onfinally, oncancelled); - } - return this.then((value) => CancellablePromise.resolve(onfinally()).then(() => value), (reason) => CancellablePromise.resolve(onfinally()).then(() => { - throw reason; - }), oncancelled); - } - /** - * We use the `[Symbol.species]` static property, if available, - * to disable the built-in automatic subclassing features from {@link Promise}. - * It is critical for performance reasons that extenders do not override this. - * Once the proposal at https://github.com/tc39/proposal-rm-builtin-subclassing - * is either accepted or retired, this implementation will have to be revised accordingly. - * - * @ignore - * @internal - */ - static get [species]() { - return Promise; - } - static all(values) { - let collected = Array.from(values); - const promise = collected.length === 0 ? CancellablePromise.resolve(collected) : new CancellablePromise((resolve, reject) => { - void Promise.all(collected).then(resolve, reject); - }, (cause) => cancelAll(promise, collected, cause)); - return promise; - } - static allSettled(values) { - let collected = Array.from(values); - const promise = collected.length === 0 ? CancellablePromise.resolve(collected) : new CancellablePromise((resolve, reject) => { - void Promise.allSettled(collected).then(resolve, reject); - }, (cause) => cancelAll(promise, collected, cause)); - return promise; - } - static any(values) { - let collected = Array.from(values); - const promise = collected.length === 0 ? CancellablePromise.resolve(collected) : new CancellablePromise((resolve, reject) => { - void Promise.any(collected).then(resolve, reject); - }, (cause) => cancelAll(promise, collected, cause)); - return promise; - } - static race(values) { - let collected = Array.from(values); - const promise = new CancellablePromise((resolve, reject) => { - void Promise.race(collected).then(resolve, reject); - }, (cause) => cancelAll(promise, collected, cause)); - return promise; - } - /** - * Creates a new cancelled CancellablePromise for the provided cause. - * - * @group Static Methods - */ - static cancel(cause) { - const p = new CancellablePromise(() => { - }); - p.cancel(cause); - return p; - } - /** - * Creates a new CancellablePromise that cancels - * after the specified timeout, with the provided cause. - * - * If the {@link AbortSignal.timeout} factory method is available, - * it is used to base the timeout on _active_ time rather than _elapsed_ time. - * Otherwise, `timeout` falls back to {@link setTimeout}. - * - * @group Static Methods - */ - static timeout(milliseconds, cause) { - const promise = new CancellablePromise(() => { - }); - if (AbortSignal && typeof AbortSignal === "function" && AbortSignal.timeout && typeof AbortSignal.timeout === "function") { - AbortSignal.timeout(milliseconds).addEventListener("abort", () => void promise.cancel(cause)); - } else { - setTimeout(() => void promise.cancel(cause), milliseconds); - } - return promise; - } - static sleep(milliseconds, value) { - return new CancellablePromise((resolve) => { - setTimeout(() => resolve(value), milliseconds); - }); - } - /** - * Creates a new rejected CancellablePromise for the provided reason. - * - * @group Static Methods - */ - static reject(reason) { - return new CancellablePromise((_, reject) => reject(reason)); - } - static resolve(value) { - if (value instanceof CancellablePromise) { - return value; - } - return new CancellablePromise((resolve) => resolve(value)); - } - /** - * Creates a new CancellablePromise and returns it in an object, along with its resolve and reject functions - * and a getter/setter for the cancellation callback. - * - * This method is polyfilled, hence available in every OS/webview version. - * - * @group Static Methods - */ - static withResolvers() { - let result = { oncancelled: null }; - result.promise = new CancellablePromise((resolve, reject) => { - result.resolve = resolve; - result.reject = reject; - }, (cause) => { - var _a2; - (_a2 = result.oncancelled) === null || _a2 === void 0 ? void 0 : _a2.call(result, cause); - }); - return result; - } -} -function cancellerFor(promise, state) { - let cancellationPromise = void 0; - return (reason) => { - if (!state.settled) { - state.settled = true; - state.reason = reason; - promise.reject(reason); - void Promise.prototype.then.call(promise.promise, void 0, (err) => { - if (err !== reason) { - throw err; - } - }); - } - if (!state.reason || !promise.oncancelled) { - return; - } - cancellationPromise = new Promise((resolve) => { - try { - resolve(promise.oncancelled(state.reason.cause)); - } catch (err) { - Promise.reject(new CancelledRejectionError(promise.promise, err, "Unhandled exception in oncancelled callback.")); - } - }).catch((reason2) => { - Promise.reject(new CancelledRejectionError(promise.promise, reason2, "Unhandled rejection in oncancelled callback.")); - }); - promise.oncancelled = null; - return cancellationPromise; - }; -} -function resolverFor(promise, state) { - return (value) => { - if (state.resolving) { - return; - } - state.resolving = true; - if (value === promise.promise) { - if (state.settled) { - return; - } - state.settled = true; - promise.reject(new TypeError("A promise cannot be resolved with itself.")); - return; - } - if (value != null && (typeof value === "object" || typeof value === "function")) { - let then; - try { - then = value.then; - } catch (err) { - state.settled = true; - promise.reject(err); - return; - } - if (isCallable(then)) { - try { - let cancel = value.cancel; - if (isCallable(cancel)) { - const oncancelled = (cause) => { - Reflect.apply(cancel, value, [cause]); - }; - if (state.reason) { - void cancellerFor(Object.assign(Object.assign({}, promise), { oncancelled }), state)(state.reason); - } else { - promise.oncancelled = oncancelled; - } - } - } catch (_a2) { - } - const newState = { - root: state.root, - resolving: false, - get settled() { - return this.root.settled; - }, - set settled(value2) { - this.root.settled = value2; - }, - get reason() { - return this.root.reason; - } - }; - const rejector = rejectorFor(promise, newState); - try { - Reflect.apply(then, value, [resolverFor(promise, newState), rejector]); - } catch (err) { - rejector(err); - } - return; - } - } - if (state.settled) { - return; - } - state.settled = true; - promise.resolve(value); - }; -} -function rejectorFor(promise, state) { - return (reason) => { - if (state.resolving) { - return; - } - state.resolving = true; - if (state.settled) { - try { - if (reason instanceof CancelError && state.reason instanceof CancelError && Object.is(reason.cause, state.reason.cause)) { - return; - } - } catch (_a2) { - } - void Promise.reject(new CancelledRejectionError(promise.promise, reason)); - } else { - state.settled = true; - promise.reject(reason); - } - }; -} -function cancelAll(parent, values, cause) { - const results = []; - for (const value of values) { - let cancel; - try { - if (!isCallable(value.then)) { - continue; - } - cancel = value.cancel; - if (!isCallable(cancel)) { - continue; - } - } catch (_a2) { - continue; - } - let result; - try { - result = Reflect.apply(cancel, value, [cause]); - } catch (err) { - Promise.reject(new CancelledRejectionError(parent, err, "Unhandled exception in cancel method.")); - continue; - } - if (!result) { - continue; - } - results.push((result instanceof Promise ? result : Promise.resolve(result)).catch((reason) => { - Promise.reject(new CancelledRejectionError(parent, reason, "Unhandled rejection in cancel method.")); - })); - } - return Promise.all(results); -} -function identity(x) { - return x; -} -function thrower(reason) { - throw reason; -} -function errorMessage(err) { - try { - if (err instanceof Error || typeof err !== "object" || err.toString !== Object.prototype.toString) { - return "" + err; - } - } catch (_a2) { - } - try { - return JSON.stringify(err); - } catch (_b) { - } - try { - return Object.prototype.toString.call(err); - } catch (_c) { - } - return ""; -} -function currentBarrier(promise) { - var _a2; - let pwr = (_a2 = promise[barrierSym]) !== null && _a2 !== void 0 ? _a2 : {}; - if (!("promise" in pwr)) { - Object.assign(pwr, promiseWithResolvers()); - } - if (promise[barrierSym] == null) { - pwr.resolve(); - promise[barrierSym] = pwr; - } - return pwr.promise; -} -let promiseWithResolvers = Promise.withResolvers; -if (promiseWithResolvers && typeof promiseWithResolvers === "function") { - promiseWithResolvers = promiseWithResolvers.bind(Promise); -} else { - promiseWithResolvers = function() { - let resolve; - let reject; - const promise = new Promise((res, rej) => { - resolve = res; - reject = rej; - }); - return { promise, resolve, reject }; - }; -} -window._wails = window._wails || {}; -window._wails.callResultHandler = resultHandler; -window._wails.callErrorHandler = errorHandler; -const call$1 = newRuntimeCaller(objectNames.Call); -const cancelCall = newRuntimeCaller(objectNames.CancelCall); -const callResponses = /* @__PURE__ */ new Map(); -const CallBinding = 0; -const CancelMethod = 0; -class RuntimeError extends Error { - /** - * Constructs a new RuntimeError instance. - * @param message - The error message. - * @param options - Options to be forwarded to the Error constructor. - */ - constructor(message, options) { - super(message, options); - this.name = "RuntimeError"; - } -} -function resultHandler(id, data, isJSON) { - const resolvers = getAndDeleteResponse(id); - if (!resolvers) { - return; - } - if (!data) { - resolvers.resolve(void 0); - } else if (!isJSON) { - resolvers.resolve(data); - } else { - try { - resolvers.resolve(JSON.parse(data)); - } catch (err) { - resolvers.reject(new TypeError("could not parse result: " + err.message, { cause: err })); - } - } -} -function errorHandler(id, data, isJSON) { - const resolvers = getAndDeleteResponse(id); - if (!resolvers) { - return; - } - if (!isJSON) { - resolvers.reject(new Error(data)); - } else { - let error; - try { - error = JSON.parse(data); - } catch (err) { - resolvers.reject(new TypeError("could not parse error: " + err.message, { cause: err })); - return; - } - let options = {}; - if (error.cause) { - options.cause = error.cause; - } - let exception; - switch (error.kind) { - case "ReferenceError": - exception = new ReferenceError(error.message, options); - break; - case "TypeError": - exception = new TypeError(error.message, options); - break; - case "RuntimeError": - exception = new RuntimeError(error.message, options); - break; - default: - exception = new Error(error.message, options); - break; - } - resolvers.reject(exception); - } -} -function getAndDeleteResponse(id) { - const response = callResponses.get(id); - callResponses.delete(id); - return response; -} -function generateID() { - let result; - do { - result = nanoid(); - } while (callResponses.has(result)); - return result; -} -function Call(options) { - const id = generateID(); - const result = CancellablePromise.withResolvers(); - callResponses.set(id, { resolve: result.resolve, reject: result.reject }); - const request = call$1(CallBinding, Object.assign({ "call-id": id }, options)); - let running = false; - request.then(() => { - running = true; - }, (err) => { - callResponses.delete(id); - result.reject(err); - }); - const cancel = () => { - callResponses.delete(id); - return cancelCall(CancelMethod, { "call-id": id }).catch((err) => { - console.error("Error while requesting binding call cancellation:", err); - }); - }; - result.oncancelled = () => { - if (running) { - return cancel(); - } else { - return request.then(cancel); - } - }; - return result.promise; -} -function ByID(methodID, ...args) { - return Call({ methodID, args }); -} -const eventListeners = /* @__PURE__ */ new Map(); -class Listener { - constructor(eventName, callback, maxCallbacks) { - this.eventName = eventName; - this.callback = callback; - this.maxCallbacks = maxCallbacks || -1; - } - dispatch(data) { - try { - this.callback(data); - } catch (err) { - console.error(err); - } - if (this.maxCallbacks === -1) - return false; - this.maxCallbacks -= 1; - return this.maxCallbacks === 0; - } -} -function listenerOff(listener) { - let listeners = eventListeners.get(listener.eventName); - if (!listeners) { - return; - } - listeners = listeners.filter((l) => l !== listener); - if (listeners.length === 0) { - eventListeners.delete(listener.eventName); - } else { - eventListeners.set(listener.eventName, listeners); - } -} -window._wails = window._wails || {}; -window._wails.dispatchWailsEvent = dispatchWailsEvent; -const call = newRuntimeCaller(objectNames.Events); -const EmitMethod = 0; -class WailsEvent { - constructor(name, data = null) { - this.name = name; - this.data = data; - } -} -function dispatchWailsEvent(event) { - let listeners = eventListeners.get(event.name); - if (!listeners) { - return; - } - let wailsEvent = new WailsEvent(event.name, event.data); - if ("sender" in event) { - wailsEvent.sender = event.sender; - } - listeners = listeners.filter((listener) => !listener.dispatch(wailsEvent)); - if (listeners.length === 0) { - eventListeners.delete(event.name); - } else { - eventListeners.set(event.name, listeners); - } -} -function OnMultiple(eventName, callback, maxCallbacks) { - let listeners = eventListeners.get(eventName) || []; - const thisListener = new Listener(eventName, callback, maxCallbacks); - listeners.push(thisListener); - eventListeners.set(eventName, listeners); - return () => listenerOff(thisListener); -} -function On(eventName, callback) { - return OnMultiple(eventName, callback, -1); -} -function Emit(event) { - return call(EmitMethod, event); -} -window._wails = window._wails || {}; -window._wails.invoke = invoke; -invoke("wails:runtime:ready"); -function RemoveBadge() { - return ByID(2752757297); -} -function SetBadge(label) { - return ByID(1717705661, label); -} -function SetCustomBadge(label, options) { - return ByID(2730169760, label, options); -} -class RGBA { - /** Creates a new RGBA instance. */ - constructor($$source = {}) { - __publicField(this, "R"); - __publicField(this, "G"); - __publicField(this, "B"); - __publicField(this, "A"); - if (!("R" in $$source)) { - this["R"] = 0; - } - if (!("G" in $$source)) { - this["G"] = 0; - } - if (!("B" in $$source)) { - this["B"] = 0; - } - if (!("A" in $$source)) { - this["A"] = 0; - } - Object.assign(this, $$source); - } - /** - * Creates a new RGBA instance from a string or object. - */ - static createFrom($$source = {}) { - let $$parsedSource = typeof $$source === "string" ? JSON.parse($$source) : $$source; - return new RGBA($$parsedSource); - } -} -const setCustomButton = document.getElementById("set-custom"); -const setButton = document.getElementById("set"); -const removeButton = document.getElementById("remove"); -const setButtonUsingGo = document.getElementById("set-go"); -const removeButtonUsingGo = document.getElementById("remove-go"); -const labelElement = document.getElementById("label"); -const timeElement = document.getElementById("time"); -setCustomButton.addEventListener("click", () => { - console.log("click!"); - let label = labelElement.value; - SetCustomBadge(label, { - BackgroundColour: RGBA.createFrom({ - R: 0, - G: 255, - B: 255, - A: 255 - }), - FontName: "arialb.ttf", - // System font - FontSize: 16, - SmallFontSize: 10, - TextColour: RGBA.createFrom({ - R: 0, - G: 0, - B: 0, - A: 255 - }) - }); -}); -setButton.addEventListener("click", () => { - let label = labelElement.value; - SetBadge(label); -}); -removeButton.addEventListener("click", () => { - RemoveBadge(); -}); -setButtonUsingGo.addEventListener("click", () => { - let label = labelElement.value; - void Emit({ - name: "set:badge", - data: label - }); -}); -removeButtonUsingGo.addEventListener("click", () => { - void Emit({ name: "remove:badge", data: null }); -}); -On("time", (time) => { - timeElement.innerText = time.data; -}); diff --git a/v3/examples/badge-custom/frontend/dist/index.html b/v3/examples/badge-custom/frontend/dist/index.html deleted file mode 100644 index 11b9fcd50..000000000 --- a/v3/examples/badge-custom/frontend/dist/index.html +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - - - Wails App - - - -
      - -

      Wails + Typescript

      -
      Set a badge label below 👇
      -
      -
      - - - - - - -
      -
      - -
      - - diff --git a/v3/examples/badge-custom/frontend/dist/style.css b/v3/examples/badge-custom/frontend/dist/style.css deleted file mode 100644 index 6ce81cad2..000000000 --- a/v3/examples/badge-custom/frontend/dist/style.css +++ /dev/null @@ -1,155 +0,0 @@ -:root { - font-family: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", - "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", - sans-serif; - font-size: 16px; - line-height: 24px; - font-weight: 400; - color-scheme: light dark; - color: rgba(255, 255, 255, 0.87); - background-color: rgba(27, 38, 54, 1); - font-synthesis: none; - text-rendering: optimizeLegibility; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - -webkit-text-size-adjust: 100%; - user-select: none; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; -} - -@font-face { - font-family: "Inter"; - font-style: normal; - font-weight: 400; - src: local(""), - url("./Inter-Medium.ttf") format("truetype"); -} - -h3 { - font-size: 3em; - line-height: 1.1; -} - -a { - font-weight: 500; - color: #646cff; - text-decoration: inherit; -} - -a:hover { - color: #535bf2; -} - -button { - line-height: 30px; - border-radius: 3px; - border: none; - margin: 0 0 0 20px; - padding: 0 8px; - cursor: pointer; -} - -.result { - height: 20px; - line-height: 20px; -} - -body { - margin: 0; - display: flex; - place-items: center; - place-content: center; - min-width: 320px; - min-height: 100vh; -} - -.container { - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; -} - -h1 { - font-size: 3.2em; - line-height: 1.1; -} - -#app { - max-width: 1280px; - margin: 0 auto; - padding: 2rem; - text-align: center; -} - -.logo { - height: 6em; - padding: 1.5em; - will-change: filter; -} - -.logo:hover { - filter: drop-shadow(0 0 2em #e80000aa); -} - -.logo.vanilla:hover { - filter: drop-shadow(0 0 2em #f7df1eaa); -} - -.result { - height: 20px; - line-height: 20px; - margin: 1.5rem auto; - text-align: center; -} - -.footer { - margin-top: 1rem; - align-content: center; - text-align: center; -} - -@media (prefers-color-scheme: light) { - :root { - color: #213547; - background-color: #ffffff; - } - - a:hover { - color: #747bff; - } - - button { - background-color: #f9f9f9; - } -} - - -.input-box .btn:hover { - background-image: linear-gradient(to top, #cfd9df 0%, #e2ebf0 100%); - color: #333333; -} - -.input-box .input { - border: none; - border-radius: 3px; - outline: none; - height: 30px; - line-height: 30px; - padding: 0 10px; - color: black; - background-color: rgba(240, 240, 240, 1); - -webkit-font-smoothing: antialiased; -} - -.input-box .input:hover { - border: none; - background-color: rgba(255, 255, 255, 1); -} - -.input-box .input:focus { - border: none; - background-color: rgba(255, 255, 255, 1); -} \ No newline at end of file diff --git a/v3/examples/badge-custom/frontend/dist/typescript.svg b/v3/examples/badge-custom/frontend/dist/typescript.svg deleted file mode 100644 index d91c910cc..000000000 --- a/v3/examples/badge-custom/frontend/dist/typescript.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/v3/examples/badge-custom/frontend/dist/wails.png b/v3/examples/badge-custom/frontend/dist/wails.png deleted file mode 100644 index 8bdf42483..000000000 Binary files a/v3/examples/badge-custom/frontend/dist/wails.png and /dev/null differ diff --git a/v3/examples/badge-custom/frontend/index.html b/v3/examples/badge-custom/frontend/index.html deleted file mode 100644 index e4a9ec4a2..000000000 --- a/v3/examples/badge-custom/frontend/index.html +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - - - Wails App - - -
      - -

      Wails + Typescript

      -
      Set a badge label below 👇
      -
      -
      - - - - - - -
      -
      - -
      - - - diff --git a/v3/examples/badge-custom/frontend/package.json b/v3/examples/badge-custom/frontend/package.json deleted file mode 100644 index b39da7ece..000000000 --- a/v3/examples/badge-custom/frontend/package.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "name": "frontend", - "private": true, - "version": "0.0.0", - "type": "module", - "scripts": { - "dev": "vite", - "build:dev": "tsc && vite build --minify false --mode development", - "build": "tsc && vite build --mode production", - "preview": "vite preview" - }, - "dependencies": { - "@wailsio/runtime": "latest" - }, - "devDependencies": { - "typescript": "^4.9.3", - "vite": "^5.0.0" - } -} diff --git a/v3/examples/badge-custom/frontend/public/Inter-Medium.ttf b/v3/examples/badge-custom/frontend/public/Inter-Medium.ttf deleted file mode 100644 index a01f3777a..000000000 Binary files a/v3/examples/badge-custom/frontend/public/Inter-Medium.ttf and /dev/null differ diff --git a/v3/examples/badge-custom/frontend/public/style.css b/v3/examples/badge-custom/frontend/public/style.css deleted file mode 100644 index 6ce81cad2..000000000 --- a/v3/examples/badge-custom/frontend/public/style.css +++ /dev/null @@ -1,155 +0,0 @@ -:root { - font-family: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", - "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", - sans-serif; - font-size: 16px; - line-height: 24px; - font-weight: 400; - color-scheme: light dark; - color: rgba(255, 255, 255, 0.87); - background-color: rgba(27, 38, 54, 1); - font-synthesis: none; - text-rendering: optimizeLegibility; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - -webkit-text-size-adjust: 100%; - user-select: none; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; -} - -@font-face { - font-family: "Inter"; - font-style: normal; - font-weight: 400; - src: local(""), - url("./Inter-Medium.ttf") format("truetype"); -} - -h3 { - font-size: 3em; - line-height: 1.1; -} - -a { - font-weight: 500; - color: #646cff; - text-decoration: inherit; -} - -a:hover { - color: #535bf2; -} - -button { - line-height: 30px; - border-radius: 3px; - border: none; - margin: 0 0 0 20px; - padding: 0 8px; - cursor: pointer; -} - -.result { - height: 20px; - line-height: 20px; -} - -body { - margin: 0; - display: flex; - place-items: center; - place-content: center; - min-width: 320px; - min-height: 100vh; -} - -.container { - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; -} - -h1 { - font-size: 3.2em; - line-height: 1.1; -} - -#app { - max-width: 1280px; - margin: 0 auto; - padding: 2rem; - text-align: center; -} - -.logo { - height: 6em; - padding: 1.5em; - will-change: filter; -} - -.logo:hover { - filter: drop-shadow(0 0 2em #e80000aa); -} - -.logo.vanilla:hover { - filter: drop-shadow(0 0 2em #f7df1eaa); -} - -.result { - height: 20px; - line-height: 20px; - margin: 1.5rem auto; - text-align: center; -} - -.footer { - margin-top: 1rem; - align-content: center; - text-align: center; -} - -@media (prefers-color-scheme: light) { - :root { - color: #213547; - background-color: #ffffff; - } - - a:hover { - color: #747bff; - } - - button { - background-color: #f9f9f9; - } -} - - -.input-box .btn:hover { - background-image: linear-gradient(to top, #cfd9df 0%, #e2ebf0 100%); - color: #333333; -} - -.input-box .input { - border: none; - border-radius: 3px; - outline: none; - height: 30px; - line-height: 30px; - padding: 0 10px; - color: black; - background-color: rgba(240, 240, 240, 1); - -webkit-font-smoothing: antialiased; -} - -.input-box .input:hover { - border: none; - background-color: rgba(255, 255, 255, 1); -} - -.input-box .input:focus { - border: none; - background-color: rgba(255, 255, 255, 1); -} \ No newline at end of file diff --git a/v3/examples/badge-custom/frontend/public/typescript.svg b/v3/examples/badge-custom/frontend/public/typescript.svg deleted file mode 100644 index d91c910cc..000000000 --- a/v3/examples/badge-custom/frontend/public/typescript.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/v3/examples/badge-custom/frontend/public/wails.png b/v3/examples/badge-custom/frontend/public/wails.png deleted file mode 100644 index 8bdf42483..000000000 Binary files a/v3/examples/badge-custom/frontend/public/wails.png and /dev/null differ diff --git a/v3/examples/badge-custom/frontend/src/main.ts b/v3/examples/badge-custom/frontend/src/main.ts deleted file mode 100644 index cbb4cd842..000000000 --- a/v3/examples/badge-custom/frontend/src/main.ts +++ /dev/null @@ -1,56 +0,0 @@ -import {Events} from "@wailsio/runtime"; -import {SetBadge, RemoveBadge, SetCustomBadge} from "../bindings/github.com/wailsapp/wails/v3/pkg/services/dock/dockservice"; -import { RGBA } from "../bindings/image/color/models"; - -const setCustomButton = document.getElementById('set-custom')! as HTMLButtonElement; -const setButton = document.getElementById('set')! as HTMLButtonElement; -const removeButton = document.getElementById('remove')! as HTMLButtonElement; -const setButtonUsingGo = document.getElementById('set-go')! as HTMLButtonElement; -const removeButtonUsingGo = document.getElementById('remove-go')! as HTMLButtonElement; -const labelElement : HTMLInputElement = document.getElementById('label')! as HTMLInputElement; -const timeElement = document.getElementById('time')! as HTMLDivElement; - -setCustomButton.addEventListener('click', () => { - console.log("click!") - let label = (labelElement as HTMLInputElement).value - SetCustomBadge(label, { - BackgroundColour: RGBA.createFrom({ - R: 0, - G: 255, - B: 255, - A: 255, - }), - FontName: "arialb.ttf", // System font - FontSize: 16, - SmallFontSize: 10, - TextColour: RGBA.createFrom({ - R: 0, - G: 0, - B: 0, - A: 255, - }), - }); -}) - -setButton.addEventListener('click', () => { - let label = (labelElement as HTMLInputElement).value - SetBadge(label); -}); - -removeButton.addEventListener('click', () => { - RemoveBadge(); -}); - -setButtonUsingGo.addEventListener('click', () => { - let label = (labelElement as HTMLInputElement).value - void Events.Emit("set:badge", label); -}) - -removeButtonUsingGo.addEventListener('click', () => { - void Events.Emit("remove:badge"); -}) - -Events.On('time', (time: {data: any}) => { - timeElement.innerText = time.data; -}); - diff --git a/v3/examples/badge-custom/frontend/src/vite-env.d.ts b/v3/examples/badge-custom/frontend/src/vite-env.d.ts deleted file mode 100644 index 11f02fe2a..000000000 --- a/v3/examples/badge-custom/frontend/src/vite-env.d.ts +++ /dev/null @@ -1 +0,0 @@ -/// diff --git a/v3/examples/badge-custom/frontend/tsconfig.json b/v3/examples/badge-custom/frontend/tsconfig.json deleted file mode 100644 index c267ecf24..000000000 --- a/v3/examples/badge-custom/frontend/tsconfig.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "compilerOptions": { - "target": "ESNext", - "useDefineForClassFields": true, - "module": "ESNext", - "lib": ["ESNext", "DOM"], - "moduleResolution": "Node", - "strict": true, - "resolveJsonModule": true, - "isolatedModules": true, - "esModuleInterop": true, - "noEmit": true, - "noUnusedLocals": true, - "noUnusedParameters": false, - "noImplicitAny": false, - "noImplicitReturns": true, - "skipLibCheck": true - }, - "include": ["src"] -} diff --git a/v3/examples/badge-custom/main.go b/v3/examples/badge-custom/main.go deleted file mode 100644 index 93a32d1ff..000000000 --- a/v3/examples/badge-custom/main.go +++ /dev/null @@ -1,108 +0,0 @@ -package main - -import ( - "embed" - _ "embed" - "image/color" - "log" - "time" - - "github.com/wailsapp/wails/v3/pkg/application" - "github.com/wailsapp/wails/v3/pkg/services/dock" -) - -// Wails uses Go's `embed` package to embed the frontend files into the binary. -// Any files in the frontend/dist folder will be embedded into the binary and -// made available to the frontend. -// See https://pkg.go.dev/embed for more information. - -//go:embed all:frontend/dist -var assets embed.FS - -// main function serves as the application's entry point. It initializes the application, creates a window, -// and starts a goroutine that emits a time-based event every second. It subsequently runs the application and -// logs any error that might occur. -func main() { - // Create a new Wails application by providing the necessary options. - // Variables 'Name' and 'Description' are for application metadata. - // 'Assets' configures the asset server with the 'FS' variable pointing to the frontend files. - // 'Bind' is a list of Go struct instances. The frontend has access to the methods of these instances. - // 'Mac' options tailor the application when running an macOS. - - dockService := dock.NewWithOptions(dock.BadgeOptions{ - TextColour: color.RGBA{255, 255, 204, 255}, - BackgroundColour: color.RGBA{16, 124, 16, 255}, - FontName: "consolab.ttf", - FontSize: 20, - SmallFontSize: 14, - }) - - app := application.New(application.Options{ - Name: "badge", - Description: "A demo of using raw HTML & CSS", - Services: []application.Service{ - application.NewService(dockService), - }, - Assets: application.AssetOptions{ - Handler: application.AssetFileServerFS(assets), - }, - Mac: application.MacOptions{ - ApplicationShouldTerminateAfterLastWindowClosed: true, - }, - }) - - // Create a new window with the necessary options. - // 'Title' is the title of the window. - // 'Mac' options tailor the window when running on macOS. - // 'BackgroundColour' is the background colour of the window. - // 'URL' is the URL that will be loaded into the webview. - app.Window.NewWithOptions(application.WebviewWindowOptions{ - Title: "Window 1", - Mac: application.MacWindow{ - InvisibleTitleBarHeight: 50, - Backdrop: application.MacBackdropTranslucent, - TitleBar: application.MacTitleBarHiddenInset, - }, - BackgroundColour: application.NewRGB(27, 38, 54), - URL: "/", - }) - - app.Event.On("remove:badge", func(event *application.CustomEvent) { - err := dockService.RemoveBadge() - if err != nil { - log.Fatal(err) - } - }) - - app.Event.On("set:badge", func(event *application.CustomEvent) { - text := event.Data.(string) - err := dockService.SetBadge(text) - if err != nil { - log.Fatal(err) - } - }) - - // Create a goroutine that emits an event containing the current time every second. - // The frontend can listen to this event and update the UI accordingly. - go func() { - ticker := time.NewTicker(time.Second) - defer ticker.Stop() - for { - select { - case <-ticker.C: - now := time.Now().Format(time.RFC1123) - app.Event.Emit("time", now) - case <-app.Context().Done(): - return - } - } - }() - - // Run the application. This blocks until the application has been exited. - err := app.Run() - - // If an error occurred while running the application, log it and exit. - if err != nil { - log.Fatal(err) - } -} diff --git a/v3/examples/badge/README.md b/v3/examples/badge/README.md deleted file mode 100644 index abb7b9653..000000000 --- a/v3/examples/badge/README.md +++ /dev/null @@ -1,71 +0,0 @@ -# Welcome to Your New Wails3 Project! -Now that you have your project set up, it's time to explore the basic badge features that Wails3 offers on **macOS** and **Windows**. - -## Exploring Badge Features - -### Creating the Service - -First, initialize the badge service: - -```go -import "github.com/wailsapp/wails/v3/pkg/application" -import "github.com/wailsapp/wails/v3/pkg/services/badge" - -// Create a new badge service -badgeService := badge.New() - -// Register the service with the application -app := application.New(application.Options{ - Services: []application.Service{ - application.NewService(badgeService), - }, -}) -``` - -## Badge Operations - -### Setting a Badge - -Set a badge on the application tile/dock icon: - -#### Go -```go -// Set a default badge -badgeService.SetBadge("") - -// Set a numeric badge -badgeService.SetBadge("3") - -// Set a text badge -badgeService.SetBadge("New") -``` - -#### JS -```js -import {SetBadge} from "../bindings/github.com/wailsapp/wails/v3/pkg/services/badge/service"; - -// Set a default badge -SetBadge("") - -// Set a numeric badge -SetBadge("3") - -// Set a text badge -SetBadge("New") -``` - -### Removing a Badge - -Remove the badge from the application icon: - -#### Go -```go -badgeService.RemoveBadge() -``` - -#### JS -```js -import {RemoveBadge} from "../bindings/github.com/wailsapp/wails/v3/pkg/services/badge/service"; - -RemoveBadge() -``` \ No newline at end of file diff --git a/v3/examples/badge/Taskfile.yml b/v3/examples/badge/Taskfile.yml deleted file mode 100644 index d1bcfaacf..000000000 --- a/v3/examples/badge/Taskfile.yml +++ /dev/null @@ -1,34 +0,0 @@ -version: '3' - -includes: - common: ./build/Taskfile.yml - windows: ./build/windows/Taskfile.yml - darwin: ./build/darwin/Taskfile.yml - linux: ./build/linux/Taskfile.yml - -vars: - APP_NAME: "badge" - BIN_DIR: "bin" - VITE_PORT: '{{.WAILS_VITE_PORT | default 9245}}' - -tasks: - build: - summary: Builds the application - cmds: - - task: "{{OS}}:build" - - package: - summary: Packages a production build of the application - cmds: - - task: "{{OS}}:package" - - run: - summary: Runs the application - cmds: - - task: "{{OS}}:run" - - dev: - summary: Runs the application in development mode - cmds: - - wails3 dev -config ./build/config.yml -port {{.VITE_PORT}} - diff --git a/v3/examples/badge/build/Taskfile.yml b/v3/examples/badge/build/Taskfile.yml deleted file mode 100644 index 5f3517efc..000000000 --- a/v3/examples/badge/build/Taskfile.yml +++ /dev/null @@ -1,86 +0,0 @@ -version: '3' - -tasks: - go:mod:tidy: - summary: Runs `go mod tidy` - internal: true - cmds: - - go mod tidy - - install:frontend:deps: - summary: Install frontend dependencies - dir: frontend - sources: - - package.json - - package-lock.json - generates: - - node_modules/* - preconditions: - - sh: npm version - msg: "Looks like npm isn't installed. Npm is part of the Node installer: https://nodejs.org/en/download/" - cmds: - - npm install - - build:frontend: - label: build:frontend (PRODUCTION={{.PRODUCTION}}) - summary: Build the frontend project - dir: frontend - sources: - - "**/*" - generates: - - dist/**/* - deps: - - task: install:frontend:deps - - task: generate:bindings - vars: - BUILD_FLAGS: - ref: .BUILD_FLAGS - cmds: - - npm run {{.BUILD_COMMAND}} -q - env: - PRODUCTION: '{{.PRODUCTION | default "false"}}' - vars: - BUILD_COMMAND: '{{if eq .PRODUCTION "true"}}build{{else}}build:dev{{end}}' - - - generate:bindings: - label: generate:bindings (BUILD_FLAGS={{.BUILD_FLAGS}}) - summary: Generates bindings for the frontend - deps: - - task: go:mod:tidy - sources: - - "**/*.[jt]s" - - exclude: frontend/**/* - - frontend/bindings/**/* # Rerun when switching between dev/production mode causes changes in output - - "**/*.go" - - go.mod - - go.sum - generates: - - frontend/bindings/**/* - cmds: - - wails3 generate bindings -f '{{.BUILD_FLAGS}}' -clean=true -ts - - generate:icons: - summary: Generates Windows `.ico` and Mac `.icns` files from an image - dir: build - sources: - - "appicon.png" - generates: - - "darwin/icons.icns" - - "windows/icon.ico" - cmds: - - wails3 generate icons -input appicon.png -macfilename darwin/icons.icns -windowsfilename windows/icon.ico - - dev:frontend: - summary: Runs the frontend in development mode - dir: frontend - deps: - - task: install:frontend:deps - cmds: - - npm run dev -- --port {{.VITE_PORT}} --strictPort - - update:build-assets: - summary: Updates the build assets - dir: build - cmds: - - wails3 update build-assets -name "{{.APP_NAME}}" -binaryname "{{.APP_NAME}}" -config config.yml -dir . diff --git a/v3/examples/badge/build/appicon.png b/v3/examples/badge/build/appicon.png deleted file mode 100644 index 63617fe4f..000000000 Binary files a/v3/examples/badge/build/appicon.png and /dev/null differ diff --git a/v3/examples/badge/build/config.yml b/v3/examples/badge/build/config.yml deleted file mode 100644 index aaa3240fb..000000000 --- a/v3/examples/badge/build/config.yml +++ /dev/null @@ -1,63 +0,0 @@ -# This file contains the configuration for this project. -# When you update `info` or `fileAssociations`, run `wails3 task common:update:build-assets` to update the assets. -# Note that this will overwrite any changes you have made to the assets. -version: '3' - -# This information is used to generate the build assets. -info: - companyName: "My Company" # The name of the company - productName: "My Product" # The name of the application - productIdentifier: "com.mycompany.myproduct" # The unique product identifier - description: "A program that does X" # The application description - copyright: "(c) 2025, My Company" # Copyright text - comments: "Some Product Comments" # Comments - version: "0.0.1" # The application version - -# Dev mode configuration -dev_mode: - root_path: . - log_level: warn - debounce: 1000 - ignore: - dir: - - .git - - node_modules - - frontend - - bin - file: - - .DS_Store - - .gitignore - - .gitkeep - watched_extension: - - "*.go" - git_ignore: true - executes: - - cmd: wails3 task common:install:frontend:deps - type: once - - cmd: wails3 task common:dev:frontend - type: background - - cmd: go mod tidy - type: blocking - - cmd: wails3 task build - type: blocking - - cmd: wails3 task run - type: primary - -# File Associations -# More information at: https://v3.wails.io/noit/done/yet -fileAssociations: -# - ext: wails -# name: Wails -# description: Wails Application File -# iconName: wailsFileIcon -# role: Editor -# - ext: jpg -# name: JPEG -# description: Image File -# iconName: jpegFileIcon -# role: Editor -# mimeType: image/jpeg # (optional) - -# Other data -other: - - name: My Other Data \ No newline at end of file diff --git a/v3/examples/badge/build/darwin/Info.dev.plist b/v3/examples/badge/build/darwin/Info.dev.plist deleted file mode 100644 index 4caddf720..000000000 --- a/v3/examples/badge/build/darwin/Info.dev.plist +++ /dev/null @@ -1,32 +0,0 @@ - - - - CFBundlePackageType - APPL - CFBundleName - My Product - CFBundleExecutable - badge - CFBundleIdentifier - com.wails.badge - CFBundleVersion - 0.1.0 - CFBundleGetInfoString - This is a comment - CFBundleShortVersionString - 0.1.0 - CFBundleIconFile - icons - LSMinimumSystemVersion - 10.15.0 - NSHighResolutionCapable - true - NSHumanReadableCopyright - © now, My Company - NSAppTransportSecurity - - NSAllowsLocalNetworking - - - - \ No newline at end of file diff --git a/v3/examples/badge/build/darwin/Info.plist b/v3/examples/badge/build/darwin/Info.plist deleted file mode 100644 index 0dc90b2e7..000000000 --- a/v3/examples/badge/build/darwin/Info.plist +++ /dev/null @@ -1,27 +0,0 @@ - - - - CFBundlePackageType - APPL - CFBundleName - My Product - CFBundleExecutable - badge - CFBundleIdentifier - com.wails.badge - CFBundleVersion - 0.1.0 - CFBundleGetInfoString - This is a comment - CFBundleShortVersionString - 0.1.0 - CFBundleIconFile - icons - LSMinimumSystemVersion - 10.15.0 - NSHighResolutionCapable - true - NSHumanReadableCopyright - © now, My Company - - \ No newline at end of file diff --git a/v3/examples/badge/build/darwin/Taskfile.yml b/v3/examples/badge/build/darwin/Taskfile.yml deleted file mode 100644 index f0791fea9..000000000 --- a/v3/examples/badge/build/darwin/Taskfile.yml +++ /dev/null @@ -1,81 +0,0 @@ -version: '3' - -includes: - common: ../Taskfile.yml - -tasks: - build: - summary: Creates a production build of the application - deps: - - task: common:go:mod:tidy - - task: common:build:frontend - vars: - BUILD_FLAGS: - ref: .BUILD_FLAGS - PRODUCTION: - ref: .PRODUCTION - - task: common:generate:icons - cmds: - - go build {{.BUILD_FLAGS}} -o {{.OUTPUT}} - vars: - BUILD_FLAGS: '{{if eq .PRODUCTION "true"}}-tags production -trimpath -buildvcs=false -ldflags="-w -s"{{else}}-buildvcs=false -gcflags=all="-l"{{end}}' - DEFAULT_OUTPUT: '{{.BIN_DIR}}/{{.APP_NAME}}' - OUTPUT: '{{ .OUTPUT | default .DEFAULT_OUTPUT }}' - env: - GOOS: darwin - CGO_ENABLED: 1 - GOARCH: '{{.ARCH | default ARCH}}' - CGO_CFLAGS: "-mmacosx-version-min=10.15" - CGO_LDFLAGS: "-mmacosx-version-min=10.15" - MACOSX_DEPLOYMENT_TARGET: "10.15" - PRODUCTION: '{{.PRODUCTION | default "false"}}' - - build:universal: - summary: Builds darwin universal binary (arm64 + amd64) - deps: - - task: build - vars: - ARCH: amd64 - OUTPUT: "{{.BIN_DIR}}/{{.APP_NAME}}-amd64" - - task: build - vars: - ARCH: arm64 - OUTPUT: "{{.BIN_DIR}}/{{.APP_NAME}}-arm64" - cmds: - - lipo -create -output "{{.BIN_DIR}}/{{.APP_NAME}}" "{{.BIN_DIR}}/{{.APP_NAME}}-amd64" "{{.BIN_DIR}}/{{.APP_NAME}}-arm64" - - rm "{{.BIN_DIR}}/{{.APP_NAME}}-amd64" "{{.BIN_DIR}}/{{.APP_NAME}}-arm64" - - package: - summary: Packages a production build of the application into a `.app` bundle - deps: - - task: build - vars: - PRODUCTION: "true" - cmds: - - task: create:app:bundle - - package:universal: - summary: Packages darwin universal binary (arm64 + amd64) - deps: - - task: build:universal - cmds: - - task: create:app:bundle - - - create:app:bundle: - summary: Creates an `.app` bundle - cmds: - - mkdir -p {{.BIN_DIR}}/{{.APP_NAME}}.app/Contents/{MacOS,Resources} - - cp build/darwin/icons.icns {{.BIN_DIR}}/{{.APP_NAME}}.app/Contents/Resources - - cp {{.BIN_DIR}}/{{.APP_NAME}} {{.BIN_DIR}}/{{.APP_NAME}}.app/Contents/MacOS - - cp build/darwin/Info.plist {{.BIN_DIR}}/{{.APP_NAME}}.app/Contents - - codesign --force --deep --sign - {{.BIN_DIR}}/{{.APP_NAME}}.app - - run: - cmds: - - mkdir -p {{.BIN_DIR}}/{{.APP_NAME}}.dev.app/Contents/{MacOS,Resources} - - cp build/darwin/icons.icns {{.BIN_DIR}}/{{.APP_NAME}}.dev.app/Contents/Resources - - cp {{.BIN_DIR}}/{{.APP_NAME}} {{.BIN_DIR}}/{{.APP_NAME}}.dev.app/Contents/MacOS - - cp build/darwin/Info.dev.plist {{.BIN_DIR}}/{{.APP_NAME}}.dev.app/Contents/Info.plist - - codesign --force --deep --sign - {{.BIN_DIR}}/{{.APP_NAME}}.dev.app - - '{{.BIN_DIR}}/{{.APP_NAME}}.dev.app/Contents/MacOS/{{.APP_NAME}}' diff --git a/v3/examples/badge/build/darwin/icons.icns b/v3/examples/badge/build/darwin/icons.icns deleted file mode 100644 index 1b5bd4c86..000000000 Binary files a/v3/examples/badge/build/darwin/icons.icns and /dev/null differ diff --git a/v3/examples/badge/build/linux/Taskfile.yml b/v3/examples/badge/build/linux/Taskfile.yml deleted file mode 100644 index 560cc9c92..000000000 --- a/v3/examples/badge/build/linux/Taskfile.yml +++ /dev/null @@ -1,119 +0,0 @@ -version: '3' - -includes: - common: ../Taskfile.yml - -tasks: - build: - summary: Builds the application for Linux - deps: - - task: common:go:mod:tidy - - task: common:build:frontend - vars: - BUILD_FLAGS: - ref: .BUILD_FLAGS - PRODUCTION: - ref: .PRODUCTION - - task: common:generate:icons - cmds: - - go build {{.BUILD_FLAGS}} -o {{.BIN_DIR}}/{{.APP_NAME}} - vars: - BUILD_FLAGS: '{{if eq .PRODUCTION "true"}}-tags production -trimpath -buildvcs=false -ldflags="-w -s"{{else}}-buildvcs=false -gcflags=all="-l"{{end}}' - env: - GOOS: linux - CGO_ENABLED: 1 - GOARCH: '{{.ARCH | default ARCH}}' - PRODUCTION: '{{.PRODUCTION | default "false"}}' - - package: - summary: Packages a production build of the application for Linux - deps: - - task: build - vars: - PRODUCTION: "true" - cmds: - - task: create:appimage - - task: create:deb - - task: create:rpm - - task: create:aur - - create:appimage: - summary: Creates an AppImage - dir: build/linux/appimage - deps: - - task: build - vars: - PRODUCTION: "true" - - task: generate:dotdesktop - cmds: - - cp {{.APP_BINARY}} {{.APP_NAME}} - - cp ../../appicon.png appicon.png - - wails3 generate appimage -binary {{.APP_NAME}} -icon {{.ICON}} -desktopfile {{.DESKTOP_FILE}} -outputdir {{.OUTPUT_DIR}} -builddir {{.ROOT_DIR}}/build/linux/appimage/build - vars: - APP_NAME: '{{.APP_NAME}}' - APP_BINARY: '../../../bin/{{.APP_NAME}}' - ICON: '../../appicon.png' - DESKTOP_FILE: '../{{.APP_NAME}}.desktop' - OUTPUT_DIR: '../../../bin' - - create:deb: - summary: Creates a deb package - deps: - - task: build - vars: - PRODUCTION: "true" - cmds: - - task: generate:dotdesktop - - task: generate:deb - - create:rpm: - summary: Creates a rpm package - deps: - - task: build - vars: - PRODUCTION: "true" - cmds: - - task: generate:dotdesktop - - task: generate:rpm - - create:aur: - summary: Creates a arch linux packager package - deps: - - task: build - vars: - PRODUCTION: "true" - cmds: - - task: generate:dotdesktop - - task: generate:aur - - generate:deb: - summary: Creates a deb package - cmds: - - wails3 tool package -name {{.APP_NAME}} -format deb -config ./build/linux/nfpm/nfpm.yaml -out {{.ROOT_DIR}}/bin - - generate:rpm: - summary: Creates a rpm package - cmds: - - wails3 tool package -name {{.APP_NAME}} -format rpm -config ./build/linux/nfpm/nfpm.yaml -out {{.ROOT_DIR}}/bin - - generate:aur: - summary: Creates a arch linux packager package - cmds: - - wails3 tool package -name {{.APP_NAME}} -format archlinux -config ./build/linux/nfpm/nfpm.yaml -out {{.ROOT_DIR}}/bin - - generate:dotdesktop: - summary: Generates a `.desktop` file - dir: build - cmds: - - mkdir -p {{.ROOT_DIR}}/build/linux/appimage - - wails3 generate .desktop -name "{{.APP_NAME}}" -exec "{{.EXEC}}" -icon "{{.ICON}}" -outputfile {{.ROOT_DIR}}/build/linux/{{.APP_NAME}}.desktop -categories "{{.CATEGORIES}}" - vars: - APP_NAME: '{{.APP_NAME}}' - EXEC: '{{.APP_NAME}}' - ICON: 'appicon' - CATEGORIES: 'Development;' - OUTPUTFILE: '{{.ROOT_DIR}}/build/linux/{{.APP_NAME}}.desktop' - - run: - cmds: - - '{{.BIN_DIR}}/{{.APP_NAME}}' diff --git a/v3/examples/badge/build/linux/appimage/build.sh b/v3/examples/badge/build/linux/appimage/build.sh deleted file mode 100644 index 85901c34e..000000000 --- a/v3/examples/badge/build/linux/appimage/build.sh +++ /dev/null @@ -1,35 +0,0 @@ -#!/usr/bin/env bash -# Copyright (c) 2018-Present Lea Anthony -# SPDX-License-Identifier: MIT - -# Fail script on any error -set -euxo pipefail - -# Define variables -APP_DIR="${APP_NAME}.AppDir" - -# Create AppDir structure -mkdir -p "${APP_DIR}/usr/bin" -cp -r "${APP_BINARY}" "${APP_DIR}/usr/bin/" -cp "${ICON_PATH}" "${APP_DIR}/" -cp "${DESKTOP_FILE}" "${APP_DIR}/" - -if [[ $(uname -m) == *x86_64* ]]; then - # Download linuxdeploy and make it executable - wget -q -4 -N https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-x86_64.AppImage - chmod +x linuxdeploy-x86_64.AppImage - - # Run linuxdeploy to bundle the application - ./linuxdeploy-x86_64.AppImage --appdir "${APP_DIR}" --output appimage -else - # Download linuxdeploy and make it executable (arm64) - wget -q -4 -N https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-aarch64.AppImage - chmod +x linuxdeploy-aarch64.AppImage - - # Run linuxdeploy to bundle the application (arm64) - ./linuxdeploy-aarch64.AppImage --appdir "${APP_DIR}" --output appimage -fi - -# Rename the generated AppImage -mv "${APP_NAME}*.AppImage" "${APP_NAME}.AppImage" - diff --git a/v3/examples/badge/build/linux/nfpm/nfpm.yaml b/v3/examples/badge/build/linux/nfpm/nfpm.yaml deleted file mode 100644 index 5b7ea9d02..000000000 --- a/v3/examples/badge/build/linux/nfpm/nfpm.yaml +++ /dev/null @@ -1,50 +0,0 @@ -# Feel free to remove those if you don't want/need to use them. -# Make sure to check the documentation at https://nfpm.goreleaser.com -# -# The lines below are called `modelines`. See `:help modeline` - -name: "badge" -arch: ${GOARCH} -platform: "linux" -version: "0.1.0" -section: "default" -priority: "extra" -maintainer: ${GIT_COMMITTER_NAME} <${GIT_COMMITTER_EMAIL}> -description: "My Product Description" -vendor: "My Company" -homepage: "https://wails.io" -license: "MIT" -release: "1" - -contents: - - src: "./bin/badge" - dst: "/usr/local/bin/badge" - - src: "./build/appicon.png" - dst: "/usr/share/icons/hicolor/128x128/apps/badge.png" - - src: "./build/linux/badge.desktop" - dst: "/usr/share/applications/badge.desktop" - -depends: - - gtk3 - - libwebkit2gtk - -# replaces: -# - foobar -# provides: -# - bar -# depends: -# - gtk3 -# - libwebkit2gtk -# recommends: -# - whatever -# suggests: -# - something-else -# conflicts: -# - not-foo -# - not-bar -# changelog: "changelog.yaml" -# scripts: -# preinstall: ./build/linux/nfpm/scripts/preinstall.sh -# postinstall: ./build/linux/nfpm/scripts/postinstall.sh -# preremove: ./build/linux/nfpm/scripts/preremove.sh -# postremove: ./build/linux/nfpm/scripts/postremove.sh diff --git a/v3/examples/badge/build/linux/nfpm/scripts/postinstall.sh b/v3/examples/badge/build/linux/nfpm/scripts/postinstall.sh deleted file mode 100644 index a9bf588e2..000000000 --- a/v3/examples/badge/build/linux/nfpm/scripts/postinstall.sh +++ /dev/null @@ -1 +0,0 @@ -#!/bin/bash diff --git a/v3/examples/badge/build/linux/nfpm/scripts/postremove.sh b/v3/examples/badge/build/linux/nfpm/scripts/postremove.sh deleted file mode 100644 index a9bf588e2..000000000 --- a/v3/examples/badge/build/linux/nfpm/scripts/postremove.sh +++ /dev/null @@ -1 +0,0 @@ -#!/bin/bash diff --git a/v3/examples/badge/build/linux/nfpm/scripts/preinstall.sh b/v3/examples/badge/build/linux/nfpm/scripts/preinstall.sh deleted file mode 100644 index a9bf588e2..000000000 --- a/v3/examples/badge/build/linux/nfpm/scripts/preinstall.sh +++ /dev/null @@ -1 +0,0 @@ -#!/bin/bash diff --git a/v3/examples/badge/build/linux/nfpm/scripts/preremove.sh b/v3/examples/badge/build/linux/nfpm/scripts/preremove.sh deleted file mode 100644 index a9bf588e2..000000000 --- a/v3/examples/badge/build/linux/nfpm/scripts/preremove.sh +++ /dev/null @@ -1 +0,0 @@ -#!/bin/bash diff --git a/v3/examples/badge/build/windows/Taskfile.yml b/v3/examples/badge/build/windows/Taskfile.yml deleted file mode 100644 index 534f4fb31..000000000 --- a/v3/examples/badge/build/windows/Taskfile.yml +++ /dev/null @@ -1,63 +0,0 @@ -version: '3' - -includes: - common: ../Taskfile.yml - -tasks: - build: - summary: Builds the application for Windows - deps: - - task: common:go:mod:tidy - - task: common:build:frontend - vars: - BUILD_FLAGS: - ref: .BUILD_FLAGS - PRODUCTION: - ref: .PRODUCTION - - task: common:generate:icons - cmds: - - task: generate:syso - - go build {{.BUILD_FLAGS}} -o {{.BIN_DIR}}/{{.APP_NAME}}.exe - - cmd: powershell Remove-item *.syso - platforms: [windows] - - cmd: rm -f *.syso - platforms: [linux, darwin] - vars: - BUILD_FLAGS: '{{if eq .PRODUCTION "true"}}-tags production -trimpath -buildvcs=false -ldflags="-w -s -H windowsgui"{{else}}-buildvcs=false -gcflags=all="-l"{{end}}' - env: - GOOS: windows - CGO_ENABLED: 0 - GOARCH: '{{.ARCH | default ARCH}}' - PRODUCTION: '{{.PRODUCTION | default "false"}}' - - package: - summary: Packages a production build of the application into a `.exe` bundle - cmds: - - task: create:nsis:installer - - generate:syso: - summary: Generates Windows `.syso` file - dir: build - cmds: - - wails3 generate syso -arch {{.ARCH}} -icon windows/icon.ico -manifest windows/wails.exe.manifest -info windows/info.json -out ../wails_windows_{{.ARCH}}.syso - vars: - ARCH: '{{.ARCH | default ARCH}}' - - create:nsis:installer: - summary: Creates an NSIS installer - dir: build/windows/nsis - deps: - - task: build - vars: - PRODUCTION: "true" - cmds: - # Create the Microsoft WebView2 bootstrapper if it doesn't exist - - wails3 generate webview2bootstrapper -dir "{{.ROOT_DIR}}/build/windows/nsis" - - makensis -DARG_WAILS_{{.ARG_FLAG}}_BINARY="{{.ROOT_DIR}}/{{.BIN_DIR}}/{{.APP_NAME}}.exe" project.nsi - vars: - ARCH: '{{.ARCH | default ARCH}}' - ARG_FLAG: '{{if eq .ARCH "amd64"}}AMD64{{else}}ARM64{{end}}' - - run: - cmds: - - '{{.BIN_DIR}}/{{.APP_NAME}}.exe' diff --git a/v3/examples/badge/build/windows/icon.ico b/v3/examples/badge/build/windows/icon.ico deleted file mode 100644 index bfa0690b7..000000000 Binary files a/v3/examples/badge/build/windows/icon.ico and /dev/null differ diff --git a/v3/examples/badge/build/windows/info.json b/v3/examples/badge/build/windows/info.json deleted file mode 100644 index 850b2b5b0..000000000 --- a/v3/examples/badge/build/windows/info.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "fixed": { - "file_version": "0.1.0" - }, - "info": { - "0000": { - "ProductVersion": "0.1.0", - "CompanyName": "My Company", - "FileDescription": "My Product Description", - "LegalCopyright": "© now, My Company", - "ProductName": "My Product", - "Comments": "This is a comment" - } - } -} \ No newline at end of file diff --git a/v3/examples/badge/build/windows/nsis/project.nsi b/v3/examples/badge/build/windows/nsis/project.nsi deleted file mode 100644 index 985b8e207..000000000 --- a/v3/examples/badge/build/windows/nsis/project.nsi +++ /dev/null @@ -1,112 +0,0 @@ -Unicode true - -#### -## Please note: Template replacements don't work in this file. They are provided with default defines like -## mentioned underneath. -## If the keyword is not defined, "wails_tools.nsh" will populate them. -## If they are defined here, "wails_tools.nsh" will not touch them. This allows you to use this project.nsi manually -## from outside of Wails for debugging and development of the installer. -## -## For development first make a wails nsis build to populate the "wails_tools.nsh": -## > wails build --target windows/amd64 --nsis -## Then you can call makensis on this file with specifying the path to your binary: -## For a AMD64 only installer: -## > makensis -DARG_WAILS_AMD64_BINARY=..\..\bin\app.exe -## For a ARM64 only installer: -## > makensis -DARG_WAILS_ARM64_BINARY=..\..\bin\app.exe -## For a installer with both architectures: -## > makensis -DARG_WAILS_AMD64_BINARY=..\..\bin\app-amd64.exe -DARG_WAILS_ARM64_BINARY=..\..\bin\app-arm64.exe -#### -## The following information is taken from the wails_tools.nsh file, but they can be overwritten here. -#### -## !define INFO_PROJECTNAME "my-project" # Default "badge" -## !define INFO_COMPANYNAME "My Company" # Default "My Company" -## !define INFO_PRODUCTNAME "My Product Name" # Default "My Product" -## !define INFO_PRODUCTVERSION "1.0.0" # Default "0.1.0" -## !define INFO_COPYRIGHT "(c) Now, My Company" # Default "© now, My Company" -### -## !define PRODUCT_EXECUTABLE "Application.exe" # Default "${INFO_PROJECTNAME}.exe" -## !define UNINST_KEY_NAME "UninstKeyInRegistry" # Default "${INFO_COMPANYNAME}${INFO_PRODUCTNAME}" -#### -## !define REQUEST_EXECUTION_LEVEL "admin" # Default "admin" see also https://nsis.sourceforge.io/Docs/Chapter4.html -#### -## Include the wails tools -#### -!include "wails_tools.nsh" - -# The version information for this two must consist of 4 parts -VIProductVersion "${INFO_PRODUCTVERSION}.0" -VIFileVersion "${INFO_PRODUCTVERSION}.0" - -VIAddVersionKey "CompanyName" "${INFO_COMPANYNAME}" -VIAddVersionKey "FileDescription" "${INFO_PRODUCTNAME} Installer" -VIAddVersionKey "ProductVersion" "${INFO_PRODUCTVERSION}" -VIAddVersionKey "FileVersion" "${INFO_PRODUCTVERSION}" -VIAddVersionKey "LegalCopyright" "${INFO_COPYRIGHT}" -VIAddVersionKey "ProductName" "${INFO_PRODUCTNAME}" - -# Enable HiDPI support. https://nsis.sourceforge.io/Reference/ManifestDPIAware -ManifestDPIAware true - -!include "MUI.nsh" - -!define MUI_ICON "..\icon.ico" -!define MUI_UNICON "..\icon.ico" -# !define MUI_WELCOMEFINISHPAGE_BITMAP "resources\leftimage.bmp" #Include this to add a bitmap on the left side of the Welcome Page. Must be a size of 164x314 -!define MUI_FINISHPAGE_NOAUTOCLOSE # Wait on the INSTFILES page so the user can take a look into the details of the installation steps -!define MUI_ABORTWARNING # This will warn the user if they exit from the installer. - -!insertmacro MUI_PAGE_WELCOME # Welcome to the installer page. -# !insertmacro MUI_PAGE_LICENSE "resources\eula.txt" # Adds a EULA page to the installer -!insertmacro MUI_PAGE_DIRECTORY # In which folder install page. -!insertmacro MUI_PAGE_INSTFILES # Installing page. -!insertmacro MUI_PAGE_FINISH # Finished installation page. - -!insertmacro MUI_UNPAGE_INSTFILES # Uninstalling page - -!insertmacro MUI_LANGUAGE "English" # Set the Language of the installer - -## The following two statements can be used to sign the installer and the uninstaller. The path to the binaries are provided in %1 -#!uninstfinalize 'signtool --file "%1"' -#!finalize 'signtool --file "%1"' - -Name "${INFO_PRODUCTNAME}" -OutFile "..\..\..\bin\${INFO_PROJECTNAME}-${ARCH}-installer.exe" # Name of the installer's file. -InstallDir "$PROGRAMFILES64\${INFO_COMPANYNAME}\${INFO_PRODUCTNAME}" # Default installing folder ($PROGRAMFILES is Program Files folder). -ShowInstDetails show # This will always show the installation details. - -Function .onInit - !insertmacro wails.checkArchitecture -FunctionEnd - -Section - !insertmacro wails.setShellContext - - !insertmacro wails.webview2runtime - - SetOutPath $INSTDIR - - !insertmacro wails.files - - CreateShortcut "$SMPROGRAMS\${INFO_PRODUCTNAME}.lnk" "$INSTDIR\${PRODUCT_EXECUTABLE}" - CreateShortCut "$DESKTOP\${INFO_PRODUCTNAME}.lnk" "$INSTDIR\${PRODUCT_EXECUTABLE}" - - !insertmacro wails.associateFiles - - !insertmacro wails.writeUninstaller -SectionEnd - -Section "uninstall" - !insertmacro wails.setShellContext - - RMDir /r "$AppData\${PRODUCT_EXECUTABLE}" # Remove the WebView2 DataPath - - RMDir /r $INSTDIR - - Delete "$SMPROGRAMS\${INFO_PRODUCTNAME}.lnk" - Delete "$DESKTOP\${INFO_PRODUCTNAME}.lnk" - - !insertmacro wails.unassociateFiles - - !insertmacro wails.deleteUninstaller -SectionEnd diff --git a/v3/examples/badge/build/windows/nsis/wails_tools.nsh b/v3/examples/badge/build/windows/nsis/wails_tools.nsh deleted file mode 100644 index 6fc10ab79..000000000 --- a/v3/examples/badge/build/windows/nsis/wails_tools.nsh +++ /dev/null @@ -1,212 +0,0 @@ -# DO NOT EDIT - Generated automatically by `wails build` - -!include "x64.nsh" -!include "WinVer.nsh" -!include "FileFunc.nsh" - -!ifndef INFO_PROJECTNAME - !define INFO_PROJECTNAME "badge" -!endif -!ifndef INFO_COMPANYNAME - !define INFO_COMPANYNAME "My Company" -!endif -!ifndef INFO_PRODUCTNAME - !define INFO_PRODUCTNAME "My Product" -!endif -!ifndef INFO_PRODUCTVERSION - !define INFO_PRODUCTVERSION "0.1.0" -!endif -!ifndef INFO_COPYRIGHT - !define INFO_COPYRIGHT "© now, My Company" -!endif -!ifndef PRODUCT_EXECUTABLE - !define PRODUCT_EXECUTABLE "${INFO_PROJECTNAME}.exe" -!endif -!ifndef UNINST_KEY_NAME - !define UNINST_KEY_NAME "${INFO_COMPANYNAME}${INFO_PRODUCTNAME}" -!endif -!define UNINST_KEY "Software\Microsoft\Windows\CurrentVersion\Uninstall\${UNINST_KEY_NAME}" - -!ifndef REQUEST_EXECUTION_LEVEL - !define REQUEST_EXECUTION_LEVEL "admin" -!endif - -RequestExecutionLevel "${REQUEST_EXECUTION_LEVEL}" - -!ifdef ARG_WAILS_AMD64_BINARY - !define SUPPORTS_AMD64 -!endif - -!ifdef ARG_WAILS_ARM64_BINARY - !define SUPPORTS_ARM64 -!endif - -!ifdef SUPPORTS_AMD64 - !ifdef SUPPORTS_ARM64 - !define ARCH "amd64_arm64" - !else - !define ARCH "amd64" - !endif -!else - !ifdef SUPPORTS_ARM64 - !define ARCH "arm64" - !else - !error "Wails: Undefined ARCH, please provide at least one of ARG_WAILS_AMD64_BINARY or ARG_WAILS_ARM64_BINARY" - !endif -!endif - -!macro wails.checkArchitecture - !ifndef WAILS_WIN10_REQUIRED - !define WAILS_WIN10_REQUIRED "This product is only supported on Windows 10 (Server 2016) and later." - !endif - - !ifndef WAILS_ARCHITECTURE_NOT_SUPPORTED - !define WAILS_ARCHITECTURE_NOT_SUPPORTED "This product can't be installed on the current Windows architecture. Supports: ${ARCH}" - !endif - - ${If} ${AtLeastWin10} - !ifdef SUPPORTS_AMD64 - ${if} ${IsNativeAMD64} - Goto ok - ${EndIf} - !endif - - !ifdef SUPPORTS_ARM64 - ${if} ${IsNativeARM64} - Goto ok - ${EndIf} - !endif - - IfSilent silentArch notSilentArch - silentArch: - SetErrorLevel 65 - Abort - notSilentArch: - MessageBox MB_OK "${WAILS_ARCHITECTURE_NOT_SUPPORTED}" - Quit - ${else} - IfSilent silentWin notSilentWin - silentWin: - SetErrorLevel 64 - Abort - notSilentWin: - MessageBox MB_OK "${WAILS_WIN10_REQUIRED}" - Quit - ${EndIf} - - ok: -!macroend - -!macro wails.files - !ifdef SUPPORTS_AMD64 - ${if} ${IsNativeAMD64} - File "/oname=${PRODUCT_EXECUTABLE}" "${ARG_WAILS_AMD64_BINARY}" - ${EndIf} - !endif - - !ifdef SUPPORTS_ARM64 - ${if} ${IsNativeARM64} - File "/oname=${PRODUCT_EXECUTABLE}" "${ARG_WAILS_ARM64_BINARY}" - ${EndIf} - !endif -!macroend - -!macro wails.writeUninstaller - WriteUninstaller "$INSTDIR\uninstall.exe" - - SetRegView 64 - WriteRegStr HKLM "${UNINST_KEY}" "Publisher" "${INFO_COMPANYNAME}" - WriteRegStr HKLM "${UNINST_KEY}" "DisplayName" "${INFO_PRODUCTNAME}" - WriteRegStr HKLM "${UNINST_KEY}" "DisplayVersion" "${INFO_PRODUCTVERSION}" - WriteRegStr HKLM "${UNINST_KEY}" "DisplayIcon" "$INSTDIR\${PRODUCT_EXECUTABLE}" - WriteRegStr HKLM "${UNINST_KEY}" "UninstallString" "$\"$INSTDIR\uninstall.exe$\"" - WriteRegStr HKLM "${UNINST_KEY}" "QuietUninstallString" "$\"$INSTDIR\uninstall.exe$\" /S" - - ${GetSize} "$INSTDIR" "/S=0K" $0 $1 $2 - IntFmt $0 "0x%08X" $0 - WriteRegDWORD HKLM "${UNINST_KEY}" "EstimatedSize" "$0" -!macroend - -!macro wails.deleteUninstaller - Delete "$INSTDIR\uninstall.exe" - - SetRegView 64 - DeleteRegKey HKLM "${UNINST_KEY}" -!macroend - -!macro wails.setShellContext - ${If} ${REQUEST_EXECUTION_LEVEL} == "admin" - SetShellVarContext all - ${else} - SetShellVarContext current - ${EndIf} -!macroend - -# Install webview2 by launching the bootstrapper -# See https://docs.microsoft.com/en-us/microsoft-edge/webview2/concepts/distribution#online-only-deployment -!macro wails.webview2runtime - !ifndef WAILS_INSTALL_WEBVIEW_DETAILPRINT - !define WAILS_INSTALL_WEBVIEW_DETAILPRINT "Installing: WebView2 Runtime" - !endif - - SetRegView 64 - # If the admin key exists and is not empty then webview2 is already installed - ReadRegStr $0 HKLM "SOFTWARE\WOW6432Node\Microsoft\EdgeUpdate\Clients\{F3017226-FE2A-4295-8BDF-00C3A9A7E4C5}" "pv" - ${If} $0 != "" - Goto ok - ${EndIf} - - ${If} ${REQUEST_EXECUTION_LEVEL} == "user" - # If the installer is run in user level, check the user specific key exists and is not empty then webview2 is already installed - ReadRegStr $0 HKCU "Software\Microsoft\EdgeUpdate\Clients\{F3017226-FE2A-4295-8BDF-00C3A9A7E4C5}" "pv" - ${If} $0 != "" - Goto ok - ${EndIf} - ${EndIf} - - SetDetailsPrint both - DetailPrint "${WAILS_INSTALL_WEBVIEW_DETAILPRINT}" - SetDetailsPrint listonly - - InitPluginsDir - CreateDirectory "$pluginsdir\webview2bootstrapper" - SetOutPath "$pluginsdir\webview2bootstrapper" - File "MicrosoftEdgeWebview2Setup.exe" - ExecWait '"$pluginsdir\webview2bootstrapper\MicrosoftEdgeWebview2Setup.exe" /silent /install' - - SetDetailsPrint both - ok: -!macroend - -# Copy of APP_ASSOCIATE and APP_UNASSOCIATE macros from here https://gist.github.com/nikku/281d0ef126dbc215dd58bfd5b3a5cd5b -!macro APP_ASSOCIATE EXT FILECLASS DESCRIPTION ICON COMMANDTEXT COMMAND - ; Backup the previously associated file class - ReadRegStr $R0 SHELL_CONTEXT "Software\Classes\.${EXT}" "" - WriteRegStr SHELL_CONTEXT "Software\Classes\.${EXT}" "${FILECLASS}_backup" "$R0" - - WriteRegStr SHELL_CONTEXT "Software\Classes\.${EXT}" "" "${FILECLASS}" - - WriteRegStr SHELL_CONTEXT "Software\Classes\${FILECLASS}" "" `${DESCRIPTION}` - WriteRegStr SHELL_CONTEXT "Software\Classes\${FILECLASS}\DefaultIcon" "" `${ICON}` - WriteRegStr SHELL_CONTEXT "Software\Classes\${FILECLASS}\shell" "" "open" - WriteRegStr SHELL_CONTEXT "Software\Classes\${FILECLASS}\shell\open" "" `${COMMANDTEXT}` - WriteRegStr SHELL_CONTEXT "Software\Classes\${FILECLASS}\shell\open\command" "" `${COMMAND}` -!macroend - -!macro APP_UNASSOCIATE EXT FILECLASS - ; Backup the previously associated file class - ReadRegStr $R0 SHELL_CONTEXT "Software\Classes\.${EXT}" `${FILECLASS}_backup` - WriteRegStr SHELL_CONTEXT "Software\Classes\.${EXT}" "" "$R0" - - DeleteRegKey SHELL_CONTEXT `Software\Classes\${FILECLASS}` -!macroend - -!macro wails.associateFiles - ; Create file associations - -!macroend - -!macro wails.unassociateFiles - ; Delete app associations - -!macroend \ No newline at end of file diff --git a/v3/examples/badge/build/windows/wails.exe.manifest b/v3/examples/badge/build/windows/wails.exe.manifest deleted file mode 100644 index fcfd2fc46..000000000 --- a/v3/examples/badge/build/windows/wails.exe.manifest +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - - - - - true/pm - permonitorv2,permonitor - - - - - - - - - - \ No newline at end of file diff --git a/v3/examples/badge/frontend/Inter Font License.txt b/v3/examples/badge/frontend/Inter Font License.txt deleted file mode 100644 index b525cbf3a..000000000 --- a/v3/examples/badge/frontend/Inter Font License.txt +++ /dev/null @@ -1,93 +0,0 @@ -Copyright 2020 The Inter Project Authors (https://github.com/rsms/inter) - -This Font Software is licensed under the SIL Open Font License, Version 1.1. -This license is copied below, and is also available with a FAQ at: -http://scripts.sil.org/OFL - - ------------------------------------------------------------ -SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 ------------------------------------------------------------ - -PREAMBLE -The goals of the Open Font License (OFL) are to stimulate worldwide -development of collaborative font projects, to support the font creation -efforts of academic and linguistic communities, and to provide a free and -open framework in which fonts may be shared and improved in partnership -with others. - -The OFL allows the licensed fonts to be used, studied, modified and -redistributed freely as long as they are not sold by themselves. The -fonts, including any derivative works, can be bundled, embedded, -redistributed and/or sold with any software provided that any reserved -names are not used by derivative works. The fonts and derivatives, -however, cannot be released under any other type of license. The -requirement for fonts to remain under this license does not apply -to any document created using the fonts or their derivatives. - -DEFINITIONS -"Font Software" refers to the set of files released by the Copyright -Holder(s) under this license and clearly marked as such. This may -include source files, build scripts and documentation. - -"Reserved Font Name" refers to any names specified as such after the -copyright statement(s). - -"Original Version" refers to the collection of Font Software components as -distributed by the Copyright Holder(s). - -"Modified Version" refers to any derivative made by adding to, deleting, -or substituting -- in part or in whole -- any of the components of the -Original Version, by changing formats or by porting the Font Software to a -new environment. - -"Author" refers to any designer, engineer, programmer, technical -writer or other person who contributed to the Font Software. - -PERMISSION & CONDITIONS -Permission is hereby granted, free of charge, to any person obtaining -a copy of the Font Software, to use, study, copy, merge, embed, modify, -redistribute, and sell modified and unmodified copies of the Font -Software, subject to the following conditions: - -1) Neither the Font Software nor any of its individual components, -in Original or Modified Versions, may be sold by itself. - -2) Original or Modified Versions of the Font Software may be bundled, -redistributed and/or sold with any software, provided that each copy -contains the above copyright notice and this license. These can be -included either as stand-alone text files, human-readable headers or -in the appropriate machine-readable metadata fields within text or -binary files as long as those fields can be easily viewed by the user. - -3) No Modified Version of the Font Software may use the Reserved Font -Name(s) unless explicit written permission is granted by the corresponding -Copyright Holder. This restriction only applies to the primary font name as -presented to the users. - -4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font -Software shall not be used to promote, endorse or advertise any -Modified Version, except to acknowledge the contribution(s) of the -Copyright Holder(s) and the Author(s) or with their explicit written -permission. - -5) The Font Software, modified or unmodified, in part or in whole, -must be distributed entirely under this license, and must not be -distributed under any other license. The requirement for fonts to -remain under this license does not apply to any document created -using the Font Software. - -TERMINATION -This license becomes null and void if any of the above conditions are -not met. - -DISCLAIMER -THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT -OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE -COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL -DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM -OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/v3/examples/badge/frontend/bindings/github.com/wailsapp/wails/v3/pkg/services/dock/dockservice.ts b/v3/examples/badge/frontend/bindings/github.com/wailsapp/wails/v3/pkg/services/dock/dockservice.ts deleted file mode 100644 index abf1f22e4..000000000 --- a/v3/examples/badge/frontend/bindings/github.com/wailsapp/wails/v3/pkg/services/dock/dockservice.ts +++ /dev/null @@ -1,53 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * Service represents the dock service - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "@wailsio/runtime"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * HideAppIcon hides the app icon in the dock/taskbar. - */ -export function HideAppIcon(): $CancellablePromise { - return $Call.ByID(3413658144); -} - -/** - * RemoveBadge removes the badge label from the application icon. - * This method ensures the badge call is made on the main thread to avoid crashes. - */ -export function RemoveBadge(): $CancellablePromise { - return $Call.ByID(2752757297); -} - -/** - * SetBadge sets the badge label on the application icon. - * This method ensures the badge call is made on the main thread to avoid crashes. - */ -export function SetBadge(label: string): $CancellablePromise { - return $Call.ByID(1717705661, label); -} - -/** - * SetCustomBadge sets the badge label on the application icon with custom options. - * This method ensures the badge call is made on the main thread to avoid crashes. - */ -export function SetCustomBadge(label: string, options: $models.BadgeOptions): $CancellablePromise { - return $Call.ByID(2730169760, label, options); -} - -/** - * ShowAppIcon shows the app icon in the dock/taskbar. - */ -export function ShowAppIcon(): $CancellablePromise { - return $Call.ByID(3409697379); -} diff --git a/v3/examples/badge/frontend/bindings/github.com/wailsapp/wails/v3/pkg/services/dock/index.ts b/v3/examples/badge/frontend/bindings/github.com/wailsapp/wails/v3/pkg/services/dock/index.ts deleted file mode 100644 index fbdaf19f3..000000000 --- a/v3/examples/badge/frontend/bindings/github.com/wailsapp/wails/v3/pkg/services/dock/index.ts +++ /dev/null @@ -1,11 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as DockService from "./dockservice.js"; -export { - DockService -}; - -export { - BadgeOptions -} from "./models.js"; diff --git a/v3/examples/badge/frontend/bindings/github.com/wailsapp/wails/v3/pkg/services/dock/models.ts b/v3/examples/badge/frontend/bindings/github.com/wailsapp/wails/v3/pkg/services/dock/models.ts deleted file mode 100644 index f97c8a4c6..000000000 --- a/v3/examples/badge/frontend/bindings/github.com/wailsapp/wails/v3/pkg/services/dock/models.ts +++ /dev/null @@ -1,61 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Create as $Create } from "@wailsio/runtime"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as color$0 from "../../../../../../../image/color/models.js"; - -/** - * BadgeOptions represents options for customizing badge appearance - */ -export class BadgeOptions { - "TextColour": color$0.RGBA; - "BackgroundColour": color$0.RGBA; - "FontName": string; - "FontSize": number; - "SmallFontSize": number; - - /** Creates a new BadgeOptions instance. */ - constructor($$source: Partial = {}) { - if (!("TextColour" in $$source)) { - this["TextColour"] = (new color$0.RGBA()); - } - if (!("BackgroundColour" in $$source)) { - this["BackgroundColour"] = (new color$0.RGBA()); - } - if (!("FontName" in $$source)) { - this["FontName"] = ""; - } - if (!("FontSize" in $$source)) { - this["FontSize"] = 0; - } - if (!("SmallFontSize" in $$source)) { - this["SmallFontSize"] = 0; - } - - Object.assign(this, $$source); - } - - /** - * Creates a new BadgeOptions instance from a string or object. - */ - static createFrom($$source: any = {}): BadgeOptions { - const $$createField0_0 = $$createType0; - const $$createField1_0 = $$createType0; - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - if ("TextColour" in $$parsedSource) { - $$parsedSource["TextColour"] = $$createField0_0($$parsedSource["TextColour"]); - } - if ("BackgroundColour" in $$parsedSource) { - $$parsedSource["BackgroundColour"] = $$createField1_0($$parsedSource["BackgroundColour"]); - } - return new BadgeOptions($$parsedSource as Partial); - } -} - -// Private type creation functions -const $$createType0 = color$0.RGBA.createFrom; diff --git a/v3/examples/badge/frontend/bindings/image/color/index.ts b/v3/examples/badge/frontend/bindings/image/color/index.ts deleted file mode 100644 index 97b507b08..000000000 --- a/v3/examples/badge/frontend/bindings/image/color/index.ts +++ /dev/null @@ -1,6 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -export { - RGBA -} from "./models.js"; diff --git a/v3/examples/badge/frontend/bindings/image/color/models.ts b/v3/examples/badge/frontend/bindings/image/color/models.ts deleted file mode 100644 index 0d4eab56d..000000000 --- a/v3/examples/badge/frontend/bindings/image/color/models.ts +++ /dev/null @@ -1,46 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Create as $Create } from "@wailsio/runtime"; - -/** - * RGBA represents a traditional 32-bit alpha-premultiplied color, having 8 - * bits for each of red, green, blue and alpha. - * - * An alpha-premultiplied color component C has been scaled by alpha (A), so - * has valid values 0 <= C <= A. - */ -export class RGBA { - "R": number; - "G": number; - "B": number; - "A": number; - - /** Creates a new RGBA instance. */ - constructor($$source: Partial = {}) { - if (!("R" in $$source)) { - this["R"] = 0; - } - if (!("G" in $$source)) { - this["G"] = 0; - } - if (!("B" in $$source)) { - this["B"] = 0; - } - if (!("A" in $$source)) { - this["A"] = 0; - } - - Object.assign(this, $$source); - } - - /** - * Creates a new RGBA instance from a string or object. - */ - static createFrom($$source: any = {}): RGBA { - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - return new RGBA($$parsedSource as Partial); - } -} diff --git a/v3/examples/badge/frontend/dist/Inter-Medium.ttf b/v3/examples/badge/frontend/dist/Inter-Medium.ttf deleted file mode 100644 index a01f3777a..000000000 Binary files a/v3/examples/badge/frontend/dist/Inter-Medium.ttf and /dev/null differ diff --git a/v3/examples/badge/frontend/dist/assets/index-CtfGGYXM.js b/v3/examples/badge/frontend/dist/assets/index-CtfGGYXM.js deleted file mode 100644 index 6149df5db..000000000 --- a/v3/examples/badge/frontend/dist/assets/index-CtfGGYXM.js +++ /dev/null @@ -1,1357 +0,0 @@ -(function polyfill() { - const relList = document.createElement("link").relList; - if (relList && relList.supports && relList.supports("modulepreload")) { - return; - } - for (const link of document.querySelectorAll('link[rel="modulepreload"]')) { - processPreload(link); - } - new MutationObserver((mutations) => { - for (const mutation of mutations) { - if (mutation.type !== "childList") { - continue; - } - for (const node of mutation.addedNodes) { - if (node.tagName === "LINK" && node.rel === "modulepreload") - processPreload(node); - } - } - }).observe(document, { childList: true, subtree: true }); - function getFetchOpts(link) { - const fetchOpts = {}; - if (link.integrity) fetchOpts.integrity = link.integrity; - if (link.referrerPolicy) fetchOpts.referrerPolicy = link.referrerPolicy; - if (link.crossOrigin === "use-credentials") - fetchOpts.credentials = "include"; - else if (link.crossOrigin === "anonymous") fetchOpts.credentials = "omit"; - else fetchOpts.credentials = "same-origin"; - return fetchOpts; - } - function processPreload(link) { - if (link.ep) - return; - link.ep = true; - const fetchOpts = getFetchOpts(link); - fetch(link.href, fetchOpts); - } -})(); -const urlAlphabet = "useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict"; -function nanoid(size = 21) { - let id = ""; - let i = size | 0; - while (i--) { - id += urlAlphabet[Math.random() * 64 | 0]; - } - return id; -} -const runtimeURL = window.location.origin + "/wails/runtime"; -const objectNames = Object.freeze({ - Call: 0, - Clipboard: 1, - Application: 2, - Events: 3, - ContextMenu: 4, - Dialog: 5, - Window: 6, - Screens: 7, - System: 8, - Browser: 9, - CancelCall: 10 -}); -let clientId = nanoid(); -function newRuntimeCaller(object, windowName = "") { - return function(method, args = null) { - return runtimeCallWithID(object, method, windowName, args); - }; -} -async function runtimeCallWithID(objectID, method, windowName, args) { - var _a2, _b; - let url = new URL(runtimeURL); - url.searchParams.append("object", objectID.toString()); - url.searchParams.append("method", method.toString()); - if (args) { - url.searchParams.append("args", JSON.stringify(args)); - } - let headers = { - ["x-wails-client-id"]: clientId - }; - if (windowName) { - headers["x-wails-window-name"] = windowName; - } - let response = await fetch(url, { headers }); - if (!response.ok) { - throw new Error(await response.text()); - } - if (((_b = (_a2 = response.headers.get("Content-Type")) === null || _a2 === void 0 ? void 0 : _a2.indexOf("application/json")) !== null && _b !== void 0 ? _b : -1) !== -1) { - return response.json(); - } else { - return response.text(); - } -} -newRuntimeCaller(objectNames.System); -const _invoke = function() { - var _a2, _b, _c, _d, _e; - try { - if ((_b = (_a2 = window.chrome) === null || _a2 === void 0 ? void 0 : _a2.webview) === null || _b === void 0 ? void 0 : _b.postMessage) { - return window.chrome.webview.postMessage.bind(window.chrome.webview); - } else if ((_e = (_d = (_c = window.webkit) === null || _c === void 0 ? void 0 : _c.messageHandlers) === null || _d === void 0 ? void 0 : _d["external"]) === null || _e === void 0 ? void 0 : _e.postMessage) { - return window.webkit.messageHandlers["external"].postMessage.bind(window.webkit.messageHandlers["external"]); - } - } catch (e) { - } - console.warn("\n%c⚠️ Browser Environment Detected %c\n\n%cOnly UI previews are available in the browser. For full functionality, please run the application in desktop mode.\nMore information at: https://v3.wails.io/learn/build/#using-a-browser-for-development\n", "background: #ffffff; color: #000000; font-weight: bold; padding: 4px 8px; border-radius: 4px; border: 2px solid #000000;", "background: transparent;", "color: #ffffff; font-style: italic; font-weight: bold;"); - return null; -}(); -function invoke(msg) { - _invoke === null || _invoke === void 0 ? void 0 : _invoke(msg); -} -function IsWindows() { - return window._wails.environment.OS === "windows"; -} -function IsDebug() { - return Boolean(window._wails.environment.Debug); -} -function canTrackButtons() { - return new MouseEvent("mousedown").buttons === 0; -} -function eventTarget(event) { - var _a2; - if (event.target instanceof HTMLElement) { - return event.target; - } else if (!(event.target instanceof HTMLElement) && event.target instanceof Node) { - return (_a2 = event.target.parentElement) !== null && _a2 !== void 0 ? _a2 : document.body; - } else { - return document.body; - } -} -document.addEventListener("DOMContentLoaded", () => { -}); -window.addEventListener("contextmenu", contextMenuHandler); -const call$2 = newRuntimeCaller(objectNames.ContextMenu); -const ContextMenuOpen = 0; -function openContextMenu(id, x, y, data) { - void call$2(ContextMenuOpen, { id, x, y, data }); -} -function contextMenuHandler(event) { - const target = eventTarget(event); - const customContextMenu = window.getComputedStyle(target).getPropertyValue("--custom-contextmenu").trim(); - if (customContextMenu) { - event.preventDefault(); - const data = window.getComputedStyle(target).getPropertyValue("--custom-contextmenu-data"); - openContextMenu(customContextMenu, event.clientX, event.clientY, data); - } else { - processDefaultContextMenu(event, target); - } -} -function processDefaultContextMenu(event, target) { - if (IsDebug()) { - return; - } - switch (window.getComputedStyle(target).getPropertyValue("--default-contextmenu").trim()) { - case "show": - return; - case "hide": - event.preventDefault(); - return; - } - if (target.isContentEditable) { - return; - } - const selection = window.getSelection(); - const hasSelection = selection && selection.toString().length > 0; - if (hasSelection) { - for (let i = 0; i < selection.rangeCount; i++) { - const range = selection.getRangeAt(i); - const rects = range.getClientRects(); - for (let j = 0; j < rects.length; j++) { - const rect = rects[j]; - if (document.elementFromPoint(rect.left, rect.top) === target) { - return; - } - } - } - } - if (target instanceof HTMLInputElement || target instanceof HTMLTextAreaElement) { - if (hasSelection || !target.readOnly && !target.disabled) { - return; - } - } - event.preventDefault(); -} -function GetFlag(key) { - try { - return window._wails.flags[key]; - } catch (e) { - throw new Error("Unable to retrieve flag '" + key + "': " + e, { cause: e }); - } -} -let canDrag = false; -let dragging = false; -let resizable = false; -let canResize = false; -let resizing = false; -let resizeEdge = ""; -let defaultCursor = "auto"; -let buttons = 0; -const buttonsTracked = canTrackButtons(); -window._wails = window._wails || {}; -window._wails.setResizable = (value) => { - resizable = value; - if (!resizable) { - canResize = resizing = false; - setResize(); - } -}; -window.addEventListener("mousedown", update, { capture: true }); -window.addEventListener("mousemove", update, { capture: true }); -window.addEventListener("mouseup", update, { capture: true }); -for (const ev of ["click", "contextmenu", "dblclick"]) { - window.addEventListener(ev, suppressEvent, { capture: true }); -} -function suppressEvent(event) { - if (dragging || resizing) { - event.stopImmediatePropagation(); - event.stopPropagation(); - event.preventDefault(); - } -} -const MouseDown = 0; -const MouseUp = 1; -const MouseMove = 2; -function update(event) { - let eventType, eventButtons = event.buttons; - switch (event.type) { - case "mousedown": - eventType = MouseDown; - if (!buttonsTracked) { - eventButtons = buttons | 1 << event.button; - } - break; - case "mouseup": - eventType = MouseUp; - if (!buttonsTracked) { - eventButtons = buttons & ~(1 << event.button); - } - break; - default: - eventType = MouseMove; - if (!buttonsTracked) { - eventButtons = buttons; - } - break; - } - let released = buttons & ~eventButtons; - let pressed = eventButtons & ~buttons; - buttons = eventButtons; - if (eventType === MouseDown && !(pressed & event.button)) { - released |= 1 << event.button; - pressed |= 1 << event.button; - } - if (eventType !== MouseMove && resizing || dragging && (eventType === MouseDown || event.button !== 0)) { - event.stopImmediatePropagation(); - event.stopPropagation(); - event.preventDefault(); - } - if (released & 1) { - primaryUp(); - } - if (pressed & 1) { - primaryDown(event); - } - if (eventType === MouseMove) { - onMouseMove(event); - } -} -function primaryDown(event) { - canDrag = false; - canResize = false; - if (!IsWindows()) { - if (event.type === "mousedown" && event.button === 0 && event.detail !== 1) { - return; - } - } - if (resizeEdge) { - canResize = true; - return; - } - const target = eventTarget(event); - const style = window.getComputedStyle(target); - canDrag = style.getPropertyValue("--wails-draggable").trim() === "drag" && (event.offsetX - parseFloat(style.paddingLeft) < target.clientWidth && event.offsetY - parseFloat(style.paddingTop) < target.clientHeight); -} -function primaryUp(event) { - canDrag = false; - dragging = false; - canResize = false; - resizing = false; -} -const cursorForEdge = Object.freeze({ - "se-resize": "nwse-resize", - "sw-resize": "nesw-resize", - "nw-resize": "nwse-resize", - "ne-resize": "nesw-resize", - "w-resize": "ew-resize", - "n-resize": "ns-resize", - "s-resize": "ns-resize", - "e-resize": "ew-resize" -}); -function setResize(edge) { - if (edge) { - if (!resizeEdge) { - defaultCursor = document.body.style.cursor; - } - document.body.style.cursor = cursorForEdge[edge]; - } else if (!edge && resizeEdge) { - document.body.style.cursor = defaultCursor; - } - resizeEdge = edge || ""; -} -function onMouseMove(event) { - if (canResize && resizeEdge) { - resizing = true; - invoke("wails:resize:" + resizeEdge); - } else if (canDrag) { - dragging = true; - invoke("wails:drag"); - } - if (dragging || resizing) { - canDrag = canResize = false; - return; - } - if (!resizable || !IsWindows()) { - if (resizeEdge) { - setResize(); - } - return; - } - const resizeHandleHeight = GetFlag("system.resizeHandleHeight") || 5; - const resizeHandleWidth = GetFlag("system.resizeHandleWidth") || 5; - const cornerExtra = GetFlag("resizeCornerExtra") || 10; - const rightBorder = window.outerWidth - event.clientX < resizeHandleWidth; - const leftBorder = event.clientX < resizeHandleWidth; - const topBorder = event.clientY < resizeHandleHeight; - const bottomBorder = window.outerHeight - event.clientY < resizeHandleHeight; - const rightCorner = window.outerWidth - event.clientX < resizeHandleWidth + cornerExtra; - const leftCorner = event.clientX < resizeHandleWidth + cornerExtra; - const topCorner = event.clientY < resizeHandleHeight + cornerExtra; - const bottomCorner = window.outerHeight - event.clientY < resizeHandleHeight + cornerExtra; - if (!leftCorner && !topCorner && !bottomCorner && !rightCorner) { - setResize(); - } else if (rightCorner && bottomCorner) - setResize("se-resize"); - else if (leftCorner && bottomCorner) - setResize("sw-resize"); - else if (leftCorner && topCorner) - setResize("nw-resize"); - else if (topCorner && rightCorner) - setResize("ne-resize"); - else if (leftBorder) - setResize("w-resize"); - else if (topBorder) - setResize("n-resize"); - else if (bottomBorder) - setResize("s-resize"); - else if (rightBorder) - setResize("e-resize"); - else - setResize(); -} -var fnToStr = Function.prototype.toString; -var reflectApply = typeof Reflect === "object" && Reflect !== null && Reflect.apply; -var badArrayLike; -var isCallableMarker; -if (typeof reflectApply === "function" && typeof Object.defineProperty === "function") { - try { - badArrayLike = Object.defineProperty({}, "length", { - get: function() { - throw isCallableMarker; - } - }); - isCallableMarker = {}; - reflectApply(function() { - throw 42; - }, null, badArrayLike); - } catch (_) { - if (_ !== isCallableMarker) { - reflectApply = null; - } - } -} else { - reflectApply = null; -} -var constructorRegex = /^\s*class\b/; -var isES6ClassFn = function isES6ClassFunction(value) { - try { - var fnStr = fnToStr.call(value); - return constructorRegex.test(fnStr); - } catch (e) { - return false; - } -}; -var tryFunctionObject = function tryFunctionToStr(value) { - try { - if (isES6ClassFn(value)) { - return false; - } - fnToStr.call(value); - return true; - } catch (e) { - return false; - } -}; -var toStr = Object.prototype.toString; -var objectClass = "[object Object]"; -var fnClass = "[object Function]"; -var genClass = "[object GeneratorFunction]"; -var ddaClass = "[object HTMLAllCollection]"; -var ddaClass2 = "[object HTML document.all class]"; -var ddaClass3 = "[object HTMLCollection]"; -var hasToStringTag = typeof Symbol === "function" && !!Symbol.toStringTag; -var isIE68 = !(0 in [,]); -var isDDA = function isDocumentDotAll() { - return false; -}; -if (typeof document === "object") { - var all = document.all; - if (toStr.call(all) === toStr.call(document.all)) { - isDDA = function isDocumentDotAll2(value) { - if ((isIE68 || !value) && (typeof value === "undefined" || typeof value === "object")) { - try { - var str = toStr.call(value); - return (str === ddaClass || str === ddaClass2 || str === ddaClass3 || str === objectClass) && value("") == null; - } catch (e) { - } - } - return false; - }; - } -} -function isCallableRefApply(value) { - if (isDDA(value)) { - return true; - } - if (!value) { - return false; - } - if (typeof value !== "function" && typeof value !== "object") { - return false; - } - try { - reflectApply(value, null, badArrayLike); - } catch (e) { - if (e !== isCallableMarker) { - return false; - } - } - return !isES6ClassFn(value) && tryFunctionObject(value); -} -function isCallableNoRefApply(value) { - if (isDDA(value)) { - return true; - } - if (!value) { - return false; - } - if (typeof value !== "function" && typeof value !== "object") { - return false; - } - if (hasToStringTag) { - return tryFunctionObject(value); - } - if (isES6ClassFn(value)) { - return false; - } - var strClass = toStr.call(value); - if (strClass !== fnClass && strClass !== genClass && !/^\[object HTML/.test(strClass)) { - return false; - } - return tryFunctionObject(value); -} -const isCallable = reflectApply ? isCallableRefApply : isCallableNoRefApply; -var _a; -class CancelError extends Error { - /** - * Constructs a new `CancelError` instance. - * @param message - The error message. - * @param options - Options to be forwarded to the Error constructor. - */ - constructor(message, options) { - super(message, options); - this.name = "CancelError"; - } -} -class CancelledRejectionError extends Error { - /** - * Constructs a new `CancelledRejectionError` instance. - * @param promise - The promise that caused the error originally. - * @param reason - The rejection reason. - * @param info - An optional informative message specifying the circumstances in which the error was thrown. - * Defaults to the string `"Unhandled rejection in cancelled promise."`. - */ - constructor(promise, reason, info) { - super((info !== null && info !== void 0 ? info : "Unhandled rejection in cancelled promise.") + " Reason: " + errorMessage(reason), { cause: reason }); - this.promise = promise; - this.name = "CancelledRejectionError"; - } -} -const barrierSym = Symbol("barrier"); -const cancelImplSym = Symbol("cancelImpl"); -const species = (_a = Symbol.species) !== null && _a !== void 0 ? _a : Symbol("speciesPolyfill"); -class CancellablePromise extends Promise { - /** - * Creates a new `CancellablePromise`. - * - * @param executor - A callback used to initialize the promise. This callback is passed two arguments: - * a `resolve` callback used to resolve the promise with a value - * or the result of another promise (possibly cancellable), - * and a `reject` callback used to reject the promise with a provided reason or error. - * If the value provided to the `resolve` callback is a thenable _and_ cancellable object - * (it has a `then` _and_ a `cancel` method), - * cancellation requests will be forwarded to that object and the oncancelled will not be invoked anymore. - * If any one of the two callbacks is called _after_ the promise has been cancelled, - * the provided values will be cancelled and resolved as usual, - * but their results will be discarded. - * However, if the resolution process ultimately ends up in a rejection - * that is not due to cancellation, the rejection reason - * will be wrapped in a {@link CancelledRejectionError} - * and bubbled up as an unhandled rejection. - * @param oncancelled - It is the caller's responsibility to ensure that any operation - * started by the executor is properly halted upon cancellation. - * This optional callback can be used to that purpose. - * It will be called _synchronously_ with a cancellation cause - * when cancellation is requested, _after_ the promise has already rejected - * with a {@link CancelError}, but _before_ - * any {@link then}/{@link catch}/{@link finally} callback runs. - * If the callback returns a thenable, the promise returned from {@link cancel} - * will only fulfill after the former has settled. - * Unhandled exceptions or rejections from the callback will be wrapped - * in a {@link CancelledRejectionError} and bubbled up as unhandled rejections. - * If the `resolve` callback is called before cancellation with a cancellable promise, - * cancellation requests on this promise will be diverted to that promise, - * and the original `oncancelled` callback will be discarded. - */ - constructor(executor, oncancelled) { - let resolve; - let reject; - super((res, rej) => { - resolve = res; - reject = rej; - }); - if (this.constructor[species] !== Promise) { - throw new TypeError("CancellablePromise does not support transparent subclassing. Please refrain from overriding the [Symbol.species] static property."); - } - let promise = { - promise: this, - resolve, - reject, - get oncancelled() { - return oncancelled !== null && oncancelled !== void 0 ? oncancelled : null; - }, - set oncancelled(cb) { - oncancelled = cb !== null && cb !== void 0 ? cb : void 0; - } - }; - const state = { - get root() { - return state; - }, - resolving: false, - settled: false - }; - void Object.defineProperties(this, { - [barrierSym]: { - configurable: false, - enumerable: false, - writable: true, - value: null - }, - [cancelImplSym]: { - configurable: false, - enumerable: false, - writable: false, - value: cancellerFor(promise, state) - } - }); - const rejector = rejectorFor(promise, state); - try { - executor(resolverFor(promise, state), rejector); - } catch (err) { - if (state.resolving) { - console.log("Unhandled exception in CancellablePromise executor.", err); - } else { - rejector(err); - } - } - } - /** - * Cancels immediately the execution of the operation associated with this promise. - * The promise rejects with a {@link CancelError} instance as reason, - * with the {@link CancelError#cause} property set to the given argument, if any. - * - * Has no effect if called after the promise has already settled; - * repeated calls in particular are safe, but only the first one - * will set the cancellation cause. - * - * The `CancelError` exception _need not_ be handled explicitly _on the promises that are being cancelled:_ - * cancelling a promise with no attached rejection handler does not trigger an unhandled rejection event. - * Therefore, the following idioms are all equally correct: - * ```ts - * new CancellablePromise((resolve, reject) => { ... }).cancel(); - * new CancellablePromise((resolve, reject) => { ... }).then(...).cancel(); - * new CancellablePromise((resolve, reject) => { ... }).then(...).catch(...).cancel(); - * ``` - * Whenever some cancelled promise in a chain rejects with a `CancelError` - * with the same cancellation cause as itself, the error will be discarded silently. - * However, the `CancelError` _will still be delivered_ to all attached rejection handlers - * added by {@link then} and related methods: - * ```ts - * let cancellable = new CancellablePromise((resolve, reject) => { ... }); - * cancellable.then(() => { ... }).catch(console.log); - * cancellable.cancel(); // A CancelError is printed to the console. - * ``` - * If the `CancelError` is not handled downstream by the time it reaches - * a _non-cancelled_ promise, it _will_ trigger an unhandled rejection event, - * just like normal rejections would: - * ```ts - * let cancellable = new CancellablePromise((resolve, reject) => { ... }); - * let chained = cancellable.then(() => { ... }).then(() => { ... }); // No catch... - * cancellable.cancel(); // Unhandled rejection event on chained! - * ``` - * Therefore, it is important to either cancel whole promise chains from their tail, - * as shown in the correct idioms above, or take care of handling errors everywhere. - * - * @returns A cancellable promise that _fulfills_ after the cancel callback (if any) - * and all handlers attached up to the call to cancel have run. - * If the cancel callback returns a thenable, the promise returned by `cancel` - * will also wait for that thenable to settle. - * This enables callers to wait for the cancelled operation to terminate - * without being forced to handle potential errors at the call site. - * ```ts - * cancellable.cancel().then(() => { - * // Cleanup finished, it's safe to do something else. - * }, (err) => { - * // Unreachable: the promise returned from cancel will never reject. - * }); - * ``` - * Note that the returned promise will _not_ handle implicitly any rejection - * that might have occurred already in the cancelled chain. - * It will just track whether registered handlers have been executed or not. - * Therefore, unhandled rejections will never be silently handled by calling cancel. - */ - cancel(cause) { - return new CancellablePromise((resolve) => { - Promise.all([ - this[cancelImplSym](new CancelError("Promise cancelled.", { cause })), - currentBarrier(this) - ]).then(() => resolve(), () => resolve()); - }); - } - /** - * Binds promise cancellation to the abort event of the given {@link AbortSignal}. - * If the signal has already aborted, the promise will be cancelled immediately. - * When either condition is verified, the cancellation cause will be set - * to the signal's abort reason (see {@link AbortSignal#reason}). - * - * Has no effect if called (or if the signal aborts) _after_ the promise has already settled. - * Only the first signal to abort will set the cancellation cause. - * - * For more details about the cancellation process, - * see {@link cancel} and the `CancellablePromise` constructor. - * - * This method enables `await`ing cancellable promises without having - * to store them for future cancellation, e.g.: - * ```ts - * await longRunningOperation().cancelOn(signal); - * ``` - * instead of: - * ```ts - * let promiseToBeCancelled = longRunningOperation(); - * await promiseToBeCancelled; - * ``` - * - * @returns This promise, for method chaining. - */ - cancelOn(signal) { - if (signal.aborted) { - void this.cancel(signal.reason); - } else { - signal.addEventListener("abort", () => void this.cancel(signal.reason), { capture: true }); - } - return this; - } - /** - * Attaches callbacks for the resolution and/or rejection of the `CancellablePromise`. - * - * The optional `oncancelled` argument will be invoked when the returned promise is cancelled, - * with the same semantics as the `oncancelled` argument of the constructor. - * When the parent promise rejects or is cancelled, the `onrejected` callback will run, - * _even after the returned promise has been cancelled:_ - * in that case, should it reject or throw, the reason will be wrapped - * in a {@link CancelledRejectionError} and bubbled up as an unhandled rejection. - * - * @param onfulfilled The callback to execute when the Promise is resolved. - * @param onrejected The callback to execute when the Promise is rejected. - * @returns A `CancellablePromise` for the completion of whichever callback is executed. - * The returned promise is hooked up to propagate cancellation requests up the chain, but not down: - * - * - if the parent promise is cancelled, the `onrejected` handler will be invoked with a `CancelError` - * and the returned promise _will resolve regularly_ with its result; - * - conversely, if the returned promise is cancelled, _the parent promise is cancelled too;_ - * the `onrejected` handler will still be invoked with the parent's `CancelError`, - * but its result will be discarded - * and the returned promise will reject with a `CancelError` as well. - * - * The promise returned from {@link cancel} will fulfill only after all attached handlers - * up the entire promise chain have been run. - * - * If either callback returns a cancellable promise, - * cancellation requests will be diverted to it, - * and the specified `oncancelled` callback will be discarded. - */ - then(onfulfilled, onrejected, oncancelled) { - if (!(this instanceof CancellablePromise)) { - throw new TypeError("CancellablePromise.prototype.then called on an invalid object."); - } - if (!isCallable(onfulfilled)) { - onfulfilled = identity; - } - if (!isCallable(onrejected)) { - onrejected = thrower; - } - if (onfulfilled === identity && onrejected == thrower) { - return new CancellablePromise((resolve) => resolve(this)); - } - const barrier = {}; - this[barrierSym] = barrier; - return new CancellablePromise((resolve, reject) => { - void super.then((value) => { - var _a2; - if (this[barrierSym] === barrier) { - this[barrierSym] = null; - } - (_a2 = barrier.resolve) === null || _a2 === void 0 ? void 0 : _a2.call(barrier); - try { - resolve(onfulfilled(value)); - } catch (err) { - reject(err); - } - }, (reason) => { - var _a2; - if (this[barrierSym] === barrier) { - this[barrierSym] = null; - } - (_a2 = barrier.resolve) === null || _a2 === void 0 ? void 0 : _a2.call(barrier); - try { - resolve(onrejected(reason)); - } catch (err) { - reject(err); - } - }); - }, async (cause) => { - try { - return oncancelled === null || oncancelled === void 0 ? void 0 : oncancelled(cause); - } finally { - await this.cancel(cause); - } - }); - } - /** - * Attaches a callback for only the rejection of the Promise. - * - * The optional `oncancelled` argument will be invoked when the returned promise is cancelled, - * with the same semantics as the `oncancelled` argument of the constructor. - * When the parent promise rejects or is cancelled, the `onrejected` callback will run, - * _even after the returned promise has been cancelled:_ - * in that case, should it reject or throw, the reason will be wrapped - * in a {@link CancelledRejectionError} and bubbled up as an unhandled rejection. - * - * It is equivalent to - * ```ts - * cancellablePromise.then(undefined, onrejected, oncancelled); - * ``` - * and the same caveats apply. - * - * @returns A Promise for the completion of the callback. - * Cancellation requests on the returned promise - * will propagate up the chain to the parent promise, - * but not in the other direction. - * - * The promise returned from {@link cancel} will fulfill only after all attached handlers - * up the entire promise chain have been run. - * - * If `onrejected` returns a cancellable promise, - * cancellation requests will be diverted to it, - * and the specified `oncancelled` callback will be discarded. - * See {@link then} for more details. - */ - catch(onrejected, oncancelled) { - return this.then(void 0, onrejected, oncancelled); - } - /** - * Attaches a callback that is invoked when the CancellablePromise is settled (fulfilled or rejected). The - * resolved value cannot be accessed or modified from the callback. - * The returned promise will settle in the same state as the original one - * after the provided callback has completed execution, - * unless the callback throws or returns a rejecting promise, - * in which case the returned promise will reject as well. - * - * The optional `oncancelled` argument will be invoked when the returned promise is cancelled, - * with the same semantics as the `oncancelled` argument of the constructor. - * Once the parent promise settles, the `onfinally` callback will run, - * _even after the returned promise has been cancelled:_ - * in that case, should it reject or throw, the reason will be wrapped - * in a {@link CancelledRejectionError} and bubbled up as an unhandled rejection. - * - * This method is implemented in terms of {@link then} and the same caveats apply. - * It is polyfilled, hence available in every OS/webview version. - * - * @returns A Promise for the completion of the callback. - * Cancellation requests on the returned promise - * will propagate up the chain to the parent promise, - * but not in the other direction. - * - * The promise returned from {@link cancel} will fulfill only after all attached handlers - * up the entire promise chain have been run. - * - * If `onfinally` returns a cancellable promise, - * cancellation requests will be diverted to it, - * and the specified `oncancelled` callback will be discarded. - * See {@link then} for more details. - */ - finally(onfinally, oncancelled) { - if (!(this instanceof CancellablePromise)) { - throw new TypeError("CancellablePromise.prototype.finally called on an invalid object."); - } - if (!isCallable(onfinally)) { - return this.then(onfinally, onfinally, oncancelled); - } - return this.then((value) => CancellablePromise.resolve(onfinally()).then(() => value), (reason) => CancellablePromise.resolve(onfinally()).then(() => { - throw reason; - }), oncancelled); - } - /** - * We use the `[Symbol.species]` static property, if available, - * to disable the built-in automatic subclassing features from {@link Promise}. - * It is critical for performance reasons that extenders do not override this. - * Once the proposal at https://github.com/tc39/proposal-rm-builtin-subclassing - * is either accepted or retired, this implementation will have to be revised accordingly. - * - * @ignore - * @internal - */ - static get [species]() { - return Promise; - } - static all(values) { - let collected = Array.from(values); - const promise = collected.length === 0 ? CancellablePromise.resolve(collected) : new CancellablePromise((resolve, reject) => { - void Promise.all(collected).then(resolve, reject); - }, (cause) => cancelAll(promise, collected, cause)); - return promise; - } - static allSettled(values) { - let collected = Array.from(values); - const promise = collected.length === 0 ? CancellablePromise.resolve(collected) : new CancellablePromise((resolve, reject) => { - void Promise.allSettled(collected).then(resolve, reject); - }, (cause) => cancelAll(promise, collected, cause)); - return promise; - } - static any(values) { - let collected = Array.from(values); - const promise = collected.length === 0 ? CancellablePromise.resolve(collected) : new CancellablePromise((resolve, reject) => { - void Promise.any(collected).then(resolve, reject); - }, (cause) => cancelAll(promise, collected, cause)); - return promise; - } - static race(values) { - let collected = Array.from(values); - const promise = new CancellablePromise((resolve, reject) => { - void Promise.race(collected).then(resolve, reject); - }, (cause) => cancelAll(promise, collected, cause)); - return promise; - } - /** - * Creates a new cancelled CancellablePromise for the provided cause. - * - * @group Static Methods - */ - static cancel(cause) { - const p = new CancellablePromise(() => { - }); - p.cancel(cause); - return p; - } - /** - * Creates a new CancellablePromise that cancels - * after the specified timeout, with the provided cause. - * - * If the {@link AbortSignal.timeout} factory method is available, - * it is used to base the timeout on _active_ time rather than _elapsed_ time. - * Otherwise, `timeout` falls back to {@link setTimeout}. - * - * @group Static Methods - */ - static timeout(milliseconds, cause) { - const promise = new CancellablePromise(() => { - }); - if (AbortSignal && typeof AbortSignal === "function" && AbortSignal.timeout && typeof AbortSignal.timeout === "function") { - AbortSignal.timeout(milliseconds).addEventListener("abort", () => void promise.cancel(cause)); - } else { - setTimeout(() => void promise.cancel(cause), milliseconds); - } - return promise; - } - static sleep(milliseconds, value) { - return new CancellablePromise((resolve) => { - setTimeout(() => resolve(value), milliseconds); - }); - } - /** - * Creates a new rejected CancellablePromise for the provided reason. - * - * @group Static Methods - */ - static reject(reason) { - return new CancellablePromise((_, reject) => reject(reason)); - } - static resolve(value) { - if (value instanceof CancellablePromise) { - return value; - } - return new CancellablePromise((resolve) => resolve(value)); - } - /** - * Creates a new CancellablePromise and returns it in an object, along with its resolve and reject functions - * and a getter/setter for the cancellation callback. - * - * This method is polyfilled, hence available in every OS/webview version. - * - * @group Static Methods - */ - static withResolvers() { - let result = { oncancelled: null }; - result.promise = new CancellablePromise((resolve, reject) => { - result.resolve = resolve; - result.reject = reject; - }, (cause) => { - var _a2; - (_a2 = result.oncancelled) === null || _a2 === void 0 ? void 0 : _a2.call(result, cause); - }); - return result; - } -} -function cancellerFor(promise, state) { - let cancellationPromise = void 0; - return (reason) => { - if (!state.settled) { - state.settled = true; - state.reason = reason; - promise.reject(reason); - void Promise.prototype.then.call(promise.promise, void 0, (err) => { - if (err !== reason) { - throw err; - } - }); - } - if (!state.reason || !promise.oncancelled) { - return; - } - cancellationPromise = new Promise((resolve) => { - try { - resolve(promise.oncancelled(state.reason.cause)); - } catch (err) { - Promise.reject(new CancelledRejectionError(promise.promise, err, "Unhandled exception in oncancelled callback.")); - } - }).catch((reason2) => { - Promise.reject(new CancelledRejectionError(promise.promise, reason2, "Unhandled rejection in oncancelled callback.")); - }); - promise.oncancelled = null; - return cancellationPromise; - }; -} -function resolverFor(promise, state) { - return (value) => { - if (state.resolving) { - return; - } - state.resolving = true; - if (value === promise.promise) { - if (state.settled) { - return; - } - state.settled = true; - promise.reject(new TypeError("A promise cannot be resolved with itself.")); - return; - } - if (value != null && (typeof value === "object" || typeof value === "function")) { - let then; - try { - then = value.then; - } catch (err) { - state.settled = true; - promise.reject(err); - return; - } - if (isCallable(then)) { - try { - let cancel = value.cancel; - if (isCallable(cancel)) { - const oncancelled = (cause) => { - Reflect.apply(cancel, value, [cause]); - }; - if (state.reason) { - void cancellerFor(Object.assign(Object.assign({}, promise), { oncancelled }), state)(state.reason); - } else { - promise.oncancelled = oncancelled; - } - } - } catch (_a2) { - } - const newState = { - root: state.root, - resolving: false, - get settled() { - return this.root.settled; - }, - set settled(value2) { - this.root.settled = value2; - }, - get reason() { - return this.root.reason; - } - }; - const rejector = rejectorFor(promise, newState); - try { - Reflect.apply(then, value, [resolverFor(promise, newState), rejector]); - } catch (err) { - rejector(err); - } - return; - } - } - if (state.settled) { - return; - } - state.settled = true; - promise.resolve(value); - }; -} -function rejectorFor(promise, state) { - return (reason) => { - if (state.resolving) { - return; - } - state.resolving = true; - if (state.settled) { - try { - if (reason instanceof CancelError && state.reason instanceof CancelError && Object.is(reason.cause, state.reason.cause)) { - return; - } - } catch (_a2) { - } - void Promise.reject(new CancelledRejectionError(promise.promise, reason)); - } else { - state.settled = true; - promise.reject(reason); - } - }; -} -function cancelAll(parent, values, cause) { - const results = []; - for (const value of values) { - let cancel; - try { - if (!isCallable(value.then)) { - continue; - } - cancel = value.cancel; - if (!isCallable(cancel)) { - continue; - } - } catch (_a2) { - continue; - } - let result; - try { - result = Reflect.apply(cancel, value, [cause]); - } catch (err) { - Promise.reject(new CancelledRejectionError(parent, err, "Unhandled exception in cancel method.")); - continue; - } - if (!result) { - continue; - } - results.push((result instanceof Promise ? result : Promise.resolve(result)).catch((reason) => { - Promise.reject(new CancelledRejectionError(parent, reason, "Unhandled rejection in cancel method.")); - })); - } - return Promise.all(results); -} -function identity(x) { - return x; -} -function thrower(reason) { - throw reason; -} -function errorMessage(err) { - try { - if (err instanceof Error || typeof err !== "object" || err.toString !== Object.prototype.toString) { - return "" + err; - } - } catch (_a2) { - } - try { - return JSON.stringify(err); - } catch (_b) { - } - try { - return Object.prototype.toString.call(err); - } catch (_c) { - } - return ""; -} -function currentBarrier(promise) { - var _a2; - let pwr = (_a2 = promise[barrierSym]) !== null && _a2 !== void 0 ? _a2 : {}; - if (!("promise" in pwr)) { - Object.assign(pwr, promiseWithResolvers()); - } - if (promise[barrierSym] == null) { - pwr.resolve(); - promise[barrierSym] = pwr; - } - return pwr.promise; -} -let promiseWithResolvers = Promise.withResolvers; -if (promiseWithResolvers && typeof promiseWithResolvers === "function") { - promiseWithResolvers = promiseWithResolvers.bind(Promise); -} else { - promiseWithResolvers = function() { - let resolve; - let reject; - const promise = new Promise((res, rej) => { - resolve = res; - reject = rej; - }); - return { promise, resolve, reject }; - }; -} -window._wails = window._wails || {}; -window._wails.callResultHandler = resultHandler; -window._wails.callErrorHandler = errorHandler; -const call$1 = newRuntimeCaller(objectNames.Call); -const cancelCall = newRuntimeCaller(objectNames.CancelCall); -const callResponses = /* @__PURE__ */ new Map(); -const CallBinding = 0; -const CancelMethod = 0; -class RuntimeError extends Error { - /** - * Constructs a new RuntimeError instance. - * @param message - The error message. - * @param options - Options to be forwarded to the Error constructor. - */ - constructor(message, options) { - super(message, options); - this.name = "RuntimeError"; - } -} -function resultHandler(id, data, isJSON) { - const resolvers = getAndDeleteResponse(id); - if (!resolvers) { - return; - } - if (!data) { - resolvers.resolve(void 0); - } else if (!isJSON) { - resolvers.resolve(data); - } else { - try { - resolvers.resolve(JSON.parse(data)); - } catch (err) { - resolvers.reject(new TypeError("could not parse result: " + err.message, { cause: err })); - } - } -} -function errorHandler(id, data, isJSON) { - const resolvers = getAndDeleteResponse(id); - if (!resolvers) { - return; - } - if (!isJSON) { - resolvers.reject(new Error(data)); - } else { - let error; - try { - error = JSON.parse(data); - } catch (err) { - resolvers.reject(new TypeError("could not parse error: " + err.message, { cause: err })); - return; - } - let options = {}; - if (error.cause) { - options.cause = error.cause; - } - let exception; - switch (error.kind) { - case "ReferenceError": - exception = new ReferenceError(error.message, options); - break; - case "TypeError": - exception = new TypeError(error.message, options); - break; - case "RuntimeError": - exception = new RuntimeError(error.message, options); - break; - default: - exception = new Error(error.message, options); - break; - } - resolvers.reject(exception); - } -} -function getAndDeleteResponse(id) { - const response = callResponses.get(id); - callResponses.delete(id); - return response; -} -function generateID() { - let result; - do { - result = nanoid(); - } while (callResponses.has(result)); - return result; -} -function Call(options) { - const id = generateID(); - const result = CancellablePromise.withResolvers(); - callResponses.set(id, { resolve: result.resolve, reject: result.reject }); - const request = call$1(CallBinding, Object.assign({ "call-id": id }, options)); - let running = false; - request.then(() => { - running = true; - }, (err) => { - callResponses.delete(id); - result.reject(err); - }); - const cancel = () => { - callResponses.delete(id); - return cancelCall(CancelMethod, { "call-id": id }).catch((err) => { - console.error("Error while requesting binding call cancellation:", err); - }); - }; - result.oncancelled = () => { - if (running) { - return cancel(); - } else { - return request.then(cancel); - } - }; - return result.promise; -} -function ByID(methodID, ...args) { - return Call({ methodID, args }); -} -const eventListeners = /* @__PURE__ */ new Map(); -class Listener { - constructor(eventName, callback, maxCallbacks) { - this.eventName = eventName; - this.callback = callback; - this.maxCallbacks = maxCallbacks || -1; - } - dispatch(data) { - try { - this.callback(data); - } catch (err) { - console.error(err); - } - if (this.maxCallbacks === -1) - return false; - this.maxCallbacks -= 1; - return this.maxCallbacks === 0; - } -} -function listenerOff(listener) { - let listeners = eventListeners.get(listener.eventName); - if (!listeners) { - return; - } - listeners = listeners.filter((l) => l !== listener); - if (listeners.length === 0) { - eventListeners.delete(listener.eventName); - } else { - eventListeners.set(listener.eventName, listeners); - } -} -window._wails = window._wails || {}; -window._wails.dispatchWailsEvent = dispatchWailsEvent; -const call = newRuntimeCaller(objectNames.Events); -const EmitMethod = 0; -class WailsEvent { - constructor(name, data = null) { - this.name = name; - this.data = data; - } -} -function dispatchWailsEvent(event) { - let listeners = eventListeners.get(event.name); - if (!listeners) { - return; - } - let wailsEvent = new WailsEvent(event.name, event.data); - if ("sender" in event) { - wailsEvent.sender = event.sender; - } - listeners = listeners.filter((listener) => !listener.dispatch(wailsEvent)); - if (listeners.length === 0) { - eventListeners.delete(event.name); - } else { - eventListeners.set(event.name, listeners); - } -} -function OnMultiple(eventName, callback, maxCallbacks) { - let listeners = eventListeners.get(eventName) || []; - const thisListener = new Listener(eventName, callback, maxCallbacks); - listeners.push(thisListener); - eventListeners.set(eventName, listeners); - return () => listenerOff(thisListener); -} -function On(eventName, callback) { - return OnMultiple(eventName, callback, -1); -} -function Emit(event) { - return call(EmitMethod, event); -} -window._wails = window._wails || {}; -window._wails.invoke = invoke; -invoke("wails:runtime:ready"); -function RemoveBadge() { - return ByID(2752757297); -} -function SetBadge(label) { - return ByID(1717705661, label); -} -const setButton = document.getElementById("set"); -const removeButton = document.getElementById("remove"); -const setButtonUsingGo = document.getElementById("set-go"); -const removeButtonUsingGo = document.getElementById("remove-go"); -const labelElement = document.getElementById("label"); -const timeElement = document.getElementById("time"); -setButton.addEventListener("click", () => { - let label = labelElement.value; - SetBadge(label); -}); -removeButton.addEventListener("click", () => { - RemoveBadge(); -}); -setButtonUsingGo.addEventListener("click", () => { - let label = labelElement.value; - void Emit({ - name: "set:badge", - data: label - }); -}); -removeButtonUsingGo.addEventListener("click", () => { - void Emit({ name: "remove:badge", data: null }); -}); -On("time", (time) => { - timeElement.innerText = time.data; -}); diff --git a/v3/examples/badge/frontend/dist/index.html b/v3/examples/badge/frontend/dist/index.html deleted file mode 100644 index b8ca49f06..000000000 --- a/v3/examples/badge/frontend/dist/index.html +++ /dev/null @@ -1,38 +0,0 @@ - - - - - - - - Wails App - - - -
      - -

      Wails + Typescript

      -
      Set a badge label below 👇
      -
      -
      - - - - - -
      -
      - -
      - - diff --git a/v3/examples/badge/frontend/dist/style.css b/v3/examples/badge/frontend/dist/style.css deleted file mode 100644 index 6ce81cad2..000000000 --- a/v3/examples/badge/frontend/dist/style.css +++ /dev/null @@ -1,155 +0,0 @@ -:root { - font-family: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", - "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", - sans-serif; - font-size: 16px; - line-height: 24px; - font-weight: 400; - color-scheme: light dark; - color: rgba(255, 255, 255, 0.87); - background-color: rgba(27, 38, 54, 1); - font-synthesis: none; - text-rendering: optimizeLegibility; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - -webkit-text-size-adjust: 100%; - user-select: none; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; -} - -@font-face { - font-family: "Inter"; - font-style: normal; - font-weight: 400; - src: local(""), - url("./Inter-Medium.ttf") format("truetype"); -} - -h3 { - font-size: 3em; - line-height: 1.1; -} - -a { - font-weight: 500; - color: #646cff; - text-decoration: inherit; -} - -a:hover { - color: #535bf2; -} - -button { - line-height: 30px; - border-radius: 3px; - border: none; - margin: 0 0 0 20px; - padding: 0 8px; - cursor: pointer; -} - -.result { - height: 20px; - line-height: 20px; -} - -body { - margin: 0; - display: flex; - place-items: center; - place-content: center; - min-width: 320px; - min-height: 100vh; -} - -.container { - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; -} - -h1 { - font-size: 3.2em; - line-height: 1.1; -} - -#app { - max-width: 1280px; - margin: 0 auto; - padding: 2rem; - text-align: center; -} - -.logo { - height: 6em; - padding: 1.5em; - will-change: filter; -} - -.logo:hover { - filter: drop-shadow(0 0 2em #e80000aa); -} - -.logo.vanilla:hover { - filter: drop-shadow(0 0 2em #f7df1eaa); -} - -.result { - height: 20px; - line-height: 20px; - margin: 1.5rem auto; - text-align: center; -} - -.footer { - margin-top: 1rem; - align-content: center; - text-align: center; -} - -@media (prefers-color-scheme: light) { - :root { - color: #213547; - background-color: #ffffff; - } - - a:hover { - color: #747bff; - } - - button { - background-color: #f9f9f9; - } -} - - -.input-box .btn:hover { - background-image: linear-gradient(to top, #cfd9df 0%, #e2ebf0 100%); - color: #333333; -} - -.input-box .input { - border: none; - border-radius: 3px; - outline: none; - height: 30px; - line-height: 30px; - padding: 0 10px; - color: black; - background-color: rgba(240, 240, 240, 1); - -webkit-font-smoothing: antialiased; -} - -.input-box .input:hover { - border: none; - background-color: rgba(255, 255, 255, 1); -} - -.input-box .input:focus { - border: none; - background-color: rgba(255, 255, 255, 1); -} \ No newline at end of file diff --git a/v3/examples/badge/frontend/dist/typescript.svg b/v3/examples/badge/frontend/dist/typescript.svg deleted file mode 100644 index d91c910cc..000000000 --- a/v3/examples/badge/frontend/dist/typescript.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/v3/examples/badge/frontend/dist/wails.png b/v3/examples/badge/frontend/dist/wails.png deleted file mode 100644 index 8bdf42483..000000000 Binary files a/v3/examples/badge/frontend/dist/wails.png and /dev/null differ diff --git a/v3/examples/badge/frontend/index.html b/v3/examples/badge/frontend/index.html deleted file mode 100644 index 616cb4c0f..000000000 --- a/v3/examples/badge/frontend/index.html +++ /dev/null @@ -1,38 +0,0 @@ - - - - - - - - Wails App - - -
      - -

      Wails + Typescript

      -
      Set a badge label below 👇
      -
      -
      - - - - - -
      -
      - -
      - - - diff --git a/v3/examples/badge/frontend/package.json b/v3/examples/badge/frontend/package.json deleted file mode 100644 index b39da7ece..000000000 --- a/v3/examples/badge/frontend/package.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "name": "frontend", - "private": true, - "version": "0.0.0", - "type": "module", - "scripts": { - "dev": "vite", - "build:dev": "tsc && vite build --minify false --mode development", - "build": "tsc && vite build --mode production", - "preview": "vite preview" - }, - "dependencies": { - "@wailsio/runtime": "latest" - }, - "devDependencies": { - "typescript": "^4.9.3", - "vite": "^5.0.0" - } -} diff --git a/v3/examples/badge/frontend/public/Inter-Medium.ttf b/v3/examples/badge/frontend/public/Inter-Medium.ttf deleted file mode 100644 index a01f3777a..000000000 Binary files a/v3/examples/badge/frontend/public/Inter-Medium.ttf and /dev/null differ diff --git a/v3/examples/badge/frontend/public/style.css b/v3/examples/badge/frontend/public/style.css deleted file mode 100644 index 6ce81cad2..000000000 --- a/v3/examples/badge/frontend/public/style.css +++ /dev/null @@ -1,155 +0,0 @@ -:root { - font-family: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", - "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", - sans-serif; - font-size: 16px; - line-height: 24px; - font-weight: 400; - color-scheme: light dark; - color: rgba(255, 255, 255, 0.87); - background-color: rgba(27, 38, 54, 1); - font-synthesis: none; - text-rendering: optimizeLegibility; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - -webkit-text-size-adjust: 100%; - user-select: none; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; -} - -@font-face { - font-family: "Inter"; - font-style: normal; - font-weight: 400; - src: local(""), - url("./Inter-Medium.ttf") format("truetype"); -} - -h3 { - font-size: 3em; - line-height: 1.1; -} - -a { - font-weight: 500; - color: #646cff; - text-decoration: inherit; -} - -a:hover { - color: #535bf2; -} - -button { - line-height: 30px; - border-radius: 3px; - border: none; - margin: 0 0 0 20px; - padding: 0 8px; - cursor: pointer; -} - -.result { - height: 20px; - line-height: 20px; -} - -body { - margin: 0; - display: flex; - place-items: center; - place-content: center; - min-width: 320px; - min-height: 100vh; -} - -.container { - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; -} - -h1 { - font-size: 3.2em; - line-height: 1.1; -} - -#app { - max-width: 1280px; - margin: 0 auto; - padding: 2rem; - text-align: center; -} - -.logo { - height: 6em; - padding: 1.5em; - will-change: filter; -} - -.logo:hover { - filter: drop-shadow(0 0 2em #e80000aa); -} - -.logo.vanilla:hover { - filter: drop-shadow(0 0 2em #f7df1eaa); -} - -.result { - height: 20px; - line-height: 20px; - margin: 1.5rem auto; - text-align: center; -} - -.footer { - margin-top: 1rem; - align-content: center; - text-align: center; -} - -@media (prefers-color-scheme: light) { - :root { - color: #213547; - background-color: #ffffff; - } - - a:hover { - color: #747bff; - } - - button { - background-color: #f9f9f9; - } -} - - -.input-box .btn:hover { - background-image: linear-gradient(to top, #cfd9df 0%, #e2ebf0 100%); - color: #333333; -} - -.input-box .input { - border: none; - border-radius: 3px; - outline: none; - height: 30px; - line-height: 30px; - padding: 0 10px; - color: black; - background-color: rgba(240, 240, 240, 1); - -webkit-font-smoothing: antialiased; -} - -.input-box .input:hover { - border: none; - background-color: rgba(255, 255, 255, 1); -} - -.input-box .input:focus { - border: none; - background-color: rgba(255, 255, 255, 1); -} \ No newline at end of file diff --git a/v3/examples/badge/frontend/public/typescript.svg b/v3/examples/badge/frontend/public/typescript.svg deleted file mode 100644 index d91c910cc..000000000 --- a/v3/examples/badge/frontend/public/typescript.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/v3/examples/badge/frontend/public/wails.png b/v3/examples/badge/frontend/public/wails.png deleted file mode 100644 index 8bdf42483..000000000 Binary files a/v3/examples/badge/frontend/public/wails.png and /dev/null differ diff --git a/v3/examples/badge/frontend/src/main.ts b/v3/examples/badge/frontend/src/main.ts deleted file mode 100644 index 222564848..000000000 --- a/v3/examples/badge/frontend/src/main.ts +++ /dev/null @@ -1,32 +0,0 @@ -import {Events} from "@wailsio/runtime"; -import {SetBadge, RemoveBadge} from "../bindings/github.com/wailsapp/wails/v3/pkg/services/dock/dockservice"; - -const setButton = document.getElementById('set')! as HTMLButtonElement; -const removeButton = document.getElementById('remove')! as HTMLButtonElement; -const setButtonUsingGo = document.getElementById('set-go')! as HTMLButtonElement; -const removeButtonUsingGo = document.getElementById('remove-go')! as HTMLButtonElement; -const labelElement : HTMLInputElement = document.getElementById('label')! as HTMLInputElement; -const timeElement = document.getElementById('time')! as HTMLDivElement; - -setButton.addEventListener('click', () => { - let label = (labelElement as HTMLInputElement).value - SetBadge(label); -}); - -removeButton.addEventListener('click', () => { - RemoveBadge(); -}); - -setButtonUsingGo.addEventListener('click', () => { - let label = (labelElement as HTMLInputElement).value - void Events.Emit("set:badge", label) -}) - -removeButtonUsingGo.addEventListener('click', () => { - void Events.Emit("remove:badge") -}) - -Events.On('time', (time: {data: any}) => { - timeElement.innerText = time.data; -}); - diff --git a/v3/examples/badge/frontend/src/vite-env.d.ts b/v3/examples/badge/frontend/src/vite-env.d.ts deleted file mode 100644 index 11f02fe2a..000000000 --- a/v3/examples/badge/frontend/src/vite-env.d.ts +++ /dev/null @@ -1 +0,0 @@ -/// diff --git a/v3/examples/badge/frontend/tsconfig.json b/v3/examples/badge/frontend/tsconfig.json deleted file mode 100644 index c267ecf24..000000000 --- a/v3/examples/badge/frontend/tsconfig.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "compilerOptions": { - "target": "ESNext", - "useDefineForClassFields": true, - "module": "ESNext", - "lib": ["ESNext", "DOM"], - "moduleResolution": "Node", - "strict": true, - "resolveJsonModule": true, - "isolatedModules": true, - "esModuleInterop": true, - "noEmit": true, - "noUnusedLocals": true, - "noUnusedParameters": false, - "noImplicitAny": false, - "noImplicitReturns": true, - "skipLibCheck": true - }, - "include": ["src"] -} diff --git a/v3/examples/badge/main.go b/v3/examples/badge/main.go deleted file mode 100644 index f97f3924e..000000000 --- a/v3/examples/badge/main.go +++ /dev/null @@ -1,109 +0,0 @@ -package main - -import ( - "embed" - _ "embed" - "log" - "time" - - "github.com/wailsapp/wails/v3/pkg/application" - "github.com/wailsapp/wails/v3/pkg/services/dock" -) - -// Wails uses Go's `embed` package to embed the frontend files into the binary. -// Any files in the frontend/dist folder will be embedded into the binary and -// made available to the frontend. -// See https://pkg.go.dev/embed for more information. - -//go:embed all:frontend/dist -var assets embed.FS - -// main function serves as the application's entry point. It initializes the application, creates a window, -// and starts a goroutine that emits a time-based event every second. It subsequently runs the application and -// logs any error that might occur. -func main() { - // Create a new Wails application by providing the necessary options. - // Variables 'Name' and 'Description' are for application metadata. - // 'Assets' configures the asset server with the 'FS' variable pointing to the frontend files. - // 'Bind' is a list of Go struct instances. The frontend has access to the methods of these instances. - // 'Mac' options tailor the application when running an macOS. - - dockService := dock.New() - - app := application.New(application.Options{ - Name: "badge", - Description: "A demo of using raw HTML & CSS", - Services: []application.Service{ - application.NewService(dockService), - }, - Assets: application.AssetOptions{ - Handler: application.AssetFileServerFS(assets), - }, - Mac: application.MacOptions{ - ApplicationShouldTerminateAfterLastWindowClosed: true, - }, - }) - - // Create a new window with the necessary options. - // 'Title' is the title of the window. - // 'Mac' options tailor the window when running on macOS. - // 'BackgroundColour' is the background colour of the window. - // 'URL' is the URL that will be loaded into the webview. - app.Window.NewWithOptions(application.WebviewWindowOptions{ - Title: "Window 1", - Mac: application.MacWindow{ - InvisibleTitleBarHeight: 50, - Backdrop: application.MacBackdropTranslucent, - TitleBar: application.MacTitleBarHiddenInset, - }, - BackgroundColour: application.NewRGB(27, 38, 54), - URL: "/", - }) - - // Store cleanup functions for proper resource management - removeBadgeHandler := app.Event.On("remove:badge", func(event *application.CustomEvent) { - err := dockService.RemoveBadge() - if err != nil { - log.Fatal(err) - } - }) - - setBadgeHandler := app.Event.On("set:badge", func(event *application.CustomEvent) { - text := event.Data.(string) - err := dockService.SetBadge(text) - if err != nil { - log.Fatal(err) - } - }) - - // Note: In a production application, you would call these cleanup functions - // when the handlers are no longer needed, e.g., during shutdown: - // defer removeBadgeHandler() - // defer setBadgeHandler() - _ = removeBadgeHandler // Acknowledge we're storing the cleanup functions - _ = setBadgeHandler - - // Create a goroutine that emits an event containing the current time every second. - // The frontend can listen to this event and update the UI accordingly. - go func() { - ticker := time.NewTicker(time.Second) - defer ticker.Stop() - for { - select { - case <-ticker.C: - now := time.Now().Format(time.RFC1123) - app.Event.Emit("time", now) - case <-app.Context().Done(): - return - } - } - }() - - // Run the application. This blocks until the application has been exited. - err := app.Run() - - // If an error occurred while running the application, log it and exit. - if err != nil { - log.Fatal(err) - } -} diff --git a/v3/examples/binding/GreetService.go b/v3/examples/binding/GreetService.go deleted file mode 100644 index 262fea722..000000000 --- a/v3/examples/binding/GreetService.go +++ /dev/null @@ -1,39 +0,0 @@ -package main - -import ( - "strconv" - - "github.com/wailsapp/wails/v3/examples/binding/data" -) - -// GreetService is a service that greets people -type GreetService struct { -} - -// Greet greets a person -func (*GreetService) Greet(name string, counts ...int) string { - times := " " - - for index, count := range counts { - if index > 0 { - times += ", " - } - times += strconv.Itoa(count) - } - - if len(counts) > 0 { - times += " times " - } - - return "Hello" + times + name -} - -// GreetPerson greets a person -func (srv *GreetService) GreetPerson(person data.Person) string { - return srv.Greet(person.Name, person.Counts...) -} - -// GetPerson returns a person with the given name. -func (srv *GreetService) GetPerson(name string) data.Person { - return data.Person{Name: name} -} diff --git a/v3/examples/binding/README.md b/v3/examples/binding/README.md deleted file mode 100644 index 37d0f2cc8..000000000 --- a/v3/examples/binding/README.md +++ /dev/null @@ -1,11 +0,0 @@ -# Bindings Example - -This example demonstrates how to generate bindings for your application. - -To generate bindings, run `wails3 generate bindings -clean -b -d assets/bindings` in this directory. - -See more options by running `wails3 generate bindings --help`. - -## Notes - - The bindings generator is still a work in progress and is subject to change. - - The generated code uses `wails.CallByID` by default. This is the most robust way to call a function. diff --git a/v3/examples/binding/assets/bindings/github.com/wailsapp/wails/v3/examples/binding/data/index.js b/v3/examples/binding/assets/bindings/github.com/wailsapp/wails/v3/examples/binding/data/index.js deleted file mode 100644 index 4c7e0b9c6..000000000 --- a/v3/examples/binding/assets/bindings/github.com/wailsapp/wails/v3/examples/binding/data/index.js +++ /dev/null @@ -1,7 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -export { - Person -} from "./models.js"; diff --git a/v3/examples/binding/assets/bindings/github.com/wailsapp/wails/v3/examples/binding/data/models.js b/v3/examples/binding/assets/bindings/github.com/wailsapp/wails/v3/examples/binding/data/models.js deleted file mode 100644 index 19a39472c..000000000 --- a/v3/examples/binding/assets/bindings/github.com/wailsapp/wails/v3/examples/binding/data/models.js +++ /dev/null @@ -1,55 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import {Create as $Create} from "/wails/runtime.js"; - -/** - * Person holds someone's most important attributes - */ -export class Person { - /** - * Creates a new Person instance. - * @param {Partial} [$$source = {}] - The source object to create the Person. - */ - constructor($$source = {}) { - if (!("name" in $$source)) { - /** - * Name is the person's name - * @member - * @type {string} - */ - this["name"] = ""; - } - if (!("counts" in $$source)) { - /** - * Counts tracks the number of time the person - * has been greeted in various ways - * @member - * @type {number[]} - */ - this["counts"] = []; - } - - Object.assign(this, $$source); - } - - /** - * Creates a new Person instance from a string or object. - * @param {any} [$$source = {}] - * @returns {Person} - */ - static createFrom($$source = {}) { - const $$createField1_0 = $$createType0; - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - if ("counts" in $$parsedSource) { - $$parsedSource["counts"] = $$createField1_0($$parsedSource["counts"]); - } - return new Person(/** @type {Partial} */($$parsedSource)); - } -} - -// Private type creation functions -const $$createType0 = $Create.Array($Create.Any); diff --git a/v3/examples/binding/assets/bindings/github.com/wailsapp/wails/v3/examples/binding/greetservice.js b/v3/examples/binding/assets/bindings/github.com/wailsapp/wails/v3/examples/binding/greetservice.js deleted file mode 100644 index 0e5e40d84..000000000 --- a/v3/examples/binding/assets/bindings/github.com/wailsapp/wails/v3/examples/binding/greetservice.js +++ /dev/null @@ -1,49 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is a service that greets people - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import {Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create} from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as data$0 from "./data/models.js"; - -/** - * GetPerson returns a person with the given name. - * @param {string} name - * @returns {$CancellablePromise} - */ -export function GetPerson(name) { - return $Call.ByID(2952413357, name).then(/** @type {($result: any) => any} */(($result) => { - return $$createType0($result); - })); -} - -/** - * Greet greets a person - * @param {string} name - * @param {number[]} counts - * @returns {$CancellablePromise} - */ -export function Greet(name, ...counts) { - return $Call.ByID(1411160069, name, counts); -} - -/** - * GreetPerson greets a person - * @param {data$0.Person} person - * @returns {$CancellablePromise} - */ -export function GreetPerson(person) { - return $Call.ByID(4021313248, person); -} - -// Private type creation functions -const $$createType0 = data$0.Person.createFrom; diff --git a/v3/examples/binding/assets/bindings/github.com/wailsapp/wails/v3/examples/binding/index.js b/v3/examples/binding/assets/bindings/github.com/wailsapp/wails/v3/examples/binding/index.js deleted file mode 100644 index fdf1ff435..000000000 --- a/v3/examples/binding/assets/bindings/github.com/wailsapp/wails/v3/examples/binding/index.js +++ /dev/null @@ -1,8 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; diff --git a/v3/examples/binding/assets/index.html b/v3/examples/binding/assets/index.html deleted file mode 100644 index c86c7b7af..000000000 --- a/v3/examples/binding/assets/index.html +++ /dev/null @@ -1,130 +0,0 @@ - - - - - Wails Alpha - - - - -
      Alpha
      -
      -

      Documentation

      -

      Feedback

      -
      -
      Please enter your name below 👇
      -
      - - - -
      - - - diff --git a/v3/examples/binding/data/person.go b/v3/examples/binding/data/person.go deleted file mode 100644 index 114dfdf4c..000000000 --- a/v3/examples/binding/data/person.go +++ /dev/null @@ -1,11 +0,0 @@ -package data - -// Person holds someone's most important attributes -type Person struct { - // Name is the person's name - Name string `json:"name"` - - // Counts tracks the number of time the person - // has been greeted in various ways - Counts []int `json:"counts"` -} diff --git a/v3/examples/binding/main.go b/v3/examples/binding/main.go deleted file mode 100644 index 6e956bac1..000000000 --- a/v3/examples/binding/main.go +++ /dev/null @@ -1,37 +0,0 @@ -package main - -import ( - "embed" - "log" - - "github.com/wailsapp/wails/v3/pkg/application" -) - -//go:embed assets/* -var assets embed.FS - -func main() { - app := application.New(application.Options{ - Services: []application.Service{ - application.NewService(&GreetService{}), - }, - Assets: application.AssetOptions{ - Handler: application.BundledAssetFileServer(assets), - }, - Mac: application.MacOptions{ - ApplicationShouldTerminateAfterLastWindowClosed: true, - }, - }) - - app.Window.NewWithOptions(application.WebviewWindowOptions{ - URL: "/", - DevToolsEnabled: true, - }) - - err := app.Run() - - if err != nil { - log.Fatal(err) - } - -} diff --git a/v3/examples/build/README.md b/v3/examples/build/README.md deleted file mode 100644 index 3e2c246a0..000000000 --- a/v3/examples/build/README.md +++ /dev/null @@ -1,23 +0,0 @@ -# Build - -Wails has adopted [Taskfile](https://taskfile.dev) as its build tool. This is optional -and any build tool can be used. However, Taskfile is a great tool, and we recommend it. - -The Wails CLI has built-in integration with Taskfile so the standalone version is not a -requirement. - -## Building - -To build the example, run: - -```bash -wails3 task build -``` - -# Status - -| Platform | Status | -|----------|---------| -| Mac | Working | -| Windows | Working | -| Linux | | \ No newline at end of file diff --git a/v3/examples/build/Taskfile.yml b/v3/examples/build/Taskfile.yml deleted file mode 100644 index f4e5e1f15..000000000 --- a/v3/examples/build/Taskfile.yml +++ /dev/null @@ -1,110 +0,0 @@ -version: '3' - -vars: - APP_NAME: "buildtest{{exeExt}}" -tasks: - - build: - summary: Builds the application - cmds: - - go build -gcflags=all="-N -l" -o bin/{{.APP_NAME}} - - package: - summary: Packages a production build of the application into a `.app` or `.exe` bundle - deps: - - task: build - cmds: - - task: package:darwin - - task: package:windows - -# ------------------------------------------------------------------------------ - - generate:icons: - summary: Generates Windows `.ico` and Mac `.icns` files from an image - dir: build - cmds: - # Generates both .ico and .icns files - - wails3 generate icons -input appicon.png - - build:production:darwin: - summary: Creates a production build of the application - cmds: - - GOOS=darwin GOARCH={{.GOARCH}} go build -tags production -ldflags="-w -s" -o build/bin/{{.APP_NAME}} - env: - CGO_CFLAGS: "-mmacosx-version-min=10.13" - CGO_LDFLAGS: "-mmacosx-version-min=10.13" - MACOSX_DEPLOYMENT_TARGET: "10.13" - GOARCH: '{{.GOARCH}}' - - build:production:linux: - summary: Creates a production build of the application - cmds: - - GOOS=linux GOARCH={{.GOARCH}} go build -tags production -ldflags="-w -s" -o build/bin/{{.APP_NAME}} - env: - GOARCH: '{{.GOARCH}}' - - generate:app_bundle: - summary: Builds a `.app` bundle - cmds: - - mkdir -p {{.APP_NAME}}.app/Contents/{MacOS,Resources} - - cp build/icons.icns {{.APP_NAME}}.app/Contents/Resources - - cp build/bin/{{.APP_NAME}} {{.APP_NAME}}.app/Contents/MacOS - - cp build/Info.plist {{.APP_NAME}}.app/Contents - - package:darwin:arm64: - summary: Packages a production build of the application into a `.app` bundle - platforms: - - darwin - deps: - - task: build:production:darwin - vars: - ARCH: arm64 - - generate:icons - cmds: - - task: generate:app_bundle - - package:darwin: - summary: Packages a production build of the application into a `.app` bundle - platforms: - - darwin - deps: - - task: build:production:darwin - - generate:icons - cmds: - - task: generate:app_bundle - - generate:syso: - dir: build - platforms: - - windows - cmds: - - wails3 generate syso -arch {{.GOARCH}} -icon icon.ico -manifest wails.exe.manifest -info info.json -out ../wails_windows.syso - vars: - GOARCH: '{{.GOARCH}}' - - package:windows: - summary: Packages a production build of the application into a `.exe` bundle - platforms: - - windows/amd64 - deps: - - generate:icons - cmds: - - task: generate:syso - vars: - GOARCH: amd64 - - go build -tags production -ldflags="-w -s -H windowsgui" -o bin/{{.APP_NAME}} - - powershell Remove-item *.syso - - - package:windows:arm64: - summary: Packages a production build of the application into a `.exe` bundle (ARM64) - platforms: - - windows - cmds: - - task: generate:syso - vars: - GOARCH: arm64 - - go build -tags production -ldflags="-w -s -H windowsgui" -o bin/buildtest.arm64.exe - - powershell Remove-item *.syso - env: - GOARCH: arm64 diff --git a/v3/examples/build/build/Info.dev.plist b/v3/examples/build/build/Info.dev.plist deleted file mode 100644 index d6d28b179..000000000 --- a/v3/examples/build/build/Info.dev.plist +++ /dev/null @@ -1,35 +0,0 @@ - - - - CFBundlePackageType - APPL - CFBundleName - My App - CFBundleExecutable - app - CFBundleIdentifier - com.wails.app - CFBundleVersion - v1.0.0 - CFBundleGetInfoString - The ultimate thing - CFBundleShortVersionString - v1 - CFBundleIconFile - icons - LSMinimumSystemVersion - 10.13.0 - NSHighResolutionCapable - true - NSHumanReadableCopyright - (c) Me - NSAppTransportSecurity - - NSAllowsLocalNetworking - - - - - - - \ No newline at end of file diff --git a/v3/examples/build/build/Info.plist b/v3/examples/build/build/Info.plist deleted file mode 100644 index 7f03f54e9..000000000 --- a/v3/examples/build/build/Info.plist +++ /dev/null @@ -1,27 +0,0 @@ - - - - CFBundlePackageType - APPL - CFBundleName - My App - CFBundleExecutable - app - CFBundleIdentifier - com.wails.app - CFBundleVersion - v1.0.0 - CFBundleGetInfoString - The ultimate thing - CFBundleShortVersionString - v1 - CFBundleIconFile - icons - LSMinimumSystemVersion - 10.13.0 - NSHighResolutionCapable - true - NSHumanReadableCopyright - (c) Me - - \ No newline at end of file diff --git a/v3/examples/build/build/appicon.png b/v3/examples/build/build/appicon.png deleted file mode 100644 index 63617fe4f..000000000 Binary files a/v3/examples/build/build/appicon.png and /dev/null differ diff --git a/v3/examples/build/build/icon.ico b/v3/examples/build/build/icon.ico deleted file mode 100644 index bfa0690b7..000000000 Binary files a/v3/examples/build/build/icon.ico and /dev/null differ diff --git a/v3/examples/build/build/icons.icns b/v3/examples/build/build/icons.icns deleted file mode 100644 index 1b5bd4c86..000000000 Binary files a/v3/examples/build/build/icons.icns and /dev/null differ diff --git a/v3/examples/build/build/info.json b/v3/examples/build/build/info.json deleted file mode 100644 index 1005eb5cb..000000000 --- a/v3/examples/build/build/info.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "fixed": { - "file_version": "v1.0.0" - }, - "info": { - "0000": { - "ProductVersion": "v1.0.0", - "CompanyName": "My Company Name", - "FileDescription": "A thing that does a thing", - "LegalCopyright": "(c) 2023 My Company Name", - "ProductName": "My Product Name", - "Comments": "This is a comment" - } - } -} \ No newline at end of file diff --git a/v3/examples/build/build/wails.exe.manifest b/v3/examples/build/build/wails.exe.manifest deleted file mode 100644 index fb1ce5bde..000000000 --- a/v3/examples/build/build/wails.exe.manifest +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - true/pm - permonitorv2,permonitor - - - \ No newline at end of file diff --git a/v3/examples/build/main.go b/v3/examples/build/main.go deleted file mode 100755 index 752ad3395..000000000 --- a/v3/examples/build/main.go +++ /dev/null @@ -1,273 +0,0 @@ -package main - -import ( - _ "embed" - "fmt" - "log" - "math/rand" - "runtime" - "strconv" - "time" - - "github.com/wailsapp/wails/v3/pkg/events" - - "github.com/wailsapp/wails/v3/pkg/application" -) - -func main() { - - app := application.New(application.Options{ - Name: "WebviewWindow Demo (debug)", - Description: "A demo of the WebviewWindow API", - Assets: application.AlphaAssets, - Mac: application.MacOptions{ - ApplicationShouldTerminateAfterLastWindowClosed: true, - }, - }) - - app.Event.OnApplicationEvent(events.Mac.ApplicationDidFinishLaunching, func(*application.ApplicationEvent) { - log.Println("ApplicationDidFinishLaunching") - }) - - currentWindow := func(fn func(window application.Window)) { - current := app.Window.Current() - if current != nil { - fn(current) - } else { - println("Current WebviewWindow is nil") - } - } - - // Create a custom menu - menu := app.NewMenu() - if runtime.GOOS == "darwin" { - menu.AddRole(application.AppMenu) - } - - windowCounter := 1 - - // Let's make a "Demo" menu - myMenu := menu.AddSubmenu("New") - - myMenu.Add("New WebviewWindow"). - SetAccelerator("CmdOrCtrl+N"). - OnClick(func(ctx *application.Context) { - app.Window.New(). - SetTitle("WebviewWindow "+strconv.Itoa(windowCounter)). - SetRelativePosition(rand.Intn(1000), rand.Intn(800)). - SetURL("https://wails.io"). - Show() - windowCounter++ - }) - myMenu.Add("New Frameless WebviewWindow"). - SetAccelerator("CmdOrCtrl+F"). - OnClick(func(ctx *application.Context) { - app.Window.NewWithOptions(application.WebviewWindowOptions{ - X: rand.Intn(1000), - Y: rand.Intn(800), - Frameless: true, - Mac: application.MacWindow{ - InvisibleTitleBarHeight: 50, - }, - }).Show() - windowCounter++ - }) - if runtime.GOOS == "darwin" { - myMenu.Add("New WebviewWindow (MacTitleBarHiddenInset)"). - OnClick(func(ctx *application.Context) { - app.Window.NewWithOptions(application.WebviewWindowOptions{ - Mac: application.MacWindow{ - TitleBar: application.MacTitleBarHiddenInset, - InvisibleTitleBarHeight: 25, - }, - }). - SetTitle("WebviewWindow "+strconv.Itoa(windowCounter)). - SetRelativePosition(rand.Intn(1000), rand.Intn(800)). - SetHTML("

      A MacTitleBarHiddenInset WebviewWindow example

      "). - Show() - windowCounter++ - }) - myMenu.Add("New WebviewWindow (MacTitleBarHiddenInsetUnified)"). - OnClick(func(ctx *application.Context) { - app.Window.NewWithOptions(application.WebviewWindowOptions{ - Mac: application.MacWindow{ - TitleBar: application.MacTitleBarHiddenInsetUnified, - InvisibleTitleBarHeight: 50, - }, - }). - SetTitle("WebviewWindow "+strconv.Itoa(windowCounter)). - SetRelativePosition(rand.Intn(1000), rand.Intn(800)). - SetHTML("

      A MacTitleBarHiddenInsetUnified WebviewWindow example

      "). - Show() - windowCounter++ - }) - myMenu.Add("New WebviewWindow (MacTitleBarHidden)"). - OnClick(func(ctx *application.Context) { - app.Window.NewWithOptions(application.WebviewWindowOptions{ - Mac: application.MacWindow{ - TitleBar: application.MacTitleBarHidden, - InvisibleTitleBarHeight: 25, - }, - }). - SetTitle("WebviewWindow "+strconv.Itoa(windowCounter)). - SetRelativePosition(rand.Intn(1000), rand.Intn(800)). - SetHTML("

      A MacTitleBarHidden WebviewWindow example

      "). - Show() - windowCounter++ - }) - } - - sizeMenu := menu.AddSubmenu("Size") - sizeMenu.Add("Set Size (800,600)").OnClick(func(ctx *application.Context) { - currentWindow(func(w application.Window) { - w.SetSize(800, 600) - }) - }) - - sizeMenu.Add("Set Size (Random)").OnClick(func(ctx *application.Context) { - currentWindow(func(w application.Window) { - w.SetSize(rand.Intn(800)+200, rand.Intn(600)+200) - }) - }) - sizeMenu.Add("Set Min Size (200,200)").OnClick(func(ctx *application.Context) { - currentWindow(func(w application.Window) { - w.SetMinSize(200, 200) - }) - }) - sizeMenu.Add("Set Max Size (600,600)").OnClick(func(ctx *application.Context) { - currentWindow(func(w application.Window) { - w.SetMaximiseButtonState(application.ButtonDisabled) - w.SetMaxSize(600, 600) - }) - }) - sizeMenu.Add("Get Current WebviewWindow Size").OnClick(func(ctx *application.Context) { - currentWindow(func(w application.Window) { - width, height := w.Size() - app.Dialog.Info().SetTitle("Current WebviewWindow Size").SetMessage("Width: " + strconv.Itoa(width) + " Height: " + strconv.Itoa(height)).Show() - }) - }) - - sizeMenu.Add("Reset Min Size").OnClick(func(ctx *application.Context) { - currentWindow(func(w application.Window) { - w.SetMinSize(0, 0) - }) - }) - - sizeMenu.Add("Reset Max Size").OnClick(func(ctx *application.Context) { - currentWindow(func(w application.Window) { - w.SetMaxSize(0, 0) - w.SetMaximiseButtonState(application.ButtonEnabled) - }) - }) - positionMenu := menu.AddSubmenu("Position") - positionMenu.Add("Set Relative Position (0,0)").OnClick(func(ctx *application.Context) { - currentWindow(func(w application.Window) { - w.SetRelativePosition(0, 0) - }) - }) - positionMenu.Add("Set Relative Position (Random)").OnClick(func(ctx *application.Context) { - currentWindow(func(w application.Window) { - w.SetRelativePosition(rand.Intn(1000), rand.Intn(800)) - }) - }) - - positionMenu.Add("Get Relative Position").OnClick(func(ctx *application.Context) { - currentWindow(func(w application.Window) { - x, y := w.RelativePosition() - app.Dialog.Info().SetTitle("Current WebviewWindow Relative Position").SetMessage("X: " + strconv.Itoa(x) + " Y: " + strconv.Itoa(y)).Show() - }) - }) - - positionMenu.Add("Center").OnClick(func(ctx *application.Context) { - currentWindow(func(w application.Window) { - w.Center() - }) - }) - stateMenu := menu.AddSubmenu("State") - stateMenu.Add("Minimise (for 2 secs)").OnClick(func(ctx *application.Context) { - currentWindow(func(w application.Window) { - w.Minimise() - time.Sleep(2 * time.Second) - w.Restore() - }) - }) - stateMenu.Add("Maximise").OnClick(func(ctx *application.Context) { - currentWindow(func(w application.Window) { - w.Maximise() - }) - }) - stateMenu.Add("Fullscreen").OnClick(func(ctx *application.Context) { - currentWindow(func(w application.Window) { - w.Fullscreen() - }) - }) - stateMenu.Add("UnFullscreen").OnClick(func(ctx *application.Context) { - currentWindow(func(w application.Window) { - w.UnFullscreen() - }) - }) - stateMenu.Add("Restore").OnClick(func(ctx *application.Context) { - currentWindow(func(w application.Window) { - w.Restore() - }) - }) - stateMenu.Add("Hide (for 2 seconds)").OnClick(func(ctx *application.Context) { - currentWindow(func(w application.Window) { - w.Hide() - time.Sleep(2 * time.Second) - w.Show() - }) - }) - stateMenu.Add("Always on Top").OnClick(func(ctx *application.Context) { - currentWindow(func(w application.Window) { - w.SetAlwaysOnTop(true) - }) - }) - stateMenu.Add("Not always on Top").OnClick(func(ctx *application.Context) { - currentWindow(func(w application.Window) { - w.SetAlwaysOnTop(false) - }) - }) - stateMenu.Add("Google.com").OnClick(func(ctx *application.Context) { - currentWindow(func(w application.Window) { - w.SetURL("https://google.com") - }) - }) - stateMenu.Add("wails.io").OnClick(func(ctx *application.Context) { - currentWindow(func(w application.Window) { - w.SetURL("https://wails.io") - }) - }) - stateMenu.Add("Get Primary Screen").OnClick(func(ctx *application.Context) { - screen := app.Screen.GetPrimary() - msg := fmt.Sprintf("Screen: %+v", screen) - app.Dialog.Info().SetTitle("Primary Screen").SetMessage(msg).Show() - }) - stateMenu.Add("Get Screens").OnClick(func(ctx *application.Context) { - screens := app.Screen.GetAll() - for _, screen := range screens { - msg := fmt.Sprintf("Screen: %+v", screen) - app.Dialog.Info().SetTitle(fmt.Sprintf("Screen %s", screen.ID)).SetMessage(msg).Show() - } - }) - stateMenu.Add("Get Screen for WebviewWindow").OnClick(func(ctx *application.Context) { - currentWindow(func(w application.Window) { - screen, err := w.GetScreen() - if err != nil { - app.Dialog.Error().SetTitle("Error").SetMessage(err.Error()).Show() - return - } - msg := fmt.Sprintf("Screen: %+v", screen) - app.Dialog.Info().SetTitle(fmt.Sprintf("Screen %s", screen.ID)).SetMessage(msg).Show() - }) - }) - app.Window.New() - - app.Menu.Set(menu) - err := app.Run() - - if err != nil { - log.Fatal(err) - } - -} diff --git a/v3/examples/cancel-async/README.md b/v3/examples/cancel-async/README.md deleted file mode 100644 index feec0e5d6..000000000 --- a/v3/examples/cancel-async/README.md +++ /dev/null @@ -1,5 +0,0 @@ -# Binding Call Cancelling Example - -This example demonstrates how to cancel binding calls in async/await style. - -To regenerate bindings, run `wails3 generate bindings -clean -b -d assets/bindings` in this directory. diff --git a/v3/examples/cancel-async/assets/bindings/github.com/wailsapp/wails/v3/examples/cancel-async/index.js b/v3/examples/cancel-async/assets/bindings/github.com/wailsapp/wails/v3/examples/cancel-async/index.js deleted file mode 100644 index d2bf43c94..000000000 --- a/v3/examples/cancel-async/assets/bindings/github.com/wailsapp/wails/v3/examples/cancel-async/index.js +++ /dev/null @@ -1,8 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as Service from "./service.js"; -export { - Service -}; diff --git a/v3/examples/cancel-async/assets/bindings/github.com/wailsapp/wails/v3/examples/cancel-async/service.js b/v3/examples/cancel-async/assets/bindings/github.com/wailsapp/wails/v3/examples/cancel-async/service.js deleted file mode 100644 index 6aae91e1d..000000000 --- a/v3/examples/cancel-async/assets/bindings/github.com/wailsapp/wails/v3/examples/cancel-async/service.js +++ /dev/null @@ -1,16 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import {Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create} from "/wails/runtime.js"; - -/** - * A long running operation of specified duration. - * @param {number} milliseconds - * @returns {$CancellablePromise} - */ -export function LongRunning(milliseconds) { - return $Call.ByID(298191698, milliseconds); -} diff --git a/v3/examples/cancel-async/assets/index.html b/v3/examples/cancel-async/assets/index.html deleted file mode 100644 index ff0609928..000000000 --- a/v3/examples/cancel-async/assets/index.html +++ /dev/null @@ -1,134 +0,0 @@ - - - - - Wails Alpha - - - - -
      Alpha
      -
      -

      Documentation

      -

      Feedback

      -
      -
      Please enter a duration in milliseconds below 👇
      -
      - - - - -
      - - - diff --git a/v3/examples/cancel-async/main.go b/v3/examples/cancel-async/main.go deleted file mode 100644 index 9fb52481b..000000000 --- a/v3/examples/cancel-async/main.go +++ /dev/null @@ -1,37 +0,0 @@ -package main - -import ( - "embed" - "log" - - "github.com/wailsapp/wails/v3/pkg/application" -) - -//go:embed assets/* -var assets embed.FS - -func main() { - app := application.New(application.Options{ - Services: []application.Service{ - application.NewService(&Service{}), - }, - Assets: application.AssetOptions{ - Handler: application.BundledAssetFileServer(assets), - }, - Mac: application.MacOptions{ - ApplicationShouldTerminateAfterLastWindowClosed: true, - }, - }) - - app.Window.NewWithOptions(application.WebviewWindowOptions{ - URL: "/", - DevToolsEnabled: true, - }) - - err := app.Run() - - if err != nil { - log.Fatal(err) - } - -} diff --git a/v3/examples/cancel-async/service.go b/v3/examples/cancel-async/service.go deleted file mode 100644 index b2cc72e9b..000000000 --- a/v3/examples/cancel-async/service.go +++ /dev/null @@ -1,19 +0,0 @@ -package main - -import ( - "context" - "time" -) - -type Service struct { -} - -// A long running operation of specified duration. -func (*Service) LongRunning(ctx context.Context, milliseconds int) error { - select { - case <-time.After(time.Duration(milliseconds) * time.Millisecond): - return nil - case <-ctx.Done(): - return ctx.Err() - } -} diff --git a/v3/examples/cancel-chaining/README.md b/v3/examples/cancel-chaining/README.md deleted file mode 100644 index 10c5855ea..000000000 --- a/v3/examples/cancel-chaining/README.md +++ /dev/null @@ -1,5 +0,0 @@ -# Binding Call Cancelling Example - -This example demonstrates how to cancel binding calls in promise chaining style. - -To regenerate bindings, run `wails3 generate bindings -clean -b -d assets/bindings` in this directory. diff --git a/v3/examples/cancel-chaining/assets/bindings/github.com/wailsapp/wails/v3/examples/cancel-chaining/index.js b/v3/examples/cancel-chaining/assets/bindings/github.com/wailsapp/wails/v3/examples/cancel-chaining/index.js deleted file mode 100644 index d2bf43c94..000000000 --- a/v3/examples/cancel-chaining/assets/bindings/github.com/wailsapp/wails/v3/examples/cancel-chaining/index.js +++ /dev/null @@ -1,8 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as Service from "./service.js"; -export { - Service -}; diff --git a/v3/examples/cancel-chaining/assets/bindings/github.com/wailsapp/wails/v3/examples/cancel-chaining/service.js b/v3/examples/cancel-chaining/assets/bindings/github.com/wailsapp/wails/v3/examples/cancel-chaining/service.js deleted file mode 100644 index 6aae91e1d..000000000 --- a/v3/examples/cancel-chaining/assets/bindings/github.com/wailsapp/wails/v3/examples/cancel-chaining/service.js +++ /dev/null @@ -1,16 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import {Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create} from "/wails/runtime.js"; - -/** - * A long running operation of specified duration. - * @param {number} milliseconds - * @returns {$CancellablePromise} - */ -export function LongRunning(milliseconds) { - return $Call.ByID(298191698, milliseconds); -} diff --git a/v3/examples/cancel-chaining/assets/index.html b/v3/examples/cancel-chaining/assets/index.html deleted file mode 100644 index 71221c28d..000000000 --- a/v3/examples/cancel-chaining/assets/index.html +++ /dev/null @@ -1,136 +0,0 @@ - - - - - Wails Alpha - - - - -
      Alpha
      -
      -

      Documentation

      -

      Feedback

      -
      -
      Please enter a duration in milliseconds below 👇
      -
      - - - - -
      - - - diff --git a/v3/examples/cancel-chaining/main.go b/v3/examples/cancel-chaining/main.go deleted file mode 100644 index 9fb52481b..000000000 --- a/v3/examples/cancel-chaining/main.go +++ /dev/null @@ -1,37 +0,0 @@ -package main - -import ( - "embed" - "log" - - "github.com/wailsapp/wails/v3/pkg/application" -) - -//go:embed assets/* -var assets embed.FS - -func main() { - app := application.New(application.Options{ - Services: []application.Service{ - application.NewService(&Service{}), - }, - Assets: application.AssetOptions{ - Handler: application.BundledAssetFileServer(assets), - }, - Mac: application.MacOptions{ - ApplicationShouldTerminateAfterLastWindowClosed: true, - }, - }) - - app.Window.NewWithOptions(application.WebviewWindowOptions{ - URL: "/", - DevToolsEnabled: true, - }) - - err := app.Run() - - if err != nil { - log.Fatal(err) - } - -} diff --git a/v3/examples/cancel-chaining/service.go b/v3/examples/cancel-chaining/service.go deleted file mode 100644 index b2cc72e9b..000000000 --- a/v3/examples/cancel-chaining/service.go +++ /dev/null @@ -1,19 +0,0 @@ -package main - -import ( - "context" - "time" -) - -type Service struct { -} - -// A long running operation of specified duration. -func (*Service) LongRunning(ctx context.Context, milliseconds int) error { - select { - case <-time.After(time.Duration(milliseconds) * time.Millisecond): - return nil - case <-ctx.Done(): - return ctx.Err() - } -} diff --git a/v3/examples/clipboard/README.md b/v3/examples/clipboard/README.md deleted file mode 100644 index b3128b531..000000000 --- a/v3/examples/clipboard/README.md +++ /dev/null @@ -1,11 +0,0 @@ -# clipboard - -This example demonstrates how to use the clipboard API. - -# Status - -| Platform | Status | -|----------|---------| -| Mac | Working | -| Windows | Working | -| Linux | | \ No newline at end of file diff --git a/v3/examples/clipboard/main.go b/v3/examples/clipboard/main.go deleted file mode 100644 index 0c97693aa..000000000 --- a/v3/examples/clipboard/main.go +++ /dev/null @@ -1,77 +0,0 @@ -package main - -import ( - _ "embed" - "log" - "runtime" - "time" - - "github.com/wailsapp/wails/v3/pkg/application" -) - -func main() { - - app := application.New(application.Options{ - Name: "Clipboard Demo", - Description: "A demo of the clipboard API", - Assets: application.AlphaAssets, - Mac: application.MacOptions{ - ApplicationShouldTerminateAfterLastWindowClosed: true, - }, - }) - - // Create a custom menu - menu := app.NewMenu() - if runtime.GOOS == "darwin" { - menu.AddRole(application.AppMenu) - } - - setClipboardMenu := menu.AddSubmenu("Set Clipboard") - setClipboardMenu.Add("Set Text 'Hello'").OnClick(func(ctx *application.Context) { - success := app.Clipboard.SetText("Hello") - if !success { - app.Dialog.Info().SetMessage("Failed to set clipboard text").Show() - } - }) - setClipboardMenu.Add("Set Text 'World'").OnClick(func(ctx *application.Context) { - success := app.Clipboard.SetText("World") - if !success { - app.Dialog.Info().SetMessage("Failed to set clipboard text").Show() - } - }) - setClipboardMenu.Add("Set Text (current time)").OnClick(func(ctx *application.Context) { - success := app.Clipboard.SetText(time.Now().String()) - if !success { - app.Dialog.Info().SetMessage("Failed to set clipboard text").Show() - } - }) - getClipboardMenu := menu.AddSubmenu("Get Clipboard") - getClipboardMenu.Add("Get Text").OnClick(func(ctx *application.Context) { - result, ok := app.Clipboard.Text() - if !ok { - app.Dialog.Info().SetMessage("Failed to get clipboard text").Show() - } else { - app.Dialog.Info().SetMessage("Got:\n\n" + result).Show() - } - }) - - clearClipboardMenu := menu.AddSubmenu("Clear Clipboard") - clearClipboardMenu.Add("Clear Text").OnClick(func(ctx *application.Context) { - success := app.Clipboard.SetText("") - if success { - app.Dialog.Info().SetMessage("Clipboard text cleared").Show() - } else { - app.Dialog.Info().SetMessage("Clipboard text not cleared").Show() - } - }) - - app.Menu.Set(menu) - - app.Window.New() - - err := app.Run() - - if err != nil { - log.Fatal(err.Error()) - } -} diff --git a/v3/examples/contextmenus/README.md b/v3/examples/contextmenus/README.md deleted file mode 100644 index ba6d498e7..000000000 --- a/v3/examples/contextmenus/README.md +++ /dev/null @@ -1,30 +0,0 @@ -# contextmenus - -This example shows how to create a context menu for your application. -It demonstrates window level and global context menus. - -A simple menu is registered with the window and the application with the id "test". -In our frontend html, we then use the `--custom-contextmenu` style to attach the menu to an element. -We also use the `--custom-contextmenu-data` style to pass data to the menu callback which can be read in Go. -This is really useful when using components to distinguish between different elements. - -```go - -```html - -
      -

      1

      -
      -
      -

      2

      -
      -``` - -# Status - -| Platform | Status | -|----------|---------| -| Mac | Working | -| Windows | Working | -| Linux | | - diff --git a/v3/examples/contextmenus/assets/index.html b/v3/examples/contextmenus/assets/index.html deleted file mode 100644 index 23224084d..000000000 --- a/v3/examples/contextmenus/assets/index.html +++ /dev/null @@ -1,82 +0,0 @@ - - - - - Title - - - - - - -

      Context Menu Demo

      -

      - You need to run this example in production for it to work : -

      go run -tags production .
      - -
      -
      -

      1

      -
      -
      -

      2

      -
      -
      -

      Default Context Menu shown here

      - -
      -
      -

      Default auto (smart) Context Menu here

      - -
      -
      -

      Context menu shown here only if you select text

      -

      Selecting text here and right-clicking the box below or its border shouldn't show the context menu

      -
      -
      -
      -
      -
      -
      - - - - -

      content editable

      -
      -
      -
      -

      Default Context Menu hidden here

      -

      Context Menu hidden here even if text is selected

      - -
      -
      -

      Nested section reverted to auto (smart) default Context Menu

      -

      Context menu shown here only if you select text

      -
      -
      -
      - - diff --git a/v3/examples/contextmenus/main.go b/v3/examples/contextmenus/main.go deleted file mode 100644 index 70cdf5c7e..000000000 --- a/v3/examples/contextmenus/main.go +++ /dev/null @@ -1,55 +0,0 @@ -package main - -import ( - "embed" - _ "embed" - "log" - - "github.com/wailsapp/wails/v3/pkg/application" -) - -//go:embed assets -var assets embed.FS - -func main() { - - app := application.New(application.Options{ - Name: "Context Menu Demo", - Description: "A demo of the Context Menu API", - Assets: application.AssetOptions{ - Handler: application.BundledAssetFileServer(assets), - }, - Mac: application.MacOptions{ - ApplicationShouldTerminateAfterLastWindowClosed: true, - }, - }) - - app.Window.NewWithOptions(application.WebviewWindowOptions{ - Title: "Context Menu Demo", - Width: 1024, - Height: 1024, - Mac: application.MacWindow{ - Backdrop: application.MacBackdropTranslucent, - TitleBar: application.MacTitleBarHiddenInsetUnified, - InvisibleTitleBarHeight: 50, - }, - }) - - contextMenu := app.ContextMenu.New() - clickMe := contextMenu.Add("Click to set Menuitem label to Context Data") - contextDataMenuItem := contextMenu.Add("Current context data: No Context Data") - clickMe.OnClick(func(data *application.Context) { - app.Logger.Info("Context menu", "context data", data.ContextMenuData()) - contextDataMenuItem.SetLabel("Current context data: " + data.ContextMenuData()) - contextMenu.Update() - }) - - // Register the context menu - app.ContextMenu.Add("test", contextMenu) - - err := app.Run() - - if err != nil { - log.Fatal(err.Error()) - } -} diff --git a/v3/examples/custom-protocol-example/.gitignore b/v3/examples/custom-protocol-example/.gitignore deleted file mode 100644 index ba8194ab6..000000000 --- a/v3/examples/custom-protocol-example/.gitignore +++ /dev/null @@ -1,6 +0,0 @@ -.task -bin -frontend/dist -frontend/node_modules -build/linux/appimage/build -build/windows/nsis/MicrosoftEdgeWebview2Setup.exe \ No newline at end of file diff --git a/v3/examples/custom-protocol-example/README.md b/v3/examples/custom-protocol-example/README.md deleted file mode 100644 index ad12c3f40..000000000 --- a/v3/examples/custom-protocol-example/README.md +++ /dev/null @@ -1,59 +0,0 @@ -# Welcome to Your New Wails3 Project! - -Congratulations on generating your Wails3 application! This README will guide you through the next steps to get your project up and running. - -## Getting Started - -1. Navigate to your project directory in the terminal. - -2. To run your application in development mode, use the following command: - - ``` - wails3 dev - ``` - - This will start your application and enable hot-reloading for both frontend and backend changes. - -3. To build your application for production, use: - - ``` - wails3 build - ``` - - This will create a production-ready executable in the `build` directory. - -## Exploring Wails3 Features - -Now that you have your project set up, it's time to explore the features that Wails3 offers: - -1. **Check out the examples**: The best way to learn is by example. Visit the `examples` directory in the `v3/examples` directory to see various sample applications. - -2. **Run an example**: To run any of the examples, navigate to the example's directory and use: - - ``` - go run . - ``` - - Note: Some examples may be under development during the alpha phase. - -3. **Explore the documentation**: Visit the [Wails3 documentation](https://v3.wails.io/) for in-depth guides and API references. - -4. **Join the community**: Have questions or want to share your progress? Join the [Wails Discord](https://discord.gg/JDdSxwjhGf) or visit the [Wails discussions on GitHub](https://github.com/wailsapp/wails/discussions). - -## Project Structure - -Take a moment to familiarize yourself with your project structure: - -- `frontend/`: Contains your frontend code (HTML, CSS, JavaScript/TypeScript) -- `main.go`: The entry point of your Go backend -- `app.go`: Define your application structure and methods here -- `wails.json`: Configuration file for your Wails project - -## Next Steps - -1. Modify the frontend in the `frontend/` directory to create your desired UI. -2. Add backend functionality in `main.go`. -3. Use `wails3 dev` to see your changes in real-time. -4. When ready, build your application with `wails3 build`. - -Happy coding with Wails3! If you encounter any issues or have questions, don't hesitate to consult the documentation or reach out to the Wails community. diff --git a/v3/examples/custom-protocol-example/Taskfile.yml b/v3/examples/custom-protocol-example/Taskfile.yml deleted file mode 100644 index 572db59ac..000000000 --- a/v3/examples/custom-protocol-example/Taskfile.yml +++ /dev/null @@ -1,33 +0,0 @@ -version: '3' - -includes: - common: ./build/Taskfile.yml - windows: ./build/windows/Taskfile.yml - darwin: ./build/darwin/Taskfile.yml - linux: ./build/linux/Taskfile.yml - -vars: - APP_NAME: "custom-protocol-example" - BIN_DIR: "bin" - -tasks: - build: - summary: Builds the application - cmds: - - task: "{{OS}}:build" - - package: - summary: Packages a production build of the application - cmds: - - task: "{{OS}}:package" - - run: - summary: Runs the application - cmds: - - task: "{{OS}}:run" - - dev: - summary: Runs the application in development mode - cmds: - - wails3 dev -config ./build/config.yml - diff --git a/v3/examples/custom-protocol-example/build/Taskfile.yml b/v3/examples/custom-protocol-example/build/Taskfile.yml deleted file mode 100644 index ba497b5b6..000000000 --- a/v3/examples/custom-protocol-example/build/Taskfile.yml +++ /dev/null @@ -1,85 +0,0 @@ -version: '3' - -tasks: - go:mod:tidy: - summary: Runs `go mod tidy` - internal: true - cmds: - - go mod tidy - - install:frontend:deps: - summary: Install frontend dependencies - dir: frontend - sources: - - package.json - - package-lock.json - generates: - - node_modules/* - preconditions: - - sh: npm version - cmds: - - echo "Skipping frontend dependencies installation" - - build:frontend: - label: build:frontend (PRODUCTION={{.PRODUCTION}}) - summary: Build the frontend project - dir: frontend - sources: - - "**/*" - generates: - - dist/**/* - deps: - - task: install:frontend:deps - - task: generate:bindings - vars: - BUILD_FLAGS: - ref: .BUILD_FLAGS - cmds: - - npm run {{.BUILD_COMMAND}} -q - env: - PRODUCTION: '{{.PRODUCTION | default "false"}}' - vars: - BUILD_COMMAND: '{{if eq .PRODUCTION "true"}}build{{else}}build{{end}}' - - - generate:bindings: - label: generate:bindings (BUILD_FLAGS={{.BUILD_FLAGS}}) - summary: Generates bindings for the frontend - deps: - - task: go:mod:tidy - sources: - - "**/*.[jt]s" - - exclude: frontend/**/* - - frontend/bindings/**/* # Rerun when switching between dev/production mode causes changes in output - - "**/*.go" - - go.mod - - go.sum - generates: - - frontend/bindings/**/* - cmds: - - wails3 generate bindings -f '{{.BUILD_FLAGS}}' -clean=true - - generate:icons: - summary: Generates Windows `.ico` and Mac `.icns` files from an image - dir: build - sources: - - "appicon.png" - generates: - - "darwin/icons.icns" - - "windows/icon.ico" - cmds: - - wails3 generate icons -input appicon.png -macfilename darwin/icons.icns -windowsfilename windows/icon.ico - - dev:frontend: - summary: Runs the frontend in development mode - dir: frontend - deps: - - task: install:frontend:deps - cmds: - - echo "Skipping frontend development mode" - - update:build-assets: - summary: Updates the build assets - dir: build - cmds: - - wails3 update build-assets -name "{{.APP_NAME}}" -binaryname "{{.APP_NAME}}" -config config.yml -dir . diff --git a/v3/examples/custom-protocol-example/build/appicon.png b/v3/examples/custom-protocol-example/build/appicon.png deleted file mode 100644 index 63617fe4f..000000000 Binary files a/v3/examples/custom-protocol-example/build/appicon.png and /dev/null differ diff --git a/v3/examples/custom-protocol-example/build/config.yml b/v3/examples/custom-protocol-example/build/config.yml deleted file mode 100644 index 8f2cb0348..000000000 --- a/v3/examples/custom-protocol-example/build/config.yml +++ /dev/null @@ -1,67 +0,0 @@ -# This file contains the configuration for this project. -# When you update `info` or `fileAssociations`, run `wails3 task common:update:build-assets` to update the assets. -# Note that this will overwrite any changes you have made to the assets. -version: '3' - -# This information is used to generate the build assets. -info: - companyName: "My Company" # The name of the company - productName: "My Product" # The name of the application - productIdentifier: "com.mycompany.myproduct" # The unique product identifier - description: "A program that does X" # The application description - copyright: "(c) 2025, My Company" # Copyright text - comments: "Some Product Comments" # Comments - version: "0.0.1" # The application version - -# Dev mode configuration -dev_mode: - root_path: . - log_level: warn - debounce: 1000 - ignore: - dir: - - .git - - node_modules - - frontend - - bin - file: - - .DS_Store - - .gitignore - - .gitkeep - watched_extension: - - "*.go" - git_ignore: true - executes: - - cmd: wails3 task common:install:frontend:deps - type: once - - cmd: wails3 task common:dev:frontend - type: background - - cmd: go mod tidy - type: blocking - - cmd: wails3 task build - type: blocking - - cmd: wails3 task run - type: primary - -# File Associations -# More information at: https://v3.wails.io/noit/done/yet -fileAssociations: -# - ext: wails -# name: Wails -# description: Wails Application File -# iconName: wailsFileIcon -# role: Editor -# - ext: jpg -# name: JPEG -# description: Image File -# iconName: jpegFileIcon -# role: Editor -# mimeType: image/jpeg # (optional) - -protocols: - - scheme: wailsexample - description: Wails Example Application Custom Protocol - -# Other data -other: - - name: My Other Data \ No newline at end of file diff --git a/v3/examples/custom-protocol-example/build/darwin/Info.dev.plist b/v3/examples/custom-protocol-example/build/darwin/Info.dev.plist deleted file mode 100644 index a46aa82d9..000000000 --- a/v3/examples/custom-protocol-example/build/darwin/Info.dev.plist +++ /dev/null @@ -1,43 +0,0 @@ - - - - CFBundlePackageType - APPL - CFBundleName - My Product - CFBundleExecutable - custom-protocol-example - CFBundleIdentifier - com.mycompany.myproduct - CFBundleVersion - 0.0.1 - CFBundleGetInfoString - Some Product Comments - CFBundleShortVersionString - 0.0.1 - CFBundleIconFile - icons - LSMinimumSystemVersion - 10.15.0 - NSHighResolutionCapable - true - NSHumanReadableCopyright - (c) 2025, My Company - NSAppTransportSecurity - - NSAllowsLocalNetworking - - - CFBundleURLTypes - - - CFBundleURLName - wails.com.wailsexample - CFBundleURLSchemes - - wailsexample - - - - - \ No newline at end of file diff --git a/v3/examples/custom-protocol-example/build/darwin/Info.plist b/v3/examples/custom-protocol-example/build/darwin/Info.plist deleted file mode 100644 index d88fd1030..000000000 --- a/v3/examples/custom-protocol-example/build/darwin/Info.plist +++ /dev/null @@ -1,38 +0,0 @@ - - - - CFBundlePackageType - APPL - CFBundleName - My Product - CFBundleExecutable - custom-protocol-example - CFBundleIdentifier - com.mycompany.myproduct - CFBundleVersion - 0.0.1 - CFBundleGetInfoString - Some Product Comments - CFBundleShortVersionString - 0.0.1 - CFBundleIconFile - icons - LSMinimumSystemVersion - 10.15.0 - NSHighResolutionCapable - true - NSHumanReadableCopyright - (c) 2025, My Company - CFBundleURLTypes - - - CFBundleURLName - wails.com.wailsexample - CFBundleURLSchemes - - wailsexample - - - - - \ No newline at end of file diff --git a/v3/examples/custom-protocol-example/build/darwin/Taskfile.yml b/v3/examples/custom-protocol-example/build/darwin/Taskfile.yml deleted file mode 100644 index e456dbad5..000000000 --- a/v3/examples/custom-protocol-example/build/darwin/Taskfile.yml +++ /dev/null @@ -1,76 +0,0 @@ -version: '3' - -includes: - common: ../Taskfile.yml - -tasks: - build: - summary: Creates a production build of the application - deps: - - task: common:go:mod:tidy - - task: common:generate:icons - - task: common:build:frontend - cmds: - - go build {{.BUILD_FLAGS}} -o {{.OUTPUT}} - vars: - BUILD_FLAGS: '{{if eq .PRODUCTION "true"}}-tags production -trimpath -buildvcs=false -ldflags="-w -s"{{else}}-buildvcs=false -gcflags=all="-l"{{end}}' - DEFAULT_OUTPUT: '{{.BIN_DIR}}/{{.APP_NAME}}' - OUTPUT: '{{ .OUTPUT | default .DEFAULT_OUTPUT }}' - env: - GOOS: darwin - CGO_ENABLED: 1 - GOARCH: '{{.ARCH | default ARCH}}' - CGO_CFLAGS: "-mmacosx-version-min=10.15" - CGO_LDFLAGS: "-mmacosx-version-min=10.15" - MACOSX_DEPLOYMENT_TARGET: "10.15" - PRODUCTION: '{{.PRODUCTION | default "false"}}' - - build:universal: - summary: Builds darwin universal binary (arm64 + amd64) - deps: - - task: build - vars: - ARCH: amd64 - OUTPUT: "{{.BIN_DIR}}/{{.APP_NAME}}-amd64" - - task: build - vars: - ARCH: arm64 - OUTPUT: "{{.BIN_DIR}}/{{.APP_NAME}}-arm64" - cmds: - - lipo -create -output "{{.BIN_DIR}}/{{.APP_NAME}}" "{{.BIN_DIR}}/{{.APP_NAME}}-amd64" "{{.BIN_DIR}}/{{.APP_NAME}}-arm64" - - rm "{{.BIN_DIR}}/{{.APP_NAME}}-amd64" "{{.BIN_DIR}}/{{.APP_NAME}}-arm64" - - package: - summary: Packages a production build of the application into a `.app` bundle - deps: - - task: build - vars: - PRODUCTION: "false" - cmds: - - task: create:app:bundle - - package:universal: - summary: Packages darwin universal binary (arm64 + amd64) - deps: - - task: build:universal - cmds: - - task: create:app:bundle - - - create:app:bundle: - summary: Creates an `.app` bundle - cmds: - - mkdir -p {{.BIN_DIR}}/{{.APP_NAME}}.app/Contents/{MacOS,Resources} - - cp build/darwin/icons.icns {{.BIN_DIR}}/{{.APP_NAME}}.app/Contents/Resources - - cp {{.BIN_DIR}}/{{.APP_NAME}} {{.BIN_DIR}}/{{.APP_NAME}}.app/Contents/MacOS - - cp build/darwin/Info.plist {{.BIN_DIR}}/{{.APP_NAME}}.app/Contents - - codesign --force --deep --sign - {{.BIN_DIR}}/{{.APP_NAME}}.app - - run: - cmds: - - mkdir -p {{.BIN_DIR}}/{{.APP_NAME}}.dev.app/Contents/{MacOS,Resources} - - cp build/darwin/icons.icns {{.BIN_DIR}}/{{.APP_NAME}}.dev.app/Contents/Resources - - cp {{.BIN_DIR}}/{{.APP_NAME}} {{.BIN_DIR}}/{{.APP_NAME}}.dev.app/Contents/MacOS - - cp build/darwin/Info.dev.plist {{.BIN_DIR}}/{{.APP_NAME}}.dev.app/Contents/Info.plist - - codesign --force --deep --sign - {{.BIN_DIR}}/{{.APP_NAME}}.dev.app - - '{{.BIN_DIR}}/{{.APP_NAME}}.dev.app/Contents/MacOS/{{.APP_NAME}}' diff --git a/v3/examples/custom-protocol-example/build/darwin/icons.icns b/v3/examples/custom-protocol-example/build/darwin/icons.icns deleted file mode 100644 index 1b5bd4c86..000000000 Binary files a/v3/examples/custom-protocol-example/build/darwin/icons.icns and /dev/null differ diff --git a/v3/examples/custom-protocol-example/build/linux/Taskfile.yml b/v3/examples/custom-protocol-example/build/linux/Taskfile.yml deleted file mode 100644 index a6115574a..000000000 --- a/v3/examples/custom-protocol-example/build/linux/Taskfile.yml +++ /dev/null @@ -1,113 +0,0 @@ -version: '3' - -includes: - common: ../Taskfile.yml - -tasks: - build: - summary: Builds the application for Linux - deps: - - task: common:go:mod:tidy - - task: common:generate:icons - cmds: - - go build {{.BUILD_FLAGS}} -o {{.BIN_DIR}}/{{.APP_NAME}} - vars: - BUILD_FLAGS: '{{if eq .PRODUCTION "true"}}-tags production -trimpath -buildvcs=false -ldflags="-w -s"{{else}}-buildvcs=false -gcflags=all="-l"{{end}}' - env: - GOOS: linux - CGO_ENABLED: 1 - GOARCH: '{{.ARCH | default ARCH}}' - PRODUCTION: '{{.PRODUCTION | default "false"}}' - - package: - summary: Packages a production build of the application for Linux - deps: - - task: build - vars: - PRODUCTION: "true" - cmds: - - task: create:appimage - - task: create:deb - - task: create:rpm - - task: create:aur - - create:appimage: - summary: Creates an AppImage - dir: build/linux/appimage - deps: - - task: build - vars: - PRODUCTION: "true" - - task: generate:dotdesktop - cmds: - - cp {{.APP_BINARY}} {{.APP_NAME}} - - cp ../../appicon.png appicon.png - - wails3 generate appimage -binary {{.APP_NAME}} -icon {{.ICON}} -desktopfile {{.DESKTOP_FILE}} -outputdir {{.OUTPUT_DIR}} -builddir {{.ROOT_DIR}}/build/linux/appimage/build - vars: - APP_NAME: '{{.APP_NAME}}' - APP_BINARY: '../../../bin/{{.APP_NAME}}' - ICON: '../../appicon.png' - DESKTOP_FILE: '../{{.APP_NAME}}.desktop' - OUTPUT_DIR: '../../../bin' - - create:deb: - summary: Creates a deb package - deps: - - task: build - vars: - PRODUCTION: "true" - cmds: - - task: generate:dotdesktop - - task: generate:deb - - create:rpm: - summary: Creates a rpm package - deps: - - task: build - vars: - PRODUCTION: "true" - cmds: - - task: generate:dotdesktop - - task: generate:rpm - - create:aur: - summary: Creates a arch linux packager package - deps: - - task: build - vars: - PRODUCTION: "true" - cmds: - - task: generate:dotdesktop - - task: generate:aur - - generate:deb: - summary: Creates a deb package - cmds: - - wails3 tool package -name {{.APP_NAME}} -format deb -config ./build/linux/nfpm/nfpm.yaml -out {{.ROOT_DIR}}/bin - - generate:rpm: - summary: Creates a rpm package - cmds: - - wails3 tool package -name {{.APP_NAME}} -format rpm -config ./build/linux/nfpm/nfpm.yaml -out {{.ROOT_DIR}}/bin - - generate:aur: - summary: Creates a arch linux packager package - cmds: - - wails3 tool package -name {{.APP_NAME}} -format archlinux -config ./build/linux/nfpm/nfpm.yaml -out {{.ROOT_DIR}}/bin - - generate:dotdesktop: - summary: Generates a `.desktop` file - dir: build - cmds: - - mkdir -p {{.ROOT_DIR}}/build/linux/appimage - - wails3 generate .desktop -name "{{.APP_NAME}}" -exec "{{.EXEC}}" -icon "{{.ICON}}" -outputfile {{.ROOT_DIR}}/build/linux/{{.APP_NAME}}.desktop -categories "{{.CATEGORIES}}" - vars: - APP_NAME: '{{.APP_NAME}}' - EXEC: '{{.APP_NAME}}' - ICON: 'appicon' - CATEGORIES: 'Development;' - OUTPUTFILE: '{{.ROOT_DIR}}/build/linux/{{.APP_NAME}}.desktop' - - run: - cmds: - - '{{.BIN_DIR}}/{{.APP_NAME}}' diff --git a/v3/examples/custom-protocol-example/build/linux/appimage/build.sh b/v3/examples/custom-protocol-example/build/linux/appimage/build.sh deleted file mode 100644 index 85901c34e..000000000 --- a/v3/examples/custom-protocol-example/build/linux/appimage/build.sh +++ /dev/null @@ -1,35 +0,0 @@ -#!/usr/bin/env bash -# Copyright (c) 2018-Present Lea Anthony -# SPDX-License-Identifier: MIT - -# Fail script on any error -set -euxo pipefail - -# Define variables -APP_DIR="${APP_NAME}.AppDir" - -# Create AppDir structure -mkdir -p "${APP_DIR}/usr/bin" -cp -r "${APP_BINARY}" "${APP_DIR}/usr/bin/" -cp "${ICON_PATH}" "${APP_DIR}/" -cp "${DESKTOP_FILE}" "${APP_DIR}/" - -if [[ $(uname -m) == *x86_64* ]]; then - # Download linuxdeploy and make it executable - wget -q -4 -N https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-x86_64.AppImage - chmod +x linuxdeploy-x86_64.AppImage - - # Run linuxdeploy to bundle the application - ./linuxdeploy-x86_64.AppImage --appdir "${APP_DIR}" --output appimage -else - # Download linuxdeploy and make it executable (arm64) - wget -q -4 -N https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-aarch64.AppImage - chmod +x linuxdeploy-aarch64.AppImage - - # Run linuxdeploy to bundle the application (arm64) - ./linuxdeploy-aarch64.AppImage --appdir "${APP_DIR}" --output appimage -fi - -# Rename the generated AppImage -mv "${APP_NAME}*.AppImage" "${APP_NAME}.AppImage" - diff --git a/v3/examples/custom-protocol-example/build/linux/nfpm/nfpm.yaml b/v3/examples/custom-protocol-example/build/linux/nfpm/nfpm.yaml deleted file mode 100644 index 7356f2992..000000000 --- a/v3/examples/custom-protocol-example/build/linux/nfpm/nfpm.yaml +++ /dev/null @@ -1,50 +0,0 @@ -# Feel free to remove those if you don't want/need to use them. -# Make sure to check the documentation at https://nfpm.goreleaser.com -# -# The lines below are called `modelines`. See `:help modeline` - -name: "custom-protocol-example" -arch: ${GOARCH} -platform: "linux" -version: "0.0.1" -section: "default" -priority: "extra" -maintainer: ${GIT_COMMITTER_NAME} <${GIT_COMMITTER_EMAIL}> -description: "A program that does X" -vendor: "My Company" -homepage: "https://wails.io" -license: "MIT" -release: "1" - -contents: - - src: "./bin/custom-protocol-example" - dst: "/usr/local/bin/custom-protocol-example" - - src: "./build/appicon.png" - dst: "/usr/share/icons/hicolor/128x128/apps/custom-protocol-example.png" - - src: "./build/linux/custom-protocol-example.desktop" - dst: "/usr/share/applications/custom-protocol-example.desktop" - -depends: - - gtk3 - - libwebkit2gtk - -# replaces: -# - foobar -# provides: -# - bar -# depends: -# - gtk3 -# - libwebkit2gtk -# recommends: -# - whatever -# suggests: -# - something-else -# conflicts: -# - not-foo -# - not-bar -# changelog: "changelog.yaml" -# scripts: -# preinstall: ./build/linux/nfpm/scripts/preinstall.sh -# postinstall: ./build/linux/nfpm/scripts/postinstall.sh -# preremove: ./build/linux/nfpm/scripts/preremove.sh -# postremove: ./build/linux/nfpm/scripts/postremove.sh diff --git a/v3/examples/custom-protocol-example/build/linux/nfpm/scripts/postinstall.sh b/v3/examples/custom-protocol-example/build/linux/nfpm/scripts/postinstall.sh deleted file mode 100644 index a9bf588e2..000000000 --- a/v3/examples/custom-protocol-example/build/linux/nfpm/scripts/postinstall.sh +++ /dev/null @@ -1 +0,0 @@ -#!/bin/bash diff --git a/v3/examples/custom-protocol-example/build/linux/nfpm/scripts/postremove.sh b/v3/examples/custom-protocol-example/build/linux/nfpm/scripts/postremove.sh deleted file mode 100644 index a9bf588e2..000000000 --- a/v3/examples/custom-protocol-example/build/linux/nfpm/scripts/postremove.sh +++ /dev/null @@ -1 +0,0 @@ -#!/bin/bash diff --git a/v3/examples/custom-protocol-example/build/linux/nfpm/scripts/preinstall.sh b/v3/examples/custom-protocol-example/build/linux/nfpm/scripts/preinstall.sh deleted file mode 100644 index a9bf588e2..000000000 --- a/v3/examples/custom-protocol-example/build/linux/nfpm/scripts/preinstall.sh +++ /dev/null @@ -1 +0,0 @@ -#!/bin/bash diff --git a/v3/examples/custom-protocol-example/build/linux/nfpm/scripts/preremove.sh b/v3/examples/custom-protocol-example/build/linux/nfpm/scripts/preremove.sh deleted file mode 100644 index a9bf588e2..000000000 --- a/v3/examples/custom-protocol-example/build/linux/nfpm/scripts/preremove.sh +++ /dev/null @@ -1 +0,0 @@ -#!/bin/bash diff --git a/v3/examples/custom-protocol-example/build/windows/Taskfile.yml b/v3/examples/custom-protocol-example/build/windows/Taskfile.yml deleted file mode 100644 index 805c1aa7f..000000000 --- a/v3/examples/custom-protocol-example/build/windows/Taskfile.yml +++ /dev/null @@ -1,57 +0,0 @@ -version: '3' - -includes: - common: ../Taskfile.yml - -tasks: - build: - summary: Builds the application for Windows - deps: - - task: common:go:mod:tidy - - task: common:generate:icons - cmds: - - task: generate:syso - - go build {{.BUILD_FLAGS}} -o {{.BIN_DIR}}/{{.APP_NAME}}.exe - - cmd: powershell Remove-item *.syso - platforms: [windows] - - cmd: rm -f *.syso - platforms: [linux, darwin] - vars: - BUILD_FLAGS: '{{if eq .PRODUCTION "true"}}-tags production -trimpath -buildvcs=false -ldflags="-w -s -H windowsgui"{{else}}-buildvcs=false -gcflags=all="-l"{{end}}' - env: - GOOS: windows - CGO_ENABLED: 0 - GOARCH: '{{.ARCH | default ARCH}}' - PRODUCTION: '{{.PRODUCTION | default "false"}}' - - package: - summary: Packages a production build of the application into a `.exe` bundle - cmds: - - task: create:nsis:installer - - generate:syso: - summary: Generates Windows `.syso` file - dir: build - cmds: - - wails3 generate syso -arch {{.ARCH}} -icon windows/icon.ico -manifest windows/wails.exe.manifest -info windows/info.json -out ../wails_windows_{{.ARCH}}.syso - vars: - ARCH: '{{.ARCH | default ARCH}}' - - create:nsis:installer: - summary: Creates an NSIS installer - dir: build/windows/nsis - deps: - - task: build - vars: - PRODUCTION: "true" - cmds: - # Create the Microsoft WebView2 bootstrapper if it doesn't exist - - wails3 generate webview2bootstrapper -dir "{{.ROOT_DIR}}/build/windows/nsis" - - makensis -DARG_WAILS_{{.ARG_FLAG}}_BINARY="{{.ROOT_DIR}}/{{.BIN_DIR}}/{{.APP_NAME}}.exe" project.nsi - vars: - ARCH: '{{.ARCH | default ARCH}}' - ARG_FLAG: '{{if eq .ARCH "amd64"}}AMD64{{else}}ARM64{{end}}' - - run: - cmds: - - '{{.BIN_DIR}}/{{.APP_NAME}}.exe' diff --git a/v3/examples/custom-protocol-example/build/windows/icon.ico b/v3/examples/custom-protocol-example/build/windows/icon.ico deleted file mode 100644 index bfa0690b7..000000000 Binary files a/v3/examples/custom-protocol-example/build/windows/icon.ico and /dev/null differ diff --git a/v3/examples/custom-protocol-example/build/windows/info.json b/v3/examples/custom-protocol-example/build/windows/info.json deleted file mode 100644 index 71dfd6d99..000000000 --- a/v3/examples/custom-protocol-example/build/windows/info.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "fixed": { - "file_version": "0.0.1" - }, - "info": { - "0000": { - "ProductVersion": "0.0.1", - "CompanyName": "My Company", - "FileDescription": "A program that does X", - "LegalCopyright": "(c) 2025, My Company", - "ProductName": "My Product", - "Comments": "Some Product Comments" - } - } -} \ No newline at end of file diff --git a/v3/examples/custom-protocol-example/build/windows/nsis/project.nsi b/v3/examples/custom-protocol-example/build/windows/nsis/project.nsi deleted file mode 100644 index 5ff2eb085..000000000 --- a/v3/examples/custom-protocol-example/build/windows/nsis/project.nsi +++ /dev/null @@ -1,112 +0,0 @@ -Unicode true - -#### -## Please note: Template replacements don't work in this file. They are provided with default defines like -## mentioned underneath. -## If the keyword is not defined, "wails_tools.nsh" will populate them. -## If they are defined here, "wails_tools.nsh" will not touch them. This allows you to use this project.nsi manually -## from outside of Wails for debugging and development of the installer. -## -## For development first make a wails nsis build to populate the "wails_tools.nsh": -## > wails build --target windows/amd64 --nsis -## Then you can call makensis on this file with specifying the path to your binary: -## For a AMD64 only installer: -## > makensis -DARG_WAILS_AMD64_BINARY=..\..\bin\app.exe -## For a ARM64 only installer: -## > makensis -DARG_WAILS_ARM64_BINARY=..\..\bin\app.exe -## For a installer with both architectures: -## > makensis -DARG_WAILS_AMD64_BINARY=..\..\bin\app-amd64.exe -DARG_WAILS_ARM64_BINARY=..\..\bin\app-arm64.exe -#### -## The following information is taken from the wails_tools.nsh file, but they can be overwritten here. -#### -## !define INFO_PROJECTNAME "my-project" # Default "custom-protocol-example" -## !define INFO_COMPANYNAME "My Company" # Default "My Company" -## !define INFO_PRODUCTNAME "My Product Name" # Default "My Product" -## !define INFO_PRODUCTVERSION "1.0.0" # Default "0.1.0" -## !define INFO_COPYRIGHT "(c) Now, My Company" # Default "© now, My Company" -### -## !define PRODUCT_EXECUTABLE "Application.exe" # Default "${INFO_PROJECTNAME}.exe" -## !define UNINST_KEY_NAME "UninstKeyInRegistry" # Default "${INFO_COMPANYNAME}${INFO_PRODUCTNAME}" -#### -## !define REQUEST_EXECUTION_LEVEL "admin" # Default "admin" see also https://nsis.sourceforge.io/Docs/Chapter4.html -#### -## Include the wails tools -#### -!include "wails_tools.nsh" - -# The version information for this two must consist of 4 parts -VIProductVersion "${INFO_PRODUCTVERSION}.0" -VIFileVersion "${INFO_PRODUCTVERSION}.0" - -VIAddVersionKey "CompanyName" "${INFO_COMPANYNAME}" -VIAddVersionKey "FileDescription" "${INFO_PRODUCTNAME} Installer" -VIAddVersionKey "ProductVersion" "${INFO_PRODUCTVERSION}" -VIAddVersionKey "FileVersion" "${INFO_PRODUCTVERSION}" -VIAddVersionKey "LegalCopyright" "${INFO_COPYRIGHT}" -VIAddVersionKey "ProductName" "${INFO_PRODUCTNAME}" - -# Enable HiDPI support. https://nsis.sourceforge.io/Reference/ManifestDPIAware -ManifestDPIAware true - -!include "MUI.nsh" - -!define MUI_ICON "..\icon.ico" -!define MUI_UNICON "..\icon.ico" -# !define MUI_WELCOMEFINISHPAGE_BITMAP "resources\leftimage.bmp" #Include this to add a bitmap on the left side of the Welcome Page. Must be a size of 164x314 -!define MUI_FINISHPAGE_NOAUTOCLOSE # Wait on the INSTFILES page so the user can take a look into the details of the installation steps -!define MUI_ABORTWARNING # This will warn the user if they exit from the installer. - -!insertmacro MUI_PAGE_WELCOME # Welcome to the installer page. -# !insertmacro MUI_PAGE_LICENSE "resources\eula.txt" # Adds a EULA page to the installer -!insertmacro MUI_PAGE_DIRECTORY # In which folder install page. -!insertmacro MUI_PAGE_INSTFILES # Installing page. -!insertmacro MUI_PAGE_FINISH # Finished installation page. - -!insertmacro MUI_UNPAGE_INSTFILES # Uninstalling page - -!insertmacro MUI_LANGUAGE "English" # Set the Language of the installer - -## The following two statements can be used to sign the installer and the uninstaller. The path to the binaries are provided in %1 -#!uninstfinalize 'signtool --file "%1"' -#!finalize 'signtool --file "%1"' - -Name "${INFO_PRODUCTNAME}" -OutFile "..\..\..\bin\${INFO_PROJECTNAME}-${ARCH}-installer.exe" # Name of the installer's file. -InstallDir "$PROGRAMFILES64\${INFO_COMPANYNAME}\${INFO_PRODUCTNAME}" # Default installing folder ($PROGRAMFILES is Program Files folder). -ShowInstDetails show # This will always show the installation details. - -Function .onInit - !insertmacro wails.checkArchitecture -FunctionEnd - -Section - !insertmacro wails.setShellContext - - !insertmacro wails.webview2runtime - - SetOutPath $INSTDIR - - !insertmacro wails.files - - CreateShortcut "$SMPROGRAMS\${INFO_PRODUCTNAME}.lnk" "$INSTDIR\${PRODUCT_EXECUTABLE}" - CreateShortCut "$DESKTOP\${INFO_PRODUCTNAME}.lnk" "$INSTDIR\${PRODUCT_EXECUTABLE}" - - !insertmacro wails.associateFiles - - !insertmacro wails.writeUninstaller -SectionEnd - -Section "uninstall" - !insertmacro wails.setShellContext - - RMDir /r "$AppData\${PRODUCT_EXECUTABLE}" # Remove the WebView2 DataPath - - RMDir /r $INSTDIR - - Delete "$SMPROGRAMS\${INFO_PRODUCTNAME}.lnk" - Delete "$DESKTOP\${INFO_PRODUCTNAME}.lnk" - - !insertmacro wails.unassociateFiles - - !insertmacro wails.deleteUninstaller -SectionEnd diff --git a/v3/examples/custom-protocol-example/build/windows/nsis/wails_tools.nsh b/v3/examples/custom-protocol-example/build/windows/nsis/wails_tools.nsh deleted file mode 100644 index 607fc4e85..000000000 --- a/v3/examples/custom-protocol-example/build/windows/nsis/wails_tools.nsh +++ /dev/null @@ -1,212 +0,0 @@ -# DO NOT EDIT - Generated automatically by `wails build` - -!include "x64.nsh" -!include "WinVer.nsh" -!include "FileFunc.nsh" - -!ifndef INFO_PROJECTNAME - !define INFO_PROJECTNAME "custom-protocol-example" -!endif -!ifndef INFO_COMPANYNAME - !define INFO_COMPANYNAME "My Company" -!endif -!ifndef INFO_PRODUCTNAME - !define INFO_PRODUCTNAME "My Product" -!endif -!ifndef INFO_PRODUCTVERSION - !define INFO_PRODUCTVERSION "0.0.1" -!endif -!ifndef INFO_COPYRIGHT - !define INFO_COPYRIGHT "(c) 2025, My Company" -!endif -!ifndef PRODUCT_EXECUTABLE - !define PRODUCT_EXECUTABLE "${INFO_PROJECTNAME}.exe" -!endif -!ifndef UNINST_KEY_NAME - !define UNINST_KEY_NAME "${INFO_COMPANYNAME}${INFO_PRODUCTNAME}" -!endif -!define UNINST_KEY "Software\Microsoft\Windows\CurrentVersion\Uninstall\${UNINST_KEY_NAME}" - -!ifndef REQUEST_EXECUTION_LEVEL - !define REQUEST_EXECUTION_LEVEL "admin" -!endif - -RequestExecutionLevel "${REQUEST_EXECUTION_LEVEL}" - -!ifdef ARG_WAILS_AMD64_BINARY - !define SUPPORTS_AMD64 -!endif - -!ifdef ARG_WAILS_ARM64_BINARY - !define SUPPORTS_ARM64 -!endif - -!ifdef SUPPORTS_AMD64 - !ifdef SUPPORTS_ARM64 - !define ARCH "amd64_arm64" - !else - !define ARCH "amd64" - !endif -!else - !ifdef SUPPORTS_ARM64 - !define ARCH "arm64" - !else - !error "Wails: Undefined ARCH, please provide at least one of ARG_WAILS_AMD64_BINARY or ARG_WAILS_ARM64_BINARY" - !endif -!endif - -!macro wails.checkArchitecture - !ifndef WAILS_WIN10_REQUIRED - !define WAILS_WIN10_REQUIRED "This product is only supported on Windows 10 (Server 2016) and later." - !endif - - !ifndef WAILS_ARCHITECTURE_NOT_SUPPORTED - !define WAILS_ARCHITECTURE_NOT_SUPPORTED "This product can't be installed on the current Windows architecture. Supports: ${ARCH}" - !endif - - ${If} ${AtLeastWin10} - !ifdef SUPPORTS_AMD64 - ${if} ${IsNativeAMD64} - Goto ok - ${EndIf} - !endif - - !ifdef SUPPORTS_ARM64 - ${if} ${IsNativeARM64} - Goto ok - ${EndIf} - !endif - - IfSilent silentArch notSilentArch - silentArch: - SetErrorLevel 65 - Abort - notSilentArch: - MessageBox MB_OK "${WAILS_ARCHITECTURE_NOT_SUPPORTED}" - Quit - ${else} - IfSilent silentWin notSilentWin - silentWin: - SetErrorLevel 64 - Abort - notSilentWin: - MessageBox MB_OK "${WAILS_WIN10_REQUIRED}" - Quit - ${EndIf} - - ok: -!macroend - -!macro wails.files - !ifdef SUPPORTS_AMD64 - ${if} ${IsNativeAMD64} - File "/oname=${PRODUCT_EXECUTABLE}" "${ARG_WAILS_AMD64_BINARY}" - ${EndIf} - !endif - - !ifdef SUPPORTS_ARM64 - ${if} ${IsNativeARM64} - File "/oname=${PRODUCT_EXECUTABLE}" "${ARG_WAILS_ARM64_BINARY}" - ${EndIf} - !endif -!macroend - -!macro wails.writeUninstaller - WriteUninstaller "$INSTDIR\uninstall.exe" - - SetRegView 64 - WriteRegStr HKLM "${UNINST_KEY}" "Publisher" "${INFO_COMPANYNAME}" - WriteRegStr HKLM "${UNINST_KEY}" "DisplayName" "${INFO_PRODUCTNAME}" - WriteRegStr HKLM "${UNINST_KEY}" "DisplayVersion" "${INFO_PRODUCTVERSION}" - WriteRegStr HKLM "${UNINST_KEY}" "DisplayIcon" "$INSTDIR\${PRODUCT_EXECUTABLE}" - WriteRegStr HKLM "${UNINST_KEY}" "UninstallString" "$\"$INSTDIR\uninstall.exe$\"" - WriteRegStr HKLM "${UNINST_KEY}" "QuietUninstallString" "$\"$INSTDIR\uninstall.exe$\" /S" - - ${GetSize} "$INSTDIR" "/S=0K" $0 $1 $2 - IntFmt $0 "0x%08X" $0 - WriteRegDWORD HKLM "${UNINST_KEY}" "EstimatedSize" "$0" -!macroend - -!macro wails.deleteUninstaller - Delete "$INSTDIR\uninstall.exe" - - SetRegView 64 - DeleteRegKey HKLM "${UNINST_KEY}" -!macroend - -!macro wails.setShellContext - ${If} ${REQUEST_EXECUTION_LEVEL} == "admin" - SetShellVarContext all - ${else} - SetShellVarContext current - ${EndIf} -!macroend - -# Install webview2 by launching the bootstrapper -# See https://docs.microsoft.com/en-us/microsoft-edge/webview2/concepts/distribution#online-only-deployment -!macro wails.webview2runtime - !ifndef WAILS_INSTALL_WEBVIEW_DETAILPRINT - !define WAILS_INSTALL_WEBVIEW_DETAILPRINT "Installing: WebView2 Runtime" - !endif - - SetRegView 64 - # If the admin key exists and is not empty then webview2 is already installed - ReadRegStr $0 HKLM "SOFTWARE\WOW6432Node\Microsoft\EdgeUpdate\Clients\{F3017226-FE2A-4295-8BDF-00C3A9A7E4C5}" "pv" - ${If} $0 != "" - Goto ok - ${EndIf} - - ${If} ${REQUEST_EXECUTION_LEVEL} == "user" - # If the installer is run in user level, check the user specific key exists and is not empty then webview2 is already installed - ReadRegStr $0 HKCU "Software\Microsoft\EdgeUpdate\Clients\{F3017226-FE2A-4295-8BDF-00C3A9A7E4C5}" "pv" - ${If} $0 != "" - Goto ok - ${EndIf} - ${EndIf} - - SetDetailsPrint both - DetailPrint "${WAILS_INSTALL_WEBVIEW_DETAILPRINT}" - SetDetailsPrint listonly - - InitPluginsDir - CreateDirectory "$pluginsdir\webview2bootstrapper" - SetOutPath "$pluginsdir\webview2bootstrapper" - File "MicrosoftEdgeWebview2Setup.exe" - ExecWait '"$pluginsdir\webview2bootstrapper\MicrosoftEdgeWebview2Setup.exe" /silent /install' - - SetDetailsPrint both - ok: -!macroend - -# Copy of APP_ASSOCIATE and APP_UNASSOCIATE macros from here https://gist.github.com/nikku/281d0ef126dbc215dd58bfd5b3a5cd5b -!macro APP_ASSOCIATE EXT FILECLASS DESCRIPTION ICON COMMANDTEXT COMMAND - ; Backup the previously associated file class - ReadRegStr $R0 SHELL_CONTEXT "Software\Classes\.${EXT}" "" - WriteRegStr SHELL_CONTEXT "Software\Classes\.${EXT}" "${FILECLASS}_backup" "$R0" - - WriteRegStr SHELL_CONTEXT "Software\Classes\.${EXT}" "" "${FILECLASS}" - - WriteRegStr SHELL_CONTEXT "Software\Classes\${FILECLASS}" "" `${DESCRIPTION}` - WriteRegStr SHELL_CONTEXT "Software\Classes\${FILECLASS}\DefaultIcon" "" `${ICON}` - WriteRegStr SHELL_CONTEXT "Software\Classes\${FILECLASS}\shell" "" "open" - WriteRegStr SHELL_CONTEXT "Software\Classes\${FILECLASS}\shell\open" "" `${COMMANDTEXT}` - WriteRegStr SHELL_CONTEXT "Software\Classes\${FILECLASS}\shell\open\command" "" `${COMMAND}` -!macroend - -!macro APP_UNASSOCIATE EXT FILECLASS - ; Backup the previously associated file class - ReadRegStr $R0 SHELL_CONTEXT "Software\Classes\.${EXT}" `${FILECLASS}_backup` - WriteRegStr SHELL_CONTEXT "Software\Classes\.${EXT}" "" "$R0" - - DeleteRegKey SHELL_CONTEXT `Software\Classes\${FILECLASS}` -!macroend - -!macro wails.associateFiles - ; Create file associations - -!macroend - -!macro wails.unassociateFiles - ; Delete app associations - -!macroend \ No newline at end of file diff --git a/v3/examples/custom-protocol-example/build/windows/wails.exe.manifest b/v3/examples/custom-protocol-example/build/windows/wails.exe.manifest deleted file mode 100644 index 21af92674..000000000 --- a/v3/examples/custom-protocol-example/build/windows/wails.exe.manifest +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - true/pm - permonitorv2,permonitor - - - \ No newline at end of file diff --git a/v3/examples/custom-protocol-example/frontend/.gitignore b/v3/examples/custom-protocol-example/frontend/.gitignore deleted file mode 100644 index a547bf36d..000000000 --- a/v3/examples/custom-protocol-example/frontend/.gitignore +++ /dev/null @@ -1,24 +0,0 @@ -# Logs -logs -*.log -npm-debug.log* -yarn-debug.log* -yarn-error.log* -pnpm-debug.log* -lerna-debug.log* - -node_modules -dist -dist-ssr -*.local - -# Editor directories and files -.vscode/* -!.vscode/extensions.json -.idea -.DS_Store -*.suo -*.ntvs* -*.njsproj -*.sln -*.sw? diff --git a/v3/examples/custom-protocol-example/frontend/bindings/github.com/wailsapp/wails/v3/examples/custom-protocol-example/greetservice.js b/v3/examples/custom-protocol-example/frontend/bindings/github.com/wailsapp/wails/v3/examples/custom-protocol-example/greetservice.js deleted file mode 100644 index 0b93e6d75..000000000 --- a/v3/examples/custom-protocol-example/frontend/bindings/github.com/wailsapp/wails/v3/examples/custom-protocol-example/greetservice.js +++ /dev/null @@ -1,15 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "@wailsio/runtime"; - -/** - * @param {string} name - * @returns {$CancellablePromise} - */ -export function Greet(name) { - return $Call.ByID(1411160069, name); -} diff --git a/v3/examples/custom-protocol-example/frontend/bindings/github.com/wailsapp/wails/v3/examples/custom-protocol-example/index.js b/v3/examples/custom-protocol-example/frontend/bindings/github.com/wailsapp/wails/v3/examples/custom-protocol-example/index.js deleted file mode 100644 index fdf1ff435..000000000 --- a/v3/examples/custom-protocol-example/frontend/bindings/github.com/wailsapp/wails/v3/examples/custom-protocol-example/index.js +++ /dev/null @@ -1,8 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; diff --git a/v3/examples/custom-protocol-example/frontend/dist/assets/index-BS9x21Y4.js b/v3/examples/custom-protocol-example/frontend/dist/assets/index-BS9x21Y4.js deleted file mode 100644 index 4f1023c59..000000000 --- a/v3/examples/custom-protocol-example/frontend/dist/assets/index-BS9x21Y4.js +++ /dev/null @@ -1,24 +0,0 @@ -(function(){const t=document.createElement("link").relList;if(t&&t.supports&&t.supports("modulepreload"))return;for(const i of document.querySelectorAll('link[rel="modulepreload"]'))o(i);new MutationObserver(i=>{for(const r of i)if(r.type==="childList")for(const s of r.addedNodes)s.tagName==="LINK"&&s.rel==="modulepreload"&&o(s)}).observe(document,{childList:!0,subtree:!0});function n(i){const r={};return i.integrity&&(r.integrity=i.integrity),i.referrerPolicy&&(r.referrerPolicy=i.referrerPolicy),i.crossOrigin==="use-credentials"?r.credentials="include":i.crossOrigin==="anonymous"?r.credentials="omit":r.credentials="same-origin",r}function o(i){if(i.ep)return;i.ep=!0;const r=n(i);fetch(i.href,r)}})();const S="useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict";function R(e=21){let t="",n=e|0;for(;n--;)t+=S[Math.random()*64|0];return t}const U=window.location.origin+"/wails/runtime",_=Object.freeze({Call:0,Clipboard:1,Application:2,Events:3,ContextMenu:4,Dialog:5,Window:6,Screens:7,System:8,Browser:9,CancelCall:10});let T=R();function k(e,t=""){return function(n,o=null){return I(e,n,t,o)}}async function I(e,t,n,o){var i,r;let s=new URL(U);s.searchParams.append("object",e.toString()),s.searchParams.append("method",t.toString()),o&&s.searchParams.append("args",JSON.stringify(o));let c={"x-wails-client-id":T};n&&(c["x-wails-window-name"]=n);let a=await fetch(s,{headers:c});if(!a.ok)throw new Error(await a.text());return((r=(i=a.headers.get("Content-Type"))===null||i===void 0?void 0:i.indexOf("application/json"))!==null&&r!==void 0?r:-1)!==-1?a.json():a.text()}k(_.System);const z=function(){var e,t,n,o,i;try{if(!((t=(e=window.chrome)===null||e===void 0?void 0:e.webview)===null||t===void 0)&&t.postMessage)return window.chrome.webview.postMessage.bind(window.chrome.webview);if(!((i=(o=(n=window.webkit)===null||n===void 0?void 0:n.messageHandlers)===null||o===void 0?void 0:o.external)===null||i===void 0)&&i.postMessage)return window.webkit.messageHandlers.external.postMessage.bind(window.webkit.messageHandlers.external)}catch{}return console.warn(` -%c⚠️ Browser Environment Detected %c - -%cOnly UI previews are available in the browser. For full functionality, please run the application in desktop mode. -More information at: https://v3.wails.io/learn/build/#using-a-browser-for-development -`,"background: #ffffff; color: #000000; font-weight: bold; padding: 4px 8px; border-radius: 4px; border: 2px solid #000000;","background: transparent;","color: #ffffff; font-style: italic; font-weight: bold;"),null}();function h(e){z==null||z(e)}function H(){return window._wails.environment.OS==="windows"}function W(){return!!window._wails.environment.Debug}function B(){return new MouseEvent("mousedown").buttons===0}function P(e){var t;return e.target instanceof HTMLElement?e.target:!(e.target instanceof HTMLElement)&&e.target instanceof Node&&(t=e.target.parentElement)!==null&&t!==void 0?t:document.body}document.addEventListener("DOMContentLoaded",()=>{});window.addEventListener("contextmenu",X);const N=k(_.ContextMenu),j=0;function F(e,t,n,o){N(j,{id:e,x:t,y:n,data:o})}function X(e){const t=P(e),n=window.getComputedStyle(t).getPropertyValue("--custom-contextmenu").trim();if(n){e.preventDefault();const o=window.getComputedStyle(t).getPropertyValue("--custom-contextmenu-data");F(n,e.clientX,e.clientY,o)}else Y(e,t)}function Y(e,t){if(W())return;switch(window.getComputedStyle(t).getPropertyValue("--default-contextmenu").trim()){case"show":return;case"hide":e.preventDefault();return}if(t.isContentEditable)return;const n=window.getSelection(),o=n&&n.toString().length>0;if(o)for(let i=0;i{M=e,M||(w=p=!1,l())};window.addEventListener("mousedown",D,{capture:!0});window.addEventListener("mousemove",D,{capture:!0});window.addEventListener("mouseup",D,{capture:!0});for(const e of["click","contextmenu","dblclick"])window.addEventListener(e,A,{capture:!0});function A(e){(g||p)&&(e.stopImmediatePropagation(),e.stopPropagation(),e.preventDefault())}const C=0,V=1,L=2;function D(e){let t,n=e.buttons;switch(e.type){case"mousedown":t=C,E||(n=f|1<n!==e),t.length===0?d.delete(e.eventName):d.set(e.eventName,t))}window._wails=window._wails||{};window._wails.dispatchWailsEvent=ee;k(_.Events);class ${constructor(t,n=null){this.name=t,this.data=n}}function ee(e){let t=d.get(e.name);if(!t)return;let n=new $(e.name,e.data);"sender"in e&&(n.sender=e.sender),t=t.filter(o=>!o.dispatch(n)),t.length===0?d.delete(e.name):d.set(e.name,t)}function te(e,t,n){let o=d.get(e)||[];const i=new Q(e,t,n);return o.push(i),d.set(e,o),()=>Z(i)}function ne(e,t){return te(e,t,-1)}window._wails=window._wails||{};window._wails.invoke=h;h("wails:runtime:ready");document.addEventListener("DOMContentLoaded",()=>{const e=document.getElementById("app");e?e.innerHTML=` -
      -

      Custom Protocol / Deep Link Test

      -

      - This page demonstrates handling custom URL schemes (deep links). -

      -

      - Example Link: - Try opening this URL (e.g., by pasting it into your browser's address bar or using open your-app-scheme://... in terminal): -
      - wailsexample://test/path?value=123&message=hello -

      - -
      - Received URL: -
      Waiting for application to be opened via a custom URL...
      -
      -
      - `:console.error('Element with ID "app" not found.')});ne("frontend:ShowURL",e=>{console.log("frontend:ShowURL event received, data:",e),displayUrl(e.data)});window.displayUrl=function(e){const t=document.getElementById("received-url");t?t.textContent=e||"No URL received or an error occurred.":console.error("Element with ID 'received-url' not found in displayUrl.")}; diff --git a/v3/examples/custom-protocol-example/frontend/dist/assets/index-uDrhEpT0.css b/v3/examples/custom-protocol-example/frontend/dist/assets/index-uDrhEpT0.css deleted file mode 100644 index 37a5c205c..000000000 --- a/v3/examples/custom-protocol-example/frontend/dist/assets/index-uDrhEpT0.css +++ /dev/null @@ -1 +0,0 @@ -:root{font-family:system-ui,Avenir,Helvetica,Arial,sans-serif;line-height:1.5;font-weight:400;color-scheme:light dark;color:#ffffffde;background-color:#242424;font-synthesis:none;text-rendering:optimizeLegibility;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}a{font-weight:500;color:#646cff;text-decoration:inherit}a:hover{color:#535bf2}body{font-family:system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Open Sans,Helvetica Neue,sans-serif;margin:0;background-color:#f7f7f7;color:#333;display:flex;justify-content:center;align-items:center;min-height:100vh;padding:20px;box-sizing:border-box}h1{color:#0056b3;font-size:1.8em;margin-bottom:.8em}#app{width:100%;max-width:600px;margin:auto}.container{background-color:#fff;padding:25px 30px;border-radius:8px;box-shadow:0 2px 10px #0000001a;text-align:left}p{line-height:1.6;font-size:1em;margin-bottom:1em}a{color:#007bff;text-decoration:none}a:hover{text-decoration:underline}.url-display{margin-top:25px;padding:15px;background-color:#e9ecef;border:1px solid #ced4da;border-radius:4px;font-family:Courier New,Courier,monospace;font-size:.95em;word-break:break-all}.label{font-weight:700;display:block;margin-bottom:8px;color:#495057}.logo{height:6em;padding:1.5em;will-change:filter;transition:filter .3s}.logo:hover{filter:drop-shadow(0 0 2em #646cffaa)}.logo.vanilla:hover{filter:drop-shadow(0 0 2em #f7df1eaa)}.card{padding:2em}.read-the-docs{color:#888}button{border-radius:8px;border:1px solid transparent;padding:.6em 1.2em;font-size:1em;font-weight:500;font-family:inherit;background-color:#1a1a1a;cursor:pointer;transition:border-color .25s}button:hover{border-color:#646cff}button:focus,button:focus-visible{outline:4px auto -webkit-focus-ring-color}@media (prefers-color-scheme: light){:root{color:#213547;background-color:#fff}a:hover{color:#747bff}button{background-color:#f9f9f9}} diff --git a/v3/examples/custom-protocol-example/frontend/dist/index.html b/v3/examples/custom-protocol-example/frontend/dist/index.html deleted file mode 100644 index 126962c69..000000000 --- a/v3/examples/custom-protocol-example/frontend/dist/index.html +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - Vite App - - - - -
      - - diff --git a/v3/examples/custom-protocol-example/frontend/dist/vite.svg b/v3/examples/custom-protocol-example/frontend/dist/vite.svg deleted file mode 100644 index e7b8dfb1b..000000000 --- a/v3/examples/custom-protocol-example/frontend/dist/vite.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/v3/examples/custom-protocol-example/frontend/index.html b/v3/examples/custom-protocol-example/frontend/index.html deleted file mode 100644 index 72ba3a8b3..000000000 --- a/v3/examples/custom-protocol-example/frontend/index.html +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - Vite App - - -
      - - - diff --git a/v3/examples/custom-protocol-example/frontend/package-lock.json b/v3/examples/custom-protocol-example/frontend/package-lock.json deleted file mode 100644 index 2b2b28cc5..000000000 --- a/v3/examples/custom-protocol-example/frontend/package-lock.json +++ /dev/null @@ -1,1017 +0,0 @@ -{ - "name": "frontend", - "version": "0.0.0", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "frontend", - "version": "0.0.0", - "dependencies": { - "@wailsio/runtime": "^3.0.0-alpha.66" - }, - "devDependencies": { - "vite": "^6.3.5" - } - }, - "node_modules/@esbuild/aix-ppc64": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.4.tgz", - "integrity": "sha512-1VCICWypeQKhVbE9oW/sJaAmjLxhVqacdkvPLEjwlttjfwENRSClS8EjBz0KzRyFSCPDIkuXW34Je/vk7zdB7Q==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "aix" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-arm": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.25.4.tgz", - "integrity": "sha512-QNdQEps7DfFwE3hXiU4BZeOV68HHzYwGd0Nthhd3uCkkEKK7/R6MTgM0P7H7FAs5pU/DIWsviMmEGxEoxIZ+ZQ==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-arm64": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.25.4.tgz", - "integrity": "sha512-bBy69pgfhMGtCnwpC/x5QhfxAz/cBgQ9enbtwjf6V9lnPI/hMyT9iWpR1arm0l3kttTr4L0KSLpKmLp/ilKS9A==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/android-x64": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.25.4.tgz", - "integrity": "sha512-TVhdVtQIFuVpIIR282btcGC2oGQoSfZfmBdTip2anCaVYcqWlZXGcdcKIUklfX2wj0JklNYgz39OBqh2cqXvcQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/darwin-arm64": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.25.4.tgz", - "integrity": "sha512-Y1giCfM4nlHDWEfSckMzeWNdQS31BQGs9/rouw6Ub91tkK79aIMTH3q9xHvzH8d0wDru5Ci0kWB8b3up/nl16g==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/darwin-x64": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.25.4.tgz", - "integrity": "sha512-CJsry8ZGM5VFVeyUYB3cdKpd/H69PYez4eJh1W/t38vzutdjEjtP7hB6eLKBoOdxcAlCtEYHzQ/PJ/oU9I4u0A==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/freebsd-arm64": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.4.tgz", - "integrity": "sha512-yYq+39NlTRzU2XmoPW4l5Ifpl9fqSk0nAJYM/V/WUGPEFfek1epLHJIkTQM6bBs1swApjO5nWgvr843g6TjxuQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/freebsd-x64": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.25.4.tgz", - "integrity": "sha512-0FgvOJ6UUMflsHSPLzdfDnnBBVoCDtBTVyn/MrWloUNvq/5SFmh13l3dvgRPkDihRxb77Y17MbqbCAa2strMQQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-arm": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.25.4.tgz", - "integrity": "sha512-kro4c0P85GMfFYqW4TWOpvmF8rFShbWGnrLqlzp4X1TNWjRY3JMYUfDCtOxPKOIY8B0WC8HN51hGP4I4hz4AaQ==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-arm64": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.25.4.tgz", - "integrity": "sha512-+89UsQTfXdmjIvZS6nUnOOLoXnkUTB9hR5QAeLrQdzOSWZvNSAXAtcRDHWtqAUtAmv7ZM1WPOOeSxDzzzMogiQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-ia32": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.25.4.tgz", - "integrity": "sha512-yTEjoapy8UP3rv8dB0ip3AfMpRbyhSN3+hY8mo/i4QXFeDxmiYbEKp3ZRjBKcOP862Ua4b1PDfwlvbuwY7hIGQ==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-loong64": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.25.4.tgz", - "integrity": "sha512-NeqqYkrcGzFwi6CGRGNMOjWGGSYOpqwCjS9fvaUlX5s3zwOtn1qwg1s2iE2svBe4Q/YOG1q6875lcAoQK/F4VA==", - "cpu": [ - "loong64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-mips64el": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.25.4.tgz", - "integrity": "sha512-IcvTlF9dtLrfL/M8WgNI/qJYBENP3ekgsHbYUIzEzq5XJzzVEV/fXY9WFPfEEXmu3ck2qJP8LG/p3Q8f7Zc2Xg==", - "cpu": [ - "mips64el" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-ppc64": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.25.4.tgz", - "integrity": "sha512-HOy0aLTJTVtoTeGZh4HSXaO6M95qu4k5lJcH4gxv56iaycfz1S8GO/5Jh6X4Y1YiI0h7cRyLi+HixMR+88swag==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-riscv64": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.25.4.tgz", - "integrity": "sha512-i8JUDAufpz9jOzo4yIShCTcXzS07vEgWzyX3NH2G7LEFVgrLEhjwL3ajFE4fZI3I4ZgiM7JH3GQ7ReObROvSUA==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-s390x": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.25.4.tgz", - "integrity": "sha512-jFnu+6UbLlzIjPQpWCNh5QtrcNfMLjgIavnwPQAfoGx4q17ocOU9MsQ2QVvFxwQoWpZT8DvTLooTvmOQXkO51g==", - "cpu": [ - "s390x" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/linux-x64": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.4.tgz", - "integrity": "sha512-6e0cvXwzOnVWJHq+mskP8DNSrKBr1bULBvnFLpc1KY+d+irZSgZ02TGse5FsafKS5jg2e4pbvK6TPXaF/A6+CA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/netbsd-arm64": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.4.tgz", - "integrity": "sha512-vUnkBYxZW4hL/ie91hSqaSNjulOnYXE1VSLusnvHg2u3jewJBz3YzB9+oCw8DABeVqZGg94t9tyZFoHma8gWZQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/netbsd-x64": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.25.4.tgz", - "integrity": "sha512-XAg8pIQn5CzhOB8odIcAm42QsOfa98SBeKUdo4xa8OvX8LbMZqEtgeWE9P/Wxt7MlG2QqvjGths+nq48TrUiKw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openbsd-arm64": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.4.tgz", - "integrity": "sha512-Ct2WcFEANlFDtp1nVAXSNBPDxyU+j7+tId//iHXU2f/lN5AmO4zLyhDcpR5Cz1r08mVxzt3Jpyt4PmXQ1O6+7A==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/openbsd-x64": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.25.4.tgz", - "integrity": "sha512-xAGGhyOQ9Otm1Xu8NT1ifGLnA6M3sJxZ6ixylb+vIUVzvvd6GOALpwQrYrtlPouMqd/vSbgehz6HaVk4+7Afhw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/sunos-x64": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.25.4.tgz", - "integrity": "sha512-Mw+tzy4pp6wZEK0+Lwr76pWLjrtjmJyUB23tHKqEDP74R3q95luY/bXqXZeYl4NYlvwOqoRKlInQialgCKy67Q==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-arm64": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.25.4.tgz", - "integrity": "sha512-AVUP428VQTSddguz9dO9ngb+E5aScyg7nOeJDrF1HPYu555gmza3bDGMPhmVXL8svDSoqPCsCPjb265yG/kLKQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-ia32": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.25.4.tgz", - "integrity": "sha512-i1sW+1i+oWvQzSgfRcxxG2k4I9n3O9NRqy8U+uugaT2Dy7kLO9Y7wI72haOahxceMX8hZAzgGou1FhndRldxRg==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@esbuild/win32-x64": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.25.4.tgz", - "integrity": "sha512-nOT2vZNw6hJ+z43oP1SPea/G/6AbN6X+bGNhNuq8NtRHy4wsMhw765IKLNmnjek7GvjWBYQ8Q5VBoYTFg9y1UQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=18" - } - }, - "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.41.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.41.0.tgz", - "integrity": "sha512-KxN+zCjOYHGwCl4UCtSfZ6jrq/qi88JDUtiEFk8LELEHq2Egfc/FgW+jItZiOLRuQfb/3xJSgFuNPC9jzggX+A==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/@rollup/rollup-android-arm64": { - "version": "4.41.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.41.0.tgz", - "integrity": "sha512-yDvqx3lWlcugozax3DItKJI5j05B0d4Kvnjx+5mwiUpWramVvmAByYigMplaoAQ3pvdprGCTCE03eduqE/8mPQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.41.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.41.0.tgz", - "integrity": "sha512-2KOU574vD3gzcPSjxO0eyR5iWlnxxtmW1F5CkNOHmMlueKNCQkxR6+ekgWyVnz6zaZihpUNkGxjsYrkTJKhkaw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.41.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.41.0.tgz", - "integrity": "sha512-gE5ACNSxHcEZyP2BA9TuTakfZvULEW4YAOtxl/A/YDbIir/wPKukde0BNPlnBiP88ecaN4BJI2TtAd+HKuZPQQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.41.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.41.0.tgz", - "integrity": "sha512-GSxU6r5HnWij7FoSo7cZg3l5GPg4HFLkzsFFh0N/b16q5buW1NAWuCJ+HMtIdUEi6XF0qH+hN0TEd78laRp7Dg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ] - }, - "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.41.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.41.0.tgz", - "integrity": "sha512-KGiGKGDg8qLRyOWmk6IeiHJzsN/OYxO6nSbT0Vj4MwjS2XQy/5emsmtoqLAabqrohbgLWJ5GV3s/ljdrIr8Qjg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ] - }, - "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.41.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.41.0.tgz", - "integrity": "sha512-46OzWeqEVQyX3N2/QdiU/CMXYDH/lSHpgfBkuhl3igpZiaB3ZIfSjKuOnybFVBQzjsLwkus2mjaESy8H41SzvA==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.41.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.41.0.tgz", - "integrity": "sha512-lfgW3KtQP4YauqdPpcUZHPcqQXmTmH4nYU0cplNeW583CMkAGjtImw4PKli09NFi2iQgChk4e9erkwlfYem6Lg==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.41.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.41.0.tgz", - "integrity": "sha512-nn8mEyzMbdEJzT7cwxgObuwviMx6kPRxzYiOl6o/o+ChQq23gfdlZcUNnt89lPhhz3BYsZ72rp0rxNqBSfqlqw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.41.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.41.0.tgz", - "integrity": "sha512-l+QK99je2zUKGd31Gh+45c4pGDAqZSuWQiuRFCdHYC2CSiO47qUWsCcenrI6p22hvHZrDje9QjwSMAFL3iwXwQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-loongarch64-gnu": { - "version": "4.41.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.41.0.tgz", - "integrity": "sha512-WbnJaxPv1gPIm6S8O/Wg+wfE/OzGSXlBMbOe4ie+zMyykMOeqmgD1BhPxZQuDqwUN+0T/xOFtL2RUWBspnZj3w==", - "cpu": [ - "loong64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { - "version": "4.41.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.41.0.tgz", - "integrity": "sha512-eRDWR5t67/b2g8Q/S8XPi0YdbKcCs4WQ8vklNnUYLaSWF+Cbv2axZsp4jni6/j7eKvMLYCYdcsv8dcU+a6QNFg==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.41.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.41.0.tgz", - "integrity": "sha512-TWrZb6GF5jsEKG7T1IHwlLMDRy2f3DPqYldmIhnA2DVqvvhY2Ai184vZGgahRrg8k9UBWoSlHv+suRfTN7Ua4A==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-riscv64-musl": { - "version": "4.41.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.41.0.tgz", - "integrity": "sha512-ieQljaZKuJpmWvd8gW87ZmSFwid6AxMDk5bhONJ57U8zT77zpZ/TPKkU9HpnnFrM4zsgr4kiGuzbIbZTGi7u9A==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.41.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.41.0.tgz", - "integrity": "sha512-/L3pW48SxrWAlVsKCN0dGLB2bi8Nv8pr5S5ocSM+S0XCn5RCVCXqi8GVtHFsOBBCSeR+u9brV2zno5+mg3S4Aw==", - "cpu": [ - "s390x" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.41.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.41.0.tgz", - "integrity": "sha512-XMLeKjyH8NsEDCRptf6LO8lJk23o9wvB+dJwcXMaH6ZQbbkHu2dbGIUindbMtRN6ux1xKi16iXWu6q9mu7gDhQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.41.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.41.0.tgz", - "integrity": "sha512-m/P7LycHZTvSQeXhFmgmdqEiTqSV80zn6xHaQ1JSqwCtD1YGtwEK515Qmy9DcB2HK4dOUVypQxvhVSy06cJPEg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.41.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.41.0.tgz", - "integrity": "sha512-4yodtcOrFHpbomJGVEqZ8fzD4kfBeCbpsUy5Pqk4RluXOdsWdjLnjhiKy2w3qzcASWd04fp52Xz7JKarVJ5BTg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.41.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.41.0.tgz", - "integrity": "sha512-tmazCrAsKzdkXssEc65zIE1oC6xPHwfy9d5Ta25SRCDOZS+I6RypVVShWALNuU9bxIfGA0aqrmzlzoM5wO5SPQ==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.41.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.41.0.tgz", - "integrity": "sha512-h1J+Yzjo/X+0EAvR2kIXJDuTuyT7drc+t2ALY0nIcGPbTatNOf0VWdhEA2Z4AAjv6X1NJV7SYo5oCTYRJhSlVA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@types/estree": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.7.tgz", - "integrity": "sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/@wailsio/runtime": { - "version": "3.0.0-alpha.66", - "resolved": "https://registry.npmjs.org/@wailsio/runtime/-/runtime-3.0.0-alpha.66.tgz", - "integrity": "sha512-ENLu8rn1griL1gFHJqkq1i+BVxrrA0JPJHYneUJYuf/s54kjuQViW0RKDEe/WTDo56ABpfykrd/T8OYpPUyXUw==", - "license": "MIT" - }, - "node_modules/esbuild": { - "version": "0.25.4", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.25.4.tgz", - "integrity": "sha512-8pgjLUcUjcgDg+2Q4NYXnPbo/vncAY4UmyaCm0jZevERqCHZIaWwdJHkf8XQtu4AxSKCdvrUbT0XUr1IdZzI8Q==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=18" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.25.4", - "@esbuild/android-arm": "0.25.4", - "@esbuild/android-arm64": "0.25.4", - "@esbuild/android-x64": "0.25.4", - "@esbuild/darwin-arm64": "0.25.4", - "@esbuild/darwin-x64": "0.25.4", - "@esbuild/freebsd-arm64": "0.25.4", - "@esbuild/freebsd-x64": "0.25.4", - "@esbuild/linux-arm": "0.25.4", - "@esbuild/linux-arm64": "0.25.4", - "@esbuild/linux-ia32": "0.25.4", - "@esbuild/linux-loong64": "0.25.4", - "@esbuild/linux-mips64el": "0.25.4", - "@esbuild/linux-ppc64": "0.25.4", - "@esbuild/linux-riscv64": "0.25.4", - "@esbuild/linux-s390x": "0.25.4", - "@esbuild/linux-x64": "0.25.4", - "@esbuild/netbsd-arm64": "0.25.4", - "@esbuild/netbsd-x64": "0.25.4", - "@esbuild/openbsd-arm64": "0.25.4", - "@esbuild/openbsd-x64": "0.25.4", - "@esbuild/sunos-x64": "0.25.4", - "@esbuild/win32-arm64": "0.25.4", - "@esbuild/win32-ia32": "0.25.4", - "@esbuild/win32-x64": "0.25.4" - } - }, - "node_modules/fdir": { - "version": "6.4.4", - "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.4.4.tgz", - "integrity": "sha512-1NZP+GK4GfuAv3PqKvxQRDMjdSRZjnkq7KfhlNrCNNlZ0ygQFpebfrnfnq/W7fpUnAv9aGWmY1zKx7FYL3gwhg==", - "dev": true, - "license": "MIT", - "peerDependencies": { - "picomatch": "^3 || ^4" - }, - "peerDependenciesMeta": { - "picomatch": { - "optional": true - } - } - }, - "node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/nanoid": { - "version": "3.3.11", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", - "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "bin": { - "nanoid": "bin/nanoid.cjs" - }, - "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" - } - }, - "node_modules/picocolors": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", - "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", - "dev": true, - "license": "ISC" - }, - "node_modules/picomatch": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", - "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/postcss": { - "version": "8.5.3", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.3.tgz", - "integrity": "sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "nanoid": "^3.3.8", - "picocolors": "^1.1.1", - "source-map-js": "^1.2.1" - }, - "engines": { - "node": "^10 || ^12 || >=14" - } - }, - "node_modules/rollup": { - "version": "4.41.0", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.41.0.tgz", - "integrity": "sha512-HqMFpUbWlf/tvcxBFNKnJyzc7Lk+XO3FGc3pbNBLqEbOz0gPLRgcrlS3UF4MfUrVlstOaP/q0kM6GVvi+LrLRg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/estree": "1.0.7" - }, - "bin": { - "rollup": "dist/bin/rollup" - }, - "engines": { - "node": ">=18.0.0", - "npm": ">=8.0.0" - }, - "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.41.0", - "@rollup/rollup-android-arm64": "4.41.0", - "@rollup/rollup-darwin-arm64": "4.41.0", - "@rollup/rollup-darwin-x64": "4.41.0", - "@rollup/rollup-freebsd-arm64": "4.41.0", - "@rollup/rollup-freebsd-x64": "4.41.0", - "@rollup/rollup-linux-arm-gnueabihf": "4.41.0", - "@rollup/rollup-linux-arm-musleabihf": "4.41.0", - "@rollup/rollup-linux-arm64-gnu": "4.41.0", - "@rollup/rollup-linux-arm64-musl": "4.41.0", - "@rollup/rollup-linux-loongarch64-gnu": "4.41.0", - "@rollup/rollup-linux-powerpc64le-gnu": "4.41.0", - "@rollup/rollup-linux-riscv64-gnu": "4.41.0", - "@rollup/rollup-linux-riscv64-musl": "4.41.0", - "@rollup/rollup-linux-s390x-gnu": "4.41.0", - "@rollup/rollup-linux-x64-gnu": "4.41.0", - "@rollup/rollup-linux-x64-musl": "4.41.0", - "@rollup/rollup-win32-arm64-msvc": "4.41.0", - "@rollup/rollup-win32-ia32-msvc": "4.41.0", - "@rollup/rollup-win32-x64-msvc": "4.41.0", - "fsevents": "~2.3.2" - } - }, - "node_modules/source-map-js": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", - "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/tinyglobby": { - "version": "0.2.13", - "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.13.tgz", - "integrity": "sha512-mEwzpUgrLySlveBwEVDMKk5B57bhLPYovRfPAXD5gA/98Opn0rCDj3GtLwFvCvH5RK9uPCExUROW5NjDwvqkxw==", - "dev": true, - "license": "MIT", - "dependencies": { - "fdir": "^6.4.4", - "picomatch": "^4.0.2" - }, - "engines": { - "node": ">=12.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/SuperchupuDev" - } - }, - "node_modules/vite": { - "version": "6.3.5", - "resolved": "https://registry.npmjs.org/vite/-/vite-6.3.5.tgz", - "integrity": "sha512-cZn6NDFE7wdTpINgs++ZJ4N49W2vRp8LCKrn3Ob1kYNtOo21vfDoaV5GzBfLU4MovSAB8uNRm4jgzVQZ+mBzPQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "esbuild": "^0.25.0", - "fdir": "^6.4.4", - "picomatch": "^4.0.2", - "postcss": "^8.5.3", - "rollup": "^4.34.9", - "tinyglobby": "^0.2.13" - }, - "bin": { - "vite": "bin/vite.js" - }, - "engines": { - "node": "^18.0.0 || ^20.0.0 || >=22.0.0" - }, - "funding": { - "url": "https://github.com/vitejs/vite?sponsor=1" - }, - "optionalDependencies": { - "fsevents": "~2.3.3" - }, - "peerDependencies": { - "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", - "jiti": ">=1.21.0", - "less": "*", - "lightningcss": "^1.21.0", - "sass": "*", - "sass-embedded": "*", - "stylus": "*", - "sugarss": "*", - "terser": "^5.16.0", - "tsx": "^4.8.1", - "yaml": "^2.4.2" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - }, - "jiti": { - "optional": true - }, - "less": { - "optional": true - }, - "lightningcss": { - "optional": true - }, - "sass": { - "optional": true - }, - "sass-embedded": { - "optional": true - }, - "stylus": { - "optional": true - }, - "sugarss": { - "optional": true - }, - "terser": { - "optional": true - }, - "tsx": { - "optional": true - }, - "yaml": { - "optional": true - } - } - } - } -} diff --git a/v3/examples/custom-protocol-example/frontend/package.json b/v3/examples/custom-protocol-example/frontend/package.json deleted file mode 100644 index 09086988e..000000000 --- a/v3/examples/custom-protocol-example/frontend/package.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "name": "frontend", - "private": true, - "version": "0.0.0", - "type": "module", - "scripts": { - "dev": "vite", - "build": "vite build", - "preview": "vite preview" - }, - "devDependencies": { - "vite": "^6.3.5" - }, - "dependencies": { - "@wailsio/runtime": "latest" - } -} diff --git a/v3/examples/custom-protocol-example/frontend/public/vite.svg b/v3/examples/custom-protocol-example/frontend/public/vite.svg deleted file mode 100644 index e7b8dfb1b..000000000 --- a/v3/examples/custom-protocol-example/frontend/public/vite.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/v3/examples/custom-protocol-example/frontend/src/counter.js b/v3/examples/custom-protocol-example/frontend/src/counter.js deleted file mode 100644 index 881e2d7ad..000000000 --- a/v3/examples/custom-protocol-example/frontend/src/counter.js +++ /dev/null @@ -1,9 +0,0 @@ -export function setupCounter(element) { - let counter = 0 - const setCounter = (count) => { - counter = count - element.innerHTML = `count is ${counter}` - } - element.addEventListener('click', () => setCounter(counter + 1)) - setCounter(0) -} diff --git a/v3/examples/custom-protocol-example/frontend/src/javascript.svg b/v3/examples/custom-protocol-example/frontend/src/javascript.svg deleted file mode 100644 index f9abb2b72..000000000 --- a/v3/examples/custom-protocol-example/frontend/src/javascript.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/v3/examples/custom-protocol-example/frontend/src/main.js b/v3/examples/custom-protocol-example/frontend/src/main.js deleted file mode 100644 index fd11d82fa..000000000 --- a/v3/examples/custom-protocol-example/frontend/src/main.js +++ /dev/null @@ -1,45 +0,0 @@ -import './style.css' -import { Events } from '@wailsio/runtime' - -document.addEventListener('DOMContentLoaded', () => { - const appDiv = document.getElementById('app'); - if (appDiv) { - appDiv.innerHTML = ` -
      -

      Custom Protocol / Deep Link Test

      -

      - This page demonstrates handling custom URL schemes (deep links). -

      -

      - Example Link: - Try opening this URL (e.g., by pasting it into your browser's address bar or using open your-app-scheme://... in terminal): -
      - wailsexample://test/path?value=123&message=hello -

      - -
      - Received URL: -
      Waiting for application to be opened via a custom URL...
      -
      -
      - `; - } else { - console.error('Element with ID "app" not found.'); - } -}); - -// Listen for the event from Go -Events.On('frontend:ShowURL', (e) => { - console.log('frontend:ShowURL event received, data:', e); - displayUrl(e.data); -}); - -// Make displayUrl available globally just in case, though direct call from event is better -window.displayUrl = function(url) { - const urlElement = document.getElementById('received-url'); - if (urlElement) { - urlElement.textContent = url || "No URL received or an error occurred."; - } else { - console.error("Element with ID 'received-url' not found in displayUrl."); - } -} diff --git a/v3/examples/custom-protocol-example/frontend/src/style.css b/v3/examples/custom-protocol-example/frontend/src/style.css deleted file mode 100644 index 0fb047c33..000000000 --- a/v3/examples/custom-protocol-example/frontend/src/style.css +++ /dev/null @@ -1,142 +0,0 @@ -:root { - font-family: system-ui, Avenir, Helvetica, Arial, sans-serif; - line-height: 1.5; - font-weight: 400; - - color-scheme: light dark; - color: rgba(255, 255, 255, 0.87); - background-color: #242424; - - font-synthesis: none; - text-rendering: optimizeLegibility; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; -} - -a { - font-weight: 500; - color: #646cff; - text-decoration: inherit; -} -a:hover { - color: #535bf2; -} - -body { - font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif; - margin: 0; /* Reset default margin */ - background-color: #f7f7f7; - color: #333; - display: flex; /* Use flexbox to center content */ - justify-content: center; /* Center horizontally */ - align-items: center; /* Center vertically */ - min-height: 100vh; /* Full viewport height */ - padding: 20px; /* Add some padding around the content */ - box-sizing: border-box; /* Ensure padding doesn't expand body beyond viewport */ -} - -h1 { - color: #0056b3; - font-size: 1.8em; - margin-bottom: 0.8em; -} - -#app { - width: 100%; - max-width: 600px; - margin: auto; /* This also helps in centering if body flex isn't enough or overridden */ -} - -.container { - background-color: #fff; - padding: 25px 30px; - border-radius: 8px; - box-shadow: 0 2px 10px rgba(0,0,0,0.1); - text-align: left; -} - -p { - line-height: 1.6; - font-size: 1em; - margin-bottom: 1em; -} - -a { - color: #007bff; - text-decoration: none; -} - -a:hover { - text-decoration: underline; -} - -.url-display { - margin-top: 25px; - padding: 15px; - background-color: #e9ecef; - border: 1px solid #ced4da; - border-radius: 4px; - font-family: 'Courier New', Courier, monospace; - font-size: 0.95em; - word-break: break-all; -} - -.label { - font-weight: bold; - display: block; - margin-bottom: 8px; - color: #495057; -} - -.logo { - height: 6em; - padding: 1.5em; - will-change: filter; - transition: filter 300ms; -} -.logo:hover { - filter: drop-shadow(0 0 2em #646cffaa); -} -.logo.vanilla:hover { - filter: drop-shadow(0 0 2em #f7df1eaa); -} - -.card { - padding: 2em; -} - -.read-the-docs { - color: #888; -} - -button { - border-radius: 8px; - border: 1px solid transparent; - padding: 0.6em 1.2em; - font-size: 1em; - font-weight: 500; - font-family: inherit; - background-color: #1a1a1a; - cursor: pointer; - transition: border-color 0.25s; -} -button:hover { - border-color: #646cff; -} -button:focus, -button:focus-visible { - outline: 4px auto -webkit-focus-ring-color; -} - -@media (prefers-color-scheme: light) { - :root { - color: #213547; - background-color: #ffffff; - } - a:hover { - color: #747bff; - } - button { - background-color: #f9f9f9; - } -} diff --git a/v3/examples/custom-protocol-example/greetservice.go b/v3/examples/custom-protocol-example/greetservice.go deleted file mode 100644 index 8972c39cd..000000000 --- a/v3/examples/custom-protocol-example/greetservice.go +++ /dev/null @@ -1,7 +0,0 @@ -package main - -type GreetService struct{} - -func (g *GreetService) Greet(name string) string { - return "Hello " + name + "!" -} diff --git a/v3/examples/custom-protocol-example/main.go b/v3/examples/custom-protocol-example/main.go deleted file mode 100644 index f5c5db38b..000000000 --- a/v3/examples/custom-protocol-example/main.go +++ /dev/null @@ -1,82 +0,0 @@ -package main - -import ( - "embed" - _ "embed" - "log" - "time" - - "github.com/wailsapp/wails/v3/pkg/application" - "github.com/wailsapp/wails/v3/pkg/events" -) - -// Wails uses Go's `embed` package to embed the frontend files into the binary. -// Any files in the frontend/dist folder will be embedded into the binary and -// made available to the frontend. -// See https://pkg.go.dev/embed for more information. - -//go:embed all:frontend/dist -var assets embed.FS - -// main function serves as the application's entry point. It initializes the application, creates a window, -// and starts a goroutine that emits a time-based event every second. It subsequently runs the application and -// logs any error that might occur. -func main() { - // Create a new Wails application by providing the necessary options. - // Variables 'Name' and 'Description' are for application metadata. - // 'Assets' configures the asset server with the 'FS' variable pointing to the frontend files. - // 'Bind' is a list of Go struct instances. The frontend has access to the methods of these instances. - // 'Mac' options tailor the application when running an macOS. - app := application.New(application.Options{ - Name: "custom-protocol-example", - Description: "A demo of using raw HTML & CSS", - Services: []application.Service{ - application.NewService(&GreetService{}), - }, - Assets: application.AssetOptions{ - Handler: application.AssetFileServerFS(assets), - }, - Mac: application.MacOptions{ - ApplicationShouldTerminateAfterLastWindowClosed: true, - }, - }) - - // Listen for the system event indicating the app was launched with a URL - app.Event.OnApplicationEvent(events.Common.ApplicationLaunchedWithUrl, func(e *application.ApplicationEvent) { - app.Event.Emit("frontend:ShowURL", e.Context().URL()) - }) - - // Create a new window with the necessary options. - // 'Title' is the title of the window. - // 'Mac' options tailor the window when running on macOS. - // 'BackgroundColour' is the background colour of the window. - // 'URL' is the URL that will be loaded into the webview. - _ = app.Window.NewWithOptions(application.WebviewWindowOptions{ - Title: "Window 1", - Mac: application.MacWindow{ - InvisibleTitleBarHeight: 50, - Backdrop: application.MacBackdropTranslucent, - TitleBar: application.MacTitleBarHiddenInset, - }, - BackgroundColour: application.NewRGB(27, 38, 54), - URL: "/", - }) - - // Create a goroutine that emits an event containing the current time every second. - // The frontend can listen to this event and update the UI accordingly. - go func() { - for { - now := time.Now().Format(time.RFC1123) - app.Event.Emit("time", now) - time.Sleep(time.Second) - } - }() - - // Run the application. This blocks until the application has been exited. - err := app.Run() - - // If an error occurred while running the application, log it and exit. - if err != nil { - log.Fatal(err) - } -} diff --git a/v3/examples/dev/.gitignore b/v3/examples/dev/.gitignore deleted file mode 100644 index c2a88322f..000000000 --- a/v3/examples/dev/.gitignore +++ /dev/null @@ -1 +0,0 @@ -.task \ No newline at end of file diff --git a/v3/examples/dev/README.md b/v3/examples/dev/README.md deleted file mode 100644 index 5dcc421f7..000000000 --- a/v3/examples/dev/README.md +++ /dev/null @@ -1,4 +0,0 @@ -# Dev Example - -**NOTE**: This example is currently a work in progress. It is not yet ready for use. - diff --git a/v3/examples/dev/Taskfile.yml b/v3/examples/dev/Taskfile.yml deleted file mode 100644 index 8d2d46716..000000000 --- a/v3/examples/dev/Taskfile.yml +++ /dev/null @@ -1,183 +0,0 @@ -version: '3' - -vars: - APP_NAME: "dev{{exeExt}}" - -tasks: - - pre-build: - summary: Pre-build hooks - - post-build: - summary: Post-build hooks - - install-frontend-deps: - summary: Install frontend dependencies - dir: frontend - sources: - - package.json - - package-lock.json - generates: - - node_modules/* - preconditions: - - sh: npm version - msg: "Looks like npm isn't installed. Npm is part of the Node installer: https://nodejs.org/en/download/" - cmds: - - npm install - - build-frontend: - summary: Build the frontend project - dir: frontend - sources: - - src/* - generates: - - dist/* - deps: - - install-frontend-deps - cmds: - - npm run build - - build:darwin: - summary: Builds the application - platforms: - - darwin - cmds: - - task: pre-build - - task: build-frontend - - go build -gcflags=all="-N -l" -o bin/{{.APP_NAME}} - - task: post-build - env: - CGO_CFLAGS: "-mmacosx-version-min=10.13" - CGO_LDFLAGS: "-mmacosx-version-min=10.13" - MACOSX_DEPLOYMENT_TARGET: "10.13" - - build:backend:darwin: - summary: Builds the application - platforms: - - darwin - cmds: - - task: pre-build - - go build -gcflags=all="-N -l" -o bin/{{.APP_NAME}} - - task: post-build - env: - CGO_CFLAGS: "-mmacosx-version-min=10.13" - CGO_LDFLAGS: "-mmacosx-version-min=10.13" - MACOSX_DEPLOYMENT_TARGET: "10.13" - - build:windows: - summary: Builds the application for Windows - platforms: - - windows - cmds: - - task: pre-build - - task: build-frontend - - go build -gcflags=all="-N -l" -o bin/{{.APP_NAME}} - - task: post-build - - - build:backend:windows: - summary: Builds the backend application for Windows - platforms: - - windows - cmds: - - task: pre-build - - go build -gcflags=all="-N -l" -o bin/{{.APP_NAME}} - - task: post-build - - build: - summary: Builds the application - watch: true - sources: - - main.go - cmds: - - task: build:darwin - - task: build:windows - - task: run - - build:backend: - summary: Builds the backend application - cmds: - - task: build:backend:darwin - - task: build:backend:windows - - generate-icons: - summary: Generates Windows `.ico` and Mac `.icns` files from an image - dir: build - cmds: - # Generates both .ico and .icns files - - wails generate icons -input appicon.png - - build-app-prod-darwin: - summary: Creates a production build of the application - cmds: - - task: pre-build - - task: build-frontend - - GOOS=darwin GOARCH={{.ARCH}} go build -tags production -ldflags="-w -s" -o build/bin/{{.APP_NAME}} - - task: post-build - env: - CGO_CFLAGS: "-mmacosx-version-min=10.13" - CGO_LDFLAGS: "-mmacosx-version-min=10.13" - MACOSX_DEPLOYMENT_TARGET: "10.13" - vars: - ARCH: $GOARCH - - frontend:dev: - summary: Runs the frontend in development mode - deps: - - task: install-frontend-deps - dir: frontend - cmds: - - npm run dev - - run: - summary: Runs the application - cmds: - - ./bin/{{.APP_NAME}} - - dev: - summary: Runs the application in development mode - watch: true - preconditions: - - sh: 'wails3 tool checkport -p 5173' - msg: "Vite does not appear to be running. Please run `wails3 task frontend:dev` in another terminal." - cmds: - - task: build:backend - - create-app-bundle: - summary: Builds a `.app` bundle - cmds: - - mkdir -p {{.APP_NAME}}.app/Contents/{MacOS,Resources} - - cp build/icons.icns {{.APP_NAME}}.app/Contents/Resources - - cp build/bin/{{.APP_NAME}} {{.APP_NAME}}.app/Contents/MacOS - - cp build/Info.plist {{.APP_NAME}}.app/Contents - - package-darwin-arm64: - summary: Packages a production build of the application into a `.app` bundle - platform: darwin - deps: - - task: build-app-prod-darwin - vars: - ARCH: arm64 - - generate-icons - cmds: - - task: create-app-bundle - - generate:syso: - dir: build - platform: windows - cmds: - - wails generate syso -arch {{.ARCH}} -icon icon.ico -manifest wails.exe.manifest -info info.json - vars: - ARCH: $GOARCH - - package:windows: - summary: Packages a production build of the application into a `.exe` bundle - platform: windows - deps: - - generate-icons - cmds: - - task: generate:syso - vars: - ARCH: amd64 - - go build -tags production -ldflags="-w -s -H windowsgui" -o bin/{{.APP_NAME}}.exe - - powershell Remove-item *.syso diff --git a/v3/examples/dev/build/Info.dev.plist b/v3/examples/dev/build/Info.dev.plist deleted file mode 100644 index 0c0ed6032..000000000 --- a/v3/examples/dev/build/Info.dev.plist +++ /dev/null @@ -1,32 +0,0 @@ - - - - CFBundlePackageType - APPL - CFBundleName - My Product Name - CFBundleExecutable - dev - CFBundleIdentifier - com.wails.dev - CFBundleVersion - v1.0.0 - CFBundleGetInfoString - This is a comment - CFBundleShortVersionString - v1.0.0 - CFBundleIconFile - icons - LSMinimumSystemVersion - 10.13.0 - NSHighResolutionCapable - true - NSHumanReadableCopyright - (c) 2023 My Company Name - NSAppTransportSecurity - - NSAllowsLocalNetworking - - - - \ No newline at end of file diff --git a/v3/examples/dev/build/Info.plist b/v3/examples/dev/build/Info.plist deleted file mode 100644 index f9ea24900..000000000 --- a/v3/examples/dev/build/Info.plist +++ /dev/null @@ -1,27 +0,0 @@ - - - - CFBundlePackageType - APPL - CFBundleName - My Product Name - CFBundleExecutable - dev - CFBundleIdentifier - com.wails.dev - CFBundleVersion - v1.0.0 - CFBundleGetInfoString - This is a comment - CFBundleShortVersionString - v1.0.0 - CFBundleIconFile - icons - LSMinimumSystemVersion - 10.13.0 - NSHighResolutionCapable - true - NSHumanReadableCopyright - (c) 2023 My Company Name - - \ No newline at end of file diff --git a/v3/examples/dev/build/appicon.png b/v3/examples/dev/build/appicon.png deleted file mode 100644 index 63617fe4f..000000000 Binary files a/v3/examples/dev/build/appicon.png and /dev/null differ diff --git a/v3/examples/dev/build/icons.icns b/v3/examples/dev/build/icons.icns deleted file mode 100644 index 1b5bd4c86..000000000 Binary files a/v3/examples/dev/build/icons.icns and /dev/null differ diff --git a/v3/examples/dev/frontend/dist/assets/index-3635012e.css b/v3/examples/dev/frontend/dist/assets/index-3635012e.css deleted file mode 100644 index 14cfb027f..000000000 --- a/v3/examples/dev/frontend/dist/assets/index-3635012e.css +++ /dev/null @@ -1 +0,0 @@ -:root{font-family:Inter,Avenir,Helvetica,Arial,sans-serif;font-size:16px;line-height:24px;font-weight:400;color-scheme:light dark;color:#ffffffde;background-color:#242424;font-synthesis:none;text-rendering:optimizeLegibility;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;-webkit-text-size-adjust:100%}a{font-weight:500;color:#646cff;text-decoration:inherit}a:hover{color:#535bf2}body{margin:0;display:flex;place-items:center;min-width:320px;min-height:100vh}h1{font-size:3.2em;line-height:1.1}.card{padding:2em}#app{max-width:1280px;margin:0 auto;padding:2rem;text-align:center}button{border-radius:8px;border:1px solid transparent;padding:.6em 1.2em;font-size:1em;font-weight:500;font-family:inherit;background-color:#1a1a1a;cursor:pointer;transition:border-color .25s}button:hover{border-color:#646cff}button:focus,button:focus-visible{outline:4px auto -webkit-focus-ring-color}@media (prefers-color-scheme: light){:root{color:#213547;background-color:#fff}a:hover{color:#747bff}button{background-color:#f9f9f9}}.logo.svelte-c9fbf7{height:6em;padding:1.5em;will-change:filter}.logo.svelte-c9fbf7:hover{filter:drop-shadow(0 0 2em #646cffaa)}.logo.svelte.svelte-c9fbf7:hover{filter:drop-shadow(0 0 2em #ff3e00aa)}.read-the-docs.svelte-c9fbf7{color:#888} diff --git a/v3/examples/dev/frontend/dist/assets/index-9076c63b.js b/v3/examples/dev/frontend/dist/assets/index-9076c63b.js deleted file mode 100644 index e2b665b28..000000000 --- a/v3/examples/dev/frontend/dist/assets/index-9076c63b.js +++ /dev/null @@ -1 +0,0 @@ -(function(){const t=document.createElement("link").relList;if(t&&t.supports&&t.supports("modulepreload"))return;for(const o of document.querySelectorAll('link[rel="modulepreload"]'))r(o);new MutationObserver(o=>{for(const s of o)if(s.type==="childList")for(const i of s.addedNodes)i.tagName==="LINK"&&i.rel==="modulepreload"&&r(i)}).observe(document,{childList:!0,subtree:!0});function n(o){const s={};return o.integrity&&(s.integrity=o.integrity),o.referrerPolicy&&(s.referrerPolicy=o.referrerPolicy),o.crossOrigin==="use-credentials"?s.credentials="include":o.crossOrigin==="anonymous"?s.credentials="omit":s.credentials="same-origin",s}function r(o){if(o.ep)return;o.ep=!0;const s=n(o);fetch(o.href,s)}})();function v(){}function I(e){return e()}function W(){return Object.create(null)}function A(e){e.forEach(I)}function K(e){return typeof e=="function"}function F(e,t){return e!=e?t==t:e!==t||e&&typeof e=="object"||typeof e=="function"}let S;function X(e,t){return S||(S=document.createElement("a")),S.href=t,e===S.href}function Y(e){return Object.keys(e).length===0}function c(e,t){e.appendChild(t)}function V(e,t,n){e.insertBefore(t,n||null)}function M(e){e.parentNode&&e.parentNode.removeChild(e)}function a(e){return document.createElement(e)}function k(e){return document.createTextNode(e)}function w(){return k(" ")}function Z(e,t,n,r){return e.addEventListener(t,n,r),()=>e.removeEventListener(t,n,r)}function u(e,t,n){n==null?e.removeAttribute(t):e.getAttribute(t)!==n&&e.setAttribute(t,n)}function ee(e){return Array.from(e.childNodes)}function te(e,t){t=""+t,e.data!==t&&(e.data=t)}let q;function E(e){q=e}const $=[],B=[];let y=[];const H=[],ne=Promise.resolve();let j=!1;function re(){j||(j=!0,ne.then(z))}function P(e){y.push(e)}const N=new Set;let g=0;function z(){if(g!==0)return;const e=q;do{try{for(;g<$.length;){const t=$[g];g++,E(t),oe(t.$$)}}catch(t){throw $.length=0,g=0,t}for(E(null),$.length=0,g=0;B.length;)B.pop()();for(let t=0;te.indexOf(r)===-1?t.push(r):n.push(r)),n.forEach(r=>r()),y=t}const C=new Set;let ie;function D(e,t){e&&e.i&&(C.delete(e),e.i(t))}function le(e,t,n,r){if(e&&e.o){if(C.has(e))return;C.add(e),ie.c.push(()=>{C.delete(e),r&&(n&&e.d(1),r())}),e.o(t)}else r&&r()}function ce(e){e&&e.c()}function G(e,t,n,r){const{fragment:o,after_update:s}=e.$$;o&&o.m(t,n),r||P(()=>{const i=e.$$.on_mount.map(I).filter(K);e.$$.on_destroy?e.$$.on_destroy.push(...i):A(i),e.$$.on_mount=[]}),s.forEach(P)}function J(e,t){const n=e.$$;n.fragment!==null&&(se(n.after_update),A(n.on_destroy),n.fragment&&n.fragment.d(t),n.on_destroy=n.fragment=null,n.ctx=[])}function fe(e,t){e.$$.dirty[0]===-1&&($.push(e),re(),e.$$.dirty.fill(0)),e.$$.dirty[t/31|0]|=1<{const _=x.length?x[0]:d;return l.ctx&&o(l.ctx[f],l.ctx[f]=_)&&(!l.skip_bound&&l.bound[f]&&l.bound[f](_),b&&fe(e,f)),d}):[],l.update(),b=!0,A(l.before_update),l.fragment=r?r(l.ctx):!1,t.target){if(t.hydrate){const f=ee(t.target);l.fragment&&l.fragment.l(f),f.forEach(M)}else l.fragment&&l.fragment.c();t.intro&&D(e.$$.fragment),G(e,t.target,t.anchor,t.customElement),z()}E(p)}class R{$destroy(){J(this,1),this.$destroy=v}$on(t,n){if(!K(n))return v;const r=this.$$.callbacks[t]||(this.$$.callbacks[t]=[]);return r.push(n),()=>{const o=r.indexOf(n);o!==-1&&r.splice(o,1)}}$set(t){this.$$set&&!Y(t)&&(this.$$.skip_bound=!0,this.$$set(t),this.$$.skip_bound=!1)}}const ue="/assets/svelte-a39f39b7.svg";function ae(e){let t,n,r,o,s;return{c(){t=a("button"),n=k("count is "),r=k(e[0])},m(i,h){V(i,t,h),c(t,n),c(t,r),o||(s=Z(t,"click",e[1]),o=!0)},p(i,[h]){h&1&&te(r,i[0])},i:v,o:v,d(i){i&&M(t),o=!1,s()}}}function de(e,t,n){let r=0;return[r,()=>{n(0,r+=1)}]}class he extends R{constructor(t){super(),Q(this,t,de,ae,F,{})}}function pe(e){let t,n,r,o,s,i,h,p,l,b,f,d,x,_,T,L,O;return d=new he({}),{c(){t=a("main"),n=a("div"),r=a("a"),r.innerHTML='',o=w(),s=a("a"),i=a("img"),p=w(),l=a("h1"),l.textContent="Wails + Svelte",b=w(),f=a("div"),ce(d.$$.fragment),x=w(),_=a("p"),_.innerHTML='Check out SvelteKit, the official Svelte app framework powered by Vite!',T=w(),L=a("p"),L.textContent="Click on the Wails and Svelte logos to learn more",u(r,"href","https://wails.io"),u(r,"target","_blank"),u(r,"rel","noreferrer"),X(i.src,h=ue)||u(i,"src",h),u(i,"class","logo svelte svelte-c9fbf7"),u(i,"alt","Svelte Logo"),u(s,"href","https://svelte.dev"),u(s,"target","_blank"),u(s,"rel","noreferrer"),u(f,"class","card"),u(L,"class","read-the-docs svelte-c9fbf7")},m(m,U){V(m,t,U),c(t,n),c(n,r),c(n,o),c(n,s),c(s,i),c(t,p),c(t,l),c(t,b),c(t,f),G(d,f,null),c(t,x),c(t,_),c(t,T),c(t,L),O=!0},p:v,i(m){O||(D(d.$$.fragment,m),O=!0)},o(m){le(d.$$.fragment,m),O=!1},d(m){m&&M(t),J(d)}}}class me extends R{constructor(t){super(),Q(this,t,null,pe,F,{})}}new me({target:document.getElementById("app")}); diff --git a/v3/examples/dev/frontend/dist/assets/svelte-a39f39b7.svg b/v3/examples/dev/frontend/dist/assets/svelte-a39f39b7.svg deleted file mode 100644 index c5e08481f..000000000 --- a/v3/examples/dev/frontend/dist/assets/svelte-a39f39b7.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/v3/examples/dev/frontend/dist/index.html b/v3/examples/dev/frontend/dist/index.html deleted file mode 100644 index c4380af7b..000000000 --- a/v3/examples/dev/frontend/dist/index.html +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - Wails + Svelte - - - - -
      - - - diff --git a/v3/examples/dev/frontend/dist/wails.png b/v3/examples/dev/frontend/dist/wails.png deleted file mode 100644 index 8bdf42483..000000000 Binary files a/v3/examples/dev/frontend/dist/wails.png and /dev/null differ diff --git a/v3/examples/dev/frontend/index.html b/v3/examples/dev/frontend/index.html deleted file mode 100644 index 1ea50f904..000000000 --- a/v3/examples/dev/frontend/index.html +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - Wails + Svelte - - -
      - - - diff --git a/v3/examples/dev/frontend/package-lock.json b/v3/examples/dev/frontend/package-lock.json deleted file mode 100644 index 309115bf9..000000000 --- a/v3/examples/dev/frontend/package-lock.json +++ /dev/null @@ -1,685 +0,0 @@ -{ - "name": "frontend", - "version": "0.0.0", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "frontend", - "version": "0.0.0", - "devDependencies": { - "@sveltejs/vite-plugin-svelte": "^2.0.0", - "svelte": "^3.54.0", - "vite": "^4.5.2" - } - }, - "node_modules/@esbuild/android-arm": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.18.20.tgz", - "integrity": "sha512-fyi7TDI/ijKKNZTUJAQqiG5T7YjJXgnzkURqmGj13C6dCqckZBLdl4h7bkhHt/t0WP+zO9/zwroDvANaOqO5Sw==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/android-arm64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.18.20.tgz", - "integrity": "sha512-Nz4rJcchGDtENV0eMKUNa6L12zz2zBDXuhj/Vjh18zGqB44Bi7MBMSXjgunJgjRhCmKOjnPuZp4Mb6OKqtMHLQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/android-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.18.20.tgz", - "integrity": "sha512-8GDdlePJA8D6zlZYJV/jnrRAi6rOiNaCC/JclcXpB+KIuvfBN4owLtgzY2bsxnx666XjJx2kDPUmnTtR8qKQUg==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/darwin-arm64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.18.20.tgz", - "integrity": "sha512-bxRHW5kHU38zS2lPTPOyuyTm+S+eobPUnTNkdJEfAddYgEcll4xkT8DB9d2008DtTbl7uJag2HuE5NZAZgnNEA==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/darwin-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.18.20.tgz", - "integrity": "sha512-pc5gxlMDxzm513qPGbCbDukOdsGtKhfxD1zJKXjCCcU7ju50O7MeAZ8c4krSJcOIJGFR+qx21yMMVYwiQvyTyQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/freebsd-arm64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.18.20.tgz", - "integrity": "sha512-yqDQHy4QHevpMAaxhhIwYPMv1NECwOvIpGCZkECn8w2WFHXjEwrBn3CeNIYsibZ/iZEUemj++M26W3cNR5h+Tw==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/freebsd-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.18.20.tgz", - "integrity": "sha512-tgWRPPuQsd3RmBZwarGVHZQvtzfEBOreNuxEMKFcd5DaDn2PbBxfwLcj4+aenoh7ctXcbXmOQIn8HI6mCSw5MQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-arm": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.18.20.tgz", - "integrity": "sha512-/5bHkMWnq1EgKr1V+Ybz3s1hWXok7mDFUMQ4cG10AfW3wL02PSZi5kFpYKrptDsgb2WAJIvRcDm+qIvXf/apvg==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-arm64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.18.20.tgz", - "integrity": "sha512-2YbscF+UL7SQAVIpnWvYwM+3LskyDmPhe31pE7/aoTMFKKzIc9lLbyGUpmmb8a8AixOL61sQ/mFh3jEjHYFvdA==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-ia32": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.18.20.tgz", - "integrity": "sha512-P4etWwq6IsReT0E1KHU40bOnzMHoH73aXp96Fs8TIT6z9Hu8G6+0SHSw9i2isWrD2nbx2qo5yUqACgdfVGx7TA==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-loong64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.18.20.tgz", - "integrity": "sha512-nXW8nqBTrOpDLPgPY9uV+/1DjxoQ7DoB2N8eocyq8I9XuqJ7BiAMDMf9n1xZM9TgW0J8zrquIb/A7s3BJv7rjg==", - "cpu": [ - "loong64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-mips64el": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.18.20.tgz", - "integrity": "sha512-d5NeaXZcHp8PzYy5VnXV3VSd2D328Zb+9dEq5HE6bw6+N86JVPExrA6O68OPwobntbNJ0pzCpUFZTo3w0GyetQ==", - "cpu": [ - "mips64el" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-ppc64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.18.20.tgz", - "integrity": "sha512-WHPyeScRNcmANnLQkq6AfyXRFr5D6N2sKgkFo2FqguP44Nw2eyDlbTdZwd9GYk98DZG9QItIiTlFLHJHjxP3FA==", - "cpu": [ - "ppc64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-riscv64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.18.20.tgz", - "integrity": "sha512-WSxo6h5ecI5XH34KC7w5veNnKkju3zBRLEQNY7mv5mtBmrP/MjNBCAlsM2u5hDBlS3NGcTQpoBvRzqBcRtpq1A==", - "cpu": [ - "riscv64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-s390x": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.18.20.tgz", - "integrity": "sha512-+8231GMs3mAEth6Ja1iK0a1sQ3ohfcpzpRLH8uuc5/KVDFneH6jtAJLFGafpzpMRO6DzJ6AvXKze9LfFMrIHVQ==", - "cpu": [ - "s390x" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.18.20.tgz", - "integrity": "sha512-UYqiqemphJcNsFEskc73jQ7B9jgwjWrSayxawS6UVFZGWrAAtkzjxSqnoclCXxWtfwLdzU+vTpcNYhpn43uP1w==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/netbsd-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.18.20.tgz", - "integrity": "sha512-iO1c++VP6xUBUmltHZoMtCUdPlnPGdBom6IrO4gyKPFFVBKioIImVooR5I83nTew5UOYrk3gIJhbZh8X44y06A==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/openbsd-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.18.20.tgz", - "integrity": "sha512-e5e4YSsuQfX4cxcygw/UCPIEP6wbIL+se3sxPdCiMbFLBWu0eiZOJ7WoD+ptCLrmjZBK1Wk7I6D/I3NglUGOxg==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/sunos-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.18.20.tgz", - "integrity": "sha512-kDbFRFp0YpTQVVrqUd5FTYmWo45zGaXe0X8E1G/LKFC0v8x0vWrhOWSLITcCn63lmZIxfOMXtCfti/RxN/0wnQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/win32-arm64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.18.20.tgz", - "integrity": "sha512-ddYFR6ItYgoaq4v4JmQQaAI5s7npztfV4Ag6NrhiaW0RrnOXqBkgwZLofVTlq1daVTQNhtI5oieTvkRPfZrePg==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/win32-ia32": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.18.20.tgz", - "integrity": "sha512-Wv7QBi3ID/rROT08SABTS7eV4hX26sVduqDOTe1MvGMjNd3EjOz4b7zeexIR62GTIEKrfJXKL9LFxTYgkyeu7g==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/win32-x64": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.18.20.tgz", - "integrity": "sha512-kTdfRcSiDfQca/y9QIkng02avJ+NCaQvrMejlsB3RRv5sE9rRoeBPISaZpKxHELzRxZyLvNts1P27W3wV+8geQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.4.15", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", - "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", - "dev": true - }, - "node_modules/@sveltejs/vite-plugin-svelte": { - "version": "2.4.5", - "resolved": "https://registry.npmjs.org/@sveltejs/vite-plugin-svelte/-/vite-plugin-svelte-2.4.5.tgz", - "integrity": "sha512-UJKsFNwhzCVuiZd06jM/psscyNJNDwjQC+qIeb7GBJK9iWeQCcIyfcPWDvbCudfcJggY9jtxJeeaZH7uny93FQ==", - "dev": true, - "dependencies": { - "@sveltejs/vite-plugin-svelte-inspector": "^1.0.3", - "debug": "^4.3.4", - "deepmerge": "^4.3.1", - "kleur": "^4.1.5", - "magic-string": "^0.30.2", - "svelte-hmr": "^0.15.3", - "vitefu": "^0.2.4" - }, - "engines": { - "node": "^14.18.0 || >= 16" - }, - "peerDependencies": { - "svelte": "^3.54.0 || ^4.0.0", - "vite": "^4.0.0" - } - }, - "node_modules/@sveltejs/vite-plugin-svelte-inspector": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@sveltejs/vite-plugin-svelte-inspector/-/vite-plugin-svelte-inspector-1.0.3.tgz", - "integrity": "sha512-Khdl5jmmPN6SUsVuqSXatKpQTMIifoQPDanaxC84m9JxIibWvSABJyHpyys0Z+1yYrxY5TTEQm+6elh0XCMaOA==", - "dev": true, - "dependencies": { - "debug": "^4.3.4" - }, - "engines": { - "node": "^14.18.0 || >= 16" - }, - "peerDependencies": { - "@sveltejs/vite-plugin-svelte": "^2.2.0", - "svelte": "^3.54.0 || ^4.0.0", - "vite": "^4.0.0" - } - }, - "node_modules/debug": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", - "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", - "dev": true, - "dependencies": { - "ms": "2.1.2" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/deepmerge": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", - "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/esbuild": { - "version": "0.18.20", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.18.20.tgz", - "integrity": "sha512-ceqxoedUrcayh7Y7ZX6NdbbDzGROiyVBgC4PriJThBKSVPWnnFHZAkfI1lJT8QFkOwH4qOS2SJkS4wvpGl8BpA==", - "dev": true, - "hasInstallScript": true, - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=12" - }, - "optionalDependencies": { - "@esbuild/android-arm": "0.18.20", - "@esbuild/android-arm64": "0.18.20", - "@esbuild/android-x64": "0.18.20", - "@esbuild/darwin-arm64": "0.18.20", - "@esbuild/darwin-x64": "0.18.20", - "@esbuild/freebsd-arm64": "0.18.20", - "@esbuild/freebsd-x64": "0.18.20", - "@esbuild/linux-arm": "0.18.20", - "@esbuild/linux-arm64": "0.18.20", - "@esbuild/linux-ia32": "0.18.20", - "@esbuild/linux-loong64": "0.18.20", - "@esbuild/linux-mips64el": "0.18.20", - "@esbuild/linux-ppc64": "0.18.20", - "@esbuild/linux-riscv64": "0.18.20", - "@esbuild/linux-s390x": "0.18.20", - "@esbuild/linux-x64": "0.18.20", - "@esbuild/netbsd-x64": "0.18.20", - "@esbuild/openbsd-x64": "0.18.20", - "@esbuild/sunos-x64": "0.18.20", - "@esbuild/win32-arm64": "0.18.20", - "@esbuild/win32-ia32": "0.18.20", - "@esbuild/win32-x64": "0.18.20" - } - }, - "node_modules/fsevents": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", - "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", - "dev": true, - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/kleur": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz", - "integrity": "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==", - "dev": true, - "engines": { - "node": ">=6" - } - }, - "node_modules/magic-string": { - "version": "0.30.2", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.2.tgz", - "integrity": "sha512-lNZdu7pewtq/ZvWUp9Wpf/x7WzMTsR26TWV03BRZrXFsv+BI6dy8RAiKgm1uM/kyR0rCfUcqvOlXKG66KhIGug==", - "dev": true, - "dependencies": { - "@jridgewell/sourcemap-codec": "^1.4.15" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - }, - "node_modules/nanoid": { - "version": "3.3.6", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.6.tgz", - "integrity": "sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "bin": { - "nanoid": "bin/nanoid.cjs" - }, - "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" - } - }, - "node_modules/picocolors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==", - "dev": true - }, - "node_modules/postcss": { - "version": "8.4.28", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.28.tgz", - "integrity": "sha512-Z7V5j0cq8oEKyejIKfpD8b4eBy9cwW2JWPk0+fB1HOAMsfHbnAXLLS+PfVWlzMSLQaWttKDt607I0XHmpE67Vw==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "dependencies": { - "nanoid": "^3.3.6", - "picocolors": "^1.0.0", - "source-map-js": "^1.0.2" - }, - "engines": { - "node": "^10 || ^12 || >=14" - } - }, - "node_modules/rollup": { - "version": "3.28.0", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.28.0.tgz", - "integrity": "sha512-d7zhvo1OUY2SXSM6pfNjgD5+d0Nz87CUp4mt8l/GgVP3oBsPwzNvSzyu1me6BSG9JIgWNTVcafIXBIyM8yQ3yw==", - "dev": true, - "bin": { - "rollup": "dist/bin/rollup" - }, - "engines": { - "node": ">=14.18.0", - "npm": ">=8.0.0" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - } - }, - "node_modules/source-map-js": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz", - "integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/svelte": { - "version": "3.59.2", - "resolved": "https://registry.npmjs.org/svelte/-/svelte-3.59.2.tgz", - "integrity": "sha512-vzSyuGr3eEoAtT/A6bmajosJZIUWySzY2CzB3w2pgPvnkUjGqlDnsNnA0PMO+mMAhuyMul6C2uuZzY6ELSkzyA==", - "dev": true, - "engines": { - "node": ">= 8" - } - }, - "node_modules/svelte-hmr": { - "version": "0.15.3", - "resolved": "https://registry.npmjs.org/svelte-hmr/-/svelte-hmr-0.15.3.tgz", - "integrity": "sha512-41snaPswvSf8TJUhlkoJBekRrABDXDMdpNpT2tfHIv4JuhgvHqLMhEPGtaQn0BmbNSTkuz2Ed20DF2eHw0SmBQ==", - "dev": true, - "engines": { - "node": "^12.20 || ^14.13.1 || >= 16" - }, - "peerDependencies": { - "svelte": "^3.19.0 || ^4.0.0" - } - }, - "node_modules/vite": { - "version": "4.5.5", - "resolved": "https://registry.npmjs.org/vite/-/vite-4.5.5.tgz", - "integrity": "sha512-ifW3Lb2sMdX+WU91s3R0FyQlAyLxOzCSCP37ujw0+r5POeHPwe6udWVIElKQq8gk3t7b8rkmvqC6IHBpCff4GQ==", - "dev": true, - "dependencies": { - "esbuild": "^0.18.10", - "postcss": "^8.4.27", - "rollup": "^3.27.1" - }, - "bin": { - "vite": "bin/vite.js" - }, - "engines": { - "node": "^14.18.0 || >=16.0.0" - }, - "funding": { - "url": "https://github.com/vitejs/vite?sponsor=1" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - }, - "peerDependencies": { - "@types/node": ">= 14", - "less": "*", - "lightningcss": "^1.21.0", - "sass": "*", - "stylus": "*", - "sugarss": "*", - "terser": "^5.4.0" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - }, - "less": { - "optional": true - }, - "lightningcss": { - "optional": true - }, - "sass": { - "optional": true - }, - "stylus": { - "optional": true - }, - "sugarss": { - "optional": true - }, - "terser": { - "optional": true - } - } - }, - "node_modules/vitefu": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/vitefu/-/vitefu-0.2.4.tgz", - "integrity": "sha512-fanAXjSaf9xXtOOeno8wZXIhgia+CZury481LsDaV++lSvcU2R9Ch2bPh3PYFyoHW+w9LqAeYRISVQjUIew14g==", - "dev": true, - "peerDependencies": { - "vite": "^3.0.0 || ^4.0.0" - }, - "peerDependenciesMeta": { - "vite": { - "optional": true - } - } - } - } -} diff --git a/v3/examples/dev/frontend/package.json b/v3/examples/dev/frontend/package.json deleted file mode 100644 index ed218cf99..000000000 --- a/v3/examples/dev/frontend/package.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "name": "frontend", - "private": true, - "version": "0.0.0", - "type": "module", - "scripts": { - "dev": "vite", - "build": "vite build", - "preview": "vite preview" - }, - "devDependencies": { - "@sveltejs/vite-plugin-svelte": "^2.0.0", - "svelte": "^3.54.0", - "vite": "^4.5.2" - } -} \ No newline at end of file diff --git a/v3/examples/dev/frontend/public/wails.png b/v3/examples/dev/frontend/public/wails.png deleted file mode 100644 index 8bdf42483..000000000 Binary files a/v3/examples/dev/frontend/public/wails.png and /dev/null differ diff --git a/v3/examples/dev/frontend/src/App.svelte b/v3/examples/dev/frontend/src/App.svelte deleted file mode 100644 index 539c395dd..000000000 --- a/v3/examples/dev/frontend/src/App.svelte +++ /dev/null @@ -1,45 +0,0 @@ - - -
      - -

      Wails + Svelte

      - -
      - -
      - -

      - Check out SvelteKit, the official Svelte app framework powered by Vite! -

      - -

      - Click on the Wails and Svelte logos to learn more -

      -
      - - diff --git a/v3/examples/dev/frontend/src/app.css b/v3/examples/dev/frontend/src/app.css deleted file mode 100644 index bcc7233dd..000000000 --- a/v3/examples/dev/frontend/src/app.css +++ /dev/null @@ -1,81 +0,0 @@ -:root { - font-family: Inter, Avenir, Helvetica, Arial, sans-serif; - font-size: 16px; - line-height: 24px; - font-weight: 400; - - color-scheme: light dark; - color: rgba(255, 255, 255, 0.87); - background-color: #242424; - - font-synthesis: none; - text-rendering: optimizeLegibility; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - -webkit-text-size-adjust: 100%; -} - -a { - font-weight: 500; - color: #646cff; - text-decoration: inherit; -} -a:hover { - color: #535bf2; -} - -body { - margin: 0; - display: flex; - place-items: center; - min-width: 320px; - min-height: 100vh; -} - -h1 { - font-size: 3.2em; - line-height: 1.1; -} - -.card { - padding: 2em; -} - -#app { - max-width: 1280px; - margin: 0 auto; - padding: 2rem; - text-align: center; -} - -button { - border-radius: 8px; - border: 1px solid transparent; - padding: 0.6em 1.2em; - font-size: 1em; - font-weight: 500; - font-family: inherit; - background-color: #1a1a1a; - cursor: pointer; - transition: border-color 0.25s; -} -button:hover { - border-color: #646cff; -} -button:focus, -button:focus-visible { - outline: 4px auto -webkit-focus-ring-color; -} - -@media (prefers-color-scheme: light) { - :root { - color: #213547; - background-color: #ffffff; - } - a:hover { - color: #747bff; - } - button { - background-color: #f9f9f9; - } -} diff --git a/v3/examples/dev/frontend/src/assets/svelte.svg b/v3/examples/dev/frontend/src/assets/svelte.svg deleted file mode 100644 index c5e08481f..000000000 --- a/v3/examples/dev/frontend/src/assets/svelte.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/v3/examples/dev/frontend/src/lib/Counter.svelte b/v3/examples/dev/frontend/src/lib/Counter.svelte deleted file mode 100644 index e45f90310..000000000 --- a/v3/examples/dev/frontend/src/lib/Counter.svelte +++ /dev/null @@ -1,10 +0,0 @@ - - - diff --git a/v3/examples/dev/frontend/src/main.js b/v3/examples/dev/frontend/src/main.js deleted file mode 100644 index 8a909a15a..000000000 --- a/v3/examples/dev/frontend/src/main.js +++ /dev/null @@ -1,8 +0,0 @@ -import './app.css' -import App from './App.svelte' - -const app = new App({ - target: document.getElementById('app'), -}) - -export default app diff --git a/v3/examples/dev/frontend/src/vite-env.d.ts b/v3/examples/dev/frontend/src/vite-env.d.ts deleted file mode 100644 index 4078e7476..000000000 --- a/v3/examples/dev/frontend/src/vite-env.d.ts +++ /dev/null @@ -1,2 +0,0 @@ -/// -/// diff --git a/v3/examples/dev/frontend/tsconfig.json b/v3/examples/dev/frontend/tsconfig.json deleted file mode 100644 index b3e8a23aa..000000000 --- a/v3/examples/dev/frontend/tsconfig.json +++ /dev/null @@ -1,34 +0,0 @@ -{ - "compilerOptions": { - "allowJs": true, - "moduleResolution": "Node", - "target": "ESNext", - "module": "ESNext", - /** - * svelte-preprocess cannot figure out whether you have - * a value or a type, so tell TypeScript to enforce using - * `import type` instead of `import` for Types. - */ - "importsNotUsedAsValues": "error", - "isolatedModules": true, - "resolveJsonModule": true, - /** - * To have warnings / errors of the Svelte compiler at the - * correct position, enable source maps by default. - */ - "sourceMap": true, - "esModuleInterop": true, - "skipLibCheck": true, - "forceConsistentCasingInFileNames": true, - /** - * Typecheck JS in `.svelte` and `.js` files by default. - * Disable this if you'd like to use dynamic types. - */ - "checkJs": true - }, - /** - * Use global.d.ts instead of compilerOptions.types - * to avoid limiting type declarations. - */ - "include": ["src/**/*.d.ts", "src/**/*.js", "src/**/*.svelte", "bindings"] -} diff --git a/v3/examples/dev/frontend/vite.config.js b/v3/examples/dev/frontend/vite.config.js deleted file mode 100644 index d70196943..000000000 --- a/v3/examples/dev/frontend/vite.config.js +++ /dev/null @@ -1,7 +0,0 @@ -import { defineConfig } from 'vite' -import { svelte } from '@sveltejs/vite-plugin-svelte' - -// https://vitejs.dev/config/ -export default defineConfig({ - plugins: [svelte()], -}) diff --git a/v3/examples/dev/go.mod b/v3/examples/dev/go.mod deleted file mode 100644 index 296394de3..000000000 --- a/v3/examples/dev/go.mod +++ /dev/null @@ -1,49 +0,0 @@ -module changeme - -go 1.25 - -require github.com/wailsapp/wails/v3 v3.0.0-alpha.62 - -require ( - dario.cat/mergo v1.0.2 // indirect - github.com/Microsoft/go-winio v0.6.2 // indirect - github.com/ProtonMail/go-crypto v1.3.0 // indirect - github.com/adrg/xdg v0.5.3 // indirect - github.com/bep/debounce v1.2.1 // indirect - github.com/cloudflare/circl v1.6.3 // indirect - github.com/coder/websocket v1.8.14 // indirect - github.com/cyphar/filepath-securejoin v0.6.1 // indirect - github.com/ebitengine/purego v0.9.1 // indirect - github.com/emirpasic/gods v1.18.1 // indirect - github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect - github.com/go-git/go-billy/v5 v5.7.0 // indirect - github.com/go-git/go-git/v5 v5.16.4 // indirect - github.com/go-ole/go-ole v1.3.0 // indirect - github.com/godbus/dbus/v5 v5.2.2 // indirect - github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect - github.com/google/uuid v1.6.0 // indirect - github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect - github.com/jchv/go-winloader v0.0.0-20250406163304-c1995be93bd1 // indirect - github.com/kevinburke/ssh_config v1.4.0 // indirect - github.com/klauspost/cpuid/v2 v2.3.0 // indirect - github.com/leaanthony/go-ansi-parser v1.6.1 // indirect - github.com/leaanthony/u v1.1.1 // indirect - github.com/lmittmann/tint v1.1.2 // indirect - github.com/mattn/go-colorable v0.1.14 // indirect - github.com/mattn/go-isatty v0.0.20 // indirect - github.com/pjbgf/sha1cd v0.5.0 // indirect - github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c // indirect - github.com/rivo/uniseg v0.4.7 // indirect - github.com/samber/lo v1.52.0 // indirect - github.com/sergi/go-diff v1.4.0 // indirect - github.com/skeema/knownhosts v1.3.2 // indirect - github.com/wailsapp/go-webview2 v1.0.23 // indirect - github.com/xanzy/ssh-agent v0.3.3 // indirect - golang.org/x/crypto v0.47.0 // indirect - golang.org/x/net v0.49.0 // indirect - golang.org/x/sys v0.40.0 // indirect - golang.org/x/text v0.33.0 // indirect - gopkg.in/warnings.v0 v0.1.2 // indirect -) - -replace github.com/wailsapp/wails/v3 => ../.. diff --git a/v3/examples/dev/go.sum b/v3/examples/dev/go.sum deleted file mode 100644 index 56f1153ea..000000000 --- a/v3/examples/dev/go.sum +++ /dev/null @@ -1,147 +0,0 @@ -dario.cat/mergo v1.0.2 h1:85+piFYR1tMbRrLcDwR18y4UKJ3aH1Tbzi24VRW1TK8= -dario.cat/mergo v1.0.2/go.mod h1:E/hbnu0NxMFBjpMIE34DRGLWqDy0g5FuKDhCb31ngxA= -github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY= -github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= -github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= -github.com/ProtonMail/go-crypto v1.3.0 h1:ILq8+Sf5If5DCpHQp4PbZdS1J7HDFRXz/+xKBiRGFrw= -github.com/ProtonMail/go-crypto v1.3.0/go.mod h1:9whxjD8Rbs29b4XWbB8irEcE8KHMqaR2e7GWU1R+/PE= -github.com/adrg/xdg v0.5.3 h1:xRnxJXne7+oWDatRhR1JLnvuccuIeCoBu2rtuLqQB78= -github.com/adrg/xdg v0.5.3/go.mod h1:nlTsY+NNiCBGCK2tpm09vRqfVzrc2fLmXGpBLF0zlTQ= -github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8= -github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4= -github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= -github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= -github.com/bep/debounce v1.2.1 h1:v67fRdBA9UQu2NhLFXrSg0Brw7CexQekrBwDMM8bzeY= -github.com/bep/debounce v1.2.1/go.mod h1:H8yggRPQKLUhUoqrJC1bO2xNya7vanpDl7xR3ISbCJ0= -github.com/cloudflare/circl v1.6.3 h1:9GPOhQGF9MCYUeXyMYlqTR6a5gTrgR/fBLXvUgtVcg8= -github.com/cloudflare/circl v1.6.3/go.mod h1:2eXP6Qfat4O/Yhh8BznvKnJ+uzEoTQ6jVKJRn81BiS4= -github.com/coder/websocket v1.8.14 h1:9L0p0iKiNOibykf283eHkKUHHrpG7f65OE3BhhO7v9g= -github.com/coder/websocket v1.8.14/go.mod h1:NX3SzP+inril6yawo5CQXx8+fk145lPDC6pumgx0mVg= -github.com/cyphar/filepath-securejoin v0.6.1 h1:5CeZ1jPXEiYt3+Z6zqprSAgSWiggmpVyciv8syjIpVE= -github.com/cyphar/filepath-securejoin v0.6.1/go.mod h1:A8hd4EnAeyujCJRrICiOWqjS1AX0a9kM5XL+NwKoYSc= -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= -github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/ebitengine/purego v0.9.1 h1:a/k2f2HQU3Pi399RPW1MOaZyhKJL9w/xFpKAg4q1s0A= -github.com/ebitengine/purego v0.9.1/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ= -github.com/elazarl/goproxy v1.7.2 h1:Y2o6urb7Eule09PjlhQRGNsqRfPmYI3KKQLFpCAV3+o= -github.com/elazarl/goproxy v1.7.2/go.mod h1:82vkLNir0ALaW14Rc399OTTjyNREgmdL2cVoIbS6XaE= -github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc= -github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ= -github.com/gliderlabs/ssh v0.3.8 h1:a4YXD1V7xMF9g5nTkdfnja3Sxy1PVDCj1Zg4Wb8vY6c= -github.com/gliderlabs/ssh v0.3.8/go.mod h1:xYoytBv1sV0aL3CavoDuJIQNURXkkfPA/wxQ1pL1fAU= -github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI= -github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmSxCcxctByoQdvwPiA7DTK7jaaFDBTtu0ic= -github.com/go-git/go-billy/v5 v5.7.0 h1:83lBUJhGWhYp0ngzCMSgllhUSuoHP1iEWYjsPl9nwqM= -github.com/go-git/go-billy/v5 v5.7.0/go.mod h1:/1IUejTKH8xipsAcdfcSAlUlo2J7lkYV8GTKxAT/L3E= -github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399 h1:eMje31YglSBqCdIqdhKBW8lokaMrL3uTkpGYlE2OOT4= -github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399/go.mod h1:1OCfN199q1Jm3HZlxleg+Dw/mwps2Wbk9frAWm+4FII= -github.com/go-git/go-git/v5 v5.16.4 h1:7ajIEZHZJULcyJebDLo99bGgS0jRrOxzZG4uCk2Yb2Y= -github.com/go-git/go-git/v5 v5.16.4/go.mod h1:4Ge4alE/5gPs30F2H1esi2gPd69R0C39lolkucHBOp8= -github.com/go-json-experiment/json v0.0.0-20251027170946-4849db3c2f7e h1:Lf/gRkoycfOBPa42vU2bbgPurFong6zXeFtPoxholzU= -github.com/go-json-experiment/json v0.0.0-20251027170946-4849db3c2f7e/go.mod h1:uNVvRXArCGbZ508SxYYTC5v1JWoz2voff5pm25jU1Ok= -github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE= -github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78= -github.com/godbus/dbus/v5 v5.2.2 h1:TUR3TgtSVDmjiXOgAAyaZbYmIeP3DPkld3jgKGV8mXQ= -github.com/godbus/dbus/v5 v5.2.2/go.mod h1:3AAv2+hPq5rdnr5txxxRwiGjPXamgoIHgz9FPBfOp3c= -github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 h1:f+oWsMOmNPc8JmEHVZIycC7hBoQxHH9pNKQORJNozsQ= -github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8/go.mod h1:wcDNUvekVysuuOpQKo3191zZyTpiI6se1N1ULghS0sw= -github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= -github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= -github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= -github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A= -github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= -github.com/jchv/go-winloader v0.0.0-20250406163304-c1995be93bd1 h1:njuLRcjAuMKr7kI3D85AXWkw6/+v9PwtV6M6o11sWHQ= -github.com/jchv/go-winloader v0.0.0-20250406163304-c1995be93bd1/go.mod h1:alcuEEnZsY1WQsagKhZDsoPCRoOijYqhZvPwLG0kzVs= -github.com/kevinburke/ssh_config v1.4.0 h1:6xxtP5bZ2E4NF5tuQulISpTO2z8XbtH8cg1PWkxoFkQ= -github.com/kevinburke/ssh_config v1.4.0/go.mod h1:q2RIzfka+BXARoNexmF9gkxEX7DmvbW9P4hIVx2Kg4M= -github.com/klauspost/cpuid/v2 v2.3.0 h1:S4CRMLnYUhGeDFDqkGriYKdfoFlDnMtqTiI/sFzhA9Y= -github.com/klauspost/cpuid/v2 v2.3.0/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0= -github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= -github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= -github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= -github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= -github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/leaanthony/go-ansi-parser v1.6.1 h1:xd8bzARK3dErqkPFtoF9F3/HgN8UQk0ed1YDKpEz01A= -github.com/leaanthony/go-ansi-parser v1.6.1/go.mod h1:+vva/2y4alzVmmIEpk9QDhA7vLC5zKDTRwfZGOp3IWU= -github.com/leaanthony/u v1.1.1 h1:TUFjwDGlNX+WuwVEzDqQwC2lOv0P4uhTQw7CMFdiK7M= -github.com/leaanthony/u v1.1.1/go.mod h1:9+o6hejoRljvZ3BzdYlVL0JYCwtnAsVuN9pVTQcaRfI= -github.com/lmittmann/tint v1.1.2 h1:2CQzrL6rslrsyjqLDwD11bZ5OpLBPU+g3G/r5LSfS8w= -github.com/lmittmann/tint v1.1.2/go.mod h1:HIS3gSy7qNwGCj+5oRjAutErFBl4BzdQP6cJZ0NfMwE= -github.com/matryer/is v1.4.0/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwMRU= -github.com/matryer/is v1.4.1 h1:55ehd8zaGABKLXQUe2awZ99BD/PTc2ls+KV/dXphgEQ= -github.com/matryer/is v1.4.1/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwMRU= -github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE= -github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8= -github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= -github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= -github.com/onsi/gomega v1.34.1 h1:EUMJIKUjM8sKjYbtxQI9A4z2o+rruxnzNvpknOXie6k= -github.com/onsi/gomega v1.34.1/go.mod h1:kU1QgUvBDLXBJq618Xvm2LUX6rSAfRaFRTcdOeDLwwY= -github.com/pjbgf/sha1cd v0.5.0 h1:a+UkboSi1znleCDUNT3M5YxjOnN1fz2FhN48FlwCxs0= -github.com/pjbgf/sha1cd v0.5.0/go.mod h1:lhpGlyHLpQZoxMv8HcgXvZEhcGs0PG/vsZnEJ7H0iCM= -github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmdv1U2eRNDiU2ErMBj1gwrq8eQ= -github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c/go.mod h1:7rwL4CYBLnjLxUqIJNnCWiEdr3bn6IUYi15bNlnbCCU= -github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= -github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= -github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= -github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= -github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= -github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= -github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= -github.com/samber/lo v1.52.0 h1:Rvi+3BFHES3A8meP33VPAxiBZX/Aws5RxrschYGjomw= -github.com/samber/lo v1.52.0/go.mod h1:4+MXEGsJzbKGaUEQFKBq2xtfuznW9oz/WrgyzMzRoM0= -github.com/sergi/go-diff v1.4.0 h1:n/SP9D5ad1fORl+llWyN+D6qoUETXNZARKjyY2/KVCw= -github.com/sergi/go-diff v1.4.0/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4= -github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= -github.com/skeema/knownhosts v1.3.2 h1:EDL9mgf4NzwMXCTfaxSD/o/a5fxDw/xL9nkU28JjdBg= -github.com/skeema/knownhosts v1.3.2/go.mod h1:bEg3iQAuw+jyiw+484wwFJoKSLwcfd7fqRy+N0QTiow= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= -github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= -github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= -github.com/wailsapp/go-webview2 v1.0.23 h1:jmv8qhz1lHibCc79bMM/a/FqOnnzOGEisLav+a0b9P0= -github.com/wailsapp/go-webview2 v1.0.23/go.mod h1:qJmWAmAmaniuKGZPWwne+uor3AHMB5PFhqiK0Bbj8kc= -github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM= -github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw= -golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.47.0 h1:V6e3FRj+n4dbpw86FJ8Fv7XVOql7TEwpHapKoMJ/GO8= -golang.org/x/crypto v0.47.0/go.mod h1:ff3Y9VzzKbwSSEzWqJsJVBnWmRwRSHt/6Op5n9bQc4A= -golang.org/x/exp v0.0.0-20260112195511-716be5621a96 h1:Z/6YuSHTLOHfNFdb8zVZomZr7cqNgTJvA8+Qz75D8gU= -golang.org/x/exp v0.0.0-20260112195511-716be5621a96/go.mod h1:nzimsREAkjBCIEFtHiYkrJyT+2uy9YZJB7H1k68CXZU= -golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.49.0 h1:eeHFmOGUTtaaPSGNmjBKpbng9MulQsJURQUAfUwY++o= -golang.org/x/net v0.49.0/go.mod h1:/ysNB2EvaqvesRkuLAyjI1ycPZlQHM3q01F02UY/MV8= -golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200810151505-1b9f1253b3ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.40.0 h1:DBZZqJ2Rkml6QMQsZywtnjnnGvHza6BTfYFWY9kjEWQ= -golang.org/x/sys v0.40.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= -golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.39.0 h1:RclSuaJf32jOqZz74CkPA9qFuVTX7vhLlpfj/IGWlqY= -golang.org/x/term v0.39.0/go.mod h1:yxzUCTP/U+FzoxfdKmLaA0RV1WgE0VY7hXBwKtY/4ww= -golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.33.0 h1:B3njUFyqtHDUI5jMn1YIr5B0IE2U0qck04r6d4KPAxE= -golang.org/x/text v0.33.0/go.mod h1:LuMebE6+rBincTi9+xWTY8TztLzKHc/9C1uBCG27+q8= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= -gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME= -gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= -gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= -gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= -gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/v3/examples/dev/main.go b/v3/examples/dev/main.go deleted file mode 100644 index 111273721..000000000 --- a/v3/examples/dev/main.go +++ /dev/null @@ -1,43 +0,0 @@ -package main - -import ( - "embed" - _ "embed" - "log" - - "github.com/wailsapp/wails/v3/pkg/application" -) - -//go:embed frontend/dist -var assets embed.FS - -func main() { - app := application.New(application.Options{ - Name: "dev", - Description: "A demo of using raw HTML & CSS", - Assets: application.AssetOptions{ - Handler: application.AssetFileServerFS(assets), - }, - Mac: application.MacOptions{ - ApplicationShouldTerminateAfterLastWindowClosed: true, - }, - }) - // Create window - app.Window.NewWithOptions(application.WebviewWindowOptions{ - Title: "Plain Bundle", - CSS: `body { background-color: rgba(255, 255, 255, 0); } .main { color: white; margin: 20%; }`, - Mac: application.MacWindow{ - InvisibleTitleBarHeight: 50, - Backdrop: application.MacBackdropTranslucent, - TitleBar: application.MacTitleBarHiddenInset, - }, - - URL: "/", - }) - - err := app.Run() - - if err != nil { - log.Fatal(err) - } -} diff --git a/v3/examples/dialogs-basic/.hidden_file b/v3/examples/dialogs-basic/.hidden_file deleted file mode 100644 index e69de29bb..000000000 diff --git a/v3/examples/dialogs-basic/README.md b/v3/examples/dialogs-basic/README.md deleted file mode 100644 index c03911376..000000000 --- a/v3/examples/dialogs-basic/README.md +++ /dev/null @@ -1,36 +0,0 @@ -# Dialog Test Application - -This application is designed to test macOS file dialog functionality across different versions of macOS. It provides a comprehensive suite of tests for various dialog features and configurations. - -## Features Tested - -1. Basic file open dialog -2. Single extension filter -3. Multiple extension filter -4. Multiple file selection -5. Directory selection -6. Save dialog with extension -7. Complex filters -8. Hidden files -9. Default directory -10. Full featured dialog with all options - -## Running the Tests - -```bash -go run main.go -``` - -## Test Results - -When running tests: -- Each test will show the selected file(s) and their types -- For multiple selections, all selected files will be listed -- Errors will be displayed in an error dialog -- The application logs debug information to help track issues - -## Notes - -- This test application is primarily for development and testing purposes -- It can be used to verify dialog behavior across different macOS versions -- The tests are designed to not interfere with CI pipelines diff --git a/v3/examples/dialogs-basic/main.go b/v3/examples/dialogs-basic/main.go deleted file mode 100644 index 0b47b34b3..000000000 --- a/v3/examples/dialogs-basic/main.go +++ /dev/null @@ -1,257 +0,0 @@ -package main - -import ( - "fmt" - "log" - "log/slog" - "os" - "path/filepath" - "runtime" - "strings" - - "github.com/wailsapp/wails/v3/pkg/application" -) - -func main() { - app := application.New(application.Options{ - Name: "Dialog Test", - Description: "Test application for macOS dialogs", - Logger: application.DefaultLogger(slog.LevelDebug), - Mac: application.MacOptions{ - ApplicationShouldTerminateAfterLastWindowClosed: true, - }, - }) - - // Create main window - mainWindow := app.Window.NewWithOptions(application.WebviewWindowOptions{ - Title: "Dialog Tests", - Width: 800, - Height: 600, - MinWidth: 800, - MinHeight: 600, - }) - mainWindow.SetAlwaysOnTop(true) - - // Create main menu - menu := app.NewMenu() - app.Menu.Set(menu) - menu.AddRole(application.AppMenu) - menu.AddRole(application.EditMenu) - menu.AddRole(application.WindowMenu) - - // Add test menu - testMenu := menu.AddSubmenu("Tests") - - // Test 1: Basic file open with no filters (no window) - testMenu.Add("1. Basic Open (No Window)").OnClick(func(ctx *application.Context) { - result, err := app.Dialog.OpenFile(). - CanChooseFiles(true). - PromptForSingleSelection() - showResult("Basic Open", result, err, nil) - }) - - // Test 1b: Basic file open with window - testMenu.Add("1b. Basic Open (With Window)").OnClick(func(ctx *application.Context) { - result, err := app.Dialog.OpenFile(). - CanChooseFiles(true). - AttachToWindow(mainWindow). - PromptForSingleSelection() - showResult("Basic Open", result, err, mainWindow) - }) - - // Test 2: Open with single extension filter - testMenu.Add("2. Single Filter").OnClick(func(ctx *application.Context) { - result, err := app.Dialog.OpenFile(). - CanChooseFiles(true). - AddFilter("Text Files", "*.txt"). - AttachToWindow(mainWindow). - PromptForSingleSelection() - showResult("Single Filter", result, err, mainWindow) - }) - - // Test 3: Open with multiple extension filter - testMenu.Add("3. Multiple Filter").OnClick(func(ctx *application.Context) { - result, err := app.Dialog.OpenFile(). - CanChooseFiles(true). - AddFilter("Documents", "*.txt;*.md;*.doc;*.docx"). - AttachToWindow(mainWindow). - PromptForSingleSelection() - showResult("Multiple Filter", result, err, mainWindow) - }) - - // Test 4: Multiple file selection - testMenu.Add("4. Multiple Selection").OnClick(func(ctx *application.Context) { - results, err := app.Dialog.OpenFile(). - CanChooseFiles(true). - AddFilter("Images", "*.png;*.jpg;*.jpeg"). - AttachToWindow(mainWindow). - PromptForMultipleSelection() - if err != nil { - showError("Multiple Selection", err, mainWindow) - return - } - showResults("Multiple Selection", results, mainWindow) - }) - - // Test 5: Directory selection - testMenu.Add("5. Directory Selection").OnClick(func(ctx *application.Context) { - result, err := app.Dialog.OpenFile(). - CanChooseDirectories(true). - CanChooseFiles(false). - AttachToWindow(mainWindow). - PromptForSingleSelection() - showResult("Directory Selection", result, err, mainWindow) - }) - - // Test 6: Save dialog with extension - testMenu.Add("6. Save Dialog").OnClick(func(ctx *application.Context) { - result, err := app.Dialog.SaveFile(). - SetFilename("test.txt"). - AddFilter("Text Files", "*.txt"). - AttachToWindow(mainWindow). - PromptForSingleSelection() - showResult("Save Dialog", result, err, mainWindow) - }) - - // Test 7: Complex filters - testMenu.Add("7. Complex Filters").OnClick(func(ctx *application.Context) { - result, err := app.Dialog.OpenFile(). - CanChooseFiles(true). - AddFilter("All Documents", "*.txt;*.md;*.doc;*.docx;*.pdf"). - AddFilter("Text Files", "*.txt"). - AddFilter("Markdown", "*.md"). - AddFilter("Word Documents", "*.doc;*.docx"). - AddFilter("PDF Files", "*.pdf"). - AttachToWindow(mainWindow). - PromptForSingleSelection() - showResult("Complex Filters", result, err, mainWindow) - }) - - // Test 8: Hidden files - testMenu.Add("8. Show Hidden").OnClick(func(ctx *application.Context) { - result, err := app.Dialog.OpenFile(). - CanChooseFiles(true). - ShowHiddenFiles(true). - AttachToWindow(mainWindow). - PromptForSingleSelection() - showResult("Show Hidden", result, err, mainWindow) - }) - - // Test 9: Default directory - testMenu.Add("9. Default Directory").OnClick(func(ctx *application.Context) { - home, _ := os.UserHomeDir() - result, err := app.Dialog.OpenFile(). - CanChooseFiles(true). - SetDirectory(home). - AttachToWindow(mainWindow). - PromptForSingleSelection() - showResult("Default Directory", result, err, mainWindow) - }) - - // Test 10: Full featured dialog - testMenu.Add("10. Full Featured").OnClick(func(ctx *application.Context) { - home, _ := os.UserHomeDir() - dialog := app.Dialog.OpenFile(). - SetTitle("Full Featured Dialog"). - SetDirectory(home). - CanChooseFiles(true). - CanCreateDirectories(true). - ShowHiddenFiles(true). - ResolvesAliases(true). - AllowsOtherFileTypes(true). - AttachToWindow(mainWindow) - - if runtime.GOOS == "darwin" { - dialog.SetMessage("Please select files") - } - - dialog.AddFilter("All Supported", "*.txt;*.md;*.pdf;*.png;*.jpg") - dialog.AddFilter("Documents", "*.txt;*.md;*.pdf") - dialog.AddFilter("Images", "*.png;*.jpg;*.jpeg") - - results, err := dialog.PromptForMultipleSelection() - if err != nil { - showError("Full Featured", err, mainWindow) - return - } - showResults("Full Featured", results, mainWindow) - }) - - // Show the window - mainWindow.Show() - - // Run the app - if err := app.Run(); err != nil { - log.Fatal(err) - } -} - -func showResult(test string, result string, err error, window *application.WebviewWindow) { - if err != nil { - showError(test, err, window) - return - } - if result == "" { - dialog := application.Get().Dialog.Info(). - SetTitle(test). - SetMessage("No file selected") - if window != nil { - dialog.AttachToWindow(window) - } - dialog.Show() - return - } - dialog := application.Get().Dialog.Info(). - SetTitle(test). - SetMessage(fmt.Sprintf("Selected: %s\nType: %s", result, getFileType(result))) - if window != nil { - dialog.AttachToWindow(window) - } - dialog.Show() -} - -func showResults(test string, results []string, window *application.WebviewWindow) { - if len(results) == 0 { - dialog := application.Get().Dialog.Info(). - SetTitle(test). - SetMessage("No files selected") - if window != nil { - dialog.AttachToWindow(window) - } - dialog.Show() - return - } - var message strings.Builder - message.WriteString(fmt.Sprintf("Selected %d files:\n\n", len(results))) - for _, result := range results { - message.WriteString(fmt.Sprintf("%s (%s)\n", result, getFileType(result))) - } - dialog := application.Get().Dialog.Info(). - SetTitle(test). - SetMessage(message.String()) - if window != nil { - dialog.AttachToWindow(window) - } - dialog.Show() -} - -func showError(test string, err error, window *application.WebviewWindow) { - dialog := application.Get().Dialog.Error(). - SetTitle(test). - SetMessage(fmt.Sprintf("Error: %v", err)) - if window != nil { - dialog.AttachToWindow(window) - } - dialog.Show() -} - -func getFileType(path string) string { - if path == "" { - return "unknown" - } - ext := filepath.Ext(path) - if ext == "" { - return "no extension" - } - return ext -} diff --git a/v3/examples/dialogs-basic/test.txt b/v3/examples/dialogs-basic/test.txt deleted file mode 100644 index 64b89ccaf..000000000 --- a/v3/examples/dialogs-basic/test.txt +++ /dev/null @@ -1 +0,0 @@ -This is a sample text file to test filtering. \ No newline at end of file diff --git a/v3/examples/dialogs-basic/wails-logo-small.jpg b/v3/examples/dialogs-basic/wails-logo-small.jpg deleted file mode 100644 index 29cb1129e..000000000 Binary files a/v3/examples/dialogs-basic/wails-logo-small.jpg and /dev/null differ diff --git a/v3/examples/dialogs-basic/wails-logo-small.png b/v3/examples/dialogs-basic/wails-logo-small.png deleted file mode 100644 index cbd40bf90..000000000 Binary files a/v3/examples/dialogs-basic/wails-logo-small.png and /dev/null differ diff --git a/v3/examples/dialogs/README.md b/v3/examples/dialogs/README.md deleted file mode 100644 index d80afc91a..000000000 --- a/v3/examples/dialogs/README.md +++ /dev/null @@ -1,33 +0,0 @@ -# Dialogs Example - -This example is a comprehensive example of using dialogs in Wails. - -## Running the example - -To run the example, simply run the following command: - -```bash -go run main.go -``` - -## Building the example - -To build the example in debug mode, simply run the following command: - -```bash -wails3 task build -``` - -To build the example to use application icons, simply run the following command: - -```bash -wails3 task package -``` - -# Status - -| Platform | Status | -|----------|----------------| -| Mac | Mostly Working | -| Windows | Working | -| Linux | | diff --git a/v3/examples/dialogs/Taskfile.yml b/v3/examples/dialogs/Taskfile.yml deleted file mode 100644 index 90ac01145..000000000 --- a/v3/examples/dialogs/Taskfile.yml +++ /dev/null @@ -1,107 +0,0 @@ -version: '3' - -vars: - APP_NAME: "buildtest{{exeExt}}" - - -tasks: - - build: - summary: Builds the application - cmds: - - go build -gcflags=all="-N -l" -o bin/{{.APP_NAME}} - env: - CGO_CFLAGS: "-mmacosx-version-min=10.13" - CGO_LDFLAGS: "-mmacosx-version-min=10.13" - MACOSX_DEPLOYMENT_TARGET: "10.13" - - package: - summary: Packages a production build of the application into a `.app` or `.exe` bundle - cmds: - - task: package:darwin - - task: package:windows - -# ------------------------------------------------------------------------------ - - generate:icons: - summary: Generates Windows `.ico` and Mac `.icns` files from an image - dir: build - cmds: - # Generates both .ico and .icns files - - wails3 generate icons -input appicon.png - - build:production:darwin: - summary: Creates a production build of the application - cmds: - - GOOS=darwin GOARCH={{.GOARCH}} go build -tags production -ldflags="-w -s" -o build/bin/{{.APP_NAME}} - env: - CGO_CFLAGS: "-mmacosx-version-min=10.13" - CGO_LDFLAGS: "-mmacosx-version-min=10.13" - MACOSX_DEPLOYMENT_TARGET: "10.13" - GOARCH: '{{.GOARCH}}' - - generate:app_bundle: - summary: Builds a `.app` bundle - cmds: - - mkdir -p {{.APP_NAME}}.app/Contents/{MacOS,Resources} - - cp build/icons.icns {{.APP_NAME}}.app/Contents/Resources - - cp build/bin/{{.APP_NAME}} {{.APP_NAME}}.app/Contents/MacOS - - cp build/Info.plist {{.APP_NAME}}.app/Contents - - package:darwin:arm64: - summary: Packages a production build of the application into a `.app` bundle - platforms: - - darwin - deps: - - task: build:production:darwin - vars: - ARCH: arm64 - - generate:icons - cmds: - - task: generate:app_bundle - - package:darwin: - summary: Packages a production build of the application into a `.app` bundle - platforms: - - darwin - deps: - - task: build:production:darwin - - generate:icons - cmds: - - task: generate:app_bundle - - generate:syso: - dir: build - platforms: - - windows - cmds: - - wails3 generate syso -arch {{.GOARCH}} -icon icon.ico -manifest wails.exe.manifest -info info.json - vars: - GOARCH: '{{.GOARCH}}' - - package:windows: - summary: Packages a production build of the application into a `.exe` bundle - platforms: - - windows/amd64 - deps: - - generate:icons - cmds: - - task: generate:syso - vars: - GOARCH: amd64 - - go build -tags production -gcflags=all="-N -l" -o bin/{{.APP_NAME}} - - powershell Remove-item *.syso - - - package:windows:arm64: - summary: Packages a production build of the application into a `.exe` bundle (ARM64) - platforms: - - windows - cmds: - - task: generate:syso - vars: - GOARCH: arm64 - - go build -tags production -ldflags="-w -s -H windowsgui" -o bin/buildtest.arm64.exe - - powershell Remove-item *.syso - env: - GOARCH: arm64 diff --git a/v3/examples/dialogs/build/Info.dev.plist b/v3/examples/dialogs/build/Info.dev.plist deleted file mode 100644 index d6d28b179..000000000 --- a/v3/examples/dialogs/build/Info.dev.plist +++ /dev/null @@ -1,35 +0,0 @@ - - - - CFBundlePackageType - APPL - CFBundleName - My App - CFBundleExecutable - app - CFBundleIdentifier - com.wails.app - CFBundleVersion - v1.0.0 - CFBundleGetInfoString - The ultimate thing - CFBundleShortVersionString - v1 - CFBundleIconFile - icons - LSMinimumSystemVersion - 10.13.0 - NSHighResolutionCapable - true - NSHumanReadableCopyright - (c) Me - NSAppTransportSecurity - - NSAllowsLocalNetworking - - - - - - - \ No newline at end of file diff --git a/v3/examples/dialogs/build/Info.plist b/v3/examples/dialogs/build/Info.plist deleted file mode 100644 index 7f03f54e9..000000000 --- a/v3/examples/dialogs/build/Info.plist +++ /dev/null @@ -1,27 +0,0 @@ - - - - CFBundlePackageType - APPL - CFBundleName - My App - CFBundleExecutable - app - CFBundleIdentifier - com.wails.app - CFBundleVersion - v1.0.0 - CFBundleGetInfoString - The ultimate thing - CFBundleShortVersionString - v1 - CFBundleIconFile - icons - LSMinimumSystemVersion - 10.13.0 - NSHighResolutionCapable - true - NSHumanReadableCopyright - (c) Me - - \ No newline at end of file diff --git a/v3/examples/dialogs/build/appicon.png b/v3/examples/dialogs/build/appicon.png deleted file mode 100644 index 63617fe4f..000000000 Binary files a/v3/examples/dialogs/build/appicon.png and /dev/null differ diff --git a/v3/examples/dialogs/build/icon.ico b/v3/examples/dialogs/build/icon.ico deleted file mode 100644 index bfa0690b7..000000000 Binary files a/v3/examples/dialogs/build/icon.ico and /dev/null differ diff --git a/v3/examples/dialogs/build/icons.icns b/v3/examples/dialogs/build/icons.icns deleted file mode 100644 index 1b5bd4c86..000000000 Binary files a/v3/examples/dialogs/build/icons.icns and /dev/null differ diff --git a/v3/examples/dialogs/build/info.json b/v3/examples/dialogs/build/info.json deleted file mode 100644 index 1005eb5cb..000000000 --- a/v3/examples/dialogs/build/info.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "fixed": { - "file_version": "v1.0.0" - }, - "info": { - "0000": { - "ProductVersion": "v1.0.0", - "CompanyName": "My Company Name", - "FileDescription": "A thing that does a thing", - "LegalCopyright": "(c) 2023 My Company Name", - "ProductName": "My Product Name", - "Comments": "This is a comment" - } - } -} \ No newline at end of file diff --git a/v3/examples/dialogs/build/wails.exe.manifest b/v3/examples/dialogs/build/wails.exe.manifest deleted file mode 100644 index fb1ce5bde..000000000 --- a/v3/examples/dialogs/build/wails.exe.manifest +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - true/pm - permonitorv2,permonitor - - - \ No newline at end of file diff --git a/v3/examples/dialogs/main.go b/v3/examples/dialogs/main.go deleted file mode 100644 index 981fdb7b3..000000000 --- a/v3/examples/dialogs/main.go +++ /dev/null @@ -1,380 +0,0 @@ -package main - -import ( - _ "embed" - "log" - "log/slog" - "os" - "runtime" - "strings" - - "github.com/wailsapp/wails/v3/pkg/icons" - - "github.com/wailsapp/wails/v3/pkg/application" -) - -func main() { - - app := application.New(application.Options{ - Name: "Dialogs Demo", - Description: "A demo of the dialogs API", - Assets: application.AlphaAssets, - Logger: application.DefaultLogger(slog.LevelDebug), - Mac: application.MacOptions{ - ApplicationShouldTerminateAfterLastWindowClosed: true, - }, - }) - - // Create a custom menu - menu := app.NewMenu() - - // macOS: Add application menu - if runtime.GOOS == "darwin" { - menu.AddRole(application.AppMenu) - } - - // All platforms: Add standard menus - menu.AddRole(application.FileMenu) - menu.AddRole(application.EditMenu) - menu.AddRole(application.WindowMenu) - menu.AddRole(application.ServicesMenu) - menu.AddRole(application.HelpMenu) - - // Let's make a "Demo" menu - infoMenu := menu.AddSubmenu("Info") - infoMenu.Add("Info").OnClick(func(ctx *application.Context) { - dialog := app.Dialog.Info() - dialog.SetTitle("Custom Title") - dialog.SetMessage("This is a custom message") - dialog.Show() - }) - - infoMenu.Add("Info (Title only)").OnClick(func(ctx *application.Context) { - dialog := app.Dialog.Info() - dialog.SetTitle("Custom Title") - dialog.Show() - }) - infoMenu.Add("Info (Message only)").OnClick(func(ctx *application.Context) { - dialog := app.Dialog.Info() - dialog.SetMessage("This is a custom message") - dialog.Show() - }) - infoMenu.Add("Info (Custom Icon)").OnClick(func(ctx *application.Context) { - dialog := app.Dialog.Info() - dialog.SetTitle("Custom Icon Example") - dialog.SetMessage("Using a custom icon") - dialog.SetIcon(icons.ApplicationDarkMode256) - dialog.Show() - }) - infoMenu.Add("About").OnClick(func(ctx *application.Context) { - app.Menu.ShowAbout() - }) - - questionMenu := menu.AddSubmenu("Question") - questionMenu.Add("Question (No default)").OnClick(func(ctx *application.Context) { - dialog := app.Dialog.Question() - dialog.SetMessage("No default button") - dialog.AddButton("Yes") - dialog.AddButton("No") - dialog.Show() - }) - questionMenu.Add("Question (Attached to Window)").OnClick(func(ctx *application.Context) { - dialog := app.Dialog.Question() - dialog.AttachToWindow(app.Window.Current()) - dialog.SetMessage("No default button") - dialog.AddButton("Yes") - dialog.AddButton("No") - dialog.Show() - }) - questionMenu.Add("Question (With Default)").OnClick(func(ctx *application.Context) { - dialog := app.Dialog.Question() - dialog.SetTitle("Quit") - dialog.SetMessage("You have unsaved work. Are you sure you want to quit?") - dialog.AddButton("Yes").OnClick(func() { - app.Quit() - }) - no := dialog.AddButton("No") - dialog.SetDefaultButton(no) - dialog.Show() - }) - questionMenu.Add("Question (With Cancel)").OnClick(func(ctx *application.Context) { - dialog := app.Dialog.Question(). - SetTitle("Update"). - SetMessage("The cancel button is selected when pressing escape") - download := dialog.AddButton("📥 Download") - download.OnClick(func() { - app.Dialog.Info().SetMessage("Downloading...").Show() - }) - no := dialog.AddButton("Cancel") - dialog.SetDefaultButton(download) - dialog.SetCancelButton(no) - dialog.Show() - }) - questionMenu.Add("Question (Custom Icon)").OnClick(func(ctx *application.Context) { - dialog := app.Dialog.Question() - dialog.SetTitle("Custom Icon Example") - dialog.SetMessage("Using a custom icon") - dialog.SetIcon(icons.WailsLogoWhiteTransparent) - likeIt := dialog.AddButton("I like it!").OnClick(func() { - app.Dialog.Info().SetMessage("Thanks!").Show() - }) - dialog.AddButton("Not so keen...").OnClick(func() { - app.Dialog.Info().SetMessage("Too bad!").Show() - }) - dialog.SetDefaultButton(likeIt) - dialog.Show() - }) - - warningMenu := menu.AddSubmenu("Warning") - warningMenu.Add("Warning").OnClick(func(ctx *application.Context) { - app.Dialog.Warning(). - SetTitle("Custom Title"). - SetMessage("This is a custom message"). - Show() - }) - warningMenu.Add("Warning (Title only)").OnClick(func(ctx *application.Context) { - dialog := app.Dialog.Warning() - dialog.SetTitle("Custom Title") - dialog.Show() - }) - warningMenu.Add("Warning (Message only)").OnClick(func(ctx *application.Context) { - dialog := app.Dialog.Warning() - dialog.SetMessage("This is a custom message") - dialog.Show() - }) - warningMenu.Add("Warning (Custom Icon)").OnClick(func(ctx *application.Context) { - dialog := app.Dialog.Warning() - dialog.SetTitle("Custom Icon Example") - dialog.SetMessage("Using a custom icon") - dialog.SetIcon(icons.ApplicationLightMode256) - dialog.Show() - }) - - errorMenu := menu.AddSubmenu("Error") - errorMenu.Add("Error").OnClick(func(ctx *application.Context) { - dialog := app.Dialog.Error() - dialog.SetTitle("Ooops") - dialog.SetMessage("I accidentally the whole of Twitter") - dialog.Show() - }) - errorMenu.Add("Error (Title Only)").OnClick(func(ctx *application.Context) { - dialog := app.Dialog.Error() - dialog.SetTitle("Custom Title") - dialog.Show() - }) - errorMenu.Add("Error (Custom Message)").OnClick(func(ctx *application.Context) { - app.Dialog.Error(). - SetMessage("This is a custom message"). - Show() - }) - errorMenu.Add("Error (Custom Icon)").OnClick(func(ctx *application.Context) { - dialog := app.Dialog.Error() - dialog.SetTitle("Custom Icon Example") - dialog.SetMessage("Using a custom icon") - dialog.SetIcon(icons.WailsLogoWhite) - dialog.Show() - }) - - openMenu := menu.AddSubmenu("Open") - openMenu.Add("Open File").OnClick(func(ctx *application.Context) { - result, _ := app.Dialog.OpenFile(). - CanChooseFiles(true). - PromptForSingleSelection() - if result != "" { - app.Dialog.Info().SetMessage(result).Show() - } else { - app.Dialog.Info().SetMessage("No file selected").Show() - } - }) - openMenu.Add("Open File (Show Hidden Files)").OnClick(func(ctx *application.Context) { - result, _ := app.Dialog.OpenFile(). - CanChooseFiles(true). - CanCreateDirectories(true). - ShowHiddenFiles(true). - PromptForSingleSelection() - if result != "" { - app.Dialog.Info().SetMessage(result).Show() - } else { - app.Dialog.Info().SetMessage("No file selected").Show() - } - }) - openMenu.Add("Open File (Attach to window)").OnClick(func(ctx *application.Context) { - result, _ := app.Dialog.OpenFile(). - CanChooseFiles(true). - CanCreateDirectories(true). - ShowHiddenFiles(true). - AttachToWindow(app.Window.Current()). - PromptForSingleSelection() - if result != "" { - app.Dialog.Info().SetMessage(result).Show() - } else { - app.Dialog.Info().SetMessage("No file selected").Show() - } - }) - openMenu.Add("Open Multiple Files (Show Hidden Files)").OnClick(func(ctx *application.Context) { - result, _ := app.Dialog.OpenFile(). - CanChooseFiles(true). - CanCreateDirectories(true). - ShowHiddenFiles(true). - PromptForMultipleSelection() - if len(result) > 0 { - app.Dialog.Info().SetMessage(strings.Join(result, ",")).Show() - } else { - app.Dialog.Info().SetMessage("No file selected").Show() - } - }) - openMenu.Add("Open Directory").OnClick(func(ctx *application.Context) { - result, _ := app.Dialog.OpenFile(). - CanChooseDirectories(true). - CanChooseFiles(false). - PromptForSingleSelection() - if result != "" { - app.Dialog.Info().SetMessage(result).Show() - } else { - app.Dialog.Info().SetMessage("No directory selected").Show() - } - }) - openMenu.Add("Open Directory (Create Directories)").OnClick(func(ctx *application.Context) { - result, _ := app.Dialog.OpenFile(). - CanChooseDirectories(true). - CanCreateDirectories(true). - CanChooseFiles(false). - PromptForSingleSelection() - if result != "" { - app.Dialog.Info().SetMessage(result).Show() - } else { - app.Dialog.Info().SetMessage("No directory selected").Show() - } - }) - openMenu.Add("Open Directory (Resolves Aliases)").OnClick(func(ctx *application.Context) { - result, _ := app.Dialog.OpenFile(). - CanChooseDirectories(true). - CanCreateDirectories(true). - CanChooseFiles(false). - ResolvesAliases(true). - PromptForSingleSelection() - if result != "" { - app.Dialog.Info().SetMessage(result).Show() - } else { - app.Dialog.Info().SetMessage("No directory selected").Show() - } - }) - openMenu.Add("Open File/Directory (Set Title)").OnClick(func(ctx *application.Context) { - dialog := app.Dialog.OpenFile(). - CanChooseDirectories(true). - CanCreateDirectories(true). - ResolvesAliases(true) - if runtime.GOOS == "darwin" { - dialog.SetMessage("Select a file/directory") - } else { - dialog.SetTitle("Select a file/directory") - } - - result, _ := dialog.PromptForSingleSelection() - if result != "" { - app.Dialog.Info().SetMessage(result).Show() - } else { - app.Dialog.Info().SetMessage("No file/directory selected").Show() - } - }) - openMenu.Add("Open (Full Example)").OnClick(func(ctx *application.Context) { - cwd, _ := os.Getwd() - dialog := app.Dialog.OpenFile(). - SetTitle("Select a file"). - SetMessage("Select a file to open"). - SetButtonText("Let's do this!"). - SetDirectory(cwd). - CanCreateDirectories(true). - ResolvesAliases(true). - AllowsOtherFileTypes(true). - TreatsFilePackagesAsDirectories(true). - ShowHiddenFiles(true). - CanSelectHiddenExtension(true). - AddFilter("Text Files", "*.txt; *.md"). - AddFilter("Video Files", "*.mov; *.mp4; *.avi") - - if runtime.GOOS == "darwin" { - dialog.SetMessage("Select a file") - } else { - dialog.SetTitle("Select a file") - } - - result, _ := dialog.PromptForSingleSelection() - if result != "" { - app.Dialog.Info().SetMessage(result).Show() - } else { - app.Dialog.Info().SetMessage("No file selected").Show() - } - }) - - saveMenu := menu.AddSubmenu("Save") - saveMenu.Add("Select File (Defaults)").OnClick(func(ctx *application.Context) { - result, _ := app.Dialog.SaveFile(). - PromptForSingleSelection() - if result != "" { - app.Dialog.Info().SetMessage(result).Show() - } - }) - saveMenu.Add("Select File (Attach To WebviewWindow)").OnClick(func(ctx *application.Context) { - result, _ := app.Dialog.SaveFile(). - AttachToWindow(app.Window.Current()). - PromptForSingleSelection() - if result != "" { - app.Dialog.Info().SetMessage(result).Show() - } - }) - saveMenu.Add("Select File (Show Hidden Files)").OnClick(func(ctx *application.Context) { - result, _ := app.Dialog.SaveFile(). - ShowHiddenFiles(true). - PromptForSingleSelection() - if result != "" { - app.Dialog.Info().SetMessage(result).Show() - } - }) - saveMenu.Add("Select File (Cannot Create Directories)").OnClick(func(ctx *application.Context) { - result, _ := app.Dialog.SaveFile(). - CanCreateDirectories(false). - PromptForSingleSelection() - if result != "" { - app.Dialog.Info().SetMessage(result).Show() - } - }) - - userHomeDir, err := os.UserHomeDir() - if err != nil || userHomeDir == "" { - userHomeDir = os.TempDir() - } - - saveMenu.Add("Select File (Full Example)").OnClick(func(ctx *application.Context) { - result, _ := app.Dialog.SaveFile(). - CanCreateDirectories(false). - ShowHiddenFiles(true). - SetMessage("Select a file"). - SetDirectory(userHomeDir). - SetButtonText("Let's do this!"). - SetFilename("README.md"). - HideExtension(true). - AllowsOtherFileTypes(true). - TreatsFilePackagesAsDirectories(true). - ShowHiddenFiles(true). - PromptForSingleSelection() - if result != "" { - app.Dialog.Info().SetMessage(result).Show() - } - }) - - // Set the application menu - app.Menu.Set(menu) - - // Create window with UseApplicationMenu to inherit the app menu on Windows/Linux - app.Window.NewWithOptions(application.WebviewWindowOptions{ - Title: "Dialogs Demo", - UseApplicationMenu: true, - }) - - err = app.Run() - - if err != nil { - log.Fatal(err.Error()) - } -} diff --git a/v3/examples/dock/README.md b/v3/examples/dock/README.md deleted file mode 100644 index ad12c3f40..000000000 --- a/v3/examples/dock/README.md +++ /dev/null @@ -1,59 +0,0 @@ -# Welcome to Your New Wails3 Project! - -Congratulations on generating your Wails3 application! This README will guide you through the next steps to get your project up and running. - -## Getting Started - -1. Navigate to your project directory in the terminal. - -2. To run your application in development mode, use the following command: - - ``` - wails3 dev - ``` - - This will start your application and enable hot-reloading for both frontend and backend changes. - -3. To build your application for production, use: - - ``` - wails3 build - ``` - - This will create a production-ready executable in the `build` directory. - -## Exploring Wails3 Features - -Now that you have your project set up, it's time to explore the features that Wails3 offers: - -1. **Check out the examples**: The best way to learn is by example. Visit the `examples` directory in the `v3/examples` directory to see various sample applications. - -2. **Run an example**: To run any of the examples, navigate to the example's directory and use: - - ``` - go run . - ``` - - Note: Some examples may be under development during the alpha phase. - -3. **Explore the documentation**: Visit the [Wails3 documentation](https://v3.wails.io/) for in-depth guides and API references. - -4. **Join the community**: Have questions or want to share your progress? Join the [Wails Discord](https://discord.gg/JDdSxwjhGf) or visit the [Wails discussions on GitHub](https://github.com/wailsapp/wails/discussions). - -## Project Structure - -Take a moment to familiarize yourself with your project structure: - -- `frontend/`: Contains your frontend code (HTML, CSS, JavaScript/TypeScript) -- `main.go`: The entry point of your Go backend -- `app.go`: Define your application structure and methods here -- `wails.json`: Configuration file for your Wails project - -## Next Steps - -1. Modify the frontend in the `frontend/` directory to create your desired UI. -2. Add backend functionality in `main.go`. -3. Use `wails3 dev` to see your changes in real-time. -4. When ready, build your application with `wails3 build`. - -Happy coding with Wails3! If you encounter any issues or have questions, don't hesitate to consult the documentation or reach out to the Wails community. diff --git a/v3/examples/dock/Taskfile.yml b/v3/examples/dock/Taskfile.yml deleted file mode 100644 index b80b6614a..000000000 --- a/v3/examples/dock/Taskfile.yml +++ /dev/null @@ -1,34 +0,0 @@ -version: '3' - -includes: - common: ./build/Taskfile.yml - windows: ./build/windows/Taskfile.yml - darwin: ./build/darwin/Taskfile.yml - linux: ./build/linux/Taskfile.yml - -vars: - APP_NAME: "dock" - BIN_DIR: "bin" - VITE_PORT: '{{.WAILS_VITE_PORT | default 9245}}' - -tasks: - build: - summary: Builds the application - cmds: - - task: "{{OS}}:build" - - package: - summary: Packages a production build of the application - cmds: - - task: "{{OS}}:package" - - run: - summary: Runs the application - cmds: - - task: "{{OS}}:run" - - dev: - summary: Runs the application in development mode - cmds: - - wails3 dev -config ./build/config.yml -port {{.VITE_PORT}} - diff --git a/v3/examples/dock/build/Taskfile.yml b/v3/examples/dock/build/Taskfile.yml deleted file mode 100644 index 5f3517efc..000000000 --- a/v3/examples/dock/build/Taskfile.yml +++ /dev/null @@ -1,86 +0,0 @@ -version: '3' - -tasks: - go:mod:tidy: - summary: Runs `go mod tidy` - internal: true - cmds: - - go mod tidy - - install:frontend:deps: - summary: Install frontend dependencies - dir: frontend - sources: - - package.json - - package-lock.json - generates: - - node_modules/* - preconditions: - - sh: npm version - msg: "Looks like npm isn't installed. Npm is part of the Node installer: https://nodejs.org/en/download/" - cmds: - - npm install - - build:frontend: - label: build:frontend (PRODUCTION={{.PRODUCTION}}) - summary: Build the frontend project - dir: frontend - sources: - - "**/*" - generates: - - dist/**/* - deps: - - task: install:frontend:deps - - task: generate:bindings - vars: - BUILD_FLAGS: - ref: .BUILD_FLAGS - cmds: - - npm run {{.BUILD_COMMAND}} -q - env: - PRODUCTION: '{{.PRODUCTION | default "false"}}' - vars: - BUILD_COMMAND: '{{if eq .PRODUCTION "true"}}build{{else}}build:dev{{end}}' - - - generate:bindings: - label: generate:bindings (BUILD_FLAGS={{.BUILD_FLAGS}}) - summary: Generates bindings for the frontend - deps: - - task: go:mod:tidy - sources: - - "**/*.[jt]s" - - exclude: frontend/**/* - - frontend/bindings/**/* # Rerun when switching between dev/production mode causes changes in output - - "**/*.go" - - go.mod - - go.sum - generates: - - frontend/bindings/**/* - cmds: - - wails3 generate bindings -f '{{.BUILD_FLAGS}}' -clean=true -ts - - generate:icons: - summary: Generates Windows `.ico` and Mac `.icns` files from an image - dir: build - sources: - - "appicon.png" - generates: - - "darwin/icons.icns" - - "windows/icon.ico" - cmds: - - wails3 generate icons -input appicon.png -macfilename darwin/icons.icns -windowsfilename windows/icon.ico - - dev:frontend: - summary: Runs the frontend in development mode - dir: frontend - deps: - - task: install:frontend:deps - cmds: - - npm run dev -- --port {{.VITE_PORT}} --strictPort - - update:build-assets: - summary: Updates the build assets - dir: build - cmds: - - wails3 update build-assets -name "{{.APP_NAME}}" -binaryname "{{.APP_NAME}}" -config config.yml -dir . diff --git a/v3/examples/dock/build/appicon.png b/v3/examples/dock/build/appicon.png deleted file mode 100644 index 63617fe4f..000000000 Binary files a/v3/examples/dock/build/appicon.png and /dev/null differ diff --git a/v3/examples/dock/build/config.yml b/v3/examples/dock/build/config.yml deleted file mode 100644 index aaa3240fb..000000000 --- a/v3/examples/dock/build/config.yml +++ /dev/null @@ -1,63 +0,0 @@ -# This file contains the configuration for this project. -# When you update `info` or `fileAssociations`, run `wails3 task common:update:build-assets` to update the assets. -# Note that this will overwrite any changes you have made to the assets. -version: '3' - -# This information is used to generate the build assets. -info: - companyName: "My Company" # The name of the company - productName: "My Product" # The name of the application - productIdentifier: "com.mycompany.myproduct" # The unique product identifier - description: "A program that does X" # The application description - copyright: "(c) 2025, My Company" # Copyright text - comments: "Some Product Comments" # Comments - version: "0.0.1" # The application version - -# Dev mode configuration -dev_mode: - root_path: . - log_level: warn - debounce: 1000 - ignore: - dir: - - .git - - node_modules - - frontend - - bin - file: - - .DS_Store - - .gitignore - - .gitkeep - watched_extension: - - "*.go" - git_ignore: true - executes: - - cmd: wails3 task common:install:frontend:deps - type: once - - cmd: wails3 task common:dev:frontend - type: background - - cmd: go mod tidy - type: blocking - - cmd: wails3 task build - type: blocking - - cmd: wails3 task run - type: primary - -# File Associations -# More information at: https://v3.wails.io/noit/done/yet -fileAssociations: -# - ext: wails -# name: Wails -# description: Wails Application File -# iconName: wailsFileIcon -# role: Editor -# - ext: jpg -# name: JPEG -# description: Image File -# iconName: jpegFileIcon -# role: Editor -# mimeType: image/jpeg # (optional) - -# Other data -other: - - name: My Other Data \ No newline at end of file diff --git a/v3/examples/dock/build/darwin/Info.dev.plist b/v3/examples/dock/build/darwin/Info.dev.plist deleted file mode 100644 index 58d7f65e7..000000000 --- a/v3/examples/dock/build/darwin/Info.dev.plist +++ /dev/null @@ -1,32 +0,0 @@ - - - - CFBundlePackageType - APPL - CFBundleName - My Product - CFBundleExecutable - dock - CFBundleIdentifier - com.wails.dock - CFBundleVersion - 0.1.0 - CFBundleGetInfoString - This is a comment - CFBundleShortVersionString - 0.1.0 - CFBundleIconFile - icons - LSMinimumSystemVersion - 10.15.0 - NSHighResolutionCapable - true - NSHumanReadableCopyright - © now, My Company - NSAppTransportSecurity - - NSAllowsLocalNetworking - - - - \ No newline at end of file diff --git a/v3/examples/dock/build/darwin/Info.plist b/v3/examples/dock/build/darwin/Info.plist deleted file mode 100644 index aff7a2812..000000000 --- a/v3/examples/dock/build/darwin/Info.plist +++ /dev/null @@ -1,27 +0,0 @@ - - - - CFBundlePackageType - APPL - CFBundleName - My Product - CFBundleExecutable - dock - CFBundleIdentifier - com.wails.dock - CFBundleVersion - 0.1.0 - CFBundleGetInfoString - This is a comment - CFBundleShortVersionString - 0.1.0 - CFBundleIconFile - icons - LSMinimumSystemVersion - 10.15.0 - NSHighResolutionCapable - true - NSHumanReadableCopyright - © now, My Company - - \ No newline at end of file diff --git a/v3/examples/dock/build/darwin/Taskfile.yml b/v3/examples/dock/build/darwin/Taskfile.yml deleted file mode 100644 index f0791fea9..000000000 --- a/v3/examples/dock/build/darwin/Taskfile.yml +++ /dev/null @@ -1,81 +0,0 @@ -version: '3' - -includes: - common: ../Taskfile.yml - -tasks: - build: - summary: Creates a production build of the application - deps: - - task: common:go:mod:tidy - - task: common:build:frontend - vars: - BUILD_FLAGS: - ref: .BUILD_FLAGS - PRODUCTION: - ref: .PRODUCTION - - task: common:generate:icons - cmds: - - go build {{.BUILD_FLAGS}} -o {{.OUTPUT}} - vars: - BUILD_FLAGS: '{{if eq .PRODUCTION "true"}}-tags production -trimpath -buildvcs=false -ldflags="-w -s"{{else}}-buildvcs=false -gcflags=all="-l"{{end}}' - DEFAULT_OUTPUT: '{{.BIN_DIR}}/{{.APP_NAME}}' - OUTPUT: '{{ .OUTPUT | default .DEFAULT_OUTPUT }}' - env: - GOOS: darwin - CGO_ENABLED: 1 - GOARCH: '{{.ARCH | default ARCH}}' - CGO_CFLAGS: "-mmacosx-version-min=10.15" - CGO_LDFLAGS: "-mmacosx-version-min=10.15" - MACOSX_DEPLOYMENT_TARGET: "10.15" - PRODUCTION: '{{.PRODUCTION | default "false"}}' - - build:universal: - summary: Builds darwin universal binary (arm64 + amd64) - deps: - - task: build - vars: - ARCH: amd64 - OUTPUT: "{{.BIN_DIR}}/{{.APP_NAME}}-amd64" - - task: build - vars: - ARCH: arm64 - OUTPUT: "{{.BIN_DIR}}/{{.APP_NAME}}-arm64" - cmds: - - lipo -create -output "{{.BIN_DIR}}/{{.APP_NAME}}" "{{.BIN_DIR}}/{{.APP_NAME}}-amd64" "{{.BIN_DIR}}/{{.APP_NAME}}-arm64" - - rm "{{.BIN_DIR}}/{{.APP_NAME}}-amd64" "{{.BIN_DIR}}/{{.APP_NAME}}-arm64" - - package: - summary: Packages a production build of the application into a `.app` bundle - deps: - - task: build - vars: - PRODUCTION: "true" - cmds: - - task: create:app:bundle - - package:universal: - summary: Packages darwin universal binary (arm64 + amd64) - deps: - - task: build:universal - cmds: - - task: create:app:bundle - - - create:app:bundle: - summary: Creates an `.app` bundle - cmds: - - mkdir -p {{.BIN_DIR}}/{{.APP_NAME}}.app/Contents/{MacOS,Resources} - - cp build/darwin/icons.icns {{.BIN_DIR}}/{{.APP_NAME}}.app/Contents/Resources - - cp {{.BIN_DIR}}/{{.APP_NAME}} {{.BIN_DIR}}/{{.APP_NAME}}.app/Contents/MacOS - - cp build/darwin/Info.plist {{.BIN_DIR}}/{{.APP_NAME}}.app/Contents - - codesign --force --deep --sign - {{.BIN_DIR}}/{{.APP_NAME}}.app - - run: - cmds: - - mkdir -p {{.BIN_DIR}}/{{.APP_NAME}}.dev.app/Contents/{MacOS,Resources} - - cp build/darwin/icons.icns {{.BIN_DIR}}/{{.APP_NAME}}.dev.app/Contents/Resources - - cp {{.BIN_DIR}}/{{.APP_NAME}} {{.BIN_DIR}}/{{.APP_NAME}}.dev.app/Contents/MacOS - - cp build/darwin/Info.dev.plist {{.BIN_DIR}}/{{.APP_NAME}}.dev.app/Contents/Info.plist - - codesign --force --deep --sign - {{.BIN_DIR}}/{{.APP_NAME}}.dev.app - - '{{.BIN_DIR}}/{{.APP_NAME}}.dev.app/Contents/MacOS/{{.APP_NAME}}' diff --git a/v3/examples/dock/build/darwin/icons.icns b/v3/examples/dock/build/darwin/icons.icns deleted file mode 100644 index 1b5bd4c86..000000000 Binary files a/v3/examples/dock/build/darwin/icons.icns and /dev/null differ diff --git a/v3/examples/dock/build/linux/Taskfile.yml b/v3/examples/dock/build/linux/Taskfile.yml deleted file mode 100644 index 560cc9c92..000000000 --- a/v3/examples/dock/build/linux/Taskfile.yml +++ /dev/null @@ -1,119 +0,0 @@ -version: '3' - -includes: - common: ../Taskfile.yml - -tasks: - build: - summary: Builds the application for Linux - deps: - - task: common:go:mod:tidy - - task: common:build:frontend - vars: - BUILD_FLAGS: - ref: .BUILD_FLAGS - PRODUCTION: - ref: .PRODUCTION - - task: common:generate:icons - cmds: - - go build {{.BUILD_FLAGS}} -o {{.BIN_DIR}}/{{.APP_NAME}} - vars: - BUILD_FLAGS: '{{if eq .PRODUCTION "true"}}-tags production -trimpath -buildvcs=false -ldflags="-w -s"{{else}}-buildvcs=false -gcflags=all="-l"{{end}}' - env: - GOOS: linux - CGO_ENABLED: 1 - GOARCH: '{{.ARCH | default ARCH}}' - PRODUCTION: '{{.PRODUCTION | default "false"}}' - - package: - summary: Packages a production build of the application for Linux - deps: - - task: build - vars: - PRODUCTION: "true" - cmds: - - task: create:appimage - - task: create:deb - - task: create:rpm - - task: create:aur - - create:appimage: - summary: Creates an AppImage - dir: build/linux/appimage - deps: - - task: build - vars: - PRODUCTION: "true" - - task: generate:dotdesktop - cmds: - - cp {{.APP_BINARY}} {{.APP_NAME}} - - cp ../../appicon.png appicon.png - - wails3 generate appimage -binary {{.APP_NAME}} -icon {{.ICON}} -desktopfile {{.DESKTOP_FILE}} -outputdir {{.OUTPUT_DIR}} -builddir {{.ROOT_DIR}}/build/linux/appimage/build - vars: - APP_NAME: '{{.APP_NAME}}' - APP_BINARY: '../../../bin/{{.APP_NAME}}' - ICON: '../../appicon.png' - DESKTOP_FILE: '../{{.APP_NAME}}.desktop' - OUTPUT_DIR: '../../../bin' - - create:deb: - summary: Creates a deb package - deps: - - task: build - vars: - PRODUCTION: "true" - cmds: - - task: generate:dotdesktop - - task: generate:deb - - create:rpm: - summary: Creates a rpm package - deps: - - task: build - vars: - PRODUCTION: "true" - cmds: - - task: generate:dotdesktop - - task: generate:rpm - - create:aur: - summary: Creates a arch linux packager package - deps: - - task: build - vars: - PRODUCTION: "true" - cmds: - - task: generate:dotdesktop - - task: generate:aur - - generate:deb: - summary: Creates a deb package - cmds: - - wails3 tool package -name {{.APP_NAME}} -format deb -config ./build/linux/nfpm/nfpm.yaml -out {{.ROOT_DIR}}/bin - - generate:rpm: - summary: Creates a rpm package - cmds: - - wails3 tool package -name {{.APP_NAME}} -format rpm -config ./build/linux/nfpm/nfpm.yaml -out {{.ROOT_DIR}}/bin - - generate:aur: - summary: Creates a arch linux packager package - cmds: - - wails3 tool package -name {{.APP_NAME}} -format archlinux -config ./build/linux/nfpm/nfpm.yaml -out {{.ROOT_DIR}}/bin - - generate:dotdesktop: - summary: Generates a `.desktop` file - dir: build - cmds: - - mkdir -p {{.ROOT_DIR}}/build/linux/appimage - - wails3 generate .desktop -name "{{.APP_NAME}}" -exec "{{.EXEC}}" -icon "{{.ICON}}" -outputfile {{.ROOT_DIR}}/build/linux/{{.APP_NAME}}.desktop -categories "{{.CATEGORIES}}" - vars: - APP_NAME: '{{.APP_NAME}}' - EXEC: '{{.APP_NAME}}' - ICON: 'appicon' - CATEGORIES: 'Development;' - OUTPUTFILE: '{{.ROOT_DIR}}/build/linux/{{.APP_NAME}}.desktop' - - run: - cmds: - - '{{.BIN_DIR}}/{{.APP_NAME}}' diff --git a/v3/examples/dock/build/linux/appimage/build.sh b/v3/examples/dock/build/linux/appimage/build.sh deleted file mode 100644 index 85901c34e..000000000 --- a/v3/examples/dock/build/linux/appimage/build.sh +++ /dev/null @@ -1,35 +0,0 @@ -#!/usr/bin/env bash -# Copyright (c) 2018-Present Lea Anthony -# SPDX-License-Identifier: MIT - -# Fail script on any error -set -euxo pipefail - -# Define variables -APP_DIR="${APP_NAME}.AppDir" - -# Create AppDir structure -mkdir -p "${APP_DIR}/usr/bin" -cp -r "${APP_BINARY}" "${APP_DIR}/usr/bin/" -cp "${ICON_PATH}" "${APP_DIR}/" -cp "${DESKTOP_FILE}" "${APP_DIR}/" - -if [[ $(uname -m) == *x86_64* ]]; then - # Download linuxdeploy and make it executable - wget -q -4 -N https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-x86_64.AppImage - chmod +x linuxdeploy-x86_64.AppImage - - # Run linuxdeploy to bundle the application - ./linuxdeploy-x86_64.AppImage --appdir "${APP_DIR}" --output appimage -else - # Download linuxdeploy and make it executable (arm64) - wget -q -4 -N https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-aarch64.AppImage - chmod +x linuxdeploy-aarch64.AppImage - - # Run linuxdeploy to bundle the application (arm64) - ./linuxdeploy-aarch64.AppImage --appdir "${APP_DIR}" --output appimage -fi - -# Rename the generated AppImage -mv "${APP_NAME}*.AppImage" "${APP_NAME}.AppImage" - diff --git a/v3/examples/dock/build/linux/desktop b/v3/examples/dock/build/linux/desktop deleted file mode 100644 index ddb025903..000000000 --- a/v3/examples/dock/build/linux/desktop +++ /dev/null @@ -1,13 +0,0 @@ -[Desktop Entry] -Version=1.0 -Name=My Product -Comment=My Product Description -# The Exec line includes %u to pass the URL to the application -Exec=/usr/local/bin/dock %u -Terminal=false -Type=Application -Icon=dock -Categories=Utility; -StartupWMClass=dock - - diff --git a/v3/examples/dock/build/linux/nfpm/nfpm.yaml b/v3/examples/dock/build/linux/nfpm/nfpm.yaml deleted file mode 100644 index 6e9be6550..000000000 --- a/v3/examples/dock/build/linux/nfpm/nfpm.yaml +++ /dev/null @@ -1,73 +0,0 @@ -# Feel free to remove those if you don't want/need to use them. -# Make sure to check the documentation at https://nfpm.goreleaser.com -# -# The lines below are called `modelines`. See `:help modeline` - -name: "dock" -arch: ${GOARCH} -platform: "linux" -version: "0.1.0" -section: "default" -priority: "extra" -maintainer: ${GIT_COMMITTER_NAME} <${GIT_COMMITTER_EMAIL}> -description: "My Product Description" -vendor: "My Company" -homepage: "https://wails.io" -license: "MIT" -release: "1" - -contents: - - src: "./bin/dock" - dst: "/usr/local/bin/dock" - - src: "./build/appicon.png" - dst: "/usr/share/icons/hicolor/128x128/apps/dock.png" - - src: "./build/linux/dock.desktop" - dst: "/usr/share/applications/dock.desktop" - -# Default dependencies for Debian 12/Ubuntu 22.04+ with WebKit 4.1 -depends: - - libgtk-3-dev - - libwebkit2gtk-4.1-dev - - build-essential - - pkg-config - -# Distribution-specific overrides for different package formats and WebKit versions -overrides: - # RPM packages for RHEL/CentOS/AlmaLinux/Rocky Linux (WebKit 4.0) - rpm: - depends: - - gtk3-devel - - webkit2gtk3-devel - - gcc-c++ - - pkg-config - - # Arch Linux packages (WebKit 4.1) - archlinux: - depends: - - gtk3 - - webkit2gtk-4.1 - - base-devel - - pkgconf - -# scripts section to ensure desktop database is updated after install -scripts: - postinstall: "./build/linux/nfpm/scripts/postinstall.sh" - # You can also add preremove, postremove if needed - # preremove: "./build/linux/nfpm/scripts/preremove.sh" - # postremove: "./build/linux/nfpm/scripts/postremove.sh" - -# replaces: -# - foobar -# provides: -# - bar -# depends: -# - gtk3 -# - libwebkit2gtk -# recommends: -# - whatever -# suggests: -# - something-else -# conflicts: -# - not-foo -# - not-bar -# changelog: "changelog.yaml" \ No newline at end of file diff --git a/v3/examples/dock/build/linux/nfpm/scripts/postinstall.sh b/v3/examples/dock/build/linux/nfpm/scripts/postinstall.sh deleted file mode 100644 index 4bbb815a3..000000000 --- a/v3/examples/dock/build/linux/nfpm/scripts/postinstall.sh +++ /dev/null @@ -1,21 +0,0 @@ -#!/bin/sh - -# Update desktop database for .desktop file changes -# This makes the application appear in application menus and registers its capabilities. -if command -v update-desktop-database >/dev/null 2>&1; then - echo "Updating desktop database..." - update-desktop-database -q /usr/share/applications -else - echo "Warning: update-desktop-database command not found. Desktop file may not be immediately recognized." >&2 -fi - -# Update MIME database for custom URL schemes (x-scheme-handler) -# This ensures the system knows how to handle your custom protocols. -if command -v update-mime-database >/dev/null 2>&1; then - echo "Updating MIME database..." - update-mime-database -n /usr/share/mime -else - echo "Warning: update-mime-database command not found. Custom URL schemes may not be immediately recognized." >&2 -fi - -exit 0 diff --git a/v3/examples/dock/build/linux/nfpm/scripts/postremove.sh b/v3/examples/dock/build/linux/nfpm/scripts/postremove.sh deleted file mode 100644 index a9bf588e2..000000000 --- a/v3/examples/dock/build/linux/nfpm/scripts/postremove.sh +++ /dev/null @@ -1 +0,0 @@ -#!/bin/bash diff --git a/v3/examples/dock/build/linux/nfpm/scripts/preinstall.sh b/v3/examples/dock/build/linux/nfpm/scripts/preinstall.sh deleted file mode 100644 index a9bf588e2..000000000 --- a/v3/examples/dock/build/linux/nfpm/scripts/preinstall.sh +++ /dev/null @@ -1 +0,0 @@ -#!/bin/bash diff --git a/v3/examples/dock/build/linux/nfpm/scripts/preremove.sh b/v3/examples/dock/build/linux/nfpm/scripts/preremove.sh deleted file mode 100644 index a9bf588e2..000000000 --- a/v3/examples/dock/build/linux/nfpm/scripts/preremove.sh +++ /dev/null @@ -1 +0,0 @@ -#!/bin/bash diff --git a/v3/examples/dock/build/windows/Taskfile.yml b/v3/examples/dock/build/windows/Taskfile.yml deleted file mode 100644 index 19f137616..000000000 --- a/v3/examples/dock/build/windows/Taskfile.yml +++ /dev/null @@ -1,98 +0,0 @@ -version: '3' - -includes: - common: ../Taskfile.yml - -tasks: - build: - summary: Builds the application for Windows - deps: - - task: common:go:mod:tidy - - task: common:build:frontend - vars: - BUILD_FLAGS: - ref: .BUILD_FLAGS - PRODUCTION: - ref: .PRODUCTION - - task: common:generate:icons - cmds: - - task: generate:syso - - go build {{.BUILD_FLAGS}} -o {{.BIN_DIR}}/{{.APP_NAME}}.exe - - cmd: powershell Remove-item *.syso - platforms: [windows] - - cmd: rm -f *.syso - platforms: [linux, darwin] - vars: - BUILD_FLAGS: '{{if eq .PRODUCTION "true"}}-tags production -trimpath -buildvcs=false -ldflags="-w -s -H windowsgui"{{else}}-buildvcs=false -gcflags=all="-l"{{end}}' - env: - GOOS: windows - CGO_ENABLED: 0 - GOARCH: '{{.ARCH | default ARCH}}' - PRODUCTION: '{{.PRODUCTION | default "false"}}' - - package: - summary: Packages a production build of the application - cmds: - - |- - if [ "{{.FORMAT | default "nsis"}}" = "msix" ]; then - task: create:msix:package - else - task: create:nsis:installer - fi - vars: - FORMAT: '{{.FORMAT | default "nsis"}}' - - generate:syso: - summary: Generates Windows `.syso` file - dir: build - cmds: - - wails3 generate syso -arch {{.ARCH}} -icon windows/icon.ico -manifest windows/wails.exe.manifest -info windows/info.json -out ../wails_windows_{{.ARCH}}.syso - vars: - ARCH: '{{.ARCH | default ARCH}}' - - create:nsis:installer: - summary: Creates an NSIS installer - dir: build/windows/nsis - deps: - - task: build - vars: - PRODUCTION: "true" - cmds: - # Create the Microsoft WebView2 bootstrapper if it doesn't exist - - wails3 generate webview2bootstrapper -dir "{{.ROOT_DIR}}/build/windows/nsis" - - makensis -DARG_WAILS_{{.ARG_FLAG}}_BINARY="{{.ROOT_DIR}}/{{.BIN_DIR}}/{{.APP_NAME}}.exe" project.nsi - vars: - ARCH: '{{.ARCH | default ARCH}}' - ARG_FLAG: '{{if eq .ARCH "amd64"}}AMD64{{else}}ARM64{{end}}' - - create:msix:package: - summary: Creates an MSIX package - deps: - - task: build - vars: - PRODUCTION: "true" - cmds: - - |- - wails3 tool msix \ - --config "{{.ROOT_DIR}}/wails.json" \ - --name "{{.APP_NAME}}" \ - --executable "{{.ROOT_DIR}}/{{.BIN_DIR}}/{{.APP_NAME}}.exe" \ - --arch "{{.ARCH}}" \ - --out "{{.ROOT_DIR}}/{{.BIN_DIR}}/{{.APP_NAME}}-{{.ARCH}}.msix" \ - {{if .CERT_PATH}}--cert "{{.CERT_PATH}}"{{end}} \ - {{if .PUBLISHER}}--publisher "{{.PUBLISHER}}"{{end}} \ - {{if .USE_MSIX_TOOL}}--use-msix-tool{{else}}--use-makeappx{{end}} - vars: - ARCH: '{{.ARCH | default ARCH}}' - CERT_PATH: '{{.CERT_PATH | default ""}}' - PUBLISHER: '{{.PUBLISHER | default ""}}' - USE_MSIX_TOOL: '{{.USE_MSIX_TOOL | default "false"}}' - - install:msix:tools: - summary: Installs tools required for MSIX packaging - cmds: - - wails3 tool msix-install-tools - - run: - cmds: - - '{{.BIN_DIR}}/{{.APP_NAME}}.exe' diff --git a/v3/examples/dock/build/windows/icon.ico b/v3/examples/dock/build/windows/icon.ico deleted file mode 100644 index bfa0690b7..000000000 Binary files a/v3/examples/dock/build/windows/icon.ico and /dev/null differ diff --git a/v3/examples/dock/build/windows/info.json b/v3/examples/dock/build/windows/info.json deleted file mode 100644 index 850b2b5b0..000000000 --- a/v3/examples/dock/build/windows/info.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "fixed": { - "file_version": "0.1.0" - }, - "info": { - "0000": { - "ProductVersion": "0.1.0", - "CompanyName": "My Company", - "FileDescription": "My Product Description", - "LegalCopyright": "© now, My Company", - "ProductName": "My Product", - "Comments": "This is a comment" - } - } -} \ No newline at end of file diff --git a/v3/examples/dock/build/windows/msix/app_manifest.xml b/v3/examples/dock/build/windows/msix/app_manifest.xml deleted file mode 100644 index 8eabe1a03..000000000 --- a/v3/examples/dock/build/windows/msix/app_manifest.xml +++ /dev/null @@ -1,52 +0,0 @@ - - - - - - - My Product - My Company - My Product Description - Assets\StoreLogo.png - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/v3/examples/dock/build/windows/msix/template.xml b/v3/examples/dock/build/windows/msix/template.xml deleted file mode 100644 index 2824a2932..000000000 --- a/v3/examples/dock/build/windows/msix/template.xml +++ /dev/null @@ -1,54 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - false - My Product - My Company - My Product Description - Assets\AppIcon.png - - - - - - - diff --git a/v3/examples/dock/build/windows/nsis/project.nsi b/v3/examples/dock/build/windows/nsis/project.nsi deleted file mode 100644 index b992809bc..000000000 --- a/v3/examples/dock/build/windows/nsis/project.nsi +++ /dev/null @@ -1,112 +0,0 @@ -Unicode true - -#### -## Please note: Template replacements don't work in this file. They are provided with default defines like -## mentioned underneath. -## If the keyword is not defined, "wails_tools.nsh" will populate them. -## If they are defined here, "wails_tools.nsh" will not touch them. This allows you to use this project.nsi manually -## from outside of Wails for debugging and development of the installer. -## -## For development first make a wails nsis build to populate the "wails_tools.nsh": -## > wails build --target windows/amd64 --nsis -## Then you can call makensis on this file with specifying the path to your binary: -## For a AMD64 only installer: -## > makensis -DARG_WAILS_AMD64_BINARY=..\..\bin\app.exe -## For a ARM64 only installer: -## > makensis -DARG_WAILS_ARM64_BINARY=..\..\bin\app.exe -## For a installer with both architectures: -## > makensis -DARG_WAILS_AMD64_BINARY=..\..\bin\app-amd64.exe -DARG_WAILS_ARM64_BINARY=..\..\bin\app-arm64.exe -#### -## The following information is taken from the wails_tools.nsh file, but they can be overwritten here. -#### -## !define INFO_PROJECTNAME "my-project" # Default "dock" -## !define INFO_COMPANYNAME "My Company" # Default "My Company" -## !define INFO_PRODUCTNAME "My Product Name" # Default "My Product" -## !define INFO_PRODUCTVERSION "1.0.0" # Default "0.1.0" -## !define INFO_COPYRIGHT "(c) Now, My Company" # Default "© now, My Company" -### -## !define PRODUCT_EXECUTABLE "Application.exe" # Default "${INFO_PROJECTNAME}.exe" -## !define UNINST_KEY_NAME "UninstKeyInRegistry" # Default "${INFO_COMPANYNAME}${INFO_PRODUCTNAME}" -#### -## !define REQUEST_EXECUTION_LEVEL "admin" # Default "admin" see also https://nsis.sourceforge.io/Docs/Chapter4.html -#### -## Include the wails tools -#### -!include "wails_tools.nsh" - -# The version information for this two must consist of 4 parts -VIProductVersion "${INFO_PRODUCTVERSION}.0" -VIFileVersion "${INFO_PRODUCTVERSION}.0" - -VIAddVersionKey "CompanyName" "${INFO_COMPANYNAME}" -VIAddVersionKey "FileDescription" "${INFO_PRODUCTNAME} Installer" -VIAddVersionKey "ProductVersion" "${INFO_PRODUCTVERSION}" -VIAddVersionKey "FileVersion" "${INFO_PRODUCTVERSION}" -VIAddVersionKey "LegalCopyright" "${INFO_COPYRIGHT}" -VIAddVersionKey "ProductName" "${INFO_PRODUCTNAME}" - -# Enable HiDPI support. https://nsis.sourceforge.io/Reference/ManifestDPIAware -ManifestDPIAware true - -!include "MUI.nsh" - -!define MUI_ICON "..\icon.ico" -!define MUI_UNICON "..\icon.ico" -# !define MUI_WELCOMEFINISHPAGE_BITMAP "resources\leftimage.bmp" #Include this to add a bitmap on the left side of the Welcome Page. Must be a size of 164x314 -!define MUI_FINISHPAGE_NOAUTOCLOSE # Wait on the INSTFILES page so the user can take a look into the details of the installation steps -!define MUI_ABORTWARNING # This will warn the user if they exit from the installer. - -!insertmacro MUI_PAGE_WELCOME # Welcome to the installer page. -# !insertmacro MUI_PAGE_LICENSE "resources\eula.txt" # Adds a EULA page to the installer -!insertmacro MUI_PAGE_DIRECTORY # In which folder install page. -!insertmacro MUI_PAGE_INSTFILES # Installing page. -!insertmacro MUI_PAGE_FINISH # Finished installation page. - -!insertmacro MUI_UNPAGE_INSTFILES # Uninstalling page - -!insertmacro MUI_LANGUAGE "English" # Set the Language of the installer - -## The following two statements can be used to sign the installer and the uninstaller. The path to the binaries are provided in %1 -#!uninstfinalize 'signtool --file "%1"' -#!finalize 'signtool --file "%1"' - -Name "${INFO_PRODUCTNAME}" -OutFile "..\..\..\bin\${INFO_PROJECTNAME}-${ARCH}-installer.exe" # Name of the installer's file. -InstallDir "$PROGRAMFILES64\${INFO_COMPANYNAME}\${INFO_PRODUCTNAME}" # Default installing folder ($PROGRAMFILES is Program Files folder). -ShowInstDetails show # This will always show the installation details. - -Function .onInit - !insertmacro wails.checkArchitecture -FunctionEnd - -Section - !insertmacro wails.setShellContext - - !insertmacro wails.webview2runtime - - SetOutPath $INSTDIR - - !insertmacro wails.files - - CreateShortcut "$SMPROGRAMS\${INFO_PRODUCTNAME}.lnk" "$INSTDIR\${PRODUCT_EXECUTABLE}" - CreateShortCut "$DESKTOP\${INFO_PRODUCTNAME}.lnk" "$INSTDIR\${PRODUCT_EXECUTABLE}" - - !insertmacro wails.associateFiles - - !insertmacro wails.writeUninstaller -SectionEnd - -Section "uninstall" - !insertmacro wails.setShellContext - - RMDir /r "$AppData\${PRODUCT_EXECUTABLE}" # Remove the WebView2 DataPath - - RMDir /r $INSTDIR - - Delete "$SMPROGRAMS\${INFO_PRODUCTNAME}.lnk" - Delete "$DESKTOP\${INFO_PRODUCTNAME}.lnk" - - !insertmacro wails.unassociateFiles - - !insertmacro wails.deleteUninstaller -SectionEnd diff --git a/v3/examples/dock/build/windows/nsis/wails_tools.nsh b/v3/examples/dock/build/windows/nsis/wails_tools.nsh deleted file mode 100644 index b5ff5b23c..000000000 --- a/v3/examples/dock/build/windows/nsis/wails_tools.nsh +++ /dev/null @@ -1,212 +0,0 @@ -# DO NOT EDIT - Generated automatically by `wails build` - -!include "x64.nsh" -!include "WinVer.nsh" -!include "FileFunc.nsh" - -!ifndef INFO_PROJECTNAME - !define INFO_PROJECTNAME "dock" -!endif -!ifndef INFO_COMPANYNAME - !define INFO_COMPANYNAME "My Company" -!endif -!ifndef INFO_PRODUCTNAME - !define INFO_PRODUCTNAME "My Product" -!endif -!ifndef INFO_PRODUCTVERSION - !define INFO_PRODUCTVERSION "0.1.0" -!endif -!ifndef INFO_COPYRIGHT - !define INFO_COPYRIGHT "© now, My Company" -!endif -!ifndef PRODUCT_EXECUTABLE - !define PRODUCT_EXECUTABLE "${INFO_PROJECTNAME}.exe" -!endif -!ifndef UNINST_KEY_NAME - !define UNINST_KEY_NAME "${INFO_COMPANYNAME}${INFO_PRODUCTNAME}" -!endif -!define UNINST_KEY "Software\Microsoft\Windows\CurrentVersion\Uninstall\${UNINST_KEY_NAME}" - -!ifndef REQUEST_EXECUTION_LEVEL - !define REQUEST_EXECUTION_LEVEL "admin" -!endif - -RequestExecutionLevel "${REQUEST_EXECUTION_LEVEL}" - -!ifdef ARG_WAILS_AMD64_BINARY - !define SUPPORTS_AMD64 -!endif - -!ifdef ARG_WAILS_ARM64_BINARY - !define SUPPORTS_ARM64 -!endif - -!ifdef SUPPORTS_AMD64 - !ifdef SUPPORTS_ARM64 - !define ARCH "amd64_arm64" - !else - !define ARCH "amd64" - !endif -!else - !ifdef SUPPORTS_ARM64 - !define ARCH "arm64" - !else - !error "Wails: Undefined ARCH, please provide at least one of ARG_WAILS_AMD64_BINARY or ARG_WAILS_ARM64_BINARY" - !endif -!endif - -!macro wails.checkArchitecture - !ifndef WAILS_WIN10_REQUIRED - !define WAILS_WIN10_REQUIRED "This product is only supported on Windows 10 (Server 2016) and later." - !endif - - !ifndef WAILS_ARCHITECTURE_NOT_SUPPORTED - !define WAILS_ARCHITECTURE_NOT_SUPPORTED "This product can't be installed on the current Windows architecture. Supports: ${ARCH}" - !endif - - ${If} ${AtLeastWin10} - !ifdef SUPPORTS_AMD64 - ${if} ${IsNativeAMD64} - Goto ok - ${EndIf} - !endif - - !ifdef SUPPORTS_ARM64 - ${if} ${IsNativeARM64} - Goto ok - ${EndIf} - !endif - - IfSilent silentArch notSilentArch - silentArch: - SetErrorLevel 65 - Abort - notSilentArch: - MessageBox MB_OK "${WAILS_ARCHITECTURE_NOT_SUPPORTED}" - Quit - ${else} - IfSilent silentWin notSilentWin - silentWin: - SetErrorLevel 64 - Abort - notSilentWin: - MessageBox MB_OK "${WAILS_WIN10_REQUIRED}" - Quit - ${EndIf} - - ok: -!macroend - -!macro wails.files - !ifdef SUPPORTS_AMD64 - ${if} ${IsNativeAMD64} - File "/oname=${PRODUCT_EXECUTABLE}" "${ARG_WAILS_AMD64_BINARY}" - ${EndIf} - !endif - - !ifdef SUPPORTS_ARM64 - ${if} ${IsNativeARM64} - File "/oname=${PRODUCT_EXECUTABLE}" "${ARG_WAILS_ARM64_BINARY}" - ${EndIf} - !endif -!macroend - -!macro wails.writeUninstaller - WriteUninstaller "$INSTDIR\uninstall.exe" - - SetRegView 64 - WriteRegStr HKLM "${UNINST_KEY}" "Publisher" "${INFO_COMPANYNAME}" - WriteRegStr HKLM "${UNINST_KEY}" "DisplayName" "${INFO_PRODUCTNAME}" - WriteRegStr HKLM "${UNINST_KEY}" "DisplayVersion" "${INFO_PRODUCTVERSION}" - WriteRegStr HKLM "${UNINST_KEY}" "DisplayIcon" "$INSTDIR\${PRODUCT_EXECUTABLE}" - WriteRegStr HKLM "${UNINST_KEY}" "UninstallString" "$\"$INSTDIR\uninstall.exe$\"" - WriteRegStr HKLM "${UNINST_KEY}" "QuietUninstallString" "$\"$INSTDIR\uninstall.exe$\" /S" - - ${GetSize} "$INSTDIR" "/S=0K" $0 $1 $2 - IntFmt $0 "0x%08X" $0 - WriteRegDWORD HKLM "${UNINST_KEY}" "EstimatedSize" "$0" -!macroend - -!macro wails.deleteUninstaller - Delete "$INSTDIR\uninstall.exe" - - SetRegView 64 - DeleteRegKey HKLM "${UNINST_KEY}" -!macroend - -!macro wails.setShellContext - ${If} ${REQUEST_EXECUTION_LEVEL} == "admin" - SetShellVarContext all - ${else} - SetShellVarContext current - ${EndIf} -!macroend - -# Install webview2 by launching the bootstrapper -# See https://docs.microsoft.com/en-us/microsoft-edge/webview2/concepts/distribution#online-only-deployment -!macro wails.webview2runtime - !ifndef WAILS_INSTALL_WEBVIEW_DETAILPRINT - !define WAILS_INSTALL_WEBVIEW_DETAILPRINT "Installing: WebView2 Runtime" - !endif - - SetRegView 64 - # If the admin key exists and is not empty then webview2 is already installed - ReadRegStr $0 HKLM "SOFTWARE\WOW6432Node\Microsoft\EdgeUpdate\Clients\{F3017226-FE2A-4295-8BDF-00C3A9A7E4C5}" "pv" - ${If} $0 != "" - Goto ok - ${EndIf} - - ${If} ${REQUEST_EXECUTION_LEVEL} == "user" - # If the installer is run in user level, check the user specific key exists and is not empty then webview2 is already installed - ReadRegStr $0 HKCU "Software\Microsoft\EdgeUpdate\Clients\{F3017226-FE2A-4295-8BDF-00C3A9A7E4C5}" "pv" - ${If} $0 != "" - Goto ok - ${EndIf} - ${EndIf} - - SetDetailsPrint both - DetailPrint "${WAILS_INSTALL_WEBVIEW_DETAILPRINT}" - SetDetailsPrint listonly - - InitPluginsDir - CreateDirectory "$pluginsdir\webview2bootstrapper" - SetOutPath "$pluginsdir\webview2bootstrapper" - File "MicrosoftEdgeWebview2Setup.exe" - ExecWait '"$pluginsdir\webview2bootstrapper\MicrosoftEdgeWebview2Setup.exe" /silent /install' - - SetDetailsPrint both - ok: -!macroend - -# Copy of APP_ASSOCIATE and APP_UNASSOCIATE macros from here https://gist.github.com/nikku/281d0ef126dbc215dd58bfd5b3a5cd5b -!macro APP_ASSOCIATE EXT FILECLASS DESCRIPTION ICON COMMANDTEXT COMMAND - ; Backup the previously associated file class - ReadRegStr $R0 SHELL_CONTEXT "Software\Classes\.${EXT}" "" - WriteRegStr SHELL_CONTEXT "Software\Classes\.${EXT}" "${FILECLASS}_backup" "$R0" - - WriteRegStr SHELL_CONTEXT "Software\Classes\.${EXT}" "" "${FILECLASS}" - - WriteRegStr SHELL_CONTEXT "Software\Classes\${FILECLASS}" "" `${DESCRIPTION}` - WriteRegStr SHELL_CONTEXT "Software\Classes\${FILECLASS}\DefaultIcon" "" `${ICON}` - WriteRegStr SHELL_CONTEXT "Software\Classes\${FILECLASS}\shell" "" "open" - WriteRegStr SHELL_CONTEXT "Software\Classes\${FILECLASS}\shell\open" "" `${COMMANDTEXT}` - WriteRegStr SHELL_CONTEXT "Software\Classes\${FILECLASS}\shell\open\command" "" `${COMMAND}` -!macroend - -!macro APP_UNASSOCIATE EXT FILECLASS - ; Backup the previously associated file class - ReadRegStr $R0 SHELL_CONTEXT "Software\Classes\.${EXT}" `${FILECLASS}_backup` - WriteRegStr SHELL_CONTEXT "Software\Classes\.${EXT}" "" "$R0" - - DeleteRegKey SHELL_CONTEXT `Software\Classes\${FILECLASS}` -!macroend - -!macro wails.associateFiles - ; Create file associations - -!macroend - -!macro wails.unassociateFiles - ; Delete app associations - -!macroend \ No newline at end of file diff --git a/v3/examples/dock/build/windows/wails.exe.manifest b/v3/examples/dock/build/windows/wails.exe.manifest deleted file mode 100644 index 48052e7e6..000000000 --- a/v3/examples/dock/build/windows/wails.exe.manifest +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - - - - - true/pm - permonitorv2,permonitor - - - - - - - - - - \ No newline at end of file diff --git a/v3/examples/dock/frontend/Inter Font License.txt b/v3/examples/dock/frontend/Inter Font License.txt deleted file mode 100644 index b525cbf3a..000000000 --- a/v3/examples/dock/frontend/Inter Font License.txt +++ /dev/null @@ -1,93 +0,0 @@ -Copyright 2020 The Inter Project Authors (https://github.com/rsms/inter) - -This Font Software is licensed under the SIL Open Font License, Version 1.1. -This license is copied below, and is also available with a FAQ at: -http://scripts.sil.org/OFL - - ------------------------------------------------------------ -SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 ------------------------------------------------------------ - -PREAMBLE -The goals of the Open Font License (OFL) are to stimulate worldwide -development of collaborative font projects, to support the font creation -efforts of academic and linguistic communities, and to provide a free and -open framework in which fonts may be shared and improved in partnership -with others. - -The OFL allows the licensed fonts to be used, studied, modified and -redistributed freely as long as they are not sold by themselves. The -fonts, including any derivative works, can be bundled, embedded, -redistributed and/or sold with any software provided that any reserved -names are not used by derivative works. The fonts and derivatives, -however, cannot be released under any other type of license. The -requirement for fonts to remain under this license does not apply -to any document created using the fonts or their derivatives. - -DEFINITIONS -"Font Software" refers to the set of files released by the Copyright -Holder(s) under this license and clearly marked as such. This may -include source files, build scripts and documentation. - -"Reserved Font Name" refers to any names specified as such after the -copyright statement(s). - -"Original Version" refers to the collection of Font Software components as -distributed by the Copyright Holder(s). - -"Modified Version" refers to any derivative made by adding to, deleting, -or substituting -- in part or in whole -- any of the components of the -Original Version, by changing formats or by porting the Font Software to a -new environment. - -"Author" refers to any designer, engineer, programmer, technical -writer or other person who contributed to the Font Software. - -PERMISSION & CONDITIONS -Permission is hereby granted, free of charge, to any person obtaining -a copy of the Font Software, to use, study, copy, merge, embed, modify, -redistribute, and sell modified and unmodified copies of the Font -Software, subject to the following conditions: - -1) Neither the Font Software nor any of its individual components, -in Original or Modified Versions, may be sold by itself. - -2) Original or Modified Versions of the Font Software may be bundled, -redistributed and/or sold with any software, provided that each copy -contains the above copyright notice and this license. These can be -included either as stand-alone text files, human-readable headers or -in the appropriate machine-readable metadata fields within text or -binary files as long as those fields can be easily viewed by the user. - -3) No Modified Version of the Font Software may use the Reserved Font -Name(s) unless explicit written permission is granted by the corresponding -Copyright Holder. This restriction only applies to the primary font name as -presented to the users. - -4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font -Software shall not be used to promote, endorse or advertise any -Modified Version, except to acknowledge the contribution(s) of the -Copyright Holder(s) and the Author(s) or with their explicit written -permission. - -5) The Font Software, modified or unmodified, in part or in whole, -must be distributed entirely under this license, and must not be -distributed under any other license. The requirement for fonts to -remain under this license does not apply to any document created -using the Font Software. - -TERMINATION -This license becomes null and void if any of the above conditions are -not met. - -DISCLAIMER -THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT -OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE -COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL -DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM -OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/v3/examples/dock/frontend/bindings/github.com/wailsapp/wails/v3/pkg/services/dock/dockservice.ts b/v3/examples/dock/frontend/bindings/github.com/wailsapp/wails/v3/pkg/services/dock/dockservice.ts deleted file mode 100644 index abf1f22e4..000000000 --- a/v3/examples/dock/frontend/bindings/github.com/wailsapp/wails/v3/pkg/services/dock/dockservice.ts +++ /dev/null @@ -1,53 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * Service represents the dock service - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "@wailsio/runtime"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * HideAppIcon hides the app icon in the dock/taskbar. - */ -export function HideAppIcon(): $CancellablePromise { - return $Call.ByID(3413658144); -} - -/** - * RemoveBadge removes the badge label from the application icon. - * This method ensures the badge call is made on the main thread to avoid crashes. - */ -export function RemoveBadge(): $CancellablePromise { - return $Call.ByID(2752757297); -} - -/** - * SetBadge sets the badge label on the application icon. - * This method ensures the badge call is made on the main thread to avoid crashes. - */ -export function SetBadge(label: string): $CancellablePromise { - return $Call.ByID(1717705661, label); -} - -/** - * SetCustomBadge sets the badge label on the application icon with custom options. - * This method ensures the badge call is made on the main thread to avoid crashes. - */ -export function SetCustomBadge(label: string, options: $models.BadgeOptions): $CancellablePromise { - return $Call.ByID(2730169760, label, options); -} - -/** - * ShowAppIcon shows the app icon in the dock/taskbar. - */ -export function ShowAppIcon(): $CancellablePromise { - return $Call.ByID(3409697379); -} diff --git a/v3/examples/dock/frontend/bindings/github.com/wailsapp/wails/v3/pkg/services/dock/index.ts b/v3/examples/dock/frontend/bindings/github.com/wailsapp/wails/v3/pkg/services/dock/index.ts deleted file mode 100644 index fbdaf19f3..000000000 --- a/v3/examples/dock/frontend/bindings/github.com/wailsapp/wails/v3/pkg/services/dock/index.ts +++ /dev/null @@ -1,11 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as DockService from "./dockservice.js"; -export { - DockService -}; - -export { - BadgeOptions -} from "./models.js"; diff --git a/v3/examples/dock/frontend/bindings/github.com/wailsapp/wails/v3/pkg/services/dock/models.ts b/v3/examples/dock/frontend/bindings/github.com/wailsapp/wails/v3/pkg/services/dock/models.ts deleted file mode 100644 index f97c8a4c6..000000000 --- a/v3/examples/dock/frontend/bindings/github.com/wailsapp/wails/v3/pkg/services/dock/models.ts +++ /dev/null @@ -1,61 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Create as $Create } from "@wailsio/runtime"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as color$0 from "../../../../../../../image/color/models.js"; - -/** - * BadgeOptions represents options for customizing badge appearance - */ -export class BadgeOptions { - "TextColour": color$0.RGBA; - "BackgroundColour": color$0.RGBA; - "FontName": string; - "FontSize": number; - "SmallFontSize": number; - - /** Creates a new BadgeOptions instance. */ - constructor($$source: Partial = {}) { - if (!("TextColour" in $$source)) { - this["TextColour"] = (new color$0.RGBA()); - } - if (!("BackgroundColour" in $$source)) { - this["BackgroundColour"] = (new color$0.RGBA()); - } - if (!("FontName" in $$source)) { - this["FontName"] = ""; - } - if (!("FontSize" in $$source)) { - this["FontSize"] = 0; - } - if (!("SmallFontSize" in $$source)) { - this["SmallFontSize"] = 0; - } - - Object.assign(this, $$source); - } - - /** - * Creates a new BadgeOptions instance from a string or object. - */ - static createFrom($$source: any = {}): BadgeOptions { - const $$createField0_0 = $$createType0; - const $$createField1_0 = $$createType0; - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - if ("TextColour" in $$parsedSource) { - $$parsedSource["TextColour"] = $$createField0_0($$parsedSource["TextColour"]); - } - if ("BackgroundColour" in $$parsedSource) { - $$parsedSource["BackgroundColour"] = $$createField1_0($$parsedSource["BackgroundColour"]); - } - return new BadgeOptions($$parsedSource as Partial); - } -} - -// Private type creation functions -const $$createType0 = color$0.RGBA.createFrom; diff --git a/v3/examples/dock/frontend/bindings/image/color/index.ts b/v3/examples/dock/frontend/bindings/image/color/index.ts deleted file mode 100644 index 97b507b08..000000000 --- a/v3/examples/dock/frontend/bindings/image/color/index.ts +++ /dev/null @@ -1,6 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -export { - RGBA -} from "./models.js"; diff --git a/v3/examples/dock/frontend/bindings/image/color/models.ts b/v3/examples/dock/frontend/bindings/image/color/models.ts deleted file mode 100644 index 0d4eab56d..000000000 --- a/v3/examples/dock/frontend/bindings/image/color/models.ts +++ /dev/null @@ -1,46 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Create as $Create } from "@wailsio/runtime"; - -/** - * RGBA represents a traditional 32-bit alpha-premultiplied color, having 8 - * bits for each of red, green, blue and alpha. - * - * An alpha-premultiplied color component C has been scaled by alpha (A), so - * has valid values 0 <= C <= A. - */ -export class RGBA { - "R": number; - "G": number; - "B": number; - "A": number; - - /** Creates a new RGBA instance. */ - constructor($$source: Partial = {}) { - if (!("R" in $$source)) { - this["R"] = 0; - } - if (!("G" in $$source)) { - this["G"] = 0; - } - if (!("B" in $$source)) { - this["B"] = 0; - } - if (!("A" in $$source)) { - this["A"] = 0; - } - - Object.assign(this, $$source); - } - - /** - * Creates a new RGBA instance from a string or object. - */ - static createFrom($$source: any = {}): RGBA { - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - return new RGBA($$parsedSource as Partial); - } -} diff --git a/v3/examples/dock/frontend/dist/Inter-Medium.ttf b/v3/examples/dock/frontend/dist/Inter-Medium.ttf deleted file mode 100644 index a01f3777a..000000000 Binary files a/v3/examples/dock/frontend/dist/Inter-Medium.ttf and /dev/null differ diff --git a/v3/examples/dock/frontend/dist/assets/index-BJIh-HIc.js b/v3/examples/dock/frontend/dist/assets/index-BJIh-HIc.js deleted file mode 100644 index 5217ab9a7..000000000 --- a/v3/examples/dock/frontend/dist/assets/index-BJIh-HIc.js +++ /dev/null @@ -1,6 +0,0 @@ -(function(){const e=document.createElement("link").relList;if(e&&e.supports&&e.supports("modulepreload"))return;for(const o of document.querySelectorAll('link[rel="modulepreload"]'))n(o);new MutationObserver(o=>{for(const i of o)if(i.type==="childList")for(const s of i.addedNodes)s.tagName==="LINK"&&s.rel==="modulepreload"&&n(s)}).observe(document,{childList:!0,subtree:!0});function r(o){const i={};return o.integrity&&(i.integrity=o.integrity),o.referrerPolicy&&(i.referrerPolicy=o.referrerPolicy),o.crossOrigin==="use-credentials"?i.credentials="include":o.crossOrigin==="anonymous"?i.credentials="omit":i.credentials="same-origin",i}function n(o){if(o.ep)return;o.ep=!0;const i=r(o);fetch(o.href,i)}})();const ie="useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict";function K(t=21){let e="",r=t|0;for(;r--;)e+=ie[Math.random()*64|0];return e}const se=window.location.origin+"/wails/runtime",O=Object.freeze({Call:0,Clipboard:1,Application:2,Events:3,ContextMenu:4,Dialog:5,Window:6,Screens:7,System:8,Browser:9,CancelCall:10});let ce=K();function R(t,e=""){return function(r,n=null){return le(t,r,e,n)}}async function le(t,e,r,n){var o,i;let s=new URL(se);s.searchParams.append("object",t.toString()),s.searchParams.append("method",e.toString()),n&&s.searchParams.append("args",JSON.stringify(n));let l={"x-wails-client-id":ce};r&&(l["x-wails-window-name"]=r);let c=await fetch(s,{headers:l});if(!c.ok)throw new Error(await c.text());return((i=(o=c.headers.get("Content-Type"))===null||o===void 0?void 0:o.indexOf("application/json"))!==null&&i!==void 0?i:-1)!==-1?c.json():c.text()}R(O.System);const P=function(){var t,e,r,n,o;try{if(!((e=(t=window.chrome)===null||t===void 0?void 0:t.webview)===null||e===void 0)&&e.postMessage)return window.chrome.webview.postMessage.bind(window.chrome.webview);if(!((o=(n=(r=window.webkit)===null||r===void 0?void 0:r.messageHandlers)===null||n===void 0?void 0:n.external)===null||o===void 0)&&o.postMessage)return window.webkit.messageHandlers.external.postMessage.bind(window.webkit.messageHandlers.external)}catch{}return console.warn(` -%c⚠️ Browser Environment Detected %c - -%cOnly UI previews are available in the browser. For full functionality, please run the application in desktop mode. -More information at: https://v3.wails.io/learn/build/#using-a-browser-for-development -`,"background: #ffffff; color: #000000; font-weight: bold; padding: 4px 8px; border-radius: 4px; border: 2px solid #000000;","background: transparent;","color: #ffffff; font-style: italic; font-weight: bold;"),null}();function M(t){P==null||P(t)}function Q(){return window._wails.environment.OS==="windows"}function ae(){return!!window._wails.environment.Debug}function ue(){return new MouseEvent("mousedown").buttons===0}function Z(t){var e;return t.target instanceof HTMLElement?t.target:!(t.target instanceof HTMLElement)&&t.target instanceof Node&&(e=t.target.parentElement)!==null&&e!==void 0?e:document.body}document.addEventListener("DOMContentLoaded",()=>{});window.addEventListener("contextmenu",pe);const de=R(O.ContextMenu),fe=0;function we(t,e,r,n){de(fe,{id:t,x:e,y:r,data:n})}function pe(t){const e=Z(t),r=window.getComputedStyle(e).getPropertyValue("--custom-contextmenu").trim();if(r){t.preventDefault();const n=window.getComputedStyle(e).getPropertyValue("--custom-contextmenu-data");we(r,t.clientX,t.clientY,n)}else he(t,e)}function he(t,e){if(ae())return;switch(window.getComputedStyle(e).getPropertyValue("--default-contextmenu").trim()){case"show":return;case"hide":t.preventDefault();return}if(e.isContentEditable)return;const r=window.getSelection(),n=r&&r.toString().length>0;if(n)for(let o=0;o{F=t,F||(b=v=!1,u())};window.addEventListener("mousedown",N,{capture:!0});window.addEventListener("mousemove",N,{capture:!0});window.addEventListener("mouseup",N,{capture:!0});for(const t of["click","contextmenu","dblclick"])window.addEventListener(t,me,{capture:!0});function me(t){(E||v)&&(t.stopImmediatePropagation(),t.stopPropagation(),t.preventDefault())}const D=0,ye=1,k=2;function N(t){let e,r=t.buttons;switch(t.type){case"mousedown":e=D,H||(r=h|1<"u"||typeof e=="object"))try{var r=C.call(e);return(r===Ce||r===Me||r===Oe||r===Se)&&e("")==null}catch{}return!1})}function Pe(t){if(X(t))return!0;if(!t||typeof t!="function"&&typeof t!="object")return!1;try{y(t,null,B)}catch(e){if(e!==x)return!1}return!W(t)&&_(t)}function Ae(t){if(X(t))return!0;if(!t||typeof t!="function"&&typeof t!="object")return!1;if(Re)return _(t);if(W(t))return!1;var e=C.call(t);return e!==ze&&e!==xe&&!/^\[object HTML/.test(e)?!1:_(t)}const p=y?Pe:Ae;var I;class U extends Error{constructor(e,r){super(e,r),this.name="CancelError"}}class S extends Error{constructor(e,r,n){super((n??"Unhandled rejection in cancelled promise.")+" Reason: "+He(r),{cause:r}),this.promise=e,this.name="CancelledRejectionError"}}const f=Symbol("barrier"),J=Symbol("cancelImpl"),V=(I=Symbol.species)!==null&&I!==void 0?I:Symbol("speciesPolyfill");class a extends Promise{constructor(e,r){let n,o;if(super((c,d)=>{n=c,o=d}),this.constructor[V]!==Promise)throw new TypeError("CancellablePromise does not support transparent subclassing. Please refrain from overriding the [Symbol.species] static property.");let i={promise:this,resolve:n,reject:o,get oncancelled(){return r??null},set oncancelled(c){r=c??void 0}};const s={get root(){return s},resolving:!1,settled:!1};Object.defineProperties(this,{[f]:{configurable:!1,enumerable:!1,writable:!0,value:null},[J]:{configurable:!1,enumerable:!1,writable:!1,value:ee(i,s)}});const l=re(i,s);try{e(te(i,s),l)}catch(c){s.resolving?console.log("Unhandled exception in CancellablePromise executor.",c):l(c)}}cancel(e){return new a(r=>{Promise.all([this[J](new U("Promise cancelled.",{cause:e})),De(this)]).then(()=>r(),()=>r())})}cancelOn(e){return e.aborted?this.cancel(e.reason):e.addEventListener("abort",()=>void this.cancel(e.reason),{capture:!0}),this}then(e,r,n){if(!(this instanceof a))throw new TypeError("CancellablePromise.prototype.then called on an invalid object.");if(p(e)||(e=q),p(r)||(r=G),e===q&&r==G)return new a(i=>i(this));const o={};return this[f]=o,new a((i,s)=>{super.then(l=>{var c;this[f]===o&&(this[f]=null),(c=o.resolve)===null||c===void 0||c.call(o);try{i(e(l))}catch(d){s(d)}},l=>{var c;this[f]===o&&(this[f]=null),(c=o.resolve)===null||c===void 0||c.call(o);try{i(r(l))}catch(d){s(d)}})},async i=>{try{return n==null?void 0:n(i)}finally{await this.cancel(i)}})}catch(e,r){return this.then(void 0,e,r)}finally(e,r){if(!(this instanceof a))throw new TypeError("CancellablePromise.prototype.finally called on an invalid object.");return p(e)?this.then(n=>a.resolve(e()).then(()=>n),n=>a.resolve(e()).then(()=>{throw n}),r):this.then(e,e,r)}static get[V](){return Promise}static all(e){let r=Array.from(e);const n=r.length===0?a.resolve(r):new a((o,i)=>{Promise.all(r).then(o,i)},o=>z(n,r,o));return n}static allSettled(e){let r=Array.from(e);const n=r.length===0?a.resolve(r):new a((o,i)=>{Promise.allSettled(r).then(o,i)},o=>z(n,r,o));return n}static any(e){let r=Array.from(e);const n=r.length===0?a.resolve(r):new a((o,i)=>{Promise.any(r).then(o,i)},o=>z(n,r,o));return n}static race(e){let r=Array.from(e);const n=new a((o,i)=>{Promise.race(r).then(o,i)},o=>z(n,r,o));return n}static cancel(e){const r=new a(()=>{});return r.cancel(e),r}static timeout(e,r){const n=new a(()=>{});return AbortSignal&&typeof AbortSignal=="function"&&AbortSignal.timeout&&typeof AbortSignal.timeout=="function"?AbortSignal.timeout(e).addEventListener("abort",()=>void n.cancel(r)):setTimeout(()=>void n.cancel(r),e),n}static sleep(e,r){return new a(n=>{setTimeout(()=>n(r),e)})}static reject(e){return new a((r,n)=>n(e))}static resolve(e){return e instanceof a?e:new a(r=>r(e))}static withResolvers(){let e={oncancelled:null};return e.promise=new a((r,n)=>{e.resolve=r,e.reject=n},r=>{var n;(n=e.oncancelled)===null||n===void 0||n.call(e,r)}),e}}function ee(t,e){let r;return n=>{if(e.settled||(e.settled=!0,e.reason=n,t.reject(n),Promise.prototype.then.call(t.promise,void 0,o=>{if(o!==n)throw o})),!(!e.reason||!t.oncancelled))return r=new Promise(o=>{try{o(t.oncancelled(e.reason.cause))}catch(i){Promise.reject(new S(t.promise,i,"Unhandled exception in oncancelled callback."))}}).catch(o=>{Promise.reject(new S(t.promise,o,"Unhandled rejection in oncancelled callback."))}),t.oncancelled=null,r}}function te(t,e){return r=>{if(!e.resolving){if(e.resolving=!0,r===t.promise){if(e.settled)return;e.settled=!0,t.reject(new TypeError("A promise cannot be resolved with itself."));return}if(r!=null&&(typeof r=="object"||typeof r=="function")){let n;try{n=r.then}catch(o){e.settled=!0,t.reject(o);return}if(p(n)){try{let s=r.cancel;if(p(s)){const l=c=>{Reflect.apply(s,r,[c])};e.reason?ee(Object.assign(Object.assign({},t),{oncancelled:l}),e)(e.reason):t.oncancelled=l}}catch{}const o={root:e.root,resolving:!1,get settled(){return this.root.settled},set settled(s){this.root.settled=s},get reason(){return this.root.reason}},i=re(t,o);try{Reflect.apply(n,r,[te(t,o),i])}catch(s){i(s)}return}}e.settled||(e.settled=!0,t.resolve(r))}}}function re(t,e){return r=>{if(!e.resolving)if(e.resolving=!0,e.settled){try{if(r instanceof U&&e.reason instanceof U&&Object.is(r.cause,e.reason.cause))return}catch{}Promise.reject(new S(t.promise,r))}else e.settled=!0,t.reject(r)}}function z(t,e,r){const n=[];for(const o of e){let i;try{if(!p(o.then)||(i=o.cancel,!p(i)))continue}catch{continue}let s;try{s=Reflect.apply(i,o,[r])}catch(l){Promise.reject(new S(t,l,"Unhandled exception in cancel method."));continue}s&&n.push((s instanceof Promise?s:Promise.resolve(s)).catch(l=>{Promise.reject(new S(t,l,"Unhandled rejection in cancel method."))}))}return Promise.all(n)}function q(t){return t}function G(t){throw t}function He(t){try{if(t instanceof Error||typeof t!="object"||t.toString!==Object.prototype.toString)return""+t}catch{}try{return JSON.stringify(t)}catch{}try{return Object.prototype.toString.call(t)}catch{}return""}function De(t){var e;let r=(e=t[f])!==null&&e!==void 0?e:{};return"promise"in r||Object.assign(r,m()),t[f]==null&&(r.resolve(),t[f]=r),r.promise}let m=Promise.withResolvers;m&&typeof m=="function"?m=m.bind(Promise):m=function(){let t,e;return{promise:new Promise((n,o)=>{t=n,e=o}),resolve:t,reject:e}};window._wails=window._wails||{};window._wails.callResultHandler=Ue;window._wails.callErrorHandler=Ne;const ke=R(O.Call),Ie=R(O.CancelCall),g=new Map,Fe=0,Be=0;class _e extends Error{constructor(e,r){super(e,r),this.name="RuntimeError"}}function Ue(t,e,r){const n=ne(t);if(n)if(!e)n.resolve(void 0);else if(!r)n.resolve(e);else try{n.resolve(JSON.parse(e))}catch(o){n.reject(new TypeError("could not parse result: "+o.message,{cause:o}))}}function Ne(t,e,r){const n=ne(t);if(n)if(!r)n.reject(new Error(e));else{let o;try{o=JSON.parse(e)}catch(l){n.reject(new TypeError("could not parse error: "+l.message,{cause:l}));return}let i={};o.cause&&(i.cause=o.cause);let s;switch(o.kind){case"ReferenceError":s=new ReferenceError(o.message,i);break;case"TypeError":s=new TypeError(o.message,i);break;case"RuntimeError":s=new _e(o.message,i);break;default:s=new Error(o.message,i);break}n.reject(s)}}function ne(t){const e=g.get(t);return g.delete(t),e}function We(){let t;do t=K();while(g.has(t));return t}function Xe(t){const e=We(),r=a.withResolvers();g.set(e,{resolve:r.resolve,reject:r.reject});const n=ke(Fe,Object.assign({"call-id":e},t));let o=!1;n.then(()=>{o=!0},s=>{g.delete(e),r.reject(s)});const i=()=>(g.delete(e),Ie(Be,{"call-id":e}).catch(s=>{console.error("Error while requesting binding call cancellation:",s)}));return r.oncancelled=()=>o?i():n.then(i),r.promise}function oe(t,...e){return Xe({methodID:t,args:e})}window._wails=window._wails||{};window._wails.invoke=M;M("wails:runtime:ready");function Ye(){return oe(3413658144)}function Je(){return oe(3409697379)}const Ve=document.getElementById("show"),qe=document.getElementById("hide");Ve.addEventListener("click",()=>{Je()});qe.addEventListener("click",()=>{Ye()}); diff --git a/v3/examples/dock/frontend/dist/index.html b/v3/examples/dock/frontend/dist/index.html deleted file mode 100644 index 1836ad6e7..000000000 --- a/v3/examples/dock/frontend/dist/index.html +++ /dev/null @@ -1,33 +0,0 @@ - - - - - - - - Wails App - - - -
      - -

      Wails + Typescript

      -
      -
      - - -
      -
      - -
      - - diff --git a/v3/examples/dock/frontend/dist/style.css b/v3/examples/dock/frontend/dist/style.css deleted file mode 100644 index 0b9c58279..000000000 --- a/v3/examples/dock/frontend/dist/style.css +++ /dev/null @@ -1,157 +0,0 @@ -:root { - font-family: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", - "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", - sans-serif; - font-size: 16px; - line-height: 24px; - font-weight: 400; - color-scheme: light dark; - color: rgba(255, 255, 255, 0.87); - background-color: rgba(27, 38, 54, 1); - font-synthesis: none; - text-rendering: optimizeLegibility; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - -webkit-text-size-adjust: 100%; - user-select: none; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; -} - -@font-face { - font-family: "Inter"; - font-style: normal; - font-weight: 400; - src: local(""), - url("./Inter-Medium.ttf") format("truetype"); -} - -h3 { - font-size: 3em; - line-height: 1.1; -} - -a { - font-weight: 500; - color: #646cff; - text-decoration: inherit; -} - -a:hover { - color: #535bf2; -} - -button { - width: 60px; - height: 30px; - line-height: 30px; - border-radius: 3px; - border: none; - margin: 0 0 0 20px; - padding: 0 8px; - cursor: pointer; -} - -.result { - height: 20px; - line-height: 20px; -} - -body { - margin: 0; - display: flex; - place-items: center; - place-content: center; - min-width: 320px; - min-height: 100vh; -} - -.container { - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; -} - -h1 { - font-size: 3.2em; - line-height: 1.1; -} - -#app { - max-width: 1280px; - margin: 0 auto; - padding: 2rem; - text-align: center; -} - -.logo { - height: 6em; - padding: 1.5em; - will-change: filter; -} - -.logo:hover { - filter: drop-shadow(0 0 2em #e80000aa); -} - -.logo.vanilla:hover { - filter: drop-shadow(0 0 2em #f7df1eaa); -} - -.result { - height: 20px; - line-height: 20px; - margin: 1.5rem auto; - text-align: center; -} - -.footer { - margin-top: 1rem; - align-content: center; - text-align: center; -} - -@media (prefers-color-scheme: light) { - :root { - color: #213547; - background-color: #ffffff; - } - - a:hover { - color: #747bff; - } - - button { - background-color: #f9f9f9; - } -} - - -.input-box .btn:hover { - background-image: linear-gradient(to top, #cfd9df 0%, #e2ebf0 100%); - color: #333333; -} - -.input-box .input { - border: none; - border-radius: 3px; - outline: none; - height: 30px; - line-height: 30px; - padding: 0 10px; - color: black; - background-color: rgba(240, 240, 240, 1); - -webkit-font-smoothing: antialiased; -} - -.input-box .input:hover { - border: none; - background-color: rgba(255, 255, 255, 1); -} - -.input-box .input:focus { - border: none; - background-color: rgba(255, 255, 255, 1); -} \ No newline at end of file diff --git a/v3/examples/dock/frontend/dist/typescript.svg b/v3/examples/dock/frontend/dist/typescript.svg deleted file mode 100644 index d91c910cc..000000000 --- a/v3/examples/dock/frontend/dist/typescript.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/v3/examples/dock/frontend/dist/wails.png b/v3/examples/dock/frontend/dist/wails.png deleted file mode 100644 index 8bdf42483..000000000 Binary files a/v3/examples/dock/frontend/dist/wails.png and /dev/null differ diff --git a/v3/examples/dock/frontend/index.html b/v3/examples/dock/frontend/index.html deleted file mode 100644 index 1a310f0e9..000000000 --- a/v3/examples/dock/frontend/index.html +++ /dev/null @@ -1,33 +0,0 @@ - - - - - - - - Wails App - - -
      - -

      Wails + Typescript

      -
      -
      - - -
      -
      - -
      - - - diff --git a/v3/examples/dock/frontend/package-lock.json b/v3/examples/dock/frontend/package-lock.json deleted file mode 100644 index 0c0df727a..000000000 --- a/v3/examples/dock/frontend/package-lock.json +++ /dev/null @@ -1,936 +0,0 @@ -{ - "name": "frontend", - "version": "0.0.0", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "frontend", - "version": "0.0.0", - "dependencies": { - "@wailsio/runtime": "latest" - }, - "devDependencies": { - "typescript": "^4.9.3", - "vite": "^5.0.0" - } - }, - "node_modules/@esbuild/aix-ppc64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", - "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "aix" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/android-arm": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz", - "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/android-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz", - "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/android-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz", - "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/darwin-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz", - "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/darwin-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz", - "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/freebsd-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz", - "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/freebsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz", - "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-arm": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz", - "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz", - "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-ia32": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz", - "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-loong64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz", - "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==", - "cpu": [ - "loong64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-mips64el": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz", - "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==", - "cpu": [ - "mips64el" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-ppc64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz", - "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-riscv64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz", - "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-s390x": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz", - "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==", - "cpu": [ - "s390x" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz", - "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/netbsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz", - "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/openbsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz", - "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/sunos-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz", - "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/win32-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz", - "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/win32-ia32": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz", - "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/win32-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz", - "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.46.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.46.2.tgz", - "integrity": "sha512-Zj3Hl6sN34xJtMv7Anwb5Gu01yujyE/cLBDB2gnHTAHaWS1Z38L7kuSG+oAh0giZMqG060f/YBStXtMH6FvPMA==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/@rollup/rollup-android-arm64": { - "version": "4.46.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.46.2.tgz", - "integrity": "sha512-nTeCWY83kN64oQ5MGz3CgtPx8NSOhC5lWtsjTs+8JAJNLcP3QbLCtDDgUKQc/Ro/frpMq4SHUaHN6AMltcEoLQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.46.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.46.2.tgz", - "integrity": "sha512-HV7bW2Fb/F5KPdM/9bApunQh68YVDU8sO8BvcW9OngQVN3HHHkw99wFupuUJfGR9pYLLAjcAOA6iO+evsbBaPQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.46.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.46.2.tgz", - "integrity": "sha512-SSj8TlYV5nJixSsm/y3QXfhspSiLYP11zpfwp6G/YDXctf3Xkdnk4woJIF5VQe0of2OjzTt8EsxnJDCdHd2xMA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.46.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.46.2.tgz", - "integrity": "sha512-ZyrsG4TIT9xnOlLsSSi9w/X29tCbK1yegE49RYm3tu3wF1L/B6LVMqnEWyDB26d9Ecx9zrmXCiPmIabVuLmNSg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ] - }, - "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.46.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.46.2.tgz", - "integrity": "sha512-pCgHFoOECwVCJ5GFq8+gR8SBKnMO+xe5UEqbemxBpCKYQddRQMgomv1104RnLSg7nNvgKy05sLsY51+OVRyiVw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ] - }, - "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.46.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.46.2.tgz", - "integrity": "sha512-EtP8aquZ0xQg0ETFcxUbU71MZlHaw9MChwrQzatiE8U/bvi5uv/oChExXC4mWhjiqK7azGJBqU0tt5H123SzVA==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.46.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.46.2.tgz", - "integrity": "sha512-qO7F7U3u1nfxYRPM8HqFtLd+raev2K137dsV08q/LRKRLEc7RsiDWihUnrINdsWQxPR9jqZ8DIIZ1zJJAm5PjQ==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.46.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.46.2.tgz", - "integrity": "sha512-3dRaqLfcOXYsfvw5xMrxAk9Lb1f395gkoBYzSFcc/scgRFptRXL9DOaDpMiehf9CO8ZDRJW2z45b6fpU5nwjng==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.46.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.46.2.tgz", - "integrity": "sha512-fhHFTutA7SM+IrR6lIfiHskxmpmPTJUXpWIsBXpeEwNgZzZZSg/q4i6FU4J8qOGyJ0TR+wXBwx/L7Ho9z0+uDg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-loongarch64-gnu": { - "version": "4.46.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.46.2.tgz", - "integrity": "sha512-i7wfGFXu8x4+FRqPymzjD+Hyav8l95UIZ773j7J7zRYc3Xsxy2wIn4x+llpunexXe6laaO72iEjeeGyUFmjKeA==", - "cpu": [ - "loong64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-ppc64-gnu": { - "version": "4.46.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.46.2.tgz", - "integrity": "sha512-B/l0dFcHVUnqcGZWKcWBSV2PF01YUt0Rvlurci5P+neqY/yMKchGU8ullZvIv5e8Y1C6wOn+U03mrDylP5q9Yw==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.46.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.46.2.tgz", - "integrity": "sha512-32k4ENb5ygtkMwPMucAb8MtV8olkPT03oiTxJbgkJa7lJ7dZMr0GCFJlyvy+K8iq7F/iuOr41ZdUHaOiqyR3iQ==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-riscv64-musl": { - "version": "4.46.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.46.2.tgz", - "integrity": "sha512-t5B2loThlFEauloaQkZg9gxV05BYeITLvLkWOkRXogP4qHXLkWSbSHKM9S6H1schf/0YGP/qNKtiISlxvfmmZw==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.46.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.46.2.tgz", - "integrity": "sha512-YKjekwTEKgbB7n17gmODSmJVUIvj8CX7q5442/CK80L8nqOUbMtf8b01QkG3jOqyr1rotrAnW6B/qiHwfcuWQA==", - "cpu": [ - "s390x" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.46.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.46.2.tgz", - "integrity": "sha512-Jj5a9RUoe5ra+MEyERkDKLwTXVu6s3aACP51nkfnK9wJTraCC8IMe3snOfALkrjTYd2G1ViE1hICj0fZ7ALBPA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.46.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.46.2.tgz", - "integrity": "sha512-7kX69DIrBeD7yNp4A5b81izs8BqoZkCIaxQaOpumcJ1S/kmqNFjPhDu1LHeVXv0SexfHQv5cqHsxLOjETuqDuA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.46.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.46.2.tgz", - "integrity": "sha512-wiJWMIpeaak/jsbaq2HMh/rzZxHVW1rU6coyeNNpMwk5isiPjSTx0a4YLSlYDwBH/WBvLz+EtsNqQScZTLJy3g==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.46.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.46.2.tgz", - "integrity": "sha512-gBgaUDESVzMgWZhcyjfs9QFK16D8K6QZpwAaVNJxYDLHWayOta4ZMjGm/vsAEy3hvlS2GosVFlBlP9/Wb85DqQ==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.46.2", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.46.2.tgz", - "integrity": "sha512-CvUo2ixeIQGtF6WvuB87XWqPQkoFAFqW+HUo/WzHwuHDvIwZCtjdWXoYCcr06iKGydiqTclC4jU/TNObC/xKZg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@types/estree": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", - "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", - "dev": true, - "license": "MIT" - }, - "node_modules/@wailsio/runtime": { - "version": "3.0.0-alpha.66", - "resolved": "https://registry.npmjs.org/@wailsio/runtime/-/runtime-3.0.0-alpha.66.tgz", - "integrity": "sha512-ENLu8rn1griL1gFHJqkq1i+BVxrrA0JPJHYneUJYuf/s54kjuQViW0RKDEe/WTDo56ABpfykrd/T8OYpPUyXUw==", - "license": "MIT" - }, - "node_modules/esbuild": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", - "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=12" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.21.5", - "@esbuild/android-arm": "0.21.5", - "@esbuild/android-arm64": "0.21.5", - "@esbuild/android-x64": "0.21.5", - "@esbuild/darwin-arm64": "0.21.5", - "@esbuild/darwin-x64": "0.21.5", - "@esbuild/freebsd-arm64": "0.21.5", - "@esbuild/freebsd-x64": "0.21.5", - "@esbuild/linux-arm": "0.21.5", - "@esbuild/linux-arm64": "0.21.5", - "@esbuild/linux-ia32": "0.21.5", - "@esbuild/linux-loong64": "0.21.5", - "@esbuild/linux-mips64el": "0.21.5", - "@esbuild/linux-ppc64": "0.21.5", - "@esbuild/linux-riscv64": "0.21.5", - "@esbuild/linux-s390x": "0.21.5", - "@esbuild/linux-x64": "0.21.5", - "@esbuild/netbsd-x64": "0.21.5", - "@esbuild/openbsd-x64": "0.21.5", - "@esbuild/sunos-x64": "0.21.5", - "@esbuild/win32-arm64": "0.21.5", - "@esbuild/win32-ia32": "0.21.5", - "@esbuild/win32-x64": "0.21.5" - } - }, - "node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/nanoid": { - "version": "3.3.11", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", - "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "bin": { - "nanoid": "bin/nanoid.cjs" - }, - "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" - } - }, - "node_modules/picocolors": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", - "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", - "dev": true, - "license": "ISC" - }, - "node_modules/postcss": { - "version": "8.5.6", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", - "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "nanoid": "^3.3.11", - "picocolors": "^1.1.1", - "source-map-js": "^1.2.1" - }, - "engines": { - "node": "^10 || ^12 || >=14" - } - }, - "node_modules/rollup": { - "version": "4.46.2", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.46.2.tgz", - "integrity": "sha512-WMmLFI+Boh6xbop+OAGo9cQ3OgX9MIg7xOQjn+pTCwOkk+FNDAeAemXkJ3HzDJrVXleLOFVa1ipuc1AmEx1Dwg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/estree": "1.0.8" - }, - "bin": { - "rollup": "dist/bin/rollup" - }, - "engines": { - "node": ">=18.0.0", - "npm": ">=8.0.0" - }, - "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.46.2", - "@rollup/rollup-android-arm64": "4.46.2", - "@rollup/rollup-darwin-arm64": "4.46.2", - "@rollup/rollup-darwin-x64": "4.46.2", - "@rollup/rollup-freebsd-arm64": "4.46.2", - "@rollup/rollup-freebsd-x64": "4.46.2", - "@rollup/rollup-linux-arm-gnueabihf": "4.46.2", - "@rollup/rollup-linux-arm-musleabihf": "4.46.2", - "@rollup/rollup-linux-arm64-gnu": "4.46.2", - "@rollup/rollup-linux-arm64-musl": "4.46.2", - "@rollup/rollup-linux-loongarch64-gnu": "4.46.2", - "@rollup/rollup-linux-ppc64-gnu": "4.46.2", - "@rollup/rollup-linux-riscv64-gnu": "4.46.2", - "@rollup/rollup-linux-riscv64-musl": "4.46.2", - "@rollup/rollup-linux-s390x-gnu": "4.46.2", - "@rollup/rollup-linux-x64-gnu": "4.46.2", - "@rollup/rollup-linux-x64-musl": "4.46.2", - "@rollup/rollup-win32-arm64-msvc": "4.46.2", - "@rollup/rollup-win32-ia32-msvc": "4.46.2", - "@rollup/rollup-win32-x64-msvc": "4.46.2", - "fsevents": "~2.3.2" - } - }, - "node_modules/source-map-js": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", - "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/typescript": { - "version": "4.9.5", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz", - "integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==", - "dev": true, - "license": "Apache-2.0", - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=4.2.0" - } - }, - "node_modules/vite": { - "version": "5.4.19", - "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.19.tgz", - "integrity": "sha512-qO3aKv3HoQC8QKiNSTuUM1l9o/XX3+c+VTgLHbJWHZGeTPVAg2XwazI9UWzoxjIJCGCV2zU60uqMzjeLZuULqA==", - "dev": true, - "license": "MIT", - "dependencies": { - "esbuild": "^0.21.3", - "postcss": "^8.4.43", - "rollup": "^4.20.0" - }, - "bin": { - "vite": "bin/vite.js" - }, - "engines": { - "node": "^18.0.0 || >=20.0.0" - }, - "funding": { - "url": "https://github.com/vitejs/vite?sponsor=1" - }, - "optionalDependencies": { - "fsevents": "~2.3.3" - }, - "peerDependencies": { - "@types/node": "^18.0.0 || >=20.0.0", - "less": "*", - "lightningcss": "^1.21.0", - "sass": "*", - "sass-embedded": "*", - "stylus": "*", - "sugarss": "*", - "terser": "^5.4.0" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - }, - "less": { - "optional": true - }, - "lightningcss": { - "optional": true - }, - "sass": { - "optional": true - }, - "sass-embedded": { - "optional": true - }, - "stylus": { - "optional": true - }, - "sugarss": { - "optional": true - }, - "terser": { - "optional": true - } - } - } - } -} diff --git a/v3/examples/dock/frontend/package.json b/v3/examples/dock/frontend/package.json deleted file mode 100644 index b39da7ece..000000000 --- a/v3/examples/dock/frontend/package.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "name": "frontend", - "private": true, - "version": "0.0.0", - "type": "module", - "scripts": { - "dev": "vite", - "build:dev": "tsc && vite build --minify false --mode development", - "build": "tsc && vite build --mode production", - "preview": "vite preview" - }, - "dependencies": { - "@wailsio/runtime": "latest" - }, - "devDependencies": { - "typescript": "^4.9.3", - "vite": "^5.0.0" - } -} diff --git a/v3/examples/dock/frontend/public/Inter-Medium.ttf b/v3/examples/dock/frontend/public/Inter-Medium.ttf deleted file mode 100644 index a01f3777a..000000000 Binary files a/v3/examples/dock/frontend/public/Inter-Medium.ttf and /dev/null differ diff --git a/v3/examples/dock/frontend/public/style.css b/v3/examples/dock/frontend/public/style.css deleted file mode 100644 index 0b9c58279..000000000 --- a/v3/examples/dock/frontend/public/style.css +++ /dev/null @@ -1,157 +0,0 @@ -:root { - font-family: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", - "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", - sans-serif; - font-size: 16px; - line-height: 24px; - font-weight: 400; - color-scheme: light dark; - color: rgba(255, 255, 255, 0.87); - background-color: rgba(27, 38, 54, 1); - font-synthesis: none; - text-rendering: optimizeLegibility; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - -webkit-text-size-adjust: 100%; - user-select: none; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; -} - -@font-face { - font-family: "Inter"; - font-style: normal; - font-weight: 400; - src: local(""), - url("./Inter-Medium.ttf") format("truetype"); -} - -h3 { - font-size: 3em; - line-height: 1.1; -} - -a { - font-weight: 500; - color: #646cff; - text-decoration: inherit; -} - -a:hover { - color: #535bf2; -} - -button { - width: 60px; - height: 30px; - line-height: 30px; - border-radius: 3px; - border: none; - margin: 0 0 0 20px; - padding: 0 8px; - cursor: pointer; -} - -.result { - height: 20px; - line-height: 20px; -} - -body { - margin: 0; - display: flex; - place-items: center; - place-content: center; - min-width: 320px; - min-height: 100vh; -} - -.container { - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; -} - -h1 { - font-size: 3.2em; - line-height: 1.1; -} - -#app { - max-width: 1280px; - margin: 0 auto; - padding: 2rem; - text-align: center; -} - -.logo { - height: 6em; - padding: 1.5em; - will-change: filter; -} - -.logo:hover { - filter: drop-shadow(0 0 2em #e80000aa); -} - -.logo.vanilla:hover { - filter: drop-shadow(0 0 2em #f7df1eaa); -} - -.result { - height: 20px; - line-height: 20px; - margin: 1.5rem auto; - text-align: center; -} - -.footer { - margin-top: 1rem; - align-content: center; - text-align: center; -} - -@media (prefers-color-scheme: light) { - :root { - color: #213547; - background-color: #ffffff; - } - - a:hover { - color: #747bff; - } - - button { - background-color: #f9f9f9; - } -} - - -.input-box .btn:hover { - background-image: linear-gradient(to top, #cfd9df 0%, #e2ebf0 100%); - color: #333333; -} - -.input-box .input { - border: none; - border-radius: 3px; - outline: none; - height: 30px; - line-height: 30px; - padding: 0 10px; - color: black; - background-color: rgba(240, 240, 240, 1); - -webkit-font-smoothing: antialiased; -} - -.input-box .input:hover { - border: none; - background-color: rgba(255, 255, 255, 1); -} - -.input-box .input:focus { - border: none; - background-color: rgba(255, 255, 255, 1); -} \ No newline at end of file diff --git a/v3/examples/dock/frontend/public/typescript.svg b/v3/examples/dock/frontend/public/typescript.svg deleted file mode 100644 index d91c910cc..000000000 --- a/v3/examples/dock/frontend/public/typescript.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/v3/examples/dock/frontend/public/wails.png b/v3/examples/dock/frontend/public/wails.png deleted file mode 100644 index 8bdf42483..000000000 Binary files a/v3/examples/dock/frontend/public/wails.png and /dev/null differ diff --git a/v3/examples/dock/frontend/src/main.ts b/v3/examples/dock/frontend/src/main.ts deleted file mode 100644 index 6ef5af25f..000000000 --- a/v3/examples/dock/frontend/src/main.ts +++ /dev/null @@ -1,12 +0,0 @@ -import { DockService } from "../bindings/github.com/wailsapp/wails/v3/pkg/services/dock" - -const showButton = document.getElementById('show')! as HTMLButtonElement; -const hideButton = document.getElementById('hide')! as HTMLButtonElement; - -showButton.addEventListener('click', () => { - DockService.ShowAppIcon(); -}); - -hideButton.addEventListener('click', () => { - DockService.HideAppIcon(); -}); \ No newline at end of file diff --git a/v3/examples/dock/frontend/src/vite-env.d.ts b/v3/examples/dock/frontend/src/vite-env.d.ts deleted file mode 100644 index 11f02fe2a..000000000 --- a/v3/examples/dock/frontend/src/vite-env.d.ts +++ /dev/null @@ -1 +0,0 @@ -/// diff --git a/v3/examples/dock/frontend/tsconfig.json b/v3/examples/dock/frontend/tsconfig.json deleted file mode 100644 index c267ecf24..000000000 --- a/v3/examples/dock/frontend/tsconfig.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "compilerOptions": { - "target": "ESNext", - "useDefineForClassFields": true, - "module": "ESNext", - "lib": ["ESNext", "DOM"], - "moduleResolution": "Node", - "strict": true, - "resolveJsonModule": true, - "isolatedModules": true, - "esModuleInterop": true, - "noEmit": true, - "noUnusedLocals": true, - "noUnusedParameters": false, - "noImplicitAny": false, - "noImplicitReturns": true, - "skipLibCheck": true - }, - "include": ["src"] -} diff --git a/v3/examples/dock/main.go b/v3/examples/dock/main.go deleted file mode 100644 index 446645448..000000000 --- a/v3/examples/dock/main.go +++ /dev/null @@ -1,70 +0,0 @@ -package main - -import ( - "embed" - _ "embed" - "log" - - "github.com/wailsapp/wails/v3/pkg/application" - "github.com/wailsapp/wails/v3/pkg/services/dock" -) - -// Wails uses Go's `embed` package to embed the frontend files into the binary. -// Any files in the frontend/dist folder will be embedded into the binary and -// made available to the frontend. -// See https://pkg.go.dev/embed for more information. - -//go:embed all:frontend/dist -var assets embed.FS - -// main function serves as the application's entry point. It initializes the application, creates a window, -// and starts a goroutine that emits a time-based event every second. It subsequently runs the application and -// logs any error that might occur. -func main() { - - // Create a new Wails application by providing the necessary options. - // Variables 'Name' and 'Description' are for application metadata. - // 'Assets' configures the asset server with the 'FS' variable pointing to the frontend files. - // 'Bind' is a list of Go struct instances. The frontend has access to the methods of these instances. - // 'Mac' options tailor the application when running an macOS. - - dockService := dock.New() - - app := application.New(application.Options{ - Name: "dock", - Description: "A demo of using raw HTML & CSS", - Services: []application.Service{ - application.NewService(dockService), - }, - Assets: application.AssetOptions{ - Handler: application.AssetFileServerFS(assets), - }, - Mac: application.MacOptions{ - ApplicationShouldTerminateAfterLastWindowClosed: true, - }, - }) - - // Create a new window with the necessary options. - // 'Title' is the title of the window. - // 'Mac' options tailor the window when running on macOS. - // 'BackgroundColour' is the background colour of the window. - // 'URL' is the URL that will be loaded into the webview. - app.Window.NewWithOptions(application.WebviewWindowOptions{ - Title: "Window 1", - Mac: application.MacWindow{ - InvisibleTitleBarHeight: 50, - Backdrop: application.MacBackdropTranslucent, - TitleBar: application.MacTitleBarHiddenInset, - }, - BackgroundColour: application.NewRGB(27, 38, 54), - URL: "/", - }) - - // Run the application. This blocks until the application has been exited. - err := app.Run() - - // If an error occurred while running the application, log it and exit. - if err != nil { - log.Fatal(err) - } -} diff --git a/v3/examples/drag-n-drop/README.md b/v3/examples/drag-n-drop/README.md deleted file mode 100644 index a2cde8844..000000000 --- a/v3/examples/drag-n-drop/README.md +++ /dev/null @@ -1,75 +0,0 @@ -# File Drop Example - -This example demonstrates how to handle files being dragged from the operating system (Finder, Explorer, file managers) into a Wails application. - -Dropped files are automatically categorised by type and displayed in separate buckets: documents, images, or other files. - -## How it works - -1. Enable file drops in window options: - ```go - EnableFileDrop: true - ``` - -2. Mark elements as drop targets in HTML: - ```html -
      Drop files here
      - ``` - -3. Listen for the `WindowFilesDropped` event: - ```go - win.OnWindowEvent(events.Common.WindowFilesDropped, func(event *application.WindowEvent) { - files := event.Context().DroppedFiles() - details := event.Context().DropTargetDetails() - // Handle the dropped files - }) - ``` - -4. Optionally forward to frontend: - ```go - application.Get().Event.Emit("files-dropped", map[string]any{ - "files": files, - "details": details, - }) - ``` - -## Drop Target Details - -When files are dropped, you can get information about the drop location: - -- `ElementID` - The ID of the element that received the drop -- `ClassList` - CSS classes on the drop target -- `X`, `Y` - Coordinates of the drop within the element - -## Styling - -When files are dragged over a valid drop target, Wails adds the `file-drop-target-active` class: - -```css -.file-drop-target-active { - border-color: #4a9eff; - background: rgba(74, 158, 255, 0.1); -} -``` - -## Running the example - -```bash -go run main.go -``` - -Then drag files from your desktop or file manager into the drop zone. - -## HTML5 Drag and Drop API - -This example also includes a demonstration for dragging elements *within* your application via the HTML5 Drag and Drop API. - -Scroll down to the `Internal Drag and Drop` section within the launched application to interact with the demo. - -## Status - -| Platform | Status | -|----------|---------| -| Mac | Working | -| Windows | Working | -| Linux | Working | diff --git a/v3/examples/drag-n-drop/assets/index.html b/v3/examples/drag-n-drop/assets/index.html deleted file mode 100644 index 53af94212..000000000 --- a/v3/examples/drag-n-drop/assets/index.html +++ /dev/null @@ -1,435 +0,0 @@ - - - - - - Drag and Drop Demo - - - -

      Drag and Drop Demo

      - - -

      External File Drop

      -
      -

      - Drop files from your operating system (Finder, Explorer, file managers). - Uses EnableFileDrop: true and data-file-drop-target -

      -
      - -
      -
      -

      Drop files from your desktop or file manager here

      -
      - -
      -
      -

      Documents

      -
        -
      • No documents yet
      • -
      -
      - -
      -

      Images

      -
        -
      • No images yet
      • -
      -
      - -
      -

      Other Files

      -
        -
      • No other files yet
      • -
      -
      -
      -
      - - -

      Internal Drag and Drop

      -
      -

      - Drag items between zones using the HTML5 Drag and Drop API. - Uses draggable="true" and standard DOM events. -

      -
      - -
      -
      -
      -

      Tasks

      -
      Fix login bug
      -
      Update documentation
      -
      Add dark mode
      -
      Refactor API calls
      -
      Write unit tests
      -
      - -
      -
      -

      High Priority

      -
        -
        - -
        -

        Medium Priority

        -
          -
          - -
          -

          Low Priority

          -
            -
            -
            -
            -
            - -
            - Last action: No actions yet -
            - - - - diff --git a/v3/examples/drag-n-drop/main.go b/v3/examples/drag-n-drop/main.go deleted file mode 100644 index 5caafef1e..000000000 --- a/v3/examples/drag-n-drop/main.go +++ /dev/null @@ -1,60 +0,0 @@ -package main - -import ( - "embed" - "log" - - "github.com/wailsapp/wails/v3/pkg/application" - "github.com/wailsapp/wails/v3/pkg/events" -) - -//go:embed assets -var assets embed.FS - -func main() { - app := application.New(application.Options{ - Name: "File Drop Demo", - Description: "A demo of file drag and drop", - Assets: application.AssetOptions{ - Handler: application.BundledAssetFileServer(assets), - }, - Mac: application.MacOptions{ - ApplicationShouldTerminateAfterLastWindowClosed: true, - }, - }) - - win := app.Window.NewWithOptions(application.WebviewWindowOptions{ - Title: "File Drop Demo", - Width: 800, - Height: 600, - EnableFileDrop: true, - Mac: application.MacWindow{ - Backdrop: application.MacBackdropTranslucent, - TitleBar: application.MacTitleBarHiddenInsetUnified, - InvisibleTitleBarHeight: 50, - }, - }) - - // Listen for file drop events - win.OnWindowEvent(events.Common.WindowFilesDropped, func(event *application.WindowEvent) { - files := event.Context().DroppedFiles() - details := event.Context().DropTargetDetails() - - log.Printf("Files dropped: %v", files) - if details != nil { - log.Printf("Drop target: id=%s, classes=%v, x=%d, y=%d", - details.ElementID, details.ClassList, details.X, details.Y) - } - - // Emit event to frontend - application.Get().Event.Emit("files-dropped", map[string]any{ - "files": files, - "details": details, - }) - }) - - err := app.Run() - if err != nil { - log.Fatal(err) - } -} diff --git a/v3/examples/environment/README.md b/v3/examples/environment/README.md deleted file mode 100644 index 1f922f341..000000000 --- a/v3/examples/environment/README.md +++ /dev/null @@ -1,19 +0,0 @@ -# Screen Example - -This example will detect all attached screens and display their details. - -## Running the example - -To run the example, simply run the following command: - -```bash -go run . -``` - -# Status - -| Platform | Status | -|----------|---------| -| Mac | Working | -| Windows | Working | -| Linux | | diff --git a/v3/examples/environment/assets/index.html b/v3/examples/environment/assets/index.html deleted file mode 100644 index 32bb5ebba..000000000 --- a/v3/examples/environment/assets/index.html +++ /dev/null @@ -1,66 +0,0 @@ - - - - - Screens Demo - - - - - - - diff --git a/v3/examples/environment/main.go b/v3/examples/environment/main.go deleted file mode 100644 index 76822aaa9..000000000 --- a/v3/examples/environment/main.go +++ /dev/null @@ -1,43 +0,0 @@ -package main - -import ( - "embed" - _ "embed" - "log" - - "github.com/wailsapp/wails/v3/pkg/application" -) - -//go:embed assets/* -var assets embed.FS - -func main() { - - app := application.New(application.Options{ - Name: "Environment Demo", - Description: "A demo of the Environment API", - Mac: application.MacOptions{ - ApplicationShouldTerminateAfterLastWindowClosed: true, - }, - Assets: application.AssetOptions{ - Handler: application.BundledAssetFileServer(assets), - }, - }) - - app.Window.NewWithOptions(application.WebviewWindowOptions{ - Title: "Environment Demo", - Width: 800, - Height: 600, - Mac: application.MacWindow{ - Backdrop: application.MacBackdropTranslucent, - TitleBar: application.MacTitleBarHiddenInsetUnified, - InvisibleTitleBarHeight: 50, - }, - }) - - err := app.Run() - - if err != nil { - log.Fatal(err.Error()) - } -} diff --git a/v3/examples/events-bug/main.go b/v3/examples/events-bug/main.go deleted file mode 100644 index f3bf88554..000000000 --- a/v3/examples/events-bug/main.go +++ /dev/null @@ -1,60 +0,0 @@ -package main - -import ( - _ "embed" - "github.com/wailsapp/wails/v3/pkg/application" - "log" -) - -var app *application.App - -func main() { - app = application.New(application.Options{ - Name: "Key Bindings Demo", - Description: "A demo of the Key Bindings Options", - Mac: application.MacOptions{ - ApplicationShouldTerminateAfterLastWindowClosed: true, - }, - KeyBindings: map[string]func(window application.Window){ - "shift+ctrl+c": func(window application.Window) { - selection, err := app.Dialog.OpenFile(). - CanChooseFiles(true). - CanCreateDirectories(true). - ShowHiddenFiles(true). - PromptForMultipleSelection() - if err != nil { - println(err.Error()) - } - println(selection) - }, - }, - }) - - app.Window.NewWithOptions(application.WebviewWindowOptions{ - Name: "Window 1", - Title: "Window 1", - URL: "https://wails.io", - KeyBindings: map[string]func(window application.Window){ - "F12": func(window application.Window) { - window.OpenDevTools() - }, - }, - }) - - app.Window.NewWithOptions(application.WebviewWindowOptions{ - Name: "Window 2", - Title: "Window 2", - URL: "https://google.com", - KeyBindings: map[string]func(window application.Window){ - "F12": func(window application.Window) { - println("Window 2: Toggle Dev Tools") - }, - }, - }) - - err := app.Run() - if err != nil { - log.Fatal(err) - } - -} diff --git a/v3/examples/events/README.md b/v3/examples/events/README.md deleted file mode 100644 index 596540f5a..000000000 --- a/v3/examples/events/README.md +++ /dev/null @@ -1,25 +0,0 @@ -# Events Example - -This example is a demonstration of using the new events API. -It has 2 windows that can emit events from the frontend and the backend emits an event every 10 seconds. -All events emitted are logged either to the console or the window. - -It also demonstrates the use of `RegisterHook` to register a function to be called when an event is emitted. -For one window, it captures the `WindowClosing` event and prevents the window from closing twice. -The other window uses both hooks and events to show the window is gaining focus. - -## Running the example - -To run the example, simply run the following command: - -```bash -go run main.go -``` - -# Status - -| Platform | Status | -|----------|---------| -| Mac | | -| Windows | Working | -| Linux | | \ No newline at end of file diff --git a/v3/examples/events/assets/index.html b/v3/examples/events/assets/index.html deleted file mode 100644 index 069baabdb..000000000 --- a/v3/examples/events/assets/index.html +++ /dev/null @@ -1,29 +0,0 @@ - - - - - Title - - - -

            Events Demo

            -
            -The main program emits an event every 10s which will be displayed in the section below. -To send an event from this window, click here: -
            - - - - - diff --git a/v3/examples/events/main.go b/v3/examples/events/main.go deleted file mode 100644 index 6f3d71be5..000000000 --- a/v3/examples/events/main.go +++ /dev/null @@ -1,129 +0,0 @@ -package main - -import ( - "embed" - _ "embed" - "log" - "time" - - "github.com/wailsapp/wails/v3/pkg/application" - "github.com/wailsapp/wails/v3/pkg/events" -) - -//go:embed assets -var assets embed.FS - -func main() { - - app := application.New(application.Options{ - Name: "customEventProcessor Demo", - Description: "A demo of the customEventProcessor API", - Assets: application.AssetOptions{ - Handler: application.BundledAssetFileServer(assets), - }, - Mac: application.MacOptions{ - ApplicationShouldTerminateAfterLastWindowClosed: true, - }, - }) - - // Custom event handling - app.Event.On("myevent", func(e *application.CustomEvent) { - app.Logger.Info("[Go] CustomEvent received", "name", e.Name, "data", e.Data, "sender", e.Sender, "cancelled", e.IsCancelled()) - }) - - // OS specific application events - app.Event.OnApplicationEvent(events.Common.ApplicationStarted, func(event *application.ApplicationEvent) { - go func() { - ticker := time.NewTicker(10 * time.Second) - defer ticker.Stop() - for { - select { - case <-ticker.C: - // This emits a custom event every 10 seconds - // As it's sent from the application, the sender will be blank - app.Event.Emit("myevent", "hello") - case <-app.Context().Done(): - return - } - } - }() - }) - - app.Event.OnApplicationEvent(events.Common.ThemeChanged, func(event *application.ApplicationEvent) { - app.Logger.Info("System theme changed!") - if event.Context().IsDarkMode() { - app.Logger.Info("System is now using dark mode!") - } else { - app.Logger.Info("System is now using light mode!") - } - }) - - // Platform agnostic events - app.Event.OnApplicationEvent(events.Common.ApplicationStarted, func(event *application.ApplicationEvent) { - app.Logger.Info("events.Common.ApplicationStarted fired!") - }) - - win1 := app.Window.NewWithOptions(application.WebviewWindowOptions{ - Title: "Window 1", - Name: "Window 1", - Mac: application.MacWindow{ - Backdrop: application.MacBackdropTranslucent, - TitleBar: application.MacTitleBarHiddenInsetUnified, - InvisibleTitleBarHeight: 50, - }, - }) - - var countdown = 3 - - win1.RegisterHook(events.Common.WindowClosing, func(e *application.WindowEvent) { - countdown-- - if countdown == 0 { - app.Logger.Info("Window 1 Closing!") - return - } - app.Logger.Info("Window 1 Closing? Nope! Not closing!") - e.Cancel() - }) - - win2 := app.Window.NewWithOptions(application.WebviewWindowOptions{ - Title: "Window 2", - Mac: application.MacWindow{ - Backdrop: application.MacBackdropTranslucent, - TitleBar: application.MacTitleBarHiddenInsetUnified, - InvisibleTitleBarHeight: 50, - }, - }) - - go func() { - ticker := time.NewTicker(10 * time.Second) - defer ticker.Stop() - for { - select { - case <-ticker.C: - win2.EmitEvent("windowevent", "ooooh!") - case <-app.Context().Done(): - return - } - } - }() - - var cancel bool - - win2.RegisterHook(events.Common.WindowFocus, func(e *application.WindowEvent) { - app.Logger.Info("[Hook] Window focus!") - cancel = !cancel - if cancel { - e.Cancel() - } - }) - - win2.OnWindowEvent(events.Common.WindowFocus, func(e *application.WindowEvent) { - app.Logger.Info("[OnWindowEvent] Window focus!") - }) - - err := app.Run() - - if err != nil { - log.Fatal(err.Error()) - } -} diff --git a/v3/examples/file-association/.gitignore b/v3/examples/file-association/.gitignore deleted file mode 100644 index 4b51c175c..000000000 --- a/v3/examples/file-association/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -.task -bin -wails.syso \ No newline at end of file diff --git a/v3/examples/file-association/Inter Font License.txt b/v3/examples/file-association/Inter Font License.txt deleted file mode 100644 index b525cbf3a..000000000 --- a/v3/examples/file-association/Inter Font License.txt +++ /dev/null @@ -1,93 +0,0 @@ -Copyright 2020 The Inter Project Authors (https://github.com/rsms/inter) - -This Font Software is licensed under the SIL Open Font License, Version 1.1. -This license is copied below, and is also available with a FAQ at: -http://scripts.sil.org/OFL - - ------------------------------------------------------------ -SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 ------------------------------------------------------------ - -PREAMBLE -The goals of the Open Font License (OFL) are to stimulate worldwide -development of collaborative font projects, to support the font creation -efforts of academic and linguistic communities, and to provide a free and -open framework in which fonts may be shared and improved in partnership -with others. - -The OFL allows the licensed fonts to be used, studied, modified and -redistributed freely as long as they are not sold by themselves. The -fonts, including any derivative works, can be bundled, embedded, -redistributed and/or sold with any software provided that any reserved -names are not used by derivative works. The fonts and derivatives, -however, cannot be released under any other type of license. The -requirement for fonts to remain under this license does not apply -to any document created using the fonts or their derivatives. - -DEFINITIONS -"Font Software" refers to the set of files released by the Copyright -Holder(s) under this license and clearly marked as such. This may -include source files, build scripts and documentation. - -"Reserved Font Name" refers to any names specified as such after the -copyright statement(s). - -"Original Version" refers to the collection of Font Software components as -distributed by the Copyright Holder(s). - -"Modified Version" refers to any derivative made by adding to, deleting, -or substituting -- in part or in whole -- any of the components of the -Original Version, by changing formats or by porting the Font Software to a -new environment. - -"Author" refers to any designer, engineer, programmer, technical -writer or other person who contributed to the Font Software. - -PERMISSION & CONDITIONS -Permission is hereby granted, free of charge, to any person obtaining -a copy of the Font Software, to use, study, copy, merge, embed, modify, -redistribute, and sell modified and unmodified copies of the Font -Software, subject to the following conditions: - -1) Neither the Font Software nor any of its individual components, -in Original or Modified Versions, may be sold by itself. - -2) Original or Modified Versions of the Font Software may be bundled, -redistributed and/or sold with any software, provided that each copy -contains the above copyright notice and this license. These can be -included either as stand-alone text files, human-readable headers or -in the appropriate machine-readable metadata fields within text or -binary files as long as those fields can be easily viewed by the user. - -3) No Modified Version of the Font Software may use the Reserved Font -Name(s) unless explicit written permission is granted by the corresponding -Copyright Holder. This restriction only applies to the primary font name as -presented to the users. - -4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font -Software shall not be used to promote, endorse or advertise any -Modified Version, except to acknowledge the contribution(s) of the -Copyright Holder(s) and the Author(s) or with their explicit written -permission. - -5) The Font Software, modified or unmodified, in part or in whole, -must be distributed entirely under this license, and must not be -distributed under any other license. The requirement for fonts to -remain under this license does not apply to any document created -using the Font Software. - -TERMINATION -This license becomes null and void if any of the above conditions are -not met. - -DISCLAIMER -THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT -OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE -COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL -DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM -OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/v3/examples/file-association/README.md b/v3/examples/file-association/README.md deleted file mode 100644 index 0aa08023f..000000000 --- a/v3/examples/file-association/README.md +++ /dev/null @@ -1,11 +0,0 @@ -# File Association Sample Project - -This sample project demonstrates how to associate a file type with an application. -More info at: https://v3.wails.io/learn/guides/file-associations/ - -To run the sample, follow these steps: - -1. Run `wails3 package` to generate the package. -2. On Windows, run the installer that was built in the `bin` directory. -3. Double-click on the `test.wails` file to open it with the application. -4. On macOS, double-click on the `test.wails` file and select the built application. \ No newline at end of file diff --git a/v3/examples/file-association/Taskfile.yml b/v3/examples/file-association/Taskfile.yml deleted file mode 100644 index 4ec68e23f..000000000 --- a/v3/examples/file-association/Taskfile.yml +++ /dev/null @@ -1,54 +0,0 @@ -version: '3' - -includes: - common: ./build/Taskfile.common.yml - windows: ./build/Taskfile.windows.yml - darwin: ./build/Taskfile.darwin.yml - linux: ./build/Taskfile.linux.yml - -vars: - APP_NAME: "fileassoc" - BIN_DIR: "bin" - VITE_PORT: '{{.WAILS_VITE_PORT | default 9245}}' - -tasks: - build: - summary: Builds the application - cmds: - - task: "{{OS}}:build" - - package: - summary: Packages a production build of the application - cmds: - - task: "{{OS}}:package" - - run: - summary: Runs the application - cmds: - - task: "{{OS}}:run" - - dev: - summary: Runs the application in development mode - cmds: - - wails3 dev -config ./build/config.yml -port {{.VITE_PORT}} - - darwin:build:universal: - summary: Builds darwin universal binary (arm64 + amd64) - cmds: - - task: darwin:build - vars: - ARCH: amd64 - - mv {{.BIN_DIR}}/{{.APP_NAME}} {{.BIN_DIR}}/{{.APP_NAME}}-amd64 - - task: darwin:build - vars: - ARCH: arm64 - - mv {{.BIN_DIR}}/{{.APP_NAME}} {{.BIN_DIR}}/{{.APP_NAME}}-arm64 - - lipo -create -output {{.BIN_DIR}}/{{.APP_NAME}} {{.BIN_DIR}}/{{.APP_NAME}}-amd64 {{.BIN_DIR}}/{{.APP_NAME}}-arm64 - - rm {{.BIN_DIR}}/{{.APP_NAME}}-amd64 {{.BIN_DIR}}/{{.APP_NAME}}-arm64 - - darwin:package:universal: - summary: Packages darwin universal binary (arm64 + amd64) - deps: - - darwin:build:universal - cmds: - - task: darwin:create:app:bundle diff --git a/v3/examples/file-association/build/Info.dev.plist b/v3/examples/file-association/build/Info.dev.plist deleted file mode 100644 index 327c94603..000000000 --- a/v3/examples/file-association/build/Info.dev.plist +++ /dev/null @@ -1,32 +0,0 @@ - - - - CFBundlePackageType - APPL - CFBundleName - My Product - CFBundleExecutable - fileassoc - CFBundleIdentifier - - CFBundleVersion - 0.1.0 - CFBundleGetInfoString - This is a comment - CFBundleShortVersionString - 0.1.0 - CFBundleIconFile - icons - LSMinimumSystemVersion - 10.13.0 - NSHighResolutionCapable - true - NSHumanReadableCopyright - © now, My Company - NSAppTransportSecurity - - NSAllowsLocalNetworking - - - - \ No newline at end of file diff --git a/v3/examples/file-association/build/Info.plist b/v3/examples/file-association/build/Info.plist deleted file mode 100644 index 1b3520754..000000000 --- a/v3/examples/file-association/build/Info.plist +++ /dev/null @@ -1,27 +0,0 @@ - - - - CFBundlePackageType - APPL - CFBundleName - My Product - CFBundleExecutable - fileassoc - CFBundleIdentifier - - CFBundleVersion - 0.1.0 - CFBundleGetInfoString - This is a comment - CFBundleShortVersionString - 0.1.0 - CFBundleIconFile - icons - LSMinimumSystemVersion - 10.13.0 - NSHighResolutionCapable - true - NSHumanReadableCopyright - © now, My Company - - \ No newline at end of file diff --git a/v3/examples/file-association/build/Taskfile.common.yml b/v3/examples/file-association/build/Taskfile.common.yml deleted file mode 100644 index 650c8ea83..000000000 --- a/v3/examples/file-association/build/Taskfile.common.yml +++ /dev/null @@ -1,75 +0,0 @@ -version: '3' - -tasks: - go:mod:tidy: - summary: Runs `go mod tidy` - internal: true - generates: - - go.sum - sources: - - go.mod - cmds: - - go mod tidy - - install:frontend:deps: - summary: Install frontend dependencies - dir: frontend - sources: - - package.json - - package-lock.json - generates: - - node_modules/* - preconditions: - - sh: npm version - msg: "Looks like npm isn't installed. Npm is part of the Node installer: https://nodejs.org/en/download/" - cmds: - - npm install - - build:frontend: - summary: Build the frontend project - dir: frontend - sources: - - "**/*" - generates: - - dist/* - deps: - - task: install:frontend:deps - - task: generate:bindings - cmds: - - npm run build -q - - generate:bindings: - summary: Generates bindings for the frontend - sources: - - "**/*.go" - - go.mod - - go.sum - generates: - - "frontend/bindings/**/*" - cmds: - - wails3 generate bindings -f '{{.BUILD_FLAGS}}' -clean=true {{if .UseTypescript}} -ts{{end}} - - generate:icons: - summary: Generates Windows `.ico` and Mac `.icns` files from an image - dir: build - sources: - - "appicon.png" - generates: - - "icons.icns" - - "icon.ico" - cmds: - - wails3 generate icons -input appicon.png - - dev:frontend: - summary: Runs the frontend in development mode - dir: frontend - deps: - - task: install:frontend:deps - cmds: - - npm run dev -- --port {{.VITE_PORT}} --strictPort - - update:build-assets: - summary: Updates the build assets - dir: build - cmds: - - wails3 update build-assets -name "{{.APP_NAME}}" -binaryname "{{.APP_NAME}}" -config config.yml -dir . \ No newline at end of file diff --git a/v3/examples/file-association/build/Taskfile.darwin.yml b/v3/examples/file-association/build/Taskfile.darwin.yml deleted file mode 100644 index 45db6d067..000000000 --- a/v3/examples/file-association/build/Taskfile.darwin.yml +++ /dev/null @@ -1,45 +0,0 @@ -version: '3' - -includes: - common: Taskfile.common.yml - -tasks: - build: - summary: Creates a production build of the application - deps: - - task: common:go:mod:tidy - - task: common:build:frontend - - task: common:generate:icons - cmds: - - go build {{.BUILD_FLAGS}} -o {{.BIN_DIR}}/{{.APP_NAME}} - vars: - BUILD_FLAGS: '{{if eq .PRODUCTION "true"}}-tags production -trimpath -ldflags="-w -s"{{else}}-gcflags=all="-l"{{end}}' - env: - GOOS: darwin - CGO_ENABLED: 1 - GOARCH: '{{.ARCH | default ARCH}}' - CGO_CFLAGS: "-mmacosx-version-min=10.15" - CGO_LDFLAGS: "-mmacosx-version-min=10.15" - MACOSX_DEPLOYMENT_TARGET: "10.15" - PRODUCTION: '{{.PRODUCTION | default "false"}}' - - package: - summary: Packages a production build of the application into a `.app` bundle - deps: - - task: build - vars: - PRODUCTION: "true" - cmds: - - task: create:app:bundle - - create:app:bundle: - summary: Creates an `.app` bundle - cmds: - - mkdir -p {{.BIN_DIR}}/{{.APP_NAME}}.app/Contents/{MacOS,Resources} - - cp build/icons.icns {{.BIN_DIR}}/{{.APP_NAME}}.app/Contents/Resources - - cp {{.BIN_DIR}}/{{.APP_NAME}} {{.BIN_DIR}}/{{.APP_NAME}}.app/Contents/MacOS - - cp build/Info.plist {{.BIN_DIR}}/{{.APP_NAME}}.app/Contents - - run: - cmds: - - '{{.BIN_DIR}}/{{.APP_NAME}}' diff --git a/v3/examples/file-association/build/Taskfile.linux.yml b/v3/examples/file-association/build/Taskfile.linux.yml deleted file mode 100644 index 814ee0ae1..000000000 --- a/v3/examples/file-association/build/Taskfile.linux.yml +++ /dev/null @@ -1,66 +0,0 @@ -version: '3' - -includes: - common: Taskfile.common.yml - -tasks: - build: - summary: Builds the application for Linux - deps: - - task: common:go:mod:tidy - - task: common:build:frontend - - task: common:generate:icons - cmds: - - go build {{.BUILD_FLAGS}} -o {{.BIN_DIR}}/{{.APP_NAME}} - vars: - BUILD_FLAGS: '{{if eq .PRODUCTION "true"}}-tags production -trimpath -ldflags="-w -s"{{else}}-gcflags=all="-l"{{end}}' - env: - GOOS: linux - CGO_ENABLED: 1 - GOARCH: '{{.ARCH | default ARCH}}' - PRODUCTION: '{{.PRODUCTION | default "false"}}' - - package: - summary: Packages a production build of the application for Linux - deps: - - task: build - vars: - PRODUCTION: "true" - cmds: - - task: create:appimage - - create:appimage: - summary: Creates an AppImage - dir: build/appimage - deps: - - task: build - vars: - PRODUCTION: "true" - - task: generate:dotdesktop - cmds: - - cp {{.APP_BINARY}} {{.APP_NAME}} - - cp ../appicon.png appicon.png - - wails3 generate appimage -binary {{.APP_NAME}} -icon {{.ICON}} -desktopfile {{.DESKTOP_FILE}} -outputdir {{.OUTPUT_DIR}} -builddir {{.ROOT_DIR}}/build/appimage - vars: - APP_NAME: '{{.APP_NAME}}' - APP_BINARY: '../../bin/{{.APP_NAME}}' - ICON: '../appicon.png' - DESKTOP_FILE: '{{.APP_NAME}}.desktop' - OUTPUT_DIR: '../../bin' - - generate:dotdesktop: - summary: Generates a `.desktop` file - dir: build - cmds: - - mkdir -p {{.ROOT_DIR}}/build/appimage - - wails3 generate .desktop -name "{{.APP_NAME}}" -exec "{{.EXEC}}" -icon "{{.ICON}}" -outputfile {{.ROOT_DIR}}/build/appimage/{{.APP_NAME}}.desktop -categories "{{.CATEGORIES}}" - vars: - APP_NAME: '{{.APP_NAME}}' - EXEC: '{{.APP_NAME}}' - ICON: 'appicon' - CATEGORIES: 'Development;' - OUTPUTFILE: '{{.ROOT_DIR}}/build/appimage/{{.APP_NAME}}.desktop' - - run: - cmds: - - '{{.BIN_DIR}}/{{.APP_NAME}}' diff --git a/v3/examples/file-association/build/Taskfile.windows.yml b/v3/examples/file-association/build/Taskfile.windows.yml deleted file mode 100644 index f141fcd2f..000000000 --- a/v3/examples/file-association/build/Taskfile.windows.yml +++ /dev/null @@ -1,53 +0,0 @@ -version: '3' - -includes: - common: Taskfile.common.yml - -tasks: - build: - summary: Builds the application for Windows - deps: - - task: common:go:mod:tidy - - task: common:build:frontend - - task: common:generate:icons - - task: generate:syso - cmds: - - go build {{.BUILD_FLAGS}} -o {{.BIN_DIR}}/{{.APP_NAME}}.exe - - powershell Remove-item *.syso - vars: - BUILD_FLAGS: '{{if eq .PRODUCTION "true"}}-tags production -trimpath -ldflags="-w -s -H windowsgui"{{else}}-gcflags=all="-l"{{end}}' - env: - GOOS: windows - CGO_ENABLED: 0 - GOARCH: '{{.ARCH | default ARCH}}' - PRODUCTION: '{{.PRODUCTION | default "false"}}' - - package: - summary: Packages a production build of the application into a `.exe` bundle - cmds: - - task: create:nsis:installer - - generate:syso: - summary: Generates Windows `.syso` file - dir: build - cmds: - - wails3 generate syso -arch {{.ARCH}} -icon icon.ico -manifest wails.exe.manifest -info info.json - vars: - ARCH: '{{.ARCH | default ARCH}}' - - create:nsis:installer: - summary: Creates an NSIS installer - dir: build/nsis - deps: - - task: build - vars: - PRODUCTION: "true" - cmds: - - makensis -DARG_WAILS_{{.ARG_FLAG}}_BINARY="{{.ROOT_DIR}}\{{.BIN_DIR}}\{{.APP_NAME}}.exe" project.nsi - vars: - ARCH: '{{.ARCH | default ARCH}}' - ARG_FLAG: '{{if eq .ARCH "amd64"}}AMD64{{else}}ARM64{{end}}' - - run: - cmds: - - '{{.BIN_DIR}}\\{{.APP_NAME}}.exe' \ No newline at end of file diff --git a/v3/examples/file-association/build/appicon.png b/v3/examples/file-association/build/appicon.png deleted file mode 100644 index 63617fe4f..000000000 Binary files a/v3/examples/file-association/build/appicon.png and /dev/null differ diff --git a/v3/examples/file-association/build/appimage/build.sh b/v3/examples/file-association/build/appimage/build.sh deleted file mode 100644 index fcba535e5..000000000 --- a/v3/examples/file-association/build/appimage/build.sh +++ /dev/null @@ -1,26 +0,0 @@ -#!/usr/bin/env bash -# Copyright (c) 2018-Present Lea Anthony -# SPDX-License-Identifier: MIT - -# Fail script on any error -set -euxo pipefail - -# Define variables -APP_DIR="${APP_NAME}.AppDir" - -# Create AppDir structure -mkdir -p "${APP_DIR}/usr/bin" -cp -r "${APP_BINARY}" "${APP_DIR}/usr/bin/" -cp "${ICON_PATH}" "${APP_DIR}/" -cp "${DESKTOP_FILE}" "${APP_DIR}/" - -# Download linuxdeploy and make it executable -wget -q -4 -N https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-x86_64.AppImage -chmod +x linuxdeploy-x86_64.AppImage - -# Run linuxdeploy to bundle the application -./linuxdeploy-x86_64.AppImage --appdir "${APP_DIR}" --output appimage - -# Rename the generated AppImage -mv "${APP_NAME}*.AppImage" "${APP_NAME}.AppImage" - diff --git a/v3/examples/file-association/build/config.yml b/v3/examples/file-association/build/config.yml deleted file mode 100644 index 0786788ae..000000000 --- a/v3/examples/file-association/build/config.yml +++ /dev/null @@ -1,32 +0,0 @@ -# This file contains the configuration for this project. -# When you update `info` or `fileAssociations`, run `wails3 task common:update:build-assets` to update the assets. -# Note that this will overwrite any changes you have made to the assets. -version: '3' - -# This information is used to generate the build assets. -info: - companyName: "My Company" # The name of the company - productName: "My Product" # The name of the application - productIdentifier: "com.mycompany.myproduct" # The unique product identifier - description: "A program that does X" # The application description - copyright: "(c) 2025, My Company" # Copyright text - comments: "Some Product Comments" # Comments - version: "v0.0.1" # The application version - -# File Associations -# More information at: https://v3.wails.io/noit/done/yet -fileAssociations: - - ext: wails - name: Wails - description: Wails Application File - iconName: icon - role: Editor -# - ext: jpg -# name: JPEG -# description: Image File -# iconName: jpegFileIcon -# role: Editor - -# Other data -other: - - name: My Other Data \ No newline at end of file diff --git a/v3/examples/file-association/build/devmode.config.yaml b/v3/examples/file-association/build/devmode.config.yaml deleted file mode 100644 index 7d674a261..000000000 --- a/v3/examples/file-association/build/devmode.config.yaml +++ /dev/null @@ -1,28 +0,0 @@ -config: - root_path: . - log_level: warn - debounce: 1000 - ignore: - dir: - - .git - - node_modules - - frontend - - bin - file: - - .DS_Store - - .gitignore - - .gitkeep - watched_extension: - - "*.go" - git_ignore: true - executes: - - cmd: wails3 task common:install:frontend:deps - type: once - - cmd: wails3 task common:dev:frontend - type: background - - cmd: go mod tidy - type: blocking - - cmd: wails3 task build - type: blocking - - cmd: wails3 task run - type: primary diff --git a/v3/examples/file-association/build/icon.ico b/v3/examples/file-association/build/icon.ico deleted file mode 100644 index bfa0690b7..000000000 Binary files a/v3/examples/file-association/build/icon.ico and /dev/null differ diff --git a/v3/examples/file-association/build/icons.icns b/v3/examples/file-association/build/icons.icns deleted file mode 100644 index 1b5bd4c86..000000000 Binary files a/v3/examples/file-association/build/icons.icns and /dev/null differ diff --git a/v3/examples/file-association/build/info.json b/v3/examples/file-association/build/info.json deleted file mode 100644 index 850b2b5b0..000000000 --- a/v3/examples/file-association/build/info.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "fixed": { - "file_version": "0.1.0" - }, - "info": { - "0000": { - "ProductVersion": "0.1.0", - "CompanyName": "My Company", - "FileDescription": "My Product Description", - "LegalCopyright": "© now, My Company", - "ProductName": "My Product", - "Comments": "This is a comment" - } - } -} \ No newline at end of file diff --git a/v3/examples/file-association/build/nsis/project.nsi b/v3/examples/file-association/build/nsis/project.nsi deleted file mode 100644 index 11ebc1ec7..000000000 --- a/v3/examples/file-association/build/nsis/project.nsi +++ /dev/null @@ -1,112 +0,0 @@ -Unicode true - -#### -## Please note: Template replacements don't work in this file. They are provided with default defines like -## mentioned underneath. -## If the keyword is not defined, "wails_tools.nsh" will populate them. -## If they are defined here, "wails_tools.nsh" will not touch them. This allows you to use this project.nsi manually -## from outside of Wails for debugging and development of the installer. -## -## For development first make a wails nsis build to populate the "wails_tools.nsh": -## > wails build --target windows/amd64 --nsis -## Then you can call makensis on this file with specifying the path to your binary: -## For a AMD64 only installer: -## > makensis -DARG_WAILS_AMD64_BINARY=..\..\bin\app.exe -## For a ARM64 only installer: -## > makensis -DARG_WAILS_ARM64_BINARY=..\..\bin\app.exe -## For a installer with both architectures: -## > makensis -DARG_WAILS_AMD64_BINARY=..\..\bin\app-amd64.exe -DARG_WAILS_ARM64_BINARY=..\..\bin\app-arm64.exe -#### -## The following information is taken from the wails_tools.nsh file, but they can be overwritten here. -#### -## !define INFO_PROJECTNAME "my-project" # Default "fileassoc" -## !define INFO_COMPANYNAME "My Company" # Default "My Company" -## !define INFO_PRODUCTNAME "My Product Name" # Default "My Product" -## !define INFO_PRODUCTVERSION "1.0.0" # Default "0.1.0" -## !define INFO_COPYRIGHT "(c) Now, My Company" # Default "© now, My Company" -### -## !define PRODUCT_EXECUTABLE "Application.exe" # Default "${INFO_PROJECTNAME}.exe" -## !define UNINST_KEY_NAME "UninstKeyInRegistry" # Default "${INFO_COMPANYNAME}${INFO_PRODUCTNAME}" -#### -## !define REQUEST_EXECUTION_LEVEL "admin" # Default "admin" see also https://nsis.sourceforge.io/Docs/Chapter4.html -#### -## Include the wails tools -#### -!include "wails_tools.nsh" - -# The version information for this two must consist of 4 parts -VIProductVersion "${INFO_PRODUCTVERSION}.0" -VIFileVersion "${INFO_PRODUCTVERSION}.0" - -VIAddVersionKey "CompanyName" "${INFO_COMPANYNAME}" -VIAddVersionKey "FileDescription" "${INFO_PRODUCTNAME} Installer" -VIAddVersionKey "ProductVersion" "${INFO_PRODUCTVERSION}" -VIAddVersionKey "FileVersion" "${INFO_PRODUCTVERSION}" -VIAddVersionKey "LegalCopyright" "${INFO_COPYRIGHT}" -VIAddVersionKey "ProductName" "${INFO_PRODUCTNAME}" - -# Enable HiDPI support. https://nsis.sourceforge.io/Reference/ManifestDPIAware -ManifestDPIAware true - -!include "MUI.nsh" - -!define MUI_ICON "..\icon.ico" -!define MUI_UNICON "..\icon.ico" -# !define MUI_WELCOMEFINISHPAGE_BITMAP "resources\leftimage.bmp" #Include this to add a bitmap on the left side of the Welcome Page. Must be a size of 164x314 -!define MUI_FINISHPAGE_NOAUTOCLOSE # Wait on the INSTFILES page so the user can take a look into the details of the installation steps -!define MUI_ABORTWARNING # This will warn the user if they exit from the installer. - -!insertmacro MUI_PAGE_WELCOME # Welcome to the installer page. -# !insertmacro MUI_PAGE_LICENSE "resources\eula.txt" # Adds a EULA page to the installer -!insertmacro MUI_PAGE_DIRECTORY # In which folder install page. -!insertmacro MUI_PAGE_INSTFILES # Installing page. -!insertmacro MUI_PAGE_FINISH # Finished installation page. - -!insertmacro MUI_UNPAGE_INSTFILES # Uninstalling page - -!insertmacro MUI_LANGUAGE "English" # Set the Language of the installer - -## The following two statements can be used to sign the installer and the uninstaller. The path to the binaries are provided in %1 -#!uninstfinalize 'signtool --file "%1"' -#!finalize 'signtool --file "%1"' - -Name "${INFO_PRODUCTNAME}" -OutFile "..\..\bin\${INFO_PROJECTNAME}-${ARCH}-installer.exe" # Name of the installer's file. -InstallDir "$PROGRAMFILES64\${INFO_COMPANYNAME}\${INFO_PRODUCTNAME}" # Default installing folder ($PROGRAMFILES is Program Files folder). -ShowInstDetails show # This will always show the installation details. - -Function .onInit - !insertmacro wails.checkArchitecture -FunctionEnd - -Section - !insertmacro wails.setShellContext - - !insertmacro wails.webview2runtime - - SetOutPath $INSTDIR - - !insertmacro wails.files - - CreateShortcut "$SMPROGRAMS\${INFO_PRODUCTNAME}.lnk" "$INSTDIR\${PRODUCT_EXECUTABLE}" - CreateShortCut "$DESKTOP\${INFO_PRODUCTNAME}.lnk" "$INSTDIR\${PRODUCT_EXECUTABLE}" - - !insertmacro wails.associateFiles - - !insertmacro wails.writeUninstaller -SectionEnd - -Section "uninstall" - !insertmacro wails.setShellContext - - RMDir /r "$AppData\${PRODUCT_EXECUTABLE}" # Remove the WebView2 DataPath - - RMDir /r $INSTDIR - - Delete "$SMPROGRAMS\${INFO_PRODUCTNAME}.lnk" - Delete "$DESKTOP\${INFO_PRODUCTNAME}.lnk" - - !insertmacro wails.unassociateFiles - - !insertmacro wails.deleteUninstaller -SectionEnd diff --git a/v3/examples/file-association/build/nsis/wails_tools.nsh b/v3/examples/file-association/build/nsis/wails_tools.nsh deleted file mode 100644 index d49f6c803..000000000 --- a/v3/examples/file-association/build/nsis/wails_tools.nsh +++ /dev/null @@ -1,218 +0,0 @@ -# DO NOT EDIT - Generated automatically by `wails build` - -!include "x64.nsh" -!include "WinVer.nsh" -!include "FileFunc.nsh" - -!ifndef INFO_PROJECTNAME - !define INFO_PROJECTNAME "fileassoc" -!endif -!ifndef INFO_COMPANYNAME - !define INFO_COMPANYNAME "My Company" -!endif -!ifndef INFO_PRODUCTNAME - !define INFO_PRODUCTNAME "My Product" -!endif -!ifndef INFO_PRODUCTVERSION - !define INFO_PRODUCTVERSION "0.1.0" -!endif -!ifndef INFO_COPYRIGHT - !define INFO_COPYRIGHT "© now, My Company" -!endif -!ifndef PRODUCT_EXECUTABLE - !define PRODUCT_EXECUTABLE "${INFO_PROJECTNAME}.exe" -!endif -!ifndef UNINST_KEY_NAME - !define UNINST_KEY_NAME "${INFO_COMPANYNAME}${INFO_PRODUCTNAME}" -!endif -!define UNINST_KEY "Software\Microsoft\Windows\CurrentVersion\Uninstall\${UNINST_KEY_NAME}" - -!ifndef REQUEST_EXECUTION_LEVEL - !define REQUEST_EXECUTION_LEVEL "admin" -!endif - -RequestExecutionLevel "${REQUEST_EXECUTION_LEVEL}" - -!ifdef ARG_WAILS_AMD64_BINARY - !define SUPPORTS_AMD64 -!endif - -!ifdef ARG_WAILS_ARM64_BINARY - !define SUPPORTS_ARM64 -!endif - -!ifdef SUPPORTS_AMD64 - !ifdef SUPPORTS_ARM64 - !define ARCH "amd64_arm64" - !else - !define ARCH "amd64" - !endif -!else - !ifdef SUPPORTS_ARM64 - !define ARCH "arm64" - !else - !error "Wails: Undefined ARCH, please provide at least one of ARG_WAILS_AMD64_BINARY or ARG_WAILS_ARM64_BINARY" - !endif -!endif - -!macro wails.checkArchitecture - !ifndef WAILS_WIN10_REQUIRED - !define WAILS_WIN10_REQUIRED "This product is only supported on Windows 10 (Server 2016) and later." - !endif - - !ifndef WAILS_ARCHITECTURE_NOT_SUPPORTED - !define WAILS_ARCHITECTURE_NOT_SUPPORTED "This product can't be installed on the current Windows architecture. Supports: ${ARCH}" - !endif - - ${If} ${AtLeastWin10} - !ifdef SUPPORTS_AMD64 - ${if} ${IsNativeAMD64} - Goto ok - ${EndIf} - !endif - - !ifdef SUPPORTS_ARM64 - ${if} ${IsNativeARM64} - Goto ok - ${EndIf} - !endif - - IfSilent silentArch notSilentArch - silentArch: - SetErrorLevel 65 - Abort - notSilentArch: - MessageBox MB_OK "${WAILS_ARCHITECTURE_NOT_SUPPORTED}" - Quit - ${else} - IfSilent silentWin notSilentWin - silentWin: - SetErrorLevel 64 - Abort - notSilentWin: - MessageBox MB_OK "${WAILS_WIN10_REQUIRED}" - Quit - ${EndIf} - - ok: -!macroend - -!macro wails.files - !ifdef SUPPORTS_AMD64 - ${if} ${IsNativeAMD64} - File "/oname=${PRODUCT_EXECUTABLE}" "${ARG_WAILS_AMD64_BINARY}" - ${EndIf} - !endif - - !ifdef SUPPORTS_ARM64 - ${if} ${IsNativeARM64} - File "/oname=${PRODUCT_EXECUTABLE}" "${ARG_WAILS_ARM64_BINARY}" - ${EndIf} - !endif -!macroend - -!macro wails.writeUninstaller - WriteUninstaller "$INSTDIR\uninstall.exe" - - SetRegView 64 - WriteRegStr HKLM "${UNINST_KEY}" "Publisher" "${INFO_COMPANYNAME}" - WriteRegStr HKLM "${UNINST_KEY}" "DisplayName" "${INFO_PRODUCTNAME}" - WriteRegStr HKLM "${UNINST_KEY}" "DisplayVersion" "${INFO_PRODUCTVERSION}" - WriteRegStr HKLM "${UNINST_KEY}" "DisplayIcon" "$INSTDIR\${PRODUCT_EXECUTABLE}" - WriteRegStr HKLM "${UNINST_KEY}" "UninstallString" "$\"$INSTDIR\uninstall.exe$\"" - WriteRegStr HKLM "${UNINST_KEY}" "QuietUninstallString" "$\"$INSTDIR\uninstall.exe$\" /S" - - ${GetSize} "$INSTDIR" "/S=0K" $0 $1 $2 - IntFmt $0 "0x%08X" $0 - WriteRegDWORD HKLM "${UNINST_KEY}" "EstimatedSize" "$0" -!macroend - -!macro wails.deleteUninstaller - Delete "$INSTDIR\uninstall.exe" - - SetRegView 64 - DeleteRegKey HKLM "${UNINST_KEY}" -!macroend - -!macro wails.setShellContext - ${If} ${REQUEST_EXECUTION_LEVEL} == "admin" - SetShellVarContext all - ${else} - SetShellVarContext current - ${EndIf} -!macroend - -# Install webview2 by launching the bootstrapper -# See https://docs.microsoft.com/en-us/microsoft-edge/webview2/concepts/distribution#online-only-deployment -!macro wails.webview2runtime - !ifndef WAILS_INSTALL_WEBVIEW_DETAILPRINT - !define WAILS_INSTALL_WEBVIEW_DETAILPRINT "Installing: WebView2 Runtime" - !endif - - SetRegView 64 - # If the admin key exists and is not empty then webview2 is already installed - ReadRegStr $0 HKLM "SOFTWARE\WOW6432Node\Microsoft\EdgeUpdate\Clients\{F3017226-FE2A-4295-8BDF-00C3A9A7E4C5}" "pv" - ${If} $0 != "" - Goto ok - ${EndIf} - - ${If} ${REQUEST_EXECUTION_LEVEL} == "user" - # If the installer is run in user level, check the user specific key exists and is not empty then webview2 is already installed - ReadRegStr $0 HKCU "Software\Microsoft\EdgeUpdate\Clients{F3017226-FE2A-4295-8BDF-00C3A9A7E4C5}" "pv" - ${If} $0 != "" - Goto ok - ${EndIf} - ${EndIf} - - SetDetailsPrint both - DetailPrint "${WAILS_INSTALL_WEBVIEW_DETAILPRINT}" - SetDetailsPrint listonly - - InitPluginsDir - CreateDirectory "$pluginsdir\webview2bootstrapper" - SetOutPath "$pluginsdir\webview2bootstrapper" - File "MicrosoftEdgeWebview2Setup.exe" - ExecWait '"$pluginsdir\webview2bootstrapper\MicrosoftEdgeWebview2Setup.exe" /silent /install' - - SetDetailsPrint both - ok: -!macroend - -# Copy of APP_ASSOCIATE and APP_UNASSOCIATE macros from here https://gist.github.com/nikku/281d0ef126dbc215dd58bfd5b3a5cd5b -!macro APP_ASSOCIATE EXT FILECLASS DESCRIPTION ICON COMMANDTEXT COMMAND - ; Backup the previously associated file class - ReadRegStr $R0 SHELL_CONTEXT "Software\Classes\.${EXT}" "" - WriteRegStr SHELL_CONTEXT "Software\Classes\.${EXT}" "${FILECLASS}_backup" "$R0" - - WriteRegStr SHELL_CONTEXT "Software\Classes\.${EXT}" "" "${FILECLASS}" - - WriteRegStr SHELL_CONTEXT "Software\Classes\${FILECLASS}" "" `${DESCRIPTION}` - WriteRegStr SHELL_CONTEXT "Software\Classes\${FILECLASS}\DefaultIcon" "" `${ICON}` - WriteRegStr SHELL_CONTEXT "Software\Classes\${FILECLASS}\shell" "" "open" - WriteRegStr SHELL_CONTEXT "Software\Classes\${FILECLASS}\shell\open" "" `${COMMANDTEXT}` - WriteRegStr SHELL_CONTEXT "Software\Classes\${FILECLASS}\shell\open\command" "" `${COMMAND}` -!macroend - -!macro APP_UNASSOCIATE EXT FILECLASS - ; Backup the previously associated file class - ReadRegStr $R0 SHELL_CONTEXT "Software\Classes\.${EXT}" `${FILECLASS}_backup` - WriteRegStr SHELL_CONTEXT "Software\Classes\.${EXT}" "" "$R0" - - DeleteRegKey SHELL_CONTEXT `Software\Classes\${FILECLASS}` -!macroend - -!macro wails.associateFiles - ; Create file associations - - !insertmacro APP_ASSOCIATE "wails" "Wails" "Wails Application File" "$INSTDIR\icon.ico" "Open with ${INFO_PRODUCTNAME}" "$INSTDIR\${PRODUCT_EXECUTABLE} $\"%1$\"" - File "..\icon.ico" - -!macroend - -!macro wails.unassociateFiles - ; Delete app associations - - !insertmacro APP_UNASSOCIATE "wails" "Wails" - Delete "$INSTDIR\icon.ico" - -!macroend \ No newline at end of file diff --git a/v3/examples/file-association/build/wails.exe.manifest b/v3/examples/file-association/build/wails.exe.manifest deleted file mode 100644 index 03a121e40..000000000 --- a/v3/examples/file-association/build/wails.exe.manifest +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - true/pm - permonitorv2,permonitor - - - \ No newline at end of file diff --git a/v3/examples/file-association/frontend/bindings/changeme/greetservice.js b/v3/examples/file-association/frontend/bindings/changeme/greetservice.js deleted file mode 100644 index 860020abd..000000000 --- a/v3/examples/file-association/frontend/bindings/changeme/greetservice.js +++ /dev/null @@ -1,16 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import {Call as $Call, Create as $Create} from "@wailsio/runtime"; - -/** - * @param {string} name - * @returns {Promise & { cancel(): void }} - */ -export function Greet(name) { - let $resultPromise = /** @type {any} */($Call.ByID(1411160069, name)); - return $resultPromise; -} diff --git a/v3/examples/file-association/frontend/bindings/changeme/index.js b/v3/examples/file-association/frontend/bindings/changeme/index.js deleted file mode 100644 index fdf1ff435..000000000 --- a/v3/examples/file-association/frontend/bindings/changeme/index.js +++ /dev/null @@ -1,8 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; diff --git a/v3/examples/file-association/frontend/index.html b/v3/examples/file-association/frontend/index.html deleted file mode 100644 index b81d9729f..000000000 --- a/v3/examples/file-association/frontend/index.html +++ /dev/null @@ -1,35 +0,0 @@ - - - - - - - - Wails App - - -
            - -

            Wails + Javascript

            -
            -
            Please enter your name below 👇
            -
            - - -
            -
            - -
            - - - diff --git a/v3/examples/file-association/frontend/main.js b/v3/examples/file-association/frontend/main.js deleted file mode 100644 index c24b3b1ef..000000000 --- a/v3/examples/file-association/frontend/main.js +++ /dev/null @@ -1,21 +0,0 @@ -import {GreetService} from "./bindings/changeme"; -import {Events} from "@wailsio/runtime"; - -const resultElement = document.getElementById('result'); -const timeElement = document.getElementById('time'); - -window.doGreet = () => { - let name = document.getElementById('name').value; - if (!name) { - name = 'anonymous'; - } - GreetService.Greet(name).then((result) => { - resultElement.innerText = result; - }).catch((err) => { - console.log(err); - }); -} - -Events.On('time', (time) => { - timeElement.innerText = time.data; -}); diff --git a/v3/examples/file-association/frontend/package-lock.json b/v3/examples/file-association/frontend/package-lock.json deleted file mode 100644 index 9ba47fffa..000000000 --- a/v3/examples/file-association/frontend/package-lock.json +++ /dev/null @@ -1,860 +0,0 @@ -{ - "name": "frontend", - "version": "0.0.0", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "frontend", - "version": "0.0.0", - "devDependencies": { - "@wailsio/runtime": "latest", - "vite": "^5.0.0" - } - }, - "node_modules/@esbuild/aix-ppc64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", - "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==", - "cpu": [ - "ppc64" - ], - "dev": true, - "optional": true, - "os": [ - "aix" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/android-arm": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz", - "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/android-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz", - "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/android-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz", - "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/darwin-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz", - "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/darwin-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz", - "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/freebsd-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz", - "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/freebsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz", - "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-arm": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz", - "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz", - "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-ia32": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz", - "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-loong64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz", - "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==", - "cpu": [ - "loong64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-mips64el": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz", - "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==", - "cpu": [ - "mips64el" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-ppc64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz", - "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==", - "cpu": [ - "ppc64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-riscv64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz", - "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==", - "cpu": [ - "riscv64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-s390x": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz", - "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==", - "cpu": [ - "s390x" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz", - "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/netbsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz", - "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/openbsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz", - "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/sunos-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz", - "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/win32-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz", - "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/win32-ia32": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz", - "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/win32-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz", - "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.24.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.24.3.tgz", - "integrity": "sha512-ufb2CH2KfBWPJok95frEZZ82LtDl0A6QKTa8MoM+cWwDZvVGl5/jNb79pIhRvAalUu+7LD91VYR0nwRD799HkQ==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/@rollup/rollup-android-arm64": { - "version": "4.24.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.24.3.tgz", - "integrity": "sha512-iAHpft/eQk9vkWIV5t22V77d90CRofgR2006UiCjHcHJFVI1E0oBkQIAbz+pLtthFw3hWEmVB4ilxGyBf48i2Q==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.24.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.24.3.tgz", - "integrity": "sha512-QPW2YmkWLlvqmOa2OwrfqLJqkHm7kJCIMq9kOz40Zo9Ipi40kf9ONG5Sz76zszrmIZZ4hgRIkez69YnTHgEz1w==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.24.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.24.3.tgz", - "integrity": "sha512-KO0pN5x3+uZm1ZXeIfDqwcvnQ9UEGN8JX5ufhmgH5Lz4ujjZMAnxQygZAVGemFWn+ZZC0FQopruV4lqmGMshow==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.24.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.24.3.tgz", - "integrity": "sha512-CsC+ZdIiZCZbBI+aRlWpYJMSWvVssPuWqrDy/zi9YfnatKKSLFCe6fjna1grHuo/nVaHG+kiglpRhyBQYRTK4A==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ] - }, - "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.24.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.24.3.tgz", - "integrity": "sha512-F0nqiLThcfKvRQhZEzMIXOQG4EeX61im61VYL1jo4eBxv4aZRmpin6crnBJQ/nWnCsjH5F6J3W6Stdm0mBNqBg==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "freebsd" - ] - }, - "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.24.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.24.3.tgz", - "integrity": "sha512-KRSFHyE/RdxQ1CSeOIBVIAxStFC/hnBgVcaiCkQaVC+EYDtTe4X7z5tBkFyRoBgUGtB6Xg6t9t2kulnX6wJc6A==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.24.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.24.3.tgz", - "integrity": "sha512-h6Q8MT+e05zP5BxEKz0vi0DhthLdrNEnspdLzkoFqGwnmOzakEHSlXfVyA4HJ322QtFy7biUAVFPvIDEDQa6rw==", - "cpu": [ - "arm" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.24.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.24.3.tgz", - "integrity": "sha512-fKElSyXhXIJ9pqiYRqisfirIo2Z5pTTve5K438URf08fsypXrEkVmShkSfM8GJ1aUyvjakT+fn2W7Czlpd/0FQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.24.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.24.3.tgz", - "integrity": "sha512-YlddZSUk8G0px9/+V9PVilVDC6ydMz7WquxozToozSnfFK6wa6ne1ATUjUvjin09jp34p84milxlY5ikueoenw==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { - "version": "4.24.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.24.3.tgz", - "integrity": "sha512-yNaWw+GAO8JjVx3s3cMeG5Esz1cKVzz8PkTJSfYzE5u7A+NvGmbVFEHP+BikTIyYWuz0+DX9kaA3pH9Sqxp69g==", - "cpu": [ - "ppc64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.24.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.24.3.tgz", - "integrity": "sha512-lWKNQfsbpv14ZCtM/HkjCTm4oWTKTfxPmr7iPfp3AHSqyoTz5AgLemYkWLwOBWc+XxBbrU9SCokZP0WlBZM9lA==", - "cpu": [ - "riscv64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.24.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.24.3.tgz", - "integrity": "sha512-HoojGXTC2CgCcq0Woc/dn12wQUlkNyfH0I1ABK4Ni9YXyFQa86Fkt2Q0nqgLfbhkyfQ6003i3qQk9pLh/SpAYw==", - "cpu": [ - "s390x" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.24.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.24.3.tgz", - "integrity": "sha512-mnEOh4iE4USSccBOtcrjF5nj+5/zm6NcNhbSEfR3Ot0pxBwvEn5QVUXcuOwwPkapDtGZ6pT02xLoPaNv06w7KQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.24.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.24.3.tgz", - "integrity": "sha512-rMTzawBPimBQkG9NKpNHvquIUTQPzrnPxPbCY1Xt+mFkW7pshvyIS5kYgcf74goxXOQk0CP3EoOC1zcEezKXhw==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.24.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.24.3.tgz", - "integrity": "sha512-2lg1CE305xNvnH3SyiKwPVsTVLCg4TmNCF1z7PSHX2uZY2VbUpdkgAllVoISD7JO7zu+YynpWNSKAtOrX3AiuA==", - "cpu": [ - "arm64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.24.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.24.3.tgz", - "integrity": "sha512-9SjYp1sPyxJsPWuhOCX6F4jUMXGbVVd5obVpoVEi8ClZqo52ViZewA6eFz85y8ezuOA+uJMP5A5zo6Oz4S5rVQ==", - "cpu": [ - "ia32" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.24.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.24.3.tgz", - "integrity": "sha512-HGZgRFFYrMrP3TJlq58nR1xy8zHKId25vhmm5S9jETEfDf6xybPxsavFTJaufe2zgOGYJBskGlj49CwtEuFhWQ==", - "cpu": [ - "x64" - ], - "dev": true, - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@types/estree": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", - "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", - "dev": true - }, - "node_modules/@wailsio/runtime": { - "version": "3.0.0-alpha.28", - "resolved": "https://registry.npmjs.org/@wailsio/runtime/-/runtime-3.0.0-alpha.28.tgz", - "integrity": "sha512-caMnAcKxxDrIWYgCZAMY2kdL++X4ehO2+JvH5na21xfDqz3VnHkEjxsH3jfhgd34M8LY80QEH8iqoMYytDFE/g==", - "dev": true, - "dependencies": { - "nanoid": "^5.0.7" - } - }, - "node_modules/esbuild": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", - "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", - "dev": true, - "hasInstallScript": true, - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=12" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.21.5", - "@esbuild/android-arm": "0.21.5", - "@esbuild/android-arm64": "0.21.5", - "@esbuild/android-x64": "0.21.5", - "@esbuild/darwin-arm64": "0.21.5", - "@esbuild/darwin-x64": "0.21.5", - "@esbuild/freebsd-arm64": "0.21.5", - "@esbuild/freebsd-x64": "0.21.5", - "@esbuild/linux-arm": "0.21.5", - "@esbuild/linux-arm64": "0.21.5", - "@esbuild/linux-ia32": "0.21.5", - "@esbuild/linux-loong64": "0.21.5", - "@esbuild/linux-mips64el": "0.21.5", - "@esbuild/linux-ppc64": "0.21.5", - "@esbuild/linux-riscv64": "0.21.5", - "@esbuild/linux-s390x": "0.21.5", - "@esbuild/linux-x64": "0.21.5", - "@esbuild/netbsd-x64": "0.21.5", - "@esbuild/openbsd-x64": "0.21.5", - "@esbuild/sunos-x64": "0.21.5", - "@esbuild/win32-arm64": "0.21.5", - "@esbuild/win32-ia32": "0.21.5", - "@esbuild/win32-x64": "0.21.5" - } - }, - "node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "dev": true, - "hasInstallScript": true, - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/nanoid": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-5.0.8.tgz", - "integrity": "sha512-TcJPw+9RV9dibz1hHUzlLVy8N4X9TnwirAjrU08Juo6BNKggzVfP2ZJ/3ZUSq15Xl5i85i+Z89XBO90pB2PghQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "bin": { - "nanoid": "bin/nanoid.js" - }, - "engines": { - "node": "^18 || >=20" - } - }, - "node_modules/picocolors": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", - "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", - "dev": true - }, - "node_modules/postcss": { - "version": "8.4.47", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.47.tgz", - "integrity": "sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "dependencies": { - "nanoid": "^3.3.7", - "picocolors": "^1.1.0", - "source-map-js": "^1.2.1" - }, - "engines": { - "node": "^10 || ^12 || >=14" - } - }, - "node_modules/postcss/node_modules/nanoid": { - "version": "3.3.7", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", - "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "bin": { - "nanoid": "bin/nanoid.cjs" - }, - "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" - } - }, - "node_modules/rollup": { - "version": "4.24.3", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.24.3.tgz", - "integrity": "sha512-HBW896xR5HGmoksbi3JBDtmVzWiPAYqp7wip50hjQ67JbDz61nyoMPdqu1DvVW9asYb2M65Z20ZHsyJCMqMyDg==", - "dev": true, - "dependencies": { - "@types/estree": "1.0.6" - }, - "bin": { - "rollup": "dist/bin/rollup" - }, - "engines": { - "node": ">=18.0.0", - "npm": ">=8.0.0" - }, - "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.24.3", - "@rollup/rollup-android-arm64": "4.24.3", - "@rollup/rollup-darwin-arm64": "4.24.3", - "@rollup/rollup-darwin-x64": "4.24.3", - "@rollup/rollup-freebsd-arm64": "4.24.3", - "@rollup/rollup-freebsd-x64": "4.24.3", - "@rollup/rollup-linux-arm-gnueabihf": "4.24.3", - "@rollup/rollup-linux-arm-musleabihf": "4.24.3", - "@rollup/rollup-linux-arm64-gnu": "4.24.3", - "@rollup/rollup-linux-arm64-musl": "4.24.3", - "@rollup/rollup-linux-powerpc64le-gnu": "4.24.3", - "@rollup/rollup-linux-riscv64-gnu": "4.24.3", - "@rollup/rollup-linux-s390x-gnu": "4.24.3", - "@rollup/rollup-linux-x64-gnu": "4.24.3", - "@rollup/rollup-linux-x64-musl": "4.24.3", - "@rollup/rollup-win32-arm64-msvc": "4.24.3", - "@rollup/rollup-win32-ia32-msvc": "4.24.3", - "@rollup/rollup-win32-x64-msvc": "4.24.3", - "fsevents": "~2.3.2" - } - }, - "node_modules/source-map-js": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", - "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", - "dev": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/vite": { - "version": "5.4.10", - "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.10.tgz", - "integrity": "sha512-1hvaPshuPUtxeQ0hsVH3Mud0ZanOLwVTneA1EgbAM5LhaZEqyPWGRQ7BtaMvUrTDeEaC8pxtj6a6jku3x4z6SQ==", - "dev": true, - "dependencies": { - "esbuild": "^0.21.3", - "postcss": "^8.4.43", - "rollup": "^4.20.0" - }, - "bin": { - "vite": "bin/vite.js" - }, - "engines": { - "node": "^18.0.0 || >=20.0.0" - }, - "funding": { - "url": "https://github.com/vitejs/vite?sponsor=1" - }, - "optionalDependencies": { - "fsevents": "~2.3.3" - }, - "peerDependencies": { - "@types/node": "^18.0.0 || >=20.0.0", - "less": "*", - "lightningcss": "^1.21.0", - "sass": "*", - "sass-embedded": "*", - "stylus": "*", - "sugarss": "*", - "terser": "^5.4.0" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - }, - "less": { - "optional": true - }, - "lightningcss": { - "optional": true - }, - "sass": { - "optional": true - }, - "sass-embedded": { - "optional": true - }, - "stylus": { - "optional": true - }, - "sugarss": { - "optional": true - }, - "terser": { - "optional": true - } - } - } - } -} diff --git a/v3/examples/file-association/frontend/package.json b/v3/examples/file-association/frontend/package.json deleted file mode 100644 index 2642d7a41..000000000 --- a/v3/examples/file-association/frontend/package.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "name": "frontend", - "private": true, - "version": "0.0.0", - "type": "module", - "scripts": { - "dev": "vite", - "build": "vite build --minify false --mode development", - "build:prod": "vite build --mode production", - "preview": "vite preview" - }, - "devDependencies": { - "vite": "^5.0.0", - "@wailsio/runtime": "latest" - } -} \ No newline at end of file diff --git a/v3/examples/file-association/frontend/public/Inter-Medium.ttf b/v3/examples/file-association/frontend/public/Inter-Medium.ttf deleted file mode 100644 index a01f3777a..000000000 Binary files a/v3/examples/file-association/frontend/public/Inter-Medium.ttf and /dev/null differ diff --git a/v3/examples/file-association/frontend/public/javascript.svg b/v3/examples/file-association/frontend/public/javascript.svg deleted file mode 100644 index f9abb2b72..000000000 --- a/v3/examples/file-association/frontend/public/javascript.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/v3/examples/file-association/frontend/public/style.css b/v3/examples/file-association/frontend/public/style.css deleted file mode 100644 index 259397254..000000000 --- a/v3/examples/file-association/frontend/public/style.css +++ /dev/null @@ -1,160 +0,0 @@ -:root { - font-family: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", - "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", - sans-serif; - font-size: 16px; - line-height: 24px; - font-weight: 400; - color-scheme: light dark; - color: rgba(255, 255, 255, 0.87); - background-color: rgba(27, 38, 54, 1); - font-synthesis: none; - text-rendering: optimizeLegibility; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - -webkit-text-size-adjust: 100%; -} - -* { - user-select: none; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; -} - -@font-face { - font-family: "Inter"; - font-style: normal; - font-weight: 400; - src: local(""), - url("./Inter-Medium.ttf") format("truetype"); -} - -h3 { - font-size: 3em; - line-height: 1.1; -} - -a { - font-weight: 500; - color: #646cff; - text-decoration: inherit; -} - -a:hover { - color: #535bf2; -} - -button { - width: 60px; - height: 30px; - line-height: 30px; - border-radius: 3px; - border: none; - margin: 0 0 0 20px; - padding: 0 8px; - cursor: pointer; -} - -.result { - height: 20px; - line-height: 20px; -} - -body { - margin: 0; - display: flex; - place-items: center; - place-content: center; - min-width: 320px; - min-height: 100vh; -} - -.container { - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; -} - -h1 { - font-size: 3.2em; - line-height: 1.1; -} - -#app { - max-width: 1280px; - margin: 0 auto; - padding: 2rem; - text-align: center; -} - -.logo { - height: 6em; - padding: 1.5em; - will-change: filter; -} - -.logo:hover { - filter: drop-shadow(0 0 2em #e80000aa); -} - -.logo.vanilla:hover { - filter: drop-shadow(0 0 2em #f7df1eaa); -} - -.result { - height: 20px; - line-height: 20px; - margin: 1.5rem auto; - text-align: center; -} - -.footer { - margin-top: 1rem; - align-content: center; - text-align: center; -} - -@media (prefers-color-scheme: light) { - :root { - color: #213547; - background-color: #ffffff; - } - - a:hover { - color: #747bff; - } - - button { - background-color: #f9f9f9; - } -} - - -.input-box .btn:hover { - background-image: linear-gradient(to top, #cfd9df 0%, #e2ebf0 100%); - color: #333333; -} - -.input-box .input { - border: none; - border-radius: 3px; - outline: none; - height: 30px; - line-height: 30px; - padding: 0 10px; - color: black; - background-color: rgba(240, 240, 240, 1); - -webkit-font-smoothing: antialiased; -} - -.input-box .input:hover { - border: none; - background-color: rgba(255, 255, 255, 1); -} - -.input-box .input:focus { - border: none; - background-color: rgba(255, 255, 255, 1); -} \ No newline at end of file diff --git a/v3/examples/file-association/frontend/public/wails.png b/v3/examples/file-association/frontend/public/wails.png deleted file mode 100644 index 8bdf42483..000000000 Binary files a/v3/examples/file-association/frontend/public/wails.png and /dev/null differ diff --git a/v3/examples/file-association/go.mod b/v3/examples/file-association/go.mod deleted file mode 100644 index 296394de3..000000000 --- a/v3/examples/file-association/go.mod +++ /dev/null @@ -1,49 +0,0 @@ -module changeme - -go 1.25 - -require github.com/wailsapp/wails/v3 v3.0.0-alpha.62 - -require ( - dario.cat/mergo v1.0.2 // indirect - github.com/Microsoft/go-winio v0.6.2 // indirect - github.com/ProtonMail/go-crypto v1.3.0 // indirect - github.com/adrg/xdg v0.5.3 // indirect - github.com/bep/debounce v1.2.1 // indirect - github.com/cloudflare/circl v1.6.3 // indirect - github.com/coder/websocket v1.8.14 // indirect - github.com/cyphar/filepath-securejoin v0.6.1 // indirect - github.com/ebitengine/purego v0.9.1 // indirect - github.com/emirpasic/gods v1.18.1 // indirect - github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect - github.com/go-git/go-billy/v5 v5.7.0 // indirect - github.com/go-git/go-git/v5 v5.16.4 // indirect - github.com/go-ole/go-ole v1.3.0 // indirect - github.com/godbus/dbus/v5 v5.2.2 // indirect - github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect - github.com/google/uuid v1.6.0 // indirect - github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect - github.com/jchv/go-winloader v0.0.0-20250406163304-c1995be93bd1 // indirect - github.com/kevinburke/ssh_config v1.4.0 // indirect - github.com/klauspost/cpuid/v2 v2.3.0 // indirect - github.com/leaanthony/go-ansi-parser v1.6.1 // indirect - github.com/leaanthony/u v1.1.1 // indirect - github.com/lmittmann/tint v1.1.2 // indirect - github.com/mattn/go-colorable v0.1.14 // indirect - github.com/mattn/go-isatty v0.0.20 // indirect - github.com/pjbgf/sha1cd v0.5.0 // indirect - github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c // indirect - github.com/rivo/uniseg v0.4.7 // indirect - github.com/samber/lo v1.52.0 // indirect - github.com/sergi/go-diff v1.4.0 // indirect - github.com/skeema/knownhosts v1.3.2 // indirect - github.com/wailsapp/go-webview2 v1.0.23 // indirect - github.com/xanzy/ssh-agent v0.3.3 // indirect - golang.org/x/crypto v0.47.0 // indirect - golang.org/x/net v0.49.0 // indirect - golang.org/x/sys v0.40.0 // indirect - golang.org/x/text v0.33.0 // indirect - gopkg.in/warnings.v0 v0.1.2 // indirect -) - -replace github.com/wailsapp/wails/v3 => ../.. diff --git a/v3/examples/file-association/go.sum b/v3/examples/file-association/go.sum deleted file mode 100644 index 56f1153ea..000000000 --- a/v3/examples/file-association/go.sum +++ /dev/null @@ -1,147 +0,0 @@ -dario.cat/mergo v1.0.2 h1:85+piFYR1tMbRrLcDwR18y4UKJ3aH1Tbzi24VRW1TK8= -dario.cat/mergo v1.0.2/go.mod h1:E/hbnu0NxMFBjpMIE34DRGLWqDy0g5FuKDhCb31ngxA= -github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY= -github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= -github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= -github.com/ProtonMail/go-crypto v1.3.0 h1:ILq8+Sf5If5DCpHQp4PbZdS1J7HDFRXz/+xKBiRGFrw= -github.com/ProtonMail/go-crypto v1.3.0/go.mod h1:9whxjD8Rbs29b4XWbB8irEcE8KHMqaR2e7GWU1R+/PE= -github.com/adrg/xdg v0.5.3 h1:xRnxJXne7+oWDatRhR1JLnvuccuIeCoBu2rtuLqQB78= -github.com/adrg/xdg v0.5.3/go.mod h1:nlTsY+NNiCBGCK2tpm09vRqfVzrc2fLmXGpBLF0zlTQ= -github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8= -github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4= -github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= -github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= -github.com/bep/debounce v1.2.1 h1:v67fRdBA9UQu2NhLFXrSg0Brw7CexQekrBwDMM8bzeY= -github.com/bep/debounce v1.2.1/go.mod h1:H8yggRPQKLUhUoqrJC1bO2xNya7vanpDl7xR3ISbCJ0= -github.com/cloudflare/circl v1.6.3 h1:9GPOhQGF9MCYUeXyMYlqTR6a5gTrgR/fBLXvUgtVcg8= -github.com/cloudflare/circl v1.6.3/go.mod h1:2eXP6Qfat4O/Yhh8BznvKnJ+uzEoTQ6jVKJRn81BiS4= -github.com/coder/websocket v1.8.14 h1:9L0p0iKiNOibykf283eHkKUHHrpG7f65OE3BhhO7v9g= -github.com/coder/websocket v1.8.14/go.mod h1:NX3SzP+inril6yawo5CQXx8+fk145lPDC6pumgx0mVg= -github.com/cyphar/filepath-securejoin v0.6.1 h1:5CeZ1jPXEiYt3+Z6zqprSAgSWiggmpVyciv8syjIpVE= -github.com/cyphar/filepath-securejoin v0.6.1/go.mod h1:A8hd4EnAeyujCJRrICiOWqjS1AX0a9kM5XL+NwKoYSc= -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= -github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/ebitengine/purego v0.9.1 h1:a/k2f2HQU3Pi399RPW1MOaZyhKJL9w/xFpKAg4q1s0A= -github.com/ebitengine/purego v0.9.1/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ= -github.com/elazarl/goproxy v1.7.2 h1:Y2o6urb7Eule09PjlhQRGNsqRfPmYI3KKQLFpCAV3+o= -github.com/elazarl/goproxy v1.7.2/go.mod h1:82vkLNir0ALaW14Rc399OTTjyNREgmdL2cVoIbS6XaE= -github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc= -github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ= -github.com/gliderlabs/ssh v0.3.8 h1:a4YXD1V7xMF9g5nTkdfnja3Sxy1PVDCj1Zg4Wb8vY6c= -github.com/gliderlabs/ssh v0.3.8/go.mod h1:xYoytBv1sV0aL3CavoDuJIQNURXkkfPA/wxQ1pL1fAU= -github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI= -github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmSxCcxctByoQdvwPiA7DTK7jaaFDBTtu0ic= -github.com/go-git/go-billy/v5 v5.7.0 h1:83lBUJhGWhYp0ngzCMSgllhUSuoHP1iEWYjsPl9nwqM= -github.com/go-git/go-billy/v5 v5.7.0/go.mod h1:/1IUejTKH8xipsAcdfcSAlUlo2J7lkYV8GTKxAT/L3E= -github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399 h1:eMje31YglSBqCdIqdhKBW8lokaMrL3uTkpGYlE2OOT4= -github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399/go.mod h1:1OCfN199q1Jm3HZlxleg+Dw/mwps2Wbk9frAWm+4FII= -github.com/go-git/go-git/v5 v5.16.4 h1:7ajIEZHZJULcyJebDLo99bGgS0jRrOxzZG4uCk2Yb2Y= -github.com/go-git/go-git/v5 v5.16.4/go.mod h1:4Ge4alE/5gPs30F2H1esi2gPd69R0C39lolkucHBOp8= -github.com/go-json-experiment/json v0.0.0-20251027170946-4849db3c2f7e h1:Lf/gRkoycfOBPa42vU2bbgPurFong6zXeFtPoxholzU= -github.com/go-json-experiment/json v0.0.0-20251027170946-4849db3c2f7e/go.mod h1:uNVvRXArCGbZ508SxYYTC5v1JWoz2voff5pm25jU1Ok= -github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE= -github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78= -github.com/godbus/dbus/v5 v5.2.2 h1:TUR3TgtSVDmjiXOgAAyaZbYmIeP3DPkld3jgKGV8mXQ= -github.com/godbus/dbus/v5 v5.2.2/go.mod h1:3AAv2+hPq5rdnr5txxxRwiGjPXamgoIHgz9FPBfOp3c= -github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 h1:f+oWsMOmNPc8JmEHVZIycC7hBoQxHH9pNKQORJNozsQ= -github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8/go.mod h1:wcDNUvekVysuuOpQKo3191zZyTpiI6se1N1ULghS0sw= -github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= -github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= -github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= -github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A= -github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= -github.com/jchv/go-winloader v0.0.0-20250406163304-c1995be93bd1 h1:njuLRcjAuMKr7kI3D85AXWkw6/+v9PwtV6M6o11sWHQ= -github.com/jchv/go-winloader v0.0.0-20250406163304-c1995be93bd1/go.mod h1:alcuEEnZsY1WQsagKhZDsoPCRoOijYqhZvPwLG0kzVs= -github.com/kevinburke/ssh_config v1.4.0 h1:6xxtP5bZ2E4NF5tuQulISpTO2z8XbtH8cg1PWkxoFkQ= -github.com/kevinburke/ssh_config v1.4.0/go.mod h1:q2RIzfka+BXARoNexmF9gkxEX7DmvbW9P4hIVx2Kg4M= -github.com/klauspost/cpuid/v2 v2.3.0 h1:S4CRMLnYUhGeDFDqkGriYKdfoFlDnMtqTiI/sFzhA9Y= -github.com/klauspost/cpuid/v2 v2.3.0/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0= -github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= -github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= -github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= -github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= -github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/leaanthony/go-ansi-parser v1.6.1 h1:xd8bzARK3dErqkPFtoF9F3/HgN8UQk0ed1YDKpEz01A= -github.com/leaanthony/go-ansi-parser v1.6.1/go.mod h1:+vva/2y4alzVmmIEpk9QDhA7vLC5zKDTRwfZGOp3IWU= -github.com/leaanthony/u v1.1.1 h1:TUFjwDGlNX+WuwVEzDqQwC2lOv0P4uhTQw7CMFdiK7M= -github.com/leaanthony/u v1.1.1/go.mod h1:9+o6hejoRljvZ3BzdYlVL0JYCwtnAsVuN9pVTQcaRfI= -github.com/lmittmann/tint v1.1.2 h1:2CQzrL6rslrsyjqLDwD11bZ5OpLBPU+g3G/r5LSfS8w= -github.com/lmittmann/tint v1.1.2/go.mod h1:HIS3gSy7qNwGCj+5oRjAutErFBl4BzdQP6cJZ0NfMwE= -github.com/matryer/is v1.4.0/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwMRU= -github.com/matryer/is v1.4.1 h1:55ehd8zaGABKLXQUe2awZ99BD/PTc2ls+KV/dXphgEQ= -github.com/matryer/is v1.4.1/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwMRU= -github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE= -github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8= -github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= -github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= -github.com/onsi/gomega v1.34.1 h1:EUMJIKUjM8sKjYbtxQI9A4z2o+rruxnzNvpknOXie6k= -github.com/onsi/gomega v1.34.1/go.mod h1:kU1QgUvBDLXBJq618Xvm2LUX6rSAfRaFRTcdOeDLwwY= -github.com/pjbgf/sha1cd v0.5.0 h1:a+UkboSi1znleCDUNT3M5YxjOnN1fz2FhN48FlwCxs0= -github.com/pjbgf/sha1cd v0.5.0/go.mod h1:lhpGlyHLpQZoxMv8HcgXvZEhcGs0PG/vsZnEJ7H0iCM= -github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmdv1U2eRNDiU2ErMBj1gwrq8eQ= -github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c/go.mod h1:7rwL4CYBLnjLxUqIJNnCWiEdr3bn6IUYi15bNlnbCCU= -github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= -github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= -github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= -github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= -github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= -github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= -github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= -github.com/samber/lo v1.52.0 h1:Rvi+3BFHES3A8meP33VPAxiBZX/Aws5RxrschYGjomw= -github.com/samber/lo v1.52.0/go.mod h1:4+MXEGsJzbKGaUEQFKBq2xtfuznW9oz/WrgyzMzRoM0= -github.com/sergi/go-diff v1.4.0 h1:n/SP9D5ad1fORl+llWyN+D6qoUETXNZARKjyY2/KVCw= -github.com/sergi/go-diff v1.4.0/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4= -github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= -github.com/skeema/knownhosts v1.3.2 h1:EDL9mgf4NzwMXCTfaxSD/o/a5fxDw/xL9nkU28JjdBg= -github.com/skeema/knownhosts v1.3.2/go.mod h1:bEg3iQAuw+jyiw+484wwFJoKSLwcfd7fqRy+N0QTiow= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= -github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= -github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= -github.com/wailsapp/go-webview2 v1.0.23 h1:jmv8qhz1lHibCc79bMM/a/FqOnnzOGEisLav+a0b9P0= -github.com/wailsapp/go-webview2 v1.0.23/go.mod h1:qJmWAmAmaniuKGZPWwne+uor3AHMB5PFhqiK0Bbj8kc= -github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM= -github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw= -golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.47.0 h1:V6e3FRj+n4dbpw86FJ8Fv7XVOql7TEwpHapKoMJ/GO8= -golang.org/x/crypto v0.47.0/go.mod h1:ff3Y9VzzKbwSSEzWqJsJVBnWmRwRSHt/6Op5n9bQc4A= -golang.org/x/exp v0.0.0-20260112195511-716be5621a96 h1:Z/6YuSHTLOHfNFdb8zVZomZr7cqNgTJvA8+Qz75D8gU= -golang.org/x/exp v0.0.0-20260112195511-716be5621a96/go.mod h1:nzimsREAkjBCIEFtHiYkrJyT+2uy9YZJB7H1k68CXZU= -golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.49.0 h1:eeHFmOGUTtaaPSGNmjBKpbng9MulQsJURQUAfUwY++o= -golang.org/x/net v0.49.0/go.mod h1:/ysNB2EvaqvesRkuLAyjI1ycPZlQHM3q01F02UY/MV8= -golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200810151505-1b9f1253b3ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.40.0 h1:DBZZqJ2Rkml6QMQsZywtnjnnGvHza6BTfYFWY9kjEWQ= -golang.org/x/sys v0.40.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= -golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.39.0 h1:RclSuaJf32jOqZz74CkPA9qFuVTX7vhLlpfj/IGWlqY= -golang.org/x/term v0.39.0/go.mod h1:yxzUCTP/U+FzoxfdKmLaA0RV1WgE0VY7hXBwKtY/4ww= -golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.33.0 h1:B3njUFyqtHDUI5jMn1YIr5B0IE2U0qck04r6d4KPAxE= -golang.org/x/text v0.33.0/go.mod h1:LuMebE6+rBincTi9+xWTY8TztLzKHc/9C1uBCG27+q8= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= -gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME= -gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= -gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= -gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= -gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/v3/examples/file-association/greetservice.go b/v3/examples/file-association/greetservice.go deleted file mode 100644 index 8972c39cd..000000000 --- a/v3/examples/file-association/greetservice.go +++ /dev/null @@ -1,7 +0,0 @@ -package main - -type GreetService struct{} - -func (g *GreetService) Greet(name string) string { - return "Hello " + name + "!" -} diff --git a/v3/examples/file-association/main.go b/v3/examples/file-association/main.go deleted file mode 100644 index a81506b52..000000000 --- a/v3/examples/file-association/main.go +++ /dev/null @@ -1,97 +0,0 @@ -package main - -import ( - "embed" - _ "embed" - "github.com/wailsapp/wails/v3/pkg/events" - "log" - "time" - - "github.com/wailsapp/wails/v3/pkg/application" -) - -// Wails uses Go's `embed` package to embed the frontend files into the binary. -// Any files in the frontend/dist folder will be embedded into the binary and -// made available to the frontend. -// See https://pkg.go.dev/embed for more information. - -//go:embed frontend -var assets embed.FS - -// main function serves as the application's entry point. It initializes the application, creates a window, -// and starts a goroutine that emits a time-based event every second. It subsequently runs the application and -// logs any error that might occur. -func main() { - - // Create a new Wails application by providing the necessary options. - // Variables 'Name' and 'Description' are for application metadata. - // 'Assets' configures the asset server with the 'FS' variable pointing to the frontend files. - // 'Bind' is a list of Go struct instances. The frontend has access to the methods of these instances. - // 'Mac' options tailor the application when running an macOS. - app := application.New(application.Options{ - Name: "fileassoc", - Description: "A demo of using raw HTML & CSS", - Services: []application.Service{ - application.NewService(&GreetService{}), - }, - Assets: application.AssetOptions{ - Handler: application.AssetFileServerFS(assets), - }, - Mac: application.MacOptions{ - ApplicationShouldTerminateAfterLastWindowClosed: true, - }, - FileAssociations: []string{".wails"}, - }) - - // Create a new window with the necessary options. - // 'Title' is the title of the window. - // 'Mac' options tailor the window when running on macOS. - // 'BackgroundColour' is the background colour of the window. - // 'URL' is the URL that will be loaded into the webview. - window := app.Window.NewWithOptions(application.WebviewWindowOptions{ - Title: "Window 1", - Mac: application.MacWindow{ - InvisibleTitleBarHeight: 50, - Backdrop: application.MacBackdropTranslucent, - TitleBar: application.MacTitleBarHiddenInset, - }, - BackgroundColour: application.NewRGB(27, 38, 54), - URL: "/", - }) - - var filename string - app.Event.OnApplicationEvent(events.Common.ApplicationOpenedWithFile, func(event *application.ApplicationEvent) { - filename = event.Context().Filename() - }) - - window.OnWindowEvent(events.Common.WindowShow, func(event *application.WindowEvent) { - app.Dialog.Info(). - SetTitle("File Opened"). - SetMessage("Application opened with file: " + filename). - Show() - }) - - // Create a goroutine that emits an event containing the current time every second. - // The frontend can listen to this event and update the UI accordingly. - go func() { - ticker := time.NewTicker(time.Second) - defer ticker.Stop() - for { - select { - case <-ticker.C: - now := time.Now().Format(time.RFC1123) - app.Event.Emit("time", now) - case <-app.Context().Done(): - return - } - } - }() - - // Run the application. This blocks until the application has been exited. - err := app.Run() - - // If an error occurred while running the application, log it and exit. - if err != nil { - log.Fatal(err) - } -} diff --git a/v3/examples/file-association/test.wails b/v3/examples/file-association/test.wails deleted file mode 100644 index dde58d5e8..000000000 --- a/v3/examples/file-association/test.wails +++ /dev/null @@ -1 +0,0 @@ -Once the application is built and installed, double click on this file to open the application. \ No newline at end of file diff --git a/v3/examples/file-input/README.md b/v3/examples/file-input/README.md deleted file mode 100644 index 57309cf48..000000000 --- a/v3/examples/file-input/README.md +++ /dev/null @@ -1,24 +0,0 @@ -# File Input Example - -Tests HTML `` and Wails Dialog API functionality (#4862). - -## Test Cases - -**HTML File Input:** -1. **Single File** - Basic file selection -2. **Multiple Files** - Multi-select with `multiple` attribute -3. **Files or Directories** - Selection with `webkitdirectory` attribute - -**Wails Dialog API (via generated bindings):** -4. **Directory Only** - `CanChooseDirectories(true)` + `CanChooseFiles(false)` -5. **Filtered (.txt)** - Using `AddFilter()` for file type filtering - -## Run - -```bash -# Generate bindings (already included) -wails3 generate bindings -d assets/bindings - -# Run the app -go run . -``` diff --git a/v3/examples/file-input/assets/bindings/github.com/wailsapp/wails/v3/examples/file-input/fileservice.js b/v3/examples/file-input/assets/bindings/github.com/wailsapp/wails/v3/examples/file-input/fileservice.js deleted file mode 100644 index 6f5686c35..000000000 --- a/v3/examples/file-input/assets/bindings/github.com/wailsapp/wails/v3/examples/file-input/fileservice.js +++ /dev/null @@ -1,21 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "@wailsio/runtime"; - -/** - * @returns {$CancellablePromise} - */ -export function OpenDirectoryOnly() { - return $Call.ByID(1809289240); -} - -/** - * @returns {$CancellablePromise} - */ -export function OpenFilteredFile() { - return $Call.ByID(2331855742); -} diff --git a/v3/examples/file-input/assets/bindings/github.com/wailsapp/wails/v3/examples/file-input/index.js b/v3/examples/file-input/assets/bindings/github.com/wailsapp/wails/v3/examples/file-input/index.js deleted file mode 100644 index da3b98f1b..000000000 --- a/v3/examples/file-input/assets/bindings/github.com/wailsapp/wails/v3/examples/file-input/index.js +++ /dev/null @@ -1,8 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as FileService from "./fileservice.js"; -export { - FileService -}; diff --git a/v3/examples/file-input/assets/bindings/github.com/wailsapp/wails/v3/internal/eventcreate.js b/v3/examples/file-input/assets/bindings/github.com/wailsapp/wails/v3/internal/eventcreate.js deleted file mode 100644 index 1ea105857..000000000 --- a/v3/examples/file-input/assets/bindings/github.com/wailsapp/wails/v3/internal/eventcreate.js +++ /dev/null @@ -1,9 +0,0 @@ -//@ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Create as $Create } from "@wailsio/runtime"; - -Object.freeze($Create.Events); diff --git a/v3/examples/file-input/assets/bindings/github.com/wailsapp/wails/v3/internal/eventdata.d.ts b/v3/examples/file-input/assets/bindings/github.com/wailsapp/wails/v3/internal/eventdata.d.ts deleted file mode 100644 index 3dd1807bd..000000000 --- a/v3/examples/file-input/assets/bindings/github.com/wailsapp/wails/v3/internal/eventdata.d.ts +++ /dev/null @@ -1,2 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT diff --git a/v3/examples/file-input/assets/index.html b/v3/examples/file-input/assets/index.html deleted file mode 100644 index 8e2b298db..000000000 --- a/v3/examples/file-input/assets/index.html +++ /dev/null @@ -1,101 +0,0 @@ - - - - File Input Test - - - - -

            File Input Test (#4862)

            -
            -
            -

            1. Single File

            - -
            -
            -

            2. Multiple Files

            - -
            -
            -

            3. Files or Directories

            - -
            -
            -

            4. Directory Only (Wails API)

            - -
            -
            -

            5. Filtered .txt (Wails API)

            - -
            -
            -
            Click a file input or button to test...
            - - - diff --git a/v3/examples/file-input/main.go b/v3/examples/file-input/main.go deleted file mode 100644 index 6342f3b38..000000000 --- a/v3/examples/file-input/main.go +++ /dev/null @@ -1,69 +0,0 @@ -package main - -import ( - "embed" - "log" - - "github.com/wailsapp/wails/v3/pkg/application" -) - -//go:embed assets/* -var assets embed.FS - -type FileService struct{} - -func (f *FileService) OpenDirectoryOnly() string { - result, err := application.Get().Dialog.OpenFile(). - CanChooseDirectories(true). - CanChooseFiles(false). - SetTitle("Select Directory"). - PromptForSingleSelection() - if err != nil { - return "Error: " + err.Error() - } - if result == "" { - return "Cancelled" - } - return result -} - -func (f *FileService) OpenFilteredFile() string { - result, err := application.Get().Dialog.OpenFile(). - SetTitle("Select Text File"). - AddFilter("Text Files", "*.txt"). - PromptForSingleSelection() - if err != nil { - return "Error: " + err.Error() - } - if result == "" { - return "Cancelled" - } - return result -} - -func main() { - app := application.New(application.Options{ - Name: "File Input Test", - Description: "Test for HTML file input (#4862)", - Mac: application.MacOptions{ - ApplicationShouldTerminateAfterLastWindowClosed: true, - }, - Services: []application.Service{ - application.NewService(&FileService{}), - }, - Assets: application.AssetOptions{ - Handler: application.BundledAssetFileServer(assets), - }, - }) - - app.Window.NewWithOptions(application.WebviewWindowOptions{ - Title: "File Input Test", - Width: 700, - Height: 500, - URL: "/", - }) - - if err := app.Run(); err != nil { - log.Fatal(err) - } -} diff --git a/v3/examples/frameless/README.md b/v3/examples/frameless/README.md deleted file mode 100644 index f17f7a5d3..000000000 --- a/v3/examples/frameless/README.md +++ /dev/null @@ -1,19 +0,0 @@ -# Frameless Example - -This example is a demonstration of using frameless windows in Wails. - -## Running the example - -To run the example, simply run the following command: - -```bash -go run . -``` - -# Status - -| Platform | Status | -|----------|---------| -| Mac | Working | -| Windows | Working | -| Linux | | diff --git a/v3/examples/frameless/assets/index.html b/v3/examples/frameless/assets/index.html deleted file mode 100644 index 2776cfaa9..000000000 --- a/v3/examples/frameless/assets/index.html +++ /dev/null @@ -1,53 +0,0 @@ - - - - - - - - -
            -
            Draggable
            -
            Not Draggable
            -
            Not Draggable
            -
            Not Draggable
            -
            Draggable
            -
            - - diff --git a/v3/examples/frameless/main.go b/v3/examples/frameless/main.go deleted file mode 100644 index 93be412fd..000000000 --- a/v3/examples/frameless/main.go +++ /dev/null @@ -1,36 +0,0 @@ -package main - -import ( - "embed" - _ "embed" - "log" - - "github.com/wailsapp/wails/v3/pkg/application" -) - -//go:embed assets -var assets embed.FS - -func main() { - - app := application.New(application.Options{ - Name: "Frameless Demo", - Description: "A demo of frameless windows", - Assets: application.AssetOptions{ - Handler: application.BundledAssetFileServer(assets), - }, - Mac: application.MacOptions{ - ApplicationShouldTerminateAfterLastWindowClosed: true, - }, - }) - - app.Window.NewWithOptions(application.WebviewWindowOptions{ - Frameless: true, - }) - - err := app.Run() - - if err != nil { - log.Fatal(err.Error()) - } -} diff --git a/v3/examples/gin-example/README.md b/v3/examples/gin-example/README.md deleted file mode 100644 index b4d85cb9b..000000000 --- a/v3/examples/gin-example/README.md +++ /dev/null @@ -1,104 +0,0 @@ -# Gin Example - -This example demonstrates how to use the [Gin web framework](https://github.com/gin-gonic/gin) with Wails. - -## Overview - -This example shows how to: - -- Set up Gin as the asset handler for a Wails application -- Create a middleware that routes requests between Wails and Gin -- Define API endpoints with Gin -- Communicate between the Gin-served frontend and Wails backend -- Implement custom Gin middleware - -## Running the Example - -```bash -cd v3/examples/gin-example -go mod tidy -go run . -``` - -## How It Works - -The example uses Gin's HTTP router to serve the frontend content whilst still allowing Wails to handle its internal routes. This is achieved through: - -1. Creating a Gin router with routes for the frontend -2. Implementing a middleware function that decides whether to pass requests to Gin or let Wails handle them -3. Configuring the Wails application to use both the Gin router as the asset handler and the custom middleware - -### Wails-Gin Integration - -The key part of the integration is the middleware function: - -```go -func GinMiddleware(ginEngine *gin.Engine) application.Middleware { - return func(next http.Handler) http.Handler { - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - // Let Wails handle its internal routes - if r.URL.Path == "/wails/runtime.js" || r.URL.Path == "/wails/ipc" { - next.ServeHTTP(w, r) - return - } - - // Let Gin handle everything else - ginEngine.ServeHTTP(w, r) - }) - } -} -``` - -This allows you to leverage Gin's powerful routing and middleware capabilities whilst still maintaining full access to Wails features. - -### Custom Gin Middleware - -The example also demonstrates how to create custom Gin middleware: - -```go -func LoggingMiddleware() gin.HandlerFunc { - return func(c *gin.Context) { - // Start timer - startTime := time.Now() - - // Process request - c.Next() - - // Calculate latency - latency := time.Since(startTime) - - // Log request details - log.Printf("[GIN] %s | %s | %s | %d | %s", - c.Request.Method, - c.Request.URL.Path, - c.ClientIP(), - c.Writer.Status(), - latency, - ) - } -} -``` - -This middleware is applied to all Gin routes and logs details about each request. - -### Application Configuration - -The Wails application is configured to use Gin as follows: - -```go -app := application.New(application.Options{ - Name: "Gin Example", - Description: "A demo of using Gin with Wails", - Mac: application.MacOptions{ - ApplicationShouldTerminateAfterLastWindowClosed: true, - }, - Assets: application.AssetOptions{ - Handler: ginEngine, - Middleware: GinMiddleware(ginEngine), - }, -}) -``` - -This configuration tells Wails to: -1. Use the Gin engine as the primary handler for HTTP requests -2. Use our custom middleware to route requests between Wails and Gin diff --git a/v3/examples/gin-example/go.mod b/v3/examples/gin-example/go.mod deleted file mode 100644 index 4badef3b4..000000000 --- a/v3/examples/gin-example/go.mod +++ /dev/null @@ -1,75 +0,0 @@ -module gin-example - -go 1.25 - -require ( - github.com/gin-gonic/gin v1.11.0 - github.com/wailsapp/wails/v3 v3.0.0 -) - -require ( - dario.cat/mergo v1.0.2 // indirect - github.com/Microsoft/go-winio v0.6.2 // indirect - github.com/ProtonMail/go-crypto v1.3.0 // indirect - github.com/adrg/xdg v0.5.3 // indirect - github.com/bep/debounce v1.2.1 // indirect - github.com/bytedance/gopkg v0.1.3 // indirect - github.com/bytedance/sonic v1.15.0 // indirect - github.com/bytedance/sonic/loader v0.5.0 // indirect - github.com/cloudflare/circl v1.6.3 // indirect - github.com/cloudwego/base64x v0.1.6 // indirect - github.com/coder/websocket v1.8.14 // indirect - github.com/cyphar/filepath-securejoin v0.6.1 // indirect - github.com/ebitengine/purego v0.9.1 // indirect - github.com/emirpasic/gods v1.18.1 // indirect - github.com/gabriel-vasile/mimetype v1.4.12 // indirect - github.com/gin-contrib/sse v1.1.0 // indirect - github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect - github.com/go-git/go-billy/v5 v5.7.0 // indirect - github.com/go-git/go-git/v5 v5.16.4 // indirect - github.com/go-ole/go-ole v1.3.0 // indirect - github.com/go-playground/locales v0.14.1 // indirect - github.com/go-playground/universal-translator v0.18.1 // indirect - github.com/go-playground/validator/v10 v10.30.1 // indirect - github.com/goccy/go-json v0.10.5 // indirect - github.com/goccy/go-yaml v1.19.2 // indirect - github.com/godbus/dbus/v5 v5.2.2 // indirect - github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect - github.com/google/uuid v1.6.0 // indirect - github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect - github.com/jchv/go-winloader v0.0.0-20250406163304-c1995be93bd1 // indirect - github.com/json-iterator/go v1.1.12 // indirect - github.com/kevinburke/ssh_config v1.4.0 // indirect - github.com/klauspost/cpuid/v2 v2.3.0 // indirect - github.com/leaanthony/go-ansi-parser v1.6.1 // indirect - github.com/leaanthony/u v1.1.1 // indirect - github.com/leodido/go-urn v1.4.0 // indirect - github.com/lmittmann/tint v1.1.2 // indirect - github.com/mattn/go-colorable v0.1.14 // indirect - github.com/mattn/go-isatty v0.0.20 // indirect - github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect - github.com/modern-go/reflect2 v1.0.2 // indirect - github.com/pelletier/go-toml/v2 v2.2.4 // indirect - github.com/pjbgf/sha1cd v0.5.0 // indirect - github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c // indirect - github.com/quic-go/qpack v0.6.0 // indirect - github.com/quic-go/quic-go v0.59.0 // indirect - github.com/rivo/uniseg v0.4.7 // indirect - github.com/samber/lo v1.52.0 // indirect - github.com/sergi/go-diff v1.4.0 // indirect - github.com/skeema/knownhosts v1.3.2 // indirect - github.com/twitchyliquid64/golang-asm v0.15.1 // indirect - github.com/ugorji/go/codec v1.3.1 // indirect - github.com/wailsapp/go-webview2 v1.0.23 // indirect - github.com/xanzy/ssh-agent v0.3.3 // indirect - go.uber.org/mock v0.6.0 // indirect - golang.org/x/arch v0.23.0 // indirect - golang.org/x/crypto v0.47.0 // indirect - golang.org/x/net v0.49.0 // indirect - golang.org/x/sys v0.40.0 // indirect - golang.org/x/text v0.33.0 // indirect - google.golang.org/protobuf v1.36.11 // indirect - gopkg.in/warnings.v0 v0.1.2 // indirect -) - -replace github.com/wailsapp/wails/v3 => ../.. diff --git a/v3/examples/gin-example/go.sum b/v3/examples/gin-example/go.sum deleted file mode 100644 index 9ca8a1297..000000000 --- a/v3/examples/gin-example/go.sum +++ /dev/null @@ -1,208 +0,0 @@ -dario.cat/mergo v1.0.2 h1:85+piFYR1tMbRrLcDwR18y4UKJ3aH1Tbzi24VRW1TK8= -dario.cat/mergo v1.0.2/go.mod h1:E/hbnu0NxMFBjpMIE34DRGLWqDy0g5FuKDhCb31ngxA= -github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY= -github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= -github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= -github.com/ProtonMail/go-crypto v1.3.0 h1:ILq8+Sf5If5DCpHQp4PbZdS1J7HDFRXz/+xKBiRGFrw= -github.com/ProtonMail/go-crypto v1.3.0/go.mod h1:9whxjD8Rbs29b4XWbB8irEcE8KHMqaR2e7GWU1R+/PE= -github.com/adrg/xdg v0.5.3 h1:xRnxJXne7+oWDatRhR1JLnvuccuIeCoBu2rtuLqQB78= -github.com/adrg/xdg v0.5.3/go.mod h1:nlTsY+NNiCBGCK2tpm09vRqfVzrc2fLmXGpBLF0zlTQ= -github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8= -github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4= -github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= -github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= -github.com/bep/debounce v1.2.1 h1:v67fRdBA9UQu2NhLFXrSg0Brw7CexQekrBwDMM8bzeY= -github.com/bep/debounce v1.2.1/go.mod h1:H8yggRPQKLUhUoqrJC1bO2xNya7vanpDl7xR3ISbCJ0= -github.com/bytedance/gopkg v0.1.3 h1:TPBSwH8RsouGCBcMBktLt1AymVo2TVsBVCY4b6TnZ/M= -github.com/bytedance/gopkg v0.1.3/go.mod h1:576VvJ+eJgyCzdjS+c4+77QF3p7ubbtiKARP3TxducM= -github.com/bytedance/sonic v1.15.0 h1:/PXeWFaR5ElNcVE84U0dOHjiMHQOwNIx3K4ymzh/uSE= -github.com/bytedance/sonic v1.15.0/go.mod h1:tFkWrPz0/CUCLEF4ri4UkHekCIcdnkqXw9VduqpJh0k= -github.com/bytedance/sonic/loader v0.5.0 h1:gXH3KVnatgY7loH5/TkeVyXPfESoqSBSBEiDd5VjlgE= -github.com/bytedance/sonic/loader v0.5.0/go.mod h1:AR4NYCk5DdzZizZ5djGqQ92eEhCCcdf5x77udYiSJRo= -github.com/cloudflare/circl v1.6.3 h1:9GPOhQGF9MCYUeXyMYlqTR6a5gTrgR/fBLXvUgtVcg8= -github.com/cloudflare/circl v1.6.3/go.mod h1:2eXP6Qfat4O/Yhh8BznvKnJ+uzEoTQ6jVKJRn81BiS4= -github.com/cloudwego/base64x v0.1.6 h1:t11wG9AECkCDk5fMSoxmufanudBtJ+/HemLstXDLI2M= -github.com/cloudwego/base64x v0.1.6/go.mod h1:OFcloc187FXDaYHvrNIjxSe8ncn0OOM8gEHfghB2IPU= -github.com/coder/websocket v1.8.14 h1:9L0p0iKiNOibykf283eHkKUHHrpG7f65OE3BhhO7v9g= -github.com/coder/websocket v1.8.14/go.mod h1:NX3SzP+inril6yawo5CQXx8+fk145lPDC6pumgx0mVg= -github.com/cyphar/filepath-securejoin v0.6.1 h1:5CeZ1jPXEiYt3+Z6zqprSAgSWiggmpVyciv8syjIpVE= -github.com/cyphar/filepath-securejoin v0.6.1/go.mod h1:A8hd4EnAeyujCJRrICiOWqjS1AX0a9kM5XL+NwKoYSc= -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= -github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/ebitengine/purego v0.9.1 h1:a/k2f2HQU3Pi399RPW1MOaZyhKJL9w/xFpKAg4q1s0A= -github.com/ebitengine/purego v0.9.1/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ= -github.com/elazarl/goproxy v1.7.2 h1:Y2o6urb7Eule09PjlhQRGNsqRfPmYI3KKQLFpCAV3+o= -github.com/elazarl/goproxy v1.7.2/go.mod h1:82vkLNir0ALaW14Rc399OTTjyNREgmdL2cVoIbS6XaE= -github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc= -github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ= -github.com/gabriel-vasile/mimetype v1.4.12 h1:e9hWvmLYvtp846tLHam2o++qitpguFiYCKbn0w9jyqw= -github.com/gabriel-vasile/mimetype v1.4.12/go.mod h1:d+9Oxyo1wTzWdyVUPMmXFvp4F9tea18J8ufA774AB3s= -github.com/gin-contrib/sse v1.1.0 h1:n0w2GMuUpWDVp7qSpvze6fAu9iRxJY4Hmj6AmBOU05w= -github.com/gin-contrib/sse v1.1.0/go.mod h1:hxRZ5gVpWMT7Z0B0gSNYqqsSCNIJMjzvm6fqCz9vjwM= -github.com/gin-gonic/gin v1.11.0 h1:OW/6PLjyusp2PPXtyxKHU0RbX6I/l28FTdDlae5ueWk= -github.com/gin-gonic/gin v1.11.0/go.mod h1:+iq/FyxlGzII0KHiBGjuNn4UNENUlKbGlNmc+W50Dls= -github.com/gliderlabs/ssh v0.3.8 h1:a4YXD1V7xMF9g5nTkdfnja3Sxy1PVDCj1Zg4Wb8vY6c= -github.com/gliderlabs/ssh v0.3.8/go.mod h1:xYoytBv1sV0aL3CavoDuJIQNURXkkfPA/wxQ1pL1fAU= -github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI= -github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmSxCcxctByoQdvwPiA7DTK7jaaFDBTtu0ic= -github.com/go-git/go-billy/v5 v5.7.0 h1:83lBUJhGWhYp0ngzCMSgllhUSuoHP1iEWYjsPl9nwqM= -github.com/go-git/go-billy/v5 v5.7.0/go.mod h1:/1IUejTKH8xipsAcdfcSAlUlo2J7lkYV8GTKxAT/L3E= -github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399 h1:eMje31YglSBqCdIqdhKBW8lokaMrL3uTkpGYlE2OOT4= -github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399/go.mod h1:1OCfN199q1Jm3HZlxleg+Dw/mwps2Wbk9frAWm+4FII= -github.com/go-git/go-git/v5 v5.16.4 h1:7ajIEZHZJULcyJebDLo99bGgS0jRrOxzZG4uCk2Yb2Y= -github.com/go-git/go-git/v5 v5.16.4/go.mod h1:4Ge4alE/5gPs30F2H1esi2gPd69R0C39lolkucHBOp8= -github.com/go-json-experiment/json v0.0.0-20251027170946-4849db3c2f7e h1:Lf/gRkoycfOBPa42vU2bbgPurFong6zXeFtPoxholzU= -github.com/go-json-experiment/json v0.0.0-20251027170946-4849db3c2f7e/go.mod h1:uNVvRXArCGbZ508SxYYTC5v1JWoz2voff5pm25jU1Ok= -github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE= -github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78= -github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= -github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= -github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= -github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= -github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= -github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= -github.com/go-playground/validator/v10 v10.30.1 h1:f3zDSN/zOma+w6+1Wswgd9fLkdwy06ntQJp0BBvFG0w= -github.com/go-playground/validator/v10 v10.30.1/go.mod h1:oSuBIQzuJxL//3MelwSLD5hc2Tu889bF0Idm9Dg26cM= -github.com/goccy/go-json v0.10.5 h1:Fq85nIqj+gXn/S5ahsiTlK3TmC85qgirsdTP/+DeaC4= -github.com/goccy/go-json v0.10.5/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M= -github.com/goccy/go-yaml v1.19.2 h1:PmFC1S6h8ljIz6gMRBopkjP1TVT7xuwrButHID66PoM= -github.com/goccy/go-yaml v1.19.2/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA= -github.com/godbus/dbus/v5 v5.2.2 h1:TUR3TgtSVDmjiXOgAAyaZbYmIeP3DPkld3jgKGV8mXQ= -github.com/godbus/dbus/v5 v5.2.2/go.mod h1:3AAv2+hPq5rdnr5txxxRwiGjPXamgoIHgz9FPBfOp3c= -github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 h1:f+oWsMOmNPc8JmEHVZIycC7hBoQxHH9pNKQORJNozsQ= -github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8/go.mod h1:wcDNUvekVysuuOpQKo3191zZyTpiI6se1N1ULghS0sw= -github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= -github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= -github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= -github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A= -github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= -github.com/jchv/go-winloader v0.0.0-20250406163304-c1995be93bd1 h1:njuLRcjAuMKr7kI3D85AXWkw6/+v9PwtV6M6o11sWHQ= -github.com/jchv/go-winloader v0.0.0-20250406163304-c1995be93bd1/go.mod h1:alcuEEnZsY1WQsagKhZDsoPCRoOijYqhZvPwLG0kzVs= -github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= -github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= -github.com/kevinburke/ssh_config v1.4.0 h1:6xxtP5bZ2E4NF5tuQulISpTO2z8XbtH8cg1PWkxoFkQ= -github.com/kevinburke/ssh_config v1.4.0/go.mod h1:q2RIzfka+BXARoNexmF9gkxEX7DmvbW9P4hIVx2Kg4M= -github.com/klauspost/cpuid/v2 v2.3.0 h1:S4CRMLnYUhGeDFDqkGriYKdfoFlDnMtqTiI/sFzhA9Y= -github.com/klauspost/cpuid/v2 v2.3.0/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0= -github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= -github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= -github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= -github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= -github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/leaanthony/go-ansi-parser v1.6.1 h1:xd8bzARK3dErqkPFtoF9F3/HgN8UQk0ed1YDKpEz01A= -github.com/leaanthony/go-ansi-parser v1.6.1/go.mod h1:+vva/2y4alzVmmIEpk9QDhA7vLC5zKDTRwfZGOp3IWU= -github.com/leaanthony/u v1.1.1 h1:TUFjwDGlNX+WuwVEzDqQwC2lOv0P4uhTQw7CMFdiK7M= -github.com/leaanthony/u v1.1.1/go.mod h1:9+o6hejoRljvZ3BzdYlVL0JYCwtnAsVuN9pVTQcaRfI= -github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ= -github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI= -github.com/lmittmann/tint v1.1.2 h1:2CQzrL6rslrsyjqLDwD11bZ5OpLBPU+g3G/r5LSfS8w= -github.com/lmittmann/tint v1.1.2/go.mod h1:HIS3gSy7qNwGCj+5oRjAutErFBl4BzdQP6cJZ0NfMwE= -github.com/matryer/is v1.4.0/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwMRU= -github.com/matryer/is v1.4.1 h1:55ehd8zaGABKLXQUe2awZ99BD/PTc2ls+KV/dXphgEQ= -github.com/matryer/is v1.4.1/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwMRU= -github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE= -github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8= -github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= -github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= -github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= -github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= -github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= -github.com/onsi/gomega v1.34.1 h1:EUMJIKUjM8sKjYbtxQI9A4z2o+rruxnzNvpknOXie6k= -github.com/onsi/gomega v1.34.1/go.mod h1:kU1QgUvBDLXBJq618Xvm2LUX6rSAfRaFRTcdOeDLwwY= -github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4= -github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY= -github.com/pjbgf/sha1cd v0.5.0 h1:a+UkboSi1znleCDUNT3M5YxjOnN1fz2FhN48FlwCxs0= -github.com/pjbgf/sha1cd v0.5.0/go.mod h1:lhpGlyHLpQZoxMv8HcgXvZEhcGs0PG/vsZnEJ7H0iCM= -github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmdv1U2eRNDiU2ErMBj1gwrq8eQ= -github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c/go.mod h1:7rwL4CYBLnjLxUqIJNnCWiEdr3bn6IUYi15bNlnbCCU= -github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= -github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= -github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/quic-go/qpack v0.6.0 h1:g7W+BMYynC1LbYLSqRt8PBg5Tgwxn214ZZR34VIOjz8= -github.com/quic-go/qpack v0.6.0/go.mod h1:lUpLKChi8njB4ty2bFLX2x4gzDqXwUpaO1DP9qMDZII= -github.com/quic-go/quic-go v0.59.0 h1:OLJkp1Mlm/aS7dpKgTc6cnpynnD2Xg7C1pwL6vy/SAw= -github.com/quic-go/quic-go v0.59.0/go.mod h1:upnsH4Ju1YkqpLXC305eW3yDZ4NfnNbmQRCMWS58IKU= -github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= -github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= -github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= -github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= -github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= -github.com/samber/lo v1.52.0 h1:Rvi+3BFHES3A8meP33VPAxiBZX/Aws5RxrschYGjomw= -github.com/samber/lo v1.52.0/go.mod h1:4+MXEGsJzbKGaUEQFKBq2xtfuznW9oz/WrgyzMzRoM0= -github.com/sergi/go-diff v1.4.0 h1:n/SP9D5ad1fORl+llWyN+D6qoUETXNZARKjyY2/KVCw= -github.com/sergi/go-diff v1.4.0/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4= -github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= -github.com/skeema/knownhosts v1.3.2 h1:EDL9mgf4NzwMXCTfaxSD/o/a5fxDw/xL9nkU28JjdBg= -github.com/skeema/knownhosts v1.3.2/go.mod h1:bEg3iQAuw+jyiw+484wwFJoKSLwcfd7fqRy+N0QTiow= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= -github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= -github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= -github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= -github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= -github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= -github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= -github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI= -github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= -github.com/ugorji/go/codec v1.3.1 h1:waO7eEiFDwidsBN6agj1vJQ4AG7lh2yqXyOXqhgQuyY= -github.com/ugorji/go/codec v1.3.1/go.mod h1:pRBVtBSKl77K30Bv8R2P+cLSGaTtex6fsA2Wjqmfxj4= -github.com/wailsapp/go-webview2 v1.0.23 h1:jmv8qhz1lHibCc79bMM/a/FqOnnzOGEisLav+a0b9P0= -github.com/wailsapp/go-webview2 v1.0.23/go.mod h1:qJmWAmAmaniuKGZPWwne+uor3AHMB5PFhqiK0Bbj8kc= -github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM= -github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw= -go.uber.org/mock v0.6.0 h1:hyF9dfmbgIX5EfOdasqLsWD6xqpNZlXblLB/Dbnwv3Y= -go.uber.org/mock v0.6.0/go.mod h1:KiVJ4BqZJaMj4svdfmHM0AUx4NJYO8ZNpPnZn1Z+BBU= -golang.org/x/arch v0.23.0 h1:lKF64A2jF6Zd8L0knGltUnegD62JMFBiCPBmQpToHhg= -golang.org/x/arch v0.23.0/go.mod h1:dNHoOeKiyja7GTvF9NJS1l3Z2yntpQNzgrjh1cU103A= -golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.47.0 h1:V6e3FRj+n4dbpw86FJ8Fv7XVOql7TEwpHapKoMJ/GO8= -golang.org/x/crypto v0.47.0/go.mod h1:ff3Y9VzzKbwSSEzWqJsJVBnWmRwRSHt/6Op5n9bQc4A= -golang.org/x/exp v0.0.0-20260112195511-716be5621a96 h1:Z/6YuSHTLOHfNFdb8zVZomZr7cqNgTJvA8+Qz75D8gU= -golang.org/x/exp v0.0.0-20260112195511-716be5621a96/go.mod h1:nzimsREAkjBCIEFtHiYkrJyT+2uy9YZJB7H1k68CXZU= -golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.49.0 h1:eeHFmOGUTtaaPSGNmjBKpbng9MulQsJURQUAfUwY++o= -golang.org/x/net v0.49.0/go.mod h1:/ysNB2EvaqvesRkuLAyjI1ycPZlQHM3q01F02UY/MV8= -golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200810151505-1b9f1253b3ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.40.0 h1:DBZZqJ2Rkml6QMQsZywtnjnnGvHza6BTfYFWY9kjEWQ= -golang.org/x/sys v0.40.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= -golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.39.0 h1:RclSuaJf32jOqZz74CkPA9qFuVTX7vhLlpfj/IGWlqY= -golang.org/x/term v0.39.0/go.mod h1:yxzUCTP/U+FzoxfdKmLaA0RV1WgE0VY7hXBwKtY/4ww= -golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.33.0 h1:B3njUFyqtHDUI5jMn1YIr5B0IE2U0qck04r6d4KPAxE= -golang.org/x/text v0.33.0/go.mod h1:LuMebE6+rBincTi9+xWTY8TztLzKHc/9C1uBCG27+q8= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE= -google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= -gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME= -gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= -gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= -gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/v3/examples/gin-example/main.go b/v3/examples/gin-example/main.go deleted file mode 100644 index 8138d5403..000000000 --- a/v3/examples/gin-example/main.go +++ /dev/null @@ -1,116 +0,0 @@ -package main - -import ( - "embed" - "log" - "net/http" - "strings" - "time" - - "github.com/gin-gonic/gin" - "github.com/wailsapp/wails/v3/pkg/application" -) - -//go:embed static -var staticFiles embed.FS - -// GinMiddleware creates a middleware that passes requests to Gin if they're not handled by Wails -func GinMiddleware(ginEngine *gin.Engine) application.Middleware { - return func(next http.Handler) http.Handler { - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - // Let Wails handle the `/wails` route - if strings.HasPrefix(r.URL.Path, "/wails") { - next.ServeHTTP(w, r) - return - } - // Let Gin handle everything else - ginEngine.ServeHTTP(w, r) - }) - } -} - -// LoggingMiddleware is a Gin middleware that logs request details -func LoggingMiddleware() gin.HandlerFunc { - return func(c *gin.Context) { - // Start timer - startTime := time.Now() - - // Process request - c.Next() - - // Calculate latency - latency := time.Since(startTime) - - // Log request details - log.Printf("[GIN] %s | %s | %s | %d | %s", - c.Request.Method, - c.Request.URL.Path, - c.ClientIP(), - c.Writer.Status(), - latency, - ) - } -} - -func main() { - // Create a new Gin router - ginEngine := gin.New() // Using New() instead of Default() to add our own middleware - - // Add middlewares - ginEngine.Use(gin.Recovery()) - ginEngine.Use(LoggingMiddleware()) - - // Serve embedded static files - ginEngine.StaticFS("/static", http.FS(staticFiles)) - - // Define routes - ginEngine.GET("/", func(c *gin.Context) { - file, err := staticFiles.ReadFile("static/index.html") - if err != nil { - c.String(http.StatusInternalServerError, "Error reading index.html") - return - } - c.Data(http.StatusOK, "text/html; charset=utf-8", file) - }) - - ginEngine.GET("/api/hello", func(c *gin.Context) { - c.JSON(http.StatusOK, gin.H{ - "message": "Hello from Gin API!", - "time": time.Now().Format(time.RFC3339), - }) - }) - - // Create a new Wails application - app := application.New(application.Options{ - Name: "Gin Example", - Description: "A demo of using Gin with Wails", - Mac: application.MacOptions{ - ApplicationShouldTerminateAfterLastWindowClosed: true, - }, - Assets: application.AssetOptions{ - Handler: ginEngine, - Middleware: GinMiddleware(ginEngine), - }, - }) - - // Register event handler and store cleanup function - removeGinHandler := app.Event.On("gin-button-clicked", func(event *application.CustomEvent) { - log.Printf("Received event from frontend: %v", event.Data) - }) - // Note: In production, call removeGinHandler() during cleanup - _ = removeGinHandler - - // Create window - app.Window.NewWithOptions(application.WebviewWindowOptions{ - Title: "Wails + Gin Example", - Width: 900, - Height: 700, - URL: "/", - }) - - // Run the app - err := app.Run() - if err != nil { - log.Fatal(err) - } -} diff --git a/v3/examples/gin-example/static/index.html b/v3/examples/gin-example/static/index.html deleted file mode 100644 index df02b840f..000000000 --- a/v3/examples/gin-example/static/index.html +++ /dev/null @@ -1,96 +0,0 @@ - - - Wails + Gin Example - - - -
            -

            Wails + Gin Integration

            -
            -

            Hello World!

            -

            This page is being served by Gin.

            -

            Click the button below to trigger a Wails event:

            - - -
            -
            -

            API Example

            -

            Try the Gin API endpoint:

            - -
            -
            -
            - - - diff --git a/v3/examples/gin-routing/README.md b/v3/examples/gin-routing/README.md deleted file mode 100644 index 5d8babc31..000000000 --- a/v3/examples/gin-routing/README.md +++ /dev/null @@ -1,26 +0,0 @@ -# Gin Routing Example - -This example demonstrates how to use the [Gin web framework](https://github.com/gin-gonic/gin) as a router with Wails. - -## Overview - -This example shows how to: - -- Set up Gin as the asset handler for a Wails application -- Create a middleware that routes requests between Wails and Gin -- Define API endpoints with Gin -- Communicate between the Gin-served frontend and Wails backend -- Implement custom Gin middleware - -## Running the Example - -```bash -cd v3/examples/gin-routing -go mod tidy -go run . -``` - -## Documentation - -Please consult the [Using Gin for Routing](https://v3.wails.io/guides/gin-routing/) guide for a detailed explanation of the example. - diff --git a/v3/examples/gin-routing/go.mod b/v3/examples/gin-routing/go.mod deleted file mode 100644 index 41069befd..000000000 --- a/v3/examples/gin-routing/go.mod +++ /dev/null @@ -1,75 +0,0 @@ -module gin-routing - -go 1.25 - -require ( - github.com/gin-gonic/gin v1.11.0 - github.com/wailsapp/wails/v3 v3.0.0 -) - -require ( - dario.cat/mergo v1.0.2 // indirect - github.com/Microsoft/go-winio v0.6.2 // indirect - github.com/ProtonMail/go-crypto v1.3.0 // indirect - github.com/adrg/xdg v0.5.3 // indirect - github.com/bep/debounce v1.2.1 // indirect - github.com/bytedance/gopkg v0.1.3 // indirect - github.com/bytedance/sonic v1.15.0 // indirect - github.com/bytedance/sonic/loader v0.5.0 // indirect - github.com/cloudflare/circl v1.6.3 // indirect - github.com/cloudwego/base64x v0.1.6 // indirect - github.com/coder/websocket v1.8.14 // indirect - github.com/cyphar/filepath-securejoin v0.6.1 // indirect - github.com/ebitengine/purego v0.9.1 // indirect - github.com/emirpasic/gods v1.18.1 // indirect - github.com/gabriel-vasile/mimetype v1.4.12 // indirect - github.com/gin-contrib/sse v1.1.0 // indirect - github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect - github.com/go-git/go-billy/v5 v5.7.0 // indirect - github.com/go-git/go-git/v5 v5.16.4 // indirect - github.com/go-ole/go-ole v1.3.0 // indirect - github.com/go-playground/locales v0.14.1 // indirect - github.com/go-playground/universal-translator v0.18.1 // indirect - github.com/go-playground/validator/v10 v10.30.1 // indirect - github.com/goccy/go-json v0.10.5 // indirect - github.com/goccy/go-yaml v1.19.2 // indirect - github.com/godbus/dbus/v5 v5.2.2 // indirect - github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect - github.com/google/uuid v1.6.0 // indirect - github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect - github.com/jchv/go-winloader v0.0.0-20250406163304-c1995be93bd1 // indirect - github.com/json-iterator/go v1.1.12 // indirect - github.com/kevinburke/ssh_config v1.4.0 // indirect - github.com/klauspost/cpuid/v2 v2.3.0 // indirect - github.com/leaanthony/go-ansi-parser v1.6.1 // indirect - github.com/leaanthony/u v1.1.1 // indirect - github.com/leodido/go-urn v1.4.0 // indirect - github.com/lmittmann/tint v1.1.2 // indirect - github.com/mattn/go-colorable v0.1.14 // indirect - github.com/mattn/go-isatty v0.0.20 // indirect - github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect - github.com/modern-go/reflect2 v1.0.2 // indirect - github.com/pelletier/go-toml/v2 v2.2.4 // indirect - github.com/pjbgf/sha1cd v0.5.0 // indirect - github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c // indirect - github.com/quic-go/qpack v0.6.0 // indirect - github.com/quic-go/quic-go v0.59.0 // indirect - github.com/rivo/uniseg v0.4.7 // indirect - github.com/samber/lo v1.52.0 // indirect - github.com/sergi/go-diff v1.4.0 // indirect - github.com/skeema/knownhosts v1.3.2 // indirect - github.com/twitchyliquid64/golang-asm v0.15.1 // indirect - github.com/ugorji/go/codec v1.3.1 // indirect - github.com/wailsapp/go-webview2 v1.0.23 // indirect - github.com/xanzy/ssh-agent v0.3.3 // indirect - go.uber.org/mock v0.6.0 // indirect - golang.org/x/arch v0.23.0 // indirect - golang.org/x/crypto v0.47.0 // indirect - golang.org/x/net v0.49.0 // indirect - golang.org/x/sys v0.40.0 // indirect - golang.org/x/text v0.33.0 // indirect - google.golang.org/protobuf v1.36.11 // indirect - gopkg.in/warnings.v0 v0.1.2 // indirect -) - -replace github.com/wailsapp/wails/v3 => ../.. diff --git a/v3/examples/gin-routing/go.sum b/v3/examples/gin-routing/go.sum deleted file mode 100644 index 9ca8a1297..000000000 --- a/v3/examples/gin-routing/go.sum +++ /dev/null @@ -1,208 +0,0 @@ -dario.cat/mergo v1.0.2 h1:85+piFYR1tMbRrLcDwR18y4UKJ3aH1Tbzi24VRW1TK8= -dario.cat/mergo v1.0.2/go.mod h1:E/hbnu0NxMFBjpMIE34DRGLWqDy0g5FuKDhCb31ngxA= -github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY= -github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= -github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= -github.com/ProtonMail/go-crypto v1.3.0 h1:ILq8+Sf5If5DCpHQp4PbZdS1J7HDFRXz/+xKBiRGFrw= -github.com/ProtonMail/go-crypto v1.3.0/go.mod h1:9whxjD8Rbs29b4XWbB8irEcE8KHMqaR2e7GWU1R+/PE= -github.com/adrg/xdg v0.5.3 h1:xRnxJXne7+oWDatRhR1JLnvuccuIeCoBu2rtuLqQB78= -github.com/adrg/xdg v0.5.3/go.mod h1:nlTsY+NNiCBGCK2tpm09vRqfVzrc2fLmXGpBLF0zlTQ= -github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8= -github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4= -github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= -github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= -github.com/bep/debounce v1.2.1 h1:v67fRdBA9UQu2NhLFXrSg0Brw7CexQekrBwDMM8bzeY= -github.com/bep/debounce v1.2.1/go.mod h1:H8yggRPQKLUhUoqrJC1bO2xNya7vanpDl7xR3ISbCJ0= -github.com/bytedance/gopkg v0.1.3 h1:TPBSwH8RsouGCBcMBktLt1AymVo2TVsBVCY4b6TnZ/M= -github.com/bytedance/gopkg v0.1.3/go.mod h1:576VvJ+eJgyCzdjS+c4+77QF3p7ubbtiKARP3TxducM= -github.com/bytedance/sonic v1.15.0 h1:/PXeWFaR5ElNcVE84U0dOHjiMHQOwNIx3K4ymzh/uSE= -github.com/bytedance/sonic v1.15.0/go.mod h1:tFkWrPz0/CUCLEF4ri4UkHekCIcdnkqXw9VduqpJh0k= -github.com/bytedance/sonic/loader v0.5.0 h1:gXH3KVnatgY7loH5/TkeVyXPfESoqSBSBEiDd5VjlgE= -github.com/bytedance/sonic/loader v0.5.0/go.mod h1:AR4NYCk5DdzZizZ5djGqQ92eEhCCcdf5x77udYiSJRo= -github.com/cloudflare/circl v1.6.3 h1:9GPOhQGF9MCYUeXyMYlqTR6a5gTrgR/fBLXvUgtVcg8= -github.com/cloudflare/circl v1.6.3/go.mod h1:2eXP6Qfat4O/Yhh8BznvKnJ+uzEoTQ6jVKJRn81BiS4= -github.com/cloudwego/base64x v0.1.6 h1:t11wG9AECkCDk5fMSoxmufanudBtJ+/HemLstXDLI2M= -github.com/cloudwego/base64x v0.1.6/go.mod h1:OFcloc187FXDaYHvrNIjxSe8ncn0OOM8gEHfghB2IPU= -github.com/coder/websocket v1.8.14 h1:9L0p0iKiNOibykf283eHkKUHHrpG7f65OE3BhhO7v9g= -github.com/coder/websocket v1.8.14/go.mod h1:NX3SzP+inril6yawo5CQXx8+fk145lPDC6pumgx0mVg= -github.com/cyphar/filepath-securejoin v0.6.1 h1:5CeZ1jPXEiYt3+Z6zqprSAgSWiggmpVyciv8syjIpVE= -github.com/cyphar/filepath-securejoin v0.6.1/go.mod h1:A8hd4EnAeyujCJRrICiOWqjS1AX0a9kM5XL+NwKoYSc= -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= -github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/ebitengine/purego v0.9.1 h1:a/k2f2HQU3Pi399RPW1MOaZyhKJL9w/xFpKAg4q1s0A= -github.com/ebitengine/purego v0.9.1/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ= -github.com/elazarl/goproxy v1.7.2 h1:Y2o6urb7Eule09PjlhQRGNsqRfPmYI3KKQLFpCAV3+o= -github.com/elazarl/goproxy v1.7.2/go.mod h1:82vkLNir0ALaW14Rc399OTTjyNREgmdL2cVoIbS6XaE= -github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc= -github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ= -github.com/gabriel-vasile/mimetype v1.4.12 h1:e9hWvmLYvtp846tLHam2o++qitpguFiYCKbn0w9jyqw= -github.com/gabriel-vasile/mimetype v1.4.12/go.mod h1:d+9Oxyo1wTzWdyVUPMmXFvp4F9tea18J8ufA774AB3s= -github.com/gin-contrib/sse v1.1.0 h1:n0w2GMuUpWDVp7qSpvze6fAu9iRxJY4Hmj6AmBOU05w= -github.com/gin-contrib/sse v1.1.0/go.mod h1:hxRZ5gVpWMT7Z0B0gSNYqqsSCNIJMjzvm6fqCz9vjwM= -github.com/gin-gonic/gin v1.11.0 h1:OW/6PLjyusp2PPXtyxKHU0RbX6I/l28FTdDlae5ueWk= -github.com/gin-gonic/gin v1.11.0/go.mod h1:+iq/FyxlGzII0KHiBGjuNn4UNENUlKbGlNmc+W50Dls= -github.com/gliderlabs/ssh v0.3.8 h1:a4YXD1V7xMF9g5nTkdfnja3Sxy1PVDCj1Zg4Wb8vY6c= -github.com/gliderlabs/ssh v0.3.8/go.mod h1:xYoytBv1sV0aL3CavoDuJIQNURXkkfPA/wxQ1pL1fAU= -github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI= -github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmSxCcxctByoQdvwPiA7DTK7jaaFDBTtu0ic= -github.com/go-git/go-billy/v5 v5.7.0 h1:83lBUJhGWhYp0ngzCMSgllhUSuoHP1iEWYjsPl9nwqM= -github.com/go-git/go-billy/v5 v5.7.0/go.mod h1:/1IUejTKH8xipsAcdfcSAlUlo2J7lkYV8GTKxAT/L3E= -github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399 h1:eMje31YglSBqCdIqdhKBW8lokaMrL3uTkpGYlE2OOT4= -github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399/go.mod h1:1OCfN199q1Jm3HZlxleg+Dw/mwps2Wbk9frAWm+4FII= -github.com/go-git/go-git/v5 v5.16.4 h1:7ajIEZHZJULcyJebDLo99bGgS0jRrOxzZG4uCk2Yb2Y= -github.com/go-git/go-git/v5 v5.16.4/go.mod h1:4Ge4alE/5gPs30F2H1esi2gPd69R0C39lolkucHBOp8= -github.com/go-json-experiment/json v0.0.0-20251027170946-4849db3c2f7e h1:Lf/gRkoycfOBPa42vU2bbgPurFong6zXeFtPoxholzU= -github.com/go-json-experiment/json v0.0.0-20251027170946-4849db3c2f7e/go.mod h1:uNVvRXArCGbZ508SxYYTC5v1JWoz2voff5pm25jU1Ok= -github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE= -github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78= -github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= -github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= -github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= -github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= -github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= -github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= -github.com/go-playground/validator/v10 v10.30.1 h1:f3zDSN/zOma+w6+1Wswgd9fLkdwy06ntQJp0BBvFG0w= -github.com/go-playground/validator/v10 v10.30.1/go.mod h1:oSuBIQzuJxL//3MelwSLD5hc2Tu889bF0Idm9Dg26cM= -github.com/goccy/go-json v0.10.5 h1:Fq85nIqj+gXn/S5ahsiTlK3TmC85qgirsdTP/+DeaC4= -github.com/goccy/go-json v0.10.5/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M= -github.com/goccy/go-yaml v1.19.2 h1:PmFC1S6h8ljIz6gMRBopkjP1TVT7xuwrButHID66PoM= -github.com/goccy/go-yaml v1.19.2/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA= -github.com/godbus/dbus/v5 v5.2.2 h1:TUR3TgtSVDmjiXOgAAyaZbYmIeP3DPkld3jgKGV8mXQ= -github.com/godbus/dbus/v5 v5.2.2/go.mod h1:3AAv2+hPq5rdnr5txxxRwiGjPXamgoIHgz9FPBfOp3c= -github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 h1:f+oWsMOmNPc8JmEHVZIycC7hBoQxHH9pNKQORJNozsQ= -github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8/go.mod h1:wcDNUvekVysuuOpQKo3191zZyTpiI6se1N1ULghS0sw= -github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= -github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= -github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= -github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A= -github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= -github.com/jchv/go-winloader v0.0.0-20250406163304-c1995be93bd1 h1:njuLRcjAuMKr7kI3D85AXWkw6/+v9PwtV6M6o11sWHQ= -github.com/jchv/go-winloader v0.0.0-20250406163304-c1995be93bd1/go.mod h1:alcuEEnZsY1WQsagKhZDsoPCRoOijYqhZvPwLG0kzVs= -github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= -github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= -github.com/kevinburke/ssh_config v1.4.0 h1:6xxtP5bZ2E4NF5tuQulISpTO2z8XbtH8cg1PWkxoFkQ= -github.com/kevinburke/ssh_config v1.4.0/go.mod h1:q2RIzfka+BXARoNexmF9gkxEX7DmvbW9P4hIVx2Kg4M= -github.com/klauspost/cpuid/v2 v2.3.0 h1:S4CRMLnYUhGeDFDqkGriYKdfoFlDnMtqTiI/sFzhA9Y= -github.com/klauspost/cpuid/v2 v2.3.0/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0= -github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= -github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= -github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= -github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= -github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/leaanthony/go-ansi-parser v1.6.1 h1:xd8bzARK3dErqkPFtoF9F3/HgN8UQk0ed1YDKpEz01A= -github.com/leaanthony/go-ansi-parser v1.6.1/go.mod h1:+vva/2y4alzVmmIEpk9QDhA7vLC5zKDTRwfZGOp3IWU= -github.com/leaanthony/u v1.1.1 h1:TUFjwDGlNX+WuwVEzDqQwC2lOv0P4uhTQw7CMFdiK7M= -github.com/leaanthony/u v1.1.1/go.mod h1:9+o6hejoRljvZ3BzdYlVL0JYCwtnAsVuN9pVTQcaRfI= -github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ= -github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI= -github.com/lmittmann/tint v1.1.2 h1:2CQzrL6rslrsyjqLDwD11bZ5OpLBPU+g3G/r5LSfS8w= -github.com/lmittmann/tint v1.1.2/go.mod h1:HIS3gSy7qNwGCj+5oRjAutErFBl4BzdQP6cJZ0NfMwE= -github.com/matryer/is v1.4.0/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwMRU= -github.com/matryer/is v1.4.1 h1:55ehd8zaGABKLXQUe2awZ99BD/PTc2ls+KV/dXphgEQ= -github.com/matryer/is v1.4.1/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwMRU= -github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE= -github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8= -github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= -github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= -github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= -github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= -github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= -github.com/onsi/gomega v1.34.1 h1:EUMJIKUjM8sKjYbtxQI9A4z2o+rruxnzNvpknOXie6k= -github.com/onsi/gomega v1.34.1/go.mod h1:kU1QgUvBDLXBJq618Xvm2LUX6rSAfRaFRTcdOeDLwwY= -github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4= -github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY= -github.com/pjbgf/sha1cd v0.5.0 h1:a+UkboSi1znleCDUNT3M5YxjOnN1fz2FhN48FlwCxs0= -github.com/pjbgf/sha1cd v0.5.0/go.mod h1:lhpGlyHLpQZoxMv8HcgXvZEhcGs0PG/vsZnEJ7H0iCM= -github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmdv1U2eRNDiU2ErMBj1gwrq8eQ= -github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c/go.mod h1:7rwL4CYBLnjLxUqIJNnCWiEdr3bn6IUYi15bNlnbCCU= -github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= -github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= -github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/quic-go/qpack v0.6.0 h1:g7W+BMYynC1LbYLSqRt8PBg5Tgwxn214ZZR34VIOjz8= -github.com/quic-go/qpack v0.6.0/go.mod h1:lUpLKChi8njB4ty2bFLX2x4gzDqXwUpaO1DP9qMDZII= -github.com/quic-go/quic-go v0.59.0 h1:OLJkp1Mlm/aS7dpKgTc6cnpynnD2Xg7C1pwL6vy/SAw= -github.com/quic-go/quic-go v0.59.0/go.mod h1:upnsH4Ju1YkqpLXC305eW3yDZ4NfnNbmQRCMWS58IKU= -github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= -github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= -github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= -github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= -github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= -github.com/samber/lo v1.52.0 h1:Rvi+3BFHES3A8meP33VPAxiBZX/Aws5RxrschYGjomw= -github.com/samber/lo v1.52.0/go.mod h1:4+MXEGsJzbKGaUEQFKBq2xtfuznW9oz/WrgyzMzRoM0= -github.com/sergi/go-diff v1.4.0 h1:n/SP9D5ad1fORl+llWyN+D6qoUETXNZARKjyY2/KVCw= -github.com/sergi/go-diff v1.4.0/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4= -github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= -github.com/skeema/knownhosts v1.3.2 h1:EDL9mgf4NzwMXCTfaxSD/o/a5fxDw/xL9nkU28JjdBg= -github.com/skeema/knownhosts v1.3.2/go.mod h1:bEg3iQAuw+jyiw+484wwFJoKSLwcfd7fqRy+N0QTiow= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= -github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= -github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= -github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= -github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= -github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= -github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= -github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI= -github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= -github.com/ugorji/go/codec v1.3.1 h1:waO7eEiFDwidsBN6agj1vJQ4AG7lh2yqXyOXqhgQuyY= -github.com/ugorji/go/codec v1.3.1/go.mod h1:pRBVtBSKl77K30Bv8R2P+cLSGaTtex6fsA2Wjqmfxj4= -github.com/wailsapp/go-webview2 v1.0.23 h1:jmv8qhz1lHibCc79bMM/a/FqOnnzOGEisLav+a0b9P0= -github.com/wailsapp/go-webview2 v1.0.23/go.mod h1:qJmWAmAmaniuKGZPWwne+uor3AHMB5PFhqiK0Bbj8kc= -github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM= -github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw= -go.uber.org/mock v0.6.0 h1:hyF9dfmbgIX5EfOdasqLsWD6xqpNZlXblLB/Dbnwv3Y= -go.uber.org/mock v0.6.0/go.mod h1:KiVJ4BqZJaMj4svdfmHM0AUx4NJYO8ZNpPnZn1Z+BBU= -golang.org/x/arch v0.23.0 h1:lKF64A2jF6Zd8L0knGltUnegD62JMFBiCPBmQpToHhg= -golang.org/x/arch v0.23.0/go.mod h1:dNHoOeKiyja7GTvF9NJS1l3Z2yntpQNzgrjh1cU103A= -golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.47.0 h1:V6e3FRj+n4dbpw86FJ8Fv7XVOql7TEwpHapKoMJ/GO8= -golang.org/x/crypto v0.47.0/go.mod h1:ff3Y9VzzKbwSSEzWqJsJVBnWmRwRSHt/6Op5n9bQc4A= -golang.org/x/exp v0.0.0-20260112195511-716be5621a96 h1:Z/6YuSHTLOHfNFdb8zVZomZr7cqNgTJvA8+Qz75D8gU= -golang.org/x/exp v0.0.0-20260112195511-716be5621a96/go.mod h1:nzimsREAkjBCIEFtHiYkrJyT+2uy9YZJB7H1k68CXZU= -golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.49.0 h1:eeHFmOGUTtaaPSGNmjBKpbng9MulQsJURQUAfUwY++o= -golang.org/x/net v0.49.0/go.mod h1:/ysNB2EvaqvesRkuLAyjI1ycPZlQHM3q01F02UY/MV8= -golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200810151505-1b9f1253b3ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.40.0 h1:DBZZqJ2Rkml6QMQsZywtnjnnGvHza6BTfYFWY9kjEWQ= -golang.org/x/sys v0.40.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= -golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.39.0 h1:RclSuaJf32jOqZz74CkPA9qFuVTX7vhLlpfj/IGWlqY= -golang.org/x/term v0.39.0/go.mod h1:yxzUCTP/U+FzoxfdKmLaA0RV1WgE0VY7hXBwKtY/4ww= -golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.33.0 h1:B3njUFyqtHDUI5jMn1YIr5B0IE2U0qck04r6d4KPAxE= -golang.org/x/text v0.33.0/go.mod h1:LuMebE6+rBincTi9+xWTY8TztLzKHc/9C1uBCG27+q8= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE= -google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= -gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME= -gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= -gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= -gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/v3/examples/gin-routing/main.go b/v3/examples/gin-routing/main.go deleted file mode 100644 index a78494808..000000000 --- a/v3/examples/gin-routing/main.go +++ /dev/null @@ -1,114 +0,0 @@ -package main - -import ( - "embed" - "log" - "net/http" - "strings" - "time" - - "github.com/gin-gonic/gin" - "github.com/wailsapp/wails/v3/pkg/application" -) - -//go:embed static -var staticFiles embed.FS - -// GinMiddleware creates a middleware that passes requests to Gin if they're not handled by Wails -func GinMiddleware(ginEngine *gin.Engine) application.Middleware { - return func(next http.Handler) http.Handler { - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - // Let Wails handle the `/wails` route - if strings.HasPrefix(r.URL.Path, "/wails") { - next.ServeHTTP(w, r) - return - } - // Let Gin handle everything else - ginEngine.ServeHTTP(w, r) - }) - } -} - -// LoggingMiddleware is a Gin middleware that logs request details -func LoggingMiddleware() gin.HandlerFunc { - return func(c *gin.Context) { - // Start timer - startTime := time.Now() - - // Process request - c.Next() - - // Calculate latency - latency := time.Since(startTime) - - // Log request details - log.Printf("[GIN] %s | %s | %s | %d | %s", - c.Request.Method, - c.Request.URL.Path, - c.ClientIP(), - c.Writer.Status(), - latency, - ) - } -} - -func main() { - // Create a new Gin router - ginEngine := gin.New() // Using New() instead of Default() to add our own middleware - - // Add middlewares - ginEngine.Use(gin.Recovery()) - ginEngine.Use(LoggingMiddleware()) - - // Serve embedded static files - ginEngine.StaticFS("/static", http.FS(staticFiles)) - - // Define routes - ginEngine.GET("/", func(c *gin.Context) { - file, err := staticFiles.ReadFile("static/index.html") - if err != nil { - c.String(http.StatusInternalServerError, "Error reading index.html") - return - } - c.Data(http.StatusOK, "text/html; charset=utf-8", file) - }) - - ginEngine.GET("/api/hello", func(c *gin.Context) { - c.JSON(http.StatusOK, gin.H{ - "message": "Hello from Gin API!", - "time": time.Now().Format(time.RFC3339), - }) - }) - - // Create a new Wails application - app := application.New(application.Options{ - Name: "Gin Example", - Description: "A demo of using Gin with Wails", - Mac: application.MacOptions{ - ApplicationShouldTerminateAfterLastWindowClosed: true, - }, - Assets: application.AssetOptions{ - Handler: ginEngine, - Middleware: GinMiddleware(ginEngine), - }, - }) - - // Register event handler - app.Event.On("gin-button-clicked", func(event *application.CustomEvent) { - log.Printf("Received event from frontend: %v", event.Data) - }) - - // Create window - app.Window.NewWithOptions(application.WebviewWindowOptions{ - Title: "Wails + Gin Example", - Width: 900, - Height: 700, - URL: "/", - }) - - // Run the app - err := app.Run() - if err != nil { - log.Fatal(err) - } -} diff --git a/v3/examples/gin-routing/static/index.html b/v3/examples/gin-routing/static/index.html deleted file mode 100644 index aefbd7a28..000000000 --- a/v3/examples/gin-routing/static/index.html +++ /dev/null @@ -1,94 +0,0 @@ - - - Wails + Gin Example - - - -
            -

            Wails + Gin Integration

            -
            -

            Hello World!

            -

            This page is being served by Gin.

            -

            Click the button below to trigger a Wails event:

            - - -
            -
            -

            API Example

            -

            Try the Gin API endpoint:

            - -
            -
            -
            - - - diff --git a/v3/examples/gin-service/README.md b/v3/examples/gin-service/README.md deleted file mode 100644 index 89e5019d7..000000000 --- a/v3/examples/gin-service/README.md +++ /dev/null @@ -1,21 +0,0 @@ -# Gin Service Example - -This example demonstrates how to use the [Gin web framework](https://github.com/gin-gonic/gin) in a Wails Service. - -## Overview - -This example shows how to: - -- Set up Gin as the asset handler for a Wails application -- Create a middleware that routes requests between Wails and Gin -- Define API endpoints with Gin -- Communicate between the Gin-served frontend and Wails backend -- Implement custom Gin middleware - -## Running the Example - - -## Documentation - -Please consult the [Using Gin for Routing](https://v3.wails.io/guides/gin-routing/) guide for a detailed explanation of the example. - diff --git a/v3/examples/gin-service/assets/index.html b/v3/examples/gin-service/assets/index.html deleted file mode 100644 index 66aea00eb..000000000 --- a/v3/examples/gin-service/assets/index.html +++ /dev/null @@ -1,249 +0,0 @@ - - - - - - Gin Service Example - - - -

            Gin Service Example

            - -
            -

            API Endpoints

            -

            Try the Gin API endpoints mounted at /api:

            - - - - - - - -
            -
            Results will appear here...
            -
            -
            - -
            -

            Event Communication

            -

            Trigger an event to communicate with the Gin service:

            - - - -
            -
            Event responses will appear here...
            -
            -
            - - - - - - diff --git a/v3/examples/gin-service/go.mod b/v3/examples/gin-service/go.mod deleted file mode 100644 index 5b46f88af..000000000 --- a/v3/examples/gin-service/go.mod +++ /dev/null @@ -1,74 +0,0 @@ -module gin-service - -go 1.25 - -require ( - github.com/gin-gonic/gin v1.11.0 - github.com/wailsapp/wails/v3 v3.0.0-alpha.62 -) - -require ( - dario.cat/mergo v1.0.2 // indirect - github.com/Microsoft/go-winio v0.6.2 // indirect - github.com/ProtonMail/go-crypto v1.3.0 // indirect - github.com/adrg/xdg v0.5.3 // indirect - github.com/bep/debounce v1.2.1 // indirect - github.com/bytedance/gopkg v0.1.3 // indirect - github.com/bytedance/sonic v1.15.0 // indirect - github.com/bytedance/sonic/loader v0.5.0 // indirect - github.com/cloudflare/circl v1.6.3 // indirect - github.com/cloudwego/base64x v0.1.6 // indirect - github.com/cyphar/filepath-securejoin v0.6.1 // indirect - github.com/ebitengine/purego v0.9.1 // indirect - github.com/emirpasic/gods v1.18.1 // indirect - github.com/gabriel-vasile/mimetype v1.4.12 // indirect - github.com/gin-contrib/sse v1.1.0 // indirect - github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect - github.com/go-git/go-billy/v5 v5.7.0 // indirect - github.com/go-git/go-git/v5 v5.16.4 // indirect - github.com/go-ole/go-ole v1.3.0 // indirect - github.com/go-playground/locales v0.14.1 // indirect - github.com/go-playground/universal-translator v0.18.1 // indirect - github.com/go-playground/validator/v10 v10.30.1 // indirect - github.com/goccy/go-json v0.10.5 // indirect - github.com/goccy/go-yaml v1.19.2 // indirect - github.com/godbus/dbus/v5 v5.2.2 // indirect - github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect - github.com/google/uuid v1.6.0 // indirect - github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect - github.com/jchv/go-winloader v0.0.0-20250406163304-c1995be93bd1 // indirect - github.com/json-iterator/go v1.1.12 // indirect - github.com/kevinburke/ssh_config v1.4.0 // indirect - github.com/klauspost/cpuid/v2 v2.3.0 // indirect - github.com/leaanthony/go-ansi-parser v1.6.1 // indirect - github.com/leaanthony/u v1.1.1 // indirect - github.com/leodido/go-urn v1.4.0 // indirect - github.com/lmittmann/tint v1.1.2 // indirect - github.com/mattn/go-colorable v0.1.14 // indirect - github.com/mattn/go-isatty v0.0.20 // indirect - github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect - github.com/modern-go/reflect2 v1.0.2 // indirect - github.com/pelletier/go-toml/v2 v2.2.4 // indirect - github.com/pjbgf/sha1cd v0.5.0 // indirect - github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c // indirect - github.com/quic-go/qpack v0.6.0 // indirect - github.com/quic-go/quic-go v0.59.0 // indirect - github.com/rivo/uniseg v0.4.7 // indirect - github.com/samber/lo v1.52.0 // indirect - github.com/sergi/go-diff v1.4.0 // indirect - github.com/skeema/knownhosts v1.3.2 // indirect - github.com/twitchyliquid64/golang-asm v0.15.1 // indirect - github.com/ugorji/go/codec v1.3.1 // indirect - github.com/wailsapp/go-webview2 v1.0.23 // indirect - github.com/xanzy/ssh-agent v0.3.3 // indirect - go.uber.org/mock v0.6.0 // indirect - golang.org/x/arch v0.23.0 // indirect - golang.org/x/crypto v0.47.0 // indirect - golang.org/x/net v0.49.0 // indirect - golang.org/x/sys v0.40.0 // indirect - golang.org/x/text v0.33.0 // indirect - google.golang.org/protobuf v1.36.11 // indirect - gopkg.in/warnings.v0 v0.1.2 // indirect -) - -replace github.com/wailsapp/wails/v3 => ../.. diff --git a/v3/examples/gin-service/go.sum b/v3/examples/gin-service/go.sum deleted file mode 100644 index 07a22c6eb..000000000 --- a/v3/examples/gin-service/go.sum +++ /dev/null @@ -1,208 +0,0 @@ -dario.cat/mergo v1.0.2 h1:85+piFYR1tMbRrLcDwR18y4UKJ3aH1Tbzi24VRW1TK8= -dario.cat/mergo v1.0.2/go.mod h1:E/hbnu0NxMFBjpMIE34DRGLWqDy0g5FuKDhCb31ngxA= -github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY= -github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= -github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= -github.com/ProtonMail/go-crypto v1.3.0 h1:ILq8+Sf5If5DCpHQp4PbZdS1J7HDFRXz/+xKBiRGFrw= -github.com/ProtonMail/go-crypto v1.3.0/go.mod h1:9whxjD8Rbs29b4XWbB8irEcE8KHMqaR2e7GWU1R+/PE= -github.com/adrg/xdg v0.5.3 h1:xRnxJXne7+oWDatRhR1JLnvuccuIeCoBu2rtuLqQB78= -github.com/adrg/xdg v0.5.3/go.mod h1:nlTsY+NNiCBGCK2tpm09vRqfVzrc2fLmXGpBLF0zlTQ= -github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8= -github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4= -github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= -github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= -github.com/bep/debounce v1.2.1 h1:v67fRdBA9UQu2NhLFXrSg0Brw7CexQekrBwDMM8bzeY= -github.com/bep/debounce v1.2.1/go.mod h1:H8yggRPQKLUhUoqrJC1bO2xNya7vanpDl7xR3ISbCJ0= -github.com/bytedance/gopkg v0.1.3 h1:TPBSwH8RsouGCBcMBktLt1AymVo2TVsBVCY4b6TnZ/M= -github.com/bytedance/gopkg v0.1.3/go.mod h1:576VvJ+eJgyCzdjS+c4+77QF3p7ubbtiKARP3TxducM= -github.com/bytedance/sonic v1.15.0 h1:/PXeWFaR5ElNcVE84U0dOHjiMHQOwNIx3K4ymzh/uSE= -github.com/bytedance/sonic v1.15.0/go.mod h1:tFkWrPz0/CUCLEF4ri4UkHekCIcdnkqXw9VduqpJh0k= -github.com/bytedance/sonic/loader v0.5.0 h1:gXH3KVnatgY7loH5/TkeVyXPfESoqSBSBEiDd5VjlgE= -github.com/bytedance/sonic/loader v0.5.0/go.mod h1:AR4NYCk5DdzZizZ5djGqQ92eEhCCcdf5x77udYiSJRo= -github.com/cloudflare/circl v1.6.3 h1:9GPOhQGF9MCYUeXyMYlqTR6a5gTrgR/fBLXvUgtVcg8= -github.com/cloudflare/circl v1.6.3/go.mod h1:2eXP6Qfat4O/Yhh8BznvKnJ+uzEoTQ6jVKJRn81BiS4= -github.com/cloudwego/base64x v0.1.6 h1:t11wG9AECkCDk5fMSoxmufanudBtJ+/HemLstXDLI2M= -github.com/cloudwego/base64x v0.1.6/go.mod h1:OFcloc187FXDaYHvrNIjxSe8ncn0OOM8gEHfghB2IPU= -github.com/cyphar/filepath-securejoin v0.6.1 h1:5CeZ1jPXEiYt3+Z6zqprSAgSWiggmpVyciv8syjIpVE= -github.com/cyphar/filepath-securejoin v0.6.1/go.mod h1:A8hd4EnAeyujCJRrICiOWqjS1AX0a9kM5XL+NwKoYSc= -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= -github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/ebitengine/purego v0.9.1 h1:a/k2f2HQU3Pi399RPW1MOaZyhKJL9w/xFpKAg4q1s0A= -github.com/ebitengine/purego v0.9.1/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ= -github.com/elazarl/goproxy v1.7.2 h1:Y2o6urb7Eule09PjlhQRGNsqRfPmYI3KKQLFpCAV3+o= -github.com/elazarl/goproxy v1.7.2/go.mod h1:82vkLNir0ALaW14Rc399OTTjyNREgmdL2cVoIbS6XaE= -github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc= -github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ= -github.com/gabriel-vasile/mimetype v1.4.12 h1:e9hWvmLYvtp846tLHam2o++qitpguFiYCKbn0w9jyqw= -github.com/gabriel-vasile/mimetype v1.4.12/go.mod h1:d+9Oxyo1wTzWdyVUPMmXFvp4F9tea18J8ufA774AB3s= -github.com/gin-contrib/sse v1.1.0 h1:n0w2GMuUpWDVp7qSpvze6fAu9iRxJY4Hmj6AmBOU05w= -github.com/gin-contrib/sse v1.1.0/go.mod h1:hxRZ5gVpWMT7Z0B0gSNYqqsSCNIJMjzvm6fqCz9vjwM= -github.com/gin-gonic/gin v1.11.0 h1:OW/6PLjyusp2PPXtyxKHU0RbX6I/l28FTdDlae5ueWk= -github.com/gin-gonic/gin v1.11.0/go.mod h1:+iq/FyxlGzII0KHiBGjuNn4UNENUlKbGlNmc+W50Dls= -github.com/gliderlabs/ssh v0.3.8 h1:a4YXD1V7xMF9g5nTkdfnja3Sxy1PVDCj1Zg4Wb8vY6c= -github.com/gliderlabs/ssh v0.3.8/go.mod h1:xYoytBv1sV0aL3CavoDuJIQNURXkkfPA/wxQ1pL1fAU= -github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI= -github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmSxCcxctByoQdvwPiA7DTK7jaaFDBTtu0ic= -github.com/go-git/go-billy/v5 v5.7.0 h1:83lBUJhGWhYp0ngzCMSgllhUSuoHP1iEWYjsPl9nwqM= -github.com/go-git/go-billy/v5 v5.7.0/go.mod h1:/1IUejTKH8xipsAcdfcSAlUlo2J7lkYV8GTKxAT/L3E= -github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399 h1:eMje31YglSBqCdIqdhKBW8lokaMrL3uTkpGYlE2OOT4= -github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399/go.mod h1:1OCfN199q1Jm3HZlxleg+Dw/mwps2Wbk9frAWm+4FII= -github.com/go-git/go-git/v5 v5.16.4 h1:7ajIEZHZJULcyJebDLo99bGgS0jRrOxzZG4uCk2Yb2Y= -github.com/go-git/go-git/v5 v5.16.4/go.mod h1:4Ge4alE/5gPs30F2H1esi2gPd69R0C39lolkucHBOp8= -github.com/go-json-experiment/json v0.0.0-20251027170946-4849db3c2f7e h1:Lf/gRkoycfOBPa42vU2bbgPurFong6zXeFtPoxholzU= -github.com/go-json-experiment/json v0.0.0-20251027170946-4849db3c2f7e/go.mod h1:uNVvRXArCGbZ508SxYYTC5v1JWoz2voff5pm25jU1Ok= -github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE= -github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78= -github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= -github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= -github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= -github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= -github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= -github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= -github.com/go-playground/validator/v10 v10.30.1 h1:f3zDSN/zOma+w6+1Wswgd9fLkdwy06ntQJp0BBvFG0w= -github.com/go-playground/validator/v10 v10.30.1/go.mod h1:oSuBIQzuJxL//3MelwSLD5hc2Tu889bF0Idm9Dg26cM= -github.com/goccy/go-json v0.10.5 h1:Fq85nIqj+gXn/S5ahsiTlK3TmC85qgirsdTP/+DeaC4= -github.com/goccy/go-json v0.10.5/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M= -github.com/goccy/go-yaml v1.19.2 h1:PmFC1S6h8ljIz6gMRBopkjP1TVT7xuwrButHID66PoM= -github.com/goccy/go-yaml v1.19.2/go.mod h1:XBurs7gK8ATbW4ZPGKgcbrY1Br56PdM69F7LkFRi1kA= -github.com/godbus/dbus/v5 v5.2.2 h1:TUR3TgtSVDmjiXOgAAyaZbYmIeP3DPkld3jgKGV8mXQ= -github.com/godbus/dbus/v5 v5.2.2/go.mod h1:3AAv2+hPq5rdnr5txxxRwiGjPXamgoIHgz9FPBfOp3c= -github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 h1:f+oWsMOmNPc8JmEHVZIycC7hBoQxHH9pNKQORJNozsQ= -github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8/go.mod h1:wcDNUvekVysuuOpQKo3191zZyTpiI6se1N1ULghS0sw= -github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= -github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= -github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= -github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A= -github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= -github.com/jchv/go-winloader v0.0.0-20250406163304-c1995be93bd1 h1:njuLRcjAuMKr7kI3D85AXWkw6/+v9PwtV6M6o11sWHQ= -github.com/jchv/go-winloader v0.0.0-20250406163304-c1995be93bd1/go.mod h1:alcuEEnZsY1WQsagKhZDsoPCRoOijYqhZvPwLG0kzVs= -github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= -github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= -github.com/kevinburke/ssh_config v1.4.0 h1:6xxtP5bZ2E4NF5tuQulISpTO2z8XbtH8cg1PWkxoFkQ= -github.com/kevinburke/ssh_config v1.4.0/go.mod h1:q2RIzfka+BXARoNexmF9gkxEX7DmvbW9P4hIVx2Kg4M= -github.com/klauspost/cpuid/v2 v2.3.0 h1:S4CRMLnYUhGeDFDqkGriYKdfoFlDnMtqTiI/sFzhA9Y= -github.com/klauspost/cpuid/v2 v2.3.0/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0= -github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= -github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= -github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= -github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= -github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/leaanthony/go-ansi-parser v1.6.1 h1:xd8bzARK3dErqkPFtoF9F3/HgN8UQk0ed1YDKpEz01A= -github.com/leaanthony/go-ansi-parser v1.6.1/go.mod h1:+vva/2y4alzVmmIEpk9QDhA7vLC5zKDTRwfZGOp3IWU= -github.com/leaanthony/u v1.1.1 h1:TUFjwDGlNX+WuwVEzDqQwC2lOv0P4uhTQw7CMFdiK7M= -github.com/leaanthony/u v1.1.1/go.mod h1:9+o6hejoRljvZ3BzdYlVL0JYCwtnAsVuN9pVTQcaRfI= -github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ= -github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI= -github.com/lmittmann/tint v1.1.2 h1:2CQzrL6rslrsyjqLDwD11bZ5OpLBPU+g3G/r5LSfS8w= -github.com/lmittmann/tint v1.1.2/go.mod h1:HIS3gSy7qNwGCj+5oRjAutErFBl4BzdQP6cJZ0NfMwE= -github.com/matryer/is v1.4.0/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwMRU= -github.com/matryer/is v1.4.1 h1:55ehd8zaGABKLXQUe2awZ99BD/PTc2ls+KV/dXphgEQ= -github.com/matryer/is v1.4.1/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwMRU= -github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE= -github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8= -github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= -github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= -github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= -github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= -github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= -github.com/onsi/gomega v1.34.1 h1:EUMJIKUjM8sKjYbtxQI9A4z2o+rruxnzNvpknOXie6k= -github.com/onsi/gomega v1.34.1/go.mod h1:kU1QgUvBDLXBJq618Xvm2LUX6rSAfRaFRTcdOeDLwwY= -github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4= -github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY= -github.com/pjbgf/sha1cd v0.5.0 h1:a+UkboSi1znleCDUNT3M5YxjOnN1fz2FhN48FlwCxs0= -github.com/pjbgf/sha1cd v0.5.0/go.mod h1:lhpGlyHLpQZoxMv8HcgXvZEhcGs0PG/vsZnEJ7H0iCM= -github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmdv1U2eRNDiU2ErMBj1gwrq8eQ= -github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c/go.mod h1:7rwL4CYBLnjLxUqIJNnCWiEdr3bn6IUYi15bNlnbCCU= -github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= -github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= -github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/quic-go/qpack v0.6.0 h1:g7W+BMYynC1LbYLSqRt8PBg5Tgwxn214ZZR34VIOjz8= -github.com/quic-go/qpack v0.6.0/go.mod h1:lUpLKChi8njB4ty2bFLX2x4gzDqXwUpaO1DP9qMDZII= -github.com/quic-go/quic-go v0.59.0 h1:OLJkp1Mlm/aS7dpKgTc6cnpynnD2Xg7C1pwL6vy/SAw= -github.com/quic-go/quic-go v0.59.0/go.mod h1:upnsH4Ju1YkqpLXC305eW3yDZ4NfnNbmQRCMWS58IKU= -github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= -github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= -github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= -github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= -github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= -github.com/samber/lo v1.52.0 h1:Rvi+3BFHES3A8meP33VPAxiBZX/Aws5RxrschYGjomw= -github.com/samber/lo v1.52.0/go.mod h1:4+MXEGsJzbKGaUEQFKBq2xtfuznW9oz/WrgyzMzRoM0= -github.com/sergi/go-diff v1.4.0 h1:n/SP9D5ad1fORl+llWyN+D6qoUETXNZARKjyY2/KVCw= -github.com/sergi/go-diff v1.4.0/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4= -github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= -github.com/skeema/knownhosts v1.3.2 h1:EDL9mgf4NzwMXCTfaxSD/o/a5fxDw/xL9nkU28JjdBg= -github.com/skeema/knownhosts v1.3.2/go.mod h1:bEg3iQAuw+jyiw+484wwFJoKSLwcfd7fqRy+N0QTiow= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= -github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= -github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= -github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= -github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= -github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= -github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= -github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= -github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= -github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= -github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI= -github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= -github.com/ugorji/go/codec v1.3.1 h1:waO7eEiFDwidsBN6agj1vJQ4AG7lh2yqXyOXqhgQuyY= -github.com/ugorji/go/codec v1.3.1/go.mod h1:pRBVtBSKl77K30Bv8R2P+cLSGaTtex6fsA2Wjqmfxj4= -github.com/wailsapp/go-webview2 v1.0.23 h1:jmv8qhz1lHibCc79bMM/a/FqOnnzOGEisLav+a0b9P0= -github.com/wailsapp/go-webview2 v1.0.23/go.mod h1:qJmWAmAmaniuKGZPWwne+uor3AHMB5PFhqiK0Bbj8kc= -github.com/wailsapp/wails/v3 v3.0.0-alpha.62 h1:ihEh+skkAt26PcVCil1xWbhPQIfl7Kkh0g64u8gBTe0= -github.com/wailsapp/wails/v3 v3.0.0-alpha.62/go.mod h1:ynGPamjQDXoaWjOGKAHJ6vw94PUDbeIxtbapunWcDjk= -github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM= -github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw= -go.uber.org/mock v0.6.0 h1:hyF9dfmbgIX5EfOdasqLsWD6xqpNZlXblLB/Dbnwv3Y= -go.uber.org/mock v0.6.0/go.mod h1:KiVJ4BqZJaMj4svdfmHM0AUx4NJYO8ZNpPnZn1Z+BBU= -golang.org/x/arch v0.23.0 h1:lKF64A2jF6Zd8L0knGltUnegD62JMFBiCPBmQpToHhg= -golang.org/x/arch v0.23.0/go.mod h1:dNHoOeKiyja7GTvF9NJS1l3Z2yntpQNzgrjh1cU103A= -golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.47.0 h1:V6e3FRj+n4dbpw86FJ8Fv7XVOql7TEwpHapKoMJ/GO8= -golang.org/x/crypto v0.47.0/go.mod h1:ff3Y9VzzKbwSSEzWqJsJVBnWmRwRSHt/6Op5n9bQc4A= -golang.org/x/exp v0.0.0-20250210185358-939b2ce775ac h1:l5+whBCLH3iH2ZNHYLbAe58bo7yrN4mVcnkHDYz5vvs= -golang.org/x/exp v0.0.0-20250210185358-939b2ce775ac/go.mod h1:hH+7mtFmImwwcMvScyxUhjuVHR3HGaDPMn9rMSUUbxo= -golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.49.0 h1:eeHFmOGUTtaaPSGNmjBKpbng9MulQsJURQUAfUwY++o= -golang.org/x/net v0.49.0/go.mod h1:/ysNB2EvaqvesRkuLAyjI1ycPZlQHM3q01F02UY/MV8= -golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200810151505-1b9f1253b3ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.40.0 h1:DBZZqJ2Rkml6QMQsZywtnjnnGvHza6BTfYFWY9kjEWQ= -golang.org/x/sys v0.40.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= -golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.39.0 h1:RclSuaJf32jOqZz74CkPA9qFuVTX7vhLlpfj/IGWlqY= -golang.org/x/term v0.39.0/go.mod h1:yxzUCTP/U+FzoxfdKmLaA0RV1WgE0VY7hXBwKtY/4ww= -golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.33.0 h1:B3njUFyqtHDUI5jMn1YIr5B0IE2U0qck04r6d4KPAxE= -golang.org/x/text v0.33.0/go.mod h1:LuMebE6+rBincTi9+xWTY8TztLzKHc/9C1uBCG27+q8= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -google.golang.org/protobuf v1.36.11 h1:fV6ZwhNocDyBLK0dj+fg8ektcVegBBuEolpbTQyBNVE= -google.golang.org/protobuf v1.36.11/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= -gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME= -gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= -gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= -gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/v3/examples/gin-service/main.go b/v3/examples/gin-service/main.go deleted file mode 100644 index f27fef415..000000000 --- a/v3/examples/gin-service/main.go +++ /dev/null @@ -1,45 +0,0 @@ -package main - -import ( - "embed" - "log/slog" - "os" - - "gin-service/services" - "github.com/wailsapp/wails/v3/pkg/application" -) - -//go:embed assets/* -var assets embed.FS - -func main() { - app := application.New(application.Options{ - Name: "Gin Service Demo", - Description: "A demo of using Gin in Wails services", - Mac: application.MacOptions{ - ApplicationShouldTerminateAfterLastWindowClosed: true, - }, - LogLevel: slog.LevelDebug, - Services: []application.Service{ - application.NewServiceWithOptions(services.NewGinService(), application.ServiceOptions{ - Route: "/api", - }), - }, - Assets: application.AssetOptions{ - Handler: application.BundledAssetFileServer(assets), - }, - }) - - app.Window.NewWithOptions(application.WebviewWindowOptions{ - Title: "Gin Service Demo", - Width: 1024, - Height: 768, - }) - - err := app.Run() - - if err != nil { - println(err.Error()) - os.Exit(1) - } -} diff --git a/v3/examples/gin-service/services/gin_service.go b/v3/examples/gin-service/services/gin_service.go deleted file mode 100644 index e0fa290ec..000000000 --- a/v3/examples/gin-service/services/gin_service.go +++ /dev/null @@ -1,250 +0,0 @@ -package services - -import ( - "context" - "net/http" - "strconv" - "strings" - "sync" - "time" - - "github.com/gin-gonic/gin" - "github.com/wailsapp/wails/v3/pkg/application" -) - -// User represents a user in the system -type User struct { - ID int `json:"id"` - Name string `json:"name"` - Email string `json:"email"` - CreatedAt time.Time `json:"createdAt"` -} - -// GinService implements a Wails service that uses Gin for HTTP handling -type GinService struct { - ginEngine *gin.Engine - users []User - nextID int - mu sync.RWMutex - app *application.App - maxUsers int // Maximum number of users to prevent unbounded growth - removeEventHandler func() // Store cleanup function for event handler -} - -type EventData struct { - Message string `json:"message"` - Timestamp string `json:"timestamp"` -} - -// NewGinService creates a new GinService instance -func NewGinService() *GinService { - // Create a new Gin router - ginEngine := gin.New() - - // Add middlewares - ginEngine.Use(gin.Recovery()) - ginEngine.Use(LoggingMiddleware()) - - service := &GinService{ - ginEngine: ginEngine, - users: []User{ - {ID: 1, Name: "Alice", Email: "alice@example.com", CreatedAt: time.Now().Add(-72 * time.Hour)}, - {ID: 2, Name: "Bob", Email: "bob@example.com", CreatedAt: time.Now().Add(-48 * time.Hour)}, - {ID: 3, Name: "Charlie", Email: "charlie@example.com", CreatedAt: time.Now().Add(-24 * time.Hour)}, - }, - nextID: 4, - maxUsers: 1000, // Limit to prevent unbounded slice growth - } - - // Define routes - service.setupRoutes() - - return service -} - -// ServiceName returns the name of the service -func (s *GinService) ServiceName() string { - return "Gin API Service" -} - -// ServiceStartup is called when the service starts -func (s *GinService) ServiceStartup(ctx context.Context, options application.ServiceOptions) error { - // You can access the application instance via ctx - s.app = application.Get() - - // Register an event handler that can be triggered from the frontend - // Store the cleanup function for proper resource management - s.removeEventHandler = s.app.Event.On("gin-api-event", func(event *application.CustomEvent) { - // Log the event data - // Parse the event data - s.app.Logger.Info("Received event from frontend", "data", event.Data) - - // You could also emit an event back to the frontend - s.app.Event.Emit("gin-api-response", map[string]interface{}{ - "message": "Response from Gin API Service", - "time": time.Now().Format(time.RFC3339), - }) - }) - - return nil -} - -// ServiceShutdown is called when the service shuts down -func (s *GinService) ServiceShutdown(ctx context.Context) error { - // Clean up event handler to prevent memory leaks - if s.removeEventHandler != nil { - s.removeEventHandler() - } - return nil -} - -// ServeHTTP implements the http.Handler interface -func (s *GinService) ServeHTTP(w http.ResponseWriter, r *http.Request) { - // All other requests go to the Gin router - s.ginEngine.ServeHTTP(w, r) -} - -// setupRoutes configures the API routes -func (s *GinService) setupRoutes() { - // Basic info endpoint - s.ginEngine.GET("/info", func(c *gin.Context) { - c.JSON(http.StatusOK, gin.H{ - "service": "Gin API Service", - "version": "1.0.0", - "time": time.Now().Format(time.RFC3339), - }) - }) - - // Users group - users := s.ginEngine.Group("/users") - { - // Get all users - users.GET("", func(c *gin.Context) { - s.mu.RLock() - defer s.mu.RUnlock() - c.JSON(http.StatusOK, s.users) - }) - - // Get user by ID - users.GET("/:id", func(c *gin.Context) { - id, err := strconv.Atoi(c.Param("id")) - if err != nil { - c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid user ID"}) - return - } - - s.mu.RLock() - defer s.mu.RUnlock() - - for _, user := range s.users { - if user.ID == id { - c.JSON(http.StatusOK, user) - return - } - } - - c.JSON(http.StatusNotFound, gin.H{"error": "User not found"}) - }) - - // Create a new user - users.POST("", func(c *gin.Context) { - var newUser User - if err := c.ShouldBindJSON(&newUser); err != nil { - c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) - return - } - - // Validate required fields - if newUser.Name == "" { - c.JSON(http.StatusBadRequest, gin.H{"error": "Name is required"}) - return - } - if newUser.Email == "" { - c.JSON(http.StatusBadRequest, gin.H{"error": "Email is required"}) - return - } - // Basic email validation (consider using a proper validator library in production) - if !strings.Contains(newUser.Email, "@") { - c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid email format"}) - return - } - - s.mu.Lock() - defer s.mu.Unlock() - - // Check if we've reached the maximum number of users - if len(s.users) >= s.maxUsers { - c.JSON(http.StatusServiceUnavailable, gin.H{"error": "Maximum number of users reached"}) - return - } - - // Set the ID and creation time - newUser.ID = s.nextID - newUser.CreatedAt = time.Now() - s.nextID++ - - // Add to the users slice - s.users = append(s.users, newUser) - - c.JSON(http.StatusCreated, newUser) - - // Emit an event to notify about the new user - s.app.Event.Emit("user-created", newUser) - }) - - // Delete a user - users.DELETE("/:id", func(c *gin.Context) { - id, err := strconv.Atoi(c.Param("id")) - if err != nil { - c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid user ID"}) - return - } - - s.mu.Lock() - defer s.mu.Unlock() - - for i, user := range s.users { - if user.ID == id { - // Remove the user from the slice - s.users = append(s.users[:i], s.users[i+1:]...) - c.JSON(http.StatusOK, gin.H{"message": "User deleted"}) - return - } - } - - c.JSON(http.StatusNotFound, gin.H{"error": "User not found"}) - }) - } -} - -// LoggingMiddleware is a Gin middleware that logs request details -func LoggingMiddleware() gin.HandlerFunc { - return func(c *gin.Context) { - // Start timer - start := time.Now() - - // Process request - c.Next() - - // Calculate latency - latency := time.Since(start) - - // Log request details - statusCode := c.Writer.Status() - clientIP := c.ClientIP() - method := c.Request.Method - path := c.Request.URL.Path - - // Get the application instance - app := application.Get() - if app != nil { - app.Logger.Info("HTTP Request", - "status", statusCode, - "method", method, - "path", path, - "ip", clientIP, - "latency", latency, - ) - } - } -} diff --git a/v3/examples/hide-window/main.go b/v3/examples/hide-window/main.go deleted file mode 100644 index 1a65c7498..000000000 --- a/v3/examples/hide-window/main.go +++ /dev/null @@ -1,69 +0,0 @@ -package main - -import ( - _ "embed" - "github.com/wailsapp/wails/v3/pkg/application" - "github.com/wailsapp/wails/v3/pkg/events" - "github.com/wailsapp/wails/v3/pkg/icons" - "log" - "runtime" -) - -func main() { - app := application.New(application.Options{ - Name: "Hide Window Demo", - Description: "A test of Hidden window and display it", - Assets: application.AlphaAssets, - Mac: application.MacOptions{ - ApplicationShouldTerminateAfterLastWindowClosed: false, - }, - }) - - systemTray := app.SystemTray.New() - - window := app.Window.NewWithOptions(application.WebviewWindowOptions{ - Width: 500, - Height: 800, - Frameless: false, - AlwaysOnTop: false, - Hidden: false, - DisableResize: false, - Windows: application.WindowsWindow{ - HiddenOnTaskbar: true, - }, - }) - - window.RegisterHook(events.Common.WindowClosing, func(e *application.WindowEvent) { - window.Hide() - e.Cancel() - }) - - if runtime.GOOS == "darwin" { - systemTray.SetTemplateIcon(icons.SystrayMacTemplate) - } - - // Click Dock icon tigger application show - app.Event.OnApplicationEvent(events.Mac.ApplicationShouldHandleReopen, func(event *application.ApplicationEvent) { - println("reopen") - window.Show() - }) - - myMenu := app.NewMenu() - myMenu.Add("Show").OnClick(func(ctx *application.Context) { - window.Show() - }) - - myMenu.Add("Quit").OnClick(func(ctx *application.Context) { - app.Quit() - }) - - systemTray.SetMenu(myMenu) - systemTray.OnClick(func() { - window.Show() - }) - - err := app.Run() - if err != nil { - log.Fatal(err) - } -} diff --git a/v3/examples/ignore-mouse/README.md b/v3/examples/ignore-mouse/README.md deleted file mode 100644 index 596d2c015..000000000 --- a/v3/examples/ignore-mouse/README.md +++ /dev/null @@ -1,19 +0,0 @@ -# Window Example - -This example is a demonstration of how to disable or enable mouse events. - -## Running the example - -To run the example, simply run the following command: - -```bash -go run . -``` - -# Status - -| Platform | Status | -|----------|---------| -| Mac | | -| Windows | Working | -| Linux | | diff --git a/v3/examples/ignore-mouse/main.go b/v3/examples/ignore-mouse/main.go deleted file mode 100644 index 1fc0304f2..000000000 --- a/v3/examples/ignore-mouse/main.go +++ /dev/null @@ -1,36 +0,0 @@ -package main - -import ( - "log" - - "github.com/wailsapp/wails/v3/pkg/application" -) - -func main() { - app := application.New(application.Options{ - Name: "WebviewWindow Demo", - Description: "A demo of the WebviewWindow API", - Assets: application.AlphaAssets, - Mac: application.MacOptions{ - ApplicationShouldTerminateAfterLastWindowClosed: false, - }, - }) - - window := app.Window.NewWithOptions(application.WebviewWindowOptions{ - Width: 800, - Height: 600, - Title: "Ignore Mouse Example", - URL: "https://wails.io", - IgnoreMouseEvents: false, - }) - - window.SetIgnoreMouseEvents(true) - log.Println("IgnoreMouseEvents set", window.IsIgnoreMouseEvents()) - - err := app.Run() - - if err != nil { - log.Fatal(err) - } - -} diff --git a/v3/examples/ios-poc/frontend/index.html b/v3/examples/ios-poc/frontend/index.html deleted file mode 100644 index 75070d43e..000000000 --- a/v3/examples/ios-poc/frontend/index.html +++ /dev/null @@ -1,247 +0,0 @@ - - - - - - Wails v3 iOS Demo - - - -
            -

            🚀 Wails v3 iOS

            -

            Proof of Concept Demo

            - -
            -

            1. WebView Test

            - -
            Ready to test...
            -
            - -
            -

            2. Asset Server Test

            - -
            Ready to test...
            -
            - -
            -

            3. JavaScript Bridge Test

            - -
            Ready to test...
            -
            - -
            -

            4. Go Communication Test

            - - -
            Ready to test...
            -
            - -
            -

            Test Results:

            -
            - - WebView Creation -
            -
            - - Request Interception -
            -
            - - JS Execution -
            -
            - - iOS Simulator -
            -
            - -
            -
            -
            - iOS WebView Active -
            -
            - Platform: iOS -
            -
            -
            - - - - \ No newline at end of file diff --git a/v3/examples/ios-poc/main.go b/v3/examples/ios-poc/main.go deleted file mode 100644 index 62cae636b..000000000 --- a/v3/examples/ios-poc/main.go +++ /dev/null @@ -1,43 +0,0 @@ -//go:build ios - -package main - -import ( - "embed" - "fmt" - "log" - - "github.com/wailsapp/wails/v3/pkg/application" -) - -//go:embed frontend/* -var assets embed.FS - -// App struct for binding methods -type App struct{} - -// Greet returns a greeting message -func (a *App) Greet(name string) string { - return fmt.Sprintf("Hello %s from Wails v3 on iOS!", name) -} - -func main() { - // Create application with options - app := application.New(application.Options{ - Name: "Wails iOS PoC", - Description: "Proof of concept for Wails v3 on iOS", - Assets: application.AssetOptions{ - FS: assets, - }, - Services: []application.Service{ - application.NewService(&App{}), - }, - LogLevel: application.LogLevelDebug, - }) - - // Run the application - err := app.Run() - if err != nil { - log.Fatal(err) - } -} \ No newline at end of file diff --git a/v3/examples/ios/.gitignore b/v3/examples/ios/.gitignore deleted file mode 100644 index ba8194ab6..000000000 --- a/v3/examples/ios/.gitignore +++ /dev/null @@ -1,6 +0,0 @@ -.task -bin -frontend/dist -frontend/node_modules -build/linux/appimage/build -build/windows/nsis/MicrosoftEdgeWebview2Setup.exe \ No newline at end of file diff --git a/v3/examples/ios/README.md b/v3/examples/ios/README.md deleted file mode 100644 index ad12c3f40..000000000 --- a/v3/examples/ios/README.md +++ /dev/null @@ -1,59 +0,0 @@ -# Welcome to Your New Wails3 Project! - -Congratulations on generating your Wails3 application! This README will guide you through the next steps to get your project up and running. - -## Getting Started - -1. Navigate to your project directory in the terminal. - -2. To run your application in development mode, use the following command: - - ``` - wails3 dev - ``` - - This will start your application and enable hot-reloading for both frontend and backend changes. - -3. To build your application for production, use: - - ``` - wails3 build - ``` - - This will create a production-ready executable in the `build` directory. - -## Exploring Wails3 Features - -Now that you have your project set up, it's time to explore the features that Wails3 offers: - -1. **Check out the examples**: The best way to learn is by example. Visit the `examples` directory in the `v3/examples` directory to see various sample applications. - -2. **Run an example**: To run any of the examples, navigate to the example's directory and use: - - ``` - go run . - ``` - - Note: Some examples may be under development during the alpha phase. - -3. **Explore the documentation**: Visit the [Wails3 documentation](https://v3.wails.io/) for in-depth guides and API references. - -4. **Join the community**: Have questions or want to share your progress? Join the [Wails Discord](https://discord.gg/JDdSxwjhGf) or visit the [Wails discussions on GitHub](https://github.com/wailsapp/wails/discussions). - -## Project Structure - -Take a moment to familiarize yourself with your project structure: - -- `frontend/`: Contains your frontend code (HTML, CSS, JavaScript/TypeScript) -- `main.go`: The entry point of your Go backend -- `app.go`: Define your application structure and methods here -- `wails.json`: Configuration file for your Wails project - -## Next Steps - -1. Modify the frontend in the `frontend/` directory to create your desired UI. -2. Add backend functionality in `main.go`. -3. Use `wails3 dev` to see your changes in real-time. -4. When ready, build your application with `wails3 build`. - -Happy coding with Wails3! If you encounter any issues or have questions, don't hesitate to consult the documentation or reach out to the Wails community. diff --git a/v3/examples/ios/Taskfile.yml b/v3/examples/ios/Taskfile.yml deleted file mode 100644 index e198e184f..000000000 --- a/v3/examples/ios/Taskfile.yml +++ /dev/null @@ -1,34 +0,0 @@ -version: '3' - -includes: - common: ./build/Taskfile.yml - windows: ./build/windows/Taskfile.yml - darwin: ./build/darwin/Taskfile.yml - linux: ./build/linux/Taskfile.yml - ios: ./build/ios/Taskfile.yml - -vars: - APP_NAME: "ios" - BIN_DIR: "bin" - VITE_PORT: '{{.WAILS_VITE_PORT | default 9245}}' - -tasks: - build: - summary: Builds the application - cmds: - - task: "{{OS}}:build" - - package: - summary: Packages a production build of the application - cmds: - - task: "{{OS}}:package" - - run: - summary: Runs the application - cmds: - - task: "{{OS}}:run" - - dev: - summary: Runs the application in development mode - cmds: - - wails3 dev -config ./build/config.yml -port {{.VITE_PORT}} diff --git a/v3/examples/ios/build/Taskfile.yml b/v3/examples/ios/build/Taskfile.yml deleted file mode 100644 index 209793bfd..000000000 --- a/v3/examples/ios/build/Taskfile.yml +++ /dev/null @@ -1,174 +0,0 @@ -version: '3' - -tasks: - go:mod:tidy: - summary: Runs `go mod tidy` - internal: true - cmds: - - go mod tidy - - install:frontend:deps: - summary: Install frontend dependencies - dir: frontend - sources: - - package.json - - package-lock.json - generates: - - node_modules/* - preconditions: - - sh: npm version - msg: "Looks like npm isn't installed. Npm is part of the Node installer: https://nodejs.org/en/download/" - cmds: - - npm install - - build:frontend: - label: build:frontend (PRODUCTION={{.PRODUCTION}}) - summary: Build the frontend project - dir: frontend - sources: - - "**/*" - generates: - - dist/**/* - deps: - - task: install:frontend:deps - - task: generate:bindings - vars: - BUILD_FLAGS: - ref: .BUILD_FLAGS - cmds: - - npm run {{.BUILD_COMMAND}} -q - env: - PRODUCTION: '{{.PRODUCTION | default "false"}}' - vars: - BUILD_COMMAND: '{{if eq .PRODUCTION "true"}}build{{else}}build:dev{{end}}' - - - frontend:vendor:puppertino: - summary: Fetches Puppertino CSS into frontend/public for consistent mobile styling - sources: - - frontend/public/puppertino/puppertino.css - generates: - - frontend/public/puppertino/puppertino.css - cmds: - - | - set -euo pipefail - mkdir -p frontend/public/puppertino - # Fetch Puppertino full.css and LICENSE from GitHub main branch - curl -fsSL https://raw.githubusercontent.com/codedgar/Puppertino/main/dist/css/full.css -o frontend/public/puppertino/puppertino.css - curl -fsSL https://raw.githubusercontent.com/codedgar/Puppertino/main/LICENSE -o frontend/public/puppertino/LICENSE - echo "Puppertino CSS updated at frontend/public/puppertino/puppertino.css" - # Ensure index.html includes Puppertino CSS and button classes - INDEX_HTML=frontend/index.html - if [ -f "$INDEX_HTML" ]; then - if ! grep -q 'href="/puppertino/puppertino.css"' "$INDEX_HTML"; then - # Insert Puppertino link tag after style.css link - awk ' - /href="\/style.css"\/?/ && !x { print; print " "; x=1; next }1 - ' "$INDEX_HTML" > "$INDEX_HTML.tmp" && mv "$INDEX_HTML.tmp" "$INDEX_HTML" - fi - # Replace default .btn with Puppertino primary button classes if present - sed -E -i'' 's/class=\"btn\"/class=\"p-btn p-prim-col\"/g' "$INDEX_HTML" || true - fi - - generate:bindings: - label: generate:bindings (BUILD_FLAGS={{.BUILD_FLAGS}}) - summary: Generates bindings for the frontend - deps: - - task: go:mod:tidy - sources: - - "**/*.[jt]s" - - exclude: frontend/**/* - - frontend/bindings/**/* # Rerun when switching between dev/production mode causes changes in output - - "**/*.go" - - go.mod - - go.sum - generates: - - frontend/bindings/**/* - cmds: - - wails3 generate bindings -f '{{.BUILD_FLAGS}}' -clean=true - - generate:icons: - summary: Generates Windows `.ico` and Mac `.icns` files from an image - dir: build - sources: - - "appicon.png" - generates: - - "darwin/icons.icns" - - "windows/icon.ico" - cmds: - - wails3 generate icons -input appicon.png -macfilename darwin/icons.icns -windowsfilename windows/icon.ico - - dev:frontend: - summary: Runs the frontend in development mode - dir: frontend - deps: - - task: install:frontend:deps - cmds: - - npm run dev -- --port {{.VITE_PORT}} --strictPort - - update:build-assets: - summary: Updates the build assets - dir: build - cmds: - - wails3 update build-assets -name "{{.APP_NAME}}" -binaryname "{{.APP_NAME}}" -config config.yml -dir . - - - ios:device:list: - summary: Lists connected iOS devices (UDIDs) - cmds: - - xcrun xcdevice list - - ios:run:device: - summary: Build, install, and launch on a physical iPhone using Apple tools (xcodebuild/devicectl) - vars: - PROJECT: '{{.PROJECT}}' # e.g., build/ios/xcode/.xcodeproj - SCHEME: '{{.SCHEME}}' # e.g., ios.dev - CONFIG: '{{.CONFIG | default "Debug"}}' - DERIVED: '{{.DERIVED | default "build/ios/DerivedData"}}' - UDID: '{{.UDID}}' # from `task ios:device:list` - BUNDLE_ID: '{{.BUNDLE_ID}}' # e.g., com.yourco.wails.ios.dev - TEAM_ID: '{{.TEAM_ID}}' # optional, if your project is not already set up for signing - preconditions: - - sh: xcrun -f xcodebuild - msg: "xcodebuild not found. Please install Xcode." - - sh: xcrun -f devicectl - msg: "devicectl not found. Please update to Xcode 15+ (which includes devicectl)." - - sh: test -n "{{.PROJECT}}" - msg: "Set PROJECT to your .xcodeproj path (e.g., PROJECT=build/ios/xcode/App.xcodeproj)." - - sh: test -n "{{.SCHEME}}" - msg: "Set SCHEME to your app scheme (e.g., SCHEME=ios.dev)." - - sh: test -n "{{.UDID}}" - msg: "Set UDID to your device UDID (see: task ios:device:list)." - - sh: test -n "{{.BUNDLE_ID}}" - msg: "Set BUNDLE_ID to your app's bundle identifier (e.g., com.yourco.wails.ios.dev)." - cmds: - - | - set -euo pipefail - echo "Building for device: UDID={{.UDID}} SCHEME={{.SCHEME}} PROJECT={{.PROJECT}}" - XCB_ARGS=( - -project "{{.PROJECT}}" - -scheme "{{.SCHEME}}" - -configuration "{{.CONFIG}}" - -destination "id={{.UDID}}" - -derivedDataPath "{{.DERIVED}}" - -allowProvisioningUpdates - -allowProvisioningDeviceRegistration - ) - # Optionally inject signing identifiers if provided - if [ -n "{{.TEAM_ID}}" ]; then XCB_ARGS+=(DEVELOPMENT_TEAM={{.TEAM_ID}}); fi - if [ -n "{{.BUNDLE_ID}}" ]; then XCB_ARGS+=(PRODUCT_BUNDLE_IDENTIFIER={{.BUNDLE_ID}}); fi - xcodebuild "${XCB_ARGS[@]}" build | xcpretty || true - # If xcpretty isn't installed, run without it - if [ "${PIPESTATUS[0]}" -ne 0 ]; then - xcodebuild "${XCB_ARGS[@]}" build - fi - # Find built .app - APP_PATH=$(find "{{.DERIVED}}/Build/Products" -type d -name "*.app" -maxdepth 3 | head -n 1) - if [ -z "$APP_PATH" ]; then - echo "Could not locate built .app under {{.DERIVED}}/Build/Products" >&2 - exit 1 - fi - echo "Installing: $APP_PATH" - xcrun devicectl device install app --device "{{.UDID}}" "$APP_PATH" - echo "Launching: {{.BUNDLE_ID}}" - xcrun devicectl device process launch --device "{{.UDID}}" --stderr console --stdout console "{{.BUNDLE_ID}}" diff --git a/v3/examples/ios/build/appicon.png b/v3/examples/ios/build/appicon.png deleted file mode 100644 index 63617fe4f..000000000 Binary files a/v3/examples/ios/build/appicon.png and /dev/null differ diff --git a/v3/examples/ios/build/config.yml b/v3/examples/ios/build/config.yml deleted file mode 100644 index a8e7e1fa5..000000000 --- a/v3/examples/ios/build/config.yml +++ /dev/null @@ -1,77 +0,0 @@ -# This file contains the configuration for this project. -# When you update `info` or `fileAssociations`, run `wails3 task common:update:build-assets` to update the assets. -# Note that this will overwrite any changes you have made to the assets. -version: '3' - -# This information is used to generate the build assets. -info: - companyName: "My Company" # The name of the company - productName: "My Product" # The name of the application - productIdentifier: "com.mycompany.myproduct" # The unique product identifier - description: "A program that does X" # The application description - copyright: "(c) 2025, My Company" # Copyright text - comments: "Some Product Comments" # Comments - version: "0.0.1" # The application version - -# iOS build configuration (uncomment to customise iOS project generation) -# Note: Keys under `ios` OVERRIDE values under `info` when set. -# ios: -# # The iOS bundle identifier used in the generated Xcode project (CFBundleIdentifier) -# bundleID: "com.mycompany.myproduct" -# # The display name shown under the app icon (CFBundleDisplayName/CFBundleName) -# displayName: "My Product" -# # The app version to embed in Info.plist (CFBundleShortVersionString/CFBundleVersion) -# version: "0.0.1" -# # The company/organisation name for templates and project settings -# company: "My Company" -# # Additional comments to embed in Info.plist metadata -# comments: "Some Product Comments" - -# Dev mode configuration -dev_mode: - root_path: . - log_level: warn - debounce: 1000 - ignore: - dir: - - .git - - node_modules - - frontend - - bin - file: - - .DS_Store - - .gitignore - - .gitkeep - watched_extension: - - "*.go" - git_ignore: true - executes: - - cmd: wails3 task common:install:frontend:deps - type: once - - cmd: wails3 task common:dev:frontend - type: background - - cmd: go mod tidy - type: blocking - - cmd: wails3 task build - type: blocking - - cmd: wails3 task run - type: primary - -# File Associations -# More information at: https://v3.wails.io/noit/done/yet -fileAssociations: -# - ext: wails -# name: Wails -# description: Wails Application File -# iconName: wailsFileIcon -# role: Editor -# - ext: jpg -# name: JPEG -# description: Image File -# iconName: jpegFileIcon -# role: Editor -# mimeType: image/jpeg # (optional) - -# Other data -other: - - name: My Other Data \ No newline at end of file diff --git a/v3/examples/ios/build/darwin/Info.dev.plist b/v3/examples/ios/build/darwin/Info.dev.plist deleted file mode 100644 index bd6a537fa..000000000 --- a/v3/examples/ios/build/darwin/Info.dev.plist +++ /dev/null @@ -1,32 +0,0 @@ - - - - CFBundlePackageType - APPL - CFBundleName - My Product - CFBundleExecutable - ios - CFBundleIdentifier - com.wails.ios - CFBundleVersion - 0.1.0 - CFBundleGetInfoString - This is a comment - CFBundleShortVersionString - 0.1.0 - CFBundleIconFile - icons - LSMinimumSystemVersion - 10.15.0 - NSHighResolutionCapable - true - NSHumanReadableCopyright - © now, My Company - NSAppTransportSecurity - - NSAllowsLocalNetworking - - - - \ No newline at end of file diff --git a/v3/examples/ios/build/darwin/Info.plist b/v3/examples/ios/build/darwin/Info.plist deleted file mode 100644 index fb52df715..000000000 --- a/v3/examples/ios/build/darwin/Info.plist +++ /dev/null @@ -1,27 +0,0 @@ - - - - CFBundlePackageType - APPL - CFBundleName - My Product - CFBundleExecutable - ios - CFBundleIdentifier - com.wails.ios - CFBundleVersion - 0.1.0 - CFBundleGetInfoString - This is a comment - CFBundleShortVersionString - 0.1.0 - CFBundleIconFile - icons - LSMinimumSystemVersion - 10.15.0 - NSHighResolutionCapable - true - NSHumanReadableCopyright - © now, My Company - - \ No newline at end of file diff --git a/v3/examples/ios/build/darwin/Taskfile.yml b/v3/examples/ios/build/darwin/Taskfile.yml deleted file mode 100644 index f0791fea9..000000000 --- a/v3/examples/ios/build/darwin/Taskfile.yml +++ /dev/null @@ -1,81 +0,0 @@ -version: '3' - -includes: - common: ../Taskfile.yml - -tasks: - build: - summary: Creates a production build of the application - deps: - - task: common:go:mod:tidy - - task: common:build:frontend - vars: - BUILD_FLAGS: - ref: .BUILD_FLAGS - PRODUCTION: - ref: .PRODUCTION - - task: common:generate:icons - cmds: - - go build {{.BUILD_FLAGS}} -o {{.OUTPUT}} - vars: - BUILD_FLAGS: '{{if eq .PRODUCTION "true"}}-tags production -trimpath -buildvcs=false -ldflags="-w -s"{{else}}-buildvcs=false -gcflags=all="-l"{{end}}' - DEFAULT_OUTPUT: '{{.BIN_DIR}}/{{.APP_NAME}}' - OUTPUT: '{{ .OUTPUT | default .DEFAULT_OUTPUT }}' - env: - GOOS: darwin - CGO_ENABLED: 1 - GOARCH: '{{.ARCH | default ARCH}}' - CGO_CFLAGS: "-mmacosx-version-min=10.15" - CGO_LDFLAGS: "-mmacosx-version-min=10.15" - MACOSX_DEPLOYMENT_TARGET: "10.15" - PRODUCTION: '{{.PRODUCTION | default "false"}}' - - build:universal: - summary: Builds darwin universal binary (arm64 + amd64) - deps: - - task: build - vars: - ARCH: amd64 - OUTPUT: "{{.BIN_DIR}}/{{.APP_NAME}}-amd64" - - task: build - vars: - ARCH: arm64 - OUTPUT: "{{.BIN_DIR}}/{{.APP_NAME}}-arm64" - cmds: - - lipo -create -output "{{.BIN_DIR}}/{{.APP_NAME}}" "{{.BIN_DIR}}/{{.APP_NAME}}-amd64" "{{.BIN_DIR}}/{{.APP_NAME}}-arm64" - - rm "{{.BIN_DIR}}/{{.APP_NAME}}-amd64" "{{.BIN_DIR}}/{{.APP_NAME}}-arm64" - - package: - summary: Packages a production build of the application into a `.app` bundle - deps: - - task: build - vars: - PRODUCTION: "true" - cmds: - - task: create:app:bundle - - package:universal: - summary: Packages darwin universal binary (arm64 + amd64) - deps: - - task: build:universal - cmds: - - task: create:app:bundle - - - create:app:bundle: - summary: Creates an `.app` bundle - cmds: - - mkdir -p {{.BIN_DIR}}/{{.APP_NAME}}.app/Contents/{MacOS,Resources} - - cp build/darwin/icons.icns {{.BIN_DIR}}/{{.APP_NAME}}.app/Contents/Resources - - cp {{.BIN_DIR}}/{{.APP_NAME}} {{.BIN_DIR}}/{{.APP_NAME}}.app/Contents/MacOS - - cp build/darwin/Info.plist {{.BIN_DIR}}/{{.APP_NAME}}.app/Contents - - codesign --force --deep --sign - {{.BIN_DIR}}/{{.APP_NAME}}.app - - run: - cmds: - - mkdir -p {{.BIN_DIR}}/{{.APP_NAME}}.dev.app/Contents/{MacOS,Resources} - - cp build/darwin/icons.icns {{.BIN_DIR}}/{{.APP_NAME}}.dev.app/Contents/Resources - - cp {{.BIN_DIR}}/{{.APP_NAME}} {{.BIN_DIR}}/{{.APP_NAME}}.dev.app/Contents/MacOS - - cp build/darwin/Info.dev.plist {{.BIN_DIR}}/{{.APP_NAME}}.dev.app/Contents/Info.plist - - codesign --force --deep --sign - {{.BIN_DIR}}/{{.APP_NAME}}.dev.app - - '{{.BIN_DIR}}/{{.APP_NAME}}.dev.app/Contents/MacOS/{{.APP_NAME}}' diff --git a/v3/examples/ios/build/darwin/icons.icns b/v3/examples/ios/build/darwin/icons.icns deleted file mode 100644 index 1b5bd4c86..000000000 Binary files a/v3/examples/ios/build/darwin/icons.icns and /dev/null differ diff --git a/v3/examples/ios/build/ios/Assets.xcassets b/v3/examples/ios/build/ios/Assets.xcassets deleted file mode 100644 index 46fbb8787..000000000 --- a/v3/examples/ios/build/ios/Assets.xcassets +++ /dev/null @@ -1,116 +0,0 @@ -{ - "info" : { - "author" : "xcode", - "version" : 1 - }, - "images" : [ - { - "filename" : "icon-20@2x.png", - "idiom" : "iphone", - "scale" : "2x", - "size" : "20x20" - }, - { - "filename" : "icon-20@3x.png", - "idiom" : "iphone", - "scale" : "3x", - "size" : "20x20" - }, - { - "filename" : "icon-29@2x.png", - "idiom" : "iphone", - "scale" : "2x", - "size" : "29x29" - }, - { - "filename" : "icon-29@3x.png", - "idiom" : "iphone", - "scale" : "3x", - "size" : "29x29" - }, - { - "filename" : "icon-40@2x.png", - "idiom" : "iphone", - "scale" : "2x", - "size" : "40x40" - }, - { - "filename" : "icon-40@3x.png", - "idiom" : "iphone", - "scale" : "3x", - "size" : "40x40" - }, - { - "filename" : "icon-60@2x.png", - "idiom" : "iphone", - "scale" : "2x", - "size" : "60x60" - }, - { - "filename" : "icon-60@3x.png", - "idiom" : "iphone", - "scale" : "3x", - "size" : "60x60" - }, - { - "filename" : "icon-20.png", - "idiom" : "ipad", - "scale" : "1x", - "size" : "20x20" - }, - { - "filename" : "icon-20@2x.png", - "idiom" : "ipad", - "scale" : "2x", - "size" : "20x20" - }, - { - "filename" : "icon-29.png", - "idiom" : "ipad", - "scale" : "1x", - "size" : "29x29" - }, - { - "filename" : "icon-29@2x.png", - "idiom" : "ipad", - "scale" : "2x", - "size" : "29x29" - }, - { - "filename" : "icon-40.png", - "idiom" : "ipad", - "scale" : "1x", - "size" : "40x40" - }, - { - "filename" : "icon-40@2x.png", - "idiom" : "ipad", - "scale" : "2x", - "size" : "40x40" - }, - { - "filename" : "icon-76.png", - "idiom" : "ipad", - "scale" : "1x", - "size" : "76x76" - }, - { - "filename" : "icon-76@2x.png", - "idiom" : "ipad", - "scale" : "2x", - "size" : "76x76" - }, - { - "filename" : "icon-83.5@2x.png", - "idiom" : "ipad", - "scale" : "2x", - "size" : "83.5x83.5" - }, - { - "filename" : "icon-1024.png", - "idiom" : "ios-marketing", - "scale" : "1x", - "size" : "1024x1024" - } - ] -} \ No newline at end of file diff --git a/v3/examples/ios/build/ios/Info.dev.plist b/v3/examples/ios/build/ios/Info.dev.plist deleted file mode 100644 index 89f0b201e..000000000 --- a/v3/examples/ios/build/ios/Info.dev.plist +++ /dev/null @@ -1,62 +0,0 @@ - - - - - CFBundleExecutable - ios - CFBundleIdentifier - com.wails.ios.dev - CFBundleName - My Product (Dev) - CFBundleDisplayName - My Product (Dev) - CFBundlePackageType - APPL - CFBundleShortVersionString - 0.1.0-dev - CFBundleVersion - 0.1.0 - LSRequiresIPhoneOS - - MinimumOSVersion - 15.0 - UILaunchStoryboardName - LaunchScreen - UIRequiredDeviceCapabilities - - armv7 - arm64 - - UISupportedInterfaceOrientations - - UIInterfaceOrientationPortrait - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - UISupportedInterfaceOrientations~ipad - - UIInterfaceOrientationPortrait - UIInterfaceOrientationPortraitUpsideDown - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - NSAppTransportSecurity - - NSAllowsArbitraryLoads - - NSAllowsLocalNetworking - - - - WailsDevelopmentMode - - - NSHumanReadableCopyright - © now, My Company - - - CFBundleGetInfoString - This is a comment - - - \ No newline at end of file diff --git a/v3/examples/ios/build/ios/Info.plist b/v3/examples/ios/build/ios/Info.plist deleted file mode 100644 index 68d63a232..000000000 --- a/v3/examples/ios/build/ios/Info.plist +++ /dev/null @@ -1,59 +0,0 @@ - - - - - CFBundleExecutable - ios - CFBundleIdentifier - com.wails.ios - CFBundleName - My Product - CFBundleDisplayName - My Product - CFBundlePackageType - APPL - CFBundleShortVersionString - 0.1.0 - CFBundleVersion - 0.1.0 - LSRequiresIPhoneOS - - MinimumOSVersion - 15.0 - UILaunchStoryboardName - LaunchScreen - UIRequiredDeviceCapabilities - - armv7 - arm64 - - UISupportedInterfaceOrientations - - UIInterfaceOrientationPortrait - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - UISupportedInterfaceOrientations~ipad - - UIInterfaceOrientationPortrait - UIInterfaceOrientationPortraitUpsideDown - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - NSAppTransportSecurity - - NSAllowsArbitraryLoads - - NSAllowsLocalNetworking - - - - NSHumanReadableCopyright - © now, My Company - - - CFBundleGetInfoString - This is a comment - - - \ No newline at end of file diff --git a/v3/examples/ios/build/ios/LaunchScreen.storyboard b/v3/examples/ios/build/ios/LaunchScreen.storyboard deleted file mode 100644 index eac48ae35..000000000 --- a/v3/examples/ios/build/ios/LaunchScreen.storyboard +++ /dev/null @@ -1,53 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/v3/examples/ios/build/ios/Taskfile.yml b/v3/examples/ios/build/ios/Taskfile.yml deleted file mode 100644 index bf1502a71..000000000 --- a/v3/examples/ios/build/ios/Taskfile.yml +++ /dev/null @@ -1,282 +0,0 @@ -version: '3' - -includes: - common: ../Taskfile.yml - -vars: - BUNDLE_ID: '{{.BUNDLE_ID | default "com.wails.app"}}' - SDK_PATH: - sh: xcrun --sdk iphonesimulator --show-sdk-path - -tasks: - install:deps: - summary: Check and install iOS development dependencies - cmds: - - go run build/ios/scripts/deps/install_deps.go - env: - TASK_FORCE_YES: '{{if .YES}}true{{else}}false{{end}}' - prompt: This will check and install iOS development dependencies. Continue? - - # Note: Bindings generation may show CGO warnings for iOS C imports. - # These warnings are harmless and don't affect the generated bindings, - # as the generator only needs to parse Go types, not C implementations. - build: - summary: Creates a build of the application for iOS - deps: - - task: generate:ios:overlay - - task: generate:ios:xcode - - task: common:go:mod:tidy - - task: generate:ios:bindings - vars: - BUILD_FLAGS: - ref: .BUILD_FLAGS - - task: common:build:frontend - vars: - BUILD_FLAGS: - ref: .BUILD_FLAGS - PRODUCTION: - ref: .PRODUCTION - - task: common:generate:icons - cmds: - - echo "Building iOS app {{.APP_NAME}}..." - - go build -buildmode=c-archive -overlay build/ios/xcode/overlay.json {{.BUILD_FLAGS}} -o {{.OUTPUT}}.a - vars: - BUILD_FLAGS: '{{if eq .PRODUCTION "true"}}-tags production,ios -trimpath -buildvcs=false -ldflags="-w -s"{{else}}-tags ios,debug -buildvcs=false -gcflags=all="-l"{{end}}' - DEFAULT_OUTPUT: '{{.BIN_DIR}}/{{.APP_NAME}}' - OUTPUT: '{{ .OUTPUT | default .DEFAULT_OUTPUT }}' - env: - GOOS: ios - CGO_ENABLED: 1 - GOARCH: '{{.ARCH | default "arm64"}}' - PRODUCTION: '{{.PRODUCTION | default "false"}}' - CGO_CFLAGS: '-isysroot {{.SDK_PATH}} -target arm64-apple-ios15.0-simulator -mios-simulator-version-min=15.0' - CGO_LDFLAGS: '-isysroot {{.SDK_PATH}} -target arm64-apple-ios15.0-simulator' - - compile:objc: - summary: Compile Objective-C iOS wrapper - cmds: - - xcrun -sdk iphonesimulator clang -target arm64-apple-ios15.0-simulator -isysroot {{.SDK_PATH}} -framework Foundation -framework UIKit -framework WebKit -o {{.BIN_DIR}}/{{.APP_NAME}} build/ios/main.m - - codesign --force --sign - {{.BIN_DIR}}/{{.APP_NAME}} - - package: - summary: Packages a production build of the application into a `.app` bundle - deps: - - task: build - vars: - PRODUCTION: "true" - cmds: - - task: create:app:bundle - - create:app:bundle: - summary: Creates an iOS `.app` bundle - cmds: - - rm -rf {{.BIN_DIR}}/{{.APP_NAME}}.app - - mkdir -p {{.BIN_DIR}}/{{.APP_NAME}}.app - - cp {{.BIN_DIR}}/{{.APP_NAME}} {{.BIN_DIR}}/{{.APP_NAME}}.app/ - - cp build/ios/Info.plist {{.BIN_DIR}}/{{.APP_NAME}}.app/ - - | - # Compile asset catalog and embed icons in the app bundle - APP_BUNDLE="{{.BIN_DIR}}/{{.APP_NAME}}.app" - AC_IN="build/ios/xcode/main/Assets.xcassets" - if [ -d "$AC_IN" ]; then - TMP_AC=$(mktemp -d) - xcrun actool \ - --compile "$TMP_AC" \ - --app-icon AppIcon \ - --platform iphonesimulator \ - --minimum-deployment-target 15.0 \ - --product-type com.apple.product-type.application \ - --target-device iphone \ - --target-device ipad \ - --output-partial-info-plist "$APP_BUNDLE/assetcatalog_generated_info.plist" \ - "$AC_IN" - if [ -f "$TMP_AC/Assets.car" ]; then - cp -f "$TMP_AC/Assets.car" "$APP_BUNDLE/Assets.car" - fi - rm -rf "$TMP_AC" - if [ -f "$APP_BUNDLE/assetcatalog_generated_info.plist" ]; then - /usr/libexec/PlistBuddy -c "Merge $APP_BUNDLE/assetcatalog_generated_info.plist" "$APP_BUNDLE/Info.plist" || true - fi - fi - - codesign --force --sign - {{.BIN_DIR}}/{{.APP_NAME}}.app - - deploy-simulator: - summary: Deploy to iOS Simulator - deps: [package] - cmds: - - xcrun simctl terminate booted {{.BUNDLE_ID}} 2>/dev/null || true - - xcrun simctl uninstall booted {{.BUNDLE_ID}} 2>/dev/null || true - - xcrun simctl install booted {{.BIN_DIR}}/{{.APP_NAME}}.app - - xcrun simctl launch booted {{.BUNDLE_ID}} - - compile:ios: - summary: Compile the iOS executable from Go archive and main.m - deps: - - task: build - cmds: - - | - MAIN_M=build/ios/xcode/main/main.m - if [ ! -f "$MAIN_M" ]; then - MAIN_M=build/ios/main.m - fi - xcrun -sdk iphonesimulator clang \ - -target arm64-apple-ios15.0-simulator \ - -isysroot {{.SDK_PATH}} \ - -framework Foundation -framework UIKit -framework WebKit \ - -framework Security -framework CoreFoundation \ - -lresolv \ - -o {{.BIN_DIR}}/{{.APP_NAME | lower}} \ - "$MAIN_M" {{.BIN_DIR}}/{{.APP_NAME}}.a - - generate:ios:bindings: - internal: true - summary: Generates bindings for iOS with proper CGO flags - sources: - - "**/*.go" - - go.mod - - go.sum - generates: - - frontend/bindings/**/* - cmds: - - wails3 generate bindings -f '{{.BUILD_FLAGS}}' -clean=true - env: - GOOS: ios - CGO_ENABLED: 1 - GOARCH: '{{.ARCH | default "arm64"}}' - CGO_CFLAGS: '-isysroot {{.SDK_PATH}} -target arm64-apple-ios15.0-simulator -mios-simulator-version-min=15.0' - CGO_LDFLAGS: '-isysroot {{.SDK_PATH}} -target arm64-apple-ios15.0-simulator' - - ensure-simulator: - internal: true - summary: Ensure iOS Simulator is running and booted - silent: true - cmds: - - | - if ! xcrun simctl list devices booted | grep -q "Booted"; then - echo "Starting iOS Simulator..." - # Get first available iPhone device - DEVICE_ID=$(xcrun simctl list devices available | grep "iPhone" | head -1 | grep -o "[A-F0-9-]\{36\}" || true) - if [ -z "$DEVICE_ID" ]; then - echo "No iPhone simulator found. Creating one..." - RUNTIME=$(xcrun simctl list runtimes | grep iOS | tail -1 | awk '{print $NF}') - DEVICE_ID=$(xcrun simctl create "iPhone 15 Pro" "iPhone 15 Pro" "$RUNTIME") - fi - # Boot the device - echo "Booting device $DEVICE_ID..." - xcrun simctl boot "$DEVICE_ID" 2>/dev/null || true - # Open Simulator app - open -a Simulator - # Wait for boot (max 30 seconds) - for i in {1..30}; do - if xcrun simctl list devices booted | grep -q "Booted"; then - echo "Simulator booted successfully" - break - fi - sleep 1 - done - # Final check - if ! xcrun simctl list devices booted | grep -q "Booted"; then - echo "Failed to boot simulator after 30 seconds" - exit 1 - fi - fi - preconditions: - - sh: command -v xcrun - msg: "xcrun not found. Please run 'wails3 task ios:install:deps' to install iOS development dependencies" - - generate:ios:overlay: - internal: true - summary: Generate Go build overlay and iOS shim - sources: - - build/config.yml - generates: - - build/ios/xcode/overlay.json - - build/ios/xcode/gen/main_ios.gen.go - cmds: - - wails3 ios overlay:gen -out build/ios/xcode/overlay.json -config build/config.yml - - generate:ios:xcode: - internal: true - summary: Generate iOS Xcode project structure and assets - sources: - - build/config.yml - - build/appicon.png - generates: - - build/ios/xcode/main/main.m - - build/ios/xcode/main/Assets.xcassets/**/* - - build/ios/xcode/project.pbxproj - cmds: - - wails3 ios xcode:gen -outdir build/ios/xcode -config build/config.yml - - run: - summary: Run the application in iOS Simulator - deps: - - task: ensure-simulator - - task: compile:ios - cmds: - - rm -rf {{.BIN_DIR}}/{{.APP_NAME}}.dev.app - - mkdir -p {{.BIN_DIR}}/{{.APP_NAME}}.dev.app - - cp {{.BIN_DIR}}/{{.APP_NAME | lower}} {{.BIN_DIR}}/{{.APP_NAME}}.dev.app/{{.APP_NAME | lower}} - - cp build/ios/Info.dev.plist {{.BIN_DIR}}/{{.APP_NAME}}.dev.app/Info.plist - - | - # Compile asset catalog and embed icons for dev bundle - APP_BUNDLE="{{.BIN_DIR}}/{{.APP_NAME}}.dev.app" - AC_IN="build/ios/xcode/main/Assets.xcassets" - if [ -d "$AC_IN" ]; then - TMP_AC=$(mktemp -d) - xcrun actool \ - --compile "$TMP_AC" \ - --app-icon AppIcon \ - --platform iphonesimulator \ - --minimum-deployment-target 15.0 \ - --product-type com.apple.product-type.application \ - --target-device iphone \ - --target-device ipad \ - --output-partial-info-plist "$APP_BUNDLE/assetcatalog_generated_info.plist" \ - "$AC_IN" - if [ -f "$TMP_AC/Assets.car" ]; then - cp -f "$TMP_AC/Assets.car" "$APP_BUNDLE/Assets.car" - fi - rm -rf "$TMP_AC" - if [ -f "$APP_BUNDLE/assetcatalog_generated_info.plist" ]; then - /usr/libexec/PlistBuddy -c "Merge $APP_BUNDLE/assetcatalog_generated_info.plist" "$APP_BUNDLE/Info.plist" || true - fi - fi - - codesign --force --sign - {{.BIN_DIR}}/{{.APP_NAME}}.dev.app - - xcrun simctl terminate booted com.wails.{{.APP_NAME | lower}}.dev 2>/dev/null || true - - xcrun simctl uninstall booted com.wails.{{.APP_NAME | lower}}.dev 2>/dev/null || true - - xcrun simctl install booted {{.BIN_DIR}}/{{.APP_NAME}}.dev.app - - xcrun simctl launch booted com.wails.{{.APP_NAME | lower}}.dev - - xcode: - summary: Open the generated Xcode project for this app - cmds: - - task: generate:ios:xcode - - open build/ios/xcode/main.xcodeproj - - logs: - summary: Stream iOS Simulator logs filtered to this app - cmds: - - | - xcrun simctl spawn booted log stream \ - --level debug \ - --style compact \ - --predicate 'senderImagePath CONTAINS[c] "{{.APP_NAME | lower}}.app/" OR composedMessage CONTAINS[c] "{{.APP_NAME | lower}}" OR eventMessage CONTAINS[c] "{{.APP_NAME | lower}}" OR process == "{{.APP_NAME | lower}}" OR category CONTAINS[c] "{{.APP_NAME | lower}}"' - - logs:dev: - summary: Stream logs for the dev bundle (used by `task ios:run`) - cmds: - - | - xcrun simctl spawn booted log stream \ - --level debug \ - --style compact \ - --predicate 'senderImagePath CONTAINS[c] ".dev.app/" OR subsystem == "com.wails.{{.APP_NAME | lower}}.dev" OR process == "{{.APP_NAME | lower}}"' - - logs:wide: - summary: Wide log stream to help discover the exact process/bundle identifiers - cmds: - - | - xcrun simctl spawn booted log stream \ - --level debug \ - --style compact \ - --predicate 'senderImagePath CONTAINS[c] ".app/"' \ No newline at end of file diff --git a/v3/examples/ios/build/ios/app_options_default.go b/v3/examples/ios/build/ios/app_options_default.go deleted file mode 100644 index 04e4f1bc9..000000000 --- a/v3/examples/ios/build/ios/app_options_default.go +++ /dev/null @@ -1,10 +0,0 @@ -//go:build !ios - -package main - -import "github.com/wailsapp/wails/v3/pkg/application" - -// modifyOptionsForIOS is a no-op on non-iOS platforms -func modifyOptionsForIOS(opts *application.Options) { - // No modifications needed for non-iOS platforms -} \ No newline at end of file diff --git a/v3/examples/ios/build/ios/app_options_ios.go b/v3/examples/ios/build/ios/app_options_ios.go deleted file mode 100644 index 565fbaad6..000000000 --- a/v3/examples/ios/build/ios/app_options_ios.go +++ /dev/null @@ -1,20 +0,0 @@ -//go:build ios - -package main - -import "github.com/wailsapp/wails/v3/pkg/application" - -// modifyOptionsForIOS adjusts the application options for iOS -func modifyOptionsForIOS(opts *application.Options) { - // Disable signal handlers on iOS to prevent crashes - opts.DisableDefaultSignalHandler = true - - // Enable native UITabBar in the iOS example by default - opts.IOS.EnableNativeTabs = true - // Configure example tab items (titles + SF Symbols) - opts.IOS.NativeTabsItems = []application.NativeTabItem{ - {Title: "Bindings", SystemImage: "link"}, - {Title: "Go Runtime", SystemImage: "gearshape"}, - {Title: "JS Runtime", SystemImage: "chevron.left.slash.chevron.right"}, - } -} \ No newline at end of file diff --git a/v3/examples/ios/build/ios/build.sh b/v3/examples/ios/build/ios/build.sh deleted file mode 100644 index fbb47a673..000000000 --- a/v3/examples/ios/build/ios/build.sh +++ /dev/null @@ -1,72 +0,0 @@ -#!/bin/bash -set -e - -# Build configuration -APP_NAME="ios" -BUNDLE_ID="com.wails.ios" -VERSION="0.1.0" -BUILD_NUMBER="0.1.0" -BUILD_DIR="build/ios" -TARGET="simulator" - -echo "Building iOS app: $APP_NAME" -echo "Bundle ID: $BUNDLE_ID" -echo "Version: $VERSION ($BUILD_NUMBER)" -echo "Target: $TARGET" - -# Ensure build directory exists -mkdir -p "$BUILD_DIR" - -# Determine SDK and target architecture -if [ "$TARGET" = "simulator" ]; then - SDK="iphonesimulator" - ARCH="arm64-apple-ios15.0-simulator" -elif [ "$TARGET" = "device" ]; then - SDK="iphoneos" - ARCH="arm64-apple-ios15.0" -else - echo "Unknown target: $TARGET" - exit 1 -fi - -# Get SDK path -SDK_PATH=$(xcrun --sdk $SDK --show-sdk-path) - -# Compile the application -echo "Compiling with SDK: $SDK" -xcrun -sdk $SDK clang \ - -target $ARCH \ - -isysroot "$SDK_PATH" \ - -framework Foundation \ - -framework UIKit \ - -framework WebKit \ - -framework CoreGraphics \ - -o "$BUILD_DIR/$APP_NAME" \ - "$BUILD_DIR/main.m" - -# Create app bundle -echo "Creating app bundle..." -APP_BUNDLE="$BUILD_DIR/$APP_NAME.app" -rm -rf "$APP_BUNDLE" -mkdir -p "$APP_BUNDLE" - -# Move executable -mv "$BUILD_DIR/$APP_NAME" "$APP_BUNDLE/" - -# Copy Info.plist -cp "$BUILD_DIR/Info.plist" "$APP_BUNDLE/" - -# Sign the app -echo "Signing app..." -codesign --force --sign - "$APP_BUNDLE" - -echo "Build complete: $APP_BUNDLE" - -# Deploy to simulator if requested -if [ "$TARGET" = "simulator" ]; then - echo "Deploying to simulator..." - xcrun simctl terminate booted "$BUNDLE_ID" 2>/dev/null || true - xcrun simctl install booted "$APP_BUNDLE" - xcrun simctl launch booted "$BUNDLE_ID" - echo "App launched on simulator" -fi \ No newline at end of file diff --git a/v3/examples/ios/build/ios/entitlements.plist b/v3/examples/ios/build/ios/entitlements.plist deleted file mode 100644 index cc5d9582b..000000000 --- a/v3/examples/ios/build/ios/entitlements.plist +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - get-task-allow - - - - com.apple.security.app-sandbox - - - - com.apple.security.network.client - - - - com.apple.security.files.user-selected.read-only - - - \ No newline at end of file diff --git a/v3/examples/ios/build/ios/icon.png b/v3/examples/ios/build/ios/icon.png deleted file mode 100644 index be7d59173..000000000 --- a/v3/examples/ios/build/ios/icon.png +++ /dev/null @@ -1,3 +0,0 @@ -# iOS Icon Placeholder -# This file should be replaced with the actual app icon (1024x1024 PNG) -# The build process will generate all required icon sizes from this base icon \ No newline at end of file diff --git a/v3/examples/ios/build/ios/main.m b/v3/examples/ios/build/ios/main.m deleted file mode 100644 index 0f2e7e8e1..000000000 --- a/v3/examples/ios/build/ios/main.m +++ /dev/null @@ -1,22 +0,0 @@ -// Minimal bootstrap: delegate comes from Go archive (WailsAppDelegate) -#import -#include - -// External Go initialization function from the c-archive (declare before use) -extern void WailsIOSMain(); - -int main(int argc, char * argv[]) { - @autoreleasepool { - // Disable buffering so stdout/stderr from Go log.Printf flush immediately - setvbuf(stdout, NULL, _IONBF, 0); - setvbuf(stderr, NULL, _IONBF, 0); - - // Start Go runtime on a background queue to avoid blocking main thread/UI - dispatch_async(dispatch_get_global_queue(QOS_CLASS_USER_INITIATED, 0), ^{ - WailsIOSMain(); - }); - - // Run UIApplicationMain using WailsAppDelegate provided by the Go archive - return UIApplicationMain(argc, argv, nil, @"WailsAppDelegate"); - } -} \ No newline at end of file diff --git a/v3/examples/ios/build/ios/main_ios.go b/v3/examples/ios/build/ios/main_ios.go deleted file mode 100644 index b75a40321..000000000 --- a/v3/examples/ios/build/ios/main_ios.go +++ /dev/null @@ -1,24 +0,0 @@ -//go:build ios - -package main - -import ( - "C" -) - -// For iOS builds, we need to export a function that can be called from Objective-C -// This wrapper allows us to keep the original main.go unmodified - -//export WailsIOSMain -func WailsIOSMain() { - // DO NOT lock the goroutine to the current OS thread on iOS! - // This causes signal handling issues: - // "signal 16 received on thread with no signal stack" - // "fatal error: non-Go code disabled sigaltstack" - // iOS apps run in a sandboxed environment where the Go runtime's - // signal handling doesn't work the same way as desktop platforms. - - // Call the actual main function from main.go - // This ensures all the user's code is executed - main() -} \ No newline at end of file diff --git a/v3/examples/ios/build/ios/project.pbxproj b/v3/examples/ios/build/ios/project.pbxproj deleted file mode 100644 index 627ab5b17..000000000 --- a/v3/examples/ios/build/ios/project.pbxproj +++ /dev/null @@ -1,222 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = {}; - objectVersion = 56; - objects = { - -/* Begin PBXBuildFile section */ - C0DEBEEF0000000000000001 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = C0DEBEEF0000000000000002 /* main.m */; }; - C0DEBEEF00000000000000F1 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C0DEBEEF0000000000000101 /* UIKit.framework */; }; - C0DEBEEF00000000000000F2 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C0DEBEEF0000000000000102 /* Foundation.framework */; }; - C0DEBEEF00000000000000F3 /* WebKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C0DEBEEF0000000000000103 /* WebKit.framework */; }; - C0DEBEEF00000000000000F4 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C0DEBEEF0000000000000104 /* Security.framework */; }; - C0DEBEEF00000000000000F5 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C0DEBEEF0000000000000105 /* CoreFoundation.framework */; }; - C0DEBEEF00000000000000F6 /* libresolv.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = C0DEBEEF0000000000000106 /* libresolv.tbd */; }; - C0DEBEEF00000000000000F7 /* My Product.a in Frameworks */ = {isa = PBXBuildFile; fileRef = C0DEBEEF0000000000000107 /* My Product.a */; }; -/* End PBXBuildFile section */ - -/* Begin PBXFileReference section */ - C0DEBEEF0000000000000002 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; - C0DEBEEF0000000000000003 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - C0DEBEEF0000000000000004 /* My Product.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "My Product.app"; sourceTree = BUILT_PRODUCTS_DIR; }; - C0DEBEEF0000000000000101 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; - C0DEBEEF0000000000000102 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; - C0DEBEEF0000000000000103 /* WebKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WebKit.framework; path = System/Library/Frameworks/WebKit.framework; sourceTree = SDKROOT; }; - C0DEBEEF0000000000000104 /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; }; - C0DEBEEF0000000000000105 /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = System/Library/Frameworks/CoreFoundation.framework; sourceTree = SDKROOT; }; - C0DEBEEF0000000000000106 /* libresolv.tbd */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.text-based-dylib-definition; name = libresolv.tbd; path = usr/lib/libresolv.tbd; sourceTree = SDKROOT; }; - C0DEBEEF0000000000000107 /* My Product.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = "My Product.a"; path = ../../../bin/My Product.a; sourceTree = SOURCE_ROOT; }; -/* End PBXFileReference section */ - -/* Begin PBXGroup section */ - C0DEBEEF0000000000000010 = { - isa = PBXGroup; - children = ( - C0DEBEEF0000000000000020 /* Products */, - C0DEBEEF0000000000000045 /* Frameworks */, - C0DEBEEF0000000000000030 /* main */, - ); - sourceTree = ""; - }; - C0DEBEEF0000000000000020 /* Products */ = { - isa = PBXGroup; - children = ( - C0DEBEEF0000000000000004 /* My Product.app */, - ); - name = Products; - sourceTree = ""; - }; - C0DEBEEF0000000000000030 /* main */ = { - isa = PBXGroup; - children = ( - C0DEBEEF0000000000000002 /* main.m */, - C0DEBEEF0000000000000003 /* Info.plist */, - ); - path = main; - sourceTree = SOURCE_ROOT; - }; - C0DEBEEF0000000000000045 /* Frameworks */ = { - isa = PBXGroup; - children = ( - C0DEBEEF0000000000000101 /* UIKit.framework */, - C0DEBEEF0000000000000102 /* Foundation.framework */, - C0DEBEEF0000000000000103 /* WebKit.framework */, - C0DEBEEF0000000000000104 /* Security.framework */, - C0DEBEEF0000000000000105 /* CoreFoundation.framework */, - C0DEBEEF0000000000000106 /* libresolv.tbd */, - C0DEBEEF0000000000000107 /* My Product.a */, - ); - name = Frameworks; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - C0DEBEEF0000000000000040 /* My Product */ = { - isa = PBXNativeTarget; - buildConfigurationList = C0DEBEEF0000000000000070 /* Build configuration list for PBXNativeTarget "My Product" */; - buildPhases = ( - C0DEBEEF0000000000000055 /* Prebuild: Wails Go Archive */, - C0DEBEEF0000000000000050 /* Sources */, - C0DEBEEF0000000000000056 /* Frameworks */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = "My Product"; - productName = "My Product"; - productReference = C0DEBEEF0000000000000004 /* My Product.app */; - productType = "com.apple.product-type.application"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - C0DEBEEF0000000000000060 /* Project object */ = { - isa = PBXProject; - attributes = { - LastUpgradeCheck = 1500; - ORGANIZATIONNAME = "My Company"; - TargetAttributes = { - C0DEBEEF0000000000000040 = { - CreatedOnToolsVersion = 15.0; - }; - }; - }; - buildConfigurationList = C0DEBEEF0000000000000080 /* Build configuration list for PBXProject "main" */; - compatibilityVersion = "Xcode 15.0"; - developmentRegion = en; - hasScannedForEncodings = 0; - knownRegions = ( - en, - ); - mainGroup = C0DEBEEF0000000000000010; - productRefGroup = C0DEBEEF0000000000000020 /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - C0DEBEEF0000000000000040 /* My Product */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXFrameworksBuildPhase section */ - C0DEBEEF0000000000000056 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - C0DEBEEF00000000000000F7 /* My Product.a in Frameworks */, - C0DEBEEF00000000000000F1 /* UIKit.framework in Frameworks */, - C0DEBEEF00000000000000F2 /* Foundation.framework in Frameworks */, - C0DEBEEF00000000000000F3 /* WebKit.framework in Frameworks */, - C0DEBEEF00000000000000F4 /* Security.framework in Frameworks */, - C0DEBEEF00000000000000F5 /* CoreFoundation.framework in Frameworks */, - C0DEBEEF00000000000000F6 /* libresolv.tbd in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXShellScriptBuildPhase section */ - C0DEBEEF0000000000000055 /* Prebuild: Wails Go Archive */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - ); - inputPaths = ( - ); - name = "Prebuild: Wails Go Archive"; - outputFileListPaths = ( - ); - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "set -e\nAPP_ROOT=\"${PROJECT_DIR}/../../..\"\nSDK_PATH=$(xcrun --sdk iphonesimulator --show-sdk-path)\nexport GOOS=ios\nexport GOARCH=arm64\nexport CGO_ENABLED=1\nexport CGO_CFLAGS=\"-isysroot ${SDK_PATH} -target arm64-apple-ios15.0-simulator -mios-simulator-version-min=15.0\"\nexport CGO_LDFLAGS=\"-isysroot ${SDK_PATH} -target arm64-apple-ios15.0-simulator\"\ncd \"${APP_ROOT}\"\n# Ensure overlay exists\nif [ ! -f build/ios/xcode/overlay.json ]; then\n wails3 ios overlay:gen -out build/ios/xcode/overlay.json -config build/config.yml || true\nfi\n# Build Go c-archive if missing or older than sources\nif [ ! -f bin/My Product.a ]; then\n echo \"Building Go c-archive...\"\n go build -buildmode=c-archive -overlay build/ios/xcode/overlay.json -o bin/My Product.a\nfi\n"; - }; -/* End PBXShellScriptBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - C0DEBEEF0000000000000050 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - C0DEBEEF0000000000000001 /* main.m in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin XCBuildConfiguration section */ - C0DEBEEF0000000000000090 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - INFOPLIST_FILE = main/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 15.0; - PRODUCT_BUNDLE_IDENTIFIER = "com.wails.ios"; - PRODUCT_NAME = "My Product"; - CODE_SIGNING_ALLOWED = NO; - SDKROOT = iphonesimulator; - }; - name = Debug; - }; - C0DEBEEF00000000000000A0 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - INFOPLIST_FILE = main/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 15.0; - PRODUCT_BUNDLE_IDENTIFIER = "com.wails.ios"; - PRODUCT_NAME = "My Product"; - CODE_SIGNING_ALLOWED = NO; - SDKROOT = iphonesimulator; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - C0DEBEEF0000000000000070 /* Build configuration list for PBXNativeTarget "My Product" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - C0DEBEEF0000000000000090 /* Debug */, - C0DEBEEF00000000000000A0 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Debug; - }; - C0DEBEEF0000000000000080 /* Build configuration list for PBXProject "main" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - C0DEBEEF0000000000000090 /* Debug */, - C0DEBEEF00000000000000A0 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Debug; - }; -/* End XCConfigurationList section */ - }; - rootObject = C0DEBEEF0000000000000060 /* Project object */; -} diff --git a/v3/examples/ios/build/ios/scripts/deps/install_deps.go b/v3/examples/ios/build/ios/scripts/deps/install_deps.go deleted file mode 100644 index 88ed47a4a..000000000 --- a/v3/examples/ios/build/ios/scripts/deps/install_deps.go +++ /dev/null @@ -1,319 +0,0 @@ -// install_deps.go - iOS development dependency checker -// This script checks for required iOS development tools. -// It's designed to be portable across different shells by using Go instead of shell scripts. -// -// Usage: -// go run install_deps.go # Interactive mode -// TASK_FORCE_YES=true go run install_deps.go # Auto-accept prompts -// CI=true go run install_deps.go # CI mode (auto-accept) - -package main - -import ( - "bufio" - "fmt" - "os" - "os/exec" - "strings" -) - -type Dependency struct { - Name string - CheckFunc func() (bool, string) // Returns (success, details) - Required bool - InstallCmd []string - InstallMsg string - SuccessMsg string - FailureMsg string -} - -func main() { - fmt.Println("Checking iOS development dependencies...") - fmt.Println("=" + strings.Repeat("=", 50)) - fmt.Println() - - hasErrors := false - dependencies := []Dependency{ - { - Name: "Xcode", - CheckFunc: func() (bool, string) { - // Check if xcodebuild exists - if !checkCommand([]string{"xcodebuild", "-version"}) { - return false, "" - } - // Get version info - out, err := exec.Command("xcodebuild", "-version").Output() - if err != nil { - return false, "" - } - lines := strings.Split(string(out), "\n") - if len(lines) > 0 { - return true, strings.TrimSpace(lines[0]) - } - return true, "" - }, - Required: true, - InstallMsg: "Please install Xcode from the Mac App Store:\n https://apps.apple.com/app/xcode/id497799835\n Xcode is REQUIRED for iOS development (includes iOS SDKs, simulators, and frameworks)", - SuccessMsg: "✅ Xcode found", - FailureMsg: "❌ Xcode not found (REQUIRED)", - }, - { - Name: "Xcode Developer Path", - CheckFunc: func() (bool, string) { - // Check if xcode-select points to a valid Xcode path - out, err := exec.Command("xcode-select", "-p").Output() - if err != nil { - return false, "xcode-select not configured" - } - path := strings.TrimSpace(string(out)) - - // Check if path exists and is in Xcode.app - if _, err := os.Stat(path); err != nil { - return false, "Invalid Xcode path" - } - - // Verify it's pointing to Xcode.app (not just Command Line Tools) - if !strings.Contains(path, "Xcode.app") { - return false, fmt.Sprintf("Points to %s (should be Xcode.app)", path) - } - - return true, path - }, - Required: true, - InstallCmd: []string{"sudo", "xcode-select", "-s", "/Applications/Xcode.app/Contents/Developer"}, - InstallMsg: "Xcode developer path needs to be configured", - SuccessMsg: "✅ Xcode developer path configured", - FailureMsg: "❌ Xcode developer path not configured correctly", - }, - { - Name: "iOS SDK", - CheckFunc: func() (bool, string) { - // Get the iOS Simulator SDK path - cmd := exec.Command("xcrun", "--sdk", "iphonesimulator", "--show-sdk-path") - output, err := cmd.Output() - if err != nil { - return false, "Cannot find iOS SDK" - } - sdkPath := strings.TrimSpace(string(output)) - - // Check if the SDK path exists - if _, err := os.Stat(sdkPath); err != nil { - return false, "iOS SDK path not found" - } - - // Check for UIKit framework (essential for iOS development) - uikitPath := fmt.Sprintf("%s/System/Library/Frameworks/UIKit.framework", sdkPath) - if _, err := os.Stat(uikitPath); err != nil { - return false, "UIKit.framework not found" - } - - // Get SDK version - versionCmd := exec.Command("xcrun", "--sdk", "iphonesimulator", "--show-sdk-version") - versionOut, _ := versionCmd.Output() - version := strings.TrimSpace(string(versionOut)) - - return true, fmt.Sprintf("iOS %s SDK", version) - }, - Required: true, - InstallMsg: "iOS SDK comes with Xcode. Please ensure Xcode is properly installed.", - SuccessMsg: "✅ iOS SDK found with UIKit framework", - FailureMsg: "❌ iOS SDK not found or incomplete", - }, - { - Name: "iOS Simulator Runtime", - CheckFunc: func() (bool, string) { - if !checkCommand([]string{"xcrun", "simctl", "help"}) { - return false, "" - } - // Check if we can list runtimes - out, err := exec.Command("xcrun", "simctl", "list", "runtimes").Output() - if err != nil { - return false, "Cannot access simulator" - } - // Count iOS runtimes - lines := strings.Split(string(out), "\n") - count := 0 - var versions []string - for _, line := range lines { - if strings.Contains(line, "iOS") && !strings.Contains(line, "unavailable") { - count++ - // Extract version number - if parts := strings.Fields(line); len(parts) > 2 { - for _, part := range parts { - if strings.HasPrefix(part, "(") && strings.HasSuffix(part, ")") { - versions = append(versions, strings.Trim(part, "()")) - break - } - } - } - } - } - if count > 0 { - return true, fmt.Sprintf("%d runtime(s): %s", count, strings.Join(versions, ", ")) - } - return false, "No iOS runtimes installed" - }, - Required: true, - InstallMsg: "iOS Simulator runtimes come with Xcode. You may need to download them:\n Xcode → Settings → Platforms → iOS", - SuccessMsg: "✅ iOS Simulator runtime available", - FailureMsg: "❌ iOS Simulator runtime not available", - }, - } - - // Check each dependency - for _, dep := range dependencies { - success, details := dep.CheckFunc() - if success { - msg := dep.SuccessMsg - if details != "" { - msg = fmt.Sprintf("%s (%s)", dep.SuccessMsg, details) - } - fmt.Println(msg) - } else { - fmt.Println(dep.FailureMsg) - if details != "" { - fmt.Printf(" Details: %s\n", details) - } - if dep.Required { - hasErrors = true - if len(dep.InstallCmd) > 0 { - fmt.Println() - fmt.Println(" " + dep.InstallMsg) - fmt.Printf(" Fix command: %s\n", strings.Join(dep.InstallCmd, " ")) - if promptUser("Do you want to run this command?") { - fmt.Println("Running command...") - cmd := exec.Command(dep.InstallCmd[0], dep.InstallCmd[1:]...) - cmd.Stdout = os.Stdout - cmd.Stderr = os.Stderr - cmd.Stdin = os.Stdin - if err := cmd.Run(); err != nil { - fmt.Printf("Command failed: %v\n", err) - os.Exit(1) - } - fmt.Println("✅ Command completed. Please run this check again.") - } else { - fmt.Printf(" Please run manually: %s\n", strings.Join(dep.InstallCmd, " ")) - } - } else { - fmt.Println(" " + dep.InstallMsg) - } - } - } - } - - // Check for iPhone simulators - fmt.Println() - fmt.Println("Checking for iPhone simulator devices...") - if !checkCommand([]string{"xcrun", "simctl", "list", "devices"}) { - fmt.Println("❌ Cannot check for iPhone simulators") - hasErrors = true - } else { - out, err := exec.Command("xcrun", "simctl", "list", "devices").Output() - if err != nil { - fmt.Println("❌ Failed to list simulator devices") - hasErrors = true - } else if !strings.Contains(string(out), "iPhone") { - fmt.Println("⚠️ No iPhone simulator devices found") - fmt.Println() - - // Get the latest iOS runtime - runtimeOut, err := exec.Command("xcrun", "simctl", "list", "runtimes").Output() - if err != nil { - fmt.Println(" Failed to get iOS runtimes:", err) - } else { - lines := strings.Split(string(runtimeOut), "\n") - var latestRuntime string - for _, line := range lines { - if strings.Contains(line, "iOS") && !strings.Contains(line, "unavailable") { - // Extract runtime identifier - parts := strings.Fields(line) - if len(parts) > 0 { - latestRuntime = parts[len(parts)-1] - } - } - } - - if latestRuntime == "" { - fmt.Println(" No iOS runtime found. Please install iOS simulators in Xcode:") - fmt.Println(" Xcode → Settings → Platforms → iOS") - } else { - fmt.Println(" Would you like to create an iPhone 15 Pro simulator?") - createCmd := []string{"xcrun", "simctl", "create", "iPhone 15 Pro", "iPhone 15 Pro", latestRuntime} - fmt.Printf(" Command: %s\n", strings.Join(createCmd, " ")) - if promptUser("Create simulator?") { - cmd := exec.Command(createCmd[0], createCmd[1:]...) - cmd.Stdout = os.Stdout - cmd.Stderr = os.Stderr - if err := cmd.Run(); err != nil { - fmt.Printf(" Failed to create simulator: %v\n", err) - } else { - fmt.Println(" ✅ iPhone 15 Pro simulator created") - } - } else { - fmt.Println(" Skipping simulator creation") - fmt.Printf(" Create manually: %s\n", strings.Join(createCmd, " ")) - } - } - } - } else { - // Count iPhone devices - count := 0 - lines := strings.Split(string(out), "\n") - for _, line := range lines { - if strings.Contains(line, "iPhone") && !strings.Contains(line, "unavailable") { - count++ - } - } - fmt.Printf("✅ %d iPhone simulator device(s) available\n", count) - } - } - - // Final summary - fmt.Println() - fmt.Println("=" + strings.Repeat("=", 50)) - if hasErrors { - fmt.Println("❌ Some required dependencies are missing or misconfigured.") - fmt.Println() - fmt.Println("Quick setup guide:") - fmt.Println("1. Install Xcode from Mac App Store (if not installed)") - fmt.Println("2. Open Xcode once and agree to the license") - fmt.Println("3. Install additional components when prompted") - fmt.Println("4. Run: sudo xcode-select -s /Applications/Xcode.app/Contents/Developer") - fmt.Println("5. Download iOS simulators: Xcode → Settings → Platforms → iOS") - fmt.Println("6. Run this check again") - os.Exit(1) - } else { - fmt.Println("✅ All required dependencies are installed!") - fmt.Println(" You're ready for iOS development with Wails!") - } -} - -func checkCommand(args []string) bool { - if len(args) == 0 { - return false - } - cmd := exec.Command(args[0], args[1:]...) - cmd.Stdout = nil - cmd.Stderr = nil - err := cmd.Run() - return err == nil -} - -func promptUser(question string) bool { - // Check if we're in a non-interactive environment - if os.Getenv("CI") != "" || os.Getenv("TASK_FORCE_YES") == "true" { - fmt.Printf("%s [y/N]: y (auto-accepted)\n", question) - return true - } - - reader := bufio.NewReader(os.Stdin) - fmt.Printf("%s [y/N]: ", question) - - response, err := reader.ReadString('\n') - if err != nil { - return false - } - - response = strings.ToLower(strings.TrimSpace(response)) - return response == "y" || response == "yes" -} \ No newline at end of file diff --git a/v3/examples/ios/build/ios/xcode/gen/main_ios.gen.go b/v3/examples/ios/build/ios/xcode/gen/main_ios.gen.go deleted file mode 100644 index b75a40321..000000000 --- a/v3/examples/ios/build/ios/xcode/gen/main_ios.gen.go +++ /dev/null @@ -1,24 +0,0 @@ -//go:build ios - -package main - -import ( - "C" -) - -// For iOS builds, we need to export a function that can be called from Objective-C -// This wrapper allows us to keep the original main.go unmodified - -//export WailsIOSMain -func WailsIOSMain() { - // DO NOT lock the goroutine to the current OS thread on iOS! - // This causes signal handling issues: - // "signal 16 received on thread with no signal stack" - // "fatal error: non-Go code disabled sigaltstack" - // iOS apps run in a sandboxed environment where the Go runtime's - // signal handling doesn't work the same way as desktop platforms. - - // Call the actual main function from main.go - // This ensures all the user's code is executed - main() -} \ No newline at end of file diff --git a/v3/examples/ios/build/ios/xcode/main.xcodeproj/project.pbxproj b/v3/examples/ios/build/ios/xcode/main.xcodeproj/project.pbxproj deleted file mode 100644 index 6db4c3928..000000000 --- a/v3/examples/ios/build/ios/xcode/main.xcodeproj/project.pbxproj +++ /dev/null @@ -1,222 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = {}; - objectVersion = 56; - objects = { - -/* Begin PBXBuildFile section */ - C0DEBEEF0000000000000001 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = C0DEBEEF0000000000000002 /* main.m */; }; - C0DEBEEF00000000000000F1 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C0DEBEEF0000000000000101 /* UIKit.framework */; }; - C0DEBEEF00000000000000F2 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C0DEBEEF0000000000000102 /* Foundation.framework */; }; - C0DEBEEF00000000000000F3 /* WebKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C0DEBEEF0000000000000103 /* WebKit.framework */; }; - C0DEBEEF00000000000000F4 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C0DEBEEF0000000000000104 /* Security.framework */; }; - C0DEBEEF00000000000000F5 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C0DEBEEF0000000000000105 /* CoreFoundation.framework */; }; - C0DEBEEF00000000000000F6 /* libresolv.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = C0DEBEEF0000000000000106 /* libresolv.tbd */; }; - C0DEBEEF00000000000000F7 /* My Product.a in Frameworks */ = {isa = PBXBuildFile; fileRef = C0DEBEEF0000000000000107 /* My Product.a */; }; -/* End PBXBuildFile section */ - -/* Begin PBXFileReference section */ - C0DEBEEF0000000000000002 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; - C0DEBEEF0000000000000003 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - C0DEBEEF0000000000000004 /* My Product.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "My Product.app"; sourceTree = BUILT_PRODUCTS_DIR; }; - C0DEBEEF0000000000000101 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; - C0DEBEEF0000000000000102 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; - C0DEBEEF0000000000000103 /* WebKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WebKit.framework; path = System/Library/Frameworks/WebKit.framework; sourceTree = SDKROOT; }; - C0DEBEEF0000000000000104 /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; }; - C0DEBEEF0000000000000105 /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = System/Library/Frameworks/CoreFoundation.framework; sourceTree = SDKROOT; }; - C0DEBEEF0000000000000106 /* libresolv.tbd */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.text-based-dylib-definition; name = libresolv.tbd; path = usr/lib/libresolv.tbd; sourceTree = SDKROOT; }; - C0DEBEEF0000000000000107 /* My Product.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = "My Product.a"; path = ../../../bin/My Product.a; sourceTree = SOURCE_ROOT; }; -/* End PBXFileReference section */ - -/* Begin PBXGroup section */ - C0DEBEEF0000000000000010 = { - isa = PBXGroup; - children = ( - C0DEBEEF0000000000000020 /* Products */, - C0DEBEEF0000000000000045 /* Frameworks */, - C0DEBEEF0000000000000030 /* main */, - ); - sourceTree = ""; - }; - C0DEBEEF0000000000000020 /* Products */ = { - isa = PBXGroup; - children = ( - C0DEBEEF0000000000000004 /* My Product.app */, - ); - name = Products; - sourceTree = ""; - }; - C0DEBEEF0000000000000030 /* main */ = { - isa = PBXGroup; - children = ( - C0DEBEEF0000000000000002 /* main.m */, - C0DEBEEF0000000000000003 /* Info.plist */, - ); - path = main; - sourceTree = SOURCE_ROOT; - }; - C0DEBEEF0000000000000045 /* Frameworks */ = { - isa = PBXGroup; - children = ( - C0DEBEEF0000000000000101 /* UIKit.framework */, - C0DEBEEF0000000000000102 /* Foundation.framework */, - C0DEBEEF0000000000000103 /* WebKit.framework */, - C0DEBEEF0000000000000104 /* Security.framework */, - C0DEBEEF0000000000000105 /* CoreFoundation.framework */, - C0DEBEEF0000000000000106 /* libresolv.tbd */, - C0DEBEEF0000000000000107 /* My Product.a */, - ); - name = Frameworks; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - C0DEBEEF0000000000000040 /* My Product */ = { - isa = PBXNativeTarget; - buildConfigurationList = C0DEBEEF0000000000000070 /* Build configuration list for PBXNativeTarget "My Product" */; - buildPhases = ( - C0DEBEEF0000000000000055 /* Prebuild: Wails Go Archive */, - C0DEBEEF0000000000000050 /* Sources */, - C0DEBEEF0000000000000056 /* Frameworks */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = "My Product"; - productName = "My Product"; - productReference = C0DEBEEF0000000000000004 /* My Product.app */; - productType = "com.apple.product-type.application"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - C0DEBEEF0000000000000060 /* Project object */ = { - isa = PBXProject; - attributes = { - LastUpgradeCheck = 1500; - ORGANIZATIONNAME = "My Company"; - TargetAttributes = { - C0DEBEEF0000000000000040 = { - CreatedOnToolsVersion = 15.0; - }; - }; - }; - buildConfigurationList = C0DEBEEF0000000000000080 /* Build configuration list for PBXProject "main" */; - compatibilityVersion = "Xcode 15.0"; - developmentRegion = en; - hasScannedForEncodings = 0; - knownRegions = ( - en, - ); - mainGroup = C0DEBEEF0000000000000010; - productRefGroup = C0DEBEEF0000000000000020 /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - C0DEBEEF0000000000000040 /* My Product */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXFrameworksBuildPhase section */ - C0DEBEEF0000000000000056 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - C0DEBEEF00000000000000F7 /* My Product.a in Frameworks */, - C0DEBEEF00000000000000F1 /* UIKit.framework in Frameworks */, - C0DEBEEF00000000000000F2 /* Foundation.framework in Frameworks */, - C0DEBEEF00000000000000F3 /* WebKit.framework in Frameworks */, - C0DEBEEF00000000000000F4 /* Security.framework in Frameworks */, - C0DEBEEF00000000000000F5 /* CoreFoundation.framework in Frameworks */, - C0DEBEEF00000000000000F6 /* libresolv.tbd in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXShellScriptBuildPhase section */ - C0DEBEEF0000000000000055 /* Prebuild: Wails Go Archive */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - ); - inputPaths = ( - ); - name = "Prebuild: Wails Go Archive"; - outputFileListPaths = ( - ); - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "set -e\nAPP_ROOT=\"${PROJECT_DIR}/../../..\"\nSDK_PATH=$(xcrun --sdk iphonesimulator --show-sdk-path)\nexport GOOS=ios\nexport GOARCH=arm64\nexport CGO_ENABLED=1\nexport CGO_CFLAGS=\"-isysroot ${SDK_PATH} -target arm64-apple-ios15.0-simulator -mios-simulator-version-min=15.0\"\nexport CGO_LDFLAGS=\"-isysroot ${SDK_PATH} -target arm64-apple-ios15.0-simulator\"\ncd \"${APP_ROOT}\"\n# Ensure overlay exists\nif [ ! -f build/ios/xcode/overlay.json ]; then\n wails3 ios overlay:gen -out build/ios/xcode/overlay.json -config build/config.yml || true\nfi\n# Build Go c-archive if missing or older than sources\nif [ ! -f bin/My Product.a ]; then\n echo \"Building Go c-archive...\"\n go build -buildmode=c-archive -overlay build/ios/xcode/overlay.json -o bin/My Product.a\nfi\n"; - }; -/* End PBXShellScriptBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - C0DEBEEF0000000000000050 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - C0DEBEEF0000000000000001 /* main.m in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin XCBuildConfiguration section */ - C0DEBEEF0000000000000090 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - INFOPLIST_FILE = main/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 15.0; - PRODUCT_BUNDLE_IDENTIFIER = "com.mycompany.myproduct"; - PRODUCT_NAME = "My Product"; - CODE_SIGNING_ALLOWED = NO; - SDKROOT = iphonesimulator; - }; - name = Debug; - }; - C0DEBEEF00000000000000A0 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - INFOPLIST_FILE = main/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 15.0; - PRODUCT_BUNDLE_IDENTIFIER = "com.mycompany.myproduct"; - PRODUCT_NAME = "My Product"; - CODE_SIGNING_ALLOWED = NO; - SDKROOT = iphonesimulator; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - C0DEBEEF0000000000000070 /* Build configuration list for PBXNativeTarget "My Product" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - C0DEBEEF0000000000000090 /* Debug */, - C0DEBEEF00000000000000A0 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Debug; - }; - C0DEBEEF0000000000000080 /* Build configuration list for PBXProject "main" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - C0DEBEEF0000000000000090 /* Debug */, - C0DEBEEF00000000000000A0 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Debug; - }; -/* End XCConfigurationList section */ - }; - rootObject = C0DEBEEF0000000000000060 /* Project object */; -} diff --git a/v3/examples/ios/build/ios/xcode/main/Assets.xcassets/AppIcon.appiconset/Contents.json b/v3/examples/ios/build/ios/xcode/main/Assets.xcassets/AppIcon.appiconset/Contents.json deleted file mode 100644 index 46fbb8787..000000000 --- a/v3/examples/ios/build/ios/xcode/main/Assets.xcassets/AppIcon.appiconset/Contents.json +++ /dev/null @@ -1,116 +0,0 @@ -{ - "info" : { - "author" : "xcode", - "version" : 1 - }, - "images" : [ - { - "filename" : "icon-20@2x.png", - "idiom" : "iphone", - "scale" : "2x", - "size" : "20x20" - }, - { - "filename" : "icon-20@3x.png", - "idiom" : "iphone", - "scale" : "3x", - "size" : "20x20" - }, - { - "filename" : "icon-29@2x.png", - "idiom" : "iphone", - "scale" : "2x", - "size" : "29x29" - }, - { - "filename" : "icon-29@3x.png", - "idiom" : "iphone", - "scale" : "3x", - "size" : "29x29" - }, - { - "filename" : "icon-40@2x.png", - "idiom" : "iphone", - "scale" : "2x", - "size" : "40x40" - }, - { - "filename" : "icon-40@3x.png", - "idiom" : "iphone", - "scale" : "3x", - "size" : "40x40" - }, - { - "filename" : "icon-60@2x.png", - "idiom" : "iphone", - "scale" : "2x", - "size" : "60x60" - }, - { - "filename" : "icon-60@3x.png", - "idiom" : "iphone", - "scale" : "3x", - "size" : "60x60" - }, - { - "filename" : "icon-20.png", - "idiom" : "ipad", - "scale" : "1x", - "size" : "20x20" - }, - { - "filename" : "icon-20@2x.png", - "idiom" : "ipad", - "scale" : "2x", - "size" : "20x20" - }, - { - "filename" : "icon-29.png", - "idiom" : "ipad", - "scale" : "1x", - "size" : "29x29" - }, - { - "filename" : "icon-29@2x.png", - "idiom" : "ipad", - "scale" : "2x", - "size" : "29x29" - }, - { - "filename" : "icon-40.png", - "idiom" : "ipad", - "scale" : "1x", - "size" : "40x40" - }, - { - "filename" : "icon-40@2x.png", - "idiom" : "ipad", - "scale" : "2x", - "size" : "40x40" - }, - { - "filename" : "icon-76.png", - "idiom" : "ipad", - "scale" : "1x", - "size" : "76x76" - }, - { - "filename" : "icon-76@2x.png", - "idiom" : "ipad", - "scale" : "2x", - "size" : "76x76" - }, - { - "filename" : "icon-83.5@2x.png", - "idiom" : "ipad", - "scale" : "2x", - "size" : "83.5x83.5" - }, - { - "filename" : "icon-1024.png", - "idiom" : "ios-marketing", - "scale" : "1x", - "size" : "1024x1024" - } - ] -} \ No newline at end of file diff --git a/v3/examples/ios/build/ios/xcode/main/Assets.xcassets/AppIcon.appiconset/icon-1024.png b/v3/examples/ios/build/ios/xcode/main/Assets.xcassets/AppIcon.appiconset/icon-1024.png deleted file mode 100644 index 50d762121..000000000 Binary files a/v3/examples/ios/build/ios/xcode/main/Assets.xcassets/AppIcon.appiconset/icon-1024.png and /dev/null differ diff --git a/v3/examples/ios/build/ios/xcode/main/Assets.xcassets/AppIcon.appiconset/icon-20.png b/v3/examples/ios/build/ios/xcode/main/Assets.xcassets/AppIcon.appiconset/icon-20.png deleted file mode 100644 index 8559d2b1d..000000000 Binary files a/v3/examples/ios/build/ios/xcode/main/Assets.xcassets/AppIcon.appiconset/icon-20.png and /dev/null differ diff --git a/v3/examples/ios/build/ios/xcode/main/Assets.xcassets/AppIcon.appiconset/icon-20@2x.png b/v3/examples/ios/build/ios/xcode/main/Assets.xcassets/AppIcon.appiconset/icon-20@2x.png deleted file mode 100644 index 0f2720a87..000000000 Binary files a/v3/examples/ios/build/ios/xcode/main/Assets.xcassets/AppIcon.appiconset/icon-20@2x.png and /dev/null differ diff --git a/v3/examples/ios/build/ios/xcode/main/Assets.xcassets/AppIcon.appiconset/icon-20@3x.png b/v3/examples/ios/build/ios/xcode/main/Assets.xcassets/AppIcon.appiconset/icon-20@3x.png deleted file mode 100644 index aa0892d9e..000000000 Binary files a/v3/examples/ios/build/ios/xcode/main/Assets.xcassets/AppIcon.appiconset/icon-20@3x.png and /dev/null differ diff --git a/v3/examples/ios/build/ios/xcode/main/Assets.xcassets/AppIcon.appiconset/icon-29.png b/v3/examples/ios/build/ios/xcode/main/Assets.xcassets/AppIcon.appiconset/icon-29.png deleted file mode 100644 index 21de36f8b..000000000 Binary files a/v3/examples/ios/build/ios/xcode/main/Assets.xcassets/AppIcon.appiconset/icon-29.png and /dev/null differ diff --git a/v3/examples/ios/build/ios/xcode/main/Assets.xcassets/AppIcon.appiconset/icon-29@2x.png b/v3/examples/ios/build/ios/xcode/main/Assets.xcassets/AppIcon.appiconset/icon-29@2x.png deleted file mode 100644 index 43f7766ae..000000000 Binary files a/v3/examples/ios/build/ios/xcode/main/Assets.xcassets/AppIcon.appiconset/icon-29@2x.png and /dev/null differ diff --git a/v3/examples/ios/build/ios/xcode/main/Assets.xcassets/AppIcon.appiconset/icon-29@3x.png b/v3/examples/ios/build/ios/xcode/main/Assets.xcassets/AppIcon.appiconset/icon-29@3x.png deleted file mode 100644 index db48d12db..000000000 Binary files a/v3/examples/ios/build/ios/xcode/main/Assets.xcassets/AppIcon.appiconset/icon-29@3x.png and /dev/null differ diff --git a/v3/examples/ios/build/ios/xcode/main/Assets.xcassets/AppIcon.appiconset/icon-40.png b/v3/examples/ios/build/ios/xcode/main/Assets.xcassets/AppIcon.appiconset/icon-40.png deleted file mode 100644 index 0f2720a87..000000000 Binary files a/v3/examples/ios/build/ios/xcode/main/Assets.xcassets/AppIcon.appiconset/icon-40.png and /dev/null differ diff --git a/v3/examples/ios/build/ios/xcode/main/Assets.xcassets/AppIcon.appiconset/icon-40@2x.png b/v3/examples/ios/build/ios/xcode/main/Assets.xcassets/AppIcon.appiconset/icon-40@2x.png deleted file mode 100644 index b0c40d1b7..000000000 Binary files a/v3/examples/ios/build/ios/xcode/main/Assets.xcassets/AppIcon.appiconset/icon-40@2x.png and /dev/null differ diff --git a/v3/examples/ios/build/ios/xcode/main/Assets.xcassets/AppIcon.appiconset/icon-40@3x.png b/v3/examples/ios/build/ios/xcode/main/Assets.xcassets/AppIcon.appiconset/icon-40@3x.png deleted file mode 100644 index a3c751376..000000000 Binary files a/v3/examples/ios/build/ios/xcode/main/Assets.xcassets/AppIcon.appiconset/icon-40@3x.png and /dev/null differ diff --git a/v3/examples/ios/build/ios/xcode/main/Assets.xcassets/AppIcon.appiconset/icon-60@2x.png b/v3/examples/ios/build/ios/xcode/main/Assets.xcassets/AppIcon.appiconset/icon-60@2x.png deleted file mode 100644 index a3c751376..000000000 Binary files a/v3/examples/ios/build/ios/xcode/main/Assets.xcassets/AppIcon.appiconset/icon-60@2x.png and /dev/null differ diff --git a/v3/examples/ios/build/ios/xcode/main/Assets.xcassets/AppIcon.appiconset/icon-60@3x.png b/v3/examples/ios/build/ios/xcode/main/Assets.xcassets/AppIcon.appiconset/icon-60@3x.png deleted file mode 100644 index fe6a86faf..000000000 Binary files a/v3/examples/ios/build/ios/xcode/main/Assets.xcassets/AppIcon.appiconset/icon-60@3x.png and /dev/null differ diff --git a/v3/examples/ios/build/ios/xcode/main/Assets.xcassets/AppIcon.appiconset/icon-76.png b/v3/examples/ios/build/ios/xcode/main/Assets.xcassets/AppIcon.appiconset/icon-76.png deleted file mode 100644 index 8ff321e60..000000000 Binary files a/v3/examples/ios/build/ios/xcode/main/Assets.xcassets/AppIcon.appiconset/icon-76.png and /dev/null differ diff --git a/v3/examples/ios/build/ios/xcode/main/Assets.xcassets/AppIcon.appiconset/icon-76@2x.png b/v3/examples/ios/build/ios/xcode/main/Assets.xcassets/AppIcon.appiconset/icon-76@2x.png deleted file mode 100644 index 8e09d8adc..000000000 Binary files a/v3/examples/ios/build/ios/xcode/main/Assets.xcassets/AppIcon.appiconset/icon-76@2x.png and /dev/null differ diff --git a/v3/examples/ios/build/ios/xcode/main/Assets.xcassets/AppIcon.appiconset/icon-83.5@2x.png b/v3/examples/ios/build/ios/xcode/main/Assets.xcassets/AppIcon.appiconset/icon-83.5@2x.png deleted file mode 100644 index fdfb581c9..000000000 Binary files a/v3/examples/ios/build/ios/xcode/main/Assets.xcassets/AppIcon.appiconset/icon-83.5@2x.png and /dev/null differ diff --git a/v3/examples/ios/build/ios/xcode/main/Info.plist b/v3/examples/ios/build/ios/xcode/main/Info.plist deleted file mode 100644 index c96f4f2ec..000000000 --- a/v3/examples/ios/build/ios/xcode/main/Info.plist +++ /dev/null @@ -1,59 +0,0 @@ - - - - - CFBundleExecutable - wailsapp - CFBundleIdentifier - com.mycompany.myproduct - CFBundleName - My Product - CFBundleDisplayName - My Product - CFBundlePackageType - APPL - CFBundleShortVersionString - 0.0.1 - CFBundleVersion - 0.0.1 - LSRequiresIPhoneOS - - MinimumOSVersion - 15.0 - UILaunchStoryboardName - LaunchScreen - UIRequiredDeviceCapabilities - - armv7 - arm64 - - UISupportedInterfaceOrientations - - UIInterfaceOrientationPortrait - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - UISupportedInterfaceOrientations~ipad - - UIInterfaceOrientationPortrait - UIInterfaceOrientationPortraitUpsideDown - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - NSAppTransportSecurity - - NSAllowsArbitraryLoads - - NSAllowsLocalNetworking - - - - NSHumanReadableCopyright - (c) 2025, My Company - - - CFBundleGetInfoString - Some Product Comments - - - \ No newline at end of file diff --git a/v3/examples/ios/build/ios/xcode/main/LaunchScreen.storyboard b/v3/examples/ios/build/ios/xcode/main/LaunchScreen.storyboard deleted file mode 100644 index d6178d6b5..000000000 --- a/v3/examples/ios/build/ios/xcode/main/LaunchScreen.storyboard +++ /dev/null @@ -1,53 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/v3/examples/ios/build/ios/xcode/main/main.m b/v3/examples/ios/build/ios/xcode/main/main.m deleted file mode 100644 index 0f2e7e8e1..000000000 --- a/v3/examples/ios/build/ios/xcode/main/main.m +++ /dev/null @@ -1,22 +0,0 @@ -// Minimal bootstrap: delegate comes from Go archive (WailsAppDelegate) -#import -#include - -// External Go initialization function from the c-archive (declare before use) -extern void WailsIOSMain(); - -int main(int argc, char * argv[]) { - @autoreleasepool { - // Disable buffering so stdout/stderr from Go log.Printf flush immediately - setvbuf(stdout, NULL, _IONBF, 0); - setvbuf(stderr, NULL, _IONBF, 0); - - // Start Go runtime on a background queue to avoid blocking main thread/UI - dispatch_async(dispatch_get_global_queue(QOS_CLASS_USER_INITIATED, 0), ^{ - WailsIOSMain(); - }); - - // Run UIApplicationMain using WailsAppDelegate provided by the Go archive - return UIApplicationMain(argc, argv, nil, @"WailsAppDelegate"); - } -} \ No newline at end of file diff --git a/v3/examples/ios/build/ios/xcode/overlay.json b/v3/examples/ios/build/ios/xcode/overlay.json deleted file mode 100644 index 9ceefc4dc..000000000 --- a/v3/examples/ios/build/ios/xcode/overlay.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "Replace": { - "/Users/leaanthony/test/wails/v3/examples/ios/main_ios.gen.go": "/Users/leaanthony/test/wails/v3/examples/ios/build/ios/xcode/gen/main_ios.gen.go" - } -} \ No newline at end of file diff --git a/v3/examples/ios/build/linux/Taskfile.yml b/v3/examples/ios/build/linux/Taskfile.yml deleted file mode 100644 index 87fd599cc..000000000 --- a/v3/examples/ios/build/linux/Taskfile.yml +++ /dev/null @@ -1,119 +0,0 @@ -version: '3' - -includes: - common: ../Taskfile.yml - -tasks: - build: - summary: Builds the application for Linux - deps: - - task: common:go:mod:tidy - - task: common:build:frontend - vars: - BUILD_FLAGS: - ref: .BUILD_FLAGS - PRODUCTION: - ref: .PRODUCTION - - task: common:generate:icons - cmds: - - go build {{.BUILD_FLAGS}} -o {{.BIN_DIR}}/{{.APP_NAME}} - vars: - BUILD_FLAGS: '{{if eq .PRODUCTION "true"}}-tags production -trimpath -buildvcs=false -ldflags="-w -s"{{else}}-buildvcs=false -gcflags=all="-l"{{end}}' - env: - GOOS: linux - CGO_ENABLED: 1 - GOARCH: '{{.ARCH | default ARCH}}' - PRODUCTION: '{{.PRODUCTION | default "false"}}' - - package: - summary: Packages a production build of the application for Linux - deps: - - task: build - vars: - PRODUCTION: "true" - cmds: - - task: create:appimage - - task: create:deb - - task: create:rpm - - task: create:aur - - create:appimage: - summary: Creates an AppImage - dir: build/linux/appimage - deps: - - task: build - vars: - PRODUCTION: "true" - - task: generate:dotdesktop - cmds: - - cp {{.APP_BINARY}} {{.APP_NAME}} - - cp ../../appicon.png appicon.png - - wails3 generate appimage -binary {{.APP_NAME}} -icon {{.ICON}} -desktopfile {{.DESKTOP_FILE}} -outputdir {{.OUTPUT_DIR}} -builddir {{.ROOT_DIR}}/build/linux/appimage/build - vars: - APP_NAME: '{{.APP_NAME}}' - APP_BINARY: '../../../bin/{{.APP_NAME}}' - ICON: '../../appicon.png' - DESKTOP_FILE: '../{{.APP_NAME}}.desktop' - OUTPUT_DIR: '../../../bin' - - create:deb: - summary: Creates a deb package - deps: - - task: build - vars: - PRODUCTION: "true" - cmds: - - task: generate:dotdesktop - - task: generate:deb - - create:rpm: - summary: Creates a rpm package - deps: - - task: build - vars: - PRODUCTION: "true" - cmds: - - task: generate:dotdesktop - - task: generate:rpm - - create:aur: - summary: Creates a arch linux packager package - deps: - - task: build - vars: - PRODUCTION: "true" - cmds: - - task: generate:dotdesktop - - task: generate:aur - - generate:deb: - summary: Creates a deb package - cmds: - - wails3 tool package -name {{.APP_NAME}} -format deb -config ./build/linux/nfpm/nfpm.yaml -out {{.ROOT_DIR}}/bin - - generate:rpm: - summary: Creates a rpm package - cmds: - - wails3 tool package -name {{.APP_NAME}} -format rpm -config ./build/linux/nfpm/nfpm.yaml -out {{.ROOT_DIR}}/bin - - generate:aur: - summary: Creates a arch linux packager package - cmds: - - wails3 tool package -name {{.APP_NAME}} -format archlinux -config ./build/linux/nfpm/nfpm.yaml -out {{.ROOT_DIR}}/bin - - generate:dotdesktop: - summary: Generates a `.desktop` file - dir: build - cmds: - - mkdir -p {{.ROOT_DIR}}/build/linux/appimage - - wails3 generate .desktop -name "{{.APP_NAME}}" -exec "{{.EXEC}}" -icon "{{.ICON}}" -outputfile {{.ROOT_DIR}}/build/linux/{{.APP_NAME}}.desktop -categories "{{.CATEGORIES}}" - vars: - APP_NAME: '{{.APP_NAME}}' - EXEC: '{{.APP_NAME}}' - ICON: '{{.APP_NAME}}' - CATEGORIES: 'Development;' - OUTPUTFILE: '{{.ROOT_DIR}}/build/linux/{{.APP_NAME}}.desktop' - - run: - cmds: - - '{{.BIN_DIR}}/{{.APP_NAME}}' diff --git a/v3/examples/ios/build/linux/appimage/build.sh b/v3/examples/ios/build/linux/appimage/build.sh deleted file mode 100644 index 858f091ab..000000000 --- a/v3/examples/ios/build/linux/appimage/build.sh +++ /dev/null @@ -1,34 +0,0 @@ -#!/usr/bin/env bash -# Copyright (c) 2018-Present Lea Anthony -# SPDX-License-Identifier: MIT - -# Fail script on any error -set -euxo pipefail - -# Define variables -APP_DIR="${APP_NAME}.AppDir" - -# Create AppDir structure -mkdir -p "${APP_DIR}/usr/bin" -cp -r "${APP_BINARY}" "${APP_DIR}/usr/bin/" -cp "${ICON_PATH}" "${APP_DIR}/" -cp "${DESKTOP_FILE}" "${APP_DIR}/" - -if [[ $(uname -m) == *x86_64* ]]; then - # Download linuxdeploy and make it executable - wget -q -4 -N https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-x86_64.AppImage - chmod +x linuxdeploy-x86_64.AppImage - - # Run linuxdeploy to bundle the application - ./linuxdeploy-x86_64.AppImage --appdir "${APP_DIR}" --output appimage -else - # Download linuxdeploy and make it executable (arm64) - wget -q -4 -N https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-aarch64.AppImage - chmod +x linuxdeploy-aarch64.AppImage - - # Run linuxdeploy to bundle the application (arm64) - ./linuxdeploy-aarch64.AppImage --appdir "${APP_DIR}" --output appimage -fi - -# Rename the generated AppImage -mv "${APP_NAME}*.AppImage" "${APP_NAME}.AppImage" diff --git a/v3/examples/ios/build/linux/desktop b/v3/examples/ios/build/linux/desktop deleted file mode 100644 index e9b30cf39..000000000 --- a/v3/examples/ios/build/linux/desktop +++ /dev/null @@ -1,11 +0,0 @@ -[Desktop Entry] -Version=1.0 -Name=My Product -Comment=My Product Description -# The Exec line includes %u to pass the URL to the application -Exec=/usr/local/bin/ios %u -Terminal=false -Type=Application -Icon=ios -Categories=Utility; -StartupWMClass=ios diff --git a/v3/examples/ios/build/linux/nfpm/nfpm.yaml b/v3/examples/ios/build/linux/nfpm/nfpm.yaml deleted file mode 100644 index 7b78433f4..000000000 --- a/v3/examples/ios/build/linux/nfpm/nfpm.yaml +++ /dev/null @@ -1,67 +0,0 @@ -# Feel free to remove those if you don't want/need to use them. -# Make sure to check the documentation at https://nfpm.goreleaser.com -# -# The lines below are called `modelines`. See `:help modeline` - -name: "ios" -arch: ${GOARCH} -platform: "linux" -version: "0.1.0" -section: "default" -priority: "extra" -maintainer: ${GIT_COMMITTER_NAME} <${GIT_COMMITTER_EMAIL}> -description: "My Product Description" -vendor: "My Company" -homepage: "https://wails.io" -license: "MIT" -release: "1" - -contents: - - src: "./bin/ios" - dst: "/usr/local/bin/ios" - - src: "./build/appicon.png" - dst: "/usr/share/icons/hicolor/128x128/apps/ios.png" - - src: "./build/linux/ios.desktop" - dst: "/usr/share/applications/ios.desktop" - -# Default dependencies for Debian 12/Ubuntu 22.04+ with WebKit 4.1 -depends: - - libgtk-3-0 - - libwebkit2gtk-4.1-0 - -# Distribution-specific overrides for different package formats and WebKit versions -overrides: - # RPM packages for RHEL/CentOS/AlmaLinux/Rocky Linux (WebKit 4.0) - rpm: - depends: - - gtk3 - - webkit2gtk4.1 - - # Arch Linux packages (WebKit 4.1) - archlinux: - depends: - - gtk3 - - webkit2gtk-4.1 - -# scripts section to ensure desktop database is updated after install -scripts: - postinstall: "./build/linux/nfpm/scripts/postinstall.sh" - # You can also add preremove, postremove if needed - # preremove: "./build/linux/nfpm/scripts/preremove.sh" - # postremove: "./build/linux/nfpm/scripts/postremove.sh" - -# replaces: -# - foobar -# provides: -# - bar -# depends: -# - gtk3 -# - libwebkit2gtk -# recommends: -# - whatever -# suggests: -# - something-else -# conflicts: -# - not-foo -# - not-bar -# changelog: "changelog.yaml" diff --git a/v3/examples/ios/build/linux/nfpm/scripts/postinstall.sh b/v3/examples/ios/build/linux/nfpm/scripts/postinstall.sh deleted file mode 100644 index 4bbb815a3..000000000 --- a/v3/examples/ios/build/linux/nfpm/scripts/postinstall.sh +++ /dev/null @@ -1,21 +0,0 @@ -#!/bin/sh - -# Update desktop database for .desktop file changes -# This makes the application appear in application menus and registers its capabilities. -if command -v update-desktop-database >/dev/null 2>&1; then - echo "Updating desktop database..." - update-desktop-database -q /usr/share/applications -else - echo "Warning: update-desktop-database command not found. Desktop file may not be immediately recognized." >&2 -fi - -# Update MIME database for custom URL schemes (x-scheme-handler) -# This ensures the system knows how to handle your custom protocols. -if command -v update-mime-database >/dev/null 2>&1; then - echo "Updating MIME database..." - update-mime-database -n /usr/share/mime -else - echo "Warning: update-mime-database command not found. Custom URL schemes may not be immediately recognized." >&2 -fi - -exit 0 diff --git a/v3/examples/ios/build/linux/nfpm/scripts/postremove.sh b/v3/examples/ios/build/linux/nfpm/scripts/postremove.sh deleted file mode 100644 index a9bf588e2..000000000 --- a/v3/examples/ios/build/linux/nfpm/scripts/postremove.sh +++ /dev/null @@ -1 +0,0 @@ -#!/bin/bash diff --git a/v3/examples/ios/build/linux/nfpm/scripts/preinstall.sh b/v3/examples/ios/build/linux/nfpm/scripts/preinstall.sh deleted file mode 100644 index a9bf588e2..000000000 --- a/v3/examples/ios/build/linux/nfpm/scripts/preinstall.sh +++ /dev/null @@ -1 +0,0 @@ -#!/bin/bash diff --git a/v3/examples/ios/build/linux/nfpm/scripts/preremove.sh b/v3/examples/ios/build/linux/nfpm/scripts/preremove.sh deleted file mode 100644 index a9bf588e2..000000000 --- a/v3/examples/ios/build/linux/nfpm/scripts/preremove.sh +++ /dev/null @@ -1 +0,0 @@ -#!/bin/bash diff --git a/v3/examples/ios/build/windows/Taskfile.yml b/v3/examples/ios/build/windows/Taskfile.yml deleted file mode 100644 index 19f137616..000000000 --- a/v3/examples/ios/build/windows/Taskfile.yml +++ /dev/null @@ -1,98 +0,0 @@ -version: '3' - -includes: - common: ../Taskfile.yml - -tasks: - build: - summary: Builds the application for Windows - deps: - - task: common:go:mod:tidy - - task: common:build:frontend - vars: - BUILD_FLAGS: - ref: .BUILD_FLAGS - PRODUCTION: - ref: .PRODUCTION - - task: common:generate:icons - cmds: - - task: generate:syso - - go build {{.BUILD_FLAGS}} -o {{.BIN_DIR}}/{{.APP_NAME}}.exe - - cmd: powershell Remove-item *.syso - platforms: [windows] - - cmd: rm -f *.syso - platforms: [linux, darwin] - vars: - BUILD_FLAGS: '{{if eq .PRODUCTION "true"}}-tags production -trimpath -buildvcs=false -ldflags="-w -s -H windowsgui"{{else}}-buildvcs=false -gcflags=all="-l"{{end}}' - env: - GOOS: windows - CGO_ENABLED: 0 - GOARCH: '{{.ARCH | default ARCH}}' - PRODUCTION: '{{.PRODUCTION | default "false"}}' - - package: - summary: Packages a production build of the application - cmds: - - |- - if [ "{{.FORMAT | default "nsis"}}" = "msix" ]; then - task: create:msix:package - else - task: create:nsis:installer - fi - vars: - FORMAT: '{{.FORMAT | default "nsis"}}' - - generate:syso: - summary: Generates Windows `.syso` file - dir: build - cmds: - - wails3 generate syso -arch {{.ARCH}} -icon windows/icon.ico -manifest windows/wails.exe.manifest -info windows/info.json -out ../wails_windows_{{.ARCH}}.syso - vars: - ARCH: '{{.ARCH | default ARCH}}' - - create:nsis:installer: - summary: Creates an NSIS installer - dir: build/windows/nsis - deps: - - task: build - vars: - PRODUCTION: "true" - cmds: - # Create the Microsoft WebView2 bootstrapper if it doesn't exist - - wails3 generate webview2bootstrapper -dir "{{.ROOT_DIR}}/build/windows/nsis" - - makensis -DARG_WAILS_{{.ARG_FLAG}}_BINARY="{{.ROOT_DIR}}/{{.BIN_DIR}}/{{.APP_NAME}}.exe" project.nsi - vars: - ARCH: '{{.ARCH | default ARCH}}' - ARG_FLAG: '{{if eq .ARCH "amd64"}}AMD64{{else}}ARM64{{end}}' - - create:msix:package: - summary: Creates an MSIX package - deps: - - task: build - vars: - PRODUCTION: "true" - cmds: - - |- - wails3 tool msix \ - --config "{{.ROOT_DIR}}/wails.json" \ - --name "{{.APP_NAME}}" \ - --executable "{{.ROOT_DIR}}/{{.BIN_DIR}}/{{.APP_NAME}}.exe" \ - --arch "{{.ARCH}}" \ - --out "{{.ROOT_DIR}}/{{.BIN_DIR}}/{{.APP_NAME}}-{{.ARCH}}.msix" \ - {{if .CERT_PATH}}--cert "{{.CERT_PATH}}"{{end}} \ - {{if .PUBLISHER}}--publisher "{{.PUBLISHER}}"{{end}} \ - {{if .USE_MSIX_TOOL}}--use-msix-tool{{else}}--use-makeappx{{end}} - vars: - ARCH: '{{.ARCH | default ARCH}}' - CERT_PATH: '{{.CERT_PATH | default ""}}' - PUBLISHER: '{{.PUBLISHER | default ""}}' - USE_MSIX_TOOL: '{{.USE_MSIX_TOOL | default "false"}}' - - install:msix:tools: - summary: Installs tools required for MSIX packaging - cmds: - - wails3 tool msix-install-tools - - run: - cmds: - - '{{.BIN_DIR}}/{{.APP_NAME}}.exe' diff --git a/v3/examples/ios/build/windows/icon.ico b/v3/examples/ios/build/windows/icon.ico deleted file mode 100644 index bfa0690b7..000000000 Binary files a/v3/examples/ios/build/windows/icon.ico and /dev/null differ diff --git a/v3/examples/ios/build/windows/info.json b/v3/examples/ios/build/windows/info.json deleted file mode 100644 index 850b2b5b0..000000000 --- a/v3/examples/ios/build/windows/info.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "fixed": { - "file_version": "0.1.0" - }, - "info": { - "0000": { - "ProductVersion": "0.1.0", - "CompanyName": "My Company", - "FileDescription": "My Product Description", - "LegalCopyright": "© now, My Company", - "ProductName": "My Product", - "Comments": "This is a comment" - } - } -} \ No newline at end of file diff --git a/v3/examples/ios/build/windows/msix/app_manifest.xml b/v3/examples/ios/build/windows/msix/app_manifest.xml deleted file mode 100644 index ecf2506b3..000000000 --- a/v3/examples/ios/build/windows/msix/app_manifest.xml +++ /dev/null @@ -1,52 +0,0 @@ - - - - - - - My Product - My Company - My Product Description - Assets\StoreLogo.png - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/v3/examples/ios/build/windows/msix/template.xml b/v3/examples/ios/build/windows/msix/template.xml deleted file mode 100644 index cab2f31e0..000000000 --- a/v3/examples/ios/build/windows/msix/template.xml +++ /dev/null @@ -1,54 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - false - My Product - My Company - My Product Description - Assets\AppIcon.png - - - - - - - diff --git a/v3/examples/ios/build/windows/nsis/project.nsi b/v3/examples/ios/build/windows/nsis/project.nsi deleted file mode 100644 index 74b8d6ad0..000000000 --- a/v3/examples/ios/build/windows/nsis/project.nsi +++ /dev/null @@ -1,112 +0,0 @@ -Unicode true - -#### -## Please note: Template replacements don't work in this file. They are provided with default defines like -## mentioned underneath. -## If the keyword is not defined, "wails_tools.nsh" will populate them. -## If they are defined here, "wails_tools.nsh" will not touch them. This allows you to use this project.nsi manually -## from outside of Wails for debugging and development of the installer. -## -## For development first make a wails nsis build to populate the "wails_tools.nsh": -## > wails build --target windows/amd64 --nsis -## Then you can call makensis on this file with specifying the path to your binary: -## For a AMD64 only installer: -## > makensis -DARG_WAILS_AMD64_BINARY=..\..\bin\app.exe -## For a ARM64 only installer: -## > makensis -DARG_WAILS_ARM64_BINARY=..\..\bin\app.exe -## For a installer with both architectures: -## > makensis -DARG_WAILS_AMD64_BINARY=..\..\bin\app-amd64.exe -DARG_WAILS_ARM64_BINARY=..\..\bin\app-arm64.exe -#### -## The following information is taken from the wails_tools.nsh file, but they can be overwritten here. -#### -## !define INFO_PROJECTNAME "my-project" # Default "ios" -## !define INFO_COMPANYNAME "My Company" # Default "My Company" -## !define INFO_PRODUCTNAME "My Product Name" # Default "My Product" -## !define INFO_PRODUCTVERSION "1.0.0" # Default "0.1.0" -## !define INFO_COPYRIGHT "(c) Now, My Company" # Default "© now, My Company" -### -## !define PRODUCT_EXECUTABLE "Application.exe" # Default "${INFO_PROJECTNAME}.exe" -## !define UNINST_KEY_NAME "UninstKeyInRegistry" # Default "${INFO_COMPANYNAME}${INFO_PRODUCTNAME}" -#### -## !define REQUEST_EXECUTION_LEVEL "admin" # Default "admin" see also https://nsis.sourceforge.io/Docs/Chapter4.html -#### -## Include the wails tools -#### -!include "wails_tools.nsh" - -# The version information for this two must consist of 4 parts -VIProductVersion "${INFO_PRODUCTVERSION}.0" -VIFileVersion "${INFO_PRODUCTVERSION}.0" - -VIAddVersionKey "CompanyName" "${INFO_COMPANYNAME}" -VIAddVersionKey "FileDescription" "${INFO_PRODUCTNAME} Installer" -VIAddVersionKey "ProductVersion" "${INFO_PRODUCTVERSION}" -VIAddVersionKey "FileVersion" "${INFO_PRODUCTVERSION}" -VIAddVersionKey "LegalCopyright" "${INFO_COPYRIGHT}" -VIAddVersionKey "ProductName" "${INFO_PRODUCTNAME}" - -# Enable HiDPI support. https://nsis.sourceforge.io/Reference/ManifestDPIAware -ManifestDPIAware true - -!include "MUI.nsh" - -!define MUI_ICON "..\icon.ico" -!define MUI_UNICON "..\icon.ico" -# !define MUI_WELCOMEFINISHPAGE_BITMAP "resources\leftimage.bmp" #Include this to add a bitmap on the left side of the Welcome Page. Must be a size of 164x314 -!define MUI_FINISHPAGE_NOAUTOCLOSE # Wait on the INSTFILES page so the user can take a look into the details of the installation steps -!define MUI_ABORTWARNING # This will warn the user if they exit from the installer. - -!insertmacro MUI_PAGE_WELCOME # Welcome to the installer page. -# !insertmacro MUI_PAGE_LICENSE "resources\eula.txt" # Adds a EULA page to the installer -!insertmacro MUI_PAGE_DIRECTORY # In which folder install page. -!insertmacro MUI_PAGE_INSTFILES # Installing page. -!insertmacro MUI_PAGE_FINISH # Finished installation page. - -!insertmacro MUI_UNPAGE_INSTFILES # Uninstalling page - -!insertmacro MUI_LANGUAGE "English" # Set the Language of the installer - -## The following two statements can be used to sign the installer and the uninstaller. The path to the binaries are provided in %1 -#!uninstfinalize 'signtool --file "%1"' -#!finalize 'signtool --file "%1"' - -Name "${INFO_PRODUCTNAME}" -OutFile "..\..\..\bin\${INFO_PROJECTNAME}-${ARCH}-installer.exe" # Name of the installer's file. -InstallDir "$PROGRAMFILES64\${INFO_COMPANYNAME}\${INFO_PRODUCTNAME}" # Default installing folder ($PROGRAMFILES is Program Files folder). -ShowInstDetails show # This will always show the installation details. - -Function .onInit - !insertmacro wails.checkArchitecture -FunctionEnd - -Section - !insertmacro wails.setShellContext - - !insertmacro wails.webview2runtime - - SetOutPath $INSTDIR - - !insertmacro wails.files - - CreateShortcut "$SMPROGRAMS\${INFO_PRODUCTNAME}.lnk" "$INSTDIR\${PRODUCT_EXECUTABLE}" - CreateShortCut "$DESKTOP\${INFO_PRODUCTNAME}.lnk" "$INSTDIR\${PRODUCT_EXECUTABLE}" - - !insertmacro wails.associateFiles - - !insertmacro wails.writeUninstaller -SectionEnd - -Section "uninstall" - !insertmacro wails.setShellContext - - RMDir /r "$AppData\${PRODUCT_EXECUTABLE}" # Remove the WebView2 DataPath - - RMDir /r $INSTDIR - - Delete "$SMPROGRAMS\${INFO_PRODUCTNAME}.lnk" - Delete "$DESKTOP\${INFO_PRODUCTNAME}.lnk" - - !insertmacro wails.unassociateFiles - - !insertmacro wails.deleteUninstaller -SectionEnd diff --git a/v3/examples/ios/build/windows/nsis/wails_tools.nsh b/v3/examples/ios/build/windows/nsis/wails_tools.nsh deleted file mode 100644 index dc9aebc17..000000000 --- a/v3/examples/ios/build/windows/nsis/wails_tools.nsh +++ /dev/null @@ -1,212 +0,0 @@ -# DO NOT EDIT - Generated automatically by `wails build` - -!include "x64.nsh" -!include "WinVer.nsh" -!include "FileFunc.nsh" - -!ifndef INFO_PROJECTNAME - !define INFO_PROJECTNAME "ios" -!endif -!ifndef INFO_COMPANYNAME - !define INFO_COMPANYNAME "My Company" -!endif -!ifndef INFO_PRODUCTNAME - !define INFO_PRODUCTNAME "My Product" -!endif -!ifndef INFO_PRODUCTVERSION - !define INFO_PRODUCTVERSION "0.1.0" -!endif -!ifndef INFO_COPYRIGHT - !define INFO_COPYRIGHT "© now, My Company" -!endif -!ifndef PRODUCT_EXECUTABLE - !define PRODUCT_EXECUTABLE "${INFO_PROJECTNAME}.exe" -!endif -!ifndef UNINST_KEY_NAME - !define UNINST_KEY_NAME "${INFO_COMPANYNAME}${INFO_PRODUCTNAME}" -!endif -!define UNINST_KEY "Software\Microsoft\Windows\CurrentVersion\Uninstall\${UNINST_KEY_NAME}" - -!ifndef REQUEST_EXECUTION_LEVEL - !define REQUEST_EXECUTION_LEVEL "admin" -!endif - -RequestExecutionLevel "${REQUEST_EXECUTION_LEVEL}" - -!ifdef ARG_WAILS_AMD64_BINARY - !define SUPPORTS_AMD64 -!endif - -!ifdef ARG_WAILS_ARM64_BINARY - !define SUPPORTS_ARM64 -!endif - -!ifdef SUPPORTS_AMD64 - !ifdef SUPPORTS_ARM64 - !define ARCH "amd64_arm64" - !else - !define ARCH "amd64" - !endif -!else - !ifdef SUPPORTS_ARM64 - !define ARCH "arm64" - !else - !error "Wails: Undefined ARCH, please provide at least one of ARG_WAILS_AMD64_BINARY or ARG_WAILS_ARM64_BINARY" - !endif -!endif - -!macro wails.checkArchitecture - !ifndef WAILS_WIN10_REQUIRED - !define WAILS_WIN10_REQUIRED "This product is only supported on Windows 10 (Server 2016) and later." - !endif - - !ifndef WAILS_ARCHITECTURE_NOT_SUPPORTED - !define WAILS_ARCHITECTURE_NOT_SUPPORTED "This product can't be installed on the current Windows architecture. Supports: ${ARCH}" - !endif - - ${If} ${AtLeastWin10} - !ifdef SUPPORTS_AMD64 - ${if} ${IsNativeAMD64} - Goto ok - ${EndIf} - !endif - - !ifdef SUPPORTS_ARM64 - ${if} ${IsNativeARM64} - Goto ok - ${EndIf} - !endif - - IfSilent silentArch notSilentArch - silentArch: - SetErrorLevel 65 - Abort - notSilentArch: - MessageBox MB_OK "${WAILS_ARCHITECTURE_NOT_SUPPORTED}" - Quit - ${else} - IfSilent silentWin notSilentWin - silentWin: - SetErrorLevel 64 - Abort - notSilentWin: - MessageBox MB_OK "${WAILS_WIN10_REQUIRED}" - Quit - ${EndIf} - - ok: -!macroend - -!macro wails.files - !ifdef SUPPORTS_AMD64 - ${if} ${IsNativeAMD64} - File "/oname=${PRODUCT_EXECUTABLE}" "${ARG_WAILS_AMD64_BINARY}" - ${EndIf} - !endif - - !ifdef SUPPORTS_ARM64 - ${if} ${IsNativeARM64} - File "/oname=${PRODUCT_EXECUTABLE}" "${ARG_WAILS_ARM64_BINARY}" - ${EndIf} - !endif -!macroend - -!macro wails.writeUninstaller - WriteUninstaller "$INSTDIR\uninstall.exe" - - SetRegView 64 - WriteRegStr HKLM "${UNINST_KEY}" "Publisher" "${INFO_COMPANYNAME}" - WriteRegStr HKLM "${UNINST_KEY}" "DisplayName" "${INFO_PRODUCTNAME}" - WriteRegStr HKLM "${UNINST_KEY}" "DisplayVersion" "${INFO_PRODUCTVERSION}" - WriteRegStr HKLM "${UNINST_KEY}" "DisplayIcon" "$INSTDIR\${PRODUCT_EXECUTABLE}" - WriteRegStr HKLM "${UNINST_KEY}" "UninstallString" "$\"$INSTDIR\uninstall.exe$\"" - WriteRegStr HKLM "${UNINST_KEY}" "QuietUninstallString" "$\"$INSTDIR\uninstall.exe$\" /S" - - ${GetSize} "$INSTDIR" "/S=0K" $0 $1 $2 - IntFmt $0 "0x%08X" $0 - WriteRegDWORD HKLM "${UNINST_KEY}" "EstimatedSize" "$0" -!macroend - -!macro wails.deleteUninstaller - Delete "$INSTDIR\uninstall.exe" - - SetRegView 64 - DeleteRegKey HKLM "${UNINST_KEY}" -!macroend - -!macro wails.setShellContext - ${If} ${REQUEST_EXECUTION_LEVEL} == "admin" - SetShellVarContext all - ${else} - SetShellVarContext current - ${EndIf} -!macroend - -# Install webview2 by launching the bootstrapper -# See https://docs.microsoft.com/en-us/microsoft-edge/webview2/concepts/distribution#online-only-deployment -!macro wails.webview2runtime - !ifndef WAILS_INSTALL_WEBVIEW_DETAILPRINT - !define WAILS_INSTALL_WEBVIEW_DETAILPRINT "Installing: WebView2 Runtime" - !endif - - SetRegView 64 - # If the admin key exists and is not empty then webview2 is already installed - ReadRegStr $0 HKLM "SOFTWARE\WOW6432Node\Microsoft\EdgeUpdate\Clients\{F3017226-FE2A-4295-8BDF-00C3A9A7E4C5}" "pv" - ${If} $0 != "" - Goto ok - ${EndIf} - - ${If} ${REQUEST_EXECUTION_LEVEL} == "user" - # If the installer is run in user level, check the user specific key exists and is not empty then webview2 is already installed - ReadRegStr $0 HKCU "Software\Microsoft\EdgeUpdate\Clients\{F3017226-FE2A-4295-8BDF-00C3A9A7E4C5}" "pv" - ${If} $0 != "" - Goto ok - ${EndIf} - ${EndIf} - - SetDetailsPrint both - DetailPrint "${WAILS_INSTALL_WEBVIEW_DETAILPRINT}" - SetDetailsPrint listonly - - InitPluginsDir - CreateDirectory "$pluginsdir\webview2bootstrapper" - SetOutPath "$pluginsdir\webview2bootstrapper" - File "MicrosoftEdgeWebview2Setup.exe" - ExecWait '"$pluginsdir\webview2bootstrapper\MicrosoftEdgeWebview2Setup.exe" /silent /install' - - SetDetailsPrint both - ok: -!macroend - -# Copy of APP_ASSOCIATE and APP_UNASSOCIATE macros from here https://gist.github.com/nikku/281d0ef126dbc215dd58bfd5b3a5cd5b -!macro APP_ASSOCIATE EXT FILECLASS DESCRIPTION ICON COMMANDTEXT COMMAND - ; Backup the previously associated file class - ReadRegStr $R0 SHELL_CONTEXT "Software\Classes\.${EXT}" "" - WriteRegStr SHELL_CONTEXT "Software\Classes\.${EXT}" "${FILECLASS}_backup" "$R0" - - WriteRegStr SHELL_CONTEXT "Software\Classes\.${EXT}" "" "${FILECLASS}" - - WriteRegStr SHELL_CONTEXT "Software\Classes\${FILECLASS}" "" `${DESCRIPTION}` - WriteRegStr SHELL_CONTEXT "Software\Classes\${FILECLASS}\DefaultIcon" "" `${ICON}` - WriteRegStr SHELL_CONTEXT "Software\Classes\${FILECLASS}\shell" "" "open" - WriteRegStr SHELL_CONTEXT "Software\Classes\${FILECLASS}\shell\open" "" `${COMMANDTEXT}` - WriteRegStr SHELL_CONTEXT "Software\Classes\${FILECLASS}\shell\open\command" "" `${COMMAND}` -!macroend - -!macro APP_UNASSOCIATE EXT FILECLASS - ; Backup the previously associated file class - ReadRegStr $R0 SHELL_CONTEXT "Software\Classes\.${EXT}" `${FILECLASS}_backup` - WriteRegStr SHELL_CONTEXT "Software\Classes\.${EXT}" "" "$R0" - - DeleteRegKey SHELL_CONTEXT `Software\Classes\${FILECLASS}` -!macroend - -!macro wails.associateFiles - ; Create file associations - -!macroend - -!macro wails.unassociateFiles - ; Delete app associations - -!macroend \ No newline at end of file diff --git a/v3/examples/ios/build/windows/wails.exe.manifest b/v3/examples/ios/build/windows/wails.exe.manifest deleted file mode 100644 index 025555a69..000000000 --- a/v3/examples/ios/build/windows/wails.exe.manifest +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - - - - - true/pm - permonitorv2,permonitor - - - - - - - - - - \ No newline at end of file diff --git a/v3/examples/ios/frontend/Inter Font License.txt b/v3/examples/ios/frontend/Inter Font License.txt deleted file mode 100644 index 00287df15..000000000 --- a/v3/examples/ios/frontend/Inter Font License.txt +++ /dev/null @@ -1,93 +0,0 @@ -Copyright 2020 The Inter Project Authors (https://github.com/rsms/inter) - -This Font Software is licensed under the SIL Open Font License, Version 1.1. -This license is copied below, and is also available with a FAQ at: -http://scripts.sil.org/OFL - - ------------------------------------------------------------ -SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 ------------------------------------------------------------ - -PREAMBLE -The goals of the Open Font License (OFL) are to stimulate worldwide -development of collaborative font projects, to support the font creation -efforts of academic and linguistic communities, and to provide a free and -open framework in which fonts may be shared and improved in partnership -with others. - -The OFL allows the licensed fonts to be used, studied, modified and -redistributed freely as long as they are not sold by themselves. The -fonts, including any derivative works, can be bundled, embedded, -redistributed and/or sold with any software provided that any reserved -names are not used by derivative works. The fonts and derivatives, -however, cannot be released under any other type of license. The -requirement for fonts to remain under this license does not apply -to any document created using the fonts or their derivatives. - -DEFINITIONS -"Font Software" refers to the set of files released by the Copyright -Holder(s) under this license and clearly marked as such. This may -include source files, build scripts and documentation. - -"Reserved Font Name" refers to any names specified as such after the -copyright statement(s). - -"Original Version" refers to the collection of Font Software components as -distributed by the Copyright Holder(s). - -"Modified Version" refers to any derivative made by adding to, deleting, -or substituting -- in part or in whole -- any of the components of the -Original Version, by changing formats or by porting the Font Software to a -new environment. - -"Author" refers to any designer, engineer, programmer, technical -writer or other person who contributed to the Font Software. - -PERMISSION & CONDITIONS -Permission is hereby granted, free of charge, to any person obtaining -a copy of the Font Software, to use, study, copy, merge, embed, modify, -redistribute, and sell modified and unmodified copies of the Font -Software, subject to the following conditions: - -1) Neither the Font Software nor any of its individual components, -in Original or Modified Versions, may be sold by itself. - -2) Original or Modified Versions of the Font Software may be bundled, -redistributed and/or sold with any software, provided that each copy -contains the above copyright notice and this license. These can be -included either as stand-alone text files, human-readable headers or -in the appropriate machine-readable metadata fields within text or -binary files as long as those fields can be easily viewed by the user. - -3) No Modified Version of the Font Software may use the Reserved Font -Name(s) unless explicit written permission is granted by the corresponding -Copyright Holder. This restriction only applies to the primary font name as -presented to the users. - -4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font -Software shall not be used to promote, endorse or advertise any -Modified Version, except to acknowledge the contribution(s) of the -Copyright Holder(s) and the Author(s) or with their explicit written -permission. - -5) The Font Software, modified or unmodified, in part or in whole, -must be distributed entirely under this license, and must not be -distributed under any other license. The requirement for fonts to -remain under this license does not apply to any document created -using the Font Software. - -TERMINATION -This license becomes null and void if any of the above conditions are -not met. - -DISCLAIMER -THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT -OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE -COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL -DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM -OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/v3/examples/ios/frontend/bindings/changeme/greetservice.js b/v3/examples/ios/frontend/bindings/changeme/greetservice.js deleted file mode 100644 index 0b93e6d75..000000000 --- a/v3/examples/ios/frontend/bindings/changeme/greetservice.js +++ /dev/null @@ -1,15 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "@wailsio/runtime"; - -/** - * @param {string} name - * @returns {$CancellablePromise} - */ -export function Greet(name) { - return $Call.ByID(1411160069, name); -} diff --git a/v3/examples/ios/frontend/bindings/changeme/index.js b/v3/examples/ios/frontend/bindings/changeme/index.js deleted file mode 100644 index fdf1ff435..000000000 --- a/v3/examples/ios/frontend/bindings/changeme/index.js +++ /dev/null @@ -1,8 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; diff --git a/v3/examples/ios/frontend/index.html b/v3/examples/ios/frontend/index.html deleted file mode 100644 index e5a37ff0c..000000000 --- a/v3/examples/ios/frontend/index.html +++ /dev/null @@ -1,96 +0,0 @@ - - - - - - - - - Wails App - - -
            - -

            Wails + Javascript

            -
            -
            Demo Screens
            -
            - -
            -
            Please enter your name below 👇
            -
            - - -
            -
            - - -
            -
            - -
            -
            - -
            -
            - -
            -
            - -
            -
            - -
            -
            - - -
            -
            - - -
            -
            - - - - -
            -
            - -
            -
            - -
            -
            - -
            -
            - -
            -
            - -
            -
            - - -
            -
            
            -          
            - -
            -
            - -
            - - - diff --git a/v3/examples/ios/frontend/main.js b/v3/examples/ios/frontend/main.js deleted file mode 100644 index ad8064576..000000000 --- a/v3/examples/ios/frontend/main.js +++ /dev/null @@ -1,113 +0,0 @@ -import {GreetService} from "./bindings/changeme"; -import * as Runtime from "@wailsio/runtime"; - -const resultElement = document.getElementById('result'); -const timeElement = document.getElementById('time'); -const deviceInfoElement = document.getElementById('deviceInfo'); -const Events = Runtime.Events; -const IOS = Runtime.IOS; // May be undefined in published package; we guard usages below. - -window.doGreet = () => { - let name = document.getElementById('name').value; - if (!name) { - name = 'anonymous'; - } - GreetService.Greet(name).then((result) => { - resultElement.innerText = result; - }).catch((err) => { - console.log(err); - }); -} - -window.doHaptic = (style) => { - if (!IOS || !IOS.Haptics?.Impact) { - console.warn('IOS runtime not available in @wailsio/runtime. Skipping haptic call.'); - return; - } - IOS.Haptics.Impact(style).catch((err) => { - console.error('Haptics error:', err); - }); -} - -window.getDeviceInfo = async () => { - if (!IOS || !IOS.Device?.Info) { - deviceInfoElement.innerText = 'iOS runtime not available; cannot fetch device info.'; - return; - } - try { - const info = await IOS.Device.Info(); - deviceInfoElement.innerText = JSON.stringify(info, null, 2); - } catch (e) { - deviceInfoElement.innerText = `Error: ${e?.message || e}`; - } -} - -// Generic caller for IOS..(args) -window.iosJsSet = async (methodPath, args) => { - if (!IOS) { - console.warn('IOS runtime not available in @wailsio/runtime.'); - return; - } - try { - const [group, method] = methodPath.split('.'); - const target = IOS?.[group]; - const fn = target?.[method]; - if (typeof fn !== 'function') { - console.warn('IOS method not found:', methodPath); - return; - } - await fn(args); - } catch (e) { - console.error('iosJsSet error for', methodPath, e); - } -} - -// Emit events for Go handlers -window.emitGo = (eventName, data) => { - try { - Events.Emit(eventName, data); - } catch (e) { - console.error('emitGo error:', e); - } -} - -// Toggle helpers for UI switches -window.setGoToggle = (eventName, enabled) => { - emitGo(eventName, { enabled: !!enabled }); -} - -window.setJsToggle = (methodPath, enabled) => { - iosJsSet(methodPath, { enabled: !!enabled }); -} - -Events.On('time', (payload) => { - // payload may be a plain value or an object with a `data` field depending on emitter/runtime - const value = (payload && typeof payload === 'object' && 'data' in payload) ? payload.data : payload; - console.log('[frontend] time event:', payload, '->', value); - timeElement.innerText = value; -}); - -// Simple pane switcher responding to native UITabBar -function showPaneByIndex(index) { - const panes = [ - document.getElementById('screen-bindings'), - document.getElementById('screen-go'), - document.getElementById('screen-js'), - ]; - panes.forEach((el, i) => { - if (!el) return; - if (i === index) el.classList.add('active'); - else el.classList.remove('active'); - }); -} - -// Listen for native tab selection events posted by the iOS layer -window.addEventListener('nativeTabSelected', (e) => { - const idx = (e && e.detail && typeof e.detail.index === 'number') ? e.detail.index : 0; - showPaneByIndex(idx); -}); - -// Ensure default pane is visible on load (index 0) -window.addEventListener('DOMContentLoaded', () => { - showPaneByIndex(0); -}); diff --git a/v3/examples/ios/frontend/package-lock.json b/v3/examples/ios/frontend/package-lock.json deleted file mode 100644 index b0b7dc68f..000000000 --- a/v3/examples/ios/frontend/package-lock.json +++ /dev/null @@ -1,936 +0,0 @@ -{ - "name": "frontend", - "version": "0.0.0", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "frontend", - "version": "0.0.0", - "dependencies": { - "@wailsio/runtime": "latest" - }, - "devDependencies": { - "vite": "^5.0.0" - } - }, - "node_modules/@esbuild/aix-ppc64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", - "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "aix" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/android-arm": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz", - "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/android-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz", - "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/android-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz", - "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/darwin-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz", - "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/darwin-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz", - "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/freebsd-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz", - "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/freebsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz", - "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-arm": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz", - "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz", - "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-ia32": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz", - "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-loong64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz", - "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==", - "cpu": [ - "loong64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-mips64el": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz", - "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==", - "cpu": [ - "mips64el" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-ppc64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz", - "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-riscv64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz", - "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-s390x": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz", - "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==", - "cpu": [ - "s390x" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz", - "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/netbsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz", - "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/openbsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz", - "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/sunos-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz", - "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/win32-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz", - "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/win32-ia32": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz", - "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/win32-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz", - "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.50.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.50.0.tgz", - "integrity": "sha512-lVgpeQyy4fWN5QYebtW4buT/4kn4p4IJ+kDNB4uYNT5b8c8DLJDg6titg20NIg7E8RWwdWZORW6vUFfrLyG3KQ==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/@rollup/rollup-android-arm64": { - "version": "4.50.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.50.0.tgz", - "integrity": "sha512-2O73dR4Dc9bp+wSYhviP6sDziurB5/HCym7xILKifWdE9UsOe2FtNcM+I4xZjKrfLJnq5UR8k9riB87gauiQtw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.50.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.50.0.tgz", - "integrity": "sha512-vwSXQN8T4sKf1RHr1F0s98Pf8UPz7pS6P3LG9NSmuw0TVh7EmaE+5Ny7hJOZ0M2yuTctEsHHRTMi2wuHkdS6Hg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.50.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.50.0.tgz", - "integrity": "sha512-cQp/WG8HE7BCGyFVuzUg0FNmupxC+EPZEwWu2FCGGw5WDT1o2/YlENbm5e9SMvfDFR6FRhVCBePLqj0o8MN7Vw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.50.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.50.0.tgz", - "integrity": "sha512-UR1uTJFU/p801DvvBbtDD7z9mQL8J80xB0bR7DqW7UGQHRm/OaKzp4is7sQSdbt2pjjSS72eAtRh43hNduTnnQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ] - }, - "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.50.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.50.0.tgz", - "integrity": "sha512-G/DKyS6PK0dD0+VEzH/6n/hWDNPDZSMBmqsElWnCRGrYOb2jC0VSupp7UAHHQ4+QILwkxSMaYIbQ72dktp8pKA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ] - }, - "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.50.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.50.0.tgz", - "integrity": "sha512-u72Mzc6jyJwKjJbZZcIYmd9bumJu7KNmHYdue43vT1rXPm2rITwmPWF0mmPzLm9/vJWxIRbao/jrQmxTO0Sm9w==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.50.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.50.0.tgz", - "integrity": "sha512-S4UefYdV0tnynDJV1mdkNawp0E5Qm2MtSs330IyHgaccOFrwqsvgigUD29uT+B/70PDY1eQ3t40+xf6wIvXJyg==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.50.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.50.0.tgz", - "integrity": "sha512-1EhkSvUQXJsIhk4msxP5nNAUWoB4MFDHhtc4gAYvnqoHlaL9V3F37pNHabndawsfy/Tp7BPiy/aSa6XBYbaD1g==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.50.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.50.0.tgz", - "integrity": "sha512-EtBDIZuDtVg75xIPIK1l5vCXNNCIRM0OBPUG+tbApDuJAy9mKago6QxX+tfMzbCI6tXEhMuZuN1+CU8iDW+0UQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-loongarch64-gnu": { - "version": "4.50.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.50.0.tgz", - "integrity": "sha512-BGYSwJdMP0hT5CCmljuSNx7+k+0upweM2M4YGfFBjnFSZMHOLYR0gEEj/dxyYJ6Zc6AiSeaBY8dWOa11GF/ppQ==", - "cpu": [ - "loong64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-ppc64-gnu": { - "version": "4.50.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.50.0.tgz", - "integrity": "sha512-I1gSMzkVe1KzAxKAroCJL30hA4DqSi+wGc5gviD0y3IL/VkvcnAqwBf4RHXHyvH66YVHxpKO8ojrgc4SrWAnLg==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.50.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.50.0.tgz", - "integrity": "sha512-bSbWlY3jZo7molh4tc5dKfeSxkqnf48UsLqYbUhnkdnfgZjgufLS/NTA8PcP/dnvct5CCdNkABJ56CbclMRYCA==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-riscv64-musl": { - "version": "4.50.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.50.0.tgz", - "integrity": "sha512-LSXSGumSURzEQLT2e4sFqFOv3LWZsEF8FK7AAv9zHZNDdMnUPYH3t8ZlaeYYZyTXnsob3htwTKeWtBIkPV27iQ==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.50.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.50.0.tgz", - "integrity": "sha512-CxRKyakfDrsLXiCyucVfVWVoaPA4oFSpPpDwlMcDFQvrv3XY6KEzMtMZrA+e/goC8xxp2WSOxHQubP8fPmmjOQ==", - "cpu": [ - "s390x" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.50.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.50.0.tgz", - "integrity": "sha512-8PrJJA7/VU8ToHVEPu14FzuSAqVKyo5gg/J8xUerMbyNkWkO9j2ExBho/68RnJsMGNJq4zH114iAttgm7BZVkA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.50.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.50.0.tgz", - "integrity": "sha512-SkE6YQp+CzpyOrbw7Oc4MgXFvTw2UIBElvAvLCo230pyxOLmYwRPwZ/L5lBe/VW/qT1ZgND9wJfOsdy0XptRvw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-openharmony-arm64": { - "version": "4.50.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.50.0.tgz", - "integrity": "sha512-PZkNLPfvXeIOgJWA804zjSFH7fARBBCpCXxgkGDRjjAhRLOR8o0IGS01ykh5GYfod4c2yiiREuDM8iZ+pVsT+Q==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openharmony" - ] - }, - "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.50.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.50.0.tgz", - "integrity": "sha512-q7cIIdFvWQoaCbLDUyUc8YfR3Jh2xx3unO8Dn6/TTogKjfwrax9SyfmGGK6cQhKtjePI7jRfd7iRYcxYs93esg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.50.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.50.0.tgz", - "integrity": "sha512-XzNOVg/YnDOmFdDKcxxK410PrcbcqZkBmz+0FicpW5jtjKQxcW1BZJEQOF0NJa6JO7CZhett8GEtRN/wYLYJuw==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.50.0", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.50.0.tgz", - "integrity": "sha512-xMmiWRR8sp72Zqwjgtf3QbZfF1wdh8X2ABu3EaozvZcyHJeU0r+XAnXdKgs4cCAp6ORoYoCygipYP1mjmbjrsg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@types/estree": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", - "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", - "dev": true, - "license": "MIT" - }, - "node_modules/@wailsio/runtime": { - "version": "3.0.0-alpha.66", - "resolved": "https://registry.npmjs.org/@wailsio/runtime/-/runtime-3.0.0-alpha.66.tgz", - "integrity": "sha512-ENLu8rn1griL1gFHJqkq1i+BVxrrA0JPJHYneUJYuf/s54kjuQViW0RKDEe/WTDo56ABpfykrd/T8OYpPUyXUw==", - "license": "MIT" - }, - "node_modules/esbuild": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", - "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=12" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.21.5", - "@esbuild/android-arm": "0.21.5", - "@esbuild/android-arm64": "0.21.5", - "@esbuild/android-x64": "0.21.5", - "@esbuild/darwin-arm64": "0.21.5", - "@esbuild/darwin-x64": "0.21.5", - "@esbuild/freebsd-arm64": "0.21.5", - "@esbuild/freebsd-x64": "0.21.5", - "@esbuild/linux-arm": "0.21.5", - "@esbuild/linux-arm64": "0.21.5", - "@esbuild/linux-ia32": "0.21.5", - "@esbuild/linux-loong64": "0.21.5", - "@esbuild/linux-mips64el": "0.21.5", - "@esbuild/linux-ppc64": "0.21.5", - "@esbuild/linux-riscv64": "0.21.5", - "@esbuild/linux-s390x": "0.21.5", - "@esbuild/linux-x64": "0.21.5", - "@esbuild/netbsd-x64": "0.21.5", - "@esbuild/openbsd-x64": "0.21.5", - "@esbuild/sunos-x64": "0.21.5", - "@esbuild/win32-arm64": "0.21.5", - "@esbuild/win32-ia32": "0.21.5", - "@esbuild/win32-x64": "0.21.5" - } - }, - "node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/nanoid": { - "version": "3.3.11", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", - "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "bin": { - "nanoid": "bin/nanoid.cjs" - }, - "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" - } - }, - "node_modules/picocolors": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", - "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", - "dev": true, - "license": "ISC" - }, - "node_modules/postcss": { - "version": "8.5.6", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", - "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "nanoid": "^3.3.11", - "picocolors": "^1.1.1", - "source-map-js": "^1.2.1" - }, - "engines": { - "node": "^10 || ^12 || >=14" - } - }, - "node_modules/rollup": { - "version": "4.50.0", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.50.0.tgz", - "integrity": "sha512-/Zl4D8zPifNmyGzJS+3kVoyXeDeT/GrsJM94sACNg9RtUE0hrHa1bNPtRSrfHTMH5HjRzce6K7rlTh3Khiw+pw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/estree": "1.0.8" - }, - "bin": { - "rollup": "dist/bin/rollup" - }, - "engines": { - "node": ">=18.0.0", - "npm": ">=8.0.0" - }, - "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.50.0", - "@rollup/rollup-android-arm64": "4.50.0", - "@rollup/rollup-darwin-arm64": "4.50.0", - "@rollup/rollup-darwin-x64": "4.50.0", - "@rollup/rollup-freebsd-arm64": "4.50.0", - "@rollup/rollup-freebsd-x64": "4.50.0", - "@rollup/rollup-linux-arm-gnueabihf": "4.50.0", - "@rollup/rollup-linux-arm-musleabihf": "4.50.0", - "@rollup/rollup-linux-arm64-gnu": "4.50.0", - "@rollup/rollup-linux-arm64-musl": "4.50.0", - "@rollup/rollup-linux-loongarch64-gnu": "4.50.0", - "@rollup/rollup-linux-ppc64-gnu": "4.50.0", - "@rollup/rollup-linux-riscv64-gnu": "4.50.0", - "@rollup/rollup-linux-riscv64-musl": "4.50.0", - "@rollup/rollup-linux-s390x-gnu": "4.50.0", - "@rollup/rollup-linux-x64-gnu": "4.50.0", - "@rollup/rollup-linux-x64-musl": "4.50.0", - "@rollup/rollup-openharmony-arm64": "4.50.0", - "@rollup/rollup-win32-arm64-msvc": "4.50.0", - "@rollup/rollup-win32-ia32-msvc": "4.50.0", - "@rollup/rollup-win32-x64-msvc": "4.50.0", - "fsevents": "~2.3.2" - } - }, - "node_modules/source-map-js": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", - "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/vite": { - "version": "5.4.19", - "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.19.tgz", - "integrity": "sha512-qO3aKv3HoQC8QKiNSTuUM1l9o/XX3+c+VTgLHbJWHZGeTPVAg2XwazI9UWzoxjIJCGCV2zU60uqMzjeLZuULqA==", - "dev": true, - "license": "MIT", - "dependencies": { - "esbuild": "^0.21.3", - "postcss": "^8.4.43", - "rollup": "^4.20.0" - }, - "bin": { - "vite": "bin/vite.js" - }, - "engines": { - "node": "^18.0.0 || >=20.0.0" - }, - "funding": { - "url": "https://github.com/vitejs/vite?sponsor=1" - }, - "optionalDependencies": { - "fsevents": "~2.3.3" - }, - "peerDependencies": { - "@types/node": "^18.0.0 || >=20.0.0", - "less": "*", - "lightningcss": "^1.21.0", - "sass": "*", - "sass-embedded": "*", - "stylus": "*", - "sugarss": "*", - "terser": "^5.4.0" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - }, - "less": { - "optional": true - }, - "lightningcss": { - "optional": true - }, - "sass": { - "optional": true - }, - "sass-embedded": { - "optional": true - }, - "stylus": { - "optional": true - }, - "sugarss": { - "optional": true - }, - "terser": { - "optional": true - } - } - } - } -} diff --git a/v3/examples/ios/frontend/package.json b/v3/examples/ios/frontend/package.json deleted file mode 100644 index 0a118e984..000000000 --- a/v3/examples/ios/frontend/package.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "name": "frontend", - "private": true, - "version": "0.0.0", - "type": "module", - "scripts": { - "dev": "vite", - "build:dev": "vite build --minify false --mode development", - "build": "vite build --mode production", - "preview": "vite preview" - }, - "dependencies": { - "@wailsio/runtime": "latest" - }, - "devDependencies": { - "vite": "^5.0.0" - } -} diff --git a/v3/examples/ios/frontend/public/Inter-Medium.ttf b/v3/examples/ios/frontend/public/Inter-Medium.ttf deleted file mode 100644 index a01f3777a..000000000 Binary files a/v3/examples/ios/frontend/public/Inter-Medium.ttf and /dev/null differ diff --git a/v3/examples/ios/frontend/public/javascript.svg b/v3/examples/ios/frontend/public/javascript.svg deleted file mode 100644 index f9abb2b72..000000000 --- a/v3/examples/ios/frontend/public/javascript.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/v3/examples/ios/frontend/public/puppertino/LICENSE b/v3/examples/ios/frontend/public/puppertino/LICENSE deleted file mode 100644 index ed9065e06..000000000 --- a/v3/examples/ios/frontend/public/puppertino/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2019 Edgar Pérez - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/v3/examples/ios/frontend/public/puppertino/css/actions.css b/v3/examples/ios/frontend/public/puppertino/css/actions.css deleted file mode 100644 index 22a9d5a13..000000000 --- a/v3/examples/ios/frontend/public/puppertino/css/actions.css +++ /dev/null @@ -1,149 +0,0 @@ -:root { - --font: -apple-system, "Inter", sans-serif; - --primary-col-ac: #0f75f5; - --p-modal-bg: rgba(255, 255, 255, 0.8); - --p-modal-bd-color: rgba(0,0,0,.1); - --p-modal-fallback-color: rgba(255,255,255,.95); - --p-actions-static-color: #555761; -} - -.p-modal-opened { - overflow: hidden; -} - -.p-action-background{ - background: rgba(0, 0, 0, 0.7); - height: 100vh; - left: 0; - opacity: 0; - pointer-events: none; - position: fixed; - top: 0; - transition: 0.3s; - width: 100vw; - z-index: 5; -} - -.p-action-background.nowactive { - opacity: 1; - pointer-events: auto; -} - - -.p-action-big-container{ - position:fixed; - width: 100%; - box-sizing: border-box; - padding: 1rem 5vw; - bottom:0; -} - -.p-action-container{ - background: var(--p-modal-bg); - display:block; - margin:auto; - margin-bottom: 10px; - border-radius: 10px; - max-width: 700px; -} - -.p-action-big-container .p-action-container:first-child{ - margin-bottom:10px; -} - -.p-action--intern{ - width: 100%; - display:block; - margin:auto; - font-size: 1rem; - font-weight: 600; - text-align:center; - padding: 15px 0; - border: 0; - border-bottom: 1px solid #bfbfbf; - color: #0f75f5; - text-decoration:none; - background-color: transparent; -} - -.p-action-destructive{ - color: #c6262e; -} - -.p-action-neutral{ - color: var(--p-actions-static-color); -} - -.p-action-cancel, .p-action-container a:last-child{ - border-bottom:none; -} - -.p-action-cancel{ - font-weight:bold; -} - -.p-action-icon{ - position:relative; -} -.p-action-icon svg, .p-action-icon img{ - position:absolute; - left:5%; - top:50%; - transform:translateY(-50%); -} - -.p-action-icon-inline{ - text-align: left; - display: flex; - align-items: center; -} - -.p-action-icon-inline svg, .p-action-icon-inline img{ - margin-left: 5%; - margin-right: 3%; -} - -.p-action-title{ - padding: 30px 15px; - border-bottom: 1px solid #bfbfbf; -} - -.p-action-title--intern,.p-action-text{ - margin:0; - color:var(--p-actions-static-color); -} - -.p-action-title--intern{ - margin-bottom: .3rem; -} - -@supports not (backdrop-filter: blur(10px)) { - .p-action-container { - background: var(--p-modal-fallback-color); - } -} - -.p-action-big-container{ - -webkit-transform: translateY(30%); - transform: translateY(30%); - opacity: 0; - transition: opacity 0.4s, transform 0.4s; - transition-timing-function: ease; - pointer-events: none; -} - -.p-action-big-container.active { - -webkit-transform: translateY(0); - transform: translateY(0); - opacity: 1; - pointer-events: all; -} - - -.p-action-big-container.active .p-action-container { - backdrop-filter: saturate(180%) blur(10px); -} - -.p-action-big-container[aria-hidden="true"] .p-action--intern { - display: none; -} diff --git a/v3/examples/ios/frontend/public/puppertino/css/buttons.css b/v3/examples/ios/frontend/public/puppertino/css/buttons.css deleted file mode 100644 index 4950b0053..000000000 --- a/v3/examples/ios/frontend/public/puppertino/css/buttons.css +++ /dev/null @@ -1,158 +0,0 @@ -@charset "UTF-8"; -:root{ - --p-btn-border: #cacaca; - --p-btn-def-bg: #FFFFFF; - --p-btn-def-col: #000000; - --p-btn-dir-col: #242424; - --p-prim-text-col: #f5f5f5; - --p-btn-scope-unactive: #212136; - --p-btn-scope-action: #212136; -} - -.p-btn { - background: var(--p-btn-def-bg); - border: 1px solid var(--p-btn-border); - border-radius: 10px; - color: var(--p-btn-def-col); - display: inline-block; - font-family: -apple-system, "Inter", sans-serif; - font-size: 1.1rem; - margin: .7rem; - padding: .4rem 1.2rem; - text-decoration: none; - text-align: center; - box-shadow: 0 1px 0.375px rgba(0, 0, 0, 0.05), 0 0.25px 0.375px rgba(0, 0, 0, 0.15); - user-select: none; - cursor: pointer; -} -.p-btn:focus{ - outline: 2px solid #64baff; -} -.p-btn.p-btn-block{ - display: block; -} -.p-btn.p-btn-sm { - padding: .3rem 1.1rem; - font-size: 1rem; -} -.p-btn.p-btn-md { - padding: .8rem 2.4rem; - font-size: 1.6rem; -} -.p-btn.p-btn-lg { - padding: 1.2rem 2.8rem; - font-size: 1.8rem; -} -.p-btn-destructive{ - color: #FF3B30; -} -.p-btn-mob{ - padding: 10px 40px; - background: #227bec; - color: #fff; - border: 0; - box-shadow: inset 0 1px 1px rgb(255 255 255 / 41%), 0px 2px 3px -2px rgba(0,0,0,.3); -} -.p-btn[disabled], -.p-btn:disabled, -.p-btn-disabled{ - filter:contrast(0.5) grayscale(.5) opacity(.8); - cursor: not-allowed; - box-shadow: none; - pointer-events: none; -} - -.p-prim-col { - position: relative; - background: #007AFF; - border: none; - box-shadow: inset 0 1px 1px rgba(255, 255, 255, 0.41), 0px 2px 3px -2px rgba(0, 0, 0, 0.3); - color: var(--p-prim-text-col); - overflow: hidden; /* Ensure the ::before element doesn't overflow */ -} - -.p-prim-col:before { - content: ''; - position: absolute; - top: 0; - left: 0; - width: 100%; - height: 100%; - background: linear-gradient(180deg, rgba(255, 255, 255, 1) 0%, rgba(255, 255, 255, 0) 100%); - opacity: 0.17; - pointer-events: none; -} - -.p-btn.p-prim-col:active { - background: #0f75f5; -} - -.p-btn-more::after { - content: "..."; -} - -.p-btn-round { - border: 0; - border-radius: 50px; - box-shadow: inset 0 1px 1px rgb(255 255 255 / 41%); - padding: 10px 30px; -} - -.p-btn-icon { - align-items: center; - background: var(--p-btn-def-bg); - border: 2px solid currentColor; - border-radius: 50%; - color: #0f75f5; - display: inline-flex; - font-weight: 900; - height: 40px; - width: 40px; - justify-content: center; - margin: 5px; - text-align: center; - text-decoration: none; - box-sizing: border-box; - user-select: none; - vertical-align: bottom; -} - -.p-btn-icon.p-btn-icon-no-border{ - border: 0px; -} - -.p-btn-scope { - background: #8e8e8e; - color: #fff; - margin: 5px; - padding: 2px 20px; - box-shadow: none; -} -.p-btn-scope-unactive { - background: transparent; - border-color: transparent; - color: var(--p-btn-scope-unactive); - transition: border-color 0.2s; -} -.p-btn-scope-unactive:hover { - border-color: var(--p-btn-border); -} - -.p-btn-scope-outline { - background: transparent; - color: var(--p-btn-scope-action); - box-shadow: none; -} - -.p-btn-outline { - background: none; - border-color: currentColor; - box-shadow: none; -} - -.p-btn-outline-dash { - background: none; - border-color: currentColor; - border-style: dashed; - box-shadow: none; -} diff --git a/v3/examples/ios/frontend/public/puppertino/css/cards.css b/v3/examples/ios/frontend/public/puppertino/css/cards.css deleted file mode 100644 index b4fa2e397..000000000 --- a/v3/examples/ios/frontend/public/puppertino/css/cards.css +++ /dev/null @@ -1,55 +0,0 @@ -:root{ - --p-color-card: #1a1a1a; - --p-bg-card: #fff; - --p-bd-card: #c5c5c55e; -} -.p-card { - background: var(--p-bg-card); - border: 1px solid var(--p-bd-card); - color: var(--p-color-card); - display: block; - margin: 15px; - margin-left:7.5px; - margin-right:7.5px; - text-decoration: none; - border-radius: 25px; - padding: 20px 0px; - transition: .3s ease; - box-shadow: 0 0.5px 1px rgba(0, 0, 0, 0.1); -} -.p-card-image > img { - border-bottom: 3px solid var(--accent-article); - display: block; - margin: auto; - width: 100%; -} -.p-card-tags { - display: flex; - overflow: hidden; - position: relative; - width: 100%; -} -.p-card-tags::before { - background: linear-gradient(to right, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0) 75%, white 100%); - content: ""; - height: 100%; - position: absolute; - right: 0; - top: 0; - width: 30%; -} -.p-card-title { - font-size: 2rem; - margin-bottom: 15px; - margin-top: 15px; -} -.p-card-content { - padding: 15px; - padding-top: 15px; -} -.p-card-text { - font-size: 17px; - margin-bottom: 10px; - margin-left: 10px; - margin-top: 0; -} diff --git a/v3/examples/ios/frontend/public/puppertino/css/color_palette.css b/v3/examples/ios/frontend/public/puppertino/css/color_palette.css deleted file mode 100644 index 33a66b91c..000000000 --- a/v3/examples/ios/frontend/public/puppertino/css/color_palette.css +++ /dev/null @@ -1,917 +0,0 @@ -:root{ ---p-strawberry: #c6262e; ---p-strawberry-100: #ff8c82; ---p-strawberry-300: #ed5353; ---p-strawberry-500: #c6262e; ---p-strawberry-700: #a10705; ---p-strawberry-900: #7a0000; - ---p-orange: #f37329; ---p-orange-100: #ffc27d; ---p-orange-300: #ffa154; ---p-orange-500: #f37329; ---p-orange-700: #cc3b02; ---p-orange-900: #a62100; - - ---p-banana: #f9c440; ---p-banana-100: #fff394; ---p-banana-300: #ffe16b; ---p-banana-500: #f9c440; ---p-banana-700: #d48e15; ---p-banana-900: #ad5f00; - ---p-lime: #68b723; ---p-lime-100: #d1ff82; ---p-lime-300: #9bdb4d; ---p-lime-500: #68b723; ---p-lime-700: #3a9104; ---p-lime-900: #206b00; - ---p-mint: #28bca3; ---p-mint-100: #89ffdd; ---p-mint-300: #43d6b5; ---p-mint-500: #28bca3; ---p-mint-700: #0e9a83; ---p-mint-900: #007367; - - ---p-blueberry: #3689e6; ---p-blueberry-100: #8cd5ff; ---p-blueberry-300: #64baff; ---p-blueberry-500: #3689e6; ---p-blueberry-700: #0d52bf; ---p-blueberry-900: #002e99; - ---p-grape: #a56de2; ---p-grape-100: #e4c6fa; ---p-grape-300: #cd9ef7; ---p-grape-500: #a56de2; ---p-grape-700: #7239b3; ---p-grape-900: #452981; - ---p-bubblegum: #de3e80; ---p-bubblegum-100: #fe9ab8; ---p-bubblegum-300: #f4679d; ---p-bubblegum-500: #de3e80; ---p-bubblegum-700: #bc245d; ---p-bubblegum-900: #910e38; - - ---p-cocoa: #715344; ---p-cocoa-100: #a3907c; ---p-cocoa-300: #8a715e; ---p-cocoa-500: #715344; ---p-cocoa-700: #57392d; ---p-cocoa-900: #3d211b; - ---p-silver: #abacae; ---p-silver-100: #fafafa; ---p-silver-300: #d4d4d4; ---p-silver-500: #abacae; ---p-silver-700: #7e8087; ---p-silver-900: #555761; - ---p-slate: #485a6c; ---p-slate-100: #95a3ab; ---p-slate-300: #667885; ---p-slate-500: #485a6c; ---p-slate-700: #273445; ---p-slate-900: #0e141f; - - ---p-dark: #333; ---p-dark-100: #666; ---p-dark-300: #4d4d4d; ---p-dark-500: #333; ---p-dark-700: #1a1a1a; ---p-dark-900: #000; - - ---p-apple-red: rgb(255, 59 , 48); ---p-apple-red-dark: rgb(255, 69 , 58); ---p-apple-orange: rgb(255,149,0); ---p-apple-orange-dark: rgb(255,159,10); ---p-apple-yellow: rgb(255,204,0); ---p-apple-yellow-dark: rgb(255,214,10); ---p-apple-green: rgb(40,205,65); ---p-apple-green-dark: rgb(40,215,75); ---p-apple-mint: rgb(0,199,190); ---p-apple-mint-dark: rgb(102,212,207); ---p-apple-teal: rgb(89, 173, 196); ---p-apple-teal-dark: rgb(106, 196, 220); ---p-apple-cyan: rgb(85,190,240); ---p-apple-cyan-dark: rgb(90,200,245); ---p-apple-blue: rgb(0, 122, 255); ---p-apple-blue-dark: rgb(10, 132, 255); ---p-apple-indigo: rgb(88, 86, 214); ---p-apple-indigo-dark: rgb(94, 92, 230); ---p-apple-purple: rgb(175, 82, 222); ---p-apple-purple-dark: rgb(191, 90, 242); ---p-apple-pink: rgb(255, 45, 85); ---p-apple-pink-dark: rgb(255, 55, 95); ---p-apple-brown: rgb(162, 132, 94); ---p-apple-brown-dark: rgb(172, 142, 104); ---p-apple-gray: rgb(142, 142, 147); ---p-apple-gray-dark: rgb(152, 152, 157); - -} - - -/* -APPLE OFFICIAL COLORS -*/ - -.p-apple-red{ - background: rgb(255, 59 , 48); -} - -.p-apple-red-dark{ - background: rgb(255, 69 , 58); -} - -.p-apple-orange{ - background: rgb(255,149,0); -} - -.p-apple-orange-dark{ - background: rgb(255,159,10); -} - -.p-apple-yellow{ - background: rgb(255,204,0); -} - -.p-apple-yellow-dark{ - background: rgb(255,214,10); -} - -.p-apple-green{ - background: rgb(40,205,65); -} - -.p-apple-green-dark{ - background: rgb(40,215,75); -} - -.p-apple-mint{ - background: rgb(0,199,190); -} - -.p-apple-mint-dark{ - background: rgb(102,212,207); -} - -.p-apple-teal{ - background: rgb(89, 173, 196); -} - -.p-apple-teal-dark{ - background: rgb(106, 196, 220); -} - -.p-apple-cyan{ - background: rgb(85,190,240); -} - -.p-apple-cyan-dark{ - background: rgb(90,200,245); -} - -.p-apple-blue{ - background: rgb(0, 122, 255); -} - -.p-apple-blue-dark{ - background: rgb(10, 132, 255); -} - -.p-apple-indigo{ - background: rgb(88, 86, 214); -} - -.p-apple-indigo-dark{ - background: rgb(94, 92, 230); -} - -.p-apple-purple{ - background: rgb(175, 82, 222); -} - -.p-apple-purple-dark{ - background: rgb(191, 90, 242); -} - -.p-apple-pink{ - background: rgb(255, 45, 85); -} - -.p-apple-pink-dark{ - background: rgb(255, 55, 95); -} - -.p-apple-brown{ - background: rgb(162, 132, 94); -} - -.p-apple-brown-dark{ - background: rgb(172, 142, 104); -} - -.p-apple-gray{ - background: rgb(142, 142, 147); -} - -.p-apple-gray-dark{ - background: rgb(152, 152, 157); -} - -.p-apple-red-color{ - color: rgb(255, 59 , 48); -} - -.p-apple-red-dark-color{ - color: rgb(255, 69 , 58); -} - -.p-apple-orange-color{ - color: rgb(255,149,0); -} - -.p-apple-orange-dark-color{ - color: rgb(255,159,10); -} - -.p-apple-yellow-color{ - color: rgb(255,204,0); -} - -.p-apple-yellow-dark-color{ - color: rgb(255,214,10); -} - -.p-apple-green-color{ - color: rgb(40,205,65); -} - -.p-apple-green-dark-color{ - color: rgb(40,215,75); -} - -.p-apple-mint-color{ - color: rgb(0,199,190); -} - -.p-apple-mint-dark-color{ - color: rgb(102,212,207); -} - -.p-apple-teal-color{ - color: rgb(89, 173, 196); -} - -.p-apple-teal-dark-color{ - color: rgb(106, 196, 220); -} - -.p-apple-cyan-color{ - color: rgb(85,190,240); -} - -.p-apple-cyan-dark-color{ - color: rgb(90,200,245); -} - -.p-apple-blue-color{ - color: rgb(0, 122, 255); -} - -.p-apple-blue-dark-color{ - color: rgb(10, 132, 255); -} - -.p-apple-indigo-color{ - color: rgb(88, 86, 214); -} - -.p-apple-indigo-dark-color{ - color: rgb(94, 92, 230); -} - -.p-apple-purple-color{ - color: rgb(175, 82, 222); -} - -.p-apple-purple-dark-color{ - color: rgb(191, 90, 242); -} - -.p-apple-pink-color{ - color: rgb(255, 45, 85); -} - -.p-apple-pink-dark-color{ - color: rgb(255, 55, 95); -} - -.p-apple-brown-color{ - color: rgb(162, 132, 94); -} - -.p-apple-brown-dark-color{ - color: rgb(172, 142, 104); -} - -.p-apple-gray-color{ - color: rgb(142, 142, 147); -} - -.p-apple-gray-dark-color{ - color: rgb(152, 152, 157); -} - -.p-strawberry { - background: #c6262e; -} - -.p-strawberry-100 { - background: #ff8c82; -} - -.p-strawberry-300 { - background: #ed5353; -} - -.p-strawberry-500 { - background: #c6262e; -} - -.p-strawberry-700 { - background: #a10705; -} - -.p-strawberry-900 { - background: #7a0000; -} - -.p-orange { - background: #f37329; -} - -.p-orange-100 { - background: #ffc27d; -} - -.p-orange-300 { - background: #ffa154; -} - -.p-orange-500 { - background: #f37329; -} - -.p-orange-700 { - background: #cc3b02; -} - -.p-orange-900 { - background: #a62100; -} - -.p-banana { - background: #f9c440; -} - -.p-banana-100 { - background: #fff394; -} - -.p-banana-300 { - background: #ffe16b; -} - -.p-banana-500 { - background: #f9c440; -} - -.p-banana-700 { - background: #d48e15; -} - -.p-banana-900 { - background: #ad5f00; -} - -.p-lime { - background: #68b723; -} - -.p-lime-100 { - background: #d1ff82; -} - -.p-lime-300 { - background: #9bdb4d; -} - -.p-lime-500 { - background: #68b723; -} - -.p-lime-700 { - background: #3a9104; -} - -.p-lime-900 { - background: #206b00; -} - -.p-mint { - background: #28bca3; -} - -.p-mint-100 { - background: #89ffdd; -} - -.p-mint-300 { - background: #43d6b5; -} - -.p-mint-500 { - background: #28bca3; -} - -.p-mint-700 { - background: #0e9a83; -} - -.p-mint-900 { - background: #007367; -} - -.p-blueberry { - background: #3689e6; -} - -.p-blueberry-100 { - background: #8cd5ff; -} - -.p-blueberry-300 { - background: #64baff; -} - -.p-blueberry-500 { - background: #3689e6; -} - -.p-blueberry-700 { - background: #0d52bf; -} - -.p-blueberry-900 { - background: #002e99; -} - -.p-grape { - background: #a56de2; -} - -.p-grape-100 { - background: #e4c6fa; -} - -.p-grape-300 { - background: #cd9ef7; -} - -.p-grape-500 { - background: #a56de2; -} - -.p-grape-700 { - background: #7239b3; -} - -.p-grape-900 { - background: #452981; -} - -.p-bubblegum { - background: #de3e80; -} - -.p-bubblegum-100 { - background: #fe9ab8; -} - -.p-bubblegum-300 { - background: #f4679d; -} - -.p-bubblegum-500 { - background: #de3e80; -} - -.p-bubblegum-700 { - background: #bc245d; -} - -.p-bubblegum-900 { - background: #910e38; -} - -.p-cocoa { - background: #715344; -} - -.p-cocoa-100 { - background: #a3907c; -} - -.p-cocoa-300 { - background: #8a715e; -} - -.p-cocoa-500 { - background: #715344; -} - -.p-cocoa-700 { - background: #57392d; -} - -.p-cocoa-900 { - background: #3d211b; -} - -.p-silver { - background: #abacae; -} - -.p-silver-100 { - background: #fafafa; -} - -.p-silver-300 { - background: #d4d4d4; -} - -.p-silver-500 { - background: #abacae; -} - -.p-silver-700 { - background: #7e8087; -} - -.p-silver-900 { - background: #555761; -} - -.p-slate { - background: #485a6c; -} - -.p-slate-100 { - background: #95a3ab; -} - -.p-slate-300 { - background: #667885; -} - -.p-slate-500 { - background: #485a6c; -} - -.p-slate-700 { - background: #273445; -} - -.p-slate-900 { - background: #0e141f; -} - -.p-dark { - background: #333; -} - -.p-dark-100 { - background: #666; - /* hehe */ -} - -.p-dark-300 { - background: #4d4d4d; -} - -.p-dark-500 { - background: #333; -} - -.p-dark-700 { - background: #1a1a1a; -} - -.p-dark-900 { - background: #000; -} - -.p-white{ - background: #fff; -} - -.p-strawberry-color { - color: #c6262e; -} - -.p-strawberry-100-color { - color: #ff8c82; -} - -.p-strawberry-300-color { - color: #ed5353; -} - -.p-strawberry-500-color { - color: #c6262e; -} - -.p-strawberry-700-color { - color: #a10705; -} - -.p-strawberry-900-color { - color: #7a0000; -} - -.p-orange-color { - color: #f37329; -} - -.p-orange-100-color { - color: #ffc27d; -} - -.p-orange-300-color { - color: #ffa154; -} - -.p-orange-500-color { - color: #f37329; -} - -.p-orange-700-color { - color: #cc3b02; -} - -.p-orange-900-color { - color: #a62100; -} - -.p-banana-color { - color: #f9c440; -} - -.p-banana-100-color { - color: #fff394; -} - -.p-banana-300-color { - color: #ffe16b; -} - -.p-banana-500-color { - color: #f9c440; -} - -.p-banana-700-color { - color: #d48e15; -} - -.p-banana-900-color { - color: #ad5f00; -} - -.p-lime-color { - color: #68b723; -} - -.p-lime-100-color { - color: #d1ff82; -} - -.p-lime-300-color { - color: #9bdb4d; -} - -.p-lime-500-color { - color: #68b723; -} - -.p-lime-700-color { - color: #3a9104; -} - -.p-lime-900-color { - color: #206b00; -} - -.p-mint-color { - color: #28bca3; -} - -.p-mint-100-color { - color: #89ffdd; -} - -.p-mint-300-color { - color: #43d6b5; -} - -.p-mint-500-color { - color: #28bca3; -} - -.p-mint-700-color { - color: #0e9a83; -} - -.p-mint-900-color { - color: #007367; -} - -.p-blueberry-color { - color: #3689e6; -} - -.p-blueberry-100-color { - color: #8cd5ff; -} - -.p-blueberry-300-color { - color: #64baff; -} - -.p-blueberry-500-color { - color: #3689e6; -} - -.p-blueberry-700-color { - color: #0d52bf; -} - -.p-blueberry-900-color { - color: #002e99; -} - -.p-grape-color { - color: #a56de2; -} - -.p-grape-100-color { - color: #e4c6fa; -} - -.p-grape-300-color { - color: #cd9ef7; -} - -.p-grape-500-color { - color: #a56de2; -} - -.p-grape-700-color { - color: #7239b3; -} - -.p-grape-900-color { - color: #452981; -} - -.p-bubblegum-color { - color: #de3e80; -} - -.p-bubblegum-100-color { - color: #fe9ab8; -} - -.p-bubblegum-300-color { - color: #f4679d; -} - -.p-bubblegum-500-color { - color: #de3e80; -} - -.p-bubblegum-700-color { - color: #bc245d; -} - -.p-bubblegum-900-color { - color: #910e38; -} - -.p-cocoa-color { - color: #715344; -} - -.p-cocoa-100-color { - color: #a3907c; -} - -.p-cocoa-300-color { - color: #8a715e; -} - -.p-cocoa-500-color { - color: #715344; -} - -.p-cocoa-700-color { - color: #57392d; -} - -.p-cocoa-900-color { - color: #3d211b; -} - -.p-silver-color { - color: #abacae; -} - -.p-silver-100-color { - color: #fafafa; -} - -.p-silver-300-color { - color: #d4d4d4; -} - -.p-silver-500-color { - color: #abacae; -} - -.p-silver-700-color { - color: #7e8087; -} - -.p-silver-900-color { - color: #555761; -} - -.p-slate-color { - color: #485a6c; -} - -.p-slate-100-color { - color: #95a3ab; -} - -.p-slate-300-color { - color: #667885; -} - -.p-slate-500-color { - color: #485a6c; -} - -.p-slate-700-color { - color: #273445; -} - -.p-slate-900-color { - color: #0e141f; -} - -.p-dark-color { - color: #333; -} - -.p-dark-100-color { - color: #666; - /* hehe */ -} - -.p-dark-300-color { - color: #4d4d4d; -} - -.p-dark-500-color { - color: #333; -} - -.p-dark-700-color { - color: #1a1a1a; -} - -.p-dark-900-color { - color: #000; -} - -.p-white-color{ - color: #fff; -} diff --git a/v3/examples/ios/frontend/public/puppertino/css/dark_mode.css b/v3/examples/ios/frontend/public/puppertino/css/dark_mode.css deleted file mode 100644 index 3c5a03e80..000000000 --- a/v3/examples/ios/frontend/public/puppertino/css/dark_mode.css +++ /dev/null @@ -1 +0,0 @@ -/* Puppertino dark_mode placeholder - local vendored */ diff --git a/v3/examples/ios/frontend/public/puppertino/css/forms.css b/v3/examples/ios/frontend/public/puppertino/css/forms.css deleted file mode 100644 index f2320ab1b..000000000 --- a/v3/examples/ios/frontend/public/puppertino/css/forms.css +++ /dev/null @@ -1,509 +0,0 @@ -:root { - --primary-col:linear-gradient(to bottom, #4fc5fa 0%,#0f75f5 100%); - --primary-col-ac:#0f75f5; - --bg-color-input:#fff; - - --p-checkbox-gradient: linear-gradient(180deg, #4B91F7 0%, #367AF6 100%); - --p-checkbox-border: rgba(0, 0, 0, 0.2); - --p-checkbox-border-active: rgba(0, 0, 0, 0.12); - --p-checkbox-bg: transparent; - --p-checkbox-shadow: inset 0px 1px 2px rgba(0, 0, 0, 0.15), inset 0px 0px 2px rgba(0, 0, 0, 0.10); - - --p-input-bg:#fff; - --p-input-color: rgba(0,0,0,.85); - --p-input-color-plac:rgba(0,0,0,0.25); - - --p-input-color:#808080; - --p-input-bd:rgba(0,0,0,0.15); - --bg-hover-color:#f9f9f9; - --bg-front-col:#000; - --invalid-color:#d6513c; - --valid-color:#94d63c; -} - -.p-dark-mode{ - --p-checkbox-bg: linear-gradient(180deg, rgba(255, 255, 255, 0.1) 0%, rgba(255, 255, 255, 0.13) 100%); - --p-checkbox-shadow: 0px 0px 1px rgba(0, 0, 0, 0.25), inset 0px 0.5px 0px rgba(255, 255, 255, 0.15); - --p-checkbox-border: rgba(0, 0, 0, 0); - - --p-checkbox-gradient: linear-gradient(180deg, #3168DD 0%, #2C5FC8 100%); - --p-checkbox-border-active: rgba(0, 0, 0, 0); -} - -.p-form-select { - border-radius: 5px; - display: inline-block; - font-family: -apple-system, "Inter", sans-serif; - margin: 10px; - position: relative; -} - -.p-form-select > select:focus{ - outline: 2px solid #64baff; -} - -.p-form-select::after { - background: url("data:image/svg+xml,%3Csvg fill='none' xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 12'%3E%3Cpath d='M.288 4.117 3.16 1.18c.168-.168.336-.246.54-.246a.731.731 0 0 1 .538.246L7.108 4.12c.125.121.184.27.184.45 0 .359-.293.656-.648.656a.655.655 0 0 1-.48-.211L3.701 2.465l-2.469 2.55a.664.664 0 0 1-.48.212.656.656 0 0 1-.465-1.11Zm3.41 7.324a.73.73 0 0 0 .54-.246l2.87-2.941a.601.601 0 0 0 .184-.45.656.656 0 0 0-.648-.656.677.677 0 0 0-.48.211L3.701 9.91 1.233 7.36a.68.68 0 0 0-.48-.212.656.656 0 0 0-.465 1.11l2.871 2.937c.172.168.336.246.54.246Z' fill='white' style='mix-blend-mode:luminosity'/%3E%3C/svg%3E"), #017AFF; - background-size: 100% 75%; - background-position: center; - background-repeat: no-repeat; - border-radius: 5px; - bottom: 0; - content: ""; - display: block; - height: 80%; - pointer-events: none; - position: absolute; - right: 3%; - top: 10%; - width: 20px; -} - -.p-form-select > select { - -webkit-appearance: none; - appearance: none; - background: var(--p-input-bg); - border: 1px solid var(--p-input-bd); - border-radius: 5px; - font-size: 14px; - margin: 0; - outline: none; - padding: 5px 35px 5px 10px; - position: relative; - width: 100%; - color: var(--p-input-color); -} - -.p-form-text:invalid, -.p-form-text-alt:invalid{ - border-color: var(--invalid-color); -} - -.p-form-text:valid, -.p-form-text-alt:valid{ - border-color: var(--valid-color); -} - -.p-form-text:placeholder-shown, -.p-form-text-alt:placeholder-shown{ - border-color: var(--p-input-bd); -} - -.p-form-text { - color: var(--p-input-color); - -webkit-appearance: none; - appearance: none; - background: var(--p-input-bg); - border: 1px solid var(--p-input-bd); - border-radius: 5px; - font-family: -apple-system, "Inter", sans-serif; - font-size: 13px; - margin: 10px; - outline: 0; - padding: 3px 7px; - resize: none; - transition: border-color 200ms; - box-shadow: 0px 0.5px 2.5px rgba(0,0,0,.3), 0px 0px 0px rgba(0,0,0,.1); -} - -.p-form-text-alt { - color: var(--p-input-color); - -webkit-appearance: none; - appearance: none; - box-shadow: none; - background: var(--p-input-bg); - border: 0px; - border-bottom: 2px solid var(--p-input-bd); - padding: 10px; - border-top-left-radius: 3px; - border-top-right-radius: 3px; - margin: 10px; -} - - - -.p-form-text-alt::placeholder, -.p-form-text::placeholder -{ - color: var(--p-input-color-plac); -} - -.p-form-text:active, -.p-form-text:focus -{ - outline: 3px solid rgb(0 122 255 / 50%); -} - -.p-form-text-alt:focus { - outline: 0; - outline: 3px solid rgb(0 122 255 / 50%); - border-color: #3689e6; -} - -.p-form-no-validate:valid, -.p-form-no-validate:invalid{ - border-color: var(--p-input-bd); - color: var(--p-input-color)!important; -} - -.p-form-text:focus { - border-color: rgb(0 122 255); -} - -textarea.p-form-text { - -webkit-appearance: none; - appearance: none; - height: 100px; -} - -.p-form-truncated { - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; -} - -.p-form-text[type=password] { - font-family: caption; -} - -.p-form-label, -.p-form-radio-cont, -.p-form-checkbox-cont, -.p-form-label-inline { - font-family: -apple-system, "Inter", sans-serif; -} - -.p-form-label, .p-form-label-inline { - display: inline-block; -} - -.p-form-label{ - font-size: 11px; -} - -.p-form-label-inline { - background: var(--p-input-bg); - padding: 5px; - border-bottom: 2px solid var(--p-input-bd); - color: #656565; - font-weight: 500; - transition: .3s; -} - -.p-form-label-inline:focus-within { - color: #3689e6; - border-color: #3689e6; -} - -.p-form-label-inline > .p-form-text-alt { - border-bottom: 0px; - padding: 0; - outline: 0; - background: var(--p-input-bg); - -} - -.p-form-label-inline > .p-form-text-alt:-webkit-autofill{ - background: var(--p-input-bg); - -webkit-box-shadow: 0 0 0 30px rgba(0,0,0,0) inset !important; -} - -.p-form-label-inline > .p-form-text-alt:invalid { - color: var(--invalid-color); -} - -.p-form-label-inline > .p-form-text-alt:valid { - color: #3689e6; -} - -.p-form-label-inline > .p-form-text-alt:focus{ - color: var(--p-input-color); -} - -.p-form-radio-cont, -.p-form-checkbox-cont { - align-items: center; - display: inline-flex; - cursor: pointer; - margin: 0 10px; - user-select: none; -} - -.p-form-radio-cont > input + span, -.p-form-checkbox-cont > input + span { - background: var(--p-input-bg); - border: 1px solid var(--p-input-bd); - border-radius: 50%; - display: inline-block; - height: 20px; - margin-right: 5px; - position: relative; - transition: 0.2s; - width: 20px; -} - -.p-form-radio-cont > input + span{ - box-shadow: inset 0px 1px 2px rgba(0,0,0,0.10), inset 0px 0px 2px rgba(0,0,0,0.10); -} - -.p-form-radio-cont > input:focus + span, -.p-form-checkbox-cont > input:focus + span{ - outline: 3px solid rgb(0 122 255 / 50%); -} - -.p-form-radio-cont:hover > input + span{ - background: #f9f9f9; -} - -.p-form-radio-cont > input, -.p-form-checkbox-cont > input { - opacity: 0; - pointer-events: none; - position: absolute; -} - -.p-form-radio-cont > input + span::after { - background: #fff; - border-radius: 50%; - content: ""; - display: block; - height: 30%; - left: calc(50% - 15%); - opacity: 0; - position: absolute; - top: calc(50% - 15%); - transform: scale(2); - transition: opacity 0.2s, transform 0.3s; - width: 30%; -} - -.p-form-radio-cont > input:checked + span { - background: #0f75f5; - box-shadow: 0px 1px 2.5px 1px rgba(0, 122, 255, 0.24), inset 0px 0px 0px 0.5px rgba(0, 122, 255, 0.12); -} - -.p-form-radio-cont > input:checked + span::after { - opacity: 1; - transform: scale(1); -} - -.p-form-checkbox-cont > input + span { - border-radius: 5px; - box-shadow: var(--p-checkbox-shadow); - border: 0.5px solid var(--p-checkbox-border); - background: var(--p-checkbox-bg) -} - -.p-form-checkbox-cont > input:checked + span { - background: var(--p-checkbox-gradient); - border: 0.5px solid var(--p-checkbox-border-active); - box-shadow: 0px 1px 2.5px rgba(0, 122, 255, 0.24), 0px 0px 0px 0.5px rgba(0, 122, 255, 0.12); -} - -.p-form-checkbox-cont > input + span::before{ - content: ""; - display: block; - height: 100%; - width: 100%; - position: absolute; - left: 0%; - top: 0%; - opacity: 0; - transition: opacity 0.2s; - background-image: url("data:image/svg+xml,%3Csvg width='10' height='8' viewBox='0 0 10 8' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M4.10791 7.81299C3.83545 7.81299 3.6084 7.70459 3.42676 7.48779L1.15918 4.74121C1.08008 4.65039 1.02441 4.5625 0.992188 4.47754C0.959961 4.39258 0.943848 4.30469 0.943848 4.21387C0.943848 4.00586 1.0127 3.83447 1.15039 3.69971C1.29102 3.56201 1.4668 3.49316 1.67773 3.49316C1.91211 3.49316 2.10693 3.58838 2.26221 3.77881L4.10791 6.04297L7.68066 0.368652C7.77148 0.230957 7.86523 0.134277 7.96191 0.0786133C8.06152 0.0200195 8.18311 -0.00927734 8.32666 -0.00927734C8.5376 -0.00927734 8.71191 0.0581055 8.84961 0.192871C8.9873 0.327637 9.05615 0.497559 9.05615 0.702637C9.05615 0.778809 9.04297 0.85791 9.0166 0.939941C8.99023 1.02197 8.94922 1.10693 8.89355 1.19482L4.80225 7.45703C4.64111 7.69434 4.40967 7.81299 4.10791 7.81299Z' fill='white'/%3E%3C/svg%3E%0A"); - background-size: 70%; - background-position: center; - background-repeat: no-repeat; -} - -.p-form-checkbox-cont > input + span::after{ - content: ''; - width: 100%; - height: 100%; - position: absolute; - top: 0; - left: 0; - z-index: 9; -} - -.p-form-checkbox-cont > input + span:active::after{ - border-radius: 5px; - backdrop-filter: brightness(1.2); -} - -.p-form-checkbox-cont > input:checked + span::before{ - opacity: 1; -} - - -.p-form-checkbox-cont > input[disabled] + span, -.p-form-radio-cont > input[disabled] ~ span -{ - opacity: .7; - cursor: not-allowed; -} - -.p-form-button { - -webkit-appearance: none; - appearance: none; - background: #fff; - border: 1px solid var(--p-input-bd); - border-radius: 5px; - color: #333230; - display: inline-block; - font-size: 17px; - margin: 10px; - padding: 5px 20px; - text-decoration: none; -} - -.p-form-send { - background: linear-gradient(to bottom, #4fc5fa 0%, #0f75f5 100%); - border: 0; - color: #fff; -} - -.p-form-send:active { - background: #0f75f5; -} - -.p-form-invalid, -.p-form-invalid:placeholder-shown, -.p-form-invalid:valid, -.p-form-invalid:invalid { - border-color: var(--invalid-color); -} - -.p-form-valid, -.p-form-valid:placeholder-shown, -.p-form-valid:valid, -.p-form-valid:invalid { - border-color: var(--valid-color); -} - -.p-form-switch { - --width: 80px; - cursor: pointer; - display: inline-block; -} - -.p-form-switch > input:checked + span::after { - left: calc(100% - calc(var(--width) / 1.8)); -} - -.p-form-switch > input:checked + span { - background: #60c35b; -} - -.p-form-switch > span { - background: #e0e0e0; - border: 1px solid #d3d3d3; - border-radius: 500px; - display: block; - height: calc(var(--width) / 1.6); - position: relative; - transition: all 0.2s; - width: var(--width); -} - -.p-form-switch > span::after { - background: #f9f9f9; - border-radius: 50%; - border: 0.5px solid rgba(0, 0, 0, 0.101987); - box-shadow: 0px 3px 1px rgba(0, 0, 0, 0.1), 0px 1px 1px rgba(0, 0, 0, 0.16), 0px 3px 8px rgba(0, 0, 0, 0.15); - box-sizing: border-box; - content: ""; - height: 84%; - left: 3%; - position: absolute; - top: 6.5%; - transition: all 0.2s; - width: 52.5%; -} - -.p-form-switch > input { - display: none; -} - -.p-chip input{ - opacity: 0; - pointer-events: none; - position: absolute; -} - -.p-chip span{ - padding: .8rem 1rem; - border-radius: 1.6rem; - display:inline-block; - margin:10px; - background: #e4e4e4ca; - color: #3689e6; - transition: .3s; - user-select: none; - cursor:pointer; - font-family: -apple-system, "Inter", sans-serif; - font-size: 1rem; - -webkit-tap-highlight-color: rgba(0, 0, 0, 0); - -moz-tap-highlight-color: rgba(0, 0, 0, 0); - text-align:center; -} - -.p-chip:focus-within span{ - outline: 2px solid #64baff; -} - -.p-chip svg{ - display:block; - margin:auto; -} - - -.p-chip input:checked + span{ - background: #3689e6; - color:#fff; -} - -.p-chip-outline span, .p-chip-outline-to-bg span{ - background: transparent; - color: #3e3e3e; - border: 1px solid currentColor; -} - -.p-chip-outline input:checked + span{ - background: transparent; - color: #3689e6; -} - -.p-chip-radius-b span{ - border-radius: 5px; -} - -.p-chip-dark span{ - color: #3e3e3e; -} - -.p-chip-dark input:checked + span{ - background: #3e3e3e; -} - -.p-chip input:disabled + span, -.p-chip input[disabled] + span{ - opacity: .5; - cursor: not-allowed; -} - -.p-chip-big span{ - font-size: 1.3rem; - padding: 1.5rem; - min-width: 80px; -} - -.p-form-checkbox-cont[disabled], -.p-form-label[disabled], -.p-form-text[disabled], -.p-form-text-alt[disabled], -.p-form-select[disabled], -.p-form-radio-cont[disabled]{ - filter: grayscale(1) opacity(.3); - pointer-events: none; -} diff --git a/v3/examples/ios/frontend/public/puppertino/css/layout.css b/v3/examples/ios/frontend/public/puppertino/css/layout.css deleted file mode 100644 index 1f9b36845..000000000 --- a/v3/examples/ios/frontend/public/puppertino/css/layout.css +++ /dev/null @@ -1,45 +0,0 @@ -.p-large-title{ - font-size: 2.75rem; -} - -.p-layout h1 { - font-size: 2.25rem; -} - -.p-layout h2 { - font-size: 1.75rem; -} - -.p-layout h3 { - font-size: 1.58rem; -} - -.p-headline { - font-size: 1.34rem; - font-weight: bold; -} - -.p-layout p { - font-size: 1.15rem; -} - -.p-layout .link, -.p-layout input { - font-size: 0.813rem; -} - -.p-callout { - font-size: 1.14rem; -} - -.p-subhead { - font-size: 1.167rem; -} - -.p-footnote { - font-size: 1.07rem; -} - -.p-caption { - font-size: 0.91rem; -} diff --git a/v3/examples/ios/frontend/public/puppertino/css/modals.css b/v3/examples/ios/frontend/public/puppertino/css/modals.css deleted file mode 100644 index 4d718c4f7..000000000 --- a/v3/examples/ios/frontend/public/puppertino/css/modals.css +++ /dev/null @@ -1 +0,0 @@ -/* Puppertino modals placeholder - local vendored */ diff --git a/v3/examples/ios/frontend/public/puppertino/css/newfull.css b/v3/examples/ios/frontend/public/puppertino/css/newfull.css deleted file mode 100644 index 622a2f364..000000000 --- a/v3/examples/ios/frontend/public/puppertino/css/newfull.css +++ /dev/null @@ -1,11 +0,0 @@ -@import url('actions.css'); -@import url('buttons.css'); -@import url('layout.css'); -@import url('cards.css'); -@import url('color_palette.css'); -@import url('forms.css'); -@import url('modals.css'); -@import url('segmented-controls.css'); -@import url('shadows.css'); -@import url('tabs.css'); -@import url('dark_mode.css'); diff --git a/v3/examples/ios/frontend/public/puppertino/css/segmented-controls.css b/v3/examples/ios/frontend/public/puppertino/css/segmented-controls.css deleted file mode 100644 index 22819fd5f..000000000 --- a/v3/examples/ios/frontend/public/puppertino/css/segmented-controls.css +++ /dev/null @@ -1 +0,0 @@ -/* Puppertino segmented-controls placeholder - local vendored */ diff --git a/v3/examples/ios/frontend/public/puppertino/css/shadows.css b/v3/examples/ios/frontend/public/puppertino/css/shadows.css deleted file mode 100644 index 060a61658..000000000 --- a/v3/examples/ios/frontend/public/puppertino/css/shadows.css +++ /dev/null @@ -1 +0,0 @@ -/* Puppertino shadows placeholder - local vendored */ diff --git a/v3/examples/ios/frontend/public/puppertino/css/tabs.css b/v3/examples/ios/frontend/public/puppertino/css/tabs.css deleted file mode 100644 index 61d1487ca..000000000 --- a/v3/examples/ios/frontend/public/puppertino/css/tabs.css +++ /dev/null @@ -1 +0,0 @@ -/* Puppertino tabs placeholder - local vendored */ diff --git a/v3/examples/ios/frontend/public/puppertino/puppertino.css b/v3/examples/ios/frontend/public/puppertino/puppertino.css deleted file mode 100644 index 905da220e..000000000 --- a/v3/examples/ios/frontend/public/puppertino/puppertino.css +++ /dev/null @@ -1,1774 +0,0 @@ -@charset "UTF-8"; -.p-btn { - background: #fff; - border: 1px solid #cacaca; - border-radius: 5px; - color: #333230; - display: inline-block; - font-family: -apple-system, "Inter", sans-serif; - font-size: 17px; - margin: 10px; - padding: 5px 20px; - text-decoration: none; - /* text-shadow: 0 1px 1px rgba(0, 0, 0, 0.25); */ -} -.p-btn-mob{ - padding: 10px 40px; - background: #0f75f5; - color: #fff; -} -.p-btn[disabled] { - background: #d3d3d3; - color: #555; - cursor: not-allowed; -} -.p-btn:disabled { - background: #d3d3d3; - color: #555; - cursor: not-allowed; -} -.p-btn-disabled { - background: #d3d3d3; - color: #555; - cursor: not-allowed; -} - -.p-prim-col { - background: linear-gradient(to bottom, #4fc5fa 0%, #0f75f5 100%); - border: 0; - color: #fff; -} - -.p-btn.p-prim-col:active { - background: #0f75f5; -} - -.p-btn-more::after { - content: "..."; -} - -.p-btn-round { - border: 0; - border-radius: 50px; - padding: 10px 30px; -} - -.p-btn-icon { - align-items: center; - background: #fff; - border: 2px solid currentColor; - border-radius: 50%; - box-shadow: 0 3px 10px -8px #000; - color: #0f75f5; - display: inline-flex; - font-weight: 900; - height: 36px; - justify-content: center; - margin: 5px; - text-align: center; - text-decoration: none; - width: 36px; -} - -.p-btn-scope { - background: #8e8e8e; - color: #fff; - margin: 5px; - padding: 2px 20px; -} -.p-btn-scope-unactive { - background: transparent; - border-color: transparent; - color: #212136; - transition: border-color 0.2s; -} -.p-btn-scope-unactive:hover { - border-color: #cacaca; -} -.p-btn-scope-disabled { - background: transparent; - color: #8e8e8e; - cursor: not-allowed; -} -.p-btn-scope-outline { - background: transparent; - color: #212136; -} - -.p-btn-scope-outline { - background: transparent; - color: #212136; -} - -.p-btn-outline { - background: none; - border-color: currentColor; -} - -.p-btn-outline-dash { - background: none; - border-color: currentColor; - border-style: dashed; -} - -.p-btn-direction { - color: #212136; - padding: 5px; - text-decoration: none; -} - -.p-btn-direction.p-btn-d-back::before { - content: "❬"; -} - -.p-btn-direction.p-btn-d-next::after { - content: "❭"; -} - -@media (max-width: 576px) { - .p-btn-big-sm { - border: 0; - border-radius: 0%; - bottom: 0; - font-size: 50px; - left: 0; - margin: 0; - padding: 10px 0; - position: fixed; - text-align: center; - width: 100%; - } -} - -/*END OF BUTTONS*/ - -.p-card { - background: rgba(255, 255, 255, 0.3); - border: 1px solid rgba(0, 0, 0, 0.1); - border-radius: 3px; - box-shadow: 0 8px 10px -8px rgba(0, 0, 0, 0.1); - color: #000; - display: block; - margin-top: 30px; - text-decoration: none; -} -.p-card-image > img { - border-bottom: 3px solid var(--accent-article); - display: block; - margin: auto; - width: 100%; -} -.p-card-tags { - display: flex; - overflow: hidden; - position: relative; - width: 100%; -} -.p-card-tags::before { - background: linear-gradient(to right, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0) 75%, white 100%); - content: ""; - height: 100%; - position: absolute; - right: 0; - top: 0; - width: 30%; -} -.p-card-tags span, -.p-card-tags a { - border: 1px solid #252525; - border-radius: 50px; - color: #252525; - margin: 5px; - padding: 5px 15px; - text-decoration: none; - transition: all 0.2s; -} -.p-card-tags a:hover { - background: #252525; - color: #000; -} -.p-card-title { - font-size: 2rem; - margin-bottom: 15px; - margin-top: 10px; -} -.p-card-content { - padding: 15px; - padding-top: 5px; -} -.p-card-text { - font-size: 17px; - margin-bottom: 10px; - margin-left: 10px; - margin-top: 0; -} - - -/* END OF CARDS*/ - -.p-strawberry { - background: #c6262e; -} - -.p-strawberry-100 { - background: #ff8c82; -} - -.p-strawberry-300 { - background: #ed5353; -} - -.p-strawberry-500 { - background: #c6262e; -} - -.p-strawberry-700 { - background: #a10705; -} - -.p-strawberry-900 { - background: #7a0000; -} - -.p-orange { - background: #f37329; -} - -.p-orange-100 { - background: #ffc27d; -} - -.p-orange-300 { - background: #ffa154; -} - -.p-orange-500 { - background: #f37329; -} - -.p-orange-700 { - background: #cc3b02; -} - -.p-orange-900 { - background: #a62100; -} - -.p-banana { - background: #f9c440; -} - -.p-banana-100 { - background: #fff394; -} - -.p-banana-300 { - background: #ffe16b; -} - -.p-banana-500 { - background: #f9c440; -} - -.p-banana-700 { - background: #d48e15; -} - -.p-banana-900 { - background: #ad5f00; -} - -.p-lime { - background: #68b723; -} - -.p-lime-100 { - background: #d1ff82; -} - -.p-lime-300 { - background: #9bdb4d; -} - -.p-lime-500 { - background: #68b723; -} - -.p-lime-700 { - background: #3a9104; -} - -.p-lime-900 { - background: #206b00; -} - -.p-mint { - background: #28bca3; -} - -.p-mint-100 { - background: #89ffdd; -} - -.p-mint-300 { - background: #43d6b5; -} - -.p-mint-500 { - background: #28bca3; -} - -.p-mint-700 { - background: #0e9a83; -} - -.p-mint-900 { - background: #007367; -} - -.p-blueberry { - background: #3689e6; -} - -.p-blueberry-100 { - background: #8cd5ff; -} - -.p-blueberry-300 { - background: #64baff; -} - -.p-blueberry-500 { - background: #3689e6; -} - -.p-blueberry-700 { - background: #0d52bf; -} - -.p-blueberry-900 { - background: #002e99; -} - -.p-grape { - background: #a56de2; -} - -.p-grape-100 { - background: #e4c6fa; -} - -.p-grape-300 { - background: #cd9ef7; -} - -.p-grape-500 { - background: #a56de2; -} - -.p-grape-700 { - background: #7239b3; -} - -.p-grape-900 { - background: #452981; -} - -.p-bubblegum { - background: #de3e80; -} - -.p-bubblegum-100 { - background: #fe9ab8; -} - -.p-bubblegum-300 { - background: #f4679d; -} - -.p-bubblegum-500 { - background: #de3e80; -} - -.p-bubblegum-700 { - background: #bc245d; -} - -.p-bubblegum-900 { - background: #910e38; -} - -.p-cocoa { - background: #715344; -} - -.p-cocoa-100 { - background: #a3907c; -} - -.p-cocoa-300 { - background: #8a715e; -} - -.p-cocoa-500 { - background: #715344; -} - -.p-cocoa-700 { - background: #57392d; -} - -.p-cocoa-900 { - background: #3d211b; -} - -.p-silver { - background: #abacae; -} - -.p-silver-100 { - background: #fafafa; -} - -.p-silver-300 { - background: #d4d4d4; -} - -.p-silver-500 { - background: #abacae; -} - -.p-silver-700 { - background: #7e8087; -} - -.p-silver-900 { - background: #555761; -} - -.p-slate { - background: #485a6c; -} - -.p-slate-100 { - background: #95a3ab; -} - -.p-slate-300 { - background: #667885; -} - -.p-slate-500 { - background: #485a6c; -} - -.p-slate-700 { - background: #273445; -} - -.p-slate-900 { - background: #0e141f; -} - -.p-dark { - background: #333; -} - -.p-dark-100 { - background: #666; - /* hehe */ -} - -.p-dark-300 { - background: #4d4d4d; -} - -.p-dark-500 { - background: #333; -} - -.p-dark-700 { - background: #1a1a1a; -} - -.p-dark-900 { - background: #000; -} - -.p-strawberry-color { - color: #c6262e; -} - -.p-strawberry-100-color { - color: #ff8c82; -} - -.p-strawberry-300-color { - color: #ed5353; -} - -.p-strawberry-500-color { - color: #c6262e; -} - -.p-strawberry-700-color { - color: #a10705; -} - -.p-strawberry-900-color { - color: #7a0000; -} - -.p-orange-color { - color: #f37329; -} - -.p-orange-100-color { - color: #ffc27d; -} - -.p-orange-300-color { - color: #ffa154; -} - -.p-orange-500-color { - color: #f37329; -} - -.p-orange-700-color { - color: #cc3b02; -} - -.p-orange-900-color { - color: #a62100; -} - -.p-banana-color { - color: #f9c440; -} - -.p-banana-100-color { - color: #fff394; -} - -.p-banana-300-color { - color: #ffe16b; -} - -.p-banana-500-color { - color: #f9c440; -} - -.p-banana-700-color { - color: #d48e15; -} - -.p-banana-900-color { - color: #ad5f00; -} - -.p-lime-color { - color: #68b723; -} - -.p-lime-100-color { - color: #d1ff82; -} - -.p-lime-300-color { - color: #9bdb4d; -} - -.p-lime-500-color { - color: #68b723; -} - -.p-lime-700-color { - color: #3a9104; -} - -.p-lime-900-color { - color: #206b00; -} - -.p-mint-color { - color: #28bca3; -} - -.p-mint-100-color { - color: #89ffdd; -} - -.p-mint-300-color { - color: #43d6b5; -} - -.p-mint-500-color { - color: #28bca3; -} - -.p-mint-700-color { - color: #0e9a83; -} - -.p-mint-900-color { - color: #007367; -} - -.p-blueberry-color { - color: #3689e6; -} - -.p-blueberry-100-color { - color: #8cd5ff; -} - -.p-blueberry-300-color { - color: #64baff; -} - -.p-blueberry-500-color { - color: #3689e6; -} - -.p-blueberry-700-color { - color: #0d52bf; -} - -.p-blueberry-900-color { - color: #002e99; -} - -.p-grape-color { - color: #a56de2; -} - -.p-grape-100-color { - color: #e4c6fa; -} - -.p-grape-300-color { - color: #cd9ef7; -} - -.p-grape-500-color { - color: #a56de2; -} - -.p-grape-700-color { - color: #7239b3; -} - -.p-grape-900-color { - color: #452981; -} - -.p-bubblegum-color { - color: #de3e80; -} - -.p-bubblegum-100-color { - color: #fe9ab8; -} - -.p-bubblegum-300-color { - color: #f4679d; -} - -.p-bubblegum-500-color { - color: #de3e80; -} - -.p-bubblegum-700-color { - color: #bc245d; -} - -.p-bubblegum-900-color { - color: #910e38; -} - -.p-cocoa-color { - color: #715344; -} - -.p-cocoa-100-color { - color: #a3907c; -} - -.p-cocoa-300-color { - color: #8a715e; -} - -.p-cocoa-500-color { - color: #715344; -} - -.p-cocoa-700-color { - color: #57392d; -} - -.p-cocoa-900-color { - color: #3d211b; -} - -.p-silver-color { - color: #abacae; -} - -.p-silver-100-color { - color: #fafafa; -} - -.p-silver-300-color { - color: #d4d4d4; -} - -.p-silver-500-color { - color: #abacae; -} - -.p-silver-700-color { - color: #7e8087; -} - -.p-silver-900-color { - color: #555761; -} - -.p-slate-color { - color: #485a6c; -} - -.p-slate-100-color { - color: #95a3ab; -} - -.p-slate-300-color { - color: #667885; -} - -.p-slate-500-color { - color: #485a6c; -} - -.p-slate-700-color { - color: #273445; -} - -.p-slate-900-color { - color: #0e141f; -} - -.p-dark-color { - color: #333; -} - -.p-dark-100-color { - color: #666; - /* hehe */ -} - -.p-dark-300-color { - color: #4d4d4d; -} - -.p-dark-500-color { - color: #333; -} - -.p-dark-700-color { - color: #1a1a1a; -} - -.p-dark-900-color { - color: #000; -} - -/* END OF COLORS */ - -:root { - --primary-col:linear-gradient(to bottom, #4fc5fa 0%,#0f75f5 100%); - --primary-col-ac:#0f75f5; - --bg-color:#fff; - --bg-hover-color:#f9f9f9; - --bg-front-col:#000; - --invalid-color:#d6513c; - --valid-color:#94d63c; -} - -.p-form-select { - border-radius: 5px; - display: inline-block; - font-family: -apple-system, "Inter", sans-serif; - margin: 10px; - position: relative; -} - -.p-form-select::before { - border-color: #fff transparent transparent; - border-style: solid; - border-width: 5px; - content: ""; - pointer-events: none; - position: absolute; - right: 5px; - top: calc(50% - 3px); - z-index: 3; -} - -.p-form-select::after { - background: linear-gradient(to bottom, #4fc5fa 0%, #0f75f5 100%); - border-bottom-right-radius: 5px; - border-top-right-radius: 5px; - bottom: 0; - content: ""; - display: block; - height: 100%; - pointer-events: none; - position: absolute; - right: 0; - top: 0; - width: 20px; -} - -.p-form-select > select { - -webkit-appearance: none; - background: #fff; - border: 1px solid #cacaca; - border-radius: 5px; - font-size: 14px; - margin: 0; - outline: none; - padding: 5px 30px 5px 10px; - position: relative; - width: 100%; -} - -.p-form-text:invalid, -.p-form-text-alt:invalid, -.p-form-select > select:invalid { - border-color: var(--invalid-color); -} - -.p-form-text:valid, -.p-form-text-alt:valid, -.p-form-select > select:valid { - border-color: var(--valid-color); -} - -.p-form-text:placeholder-shown, -.p-form-text-alt:placeholder-shown, -.p-form-select > select:placeholder-shown { - border-color: #cacaca; -} - -.p-form-text { - -webkit-appearance: none; - box-shadow: none; - background: #fff; - border: 1px solid #cacaca; - border-radius: 5px; - font-family: -apple-system, "Inter", sans-serif; - margin: 10px; - outline: 0; - padding: 5px; - resize: none; - transition: border-color 200ms; -} - -.p-form-text-alt { - -webkit-appearance: none; - box-shadow: none; - background: #fff; - border: 0px; - border-bottom: 2px solid #cacaca; - padding: 10px; - border-top-left-radius: 5px; - border-top-right-radius: 5px; - margin: 10px; -} - -.p-form-text-alt::placeholder { - color: #cacaca; -} - -.p-form-text-alt:focus { - outline: 3px solid #bed8f9; -} - -.p-form-no-validate:valid, -.p-form-no-validate:invalid, -.p-form-no-validate > select:valid, -.p-form-no-validate > select:invalid { - border-color: #cacaca; -} - -.p-form-text:focus { - border-color: #0f75f5; -} - -textarea.p-form-text { - -webkit-appearance: none; - height: 100px; -} - -.p-form-truncated { - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; -} - -.p-form-text[type=password] { - font-family: caption; -} - -.p-form-label, -.p-form-radio-cont, -.p-form-checkbox-cont { - font-family: -apple-system, "Inter", sans-serif; -} - -.p-form-label { - display: block; -} - -.p-form-radio-cont, -.p-form-checkbox-cont { - align-items: center; - display: inline-flex; - margin: 0 10px; -} - -.p-form-radio-cont > input + span, -.p-form-checkbox-cont > input + span { - background: #fff; - border: 1px solid #cacaca; - border-radius: 50%; - cursor: pointer; - display: inline-block; - height: 20px; - margin-right: 5px; - position: relative; - transition: background 0.2s; - width: 20px; -} - -.p-form-radio-cont > input + span:hover { - background: #f9f9f9; -} - -.p-form-radio-cont > input, -.p-form-checkbox-cont > input { - opacity: 0; - pointer-events: none; - position: absolute; -} - -.p-form-radio-cont > input + span::after { - background: #fff; - border-radius: 50%; - box-shadow: 0 1px 2px rgba(0, 0, 0, 0.3); - content: ""; - display: block; - height: 30%; - left: calc(50% - 15%); - opacity: 0; - position: absolute; - top: calc(50% - 15%); - transform: scale(2); - transition: opacity 0.2s, transform 0.3s; - width: 30%; -} - -.p-form-radio-cont > input:checked + span { - background: #0f75f5; -} - -.p-form-radio-cont > input:checked + span::after { - opacity: 1; - transform: scale(1); -} - -.p-form-checkbox-cont > input + span { - border-radius: 5px; -} - -.p-form-checkbox-cont > input:checked + span { - background: #0f75f5; -} - -.p-form-checkbox-cont > input + span::before, -.p-form-checkbox-cont > input + span::after { - background: #fff; - border-radius: 20px; - content: ""; - display: block; - height: 8%; - position: absolute; -} - -.p-form-checkbox-cont > input + span::before { - right: 30%; - top: 15%; - transform: rotate(-65deg); - transform-origin: top right; - width: 70%; -} - -.p-form-checkbox-cont > input + span::after { - left: 30%; - top: 43%; - transform: rotate(60deg); - transform-origin: top left; - width: 40%; -} - -.p-form-button { - -webkit-appearance: none; - background: #fff; - border: 1px solid #cacaca; - border-radius: 5px; - color: #333230; - display: inline-block; - font-size: 17px; - margin: 10px; - padding: 5px 20px; - text-decoration: none; - /* text-shadow: 0 1px 1px rgba(0, 0, 0, 0.25); */ -} - -.p-form-send { - background: linear-gradient(to bottom, #4fc5fa 0%, #0f75f5 100%); - border: 0; - color: #fff; -} - -.p-form-send:active { - background: #0f75f5; -} - -.p-form-invalid, -.p-form-invalid:placeholder-shown, -.p-form-invalid:valid, -.p-form-invalid:invalid { - border-color: var(--invalid-color); -} - -.p-form-valid, -.p-form-valid:placeholder-shown, -.p-form-valid:valid, -.p-form-valid:invalid { - border-color: var(--valid-color); -} - -.p-form-switch { - --width: 80px; - cursor: pointer; - display: inline-block; -} - -.p-form-switch > input:checked + span::after { - left: calc(100% - calc(var(--width) / 2.1)); -} - -.p-form-switch > input:checked + span { - background: #60c35b; -} - -.p-form-switch > span { - background: #e0e0e0; - border: 1px solid #d3d3d3; - border-radius: 500px; - display: block; - height: calc(var(--width) / 2); - overflow: hidden; - position: relative; - transition: all 0.2s; - width: var(--width); -} - -.p-form-switch > span::after { - background: #f9f9f9; - border-radius: 50%; - box-shadow: 0px 3px 1px rgba(0, 0, 0, 0.1), 0px 1px 1px rgba(0, 0, 0, 0.16), 0px 3px 8px rgba(0, 0, 0, 0.15); - content: ""; - height: 90%; - left: 3%; - position: absolute; - top: 4.5%; - transition: all 0.2s; - width: 45%; -} - -.p-form-switch > input { - display: none; -} - -input[type=range].p-form-range { - width: 100%; - margin: 11.5px 0; - background-color: transparent; - -webkit-appearance: none; -} -input[type=range].p-form-range:focus { - outline: none; -} -input[type=range].p-form-range::-webkit-slider-runnable-track { - background: #cacaca; - border: 0; - width: 100%; - height: 2px; - cursor: pointer; -} -input[type=range].p-form-range::-webkit-slider-thumb { - margin-top: -11.5px; - width: 25px; - height: 25px; - background: #ffffff; - border: 1px solid rgba(115, 115, 115, 0.6); - border-radius: 30px; - cursor: pointer; - box-shadow: 0 3px 1px rgba(0, 0, 0, 0.1), 0 1px 1px rgba(0, 0, 0, 0.16), 0 3px 8px rgba(0, 0, 0, 0.15); - -webkit-appearance: none; -} -input[type=range].p-form-range:focus::-webkit-slider-runnable-track { - background: #d7d7d7; -} -input[type=range].p-form-range::-moz-range-track { - background: #cacaca; - border: 0; - width: 100%; - height: 2px; - cursor: pointer; -} -input[type=range].p-form-range::-moz-range-thumb { - width: 25px; - height: 25px; - background: #ffffff; - border: 1px solid rgba(115, 115, 115, 0.6); - border-radius: 30px; - box-shadow: 0 3px 1px rgba(0, 0, 0, 0.1), 0 1px 1px rgba(0, 0, 0, 0.16), 0 3px 8px rgba(0, 0, 0, 0.15); - cursor: pointer; -} -input[type=range].p-form-range::-ms-track { - background: transparent; - border-color: transparent; - border-width: 26.5px 0; - color: transparent; - width: 100%; - height: 2px; - cursor: pointer; -} -input[type=range].p-form-range::-ms-fill-lower { - background: #bdbdbd; - border: 0; -} -input[type=range].p-form-range::-ms-fill-upper { - background: #cacaca; - border: 0; -} -input[type=range].p-form-range::-ms-thumb { - width: 25px; - height: 25px; - background: #ffffff; - border: 1px solid rgba(115, 115, 115, 0.6); - border-radius: 30px; - cursor: pointer; - box-shadow: 0 3px 1px rgba(0, 0, 0, 0.1), 0 1px 1px rgba(0, 0, 0, 0.16), 0 3px 8px rgba(0, 0, 0, 0.15); - margin-top: 0px; - /*Needed to keep the Edge thumb centred*/ -} -input[type=range].p-form-range:focus::-ms-fill-lower { - background: #cacaca; -} -input[type=range].p-form-range:focus::-ms-fill-upper { - background: #d7d7d7; -} -/*TODO: Use one of the selectors from https://stackoverflow.com/a/20541859/7077589 and figure out -how to remove the virtical space around the range input in IE*/ -@supports (-ms-ime-align:auto) { - /* Pre-Chromium Edge only styles, selector taken from hhttps://stackoverflow.com/a/32202953/7077589 */ - input[type=range].p-form-range { - margin: 0; - /*Edge starts the margin from the thumb, not the track as other browsers do*/ - } -} - - -/* END OF FORMS */ - -.p-layout .p-large-title { - font-size: 2.75rem; -} - -.p-layout h1 { - font-size: 2.25rem; -} - -.p-layout h2 { - font-size: 1.75rem; -} - -.p-layout h3 { - font-size: 1.58rem; -} - -.p-layout .p-headline { - font-size: 1.34rem; - font-weight: bold; -} - -.p-layout p { - font-size: 1.15rem; -} - -.p-layout a, -.p-layout input { - font-size: 1.14rem; -} - -.p-layout .p-callout { - font-size: 1.14rem; -} - -.p-layout .p-subhead { - font-size: 1.167rem; -} - -.p-layout .p-footnote { - font-size: 1.07rem; -} - -.p-layout .p-caption { - font-size: 0.91rem; -} - -/* END OF LAYOUT */ - -:root { - --font: -apple-system, "Inter", sans-serif; - --bg-hover-color: #f9f9f9; - --primary-col-ac: #0f75f5; -} - -.p-modal-opened { - overflow: hidden; -} - -.p-modal-background { - background: rgba(0, 0, 0, 0.3); - height: 100vh; - left: 0; - opacity: 0; - pointer-events: none; - position: fixed; - top: 0; - transition: all 0.3s; - width: 100vw; - z-index: 5; -} - -.p-modal { - background: rgba(255, 255, 255, 0.85); - border-radius: 20px; - top: calc(50% - 20vh); - bottom: unset; - box-shadow: 0 10px 20px -15px; - font-family: var(--font); - left: calc(50% - 20vw); - opacity: 0; - overflow: hidden; - pointer-events: none; - position: fixed; - text-align: center; - transform: scale(1.5); - transition: opacity 0.3s, transform 0.3s; - width: 40vw; - z-index: 9; -} - -.p-modal.active { - backdrop-filter: saturate(180%) blur(10px); - opacity: 1; - pointer-events: auto; - transform: scale(1); -} - -.p-modal-button-container { - border-radius: 20px; - display: flex; -} - -.p-modal-button-container > a { - border-top: 1px solid rgba(0, 0, 0, 0.1); - color: var(--primary-col-ac); - padding: 30px 0%; - text-decoration: none; - width: 100%; -} - -.p-modal-button-container > a:nth-child(2), -.p-modal-button-container > a:nth-child(3) { - border-left: 1px solid rgba(0, 0, 0, 0.1); -} - -.nowactive { - opacity: 1; - pointer-events: auto; -} - -.p-modal p { - padding: 0% 5%; -} - -@supports not (backdrop-filter: blur(5px)) { - .p-modal { - background: #fff; - } -} -@media (max-width: 568px) { - .p-modal { - bottom: 20%; - left: 15%; - top: unset; - width: 70vw; - } - - .p-modal p { - font-size: 15px; - padding: 0% 10%; - } - - .p-modal-button-container { - display: block; - } - - .p-modal-button-container > a { - border-left: 0 !important; - display: block; - padding: 2vh 0%; - } -} - -/* END OF MODALS */ - -.p-segmented-controls { - --color-segmented: #3689e6; - --color-lighter-segment: #d2e3f9; - background: #fff; - border: 1px solid var(--color-segmented); - border-radius: 5px; - display: flex; - flex-wrap: wrap; - font-family: -apple-system, "Inter", sans-serif; - margin-top: 10px; - overflow: hidden; - width: 100%; -} -.p-segmented-controls a { - color: var(--color-segmented); - flex: auto; - padding: 10px; - text-align: center; - text-decoration: none; - transition: all 0.5s; -} -.p-segmented-controls a.active { - background: var(--color-segmented); - color: #fff; -} -.p-segmented-controls a:not(:first-child) { - border-left: 1px solid currentColor; -} - -.p-segmented-radius { - border-radius: 30px; -} - -.p-segmented-internal-radius a, -.p-segmented-internal-radius a:not(:first-child) { - border: 0; - border-radius: 30px; -} - -.p-segmented-controls-alt a:not(:first-child) { - border: 0; -} -.p-segmented-controls-alt a:not(:first-child).active { - background: var(--color-lighter-segment); - color: var(--color-segmented); - font-weight: bold; -} - -.p-segmented-outline { - border: 2px solid var(--color-segmented); -} -.p-segmented-outline a:not(:first-child) { - border-left: 2px solid var(--color-segmented); -} - -.p-segmented-controls-outline-alt a:not(:first-child) { - border: 2px solid transparent; -} - -.p-segmented-controls-outline-alt { - border-radius: 30px; -} -.p-segmented-controls-outline-alt a { - border: 2px solid transparent; - border-radius: 30px; -} -.p-segmented-controls-outline-alt a.active { - background: #fff; - border-color: var(--color-segmented); - border-radius: 30px; - color: var(--color-segmented); - font-weight: bold; -} - -.p-segmented-grey { - --color-segmented: #555761; - --color-lighter-segment: #d4d4d4; -} - -/* END OF SEGMENTED CONTROLS */ - -.p-shadow-1 { - box-shadow: 0 3px 10px rgba(0, 0, 0, 0.1); -} - -.p-shadow-2 { - box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); -} - -.p-shadow-3 { - box-shadow: 0 10px 18px rgba(0, 0, 0, 0.3); -} - -.p-shadow-4 { - box-shadow: 0 25px 30px rgba(0, 0, 0, 0.2); -} - -.p-to-shadow-4, -.p-to-shadow-3, -.p-to-shadow-2, -.p-to-shadow-1 { - transition-timing-function: ease; - transition: box-shadow 0.5s; -} - -.p-to-shadow-1:hover { - box-shadow: 0 3px 10px rgba(0, 0, 0, 0.1);> -} - -.p-to-shadow-2:hover { - box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); -} - -.p-to-shadow-3:hover { - box-shadow: 0 10px 18px rgba(0, 0, 0, 0.3); -} - -.p-to-shadow-4:hover { - box-shadow: 0 25px 30px rgba(0, 0, 0, 0.2); -} - - -/* END OF SHADOWS */ - -.p-tabs-container { - background: #e3e3e3; - border: 1px solid #e0e0e0; - padding: 1em; -} - -.p-tabs-container.p-light { - background: none; - border: none; -} - -.p-tabs-container.p-light .p-panels { - margin-top: 0; - border-radius: 0; - padding: 0; -} - -.p-tabs { - display: flex; - justify-content: center; -} - -.p-tabs > :nth-of-type(1) { - border-radius: 5px 0 0 5px; -} - -.p-tabs > :last-child { - border-radius: 0 5px 5px 0; -} - -.p-tab { - margin: 0; - padding: 5px 35px; - background: #fff; - color: #333230; - text-decoration: none; - /* text-shadow: 0 1px 1px rgba(0, 0, 0, 0.25); */ - border: 1px solid #cacaca; - display: inline-block; - font-size: 17px; - font-family: -apple-system, "Inter", sans-serif; - cursor: pointer; -} - -.p-tab:focus { - outline: 0; -} - -.p-is-active { - background: linear-gradient(to bottom, #4fc5fa 0%, #0f75f5 100%); - border: 0; - color: #fff; -} - -.p-panels { - margin-top: 1em; - background: #fff; - border-radius: 3px; - position: relative; - padding: 0.8em; - overflow: hidden; -} - -.p-panel.p-is-active { - opacity: 1; - pointer-events: all; - background: none; - color: inherit; - position: static; -} - -.p-panel { - position: absolute; - opacity: 0; - pointer-events: none; -} - -@media (max-width: 768px) { - .p-tabs { - overflow: auto; - } - .p-tab { - font-size: 0.8em; - padding: 5px 28px; - } - .p-tabs-container { - padding: 0.8em; - } - - .p-panels { - padding: 0.8em; - } -} - -@media screen and (max-width: 496px) { - .p-tab { - text-align: center; - padding: 5px 18px; - } - .p-tabs-container { - padding: 0.5em; - } - - .p-panels { - padding: 0.5em; - margin-top: 0.5em; - } -} - -@media screen and (max-width: 378px) { - .p-tab { - text-align: center; - padding: 5px 10px; - } - .p-tabs-container { - padding: 0.5em; - } - - .p-panels { - padding: 0.5em; - margin-top: 0.5; - } -} - -.p-mobile-tabs { - position: fixed; - bottom: 0; - left: 0; - width: 100%; - padding: 15px 0px; - border-top: 1px solid #949494; - background: rgba(202, 202, 202, 0.8); - backdrop-filter: blur(10px); - display: flex; - font-family: -apple-system, "Inter", sans-serif; -} - -.p-mobile-tabs > div { - flex: auto; - text-align: center; -} - -.p-mobile-tabs a { - text-decoration: none; - color: #555; - transition: color 0.5s; - display: inline-block; - font-size: 0.8rem; -} - -.p-mobile-tabs a.active { - color: #0f75f5; - font-weight: 600; -} - -.p-mobile-tabs svg { - display: block; - margin: auto; - margin-bottom: 0.2rem; -} - -.p-mobile-tabs--content { - display: none; -} - -.p-mobile-tabs--content.active { - display: block; -} - -/* END OF TABS */ - - -.p-action-background{ - background: rgba(0, 0, 0, 0.3); - height: 100vh; - left: 0; - opacity: 0; - pointer-events: none; - position: fixed; - top: 0; - transition: all 0.3s; - width: 100vw; - z-index: 5; -} - -.p-action-background.nowactive { - opacity: 1; - pointer-events: auto; -} - - -.p-action-big-container{ - position:fixed; - width: 100%; - box-sizing: border-box; - padding: 1rem 5vw; - bottom:0; -} - -.p-action-container{ - background: rgba(255, 255, 255, 0.8); - backdrop-filter: blur(10px); - display:block; - margin:auto; - margin-bottom: 10px; - border-radius: 10px; -} - -.p-action-big-container .p-action-container:first-child{ - margin-bottom:10px; -} - -.p-action--intern{ - display:block; - margin:auto; - text-align:center; - padding: 15px 0; - border-bottom: 1px solid #bfbfbf; - font-weight: 500; - color: #0f75f5; - text-decoration:none; -} - -.p-action-destructive{ - color: #c6262e; -} - -.p-action-neutral{ - color: #555761; -} - -.p-action-cancel, .p-action-container a:last-child{ - border-bottom:none; -} - -.p-action-cancel{ - font-weight:bold; -} - -.p-action-icon{ - position:relative; -} -.p-action-icon svg, .p-action-icon img{ - position:absolute; - left:5%; - top:50%; - transform:translateY(-50%); -} - -.p-action-icon-inline{ - text-align: left; - display: flex; - align-items: center; -} - -.p-action-icon-inline svg, .p-action-icon-inline img{ - margin-left: 5%; - margin-right: 3%; -} - -.p-action-title{ - padding: 30px 15px; - border-bottom: 1px solid #bfbfbf; -} - -.p-action-title--intern,.p-action-text{ - margin:0; - color:#555761; -} - -.p-action-title--intern{ - margin-bottom: .3rem; -} - -@supports not (backdrop-filter: blur(10px)) { - .p-action-container { - background: rgba(255,255,255,.95); - } -} - -.p-action-big-container{ - -webkit-transform: translateY(30%); - transform: translateY(30%); - opacity: 0; - transition: opacity 0.4s, transform 0.4s; - transition-timing-function: ease-in-out; -} - -.p-action-big-container.active { --webkit-transform: translateY(0); - transform: translateY(0); - opacity: 1; -} - - -/* END OF ACTIONS */ diff --git a/v3/examples/ios/frontend/public/style.css b/v3/examples/ios/frontend/public/style.css deleted file mode 100644 index 5bf3738a9..000000000 --- a/v3/examples/ios/frontend/public/style.css +++ /dev/null @@ -1,327 +0,0 @@ -:root { - font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, - sans-serif, "Apple Color Emoji", "Segoe UI Emoji"; - font-size: 16px; - line-height: 24px; - font-weight: 400; - color-scheme: light dark; - /* Desktop defaults (mobile overrides below) */ - --bg: #ffffff; - --fg: #213547; - font-synthesis: none; - text-rendering: optimizeLegibility; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - -webkit-text-size-adjust: 100%; - user-select: none; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; -} - -/* Mobile bottom tabs layout (works on all themes) */ -.mobile-pane { - display: flex; - flex-direction: column; - width: 100%; - max-width: 520px; - height: 70vh; /* fixed-height main screen */ - border-radius: 12px; -} -.mobile-pane .p-mobile-tabs-content { - position: relative; - flex: 1 1 auto; - overflow: hidden; /* contain panels */ - display: flex; - flex-direction: column; -} -.p-mobile-tabs-content .p-mobile-tabs--content { - display: none; - overflow: auto; /* scroll inside content area */ - -webkit-overflow-scrolling: touch; - padding: 8px 8px 16px; -} -.p-mobile-tabs-content .p-mobile-tabs--content.active { display: block; } - -*, *::before, *::after { - box-sizing: border-box; -} - -/* Prefer system fonts on mobile; remove custom font to reduce bundle size */ - -h3 { - font-size: 3em; - line-height: 1.1; -} - -a { - font-weight: 500; - color: #646cff; - text-decoration: inherit; -} - -a:hover { - color: #535bf2; -} - -/* Remove generic button styling to allow Puppertino .btn to control buttons */ - -.result { - height: 20px; - line-height: 20px; -} - -html, -body { - height: 100%; - width: 100%; - overflow-x: hidden; /* prevent horizontal overflow */ - overflow-y: auto; /* allow vertical scroll if needed */ -} - -body { - margin: 0; - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - min-width: 320px; - /* Use small viewport units to avoid iOS Safari URL bar issues */ - min-height: 100svh; - height: auto; /* avoid forcing overflow */ - /* Equal responsive spacing top & bottom */ - padding-block: clamp(8px, 4vh, 48px); - color: var(--fg); - background-color: var(--bg); -} - -.container { - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - /* Responsive spacing between elements */ - gap: clamp(8px, 2vh, 24px); - width: 100%; - max-width: 480px; - padding-inline: 16px; -} - -h1 { - /* Responsive heading size */ - font-size: clamp(1.6rem, 6vw, 3.2rem); - line-height: 1.1; -} - -#app { - max-width: 1280px; - margin: 0 auto; - /* Responsive inner padding: horizontal only, no extra top/bottom */ - padding: 0 clamp(12px, 4vw, 32px); - text-align: center; -} - -.logo { - /* Consistent visual size across images: fix height, auto width */ - height: clamp(80px, 18vh, 140px); - width: auto; - max-width: 80vw; - padding: 0.5em; - will-change: filter; -} - -.logo:hover { - filter: drop-shadow(0 0 2em #e80000aa); -} - -.logo.vanilla:hover { - filter: drop-shadow(0 0 2em #f7df1eaa); -} - -.result { - height: 20px; - line-height: 20px; - margin: 1.5rem auto; - text-align: center; -} - -.footer { - margin-top: 1rem; - align-content: center; - text-align: center; -} - -/* Tabs: default hide panels, show one matching the checked radio */ -.tabs .tabs-content .tab-panel { display: none; } -.tabs input#tab-js:checked ~ .tabs-content [data-tab="tab-js"] { display: block; } -.tabs input#tab-go:checked ~ .tabs-content [data-tab="tab-go"] { display: block; } - -/* Sticky tabs header */ -.tabs .tabs-header { - position: sticky; - top: env(safe-area-inset-top); - z-index: 5; - display: grid; - grid-template-columns: 1fr 1fr; - gap: 8px; - padding: 8px 0; - background: var(--bg); - backdrop-filter: saturate(1.2) blur(4px); -} - -/* Subtle divider under sticky header */ -.tabs .tabs-header::after { - content: ""; - grid-column: 1 / -1; - height: 1px; - background: rgba(0,0,0,0.08); - margin-top: 8px; -} - -/* Mobile-specific light mode */ -@media (max-width: 768px) and (prefers-color-scheme: light) { - :root { - --fg: #213547; - --bg: #ffffff; - } - - a:hover { - color: #747bff; - } - - /* allow Puppertino to style .btn */ - - .input-box .input { - color: #111827; - background-color: #f3f4f6; - border: 1px solid #e5e7eb; /* show border in light mode */ - border-radius: 8px; - } - - button:hover { - border-color: #d1d5db; /* slate-300 */ - } - - .input-box .input:focus { - border-color: #9ca3af; /* gray-400 */ - box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.15); /* subtle focus ring */ - } -} - -/* let Puppertino handle .btn hover */ - -.input-box .input { - border: 1px solid transparent; /* default; themed in media queries */ - border-radius: 8px; - outline: none; - height: 30px; - line-height: 30px; - padding: 0 10px; - color: black; - background-color: rgba(240, 240, 240, 1); - -webkit-font-smoothing: antialiased; -} - -.input-box .input:hover { - background-color: rgba(255, 255, 255, 1); -} - -.input-box .input:focus { - background-color: rgba(255, 255, 255, 1); - outline: 2px solid transparent; - outline-offset: 2px; -} - -/* Mobile-specific dark mode */ -@media (max-width: 768px) and (prefers-color-scheme: dark) { - :root { - color: rgba(255, 255, 255, 0.88); - --fg: rgba(255, 255, 255, 0.88); - --bg: #0f1115; /* deep dark background */ - } - - a { - color: #8ea2ff; - } - - a:hover { - color: #aab6ff; - } - - /* allow Puppertino to style .btn in dark mode */ - - .input-box .input { - background-color: #111827; /* gray-900 */ - color: #e5e7eb; - caret-color: #ffffff; - border: 1px solid #374151; /* slate-700 */ - } - - .input-box .input:hover, - .input-box .input:focus { - background-color: #0b1220; - border-color: #4b5563; /* slate-600 */ - } - - /* allow Puppertino to handle active state */ -} - -/* Mobile baseline overrides (apply to both light and dark) */ -@media (max-width: 768px) { - /* Prevent iOS zoom on focus */ - input, textarea, select, button { font-size: 16px; } - - /* Make layout vertical and scrollable */ - html, body { - height: auto; - min-height: 100svh; - overflow-x: hidden; - overflow-y: auto; - -webkit-overflow-scrolling: touch; - } - - body { - padding-top: env(safe-area-inset-top); - padding-bottom: env(safe-area-inset-bottom); - position: static; - } - - .container { - width: 100%; - max-width: 520px; /* allow a bit wider on phones */ - align-items: stretch; - } - - /* Stack controls vertically with full-width tap targets */ - .input-box { - display: flex; - flex-direction: column; - align-items: stretch; - gap: 10px; - } - - .input-box .input, - .input, - button, - .p-btn { - width: 100%; - min-height: 44px; /* comfortable touch target */ - } - - /* Tabs vertical and full-width */ - .tabs { - display: grid; - grid-template-columns: 1fr; - gap: 8px; - } - .tabs .p-btn { width: 100%; } - - /* Cap device info height for readability */ - #deviceInfo { - max-height: 30vh; - overflow: auto; - padding: 8px; - border-radius: 8px; - background: rgba(0,0,0,0.04); - } -} \ No newline at end of file diff --git a/v3/examples/ios/frontend/public/wails.png b/v3/examples/ios/frontend/public/wails.png deleted file mode 100644 index 8bdf42483..000000000 Binary files a/v3/examples/ios/frontend/public/wails.png and /dev/null differ diff --git a/v3/examples/ios/frontend/vite.config.js b/v3/examples/ios/frontend/vite.config.js deleted file mode 100644 index 87b093bc3..000000000 --- a/v3/examples/ios/frontend/vite.config.js +++ /dev/null @@ -1,11 +0,0 @@ -import { defineConfig } from 'vite'; -import path from 'path'; - -export default defineConfig({ - resolve: { - alias: { - // Use the local repo runtime sources instead of the published package - '@wailsio/runtime': path.resolve(__dirname, '../../../internal/runtime/desktop/@wailsio/runtime/src/index.ts'), - }, - }, -}); diff --git a/v3/examples/ios/go.mod b/v3/examples/ios/go.mod deleted file mode 100644 index d2e86c73a..000000000 --- a/v3/examples/ios/go.mod +++ /dev/null @@ -1,49 +0,0 @@ -module ios-example - -go 1.25 - -require github.com/wailsapp/wails/v3 v3.0.0-dev - -require ( - dario.cat/mergo v1.0.2 // indirect - github.com/Microsoft/go-winio v0.6.2 // indirect - github.com/ProtonMail/go-crypto v1.3.0 // indirect - github.com/adrg/xdg v0.5.3 // indirect - github.com/bep/debounce v1.2.1 // indirect - github.com/cloudflare/circl v1.6.3 // indirect - github.com/coder/websocket v1.8.14 // indirect - github.com/cyphar/filepath-securejoin v0.6.1 // indirect - github.com/ebitengine/purego v0.9.1 // indirect - github.com/emirpasic/gods v1.18.1 // indirect - github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect - github.com/go-git/go-billy/v5 v5.7.0 // indirect - github.com/go-git/go-git/v5 v5.16.4 // indirect - github.com/go-ole/go-ole v1.3.0 // indirect - github.com/godbus/dbus/v5 v5.2.2 // indirect - github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect - github.com/google/uuid v1.6.0 // indirect - github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect - github.com/jchv/go-winloader v0.0.0-20250406163304-c1995be93bd1 // indirect - github.com/kevinburke/ssh_config v1.4.0 // indirect - github.com/klauspost/cpuid/v2 v2.3.0 // indirect - github.com/leaanthony/go-ansi-parser v1.6.1 // indirect - github.com/leaanthony/u v1.1.1 // indirect - github.com/lmittmann/tint v1.1.2 // indirect - github.com/mattn/go-colorable v0.1.14 // indirect - github.com/mattn/go-isatty v0.0.20 // indirect - github.com/pjbgf/sha1cd v0.5.0 // indirect - github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c // indirect - github.com/rivo/uniseg v0.4.7 // indirect - github.com/samber/lo v1.52.0 // indirect - github.com/sergi/go-diff v1.4.0 // indirect - github.com/skeema/knownhosts v1.3.2 // indirect - github.com/wailsapp/go-webview2 v1.0.23 // indirect - github.com/xanzy/ssh-agent v0.3.3 // indirect - golang.org/x/crypto v0.47.0 // indirect - golang.org/x/net v0.49.0 // indirect - golang.org/x/sys v0.40.0 // indirect - golang.org/x/text v0.33.0 // indirect - gopkg.in/warnings.v0 v0.1.2 // indirect -) - -replace github.com/wailsapp/wails/v3 => ../../../v3 diff --git a/v3/examples/ios/go.sum b/v3/examples/ios/go.sum deleted file mode 100644 index 56f1153ea..000000000 --- a/v3/examples/ios/go.sum +++ /dev/null @@ -1,147 +0,0 @@ -dario.cat/mergo v1.0.2 h1:85+piFYR1tMbRrLcDwR18y4UKJ3aH1Tbzi24VRW1TK8= -dario.cat/mergo v1.0.2/go.mod h1:E/hbnu0NxMFBjpMIE34DRGLWqDy0g5FuKDhCb31ngxA= -github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY= -github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= -github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= -github.com/ProtonMail/go-crypto v1.3.0 h1:ILq8+Sf5If5DCpHQp4PbZdS1J7HDFRXz/+xKBiRGFrw= -github.com/ProtonMail/go-crypto v1.3.0/go.mod h1:9whxjD8Rbs29b4XWbB8irEcE8KHMqaR2e7GWU1R+/PE= -github.com/adrg/xdg v0.5.3 h1:xRnxJXne7+oWDatRhR1JLnvuccuIeCoBu2rtuLqQB78= -github.com/adrg/xdg v0.5.3/go.mod h1:nlTsY+NNiCBGCK2tpm09vRqfVzrc2fLmXGpBLF0zlTQ= -github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8= -github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4= -github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= -github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= -github.com/bep/debounce v1.2.1 h1:v67fRdBA9UQu2NhLFXrSg0Brw7CexQekrBwDMM8bzeY= -github.com/bep/debounce v1.2.1/go.mod h1:H8yggRPQKLUhUoqrJC1bO2xNya7vanpDl7xR3ISbCJ0= -github.com/cloudflare/circl v1.6.3 h1:9GPOhQGF9MCYUeXyMYlqTR6a5gTrgR/fBLXvUgtVcg8= -github.com/cloudflare/circl v1.6.3/go.mod h1:2eXP6Qfat4O/Yhh8BznvKnJ+uzEoTQ6jVKJRn81BiS4= -github.com/coder/websocket v1.8.14 h1:9L0p0iKiNOibykf283eHkKUHHrpG7f65OE3BhhO7v9g= -github.com/coder/websocket v1.8.14/go.mod h1:NX3SzP+inril6yawo5CQXx8+fk145lPDC6pumgx0mVg= -github.com/cyphar/filepath-securejoin v0.6.1 h1:5CeZ1jPXEiYt3+Z6zqprSAgSWiggmpVyciv8syjIpVE= -github.com/cyphar/filepath-securejoin v0.6.1/go.mod h1:A8hd4EnAeyujCJRrICiOWqjS1AX0a9kM5XL+NwKoYSc= -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= -github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/ebitengine/purego v0.9.1 h1:a/k2f2HQU3Pi399RPW1MOaZyhKJL9w/xFpKAg4q1s0A= -github.com/ebitengine/purego v0.9.1/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ= -github.com/elazarl/goproxy v1.7.2 h1:Y2o6urb7Eule09PjlhQRGNsqRfPmYI3KKQLFpCAV3+o= -github.com/elazarl/goproxy v1.7.2/go.mod h1:82vkLNir0ALaW14Rc399OTTjyNREgmdL2cVoIbS6XaE= -github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc= -github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ= -github.com/gliderlabs/ssh v0.3.8 h1:a4YXD1V7xMF9g5nTkdfnja3Sxy1PVDCj1Zg4Wb8vY6c= -github.com/gliderlabs/ssh v0.3.8/go.mod h1:xYoytBv1sV0aL3CavoDuJIQNURXkkfPA/wxQ1pL1fAU= -github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI= -github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmSxCcxctByoQdvwPiA7DTK7jaaFDBTtu0ic= -github.com/go-git/go-billy/v5 v5.7.0 h1:83lBUJhGWhYp0ngzCMSgllhUSuoHP1iEWYjsPl9nwqM= -github.com/go-git/go-billy/v5 v5.7.0/go.mod h1:/1IUejTKH8xipsAcdfcSAlUlo2J7lkYV8GTKxAT/L3E= -github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399 h1:eMje31YglSBqCdIqdhKBW8lokaMrL3uTkpGYlE2OOT4= -github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399/go.mod h1:1OCfN199q1Jm3HZlxleg+Dw/mwps2Wbk9frAWm+4FII= -github.com/go-git/go-git/v5 v5.16.4 h1:7ajIEZHZJULcyJebDLo99bGgS0jRrOxzZG4uCk2Yb2Y= -github.com/go-git/go-git/v5 v5.16.4/go.mod h1:4Ge4alE/5gPs30F2H1esi2gPd69R0C39lolkucHBOp8= -github.com/go-json-experiment/json v0.0.0-20251027170946-4849db3c2f7e h1:Lf/gRkoycfOBPa42vU2bbgPurFong6zXeFtPoxholzU= -github.com/go-json-experiment/json v0.0.0-20251027170946-4849db3c2f7e/go.mod h1:uNVvRXArCGbZ508SxYYTC5v1JWoz2voff5pm25jU1Ok= -github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE= -github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78= -github.com/godbus/dbus/v5 v5.2.2 h1:TUR3TgtSVDmjiXOgAAyaZbYmIeP3DPkld3jgKGV8mXQ= -github.com/godbus/dbus/v5 v5.2.2/go.mod h1:3AAv2+hPq5rdnr5txxxRwiGjPXamgoIHgz9FPBfOp3c= -github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 h1:f+oWsMOmNPc8JmEHVZIycC7hBoQxHH9pNKQORJNozsQ= -github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8/go.mod h1:wcDNUvekVysuuOpQKo3191zZyTpiI6se1N1ULghS0sw= -github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= -github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= -github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= -github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A= -github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= -github.com/jchv/go-winloader v0.0.0-20250406163304-c1995be93bd1 h1:njuLRcjAuMKr7kI3D85AXWkw6/+v9PwtV6M6o11sWHQ= -github.com/jchv/go-winloader v0.0.0-20250406163304-c1995be93bd1/go.mod h1:alcuEEnZsY1WQsagKhZDsoPCRoOijYqhZvPwLG0kzVs= -github.com/kevinburke/ssh_config v1.4.0 h1:6xxtP5bZ2E4NF5tuQulISpTO2z8XbtH8cg1PWkxoFkQ= -github.com/kevinburke/ssh_config v1.4.0/go.mod h1:q2RIzfka+BXARoNexmF9gkxEX7DmvbW9P4hIVx2Kg4M= -github.com/klauspost/cpuid/v2 v2.3.0 h1:S4CRMLnYUhGeDFDqkGriYKdfoFlDnMtqTiI/sFzhA9Y= -github.com/klauspost/cpuid/v2 v2.3.0/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0= -github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= -github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= -github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= -github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= -github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/leaanthony/go-ansi-parser v1.6.1 h1:xd8bzARK3dErqkPFtoF9F3/HgN8UQk0ed1YDKpEz01A= -github.com/leaanthony/go-ansi-parser v1.6.1/go.mod h1:+vva/2y4alzVmmIEpk9QDhA7vLC5zKDTRwfZGOp3IWU= -github.com/leaanthony/u v1.1.1 h1:TUFjwDGlNX+WuwVEzDqQwC2lOv0P4uhTQw7CMFdiK7M= -github.com/leaanthony/u v1.1.1/go.mod h1:9+o6hejoRljvZ3BzdYlVL0JYCwtnAsVuN9pVTQcaRfI= -github.com/lmittmann/tint v1.1.2 h1:2CQzrL6rslrsyjqLDwD11bZ5OpLBPU+g3G/r5LSfS8w= -github.com/lmittmann/tint v1.1.2/go.mod h1:HIS3gSy7qNwGCj+5oRjAutErFBl4BzdQP6cJZ0NfMwE= -github.com/matryer/is v1.4.0/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwMRU= -github.com/matryer/is v1.4.1 h1:55ehd8zaGABKLXQUe2awZ99BD/PTc2ls+KV/dXphgEQ= -github.com/matryer/is v1.4.1/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwMRU= -github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE= -github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8= -github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= -github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= -github.com/onsi/gomega v1.34.1 h1:EUMJIKUjM8sKjYbtxQI9A4z2o+rruxnzNvpknOXie6k= -github.com/onsi/gomega v1.34.1/go.mod h1:kU1QgUvBDLXBJq618Xvm2LUX6rSAfRaFRTcdOeDLwwY= -github.com/pjbgf/sha1cd v0.5.0 h1:a+UkboSi1znleCDUNT3M5YxjOnN1fz2FhN48FlwCxs0= -github.com/pjbgf/sha1cd v0.5.0/go.mod h1:lhpGlyHLpQZoxMv8HcgXvZEhcGs0PG/vsZnEJ7H0iCM= -github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmdv1U2eRNDiU2ErMBj1gwrq8eQ= -github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c/go.mod h1:7rwL4CYBLnjLxUqIJNnCWiEdr3bn6IUYi15bNlnbCCU= -github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= -github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= -github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= -github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= -github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= -github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= -github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= -github.com/samber/lo v1.52.0 h1:Rvi+3BFHES3A8meP33VPAxiBZX/Aws5RxrschYGjomw= -github.com/samber/lo v1.52.0/go.mod h1:4+MXEGsJzbKGaUEQFKBq2xtfuznW9oz/WrgyzMzRoM0= -github.com/sergi/go-diff v1.4.0 h1:n/SP9D5ad1fORl+llWyN+D6qoUETXNZARKjyY2/KVCw= -github.com/sergi/go-diff v1.4.0/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4= -github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= -github.com/skeema/knownhosts v1.3.2 h1:EDL9mgf4NzwMXCTfaxSD/o/a5fxDw/xL9nkU28JjdBg= -github.com/skeema/knownhosts v1.3.2/go.mod h1:bEg3iQAuw+jyiw+484wwFJoKSLwcfd7fqRy+N0QTiow= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= -github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= -github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= -github.com/wailsapp/go-webview2 v1.0.23 h1:jmv8qhz1lHibCc79bMM/a/FqOnnzOGEisLav+a0b9P0= -github.com/wailsapp/go-webview2 v1.0.23/go.mod h1:qJmWAmAmaniuKGZPWwne+uor3AHMB5PFhqiK0Bbj8kc= -github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM= -github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw= -golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.47.0 h1:V6e3FRj+n4dbpw86FJ8Fv7XVOql7TEwpHapKoMJ/GO8= -golang.org/x/crypto v0.47.0/go.mod h1:ff3Y9VzzKbwSSEzWqJsJVBnWmRwRSHt/6Op5n9bQc4A= -golang.org/x/exp v0.0.0-20260112195511-716be5621a96 h1:Z/6YuSHTLOHfNFdb8zVZomZr7cqNgTJvA8+Qz75D8gU= -golang.org/x/exp v0.0.0-20260112195511-716be5621a96/go.mod h1:nzimsREAkjBCIEFtHiYkrJyT+2uy9YZJB7H1k68CXZU= -golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.49.0 h1:eeHFmOGUTtaaPSGNmjBKpbng9MulQsJURQUAfUwY++o= -golang.org/x/net v0.49.0/go.mod h1:/ysNB2EvaqvesRkuLAyjI1ycPZlQHM3q01F02UY/MV8= -golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200810151505-1b9f1253b3ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.40.0 h1:DBZZqJ2Rkml6QMQsZywtnjnnGvHza6BTfYFWY9kjEWQ= -golang.org/x/sys v0.40.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= -golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.39.0 h1:RclSuaJf32jOqZz74CkPA9qFuVTX7vhLlpfj/IGWlqY= -golang.org/x/term v0.39.0/go.mod h1:yxzUCTP/U+FzoxfdKmLaA0RV1WgE0VY7hXBwKtY/4ww= -golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.33.0 h1:B3njUFyqtHDUI5jMn1YIr5B0IE2U0qck04r6d4KPAxE= -golang.org/x/text v0.33.0/go.mod h1:LuMebE6+rBincTi9+xWTY8TztLzKHc/9C1uBCG27+q8= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= -gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME= -gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= -gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= -gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= -gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/v3/examples/ios/greetservice.go b/v3/examples/ios/greetservice.go deleted file mode 100644 index 8972c39cd..000000000 --- a/v3/examples/ios/greetservice.go +++ /dev/null @@ -1,7 +0,0 @@ -package main - -type GreetService struct{} - -func (g *GreetService) Greet(name string) string { - return "Hello " + name + "!" -} diff --git a/v3/examples/ios/ios_runtime_events_ios.go b/v3/examples/ios/ios_runtime_events_ios.go deleted file mode 100644 index 99ccf66d4..000000000 --- a/v3/examples/ios/ios_runtime_events_ios.go +++ /dev/null @@ -1,62 +0,0 @@ -//go:build ios - -package main - -import ( - "github.com/wailsapp/wails/v3/pkg/application" -) - -// registerIOSRuntimeEventHandlers registers Go-side event listeners that mutate iOS WKWebView at runtime. -func registerIOSRuntimeEventHandlers(app *application.App) { - // Helper to fetch boolean from event data. Accepts {"enabled":bool} or a bare bool. - getBool := func(data any, key string, def bool) bool { - switch v := data.(type) { - case bool: - return v - case map[string]any: - if raw, ok := v[key]; ok { - if b, ok := raw.(bool); ok { - return b - } - } - } - return def - } - // Helper to fetch string from event data. Accepts {"ua":string} or bare string. - getString := func(data any, key string) string { - switch v := data.(type) { - case string: - return v - case map[string]any: - if raw, ok := v[key]; ok { - if s, ok := raw.(string); ok { - return s - } - } - } - return "" - } - - app.Event.On("ios:setScrollEnabled", func(e *application.CustomEvent) { - application.IOSSetScrollEnabled(getBool(e.Data, "enabled", true)) - }) - app.Event.On("ios:setBounceEnabled", func(e *application.CustomEvent) { - application.IOSSetBounceEnabled(getBool(e.Data, "enabled", true)) - }) - app.Event.On("ios:setScrollIndicatorsEnabled", func(e *application.CustomEvent) { - application.IOSSetScrollIndicatorsEnabled(getBool(e.Data, "enabled", true)) - }) - app.Event.On("ios:setBackForwardGesturesEnabled", func(e *application.CustomEvent) { - application.IOSSetBackForwardGesturesEnabled(getBool(e.Data, "enabled", false)) - }) - app.Event.On("ios:setLinkPreviewEnabled", func(e *application.CustomEvent) { - application.IOSSetLinkPreviewEnabled(getBool(e.Data, "enabled", true)) - }) - app.Event.On("ios:setInspectableEnabled", func(e *application.CustomEvent) { - application.IOSSetInspectableEnabled(getBool(e.Data, "enabled", true)) - }) - app.Event.On("ios:setCustomUserAgent", func(e *application.CustomEvent) { - ua := getString(e.Data, "ua") - application.IOSSetCustomUserAgent(ua) - }) -} diff --git a/v3/examples/ios/ios_runtime_events_stub.go b/v3/examples/ios/ios_runtime_events_stub.go deleted file mode 100644 index 4c7376d7d..000000000 --- a/v3/examples/ios/ios_runtime_events_stub.go +++ /dev/null @@ -1,8 +0,0 @@ -//go:build !ios - -package main - -import "github.com/wailsapp/wails/v3/pkg/application" - -// Non-iOS: no-op so examples build on other platforms -func registerIOSRuntimeEventHandlers(app *application.App) {} diff --git a/v3/examples/ios/main.go b/v3/examples/ios/main.go deleted file mode 100644 index f49b73cd8..000000000 --- a/v3/examples/ios/main.go +++ /dev/null @@ -1,88 +0,0 @@ -package main - -import ( - "embed" - _ "embed" - "log" - "time" - - "github.com/wailsapp/wails/v3/pkg/application" -) - -// Wails uses Go's `embed` package to embed the frontend files into the binary. -// Any files in the frontend/dist folder will be embedded into the binary and -// made available to the frontend. -// See https://pkg.go.dev/embed for more information. - -//go:embed all:frontend/dist -var assets embed.FS - -// main function serves as the application's entry point. It initializes the application, creates a window, -// and starts a goroutine that emits a time-based event every second. It subsequently runs the application and -// logs any error that might occur. -func main() { - - // Create a new Wails application by providing the necessary options. - // Variables 'Name' and 'Description' are for application metadata. - // 'Assets' configures the asset server with the 'FS' variable pointing to the frontend files. - // 'Bind' is a list of Go struct instances. The frontend has access to the methods of these instances. - // 'Mac' options tailor the application when running an macOS. - app := application.New(application.Options{ - Name: "ios", - Description: "A demo of using raw HTML & CSS", - Services: []application.Service{ - application.NewService(&GreetService{}), - }, - Assets: application.AssetOptions{ - Handler: application.AssetFileServerFS(assets), - }, - Mac: application.MacOptions{ - ApplicationShouldTerminateAfterLastWindowClosed: true, - }, - IOS: application.IOSOptions{ - EnableNativeTabs: true, - NativeTabsItems: []application.NativeTabItem{ - {Title: "Home", SystemImage: "house"}, - {Title: "Settings", SystemImage: "gear"}, - }, - }, - }) - - // Register iOS runtime event handlers so the frontend can emit events - // to toggle WKWebView settings at runtime (Go path). - registerIOSRuntimeEventHandlers(app) - - // Create a new window with the necessary options. - // 'Title' is the title of the window. - // 'Mac' options tailor the window when running on macOS. - // 'BackgroundColour' is the background colour of the window. - // 'URL' is the URL that will be loaded into the webview. - app.Window.NewWithOptions(application.WebviewWindowOptions{ - Title: "Window 1", - Mac: application.MacWindow{ - InvisibleTitleBarHeight: 50, - Backdrop: application.MacBackdropTranslucent, - TitleBar: application.MacTitleBarHiddenInset, - }, - BackgroundColour: application.NewRGB(27, 38, 54), - URL: "/", - }) - - // Create a goroutine that emits an event containing the current time every second. - // The frontend can listen to this event and update the UI accordingly. - go func() { - for { - now := time.Now().Format(time.RFC1123) - app.Event.Emit("time", now) - time.Sleep(time.Second) - } - }() - - // Run the application. This blocks until the application has been exited. - err := app.Run() - - // If an error occurred while running the application, log it and exit. - if err != nil { - log.Fatal(err) - } -} diff --git a/v3/examples/keybindings/README.md b/v3/examples/keybindings/README.md deleted file mode 100644 index 2180cc9d0..000000000 --- a/v3/examples/keybindings/README.md +++ /dev/null @@ -1,21 +0,0 @@ -# Keybindings Example - -This simple example demonstrates how to use keybindings in your application. -Run the example and press `Ctrl/CMD+Shift+C` to center the focused window. - -## Running the example - -To run the example, simply run the following command: - -```bash -go run . -``` - -# Status - -| Platform | Status | -|----------|---------| -| Mac | Working | -| Windows | Working | -| Linux | | - diff --git a/v3/examples/keybindings/main.go b/v3/examples/keybindings/main.go deleted file mode 100644 index b07bf366b..000000000 --- a/v3/examples/keybindings/main.go +++ /dev/null @@ -1,50 +0,0 @@ -package main - -import ( - _ "embed" - "github.com/wailsapp/wails/v3/pkg/application" - "log" -) - -func main() { - app := application.New(application.Options{ - Name: "Key Bindings Demo", - Description: "A demo of the Key Bindings Options", - Mac: application.MacOptions{ - ApplicationShouldTerminateAfterLastWindowClosed: true, - }, - KeyBindings: map[string]func(window application.Window){ - "shift+ctrl+c": func(window application.Window) { - window.Center() - }, - }, - }) - - app.Window.NewWithOptions(application.WebviewWindowOptions{ - Name: "Window 1", - Title: "Window 1", - URL: "https://wails.io", - KeyBindings: map[string]func(window application.Window){ - "F12": func(window application.Window) { - window.OpenDevTools() - }, - }, - }) - - app.Window.NewWithOptions(application.WebviewWindowOptions{ - Name: "Window 2", - Title: "Window 2", - URL: "https://google.com", - KeyBindings: map[string]func(window application.Window){ - "F12": func(window application.Window) { - println("Window 2: Toggle Dev Tools") - }, - }, - }) - - err := app.Run() - if err != nil { - log.Fatal(err) - } - -} diff --git a/v3/examples/linux_status.org b/v3/examples/linux_status.org deleted file mode 100644 index fdb31ac27..000000000 --- a/v3/examples/linux_status.org +++ /dev/null @@ -1,28 +0,0 @@ - -* Status - -| Example | Status | Notes | -|--------------+-----------------+-------------------------------------------------------------------------------| -| binding | works | | -| build | works | removed OS X specific env variables from default target | -| clipboard | works | | -| contextmenus | works (partial) | | -| dev | works | purpose? | -| dialogs | | broken | -| drag-n-drop | works | | -| events | partial | receives WailsEvents - not ApplicationEvents | -| frameless | partial | drag areas do not function | -| hide-window | partial | crash on windowShow - believe this is because window is being destroyed not hidden | -| keybindings | working | | -| menu | working | Lock WebviewWindow Resize isn't correct | -| oauth | failed | Can't type in window - but can paste - redirect failed as well | -| plain | works | | -| plugins | works | Might should provide example commands or something. | -| screen | failed | | -| server | works | | -| systray | works | | -| video | works | binary is named 'frameless' | -| window | partial | Screens related stuff isn't implemented | -| wml | partial | | - - diff --git a/v3/examples/liquid-glass/.gitignore b/v3/examples/liquid-glass/.gitignore deleted file mode 100644 index 45d2406b0..000000000 --- a/v3/examples/liquid-glass/.gitignore +++ /dev/null @@ -1 +0,0 @@ -liquid-glass-demo diff --git a/v3/examples/liquid-glass/README.md b/v3/examples/liquid-glass/README.md deleted file mode 100644 index 33875af54..000000000 --- a/v3/examples/liquid-glass/README.md +++ /dev/null @@ -1,70 +0,0 @@ -# Liquid Glass Demo for Wails v3 - -This demo showcases the native Liquid Glass effect available in macOS 15.0+ with fallback to NSVisualEffectView for older systems. - -## Features Demonstrated - -### Window Styles - -1. **Light Glass** - Clean, light appearance with no tint -2. **Dark Glass** - Dark themed glass effect -3. **Vibrant Glass** - Enhanced vibrant effect for maximum transparency -4. **Tinted Glass** - Blue tinted glass with custom RGBA color -5. **Sheet Material** - Using specific NSVisualEffectMaterialSheet -6. **HUD Window** - Ultra-light HUD window material -7. **Content Background** - Content background material with warm tint - -### Customization Options - -- **Style**: `LiquidGlassStyleAutomatic`, `LiquidGlassStyleLight`, `LiquidGlassStyleDark`, `LiquidGlassStyleVibrant` -- **Material**: Direct NSVisualEffectMaterial selection (when NSGlassEffectView is not available) - - `NSVisualEffectMaterialAppearanceBased` - - `NSVisualEffectMaterialLight` - - `NSVisualEffectMaterialDark` - - `NSVisualEffectMaterialSheet` - - `NSVisualEffectMaterialHUDWindow` - - `NSVisualEffectMaterialContentBackground` - - `NSVisualEffectMaterialUnderWindowBackground` - - `NSVisualEffectMaterialUnderPageBackground` - - And more... -- **CornerRadius**: Rounded corners (0 for square corners) -- **TintColor**: Custom RGBA tint overlay -- **GroupID**: For grouping multiple glass windows (future feature) -- **GroupSpacing**: Spacing between grouped windows (future feature) - -### Running the Demo - -```bash -go build -o liquid-glass-demo . -./liquid-glass-demo -``` - -### Requirements - -- macOS 10.14+ (best experience on macOS 26.0+ with native NSGlassEffectView) -- Wails v3 - -### Implementation Details - -The implementation uses: -- Native `NSGlassEffectView` on macOS 26.0+ for authentic glass effect -- Falls back to `NSVisualEffectView` on older systems -- Runtime detection using `NSClassFromString` for compatibility -- Key-Value Coding (KVC) for dynamic property setting - -### Example Usage - -```go -window := app.Window.NewWithOptions(application.WebviewWindowOptions{ - Mac: application.MacWindow{ - Backdrop: application.MacBackdropLiquidGlass, - InvisibleTitleBarHeight: 500, // Make window draggable - LiquidGlass: application.MacLiquidGlass{ - Style: application.LiquidGlassStyleLight, - Material: application.NSVisualEffectMaterialHUDWindow, - CornerRadius: 20.0, - TintColor: &application.RGBA{Red: 0, Green: 100, Blue: 200, Alpha: 50}, - }, - }, -}) -``` \ No newline at end of file diff --git a/v3/examples/liquid-glass/index.html b/v3/examples/liquid-glass/index.html deleted file mode 100644 index 7f9ff4545..000000000 --- a/v3/examples/liquid-glass/index.html +++ /dev/null @@ -1,50 +0,0 @@ - - - - - - Wails Liquid Glass - - - -
            - -

            LIQUID GLASS

            -
            - - \ No newline at end of file diff --git a/v3/examples/liquid-glass/main.go b/v3/examples/liquid-glass/main.go deleted file mode 100644 index 61f338b96..000000000 --- a/v3/examples/liquid-glass/main.go +++ /dev/null @@ -1,237 +0,0 @@ -package main - -import ( - _ "embed" - "encoding/base64" - "fmt" - "log" - "runtime" - "strings" - - "github.com/wailsapp/wails/v3/pkg/application" -) - -//go:embed index.html -var indexHTML string - -//go:embed wails-logo.png -var wailsLogo []byte - -func main() { - app := application.New(application.Options{ - Name: "Wails Liquid Glass Demo", - Description: "Demonstrates the native Liquid Glass effect on macOS", - }) - - // Check if running on macOS - if runtime.GOOS != "darwin" { - // Show dialog for non-macOS platforms - app.Dialog.Info(). - SetTitle("macOS Only Demo"). - SetMessage("The Liquid Glass effect is a macOS-specific feature that uses native NSGlassEffectView (macOS 15.0+) or NSVisualEffectView.\n\nThis demo is not available on " + runtime.GOOS + "."). - Show() - fmt.Println("The Liquid Glass effect is a macOS-specific feature. This demo is not available on", runtime.GOOS) - return - } - - // Convert logo to base64 data URI - logoDataURI := "data:image/png;base64," + base64.StdEncoding.EncodeToString(wailsLogo) - - // Create different HTML for each window - lightHTML := strings.Replace(indexHTML, "wails-logo.png", logoDataURI, 1) - lightHTML = strings.Replace(lightHTML, "LIQUID GLASS", "Light Style", 1) - - darkHTML := strings.Replace(indexHTML, "wails-logo.png", logoDataURI, 1) - darkHTML = strings.Replace(darkHTML, "LIQUID GLASS", "Dark Style", 1) - - vibrantHTML := strings.Replace(indexHTML, "wails-logo.png", logoDataURI, 1) - vibrantHTML = strings.Replace(vibrantHTML, "LIQUID GLASS", "Vibrant Style", 1) - - tintedHTML := strings.Replace(indexHTML, "wails-logo.png", logoDataURI, 1) - tintedHTML = strings.Replace(tintedHTML, "LIQUID GLASS", "Blue Tint", 1) - - sheetHTML := strings.Replace(indexHTML, "wails-logo.png", logoDataURI, 1) - sheetHTML = strings.Replace(sheetHTML, "LIQUID GLASS", "Sheet Material", 1) - - hudHTML := strings.Replace(indexHTML, "wails-logo.png", logoDataURI, 1) - hudHTML = strings.Replace(hudHTML, "LIQUID GLASS", "HUD Window", 1) - - contentHTML := strings.Replace(indexHTML, "wails-logo.png", logoDataURI, 1) - contentHTML = strings.Replace(contentHTML, "LIQUID GLASS", "Content Background", 1) - - // Window 1: Light style with no tint - window1 := app.Window.NewWithOptions(application.WebviewWindowOptions{ - Title: "Light Glass", - Width: 350, - Height: 280, - X: 100, - Y: 100, - Frameless: true, - EnableFileDrop: false, - HTML: lightHTML, - InitialPosition: application.WindowXY, - Mac: application.MacWindow{ - Backdrop: application.MacBackdropLiquidGlass, - InvisibleTitleBarHeight: 500, - LiquidGlass: application.MacLiquidGlass{ - Style: application.LiquidGlassStyleLight, - Material: application.NSVisualEffectMaterialAuto, - CornerRadius: 20.0, - TintColor: nil, - }, - }, - }) - - // Window 2: Dark style - window2 := app.Window.NewWithOptions(application.WebviewWindowOptions{ - Title: "Dark Glass", - Width: 350, - Height: 280, - X: 500, - Y: 100, - Frameless: true, - EnableFileDrop: false, - HTML: darkHTML, - InitialPosition: application.WindowXY, - Mac: application.MacWindow{ - Backdrop: application.MacBackdropLiquidGlass, - InvisibleTitleBarHeight: 500, - LiquidGlass: application.MacLiquidGlass{ - Style: application.LiquidGlassStyleDark, - Material: application.NSVisualEffectMaterialAuto, - CornerRadius: 20.0, - TintColor: nil, - }, - }, - }) - - // Window 3: Vibrant style - window3 := app.Window.NewWithOptions(application.WebviewWindowOptions{ - Title: "Vibrant Glass", - Width: 350, - Height: 280, - X: 900, - Y: 100, - Frameless: true, - EnableFileDrop: false, - HTML: vibrantHTML, - InitialPosition: application.WindowXY, - Mac: application.MacWindow{ - Backdrop: application.MacBackdropLiquidGlass, - InvisibleTitleBarHeight: 500, - LiquidGlass: application.MacLiquidGlass{ - Style: application.LiquidGlassStyleVibrant, - Material: application.NSVisualEffectMaterialAuto, - CornerRadius: 20.0, - TintColor: nil, - }, - }, - }) - - // Window 4: Blue tinted glass - window4 := app.Window.NewWithOptions(application.WebviewWindowOptions{ - Title: "Tinted Glass", - Width: 350, - Height: 280, - X: 300, - Y: 420, - Frameless: true, - EnableFileDrop: false, - HTML: tintedHTML, - InitialPosition: application.WindowXY, - Mac: application.MacWindow{ - Backdrop: application.MacBackdropLiquidGlass, - InvisibleTitleBarHeight: 500, - LiquidGlass: application.MacLiquidGlass{ - Style: application.LiquidGlassStyleLight, - Material: application.NSVisualEffectMaterialAuto, - CornerRadius: 25.0, // Different corner radius - TintColor: &application.RGBA{Red: 0, Green: 100, Blue: 200, Alpha: 50}, // Blue tint - }, - }, - }) - - // Window 5: Using specific NSVisualEffectMaterial - window5 := app.Window.NewWithOptions(application.WebviewWindowOptions{ - Title: "Sheet Material", - Width: 350, - Height: 280, - X: 700, - Y: 420, - Frameless: true, - EnableFileDrop: false, - HTML: sheetHTML, - InitialPosition: application.WindowXY, - Mac: application.MacWindow{ - Backdrop: application.MacBackdropLiquidGlass, - InvisibleTitleBarHeight: 500, - LiquidGlass: application.MacLiquidGlass{ - Style: application.LiquidGlassStyleAutomatic, // Automatic style - Material: application.NSVisualEffectMaterialSheet, // Specific material - CornerRadius: 15.0, // Different corner radius - TintColor: nil, - }, - }, - }) - - // Window 6: HUD Window Material (very light, translucent) - window6 := app.Window.NewWithOptions(application.WebviewWindowOptions{ - Title: "HUD Window", - Width: 350, - Height: 280, - X: 100, - Y: 740, - Frameless: true, - EnableFileDrop: false, - HTML: hudHTML, - InitialPosition: application.WindowXY, - Mac: application.MacWindow{ - Backdrop: application.MacBackdropLiquidGlass, - InvisibleTitleBarHeight: 500, - LiquidGlass: application.MacLiquidGlass{ - Style: application.LiquidGlassStyleAutomatic, - Material: application.NSVisualEffectMaterialHUDWindow, // HUD Window material - very light - CornerRadius: 30.0, // Larger corner radius - TintColor: nil, - }, - }, - }) - - // Window 7: Content Background Material - window7 := app.Window.NewWithOptions(application.WebviewWindowOptions{ - Title: "Content Background", - Width: 350, - Height: 280, - X: 500, - Y: 740, - Frameless: true, - EnableFileDrop: false, - HTML: contentHTML, - InitialPosition: application.WindowXY, - Mac: application.MacWindow{ - Backdrop: application.MacBackdropLiquidGlass, - InvisibleTitleBarHeight: 500, - LiquidGlass: application.MacLiquidGlass{ - Style: application.LiquidGlassStyleAutomatic, - Material: application.NSVisualEffectMaterialContentBackground, // Content background - CornerRadius: 10.0, // Smaller corner radius - TintColor: &application.RGBA{Red: 0, Green: 200, Blue: 100, Alpha: 30}, // Warm tint - }, - }, - }) - - // Show all windows - window1.Show() - window2.Show() - window3.Show() - window4.Show() - window5.Show() - window6.Show() - window7.Show() - - // Run the application - err := app.Run() - if err != nil { - log.Fatal(err) - } -} diff --git a/v3/examples/liquid-glass/wails-logo.png b/v3/examples/liquid-glass/wails-logo.png deleted file mode 100644 index e65c582ff..000000000 Binary files a/v3/examples/liquid-glass/wails-logo.png and /dev/null differ diff --git a/v3/examples/menu/README.md b/v3/examples/menu/README.md deleted file mode 100644 index cc926df73..000000000 --- a/v3/examples/menu/README.md +++ /dev/null @@ -1,27 +0,0 @@ -# Menu Example - -This example is a demonstration of different ways to create applications without using npm. - -## Running the example - -To run the example, simply run the following command: - -```bash -go run . -``` - -# Status - -| Platform | Status | -|----------|---------| -| Mac | Working | -| Windows | Working | -| Linux | | - -# Known Issues - -- [Resize cursor still visible when not resizable](https://github.com/orgs/wailsapp/projects/6/views/1?pane=issue&itemId=40962163) - ---- - -Icon attribution: [Click icons created by kusumapotter - Flaticon](https://www.flaticon.com/free-icons/click) \ No newline at end of file diff --git a/v3/examples/menu/icon.png b/v3/examples/menu/icon.png deleted file mode 100644 index e934687ca..000000000 Binary files a/v3/examples/menu/icon.png and /dev/null differ diff --git a/v3/examples/menu/main.go b/v3/examples/menu/main.go deleted file mode 100644 index b034cbb68..000000000 --- a/v3/examples/menu/main.go +++ /dev/null @@ -1,161 +0,0 @@ -package main - -import ( - _ "embed" - "log" - "runtime" - - "github.com/wailsapp/wails/v3/pkg/application" -) - -//go:embed icon.png -var clickBitmap []byte - -func main() { - - app := application.New(application.Options{ - Name: "Menu Demo", - Description: "A demo of the menu system", - Assets: application.AlphaAssets, - Mac: application.MacOptions{ - ApplicationShouldTerminateAfterLastWindowClosed: true, - }, - }) - - // Create a custom menu - menu := app.NewMenu() - if runtime.GOOS == "darwin" { - menu.AddRole(application.AppMenu) - } - menu.AddRole(application.FileMenu) - menu.AddRole(application.EditMenu) - menu.AddRole(application.WindowMenu) - menu.AddRole(application.HelpMenu) - - // Let's make a "Demo" menu - myMenu := menu.AddSubmenu("Demo") - - // Hidden menu item that can be unhidden - hidden := myMenu.Add("I was hidden").SetHidden(true) - myMenu.Add("Toggle the hidden menu").OnClick(func(ctx *application.Context) { - hidden.SetHidden(!hidden.Hidden()) - }) - - // Disabled menu item - myMenu.Add("Not Enabled").SetEnabled(false) - - // Click callbacks - myMenu.Add("Click Me!").SetAccelerator("CmdOrCtrl+l").OnClick(func(ctx *application.Context) { - switch ctx.ClickedMenuItem().Label() { - case "Click Me!": - ctx.ClickedMenuItem().SetLabel("Thanks mate!") - case "Thanks mate!": - ctx.ClickedMenuItem().SetLabel("Click Me!") - } - }) - - // You can control the current window from the menu - myMenu.Add("Lock WebviewWindow Resize").OnClick(func(ctx *application.Context) { - if app.Window.Current().Resizable() { - app.Window.Current().SetResizable(false) - ctx.ClickedMenuItem().SetLabel("Unlock WebviewWindow Resize") - } else { - app.Window.Current().SetResizable(true) - ctx.ClickedMenuItem().SetLabel("Lock WebviewWindow Resize") - } - }) - - myMenu.AddSeparator() - - // Checkboxes will tell you their new state so you don't need to track it - myMenu.AddCheckbox("My checkbox", true).OnClick(func(context *application.Context) { - println("Clicked checkbox. Checked:", context.ClickedMenuItem().Checked()) - }) - myMenu.AddSeparator() - - // Callbacks can be shared. This is useful for radio groups - radioCallback := func(ctx *application.Context) { - menuItem := ctx.ClickedMenuItem() - menuItem.SetLabel(menuItem.Label() + "!") - } - - // Radio groups are created implicitly by placing radio items next to each other in a menu - myMenu.AddRadio("Radio 1", true).OnClick(radioCallback) - myMenu.AddRadio("Radio 2", false).OnClick(radioCallback) - myMenu.AddRadio("Radio 3", false).OnClick(radioCallback) - - // Submenus are also supported - submenu := myMenu.AddSubmenu("Submenu") - submenu.Add("Submenu item 1") - submenu.Add("Submenu item 2") - submenu.Add("Submenu item 3") - - myMenu.AddSeparator() - - beatles := myMenu.Add("Hello").OnClick(func(*application.Context) { - println("The beatles would be proud") - }) - myMenu.Add("Toggle the menuitem above").OnClick(func(*application.Context) { - if beatles.Enabled() { - beatles.SetEnabled(false) - beatles.SetLabel("Goodbye") - } else { - beatles.SetEnabled(true) - beatles.SetLabel("Hello") - } - }) - myMenu.Add("Hide the beatles").OnClick(func(ctx *application.Context) { - if beatles.Hidden() { - ctx.ClickedMenuItem().SetLabel("Hide the beatles!") - beatles.SetHidden(false) - } else { - beatles.SetHidden(true) - ctx.ClickedMenuItem().SetLabel("Unhide the beatles!") - } - }) - - myMenu.AddSeparator() - - coffee := myMenu.Add("Request Coffee").OnClick(func(*application.Context) { - println("Coffee dispatched. Productivity +10!") - }) - - myMenu.Add("Toggle coffee availability").OnClick(func(*application.Context) { - if coffee.Enabled() { - coffee.SetEnabled(false) - coffee.SetLabel("Coffee Machine Broken") - println("Alert: Developer morale critically low.") - } else { - coffee.SetEnabled(true) - coffee.SetLabel("Request Coffee") - println("All systems nominal. Coffee restored.") - } - }) - - myMenu.Add("Hide the coffee option").OnClick(func(ctx *application.Context) { - if coffee.Hidden() { - ctx.ClickedMenuItem().SetLabel("Hide the coffee option") - coffee.SetHidden(false) - println("Coffee menu item has been resurrected!") - } else { - coffee.SetHidden(true) - ctx.ClickedMenuItem().SetLabel("Unhide the coffee option") - println("The coffee option has vanished into the void.") - } - }) - - app.Menu.Set(menu) - - // UseApplicationMenu allows Windows/Linux to inherit the app menu - app.Window.NewWithOptions(application.WebviewWindowOptions{ - Name: "menu-example", - Title: "Menu Example", - UseApplicationMenu: true, - }).SetBackgroundColour(application.NewRGB(33, 37, 41)) - - err := app.Run() - - if err != nil { - log.Fatal(err.Error()) - } -} diff --git a/v3/examples/menu/menu_demo b/v3/examples/menu/menu_demo deleted file mode 100755 index 78926ad95..000000000 Binary files a/v3/examples/menu/menu_demo and /dev/null differ diff --git a/v3/examples/notifications/README.md b/v3/examples/notifications/README.md deleted file mode 100644 index ad12c3f40..000000000 --- a/v3/examples/notifications/README.md +++ /dev/null @@ -1,59 +0,0 @@ -# Welcome to Your New Wails3 Project! - -Congratulations on generating your Wails3 application! This README will guide you through the next steps to get your project up and running. - -## Getting Started - -1. Navigate to your project directory in the terminal. - -2. To run your application in development mode, use the following command: - - ``` - wails3 dev - ``` - - This will start your application and enable hot-reloading for both frontend and backend changes. - -3. To build your application for production, use: - - ``` - wails3 build - ``` - - This will create a production-ready executable in the `build` directory. - -## Exploring Wails3 Features - -Now that you have your project set up, it's time to explore the features that Wails3 offers: - -1. **Check out the examples**: The best way to learn is by example. Visit the `examples` directory in the `v3/examples` directory to see various sample applications. - -2. **Run an example**: To run any of the examples, navigate to the example's directory and use: - - ``` - go run . - ``` - - Note: Some examples may be under development during the alpha phase. - -3. **Explore the documentation**: Visit the [Wails3 documentation](https://v3.wails.io/) for in-depth guides and API references. - -4. **Join the community**: Have questions or want to share your progress? Join the [Wails Discord](https://discord.gg/JDdSxwjhGf) or visit the [Wails discussions on GitHub](https://github.com/wailsapp/wails/discussions). - -## Project Structure - -Take a moment to familiarize yourself with your project structure: - -- `frontend/`: Contains your frontend code (HTML, CSS, JavaScript/TypeScript) -- `main.go`: The entry point of your Go backend -- `app.go`: Define your application structure and methods here -- `wails.json`: Configuration file for your Wails project - -## Next Steps - -1. Modify the frontend in the `frontend/` directory to create your desired UI. -2. Add backend functionality in `main.go`. -3. Use `wails3 dev` to see your changes in real-time. -4. When ready, build your application with `wails3 build`. - -Happy coding with Wails3! If you encounter any issues or have questions, don't hesitate to consult the documentation or reach out to the Wails community. diff --git a/v3/examples/notifications/Taskfile.yml b/v3/examples/notifications/Taskfile.yml deleted file mode 100644 index 1455cd70c..000000000 --- a/v3/examples/notifications/Taskfile.yml +++ /dev/null @@ -1,34 +0,0 @@ -version: '3' - -includes: - common: ./build/Taskfile.yml - windows: ./build/windows/Taskfile.yml - darwin: ./build/darwin/Taskfile.yml - linux: ./build/linux/Taskfile.yml - -vars: - APP_NAME: "Notifications\\ Demo" - BIN_DIR: "bin" - VITE_PORT: '{{.WAILS_VITE_PORT | default 9245}}' - -tasks: - build: - summary: Builds the application - cmds: - - task: "{{OS}}:build" - - package: - summary: Packages a production build of the application - cmds: - - task: "{{OS}}:package" - - run: - summary: Runs the application - cmds: - - task: "{{OS}}:run" - - dev: - summary: Runs the application in development mode - cmds: - - wails3 dev -config ./build/config.yml -port {{.VITE_PORT}} - diff --git a/v3/examples/notifications/build/Taskfile.yml b/v3/examples/notifications/build/Taskfile.yml deleted file mode 100644 index 5f3517efc..000000000 --- a/v3/examples/notifications/build/Taskfile.yml +++ /dev/null @@ -1,86 +0,0 @@ -version: '3' - -tasks: - go:mod:tidy: - summary: Runs `go mod tidy` - internal: true - cmds: - - go mod tidy - - install:frontend:deps: - summary: Install frontend dependencies - dir: frontend - sources: - - package.json - - package-lock.json - generates: - - node_modules/* - preconditions: - - sh: npm version - msg: "Looks like npm isn't installed. Npm is part of the Node installer: https://nodejs.org/en/download/" - cmds: - - npm install - - build:frontend: - label: build:frontend (PRODUCTION={{.PRODUCTION}}) - summary: Build the frontend project - dir: frontend - sources: - - "**/*" - generates: - - dist/**/* - deps: - - task: install:frontend:deps - - task: generate:bindings - vars: - BUILD_FLAGS: - ref: .BUILD_FLAGS - cmds: - - npm run {{.BUILD_COMMAND}} -q - env: - PRODUCTION: '{{.PRODUCTION | default "false"}}' - vars: - BUILD_COMMAND: '{{if eq .PRODUCTION "true"}}build{{else}}build:dev{{end}}' - - - generate:bindings: - label: generate:bindings (BUILD_FLAGS={{.BUILD_FLAGS}}) - summary: Generates bindings for the frontend - deps: - - task: go:mod:tidy - sources: - - "**/*.[jt]s" - - exclude: frontend/**/* - - frontend/bindings/**/* # Rerun when switching between dev/production mode causes changes in output - - "**/*.go" - - go.mod - - go.sum - generates: - - frontend/bindings/**/* - cmds: - - wails3 generate bindings -f '{{.BUILD_FLAGS}}' -clean=true -ts - - generate:icons: - summary: Generates Windows `.ico` and Mac `.icns` files from an image - dir: build - sources: - - "appicon.png" - generates: - - "darwin/icons.icns" - - "windows/icon.ico" - cmds: - - wails3 generate icons -input appicon.png -macfilename darwin/icons.icns -windowsfilename windows/icon.ico - - dev:frontend: - summary: Runs the frontend in development mode - dir: frontend - deps: - - task: install:frontend:deps - cmds: - - npm run dev -- --port {{.VITE_PORT}} --strictPort - - update:build-assets: - summary: Updates the build assets - dir: build - cmds: - - wails3 update build-assets -name "{{.APP_NAME}}" -binaryname "{{.APP_NAME}}" -config config.yml -dir . diff --git a/v3/examples/notifications/build/appicon.png b/v3/examples/notifications/build/appicon.png deleted file mode 100644 index 63617fe4f..000000000 Binary files a/v3/examples/notifications/build/appicon.png and /dev/null differ diff --git a/v3/examples/notifications/build/config.yml b/v3/examples/notifications/build/config.yml deleted file mode 100644 index bc09a6d28..000000000 --- a/v3/examples/notifications/build/config.yml +++ /dev/null @@ -1,62 +0,0 @@ -# This file contains the configuration for this project. -# When you update `info` or `fileAssociations`, run `wails3 task common:update:build-assets` to update the assets. -# Note that this will overwrite any changes you have made to the assets. -version: '3' - -# This information is used to generate the build assets. -info: - companyName: "My Company" # The name of the company - productName: "My Product" # The name of the application - productIdentifier: "com.mycompany.myproduct" # The unique product identifier - description: "A program that does X" # The application description - copyright: "(c) 2025, My Company" # Copyright text - comments: "Some Product Comments" # Comments - version: "v0.0.1" # The application version - -# Dev mode configuration -dev_mode: - root_path: . - log_level: warn - debounce: 1000 - ignore: - dir: - - .git - - node_modules - - frontend - - bin - file: - - .DS_Store - - .gitignore - - .gitkeep - watched_extension: - - "*.go" - git_ignore: true - executes: - - cmd: wails3 task common:install:frontend:deps - type: once - - cmd: wails3 task common:dev:frontend - type: background - - cmd: go mod tidy - type: blocking - - cmd: wails3 task build - type: blocking - - cmd: wails3 task run - type: primary - -# File Associations -# More information at: https://v3.wails.io/noit/done/yet -fileAssociations: -# - ext: wails -# name: Wails -# description: Wails Application File -# iconName: wailsFileIcon -# role: Editor -# - ext: jpg -# name: JPEG -# description: Image File -# iconName: jpegFileIcon -# role: Editor - -# Other data -other: - - name: My Other Data \ No newline at end of file diff --git a/v3/examples/notifications/build/darwin/Info.dev.plist b/v3/examples/notifications/build/darwin/Info.dev.plist deleted file mode 100644 index 3a5b9735f..000000000 --- a/v3/examples/notifications/build/darwin/Info.dev.plist +++ /dev/null @@ -1,32 +0,0 @@ - - - - CFBundlePackageType - APPL - CFBundleName - My Product - CFBundleExecutable - Notifications Demo - CFBundleIdentifier - com.wails.notifications-demo - CFBundleVersion - 0.1.0 - CFBundleGetInfoString - This is a comment - CFBundleShortVersionString - 0.1.0 - CFBundleIconFile - icons - LSMinimumSystemVersion - 10.15.0 - NSHighResolutionCapable - true - NSHumanReadableCopyright - © now, My Company - NSAppTransportSecurity - - NSAllowsLocalNetworking - - - - \ No newline at end of file diff --git a/v3/examples/notifications/build/darwin/Info.plist b/v3/examples/notifications/build/darwin/Info.plist deleted file mode 100644 index 464270019..000000000 --- a/v3/examples/notifications/build/darwin/Info.plist +++ /dev/null @@ -1,27 +0,0 @@ - - - - CFBundlePackageType - APPL - CFBundleName - My Product - CFBundleExecutable - Notifications Demo - CFBundleIdentifier - com.wails.notifications-demo - CFBundleVersion - 0.1.0 - CFBundleGetInfoString - This is a comment - CFBundleShortVersionString - 0.1.0 - CFBundleIconFile - icons - LSMinimumSystemVersion - 10.15.0 - NSHighResolutionCapable - true - NSHumanReadableCopyright - © now, My Company - - \ No newline at end of file diff --git a/v3/examples/notifications/build/darwin/Taskfile.yml b/v3/examples/notifications/build/darwin/Taskfile.yml deleted file mode 100644 index 3b6a9dc99..000000000 --- a/v3/examples/notifications/build/darwin/Taskfile.yml +++ /dev/null @@ -1,80 +0,0 @@ -version: '3' - -includes: - common: ../Taskfile.yml - -tasks: - build: - summary: Creates a production build of the application - deps: - - task: common:go:mod:tidy - - task: common:build:frontend - vars: - BUILD_FLAGS: - ref: .BUILD_FLAGS - PRODUCTION: - ref: .PRODUCTION - - task: common:generate:icons - cmds: - - go build {{.BUILD_FLAGS}} -o {{.OUTPUT}} - vars: - BUILD_FLAGS: '{{if eq .PRODUCTION "true"}}-tags production -trimpath -buildvcs=false -ldflags="-w -s"{{else}}-buildvcs=false -gcflags=all="-l"{{end}}' - DEFAULT_OUTPUT: '{{.BIN_DIR}}/{{.APP_NAME}}' - OUTPUT: '{{ .OUTPUT | default .DEFAULT_OUTPUT }}' - env: - GOOS: darwin - CGO_ENABLED: 1 - GOARCH: '{{.ARCH | default ARCH}}' - CGO_CFLAGS: "-mmacosx-version-min=10.15" - CGO_LDFLAGS: "-mmacosx-version-min=10.15" - MACOSX_DEPLOYMENT_TARGET: "10.15" - PRODUCTION: '{{.PRODUCTION | default "false"}}' - - build:universal: - summary: Builds darwin universal binary (arm64 + amd64) - deps: - - task: build - vars: - ARCH: amd64 - OUTPUT: "{{.BIN_DIR}}/{{.APP_NAME}}-amd64" - - task: build - vars: - ARCH: arm64 - OUTPUT: "{{.BIN_DIR}}/{{.APP_NAME}}-arm64" - cmds: - - lipo -create -output "{{.BIN_DIR}}/{{.APP_NAME}}" "{{.BIN_DIR}}/{{.APP_NAME}}-amd64" "{{.BIN_DIR}}/{{.APP_NAME}}-arm64" - - rm "{{.BIN_DIR}}/{{.APP_NAME}}-amd64" "{{.BIN_DIR}}/{{.APP_NAME}}-arm64" - - package: - summary: Packages a production build of the application into a `.app` bundle - deps: - - task: build - vars: - PRODUCTION: "true" - cmds: - - task: create:app:bundle - - package:universal: - summary: Packages darwin universal binary (arm64 + amd64) - deps: - - task: build:universal - cmds: - - task: create:app:bundle - - - create:app:bundle: - summary: Creates an `.app` bundle - cmds: - - mkdir -p {{.BIN_DIR}}/{{.APP_NAME}}.app/Contents/{MacOS,Resources} - - cp build/darwin/icons.icns {{.BIN_DIR}}/{{.APP_NAME}}.app/Contents/Resources - - cp {{.BIN_DIR}}/{{.APP_NAME}} {{.BIN_DIR}}/{{.APP_NAME}}.app/Contents/MacOS - - cp build/darwin/Info.plist {{.BIN_DIR}}/{{.APP_NAME}}.app/Contents - - run: - cmds: - - mkdir -p {{.BIN_DIR}}/dev/{{.APP_NAME}}.app/Contents/{MacOS,Resources} - - cp build/darwin/icons.icns {{.BIN_DIR}}/dev/{{.APP_NAME}}.app/Contents/Resources - - cp {{.BIN_DIR}}/{{.APP_NAME}} {{.BIN_DIR}}/dev/{{.APP_NAME}}.app/Contents/MacOS - - cp build/darwin/Info.dev.plist {{.BIN_DIR}}/dev/{{.APP_NAME}}.app/Contents/Info.plist - - codesign --force --deep --sign - {{.BIN_DIR}}/dev/{{.APP_NAME}}.app - - '{{.BIN_DIR}}/dev/{{.APP_NAME}}.app/Contents/MacOS/{{.APP_NAME}}' diff --git a/v3/examples/notifications/build/darwin/icons.icns b/v3/examples/notifications/build/darwin/icons.icns deleted file mode 100644 index 1b5bd4c86..000000000 Binary files a/v3/examples/notifications/build/darwin/icons.icns and /dev/null differ diff --git a/v3/examples/notifications/build/linux/Taskfile.yml b/v3/examples/notifications/build/linux/Taskfile.yml deleted file mode 100644 index 560cc9c92..000000000 --- a/v3/examples/notifications/build/linux/Taskfile.yml +++ /dev/null @@ -1,119 +0,0 @@ -version: '3' - -includes: - common: ../Taskfile.yml - -tasks: - build: - summary: Builds the application for Linux - deps: - - task: common:go:mod:tidy - - task: common:build:frontend - vars: - BUILD_FLAGS: - ref: .BUILD_FLAGS - PRODUCTION: - ref: .PRODUCTION - - task: common:generate:icons - cmds: - - go build {{.BUILD_FLAGS}} -o {{.BIN_DIR}}/{{.APP_NAME}} - vars: - BUILD_FLAGS: '{{if eq .PRODUCTION "true"}}-tags production -trimpath -buildvcs=false -ldflags="-w -s"{{else}}-buildvcs=false -gcflags=all="-l"{{end}}' - env: - GOOS: linux - CGO_ENABLED: 1 - GOARCH: '{{.ARCH | default ARCH}}' - PRODUCTION: '{{.PRODUCTION | default "false"}}' - - package: - summary: Packages a production build of the application for Linux - deps: - - task: build - vars: - PRODUCTION: "true" - cmds: - - task: create:appimage - - task: create:deb - - task: create:rpm - - task: create:aur - - create:appimage: - summary: Creates an AppImage - dir: build/linux/appimage - deps: - - task: build - vars: - PRODUCTION: "true" - - task: generate:dotdesktop - cmds: - - cp {{.APP_BINARY}} {{.APP_NAME}} - - cp ../../appicon.png appicon.png - - wails3 generate appimage -binary {{.APP_NAME}} -icon {{.ICON}} -desktopfile {{.DESKTOP_FILE}} -outputdir {{.OUTPUT_DIR}} -builddir {{.ROOT_DIR}}/build/linux/appimage/build - vars: - APP_NAME: '{{.APP_NAME}}' - APP_BINARY: '../../../bin/{{.APP_NAME}}' - ICON: '../../appicon.png' - DESKTOP_FILE: '../{{.APP_NAME}}.desktop' - OUTPUT_DIR: '../../../bin' - - create:deb: - summary: Creates a deb package - deps: - - task: build - vars: - PRODUCTION: "true" - cmds: - - task: generate:dotdesktop - - task: generate:deb - - create:rpm: - summary: Creates a rpm package - deps: - - task: build - vars: - PRODUCTION: "true" - cmds: - - task: generate:dotdesktop - - task: generate:rpm - - create:aur: - summary: Creates a arch linux packager package - deps: - - task: build - vars: - PRODUCTION: "true" - cmds: - - task: generate:dotdesktop - - task: generate:aur - - generate:deb: - summary: Creates a deb package - cmds: - - wails3 tool package -name {{.APP_NAME}} -format deb -config ./build/linux/nfpm/nfpm.yaml -out {{.ROOT_DIR}}/bin - - generate:rpm: - summary: Creates a rpm package - cmds: - - wails3 tool package -name {{.APP_NAME}} -format rpm -config ./build/linux/nfpm/nfpm.yaml -out {{.ROOT_DIR}}/bin - - generate:aur: - summary: Creates a arch linux packager package - cmds: - - wails3 tool package -name {{.APP_NAME}} -format archlinux -config ./build/linux/nfpm/nfpm.yaml -out {{.ROOT_DIR}}/bin - - generate:dotdesktop: - summary: Generates a `.desktop` file - dir: build - cmds: - - mkdir -p {{.ROOT_DIR}}/build/linux/appimage - - wails3 generate .desktop -name "{{.APP_NAME}}" -exec "{{.EXEC}}" -icon "{{.ICON}}" -outputfile {{.ROOT_DIR}}/build/linux/{{.APP_NAME}}.desktop -categories "{{.CATEGORIES}}" - vars: - APP_NAME: '{{.APP_NAME}}' - EXEC: '{{.APP_NAME}}' - ICON: 'appicon' - CATEGORIES: 'Development;' - OUTPUTFILE: '{{.ROOT_DIR}}/build/linux/{{.APP_NAME}}.desktop' - - run: - cmds: - - '{{.BIN_DIR}}/{{.APP_NAME}}' diff --git a/v3/examples/notifications/build/linux/appimage/build.sh b/v3/examples/notifications/build/linux/appimage/build.sh deleted file mode 100644 index 85901c34e..000000000 --- a/v3/examples/notifications/build/linux/appimage/build.sh +++ /dev/null @@ -1,35 +0,0 @@ -#!/usr/bin/env bash -# Copyright (c) 2018-Present Lea Anthony -# SPDX-License-Identifier: MIT - -# Fail script on any error -set -euxo pipefail - -# Define variables -APP_DIR="${APP_NAME}.AppDir" - -# Create AppDir structure -mkdir -p "${APP_DIR}/usr/bin" -cp -r "${APP_BINARY}" "${APP_DIR}/usr/bin/" -cp "${ICON_PATH}" "${APP_DIR}/" -cp "${DESKTOP_FILE}" "${APP_DIR}/" - -if [[ $(uname -m) == *x86_64* ]]; then - # Download linuxdeploy and make it executable - wget -q -4 -N https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-x86_64.AppImage - chmod +x linuxdeploy-x86_64.AppImage - - # Run linuxdeploy to bundle the application - ./linuxdeploy-x86_64.AppImage --appdir "${APP_DIR}" --output appimage -else - # Download linuxdeploy and make it executable (arm64) - wget -q -4 -N https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-aarch64.AppImage - chmod +x linuxdeploy-aarch64.AppImage - - # Run linuxdeploy to bundle the application (arm64) - ./linuxdeploy-aarch64.AppImage --appdir "${APP_DIR}" --output appimage -fi - -# Rename the generated AppImage -mv "${APP_NAME}*.AppImage" "${APP_NAME}.AppImage" - diff --git a/v3/examples/notifications/build/linux/nfpm/nfpm.yaml b/v3/examples/notifications/build/linux/nfpm/nfpm.yaml deleted file mode 100644 index c2cb7cd81..000000000 --- a/v3/examples/notifications/build/linux/nfpm/nfpm.yaml +++ /dev/null @@ -1,50 +0,0 @@ -# Feel free to remove those if you don't want/need to use them. -# Make sure to check the documentation at https://nfpm.goreleaser.com -# -# The lines below are called `modelines`. See `:help modeline` - -name: "notifications" -arch: ${GOARCH} -platform: "linux" -version: "0.1.0" -section: "default" -priority: "extra" -maintainer: ${GIT_COMMITTER_NAME} <${GIT_COMMITTER_EMAIL}> -description: "My Product Description" -vendor: "My Company" -homepage: "https://wails.io" -license: "MIT" -release: "1" - -contents: - - src: "./bin/notifications" - dst: "/usr/local/bin/notifications" - - src: "./build/appicon.png" - dst: "/usr/share/icons/hicolor/128x128/apps/notifications.png" - - src: "./build/linux/notifications.desktop" - dst: "/usr/share/applications/notifications.desktop" - -depends: - - gtk3 - - libwebkit2gtk - -# replaces: -# - foobar -# provides: -# - bar -# depends: -# - gtk3 -# - libwebkit2gtk -# recommends: -# - whatever -# suggests: -# - something-else -# conflicts: -# - not-foo -# - not-bar -# changelog: "changelog.yaml" -# scripts: -# preinstall: ./build/linux/nfpm/scripts/preinstall.sh -# postinstall: ./build/linux/nfpm/scripts/postinstall.sh -# preremove: ./build/linux/nfpm/scripts/preremove.sh -# postremove: ./build/linux/nfpm/scripts/postremove.sh diff --git a/v3/examples/notifications/build/linux/nfpm/scripts/postinstall.sh b/v3/examples/notifications/build/linux/nfpm/scripts/postinstall.sh deleted file mode 100644 index a9bf588e2..000000000 --- a/v3/examples/notifications/build/linux/nfpm/scripts/postinstall.sh +++ /dev/null @@ -1 +0,0 @@ -#!/bin/bash diff --git a/v3/examples/notifications/build/linux/nfpm/scripts/postremove.sh b/v3/examples/notifications/build/linux/nfpm/scripts/postremove.sh deleted file mode 100644 index a9bf588e2..000000000 --- a/v3/examples/notifications/build/linux/nfpm/scripts/postremove.sh +++ /dev/null @@ -1 +0,0 @@ -#!/bin/bash diff --git a/v3/examples/notifications/build/linux/nfpm/scripts/preinstall.sh b/v3/examples/notifications/build/linux/nfpm/scripts/preinstall.sh deleted file mode 100644 index a9bf588e2..000000000 --- a/v3/examples/notifications/build/linux/nfpm/scripts/preinstall.sh +++ /dev/null @@ -1 +0,0 @@ -#!/bin/bash diff --git a/v3/examples/notifications/build/linux/nfpm/scripts/preremove.sh b/v3/examples/notifications/build/linux/nfpm/scripts/preremove.sh deleted file mode 100644 index a9bf588e2..000000000 --- a/v3/examples/notifications/build/linux/nfpm/scripts/preremove.sh +++ /dev/null @@ -1 +0,0 @@ -#!/bin/bash diff --git a/v3/examples/notifications/build/windows/Taskfile.yml b/v3/examples/notifications/build/windows/Taskfile.yml deleted file mode 100644 index be6e4125e..000000000 --- a/v3/examples/notifications/build/windows/Taskfile.yml +++ /dev/null @@ -1,63 +0,0 @@ -version: '3' - -includes: - common: ../Taskfile.yml - -tasks: - build: - summary: Builds the application for Windows - deps: - - task: common:go:mod:tidy - - task: common:build:frontend - vars: - BUILD_FLAGS: - ref: .BUILD_FLAGS - PRODUCTION: - ref: .PRODUCTION - - task: common:generate:icons - cmds: - - task: generate:syso - - go build {{.BUILD_FLAGS}} -o {{.BIN_DIR}}/{{.APP_NAME}}.exe - - cmd: powershell Remove-item *.syso - platforms: [windows] - - cmd: rm -f *.syso - platforms: [linux, darwin] - vars: - BUILD_FLAGS: '{{if eq .PRODUCTION "true"}}-tags production -trimpath -buildvcs=false -ldflags="-w -s -H windowsgui"{{else}}-buildvcs=false -gcflags=all="-l"{{end}}' - env: - GOOS: windows - CGO_ENABLED: 0 - GOARCH: '{{.ARCH | default ARCH}}' - PRODUCTION: '{{.PRODUCTION | default "false"}}' - - package: - summary: Packages a production build of the application into a `.exe` bundle - cmds: - - task: create:nsis:installer - - generate:syso: - summary: Generates Windows `.syso` file - dir: build - cmds: - - wails3 generate syso -arch {{.ARCH}} -icon windows/icon.ico -manifest windows/wails.exe.manifest -info windows/info.json -out ../wails_windows_{{.ARCH}}.syso - vars: - ARCH: '{{.ARCH | default ARCH}}' - - create:nsis:installer: - summary: Creates an NSIS installer - dir: build/windows/nsis - deps: - - task: build - vars: - PRODUCTION: "true" - cmds: - # Create the Microsoft WebView2 bootstrapper if it doesn't exist - - wails3 generate webview2bootstrapper -dir "{{.ROOT_DIR}}/build/windows/nsis" - - makensis -DARG_WAILS_{{.ARG_FLAG}}_BINARY="{{.ROOT_DIR}}/{{.BIN_DIR}}/{{.APP_NAME}}.exe" project.nsi - vars: - ARCH: '{{.ARCH | default ARCH}}' - ARG_FLAG: '{{if eq .ARCH "amd64"}}AMD64{{else}}ARM64{{end}}' - - run: - cmds: - - '{{.BIN_DIR}}\\{{.APP_NAME}}.exe' diff --git a/v3/examples/notifications/build/windows/icon.ico b/v3/examples/notifications/build/windows/icon.ico deleted file mode 100644 index bfa0690b7..000000000 Binary files a/v3/examples/notifications/build/windows/icon.ico and /dev/null differ diff --git a/v3/examples/notifications/build/windows/info.json b/v3/examples/notifications/build/windows/info.json deleted file mode 100644 index 850b2b5b0..000000000 --- a/v3/examples/notifications/build/windows/info.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "fixed": { - "file_version": "0.1.0" - }, - "info": { - "0000": { - "ProductVersion": "0.1.0", - "CompanyName": "My Company", - "FileDescription": "My Product Description", - "LegalCopyright": "© now, My Company", - "ProductName": "My Product", - "Comments": "This is a comment" - } - } -} \ No newline at end of file diff --git a/v3/examples/notifications/build/windows/nsis/project.nsi b/v3/examples/notifications/build/windows/nsis/project.nsi deleted file mode 100644 index 4cb18e04f..000000000 --- a/v3/examples/notifications/build/windows/nsis/project.nsi +++ /dev/null @@ -1,112 +0,0 @@ -Unicode true - -#### -## Please note: Template replacements don't work in this file. They are provided with default defines like -## mentioned underneath. -## If the keyword is not defined, "wails_tools.nsh" will populate them. -## If they are defined here, "wails_tools.nsh" will not touch them. This allows you to use this project.nsi manually -## from outside of Wails for debugging and development of the installer. -## -## For development first make a wails nsis build to populate the "wails_tools.nsh": -## > wails build --target windows/amd64 --nsis -## Then you can call makensis on this file with specifying the path to your binary: -## For a AMD64 only installer: -## > makensis -DARG_WAILS_AMD64_BINARY=..\..\bin\app.exe -## For a ARM64 only installer: -## > makensis -DARG_WAILS_ARM64_BINARY=..\..\bin\app.exe -## For a installer with both architectures: -## > makensis -DARG_WAILS_AMD64_BINARY=..\..\bin\app-amd64.exe -DARG_WAILS_ARM64_BINARY=..\..\bin\app-arm64.exe -#### -## The following information is taken from the wails_tools.nsh file, but they can be overwritten here. -#### -## !define INFO_PROJECTNAME "my-project" # Default "notifications" -## !define INFO_COMPANYNAME "My Company" # Default "My Company" -## !define INFO_PRODUCTNAME "My Product Name" # Default "My Product" -## !define INFO_PRODUCTVERSION "1.0.0" # Default "0.1.0" -## !define INFO_COPYRIGHT "(c) Now, My Company" # Default "© now, My Company" -### -## !define PRODUCT_EXECUTABLE "Application.exe" # Default "${INFO_PROJECTNAME}.exe" -## !define UNINST_KEY_NAME "UninstKeyInRegistry" # Default "${INFO_COMPANYNAME}${INFO_PRODUCTNAME}" -#### -## !define REQUEST_EXECUTION_LEVEL "admin" # Default "admin" see also https://nsis.sourceforge.io/Docs/Chapter4.html -#### -## Include the wails tools -#### -!include "wails_tools.nsh" - -# The version information for this two must consist of 4 parts -VIProductVersion "${INFO_PRODUCTVERSION}.0" -VIFileVersion "${INFO_PRODUCTVERSION}.0" - -VIAddVersionKey "CompanyName" "${INFO_COMPANYNAME}" -VIAddVersionKey "FileDescription" "${INFO_PRODUCTNAME} Installer" -VIAddVersionKey "ProductVersion" "${INFO_PRODUCTVERSION}" -VIAddVersionKey "FileVersion" "${INFO_PRODUCTVERSION}" -VIAddVersionKey "LegalCopyright" "${INFO_COPYRIGHT}" -VIAddVersionKey "ProductName" "${INFO_PRODUCTNAME}" - -# Enable HiDPI support. https://nsis.sourceforge.io/Reference/ManifestDPIAware -ManifestDPIAware true - -!include "MUI.nsh" - -!define MUI_ICON "..\icon.ico" -!define MUI_UNICON "..\icon.ico" -# !define MUI_WELCOMEFINISHPAGE_BITMAP "resources\leftimage.bmp" #Include this to add a bitmap on the left side of the Welcome Page. Must be a size of 164x314 -!define MUI_FINISHPAGE_NOAUTOCLOSE # Wait on the INSTFILES page so the user can take a look into the details of the installation steps -!define MUI_ABORTWARNING # This will warn the user if they exit from the installer. - -!insertmacro MUI_PAGE_WELCOME # Welcome to the installer page. -# !insertmacro MUI_PAGE_LICENSE "resources\eula.txt" # Adds a EULA page to the installer -!insertmacro MUI_PAGE_DIRECTORY # In which folder install page. -!insertmacro MUI_PAGE_INSTFILES # Installing page. -!insertmacro MUI_PAGE_FINISH # Finished installation page. - -!insertmacro MUI_UNPAGE_INSTFILES # Uninstalling page - -!insertmacro MUI_LANGUAGE "English" # Set the Language of the installer - -## The following two statements can be used to sign the installer and the uninstaller. The path to the binaries are provided in %1 -#!uninstfinalize 'signtool --file "%1"' -#!finalize 'signtool --file "%1"' - -Name "${INFO_PRODUCTNAME}" -OutFile "..\..\..\bin\${INFO_PROJECTNAME}-${ARCH}-installer.exe" # Name of the installer's file. -InstallDir "$PROGRAMFILES64\${INFO_COMPANYNAME}\${INFO_PRODUCTNAME}" # Default installing folder ($PROGRAMFILES is Program Files folder). -ShowInstDetails show # This will always show the installation details. - -Function .onInit - !insertmacro wails.checkArchitecture -FunctionEnd - -Section - !insertmacro wails.setShellContext - - !insertmacro wails.webview2runtime - - SetOutPath $INSTDIR - - !insertmacro wails.files - - CreateShortcut "$SMPROGRAMS\${INFO_PRODUCTNAME}.lnk" "$INSTDIR\${PRODUCT_EXECUTABLE}" - CreateShortCut "$DESKTOP\${INFO_PRODUCTNAME}.lnk" "$INSTDIR\${PRODUCT_EXECUTABLE}" - - !insertmacro wails.associateFiles - - !insertmacro wails.writeUninstaller -SectionEnd - -Section "uninstall" - !insertmacro wails.setShellContext - - RMDir /r "$AppData\${PRODUCT_EXECUTABLE}" # Remove the WebView2 DataPath - - RMDir /r $INSTDIR - - Delete "$SMPROGRAMS\${INFO_PRODUCTNAME}.lnk" - Delete "$DESKTOP\${INFO_PRODUCTNAME}.lnk" - - !insertmacro wails.unassociateFiles - - !insertmacro wails.deleteUninstaller -SectionEnd diff --git a/v3/examples/notifications/build/windows/nsis/wails_tools.nsh b/v3/examples/notifications/build/windows/nsis/wails_tools.nsh deleted file mode 100644 index c47c784a4..000000000 --- a/v3/examples/notifications/build/windows/nsis/wails_tools.nsh +++ /dev/null @@ -1,212 +0,0 @@ -# DO NOT EDIT - Generated automatically by `wails build` - -!include "x64.nsh" -!include "WinVer.nsh" -!include "FileFunc.nsh" - -!ifndef INFO_PROJECTNAME - !define INFO_PROJECTNAME "notifications" -!endif -!ifndef INFO_COMPANYNAME - !define INFO_COMPANYNAME "My Company" -!endif -!ifndef INFO_PRODUCTNAME - !define INFO_PRODUCTNAME "My Product" -!endif -!ifndef INFO_PRODUCTVERSION - !define INFO_PRODUCTVERSION "0.1.0" -!endif -!ifndef INFO_COPYRIGHT - !define INFO_COPYRIGHT "© now, My Company" -!endif -!ifndef PRODUCT_EXECUTABLE - !define PRODUCT_EXECUTABLE "${INFO_PROJECTNAME}.exe" -!endif -!ifndef UNINST_KEY_NAME - !define UNINST_KEY_NAME "${INFO_COMPANYNAME}${INFO_PRODUCTNAME}" -!endif -!define UNINST_KEY "Software\Microsoft\Windows\CurrentVersion\Uninstall\${UNINST_KEY_NAME}" - -!ifndef REQUEST_EXECUTION_LEVEL - !define REQUEST_EXECUTION_LEVEL "admin" -!endif - -RequestExecutionLevel "${REQUEST_EXECUTION_LEVEL}" - -!ifdef ARG_WAILS_AMD64_BINARY - !define SUPPORTS_AMD64 -!endif - -!ifdef ARG_WAILS_ARM64_BINARY - !define SUPPORTS_ARM64 -!endif - -!ifdef SUPPORTS_AMD64 - !ifdef SUPPORTS_ARM64 - !define ARCH "amd64_arm64" - !else - !define ARCH "amd64" - !endif -!else - !ifdef SUPPORTS_ARM64 - !define ARCH "arm64" - !else - !error "Wails: Undefined ARCH, please provide at least one of ARG_WAILS_AMD64_BINARY or ARG_WAILS_ARM64_BINARY" - !endif -!endif - -!macro wails.checkArchitecture - !ifndef WAILS_WIN10_REQUIRED - !define WAILS_WIN10_REQUIRED "This product is only supported on Windows 10 (Server 2016) and later." - !endif - - !ifndef WAILS_ARCHITECTURE_NOT_SUPPORTED - !define WAILS_ARCHITECTURE_NOT_SUPPORTED "This product can't be installed on the current Windows architecture. Supports: ${ARCH}" - !endif - - ${If} ${AtLeastWin10} - !ifdef SUPPORTS_AMD64 - ${if} ${IsNativeAMD64} - Goto ok - ${EndIf} - !endif - - !ifdef SUPPORTS_ARM64 - ${if} ${IsNativeARM64} - Goto ok - ${EndIf} - !endif - - IfSilent silentArch notSilentArch - silentArch: - SetErrorLevel 65 - Abort - notSilentArch: - MessageBox MB_OK "${WAILS_ARCHITECTURE_NOT_SUPPORTED}" - Quit - ${else} - IfSilent silentWin notSilentWin - silentWin: - SetErrorLevel 64 - Abort - notSilentWin: - MessageBox MB_OK "${WAILS_WIN10_REQUIRED}" - Quit - ${EndIf} - - ok: -!macroend - -!macro wails.files - !ifdef SUPPORTS_AMD64 - ${if} ${IsNativeAMD64} - File "/oname=${PRODUCT_EXECUTABLE}" "${ARG_WAILS_AMD64_BINARY}" - ${EndIf} - !endif - - !ifdef SUPPORTS_ARM64 - ${if} ${IsNativeARM64} - File "/oname=${PRODUCT_EXECUTABLE}" "${ARG_WAILS_ARM64_BINARY}" - ${EndIf} - !endif -!macroend - -!macro wails.writeUninstaller - WriteUninstaller "$INSTDIR\uninstall.exe" - - SetRegView 64 - WriteRegStr HKLM "${UNINST_KEY}" "Publisher" "${INFO_COMPANYNAME}" - WriteRegStr HKLM "${UNINST_KEY}" "DisplayName" "${INFO_PRODUCTNAME}" - WriteRegStr HKLM "${UNINST_KEY}" "DisplayVersion" "${INFO_PRODUCTVERSION}" - WriteRegStr HKLM "${UNINST_KEY}" "DisplayIcon" "$INSTDIR\${PRODUCT_EXECUTABLE}" - WriteRegStr HKLM "${UNINST_KEY}" "UninstallString" "$\"$INSTDIR\uninstall.exe$\"" - WriteRegStr HKLM "${UNINST_KEY}" "QuietUninstallString" "$\"$INSTDIR\uninstall.exe$\" /S" - - ${GetSize} "$INSTDIR" "/S=0K" $0 $1 $2 - IntFmt $0 "0x%08X" $0 - WriteRegDWORD HKLM "${UNINST_KEY}" "EstimatedSize" "$0" -!macroend - -!macro wails.deleteUninstaller - Delete "$INSTDIR\uninstall.exe" - - SetRegView 64 - DeleteRegKey HKLM "${UNINST_KEY}" -!macroend - -!macro wails.setShellContext - ${If} ${REQUEST_EXECUTION_LEVEL} == "admin" - SetShellVarContext all - ${else} - SetShellVarContext current - ${EndIf} -!macroend - -# Install webview2 by launching the bootstrapper -# See https://docs.microsoft.com/en-us/microsoft-edge/webview2/concepts/distribution#online-only-deployment -!macro wails.webview2runtime - !ifndef WAILS_INSTALL_WEBVIEW_DETAILPRINT - !define WAILS_INSTALL_WEBVIEW_DETAILPRINT "Installing: WebView2 Runtime" - !endif - - SetRegView 64 - # If the admin key exists and is not empty then webview2 is already installed - ReadRegStr $0 HKLM "SOFTWARE\WOW6432Node\Microsoft\EdgeUpdate\Clients\{F3017226-FE2A-4295-8BDF-00C3A9A7E4C5}" "pv" - ${If} $0 != "" - Goto ok - ${EndIf} - - ${If} ${REQUEST_EXECUTION_LEVEL} == "user" - # If the installer is run in user level, check the user specific key exists and is not empty then webview2 is already installed - ReadRegStr $0 HKCU "Software\Microsoft\EdgeUpdate\Clients\{F3017226-FE2A-4295-8BDF-00C3A9A7E4C5}" "pv" - ${If} $0 != "" - Goto ok - ${EndIf} - ${EndIf} - - SetDetailsPrint both - DetailPrint "${WAILS_INSTALL_WEBVIEW_DETAILPRINT}" - SetDetailsPrint listonly - - InitPluginsDir - CreateDirectory "$pluginsdir\webview2bootstrapper" - SetOutPath "$pluginsdir\webview2bootstrapper" - File "MicrosoftEdgeWebview2Setup.exe" - ExecWait '"$pluginsdir\webview2bootstrapper\MicrosoftEdgeWebview2Setup.exe" /silent /install' - - SetDetailsPrint both - ok: -!macroend - -# Copy of APP_ASSOCIATE and APP_UNASSOCIATE macros from here https://gist.github.com/nikku/281d0ef126dbc215dd58bfd5b3a5cd5b -!macro APP_ASSOCIATE EXT FILECLASS DESCRIPTION ICON COMMANDTEXT COMMAND - ; Backup the previously associated file class - ReadRegStr $R0 SHELL_CONTEXT "Software\Classes\.${EXT}" "" - WriteRegStr SHELL_CONTEXT "Software\Classes\.${EXT}" "${FILECLASS}_backup" "$R0" - - WriteRegStr SHELL_CONTEXT "Software\Classes\.${EXT}" "" "${FILECLASS}" - - WriteRegStr SHELL_CONTEXT "Software\Classes\${FILECLASS}" "" `${DESCRIPTION}` - WriteRegStr SHELL_CONTEXT "Software\Classes\${FILECLASS}\DefaultIcon" "" `${ICON}` - WriteRegStr SHELL_CONTEXT "Software\Classes\${FILECLASS}\shell" "" "open" - WriteRegStr SHELL_CONTEXT "Software\Classes\${FILECLASS}\shell\open" "" `${COMMANDTEXT}` - WriteRegStr SHELL_CONTEXT "Software\Classes\${FILECLASS}\shell\open\command" "" `${COMMAND}` -!macroend - -!macro APP_UNASSOCIATE EXT FILECLASS - ; Backup the previously associated file class - ReadRegStr $R0 SHELL_CONTEXT "Software\Classes\.${EXT}" `${FILECLASS}_backup` - WriteRegStr SHELL_CONTEXT "Software\Classes\.${EXT}" "" "$R0" - - DeleteRegKey SHELL_CONTEXT `Software\Classes\${FILECLASS}` -!macroend - -!macro wails.associateFiles - ; Create file associations - -!macroend - -!macro wails.unassociateFiles - ; Delete app associations - -!macroend \ No newline at end of file diff --git a/v3/examples/notifications/build/windows/wails.exe.manifest b/v3/examples/notifications/build/windows/wails.exe.manifest deleted file mode 100644 index 0299e62ca..000000000 --- a/v3/examples/notifications/build/windows/wails.exe.manifest +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - - - - - - true/pm - permonitorv2,permonitor - - - \ No newline at end of file diff --git a/v3/examples/notifications/frontend/Inter Font License.txt b/v3/examples/notifications/frontend/Inter Font License.txt deleted file mode 100644 index b525cbf3a..000000000 --- a/v3/examples/notifications/frontend/Inter Font License.txt +++ /dev/null @@ -1,93 +0,0 @@ -Copyright 2020 The Inter Project Authors (https://github.com/rsms/inter) - -This Font Software is licensed under the SIL Open Font License, Version 1.1. -This license is copied below, and is also available with a FAQ at: -http://scripts.sil.org/OFL - - ------------------------------------------------------------ -SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 ------------------------------------------------------------ - -PREAMBLE -The goals of the Open Font License (OFL) are to stimulate worldwide -development of collaborative font projects, to support the font creation -efforts of academic and linguistic communities, and to provide a free and -open framework in which fonts may be shared and improved in partnership -with others. - -The OFL allows the licensed fonts to be used, studied, modified and -redistributed freely as long as they are not sold by themselves. The -fonts, including any derivative works, can be bundled, embedded, -redistributed and/or sold with any software provided that any reserved -names are not used by derivative works. The fonts and derivatives, -however, cannot be released under any other type of license. The -requirement for fonts to remain under this license does not apply -to any document created using the fonts or their derivatives. - -DEFINITIONS -"Font Software" refers to the set of files released by the Copyright -Holder(s) under this license and clearly marked as such. This may -include source files, build scripts and documentation. - -"Reserved Font Name" refers to any names specified as such after the -copyright statement(s). - -"Original Version" refers to the collection of Font Software components as -distributed by the Copyright Holder(s). - -"Modified Version" refers to any derivative made by adding to, deleting, -or substituting -- in part or in whole -- any of the components of the -Original Version, by changing formats or by porting the Font Software to a -new environment. - -"Author" refers to any designer, engineer, programmer, technical -writer or other person who contributed to the Font Software. - -PERMISSION & CONDITIONS -Permission is hereby granted, free of charge, to any person obtaining -a copy of the Font Software, to use, study, copy, merge, embed, modify, -redistribute, and sell modified and unmodified copies of the Font -Software, subject to the following conditions: - -1) Neither the Font Software nor any of its individual components, -in Original or Modified Versions, may be sold by itself. - -2) Original or Modified Versions of the Font Software may be bundled, -redistributed and/or sold with any software, provided that each copy -contains the above copyright notice and this license. These can be -included either as stand-alone text files, human-readable headers or -in the appropriate machine-readable metadata fields within text or -binary files as long as those fields can be easily viewed by the user. - -3) No Modified Version of the Font Software may use the Reserved Font -Name(s) unless explicit written permission is granted by the corresponding -Copyright Holder. This restriction only applies to the primary font name as -presented to the users. - -4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font -Software shall not be used to promote, endorse or advertise any -Modified Version, except to acknowledge the contribution(s) of the -Copyright Holder(s) and the Author(s) or with their explicit written -permission. - -5) The Font Software, modified or unmodified, in part or in whole, -must be distributed entirely under this license, and must not be -distributed under any other license. The requirement for fonts to -remain under this license does not apply to any document created -using the Font Software. - -TERMINATION -This license becomes null and void if any of the above conditions are -not met. - -DISCLAIMER -THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT -OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE -COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL -DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM -OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/v3/examples/notifications/frontend/bindings/github.com/wailsapp/wails/v3/pkg/services/notifications/index.ts b/v3/examples/notifications/frontend/bindings/github.com/wailsapp/wails/v3/pkg/services/notifications/index.ts deleted file mode 100644 index 71eda3bb9..000000000 --- a/v3/examples/notifications/frontend/bindings/github.com/wailsapp/wails/v3/pkg/services/notifications/index.ts +++ /dev/null @@ -1,13 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as NotificationService from "./notificationservice.js"; -export { - NotificationService -}; - -export { - NotificationAction, - NotificationCategory, - NotificationOptions -} from "./models.js"; diff --git a/v3/examples/notifications/frontend/bindings/github.com/wailsapp/wails/v3/pkg/services/notifications/models.ts b/v3/examples/notifications/frontend/bindings/github.com/wailsapp/wails/v3/pkg/services/notifications/models.ts deleted file mode 100644 index d7f48edfe..000000000 --- a/v3/examples/notifications/frontend/bindings/github.com/wailsapp/wails/v3/pkg/services/notifications/models.ts +++ /dev/null @@ -1,107 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Create as $Create } from "@wailsio/runtime"; - -/** - * NotificationAction represents an action button for a notification. - */ -export class NotificationAction { - "id"?: string; - "title"?: string; - - /** - * (macOS-specific) - */ - "destructive"?: boolean; - - /** Creates a new NotificationAction instance. */ - constructor($$source: Partial = {}) { - - Object.assign(this, $$source); - } - - /** - * Creates a new NotificationAction instance from a string or object. - */ - static createFrom($$source: any = {}): NotificationAction { - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - return new NotificationAction($$parsedSource as Partial); - } -} - -/** - * NotificationCategory groups actions for notifications. - */ -export class NotificationCategory { - "id"?: string; - "actions"?: NotificationAction[]; - "hasReplyField"?: boolean; - "replyPlaceholder"?: string; - "replyButtonTitle"?: string; - - /** Creates a new NotificationCategory instance. */ - constructor($$source: Partial = {}) { - - Object.assign(this, $$source); - } - - /** - * Creates a new NotificationCategory instance from a string or object. - */ - static createFrom($$source: any = {}): NotificationCategory { - const $$createField1_0 = $$createType1; - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - if ("actions" in $$parsedSource) { - $$parsedSource["actions"] = $$createField1_0($$parsedSource["actions"]); - } - return new NotificationCategory($$parsedSource as Partial); - } -} - -/** - * NotificationOptions contains configuration for a notification - */ -export class NotificationOptions { - "id": string; - "title": string; - - /** - * (macOS and Linux only) - */ - "subtitle"?: string; - "body"?: string; - "categoryId"?: string; - "data"?: { [_: string]: any }; - - /** Creates a new NotificationOptions instance. */ - constructor($$source: Partial = {}) { - if (!("id" in $$source)) { - this["id"] = ""; - } - if (!("title" in $$source)) { - this["title"] = ""; - } - - Object.assign(this, $$source); - } - - /** - * Creates a new NotificationOptions instance from a string or object. - */ - static createFrom($$source: any = {}): NotificationOptions { - const $$createField5_0 = $$createType2; - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - if ("data" in $$parsedSource) { - $$parsedSource["data"] = $$createField5_0($$parsedSource["data"]); - } - return new NotificationOptions($$parsedSource as Partial); - } -} - -// Private type creation functions -const $$createType0 = NotificationAction.createFrom; -const $$createType1 = $Create.Array($$createType0); -const $$createType2 = $Create.Map($Create.Any, $Create.Any); diff --git a/v3/examples/notifications/frontend/bindings/github.com/wailsapp/wails/v3/pkg/services/notifications/notificationservice.ts b/v3/examples/notifications/frontend/bindings/github.com/wailsapp/wails/v3/pkg/services/notifications/notificationservice.ts deleted file mode 100644 index 859f3570f..000000000 --- a/v3/examples/notifications/frontend/bindings/github.com/wailsapp/wails/v3/pkg/services/notifications/notificationservice.ts +++ /dev/null @@ -1,62 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * Service represents the notifications service - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "@wailsio/runtime"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -export function CheckNotificationAuthorization(): $CancellablePromise { - return $Call.ByID(2216952893); -} - -export function RegisterNotificationCategory(category: $models.NotificationCategory): $CancellablePromise { - return $Call.ByID(2917562919, category); -} - -export function RemoveAllDeliveredNotifications(): $CancellablePromise { - return $Call.ByID(3956282340); -} - -export function RemoveAllPendingNotifications(): $CancellablePromise { - return $Call.ByID(108821341); -} - -export function RemoveDeliveredNotification(identifier: string): $CancellablePromise { - return $Call.ByID(975691940, identifier); -} - -export function RemoveNotification(identifier: string): $CancellablePromise { - return $Call.ByID(3966653866, identifier); -} - -export function RemoveNotificationCategory(categoryID: string): $CancellablePromise { - return $Call.ByID(2032615554, categoryID); -} - -export function RemovePendingNotification(identifier: string): $CancellablePromise { - return $Call.ByID(3729049703, identifier); -} - -/** - * Public methods that delegate to the implementation. - */ -export function RequestNotificationAuthorization(): $CancellablePromise { - return $Call.ByID(3933442950); -} - -export function SendNotification(options: $models.NotificationOptions): $CancellablePromise { - return $Call.ByID(3968228732, options); -} - -export function SendNotificationWithActions(options: $models.NotificationOptions): $CancellablePromise { - return $Call.ByID(1886542847, options); -} diff --git a/v3/examples/notifications/frontend/dist/Inter-Medium.ttf b/v3/examples/notifications/frontend/dist/Inter-Medium.ttf deleted file mode 100644 index a01f3777a..000000000 Binary files a/v3/examples/notifications/frontend/dist/Inter-Medium.ttf and /dev/null differ diff --git a/v3/examples/notifications/frontend/dist/assets/index-Dat4utuQ.js b/v3/examples/notifications/frontend/dist/assets/index-Dat4utuQ.js deleted file mode 100644 index b1c054dfb..000000000 --- a/v3/examples/notifications/frontend/dist/assets/index-Dat4utuQ.js +++ /dev/null @@ -1,33 +0,0 @@ -(function(){const e=document.createElement("link").relList;if(e&&e.supports&&e.supports("modulepreload"))return;for(const o of document.querySelectorAll('link[rel="modulepreload"]'))r(o);new MutationObserver(o=>{for(const i of o)if(i.type==="childList")for(const s of i.addedNodes)s.tagName==="LINK"&&s.rel==="modulepreload"&&r(s)}).observe(document,{childList:!0,subtree:!0});function n(o){const i={};return o.integrity&&(i.integrity=o.integrity),o.referrerPolicy&&(i.referrerPolicy=o.referrerPolicy),o.crossOrigin==="use-credentials"?i.credentials="include":o.crossOrigin==="anonymous"?i.credentials="omit":i.credentials="same-origin",i}function r(o){if(o.ep)return;o.ep=!0;const i=n(o);fetch(o.href,i)}})();const fe="useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict";function oe(t=21){let e="",n=t|0;for(;n--;)e+=fe[Math.random()*64|0];return e}const pe=window.location.origin+"/wails/runtime",x=Object.freeze({Call:0,Clipboard:1,Application:2,Events:3,ContextMenu:4,Dialog:5,Window:6,Screens:7,System:8,Browser:9,CancelCall:10});let we=oe();function C(t,e=""){return function(n,r=null){return he(t,n,e,r)}}async function he(t,e,n,r){var o,i;let s=new URL(pe);s.searchParams.append("object",t.toString()),s.searchParams.append("method",e.toString()),r&&s.searchParams.append("args",JSON.stringify(r));let a={"x-wails-client-id":we};n&&(a["x-wails-window-name"]=n);let c=await fetch(s,{headers:a});if(!c.ok)throw new Error(await c.text());return((i=(o=c.headers.get("Content-Type"))===null||o===void 0?void 0:o.indexOf("application/json"))!==null&&i!==void 0?i:-1)!==-1?c.json():c.text()}C(x.System);const H=function(){var t,e,n,r,o;try{if(!((e=(t=window.chrome)===null||t===void 0?void 0:t.webview)===null||e===void 0)&&e.postMessage)return window.chrome.webview.postMessage.bind(window.chrome.webview);if(!((o=(r=(n=window.webkit)===null||n===void 0?void 0:n.messageHandlers)===null||r===void 0?void 0:r.external)===null||o===void 0)&&o.postMessage)return window.webkit.messageHandlers.external.postMessage.bind(window.webkit.messageHandlers.external)}catch{}return console.warn(` -%c⚠️ Browser Environment Detected %c - -%cOnly UI previews are available in the browser. For full functionality, please run the application in desktop mode. -More information at: https://v3.wails.io/learn/build/#using-a-browser-for-development -`,"background: #ffffff; color: #000000; font-weight: bold; padding: 4px 8px; border-radius: 4px; border: 2px solid #000000;","background: transparent;","color: #ffffff; font-style: italic; font-weight: bold;"),null}();function T(t){H==null||H(t)}function ie(){return window._wails.environment.OS==="windows"}function me(){return!!window._wails.environment.Debug}function ye(){return new MouseEvent("mousedown").buttons===0}function se(t){var e;return t.target instanceof HTMLElement?t.target:!(t.target instanceof HTMLElement)&&t.target instanceof Node&&(e=t.target.parentElement)!==null&&e!==void 0?e:document.body}document.addEventListener("DOMContentLoaded",()=>{});window.addEventListener("contextmenu",je);const ge=C(x.ContextMenu),be=0;function ve(t,e,n,r){ge(be,{id:t,x:e,y:n,data:r})}function je(t){const e=se(t),n=window.getComputedStyle(e).getPropertyValue("--custom-contextmenu").trim();if(n){t.preventDefault();const r=window.getComputedStyle(e).getPropertyValue("--custom-contextmenu-data");ve(n,t.clientX,t.clientY,r)}else Ee(t,e)}function Ee(t,e){if(me())return;switch(window.getComputedStyle(e).getPropertyValue("--default-contextmenu").trim()){case"show":return;case"hide":t.preventDefault();return}if(e.isContentEditable)return;const n=window.getSelection(),r=n&&n.toString().length>0;if(r)for(let o=0;o{F=t,F||(j=E=!1,u())};window.addEventListener("mousedown",Y,{capture:!0});window.addEventListener("mousemove",Y,{capture:!0});window.addEventListener("mouseup",Y,{capture:!0});for(const t of["click","contextmenu","dblclick"])window.addEventListener(t,ze,{capture:!0});function ze(t){(S||E)&&(t.stopImmediatePropagation(),t.stopPropagation(),t.preventDefault())}const I=0,Se=1,U=2;function Y(t){let e,n=t.buttons;switch(t.type){case"mousedown":e=I,P||(n=y|1<"u"||typeof e=="object"))try{var n=O.call(e);return(n===Ne||n===De||n===He||n===Re)&&e("")==null}catch{}return!1})}function Ue(t){if(V(t))return!0;if(!t||typeof t!="function"&&typeof t!="object")return!1;try{b(t,null,_)}catch(e){if(e!==R)return!1}return!$(t)&&B(t)}function qe(t){if(V(t))return!0;if(!t||typeof t!="function"&&typeof t!="object")return!1;if(Ae)return B(t);if($(t))return!1;var e=O.call(t);return e!==Oe&&e!==Te&&!/^\[object HTML/.test(e)?!1:B(t)}const m=b?Ue:qe;var q;class W extends Error{constructor(e,n){super(e,n),this.name="CancelError"}}class M extends Error{constructor(e,n,r){super((r??"Unhandled rejection in cancelled promise.")+" Reason: "+Fe(n),{cause:n}),this.promise=e,this.name="CancelledRejectionError"}}const p=Symbol("barrier"),G=Symbol("cancelImpl"),K=(q=Symbol.species)!==null&&q!==void 0?q:Symbol("speciesPolyfill");class l extends Promise{constructor(e,n){let r,o;if(super((c,f)=>{r=c,o=f}),this.constructor[K]!==Promise)throw new TypeError("CancellablePromise does not support transparent subclassing. Please refrain from overriding the [Symbol.species] static property.");let i={promise:this,resolve:r,reject:o,get oncancelled(){return n??null},set oncancelled(c){n=c??void 0}};const s={get root(){return s},resolving:!1,settled:!1};Object.defineProperties(this,{[p]:{configurable:!1,enumerable:!1,writable:!0,value:null},[G]:{configurable:!1,enumerable:!1,writable:!1,value:ae(i,s)}});const a=ue(i,s);try{e(le(i,s),a)}catch(c){s.resolving?console.log("Unhandled exception in CancellablePromise executor.",c):a(c)}}cancel(e){return new l(n=>{Promise.all([this[G](new W("Promise cancelled.",{cause:e})),_e(this)]).then(()=>n(),()=>n())})}cancelOn(e){return e.aborted?this.cancel(e.reason):e.addEventListener("abort",()=>void this.cancel(e.reason),{capture:!0}),this}then(e,n,r){if(!(this instanceof l))throw new TypeError("CancellablePromise.prototype.then called on an invalid object.");if(m(e)||(e=Q),m(n)||(n=Z),e===Q&&n==Z)return new l(i=>i(this));const o={};return this[p]=o,new l((i,s)=>{super.then(a=>{var c;this[p]===o&&(this[p]=null),(c=o.resolve)===null||c===void 0||c.call(o);try{i(e(a))}catch(f){s(f)}},a=>{var c;this[p]===o&&(this[p]=null),(c=o.resolve)===null||c===void 0||c.call(o);try{i(n(a))}catch(f){s(f)}})},async i=>{try{return r==null?void 0:r(i)}finally{await this.cancel(i)}})}catch(e,n){return this.then(void 0,e,n)}finally(e,n){if(!(this instanceof l))throw new TypeError("CancellablePromise.prototype.finally called on an invalid object.");return m(e)?this.then(r=>l.resolve(e()).then(()=>r),r=>l.resolve(e()).then(()=>{throw r}),n):this.then(e,e,n)}static get[K](){return Promise}static all(e){let n=Array.from(e);const r=n.length===0?l.resolve(n):new l((o,i)=>{Promise.all(n).then(o,i)},o=>L(r,n,o));return r}static allSettled(e){let n=Array.from(e);const r=n.length===0?l.resolve(n):new l((o,i)=>{Promise.allSettled(n).then(o,i)},o=>L(r,n,o));return r}static any(e){let n=Array.from(e);const r=n.length===0?l.resolve(n):new l((o,i)=>{Promise.any(n).then(o,i)},o=>L(r,n,o));return r}static race(e){let n=Array.from(e);const r=new l((o,i)=>{Promise.race(n).then(o,i)},o=>L(r,n,o));return r}static cancel(e){const n=new l(()=>{});return n.cancel(e),n}static timeout(e,n){const r=new l(()=>{});return AbortSignal&&typeof AbortSignal=="function"&&AbortSignal.timeout&&typeof AbortSignal.timeout=="function"?AbortSignal.timeout(e).addEventListener("abort",()=>void r.cancel(n)):setTimeout(()=>void r.cancel(n),e),r}static sleep(e,n){return new l(r=>{setTimeout(()=>r(n),e)})}static reject(e){return new l((n,r)=>r(e))}static resolve(e){return e instanceof l?e:new l(n=>n(e))}static withResolvers(){let e={oncancelled:null};return e.promise=new l((n,r)=>{e.resolve=n,e.reject=r},n=>{var r;(r=e.oncancelled)===null||r===void 0||r.call(e,n)}),e}}function ae(t,e){let n;return r=>{if(e.settled||(e.settled=!0,e.reason=r,t.reject(r),Promise.prototype.then.call(t.promise,void 0,o=>{if(o!==r)throw o})),!(!e.reason||!t.oncancelled))return n=new Promise(o=>{try{o(t.oncancelled(e.reason.cause))}catch(i){Promise.reject(new M(t.promise,i,"Unhandled exception in oncancelled callback."))}}).catch(o=>{Promise.reject(new M(t.promise,o,"Unhandled rejection in oncancelled callback."))}),t.oncancelled=null,n}}function le(t,e){return n=>{if(!e.resolving){if(e.resolving=!0,n===t.promise){if(e.settled)return;e.settled=!0,t.reject(new TypeError("A promise cannot be resolved with itself."));return}if(n!=null&&(typeof n=="object"||typeof n=="function")){let r;try{r=n.then}catch(o){e.settled=!0,t.reject(o);return}if(m(r)){try{let s=n.cancel;if(m(s)){const a=c=>{Reflect.apply(s,n,[c])};e.reason?ae(Object.assign(Object.assign({},t),{oncancelled:a}),e)(e.reason):t.oncancelled=a}}catch{}const o={root:e.root,resolving:!1,get settled(){return this.root.settled},set settled(s){this.root.settled=s},get reason(){return this.root.reason}},i=ue(t,o);try{Reflect.apply(r,n,[le(t,o),i])}catch(s){i(s)}return}}e.settled||(e.settled=!0,t.resolve(n))}}}function ue(t,e){return n=>{if(!e.resolving)if(e.resolving=!0,e.settled){try{if(n instanceof W&&e.reason instanceof W&&Object.is(n.cause,e.reason.cause))return}catch{}Promise.reject(new M(t.promise,n))}else e.settled=!0,t.reject(n)}}function L(t,e,n){const r=[];for(const o of e){let i;try{if(!m(o.then)||(i=o.cancel,!m(i)))continue}catch{continue}let s;try{s=Reflect.apply(i,o,[n])}catch(a){Promise.reject(new M(t,a,"Unhandled exception in cancel method."));continue}s&&r.push((s instanceof Promise?s:Promise.resolve(s)).catch(a=>{Promise.reject(new M(t,a,"Unhandled rejection in cancel method."))}))}return Promise.all(r)}function Q(t){return t}function Z(t){throw t}function Fe(t){try{if(t instanceof Error||typeof t!="object"||t.toString!==Object.prototype.toString)return""+t}catch{}try{return JSON.stringify(t)}catch{}try{return Object.prototype.toString.call(t)}catch{}return""}function _e(t){var e;let n=(e=t[p])!==null&&e!==void 0?e:{};return"promise"in n||Object.assign(n,g()),t[p]==null&&(n.resolve(),t[p]=n),n.promise}let g=Promise.withResolvers;g&&typeof g=="function"?g=g.bind(Promise):g=function(){let t,e;return{promise:new Promise((r,o)=>{t=r,e=o}),resolve:t,reject:e}};window._wails=window._wails||{};window._wails.callResultHandler=Xe;window._wails.callErrorHandler=Je;const Be=C(x.Call),We=C(x.CancelCall),v=new Map,Ye=0,$e=0;class Ve extends Error{constructor(e,n){super(e,n),this.name="RuntimeError"}}function Xe(t,e,n){const r=de(t);if(r)if(!e)r.resolve(void 0);else if(!n)r.resolve(e);else try{r.resolve(JSON.parse(e))}catch(o){r.reject(new TypeError("could not parse result: "+o.message,{cause:o}))}}function Je(t,e,n){const r=de(t);if(r)if(!n)r.reject(new Error(e));else{let o;try{o=JSON.parse(e)}catch(a){r.reject(new TypeError("could not parse error: "+a.message,{cause:a}));return}let i={};o.cause&&(i.cause=o.cause);let s;switch(o.kind){case"ReferenceError":s=new ReferenceError(o.message,i);break;case"TypeError":s=new TypeError(o.message,i);break;case"RuntimeError":s=new Ve(o.message,i);break;default:s=new Error(o.message,i);break}r.reject(s)}}function de(t){const e=v.get(t);return v.delete(t),e}function Ge(){let t;do t=oe();while(v.has(t));return t}function Ke(t){const e=Ge(),n=l.withResolvers();v.set(e,{resolve:n.resolve,reject:n.reject});const r=Be(Ye,Object.assign({"call-id":e},t));let o=!1;r.then(()=>{o=!0},s=>{v.delete(e),n.reject(s)});const i=()=>(v.delete(e),We($e,{"call-id":e}).catch(s=>{console.error("Error while requesting binding call cancellation:",s)}));return n.oncancelled=()=>o?i():r.then(i),n.promise}function k(t,...e){return Ke({methodID:t,args:e})}const w=new Map;class Qe{constructor(e,n,r){this.eventName=e,this.callback=n,this.maxCallbacks=r||-1}dispatch(e){try{this.callback(e)}catch(n){console.error(n)}return this.maxCallbacks===-1?!1:(this.maxCallbacks-=1,this.maxCallbacks===0)}}function Ze(t){let e=w.get(t.eventName);e&&(e=e.filter(n=>n!==t),e.length===0?w.delete(t.eventName):w.set(t.eventName,e))}window._wails=window._wails||{};window._wails.dispatchWailsEvent=tt;C(x.Events);class et{constructor(e,n=null){this.name=e,this.data=n}}function tt(t){let e=w.get(t.name);if(!e)return;let n=new et(t.name,t.data);"sender"in t&&(n.sender=t.sender),e=e.filter(r=>!r.dispatch(n)),e.length===0?w.delete(t.name):w.set(t.name,e)}function nt(t,e,n){let r=w.get(t)||[];const o=new Qe(t,e,n);return r.push(o),w.set(t,r),()=>Ze(o)}function rt(t,e){return nt(t,e,-1)}window._wails=window._wails||{};window._wails.invoke=T;T("wails:runtime:ready");function X(){return k(2216952893)}function ot(t){return k(2917562919,t)}function it(){return k(3933442950)}function st(t){return k(3968228732,t)}function ct(t){return k(1886542847,t)}const d=document.querySelector("#response");var ee;(ee=document.querySelector("#request"))==null||ee.addEventListener("click",async()=>{try{await it()?(d&&(d.innerHTML="

            Notifications are now authorized.

            "),console.info("Notifications are now authorized.")):(d&&(d.innerHTML="

            Notifications are not authorized. You can attempt to request again or let the user know in the UI.

            "),console.warn(`Notifications are not authorized. - You can attempt to request again or let the user know in the UI. -`))}catch(t){console.error(t)}});var te;(te=document.querySelector("#check"))==null||te.addEventListener("click",async()=>{try{await X()?(d&&(d.innerHTML="

            Notifications are authorized.

            "),console.info("Notifications are authorized.")):(d&&(d.innerHTML="

            Notifications are not authorized. You can attempt to request again or let the user know in the UI.

            "),console.warn(`Notifications are not authorized. - You can attempt to request again or let the user know in the UI. -`))}catch(t){console.error(t)}});var ne;(ne=document.querySelector("#basic"))==null||ne.addEventListener("click",async()=>{try{await X()?await st({id:crypto.randomUUID(),title:"Notification Title",subtitle:"Subtitle on macOS and Linux",body:"Body text of notification.",data:{"user-id":"user-123","message-id":"msg-123",timestamp:Date.now()}}):(d&&(d.innerHTML="

            Notifications are not authorized. You can attempt to request again or let the user know in the UI.

            "),console.warn(`Notifications are not authorized. - You can attempt to request again or let the user know in the UI. -`))}catch(t){console.error(t)}});var re;(re=document.querySelector("#complex"))==null||re.addEventListener("click",async()=>{try{if(await X()){const e="frontend-notification-id";await ot({id:e,actions:[{id:"VIEW",title:"View"},{id:"MARK_READ",title:"Mark as read"},{id:"DELETE",title:"Delete",destructive:!0}],hasReplyField:!0,replyPlaceholder:"Message...",replyButtonTitle:"Reply"}),await ct({id:crypto.randomUUID(),title:"Notification Title",subtitle:"Subtitle on macOS and Linux",body:"Body text of notification.",categoryId:e,data:{"user-id":"user-123","message-id":"msg-123",timestamp:Date.now()}})}else d&&(d.innerHTML="

            Notifications are not authorized. You can attempt to request again or let the user know in the UI.

            "),console.warn(`Notifications are not authorized. - You can attempt to request again or let the user know in the UI. -`)}catch(t){console.error(t)}});const at=rt("notification:action",t=>{console.info(`Recieved a ${t.name} event`);const{userInfo:e,...n}=t.data[0];console.info("Notification Response:"),console.table(n),console.info("Notification Response Metadata:"),console.table(e);const r=` -
            Notification Response
            - - - ${Object.keys(n).map(i=>``).join("")} - - - ${Object.values(n).map(i=>``).join("")} - -
            ${i}
            ${i}
            -
            Notification Metadata
            - - - ${Object.keys(e).map(i=>``).join("")} - - - ${Object.values(e).map(i=>``).join("")} - -
            ${i}
            ${i}
            - `,o=document.querySelector("#response");o&&(o.innerHTML=r)});window.onbeforeunload=()=>at(); diff --git a/v3/examples/notifications/frontend/dist/index.html b/v3/examples/notifications/frontend/dist/index.html deleted file mode 100644 index b7794f4d8..000000000 --- a/v3/examples/notifications/frontend/dist/index.html +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - - Wails App - - - -
            - -

            Wails + Typescript + Desktop Notifications

            -

            Send notifications 👇

            -
            - - - - -
            - -
            - - diff --git a/v3/examples/notifications/frontend/dist/style.css b/v3/examples/notifications/frontend/dist/style.css deleted file mode 100644 index 074717bca..000000000 --- a/v3/examples/notifications/frontend/dist/style.css +++ /dev/null @@ -1,131 +0,0 @@ -:root { - font-family: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", - "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", - sans-serif; - font-size: 16px; - line-height: 24px; - font-weight: 400; - color-scheme: light dark; - color: rgba(255, 255, 255, 0.87); - background-color: rgba(27, 38, 54, 1); - font-synthesis: none; - text-rendering: optimizeLegibility; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - -webkit-text-size-adjust: 100%; -} - -* { - user-select: none; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; -} - -@font-face { - font-family: "Inter"; - font-style: normal; - font-weight: 400; - src: local(""), - url("./Inter-Medium.ttf") format("truetype"); -} - -a { - font-weight: 500; - color: #646cff; - text-decoration: inherit; -} - -a:hover { - color: #535bf2; -} - -.controls { - display: flex; - gap: 1em; -} - -button { - height: 30px; - line-height: 30px; - border-radius: 3px; - border: none; - margin: 0 0 0 20px; - padding: 0 8px; - cursor: pointer; -} - -body { - margin: 0; - display: flex; - place-items: center; - place-content: center; - min-width: 320px; - min-height: 100vh; -} - -.container { - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - padding: 3em; -} - -h1, h3 { - line-height: 1.1; - text-align: center; -} - -#app { - max-width: 1280px; - margin: 0 auto; - padding: 2rem; - text-align: center; -} - -.logo { - height: 6em; - padding: 1.5em; - will-change: filter; -} - -.logo:hover { - filter: drop-shadow(0 0 2em #e80000aa); -} - -.logo.vanilla:hover { - filter: drop-shadow(0 0 2em #f7df1eaa); -} - -.footer { - margin-top: 1rem; - align-content: center; - text-align: center; -} - -.footer table { - font-size: 12px; - border-collapse: collapse; - margin: 0 auto; -} - -.footer table, th, td { - border: 1px solid #ddd; - padding: 0.5em; -} - -@media (prefers-color-scheme: light) { - :root { - color: #213547; - background-color: #ffffff; - } - - a:hover { - color: #747bff; - } - - button { - background-color: #f9f9f9; - } -} \ No newline at end of file diff --git a/v3/examples/notifications/frontend/dist/typescript.svg b/v3/examples/notifications/frontend/dist/typescript.svg deleted file mode 100644 index d91c910cc..000000000 --- a/v3/examples/notifications/frontend/dist/typescript.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/v3/examples/notifications/frontend/dist/wails.png b/v3/examples/notifications/frontend/dist/wails.png deleted file mode 100644 index 8bdf42483..000000000 Binary files a/v3/examples/notifications/frontend/dist/wails.png and /dev/null differ diff --git a/v3/examples/notifications/frontend/index.html b/v3/examples/notifications/frontend/index.html deleted file mode 100644 index b873cd4f3..000000000 --- a/v3/examples/notifications/frontend/index.html +++ /dev/null @@ -1,32 +0,0 @@ - - - - - - - - Wails App - - -
            - -

            Wails + Typescript + Desktop Notifications

            -

            Send notifications 👇

            -
            - - - - -
            - -
            - - - diff --git a/v3/examples/notifications/frontend/package.json b/v3/examples/notifications/frontend/package.json deleted file mode 100644 index b39da7ece..000000000 --- a/v3/examples/notifications/frontend/package.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "name": "frontend", - "private": true, - "version": "0.0.0", - "type": "module", - "scripts": { - "dev": "vite", - "build:dev": "tsc && vite build --minify false --mode development", - "build": "tsc && vite build --mode production", - "preview": "vite preview" - }, - "dependencies": { - "@wailsio/runtime": "latest" - }, - "devDependencies": { - "typescript": "^4.9.3", - "vite": "^5.0.0" - } -} diff --git a/v3/examples/notifications/frontend/public/Inter-Medium.ttf b/v3/examples/notifications/frontend/public/Inter-Medium.ttf deleted file mode 100644 index a01f3777a..000000000 Binary files a/v3/examples/notifications/frontend/public/Inter-Medium.ttf and /dev/null differ diff --git a/v3/examples/notifications/frontend/public/style.css b/v3/examples/notifications/frontend/public/style.css deleted file mode 100644 index 074717bca..000000000 --- a/v3/examples/notifications/frontend/public/style.css +++ /dev/null @@ -1,131 +0,0 @@ -:root { - font-family: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", - "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", - sans-serif; - font-size: 16px; - line-height: 24px; - font-weight: 400; - color-scheme: light dark; - color: rgba(255, 255, 255, 0.87); - background-color: rgba(27, 38, 54, 1); - font-synthesis: none; - text-rendering: optimizeLegibility; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - -webkit-text-size-adjust: 100%; -} - -* { - user-select: none; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; -} - -@font-face { - font-family: "Inter"; - font-style: normal; - font-weight: 400; - src: local(""), - url("./Inter-Medium.ttf") format("truetype"); -} - -a { - font-weight: 500; - color: #646cff; - text-decoration: inherit; -} - -a:hover { - color: #535bf2; -} - -.controls { - display: flex; - gap: 1em; -} - -button { - height: 30px; - line-height: 30px; - border-radius: 3px; - border: none; - margin: 0 0 0 20px; - padding: 0 8px; - cursor: pointer; -} - -body { - margin: 0; - display: flex; - place-items: center; - place-content: center; - min-width: 320px; - min-height: 100vh; -} - -.container { - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - padding: 3em; -} - -h1, h3 { - line-height: 1.1; - text-align: center; -} - -#app { - max-width: 1280px; - margin: 0 auto; - padding: 2rem; - text-align: center; -} - -.logo { - height: 6em; - padding: 1.5em; - will-change: filter; -} - -.logo:hover { - filter: drop-shadow(0 0 2em #e80000aa); -} - -.logo.vanilla:hover { - filter: drop-shadow(0 0 2em #f7df1eaa); -} - -.footer { - margin-top: 1rem; - align-content: center; - text-align: center; -} - -.footer table { - font-size: 12px; - border-collapse: collapse; - margin: 0 auto; -} - -.footer table, th, td { - border: 1px solid #ddd; - padding: 0.5em; -} - -@media (prefers-color-scheme: light) { - :root { - color: #213547; - background-color: #ffffff; - } - - a:hover { - color: #747bff; - } - - button { - background-color: #f9f9f9; - } -} \ No newline at end of file diff --git a/v3/examples/notifications/frontend/public/typescript.svg b/v3/examples/notifications/frontend/public/typescript.svg deleted file mode 100644 index d91c910cc..000000000 --- a/v3/examples/notifications/frontend/public/typescript.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/v3/examples/notifications/frontend/public/wails.png b/v3/examples/notifications/frontend/public/wails.png deleted file mode 100644 index 8bdf42483..000000000 Binary files a/v3/examples/notifications/frontend/public/wails.png and /dev/null differ diff --git a/v3/examples/notifications/frontend/src/main.ts b/v3/examples/notifications/frontend/src/main.ts deleted file mode 100644 index 94bbb7df3..000000000 --- a/v3/examples/notifications/frontend/src/main.ts +++ /dev/null @@ -1,129 +0,0 @@ -import { Events } from "@wailsio/runtime"; -import { NotificationService } from "../bindings/github.com/wailsapp/wails/v3/pkg/services/notifications"; - -const footer = document.querySelector("#response"); - -document.querySelector("#request")?.addEventListener("click", async () => { - try { - const authorized = await NotificationService.RequestNotificationAuthorization(); - if (authorized) { - if (footer) footer.innerHTML = "

            Notifications are now authorized.

            "; - console.info("Notifications are now authorized."); - } else { - if (footer) footer.innerHTML = "

            Notifications are not authorized. You can attempt to request again or let the user know in the UI.

            "; - console.warn("Notifications are not authorized.\n You can attempt to request again or let the user know in the UI.\n"); - } - } catch (error) { - console.error(error); - } -}); - -document.querySelector("#check")?.addEventListener("click", async () => { - try { - const authorized = await NotificationService.CheckNotificationAuthorization(); - if (authorized) { - if (footer) footer.innerHTML = "

            Notifications are authorized.

            "; - console.info("Notifications are authorized."); - } else { - if (footer) footer.innerHTML = "

            Notifications are not authorized. You can attempt to request again or let the user know in the UI.

            "; - console.warn("Notifications are not authorized.\n You can attempt to request again or let the user know in the UI.\n"); - } - } catch (error) { - console.error(error); - } -}); - -document.querySelector("#basic")?.addEventListener("click", async () => { - try { - const authorized = await NotificationService.CheckNotificationAuthorization(); - if (authorized) { - await NotificationService.SendNotification({ - id: crypto.randomUUID(), - title: "Notification Title", - subtitle: "Subtitle on macOS and Linux", - body: "Body text of notification.", - data: { - "user-id": "user-123", - "message-id": "msg-123", - "timestamp": Date.now(), - }, - }); - } else { - if (footer) footer.innerHTML = "

            Notifications are not authorized. You can attempt to request again or let the user know in the UI.

            "; - console.warn("Notifications are not authorized.\n You can attempt to request again or let the user know in the UI.\n"); - } - } catch (error) { - console.error(error); - } -}); -document.querySelector("#complex")?.addEventListener("click", async () => { - try { - const authorized = await NotificationService.CheckNotificationAuthorization(); - if (authorized) { - const CategoryID = "frontend-notification-id"; - - await NotificationService.RegisterNotificationCategory({ - id: CategoryID, - actions: [ - { id: "VIEW", title: "View" }, - { id: "MARK_READ", title: "Mark as read" }, - { id: "DELETE", title: "Delete", destructive: true }, - ], - hasReplyField: true, - replyPlaceholder: "Message...", - replyButtonTitle: "Reply", - }); - - await NotificationService.SendNotificationWithActions({ - id: crypto.randomUUID(), - title: "Notification Title", - subtitle: "Subtitle on macOS and Linux", - body: "Body text of notification.", - categoryId: CategoryID, - data: { - "user-id": "user-123", - "message-id": "msg-123", - "timestamp": Date.now(), - }, - }); - } else { - if (footer) footer.innerHTML = "

            Notifications are not authorized. You can attempt to request again or let the user know in the UI.

            "; - console.warn("Notifications are not authorized.\n You can attempt to request again or let the user know in the UI.\n"); - } - } catch (error) { - console.error(error); - } -}); - -const unlisten = Events.On("notification:action", (response) => { - console.info(`Recieved a ${response.name} event`); - const { userInfo, ...base } = response.data[0]; - console.info("Notification Response:"); - console.table(base); - console.info("Notification Response Metadata:"); - console.table(userInfo); - const table = ` -
            Notification Response
            - - - ${Object.keys(base).map(key => ``).join("")} - - - ${Object.values(base).map(value => ``).join("")} - -
            ${key}
            ${value}
            -
            Notification Metadata
            - - - ${Object.keys(userInfo).map(key => ``).join("")} - - - ${Object.values(userInfo).map(value => ``).join("")} - -
            ${key}
            ${value}
            - `; - const footer = document.querySelector("#response"); - if (footer) footer.innerHTML = table; -}); - -window.onbeforeunload = () => unlisten(); \ No newline at end of file diff --git a/v3/examples/notifications/frontend/src/vite-env.d.ts b/v3/examples/notifications/frontend/src/vite-env.d.ts deleted file mode 100644 index 11f02fe2a..000000000 --- a/v3/examples/notifications/frontend/src/vite-env.d.ts +++ /dev/null @@ -1 +0,0 @@ -/// diff --git a/v3/examples/notifications/frontend/tsconfig.json b/v3/examples/notifications/frontend/tsconfig.json deleted file mode 100644 index c267ecf24..000000000 --- a/v3/examples/notifications/frontend/tsconfig.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "compilerOptions": { - "target": "ESNext", - "useDefineForClassFields": true, - "module": "ESNext", - "lib": ["ESNext", "DOM"], - "moduleResolution": "Node", - "strict": true, - "resolveJsonModule": true, - "isolatedModules": true, - "esModuleInterop": true, - "noEmit": true, - "noUnusedLocals": true, - "noUnusedParameters": false, - "noImplicitAny": false, - "noImplicitReturns": true, - "skipLibCheck": true - }, - "include": ["src"] -} diff --git a/v3/examples/notifications/go.mod b/v3/examples/notifications/go.mod deleted file mode 100644 index af22c8e53..000000000 --- a/v3/examples/notifications/go.mod +++ /dev/null @@ -1,50 +0,0 @@ -module notifications - -go 1.25 - -require github.com/wailsapp/wails/v3 v3.0.0-dev - -require ( - dario.cat/mergo v1.0.2 // indirect - git.sr.ht/~jackmordaunt/go-toast/v2 v2.0.3 // indirect - github.com/Microsoft/go-winio v0.6.2 // indirect - github.com/ProtonMail/go-crypto v1.3.0 // indirect - github.com/adrg/xdg v0.5.3 // indirect - github.com/bep/debounce v1.2.1 // indirect - github.com/cloudflare/circl v1.6.3 // indirect - github.com/coder/websocket v1.8.14 // indirect - github.com/cyphar/filepath-securejoin v0.6.1 // indirect - github.com/ebitengine/purego v0.9.1 // indirect - github.com/emirpasic/gods v1.18.1 // indirect - github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect - github.com/go-git/go-billy/v5 v5.7.0 // indirect - github.com/go-git/go-git/v5 v5.16.4 // indirect - github.com/go-ole/go-ole v1.3.0 // indirect - github.com/godbus/dbus/v5 v5.2.2 // indirect - github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect - github.com/google/uuid v1.6.0 // indirect - github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect - github.com/jchv/go-winloader v0.0.0-20250406163304-c1995be93bd1 // indirect - github.com/kevinburke/ssh_config v1.4.0 // indirect - github.com/klauspost/cpuid/v2 v2.3.0 // indirect - github.com/leaanthony/go-ansi-parser v1.6.1 // indirect - github.com/leaanthony/u v1.1.1 // indirect - github.com/lmittmann/tint v1.1.2 // indirect - github.com/mattn/go-colorable v0.1.14 // indirect - github.com/mattn/go-isatty v0.0.20 // indirect - github.com/pjbgf/sha1cd v0.5.0 // indirect - github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c // indirect - github.com/rivo/uniseg v0.4.7 // indirect - github.com/samber/lo v1.52.0 // indirect - github.com/sergi/go-diff v1.4.0 // indirect - github.com/skeema/knownhosts v1.3.2 // indirect - github.com/wailsapp/go-webview2 v1.0.23 // indirect - github.com/xanzy/ssh-agent v0.3.3 // indirect - golang.org/x/crypto v0.47.0 // indirect - golang.org/x/net v0.49.0 // indirect - golang.org/x/sys v0.40.0 // indirect - golang.org/x/text v0.33.0 // indirect - gopkg.in/warnings.v0 v0.1.2 // indirect -) - -replace github.com/wailsapp/wails/v3 => ../.. diff --git a/v3/examples/notifications/go.sum b/v3/examples/notifications/go.sum deleted file mode 100644 index 85f7a05c3..000000000 --- a/v3/examples/notifications/go.sum +++ /dev/null @@ -1,149 +0,0 @@ -dario.cat/mergo v1.0.2 h1:85+piFYR1tMbRrLcDwR18y4UKJ3aH1Tbzi24VRW1TK8= -dario.cat/mergo v1.0.2/go.mod h1:E/hbnu0NxMFBjpMIE34DRGLWqDy0g5FuKDhCb31ngxA= -git.sr.ht/~jackmordaunt/go-toast/v2 v2.0.3 h1:N3IGoHHp9pb6mj1cbXbuaSXV/UMKwmbKLf53nQmtqMA= -git.sr.ht/~jackmordaunt/go-toast/v2 v2.0.3/go.mod h1:QtOLZGz8olr4qH2vWK0QH0w0O4T9fEIjMuWpKUsH7nc= -github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY= -github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= -github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= -github.com/ProtonMail/go-crypto v1.3.0 h1:ILq8+Sf5If5DCpHQp4PbZdS1J7HDFRXz/+xKBiRGFrw= -github.com/ProtonMail/go-crypto v1.3.0/go.mod h1:9whxjD8Rbs29b4XWbB8irEcE8KHMqaR2e7GWU1R+/PE= -github.com/adrg/xdg v0.5.3 h1:xRnxJXne7+oWDatRhR1JLnvuccuIeCoBu2rtuLqQB78= -github.com/adrg/xdg v0.5.3/go.mod h1:nlTsY+NNiCBGCK2tpm09vRqfVzrc2fLmXGpBLF0zlTQ= -github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8= -github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4= -github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= -github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= -github.com/bep/debounce v1.2.1 h1:v67fRdBA9UQu2NhLFXrSg0Brw7CexQekrBwDMM8bzeY= -github.com/bep/debounce v1.2.1/go.mod h1:H8yggRPQKLUhUoqrJC1bO2xNya7vanpDl7xR3ISbCJ0= -github.com/cloudflare/circl v1.6.3 h1:9GPOhQGF9MCYUeXyMYlqTR6a5gTrgR/fBLXvUgtVcg8= -github.com/cloudflare/circl v1.6.3/go.mod h1:2eXP6Qfat4O/Yhh8BznvKnJ+uzEoTQ6jVKJRn81BiS4= -github.com/coder/websocket v1.8.14 h1:9L0p0iKiNOibykf283eHkKUHHrpG7f65OE3BhhO7v9g= -github.com/coder/websocket v1.8.14/go.mod h1:NX3SzP+inril6yawo5CQXx8+fk145lPDC6pumgx0mVg= -github.com/cyphar/filepath-securejoin v0.6.1 h1:5CeZ1jPXEiYt3+Z6zqprSAgSWiggmpVyciv8syjIpVE= -github.com/cyphar/filepath-securejoin v0.6.1/go.mod h1:A8hd4EnAeyujCJRrICiOWqjS1AX0a9kM5XL+NwKoYSc= -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= -github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/ebitengine/purego v0.9.1 h1:a/k2f2HQU3Pi399RPW1MOaZyhKJL9w/xFpKAg4q1s0A= -github.com/ebitengine/purego v0.9.1/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ= -github.com/elazarl/goproxy v1.7.2 h1:Y2o6urb7Eule09PjlhQRGNsqRfPmYI3KKQLFpCAV3+o= -github.com/elazarl/goproxy v1.7.2/go.mod h1:82vkLNir0ALaW14Rc399OTTjyNREgmdL2cVoIbS6XaE= -github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc= -github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ= -github.com/gliderlabs/ssh v0.3.8 h1:a4YXD1V7xMF9g5nTkdfnja3Sxy1PVDCj1Zg4Wb8vY6c= -github.com/gliderlabs/ssh v0.3.8/go.mod h1:xYoytBv1sV0aL3CavoDuJIQNURXkkfPA/wxQ1pL1fAU= -github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI= -github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmSxCcxctByoQdvwPiA7DTK7jaaFDBTtu0ic= -github.com/go-git/go-billy/v5 v5.7.0 h1:83lBUJhGWhYp0ngzCMSgllhUSuoHP1iEWYjsPl9nwqM= -github.com/go-git/go-billy/v5 v5.7.0/go.mod h1:/1IUejTKH8xipsAcdfcSAlUlo2J7lkYV8GTKxAT/L3E= -github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399 h1:eMje31YglSBqCdIqdhKBW8lokaMrL3uTkpGYlE2OOT4= -github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399/go.mod h1:1OCfN199q1Jm3HZlxleg+Dw/mwps2Wbk9frAWm+4FII= -github.com/go-git/go-git/v5 v5.16.4 h1:7ajIEZHZJULcyJebDLo99bGgS0jRrOxzZG4uCk2Yb2Y= -github.com/go-git/go-git/v5 v5.16.4/go.mod h1:4Ge4alE/5gPs30F2H1esi2gPd69R0C39lolkucHBOp8= -github.com/go-json-experiment/json v0.0.0-20251027170946-4849db3c2f7e h1:Lf/gRkoycfOBPa42vU2bbgPurFong6zXeFtPoxholzU= -github.com/go-json-experiment/json v0.0.0-20251027170946-4849db3c2f7e/go.mod h1:uNVvRXArCGbZ508SxYYTC5v1JWoz2voff5pm25jU1Ok= -github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE= -github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78= -github.com/godbus/dbus/v5 v5.2.2 h1:TUR3TgtSVDmjiXOgAAyaZbYmIeP3DPkld3jgKGV8mXQ= -github.com/godbus/dbus/v5 v5.2.2/go.mod h1:3AAv2+hPq5rdnr5txxxRwiGjPXamgoIHgz9FPBfOp3c= -github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 h1:f+oWsMOmNPc8JmEHVZIycC7hBoQxHH9pNKQORJNozsQ= -github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8/go.mod h1:wcDNUvekVysuuOpQKo3191zZyTpiI6se1N1ULghS0sw= -github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= -github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= -github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= -github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A= -github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= -github.com/jchv/go-winloader v0.0.0-20250406163304-c1995be93bd1 h1:njuLRcjAuMKr7kI3D85AXWkw6/+v9PwtV6M6o11sWHQ= -github.com/jchv/go-winloader v0.0.0-20250406163304-c1995be93bd1/go.mod h1:alcuEEnZsY1WQsagKhZDsoPCRoOijYqhZvPwLG0kzVs= -github.com/kevinburke/ssh_config v1.4.0 h1:6xxtP5bZ2E4NF5tuQulISpTO2z8XbtH8cg1PWkxoFkQ= -github.com/kevinburke/ssh_config v1.4.0/go.mod h1:q2RIzfka+BXARoNexmF9gkxEX7DmvbW9P4hIVx2Kg4M= -github.com/klauspost/cpuid/v2 v2.3.0 h1:S4CRMLnYUhGeDFDqkGriYKdfoFlDnMtqTiI/sFzhA9Y= -github.com/klauspost/cpuid/v2 v2.3.0/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0= -github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= -github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= -github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= -github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= -github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/leaanthony/go-ansi-parser v1.6.1 h1:xd8bzARK3dErqkPFtoF9F3/HgN8UQk0ed1YDKpEz01A= -github.com/leaanthony/go-ansi-parser v1.6.1/go.mod h1:+vva/2y4alzVmmIEpk9QDhA7vLC5zKDTRwfZGOp3IWU= -github.com/leaanthony/u v1.1.1 h1:TUFjwDGlNX+WuwVEzDqQwC2lOv0P4uhTQw7CMFdiK7M= -github.com/leaanthony/u v1.1.1/go.mod h1:9+o6hejoRljvZ3BzdYlVL0JYCwtnAsVuN9pVTQcaRfI= -github.com/lmittmann/tint v1.1.2 h1:2CQzrL6rslrsyjqLDwD11bZ5OpLBPU+g3G/r5LSfS8w= -github.com/lmittmann/tint v1.1.2/go.mod h1:HIS3gSy7qNwGCj+5oRjAutErFBl4BzdQP6cJZ0NfMwE= -github.com/matryer/is v1.4.0/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwMRU= -github.com/matryer/is v1.4.1 h1:55ehd8zaGABKLXQUe2awZ99BD/PTc2ls+KV/dXphgEQ= -github.com/matryer/is v1.4.1/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwMRU= -github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE= -github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8= -github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= -github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= -github.com/onsi/gomega v1.34.1 h1:EUMJIKUjM8sKjYbtxQI9A4z2o+rruxnzNvpknOXie6k= -github.com/onsi/gomega v1.34.1/go.mod h1:kU1QgUvBDLXBJq618Xvm2LUX6rSAfRaFRTcdOeDLwwY= -github.com/pjbgf/sha1cd v0.5.0 h1:a+UkboSi1znleCDUNT3M5YxjOnN1fz2FhN48FlwCxs0= -github.com/pjbgf/sha1cd v0.5.0/go.mod h1:lhpGlyHLpQZoxMv8HcgXvZEhcGs0PG/vsZnEJ7H0iCM= -github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmdv1U2eRNDiU2ErMBj1gwrq8eQ= -github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c/go.mod h1:7rwL4CYBLnjLxUqIJNnCWiEdr3bn6IUYi15bNlnbCCU= -github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= -github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= -github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= -github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= -github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= -github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= -github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= -github.com/samber/lo v1.52.0 h1:Rvi+3BFHES3A8meP33VPAxiBZX/Aws5RxrschYGjomw= -github.com/samber/lo v1.52.0/go.mod h1:4+MXEGsJzbKGaUEQFKBq2xtfuznW9oz/WrgyzMzRoM0= -github.com/sergi/go-diff v1.4.0 h1:n/SP9D5ad1fORl+llWyN+D6qoUETXNZARKjyY2/KVCw= -github.com/sergi/go-diff v1.4.0/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4= -github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= -github.com/skeema/knownhosts v1.3.2 h1:EDL9mgf4NzwMXCTfaxSD/o/a5fxDw/xL9nkU28JjdBg= -github.com/skeema/knownhosts v1.3.2/go.mod h1:bEg3iQAuw+jyiw+484wwFJoKSLwcfd7fqRy+N0QTiow= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= -github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= -github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= -github.com/wailsapp/go-webview2 v1.0.23 h1:jmv8qhz1lHibCc79bMM/a/FqOnnzOGEisLav+a0b9P0= -github.com/wailsapp/go-webview2 v1.0.23/go.mod h1:qJmWAmAmaniuKGZPWwne+uor3AHMB5PFhqiK0Bbj8kc= -github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM= -github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw= -golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.47.0 h1:V6e3FRj+n4dbpw86FJ8Fv7XVOql7TEwpHapKoMJ/GO8= -golang.org/x/crypto v0.47.0/go.mod h1:ff3Y9VzzKbwSSEzWqJsJVBnWmRwRSHt/6Op5n9bQc4A= -golang.org/x/exp v0.0.0-20260112195511-716be5621a96 h1:Z/6YuSHTLOHfNFdb8zVZomZr7cqNgTJvA8+Qz75D8gU= -golang.org/x/exp v0.0.0-20260112195511-716be5621a96/go.mod h1:nzimsREAkjBCIEFtHiYkrJyT+2uy9YZJB7H1k68CXZU= -golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.49.0 h1:eeHFmOGUTtaaPSGNmjBKpbng9MulQsJURQUAfUwY++o= -golang.org/x/net v0.49.0/go.mod h1:/ysNB2EvaqvesRkuLAyjI1ycPZlQHM3q01F02UY/MV8= -golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200810151505-1b9f1253b3ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.40.0 h1:DBZZqJ2Rkml6QMQsZywtnjnnGvHza6BTfYFWY9kjEWQ= -golang.org/x/sys v0.40.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= -golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.39.0 h1:RclSuaJf32jOqZz74CkPA9qFuVTX7vhLlpfj/IGWlqY= -golang.org/x/term v0.39.0/go.mod h1:yxzUCTP/U+FzoxfdKmLaA0RV1WgE0VY7hXBwKtY/4ww= -golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.33.0 h1:B3njUFyqtHDUI5jMn1YIr5B0IE2U0qck04r6d4KPAxE= -golang.org/x/text v0.33.0/go.mod h1:LuMebE6+rBincTi9+xWTY8TztLzKHc/9C1uBCG27+q8= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= -gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME= -gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= -gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= -gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= -gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/v3/examples/notifications/main.go b/v3/examples/notifications/main.go deleted file mode 100644 index c0e006652..000000000 --- a/v3/examples/notifications/main.go +++ /dev/null @@ -1,82 +0,0 @@ -package main - -import ( - "embed" - _ "embed" - "fmt" - "log" - - "github.com/wailsapp/wails/v3/pkg/application" - "github.com/wailsapp/wails/v3/pkg/services/notifications" -) - -// Wails uses Go's `embed` package to embed the frontend files into the binary. -// Any files in the frontend/dist folder will be embedded into the binary and -// made available to the frontend. -// See https://pkg.go.dev/embed for more information. - -//go:embed all:frontend/dist -var assets embed.FS - -// main function serves as the application's entry point. It initializes the application, creates a window, -// and starts a goroutine that emits a time-based event every second. It subsequently runs the application and -// logs any error that might occur. -func main() { - // Create a new Notification Service - ns := notifications.New() - - // Create a new Wails application by providing the necessary options. - // Variables 'Name' and 'Description' are for application metadata. - // 'Assets' configures the asset server with the 'FS' variable pointing to the frontend files. - // 'Bind' is a list of Go struct instances. The frontend has access to the methods of these instances. - // 'Mac' options tailor the application when running an macOS. - app := application.New(application.Options{ - Name: "Notifications Demo", - Description: "A demo of using desktop notifications with Wails", - Services: []application.Service{ - application.NewService(ns), - }, - Assets: application.AssetOptions{ - Handler: application.AssetFileServerFS(assets), - }, - Mac: application.MacOptions{ - ApplicationShouldTerminateAfterLastWindowClosed: true, - }, - }) - - // Create a new window with the necessary options. - // 'Title' is the title of the window. - // 'Mac' options tailor the window when running on macOS. - // 'BackgroundColour' is the background colour of the window. - // 'URL' is the URL that will be loaded into the webview. - app.Window.NewWithOptions(application.WebviewWindowOptions{ - Title: "Window 1", - Name: "main", - Mac: application.MacWindow{ - InvisibleTitleBarHeight: 50, - Backdrop: application.MacBackdropTranslucent, - TitleBar: application.MacTitleBarHiddenInset, - }, - BackgroundColour: application.NewRGB(27, 38, 54), - URL: "/", - }) - - // Pass a notification callback that will be called when a notification is actioned. - ns.OnNotificationResponse(func(result notifications.NotificationResult) { - if result.Error != nil { - println(fmt.Errorf("parsing notification result failed: %s", result.Error)) - } else { - fmt.Printf("Response: %+v\n", result.Response) - println("Sending response to frontend...") - app.Event.Emit("notification:action", result.Response) - } - }) - - // Run the application. This blocks until the application has been exited. - err := app.Run() - - // If an error occurred while running the application, log it and exit. - if err != nil { - log.Fatal(err) - } -} diff --git a/v3/examples/panic-handling/README.md b/v3/examples/panic-handling/README.md deleted file mode 100644 index 99068495f..000000000 --- a/v3/examples/panic-handling/README.md +++ /dev/null @@ -1,11 +0,0 @@ -# Panic Handling Example - -This example is a demonstration of how to handle panics in your application. - -## Running the example - -To run the example, simply run the following command: - -```bash -go run . -``` diff --git a/v3/examples/panic-handling/assets/index.html b/v3/examples/panic-handling/assets/index.html deleted file mode 100644 index f4b5fe886..000000000 --- a/v3/examples/panic-handling/assets/index.html +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - Window Call Demo - - - - - - - - - \ No newline at end of file diff --git a/v3/examples/panic-handling/main.go b/v3/examples/panic-handling/main.go deleted file mode 100644 index 3bf02136c..000000000 --- a/v3/examples/panic-handling/main.go +++ /dev/null @@ -1,62 +0,0 @@ -package main - -import ( - "embed" - "fmt" - "github.com/wailsapp/wails/v3/pkg/application" - "log" -) - -//go:embed assets/* -var assets embed.FS - -var app *application.App - -type WindowService struct{} - -func (s *WindowService) GeneratePanic() { - s.call1() -} - -func (s *WindowService) call1() { - s.call2() -} - -func (s *WindowService) call2() { - panic("oh no! something went wrong deep in my service! :(") -} - -// ============================================== - -func main() { - app = application.New(application.Options{ - Name: "Panic Handler Demo", - Description: "A demo of Handling Panics", - Assets: application.AssetOptions{ - Handler: application.BundledAssetFileServer(assets), - }, - Mac: application.MacOptions{ - ApplicationShouldTerminateAfterLastWindowClosed: false, - }, - Services: []application.Service{ - application.NewService(&WindowService{}), - }, - PanicHandler: func(panicDetails *application.PanicDetails) { - fmt.Printf("*** There was a panic! ***\n") - fmt.Printf("Time: %s\n", panicDetails.Time) - fmt.Printf("Error: %s\n", panicDetails.Error) - fmt.Printf("Stacktrace: %s\n", panicDetails.StackTrace) - app.Dialog.Info().SetMessage("There was a panic!").Show() - }, - }) - - app.Window.New(). - SetTitle("WebviewWindow 1"). - Show() - - err := app.Run() - - if err != nil { - log.Fatal(err) - } -} diff --git a/v3/examples/plain/README.md b/v3/examples/plain/README.md deleted file mode 100644 index 9d44f5119..000000000 --- a/v3/examples/plain/README.md +++ /dev/null @@ -1,19 +0,0 @@ -# Plain Example - -This example is a demonstration of different ways to create applications without using npm. - -## Running the example - -To run the example, simply run the following command: - -```bash -go run . -``` - -# Status - -| Platform | Status | -|----------|---------| -| Mac | Working | -| Windows | Working | -| Linux | | diff --git a/v3/examples/plain/main.go b/v3/examples/plain/main.go deleted file mode 100644 index 3132d65b8..000000000 --- a/v3/examples/plain/main.go +++ /dev/null @@ -1,84 +0,0 @@ -package main - -import ( - _ "embed" - "log" - "net/http" - "time" - - "github.com/wailsapp/wails/v3/pkg/application" -) - -func main() { - app := application.New(application.Options{ - Name: "Plain", - Description: "A demo of using raw HTML & CSS", - Mac: application.MacOptions{ - ApplicationShouldTerminateAfterLastWindowClosed: true, - }, - Assets: application.AssetOptions{ - Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - w.WriteHeader(http.StatusOK) - w.Write([]byte(`Plain Bundle

            Plain Bundle

            This is a plain bundle. It has no frontend code but this was Served by the AssetServer's Handler.



            Clicking this paragraph emits an event...

            `)) - }), - }, - }) - // Create window - Note: In future versions, window creation may return errors - // that should be checked. For now, window creation is deferred until app.Run() - app.Window.NewWithOptions(application.WebviewWindowOptions{ - Title: "Plain Bundle", - CSS: `body { background-color: rgb(255, 255, 255); font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif; user-select: none; -ms-user-select: none; -webkit-user-select: none; } .main { color: white; margin: 20%; }`, - Mac: application.MacWindow{ - InvisibleTitleBarHeight: 50, - Backdrop: application.MacBackdropTranslucent, - TitleBar: application.MacTitleBarHiddenInsetUnified, - }, - URL: "/", - }) - - // Create second window with direct HTML content - app.Window.NewWithOptions(application.WebviewWindowOptions{ - Title: "HTML TEST", - HTML: "

            AWESOME!

            ", - CSS: `body { background-color: rgb(255, 0, 0); font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", sans-serif; user-select: none; -ms-user-select: none; -webkit-user-select: none; } .main { color: white; margin: 20%; }`, - JS: `window.iamhere = function() { console.log("Hello World!"); }`, - }) - - // Store the cleanup function to remove event listener when needed - removeClickHandler := app.Event.On("clicked", func(_ *application.CustomEvent) { - println("clicked") - }) - // Note: In a real application, you would call removeClickHandler() when appropriate - _ = removeClickHandler // Acknowledge we're storing the cleanup function - - // Use context-aware goroutine for graceful shutdown - go func() { - // Use a ticker instead of sleep to allow for cancellation - ticker := time.NewTicker(5 * time.Second) - defer ticker.Stop() - - select { - case <-ticker.C: - // Create window after delay - in production, you should handle potential errors - app.Window.NewWithOptions(application.WebviewWindowOptions{ - Title: "Plain Bundle new Window from GoRoutine", - Width: 500, - Height: 500, - Mac: application.MacWindow{ - Backdrop: application.MacBackdropTranslucent, - TitleBar: application.MacTitleBarHiddenInsetUnified, - InvisibleTitleBarHeight: 50, - }, - }) - case <-app.Context().Done(): - // Application is shutting down, cancel the goroutine - return - } - }() - - err := app.Run() - - if err != nil { - log.Fatal(err) - } -} diff --git a/v3/examples/print/.gitignore b/v3/examples/print/.gitignore deleted file mode 100644 index bd7887dea..000000000 --- a/v3/examples/print/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -bindings/ -build/ diff --git a/v3/examples/print/assets/index.html b/v3/examples/print/assets/index.html deleted file mode 100644 index 30ec4e0ab..000000000 --- a/v3/examples/print/assets/index.html +++ /dev/null @@ -1,143 +0,0 @@ - - - - - - Print Dialog Test - - - -

            Print Dialog Test

            -

            Issue #4290: macOS Print dialog does not open

            - -
            -

            Test Instructions

            -
              -
            1. Click the "Print via Go API" button below, OR
            2. -
            3. Use the menu: File > Print, OR
            4. -
            5. Press Cmd+P
            6. -
            -

            Expected: A print dialog should appear as a sheet attached to this window.

            -

            Bug: Before the fix, nothing happens when trying to print.

            -
            - -
            -

            Test Actions

            - - -
            Ready to test...
            -
            - -
            -

            Sample Content to Print

            -

            This is sample content that should appear in the print preview.

            -
              -
            • Item 1: Testing print functionality
            • -
            • Item 2: Verifying dialog appearance
            • -
            • Item 3: Checking modal behavior
            • -
            -
            - -
            - Technical Details: -

            The bug was caused by passing a raw void* pointer instead of the properly cast NSWindow* to runOperationModalForWindow:.

            -

            Note: window.print() may not be natively supported in WKWebView. The Go API uses NSPrintOperation instead.

            -
            - - - - diff --git a/v3/examples/print/go.mod b/v3/examples/print/go.mod deleted file mode 100644 index 183b2bc09..000000000 --- a/v3/examples/print/go.mod +++ /dev/null @@ -1,49 +0,0 @@ -module print - -go 1.25 - -replace github.com/wailsapp/wails/v3 => ../../ - -require github.com/wailsapp/wails/v3 v3.0.0-alpha.0 - -require ( - dario.cat/mergo v1.0.2 // indirect - github.com/Microsoft/go-winio v0.6.2 // indirect - github.com/ProtonMail/go-crypto v1.3.0 // indirect - github.com/adrg/xdg v0.5.3 // indirect - github.com/bep/debounce v1.2.1 // indirect - github.com/cloudflare/circl v1.6.3 // indirect - github.com/coder/websocket v1.8.14 // indirect - github.com/cyphar/filepath-securejoin v0.6.1 // indirect - github.com/ebitengine/purego v0.9.1 // indirect - github.com/emirpasic/gods v1.18.1 // indirect - github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect - github.com/go-git/go-billy/v5 v5.7.0 // indirect - github.com/go-git/go-git/v5 v5.16.4 // indirect - github.com/go-ole/go-ole v1.3.0 // indirect - github.com/godbus/dbus/v5 v5.2.2 // indirect - github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect - github.com/google/uuid v1.6.0 // indirect - github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect - github.com/jchv/go-winloader v0.0.0-20250406163304-c1995be93bd1 // indirect - github.com/kevinburke/ssh_config v1.4.0 // indirect - github.com/klauspost/cpuid/v2 v2.3.0 // indirect - github.com/leaanthony/go-ansi-parser v1.6.1 // indirect - github.com/leaanthony/u v1.1.1 // indirect - github.com/lmittmann/tint v1.1.2 // indirect - github.com/mattn/go-colorable v0.1.14 // indirect - github.com/mattn/go-isatty v0.0.20 // indirect - github.com/pjbgf/sha1cd v0.5.0 // indirect - github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c // indirect - github.com/rivo/uniseg v0.4.7 // indirect - github.com/samber/lo v1.52.0 // indirect - github.com/sergi/go-diff v1.4.0 // indirect - github.com/skeema/knownhosts v1.3.2 // indirect - github.com/wailsapp/go-webview2 v1.0.23 // indirect - github.com/xanzy/ssh-agent v0.3.3 // indirect - golang.org/x/crypto v0.47.0 // indirect - golang.org/x/net v0.49.0 // indirect - golang.org/x/sys v0.40.0 // indirect - golang.org/x/text v0.33.0 // indirect - gopkg.in/warnings.v0 v0.1.2 // indirect -) diff --git a/v3/examples/print/go.sum b/v3/examples/print/go.sum deleted file mode 100644 index 56f1153ea..000000000 --- a/v3/examples/print/go.sum +++ /dev/null @@ -1,147 +0,0 @@ -dario.cat/mergo v1.0.2 h1:85+piFYR1tMbRrLcDwR18y4UKJ3aH1Tbzi24VRW1TK8= -dario.cat/mergo v1.0.2/go.mod h1:E/hbnu0NxMFBjpMIE34DRGLWqDy0g5FuKDhCb31ngxA= -github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY= -github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= -github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= -github.com/ProtonMail/go-crypto v1.3.0 h1:ILq8+Sf5If5DCpHQp4PbZdS1J7HDFRXz/+xKBiRGFrw= -github.com/ProtonMail/go-crypto v1.3.0/go.mod h1:9whxjD8Rbs29b4XWbB8irEcE8KHMqaR2e7GWU1R+/PE= -github.com/adrg/xdg v0.5.3 h1:xRnxJXne7+oWDatRhR1JLnvuccuIeCoBu2rtuLqQB78= -github.com/adrg/xdg v0.5.3/go.mod h1:nlTsY+NNiCBGCK2tpm09vRqfVzrc2fLmXGpBLF0zlTQ= -github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8= -github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4= -github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= -github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= -github.com/bep/debounce v1.2.1 h1:v67fRdBA9UQu2NhLFXrSg0Brw7CexQekrBwDMM8bzeY= -github.com/bep/debounce v1.2.1/go.mod h1:H8yggRPQKLUhUoqrJC1bO2xNya7vanpDl7xR3ISbCJ0= -github.com/cloudflare/circl v1.6.3 h1:9GPOhQGF9MCYUeXyMYlqTR6a5gTrgR/fBLXvUgtVcg8= -github.com/cloudflare/circl v1.6.3/go.mod h1:2eXP6Qfat4O/Yhh8BznvKnJ+uzEoTQ6jVKJRn81BiS4= -github.com/coder/websocket v1.8.14 h1:9L0p0iKiNOibykf283eHkKUHHrpG7f65OE3BhhO7v9g= -github.com/coder/websocket v1.8.14/go.mod h1:NX3SzP+inril6yawo5CQXx8+fk145lPDC6pumgx0mVg= -github.com/cyphar/filepath-securejoin v0.6.1 h1:5CeZ1jPXEiYt3+Z6zqprSAgSWiggmpVyciv8syjIpVE= -github.com/cyphar/filepath-securejoin v0.6.1/go.mod h1:A8hd4EnAeyujCJRrICiOWqjS1AX0a9kM5XL+NwKoYSc= -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= -github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/ebitengine/purego v0.9.1 h1:a/k2f2HQU3Pi399RPW1MOaZyhKJL9w/xFpKAg4q1s0A= -github.com/ebitengine/purego v0.9.1/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ= -github.com/elazarl/goproxy v1.7.2 h1:Y2o6urb7Eule09PjlhQRGNsqRfPmYI3KKQLFpCAV3+o= -github.com/elazarl/goproxy v1.7.2/go.mod h1:82vkLNir0ALaW14Rc399OTTjyNREgmdL2cVoIbS6XaE= -github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc= -github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ= -github.com/gliderlabs/ssh v0.3.8 h1:a4YXD1V7xMF9g5nTkdfnja3Sxy1PVDCj1Zg4Wb8vY6c= -github.com/gliderlabs/ssh v0.3.8/go.mod h1:xYoytBv1sV0aL3CavoDuJIQNURXkkfPA/wxQ1pL1fAU= -github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI= -github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmSxCcxctByoQdvwPiA7DTK7jaaFDBTtu0ic= -github.com/go-git/go-billy/v5 v5.7.0 h1:83lBUJhGWhYp0ngzCMSgllhUSuoHP1iEWYjsPl9nwqM= -github.com/go-git/go-billy/v5 v5.7.0/go.mod h1:/1IUejTKH8xipsAcdfcSAlUlo2J7lkYV8GTKxAT/L3E= -github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399 h1:eMje31YglSBqCdIqdhKBW8lokaMrL3uTkpGYlE2OOT4= -github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399/go.mod h1:1OCfN199q1Jm3HZlxleg+Dw/mwps2Wbk9frAWm+4FII= -github.com/go-git/go-git/v5 v5.16.4 h1:7ajIEZHZJULcyJebDLo99bGgS0jRrOxzZG4uCk2Yb2Y= -github.com/go-git/go-git/v5 v5.16.4/go.mod h1:4Ge4alE/5gPs30F2H1esi2gPd69R0C39lolkucHBOp8= -github.com/go-json-experiment/json v0.0.0-20251027170946-4849db3c2f7e h1:Lf/gRkoycfOBPa42vU2bbgPurFong6zXeFtPoxholzU= -github.com/go-json-experiment/json v0.0.0-20251027170946-4849db3c2f7e/go.mod h1:uNVvRXArCGbZ508SxYYTC5v1JWoz2voff5pm25jU1Ok= -github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE= -github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78= -github.com/godbus/dbus/v5 v5.2.2 h1:TUR3TgtSVDmjiXOgAAyaZbYmIeP3DPkld3jgKGV8mXQ= -github.com/godbus/dbus/v5 v5.2.2/go.mod h1:3AAv2+hPq5rdnr5txxxRwiGjPXamgoIHgz9FPBfOp3c= -github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 h1:f+oWsMOmNPc8JmEHVZIycC7hBoQxHH9pNKQORJNozsQ= -github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8/go.mod h1:wcDNUvekVysuuOpQKo3191zZyTpiI6se1N1ULghS0sw= -github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= -github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= -github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= -github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A= -github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= -github.com/jchv/go-winloader v0.0.0-20250406163304-c1995be93bd1 h1:njuLRcjAuMKr7kI3D85AXWkw6/+v9PwtV6M6o11sWHQ= -github.com/jchv/go-winloader v0.0.0-20250406163304-c1995be93bd1/go.mod h1:alcuEEnZsY1WQsagKhZDsoPCRoOijYqhZvPwLG0kzVs= -github.com/kevinburke/ssh_config v1.4.0 h1:6xxtP5bZ2E4NF5tuQulISpTO2z8XbtH8cg1PWkxoFkQ= -github.com/kevinburke/ssh_config v1.4.0/go.mod h1:q2RIzfka+BXARoNexmF9gkxEX7DmvbW9P4hIVx2Kg4M= -github.com/klauspost/cpuid/v2 v2.3.0 h1:S4CRMLnYUhGeDFDqkGriYKdfoFlDnMtqTiI/sFzhA9Y= -github.com/klauspost/cpuid/v2 v2.3.0/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0= -github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= -github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= -github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= -github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= -github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/leaanthony/go-ansi-parser v1.6.1 h1:xd8bzARK3dErqkPFtoF9F3/HgN8UQk0ed1YDKpEz01A= -github.com/leaanthony/go-ansi-parser v1.6.1/go.mod h1:+vva/2y4alzVmmIEpk9QDhA7vLC5zKDTRwfZGOp3IWU= -github.com/leaanthony/u v1.1.1 h1:TUFjwDGlNX+WuwVEzDqQwC2lOv0P4uhTQw7CMFdiK7M= -github.com/leaanthony/u v1.1.1/go.mod h1:9+o6hejoRljvZ3BzdYlVL0JYCwtnAsVuN9pVTQcaRfI= -github.com/lmittmann/tint v1.1.2 h1:2CQzrL6rslrsyjqLDwD11bZ5OpLBPU+g3G/r5LSfS8w= -github.com/lmittmann/tint v1.1.2/go.mod h1:HIS3gSy7qNwGCj+5oRjAutErFBl4BzdQP6cJZ0NfMwE= -github.com/matryer/is v1.4.0/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwMRU= -github.com/matryer/is v1.4.1 h1:55ehd8zaGABKLXQUe2awZ99BD/PTc2ls+KV/dXphgEQ= -github.com/matryer/is v1.4.1/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwMRU= -github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE= -github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8= -github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= -github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= -github.com/onsi/gomega v1.34.1 h1:EUMJIKUjM8sKjYbtxQI9A4z2o+rruxnzNvpknOXie6k= -github.com/onsi/gomega v1.34.1/go.mod h1:kU1QgUvBDLXBJq618Xvm2LUX6rSAfRaFRTcdOeDLwwY= -github.com/pjbgf/sha1cd v0.5.0 h1:a+UkboSi1znleCDUNT3M5YxjOnN1fz2FhN48FlwCxs0= -github.com/pjbgf/sha1cd v0.5.0/go.mod h1:lhpGlyHLpQZoxMv8HcgXvZEhcGs0PG/vsZnEJ7H0iCM= -github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmdv1U2eRNDiU2ErMBj1gwrq8eQ= -github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c/go.mod h1:7rwL4CYBLnjLxUqIJNnCWiEdr3bn6IUYi15bNlnbCCU= -github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= -github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= -github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= -github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= -github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= -github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= -github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= -github.com/samber/lo v1.52.0 h1:Rvi+3BFHES3A8meP33VPAxiBZX/Aws5RxrschYGjomw= -github.com/samber/lo v1.52.0/go.mod h1:4+MXEGsJzbKGaUEQFKBq2xtfuznW9oz/WrgyzMzRoM0= -github.com/sergi/go-diff v1.4.0 h1:n/SP9D5ad1fORl+llWyN+D6qoUETXNZARKjyY2/KVCw= -github.com/sergi/go-diff v1.4.0/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4= -github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= -github.com/skeema/knownhosts v1.3.2 h1:EDL9mgf4NzwMXCTfaxSD/o/a5fxDw/xL9nkU28JjdBg= -github.com/skeema/knownhosts v1.3.2/go.mod h1:bEg3iQAuw+jyiw+484wwFJoKSLwcfd7fqRy+N0QTiow= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= -github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= -github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= -github.com/wailsapp/go-webview2 v1.0.23 h1:jmv8qhz1lHibCc79bMM/a/FqOnnzOGEisLav+a0b9P0= -github.com/wailsapp/go-webview2 v1.0.23/go.mod h1:qJmWAmAmaniuKGZPWwne+uor3AHMB5PFhqiK0Bbj8kc= -github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM= -github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw= -golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.47.0 h1:V6e3FRj+n4dbpw86FJ8Fv7XVOql7TEwpHapKoMJ/GO8= -golang.org/x/crypto v0.47.0/go.mod h1:ff3Y9VzzKbwSSEzWqJsJVBnWmRwRSHt/6Op5n9bQc4A= -golang.org/x/exp v0.0.0-20260112195511-716be5621a96 h1:Z/6YuSHTLOHfNFdb8zVZomZr7cqNgTJvA8+Qz75D8gU= -golang.org/x/exp v0.0.0-20260112195511-716be5621a96/go.mod h1:nzimsREAkjBCIEFtHiYkrJyT+2uy9YZJB7H1k68CXZU= -golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.49.0 h1:eeHFmOGUTtaaPSGNmjBKpbng9MulQsJURQUAfUwY++o= -golang.org/x/net v0.49.0/go.mod h1:/ysNB2EvaqvesRkuLAyjI1ycPZlQHM3q01F02UY/MV8= -golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200810151505-1b9f1253b3ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.40.0 h1:DBZZqJ2Rkml6QMQsZywtnjnnGvHza6BTfYFWY9kjEWQ= -golang.org/x/sys v0.40.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= -golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.39.0 h1:RclSuaJf32jOqZz74CkPA9qFuVTX7vhLlpfj/IGWlqY= -golang.org/x/term v0.39.0/go.mod h1:yxzUCTP/U+FzoxfdKmLaA0RV1WgE0VY7hXBwKtY/4ww= -golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.33.0 h1:B3njUFyqtHDUI5jMn1YIr5B0IE2U0qck04r6d4KPAxE= -golang.org/x/text v0.33.0/go.mod h1:LuMebE6+rBincTi9+xWTY8TztLzKHc/9C1uBCG27+q8= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= -gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME= -gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= -gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= -gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= -gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/v3/examples/print/main.go b/v3/examples/print/main.go deleted file mode 100644 index 8de642cbc..000000000 --- a/v3/examples/print/main.go +++ /dev/null @@ -1,90 +0,0 @@ -//go:build darwin - -package main - -import ( - "embed" - "log" - "runtime" - - "github.com/wailsapp/wails/v3/pkg/application" -) - -//go:embed assets/* -var assets embed.FS - -// PrintService provides print functionality to the frontend -type PrintService struct { - app *application.App -} - -func (p *PrintService) Print() error { - if w := p.app.Window.Current(); w != nil { - log.Println("PrintService.Print() called") - return w.Print() - } - return nil -} - -func main() { - // Only run on macOS - if runtime.GOOS != "darwin" { - log.Fatal("This test is only for macOS") - } - - printService := &PrintService{} - - app := application.New(application.Options{ - Name: "Print Dialog Test", - Description: "Test for macOS print dialog (Issue #4290)", - Assets: application.AssetOptions{ - Handler: application.BundledAssetFileServer(assets), - }, - Services: []application.Service{ - application.NewService(printService), - }, - }) - - printService.app = app - - // Create application menu - menu := app.NewMenu() - - // File menu - fileMenu := menu.AddSubmenu("File") - fileMenu.Add("Print..."). - SetAccelerator("CmdOrCtrl+P"). - OnClick(func(ctx *application.Context) { - if w := app.Window.Current(); w != nil { - log.Println("Attempting to print...") - if err := w.Print(); err != nil { - log.Printf("Print error: %v", err) - } else { - log.Println("Print completed (or dialog dismissed)") - } - } - }) - fileMenu.AddSeparator() - fileMenu.Add("Quit"). - SetAccelerator("CmdOrCtrl+Q"). - OnClick(func(ctx *application.Context) { - app.Quit() - }) - - app.Menu.Set(menu) - - // Create main window - app.Window.NewWithOptions(application.WebviewWindowOptions{ - Title: "Print Dialog Test - Issue #4290", - Width: 800, - Height: 600, - URL: "/index.html", - }) - - log.Println("Starting application. Use File > Print or Cmd+P to test print dialog.") - - err := app.Run() - if err != nil { - log.Fatal(err) - } -} diff --git a/v3/examples/raw-message/README.md b/v3/examples/raw-message/README.md deleted file mode 100644 index 8d28d4f8a..000000000 --- a/v3/examples/raw-message/README.md +++ /dev/null @@ -1,11 +0,0 @@ -# Raw Message Example - -This example is a demonstration of sending raw messages from JS to Go. - -## Running the example - -To run the example, simply run the following command: - -```bash -go run main.go -``` diff --git a/v3/examples/raw-message/assets/index.html b/v3/examples/raw-message/assets/index.html deleted file mode 100644 index 52f174336..000000000 --- a/v3/examples/raw-message/assets/index.html +++ /dev/null @@ -1,25 +0,0 @@ - - - - - Title - - - - -

            Raw Message Demo

            -
            -To send a raw message from this window, enter some text and click the button: -
            -
            - - - - diff --git a/v3/examples/raw-message/main.go b/v3/examples/raw-message/main.go deleted file mode 100644 index 697773373..000000000 --- a/v3/examples/raw-message/main.go +++ /dev/null @@ -1,46 +0,0 @@ -package main - -import ( - "embed" - _ "embed" - "fmt" - "log" - - "github.com/wailsapp/wails/v3/pkg/application" -) - -//go:embed assets -var assets embed.FS - -func main() { - - app := application.New(application.Options{ - Name: "Raw Message Demo", - Description: "A demo of sending raw messages from the frontend", - Assets: application.AssetOptions{ - Handler: application.BundledAssetFileServer(assets), - }, - Mac: application.MacOptions{ - ApplicationShouldTerminateAfterLastWindowClosed: true, - }, - RawMessageHandler: func(window application.Window, message string, originInfo *application.OriginInfo) { - println(fmt.Sprintf("Raw message received from Window %s with message: %s, origin %s, topOrigin %s, isMainFrame %t", window.Name(), message, originInfo.Origin, originInfo.TopOrigin, originInfo.IsMainFrame)) - }, - }) - - app.Window.NewWithOptions(application.WebviewWindowOptions{ - Title: "Window 1", - Name: "Window 1", - Mac: application.MacWindow{ - Backdrop: application.MacBackdropTranslucent, - TitleBar: application.MacTitleBarHiddenInsetUnified, - InvisibleTitleBarHeight: 50, - }, - }) - - err := app.Run() - - if err != nil { - log.Fatal(err.Error()) - } -} diff --git a/v3/examples/screen/README.md b/v3/examples/screen/README.md deleted file mode 100644 index 1f922f341..000000000 --- a/v3/examples/screen/README.md +++ /dev/null @@ -1,19 +0,0 @@ -# Screen Example - -This example will detect all attached screens and display their details. - -## Running the example - -To run the example, simply run the following command: - -```bash -go run . -``` - -# Status - -| Platform | Status | -|----------|---------| -| Mac | Working | -| Windows | Working | -| Linux | | diff --git a/v3/examples/screen/assets/examples.js b/v3/examples/screen/assets/examples.js deleted file mode 100644 index 8abe3f0ca..000000000 --- a/v3/examples/screen/assets/examples.js +++ /dev/null @@ -1,206 +0,0 @@ -window.examples = [ - [ - // Normal examples (demonstrate real life scenarios) - { - name: "Single 4k monitor", - screens: [ - {id: 1, w: 3840, h: 2160, s: 163.0 / 96, name: `27" 4K UHD 163DPI`}, - ] - }, - { - name: "Two monitors", - screens: [ - {id: 1, w: 3840, h: 2160, s: 163.0 / 96, name: `27" 4K UHD 163DPI`}, - {id: 2, w: 1920, h: 1080, s: 1, parent: {id: 1, align: "r", offset: 0}, name: `23" FHD 96DPI`}, - ] - }, - { - name: "Two monitors (2)", - screens: [ - {id: 1, w: 1920, h: 1080, s: 1, name: `23" FHD 96DPI`}, - {id: 2, w: 1920, h: 1080, s: 1.25, parent: {id: 1, align: "r", offset: 0}, name: `23" FHD 96DPI (125%)`}, - ] - }, - { - name: "Three monitors", - screens: [ - {id: 1, w: 3840, h: 2160, s: 163.0 / 96, name: `27" 4K UHD 163DPI`}, - {id: 2, w: 1920, h: 1080, s: 1, parent: {id: 1, align: "r", offset: 0}, name: `23" FHD 96DPI`}, - {id: 3, w: 1920, h: 1080, s: 1.25, parent: {id: 1, align: "l", offset: 0}, name: `23" FHD 96DPI (125%)`}, - ] - }, - { - name: "Four monitors", - screens: [ - {id: 1, w: 3840, h: 2160, s: 163.0 / 96, name: `27" 4K UHD 163DPI`}, - {id: 2, w: 1920, h: 1080, s: 1, parent: {id: 1, align: "r", offset: 0}, name: `23" FHD 96DPI`}, - {id: 3, w: 1920, h: 1080, s: 1.25, parent: {id: 2, align: "b", offset: 0}, name: `23" FHD 96DPI (125%)`}, - {id: 4, w: 1080, h: 1920, s: 1, parent: {id: 1, align: "l", offset: 0}, name: `23" FHD (90deg)`}, - ] - }, - ], - [ - // Test cases examples (demonstrate the algorithm basics) - { - name: "Child scaled, Start offset", - screens: [ - {id: 1, w: 1200, h: 1200, s: 1, name: "Parent"}, - {id: 2, w: 1200, h: 1200, s: 1.5, parent: {id: 1, align: "r", offset: 600}, name: "Child"}, - ] - }, - { - name: "Child scaled, End offset", - screens: [ - {id: 1, w: 1200, h: 1200, s: 1, name: "Parent"}, - {id: 2, w: 1200, h: 1200, s: 1.5, parent: {id: 1, align: "r", offset: -600}, name: "Child"}, - ] - }, - { - name: "Parent scaled, Start offset percent", - screens: [ - {id: 1, w: 1200, h: 1200, s: 1.5, name: "Parent"}, - {id: 2, w: 1200, h: 1200, s: 1, parent: {id: 1, align: "r", offset: 600}, name: "Child"}, - ] - }, - { - name: "Parent scaled, End offset percent", - screens: [ - {id: 1, w: 1200, h: 1200, s: 1.5, name: "Parent"}, - {id: 2, w: 1200, h: 1200, s: 1, parent: {id: 1, align: "r", offset: -600}, name: "Child"}, - ] - }, - { - name: "Parent scaled, Start align", - screens: [ - {id: 1, w: 1200, h: 1200, s: 1.5, name: "Parent"}, - {id: 2, w: 1200, h: 1100, s: 1, parent: {id: 1, align: "r", offset: 0}, name: "Child"}, - ] - }, - { - name: "Parent scaled, End align", - screens: [ - {id: 1, w: 1200, h: 1200, s: 1.5, name: "Parent"}, - {id: 2, w: 1200, h: 1200, s: 1, parent: {id: 1, align: "r", offset: 0}, name: "Child"}, - ] - }, - { - name: "Parent scaled, in-between", - screens: [ - {id: 1, w: 1200, h: 1200, s: 1.5, name: "Parent"}, - {id: 2, w: 1200, h: 1500, s: 1, parent: {id: 1, align: "r", offset: -200}, name: "Child"}, - ] - }, - ], - [ - // Edge cases examples - { - name: "Parent order (5 is parent of 4)", - screens: [ - {id: 1, w: 1920, h: 1080, s: 1}, - {id: 2, w: 1024, h: 600, s: 1.25, parent: {id: 1, align: "r", offset: -200}}, - {id: 3, w: 800, h: 800, s: 1.25, parent: {id: 2, align: "b", offset: 0}}, - {id: 4, w: 800, h: 1080, s: 1.5, parent: {id: 2, align: "re", offset: 100}}, - {id: 5, w: 600, h: 600, s: 1, parent: {id: 3, align: "r", offset: 100}}, - ] - }, - { - name: "de-intersection reparent", - screens: [ - {id: 1, w: 1920, h: 1080, s: 1}, - {id: 2, w: 1680, h: 1050, s: 1.25, parent: {id: 1, align: "r", offset: 10}}, - {id: 3, w: 1440, h: 900, s: 1.5, parent: {id: 1, align: "le", offset: 150}}, - {id: 4, w: 1024, h: 768, s: 1, parent: {id: 3, align: "bc", offset: -200}}, - {id: 5, w: 1024, h: 768, s: 1.25, parent: {id: 4, align: "r", offset: 400}}, - ] - }, - { - name: "de-intersection (unattached child)", - screens: [ - {id: 1, w: 1920, h: 1080, s: 1}, - {id: 2, w: 1024, h: 768, s: 1.5, parent: {id: 1, align: "le", offset: 10}}, - {id: 3, w: 1024, h: 768, s: 1.25, parent: {id: 2, align: "b", offset: 100}}, - {id: 4, w: 1024, h: 768, s: 1, parent: {id: 3, align: "r", offset: 500}}, - ] - }, - { - name: "Multiple de-intersection", - screens: [ - {id: 1, w: 1920, h: 1080, s: 1}, - {id: 2, w: 1024, h: 768, s: 1, parent: {id: 1, align: "be", offset: 0}}, - {id: 3, w: 1024, h: 768, s: 1, parent: {id: 2, align: "b", offset: 300}}, - {id: 4, w: 1024, h: 768, s: 1.5, parent: {id: 2, align: "le", offset: 100}}, - {id: 5, w: 1024, h: 768, s: 1, parent: {id: 4, align: "be", offset: 100}}, - ] - }, - { - name: "Multiple de-intersection (left-side)", - screens: [ - {id: 1, w: 1920, h: 1080, s: 1}, - {id: 2, w: 1024, h: 768, s: 1, parent: {id: 1, align: "le", offset: 0}}, - {id: 3, w: 1024, h: 768, s: 1, parent: {id: 2, align: "b", offset: 300}}, - {id: 4, w: 1024, h: 768, s: 1.5, parent: {id: 2, align: "le", offset: 100}}, - {id: 5, w: 1024, h: 768, s: 1, parent: {id: 4, align: "be", offset: 100}}, - ] - }, - { - name: "Parent de-intersection child offset", - screens: [ - {id: 1, w: 1600, h: 1600, s: 1.5}, - {id: 2, w: 800, h: 800, s: 1, parent: {id: 1, align: "r", offset: 0}}, - {id: 3, w: 800, h: 800, s: 1, parent: {id: 1, align: "r", offset: 800}}, - {id: 4, w: 800, h: 1600, s: 1, parent: {id: 2, align: "r", offset: 0}}, - ] - }, - ], -].map(sections => sections.map(layout => { - return parseLayout(layout) -})) - -function parseLayout(layout) { - const screens = [] - - for (const screen of layout.screens) { - let x = 0, y = 0 - const {w, h} = screen - - if (screen.parent) { - const parent = screens.find(s => s.ID == screen.parent.id).Bounds - const offset = screen.parent.offset - let align = screen.parent.align - let align2 = "" - - if (align.length == 2) { - align2 = align.charAt(1) - align = align.charAt(0) - } - - x = parent.X - y = parent.Y - // t: top, b: bottom, l: left, r: right, e: edge, c: corner - if (align == "t" || align == "b") { - x += offset + (align2 == "e" || align2 == "c" ? parent.Width : 0) - (align2 == "e" ? w : 0) - y += (align == "t" ? -h : parent.Height) - } else { - y += offset + (align2 == "e" || align2 == "c" ? parent.Height : 0) - (align2 == "e" ? h : 0) - x += (align == "l" ? -w : parent.Width) - } - } - - screens.push({ - ID: `${screen.id}`, - Name: screen.name ?? `Display${screen.id}`, - ScaleFactor: Math.round(screen.s * 100) / 100, - X: x, - Y: y, - Size: {Width: w, Height: h}, - Bounds: {X: x, Y: y, Width: w, Height: h}, - PhysicalBounds: {X: x, Y: y, Width: w, Height: h}, - WorkArea: {X: x, Y: y, Width: w, Height: h-Math.round(40*screen.s)}, - PhysicalWorkArea: {X: x, Y: y, Width: w, Height: h-Math.round(40*screen.s)}, - IsPrimary: screen.id == 1, - Rotation: 0 - }) - } - - return {name: layout.name, screens} -} diff --git a/v3/examples/screen/assets/index.html b/v3/examples/screen/assets/index.html deleted file mode 100644 index 780f5854d..000000000 --- a/v3/examples/screen/assets/index.html +++ /dev/null @@ -1,143 +0,0 @@ - - - - - Screens Demo - - - -
            - - -
            - -  X: - - -  Width: - - -   - - -   - - -   - -   - Layers: -
            -
            -
            -
            - Screens:  - System - -  - Examples - : -   - - -
            -
            - Coordinates:  - Physical (PX) - Logical (DIP) - - -   - - - - - -
            -
            - - - - - - -
            - - - - - - diff --git a/v3/examples/screen/assets/main.js b/v3/examples/screen/assets/main.js deleted file mode 100644 index 316c08002..000000000 --- a/v3/examples/screen/assets/main.js +++ /dev/null @@ -1,406 +0,0 @@ -setExamplesType(document.getElementById('examples-type').value, 0) - -function setExamplesType(type, autoSelectLayout = 1) { - window.examples_type = parseInt(type) - document.getElementById('examples-list').innerHTML = examples[examples_type].map((layout, i) => { - return `${i + 1}` - }).join("\n") - if (autoSelectLayout != null) setLayout(autoSelectLayout) -} - -async function setLayout(indexOrLayout, physicalCoordinate = true) { - if (typeof indexOrLayout == 'number') { - await radioBtnClick(null, `#layout-selector [data-value="${indexOrLayout}"]`) - } else { - document.querySelectorAll('#layout-selector .active').forEach(el => el.classList.remove('active')) - window.layout = indexOrLayout - window.point = null - window.rect = null - await processLayout() - await draw() - } - - const physical = !parseInt(document.querySelector('#coordinate-selector .active').dataset.value) - if (physical != physicalCoordinate) { - await setCoordinateType(physicalCoordinate) - } -} - -async function setCoordinateType(physicalCoordinate = true) { - await radioBtnClick(null, `#coordinate-selector [data-value="${physicalCoordinate ? 0 : 1}"]`) -} - -async function radioBtnClick(e, selector) { - if (e == null) { - e = new Event("mousedown") - document.querySelector(selector).dispatchEvent(e) - } - if (!e.target.classList.contains('radio-btn')) return - const btnGroup = e.target.closest('.radio-btn-group') - btnGroup.querySelectorAll('.radio-btn.active').forEach(el => el.classList.remove('active')) - e.target.classList.add('active') - - if (btnGroup.id == 'layout-selector') { - window.point = null - window.rect = null - await processLayout() - } - - await draw() -} - -async function processLayout() { - const layoutBtn = document.querySelector('#layout-selector .active') - const i = layoutBtn ? parseInt(layoutBtn.dataset.value) : -1 - if (i == 0) { - // system screens - window.layout = { - name: '', - screens: await callBinding('main.ScreenService.GetSystemScreens'), - } - } else { - if (i > 0) { - // example layouts - window.layout = structuredClone(examples[examples_type][i - 1]) - } - layout.screens = await callBinding('main.ScreenService.ProcessExampleScreens', layout.screens) - } - document.getElementById('example-name').textContent = layout.name -} - -async function draw() { - console.log(layout) - let minX = 0, minY = 0, maxX = 0, maxY = 0; - let html = ''; - - const physical = !parseInt(document.querySelector('#coordinate-selector .active').dataset.value) - const retainViewbox = document.querySelector('#retain-viewbox').checked - - layout.screens.forEach(screen => { - const b = physical ? screen.PhysicalBounds : screen.Bounds - const wa = physical ? screen.PhysicalWorkArea : screen.WorkArea - const vbBounds = retainViewbox ? [screen.Bounds, screen.PhysicalBounds] : [b] - - minX = Math.min(minX, ...vbBounds.map(b => b.X)) - minY = Math.min(minY, ...vbBounds.map(b => b.Y)) - maxX = Math.max(maxX, ...vbBounds.map(b => b.X + b.Width)) - maxY = Math.max(maxY, ...vbBounds.map(b => b.Y + b.Height)) - - html += ` - - - - - - (${b.X}, ${b.Y}) - - ${screen.Name} - ${b.Width} x ${b.Height} - Scale factor: ${screen.ScaleFactor} - - - ` - }) - - const svg = document.getElementById('svg') - svg.innerHTML = ` - ${svg.querySelector('& > defs').outerHTML} - - ${html} - - - ` - - svg.setAttribute('viewBox', `${minX} ${minY} ${maxX - minX} ${maxY - minY}`) - - if (window.point) await probePoint() - if (window.rect) await drawRect() - - svg.onmousedown = async function(e) { - let pt = new DOMPoint(e.clientX, e.clientY) - pt = pt.matrixTransform(svg.getScreenCTM().inverse()) - pt.x = parseInt(pt.x) - pt.y = parseInt(pt.y) - if (e.buttons == 1) { - await probePoint({X: pt.x, Y: pt.y}) - } else if (e.buttons == 2) { - if (e.ctrlKey) { - if (!window.rect) { - window.rect = {X: pt.x, Y: pt.y, Width: 0, Height: 0} - } - if (!window.rectCursor) { - window.rectAnchor = {x: window.rect.X, y: window.rect.Y} - window.rectCursor = {x: window.rectAnchor.x + window.rect.Width, y: window.rectAnchor.y + window.rect.Height} - } - window.rectCursorOffset = { - x: pt.x - window.rectCursor.x, - y: pt.y - window.rectCursor.y, - } - } else { - window.rectAnchor = pt - window.rectCursorOffset = {x: 0, y: 0} - window.probing = true - drawRect({X: pt.x, Y: pt.y, Width: 0, Height: 0}) - window.probing = false - } - } else if (e.buttons == 4) { - drawRect({X: pt.x, Y: pt.y, Width: 50, Height: 50}) - } - } - svg.onmousemove = async function(e) { - if (window.probing) return - window.probing = true - if (e.buttons == 1) { - await svg.onmousedown(e) - } else if (e.buttons == 2) { - let pt = new DOMPoint(e.clientX, e.clientY) - pt = pt.matrixTransform(svg.getScreenCTM().inverse()) - if (e.ctrlKey) { - window.rectAnchor.x += pt.x - rectCursor.x - window.rectCursorOffset.x - window.rectAnchor.y += pt.y - rectCursor.y - window.rectCursorOffset.y - } - window.rectCursor = { - x: pt.x - window.rectCursorOffset.x, - y: pt.y - window.rectCursorOffset.y, - } - await drawRect({ - X: parseInt(Math.min(window.rectAnchor.x, window.rectCursor.x)), - Y: parseInt(Math.min(window.rectAnchor.y, window.rectCursor.y)), - Width: parseInt(Math.abs(window.rectCursor.x - window.rectAnchor.x)), - Height: parseInt(Math.abs(window.rectCursor.y - window.rectAnchor.y)), - }) - } - window.probing = false - } - svg.oncontextmenu = function(e) { - e.preventDefault() - } -} - -async function probePoint(p = null) { - const svg = document.getElementById('svg'); - const physical = !parseInt(document.querySelector('#coordinate-selector .active').dataset.value) - - if (p == null) { - if (window.pointIsPhysical == physical) { - p = window.point - } else { - p = (await callBinding('main.ScreenService.TransformPoint', window.point, window.pointIsPhysical))[0] - } - } - - window.point = p - window.pointIsPhysical = physical - const [ptTransformed, ptDblTransformed] = await callBinding('main.ScreenService.TransformPoint', p, physical) - - svg.getElementById('points').innerHTML = ` - - - - - ` - // await new Promise((resolve) => setTimeout(resolve, 200)) // delay - return ptDblTransformed -} - -async function drawRect(r = null) { - const svg = document.getElementById('svg'); - const physical = !parseInt(document.querySelector('#coordinate-selector .active').dataset.value) - - if (r == null) { - if (window.rectIsPhysical == physical) { - r = window.rect - } else { - r = await callBinding('main.ScreenService.TransformRect', window.rect, window.rectIsPhysical) - } - } - - if (!window.probing) { - window.rectAnchor = null - window.rectCursor = null - } - - document.getElementById('x').value = r.X - document.getElementById('y').value = r.Y - document.getElementById('w').value = r.Width - document.getElementById('h').value = r.Height - - window.rect = r - window.rectIsPhysical = physical - window.rTransformed = await callBinding('main.ScreenService.TransformRect', r, physical) - window.rDblTransformed = await callBinding('main.ScreenService.TransformRect', rTransformed, !physical) - window.rTransformed = rTransformed - - await rectLayers() - return rDblTransformed -} - -async function rectLayers() { - const s = document.getElementById('slider').value - if (window.rect == null) await test1() - - const r = await callBinding('main.ScreenService.TransformRect', rectIsPhysical ? rect : rTransformed, true) - const rShifted = {...r, X: r.X+50} - const rShiftedPhysical = await callBinding('main.ScreenService.TransformRect', rShifted, false) - - svg.getElementById('rects').innerHTML = [ - [window.rect, 'rgb(255 255 255 / 100%)'], // w - [window.rTransformed, 'rgb(0 255 0 / 25%)'], // g - [window.rDblTransformed, 'none'], // none - [rShifted, 'rgb(255 0 0 / 15%)'], // r - [rShiftedPhysical, 'rgb(0 0 255 / 15%)'], // b - ].filter((_,i) => i { - let lines = '' - if (i == 0) { - const center = {X: r.X + (r.Width-1)/2, Y: r.Y + (r.Height-1)/2} - lines += ` - - - ` - } - return `${lines}` - }).join('/n') -} - -async function updateDipRect(x, y=0, w=0, h=0) { - if (rect == null) { - await drawRect({ - X: +document.getElementById('x').value, - Y: +document.getElementById('y').value, - Width: +document.getElementById('w').value, - Height: +document.getElementById('h').value, - }) - } - // Simulate real window by first retrieving the physical bounds then transforming it to dip - // then updating the bounds and transforming it back to physical - let rPhysical = rectIsPhysical ? rect : rTransformed - const r = await callBinding('main.ScreenService.TransformRect', rPhysical, true) - r.X += x - r.Y += y - r.Width += w - r.Height += h - rPhysical = await callBinding('main.ScreenService.TransformRect', r, false) - drawRect(rectIsPhysical ? rPhysical : r) -} - -function arrowMove(e) { - let x = 0, y = 0 - if (e.key == 'ArrowLeft') x = -step.value - if (e.key == 'ArrowRight') x = +step.value - if (e.key == 'ArrowUp') y = -step.value - if (e.key == 'ArrowDown') y = +step.value - if (!(x || y)) return - e.preventDefault() - updateDipRect(x, y) -} - -async function test1() { - // Edge case 1: invalid dip rect: no physical rect can produce it - await setLayout(parseLayout({screens: [ - {id: 1, w: 1200, h: 1200, s: 1}, - {id: 2, w: 1200, h: 1100, s: 1.5, parent: {id: 1, align: "r", offset: 0}}, - ]}), false) - await drawRect({X: 1050, Y: 700, Width: 400, Height: 300}) -} - -async function test2() { - // Edge case 2: physical rect that changes when double transformed (2 physical rects produce the same dip rect) - await setLayout(parseLayout({screens: [ - {id: 1, w: 1200, h: 1200, s: 1.5}, - {id: 2, w: 1200, h: 900, s: 1, parent: {id: 1, align: "r", offset: 0}}, - ]}), true) - await drawRect({X: 1050, Y: 890, Width: 400, Height: 300}) -} - -async function probeLayout(finishup = true) { - const probeButtons = document.getElementById('probe-buttons') - const svg = document.getElementById('svg') - const threshold = 1 - - const physical = !parseInt(document.querySelector('#coordinate-selector .active').dataset.value) - window.cancelProbing = false - probeButtons.classList.add('active') - - const steps = 3 - let failed = false - for (const screen of layout.screens) { - if (window.cancelProbing) break - const b = physical ? screen.PhysicalBounds : screen.Bounds - const xStep = parseInt(b.Width / steps) || 1 - const yStep = parseInt(b.Height / steps) || 1 - let x = b.X, y = b.Y - let xDone = false, yDone = false - - while (!(yDone || window.cancelProbing)) { - if (y >= b.Y + b.Height - 1) { - y = b.Y + b.Height - 1 - yDone = true - } - x = b.X - xDone = false - while (!(xDone || window.cancelProbing)) { - if (x >= b.X + b.Width - 1) { - x = b.X + b.Width - 1 - xDone = true - } - const pt = {X: x, Y: y} - let ptDblTransformed, err - try { - ptDblTransformed = await probePoint(pt) - } catch (e) { - err = e - } - if (err || Math.abs(pt.X - ptDblTransformed.X) > threshold || Math.abs(pt.Y - ptDblTransformed.Y) > threshold) { - failed = true - console.log(pt, ptDblTransformed) - window.cancelProbing = true - setTimeout(() => { - alert(err ?? `**FAILED**\nProbing failed at point: {X: ${pt.X}, Y: ${pt.Y}}\nDouble transformed point: {X: ${ptDblTransformed.X}, Y: ${ptDblTransformed.Y}}\n(Exceeded threshold of ${threshold} pixels)`) - }, 50) - } - x += xStep - } - y += yStep - } - } - - if (finishup || window.cancelProbing) probeButtons.classList.remove('active') - if (!(failed || window.cancelProbing)) { - window.point = null - if (finishup) { - setTimeout(() => { - svg.getElementById('points').innerHTML = '' - alert(`Successfully probed all points!, All within threshold of ${threshold} pixels.`) - }, 50) - } - return true - } -} - -async function probeAllExamples() { - console.time('probeAllExamples') -loop1: - for (let typeI = 0; typeI < examples.length; typeI++) { - document.getElementById('examples-type').value = typeI - setExamplesType(typeI, null) - - for (let layoutI = (typeI ? 0 : -1); layoutI < examples[typeI].length; layoutI++) { - await radioBtnClick(null, `#layout-selector [data-value="${layoutI + 1}"]`) - for (let i = 0; i < 2; i++) { - const lastLayout = (typeI == examples.length - 1 && layoutI == examples[typeI].length - 1 && i == 1) - if (!await probeLayout(lastLayout)) break loop1 - if (i == 0) await setCoordinateType(!pointIsPhysical) - } - } - } - console.timeEnd('probeAllExamples') -} - -async function callBinding(name, ...params) { - return wails.Call.ByName(name, ...params) -} - -function showAdvanced(e) { - e.target.style.display = 'none' - document.querySelectorAll('.advanced').forEach(el => el.style.display = 'initial') -} diff --git a/v3/examples/screen/main.go b/v3/examples/screen/main.go deleted file mode 100644 index 75d0c8bd2..000000000 --- a/v3/examples/screen/main.go +++ /dev/null @@ -1,78 +0,0 @@ -package main - -import ( - "embed" - "log" - "log/slog" - "net/http" - "os" - "path/filepath" - "runtime" - - "github.com/wailsapp/wails/v3/pkg/application" -) - -//go:embed assets/* -var assets embed.FS - -func main() { - - app := application.New(application.Options{ - Name: "Screen Demo", - Description: "A demo of the Screen API", - Mac: application.MacOptions{ - ApplicationShouldTerminateAfterLastWindowClosed: true, - }, - Windows: application.WindowsOptions{ - WndProcInterceptor: nil, - DisableQuitOnLastWindowClosed: false, - WebviewUserDataPath: "", - WebviewBrowserPath: "", - }, - Services: []application.Service{ - application.NewService(&ScreenService{}), - }, - LogLevel: slog.LevelError, - Assets: application.AssetOptions{ - Handler: application.BundledAssetFileServer(assets), - Middleware: func(next http.Handler) http.Handler { - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - // Disable caching - w.Header().Set("Cache-Control", "no-cache, no-store, must-revalidate") - w.Header().Set("Pragma", "no-cache") - w.Header().Set("Expires", "0") - - _, filename, _, _ := runtime.Caller(0) - dir := filepath.Dir(filename) - url := r.URL.Path - path := dir + "/assets" + url - - if _, err := os.Stat(path); err == nil { - // Serve file from disk to make testing easy - http.ServeFile(w, r, path) - } else { - // Passthrough to the default asset handler if file not found on disk - next.ServeHTTP(w, r) - } - }) - }, - }, - }) - - app.Window.NewWithOptions(application.WebviewWindowOptions{ - Title: "Screen Demo", - Width: 800, - Height: 600, - Mac: application.MacWindow{ - Backdrop: application.MacBackdropTranslucent, - TitleBar: application.MacTitleBarHiddenInsetUnified, - InvisibleTitleBarHeight: 50, - }, - }) - - err := app.Run() - - if err != nil { - log.Fatal(err.Error()) - } -} diff --git a/v3/examples/screen/screens.go b/v3/examples/screen/screens.go deleted file mode 100644 index 95e8abed0..000000000 --- a/v3/examples/screen/screens.go +++ /dev/null @@ -1,182 +0,0 @@ -package main - -import ( - "github.com/wailsapp/wails/v3/pkg/application" -) - -type ScreenService struct { - screenManager application.ScreenManager - isExampleLayout bool -} - -// Helper to safely get float64 from interface{} -func getFloat64(v interface{}) float64 { - if v == nil { - return 0 - } - if f, ok := v.(float64); ok { - return f - } - return 0 -} - -// Helper to safely get int from interface{} (expecting float64 from JSON) -func getInt(v interface{}) int { - return int(getFloat64(v)) -} - -func (s *ScreenService) GetSystemScreens() []*application.Screen { - s.isExampleLayout = false - screens := application.Get().Screen.GetAll() - return screens -} - -func (s *ScreenService) ProcessExampleScreens(rawScreens []interface{}) []*application.Screen { - s.isExampleLayout = true - - parseRect := func(m map[string]interface{}) application.Rect { - if m == nil { - return application.Rect{} - } - return application.Rect{ - X: getInt(m["X"]), - Y: getInt(m["Y"]), - Width: getInt(m["Width"]), - Height: getInt(m["Height"]), - } - } - - // Prevent unbounded slice growth by limiting the number of screens - maxScreens := 32 // Reasonable limit for screen configurations - if len(rawScreens) > maxScreens { - rawScreens = rawScreens[:maxScreens] - } - - screens := make([]*application.Screen, 0, len(rawScreens)) - for _, s := range rawScreens { - sm, ok := s.(map[string]interface{}) - if !ok { - continue - } - - boundsVal, ok := sm["Bounds"] - if !ok { - continue - } - boundsMap, ok := boundsVal.(map[string]interface{}) - if !ok { - continue - } - bounds := parseRect(boundsMap) - - var id, name string - var isPrimary bool - if idVal, ok := sm["ID"].(string); ok { - id = idVal - } - if nameVal, ok := sm["Name"].(string); ok { - name = nameVal - } - if primaryVal, ok := sm["IsPrimary"].(bool); ok { - isPrimary = primaryVal - } - - var physicalBounds, workArea, physicalWorkArea application.Rect - if pb, ok := sm["PhysicalBounds"].(map[string]interface{}); ok { - physicalBounds = parseRect(pb) - } - if wa, ok := sm["WorkArea"].(map[string]interface{}); ok { - workArea = parseRect(wa) - } - if pwa, ok := sm["PhysicalWorkArea"].(map[string]interface{}); ok { - physicalWorkArea = parseRect(pwa) - } - - screens = append(screens, &application.Screen{ - ID: id, - Name: name, - X: bounds.X, - Y: bounds.Y, - Size: application.Size{Width: bounds.Width, Height: bounds.Height}, - Bounds: bounds, - PhysicalBounds: physicalBounds, - WorkArea: workArea, - PhysicalWorkArea: physicalWorkArea, - IsPrimary: isPrimary, - ScaleFactor: float32(getFloat64(sm["ScaleFactor"])), - Rotation: 0, - }) - } - - s.screenManager.LayoutScreens(screens) - return s.screenManager.GetAll() -} - -func (s *ScreenService) transformPoint(point application.Point, toDIP bool) application.Point { - if s.isExampleLayout { - if toDIP { - return s.screenManager.PhysicalToDipPoint(point) - } else { - return s.screenManager.DipToPhysicalPoint(point) - } - } else { - if toDIP { - return application.PhysicalToDipPoint(point) - } else { - return application.DipToPhysicalPoint(point) - } - } -} - -func (s *ScreenService) TransformPoint(point map[string]interface{}, toDIP bool) (points [2]application.Point) { - if point == nil { - return points - } - - pt := application.Point{ - X: getInt(point["X"]), - Y: getInt(point["Y"]), - } - - ptTransformed := s.transformPoint(pt, toDIP) - ptDblTransformed := s.transformPoint(ptTransformed, !toDIP) - - // double-transform a limited number of times to catch any double-rounding issues - // Limit iterations to prevent potential performance issues - maxIterations := 3 // Reduced from 10 to limit computational overhead - for i := 0; i < maxIterations; i++ { - ptTransformed = s.transformPoint(ptDblTransformed, toDIP) - ptDblTransformed = s.transformPoint(ptTransformed, !toDIP) - } - - points[0] = ptTransformed - points[1] = ptDblTransformed - return points -} - -func (s *ScreenService) TransformRect(rect map[string]interface{}, toDIP bool) application.Rect { - if rect == nil { - return application.Rect{} - } - - r := application.Rect{ - X: getInt(rect["X"]), - Y: getInt(rect["Y"]), - Width: getInt(rect["Width"]), - Height: getInt(rect["Height"]), - } - - if s.isExampleLayout { - if toDIP { - return s.screenManager.PhysicalToDipRect(r) - } else { - return s.screenManager.DipToPhysicalRect(r) - } - } else { - if toDIP { - return application.PhysicalToDipRect(r) - } else { - return application.DipToPhysicalRect(r) - } - } -} diff --git a/v3/examples/server/Dockerfile b/v3/examples/server/Dockerfile deleted file mode 100644 index 765354108..000000000 --- a/v3/examples/server/Dockerfile +++ /dev/null @@ -1,55 +0,0 @@ -# Wails Server Mode Dockerfile -# Multi-stage build for minimal image size -# -# BUILD FROM v3 ROOT (to use local code before server mode is published): -# docker build -t server-example -f examples/server/Dockerfile . -# -# BUILD FROM EXAMPLE DIR (after server mode is published): -# cd examples/server && docker build -t server-example . - -# Build stage -FROM golang:alpine AS builder - -WORKDIR /app - -# Install build dependencies -RUN apk add --no-cache git - -# Copy source code -COPY . . - -# If building from example dir, remove replace directive -# If building from v3 root, this is a no-op -RUN sed -i '/^replace/d' go.mod 2>/dev/null || true - -# Download dependencies -RUN go mod tidy - -# Build the server binary and prepare assets -# When building from v3 root, change to example dir -RUN if [ -d "examples/server" ]; then \ - cd examples/server && go build -tags server -ldflags="-s -w" -o /app/server . && \ - cp -r frontend/dist /app/frontend_dist; \ - else \ - go build -tags server -ldflags="-s -w" -o /app/server . && \ - cp -r frontend/dist /app/frontend_dist; \ - fi - -# Runtime stage - minimal image -FROM gcr.io/distroless/static-debian12 - -# Copy the binary -COPY --from=builder /app/server /server - -# Copy frontend assets -COPY --from=builder /app/frontend_dist /frontend/dist - -# Expose the default port -EXPOSE 8080 - -# Bind to all interfaces (required for Docker) -# Can be overridden at runtime with -e WAILS_SERVER_HOST=... -ENV WAILS_SERVER_HOST=0.0.0.0 - -# Run the server -ENTRYPOINT ["/server"] diff --git a/v3/examples/server/README.md b/v3/examples/server/README.md deleted file mode 100644 index ca9f16514..000000000 --- a/v3/examples/server/README.md +++ /dev/null @@ -1,134 +0,0 @@ -# Server Mode Example - -> **Experimental** - This feature is experimental and may change in future releases. - -This example demonstrates running a Wails application in server mode - without a native GUI window. - -## What is Server Mode? - -Server mode allows you to run your Wails application as a pure HTTP server. This enables: - -- **Docker/Container deployments** - Deploy your Wails app without X11/Wayland dependencies -- **Server-side rendering** - Use your Wails app as a web server -- **Web-only access** - Share the same codebase between desktop and web deployments -- **CI/CD testing** - Run integration tests without a display server - -## Building and Running - -The recommended way to build server mode applications is using the Taskfile: - -```bash -# Build for server mode -wails3 task build:server - -# Build and run -wails3 task run:server -``` - -Or using Go directly: - -```bash -# Build with server tag -go build -tags server -o myapp-server . - -# Run -go run -tags server . -``` - -Then open in your browser. - -## Key Differences from Desktop Mode - -1. **No native window** - The app runs as an HTTP server only -2. **Browser access** - Users access the app via their web browser -3. **No CGO required** - Can build without CGO dependencies -4. **Window APIs are no-ops** - Calls to window-related APIs are safely ignored -5. **Browser windows** - Each browser tab is represented as a "window" named `browser-1`, `browser-2`, etc. - -## Events - -Events work bidirectionally in server mode: - -- **Frontend to Backend**: Events emitted from the browser are sent via HTTP and received by your Go event handlers -- **Backend to Frontend**: Events emitted from Go are broadcast to all connected browsers via WebSocket - -```go -// Listen for events from browsers -app.Event.On("user-action", func(event *application.CustomEvent) { - log.Printf("Event from %s: %v", event.Sender, event.Data) - // event.Sender will be "browser-1", "browser-2", etc. -}) - -// Emit events to all browsers -app.Event.Emit("server-update", data) -``` - -## Configuration - -Server mode is enabled by building with the `server` build tag. Configure the HTTP server options: - -```go -app := application.New(application.Options{ - // Configure the HTTP server (used when built with -tags server) - Server: application.ServerOptions{ - Host: "localhost", // Use "0.0.0.0" for all interfaces - Port: 8080, - }, - - // ... other options work the same as desktop mode -}) -``` - -## Health Check - -A health check endpoint is automatically available at `/health`: - -```bash -curl http://localhost:8080/health -# {"status":"ok"} -``` - -## Building for Production - -```bash -# Using Taskfile (recommended) -wails3 task build:server - -# Or using Go directly -go build -tags server -o myapp-server . -``` - -## Docker - -Build and run with Docker using the built-in tasks: - -```bash -# Build Docker image -task build:docker - -# Build and run -task run:docker - -# Run on a different port -task run:docker PORT=3000 -``` - -Or build manually: - -```bash -docker build -t server-example . -docker run --rm -p 8080:8080 server-example -``` - -## Limitations - -Since server mode runs without a native GUI, the following features are not available: - -- Native dialogs (file open/save, message boxes) -- System tray -- Native menus -- Window manipulation (resize, move, minimize, etc.) -- Clipboard access (use browser clipboard APIs instead) -- Screen information - -These APIs are safe to call but will have no effect or return default values. diff --git a/v3/examples/server/Taskfile.yml b/v3/examples/server/Taskfile.yml deleted file mode 100644 index bc9d3acf8..000000000 --- a/v3/examples/server/Taskfile.yml +++ /dev/null @@ -1,80 +0,0 @@ -version: '3' - -vars: - APP_NAME: "server-example" - BIN_DIR: "bin" - -tasks: - default: - summary: Shows available tasks - cmds: - - task --list - - build: - summary: Builds the application in server mode - desc: | - Builds the application with the server build tag enabled. - Server mode runs as a pure HTTP server without native GUI dependencies. - deps: - - task: build:frontend - cmds: - - go build -tags server -o {{.BIN_DIR}}/{{.APP_NAME}} . - - build:frontend: - summary: Ensures frontend assets exist (static HTML, no build needed) - dir: frontend - sources: - - dist/index.html - preconditions: - - sh: test -f dist/index.html - msg: "frontend/dist/index.html not found" - - run: - summary: Builds and runs the application in server mode - deps: - - task: build - cmds: - - ./{{.BIN_DIR}}/{{.APP_NAME}} - - dev: - summary: Runs the application in development mode (no build step) - desc: | - Runs the application directly with `go run` for rapid development. - Changes require restarting the command. - cmds: - - go run -tags server . - - clean: - summary: Removes build artifacts - cmds: - - rm -rf {{.BIN_DIR}} - - build:docker: - summary: Builds a Docker image for deployment - desc: | - Builds from v3 root to include local server mode code. - After server mode is published, can build from example dir directly. - dir: ../.. - cmds: - - docker build -t {{.TAG | default "server-example:latest"}} -f examples/server/Dockerfile . - vars: - TAG: '{{.TAG}}' - preconditions: - - sh: docker info > /dev/null 2>&1 - msg: "Docker is required. Please install Docker first." - - run:docker: - summary: Builds and runs the Docker image - deps: - - task: build:docker - cmds: - - docker run --rm -p {{.PORT | default "8080"}}:8080 {{.TAG | default "server-example:latest"}} - vars: - TAG: '{{.TAG}}' - PORT: '{{.PORT}}' - - test: - summary: Runs the server mode tests - dir: ../../pkg/application - cmds: - - go test -tags server -v -run TestServerMode . diff --git a/v3/examples/server/frontend/dist/index.html b/v3/examples/server/frontend/dist/index.html deleted file mode 100644 index 207a89bad..000000000 --- a/v3/examples/server/frontend/dist/index.html +++ /dev/null @@ -1,187 +0,0 @@ - - - - - - Wails Headless Example - - - - -
            -

            Wails Headless

            -

            Running without a native window

            - Server Mode - -
            - - -
            - -
            Enter a name and click Greet
            - -
            - -
            - -
            - Events: -
            -
            - -

            - This Wails application is running in headless mode.
            - It serves content via HTTP without requiring a native GUI. -

            -
            - - - - diff --git a/v3/examples/server/go.mod b/v3/examples/server/go.mod deleted file mode 100644 index ba596d27a..000000000 --- a/v3/examples/server/go.mod +++ /dev/null @@ -1,50 +0,0 @@ -module github.com/wailsapp/wails/v3/examples/server - -go 1.25 - -require github.com/wailsapp/wails/v3 v3.0.0-alpha.62 - -require ( - dario.cat/mergo v1.0.2 // indirect - github.com/Microsoft/go-winio v0.6.2 // indirect - github.com/ProtonMail/go-crypto v1.3.0 // indirect - github.com/adrg/xdg v0.5.3 // indirect - github.com/bep/debounce v1.2.1 // indirect - github.com/cloudflare/circl v1.6.3 // indirect - github.com/coder/websocket v1.8.14 // indirect - github.com/cyphar/filepath-securejoin v0.6.1 // indirect - github.com/ebitengine/purego v0.9.1 // indirect - github.com/emirpasic/gods v1.18.1 // indirect - github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect - github.com/go-git/go-billy/v5 v5.7.0 // indirect - github.com/go-git/go-git/v5 v5.16.4 // indirect - github.com/go-ole/go-ole v1.3.0 // indirect - github.com/godbus/dbus/v5 v5.2.2 // indirect - github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect - github.com/google/uuid v1.6.0 // indirect - github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect - github.com/jchv/go-winloader v0.0.0-20250406163304-c1995be93bd1 // indirect - github.com/kevinburke/ssh_config v1.4.0 // indirect - github.com/klauspost/cpuid/v2 v2.3.0 // indirect - github.com/leaanthony/go-ansi-parser v1.6.1 // indirect - github.com/leaanthony/u v1.1.1 // indirect - github.com/lmittmann/tint v1.1.2 // indirect - github.com/mattn/go-colorable v0.1.14 // indirect - github.com/mattn/go-isatty v0.0.20 // indirect - github.com/pjbgf/sha1cd v0.5.0 // indirect - github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c // indirect - github.com/rivo/uniseg v0.4.7 // indirect - github.com/samber/lo v1.52.0 // indirect - github.com/sergi/go-diff v1.4.0 // indirect - github.com/skeema/knownhosts v1.3.2 // indirect - github.com/wailsapp/go-webview2 v1.0.23 // indirect - github.com/xanzy/ssh-agent v0.3.3 // indirect - golang.org/x/crypto v0.47.0 // indirect - golang.org/x/net v0.49.0 // indirect - golang.org/x/sys v0.40.0 // indirect - golang.org/x/text v0.33.0 // indirect - gopkg.in/warnings.v0 v0.1.2 // indirect -) - -// For local development - remove this line before publishing -replace github.com/wailsapp/wails/v3 => ../.. diff --git a/v3/examples/server/go.sum b/v3/examples/server/go.sum deleted file mode 100644 index 56f1153ea..000000000 --- a/v3/examples/server/go.sum +++ /dev/null @@ -1,147 +0,0 @@ -dario.cat/mergo v1.0.2 h1:85+piFYR1tMbRrLcDwR18y4UKJ3aH1Tbzi24VRW1TK8= -dario.cat/mergo v1.0.2/go.mod h1:E/hbnu0NxMFBjpMIE34DRGLWqDy0g5FuKDhCb31ngxA= -github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY= -github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= -github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= -github.com/ProtonMail/go-crypto v1.3.0 h1:ILq8+Sf5If5DCpHQp4PbZdS1J7HDFRXz/+xKBiRGFrw= -github.com/ProtonMail/go-crypto v1.3.0/go.mod h1:9whxjD8Rbs29b4XWbB8irEcE8KHMqaR2e7GWU1R+/PE= -github.com/adrg/xdg v0.5.3 h1:xRnxJXne7+oWDatRhR1JLnvuccuIeCoBu2rtuLqQB78= -github.com/adrg/xdg v0.5.3/go.mod h1:nlTsY+NNiCBGCK2tpm09vRqfVzrc2fLmXGpBLF0zlTQ= -github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8= -github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4= -github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= -github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= -github.com/bep/debounce v1.2.1 h1:v67fRdBA9UQu2NhLFXrSg0Brw7CexQekrBwDMM8bzeY= -github.com/bep/debounce v1.2.1/go.mod h1:H8yggRPQKLUhUoqrJC1bO2xNya7vanpDl7xR3ISbCJ0= -github.com/cloudflare/circl v1.6.3 h1:9GPOhQGF9MCYUeXyMYlqTR6a5gTrgR/fBLXvUgtVcg8= -github.com/cloudflare/circl v1.6.3/go.mod h1:2eXP6Qfat4O/Yhh8BznvKnJ+uzEoTQ6jVKJRn81BiS4= -github.com/coder/websocket v1.8.14 h1:9L0p0iKiNOibykf283eHkKUHHrpG7f65OE3BhhO7v9g= -github.com/coder/websocket v1.8.14/go.mod h1:NX3SzP+inril6yawo5CQXx8+fk145lPDC6pumgx0mVg= -github.com/cyphar/filepath-securejoin v0.6.1 h1:5CeZ1jPXEiYt3+Z6zqprSAgSWiggmpVyciv8syjIpVE= -github.com/cyphar/filepath-securejoin v0.6.1/go.mod h1:A8hd4EnAeyujCJRrICiOWqjS1AX0a9kM5XL+NwKoYSc= -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= -github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/ebitengine/purego v0.9.1 h1:a/k2f2HQU3Pi399RPW1MOaZyhKJL9w/xFpKAg4q1s0A= -github.com/ebitengine/purego v0.9.1/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ= -github.com/elazarl/goproxy v1.7.2 h1:Y2o6urb7Eule09PjlhQRGNsqRfPmYI3KKQLFpCAV3+o= -github.com/elazarl/goproxy v1.7.2/go.mod h1:82vkLNir0ALaW14Rc399OTTjyNREgmdL2cVoIbS6XaE= -github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc= -github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ= -github.com/gliderlabs/ssh v0.3.8 h1:a4YXD1V7xMF9g5nTkdfnja3Sxy1PVDCj1Zg4Wb8vY6c= -github.com/gliderlabs/ssh v0.3.8/go.mod h1:xYoytBv1sV0aL3CavoDuJIQNURXkkfPA/wxQ1pL1fAU= -github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI= -github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmSxCcxctByoQdvwPiA7DTK7jaaFDBTtu0ic= -github.com/go-git/go-billy/v5 v5.7.0 h1:83lBUJhGWhYp0ngzCMSgllhUSuoHP1iEWYjsPl9nwqM= -github.com/go-git/go-billy/v5 v5.7.0/go.mod h1:/1IUejTKH8xipsAcdfcSAlUlo2J7lkYV8GTKxAT/L3E= -github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399 h1:eMje31YglSBqCdIqdhKBW8lokaMrL3uTkpGYlE2OOT4= -github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399/go.mod h1:1OCfN199q1Jm3HZlxleg+Dw/mwps2Wbk9frAWm+4FII= -github.com/go-git/go-git/v5 v5.16.4 h1:7ajIEZHZJULcyJebDLo99bGgS0jRrOxzZG4uCk2Yb2Y= -github.com/go-git/go-git/v5 v5.16.4/go.mod h1:4Ge4alE/5gPs30F2H1esi2gPd69R0C39lolkucHBOp8= -github.com/go-json-experiment/json v0.0.0-20251027170946-4849db3c2f7e h1:Lf/gRkoycfOBPa42vU2bbgPurFong6zXeFtPoxholzU= -github.com/go-json-experiment/json v0.0.0-20251027170946-4849db3c2f7e/go.mod h1:uNVvRXArCGbZ508SxYYTC5v1JWoz2voff5pm25jU1Ok= -github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE= -github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78= -github.com/godbus/dbus/v5 v5.2.2 h1:TUR3TgtSVDmjiXOgAAyaZbYmIeP3DPkld3jgKGV8mXQ= -github.com/godbus/dbus/v5 v5.2.2/go.mod h1:3AAv2+hPq5rdnr5txxxRwiGjPXamgoIHgz9FPBfOp3c= -github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 h1:f+oWsMOmNPc8JmEHVZIycC7hBoQxHH9pNKQORJNozsQ= -github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8/go.mod h1:wcDNUvekVysuuOpQKo3191zZyTpiI6se1N1ULghS0sw= -github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= -github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= -github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= -github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A= -github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= -github.com/jchv/go-winloader v0.0.0-20250406163304-c1995be93bd1 h1:njuLRcjAuMKr7kI3D85AXWkw6/+v9PwtV6M6o11sWHQ= -github.com/jchv/go-winloader v0.0.0-20250406163304-c1995be93bd1/go.mod h1:alcuEEnZsY1WQsagKhZDsoPCRoOijYqhZvPwLG0kzVs= -github.com/kevinburke/ssh_config v1.4.0 h1:6xxtP5bZ2E4NF5tuQulISpTO2z8XbtH8cg1PWkxoFkQ= -github.com/kevinburke/ssh_config v1.4.0/go.mod h1:q2RIzfka+BXARoNexmF9gkxEX7DmvbW9P4hIVx2Kg4M= -github.com/klauspost/cpuid/v2 v2.3.0 h1:S4CRMLnYUhGeDFDqkGriYKdfoFlDnMtqTiI/sFzhA9Y= -github.com/klauspost/cpuid/v2 v2.3.0/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0= -github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= -github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= -github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= -github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= -github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/leaanthony/go-ansi-parser v1.6.1 h1:xd8bzARK3dErqkPFtoF9F3/HgN8UQk0ed1YDKpEz01A= -github.com/leaanthony/go-ansi-parser v1.6.1/go.mod h1:+vva/2y4alzVmmIEpk9QDhA7vLC5zKDTRwfZGOp3IWU= -github.com/leaanthony/u v1.1.1 h1:TUFjwDGlNX+WuwVEzDqQwC2lOv0P4uhTQw7CMFdiK7M= -github.com/leaanthony/u v1.1.1/go.mod h1:9+o6hejoRljvZ3BzdYlVL0JYCwtnAsVuN9pVTQcaRfI= -github.com/lmittmann/tint v1.1.2 h1:2CQzrL6rslrsyjqLDwD11bZ5OpLBPU+g3G/r5LSfS8w= -github.com/lmittmann/tint v1.1.2/go.mod h1:HIS3gSy7qNwGCj+5oRjAutErFBl4BzdQP6cJZ0NfMwE= -github.com/matryer/is v1.4.0/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwMRU= -github.com/matryer/is v1.4.1 h1:55ehd8zaGABKLXQUe2awZ99BD/PTc2ls+KV/dXphgEQ= -github.com/matryer/is v1.4.1/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwMRU= -github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE= -github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8= -github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= -github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= -github.com/onsi/gomega v1.34.1 h1:EUMJIKUjM8sKjYbtxQI9A4z2o+rruxnzNvpknOXie6k= -github.com/onsi/gomega v1.34.1/go.mod h1:kU1QgUvBDLXBJq618Xvm2LUX6rSAfRaFRTcdOeDLwwY= -github.com/pjbgf/sha1cd v0.5.0 h1:a+UkboSi1znleCDUNT3M5YxjOnN1fz2FhN48FlwCxs0= -github.com/pjbgf/sha1cd v0.5.0/go.mod h1:lhpGlyHLpQZoxMv8HcgXvZEhcGs0PG/vsZnEJ7H0iCM= -github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmdv1U2eRNDiU2ErMBj1gwrq8eQ= -github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c/go.mod h1:7rwL4CYBLnjLxUqIJNnCWiEdr3bn6IUYi15bNlnbCCU= -github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= -github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= -github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= -github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= -github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= -github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= -github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= -github.com/samber/lo v1.52.0 h1:Rvi+3BFHES3A8meP33VPAxiBZX/Aws5RxrschYGjomw= -github.com/samber/lo v1.52.0/go.mod h1:4+MXEGsJzbKGaUEQFKBq2xtfuznW9oz/WrgyzMzRoM0= -github.com/sergi/go-diff v1.4.0 h1:n/SP9D5ad1fORl+llWyN+D6qoUETXNZARKjyY2/KVCw= -github.com/sergi/go-diff v1.4.0/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4= -github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= -github.com/skeema/knownhosts v1.3.2 h1:EDL9mgf4NzwMXCTfaxSD/o/a5fxDw/xL9nkU28JjdBg= -github.com/skeema/knownhosts v1.3.2/go.mod h1:bEg3iQAuw+jyiw+484wwFJoKSLwcfd7fqRy+N0QTiow= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= -github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= -github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= -github.com/wailsapp/go-webview2 v1.0.23 h1:jmv8qhz1lHibCc79bMM/a/FqOnnzOGEisLav+a0b9P0= -github.com/wailsapp/go-webview2 v1.0.23/go.mod h1:qJmWAmAmaniuKGZPWwne+uor3AHMB5PFhqiK0Bbj8kc= -github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM= -github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw= -golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.47.0 h1:V6e3FRj+n4dbpw86FJ8Fv7XVOql7TEwpHapKoMJ/GO8= -golang.org/x/crypto v0.47.0/go.mod h1:ff3Y9VzzKbwSSEzWqJsJVBnWmRwRSHt/6Op5n9bQc4A= -golang.org/x/exp v0.0.0-20260112195511-716be5621a96 h1:Z/6YuSHTLOHfNFdb8zVZomZr7cqNgTJvA8+Qz75D8gU= -golang.org/x/exp v0.0.0-20260112195511-716be5621a96/go.mod h1:nzimsREAkjBCIEFtHiYkrJyT+2uy9YZJB7H1k68CXZU= -golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.49.0 h1:eeHFmOGUTtaaPSGNmjBKpbng9MulQsJURQUAfUwY++o= -golang.org/x/net v0.49.0/go.mod h1:/ysNB2EvaqvesRkuLAyjI1ycPZlQHM3q01F02UY/MV8= -golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200810151505-1b9f1253b3ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.40.0 h1:DBZZqJ2Rkml6QMQsZywtnjnnGvHza6BTfYFWY9kjEWQ= -golang.org/x/sys v0.40.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= -golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.39.0 h1:RclSuaJf32jOqZz74CkPA9qFuVTX7vhLlpfj/IGWlqY= -golang.org/x/term v0.39.0/go.mod h1:yxzUCTP/U+FzoxfdKmLaA0RV1WgE0VY7hXBwKtY/4ww= -golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.33.0 h1:B3njUFyqtHDUI5jMn1YIr5B0IE2U0qck04r6d4KPAxE= -golang.org/x/text v0.33.0/go.mod h1:LuMebE6+rBincTi9+xWTY8TztLzKHc/9C1uBCG27+q8= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= -gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME= -gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= -gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= -gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= -gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/v3/examples/server/main.go b/v3/examples/server/main.go deleted file mode 100644 index 5b9bbdbae..000000000 --- a/v3/examples/server/main.go +++ /dev/null @@ -1,82 +0,0 @@ -package main - -import ( - "embed" - "log" - "log/slog" - "os" - "time" - - "github.com/wailsapp/wails/v3/pkg/application" -) - -//go:embed frontend/dist -var assets embed.FS - -// GreetService is a simple service that provides greeting functionality. -type GreetService struct{} - -// Greet returns a greeting message. -func (g *GreetService) Greet(name string) string { - if name == "" { - name = "World" - } - return "Hello, " + name + "!" -} - -func main() { - // Create a logger for better visibility - logger := slog.New(slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{ - Level: slog.LevelInfo, - })) - - app := application.New(application.Options{ - Name: "Server Mode Example", - Description: "A Wails application running in server mode", - Logger: logger, - LogLevel: slog.LevelInfo, - - // Server mode is enabled by building with -tags server - // Host/port can be overridden via WAILS_SERVER_HOST and WAILS_SERVER_PORT env vars - Server: application.ServerOptions{ - Host: "localhost", - Port: 8080, - }, - - // Register services (bindings work the same as desktop mode) - Services: []application.Service{ - application.NewService(&GreetService{}), - }, - - // Serve frontend assets - Assets: application.AssetOptions{ - Handler: application.AssetFileServerFS(assets), - }, - }) - - log.Println("Starting Wails application in server mode...") - log.Println("Access at: http://localhost:8080") - log.Println("Health check: http://localhost:8080/health") - log.Println("Press Ctrl+C to stop") - - // Listen for broadcast events from browsers - app.Event.On("broadcast", func(event *application.CustomEvent) { - log.Printf("Received broadcast from %s: %v\n", event.Sender, event.Data) - }) - - // Emit periodic events to test WebSocket broadcasting - go func() { - time.Sleep(2 * time.Second) // Wait for server to start - ticker := time.NewTicker(5 * time.Second) - defer ticker.Stop() - for { - <-ticker.C - app.Event.Emit("server-tick", time.Now().Format(time.RFC3339)) - log.Println("Emitted server-tick event") - } - }() - - if err := app.Run(); err != nil { - log.Fatal(err) - } -} diff --git a/v3/examples/services/assets/bindings/github.com/wailsapp/wails/v3/examples/services/hashes/index.js b/v3/examples/services/assets/bindings/github.com/wailsapp/wails/v3/examples/services/hashes/index.js deleted file mode 100644 index cb6c1ff84..000000000 --- a/v3/examples/services/assets/bindings/github.com/wailsapp/wails/v3/examples/services/hashes/index.js +++ /dev/null @@ -1,14 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as Service from "./service.js"; -export { - Service -}; - -import * as $models from "./models.js"; - -/** - * @typedef {$models.Hashes} Hashes - */ diff --git a/v3/examples/services/assets/bindings/github.com/wailsapp/wails/v3/examples/services/hashes/models.js b/v3/examples/services/assets/bindings/github.com/wailsapp/wails/v3/examples/services/hashes/models.js deleted file mode 100644 index a48737a6b..000000000 --- a/v3/examples/services/assets/bindings/github.com/wailsapp/wails/v3/examples/services/hashes/models.js +++ /dev/null @@ -1,14 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import {Create as $Create} from "/wails/runtime.js"; - -/** - * @typedef {Object} Hashes - * @property {string} md5 - * @property {string} sha1 - * @property {string} sha256 - */ diff --git a/v3/examples/services/assets/bindings/github.com/wailsapp/wails/v3/examples/services/hashes/service.js b/v3/examples/services/assets/bindings/github.com/wailsapp/wails/v3/examples/services/hashes/service.js deleted file mode 100644 index f5c01b306..000000000 --- a/v3/examples/services/assets/bindings/github.com/wailsapp/wails/v3/examples/services/hashes/service.js +++ /dev/null @@ -1,19 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import {Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create} from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * @param {string} s - * @returns {$CancellablePromise<$models.Hashes>} - */ -export function Generate(s) { - return $Call.ByID(1123907498, s); -} diff --git a/v3/examples/services/assets/bindings/github.com/wailsapp/wails/v3/pkg/services/kvstore/index.js b/v3/examples/services/assets/bindings/github.com/wailsapp/wails/v3/pkg/services/kvstore/index.js deleted file mode 100644 index d2bf43c94..000000000 --- a/v3/examples/services/assets/bindings/github.com/wailsapp/wails/v3/pkg/services/kvstore/index.js +++ /dev/null @@ -1,8 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as Service from "./service.js"; -export { - Service -}; diff --git a/v3/examples/services/assets/bindings/github.com/wailsapp/wails/v3/pkg/services/kvstore/keyvaluestore.js b/v3/examples/services/assets/bindings/github.com/wailsapp/wails/v3/pkg/services/kvstore/keyvaluestore.js deleted file mode 100644 index e69de29bb..000000000 diff --git a/v3/examples/services/assets/bindings/github.com/wailsapp/wails/v3/pkg/services/kvstore/service.js b/v3/examples/services/assets/bindings/github.com/wailsapp/wails/v3/pkg/services/kvstore/service.js deleted file mode 100644 index b4285097c..000000000 --- a/v3/examples/services/assets/bindings/github.com/wailsapp/wails/v3/pkg/services/kvstore/service.js +++ /dev/null @@ -1,69 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import {Call as $Call, Create as $Create} from "/wails/runtime.js"; - -/** - * Clear deletes all keys from the store. If AutoSave is true, the store is saved to disk. - * @returns {Promise & { cancel(): void }} - */ -export function Clear() { - let $resultPromise = /** @type {any} */($Call.ByID(816318109)); - return $resultPromise; -} - -/** - * Delete deletes the given key from the store. If AutoSave is true, the store is saved to disk. - * @param {string} key - * @returns {Promise & { cancel(): void }} - */ -export function Delete(key) { - let $resultPromise = /** @type {any} */($Call.ByID(2889946731, key)); - return $resultPromise; -} - -/** - * Get returns the value for the given key. If key is empty, the entire store is returned. - * @param {string} key - * @returns {Promise & { cancel(): void }} - */ -export function Get(key) { - let $resultPromise = /** @type {any} */($Call.ByID(376909388, key)); - return $resultPromise; -} - -/** - * Load loads the store from disk. - * If the store is in-memory, i.e. not associated with a file, Load has no effect. - * If the operation fails, a non-nil error is returned - * and the store's content and state at call time are preserved. - * @returns {Promise & { cancel(): void }} - */ -export function Load() { - let $resultPromise = /** @type {any} */($Call.ByID(1850778156)); - return $resultPromise; -} - -/** - * Save saves the store to disk. - * If the store is in-memory, i.e. not associated with a file, Save has no effect. - * @returns {Promise & { cancel(): void }} - */ -export function Save() { - let $resultPromise = /** @type {any} */($Call.ByID(3572737965)); - return $resultPromise; -} - -/** - * Set sets the value for the given key. If AutoSave is true, the store is saved to disk. - * @param {string} key - * @param {any} value - * @returns {Promise & { cancel(): void }} - */ -export function Set(key, value) { - let $resultPromise = /** @type {any} */($Call.ByID(2491766752, key, value)); - return $resultPromise; -} diff --git a/v3/examples/services/assets/bindings/github.com/wailsapp/wails/v3/pkg/services/log/index.js b/v3/examples/services/assets/bindings/github.com/wailsapp/wails/v3/pkg/services/log/index.js deleted file mode 100644 index 564a31eeb..000000000 --- a/v3/examples/services/assets/bindings/github.com/wailsapp/wails/v3/pkg/services/log/index.js +++ /dev/null @@ -1,12 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as Service from "./service.js"; -export { - Service -}; - -export { - Level -} from "./models.js"; diff --git a/v3/examples/services/assets/bindings/github.com/wailsapp/wails/v3/pkg/services/log/models.js b/v3/examples/services/assets/bindings/github.com/wailsapp/wails/v3/pkg/services/log/models.js deleted file mode 100644 index d8579b51a..000000000 --- a/v3/examples/services/assets/bindings/github.com/wailsapp/wails/v3/pkg/services/log/models.js +++ /dev/null @@ -1,26 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import {Create as $Create} from "/wails/runtime.js"; - -/** - * A Level is the importance or severity of a log event. - * The higher the level, the more important or severe the event. - * - * Values are arbitrary, but there are four predefined ones. - * @typedef {number} Level - */ - -/** - * Predefined constants for type Level. - * @namespace - */ -export const Level = { - Debug: -4, - Info: 0, - Warning: 4, - Error: 8, -}; diff --git a/v3/examples/services/assets/bindings/github.com/wailsapp/wails/v3/pkg/services/log/service.js b/v3/examples/services/assets/bindings/github.com/wailsapp/wails/v3/pkg/services/log/service.js deleted file mode 100644 index e5128d9bc..000000000 --- a/v3/examples/services/assets/bindings/github.com/wailsapp/wails/v3/pkg/services/log/service.js +++ /dev/null @@ -1,106 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import {Call as $Call, Create as $Create} from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * DebugContext logs at level [Debug]. - * @param {string} message - * @param {any[]} args - * @returns {Promise & { cancel(): void }} - */ -function DebugContext(message, ...args) { - let $resultPromise = /** @type {any} */($Call.ByID(1481024990, message, args)); - return $resultPromise; -} - -/** - * ErrorContext logs at level [Error]. - * @param {string} message - * @param {any[]} args - * @returns {Promise & { cancel(): void }} - */ -function ErrorContext(message, ...args) { - let $resultPromise = /** @type {any} */($Call.ByID(4028761057, message, args)); - return $resultPromise; -} - -/** - * InfoContext logs at level [Info]. - * @param {string} message - * @param {any[]} args - * @returns {Promise & { cancel(): void }} - */ -function InfoContext(message, ...args) { - let $resultPromise = /** @type {any} */($Call.ByID(1400061359, message, args)); - return $resultPromise; -} - -/** - * Log emits a log record with the current time and the given level and message. - * The Record's attributes consist of the Logger's attributes followed by - * the attributes specified by args. - * - * The attribute arguments are processed as follows: - * - If an argument is a string and this is not the last argument, - * the following argument is treated as the value and the two are combined - * into an attribute. - * - Otherwise, the argument is treated as a value with key "!BADKEY". - * - * Log feeds the binding call context into the configured logger, - * so custom handlers may access context values, e.g. the current window. - * @param {$models.Level} level - * @param {string} message - * @param {any[]} args - * @returns {Promise & { cancel(): void }} - */ -export function Log(level, message, ...args) { - let $resultPromise = /** @type {any} */($Call.ByID(4156699346, level, message, args)); - return $resultPromise; -} - -/** - * LogLevel returns the currently configured log level, - * that is either the one configured initially - * or the last value passed to [Service.SetLogLevel]. - * @returns {Promise<$models.Level> & { cancel(): void }} - */ -export function LogLevel() { - let $resultPromise = /** @type {any} */($Call.ByID(4058368160)); - return $resultPromise; -} - -/** - * SetLogLevel changes the current log level. - * @param {$models.Level} level - * @returns {Promise & { cancel(): void }} - */ -export function SetLogLevel(level) { - let $resultPromise = /** @type {any} */($Call.ByID(3988219088, level)); - return $resultPromise; -} - -/** - * WarningContext logs at level [Warn]. - * @param {string} message - * @param {any[]} args - * @returns {Promise & { cancel(): void }} - */ -function WarningContext(message, ...args) { - let $resultPromise = /** @type {any} */($Call.ByID(52282975, message, args)); - return $resultPromise; -} - -export { - DebugContext as Debug, - InfoContext as Info, - WarningContext as Warning, - ErrorContext as Error, -}; diff --git a/v3/examples/services/assets/bindings/github.com/wailsapp/wails/v3/pkg/services/sqlite/index.js b/v3/examples/services/assets/bindings/github.com/wailsapp/wails/v3/pkg/services/sqlite/index.js deleted file mode 100644 index 0918a51f0..000000000 --- a/v3/examples/services/assets/bindings/github.com/wailsapp/wails/v3/pkg/services/sqlite/index.js +++ /dev/null @@ -1,22 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as Service from "./service.js"; -export { - Service -}; - -import * as $models from "./models.js"; - -/** - * Row holds a single row in the result of a query. - * It is a key-value map where keys are column names. - * @typedef {$models.Row} Row - */ - -/** - * Rows holds the result of a query - * as an array of key-value maps where keys are column names. - * @typedef {$models.Rows} Rows - */ diff --git a/v3/examples/services/assets/bindings/github.com/wailsapp/wails/v3/pkg/services/sqlite/models.js b/v3/examples/services/assets/bindings/github.com/wailsapp/wails/v3/pkg/services/sqlite/models.js deleted file mode 100644 index 041151c86..000000000 --- a/v3/examples/services/assets/bindings/github.com/wailsapp/wails/v3/pkg/services/sqlite/models.js +++ /dev/null @@ -1,25 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import {Create as $Create} from "/wails/runtime.js"; - -/** - * Row holds a single row in the result of a query. - * It is a key-value map where keys are column names. - * @typedef {{ [_: string]: any }} Row - */ - -/** - * Rows holds the result of a query - * as an array of key-value maps where keys are column names. - * @typedef {Row[]} Rows - */ - -/** - * Stmt wraps a prepared sql statement pointer. - * It provides the same methods as the [sql.Stmt] type. - * @typedef {string} Stmt - */ diff --git a/v3/examples/services/assets/bindings/github.com/wailsapp/wails/v3/pkg/services/sqlite/service.js b/v3/examples/services/assets/bindings/github.com/wailsapp/wails/v3/pkg/services/sqlite/service.js deleted file mode 100644 index 9330c1e4d..000000000 --- a/v3/examples/services/assets/bindings/github.com/wailsapp/wails/v3/pkg/services/sqlite/service.js +++ /dev/null @@ -1,167 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import {Call as $Call, Create as $Create} from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * Close closes the current database connection if one is open, otherwise has no effect. - * Additionally, Close closes all open prepared statements associated to the connection. - * - * Even when a non-nil error is returned, - * the database service is left in a consistent state, - * ready for a call to [Service.Open]. - * @returns {Promise & { cancel(): void }} - */ -export function Close() { - let $resultPromise = /** @type {any} */($Call.ByID(1888105376)); - return $resultPromise; -} - -/** - * ClosePrepared closes a prepared statement - * obtained with [Service.Prepare] or [Service.PrepareContext]. - * ClosePrepared is idempotent: - * it has no effect on prepared statements that are already closed. - * @param {$models.Stmt | null} stmt - * @returns {Promise & { cancel(): void }} - */ -function ClosePrepared(stmt) { - let $resultPromise = /** @type {any} */($Call.ByID(2526200629, stmt)); - return $resultPromise; -} - -/** - * ExecContext executes a query without returning any rows. - * It supports early cancellation. - * @param {string} query - * @param {any[]} args - * @returns {Promise & { cancel(): void }} - */ -function ExecContext(query, ...args) { - let $resultPromise = /** @type {any} */($Call.ByID(674944556, query, args)); - return $resultPromise; -} - -/** - * ExecPrepared executes a prepared statement - * obtained with [Service.Prepare] or [Service.PrepareContext] - * without returning any rows. - * It supports early cancellation. - * @param {$models.Stmt | null} stmt - * @param {any[]} args - * @returns {Promise & { cancel(): void }} - */ -function ExecPrepared(stmt, ...args) { - let $resultPromise = /** @type {any} */($Call.ByID(2086877656, stmt, args)); - return $resultPromise; -} - -/** - * Open validates the current configuration, - * closes the current connection if one is present, - * then opens and validates a new connection. - * - * Even when a non-nil error is returned, - * the database service is left in a consistent state, - * ready for a new call to Open. - * @returns {Promise & { cancel(): void }} - */ -export function Open() { - let $resultPromise = /** @type {any} */($Call.ByID(2012175612)); - return $resultPromise; -} - -/** - * PrepareContext creates a prepared statement for later queries or executions. - * Multiple queries or executions may be run concurrently from the returned statement. - * - * The caller must call the statement's Close method when it is no longer needed. - * Statements are closed automatically - * when the connection they are associated with is closed. - * - * PrepareContext supports early cancellation. - * @param {string} query - * @returns {Promise<$models.Stmt | null> & { cancel(): void }} - */ -function PrepareContext(query) { - let $resultPromise = /** @type {any} */($Call.ByID(570941694, query)); - return $resultPromise; -} - -/** - * QueryContext executes a query and returns a slice of key-value records, - * one per row, with column names as keys. - * It supports early cancellation, returning the slice of results fetched so far. - * @param {string} query - * @param {any[]} args - * @returns {Promise<$models.Rows> & { cancel(): void }} - */ -function QueryContext(query, ...args) { - let $resultPromise = /** @type {any} */($Call.ByID(4115542347, query, args)); - let $typingPromise = /** @type {any} */($resultPromise.then(($result) => { - return $$createType1($result); - })); - $typingPromise.cancel = $resultPromise.cancel.bind($resultPromise); - return $typingPromise; -} - -/** - * QueryPrepared executes a prepared statement - * obtained with [Service.Prepare] or [Service.PrepareContext] - * and returns a slice of key-value records, one per row, with column names as keys. - * It supports early cancellation, returning the slice of results fetched so far. - * @param {$models.Stmt | null} stmt - * @param {any[]} args - * @returns {Promise<$models.Rows> & { cancel(): void }} - */ -function QueryPrepared(stmt, ...args) { - let $resultPromise = /** @type {any} */($Call.ByID(3885083725, stmt, args)); - let $typingPromise = /** @type {any} */($resultPromise.then(($result) => { - return $$createType1($result); - })); - $typingPromise.cancel = $resultPromise.cancel.bind($resultPromise); - return $typingPromise; -} - -// Private type creation functions -const $$createType0 = $Create.Map($Create.Any, $Create.Any); -const $$createType1 = $Create.Array($$createType0); - -export { - ExecContext as Execute, - QueryContext as Query -}; - -import { Stmt } from "./stmt.js"; - -/** - * Prepare creates a prepared statement for later queries or executions. - * Multiple queries or executions may be run concurrently from the returned statement. - * - * The caller must call the statement's Close method when it is no longer needed. - * Statements are closed automatically - * when the connection they are associated with is closed. - * - * Prepare supports early cancellation. - * - * @param {string} query - * @returns {Promise & { cancel(): void }} - */ -export function Prepare(query) { - const promise = PrepareContext(query); - const wrapper = /** @type {any} */(promise.then(function (id) { - return id == null ? null : new Stmt( - ClosePrepared.bind(null, id), - ExecPrepared.bind(null, id), - QueryPrepared.bind(null, id)); - })); - wrapper.cancel = promise.cancel; - return wrapper; -} diff --git a/v3/examples/services/assets/bindings/github.com/wailsapp/wails/v3/pkg/services/sqlite/stmt.js b/v3/examples/services/assets/bindings/github.com/wailsapp/wails/v3/pkg/services/sqlite/stmt.js deleted file mode 100644 index 948b0c3dd..000000000 --- a/v3/examples/services/assets/bindings/github.com/wailsapp/wails/v3/pkg/services/sqlite/stmt.js +++ /dev/null @@ -1,79 +0,0 @@ -//@ts-check - -//@ts-ignore: Unused imports -import * as $models from "./models.js"; - -const execSymbol = Symbol("exec"), - querySymbol = Symbol("query"), - closeSymbol = Symbol("close"); - -/** - * Stmt represents a prepared statement for later queries or executions. - * Multiple queries or executions may be run concurrently on the same statement. - * - * The caller must call the statement's Close method when it is no longer needed. - * Statements are closed automatically - * when the connection they are associated with is closed. - */ -export class Stmt { - /** - * Constructs a new prepared statement instance. - * @param {(...args: any[]) => Promise} close - * @param {(...args: any[]) => Promise & { cancel(): void }} exec - * @param {(...args: any[]) => Promise<$models.Rows> & { cancel(): void }} query - */ - constructor(close, exec, query) { - /** - * @member - * @private - * @type {typeof close} - */ - this[closeSymbol] = close; - - /** - * @member - * @private - * @type {typeof exec} - */ - this[execSymbol] = exec; - - /** - * @member - * @private - * @type {typeof query} - */ - this[querySymbol] = query; - } - - /** - * Closes the prepared statement. - * It has no effect when the statement is already closed. - * @returns {Promise} - */ - Close() { - return this[closeSymbol](); - } - - /** - * Executes the prepared statement without returning any rows. - * It supports early cancellation. - * - * @param {any[]} args - * @returns {Promise & { cancel(): void }} - */ - Exec(...args) { - return this[execSymbol](...args); - } - - /** - * Executes the prepared statement - * and returns a slice of key-value records, one per row, with column names as keys. - * It supports early cancellation, returning the array of results fetched so far. - * - * @param {any[]} args - * @returns {Promise<$models.Rows> & { cancel(): void }} - */ - Query(...args) { - return this[querySymbol](...args); - } -} diff --git a/v3/examples/services/assets/index.html b/v3/examples/services/assets/index.html deleted file mode 100644 index c44a0679a..000000000 --- a/v3/examples/services/assets/index.html +++ /dev/null @@ -1,287 +0,0 @@ - - - - - Wails Alpha - - - - - - -

            Services

            -
            -
            - - - - -
            -
            -

            The sqlite service provides easy integration with sqlite dbs.

            -

            The demo DB has a single table: Users.

            -

            Enter a query below and hit the "Run" button.

            -
            -
            -
            - -
            -
            -
            -
            -
            -
            -

            The hashes service provides hashing functions.

            -
            -
            -
            - -
            -
            -
            -
            -
            -
            -

            The kvstore service provides a means for reading and writing to a json file.

            -

            Enter a key/value pair in the form below to add it to the file.

            -

            A blank value will remove the key.

            -
            -
            - - - -
            -
            -
            -
            -
            -
            -

            The log plugin provides a means for sending frontend logs to a Go logger.

            -

            Enter some text below, press submit and check your console logs.

            -
            - - - -
            -
            -
            - - diff --git a/v3/examples/services/assets/style.css b/v3/examples/services/assets/style.css deleted file mode 100644 index f128a1aa1..000000000 --- a/v3/examples/services/assets/style.css +++ /dev/null @@ -1,213 +0,0 @@ -html { - background-color: rgba(33, 37, 43); - text-align: center; - color: white; - user-select: none; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - -webkit-touch-callout: none; - height: 100vh; - width: 100%; -} - -body { - padding-top: 40px; - margin: 0; - font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", - "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", - sans-serif; - overscroll-behavior: none; - overflow-y: hidden; - background-image: url("/files/images/eryri1.png"); - background-color: rgba(33, 37, 43, 0.85); - background-blend-mode: overlay; - background-size: cover; - background-position: center; - background-repeat: no-repeat; - height: 100vh; - width: 100%; -} - -.logo { - width: 30%; - height: 20%; -} -/* CSS */ -.button-42 { - background-color: initial; - background-image: linear-gradient(-180deg, #555555, #2f2f2f); - border-radius: 6px; - box-shadow: rgba(0, 0, 0, 0.1) 0 2px 4px; - color: #FFFFFF; - cursor: pointer; - display: inline-block; - font-family: Inter,-apple-system,system-ui,Roboto,"Helvetica Neue",Arial,sans-serif; - height: 35px; - line-height: 35px; - outline: 0; - overflow: hidden; - padding: 0 20px; - pointer-events: auto; - position: relative; - text-align: center; - touch-action: manipulation; - user-select: none; - -webkit-user-select: none; - vertical-align: top; - white-space: nowrap; - z-index: 9; - border: 0; - transition: box-shadow .2s; - font-size: medium; -} -p { - font-size: 1rem; -} - -.button-42:hover { - background-image: linear-gradient(-180deg, #cb3939, #610000); -} -html { - background-color: rgba(33, 37, 43); - text-align: center; - color: white; - user-select: none; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - -webkit-touch-callout: none; -} - -body { - padding-top: 40px; - margin: 0; - font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", - "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", - sans-serif; - overscroll-behavior: none; -} - -.button-42 { - background-color: initial; - background-image: linear-gradient(-180deg, #555555, #2f2f2f); - border-radius: 6px; - box-shadow: rgba(0, 0, 0, 0.1) 0 2px 4px; - color: #FFFFFF; - cursor: pointer; - display: inline-block; - font-family: Inter,-apple-system,system-ui,Roboto,"Helvetica Neue",Arial,sans-serif; - height: 35px; - line-height: 35px; - outline: 0; - overflow: hidden; - padding: 0 20px; - pointer-events: auto; - position: relative; - text-align: center; - touch-action: manipulation; - user-select: none; - -webkit-user-select: none; - vertical-align: top; - white-space: nowrap; - z-index: 9; - border: 0; - transition: box-shadow .2s; - font-size: medium; -} - -p { - font-size: 1rem; -} - -.button-42:hover { - background-image: linear-gradient(-180deg, #cb3939, #610000); -} - -.tab { - overflow: hidden; - background-color: #f1f1f100; - margin-left: 20px; -} - -.tab button { - background-color: transparent; /* Make the background transparent */ - color: white; /* Make the text white */ - float: left; - border: none; - outline: none; - cursor: pointer; - padding: 14px 16px; - transition: 0.3s; - position: relative; /* Added for the underline */ -} - -.tab button::after { /* Added for the underline */ - content: ''; - position: absolute; - width: 0; - height: 2px; - bottom: 0; - left: 0; - background-color: #a40505; - visibility: hidden; - transition: all 0.3s ease-in-out; -} - -.tab button:hover::after, /* Added for the underline */ -.tab button.active::after { /* Added for the underline */ - width: 100%; - visibility: visible; -} - -.tab button.active { - background-color: transparent; /* Make the background transparent */ - color: red; -} -.tabcontent { - display: none; - padding: 6px 12px; - border-top: none; -} -#sqlresults, #hashresults { - font-family: 'Courier New', Courier, monospace; - min-height: 100px; -} -#selectquery { - width: 90%; -} -table { - width: 100%; - border-collapse: collapse; - margin-top: 20px; -} - -th, td { - border: 1px solid #ddd; - padding: 8px; - text-align: left; -} - -th { - background-color: #005467; - color: white; -} - -tr:hover { - background-color: #888; -} - -.error-message { - color: #FF4B2B; /* Bright red color for better visibility in dark mode */ - background-color: #1E1E1E; /* Dark background for the error message */ - border: 1px solid #FF4B2B; /* Border color same as text color */ - padding: 10px; /* Padding around the text */ - margin: 10px 0; /* Margin top and bottom */ - border-radius: 5px; /* Rounded corners */ - text-align: center; /* Center the text */ -} - -.narrowColumn { - width: 1%; /* Adjust as needed */ - white-space: nowrap; -} \ No newline at end of file diff --git a/v3/examples/services/files/images/eryri1.png b/v3/examples/services/files/images/eryri1.png deleted file mode 100644 index 224d3b4ac..000000000 Binary files a/v3/examples/services/files/images/eryri1.png and /dev/null differ diff --git a/v3/examples/services/hashes/hashes.go b/v3/examples/services/hashes/hashes.go deleted file mode 100644 index 1e4653dbd..000000000 --- a/v3/examples/services/hashes/hashes.go +++ /dev/null @@ -1,45 +0,0 @@ -package hashes - -import ( - "context" - "crypto/md5" - "crypto/sha1" - "crypto/sha256" - "encoding/hex" - - "github.com/wailsapp/wails/v3/pkg/application" -) - -type Hashes = struct { - MD5 string `json:"md5"` - SHA1 string `json:"sha1"` - SHA256 string `json:"sha256"` -} - -type Service struct{} - -func (h *Service) Generate(s string) Hashes { - md5Hash := md5.Sum([]byte(s)) - sha1Hash := sha1.Sum([]byte(s)) - sha256Hash := sha256.Sum256([]byte(s)) - - return Hashes{ - MD5: hex.EncodeToString(md5Hash[:]), - SHA1: hex.EncodeToString(sha1Hash[:]), - SHA256: hex.EncodeToString(sha256Hash[:]), - } -} - -func New() *Service { - return &Service{} -} - -func (h *Service) ServiceName() string { - return "Hashes Service" -} - -func (h *Service) ServiceStartup(context.Context, application.ServiceOptions) error { - return nil -} - -func (h *Service) ServiceShutdown() error { return nil } diff --git a/v3/examples/services/main.go b/v3/examples/services/main.go deleted file mode 100644 index c753a79c7..000000000 --- a/v3/examples/services/main.go +++ /dev/null @@ -1,69 +0,0 @@ -package main - -import ( - "embed" - "log/slog" - "os" - "path/filepath" - "runtime" - - "github.com/wailsapp/wails/v3/examples/services/hashes" - "github.com/wailsapp/wails/v3/pkg/application" - "github.com/wailsapp/wails/v3/pkg/services/fileserver" - "github.com/wailsapp/wails/v3/pkg/services/kvstore" - "github.com/wailsapp/wails/v3/pkg/services/log" - "github.com/wailsapp/wails/v3/pkg/services/sqlite" -) - -//go:embed assets/* -var assets embed.FS - -func main() { - - // Get the local directory of this source file - // This isn't needed when running the example with `go run .` - // but is needed when running the example from an IDE - _, thisFile, _, _ := runtime.Caller(0) - localDir := filepath.Dir(thisFile) - - rootPath := filepath.Join(localDir, "files") - app := application.New(application.Options{ - Name: "Services Demo", - Description: "A demo of the services API", - Mac: application.MacOptions{ - ApplicationShouldTerminateAfterLastWindowClosed: true, - }, - LogLevel: slog.LevelDebug, - Services: []application.Service{ - application.NewService(hashes.New()), - application.NewService(sqlite.NewWithConfig(&sqlite.Config{ - DBSource: "test.db", - })), - application.NewService(kvstore.NewWithConfig(&kvstore.Config{ - Filename: "store.json", - AutoSave: true, - })), - application.NewService(log.New()), - application.NewServiceWithOptions(fileserver.NewWithConfig(&fileserver.Config{ - RootPath: rootPath, - }), application.ServiceOptions{ - Route: "/files", - }), - }, - Assets: application.AssetOptions{ - Handler: application.BundledAssetFileServer(assets), - }, - }) - - app.Window.NewWithOptions(application.WebviewWindowOptions{ - Width: 1024, - Height: 768, - }) - - err := app.Run() - - if err != nil { - println(err.Error()) - os.Exit(1) - } -} diff --git a/v3/examples/services/store.json b/v3/examples/services/store.json deleted file mode 100644 index a56bb9842..000000000 --- a/v3/examples/services/store.json +++ /dev/null @@ -1 +0,0 @@ -{"q":"www","url2":"https://reddit.com"} \ No newline at end of file diff --git a/v3/examples/services/test.db b/v3/examples/services/test.db deleted file mode 100644 index ced6a916c..000000000 Binary files a/v3/examples/services/test.db and /dev/null differ diff --git a/v3/examples/show-macos-toolbar/README.md b/v3/examples/show-macos-toolbar/README.md deleted file mode 100644 index 21bbeac96..000000000 --- a/v3/examples/show-macos-toolbar/README.md +++ /dev/null @@ -1,20 +0,0 @@ -# Show macOS Toolbar Example - -This example is a demonstration of the macOS option `ShowToolbarWhenFullscreen`, which keeps -the system toolbar visible when in fullscreen mode. - -## Running the example - -To run the example (on macOS), simply run the following command: - -```bash -go run . -``` - -# Status - -| Platform | Status | -|----------|---------| -| Mac | Working | -| Windows | N/A | -| Linux | N/A | diff --git a/v3/examples/show-macos-toolbar/main.go b/v3/examples/show-macos-toolbar/main.go deleted file mode 100644 index 648432da6..000000000 --- a/v3/examples/show-macos-toolbar/main.go +++ /dev/null @@ -1,51 +0,0 @@ -package main - -import ( - _ "embed" - "log" - - "github.com/wailsapp/wails/v3/pkg/application" -) - -func main() { - app := application.New(application.Options{ - Name: "Show macOS Toolbar", - Description: "A demo of the ShowToolbarWhenFullscreen option", - Mac: application.MacOptions{ - ApplicationShouldTerminateAfterLastWindowClosed: true, - }, - }) - - // Create window - app.Window.NewWithOptions(application.WebviewWindowOptions{ - Title: "Toolbar hidden (default behaviour)", - HTML: "

            Switch this window to fullscreen: the toolbar will be hidden

            ", - CSS: `body { background-color: blue; color: white; height: 100vh; display: flex; justify-content: center; align-items: center; }`, - Mac: application.MacWindow{ - TitleBar: application.MacTitleBar{ - UseToolbar: true, - HideToolbarSeparator: true, - }, - }, - }) - - // Create window - app.Window.NewWithOptions(application.WebviewWindowOptions{ - Title: "Toolbar visible", - HTML: "

            Switch this window to fullscreen: the toolbar will stay visible

            ", - CSS: `body { background-color: red; color: white; height: 100vh; display: flex; justify-content: center; align-items: center; }`, - Mac: application.MacWindow{ - TitleBar: application.MacTitleBar{ - UseToolbar: true, - HideToolbarSeparator: true, - ShowToolbarWhenFullscreen: true, - }, - }, - }) - - err := app.Run() - - if err != nil { - log.Fatal(err) - } -} diff --git a/v3/examples/single-instance/README.md b/v3/examples/single-instance/README.md deleted file mode 100644 index 5982cb909..000000000 --- a/v3/examples/single-instance/README.md +++ /dev/null @@ -1,62 +0,0 @@ -# Single Instance Example - -This example demonstrates the single instance functionality in Wails v3. It shows how to: - -1. Ensure only one instance of your application can run at a time -2. Notify the first instance when a second instance is launched -3. Pass data between instances -4. Handle command line arguments and working directory information from second instances - -## Running the Example - -1. Build and run the application: - ```bash - go build - ./single-instance - ``` - -2. Try launching a second instance of the application. You'll notice: - - The second instance will exit immediately - - The first instance will receive and display: - - Command line arguments from the second instance - - Working directory of the second instance - - Additional data passed from the second instance - -3. Check the application logs to see the information received from second instances. - -## Features Demonstrated - -- Setting up single instance lock with a unique identifier -- Handling second instance launches through callbacks -- Passing custom data between instances -- Displaying instance information in a web UI -- Cross-platform support (Windows, macOS, Linux) - -## Code Overview - -The example consists of: - -- `main.go`: The main application code demonstrating single instance setup -- A simple web UI showing current instance information -- Callback handling for second instance launches - -## Implementation Details - -The application uses the Wails v3 single instance feature: - -```go -app := application.New(&application.Options{ - SingleInstance: &application.SingleInstanceOptions{ - UniqueID: "com.wails.example.single-instance", - OnSecondInstance: func(data application.SecondInstanceData) { - // Handle second instance launch - }, - AdditionalData: map[string]string{ - }, - }, -}) -``` - -The implementation uses platform-specific mechanisms: -- Windows: Named mutex and window messages -- Unix (Linux/macOS): File locking with flock and signals diff --git a/v3/examples/single-instance/assets/index.html b/v3/examples/single-instance/assets/index.html deleted file mode 100644 index 330b062ec..000000000 --- a/v3/examples/single-instance/assets/index.html +++ /dev/null @@ -1,141 +0,0 @@ - - - - - - Single Instance Demo - - - - -
            -

            Single Instance Demo

            - -
            -

            Current Instance Information

            -
            Loading...
            -
            - -
            -

            Instructions

            -

            Try launching another instance of this application. The first instance will:

            -
              -
            • Receive notification of the second instance launch
            • -
            • Get the command line arguments of the second instance
            • -
            • Get the working directory of the second instance
            • -
            • Receive any additional data passed from the second instance
            • -
            -

            Check the application logs to see the information received from second instances.

            -
            -
            - - - - \ No newline at end of file diff --git a/v3/examples/single-instance/main.go b/v3/examples/single-instance/main.go deleted file mode 100644 index 51ca48a38..000000000 --- a/v3/examples/single-instance/main.go +++ /dev/null @@ -1,82 +0,0 @@ -package main - -import ( - "embed" - "log" - "log/slog" - "os" - "time" - - "github.com/wailsapp/wails/v3/pkg/application" -) - -//go:embed assets/index.html -var assets embed.FS - -type App struct{} - -func (a *App) GetCurrentInstanceInfo() map[string]interface{} { - return map[string]interface{}{ - "args": os.Args, - "workingDir": getCurrentWorkingDir(), - } -} - -var encryptionKey = [32]byte{ - 0x1e, 0x1f, 0x1c, 0x1d, 0x1a, 0x1b, 0x18, 0x19, - 0x16, 0x17, 0x14, 0x15, 0x12, 0x13, 0x10, 0x11, - 0x0e, 0x0f, 0x0c, 0x0d, 0x0a, 0x0b, 0x08, 0x09, - 0x06, 0x07, 0x04, 0x05, 0x02, 0x03, 0x00, 0x01, -} - -func main() { - - var window *application.WebviewWindow - app := application.New(application.Options{ - Name: "Single Instance Example", - LogLevel: slog.LevelDebug, - Description: "An example of single instance functionality in Wails v3", - Services: []application.Service{ - application.NewService(&App{}), - }, - SingleInstance: &application.SingleInstanceOptions{ - UniqueID: "com.wails.example.single-instance", - EncryptionKey: encryptionKey, - OnSecondInstanceLaunch: func(data application.SecondInstanceData) { - if window != nil { - window.EmitEvent("secondInstanceLaunched", data) - window.Restore() - window.Focus() - } - log.Printf("Second instance launched with args: %v\n", data.Args) - log.Printf("Working directory: %s\n", data.WorkingDir) - if data.AdditionalData != nil { - log.Printf("Additional data: %v\n", data.AdditionalData) - } - }, - AdditionalData: map[string]string{ - "launchtime": time.Now().Local().String(), - }, - }, - Assets: application.AssetOptions{ - Handler: application.BundledAssetFileServer(assets), - }, - }) - - window = app.Window.NewWithOptions(application.WebviewWindowOptions{ - Title: "Single Instance Demo", - Width: 800, - Height: 700, - URL: "/", - }) - - app.Run() -} - -func getCurrentWorkingDir() string { - dir, err := os.Getwd() - if err != nil { - return "" - } - return dir -} diff --git a/v3/examples/spotlight/README.md b/v3/examples/spotlight/README.md deleted file mode 100644 index bda8f464e..000000000 --- a/v3/examples/spotlight/README.md +++ /dev/null @@ -1,66 +0,0 @@ -# Spotlight Example - -This example demonstrates how to create a Spotlight-like launcher window using the `CollectionBehavior` option on macOS. - -## Features - -- **Appears on all Spaces**: Using `MacWindowCollectionBehaviorCanJoinAllSpaces`, the window is visible across all virtual desktops -- **Overlays fullscreen apps**: Using `MacWindowCollectionBehaviorFullScreenAuxiliary`, the window can appear over fullscreen applications -- **Combined behaviors**: Demonstrates combining multiple behaviors with bitwise OR -- **Floating window**: `MacWindowLevelFloating` keeps the window above other windows -- **Accessory app**: Doesn't appear in the Dock (uses `ActivationPolicyAccessory`) -- **Frameless design**: Clean, borderless appearance with translucent backdrop - -## Running the example - -```bash -go run . -``` - -**Note**: This example is macOS-specific due to the use of `CollectionBehavior`. - -## Combining CollectionBehaviors - -Behaviors can be combined using bitwise OR (`|`): - -```go -CollectionBehavior: application.MacWindowCollectionBehaviorCanJoinAllSpaces | - application.MacWindowCollectionBehaviorFullScreenAuxiliary, -``` - -## CollectionBehavior Options - -These are bitmask values that can be combined: - -**Space behavior:** -| Option | Description | -|--------|-------------| -| `MacWindowCollectionBehaviorDefault` | Uses FullScreenPrimary (default) | -| `MacWindowCollectionBehaviorCanJoinAllSpaces` | Window appears on all Spaces | -| `MacWindowCollectionBehaviorMoveToActiveSpace` | Moves to active Space when shown | -| `MacWindowCollectionBehaviorManaged` | Default managed window behavior | -| `MacWindowCollectionBehaviorTransient` | Temporary/transient window | -| `MacWindowCollectionBehaviorStationary` | Stays stationary during Space switches | - -**Fullscreen behavior:** -| Option | Description | -|--------|-------------| -| `MacWindowCollectionBehaviorFullScreenPrimary` | Can enter fullscreen mode | -| `MacWindowCollectionBehaviorFullScreenAuxiliary` | Can overlay fullscreen apps | -| `MacWindowCollectionBehaviorFullScreenNone` | Disables fullscreen | -| `MacWindowCollectionBehaviorFullScreenAllowsTiling` | Allows side-by-side tiling | - -## Use Cases - -- **Launcher apps** (like Spotlight, Alfred, Raycast) -- **Quick capture tools** (notes, screenshots) -- **System utilities** that need to be accessible anywhere -- **Overlay widgets** that should appear over fullscreen apps - -## Status - -| Platform | Status | -|----------|--------| -| Mac | Working | -| Windows | N/A (macOS-specific feature) | -| Linux | N/A (macOS-specific feature) | diff --git a/v3/examples/spotlight/main.go b/v3/examples/spotlight/main.go deleted file mode 100644 index d961f1f54..000000000 --- a/v3/examples/spotlight/main.go +++ /dev/null @@ -1,142 +0,0 @@ -package main - -import ( - "log" - "net/http" - - "github.com/wailsapp/wails/v3/pkg/application" -) - -// This example demonstrates how to create a Spotlight-like launcher window -// that appears on all macOS Spaces and can overlay fullscreen applications. -// -// Key features: -// - Window appears on all Spaces (virtual desktops) -// - Can overlay fullscreen applications -// - Floating window level keeps it above other windows -// - Accessory activation policy hides from Dock -// - Frameless design with translucent backdrop - -func main() { - app := application.New(application.Options{ - Name: "Spotlight Example", - Description: "A Spotlight-like launcher demonstrating CollectionBehavior", - Mac: application.MacOptions{ - // Accessory apps don't appear in the Dock - ActivationPolicy: application.ActivationPolicyAccessory, - ApplicationShouldTerminateAfterLastWindowClosed: true, - }, - Assets: application.AssetOptions{ - Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - w.WriteHeader(http.StatusOK) - w.Write([]byte(spotlightHTML)) - }), - }, - }) - - // Create a Spotlight-like window - app.Window.NewWithOptions(application.WebviewWindowOptions{ - Title: "Spotlight", - Width: 680, - Height: 80, - Frameless: true, - // Center the window - InitialPosition: application.WindowCentered, - // Prevent resizing - DisableResize: true, - Mac: application.MacWindow{ - // Combine multiple behaviors using bitwise OR: - // - CanJoinAllSpaces: window appears on ALL Spaces (virtual desktops) - // - FullScreenAuxiliary: window can overlay fullscreen applications - CollectionBehavior: application.MacWindowCollectionBehaviorCanJoinAllSpaces | - application.MacWindowCollectionBehaviorFullScreenAuxiliary, - // Float above other windows - WindowLevel: application.MacWindowLevelFloating, - // Translucent vibrancy effect - Backdrop: application.MacBackdropTranslucent, - // Hidden title bar for clean look - TitleBar: application.MacTitleBar{ - AppearsTransparent: true, - Hide: true, - }, - }, - URL: "/", - }) - - err := app.Run() - if err != nil { - log.Fatal(err) - } -} - -const spotlightHTML = ` - - - Spotlight - - - - -
            - - - - - -
            - -` diff --git a/v3/examples/systray-basic/README.md b/v3/examples/systray-basic/README.md deleted file mode 100644 index 11b84a0bf..000000000 --- a/v3/examples/systray-basic/README.md +++ /dev/null @@ -1,16 +0,0 @@ -# Systray Basic Example - -This example creates a simple system tray with an attached window. -The window is hidden by default and toggled by left-clicking on the systray icon. -The window will hide automatically when it loses focus. - -On Windows, if the icon is in the notification flyout, -then the window will be shown in the bottom right corner. - -# Status - -| Platform | Status | -|----------|---------| -| Mac | Working | -| Windows | Working | -| Linux | | diff --git a/v3/examples/systray-basic/main.go b/v3/examples/systray-basic/main.go deleted file mode 100644 index 0c1dbf7a2..000000000 --- a/v3/examples/systray-basic/main.go +++ /dev/null @@ -1,60 +0,0 @@ -package main - -import ( - _ "embed" - "log" - "runtime" - - "github.com/wailsapp/wails/v3/pkg/application" - "github.com/wailsapp/wails/v3/pkg/events" - "github.com/wailsapp/wails/v3/pkg/icons" -) - -func main() { - app := application.New(application.Options{ - Name: "Systray Demo", - Description: "A demo of the Systray API", - Assets: application.AlphaAssets, - Mac: application.MacOptions{ - ActivationPolicy: application.ActivationPolicyAccessory, - }, - }) - - systemTray := app.SystemTray.New() - - window := app.Window.NewWithOptions(application.WebviewWindowOptions{ - Width: 500, - Height: 500, - Name: "Systray Demo Window", - Frameless: true, - AlwaysOnTop: true, - Hidden: true, - DisableResize: true, - HideOnEscape: true, - HideOnFocusLost: true, - Windows: application.WindowsWindow{ - HiddenOnTaskbar: true, - }, - KeyBindings: map[string]func(window application.Window){ - "F12": func(window application.Window) { - systemTray.OpenMenu() - }, - }, - }) - - window.RegisterHook(events.Common.WindowClosing, func(e *application.WindowEvent) { - window.Hide() - e.Cancel() - }) - - if runtime.GOOS == "darwin" { - systemTray.SetTemplateIcon(icons.SystrayMacTemplate) - } - - systemTray.AttachWindow(window).WindowOffset(5) - - err := app.Run() - if err != nil { - log.Fatal(err) - } -} diff --git a/v3/examples/systray-clock/main.go b/v3/examples/systray-clock/main.go deleted file mode 100644 index c00d6093d..000000000 --- a/v3/examples/systray-clock/main.go +++ /dev/null @@ -1,59 +0,0 @@ -package main - -import ( - "log" - "runtime" - "time" - - "github.com/wailsapp/wails/v3/pkg/application" - "github.com/wailsapp/wails/v3/pkg/icons" -) - -func main() { - app := application.New(application.Options{ - Name: "Systray Clock", - Description: "System tray clock with live tooltip updates", - Assets: application.AlphaAssets, - Mac: application.MacOptions{ - ActivationPolicy: application.ActivationPolicyAccessory, - }, - Windows: application.WindowsOptions{ - DisableQuitOnLastWindowClosed: true, - }, - }) - - systemTray := app.SystemTray.New() - - // Use the template icon on macOS so the clock respects light/dark modes. - if runtime.GOOS == "darwin" { - systemTray.SetTemplateIcon(icons.SystrayMacTemplate) - } - - menu := app.NewMenu() - menu.Add("Quit").OnClick(func(ctx *application.Context) { - app.Quit() - }) - systemTray.SetMenu(menu) - - updateTooltip := func() { - systemTray.SetTooltip(time.Now().Format("15:04:05")) - } - updateTooltip() - - go func() { - ticker := time.NewTicker(time.Second) - defer ticker.Stop() - for { - select { - case <-ticker.C: - updateTooltip() - case <-app.Context().Done(): - return - } - } - }() - - if err := app.Run(); err != nil { - log.Fatal(err) - } -} diff --git a/v3/examples/systray-custom/README.md b/v3/examples/systray-custom/README.md deleted file mode 100644 index 598d84496..000000000 --- a/v3/examples/systray-custom/README.md +++ /dev/null @@ -1,16 +0,0 @@ -# Systray Custom Example - -This example creates a simple system tray and uses hooks to attach a custom window. -The window is hidden by default and toggled by left-clicking on the systray icon. -The window will hide automatically when it loses focus. - -On Windows, if the icon is in the notification flyout, -then the window will be shown in the bottom right corner. - -# Status - -| Platform | Status | -|----------|---------| -| Mac | Working | -| Windows | | -| Linux | | diff --git a/v3/examples/systray-custom/main.go b/v3/examples/systray-custom/main.go deleted file mode 100644 index f10140792..000000000 --- a/v3/examples/systray-custom/main.go +++ /dev/null @@ -1,73 +0,0 @@ -package main - -import ( - _ "embed" - "github.com/wailsapp/wails/v3/pkg/application" - "github.com/wailsapp/wails/v3/pkg/events" - "github.com/wailsapp/wails/v3/pkg/icons" - "log" - "runtime" -) - -var windowShowing bool - -func createWindow(app *application.App) { - if windowShowing { - return - } - // Log the time taken to create the window - window := app.Window.NewWithOptions(application.WebviewWindowOptions{ - Width: 500, - Height: 500, - Name: "Systray Demo Window", - AlwaysOnTop: true, - Hidden: true, - BackgroundColour: application.NewRGB(33, 37, 41), - DisableResize: true, - Windows: application.WindowsWindow{ - HiddenOnTaskbar: true, - }, - }) - windowShowing = true - - window.OnWindowEvent(events.Common.WindowClosing, func(e *application.WindowEvent) { - windowShowing = false - }) - - window.Show() -} - -func main() { - app := application.New(application.Options{ - Name: "Systray Demo", - Description: "A demo of the Systray API", - Assets: application.AlphaAssets, - Windows: application.WindowsOptions{ - DisableQuitOnLastWindowClosed: true, - }, - Mac: application.MacOptions{ - ActivationPolicy: application.ActivationPolicyAccessory, - }, - }) - - systemTray := app.SystemTray.New() - menu := app.NewMenu() - menu.Add("Quit").OnClick(func(data *application.Context) { - app.Quit() - }) - systemTray.SetMenu(menu) - systemTray.SetTooltip("Systray Demo") - - if runtime.GOOS == "darwin" { - systemTray.SetTemplateIcon(icons.SystrayMacTemplate) - } - - systemTray.OnClick(func() { - createWindow(app) - }) - - err := app.Run() - if err != nil { - log.Fatal(err) - } -} diff --git a/v3/examples/systray-menu/README.md b/v3/examples/systray-menu/README.md deleted file mode 100644 index 2de57faea..000000000 --- a/v3/examples/systray-menu/README.md +++ /dev/null @@ -1,17 +0,0 @@ -# Systray Menu Example - -This example creates a system tray with an attached window and a menu. -The window is hidden by default and toggled by left-clicking on the systray icon. -The window will hide automatically when it loses focus. -Right-clicking on the systray icon will show the menu. - -On Windows, if the icon is in the notification flyout, -then the window will be shown in the bottom right corner. - -# Status - -| Platform | Status | -|----------|---------| -| Mac | Working | -| Windows | Working | -| Linux | | diff --git a/v3/examples/systray-menu/logo-dark-xsmall.png b/v3/examples/systray-menu/logo-dark-xsmall.png deleted file mode 100644 index 83a514c74..000000000 Binary files a/v3/examples/systray-menu/logo-dark-xsmall.png and /dev/null differ diff --git a/v3/examples/systray-menu/main.go b/v3/examples/systray-menu/main.go deleted file mode 100644 index b342f0fe1..000000000 --- a/v3/examples/systray-menu/main.go +++ /dev/null @@ -1,114 +0,0 @@ -package main - -import ( - _ "embed" - "github.com/wailsapp/wails/v3/pkg/events" - "log" - "runtime" - "time" - - "github.com/wailsapp/wails/v3/pkg/application" - "github.com/wailsapp/wails/v3/pkg/icons" -) - -//go:embed logo-dark-xsmall.png -var logo []byte - -func main() { - app := application.New(application.Options{ - Name: "Systray Demo", - Description: "A demo of the Systray API", - Assets: application.AlphaAssets, - Mac: application.MacOptions{ - ActivationPolicy: application.ActivationPolicyAccessory, - }, - }) - - systemTray := app.SystemTray.New() - - window := app.Window.NewWithOptions(application.WebviewWindowOptions{ - Width: 500, - Height: 500, - Name: "Systray Demo Window", - Frameless: true, - AlwaysOnTop: true, - Hidden: true, - DisableResize: true, - Windows: application.WindowsWindow{ - HiddenOnTaskbar: true, - }, - KeyBindings: map[string]func(window application.Window){ - "F12": func(window application.Window) { - systemTray.OpenMenu() - }, - }, - }) - - window.RegisterHook(events.Common.WindowClosing, func(e *application.WindowEvent) { - window.Hide() - e.Cancel() - }) - - if runtime.GOOS == "darwin" { - systemTray.SetTemplateIcon(icons.SystrayMacTemplate) - } - - myMenu := app.NewMenu() - myMenu.Add("Wails").SetBitmap(logo).SetEnabled(false) - myMenu.Add("Hidden").SetHidden(true) - - myMenu.Add("Hello World!").OnClick(func(ctx *application.Context) { - println("Hello World!") - q := app.Dialog.Question().SetTitle("Ready?").SetMessage("Are you feeling ready?") - q.AddButton("Yes").OnClick(func() { - println("Awesome!") - }) - q.AddButton("No").SetAsDefault().OnClick(func() { - println("Boo!") - }) - q.Show() - }) - subMenu := myMenu.AddSubmenu("Submenu") - subMenu.Add("Click me!").OnClick(func(ctx *application.Context) { - ctx.ClickedMenuItem().SetLabel("Clicked!") - }) - myMenu.AddSeparator() - myMenu.AddCheckbox("Checked", true).OnClick(func(ctx *application.Context) { - println("Checked: ", ctx.ClickedMenuItem().Checked()) - app.Dialog.Info().SetTitle("Hello World!").SetMessage("Hello World!").Show() - }) - myMenu.Add("Enabled").OnClick(func(ctx *application.Context) { - println("Click me!") - ctx.ClickedMenuItem().SetLabel("Disabled!").SetEnabled(false) - }) - myMenu.AddSeparator() - // Callbacks can be shared. This is useful for radio groups - radioCallback := func(ctx *application.Context) { - menuItem := ctx.ClickedMenuItem() - menuItem.SetLabel(menuItem.Label() + "!") - } - - // Radio groups are created implicitly by placing radio items next to each other in a menu - myMenu.AddRadio("Radio 1", true).OnClick(radioCallback) - myMenu.AddRadio("Radio 2", false).OnClick(radioCallback) - myMenu.AddRadio("Radio 3", false).OnClick(radioCallback) - myMenu.AddSeparator() - myMenu.Add("Hide System tray for 3 seconds...").OnClick(func(ctx *application.Context) { - systemTray.Hide() - time.Sleep(3 * time.Second) - systemTray.Show() - }) - myMenu.AddSeparator() - myMenu.Add("Quit").OnClick(func(ctx *application.Context) { - app.Quit() - }) - - systemTray.SetMenu(myMenu) - - systemTray.AttachWindow(window).WindowOffset(2) - - err := app.Run() - if err != nil { - log.Fatal(err) - } -} diff --git a/v3/examples/video/README.md b/v3/examples/video/README.md deleted file mode 100644 index 012469afb..000000000 --- a/v3/examples/video/README.md +++ /dev/null @@ -1,19 +0,0 @@ -# Video Example - -This example shows support for HTML5 video. - -## Running the example - -To run the example, simply run the following command: - -```bash -go run . -``` - -# Status - -| Platform | Status | -|----------|---------| -| Mac | | -| Windows | Working | -| Linux | | diff --git a/v3/examples/video/main.go b/v3/examples/video/main.go deleted file mode 100644 index 879172c61..000000000 --- a/v3/examples/video/main.go +++ /dev/null @@ -1,47 +0,0 @@ -package main - -import ( - _ "embed" - "github.com/wailsapp/wails/v3/pkg/events" - "log" - - "github.com/wailsapp/wails/v3/pkg/application" -) - -func main() { - app := application.New(application.Options{ - Name: "Video Demo", - Description: "A demo of HTML5 Video API", - Assets: application.AlphaAssets, - Mac: application.MacOptions{ - ApplicationShouldTerminateAfterLastWindowClosed: true, - }, - Windows: application.WindowsOptions{ - WndProcInterceptor: nil, - DisableQuitOnLastWindowClosed: false, - WebviewUserDataPath: "", - WebviewBrowserPath: "", - }, - }) - app.Event.OnApplicationEvent(events.Mac.ApplicationDidFinishLaunching, func(event *application.ApplicationEvent) { - log.Println("ApplicationDidFinishLaunching") - }) - - app.Window.NewWithOptions(application.WebviewWindowOptions{ - BackgroundColour: application.NewRGB(33, 37, 41), - Mac: application.MacWindow{ - DisableShadow: true, - WebviewPreferences: application.MacWebviewPreferences{ - FullscreenEnabled: application.Enabled, - }, - }, - HTML: "", - }) - - err := app.Run() - - if err != nil { - log.Fatal(err) - } - -} diff --git a/v3/examples/web-apis/beacon/frontend/index.html b/v3/examples/web-apis/beacon/frontend/index.html deleted file mode 100644 index f75654d56..000000000 --- a/v3/examples/web-apis/beacon/frontend/index.html +++ /dev/null @@ -1,315 +0,0 @@ - - - - - - Beacon API Demo - - - -
            -
            -

            Beacon API Demo

            - Checking... -
            - -
            -
            -

            Send Beacon

            -
            Beacons are fire-and-forget. Returns true/false for queue status only.
            - - - - - -
            - - - - -
            - - - - -
            - - - - -
            -
            - -
            -

            Statistics & Log

            -
            -
            -
            0
            -
            Sent
            -
            -
            -
            0
            -
            Queued
            -
            -
            -
            0
            -
            Failed
            -
            -
            -
            0
            -
            Bytes
            -
            -
            -
            - - -
            -
            -
            - --:-- - READY - Configure endpoint and send beacons -
            -
            -
            -
            -
            - - - - diff --git a/v3/examples/web-apis/beacon/main.go b/v3/examples/web-apis/beacon/main.go deleted file mode 100644 index cc1d30e29..000000000 --- a/v3/examples/web-apis/beacon/main.go +++ /dev/null @@ -1,27 +0,0 @@ -package main - -import ( - "embed" - - "github.com/wailsapp/wails/v3/pkg/application" -) - -//go:embed frontend/* -var assets embed.FS - -func main() { - app := application.New(application.Options{ - Name: "Beacon API Demo", - Description: "Beacon API for analytics", - Assets: application.AssetOptions{ - Handler: application.BundledAssetFileServer(assets), - }, - }) - app.Window.NewWithOptions(application.WebviewWindowOptions{ - Title: "Beacon API Demo", - Width: 900, - Height: 600, - URL: "/", - }) - app.Run() -} diff --git a/v3/examples/web-apis/blob/frontend/index.html b/v3/examples/web-apis/blob/frontend/index.html deleted file mode 100644 index 6ef330d16..000000000 --- a/v3/examples/web-apis/blob/frontend/index.html +++ /dev/null @@ -1,351 +0,0 @@ - - - - - - Blob API Demo - - - -
            -
            -

            Blob API Demo

            - Checking... -
            - -
            - -
            -

            Create Blob

            -
            - - - - -
            - -
            - -
            -
            -
            -
            - -
            - -
            - - -
            - -
            -
            -
            -
            - - - -
            - -
            -
            -
            -
            -
            -
            - -
            -
            - -
            Select a tab and create a blob...
            -
            - - -
            -

            Stored Blobs

            -
            -

            No blobs yet

            -
            -
            -

            Operations

            -
            -
            -
            -
            - - - -
            -
            -
            -
            -
            -
            -
            -
            - - -
            -

            API Features

            -
            -

            Output

            -
            Conversion/slice results appear here...
            -
            -
            -
            - - - - diff --git a/v3/examples/web-apis/blob/main.go b/v3/examples/web-apis/blob/main.go deleted file mode 100644 index 91c96783e..000000000 --- a/v3/examples/web-apis/blob/main.go +++ /dev/null @@ -1,26 +0,0 @@ -package main - -import ( - "embed" - "github.com/wailsapp/wails/v3/pkg/application" -) - -//go:embed frontend/* -var assets embed.FS - -func main() { - app := application.New(application.Options{ - Name: "Blob API Demo", - Description: "Binary large objects", - Assets: application.AssetOptions{ - Handler: application.BundledAssetFileServer(assets), - }, - }) - app.Window.NewWithOptions(application.WebviewWindowOptions{ - Title: "Blob API Demo", - Width: 900, - Height: 700, - URL: "/", - }) - app.Run() -} diff --git a/v3/examples/web-apis/broadcast-channel/frontend/index.html b/v3/examples/web-apis/broadcast-channel/frontend/index.html deleted file mode 100644 index 81ffe2a34..000000000 --- a/v3/examples/web-apis/broadcast-channel/frontend/index.html +++ /dev/null @@ -1,259 +0,0 @@ - - - - - - Broadcast Channel API Demo - - - -
            -
            -

            Broadcast Channel API Demo

            - Checking... -
            - -
            -
            -

            API Features

            -
            - -

            Channel

            -
            -
            -
            Channel
            -
            demo-channel
            -
            -
            -
            Window ID
            -
            --
            -
            -
            - -
            - - -
            - -

            Send Message

            - -
            - - -
            - -
            - Hello! - Sync - Logout - Theme -
            - -

            Stats

            -
            -
            0
            Sent
            -
            0
            Received
            -
            -
            - -
            -

            Messages

            -
            -
            Open another window to test cross-window messaging
            -
            -
            -
            -
            - - - - - diff --git a/v3/examples/web-apis/broadcast-channel/main.go b/v3/examples/web-apis/broadcast-channel/main.go deleted file mode 100644 index 3cac5dcfc..000000000 --- a/v3/examples/web-apis/broadcast-channel/main.go +++ /dev/null @@ -1,47 +0,0 @@ -package main - -import ( - "embed" - - "github.com/wailsapp/wails/v3/pkg/application" -) - -//go:embed frontend/* -var assets embed.FS - -var app *application.App - -// WindowService allows the frontend to open new windows -type WindowService struct{} - -// OpenNewWindow creates a new application window -func (s *WindowService) OpenNewWindow() { - app.Window.NewWithOptions(application.WebviewWindowOptions{ - Title: "Broadcast Channel Demo", - Width: 800, - Height: 550, - URL: "/", - }) -} - -func main() { - app = application.New(application.Options{ - Name: "Broadcast Channel Demo", - Description: "Cross-window communication via BroadcastChannel API", - Assets: application.AssetOptions{ - Handler: application.BundledAssetFileServer(assets), - }, - Services: []application.Service{ - application.NewService(&WindowService{}), - }, - }) - - app.Window.NewWithOptions(application.WebviewWindowOptions{ - Title: "Broadcast Channel Demo", - Width: 800, - Height: 550, - URL: "/", - }) - - app.Run() -} diff --git a/v3/examples/web-apis/cache-api/frontend/index.html b/v3/examples/web-apis/cache-api/frontend/index.html deleted file mode 100644 index 5eb9d948e..000000000 --- a/v3/examples/web-apis/cache-api/frontend/index.html +++ /dev/null @@ -1,600 +0,0 @@ - - - - - - Cache API Demo - - - -
            -

            Cache API Demo

            -

            - The Cache API provides a mechanism for storing and retrieving network requests and responses. - It's commonly used with Service Workers for offline support and performance optimization. -

            - -
            - Cache API: checking... -
            - -
            -

            Cache Management

            -
            - - -
            - - - -
            Cache list will appear here...
            -
            - -
            -

            Add to Cache

            -
            - - -
            - - - -
            - -
            -

            Retrieve from Cache

            -
            - - -
            - - - -
            - -
            -

            Cached Entries (0)

            - - -
              -
              - -
              -

              Cache-First Strategy Demo

              -

              - Demonstrates a common caching pattern: try cache first, fall back to network. -

              -
              - - -
              - - -
              Strategy results will appear here...
              -
              - -
              -

              API Support

              -
              -
              - -
              -

              Event Log

              - -
              Cache operations will be logged here...
              -
              -
              - - - - diff --git a/v3/examples/web-apis/cache-api/main.go b/v3/examples/web-apis/cache-api/main.go deleted file mode 100644 index 6732fe5cf..000000000 --- a/v3/examples/web-apis/cache-api/main.go +++ /dev/null @@ -1,26 +0,0 @@ -package main - -import ( - "embed" - "github.com/wailsapp/wails/v3/pkg/application" -) - -//go:embed frontend/* -var assets embed.FS - -func main() { - app := application.New(application.Options{ - Name: "Cache API Demo", - Description: "Cache API for offline resources", - Assets: application.AssetOptions{ - Handler: application.BundledAssetFileServer(assets), - }, - }) - app.Window.NewWithOptions(application.WebviewWindowOptions{ - Title: "Cache API Demo", - Width: 900, - Height: 700, - URL: "/", - }) - app.Run() -} diff --git a/v3/examples/web-apis/canvas/frontend/index.html b/v3/examples/web-apis/canvas/frontend/index.html deleted file mode 100644 index 36ab79212..000000000 --- a/v3/examples/web-apis/canvas/frontend/index.html +++ /dev/null @@ -1,324 +0,0 @@ - - - - - - Canvas 2D API Demo - - - -
              -

              Canvas 2D API Demo

              -

              - The Canvas API provides a means for drawing graphics via JavaScript and HTML. - It can be used for animation, game graphics, data visualization, and image manipulation. -

              - -
              - Canvas 2D supported: checking... -
              - -
              -

              Drawing Canvas

              -
              -
              - - -
              -
              - - - 5 -
              -
              - - - - - -
              -
              -
              - - - -
              - -
              - -
              -

              Canvas Demos

              -
              -
              - -
              Shapes & Paths
              -
              -
              - -
              Gradients
              -
              -
              - -
              Text Rendering
              -
              -
              - -
              Animation
              -
              -
              -
              -
              - - - - diff --git a/v3/examples/web-apis/canvas/main.go b/v3/examples/web-apis/canvas/main.go deleted file mode 100644 index 5980435b7..000000000 --- a/v3/examples/web-apis/canvas/main.go +++ /dev/null @@ -1,29 +0,0 @@ -package main - -import ( - "embed" - - "github.com/wailsapp/wails/v3/pkg/application" -) - -//go:embed frontend/* -var assets embed.FS - -func main() { - app := application.New(application.Options{ - Name: "Canvas 2D Demo", - Description: "Demonstrates the Canvas 2D API for graphics rendering", - Assets: application.AssetOptions{ - Handler: application.BundledAssetFileServer(assets), - }, - }) - - app.Window.NewWithOptions(application.WebviewWindowOptions{ - Title: "Canvas 2D Demo", - Width: 800, - Height: 600, - URL: "/", - }) - - app.Run() -} diff --git a/v3/examples/web-apis/clipboard/frontend/index.html b/v3/examples/web-apis/clipboard/frontend/index.html deleted file mode 100644 index 27a765769..000000000 --- a/v3/examples/web-apis/clipboard/frontend/index.html +++ /dev/null @@ -1,258 +0,0 @@ - - - - - - Clipboard API Demo - - - -
              -

              Clipboard API Demo

              -

              - The Clipboard API provides asynchronous read and write access to the system clipboard, - enabling secure copy/paste operations for text and other data types. -

              - -
              - Clipboard API: checking... -
              - -
              -

              Write to Clipboard

              - - - -
              - -
              -

              Read from Clipboard

              - - -
              Click "Paste Text" to read clipboard contents...
              -
              - -
              -

              Clipboard Events

              -

              Try using Ctrl+C/Ctrl+V in the text area below:

              - -
              Clipboard events will be logged here...
              -
              - -
              -

              API Support

              -
              -
              -
              - -
              - - - - diff --git a/v3/examples/web-apis/clipboard/main.go b/v3/examples/web-apis/clipboard/main.go deleted file mode 100644 index b7e2eac6c..000000000 --- a/v3/examples/web-apis/clipboard/main.go +++ /dev/null @@ -1,29 +0,0 @@ -package main - -import ( - "embed" - - "github.com/wailsapp/wails/v3/pkg/application" -) - -//go:embed frontend/* -var assets embed.FS - -func main() { - app := application.New(application.Options{ - Name: "Clipboard API Demo", - Description: "Demonstrates the Clipboard API for copy/paste", - Assets: application.AssetOptions{ - Handler: application.BundledAssetFileServer(assets), - }, - }) - - app.Window.NewWithOptions(application.WebviewWindowOptions{ - Title: "Clipboard API Demo", - Width: 800, - Height: 600, - URL: "/", - }) - - app.Run() -} diff --git a/v3/examples/web-apis/device-orientation/frontend/index.html b/v3/examples/web-apis/device-orientation/frontend/index.html deleted file mode 100644 index fe1896d5b..000000000 --- a/v3/examples/web-apis/device-orientation/frontend/index.html +++ /dev/null @@ -1,475 +0,0 @@ - - - - - - Device Orientation API Demo - - - -
              -

              Device Orientation API Demo

              -

              - The Device Orientation API provides access to the physical orientation of the device. - It reports alpha (compass direction), beta (front-to-back tilt), and gamma (left-to-right tilt). -

              - -
              - Device Orientation: checking... -
              - -
              -

              Orientation Controls

              - - - - - -
              - -
              -

              Orientation Values

              -
              -
              -
              Alpha (Z-axis rotation)
              -
              -
              -
              degrees (0-360)
              -
              -
              -
              -
              Beta (X-axis tilt)
              -
              -
              -
              degrees (-180 to 180)
              -
              -
              -
              -
              Gamma (Y-axis tilt)
              -
              -
              -
              degrees (-90 to 90)
              -
              -
              -
              -
              - -
              -

              Visual Representation

              -
              -
              -
              -
              -
              - N - S - W - E -
              -
              -
              -
              -
              -
              Compass (Alpha)
              -
              -
              -
              -
              -
              -
              FRONT
              -
              BACK
              -
              L
              -
              R
              -
              TOP
              -
              BOT
              -
              -
              -
              -
              Device Tilt (Beta/Gamma)
              -
              -
              -
              - -
              -

              Additional Information

              -
              -
              - Absolute Orientation - - -
              -
              - WebKit Compass Heading - - -
              -
              - WebKit Compass Accuracy - - -
              -
              - Update Count - 0 -
              -
              -
              - -
              -

              Event Log

              -
              -
              Waiting for orientation events...
              -
              -
              -
              - - - - diff --git a/v3/examples/web-apis/device-orientation/main.go b/v3/examples/web-apis/device-orientation/main.go deleted file mode 100644 index a6fdab2bc..000000000 --- a/v3/examples/web-apis/device-orientation/main.go +++ /dev/null @@ -1,26 +0,0 @@ -package main - -import ( - "embed" - "github.com/wailsapp/wails/v3/pkg/application" -) - -//go:embed frontend/* -var assets embed.FS - -func main() { - app := application.New(application.Options{ - Name: "Device Orientation Demo", - Description: "Accelerometer and gyroscope", - Assets: application.AssetOptions{ - Handler: application.BundledAssetFileServer(assets), - }, - }) - app.Window.NewWithOptions(application.WebviewWindowOptions{ - Title: "Device Orientation Demo", - Width: 900, - Height: 700, - URL: "/", - }) - app.Run() -} diff --git a/v3/examples/web-apis/dialog/frontend/index.html b/v3/examples/web-apis/dialog/frontend/index.html deleted file mode 100644 index 2e3bfe491..000000000 --- a/v3/examples/web-apis/dialog/frontend/index.html +++ /dev/null @@ -1,587 +0,0 @@ - - - - - - Dialog Element API Demo - - - -
              -

              Dialog Element API Demo

              -

              - The HTML <dialog> element provides a native way to create modal and non-modal dialog boxes, - with built-in accessibility features and backdrop handling. -

              - -
              - Dialog Element API: checking... -
              - -
              -

              API Support

              -
              -
              - -
              -

              Basic Modal Dialog

              -

              Modal dialogs block interaction with the rest of the page:

              - -
              -
              Last action:
              -
              -
              -
              -
              - -
              -

              Non-Modal Dialog

              -

              Non-modal dialogs allow interaction with the page:

              - - -
              - -
              -

              Confirm Dialog

              -

              A custom confirm dialog that returns user choice:

              - -
              -
              User choice:
              -
              -
              -
              -
              - -
              -

              Form Dialog

              -

              Dialog with form that uses method="dialog":

              - -
              -
              Form data:
              -
              -
              -
              -
              - -
              -

              Alert Variants

              -

              Different styled dialogs for various purposes:

              - - - - -
              - -
              -

              Stacked Dialogs

              -

              Multiple dialogs can be stacked:

              - -
              - -
              -

              Event Log

              - -
              Dialog events will appear here...
              -
              -
              - - - -
              -

              Basic Modal Dialog

              - -
              -
              -

              This is a modal dialog. The backdrop prevents interaction with the page behind it.

              -

              Press Escape or click outside to close (if enabled).

              -
              - -
              - - - -
              -

              Non-Modal Dialog

              - -
              -
              -

              This dialog allows interaction with the page behind it.

              -

              You can still click buttons and scroll the page.

              -
              -
              - - - -
              -

              Confirm Action

              - -
              -
              -

              Are you sure you want to proceed with this action?

              -

              This action may have consequences.

              -
              - -
              - - - -
              -
              -

              User Information

              - -
              -
              -
              - - -
              -
              - - -
              -
              - - -
              -
              - - -
              -
              - -
              -
              - - - -
              -

              Alert

              - -
              -
              -

              Alert message

              -
              - -
              - - - -
              -

              First Dialog

              - -
              -
              -

              This is the first dialog in the stack.

              -

              Click the button below to open another dialog on top.

              -
              - -
              - - - -
              -

              Second Dialog

              - -
              -
              -

              This is the second dialog, stacked on top of the first.

              -

              You can stack as many dialogs as needed.

              -
              - -
              - - - -
              -

              Third Dialog

              - -
              -
              -

              This is the third and final dialog in the stack.

              -

              Close dialogs in reverse order by pressing Escape or clicking Close.

              -
              - -
              - - - - diff --git a/v3/examples/web-apis/dialog/main.go b/v3/examples/web-apis/dialog/main.go deleted file mode 100644 index de3e722fe..000000000 --- a/v3/examples/web-apis/dialog/main.go +++ /dev/null @@ -1,26 +0,0 @@ -package main - -import ( - "embed" - "github.com/wailsapp/wails/v3/pkg/application" -) - -//go:embed frontend/* -var assets embed.FS - -func main() { - app := application.New(application.Options{ - Name: "Dialog Element Demo", - Description: "Native modal dialogs", - Assets: application.AssetOptions{ - Handler: application.BundledAssetFileServer(assets), - }, - }) - app.Window.NewWithOptions(application.WebviewWindowOptions{ - Title: "Dialog Element Demo", - Width: 900, - Height: 700, - URL: "/", - }) - app.Run() -} diff --git a/v3/examples/web-apis/drag-drop/frontend/index.html b/v3/examples/web-apis/drag-drop/frontend/index.html deleted file mode 100644 index db60169ea..000000000 --- a/v3/examples/web-apis/drag-drop/frontend/index.html +++ /dev/null @@ -1,740 +0,0 @@ - - - - - - HTML5 Drag and Drop API Demo - - - -
              -

              HTML5 Drag and Drop API Demo

              -

              - The HTML5 Drag and Drop API enables drag-and-drop functionality for - web applications, supporting both element dragging and file drops. -

              - -
              - Drag and Drop API: checking... -
              - -
              -

              Statistics

              -
              -
              -
              0
              -
              Drag Operations
              -
              -
              -
              0
              -
              Successful Drops
              -
              -
              -
              0
              -
              Files Dropped
              -
              -
              -
              0
              -
              Sort Operations
              -
              -
              -
              - -
              -

              Drag Items to Categories

              -

              - Drag the food items on the left and drop them into the correct category zones. -

              - -
              -
              -
              Apple
              -
              Carrot
              -
              Cheese
              -
              Steak
              -
              Banana
              -
              Broccoli
              -
              Milk
              -
              Chicken
              -
              -
              -
              -
              Fruits
              -
              -
              Drop fruits here
              -
              -
              -
              -
              Vegetables
              -
              -
              Drop vegetables here
              -
              -
              -
              -
              Dairy
              -
              -
              Drop dairy here
              -
              -
              -
              -
              Meat
              -
              -
              Drop meat here
              -
              -
              -
              -
              -
              - -
              -

              File Drop Zone

              -

              - Drag and drop files from your computer into the zone below. -

              -
              -
              📁
              -
              Drag files here or click to select
              - -
              -
              - -
              - -
              -

              Sortable List

              -

              - Drag items to reorder the list. The rank numbers will update automatically. -

              - -
                -
              • - - 1 - Learn HTML5 Drag and Drop -
              • -
              • - - 2 - Build interactive interfaces -
              • -
              • - - 3 - Implement file uploads -
              • -
              • - - 4 - Create sortable lists -
              • -
              • - - 5 - Master drag events -
              • -
              -
              - -
              -

              API Support

              -
              -
              - -
              -

              Event Log

              - -
              Drag and drop events will be logged here... - -Try dragging items between zones or dropping files.
              -
              -
              - - - - diff --git a/v3/examples/web-apis/drag-drop/main.go b/v3/examples/web-apis/drag-drop/main.go deleted file mode 100644 index 9e4342a67..000000000 --- a/v3/examples/web-apis/drag-drop/main.go +++ /dev/null @@ -1,26 +0,0 @@ -package main - -import ( - "embed" - "github.com/wailsapp/wails/v3/pkg/application" -) - -//go:embed frontend/* -var assets embed.FS - -func main() { - app := application.New(application.Options{ - Name: "Drag and Drop Demo", - Description: "Native drag and drop", - Assets: application.AssetOptions{ - Handler: application.BundledAssetFileServer(assets), - }, - }) - app.Window.NewWithOptions(application.WebviewWindowOptions{ - Title: "Drag and Drop Demo", - Width: 900, - Height: 700, - URL: "/", - }) - app.Run() -} diff --git a/v3/examples/web-apis/eventsource/frontend/index.html b/v3/examples/web-apis/eventsource/frontend/index.html deleted file mode 100644 index d85dac7eb..000000000 --- a/v3/examples/web-apis/eventsource/frontend/index.html +++ /dev/null @@ -1,495 +0,0 @@ - - - - - - Server-Sent Events (EventSource) Demo - - - -
              -

              Server-Sent Events (EventSource) Demo

              -

              - Server-Sent Events (SSE) enable servers to push data to web clients over HTTP. - Unlike WebSockets, SSE is unidirectional (server to client) and works over standard HTTP. -

              - -
              -
              - EventSource: Checking... -
              - -
              -

              Connection

              -
              -
              - - -
              -
              - - -

              - Public SSE test servers: sse.dev/test, or use the mock stream below for testing. -

              -
              - -
              -

              Mock Event Stream

              -
              -

              Local Mock (No Server Required)

              -

              - Since SSE requires a server, this mock simulates event streams locally for testing. -

              -
              - - -
              -
              - - -
              - - -
              -
              - -
              -

              Statistics

              -
              -
              -
              0
              -
              Total Events
              -
              -
              -
              0
              -
              Messages
              -
              -
              -
              0
              -
              Custom Events
              -
              -
              -
              0
              -
              Errors
              -
              -
              -
              - -
              -

              Event Log

              - -
              -
              - --:--:-- - INFO - Ready to connect to an SSE endpoint or start mock stream... -
              -
              -
              - -
              -

              EventSource API Reference

              -
              -// Create EventSource connection -const source = new EventSource('https://api.example.com/stream'); - -// Connection opened -source.onopen = (event) => { - console.log('Connection opened'); -}; - -// Default message event -source.onmessage = (event) => { - console.log('Message:', event.data); - console.log('Last Event ID:', event.lastEventId); - console.log('Origin:', event.origin); -}; - -// Custom named events -source.addEventListener('update', (event) => { - console.log('Update event:', event.data); -}); - -source.addEventListener('notification', (event) => { - console.log('Notification:', event.data); -}); - -// Error handling -source.onerror = (event) => { - if (source.readyState === EventSource.CONNECTING) { - console.log('Reconnecting...'); - } else { - console.log('Error occurred'); - } -}; - -// Close connection -source.close(); - -// Ready states -EventSource.CONNECTING // 0 - Connecting -EventSource.OPEN // 1 - Open -EventSource.CLOSED // 2 - Closed - -// Server response format (text/event-stream): -// data: Simple message\n\n -// data: {"json": "data"}\n\n -// event: custom\ndata: Custom event\n\n -// id: 123\ndata: Message with ID\n\n -// retry: 5000\n\n
              -
              -
              - - - - diff --git a/v3/examples/web-apis/eventsource/main.go b/v3/examples/web-apis/eventsource/main.go deleted file mode 100644 index 97c5622c4..000000000 --- a/v3/examples/web-apis/eventsource/main.go +++ /dev/null @@ -1,26 +0,0 @@ -package main - -import ( - "embed" - "github.com/wailsapp/wails/v3/pkg/application" -) - -//go:embed frontend/* -var assets embed.FS - -func main() { - app := application.New(application.Options{ - Name: "Server-Sent Events Demo", - Description: "EventSource/SSE API demonstration", - Assets: application.AssetOptions{ - Handler: application.BundledAssetFileServer(assets), - }, - }) - app.Window.NewWithOptions(application.WebviewWindowOptions{ - Title: "Server-Sent Events Demo", - Width: 900, - Height: 700, - URL: "/", - }) - app.Run() -} diff --git a/v3/examples/web-apis/fetch/frontend/index.html b/v3/examples/web-apis/fetch/frontend/index.html deleted file mode 100644 index e5f21526d..000000000 --- a/v3/examples/web-apis/fetch/frontend/index.html +++ /dev/null @@ -1,286 +0,0 @@ - - - - - - Fetch API Demo - - - -
              -

              Fetch API Demo

              -

              - The Fetch API provides a modern interface for making HTTP requests. - It returns Promises and supports various request/response types. -

              - -
              - Fetch API available: checking... -
              - -
              -

              Make Request

              -
              -
              - - -
              -
              - - -
              -
              -
              - - -
              -
              - - -
              - - - - -
              - -
              -

              Response

              - - -
              - - -
              -
              Make a request to see the response...
              - -
              - -
              -

              Fetch API Features

              -
              -fetch(url, options) returns a Promise<Response> - -Options: -- method: 'GET', 'POST', 'PUT', 'DELETE', etc. -- headers: Headers object or plain object -- body: String, FormData, Blob, ArrayBuffer, URLSearchParams -- mode: 'cors', 'no-cors', 'same-origin' -- credentials: 'omit', 'same-origin', 'include' -- cache: 'default', 'no-store', 'reload', 'no-cache', 'force-cache' -- redirect: 'follow', 'error', 'manual' -- signal: AbortController.signal for cancellation - -Response methods: -- response.json() - Parse as JSON -- response.text() - Get as text -- response.blob() - Get as Blob -- response.arrayBuffer() - Get as ArrayBuffer -- response.formData() - Get as FormData - -Response properties: -- response.ok (status 200-299) -- response.status -- response.statusText -- response.headers -- response.url -- response.type
              -
              -
              - - - - diff --git a/v3/examples/web-apis/fetch/main.go b/v3/examples/web-apis/fetch/main.go deleted file mode 100644 index 2e738954d..000000000 --- a/v3/examples/web-apis/fetch/main.go +++ /dev/null @@ -1,29 +0,0 @@ -package main - -import ( - "embed" - - "github.com/wailsapp/wails/v3/pkg/application" -) - -//go:embed frontend/* -var assets embed.FS - -func main() { - app := application.New(application.Options{ - Name: "Fetch API Demo", - Description: "Demonstrates the Fetch API for network requests", - Assets: application.AssetOptions{ - Handler: application.BundledAssetFileServer(assets), - }, - }) - - app.Window.NewWithOptions(application.WebviewWindowOptions{ - Title: "Fetch API Demo", - Width: 800, - Height: 600, - URL: "/", - }) - - app.Run() -} diff --git a/v3/examples/web-apis/file-api/frontend/index.html b/v3/examples/web-apis/file-api/frontend/index.html deleted file mode 100644 index eee807321..000000000 --- a/v3/examples/web-apis/file-api/frontend/index.html +++ /dev/null @@ -1,623 +0,0 @@ - - - - - - File API Demo - - - -
              -

              File API Demo

              -

              - The File API provides access to file information and content, enabling web applications - to read files selected by users through file inputs or drag-and-drop operations. -

              - -
              - File API available: checking... -
              - -
              -

              API Support

              -
              -
              - -
              -

              Select Files

              -
              -

              Drop files here or click to select

              -

              Supports multiple files of any type

              - -
              -
              -
              - -
              -

              File Information

              -

              Select a file above to see its details

              -
              No file selected yet...
              -
              - -
              -

              Read File Content

              -

              Choose how to read the selected file

              -
              - - - - -
              - - -
              -
              -
              -
              Select a file and click "Read File" to see content...
              -
              -
              - -
              -

              File Slice Demo

              -

              Read a portion of the selected file using slice()

              -
              -
              - - -
              -
              - - -
              -
              - -
              Select a file and define a range to read a slice...
              -
              - -
              -

              Create File from Text

              -

              Create a new File object from text content

              -
              - - -
              -
              -
              - - -
              -
              - - -
              -
              - - -
              Click "Create File" to create a new File object...
              -
              - -
              -

              Event Log

              - -
              -
              Ready to log file events...
              -
              -
              -
              - - - - diff --git a/v3/examples/web-apis/file-api/main.go b/v3/examples/web-apis/file-api/main.go deleted file mode 100644 index 2a81b0d64..000000000 --- a/v3/examples/web-apis/file-api/main.go +++ /dev/null @@ -1,26 +0,0 @@ -package main - -import ( - "embed" - "github.com/wailsapp/wails/v3/pkg/application" -) - -//go:embed frontend/* -var assets embed.FS - -func main() { - app := application.New(application.Options{ - Name: "File API Demo", - Description: "File reading and handling", - Assets: application.AssetOptions{ - Handler: application.BundledAssetFileServer(assets), - }, - }) - app.Window.NewWithOptions(application.WebviewWindowOptions{ - Title: "File API Demo", - Width: 900, - Height: 700, - URL: "/", - }) - app.Run() -} diff --git a/v3/examples/web-apis/fullscreen/frontend/index.html b/v3/examples/web-apis/fullscreen/frontend/index.html deleted file mode 100644 index 99adeb357..000000000 --- a/v3/examples/web-apis/fullscreen/frontend/index.html +++ /dev/null @@ -1,286 +0,0 @@ - - - - - - Fullscreen API Demo - - - -
              -

              Fullscreen API Demo

              -

              - The Fullscreen API allows elements to be displayed in full-screen mode, - hiding all browser UI for an immersive experience. -

              - -
              - Fullscreen API: checking... -
              - -
              -

              Element Fullscreen

              -
              -

              Fullscreen Target

              -

              Click the button below to make this element fullscreen

              -

              Press ESC or click Exit to leave fullscreen

              - - -
              -
              - -
              -

              Document Fullscreen

              - - - -
              - -
              -

              Video Fullscreen

              -
              - -
              - - - -
              -
              -

              - Note: A sample video would play here. The fullscreen button demonstrates video fullscreen. -

              -
              - -
              -

              Fullscreen State

              -
              Current state will be displayed here...
              -
              - -
              -

              API Support

              -
              -
              -
              - - - - diff --git a/v3/examples/web-apis/fullscreen/main.go b/v3/examples/web-apis/fullscreen/main.go deleted file mode 100644 index 4c717c91e..000000000 --- a/v3/examples/web-apis/fullscreen/main.go +++ /dev/null @@ -1,29 +0,0 @@ -package main - -import ( - "embed" - - "github.com/wailsapp/wails/v3/pkg/application" -) - -//go:embed frontend/* -var assets embed.FS - -func main() { - app := application.New(application.Options{ - Name: "Fullscreen Demo", - Description: "Demonstrates the Fullscreen API", - Assets: application.AssetOptions{ - Handler: application.BundledAssetFileServer(assets), - }, - }) - - app.Window.NewWithOptions(application.WebviewWindowOptions{ - Title: "Fullscreen Demo", - Width: 800, - Height: 600, - URL: "/", - }) - - app.Run() -} diff --git a/v3/examples/web-apis/gamepad/frontend/index.html b/v3/examples/web-apis/gamepad/frontend/index.html deleted file mode 100644 index 9cfc14e92..000000000 --- a/v3/examples/web-apis/gamepad/frontend/index.html +++ /dev/null @@ -1,754 +0,0 @@ - - - - - - Gamepad API Demo - - - -
              -

              Gamepad API Demo

              -

              - The Gamepad API provides access to game controllers. Connect a gamepad and press any button to activate it. - Supports standard controllers, analog sticks, triggers, and rumble feedback. -

              - -
              - Gamepad API: checking... -
              - -
              -

              Connected Controllers

              -
              -
              -
              1
              -
              No controller
              -
              -
              -
              2
              -
              No controller
              -
              -
              -
              3
              -
              No controller
              -
              -
              -
              4
              -
              No controller
              -
              -
              -
              - - - - - -
              -

              Axes Values

              -
              -
              Connect a gamepad to see axis values
              -
              -
              - -
              -

              Gamepad Info

              -
              -
              - ID - - -
              -
              - Mapping - - -
              -
              - Buttons - - -
              -
              - Axes - - -
              -
              - Timestamp - - -
              -
              - Vibration - - -
              -
              -
              - -
              -

              Event Log

              - -
              -
              Waiting for gamepad events... Press a button on your controller.
              -
              -
              -
              - - - - diff --git a/v3/examples/web-apis/gamepad/main.go b/v3/examples/web-apis/gamepad/main.go deleted file mode 100644 index 6604670fa..000000000 --- a/v3/examples/web-apis/gamepad/main.go +++ /dev/null @@ -1,26 +0,0 @@ -package main - -import ( - "embed" - "github.com/wailsapp/wails/v3/pkg/application" -) - -//go:embed frontend/* -var assets embed.FS - -func main() { - app := application.New(application.Options{ - Name: "Gamepad API Demo", - Description: "Game controller input", - Assets: application.AssetOptions{ - Handler: application.BundledAssetFileServer(assets), - }, - }) - app.Window.NewWithOptions(application.WebviewWindowOptions{ - Title: "Gamepad API Demo", - Width: 900, - Height: 700, - URL: "/", - }) - app.Run() -} diff --git a/v3/examples/web-apis/geolocation/frontend/index.html b/v3/examples/web-apis/geolocation/frontend/index.html deleted file mode 100644 index 110f9fa68..000000000 --- a/v3/examples/web-apis/geolocation/frontend/index.html +++ /dev/null @@ -1,315 +0,0 @@ - - - - - - Geolocation API Demo - - - -
              -

              Geolocation API Demo

              -

              - The Geolocation API allows web applications to access the user's geographical location. - It requires user permission and works best with GPS-enabled devices. -

              - -
              - Geolocation: checking... -
              - -
              -

              Current Position

              - - - - - - -
              - Get location to see coordinates -
              -
              - -
              -

              Position Options

              -
              - - - -
              -
              - -
              -

              Position History

              -
                -
              • No positions recorded yet...
              • -
              -
              - -
              -

              Raw Position Data

              -
              Position data will appear here...
              -
              -
              - - - - diff --git a/v3/examples/web-apis/geolocation/main.go b/v3/examples/web-apis/geolocation/main.go deleted file mode 100644 index 2be228d3d..000000000 --- a/v3/examples/web-apis/geolocation/main.go +++ /dev/null @@ -1,29 +0,0 @@ -package main - -import ( - "embed" - - "github.com/wailsapp/wails/v3/pkg/application" -) - -//go:embed frontend/* -var assets embed.FS - -func main() { - app := application.New(application.Options{ - Name: "Geolocation Demo", - Description: "Demonstrates the Geolocation API", - Assets: application.AssetOptions{ - Handler: application.BundledAssetFileServer(assets), - }, - }) - - app.Window.NewWithOptions(application.WebviewWindowOptions{ - Title: "Geolocation Demo", - Width: 800, - Height: 600, - URL: "/", - }) - - app.Run() -} diff --git a/v3/examples/web-apis/history/frontend/index.html b/v3/examples/web-apis/history/frontend/index.html deleted file mode 100644 index a21a58623..000000000 --- a/v3/examples/web-apis/history/frontend/index.html +++ /dev/null @@ -1,736 +0,0 @@ - - - - - - History API Demo - - - -
              -

              History API Demo

              -

              - The History API allows manipulation of the browser session history, enabling - single-page applications (SPAs) to update the URL without full page reloads. -

              - -
              - History API: checking... -
              - -
              -

              Current State

              -
              - URL: - -- -
              - -
              -
              history.state:
              -
              null
              -
              - -
              -
              -
              0
              -
              History Length
              -
              -
              -
              0
              -
              pushState Calls
              -
              -
              -
              0
              -
              replaceState Calls
              -
              -
              -
              0
              -
              popstate Events
              -
              -
              -
              - -
              -

              Navigation Controls

              - - -
              -
              Note on Navigation
              -
              - The back/forward buttons use history.back() and history.forward(). - You can also use history.go(n) to jump multiple entries. - Navigation will trigger the popstate event. -
              -
              -
              - -
              -

              Simulated SPA Navigation

              -

              - Click pages below to navigate. The URL updates without a page reload. -

              -
              - Home - Products - About - Contact - Settings -
              - -
              -
              🏠
              -
              Home
              -
              Welcome to the home page
              -
              -
              - -
              -

              pushState

              -

              - Add a new entry to the browser history. This does not reload the page. -

              -
              - - -
              -
              - - -
              -
              - - -
              - -
              - -
              -

              replaceState

              -

              - Replace the current history entry. Does not create a new entry. -

              -
              - - -
              -
              - - -
              - -
              - -
              -

              History Stack (Local Tracking)

              -

              - Note: The History API does not provide access to the full history stack for privacy reasons. - This list tracks only entries created during this session. -

              - -
              -
              -
              - 0 - -- -
              -
              Loading...
              -
              state: null
              -
              -
              -
              - -
              -

              API Support

              -
              -
              - -
              -

              Event Log

              - -
              History events will be logged here... - -Use the controls above to manipulate history and see events logged.
              -
              -
              - - - - diff --git a/v3/examples/web-apis/history/main.go b/v3/examples/web-apis/history/main.go deleted file mode 100644 index 20b75133d..000000000 --- a/v3/examples/web-apis/history/main.go +++ /dev/null @@ -1,26 +0,0 @@ -package main - -import ( - "embed" - "github.com/wailsapp/wails/v3/pkg/application" -) - -//go:embed frontend/* -var assets embed.FS - -func main() { - app := application.New(application.Options{ - Name: "History API Demo", - Description: "Browser history manipulation", - Assets: application.AssetOptions{ - Handler: application.BundledAssetFileServer(assets), - }, - }) - app.Window.NewWithOptions(application.WebviewWindowOptions{ - Title: "History API Demo", - Width: 900, - Height: 700, - URL: "/", - }) - app.Run() -} diff --git a/v3/examples/web-apis/indexeddb/frontend/index.html b/v3/examples/web-apis/indexeddb/frontend/index.html deleted file mode 100644 index 2a40533b5..000000000 --- a/v3/examples/web-apis/indexeddb/frontend/index.html +++ /dev/null @@ -1,364 +0,0 @@ - - - - - - IndexedDB API Demo - - - -
              -

              IndexedDB API Demo

              -

              - IndexedDB is a low-level API for storing significant amounts of structured data, - including files and blobs. It uses indexes for high-performance searches. -

              - -
              - IndexedDB available: checking... -
              - -
              -

              Add Person Record

              -
              -
              - - -
              -
              - - -
              -
              - - -
              -
              - - -
              - -
              -

              Search Records

              -
              -
              - - -
              -
              - - -
              -
              - - - -
              - -
              -

              Records

              - - - - - - - - - - - -
              IDNameEmailAgeActions
              -
              - -
              -

              Database Info

              -
              -
              -
              - - - - diff --git a/v3/examples/web-apis/indexeddb/main.go b/v3/examples/web-apis/indexeddb/main.go deleted file mode 100644 index c6c532d79..000000000 --- a/v3/examples/web-apis/indexeddb/main.go +++ /dev/null @@ -1,29 +0,0 @@ -package main - -import ( - "embed" - - "github.com/wailsapp/wails/v3/pkg/application" -) - -//go:embed frontend/* -var assets embed.FS - -func main() { - app := application.New(application.Options{ - Name: "IndexedDB Demo", - Description: "Demonstrates the IndexedDB API for client-side database storage", - Assets: application.AssetOptions{ - Handler: application.BundledAssetFileServer(assets), - }, - }) - - app.Window.NewWithOptions(application.WebviewWindowOptions{ - Title: "IndexedDB Demo", - Width: 800, - Height: 600, - URL: "/", - }) - - app.Run() -} diff --git a/v3/examples/web-apis/intersection-observer/frontend/index.html b/v3/examples/web-apis/intersection-observer/frontend/index.html deleted file mode 100644 index 07e21afa9..000000000 --- a/v3/examples/web-apis/intersection-observer/frontend/index.html +++ /dev/null @@ -1,285 +0,0 @@ - - - - - - Intersection Observer API Demo - - - -
              -

              Intersection Observer API Demo

              -

              - The Intersection Observer API provides a way to asynchronously observe changes - in the intersection of a target element with an ancestor element or viewport. -

              - -
              - Intersection Observer: checking... -
              - -
              -
              Visibility
              -
              Box 1
              -
              Box 2
              -
              Box 3
              -
              Box 4
              -
              Box 5
              -
              - -
              -

              Observer Options

              -
              -
              - - -
              -
              - - -
              - -
              -
              - -
              -

              Scroll Demo

              -

              Scroll down to see elements animate when they enter the viewport.

              -
              -
              -
              Box 1 - I animate when visible!
              -
              -
              Box 2 - Intersection detected!
              -
              -
              Box 3 - Lazy loading example
              -
              -
              Box 4 - Analytics trigger
              -
              -
              Box 5 - Infinite scroll trigger
              -
              -
              -
              - -
              -

              Lazy Loading Images

              -

              Images load when they enter the viewport.

              -
              -
              Scroll to load...
              -
              Scroll to load...
              -
              Scroll to load...
              -
              -
              - -
              -

              Event Log

              -
              Intersection events will appear here...
              -
              -
              - - - - diff --git a/v3/examples/web-apis/intersection-observer/main.go b/v3/examples/web-apis/intersection-observer/main.go deleted file mode 100644 index 60f32a377..000000000 --- a/v3/examples/web-apis/intersection-observer/main.go +++ /dev/null @@ -1,29 +0,0 @@ -package main - -import ( - "embed" - - "github.com/wailsapp/wails/v3/pkg/application" -) - -//go:embed frontend/* -var assets embed.FS - -func main() { - app := application.New(application.Options{ - Name: "Intersection Observer Demo", - Description: "Demonstrates the Intersection Observer API", - Assets: application.AssetOptions{ - Handler: application.BundledAssetFileServer(assets), - }, - }) - - app.Window.NewWithOptions(application.WebviewWindowOptions{ - Title: "Intersection Observer Demo", - Width: 800, - Height: 600, - URL: "/", - }) - - app.Run() -} diff --git a/v3/examples/web-apis/localstorage/frontend/index.html b/v3/examples/web-apis/localstorage/frontend/index.html deleted file mode 100644 index 59df31656..000000000 --- a/v3/examples/web-apis/localstorage/frontend/index.html +++ /dev/null @@ -1,226 +0,0 @@ - - - - - - LocalStorage API Demo - - - -
              -

              LocalStorage API Demo

              -

              - The Web Storage API provides localStorage for persistent key-value storage - that survives browser restarts. -

              - -
              - localStorage is available: checking... -
              - -
              -

              Store Data

              -
              - - -
              -
              - - -
              - - -
              - -
              -

              Stored Items (0)

              - - -
                -
                - -
                -

                Storage Info

                -
                -
                -
                - - - - diff --git a/v3/examples/web-apis/localstorage/main.go b/v3/examples/web-apis/localstorage/main.go deleted file mode 100644 index 1fc617464..000000000 --- a/v3/examples/web-apis/localstorage/main.go +++ /dev/null @@ -1,29 +0,0 @@ -package main - -import ( - "embed" - - "github.com/wailsapp/wails/v3/pkg/application" -) - -//go:embed frontend/* -var assets embed.FS - -func main() { - app := application.New(application.Options{ - Name: "LocalStorage Demo", - Description: "Demonstrates the Web Storage API (localStorage)", - Assets: application.AssetOptions{ - Handler: application.BundledAssetFileServer(assets), - }, - }) - - app.Window.NewWithOptions(application.WebviewWindowOptions{ - Title: "LocalStorage API Demo", - Width: 800, - Height: 600, - URL: "/", - }) - - app.Run() -} diff --git a/v3/examples/web-apis/mediadevices/frontend/index.html b/v3/examples/web-apis/mediadevices/frontend/index.html deleted file mode 100644 index 56d581834..000000000 --- a/v3/examples/web-apis/mediadevices/frontend/index.html +++ /dev/null @@ -1,560 +0,0 @@ - - - - - - MediaDevices API Demo - - - -
                -

                MediaDevices API Demo

                -

                - The MediaDevices API provides access to connected media input devices like cameras and microphones. - It enables applications to enumerate devices and request audio/video streams. -

                - -
                - MediaDevices API: checking... -
                - -
                -

                API Support

                -
                -
                - -
                -

                Available Devices

                - - -
                -

                Click "Enumerate Devices" to list available media devices...

                -
                -
                - -
                -

                Camera & Microphone Preview

                -
                - - -
                - - - - - -
                -
                -

                Video Preview

                - -
                -
                -

                Audio Level

                -
                -
                -
                -

                - Start preview to see audio levels... -

                -
                -
                -
                - -
                -

                Constraints Builder

                -

                Configure media constraints for getUserMedia:

                -
                - - - - - - -
                - - -
                - -
                -

                Event Log

                - -
                Events will be logged here...
                -
                -
                - - - - diff --git a/v3/examples/web-apis/mediadevices/main.go b/v3/examples/web-apis/mediadevices/main.go deleted file mode 100644 index 5cc8d1ba6..000000000 --- a/v3/examples/web-apis/mediadevices/main.go +++ /dev/null @@ -1,26 +0,0 @@ -package main - -import ( - "embed" - "github.com/wailsapp/wails/v3/pkg/application" -) - -//go:embed frontend/* -var assets embed.FS - -func main() { - app := application.New(application.Options{ - Name: "Media Devices Demo", - Description: "Camera and microphone access", - Assets: application.AssetOptions{ - Handler: application.BundledAssetFileServer(assets), - }, - }) - app.Window.NewWithOptions(application.WebviewWindowOptions{ - Title: "Media Devices Demo", - Width: 900, - Height: 700, - URL: "/", - }) - app.Run() -} diff --git a/v3/examples/web-apis/mediarecorder/frontend/index.html b/v3/examples/web-apis/mediarecorder/frontend/index.html deleted file mode 100644 index 8979d9454..000000000 --- a/v3/examples/web-apis/mediarecorder/frontend/index.html +++ /dev/null @@ -1,803 +0,0 @@ - - - - - - MediaRecorder API Demo - - - -
                -

                MediaRecorder API Demo

                -

                - The MediaRecorder API enables recording audio and video streams from MediaDevices. - Create recordings from camera, microphone, or screen capture sources. -

                - -
                - MediaRecorder API: checking... -
                - -
                -

                API Support

                -
                -
                - -
                -

                Supported MIME Types

                -
                -
                - -
                -

                Audio Recording

                - - - - - - - -
                -

                Audio Playback

                - -
                -
                - -
                -

                Video Recording

                - - -
                - -
                - -
                - - - Data chunks interval -
                - - - - - - - -
                -
                -

                Live Preview

                - -
                -
                -

                Recording Playback

                - -
                -
                - -
                -
                -
                0
                -
                Data Chunks
                -
                -
                -
                0 KB
                -
                Total Size
                -
                -
                -
                inactive
                -
                State
                -
                -
                -
                - -
                -

                Recordings

                - -
                -

                No recordings yet. Start recording to see them here.

                -
                -
                - -
                -

                Event Log

                - -
                Events will be logged here...
                -
                -
                - - - - diff --git a/v3/examples/web-apis/mediarecorder/main.go b/v3/examples/web-apis/mediarecorder/main.go deleted file mode 100644 index 85761962d..000000000 --- a/v3/examples/web-apis/mediarecorder/main.go +++ /dev/null @@ -1,26 +0,0 @@ -package main - -import ( - "embed" - "github.com/wailsapp/wails/v3/pkg/application" -) - -//go:embed frontend/* -var assets embed.FS - -func main() { - app := application.New(application.Options{ - Name: "MediaRecorder Demo", - Description: "Record audio/video streams", - Assets: application.AssetOptions{ - Handler: application.BundledAssetFileServer(assets), - }, - }) - app.Window.NewWithOptions(application.WebviewWindowOptions{ - Title: "MediaRecorder Demo", - Width: 900, - Height: 700, - URL: "/", - }) - app.Run() -} diff --git a/v3/examples/web-apis/mutation-observer/frontend/index.html b/v3/examples/web-apis/mutation-observer/frontend/index.html deleted file mode 100644 index 7f4dad734..000000000 --- a/v3/examples/web-apis/mutation-observer/frontend/index.html +++ /dev/null @@ -1,506 +0,0 @@ - - - - - - MutationObserver API Demo - - - -
                -

                MutationObserver API Demo

                -

                - The MutationObserver API provides the ability to watch for changes being made to the DOM tree, - including child elements, attributes, and text content. -

                - -
                - MutationObserver: checking... -
                - -
                -

                Observer Configuration

                -

                Configure what types of mutations to observe:

                -
                -
                - -
                Watch for added/removed child nodes
                -
                -
                - -
                Watch for attribute changes
                -
                -
                - -
                Watch for text content changes
                -
                -
                - -
                Include descendant nodes
                -
                -
                -
                - - - Inactive -
                -
                - -
                -

                Mutation Statistics

                -
                -
                -
                0
                -
                Child List Mutations
                -
                -
                -
                0
                -
                Attribute Mutations
                -
                -
                -
                0
                -
                Character Data Mutations
                -
                -
                - -
                - -
                -

                Child List Mutations

                -

                Add, remove, or modify child elements:

                -
                - - - -
                -
                -
                Initial Element 1
                -
                Initial Element 2
                -
                -
                - -
                -

                Attribute Mutations

                -

                Modify element attributes:

                -
                - - - -
                -
                -
                Watch my attributes change!
                -
                -
                - -
                -

                Character Data Mutations

                -

                Edit the text content below (click to edit):

                -
                - Edit this text to trigger characterData mutations. Try typing, deleting, or pasting text! -
                -
                - -
                -

                Batch Mutations

                -

                Perform multiple mutations at once:

                -
                - - - -
                -
                - -
                -

                Event Log

                -
                Mutation events will appear here...
                - -
                -
                - - - - diff --git a/v3/examples/web-apis/mutation-observer/main.go b/v3/examples/web-apis/mutation-observer/main.go deleted file mode 100644 index 5405a9529..000000000 --- a/v3/examples/web-apis/mutation-observer/main.go +++ /dev/null @@ -1,26 +0,0 @@ -package main - -import ( - "embed" - "github.com/wailsapp/wails/v3/pkg/application" -) - -//go:embed frontend/* -var assets embed.FS - -func main() { - app := application.New(application.Options{ - Name: "Mutation Observer Demo", - Description: "DOM change observation", - Assets: application.AssetOptions{ - Handler: application.BundledAssetFileServer(assets), - }, - }) - app.Window.NewWithOptions(application.WebviewWindowOptions{ - Title: "Mutation Observer Demo", - Width: 900, - Height: 700, - URL: "/", - }) - app.Run() -} diff --git a/v3/examples/web-apis/notifications/frontend/index.html b/v3/examples/web-apis/notifications/frontend/index.html deleted file mode 100644 index 0a968c90a..000000000 --- a/v3/examples/web-apis/notifications/frontend/index.html +++ /dev/null @@ -1,299 +0,0 @@ - - - - - - Notifications API Demo - - - -
                -

                Notifications API Demo

                -

                - The Notifications API allows web applications to display system notifications - to the user, even when the app is in the background. -

                - -
                - Notifications: checking... -
                - -
                -

                Permission

                -

                Current permission: checking...

                - -

                - Note: Permission must be granted before notifications can be shown. - Some browsers block permission requests in webviews. -

                -
                - -
                -

                Create Notification

                -
                -
                - - -
                -
                - - -
                -
                - - -
                -
                - - -
                -
                - - - -
                - -
                -

                Preview

                -
                -
                -
                -
                -
                Notification Title
                -
                Notification body text...
                -
                -
                -
                - -
                -

                Event Log

                -
                Notification events will appear here...
                -
                -
                - - - - diff --git a/v3/examples/web-apis/notifications/main.go b/v3/examples/web-apis/notifications/main.go deleted file mode 100644 index 88f1fe9de..000000000 --- a/v3/examples/web-apis/notifications/main.go +++ /dev/null @@ -1,29 +0,0 @@ -package main - -import ( - "embed" - - "github.com/wailsapp/wails/v3/pkg/application" -) - -//go:embed frontend/* -var assets embed.FS - -func main() { - app := application.New(application.Options{ - Name: "Notifications Demo", - Description: "Demonstrates the Notifications API", - Assets: application.AssetOptions{ - Handler: application.BundledAssetFileServer(assets), - }, - }) - - app.Window.NewWithOptions(application.WebviewWindowOptions{ - Title: "Notifications Demo", - Width: 800, - Height: 600, - URL: "/", - }) - - app.Run() -} diff --git a/v3/examples/web-apis/page-visibility/frontend/index.html b/v3/examples/web-apis/page-visibility/frontend/index.html deleted file mode 100644 index aa5917b45..000000000 --- a/v3/examples/web-apis/page-visibility/frontend/index.html +++ /dev/null @@ -1,543 +0,0 @@ - - - - - - Page Visibility API Demo - - - -
                -

                Page Visibility API Demo

                -

                - The Page Visibility API provides events to know when a document becomes visible or hidden, - allowing you to pause/resume activities, save resources, and improve user experience. -

                - -
                - Page Visibility API: checking... -
                - -
                -
                -
                👁
                -
                VISIBLE
                -
                document.visibilityState: visible
                -
                - -
                -
                -
                0s
                -
                Time Visible
                -
                -
                -
                0s
                -
                Time Hidden
                -
                -
                -
                0
                -
                State Changes
                -
                -
                -
                0
                -
                Times Hidden
                -
                -
                -
                - -
                -

                Timer Demo (Pauses When Hidden)

                -

                - This timer pauses when the page is hidden and resumes when visible. - Try switching to another tab or minimizing the window. -

                -
                00:00:00
                - - - - Timer stopped -
                - -
                -

                Video Simulation (Pauses When Hidden)

                -

                - Simulated video player that automatically pauses when you switch tabs. -

                -
                -
                -
                - - - Video paused -
                - -
                -

                Use Cases

                -
                -

                Common Applications

                -
                  -
                • Pause media playback - Stop videos/audio when tab is hidden
                • -
                • Stop animations - Pause CSS/JS animations to save CPU
                • -
                • Defer updates - Skip DOM updates while hidden
                • -
                • Analytics - Track actual time spent viewing content
                • -
                • Save resources - Stop polling/WebSocket activity
                • -
                • Show notifications - Alert users to updates when they return
                • -
                -
                -
                - -
                -

                API Support

                -
                -
                - -
                -

                Event Log

                - -
                Visibility events will be logged here... - -Try switching tabs, minimizing the window, or switching to another application.
                -
                -
                - - - - diff --git a/v3/examples/web-apis/page-visibility/main.go b/v3/examples/web-apis/page-visibility/main.go deleted file mode 100644 index e5499baea..000000000 --- a/v3/examples/web-apis/page-visibility/main.go +++ /dev/null @@ -1,26 +0,0 @@ -package main - -import ( - "embed" - "github.com/wailsapp/wails/v3/pkg/application" -) - -//go:embed frontend/* -var assets embed.FS - -func main() { - app := application.New(application.Options{ - Name: "Page Visibility Demo", - Description: "Tab visibility detection", - Assets: application.AssetOptions{ - Handler: application.BundledAssetFileServer(assets), - }, - }) - app.Window.NewWithOptions(application.WebviewWindowOptions{ - Title: "Page Visibility Demo", - Width: 900, - Height: 700, - URL: "/", - }) - app.Run() -} diff --git a/v3/examples/web-apis/performance/frontend/index.html b/v3/examples/web-apis/performance/frontend/index.html deleted file mode 100644 index 57f1bf586..000000000 --- a/v3/examples/web-apis/performance/frontend/index.html +++ /dev/null @@ -1,537 +0,0 @@ - - - - - - Performance API Demo - - - -
                -

                Performance API Demo

                -

                - The Performance API provides access to performance-related information, - enabling precise timing measurements, user timing marks, and performance metrics. -

                - -
                - Performance API: checking... -
                - -
                -

                Page Load Timing

                -

                Key performance metrics from page navigation:

                -
                -
                -
                DOM Content Loaded
                -
                --
                -
                milliseconds
                -
                -
                -
                Page Load Time
                -
                --
                -
                milliseconds
                -
                -
                -
                DNS Lookup
                -
                --
                -
                milliseconds
                -
                -
                -
                Time to First Byte
                -
                --
                -
                milliseconds
                -
                -
                - -
                - -
                -

                Performance Marks & Measures

                -

                Create custom timing marks and measure durations:

                -
                - - - - -
                -
                - - - - - - - - - - - - -
                TypeNameStart TimeDuration
                No marks or measures yet
                -
                -
                - -
                -

                Simulated Task Performance

                -

                Run simulated tasks and measure their performance:

                -
                -
                -
                -
                - - - - -
                -
                -
                -
                Last Task Duration
                -
                --
                -
                milliseconds
                -
                -
                -
                Total Tasks Run
                -
                0
                -
                tasks
                -
                -
                -
                Average Duration
                -
                --
                -
                milliseconds
                -
                -
                -
                - -
                -

                Navigation Timeline

                -

                Visual timeline of page load phases:

                -
                -
                Loading timeline...
                -
                -
                - -
                -

                Resource Timing

                -

                Performance entries for loaded resources:

                -
                Loading resource timing data...
                - -
                - -
                -

                Event Log

                -
                Performance events will appear here...
                -
                -
                - - - - diff --git a/v3/examples/web-apis/performance/main.go b/v3/examples/web-apis/performance/main.go deleted file mode 100644 index 2543c6c4b..000000000 --- a/v3/examples/web-apis/performance/main.go +++ /dev/null @@ -1,26 +0,0 @@ -package main - -import ( - "embed" - "github.com/wailsapp/wails/v3/pkg/application" -) - -//go:embed frontend/* -var assets embed.FS - -func main() { - app := application.New(application.Options{ - Name: "Performance API Demo", - Description: "Performance timing and metrics", - Assets: application.AssetOptions{ - Handler: application.BundledAssetFileServer(assets), - }, - }) - app.Window.NewWithOptions(application.WebviewWindowOptions{ - Title: "Performance API Demo", - Width: 900, - Height: 700, - URL: "/", - }) - app.Run() -} diff --git a/v3/examples/web-apis/permissions/frontend/index.html b/v3/examples/web-apis/permissions/frontend/index.html deleted file mode 100644 index b6c752617..000000000 --- a/v3/examples/web-apis/permissions/frontend/index.html +++ /dev/null @@ -1,512 +0,0 @@ - - - - - - Permissions API Demo - - - -
                -

                Permissions API Demo

                -

                - The Permissions API allows you to query and monitor the status of various browser permissions. - It provides a unified way to check whether permissions are granted, denied, or need to be requested. -

                - -
                - Permissions API: checking... -
                - -
                -

                Permission Summary

                -
                -
                - 0 - Granted -
                -
                - 0 - Denied -
                -
                - 0 - Prompt -
                -
                - -
                - -
                -

                Standard Permissions

                -

                - These are the commonly supported permission types across browsers. -

                -
                -
                - -
                -

                Extended Permissions

                -

                - These permissions may not be supported in all browsers or WebView implementations. -

                -
                -
                - -
                -

                Custom Permission Query

                -

                - Query any permission by name. Some permissions may require additional parameters. -

                -
                - - -
                -
                Enter a permission name and click Query to check its status...
                -
                - -
                -

                API Support

                -
                -
                - -
                -

                Event Log

                -
                Permission events will appear here...
                -
                -
                - -
                - - - - diff --git a/v3/examples/web-apis/permissions/main.go b/v3/examples/web-apis/permissions/main.go deleted file mode 100644 index 62da88fe0..000000000 --- a/v3/examples/web-apis/permissions/main.go +++ /dev/null @@ -1,26 +0,0 @@ -package main - -import ( - "embed" - "github.com/wailsapp/wails/v3/pkg/application" -) - -//go:embed frontend/* -var assets embed.FS - -func main() { - app := application.New(application.Options{ - Name: "Permissions API Demo", - Description: "Permission queries", - Assets: application.AssetOptions{ - Handler: application.BundledAssetFileServer(assets), - }, - }) - app.Window.NewWithOptions(application.WebviewWindowOptions{ - Title: "Permissions API Demo", - Width: 900, - Height: 700, - URL: "/", - }) - app.Run() -} diff --git a/v3/examples/web-apis/pointer-events/frontend/index.html b/v3/examples/web-apis/pointer-events/frontend/index.html deleted file mode 100644 index 0182d0a7d..000000000 --- a/v3/examples/web-apis/pointer-events/frontend/index.html +++ /dev/null @@ -1,579 +0,0 @@ - - - - - - Pointer Events API Demo - - - -
                -

                Pointer Events API Demo

                -

                - The Pointer Events API provides a unified way to handle input from mouse, touch, and pen/stylus - devices with a single event model, including pressure and tilt information. -

                - -
                - Pointer Events API: checking... -
                - -
                -

                API Support

                -
                -
                - -
                -

                Pointer Tracking

                -

                Move your mouse, touch, or use a stylus in the area below:

                -
                -
                -
                -
                Pointer ID
                -
                -
                -
                -
                -
                Pointer Type
                -
                -
                -
                -
                -
                Position (X, Y)
                -
                -, -
                -
                -
                -
                Pressure
                -
                -
                -
                -
                -
                Tilt (X, Y)
                -
                -, -
                -
                -
                -
                Width x Height
                -
                -
                -
                -
                -
                Twist
                -
                -
                -
                -
                -
                Buttons
                -
                -
                -
                -
                -
                -
                - -
                -

                Pressure-Sensitive Drawing

                -

                Draw with pressure sensitivity (size varies with pressure):

                -
                -
                - - -
                -
                - - - 8 -
                -
                - - -
                -
                -
                - - -
                - -
                - -
                -

                Pointer Capture Demo

                -

                Click and drag the box - it captures pointer events even outside itself:

                -
                -
                - Drag Me -
                -
                -
                -
                Capture Status
                -
                Not captured
                -
                -
                -
                -
                - -
                -

                Multi-Touch Points

                -

                Touch with multiple fingers (on touch devices):

                -
                -

                Active touch points: 0

                -
                - -
                -

                Event Log

                - -
                Pointer events will appear here...
                -
                -
                - - - - diff --git a/v3/examples/web-apis/pointer-events/main.go b/v3/examples/web-apis/pointer-events/main.go deleted file mode 100644 index 401b6b106..000000000 --- a/v3/examples/web-apis/pointer-events/main.go +++ /dev/null @@ -1,26 +0,0 @@ -package main - -import ( - "embed" - "github.com/wailsapp/wails/v3/pkg/application" -) - -//go:embed frontend/* -var assets embed.FS - -func main() { - app := application.New(application.Options{ - Name: "Pointer Events Demo", - Description: "Unified input handling", - Assets: application.AssetOptions{ - Handler: application.BundledAssetFileServer(assets), - }, - }) - app.Window.NewWithOptions(application.WebviewWindowOptions{ - Title: "Pointer Events Demo", - Width: 900, - Height: 700, - URL: "/", - }) - app.Run() -} diff --git a/v3/examples/web-apis/resize-observer/frontend/index.html b/v3/examples/web-apis/resize-observer/frontend/index.html deleted file mode 100644 index 4f108edbf..000000000 --- a/v3/examples/web-apis/resize-observer/frontend/index.html +++ /dev/null @@ -1,303 +0,0 @@ - - - - - - Resize Observer API Demo - - - -
                -

                Resize Observer API Demo

                -

                - The Resize Observer API provides a way to observe changes to the size of elements, - enabling responsive layouts without relying solely on media queries. -

                - -
                - Resize Observer: checking... -
                - -
                -

                Resizable Element

                -

                Drag the bottom-right corner to resize this element:

                -
                -
                Drag to resize me!
                -
                - Width: -- | Height: -- -
                -
                -
                - -
                -

                Responsive Component

                -

                This component changes based on its container size (not viewport):

                -
                -
                Small
                < 300px
                -
                Medium
                300-500px
                -
                Large
                > 500px
                -
                -
                -
                Resize the window to see me change
                -
                --
                -
                -
                - -
                -

                Aspect Ratio Monitor

                -

                This box displays its current aspect ratio:

                -
                - -- -
                -
                - -
                -

                Responsive Chart

                -

                This chart redraws when its container resizes:

                -
                -
                - -
                -

                Resize Events Log

                -
                Resize events will appear here...
                -
                -
                - - - - diff --git a/v3/examples/web-apis/resize-observer/main.go b/v3/examples/web-apis/resize-observer/main.go deleted file mode 100644 index b1818d2ec..000000000 --- a/v3/examples/web-apis/resize-observer/main.go +++ /dev/null @@ -1,29 +0,0 @@ -package main - -import ( - "embed" - - "github.com/wailsapp/wails/v3/pkg/application" -) - -//go:embed frontend/* -var assets embed.FS - -func main() { - app := application.New(application.Options{ - Name: "Resize Observer Demo", - Description: "Demonstrates the Resize Observer API", - Assets: application.AssetOptions{ - Handler: application.BundledAssetFileServer(assets), - }, - }) - - app.Window.NewWithOptions(application.WebviewWindowOptions{ - Title: "Resize Observer Demo", - Width: 800, - Height: 600, - URL: "/", - }) - - app.Run() -} diff --git a/v3/examples/web-apis/selection/frontend/index.html b/v3/examples/web-apis/selection/frontend/index.html deleted file mode 100644 index 2d7cd0fe7..000000000 --- a/v3/examples/web-apis/selection/frontend/index.html +++ /dev/null @@ -1,548 +0,0 @@ - - - - - - Selection API Demo - - - -
                -

                Selection API Demo

                -

                - The Selection API provides methods to programmatically select text, get the current selection, - and manipulate selected ranges within a document. -

                - -
                - Selection API: checking... -
                - -
                -

                API Support

                -
                -
                - -
                -

                Text Selection Monitor

                -

                Select any text in the paragraph below:

                -
                - The Selection API is a powerful browser feature that allows JavaScript to programmatically - interact with user text selections. It provides methods to get the currently selected text, - create new selections, modify existing selections, and respond to selection changes. - This API is essential for building rich text editors, annotation tools, and other - interactive text-based applications. Try selecting different parts of this text to see - the API in action! -
                -
                -
                -
                Selected Text
                -
                -
                -
                -
                -
                Character Count
                -
                0
                -
                -
                -
                Range Count
                -
                0
                -
                -
                -
                Selection Type
                -
                None
                -
                -
                -
                Is Collapsed
                -
                -
                -
                -
                -
                Anchor/Focus Offset
                -
                -, -
                -
                -
                -
                - -
                -

                Programmatic Selection

                -

                Select text programmatically by character position:

                -
                - ABCDEFGHIJKLMNOPQRSTUVWXYZ abcdefghijklmnopqrstuvwxyz 0123456789 -
                -
                - - - - - - - -
                -
                - -
                -

                Word Selection

                -

                Click a word to select it in the text:

                -
                - JavaScript provides powerful APIs for working with text selections in the browser. - The Selection and Range objects give developers fine-grained control over selected content. -
                -
                -
                - -
                -

                Selection Manipulation

                -

                Select text below, then apply actions:

                -
                - This is an editable area where you can select text and apply transformations. - Try selecting some text and clicking the buttons below to see the Selection API in action. - You can also type and edit the content directly. -
                -
                - - - - - - -
                -
                - -
                -

                Find and Select

                -

                Find and select text matches:

                -
                - The quick brown fox jumps over the lazy dog. The fox was very quick indeed. - A quick movement of the enemy will jeopardize five gunboats. - The five boxing wizards jump quickly. -
                -
                - - - - -
                -
                -
                - -
                -

                Event Log

                - -
                Selection events will appear here...
                -
                -
                - - - - diff --git a/v3/examples/web-apis/selection/main.go b/v3/examples/web-apis/selection/main.go deleted file mode 100644 index fe5caf580..000000000 --- a/v3/examples/web-apis/selection/main.go +++ /dev/null @@ -1,26 +0,0 @@ -package main - -import ( - "embed" - "github.com/wailsapp/wails/v3/pkg/application" -) - -//go:embed frontend/* -var assets embed.FS - -func main() { - app := application.New(application.Options{ - Name: "Selection API Demo", - Description: "Text selection handling", - Assets: application.AssetOptions{ - Handler: application.BundledAssetFileServer(assets), - }, - }) - app.Window.NewWithOptions(application.WebviewWindowOptions{ - Title: "Selection API Demo", - Width: 900, - Height: 700, - URL: "/", - }) - app.Run() -} diff --git a/v3/examples/web-apis/sessionstorage/frontend/index.html b/v3/examples/web-apis/sessionstorage/frontend/index.html deleted file mode 100644 index 90a917925..000000000 --- a/v3/examples/web-apis/sessionstorage/frontend/index.html +++ /dev/null @@ -1,385 +0,0 @@ - - - - - - Session Storage API Demo - - - -
                -

                Session Storage API Demo

                -

                - The Web Storage API provides sessionStorage for key-value storage that persists only - for the duration of the page session (until the tab or browser is closed). -

                - -
                - sessionStorage is available: checking... -
                - -
                -

                Store Data

                -
                - - -
                -
                - - -
                - - -
                - -
                -

                Stored Items (0)

                - - -
                  -
                  - -
                  -

                  Session vs Local Storage Comparison

                  -

                  Save the same key to both storages to compare behavior:

                  -
                  - - -
                  - - -
                  -
                  -

                  sessionStorage

                  -
                  -
                  -
                  -
                  -

                  localStorage

                  -
                  -
                  -
                  -
                  -

                  - Tip: Refresh the page or open a new tab to see the difference - sessionStorage is unique per tab! -

                  -
                  - -
                  -

                  Storage Info

                  -
                  -
                  - -
                  -

                  API Support

                  -
                  -
                  - -
                  -

                  Event Log

                  - -
                  Storage events will appear here... - -Note: Storage events fire when data is changed from ANOTHER tab/window of the same origin.
                  -
                  -
                  - - - - diff --git a/v3/examples/web-apis/sessionstorage/main.go b/v3/examples/web-apis/sessionstorage/main.go deleted file mode 100644 index 3beda3a5a..000000000 --- a/v3/examples/web-apis/sessionstorage/main.go +++ /dev/null @@ -1,26 +0,0 @@ -package main - -import ( - "embed" - "github.com/wailsapp/wails/v3/pkg/application" -) - -//go:embed frontend/* -var assets embed.FS - -func main() { - app := application.New(application.Options{ - Name: "Session Storage Demo", - Description: "sessionStorage API demonstration", - Assets: application.AssetOptions{ - Handler: application.BundledAssetFileServer(assets), - }, - }) - app.Window.NewWithOptions(application.WebviewWindowOptions{ - Title: "Session Storage Demo", - Width: 900, - Height: 700, - URL: "/", - }) - app.Run() -} diff --git a/v3/examples/web-apis/share/frontend/index.html b/v3/examples/web-apis/share/frontend/index.html deleted file mode 100644 index 47f5a9f17..000000000 --- a/v3/examples/web-apis/share/frontend/index.html +++ /dev/null @@ -1,503 +0,0 @@ - - - - - - Web Share API Demo - - - -
                  -

                  Web Share API Demo

                  -

                  - The Web Share API allows web applications to invoke the native sharing capabilities - of the device, enabling users to share text, URLs, and files to other apps. -

                  - -
                  - Web Share API: checking... -
                  - -
                  -

                  Share Text and URL

                  -
                  -
                  - - -
                  -
                  - - - - - - - -
                  - - -
                  -
                  - -
                  -

                  Share Files

                  -
                  -

                  Drag and drop files here or click to select

                  - -
                  -
                    - - -

                    - Note: File sharing requires the canShare() API to verify file types are supported. -

                    -
                    - -
                    -

                    Quick Share Examples

                    -
                    - - - - -
                    -
                    - -
                    -

                    API Support

                    -
                    -
                    - -
                    -

                    Event Log

                    -
                    Share events will appear here...
                    -
                    -
                    - -
                    - - - - diff --git a/v3/examples/web-apis/share/main.go b/v3/examples/web-apis/share/main.go deleted file mode 100644 index a253809d1..000000000 --- a/v3/examples/web-apis/share/main.go +++ /dev/null @@ -1,26 +0,0 @@ -package main - -import ( - "embed" - "github.com/wailsapp/wails/v3/pkg/application" -) - -//go:embed frontend/* -var assets embed.FS - -func main() { - app := application.New(application.Options{ - Name: "Web Share API Demo", - Description: "Native sharing", - Assets: application.AssetOptions{ - Handler: application.BundledAssetFileServer(assets), - }, - }) - app.Window.NewWithOptions(application.WebviewWindowOptions{ - Title: "Web Share API Demo", - Width: 900, - Height: 700, - URL: "/", - }) - app.Run() -} diff --git a/v3/examples/web-apis/speech-synthesis/frontend/index.html b/v3/examples/web-apis/speech-synthesis/frontend/index.html deleted file mode 100644 index d71b67130..000000000 --- a/v3/examples/web-apis/speech-synthesis/frontend/index.html +++ /dev/null @@ -1,656 +0,0 @@ - - - - - - Speech Synthesis API Demo - - - -
                    -

                    Speech Synthesis API Demo

                    -

                    - The Speech Synthesis API (Web Speech API) enables text-to-speech functionality, - allowing web applications to read text aloud using different voices and settings. -

                    - -
                    - Speech Synthesis API: checking... -
                    - -
                    -

                    API Support

                    -
                    -
                    - -
                    -

                    Text to Speech

                    - - - - - -
                    -
                    -
                    - -
                    -
                    - - -
                    -
                    - - -
                    -
                    - - -
                    -
                    - - -
                    -
                    - - - - - -
                    - -
                    -

                    Quick Phrases

                    -

                    Click a phrase to speak it immediately:

                    -
                    - - - - - - - - -
                    -
                    - -
                    -

                    Available Voices (0)

                    -
                    - -
                    -
                    -

                    Loading voices...

                    -
                    -
                    - -
                    -

                    Speech Queue Demo

                    -

                    Queue multiple utterances to be spoken in sequence:

                    - - - -
                    - Queue length: 0 utterances -
                    -
                    - -
                    -

                    Event Log

                    - -
                    Events will be logged here...
                    -
                    -
                    - - - - diff --git a/v3/examples/web-apis/speech-synthesis/main.go b/v3/examples/web-apis/speech-synthesis/main.go deleted file mode 100644 index e5e00fa2d..000000000 --- a/v3/examples/web-apis/speech-synthesis/main.go +++ /dev/null @@ -1,26 +0,0 @@ -package main - -import ( - "embed" - "github.com/wailsapp/wails/v3/pkg/application" -) - -//go:embed frontend/* -var assets embed.FS - -func main() { - app := application.New(application.Options{ - Name: "Speech Synthesis Demo", - Description: "Text-to-speech API", - Assets: application.AssetOptions{ - Handler: application.BundledAssetFileServer(assets), - }, - }) - app.Window.NewWithOptions(application.WebviewWindowOptions{ - Title: "Speech Synthesis Demo", - Width: 900, - Height: 700, - URL: "/", - }) - app.Run() -} diff --git a/v3/examples/web-apis/streams/frontend/index.html b/v3/examples/web-apis/streams/frontend/index.html deleted file mode 100644 index f0cfe26d1..000000000 --- a/v3/examples/web-apis/streams/frontend/index.html +++ /dev/null @@ -1,580 +0,0 @@ - - - - - - Streams API Demo - - - -
                    -

                    Streams API Demo

                    -

                    - The Streams API allows JavaScript to programmatically access streams of data, - enabling efficient processing of large data sets chunk by chunk without loading everything into memory. -

                    - -
                    - Streams API available: checking... -
                    - -
                    -

                    API Support

                    -
                    -
                    - -
                    -

                    ReadableStream Demo

                    -

                    - Create a custom ReadableStream that generates data chunks on demand. -

                    -
                    - - - - -
                    - - -
                    -
                    Click "Start ReadableStream" to begin...
                    -
                    - -
                    -

                    WritableStream Demo

                    -

                    - Create a WritableStream that processes and logs each written chunk. -

                    -
                    - - -
                    - -
                    Click "Write to Stream" to begin...
                    -
                    - -
                    -

                    TransformStream Demo

                    -

                    - Transform data as it flows through a stream pipeline. -

                    -
                    - - -
                    -
                    - - -
                    - -
                    Click "Transform" to see the result...
                    -
                    - -
                    -

                    Pipe Chain Demo

                    -

                    - Chain multiple transforms together using pipeThrough and pipeTo. -

                    -
                    - - -
                    - -

                    - Pipeline: Input -> Split into chars -> Uppercase -> Add index -> Collect -

                    -
                    Click "Run Pipe Chain" to see the result...
                    -
                    - -
                    -

                    Fetch with Streams

                    -

                    - Use streams to process fetch response body progressively. -

                    -
                    - - -
                    - - -
                    -
                    Click "Fetch with Stream" to begin...
                    -
                    - -
                    -

                    Event Log

                    - -
                    -
                    Ready to log stream events...
                    -
                    -
                    -
                    - - - - diff --git a/v3/examples/web-apis/streams/main.go b/v3/examples/web-apis/streams/main.go deleted file mode 100644 index d1dc4048a..000000000 --- a/v3/examples/web-apis/streams/main.go +++ /dev/null @@ -1,26 +0,0 @@ -package main - -import ( - "embed" - "github.com/wailsapp/wails/v3/pkg/application" -) - -//go:embed frontend/* -var assets embed.FS - -func main() { - app := application.New(application.Options{ - Name: "Streams API Demo", - Description: "Readable and writable streams", - Assets: application.AssetOptions{ - Handler: application.BundledAssetFileServer(assets), - }, - }) - app.Window.NewWithOptions(application.WebviewWindowOptions{ - Title: "Streams API Demo", - Width: 900, - Height: 700, - URL: "/", - }) - app.Run() -} diff --git a/v3/examples/web-apis/vibration/frontend/index.html b/v3/examples/web-apis/vibration/frontend/index.html deleted file mode 100644 index 0aa429b17..000000000 --- a/v3/examples/web-apis/vibration/frontend/index.html +++ /dev/null @@ -1,581 +0,0 @@ - - - - - - Vibration API Demo - - - -
                    -

                    Vibration API Demo

                    -

                    - The Vibration API provides access to the device's vibration hardware. - It allows triggering single vibrations or complex patterns of vibrations and pauses. -

                    - -
                    - Vibration API: checking... -
                    - -
                    -

                    Quick Vibrations

                    - - - - - -
                    - -
                    -

                    Vibration Presets

                    -
                    -
                    -
                    *
                    -
                    Notification
                    -
                    [100, 50, 100]
                    -
                    -
                    -
                    +
                    -
                    Success
                    -
                    [50, 50, 50, 50, 200]
                    -
                    -
                    -
                    !
                    -
                    Error
                    -
                    [200, 100, 200, 100, 200]
                    -
                    -
                    -
                    ?
                    -
                    Warning
                    -
                    [100, 100, 100]
                    -
                    -
                    -
                    <3
                    -
                    Heartbeat
                    -
                    [100, 100, 100, 400]
                    -
                    -
                    -
                    SOS
                    -
                    SOS
                    -
                    [100,50,100,50,100,200,...]
                    -
                    -
                    -
                    ~
                    -
                    Ringtone
                    -
                    [300, 200, 300, 200, ...]
                    -
                    -
                    -
                    3-2-1
                    -
                    Countdown
                    -
                    [100, 900, 100, 900, ...]
                    -
                    -
                    -
                    - -
                    -

                    Pattern Builder

                    -
                    -
                    - Click buttons below to build a pattern... -
                    - -
                    -
                    - - - ms -
                    - - - -
                    - -
                    - - - -
                    - -
                    -
                    -
                    -
                    -
                    - -
                    -

                    Haptic Pad

                    -

                    - Tap the buttons for different haptic feedback -

                    -
                    - - - - - - - - - -
                    -
                    - -
                    -

                    Event Log

                    -
                    -
                    Waiting for vibration events...
                    -
                    -
                    -
                    - - - - diff --git a/v3/examples/web-apis/vibration/main.go b/v3/examples/web-apis/vibration/main.go deleted file mode 100644 index 4ec2d52c1..000000000 --- a/v3/examples/web-apis/vibration/main.go +++ /dev/null @@ -1,26 +0,0 @@ -package main - -import ( - "embed" - "github.com/wailsapp/wails/v3/pkg/application" -) - -//go:embed frontend/* -var assets embed.FS - -func main() { - app := application.New(application.Options{ - Name: "Vibration API Demo", - Description: "Device vibration patterns", - Assets: application.AssetOptions{ - Handler: application.BundledAssetFileServer(assets), - }, - }) - app.Window.NewWithOptions(application.WebviewWindowOptions{ - Title: "Vibration API Demo", - Width: 900, - Height: 700, - URL: "/", - }) - app.Run() -} diff --git a/v3/examples/web-apis/web-components/frontend/index.html b/v3/examples/web-apis/web-components/frontend/index.html deleted file mode 100644 index 94d97b53a..000000000 --- a/v3/examples/web-apis/web-components/frontend/index.html +++ /dev/null @@ -1,518 +0,0 @@ - - - - - - Web Components API Demo - - - -
                    -

                    Web Components API Demo

                    -

                    - Web Components is a suite of APIs allowing you to create reusable custom elements with encapsulated - functionality using Custom Elements, Shadow DOM, and HTML Templates. -

                    - -
                    - Web Components API: checking... -
                    - -
                    -

                    API Support

                    -
                    -
                    - -
                    -

                    Custom Element Demo: <wails-card>

                    -

                    A custom card element with Shadow DOM encapsulation:

                    -
                    - - This is content inside a custom Web Component. The styling is encapsulated via Shadow DOM. - -
                    -
                    - - Different theme variant using the same component. - -
                    -
                    - - - -
                    -
                    -
                    - -
                    -

                    Custom Element Demo: <wails-counter>

                    -

                    A stateful counter component with reactive attributes:

                    -
                    - -
                    -
                    - -
                    -
                    - -
                    -

                    HTML Template Demo

                    -

                    Using <template> for efficient cloning:

                    - - - - -
                    -
                    - -
                    -

                    Slot Demo: <wails-panel>

                    -

                    Named slots for flexible content composition:

                    -
                    - - Panel Header -

                    This is the default slot content - the main body of the panel.

                    - Panel Footer - Created with Web Components -
                    -
                    -
                    - -
                    -

                    Event Log

                    - -
                    Component events will appear here...
                    -
                    -
                    - - - - diff --git a/v3/examples/web-apis/web-components/main.go b/v3/examples/web-apis/web-components/main.go deleted file mode 100644 index 2aea17c41..000000000 --- a/v3/examples/web-apis/web-components/main.go +++ /dev/null @@ -1,26 +0,0 @@ -package main - -import ( - "embed" - "github.com/wailsapp/wails/v3/pkg/application" -) - -//go:embed frontend/* -var assets embed.FS - -func main() { - app := application.New(application.Options{ - Name: "Web Components Demo", - Description: "Custom elements and Shadow DOM", - Assets: application.AssetOptions{ - Handler: application.BundledAssetFileServer(assets), - }, - }) - app.Window.NewWithOptions(application.WebviewWindowOptions{ - Title: "Web Components Demo", - Width: 900, - Height: 700, - URL: "/", - }) - app.Run() -} diff --git a/v3/examples/web-apis/webaudio/frontend/index.html b/v3/examples/web-apis/webaudio/frontend/index.html deleted file mode 100644 index 344398d89..000000000 --- a/v3/examples/web-apis/webaudio/frontend/index.html +++ /dev/null @@ -1,402 +0,0 @@ - - - - - - Web Audio API Demo - - - -
                    -

                    Web Audio API Demo

                    -

                    - The Web Audio API provides a powerful system for controlling audio, - allowing developers to generate, process, and analyze audio in real time. -

                    - -
                    - Web Audio API supported: checking... -
                    - -
                    -

                    Oscillator Synthesizer

                    -
                    -
                    - - -
                    -
                    - - -
                    -
                    - - -
                    -
                    - - -
                    - -
                    -

                    Piano Keyboard

                    -

                    Click keys or use keyboard: A S D F G H J K

                    -
                    -
                    C
                    -
                    C#
                    -
                    D
                    -
                    D#
                    -
                    E
                    -
                    F
                    -
                    F#
                    -
                    G
                    -
                    G#
                    -
                    A
                    -
                    A#
                    -
                    B
                    -
                    C
                    -
                    -
                    - -
                    -

                    Audio Visualizer

                    - - - -
                    - -
                    -

                    Sound Effects

                    - - - - -
                    -
                    - - - - diff --git a/v3/examples/web-apis/webaudio/main.go b/v3/examples/web-apis/webaudio/main.go deleted file mode 100644 index 6c672060c..000000000 --- a/v3/examples/web-apis/webaudio/main.go +++ /dev/null @@ -1,29 +0,0 @@ -package main - -import ( - "embed" - - "github.com/wailsapp/wails/v3/pkg/application" -) - -//go:embed frontend/* -var assets embed.FS - -func main() { - app := application.New(application.Options{ - Name: "Web Audio Demo", - Description: "Demonstrates the Web Audio API for audio processing", - Assets: application.AssetOptions{ - Handler: application.BundledAssetFileServer(assets), - }, - }) - - app.Window.NewWithOptions(application.WebviewWindowOptions{ - Title: "Web Audio Demo", - Width: 800, - Height: 600, - URL: "/", - }) - - app.Run() -} diff --git a/v3/examples/web-apis/webcrypto/frontend/index.html b/v3/examples/web-apis/webcrypto/frontend/index.html deleted file mode 100644 index bfd68155b..000000000 --- a/v3/examples/web-apis/webcrypto/frontend/index.html +++ /dev/null @@ -1,354 +0,0 @@ - - - - - - Web Crypto API Demo - - - -
                    -

                    Web Crypto API Demo

                    -

                    - The Web Cryptography API provides cryptographic operations including hashing, - signature generation, encryption/decryption, and key management. -

                    - -
                    - Web Crypto API: checking... -
                    - -
                    -

                    Random Values

                    - - - - -
                    Click a button to generate random values...
                    -
                    - -
                    -

                    Hash Functions

                    - - -
                    -
                    - - -
                    -
                    - -
                    Hash will appear here...
                    -
                    - -
                    -

                    Symmetric Encryption (AES-GCM)

                    - - - - - - -
                    Encrypted/decrypted data will appear here...
                    -
                    - -
                    -

                    Digital Signatures (ECDSA)

                    - - - - - -
                    Generate a key pair first...
                    -
                    - -
                    -

                    HMAC

                    - - - - - -
                    HMAC will appear here...
                    -
                    -
                    - - - - diff --git a/v3/examples/web-apis/webcrypto/main.go b/v3/examples/web-apis/webcrypto/main.go deleted file mode 100644 index 116259b72..000000000 --- a/v3/examples/web-apis/webcrypto/main.go +++ /dev/null @@ -1,29 +0,0 @@ -package main - -import ( - "embed" - - "github.com/wailsapp/wails/v3/pkg/application" -) - -//go:embed frontend/* -var assets embed.FS - -func main() { - app := application.New(application.Options{ - Name: "Web Crypto Demo", - Description: "Demonstrates the Web Cryptography API", - Assets: application.AssetOptions{ - Handler: application.BundledAssetFileServer(assets), - }, - }) - - app.Window.NewWithOptions(application.WebviewWindowOptions{ - Title: "Web Crypto Demo", - Width: 800, - Height: 600, - URL: "/", - }) - - app.Run() -} diff --git a/v3/examples/web-apis/webgl/frontend/index.html b/v3/examples/web-apis/webgl/frontend/index.html deleted file mode 100644 index 43e64516c..000000000 --- a/v3/examples/web-apis/webgl/frontend/index.html +++ /dev/null @@ -1,386 +0,0 @@ - - - - - - WebGL API Demo - - - -
                    -

                    WebGL API Demo

                    -

                    - WebGL enables rendering interactive 2D and 3D graphics in the browser - using the GPU for hardware-accelerated rendering. -

                    - -
                    - WebGL: checking... -
                    - -
                    -

                    3D Rotating Cube

                    -
                    -
                    - - -
                    -
                    - - -
                    -
                    - - -
                    -
                    -
                    - - -
                    - -
                    - -
                    -

                    WebGL Info

                    -
                    -
                    -
                    - - - - diff --git a/v3/examples/web-apis/webgl/main.go b/v3/examples/web-apis/webgl/main.go deleted file mode 100644 index 65ce347c5..000000000 --- a/v3/examples/web-apis/webgl/main.go +++ /dev/null @@ -1,29 +0,0 @@ -package main - -import ( - "embed" - - "github.com/wailsapp/wails/v3/pkg/application" -) - -//go:embed frontend/* -var assets embed.FS - -func main() { - app := application.New(application.Options{ - Name: "WebGL Demo", - Description: "Demonstrates the WebGL API for 3D graphics", - Assets: application.AssetOptions{ - Handler: application.BundledAssetFileServer(assets), - }, - }) - - app.Window.NewWithOptions(application.WebviewWindowOptions{ - Title: "WebGL Demo", - Width: 800, - Height: 600, - URL: "/", - }) - - app.Run() -} diff --git a/v3/examples/web-apis/websocket/frontend/index.html b/v3/examples/web-apis/websocket/frontend/index.html deleted file mode 100644 index 02f14c3a9..000000000 --- a/v3/examples/web-apis/websocket/frontend/index.html +++ /dev/null @@ -1,302 +0,0 @@ - - - - - - WebSocket API Demo - - - -
                    -

                    WebSocket API Demo

                    -

                    - WebSocket provides full-duplex communication channels over a single TCP connection, - enabling real-time data exchange between client and server. -

                    - -
                    -
                    - WebSocket: Disconnected -
                    - -
                    -

                    Connection

                    -
                    -
                    - - -
                    -
                    - - -

                    - Try: wss://echo.websocket.org (echo server) or wss://ws.postman-echo.com/raw -

                    -
                    - -
                    -

                    Send Message

                    -
                    -
                    - - -
                    - -
                    -
                    - -
                    -

                    Messages

                    - -
                    -
                    - Connect to a WebSocket server to start... -
                    -
                    -
                    - -
                    -

                    WebSocket API Reference

                    -
                    -// Create connection -const ws = new WebSocket('wss://example.com/socket'); - -// Connection opened -ws.onopen = (event) => { - console.log('Connected'); - ws.send('Hello Server!'); -}; - -// Listen for messages -ws.onmessage = (event) => { - console.log('Received:', event.data); -}; - -// Connection closed -ws.onclose = (event) => { - console.log('Disconnected', event.code, event.reason); -}; - -// Error handling -ws.onerror = (error) => { - console.error('WebSocket error:', error); -}; - -// Send data -ws.send('text message'); -ws.send(new Blob(['binary data'])); -ws.send(new ArrayBuffer(8)); - -// Close connection -ws.close(1000, 'Normal closure'); - -// Properties -ws.readyState // 0=CONNECTING, 1=OPEN, 2=CLOSING, 3=CLOSED -ws.bufferedAmount // Bytes queued for transmission -ws.protocol // Selected sub-protocol -ws.url // WebSocket URL
                    -
                    -
                    - - - - diff --git a/v3/examples/web-apis/websocket/main.go b/v3/examples/web-apis/websocket/main.go deleted file mode 100644 index 806d7e8da..000000000 --- a/v3/examples/web-apis/websocket/main.go +++ /dev/null @@ -1,29 +0,0 @@ -package main - -import ( - "embed" - - "github.com/wailsapp/wails/v3/pkg/application" -) - -//go:embed frontend/* -var assets embed.FS - -func main() { - app := application.New(application.Options{ - Name: "WebSocket Demo", - Description: "Demonstrates the WebSocket API for real-time communication", - Assets: application.AssetOptions{ - Handler: application.BundledAssetFileServer(assets), - }, - }) - - app.Window.NewWithOptions(application.WebviewWindowOptions{ - Title: "WebSocket Demo", - Width: 800, - Height: 600, - URL: "/", - }) - - app.Run() -} diff --git a/v3/examples/web-apis/webworkers/frontend/index.html b/v3/examples/web-apis/webworkers/frontend/index.html deleted file mode 100644 index 546d5d400..000000000 --- a/v3/examples/web-apis/webworkers/frontend/index.html +++ /dev/null @@ -1,373 +0,0 @@ - - - - - - Web Workers API Demo - - - -
                    -

                    Web Workers API Demo

                    -

                    - Web Workers allow JavaScript to run in background threads, - enabling CPU-intensive tasks without blocking the UI. -

                    - -
                    - Web Workers: checking... -
                    - -
                    -

                    Prime Number Calculator

                    -

                    - Calculate prime numbers up to a given limit. Try with/without a worker to see the difference. -

                    - - -
                    -
                    - This animation should stay smooth when using a worker -
                    - - - -
                    -
                    -
                    -
                    Results will appear here...
                    -
                    - -
                    -

                    Fibonacci Calculator

                    -

                    - Calculate Fibonacci numbers using a dedicated worker. -

                    - - - -
                    Result will appear here...
                    -
                    - -
                    -

                    Message Passing

                    -

                    - Send custom messages to a worker and receive responses. -

                    - - - -
                    Messages will appear here...
                    -
                    - -
                    -

                    API Support

                    -
                    -
                    -
                    - - - - diff --git a/v3/examples/web-apis/webworkers/main.go b/v3/examples/web-apis/webworkers/main.go deleted file mode 100644 index 2fbd516bd..000000000 --- a/v3/examples/web-apis/webworkers/main.go +++ /dev/null @@ -1,29 +0,0 @@ -package main - -import ( - "embed" - - "github.com/wailsapp/wails/v3/pkg/application" -) - -//go:embed frontend/* -var assets embed.FS - -func main() { - app := application.New(application.Options{ - Name: "Web Workers Demo", - Description: "Demonstrates Web Workers for background processing", - Assets: application.AssetOptions{ - Handler: application.BundledAssetFileServer(assets), - }, - }) - - app.Window.NewWithOptions(application.WebviewWindowOptions{ - Title: "Web Workers Demo", - Width: 800, - Height: 600, - URL: "/", - }) - - app.Run() -} diff --git a/v3/examples/web-apis/xmlhttprequest/frontend/index.html b/v3/examples/web-apis/xmlhttprequest/frontend/index.html deleted file mode 100644 index 9d75d15b9..000000000 --- a/v3/examples/web-apis/xmlhttprequest/frontend/index.html +++ /dev/null @@ -1,496 +0,0 @@ - - - - - - XMLHttpRequest API Demo - - - -
                    -

                    XMLHttpRequest API Demo

                    -

                    - XMLHttpRequest (XHR) is the classic API for making HTTP requests in JavaScript. - It provides detailed control over request/response handling with event-based progress tracking. -

                    - -
                    - XMLHttpRequest API available: checking... -
                    - -
                    -

                    Make Request

                    -
                    -
                    - - -
                    -
                    - - -
                    -
                    -
                    - - -
                    -
                    - - -
                    -
                    - -
                    - - - - - - -
                    - -
                    -

                    Response

                    - - -
                    - - -
                    -
                    Make a request to see the response...
                    - -
                    - -
                    -

                    Event Log

                    - -
                    -
                    - --:--:-- - INFO - Ready to make requests... -
                    -
                    -
                    - -
                    -

                    XMLHttpRequest API Reference

                    -
                    -// Create request -const xhr = new XMLHttpRequest(); - -// Configure request -xhr.open('GET', 'https://api.example.com/data', true); // async=true - -// Set headers -xhr.setRequestHeader('Content-Type', 'application/json'); -xhr.setRequestHeader('X-Custom-Header', 'value'); - -// Event handlers -xhr.onreadystatechange = () => { - // 0=UNSENT, 1=OPENED, 2=HEADERS_RECEIVED, 3=LOADING, 4=DONE - console.log('Ready state:', xhr.readyState); -}; - -xhr.onload = () => console.log('Load complete'); -xhr.onerror = () => console.log('Network error'); -xhr.onprogress = (e) => console.log(`Progress: ${e.loaded}/${e.total}`); -xhr.onabort = () => console.log('Request aborted'); -xhr.ontimeout = () => console.log('Request timed out'); - -// Response properties -xhr.status // HTTP status code (200, 404, etc.) -xhr.statusText // Status text ("OK", "Not Found", etc.) -xhr.responseText // Response as text -xhr.responseXML // Response as XML document -xhr.response // Response based on responseType -xhr.responseType // '', 'arraybuffer', 'blob', 'document', 'json', 'text' - -// Send request -xhr.send(); // GET/DELETE -xhr.send('data'); // POST/PUT with string -xhr.send(new FormData(formElement)); // POST with form data -xhr.send(JSON.stringify({key: 'value'})); // POST with JSON - -// Abort request -xhr.abort();
                    -
                    -
                    - - - - diff --git a/v3/examples/web-apis/xmlhttprequest/main.go b/v3/examples/web-apis/xmlhttprequest/main.go deleted file mode 100644 index 38d530e25..000000000 --- a/v3/examples/web-apis/xmlhttprequest/main.go +++ /dev/null @@ -1,26 +0,0 @@ -package main - -import ( - "embed" - "github.com/wailsapp/wails/v3/pkg/application" -) - -//go:embed frontend/* -var assets embed.FS - -func main() { - app := application.New(application.Options{ - Name: "XMLHttpRequest Demo", - Description: "Classic XHR API demonstration", - Assets: application.AssetOptions{ - Handler: application.BundledAssetFileServer(assets), - }, - }) - app.Window.NewWithOptions(application.WebviewWindowOptions{ - Title: "XMLHttpRequest Demo", - Width: 900, - Height: 700, - URL: "/", - }) - app.Run() -} diff --git a/v3/examples/websocket-transport/GreetService.go b/v3/examples/websocket-transport/GreetService.go deleted file mode 100644 index bdb21a277..000000000 --- a/v3/examples/websocket-transport/GreetService.go +++ /dev/null @@ -1,73 +0,0 @@ -package main - -import ( - "context" - "fmt" - "sync" - "time" - - "github.com/wailsapp/wails/v3/pkg/application" -) - -// GreetService is a service that demonstrates bound methods over WebSocket transport -type GreetService struct { - mu sync.Mutex - greetCount int - app *application.App -} - -// ServiceStartup is called when the service is initialized -func (g *GreetService) ServiceStartup(ctx context.Context, options application.ServiceOptions) error { - g.app = application.Get() - - // Start a timer that emits events every second - // This demonstrates automatic event forwarding to WebSocket transport - go func() { - ticker := time.NewTicker(1 * time.Second) - defer ticker.Stop() - - for { - select { - case <-ctx.Done(): - return - case t := <-ticker.C: - // Emit a timer event - automatically forwarded to WebSocket! - g.app.Event.Emit("timer:tick", t.Format("15:04:05")) - } - } - }() - - return nil -} - -// Greet greets a person by name and emits an event -func (g *GreetService) Greet(name string) string { - g.mu.Lock() - g.greetCount++ - count := g.greetCount - g.mu.Unlock() - result := fmt.Sprintf("Hello, %s! (Greeted %d times via WebSocket)", name, count) - - // Emit an event to demonstrate event support over WebSocket - // Events are automatically forwarded to the WebSocket transport! - if g.app != nil { - g.app.Event.Emit("greet:count", count) - } - - return result -} - -// GetTime returns the current server time -func (g *GreetService) GetTime() string { - return time.Now().Format("2006-01-02 15:04:05") -} - -// Echo echoes back the input message -func (g *GreetService) Echo(message string) string { - return "Echo: " + message -} - -// Add adds two numbers together -func (g *GreetService) Add(a, b int) int { - return a + b -} diff --git a/v3/examples/websocket-transport/README.md b/v3/examples/websocket-transport/README.md deleted file mode 100644 index d66170eb1..000000000 --- a/v3/examples/websocket-transport/README.md +++ /dev/null @@ -1,113 +0,0 @@ -# WebSocket Transport Example - -This example demonstrates how to use a custom transport like WebSocket for Wails IPC instead of the default HTTP fetch transport. All Wails bindings and features work identically - only the underlying transport layer changes. - -## What This Example Shows - -- How to configure a WebSocket transport on the backend using `NewWebSocketTransport()` -- How to override the runtime transport on the frontend using `setTransport()` and `createWebSocketTransport()` -- Full compatibility with generated bindings - no code generation changes needed -- Real-time connection status monitoring -- Automatic reconnection handling - -## Architecture - -```text -┌─────────────────────────────────────────┐ -│ Frontend (JavaScript) │ -│ - setTransport(wsTransport) │ -│ - All bindings work unchanged │ -└───────────────┬─────────────────────────┘ - │ - │ WebSocket (ws://localhost:9099) - │ -┌───────────────▼─────────────────────────┐ -│ Backend (Go) │ -│ - WebSocketTransport on port 9099 │ -│ - Standard MessageProcessor │ -│ - All Wails features available │ -└─────────────────────────────────────────┘ -``` - -## How to Run - -1. Navigate to this directory: - ```bash - cd v3/examples/websocket-transport - ``` - -2. Run the example: - ```bash - go run . - ``` - -3. The application will start with: - - WebView window displaying the UI - - WebSocket server listening on `ws://localhost:9099/wails/ws` - - Real-time connection status indicator - -## Backend Setup - -The backend configuration is simple - just pass a `WebSocketTransport` to the application options: - -```go -// Create WebSocket transport on port 9099 -wsTransport := NewWebSocketTransport(":9099") - -app := application.New(application.Options{ - Name: "WebSocket Transport Example", - Services: []application.Service{ - application.NewService(&GreetService{}), - }, - Assets: application.AssetOptions{ - Handler: application.BundledAssetFileServer(assets), - }, - // Use WebSocket transport instead of default HTTP - Transport: wsTransport, -}) -``` - -## Frontend Setup - -The frontend uses the WebSocket transport with **generated bindings**: - -```typescript -import { setTransport } from "/wails/runtime.js"; -import { createWebSocketTransport } from "/websocket-transport.js"; -import { GreetService } from "/bindings/github.com/wailsapp/wails/v3/examples/websocket-transport/index.js"; - -// Create and configure WebSocket transport -const wsTransport = createWebSocketTransport('ws://localhost:9099/wails/ws', { - reconnectDelay: 2000, // Reconnect after 2 seconds if disconnected - requestTimeout: 30000 // Request timeout of 30 seconds -}); - -// Set as the active transport -setTransport(wsTransport); - -// Now all generated bindings use WebSocket instead of HTTP fetch! -const result = await GreetService.Greet("World"); -``` - -**Key Point**: The generated bindings (`GreetService.Greet()`, `GreetService.Echo()`, etc.) automatically use whatever transport is configured via `setTransport()`. This proves the custom transport hijack works seamlessly with Wails code generation! - -## Features Demonstrated - -### 1. Generated Bindings with Custom Transport -All generated bindings work identically with WebSocket transport: -- `GreetService.Greet(name)` - Simple string parameter and return -- `GreetService.Echo(message)` - Echo back messages -- `GreetService.Add(a, b)` - Multiple parameters with numeric types -- `GreetService.GetTime()` - No parameters, string return - -### 2. Connection Management -- Automatic connection establishment on startup -- Visual connection status indicator (green = connected, red = disconnected) -- Automatic reconnection with configurable delay -- Graceful handling of connection failures - -### 3. Error Handling -- Request timeouts -- Connection errors -- Backend method errors -- All propagate correctly to the frontend diff --git a/v3/examples/websocket-transport/assets/bindings/github.com/wailsapp/wails/v3/examples/websocket-transport/greetservice.js b/v3/examples/websocket-transport/assets/bindings/github.com/wailsapp/wails/v3/examples/websocket-transport/greetservice.js deleted file mode 100644 index ffdc9c702..000000000 --- a/v3/examples/websocket-transport/assets/bindings/github.com/wailsapp/wails/v3/examples/websocket-transport/greetservice.js +++ /dev/null @@ -1,48 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is a service that demonstrates bound methods over WebSocket transport - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -/** - * Add adds two numbers together - * @param {number} a - * @param {number} b - * @returns {$CancellablePromise} - */ -export function Add(a, b) { - return $Call.ByID(1578108007, a, b); -} - -/** - * Echo echoes back the input message - * @param {string} message - * @returns {$CancellablePromise} - */ -export function Echo(message) { - return $Call.ByID(1259920061, message); -} - -/** - * GetTime returns the current server time - * @returns {$CancellablePromise} - */ -export function GetTime() { - return $Call.ByID(570467169); -} - -/** - * Greet greets a person by name - * @param {string} name - * @returns {$CancellablePromise} - */ -export function Greet(name) { - return $Call.ByID(1411160069, name); -} diff --git a/v3/examples/websocket-transport/assets/bindings/github.com/wailsapp/wails/v3/examples/websocket-transport/index.js b/v3/examples/websocket-transport/assets/bindings/github.com/wailsapp/wails/v3/examples/websocket-transport/index.js deleted file mode 100644 index fdf1ff435..000000000 --- a/v3/examples/websocket-transport/assets/bindings/github.com/wailsapp/wails/v3/examples/websocket-transport/index.js +++ /dev/null @@ -1,8 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; diff --git a/v3/examples/websocket-transport/assets/index.html b/v3/examples/websocket-transport/assets/index.html deleted file mode 100644 index 5672616f7..000000000 --- a/v3/examples/websocket-transport/assets/index.html +++ /dev/null @@ -1,353 +0,0 @@ - - - - - - WebSocket Transport Example - - - -
                    -

                    🚀 WebSocket Transport Example

                    -

                    Custom IPC transport using WebSockets instead of HTTP fetch

                    - -
                    -

                    Connection Status

                    -
                    - Disconnected -
                    -
                    - ℹ️ Transport Info: - This example uses a custom WebSocket transport running on ws://localhost:9099/wails/ws - instead of the default HTTP fetch-based transport. All Wails generated bindings work identically! -

                    - The methods below use GreetService.Greet(), GreetService.Echo(), etc. from the generated bindings, - proving that custom transports work seamlessly with Wails code generation. -
                    -
                    - -
                    -

                    🕐 Server Timer (Auto-updating via Events)

                    -
                    - Waiting for timer... -
                    -
                    - ✨ Automatic Event Forwarding: - The server emits a timer:tick event every second. Because the WebSocket transport - implements EventTransport, these events are automatically forwarded to - the frontend with zero manual wiring code! -
                    -
                    - -
                    -

                    Test Dialog

                    -
                    - -
                    -
                    Click "Open" to test the binding...
                    -
                    - -
                    -

                    Test Greet Method (with Events)

                    -
                    - - -
                    -
                    Click "Greet" to test the binding...
                    -
                    - 📡 Event Counter: - 0 (Updates via WebSocket events) -
                    -
                    - -
                    -

                    Test Echo Method

                    -
                    - - -
                    -
                    Click "Echo" to test...
                    -
                    - -
                    -

                    Test Add Method

                    -
                    - - - -
                    -
                    Click "Add" to calculate...
                    -
                    - -
                    -

                    Test GetTime Method

                    - -
                    Click to get current server time...
                    -
                    -
                    - - - - diff --git a/v3/examples/websocket-transport/frontend/bindings/github.com/wailsapp/wails/v3/examples/websocket-transport/greetservice.js b/v3/examples/websocket-transport/frontend/bindings/github.com/wailsapp/wails/v3/examples/websocket-transport/greetservice.js deleted file mode 100644 index 2e837223c..000000000 --- a/v3/examples/websocket-transport/frontend/bindings/github.com/wailsapp/wails/v3/examples/websocket-transport/greetservice.js +++ /dev/null @@ -1,48 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is a service that demonstrates bound methods over WebSocket transport - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -/** - * Add adds two numbers together - * @param {number} a - * @param {number} b - * @returns {$CancellablePromise} - */ -export function Add(a, b) { - return $Call.ByID(1578108007, a, b); -} - -/** - * Echo echoes back the input message - * @param {string} message - * @returns {$CancellablePromise} - */ -export function Echo(message) { - return $Call.ByID(1259920061, message); -} - -/** - * GetTime returns the current server time - * @returns {$CancellablePromise} - */ -export function GetTime() { - return $Call.ByID(570467169); -} - -/** - * Greet greets a person by name - * @param {string} name - * @returns {$CancellablePromise} - */ -export function Greet(name) { - return $Call.ByID(1411160069, name); -} diff --git a/v3/examples/websocket-transport/frontend/bindings/github.com/wailsapp/wails/v3/examples/websocket-transport/index.js b/v3/examples/websocket-transport/frontend/bindings/github.com/wailsapp/wails/v3/examples/websocket-transport/index.js deleted file mode 100644 index fdf1ff435..000000000 --- a/v3/examples/websocket-transport/frontend/bindings/github.com/wailsapp/wails/v3/examples/websocket-transport/index.js +++ /dev/null @@ -1,8 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; diff --git a/v3/examples/websocket-transport/main.go b/v3/examples/websocket-transport/main.go deleted file mode 100644 index 3105d2231..000000000 --- a/v3/examples/websocket-transport/main.go +++ /dev/null @@ -1,56 +0,0 @@ -package main - -import ( - "embed" - "log" - - "github.com/wailsapp/wails/v3/pkg/application" -) - -//go:embed assets/* -var assets embed.FS - -func main() { - // Create WebSocket transport on port 9099 - wsTransport := NewWebSocketTransport(":9099") - - app := application.New(application.Options{ - Name: "WebSocket Transport Example", - Description: "Example demonstrating custom WebSocket-based IPC transport with event support", - Services: []application.Service{ - application.NewService(&GreetService{}), - }, - Assets: application.AssetOptions{ - Handler: application.BundledAssetFileServer(assets), - }, - Mac: application.MacOptions{ - ApplicationShouldTerminateAfterLastWindowClosed: true, - }, - // Use WebSocket transport instead of default HTTP - // Events are automatically forwarded to the transport since it implements EventTransport - Transport: wsTransport, - }) - - // ✨ NO MANUAL EVENT WIRING NEEDED! ✨ - // Events are automatically forwarded to the WebSocket transport because it implements - // the EventTransport interface. The following code is no longer necessary: - // - // app.Events.On("greet:count", func(event *application.WailsEvent) { - // wsTransport.SendEvent(event) - // }) - // - // All events emitted via app.Events.Emit() are automatically broadcast to connected clients! - - app.Window.NewWithOptions(application.WebviewWindowOptions{ - Title: "WebSocket Transport Example", - URL: "/", - Width: 800, - Height: 600, - DevToolsEnabled: true, - }) - - err := app.Run() - if err != nil { - log.Fatal(err) - } -} diff --git a/v3/examples/websocket-transport/transport_websocket.go b/v3/examples/websocket-transport/transport_websocket.go deleted file mode 100644 index 482e7319c..000000000 --- a/v3/examples/websocket-transport/transport_websocket.go +++ /dev/null @@ -1,261 +0,0 @@ -package main - -import ( - "context" - _ "embed" - "log" - "net/http" - "sync" - - "github.com/gorilla/websocket" - "github.com/wailsapp/wails/v3/pkg/application" -) - -//go:embed websocket-transport.js -var jsClient []byte - -// WebSocketTransport is an example implementation of a WebSocket-based transport. -// This demonstrates how to create a custom transport that can replace the default -// HTTP fetch-based IPC while retaining all Wails bindings and event communication. -// -// This implementation is provided as an example and is not production-ready. -// You may need to add error handling, reconnection logic, authentication, etc. -type WebSocketTransport struct { - addr string - server *http.Server - upgrader websocket.Upgrader - clients map[*websocket.Conn]chan *WebSocketMessage - mu sync.RWMutex - handler *application.MessageProcessor -} - -// WebSocketTransportOption is a functional option for configuring WebSocketTransport -type WebSocketTransportOption func(*WebSocketTransport) - -// wsResponse represents the response to a runtime call. -type wsResponse struct { - // StatusCode is the HTTP status code equivalent (200 for success, 422 for error, etc.) - StatusCode int `json:"statusCode"` - - // Data contains the response body (can be struct, string) - Data any `json:"data"` -} - -// WebSocketMessage represents a message sent over the WebSocket transport -type WebSocketMessage struct { - ID string `json:"id"` // Unique message ID for request/response matching - Type string `json:"type"` // "request" or "response" - Request *application.RuntimeRequest `json:"request,omitempty"` - Response *wsResponse `json:"response,omitempty"` - Event *application.CustomEvent `json:"event,omitempty"` -} - -// NewWebSocketTransport creates a new WebSocket transport listening on the specified address. -// Example: NewWebSocketTransport(":9099") -func NewWebSocketTransport(addr string, opts ...WebSocketTransportOption) *WebSocketTransport { - t := &WebSocketTransport{ - addr: addr, - upgrader: websocket.Upgrader{ - CheckOrigin: func(r *http.Request) bool { - // In production, you should validate the origin - return true - }, - }, - clients: make(map[*websocket.Conn]chan *WebSocketMessage), - } - - // Apply options - for _, opt := range opts { - opt(t) - } - - return t -} - -// Start initializes and starts the WebSocket server -func (w *WebSocketTransport) Start(ctx context.Context, handler *application.MessageProcessor) error { - w.handler = handler - - // Create HTTP server but don't start it yet - // We'll set up the handler in ServeAssets() if it's called - w.server = &http.Server{ - Addr: w.addr, - } - - // Handle context cancellation - go func() { - <-ctx.Done() - w.Stop() - }() - - return nil -} - -func (w *WebSocketTransport) JSClient() []byte { - return jsClient -} - -// ServeAssets configures the transport to serve assets alongside WebSocket IPC. -// This implements the AssetServerTransport interface for browser-based deployments. -func (w *WebSocketTransport) ServeAssets(assetHandler http.Handler) error { - mux := http.NewServeMux() - - // Mount WebSocket endpoint for IPC - mux.HandleFunc("/wails/ws", w.handleWebSocket) - - // Mount asset server for all other requests - mux.Handle("/", assetHandler) - - // Set the handler and start the server - w.server.Handler = mux - - // Start server in background - go func() { - log.Printf("WebSocket transport serving assets and IPC on %s", w.addr) - log.Printf(" - Assets: http://%s/", w.addr) - log.Printf(" - WebSocket IPC: ws://%s/wails/ws", w.addr) - if err := w.server.ListenAndServe(); err != nil && err != http.ErrServerClosed { - log.Printf("WebSocket server error: %v", err) - } - }() - - return nil -} - -// Stop gracefully shuts down the WebSocket server -func (w *WebSocketTransport) Stop() error { - if w.server == nil { - return nil - } - - w.mu.Lock() - for conn := range w.clients { - conn.Close() - } - w.mu.Unlock() - - return w.server.Shutdown(context.Background()) -} - -// handleWebSocket handles WebSocket connections -func (w *WebSocketTransport) handleWebSocket(rw http.ResponseWriter, r *http.Request) { - conn, err := w.upgrader.Upgrade(rw, r, nil) - if err != nil { - log.Printf("WebSocket upgrade failed: %v", err) - return - } - - w.mu.Lock() - messageChan := make(chan *WebSocketMessage, 100) - w.clients[conn] = messageChan - w.mu.Unlock() - - ctx, cancel := context.WithCancel(r.Context()) - - defer func() { - w.mu.Lock() - cancel() - close(messageChan) - if _, ok := w.clients[conn]; ok { - delete(w.clients, conn) - } - w.mu.Unlock() - conn.Close() - }() - - // write responses in one place, as concurrent writeJSON is not allowed - go func() { - for { - select { - case msg, ok := <-messageChan: - if !ok { - return - } - - w.mu.RLock() - if err := conn.WriteJSON(msg); err != nil { - log.Printf("[WebSocket] Failed to send message: %v", err) - } else { - if msg.Type == "response" { - log.Printf("[WebSocket] Successfully sent response for msgID=%s", msg.ID) - } - } - w.mu.RUnlock() - } - } - }() - - // Read messages from client - for { - var msg WebSocketMessage - err := conn.ReadJSON(&msg) - if err != nil { - if websocket.IsUnexpectedCloseError(err, websocket.CloseGoingAway, websocket.CloseAbnormalClosure) { - log.Printf("WebSocket read error: %v", err) - } - break - } - - // Process request - if msg.Type == "request" && msg.Request != nil { - if msg.Request.Args == nil { - msg.Request.Args = &application.Args{} - } - go w.handleRequest(ctx, messageChan, msg.ID, msg.Request) - } - } -} - -// handleRequest processes a runtime call request and sends the response -func (w *WebSocketTransport) handleRequest(ctx context.Context, messageChan chan *WebSocketMessage, msgID string, req *application.RuntimeRequest) { - log.Printf("[WebSocket] Received request: msgID=%s, object=%d, method=%d, args=%s", msgID, req.Object, req.Method, req.Args.String()) - - // Call the Wails runtime handler - response, err := w.handler.HandleRuntimeCallWithIDs(ctx, req) - - w.sendResponse(ctx, messageChan, msgID, response, err) -} - -// sendResponse sends a response message to the client -func (w *WebSocketTransport) sendResponse(ctx context.Context, messageChan chan *WebSocketMessage, msgID string, resp any, err error) { - response := &wsResponse{ - StatusCode: 200, - Data: resp, - } - if err != nil { - response.StatusCode = 422 - response.Data = err.Error() - } - - responseMsg := &WebSocketMessage{ - ID: msgID, - Type: "response", - Response: response, - } - - w.mu.RLock() - defer w.mu.RUnlock() - - select { - case <-ctx.Done(): - log.Println("[WebSocket] Context cancelled before sending response.") - default: - messageChan <- responseMsg - } -} - -// BroadcastEvent sends an event to all connected clients -// This can be used for server-pushed events -func (w *WebSocketTransport) DispatchWailsEvent(event *application.CustomEvent) { - msg := &WebSocketMessage{ - Type: "event", - Event: event, - } - - w.mu.RLock() - defer w.mu.RUnlock() - - for _, channel := range w.clients { - channel <- msg - } -} diff --git a/v3/examples/websocket-transport/websocket-transport.js b/v3/examples/websocket-transport/websocket-transport.js deleted file mode 100644 index ff8d055fd..000000000 --- a/v3/examples/websocket-transport/websocket-transport.js +++ /dev/null @@ -1,253 +0,0 @@ -/** - * WebSocket Transport Implementation for Wails - * - * This is a custom transport that replaces the default HTTP fetch transport - * with WebSocket-based communication. - * - * VERSION 5 - SIMPLIFIED - */ - -console.log("[WebSocket Transport] Loading VERSION 5 - simplified"); - -import { clientId } from "/wails/runtime.js"; - -/** - * Generate a unique ID (simplified nanoid implementation) - */ -function nanoid(size = 21) { - const alphabet = "useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict"; - let id = ""; - let i = size; - while (i--) { - id += alphabet[(Math.random() * 64) | 0]; - } - return id; -} - -/** - * WebSocket Transport class - */ -export class WebSocketTransport { - constructor(url, options = {}) { - this.url = url; - this.ws = null; - this.wsReady = false; - this.pendingRequests = new Map(); - this.messageQueue = []; - this.reconnectTimer = null; - this.reconnectDelay = options.reconnectDelay || 2000; - this.requestTimeout = options.requestTimeout || 30000; - this.maxQueueSize = options.maxQueueSize || 100; - } - - /** - * Connect to the WebSocket server - */ - connect() { - if (this.ws?.readyState === WebSocket.OPEN || this.ws?.readyState === WebSocket.CONNECTING) { - return Promise.resolve(); - } - - return new Promise((resolve, reject) => { - this.ws = new WebSocket(this.url); - - this.ws.onopen = () => { - console.log(`[WebSocket] ✓ Connected to ${this.url}`); - this.wsReady = true; - - // Send queued messages - while (this.messageQueue.length > 0) { - const msg = this.messageQueue.shift(); - this.ws.send(JSON.stringify(msg)); - } - - resolve(); - }; - - this.ws.onmessage = async(event) => { - // Handle both text and binary messages - let data = event.data; - if (data instanceof Blob) { - data = await data.text(); - } - this.handleMessage(data); - }; - - this.ws.onerror = (error) => { - console.error("[WebSocket] Error:", error); - this.wsReady = false; - reject(error); - }; - - this.ws.onclose = () => { - console.log("[WebSocket] Disconnected"); - this.wsReady = false; - - // Reject all pending requests - this.pendingRequests.forEach(({ reject, timeout }) => { - clearTimeout(timeout); - reject(new Error("WebSocket connection closed")); - }); - this.pendingRequests.clear(); - this.messageQueue = []; - - // Attempt to reconnect - if (!this.reconnectTimer) { - this.reconnectTimer = setTimeout(() => { - this.reconnectTimer = null; - console.log("[WebSocket] Attempting to reconnect..."); - this.connect().catch(err => { - console.error("[WebSocket] Reconnection failed:", err); - }); - }, this.reconnectDelay); - } - }; - }); - } - - /** - * Handle incoming WebSocket message - */ - handleMessage(data) { - console.log("[WebSocket] Received raw message:", data); - try { - const msg = JSON.parse(data); - console.log("[WebSocket] Parsed message:", msg); - - if (msg.type === "response" && msg.id) { - const pending = this.pendingRequests.get(msg.id); - if (!pending) { - console.warn("[WebSocket] No pending request for ID:", msg.id); - return; - } - - this.pendingRequests.delete(msg.id); - clearTimeout(pending.timeout); - - const response = msg.response; - if (!response) { - pending.reject(new Error("Invalid response: missing response field")); - return; - } - - console.log("[WebSocket] Response statusCode:", response.statusCode); - - if (response.statusCode === 200) { - let responseData = response.data; - - console.log("[WebSocket] Response data:", responseData); - pending.resolve(responseData ?? undefined); - } else { - let errorData = response.data; - console.error("[WebSocket] Error response:", errorData); - pending.reject(new Error(errorData)); - } - } else if (msg.type === "event") { - console.log("[WebSocket] Received server event:", msg); - // Dispatch to Wails event system - if (msg.event && window._wails?.dispatchWailsEvent) { - window._wails.dispatchWailsEvent(msg.event); - console.log("[WebSocket] Event dispatched to Wails:", msg.event.name); - } - } - } catch (err) { - console.error("[WebSocket] Failed to parse WebSocket message:", err); - console.error("[WebSocket] Raw message that failed:", data); - } - } - - /** - * Send a runtime call over WebSocket - * Implements the RuntimeTransport.call() interface - */ - async call(objectID, method, windowName, args) { - // Ensure WebSocket is connected - if (!this.wsReady) { - await this.connect(); - } - - return new Promise((resolve, reject) => { - const msgID = nanoid(); - - // Set up timeout - const timeout = setTimeout(() => { - if (this.pendingRequests.has(msgID)) { - this.pendingRequests.delete(msgID); - reject(new Error(`Request timeout (${this.requestTimeout}ms)`)); - } - }, this.requestTimeout); - - // Register pending request with the message for later reference - this.pendingRequests.set(msgID, { resolve, reject, timeout, request: { object: objectID, method, args } }); - - // Build message - const message = { - id: msgID, - type: "request", - request: { - object: objectID, - method: method, - args: args, - windowName: windowName || undefined, - clientId: clientId - } - }; - - // Send or queue message - if (this.wsReady && this.ws?.readyState === WebSocket.OPEN) { - this.ws.send(JSON.stringify(message)); - } else { - if (this.messageQueue.length >= this.maxQueueSize) { - reject(new Error("Message queue full")); - return; - } - this.messageQueue.push(message); - this.connect().catch(reject); - } - }); - } - - /** - * Close the WebSocket connection - */ - close() { - if (this.reconnectTimer) { - clearTimeout(this.reconnectTimer); - this.reconnectTimer = null; - } - - if (this.ws) { - this.ws.close(); - this.ws = null; - } - - this.wsReady = false; - } - - /** - * Get connection status - */ - isConnected() { - return this.wsReady && this.ws?.readyState === WebSocket.OPEN; - } -} - -/** - * Create and configure a WebSocket transport - * - * @param url - WebSocket URL (e.g., 'ws://localhost:9099/wails/ws') - * @param options - Optional configuration - * @returns WebSocketTransport instance - */ -export async function createWebSocketTransport(url, options = {}) { - const transport = new WebSocketTransport(url, options); - await transport.connect(); - return transport; -} - -const wsTransport = await createWebSocketTransport("ws://localhost:9099/wails/ws", { - reconnectDelay: 2000, - requestTimeout: 30000 -}); - -export default wsTransport; diff --git a/v3/examples/webview-api-check/.gitignore b/v3/examples/webview-api-check/.gitignore deleted file mode 100644 index d3ca1b3e4..000000000 --- a/v3/examples/webview-api-check/.gitignore +++ /dev/null @@ -1,6 +0,0 @@ -# Compiled binary -webview-api-check -webview-api-check.exe - -# Generated reports -webview-api-report-*.json diff --git a/v3/examples/webview-api-check/README.md b/v3/examples/webview-api-check/README.md deleted file mode 100644 index 835962654..000000000 --- a/v3/examples/webview-api-check/README.md +++ /dev/null @@ -1,93 +0,0 @@ -# WebView API Compatibility Check - -This example application tests and reports which Web APIs are available in the current WebView engine. - -## Purpose - -Different platforms use different WebView engines: -- **Linux GTK4**: WebKitGTK 6.0 (WebKit-based) -- **Linux GTK3**: WebKit2GTK 4.1 (WebKit-based) -- **Windows**: WebView2 (Chromium-based) -- **macOS**: WKWebView (WebKit-based) - -Each engine supports different Web APIs. This tool helps you understand what APIs are available for your Wails application on each platform. - -## Building - -```bash -# Linux GTK4 -go build -tags gtk4 -o webview-api-check . - -# Linux GTK3 -go build -tags gtk3 -o webview-api-check . - -# Windows/macOS -go build -o webview-api-check . -``` - -## Usage - -1. Run the application -2. Click "Run API Tests" to test all Web APIs -3. View results organized by category -4. Use filters to find specific APIs -5. Export report as JSON for comparison - -## API Categories Tested - -| Category | APIs Tested | -|----------|-------------| -| Storage | localStorage, IndexedDB, Cache API, File System Access | -| Network | Fetch, WebSocket, EventSource, WebTransport | -| Media | Web Audio, MediaRecorder, MediaDevices, Speech | -| Graphics | Canvas, WebGL, WebGL2, WebGPU | -| Device | Geolocation, Sensors, Battery, Bluetooth, USB | -| Workers | Web Workers, Service Workers, Shared Workers | -| Performance | Observers, Timing APIs | -| Security | Web Crypto, Credentials, WebAuthn | -| UI & DOM | Custom Elements, Shadow DOM, Pointer Events | -| CSS | CSSOM, Container Queries, Modern Selectors | -| JavaScript | ES Modules, BigInt, Private Fields, etc. | - -## Understanding Results - -- **Supported** (green): API is fully available -- **Partial** (yellow): API exists but may have limitations -- **Unsupported** (red): API is not available - -Some APIs are marked with notes: -- "Chromium only" - Available in WebView2 but not WebKit -- "Experimental" - May not be stable -- "Requires secure context" - Needs HTTPS -- "PWA context" - Only available in installed PWAs - -## Comparing Platforms - -Run the app on different platforms and export JSON reports. Compare them to understand API availability differences: - -```bash -# On Linux GTK4 -./webview-api-check -# Export: webview-api-report-linux-20240115-143052.json - -# On Windows -./webview-api-check.exe -# Export: webview-api-report-windows-20240115-143052.json -``` - -## Known Differences - -### WebKitGTK vs WebView2 (Chromium) - -WebView2 (Windows) typically supports more APIs because Chromium is updated more frequently: -- File System Access API (Chromium only) -- Web Serial, WebHID, WebUSB (Chromium only) -- Various experimental features - -WebKitGTK may have better support for: -- Standard DOM APIs -- CSS features (varies by version) - -### GTK3 vs GTK4 WebKitGTK - -GTK4 uses WebKitGTK 6.0, GTK3 uses WebKit2GTK 4.1. The WebKit version determines API support, not GTK version. diff --git a/v3/examples/webview-api-check/frontend/api-tests.js b/v3/examples/webview-api-check/frontend/api-tests.js deleted file mode 100644 index 6da1d2471..000000000 --- a/v3/examples/webview-api-check/frontend/api-tests.js +++ /dev/null @@ -1,664 +0,0 @@ -// Comprehensive Web API Tests -// Each test returns { supported: true|false|'partial', note?: string } - -const API_TESTS = { - "Storage APIs": { - "localStorage": () => ({ - supported: typeof localStorage !== 'undefined', - note: typeof localStorage !== 'undefined' ? `${localStorage.length} items` : undefined - }), - "sessionStorage": () => ({ - supported: typeof sessionStorage !== 'undefined' - }), - "IndexedDB": () => ({ - supported: typeof indexedDB !== 'undefined' - }), - "Cache API": () => ({ - supported: 'caches' in window - }), - "CookieStore API": () => ({ - supported: 'cookieStore' in window, - note: !('cookieStore' in window) ? 'Chromium only' : undefined - }), - "Storage API": () => ({ - supported: navigator.storage !== undefined - }), - "Storage Access API": () => ({ - supported: 'hasStorageAccess' in document - }), - "File System Access": () => ({ - supported: 'showOpenFilePicker' in window, - note: !('showOpenFilePicker' in window) ? 'Chromium only' : undefined - }), - "Origin Private File System": () => ({ - supported: navigator.storage && 'getDirectory' in navigator.storage - }) - }, - - "Network APIs": { - "Fetch API": () => ({ - supported: typeof fetch !== 'undefined' - }), - "XMLHttpRequest": () => ({ - supported: typeof XMLHttpRequest !== 'undefined' - }), - "WebSocket": () => ({ - supported: typeof WebSocket !== 'undefined' - }), - "EventSource (SSE)": () => ({ - supported: typeof EventSource !== 'undefined' - }), - "Beacon API": () => ({ - supported: 'sendBeacon' in navigator - }), - "WebTransport": () => ({ - supported: typeof WebTransport !== 'undefined', - note: typeof WebTransport === 'undefined' ? 'Experimental' : undefined - }), - "Background Fetch": () => ({ - supported: 'BackgroundFetchManager' in window, - note: !('BackgroundFetchManager' in window) ? 'Chromium only' : undefined - }), - "Background Sync": () => ({ - supported: 'SyncManager' in window, - note: !('SyncManager' in window) ? 'Chromium only' : undefined - }) - }, - - "Media APIs": { - "Web Audio API": () => ({ - supported: typeof AudioContext !== 'undefined' || typeof webkitAudioContext !== 'undefined', - note: typeof AudioContext === 'undefined' && typeof webkitAudioContext !== 'undefined' ? 'webkit prefix' : undefined - }), - "MediaDevices": () => ({ - supported: 'mediaDevices' in navigator - }), - "getUserMedia": () => ({ - supported: navigator.mediaDevices && 'getUserMedia' in navigator.mediaDevices - }), - "getDisplayMedia": () => ({ - supported: navigator.mediaDevices && 'getDisplayMedia' in navigator.mediaDevices - }), - "MediaRecorder": () => ({ - supported: typeof MediaRecorder !== 'undefined' - }), - "Media Session": () => ({ - supported: 'mediaSession' in navigator - }), - "Media Capabilities": () => ({ - supported: 'mediaCapabilities' in navigator - }), - "MediaSource Extensions": () => ({ - supported: typeof MediaSource !== 'undefined' - }), - "Picture-in-Picture": () => ({ - supported: 'pictureInPictureEnabled' in document - }), - "Audio Worklet": () => ({ - supported: typeof AudioWorkletNode !== 'undefined' - }), - "Web Speech (Recognition)": () => ({ - supported: 'SpeechRecognition' in window || 'webkitSpeechRecognition' in window - }), - "Web Speech (Synthesis)": () => ({ - supported: 'speechSynthesis' in window - }), - "Encrypted Media Extensions": () => ({ - supported: 'MediaKeys' in window - }) - }, - - "Graphics APIs": { - "Canvas 2D": () => { - const canvas = document.createElement('canvas'); - const ctx = canvas.getContext('2d'); - return { supported: ctx !== null }; - }, - "WebGL": () => { - const canvas = document.createElement('canvas'); - const gl = canvas.getContext('webgl') || canvas.getContext('experimental-webgl'); - return { supported: gl !== null }; - }, - "WebGL2": () => { - const canvas = document.createElement('canvas'); - const gl = canvas.getContext('webgl2'); - return { supported: gl !== null }; - }, - "WebGPU": () => ({ - supported: 'gpu' in navigator, - note: !('gpu' in navigator) ? 'Experimental' : undefined - }), - "OffscreenCanvas": () => ({ - supported: typeof OffscreenCanvas !== 'undefined' - }), - "ImageBitmap": () => ({ - supported: typeof createImageBitmap !== 'undefined' - }), - "CSS Painting API": () => ({ - supported: 'paintWorklet' in CSS, - note: !('paintWorklet' in CSS) ? 'Houdini API' : undefined - }), - "Web Animations": () => ({ - supported: typeof Element.prototype.animate !== 'undefined' - }), - "View Transitions": () => ({ - supported: 'startViewTransition' in document, - note: !('startViewTransition' in document) ? 'Chromium 111+' : undefined - }) - }, - - "Device APIs": { - "Geolocation": () => ({ - supported: 'geolocation' in navigator - }), - "Device Orientation": () => ({ - supported: 'DeviceOrientationEvent' in window - }), - "Device Motion": () => ({ - supported: 'DeviceMotionEvent' in window - }), - "Accelerometer": () => ({ - supported: 'Accelerometer' in window, - note: !('Accelerometer' in window) ? 'Requires secure context' : undefined - }), - "Gyroscope": () => ({ - supported: 'Gyroscope' in window, - note: !('Gyroscope' in window) ? 'Requires secure context' : undefined - }), - "Magnetometer": () => ({ - supported: 'Magnetometer' in window, - note: !('Magnetometer' in window) ? 'Chromium only' : undefined - }), - "Ambient Light Sensor": () => ({ - supported: 'AmbientLightSensor' in window, - note: !('AmbientLightSensor' in window) ? 'Limited support' : undefined - }), - "Battery Status": () => ({ - supported: 'getBattery' in navigator, - note: !('getBattery' in navigator) ? 'Chromium only' : undefined - }), - "Device Memory": () => ({ - supported: 'deviceMemory' in navigator, - note: 'deviceMemory' in navigator ? `${navigator.deviceMemory} GB` : 'Chromium only' - }), - "Screen Orientation": () => ({ - supported: 'orientation' in screen - }), - "Screen Wake Lock": () => ({ - supported: 'wakeLock' in navigator - }), - "Vibration": () => ({ - supported: 'vibrate' in navigator - }), - "Web MIDI": () => ({ - supported: 'requestMIDIAccess' in navigator - }), - "Web Serial": () => ({ - supported: 'serial' in navigator, - note: !('serial' in navigator) ? 'Chromium only' : undefined - }), - "WebHID": () => ({ - supported: 'hid' in navigator, - note: !('hid' in navigator) ? 'Chromium only' : undefined - }), - "WebUSB": () => ({ - supported: 'usb' in navigator, - note: !('usb' in navigator) ? 'Chromium only' : undefined - }), - "Web NFC": () => ({ - supported: 'NDEFReader' in window, - note: !('NDEFReader' in window) ? 'Android Chrome only' : undefined - }), - "Web Bluetooth": () => ({ - supported: 'bluetooth' in navigator, - note: !('bluetooth' in navigator) ? 'Limited support' : undefined - }), - "Gamepad API": () => ({ - supported: 'getGamepads' in navigator - }) - }, - - "Worker APIs": { - "Web Workers": () => ({ - supported: typeof Worker !== 'undefined' - }), - "Shared Workers": () => ({ - supported: typeof SharedWorker !== 'undefined' - }), - "Service Worker": () => ({ - supported: 'serviceWorker' in navigator - }), - "Worklets": () => ({ - supported: typeof Worklet !== 'undefined' - }) - }, - - "Performance APIs": { - "Performance API": () => ({ - supported: typeof performance !== 'undefined' - }), - "Performance Observer": () => ({ - supported: typeof PerformanceObserver !== 'undefined' - }), - "Navigation Timing": () => ({ - supported: typeof PerformanceNavigationTiming !== 'undefined' - }), - "Resource Timing": () => ({ - supported: typeof PerformanceResourceTiming !== 'undefined' - }), - "User Timing": () => ({ - supported: performance && 'mark' in performance && 'measure' in performance - }), - "Long Tasks API": () => ({ - supported: typeof PerformanceLongTaskTiming !== 'undefined' - }), - "Intersection Observer": () => ({ - supported: typeof IntersectionObserver !== 'undefined' - }), - "Resize Observer": () => ({ - supported: typeof ResizeObserver !== 'undefined' - }), - "Mutation Observer": () => ({ - supported: typeof MutationObserver !== 'undefined' - }), - "Reporting API": () => ({ - supported: typeof ReportingObserver !== 'undefined' - }), - "Compute Pressure": () => ({ - supported: 'PressureObserver' in window, - note: !('PressureObserver' in window) ? 'Experimental' : undefined - }) - }, - - "Security APIs": { - "Web Crypto": () => ({ - supported: typeof crypto !== 'undefined' && 'subtle' in crypto - }), - "Credentials API": () => ({ - supported: 'credentials' in navigator - }), - "Web Authentication": () => ({ - supported: typeof PublicKeyCredential !== 'undefined' - }), - "Permissions API": () => ({ - supported: 'permissions' in navigator - }), - "Trusted Types": () => ({ - supported: 'trustedTypes' in window - }), - "Content Security Policy": () => ({ - supported: typeof SecurityPolicyViolationEvent !== 'undefined' - }) - }, - - "UI & DOM APIs": { - "Custom Elements": () => ({ - supported: 'customElements' in window - }), - "Shadow DOM": () => ({ - supported: 'attachShadow' in Element.prototype - }), - "HTML Templates": () => ({ - supported: 'content' in document.createElement('template') - }), - "Pointer Events": () => ({ - supported: 'PointerEvent' in window - }), - "Touch Events": () => ({ - supported: 'ontouchstart' in window || navigator.maxTouchPoints > 0 - }), - "Pointer Lock": () => ({ - supported: 'requestPointerLock' in Element.prototype - }), - "Fullscreen API": () => ({ - supported: 'fullscreenEnabled' in document || 'webkitFullscreenEnabled' in document - }), - "Selection API": () => ({ - supported: typeof Selection !== 'undefined' - }), - "Clipboard API": () => ({ - supported: 'clipboard' in navigator - }), - "Clipboard (read)": async () => { - if (!navigator.clipboard) return { supported: false }; - return { supported: 'read' in navigator.clipboard }; - }, - "Clipboard (write)": async () => { - if (!navigator.clipboard) return { supported: false }; - return { supported: 'write' in navigator.clipboard }; - }, - "Drag and Drop": () => ({ - supported: 'draggable' in document.createElement('div') - }), - "EditContext": () => ({ - supported: 'EditContext' in window, - note: !('EditContext' in window) ? 'Experimental' : undefined - }), - "Virtual Keyboard": () => ({ - supported: 'virtualKeyboard' in navigator, - note: !('virtualKeyboard' in navigator) ? 'Chromium only' : undefined - }), - "Popover API": () => ({ - supported: 'popover' in HTMLElement.prototype - }), - "Dialog Element": () => ({ - supported: typeof HTMLDialogElement !== 'undefined' - }) - }, - - "Notifications & Messaging": { - "Notifications API": () => ({ - supported: 'Notification' in window - }), - "Push API": () => ({ - supported: 'PushManager' in window - }), - "Channel Messaging": () => ({ - supported: typeof MessageChannel !== 'undefined' - }), - "Broadcast Channel": () => ({ - supported: typeof BroadcastChannel !== 'undefined' - }), - "postMessage": () => ({ - supported: 'postMessage' in window - }) - }, - - "Navigation & History": { - "History API": () => ({ - supported: 'pushState' in history - }), - "Navigation API": () => ({ - supported: 'navigation' in window, - note: !('navigation' in window) ? 'Chromium 102+' : undefined - }), - "URL API": () => ({ - supported: typeof URL !== 'undefined' - }), - "URLSearchParams": () => ({ - supported: typeof URLSearchParams !== 'undefined' - }), - "URLPattern": () => ({ - supported: typeof URLPattern !== 'undefined', - note: typeof URLPattern === 'undefined' ? 'Limited support' : undefined - }) - }, - - "Sharing & Content": { - "Share API": () => ({ - supported: 'share' in navigator - }), - "Web Share Target": () => ({ - supported: 'share' in navigator && 'canShare' in navigator - }), - "Badging API": () => ({ - supported: 'setAppBadge' in navigator, - note: !('setAppBadge' in navigator) ? 'PWA context' : undefined - }), - "Content Index": () => ({ - supported: 'ContentIndex' in window, - note: !('ContentIndex' in window) ? 'PWA context' : undefined - }), - "Contact Picker": () => ({ - supported: 'contacts' in navigator, - note: !('contacts' in navigator) ? 'Android Chrome only' : undefined - }) - }, - - "Streams & Encoding": { - "Streams API": () => ({ - supported: typeof ReadableStream !== 'undefined' - }), - "WritableStream": () => ({ - supported: typeof WritableStream !== 'undefined' - }), - "TransformStream": () => ({ - supported: typeof TransformStream !== 'undefined' - }), - "Compression Streams": () => ({ - supported: typeof CompressionStream !== 'undefined' - }), - "TextEncoder/Decoder": () => ({ - supported: typeof TextEncoder !== 'undefined' && typeof TextDecoder !== 'undefined' - }), - "Encoding API (streams)": () => ({ - supported: typeof TextEncoderStream !== 'undefined' - }), - "Blob": () => ({ - supported: typeof Blob !== 'undefined' - }), - "File API": () => ({ - supported: typeof File !== 'undefined' && typeof FileReader !== 'undefined' - }), - "FileReader": () => ({ - supported: typeof FileReader !== 'undefined' - }), - "ArrayBuffer": () => ({ - supported: typeof ArrayBuffer !== 'undefined' - }), - "DataView": () => ({ - supported: typeof DataView !== 'undefined' - }), - "Typed Arrays": () => ({ - supported: typeof Uint8Array !== 'undefined' - }) - }, - - "Payment APIs": { - "Payment Request": () => ({ - supported: 'PaymentRequest' in window - }), - "Payment Handler": () => ({ - supported: 'PaymentManager' in window, - note: !('PaymentManager' in window) ? 'Limited support' : undefined - }) - }, - - "Extended/Experimental": { - "WebXR": () => ({ - supported: 'xr' in navigator, - note: !('xr' in navigator) ? 'VR/AR devices' : undefined - }), - "Presentation API": () => ({ - supported: 'presentation' in navigator, - note: !('presentation' in navigator) ? 'Cast-like APIs' : undefined - }), - "Remote Playback": () => ({ - supported: 'remote' in HTMLMediaElement.prototype - }), - "Window Management": () => ({ - supported: 'getScreenDetails' in window, - note: !('getScreenDetails' in window) ? 'Multi-screen' : undefined - }), - "Document Picture-in-Picture": () => ({ - supported: 'documentPictureInPicture' in window, - note: !('documentPictureInPicture' in window) ? 'Chromium only' : undefined - }), - "EyeDropper": () => ({ - supported: 'EyeDropper' in window, - note: !('EyeDropper' in window) ? 'Chromium only' : undefined - }), - "File Handling": () => ({ - supported: 'launchQueue' in window, - note: !('launchQueue' in window) ? 'PWA only' : undefined - }), - "Launch Handler": () => ({ - supported: 'LaunchParams' in window, - note: !('LaunchParams' in window) ? 'PWA only' : undefined - }), - "Idle Detection": () => ({ - supported: 'IdleDetector' in window, - note: !('IdleDetector' in window) ? 'Chromium only' : undefined - }), - "Keyboard Lock": () => ({ - supported: 'keyboard' in navigator && 'lock' in navigator.keyboard, - note: !('keyboard' in navigator) ? 'Fullscreen only' : undefined - }), - "Local Font Access": () => ({ - supported: 'queryLocalFonts' in window, - note: !('queryLocalFonts' in window) ? 'Chromium only' : undefined - }), - "Screen Capture": () => ({ - supported: navigator.mediaDevices && 'getDisplayMedia' in navigator.mediaDevices - }), - "Scheduler API": () => ({ - supported: 'scheduler' in window - }), - "Task Attribution": () => ({ - supported: typeof TaskAttributionTiming !== 'undefined' - }), - "Web Codecs (Video)": () => ({ - supported: typeof VideoEncoder !== 'undefined' - }), - "Web Codecs (Audio)": () => ({ - supported: typeof AudioEncoder !== 'undefined' - }), - "Web Locks": () => ({ - supported: 'locks' in navigator - }), - "Prioritized Task Scheduling": () => ({ - supported: 'scheduler' in window && 'postTask' in scheduler - }) - }, - - "CSS APIs": { - "CSSOM": () => ({ - supported: typeof CSSStyleSheet !== 'undefined' - }), - "Constructable Stylesheets": () => ({ - supported: 'adoptedStyleSheets' in document - }), - "CSS Typed OM": () => ({ - supported: 'attributeStyleMap' in Element.prototype - }), - "CSS Properties & Values": () => ({ - supported: CSS && 'registerProperty' in CSS - }), - "CSS.supports": () => ({ - supported: CSS && 'supports' in CSS - }), - "CSS Font Loading": () => ({ - supported: 'fonts' in document - }), - "CSS Container Queries": () => ({ - supported: CSS && CSS.supports && CSS.supports('container-type', 'inline-size') - }), - "@layer support": () => ({ - supported: CSS && CSS.supports && CSS.supports('@layer test { }') - }), - "Subgrid": () => ({ - supported: CSS && CSS.supports && CSS.supports('grid-template-columns', 'subgrid') - }), - ":has() selector": () => ({ - supported: CSS && CSS.supports && CSS.supports('selector(:has(a))') - }), - "color-mix()": () => ({ - supported: CSS && CSS.supports && CSS.supports('color', 'color-mix(in srgb, red, blue)') - }), - "Scroll-driven Animations": () => ({ - supported: CSS && CSS.supports && CSS.supports('animation-timeline', 'scroll()'), - note: !(CSS && CSS.supports && CSS.supports('animation-timeline', 'scroll()')) ? 'Chromium 115+' : undefined - }) - }, - - "JavaScript Features": { - "ES Modules": () => ({ - supported: 'noModule' in document.createElement('script') - }), - "Import Maps": () => ({ - supported: HTMLScriptElement.supports && HTMLScriptElement.supports('importmap') - }), - "Dynamic Import": async () => { - try { - await import('data:text/javascript,export default 1'); - return { supported: true }; - } catch { - return { supported: false }; - } - }, - "Top-level Await": () => ({ - supported: true, // If we're running, it's supported in modules - note: 'Module context' - }), - "WeakRef": () => ({ - supported: typeof WeakRef !== 'undefined' - }), - "FinalizationRegistry": () => ({ - supported: typeof FinalizationRegistry !== 'undefined' - }), - "BigInt": () => ({ - supported: typeof BigInt !== 'undefined' - }), - "globalThis": () => ({ - supported: typeof globalThis !== 'undefined' - }), - "Optional Chaining": () => { - try { - eval('const x = null?.foo'); - return { supported: true }; - } catch { - return { supported: false }; - } - }, - "Nullish Coalescing": () => { - try { - eval('const x = null ?? "default"'); - return { supported: true }; - } catch { - return { supported: false }; - } - }, - "Private Class Fields": () => { - try { - eval('class C { #x = 1 }'); - return { supported: true }; - } catch { - return { supported: false }; - } - }, - "Static Class Blocks": () => { - try { - eval('class C { static { } }'); - return { supported: true }; - } catch { - return { supported: false }; - } - }, - "Temporal (Stage 3)": () => ({ - supported: typeof Temporal !== 'undefined', - note: typeof Temporal === 'undefined' ? 'Proposal' : undefined - }), - "Iterator Helpers": () => ({ - supported: typeof Iterator !== 'undefined' && 'from' in Iterator, - note: !(typeof Iterator !== 'undefined') ? 'Proposal' : undefined - }), - "Array.at()": () => ({ - supported: 'at' in Array.prototype - }), - "Object.hasOwn()": () => ({ - supported: 'hasOwn' in Object - }), - "structuredClone": () => ({ - supported: typeof structuredClone !== 'undefined' - }), - "Atomics.waitAsync": () => ({ - supported: typeof Atomics !== 'undefined' && 'waitAsync' in Atomics - }), - "Array.fromAsync": () => ({ - supported: 'fromAsync' in Array, - note: !('fromAsync' in Array) ? 'ES2024' : undefined - }), - "Promise.withResolvers": () => ({ - supported: 'withResolvers' in Promise, - note: !('withResolvers' in Promise) ? 'ES2024' : undefined - }), - "RegExp v flag": () => { - try { - new RegExp('.', 'v'); - return { supported: true }; - } catch { - return { supported: false, note: 'ES2024' }; - } - } - } -}; diff --git a/v3/examples/webview-api-check/frontend/index.html b/v3/examples/webview-api-check/frontend/index.html deleted file mode 100644 index bd05f0b50..000000000 --- a/v3/examples/webview-api-check/frontend/index.html +++ /dev/null @@ -1,539 +0,0 @@ - - - - - - WebView API Compatibility Check - - - -
                    -
                    -

                    WebView API Compatibility Check

                    -

                    Testing Web API support in your current WebView

                    -
                    - -
                    -
                    - Operating System - Loading... -
                    -
                    - Architecture - - -
                    -
                    - WebView Engine - - -
                    -
                    - User Agent - - -
                    -
                    - -
                    - - - - -
                    - -
                    -
                    -
                    - -
                    -
                    -
                    -
                    -
                    Supported
                    -
                    -
                    -
                    -
                    -
                    Partial
                    -
                    -
                    -
                    -
                    -
                    Unsupported
                    -
                    -
                    - -
                    - - -
                    - -
                    -
                    - - - - - diff --git a/v3/examples/webview-api-check/main.go b/v3/examples/webview-api-check/main.go deleted file mode 100644 index 667dd6ef1..000000000 --- a/v3/examples/webview-api-check/main.go +++ /dev/null @@ -1,126 +0,0 @@ -package main - -import ( - "embed" - "encoding/json" - "flag" - "fmt" - "os" - "runtime" - "time" - - "github.com/wailsapp/wails/v3/pkg/application" -) - -var autorun = flag.Bool("autorun", false, "Automatically run tests and save report") - -//go:embed frontend/* -var assets embed.FS - -// PlatformInfo contains information about the platform and webview -type PlatformInfo struct { - OS string `json:"os"` - Arch string `json:"arch"` - GoVersion string `json:"goVersion"` - WailsInfo string `json:"wailsInfo"` - WebViewInfo string `json:"webViewInfo"` - GTKVersion string `json:"gtkVersion,omitempty"` - Timestamp string `json:"timestamp"` -} - -// APIReport represents the full API compatibility report -type APIReport struct { - Platform PlatformInfo `json:"platform"` - APIs map[string]interface{} `json:"apis"` -} - -var appInstance *application.App - -// APICheckService provides methods for the frontend -type APICheckService struct{} - -// GetPlatformInfo returns information about the current platform -func (s *APICheckService) GetPlatformInfo() PlatformInfo { - info := PlatformInfo{ - OS: runtime.GOOS, - Arch: runtime.GOARCH, - GoVersion: runtime.Version(), - WailsInfo: "v3.0.0-dev", - Timestamp: time.Now().Format(time.RFC3339), - } - - // Platform-specific webview info - switch runtime.GOOS { - case "linux": - info.WebViewInfo = getLinuxWebViewInfo() - info.GTKVersion = getGTKVersionInfo() - case "darwin": - info.WebViewInfo = "WKWebView (WebKit)" - case "windows": - info.WebViewInfo = "WebView2 (Chromium-based)" - default: - info.WebViewInfo = "Unknown" - } - - return info -} - -// SaveReport saves the API report to a file -func (s *APICheckService) SaveReport(report APIReport) error { - filename := fmt.Sprintf("webview-api-report-%s-%s.json", - report.Platform.OS, - time.Now().Format("20060102-150405")) - - data, err := json.MarshalIndent(report, "", " ") - if err != nil { - return fmt.Errorf("failed to marshal report: %w", err) - } - - err = os.WriteFile(filename, data, 0644) - if err != nil { - return fmt.Errorf("failed to write report: %w", err) - } - - fmt.Printf("Report saved to: %s\n", filename) - return nil -} - -// Quit exits the application -func (s *APICheckService) Quit() { - if appInstance != nil { - appInstance.Quit() - } -} - -func main() { - flag.Parse() - - appInstance = application.New(application.Options{ - Name: "WebView API Check", - Description: "Check which Web APIs are available in the webview", - Assets: application.AssetOptions{ - Handler: application.BundledAssetFileServer(assets), - }, - Services: []application.Service{ - application.NewService(&APICheckService{}), - }, - }) - - url := "/" - if *autorun { - url = "/?autorun=1" - } - - appInstance.Window.NewWithOptions(application.WebviewWindowOptions{ - Title: "WebView API Compatibility Check", - Width: 1200, - Height: 800, - URL: url, - }) - - err := appInstance.Run() - if err != nil { - fmt.Fprintf(os.Stderr, "Error: %v\n", err) - os.Exit(1) - } -} diff --git a/v3/examples/webview-api-check/platform_darwin.go b/v3/examples/webview-api-check/platform_darwin.go deleted file mode 100644 index b6551de04..000000000 --- a/v3/examples/webview-api-check/platform_darwin.go +++ /dev/null @@ -1,11 +0,0 @@ -//go:build darwin - -package main - -func getLinuxWebViewInfo() string { - return "" -} - -func getGTKVersionInfo() string { - return "" -} diff --git a/v3/examples/webview-api-check/platform_linux.go b/v3/examples/webview-api-check/platform_linux.go deleted file mode 100644 index 17445842b..000000000 --- a/v3/examples/webview-api-check/platform_linux.go +++ /dev/null @@ -1,33 +0,0 @@ -//go:build linux - -package main - -import "os/exec" - -func getLinuxWebViewInfo() string { - // Try to get WebKitGTK version from pkg-config - // For GTK4 builds, this will be webkitgtk-6.0 - // For GTK3 builds, this will be webkit2gtk-4.1 - out, err := exec.Command("pkg-config", "--modversion", "webkitgtk-6.0").Output() - if err == nil { - return "WebKitGTK " + string(out[:len(out)-1]) - } - out, err = exec.Command("pkg-config", "--modversion", "webkit2gtk-4.1").Output() - if err == nil { - return "WebKit2GTK " + string(out[:len(out)-1]) - } - return "WebKitGTK (unknown version)" -} - -func getGTKVersionInfo() string { - // Try GTK4 first - out, err := exec.Command("pkg-config", "--modversion", "gtk4").Output() - if err == nil { - return "GTK " + string(out[:len(out)-1]) - } - out, err = exec.Command("pkg-config", "--modversion", "gtk+-3.0").Output() - if err == nil { - return "GTK " + string(out[:len(out)-1]) - } - return "GTK (unknown version)" -} diff --git a/v3/examples/webview-api-check/platform_windows.go b/v3/examples/webview-api-check/platform_windows.go deleted file mode 100644 index b224da990..000000000 --- a/v3/examples/webview-api-check/platform_windows.go +++ /dev/null @@ -1,11 +0,0 @@ -//go:build windows - -package main - -func getLinuxWebViewInfo() string { - return "" -} - -func getGTKVersionInfo() string { - return "" -} diff --git a/v3/examples/window-api/README.md b/v3/examples/window-api/README.md deleted file mode 100644 index 02c726062..000000000 --- a/v3/examples/window-api/README.md +++ /dev/null @@ -1,19 +0,0 @@ -# Window API Example - -This is an example of how to use the JS Window API - -## Running the example - -To run the example, simply run the following command: - -```bash -go run . -``` - -# Status - -| Platform | Status | -|----------|---------| -| Mac | Working | -| Windows | | -| Linux | | diff --git a/v3/examples/window-api/assets/index.html b/v3/examples/window-api/assets/index.html deleted file mode 100644 index a0dd5d8b2..000000000 --- a/v3/examples/window-api/assets/index.html +++ /dev/null @@ -1,159 +0,0 @@ - - - - - Wails Alpha - - - - - -
                    Alpha
                    -
                    -

                    Close the Window?

                    -

                    Center

                    -

                    Minimise

                    -

                    Maximise

                    -

                    UnMaximise

                    -

                    Fullscreen

                    -

                    UnFullscreen

                    -

                    Restore

                    -
                    -
                    -

                    ToggleMaximise

                    -

                    IsFocused

                    -

                    IsMaximised

                    -

                    IsFullscreen

                    -
                    -
                    - - - - - diff --git a/v3/examples/window-api/main.go b/v3/examples/window-api/main.go deleted file mode 100644 index 252608641..000000000 --- a/v3/examples/window-api/main.go +++ /dev/null @@ -1,42 +0,0 @@ -package main - -import ( - "embed" - "log" - - "github.com/wailsapp/wails/v3/pkg/application" -) - -//go:embed assets/* -var assets embed.FS - -func main() { - - app := application.New(application.Options{ - Name: "JS Window API Demo", - Description: "A demo of the JS Window API", - Mac: application.MacOptions{ - ApplicationShouldTerminateAfterLastWindowClosed: true, - }, - Assets: application.AssetOptions{ - Handler: application.BundledAssetFileServer(assets), - }, - }) - - app.Window.NewWithOptions(application.WebviewWindowOptions{ - Title: "JS Window API Demo", - Width: 1280, - Height: 1024, - Mac: application.MacWindow{ - Backdrop: application.MacBackdropTranslucent, - TitleBar: application.MacTitleBarHiddenInsetUnified, - InvisibleTitleBarHeight: 50, - }, - }) - - err := app.Run() - - if err != nil { - log.Fatal(err.Error()) - } -} diff --git a/v3/examples/window-call/README.md b/v3/examples/window-call/README.md deleted file mode 100644 index baffad046..000000000 --- a/v3/examples/window-call/README.md +++ /dev/null @@ -1,11 +0,0 @@ -# Window Call Example - -This example is a demonstration of how to know which window is calling a service. - -## Running the example - -To run the example, simply run the following command: - -```bash -go run . -``` diff --git a/v3/examples/window-call/assets/index.html b/v3/examples/window-call/assets/index.html deleted file mode 100644 index a99293f03..000000000 --- a/v3/examples/window-call/assets/index.html +++ /dev/null @@ -1,27 +0,0 @@ - - - - - - Window Call Demo - - - - - - - - - \ No newline at end of file diff --git a/v3/examples/window-call/main.go b/v3/examples/window-call/main.go deleted file mode 100644 index e6bdee23b..000000000 --- a/v3/examples/window-call/main.go +++ /dev/null @@ -1,73 +0,0 @@ -package main - -import ( - "context" - "embed" - "github.com/wailsapp/wails/v3/pkg/application" - "log" - "math/rand" - "runtime" - "strconv" -) - -//go:embed assets/* -var assets embed.FS - -type WindowService struct{} - -func (s *WindowService) RandomTitle(ctx context.Context) { - callingWindow := ctx.Value(application.WindowKey).(application.Window) - title := "Random Title " + strconv.Itoa(rand.Intn(1000)) - callingWindow.SetTitle(title) -} - -// ============================================== - -func main() { - app := application.New(application.Options{ - Name: "Window call Demo", - Description: "A demo of the WebviewWindow API", - Assets: application.AssetOptions{ - Handler: application.BundledAssetFileServer(assets), - }, - Mac: application.MacOptions{ - ApplicationShouldTerminateAfterLastWindowClosed: false, - }, - Services: []application.Service{ - application.NewService(&WindowService{}), - }, - }) - - app.Window.New(). - SetTitle("WebviewWindow 1"). - Show() - - // Create a custom menu - menu := app.NewMenu() - if runtime.GOOS == "darwin" { - menu.AddRole(application.AppMenu) - } - - windowCounter := 1 - - // Let's make a "Demo" menu - myMenu := menu.AddSubmenu("New") - - myMenu.Add("New WebviewWindow"). - SetAccelerator("CmdOrCtrl+N"). - OnClick(func(ctx *application.Context) { - app.Window.New(). - SetTitle("WebviewWindow "+strconv.Itoa(windowCounter)). - SetRelativePosition(rand.Intn(1000), rand.Intn(800)). - Show() - windowCounter++ - }) - - app.Menu.Set(menu) - err := app.Run() - - if err != nil { - log.Fatal(err) - } - -} diff --git a/v3/examples/window-menu/README.md b/v3/examples/window-menu/README.md deleted file mode 100644 index 0d825364f..000000000 --- a/v3/examples/window-menu/README.md +++ /dev/null @@ -1,24 +0,0 @@ -# Window Menu Example - -*** Windows Only *** - -This example demonstrates how to create a window with a menu bar that can be toggled using the window.ToggleMenuBar() method. - -## Features - -- Default menu bar with File, Edit, and Help menus -- F1 key to toggle menu bar visibility -- Simple HTML interface with instructions - -## Running the Example - -```bash -cd v3/examples/window-menu -go run . -``` - -## How it Works - -The example creates a window with a default menu and binds the F1 key to toggle the menu bar's visibility. The menu bar will show when F2 is pressed and hide when F3 is released. - -Note: The menu bar toggling functionality only works on Windows. On other platforms, the F1 key binding will have no effect. diff --git a/v3/examples/window-menu/assets/about.html b/v3/examples/window-menu/assets/about.html deleted file mode 100644 index e887a84ce..000000000 --- a/v3/examples/window-menu/assets/about.html +++ /dev/null @@ -1,14 +0,0 @@ - - - Window Menu Demo - - - -
                    -

                    About Window Menu Demo

                    -

                    Press F1 to toggle menu bar visibility

                    -

                    Press F2 to show menu bar

                    -

                    Press F3 to hide menu bar

                    -
                    - - \ No newline at end of file diff --git a/v3/examples/window-menu/assets/index.html b/v3/examples/window-menu/assets/index.html deleted file mode 100644 index b18f601e0..000000000 --- a/v3/examples/window-menu/assets/index.html +++ /dev/null @@ -1,48 +0,0 @@ - - - Window Menu Demo - - - -
                    -

                    Window Menu Demo

                    -

                    This example demonstrates the menu bar visibility toggle feature.

                    -

                    Press F1 to toggle the menu bar.

                    -

                    Press F2 to show the menu bar.

                    -

                    Press F3 to hide the menu bar.

                    -

                    The menu includes:

                    -
                      -
                    • File menu with Exit option
                    • -
                    • MenuBar menu with Hide options
                    • -
                    • Help menu with About
                    • -
                    -
                    - - \ No newline at end of file diff --git a/v3/examples/window-menu/assets/style.css b/v3/examples/window-menu/assets/style.css deleted file mode 100644 index c7fc71f39..000000000 --- a/v3/examples/window-menu/assets/style.css +++ /dev/null @@ -1,26 +0,0 @@ -body { - font-family: system-ui, -apple-system, sans-serif; - margin: 0; - padding: 2rem; - background: #f5f5f5; - color: #333; -} -.container { - max-width: 600px; - margin: 0 auto; - background: white; - padding: 2rem; - border-radius: 8px; - box-shadow: 0 2px 4px rgba(0,0,0,0.1); -} -h1 { - margin-top: 0; - color: #2d2d2d; -} -.key { - background: #e9e9e9; - padding: 2px 8px; - border-radius: 4px; - border: 1px solid #ccc; - font-family: monospace; -} diff --git a/v3/examples/window-menu/main.go b/v3/examples/window-menu/main.go deleted file mode 100644 index 107213b44..000000000 --- a/v3/examples/window-menu/main.go +++ /dev/null @@ -1,64 +0,0 @@ -package main - -import ( - "embed" - _ "embed" - "github.com/wailsapp/wails/v3/pkg/application" - "log" -) - -//go:embed assets/* -var assets embed.FS - -func main() { - app := application.New(application.Options{ - Name: "Window MenuBar Demo", - Description: "A demo of menu bar toggling", - Assets: application.AssetOptions{ - Handler: application.BundledAssetFileServer(assets), - }, - }) - - // Create a menu - menu := app.NewMenu() - fileMenu := menu.AddSubmenu("File") - fileMenu.Add("Exit").OnClick(func(ctx *application.Context) { - app.Quit() - }) - - editMenu := menu.AddSubmenu("MenuBar") - editMenu.Add("Hide MenuBar").OnClick(func(ctx *application.Context) { - app.Window.Current().HideMenuBar() - }) - - helpMenu := menu.AddSubmenu("Help") - helpMenu.Add("About").OnClick(func(ctx *application.Context) { - app.Window.Current().SetURL("/about.html") - }) - - // Create window with menu - app.Window.NewWithOptions(application.WebviewWindowOptions{ - Title: "Window MenuBar Demo", - Width: 800, - Height: 600, - Windows: application.WindowsWindow{ - Menu: menu, - }, - KeyBindings: map[string]func(window application.Window){ - "F1": func(window application.Window) { - window.ToggleMenuBar() - }, - "F2": func(window application.Window) { - window.ShowMenuBar() - }, - "F3": func(window application.Window) { - window.HideMenuBar() - }, - }, - }) - - err := app.Run() - if err != nil { - log.Fatal(err) - } -} diff --git a/v3/examples/window/README.md b/v3/examples/window/README.md deleted file mode 100644 index 2f1c7e810..000000000 --- a/v3/examples/window/README.md +++ /dev/null @@ -1,19 +0,0 @@ -# Window Example - -This example is a demonstration of the Windows API. - -## Running the example - -To run the example, simply run the following command: - -```bash -go run . -``` - -# Status - -| Platform | Status | -|----------|---------| -| Mac | | -| Windows | Working | -| Linux | | diff --git a/v3/examples/window/assets/index.html b/v3/examples/window/assets/index.html deleted file mode 100644 index 16baa68ff..000000000 --- a/v3/examples/window/assets/index.html +++ /dev/null @@ -1,90 +0,0 @@ - - - - - - Window Demo - - - - - -
                    -
                    - -
                    -
                    -
                    - -
                    - -  X: - - -  Width: - - -   - - -
                    - - - -   - - - -   - -
                    - - - - - - \ No newline at end of file diff --git a/v3/examples/window/main.go b/v3/examples/window/main.go deleted file mode 100644 index a70cc1e8a..000000000 --- a/v3/examples/window/main.go +++ /dev/null @@ -1,761 +0,0 @@ -package main - -import ( - "embed" - "fmt" - "log" - "math/rand" - "runtime" - "strconv" - "time" - - "github.com/samber/lo" - "github.com/wailsapp/wails/v3/pkg/events" - - "github.com/wailsapp/wails/v3/pkg/application" -) - -// This is a stub for non-windows platforms -var getExStyle = func() int { - return 0 -} - -//go:embed assets/* -var assets embed.FS - -type WindowService struct{} - -// ============================================== -func (s *WindowService) SetPos(relative bool, x, y float64) { - win := application.Get().Window.Current() - initX, initY := win.Position() - if relative { - x += float64(initX) - y += float64(initY) - } - win.SetPosition(int(x), int(y)) - currentX, currentY := win.Position() - fmt.Printf("SetPos: %d, %d => %d, %d\n", initX, initY, currentX, currentY) -} -func (s *WindowService) SetSize(relative bool, wdt, hgt float64) { - win := application.Get().Window.Current() - initW, initH := win.Size() - if relative { - wdt += float64(initW) - hgt += float64(initH) - } - win.SetSize(int(wdt), int(hgt)) - currentW, currentH := win.Size() - fmt.Printf("SetSize: %d, %d => %d, %d\n", initW, initH, currentW, currentH) -} -func (s *WindowService) SetBounds(x, y, w, h float64) { - win := application.Get().Window.Current() - initR := win.Bounds() - win.SetBounds(application.Rect{ - X: int(x), - Y: int(y), - Width: int(w), - Height: int(h), - }) - currentR := win.Bounds() - fmt.Printf("SetBounds: %+v => %+v\n", initR, currentR) -} -func (s *WindowService) GetBounds() application.Rect { - win := application.Get().Window.Current() - r := win.Bounds() - mid := r.X + (r.Width-1)/2 - fmt.Printf("GetBounds: %+v: mid: %d\n", r, mid) - return r -} - -// ============================================== - -func main() { - app := application.New(application.Options{ - Name: "WebviewWindow Demo", - Description: "A demo of the WebviewWindow API", - Assets: application.AssetOptions{ - Handler: application.BundledAssetFileServer(assets), - }, - Mac: application.MacOptions{ - ApplicationShouldTerminateAfterLastWindowClosed: false, - }, - Services: []application.Service{ - application.NewService(&WindowService{}), - }, - }) - app.Event.OnApplicationEvent(events.Common.ApplicationStarted, func(event *application.ApplicationEvent) { - log.Println("ApplicationDidFinishLaunching") - }) - - var hiddenWindows []application.Window - - currentWindow := func(fn func(window application.Window)) { - if app.Window.Current() != nil { - fn(app.Window.Current()) - } else { - println("Current Window is nil") - } - } - - // Create a custom menu - menu := app.NewMenu() - if runtime.GOOS == "darwin" { - menu.AddRole(application.AppMenu) - } else { - menu.AddRole(application.FileMenu) - } - windowCounter := 1 - - // Let's make a "Demo" menu - myMenu := menu.AddSubmenu("New") - - myMenu.Add("New WebviewWindow"). - SetAccelerator("CmdOrCtrl+N"). - OnClick(func(ctx *application.Context) { - app.Window.New(). - SetTitle("WebviewWindow "+strconv.Itoa(windowCounter)). - SetRelativePosition(rand.Intn(1000), rand.Intn(800)). - SetURL("https://wails.io"). - Show() - windowCounter++ - }) - if runtime.GOOS != "linux" { - myMenu.Add("New WebviewWindow (Content Protection Enabled)"). - OnClick(func(ctx *application.Context) { - app.Window.NewWithOptions(application.WebviewWindowOptions{ - MinimiseButtonState: application.ButtonDisabled, - ContentProtectionEnabled: true, - }). - SetTitle("WebviewWindow "+strconv.Itoa(windowCounter)). - SetRelativePosition(rand.Intn(1000), rand.Intn(800)). - SetURL("https://wails.io"). - Show() - windowCounter++ - }) - myMenu.Add("New WebviewWindow (Disable Minimise)"). - OnClick(func(ctx *application.Context) { - app.Window.NewWithOptions(application.WebviewWindowOptions{ - MinimiseButtonState: application.ButtonDisabled, - }). - SetTitle("WebviewWindow "+strconv.Itoa(windowCounter)). - SetRelativePosition(rand.Intn(1000), rand.Intn(800)). - SetURL("https://wails.io"). - Show() - windowCounter++ - }) - myMenu.Add("New WebviewWindow (Disable Maximise)"). - OnClick(func(ctx *application.Context) { - app.Window.NewWithOptions(application.WebviewWindowOptions{ - MaximiseButtonState: application.ButtonDisabled, - }). - SetTitle("WebviewWindow "+strconv.Itoa(windowCounter)). - SetRelativePosition(rand.Intn(1000), rand.Intn(800)). - SetURL("https://wails.io"). - Show() - windowCounter++ - }) - myMenu.Add("New WebviewWindow (Hide Minimise)"). - OnClick(func(ctx *application.Context) { - app.Window.NewWithOptions(application.WebviewWindowOptions{ - MinimiseButtonState: application.ButtonHidden, - }). - SetTitle("WebviewWindow "+strconv.Itoa(windowCounter)). - SetRelativePosition(rand.Intn(1000), rand.Intn(800)). - SetURL("https://wails.io"). - Show() - windowCounter++ - }) - myMenu.Add("New WebviewWindow (Always on top)"). - OnClick(func(ctx *application.Context) { - app.Window.NewWithOptions(application.WebviewWindowOptions{ - AlwaysOnTop: true, - }). - SetTitle("WebviewWindow "+strconv.Itoa(windowCounter)). - SetRelativePosition(rand.Intn(1000), rand.Intn(800)). - SetURL("https://wails.io"). - Show() - windowCounter++ - }) - myMenu.Add("New WebviewWindow (Hide Maximise)"). - OnClick(func(ctx *application.Context) { - app.Window.NewWithOptions(application.WebviewWindowOptions{ - MaximiseButtonState: application.ButtonHidden, - }). - SetTitle("WebviewWindow "+strconv.Itoa(windowCounter)). - SetRelativePosition(rand.Intn(1000), rand.Intn(800)). - SetURL("https://wails.io"). - Show() - windowCounter++ - }) - - myMenu.Add("New WebviewWindow (Centered)"). - OnClick(func(ctx *application.Context) { - app.Window.NewWithOptions(application.WebviewWindowOptions{ - MaximiseButtonState: application.ButtonHidden, - InitialPosition: application.WindowCentered, - }). - SetTitle("WebviewWindow " + strconv.Itoa(windowCounter)). - SetURL("https://wails.io"). - Show() - windowCounter++ - }) - - myMenu.Add("New WebviewWindow (Position 100,100)"). - OnClick(func(ctx *application.Context) { - app.Window.NewWithOptions(application.WebviewWindowOptions{ - MaximiseButtonState: application.ButtonHidden, - X: 100, - Y: 100, - InitialPosition: application.WindowXY, - }). - SetTitle("WebviewWindow " + strconv.Itoa(windowCounter)). - SetURL("https://wails.io"). - Show() - windowCounter++ - }) - } - if runtime.GOOS == "darwin" || runtime.GOOS == "windows" { - myMenu.Add("New WebviewWindow (Disable Close)"). - OnClick(func(ctx *application.Context) { - app.Window.NewWithOptions(application.WebviewWindowOptions{ - CloseButtonState: application.ButtonDisabled, - }). - SetTitle("WebviewWindow "+strconv.Itoa(windowCounter)). - SetRelativePosition(rand.Intn(1000), rand.Intn(800)). - SetURL("https://wails.io"). - Show() - windowCounter++ - }) - myMenu.Add("New WebviewWindow (Hide Close)"). - OnClick(func(ctx *application.Context) { - app.Window.NewWithOptions(application.WebviewWindowOptions{ - CloseButtonState: application.ButtonHidden, - }). - SetTitle("WebviewWindow "+strconv.Itoa(windowCounter)). - SetRelativePosition(rand.Intn(1000), rand.Intn(800)). - SetURL("https://wails.io"). - Show() - windowCounter++ - }) - - } - - if runtime.GOOS == "windows" { - myMenu.Add("New WebviewWindow (Custom ExStyle)"). - OnClick(func(ctx *application.Context) { - app.Window.NewWithOptions(application.WebviewWindowOptions{ - Windows: application.WindowsWindow{ - ExStyle: getExStyle(), - }, - }). - SetTitle("WebviewWindow "+strconv.Itoa(windowCounter)). - SetRelativePosition(rand.Intn(1000), rand.Intn(800)). - SetURL("https://wails.io"). - Show() - windowCounter++ - }) - } - myMenu.Add("New WebviewWindow (Listen to Move)"). - OnClick(func(ctx *application.Context) { - w := app.Window.NewWithOptions(application.WebviewWindowOptions{}). - SetTitle("WebviewWindow "+strconv.Itoa(windowCounter)). - SetRelativePosition(rand.Intn(1000), rand.Intn(800)). - SetURL("https://wails.io"). - Show() - w.OnWindowEvent(events.Common.WindowDidMove, func(event *application.WindowEvent) { - x, y := w.Position() - fmt.Printf("WindowDidMove event triggered. New position: (%d, %d)\n", x, y) - }) - windowCounter++ - }) - myMenu.Add("New WebviewWindow (Listen to Resize)"). - OnClick(func(ctx *application.Context) { - w := app.Window.NewWithOptions(application.WebviewWindowOptions{}). - SetTitle("WebviewWindow "+strconv.Itoa(windowCounter)). - SetRelativePosition(rand.Intn(1000), rand.Intn(800)). - SetURL("https://wails.io"). - Show() - w.OnWindowEvent(events.Common.WindowDidResize, func(event *application.WindowEvent) { - width, height := w.Size() - - fmt.Printf("WindowDidResize event triggered. New size: (%d, %d)\n", width, height) - }) - windowCounter++ - }) - myMenu.Add("New WebviewWindow (Hides on Close one time)"). - SetAccelerator("CmdOrCtrl+H"). - OnClick(func(ctx *application.Context) { - var w application.Window = app.Window.New() - - w.RegisterHook(events.Common.WindowClosing, func(e *application.WindowEvent) { - if !lo.Contains(hiddenWindows, w) { - hiddenWindows = append(hiddenWindows, w) - go func() { - time.Sleep(5 * time.Second) - w.Show() - }() - w.Hide() - e.Cancel() - } - // Remove the window from the hiddenWindows list - hiddenWindows = lo.Without(hiddenWindows, w) - }) - - w.SetTitle("WebviewWindow "+strconv.Itoa(windowCounter)). - SetRelativePosition(rand.Intn(1000), rand.Intn(800)). - SetURL("https://wails.io"). - Show() - - windowCounter++ - - }) - myMenu.Add("New WebviewWindow (Frameless)"). - SetAccelerator("CmdOrCtrl+F"). - OnClick(func(ctx *application.Context) { - app.Window.NewWithOptions(application.WebviewWindowOptions{ - X: rand.Intn(1000), - Y: rand.Intn(800), - BackgroundColour: application.NewRGB(33, 37, 41), - Frameless: true, - Mac: application.MacWindow{ - InvisibleTitleBarHeight: 50, - }, - }).Show() - windowCounter++ - }) - myMenu.Add("New WebviewWindow (Ignores mouse events)"). - SetAccelerator("CmdOrCtrl+F"). - OnClick(func(ctx *application.Context) { - app.Window.NewWithOptions(application.WebviewWindowOptions{ - HTML: "
                    ", - X: rand.Intn(1000), - Y: rand.Intn(800), - IgnoreMouseEvents: true, - BackgroundType: application.BackgroundTypeTransparent, - Mac: application.MacWindow{ - InvisibleTitleBarHeight: 50, - }, - }).Show() - windowCounter++ - }) - if runtime.GOOS == "darwin" { - myMenu.Add("New WebviewWindow (MacTitleBarHiddenInset)"). - OnClick(func(ctx *application.Context) { - app.Window.NewWithOptions(application.WebviewWindowOptions{ - Mac: application.MacWindow{ - TitleBar: application.MacTitleBarHiddenInset, - InvisibleTitleBarHeight: 25, - }, - }). - SetBackgroundColour(application.NewRGB(33, 37, 41)). - SetTitle("WebviewWindow "+strconv.Itoa(windowCounter)). - SetRelativePosition(rand.Intn(1000), rand.Intn(800)). - SetHTML("

                    A MacTitleBarHiddenInset WebviewWindow example

                    "). - Show() - windowCounter++ - }) - myMenu.Add("New WebviewWindow (MacTitleBarHiddenInsetUnified)"). - OnClick(func(ctx *application.Context) { - app.Window.NewWithOptions(application.WebviewWindowOptions{ - Mac: application.MacWindow{ - TitleBar: application.MacTitleBarHiddenInsetUnified, - InvisibleTitleBarHeight: 50, - }, - }). - SetTitle("WebviewWindow "+strconv.Itoa(windowCounter)). - SetRelativePosition(rand.Intn(1000), rand.Intn(800)). - SetHTML("

                    A MacTitleBarHiddenInsetUnified WebviewWindow example

                    "). - Show() - windowCounter++ - }) - myMenu.Add("New WebviewWindow (MacTitleBarHidden)"). - OnClick(func(ctx *application.Context) { - app.Window.NewWithOptions(application.WebviewWindowOptions{ - Mac: application.MacWindow{ - TitleBar: application.MacTitleBarHidden, - InvisibleTitleBarHeight: 25, - }, - }). - SetTitle("WebviewWindow "+strconv.Itoa(windowCounter)). - SetRelativePosition(rand.Intn(1000), rand.Intn(800)). - SetHTML("

                    A MacTitleBarHidden WebviewWindow example

                    "). - Show() - windowCounter++ - }) - } - if runtime.GOOS == "windows" { - myMenu.Add("New WebviewWindow (Mica)"). - OnClick(func(ctx *application.Context) { - app.Window.NewWithOptions(application.WebviewWindowOptions{ - Title: "WebviewWindow " + strconv.Itoa(windowCounter), - X: rand.Intn(1000), - Y: rand.Intn(800), - BackgroundType: application.BackgroundTypeTranslucent, - HTML: ` - - - - - -
                    -

                    This is a Window with a Mica backdrop

                    -
                    - -`, - Windows: application.WindowsWindow{ - BackdropType: application.Mica, - }, - }).Show() - windowCounter++ - }) - myMenu.Add("New WebviewWindow (Acrylic)"). - OnClick(func(ctx *application.Context) { - app.Window.NewWithOptions(application.WebviewWindowOptions{ - Title: "WebviewWindow " + strconv.Itoa(windowCounter), - X: rand.Intn(1000), - Y: rand.Intn(800), - BackgroundType: application.BackgroundTypeTranslucent, - HTML: ` - - - - - -
                    -

                    This is a Window with an Acrylic backdrop

                    -
                    - -`, - Windows: application.WindowsWindow{ - BackdropType: application.Acrylic, - }, - }).Show() - windowCounter++ - }) - myMenu.Add("New WebviewWindow (Tabbed)"). - OnClick(func(ctx *application.Context) { - app.Window.NewWithOptions(application.WebviewWindowOptions{ - Title: "WebviewWindow " + strconv.Itoa(windowCounter), - X: rand.Intn(1000), - Y: rand.Intn(800), - BackgroundType: application.BackgroundTypeTranslucent, - HTML: ` - - - - - -
                    -

                    This is a Window with a Tabbed-effect backdrop

                    -
                    - -`, - Windows: application.WindowsWindow{ - BackdropType: application.Tabbed, - }, - }).Show() - windowCounter++ - }) - } - - sizeMenu := menu.AddSubmenu("Size") - sizeMenu.Add("Set Size (800,600)").OnClick(func(ctx *application.Context) { - currentWindow(func(w application.Window) { - w.SetSize(800, 600) - }) - }) - - sizeMenu.Add("Set Size (Random)").OnClick(func(ctx *application.Context) { - currentWindow(func(w application.Window) { - w.SetSize(rand.Intn(800)+200, rand.Intn(600)+200) - }) - }) - sizeMenu.Add("Set Min Size (200,200)").OnClick(func(ctx *application.Context) { - currentWindow(func(w application.Window) { - w.SetMinSize(200, 200) - }) - }) - sizeMenu.Add("Set Max Size (600,600)").OnClick(func(ctx *application.Context) { - currentWindow(func(w application.Window) { - w.SetMaxSize(600, 600) - w.SetMaximiseButtonState(application.ButtonDisabled) - }) - }) - sizeMenu.Add("Get Current WebviewWindow Size").OnClick(func(ctx *application.Context) { - currentWindow(func(w application.Window) { - width, height := w.Size() - app.Dialog.Info().SetTitle("Current WebviewWindow Size").SetMessage("Width: " + strconv.Itoa(width) + " Height: " + strconv.Itoa(height)).Show() - }) - }) - - sizeMenu.Add("Reset Min Size").OnClick(func(ctx *application.Context) { - currentWindow(func(w application.Window) { - w.SetMinSize(0, 0) - }) - }) - sizeMenu.Add("Reset Max Size").OnClick(func(ctx *application.Context) { - currentWindow(func(w application.Window) { - w.SetMaxSize(0, 0) - w.SetMaximiseButtonState(application.ButtonEnabled) - }) - }) - - positionMenu := menu.AddSubmenu("Position") - positionMenu.Add("Set Position (0,0)").OnClick(func(ctx *application.Context) { - currentWindow(func(w application.Window) { - w.SetPosition(0, 0) - }) - }) - - positionMenu.Add("Set Position (Random)").OnClick(func(ctx *application.Context) { - currentWindow(func(w application.Window) { - w.SetPosition(rand.Intn(1000), rand.Intn(800)) - }) - }) - - positionMenu.Add("Get Position").OnClick(func(ctx *application.Context) { - currentWindow(func(w application.Window) { - x, y := w.Position() - app.Dialog.Info().SetTitle("Current WebviewWindow Position").SetMessage("X: " + strconv.Itoa(x) + " Y: " + strconv.Itoa(y)).Show() - }) - }) - - positionMenu.Add("Set Relative Position (0,0)").OnClick(func(ctx *application.Context) { - currentWindow(func(w application.Window) { - w.SetRelativePosition(0, 0) - }) - }) - positionMenu.Add("Set Relative Position (Corner)").OnClick(func(ctx *application.Context) { - currentWindow(func(w application.Window) { - screen, _ := w.GetScreen() - w.SetRelativePosition(screen.WorkArea.Width-w.Width(), screen.WorkArea.Height-w.Height()) - }) - }) - positionMenu.Add("Set Relative Position (Random)").OnClick(func(ctx *application.Context) { - currentWindow(func(w application.Window) { - w.SetRelativePosition(rand.Intn(1000), rand.Intn(800)) - }) - }) - - positionMenu.Add("Get Relative Position").OnClick(func(ctx *application.Context) { - currentWindow(func(w application.Window) { - x, y := w.RelativePosition() - app.Dialog.Info().SetTitle("Current WebviewWindow Position").SetMessage("X: " + strconv.Itoa(x) + " Y: " + strconv.Itoa(y)).Show() - }) - }) - - positionMenu.Add("Center").OnClick(func(ctx *application.Context) { - currentWindow(func(w application.Window) { - w.Center() - }) - }) - titleBarMenu := menu.AddSubmenu("Controls") - titleBarMenu.Add("Disable Minimise").OnClick(func(ctx *application.Context) { - currentWindow(func(w application.Window) { - w.SetMinimiseButtonState(application.ButtonDisabled) - }) - }) - titleBarMenu.Add("Enable Minimise").OnClick(func(ctx *application.Context) { - currentWindow(func(w application.Window) { - w.SetMinimiseButtonState(application.ButtonEnabled) - }) - }) - titleBarMenu.Add("Hide Minimise").OnClick(func(ctx *application.Context) { - currentWindow(func(w application.Window) { - w.SetMinimiseButtonState(application.ButtonHidden) - }) - }) - titleBarMenu.Add("Disable Maximise").OnClick(func(ctx *application.Context) { - currentWindow(func(w application.Window) { - w.SetMaximiseButtonState(application.ButtonDisabled) - }) - }) - titleBarMenu.Add("Enable Maximise").OnClick(func(ctx *application.Context) { - currentWindow(func(w application.Window) { - w.SetMaximiseButtonState(application.ButtonEnabled) - }) - }) - titleBarMenu.Add("Hide Maximise").OnClick(func(ctx *application.Context) { - currentWindow(func(w application.Window) { - w.SetMaximiseButtonState(application.ButtonHidden) - }) - }) - titleBarMenu.Add("Disable Close").OnClick(func(ctx *application.Context) { - currentWindow(func(w application.Window) { - w.SetCloseButtonState(application.ButtonDisabled) - }) - }) - titleBarMenu.Add("Enable Close").OnClick(func(ctx *application.Context) { - currentWindow(func(w application.Window) { - w.SetCloseButtonState(application.ButtonEnabled) - }) - }) - titleBarMenu.Add("Hide Close").OnClick(func(ctx *application.Context) { - currentWindow(func(w application.Window) { - w.SetCloseButtonState(application.ButtonHidden) - }) - }) - stateMenu := menu.AddSubmenu("State") - stateMenu.Add("Minimise (for 2 secs)").OnClick(func(ctx *application.Context) { - currentWindow(func(w application.Window) { - w.Minimise() - time.Sleep(2 * time.Second) - w.Restore() - }) - }) - stateMenu.Add("Maximise").OnClick(func(ctx *application.Context) { - currentWindow(func(w application.Window) { - w.Maximise() - }) - }) - stateMenu.Add("Fullscreen").OnClick(func(ctx *application.Context) { - currentWindow(func(w application.Window) { - w.Fullscreen() - }) - }) - stateMenu.Add("UnFullscreen").OnClick(func(ctx *application.Context) { - currentWindow(func(w application.Window) { - w.UnFullscreen() - }) - }) - stateMenu.Add("Restore").OnClick(func(ctx *application.Context) { - currentWindow(func(w application.Window) { - w.Restore() - }) - }) - stateMenu.Add("Hide (for 2 seconds)").OnClick(func(ctx *application.Context) { - currentWindow(func(w application.Window) { - w.Hide() - time.Sleep(2 * time.Second) - w.Show() - }) - }) - stateMenu.Add("Always on Top").OnClick(func(ctx *application.Context) { - currentWindow(func(w application.Window) { - w.SetAlwaysOnTop(true) - }) - }) - stateMenu.Add("Not always on Top").OnClick(func(ctx *application.Context) { - currentWindow(func(w application.Window) { - w.SetAlwaysOnTop(false) - }) - }) - stateMenu.Add("Google.com").OnClick(func(ctx *application.Context) { - currentWindow(func(w application.Window) { - w.SetURL("https://google.com") - }) - }) - stateMenu.Add("wails.io").OnClick(func(ctx *application.Context) { - currentWindow(func(w application.Window) { - w.SetURL("https://wails.io") - }) - }) - stateMenu.Add("Get Primary Screen").OnClick(func(ctx *application.Context) { - screen := app.Screen.GetPrimary() - msg := fmt.Sprintf("Screen: %+v", screen) - app.Dialog.Info().SetTitle("Primary Screen").SetMessage(msg).Show() - }) - stateMenu.Add("Get Screens").OnClick(func(ctx *application.Context) { - screens := app.Screen.GetAll() - for _, screen := range screens { - msg := fmt.Sprintf("Screen: %+v", screen) - app.Dialog.Info().SetTitle(fmt.Sprintf("Screen %s", screen.ID)).SetMessage(msg).Show() - } - }) - stateMenu.Add("Get Screen for WebviewWindow").OnClick(func(ctx *application.Context) { - currentWindow(func(w application.Window) { - screen, err := w.GetScreen() - if err != nil { - app.Dialog.Error().SetTitle("Error").SetMessage(err.Error()).Show() - return - } - msg := fmt.Sprintf("Screen: %+v", screen) - app.Dialog.Info().SetTitle(fmt.Sprintf("Screen %s", screen.ID)).SetMessage(msg).Show() - }) - }) - stateMenu.Add("Disable for 5s").OnClick(func(ctx *application.Context) { - currentWindow(func(w application.Window) { - w.SetEnabled(false) - time.Sleep(5 * time.Second) - w.SetEnabled(true) - }) - }) - stateMenu.Add("Open Dev Tools").OnClick(func(ctx *application.Context) { - currentWindow(func(w application.Window) { - w.OpenDevTools() - }) - }) - - if runtime.GOOS != "darwin" { - stateMenu.Add("Flash for 5s").OnClick(func(ctx *application.Context) { - currentWindow(func(w application.Window) { - time.Sleep(2 * time.Second) - w.Flash(true) - time.Sleep(5 * time.Second) - w.Flash(false) - }) - }) - } - - if runtime.GOOS == "windows" { - stateMenu.Add("Snap Assist").OnClick(func(ctx *application.Context) { - currentWindow(func(w application.Window) { - w.SnapAssist() - }) - }) - } - - printMenu := menu.AddSubmenu("Print") - printMenu.Add("Print").OnClick(func(ctx *application.Context) { - currentWindow(func(w application.Window) { - _ = w.Print() - }) - }) - - app.Window.NewWithOptions(application.WebviewWindowOptions{ - Title: "Window Demo", - BackgroundColour: application.NewRGB(33, 37, 41), - Mac: application.MacWindow{ - DisableShadow: true, - }, - Windows: application.WindowsWindow{ - Menu: menu, - }, - }) - - app.Menu.Set(menu) - err := app.Run() - - if err != nil { - log.Fatal(err) - } - -} diff --git a/v3/examples/window/windows.go b/v3/examples/window/windows.go deleted file mode 100644 index d66984d18..000000000 --- a/v3/examples/window/windows.go +++ /dev/null @@ -1,11 +0,0 @@ -//go:build windows - -package main - -import "github.com/wailsapp/wails/v3/pkg/w32" - -func init() { - getExStyle = func() int { - return w32.WS_EX_TOOLWINDOW | w32.WS_EX_NOREDIRECTIONBITMAP | w32.WS_EX_TOPMOST - } -} diff --git a/v3/examples/wml/README.md b/v3/examples/wml/README.md deleted file mode 100644 index c8ea7850e..000000000 --- a/v3/examples/wml/README.md +++ /dev/null @@ -1,19 +0,0 @@ -# WML Example - -This is an example of how to use the experimental WML, which provides HTMX style calling of the Wails JS API. - -## Running the example - -To run the example, simply run the following command: - -```bash -go run . -``` - -# Status - -| Platform | Status | -|----------|---------| -| Mac | Working | -| Windows | Working | -| Linux | | diff --git a/v3/examples/wml/assets/index.html b/v3/examples/wml/assets/index.html deleted file mode 100644 index 466f4c5f0..000000000 --- a/v3/examples/wml/assets/index.html +++ /dev/null @@ -1,160 +0,0 @@ - - - - - Wails Alpha - - - - - -
                    Alpha
                    -
                    -

                    Documentation

                    -

                    Feedback

                    -
                    -

                    This application contains no Javascript!

                    -

                    Emit event

                    -

                    Delete all the things!

                    -

                    Close the Window?

                    -

                    Center

                    -

                    Minimise

                    -

                    Maximise

                    -

                    UnMaximise

                    -

                    Fullscreen

                    -

                    UnFullscreen

                    -

                    Restore

                    -

                    Open Browser?

                    -

                    Hover over me

                    -
                    - - - - - diff --git a/v3/examples/wml/main.go b/v3/examples/wml/main.go deleted file mode 100644 index 8d4a55481..000000000 --- a/v3/examples/wml/main.go +++ /dev/null @@ -1,50 +0,0 @@ -package main - -import ( - "embed" - _ "embed" - "log" - - "github.com/wailsapp/wails/v3/pkg/application" -) - -//go:embed assets/* -var assets embed.FS - -func main() { - - app := application.New(application.Options{ - Name: "Wails ML Demo", - Description: "A demo of the Wails ML API", - Mac: application.MacOptions{ - ApplicationShouldTerminateAfterLastWindowClosed: true, - }, - Assets: application.AssetOptions{ - Handler: application.BundledAssetFileServer(assets), - }, - }) - - app.Window.NewWithOptions(application.WebviewWindowOptions{ - Title: "Wails ML Demo", - Width: 1280, - Height: 1024, - Mac: application.MacWindow{ - Backdrop: application.MacBackdropTranslucent, - TitleBar: application.MacTitleBarHiddenInsetUnified, - InvisibleTitleBarHeight: 50, - }, - }) - - app.Event.On("button-pressed", func(_ *application.CustomEvent) { - println("Button Pressed!") - }) - app.Event.On("hover", func(_ *application.CustomEvent) { - println("Hover time!") - }) - - err := app.Run() - - if err != nil { - log.Fatal(err.Error()) - } -} diff --git a/v3/fix-darwin-ios-constraints.sh b/v3/fix-darwin-ios-constraints.sh deleted file mode 100644 index 67211e7b9..000000000 --- a/v3/fix-darwin-ios-constraints.sh +++ /dev/null @@ -1,54 +0,0 @@ -#!/bin/bash - -# Fix build constraints for Darwin files to exclude iOS -echo "Fixing build constraints to exclude iOS from Darwin builds..." - -# List of files that need updating -files=( - "pkg/application/webview_window_darwin.m" - "pkg/application/webview_window_darwin.h" - "pkg/application/webview_window_darwin.go" - "pkg/application/webview_window_darwin_drag.m" - "pkg/application/webview_window_darwin_drag.h" - "pkg/application/webview_window_close_darwin.go" - "pkg/application/systemtray_darwin.m" - "pkg/application/systemtray_darwin.h" - "pkg/application/systemtray_darwin.go" - "pkg/application/single_instance_darwin.go" - "pkg/application/screen_darwin.go" - "pkg/application/menuitem_selectors_darwin.go" - "pkg/application/menuitem_darwin.m" - "pkg/application/menuitem_darwin.go" - "pkg/application/menu_darwin.go" - "pkg/application/mainthread_darwin.go" - "pkg/application/keys_darwin.go" - "pkg/application/events_common_darwin.go" - "pkg/application/dialogs_darwin_delegate.m" - "pkg/application/dialogs_darwin_delegate.h" - "pkg/application/dialogs_darwin.go" - "pkg/application/clipboard_darwin.go" - "pkg/application/application_darwin_delegate.m" - "pkg/application/application_darwin_delegate.h" - "pkg/application/application_darwin.h" -) - -for file in "${files[@]}"; do - if [ -f "$file" ]; then - # Check if file has the build constraint - if grep -q "^//go:build darwin$" "$file"; then - echo "Updating $file" - sed -i '' 's|^//go:build darwin$|//go:build darwin \&\& !ios|' "$file" - fi - fi -done - -# Also check for other darwin-specific files -echo "Checking for other darwin-specific build constraints..." -find . -name "*_darwin*.go" -o -name "*_darwin*.m" -o -name "*_darwin*.h" | while read -r file; do - if grep -q "^//go:build darwin$" "$file"; then - echo "Also updating: $file" - sed -i '' 's|^//go:build darwin$|//go:build darwin \&\& !ios|' "$file" - fi -done - -echo "Done! Build constraints updated." \ No newline at end of file diff --git a/v3/go.mod b/v3/go.mod deleted file mode 100644 index c5aa9a11e..000000000 --- a/v3/go.mod +++ /dev/null @@ -1,172 +0,0 @@ -module github.com/wailsapp/wails/v3 - -go 1.25 - -require ( - git.sr.ht/~jackmordaunt/go-toast/v2 v2.0.3 - github.com/Masterminds/semver v1.5.0 - github.com/adrg/xdg v0.5.3 - github.com/atterpac/refresh v0.8.6 - github.com/bep/debounce v1.2.1 - github.com/charmbracelet/glamour v0.10.0 - github.com/charmbracelet/huh v0.8.0 - github.com/coder/websocket v1.8.14 - github.com/ebitengine/purego v0.9.1 - github.com/go-git/go-git/v5 v5.16.4 - github.com/go-json-experiment/json v0.0.0-20251027170946-4849db3c2f7e - github.com/go-ole/go-ole v1.3.0 - github.com/godbus/dbus/v5 v5.2.2 - github.com/google/go-cmp v0.7.0 - github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 - github.com/google/uuid v1.6.0 - github.com/goreleaser/nfpm/v2 v2.44.1 - github.com/gorilla/websocket v1.5.3 - github.com/jackmordaunt/icns/v2 v2.2.7 - github.com/jaypipes/ghw v0.21.2 - github.com/konoui/lipo v0.10.0 - github.com/leaanthony/clir v1.7.0 - github.com/leaanthony/go-ansi-parser v1.6.1 - github.com/leaanthony/gosod v1.0.4 - github.com/leaanthony/u v1.1.1 - github.com/leaanthony/winicon v1.0.0 - github.com/lmittmann/tint v1.1.2 - github.com/matryer/is v1.4.1 - github.com/mattn/go-colorable v0.1.14 - github.com/mattn/go-isatty v0.0.20 - github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c - github.com/pkg/errors v0.9.1 - github.com/pterm/pterm v0.12.82 - github.com/samber/lo v1.52.0 - github.com/stretchr/testify v1.11.1 - github.com/tc-hib/winres v0.3.1 - github.com/wailsapp/go-webview2 v1.0.23 - github.com/wailsapp/task/v3 v3.40.1-patched3 - github.com/zalando/go-keyring v0.2.6 - golang.org/x/sys v0.40.0 - golang.org/x/term v0.39.0 - golang.org/x/tools v0.41.0 - gopkg.in/yaml.v3 v3.0.1 - modernc.org/sqlite v1.44.3 -) - -require ( - al.essio.dev/pkg/shellescape v1.6.0 // indirect - atomicgo.dev/schedule v0.1.0 // indirect - github.com/atotto/clipboard v0.1.4 // indirect - github.com/catppuccin/go v0.3.0 // indirect - github.com/charmbracelet/bubbles v0.21.1-0.20250623103423-23b8fd6302d7 // indirect - github.com/charmbracelet/bubbletea v1.3.10 // indirect - github.com/charmbracelet/colorprofile v0.4.1 // indirect - github.com/charmbracelet/x/cellbuf v0.0.14 // indirect - github.com/charmbracelet/x/exp/slice v0.0.0-20260122224438-b01af16209d9 // indirect - github.com/charmbracelet/x/exp/strings v0.0.0-20260122224438-b01af16209d9 // indirect - github.com/charmbracelet/x/term v0.2.2 // indirect - github.com/clipperhouse/displaywidth v0.7.0 // indirect - github.com/clipperhouse/stringish v0.1.1 // indirect - github.com/clipperhouse/uax29/v2 v2.4.0 // indirect - github.com/danieljoos/wincred v1.2.3 // indirect - github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f // indirect - github.com/konoui/go-qsort v0.1.0 // indirect - github.com/mattn/go-localereader v0.0.1 // indirect - github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 // indirect - github.com/ncruces/go-strftime v1.0.0 // indirect - github.com/pmezard/go-difflib v1.0.0 // indirect - github.com/yusufpapurcu/wmi v1.2.4 // indirect - go.yaml.in/yaml/v3 v3.0.4 // indirect -) - -require ( - atomicgo.dev/cursor v0.2.0 // indirect - atomicgo.dev/keyboard v0.2.9 // indirect - dario.cat/mergo v1.0.2 // indirect - github.com/AlekSi/pointer v1.2.0 // indirect - github.com/BurntSushi/toml v1.6.0 // indirect - github.com/Ladicle/tabwriter v1.0.0 // indirect - github.com/Masterminds/goutils v1.1.1 // indirect - github.com/Masterminds/semver/v3 v3.4.0 // indirect - github.com/Masterminds/sprig/v3 v3.3.0 // indirect - github.com/Microsoft/go-winio v0.6.2 // indirect - github.com/ProtonMail/go-crypto v1.3.0 - github.com/alecthomas/chroma/v2 v2.23.1 // indirect - github.com/aymanbagabas/go-osc52/v2 v2.0.1 // indirect - github.com/aymerick/douceur v0.2.0 // indirect - github.com/blakesmith/ar v0.0.0-20190502131153-809d4375e1fb // indirect - github.com/cavaliergopher/cpio v1.0.1 // indirect - github.com/chainguard-dev/git-urls v1.0.2 // indirect - github.com/charmbracelet/lipgloss v1.1.1-0.20250404203927-76690c660834 // indirect - github.com/charmbracelet/x/ansi v0.11.4 // indirect - github.com/cloudflare/circl v1.6.3 // indirect - github.com/containerd/console v1.0.5 // indirect - github.com/cyphar/filepath-securejoin v0.6.1 // indirect - github.com/davecgh/go-spew v1.1.1 // indirect - github.com/dlclark/regexp2 v1.11.5 // indirect - github.com/dominikbraun/graph v0.23.0 // indirect - github.com/dustin/go-humanize v1.0.1 // indirect - github.com/emirpasic/gods v1.18.1 // indirect - github.com/fatih/color v1.18.0 // indirect - github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect - github.com/go-git/go-billy/v5 v5.7.0 // indirect - github.com/go-task/slim-sprig/v3 v3.0.0 // indirect - github.com/go-task/template v0.2.0 // indirect - github.com/gobwas/glob v0.2.3 // indirect - github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect - github.com/google/rpmpack v0.7.1 // indirect - github.com/gookit/color v1.6.0 // indirect - github.com/goreleaser/chglog v0.7.4 // indirect - github.com/goreleaser/fileglob v1.4.0 // indirect - github.com/gorilla/css v1.0.1 // indirect - github.com/huandu/xstrings v1.5.0 // indirect - github.com/jaypipes/pcidb v1.1.1 // indirect - github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect - github.com/jchv/go-winloader v0.0.0-20250406163304-c1995be93bd1 // indirect - github.com/joho/godotenv v1.5.1 // indirect - github.com/kevinburke/ssh_config v1.4.0 // indirect - github.com/klauspost/compress v1.18.3 // indirect - github.com/klauspost/cpuid/v2 v2.3.0 // indirect - github.com/klauspost/pgzip v1.2.6 // indirect - github.com/lithammer/fuzzysearch v1.1.8 // indirect - github.com/lucasb-eyer/go-colorful v1.3.0 // indirect - github.com/mattn/go-runewidth v0.0.19 // indirect - github.com/mattn/go-zglob v0.0.6 // indirect - github.com/microcosm-cc/bluemonday v1.0.27 // indirect - github.com/mitchellh/copystructure v1.2.0 // indirect - github.com/mitchellh/hashstructure/v2 v2.0.2 // indirect - github.com/mitchellh/reflectwalk v1.0.2 // indirect - github.com/muesli/cancelreader v0.2.2 // indirect - github.com/muesli/reflow v0.3.0 // indirect - github.com/muesli/termenv v0.16.0 // indirect - github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 // indirect - github.com/pjbgf/sha1cd v0.5.0 // indirect - github.com/radovskyb/watcher v1.0.7 // indirect - github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect - github.com/rivo/uniseg v0.4.7 // indirect - github.com/rjeczalik/notify v0.9.3 // indirect - github.com/sajari/fuzzy v1.0.0 // indirect - github.com/sergi/go-diff v1.4.0 // indirect - github.com/shopspring/decimal v1.4.0 // indirect - github.com/skeema/knownhosts v1.3.2 // indirect - github.com/spf13/cast v1.10.0 // indirect - github.com/spf13/pflag v1.0.10 // indirect - github.com/ulikunitz/xz v0.5.15 // indirect - github.com/xanzy/ssh-agent v0.3.3 // indirect - github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect - github.com/yuin/goldmark v1.7.16 // indirect - github.com/yuin/goldmark-emoji v1.0.6 // indirect - github.com/zeebo/xxh3 v1.1.0 // indirect - gitlab.com/digitalxero/go-conventional-commit v1.0.7 // indirect - golang.org/x/crypto v0.47.0 // indirect - golang.org/x/exp v0.0.0-20260112195511-716be5621a96 // indirect - golang.org/x/exp/typeparams v0.0.0-20260112195511-716be5621a96 - golang.org/x/image v0.35.0 - golang.org/x/mod v0.32.0 // indirect - golang.org/x/net v0.49.0 // indirect - golang.org/x/sync v0.19.0 // indirect - golang.org/x/text v0.33.0 // indirect - gopkg.in/warnings.v0 v0.1.2 // indirect - gopkg.in/yaml.v2 v2.4.0 // indirect - howett.net/plist v1.0.2-0.20250314012144-ee69052608d9 - modernc.org/libc v1.67.6 // indirect - modernc.org/mathutil v1.7.1 // indirect - modernc.org/memory v1.11.0 // indirect - mvdan.cc/sh/v3 v3.12.0 // indirect -) diff --git a/v3/go.sum b/v3/go.sum deleted file mode 100644 index dd0b0ae81..000000000 --- a/v3/go.sum +++ /dev/null @@ -1,520 +0,0 @@ -al.essio.dev/pkg/shellescape v1.6.0 h1:NxFcEqzFSEVCGN2yq7Huv/9hyCEGVa/TncnOOBBeXHA= -al.essio.dev/pkg/shellescape v1.6.0/go.mod h1:6sIqp7X2P6mThCQ7twERpZTuigpr6KbZWtls1U8I890= -atomicgo.dev/assert v0.0.2 h1:FiKeMiZSgRrZsPo9qn/7vmr7mCsh5SZyXY4YGYiYwrg= -atomicgo.dev/assert v0.0.2/go.mod h1:ut4NcI3QDdJtlmAxQULOmA13Gz6e2DWbSAS8RUOmNYQ= -atomicgo.dev/cursor v0.2.0 h1:H6XN5alUJ52FZZUkI7AlJbUc1aW38GWZalpYRPpoPOw= -atomicgo.dev/cursor v0.2.0/go.mod h1:Lr4ZJB3U7DfPPOkbH7/6TOtJ4vFGHlgj1nc+n900IpU= -atomicgo.dev/keyboard v0.2.9 h1:tOsIid3nlPLZ3lwgG8KZMp/SFmr7P0ssEN5JUsm78K8= -atomicgo.dev/keyboard v0.2.9/go.mod h1:BC4w9g00XkxH/f1HXhW2sXmJFOCWbKn9xrOunSFtExQ= -atomicgo.dev/schedule v0.1.0 h1:nTthAbhZS5YZmgYbb2+DH8uQIZcTlIrd4eYr3UQxEjs= -atomicgo.dev/schedule v0.1.0/go.mod h1:xeUa3oAkiuHYh8bKiQBRojqAMq3PXXbJujjb0hw8pEU= -dario.cat/mergo v1.0.2 h1:85+piFYR1tMbRrLcDwR18y4UKJ3aH1Tbzi24VRW1TK8= -dario.cat/mergo v1.0.2/go.mod h1:E/hbnu0NxMFBjpMIE34DRGLWqDy0g5FuKDhCb31ngxA= -git.sr.ht/~jackmordaunt/go-toast/v2 v2.0.3 h1:N3IGoHHp9pb6mj1cbXbuaSXV/UMKwmbKLf53nQmtqMA= -git.sr.ht/~jackmordaunt/go-toast/v2 v2.0.3/go.mod h1:QtOLZGz8olr4qH2vWK0QH0w0O4T9fEIjMuWpKUsH7nc= -github.com/AlekSi/pointer v1.2.0 h1:glcy/gc4h8HnG2Z3ZECSzZ1IX1x2JxRVuDzaJwQE0+w= -github.com/AlekSi/pointer v1.2.0/go.mod h1:gZGfd3dpW4vEc/UlyfKKi1roIqcCgwOIvb0tSNSBle0= -github.com/BurntSushi/toml v1.6.0 h1:dRaEfpa2VI55EwlIW72hMRHdWouJeRF7TPYhI+AUQjk= -github.com/BurntSushi/toml v1.6.0/go.mod h1:ukJfTF/6rtPPRCnwkur4qwRxa8vTRFBF0uk2lLoLwho= -github.com/DataDog/zstd v1.5.5 h1:oWf5W7GtOLgp6bciQYDmhHHjdhYkALu6S/5Ni9ZgSvQ= -github.com/DataDog/zstd v1.5.5/go.mod h1:g4AWEaM3yOg3HYfnJ3YIawPnVdXJh9QME85blwSAmyw= -github.com/Ladicle/tabwriter v1.0.0 h1:DZQqPvMumBDwVNElso13afjYLNp0Z7pHqHnu0r4t9Dg= -github.com/Ladicle/tabwriter v1.0.0/go.mod h1:c4MdCjxQyTbGuQO/gvqJ+IA/89UEwrsD6hUCW98dyp4= -github.com/MakeNowJust/heredoc v1.0.0 h1:cXCdzVdstXyiTqTvfqk9SDHpKNjxuom+DOlyEeQ4pzQ= -github.com/MakeNowJust/heredoc v1.0.0/go.mod h1:mG5amYoWBHf8vpLOuehzbGGw0EHxpZZ6lCpQ4fNJ8LE= -github.com/MarvinJWendt/testza v0.1.0/go.mod h1:7AxNvlfeHP7Z/hDQ5JtE3OKYT3XFUeLCDE2DQninSqs= -github.com/MarvinJWendt/testza v0.2.1/go.mod h1:God7bhG8n6uQxwdScay+gjm9/LnO4D3kkcZX4hv9Rp8= -github.com/MarvinJWendt/testza v0.2.8/go.mod h1:nwIcjmr0Zz+Rcwfh3/4UhBp7ePKVhuBExvZqnKYWlII= -github.com/MarvinJWendt/testza v0.2.10/go.mod h1:pd+VWsoGUiFtq+hRKSU1Bktnn+DMCSrDrXDpX2bG66k= -github.com/MarvinJWendt/testza v0.2.12/go.mod h1:JOIegYyV7rX+7VZ9r77L/eH6CfJHHzXjB69adAhzZkI= -github.com/MarvinJWendt/testza v0.3.0/go.mod h1:eFcL4I0idjtIx8P9C6KkAuLgATNKpX4/2oUqKc6bF2c= -github.com/MarvinJWendt/testza v0.4.2/go.mod h1:mSdhXiKH8sg/gQehJ63bINcCKp7RtYewEjXsvsVUPbE= -github.com/MarvinJWendt/testza v0.5.2 h1:53KDo64C1z/h/d/stCYCPY69bt/OSwjq5KpFNwi+zB4= -github.com/MarvinJWendt/testza v0.5.2/go.mod h1:xu53QFE5sCdjtMCKk8YMQ2MnymimEctc4n3EjyIYvEY= -github.com/Masterminds/goutils v1.1.1 h1:5nUrii3FMTL5diU80unEVvNevw1nH4+ZV4DSLVJLSYI= -github.com/Masterminds/goutils v1.1.1/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU= -github.com/Masterminds/semver v1.5.0 h1:H65muMkzWKEuNDnfl9d70GUjFniHKHRbFPGBuZ3QEww= -github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF078ddwwvV3Y= -github.com/Masterminds/semver/v3 v3.4.0 h1:Zog+i5UMtVoCU8oKka5P7i9q9HgrJeGzI9SA1Xbatp0= -github.com/Masterminds/semver/v3 v3.4.0/go.mod h1:4V+yj/TJE1HU9XfppCwVMZq3I84lprf4nC11bSS5beM= -github.com/Masterminds/sprig/v3 v3.3.0 h1:mQh0Yrg1XPo6vjYXgtf5OtijNAKJRNcTdOOGZe3tPhs= -github.com/Masterminds/sprig/v3 v3.3.0/go.mod h1:Zy1iXRYNqNLUolqCpL4uhk6SHUMAOSCzdgBfDb35Lz0= -github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY= -github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= -github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= -github.com/ProtonMail/go-crypto v1.3.0 h1:ILq8+Sf5If5DCpHQp4PbZdS1J7HDFRXz/+xKBiRGFrw= -github.com/ProtonMail/go-crypto v1.3.0/go.mod h1:9whxjD8Rbs29b4XWbB8irEcE8KHMqaR2e7GWU1R+/PE= -github.com/ProtonMail/go-mime v0.0.0-20230322103455-7d82a3887f2f h1:tCbYj7/299ekTTXpdwKYF8eBlsYsDVoggDAuAjoK66k= -github.com/ProtonMail/go-mime v0.0.0-20230322103455-7d82a3887f2f/go.mod h1:gcr0kNtGBqin9zDW9GOHcVntrwnjrK+qdJ06mWYBybw= -github.com/ProtonMail/gopenpgp/v2 v2.7.1 h1:Awsg7MPc2gD3I7IFac2qE3Gdls0lZW8SzrFZ3k1oz0s= -github.com/ProtonMail/gopenpgp/v2 v2.7.1/go.mod h1:/BU5gfAVwqyd8EfC3Eu7zmuhwYQpKs+cGD8M//iiaxs= -github.com/adrg/xdg v0.5.3 h1:xRnxJXne7+oWDatRhR1JLnvuccuIeCoBu2rtuLqQB78= -github.com/adrg/xdg v0.5.3/go.mod h1:nlTsY+NNiCBGCK2tpm09vRqfVzrc2fLmXGpBLF0zlTQ= -github.com/alecthomas/assert/v2 v2.11.0 h1:2Q9r3ki8+JYXvGsDyBXwH3LcJ+WK5D0gc5E8vS6K3D0= -github.com/alecthomas/assert/v2 v2.11.0/go.mod h1:Bze95FyfUr7x34QZrjL+XP+0qgp/zg8yS+TtBj1WA3k= -github.com/alecthomas/chroma/v2 v2.23.1 h1:nv2AVZdTyClGbVQkIzlDm/rnhk1E9bU9nXwmZ/Vk/iY= -github.com/alecthomas/chroma/v2 v2.23.1/go.mod h1:NqVhfBR0lte5Ouh3DcthuUCTUpDC9cxBOfyMbMQPs3o= -github.com/alecthomas/repr v0.5.2 h1:SU73FTI9D1P5UNtvseffFSGmdNci/O6RsqzeXJtP0Qs= -github.com/alecthomas/repr v0.5.2/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4= -github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8= -github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4= -github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= -github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= -github.com/atomicgo/cursor v0.0.1/go.mod h1:cBON2QmmrysudxNBFthvMtN32r3jxVRIvzkUiF/RuIk= -github.com/atotto/clipboard v0.1.4 h1:EH0zSVneZPSuFR11BlR9YppQTVDbh5+16AmcJi4g1z4= -github.com/atotto/clipboard v0.1.4/go.mod h1:ZY9tmq7sm5xIbd9bOK4onWV4S6X0u6GY7Vn0Yu86PYI= -github.com/atterpac/refresh v0.8.6 h1:Q5miKV2qs9jW+USw8WZ/54Zz8/RSh/bOz5U6JvvDZmM= -github.com/atterpac/refresh v0.8.6/go.mod h1:fJpWySLdpbANS8Ej5OvfZVZIVvi/9bmnhTjKS5EjQes= -github.com/aymanbagabas/go-osc52/v2 v2.0.1 h1:HwpRHbFMcZLEVr42D4p7XBqjyuxQH5SMiErDT4WkJ2k= -github.com/aymanbagabas/go-osc52/v2 v2.0.1/go.mod h1:uYgXzlJ7ZpABp8OJ+exZzJJhRNQ2ASbcXHWsFqH8hp8= -github.com/aymanbagabas/go-udiff v0.3.1 h1:LV+qyBQ2pqe0u42ZsUEtPiCaUoqgA9gYRDs3vj1nolY= -github.com/aymanbagabas/go-udiff v0.3.1/go.mod h1:G0fsKmG+P6ylD0r6N/KgQD/nWzgfnl8ZBcNLgcbrw8E= -github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk= -github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4= -github.com/bep/debounce v1.2.1 h1:v67fRdBA9UQu2NhLFXrSg0Brw7CexQekrBwDMM8bzeY= -github.com/bep/debounce v1.2.1/go.mod h1:H8yggRPQKLUhUoqrJC1bO2xNya7vanpDl7xR3ISbCJ0= -github.com/blakesmith/ar v0.0.0-20190502131153-809d4375e1fb h1:m935MPodAbYS46DG4pJSv7WO+VECIWUQ7OJYSoTrMh4= -github.com/blakesmith/ar v0.0.0-20190502131153-809d4375e1fb/go.mod h1:PkYb9DJNAwrSvRx5DYA+gUcOIgTGVMNkfSCbZM8cWpI= -github.com/caarlos0/testfs v0.4.4 h1:3PHvzHi5Lt+g332CiShwS8ogTgS3HjrmzZxCm6JCDr8= -github.com/caarlos0/testfs v0.4.4/go.mod h1:bRN55zgG4XCUVVHZCeU+/Tz1Q6AxEJOEJTliBy+1DMk= -github.com/catppuccin/go v0.3.0 h1:d+0/YicIq+hSTo5oPuRi5kOpqkVA5tAsU6dNhvRu+aY= -github.com/catppuccin/go v0.3.0/go.mod h1:8IHJuMGaUUjQM82qBrGNBv7LFq6JI3NnQCF6MOlZjpc= -github.com/cavaliergopher/cpio v1.0.1 h1:KQFSeKmZhv0cr+kawA3a0xTQCU4QxXF1vhU7P7av2KM= -github.com/cavaliergopher/cpio v1.0.1/go.mod h1:pBdaqQjnvXxdS/6CvNDwIANIFSP0xRKI16PX4xejRQc= -github.com/chainguard-dev/git-urls v1.0.2 h1:pSpT7ifrpc5X55n4aTTm7FFUE+ZQHKiqpiwNkJrVcKQ= -github.com/chainguard-dev/git-urls v1.0.2/go.mod h1:rbGgj10OS7UgZlbzdUQIQpT0k/D4+An04HJY7Ol+Y/o= -github.com/charmbracelet/bubbles v0.21.1-0.20250623103423-23b8fd6302d7 h1:JFgG/xnwFfbezlUnFMJy0nusZvytYysV4SCS2cYbvws= -github.com/charmbracelet/bubbles v0.21.1-0.20250623103423-23b8fd6302d7/go.mod h1:ISC1gtLcVilLOf23wvTfoQuYbW2q0JevFxPfUzZ9Ybw= -github.com/charmbracelet/bubbletea v1.3.10 h1:otUDHWMMzQSB0Pkc87rm691KZ3SWa4KUlvF9nRvCICw= -github.com/charmbracelet/bubbletea v1.3.10/go.mod h1:ORQfo0fk8U+po9VaNvnV95UPWA1BitP1E0N6xJPlHr4= -github.com/charmbracelet/colorprofile v0.4.1 h1:a1lO03qTrSIRaK8c3JRxJDZOvhvIeSco3ej+ngLk1kk= -github.com/charmbracelet/colorprofile v0.4.1/go.mod h1:U1d9Dljmdf9DLegaJ0nGZNJvoXAhayhmidOdcBwAvKk= -github.com/charmbracelet/glamour v0.10.0 h1:MtZvfwsYCx8jEPFJm3rIBFIMZUfUJ765oX8V6kXldcY= -github.com/charmbracelet/glamour v0.10.0/go.mod h1:f+uf+I/ChNmqo087elLnVdCiVgjSKWuXa/l6NU2ndYk= -github.com/charmbracelet/huh v0.8.0 h1:Xz/Pm2h64cXQZn/Jvele4J3r7DDiqFCNIVteYukxDvY= -github.com/charmbracelet/huh v0.8.0/go.mod h1:5YVc+SlZ1IhQALxRPpkGwwEKftN/+OlJlnJYlDRFqN4= -github.com/charmbracelet/lipgloss v1.1.1-0.20250404203927-76690c660834 h1:ZR7e0ro+SZZiIZD7msJyA+NjkCNNavuiPBLgerbOziE= -github.com/charmbracelet/lipgloss v1.1.1-0.20250404203927-76690c660834/go.mod h1:aKC/t2arECF6rNOnaKaVU6y4t4ZeHQzqfxedE/VkVhA= -github.com/charmbracelet/x/ansi v0.11.4 h1:6G65PLu6HjmE858CnTUQY1LXT3ZUWwfvqEROLF8vqHI= -github.com/charmbracelet/x/ansi v0.11.4/go.mod h1:/5AZ+UfWExW3int5H5ugnsG/PWjNcSQcwYsHBlPFQN4= -github.com/charmbracelet/x/cellbuf v0.0.14 h1:iUEMryGyFTelKW3THW4+FfPgi4fkmKnnaLOXuc+/Kj4= -github.com/charmbracelet/x/cellbuf v0.0.14/go.mod h1:P447lJl49ywBbil/KjCk2HexGh4tEY9LH0/1QrZZ9rA= -github.com/charmbracelet/x/conpty v0.1.0 h1:4zc8KaIcbiL4mghEON8D72agYtSeIgq8FSThSPQIb+U= -github.com/charmbracelet/x/conpty v0.1.0/go.mod h1:rMFsDJoDwVmiYM10aD4bH2XiRgwI7NYJtQgl5yskjEQ= -github.com/charmbracelet/x/errors v0.0.0-20240508181413-e8d8b6e2de86 h1:JSt3B+U9iqk37QUU2Rvb6DSBYRLtWqFqfxf8l5hOZUA= -github.com/charmbracelet/x/errors v0.0.0-20240508181413-e8d8b6e2de86/go.mod h1:2P0UgXMEa6TsToMSuFqKFQR+fZTO9CNGUNokkPatT/0= -github.com/charmbracelet/x/exp/golden v0.0.0-20241011142426-46044092ad91 h1:payRxjMjKgx2PaCWLZ4p3ro9y97+TVLZNaRZgJwSVDQ= -github.com/charmbracelet/x/exp/golden v0.0.0-20241011142426-46044092ad91/go.mod h1:wDlXFlCrmJ8J+swcL/MnGUuYnqgQdW9rhSD61oNMb6U= -github.com/charmbracelet/x/exp/slice v0.0.0-20260122224438-b01af16209d9 h1:BBTx26Fy+CW9U3kLiWBuWn9pI9C1NybaS+p/AZeAOkA= -github.com/charmbracelet/x/exp/slice v0.0.0-20260122224438-b01af16209d9/go.mod h1:vqEfX6xzqW1pKKZUUiFOKg0OQ7bCh54Q2vR/tserrRA= -github.com/charmbracelet/x/exp/strings v0.0.0-20260122224438-b01af16209d9 h1:JevRYfkTT0sN9OIXAOncYNC0cTP1Gml/0mCSnsmRkRk= -github.com/charmbracelet/x/exp/strings v0.0.0-20260122224438-b01af16209d9/go.mod h1:/ehtMPNh9K4odGFkqYJKpIYyePhdp1hLBRvyY4bWkH8= -github.com/charmbracelet/x/term v0.2.2 h1:xVRT/S2ZcKdhhOuSP4t5cLi5o+JxklsoEObBSgfgZRk= -github.com/charmbracelet/x/term v0.2.2/go.mod h1:kF8CY5RddLWrsgVwpw4kAa6TESp6EB5y3uxGLeCqzAI= -github.com/charmbracelet/x/termios v0.1.1 h1:o3Q2bT8eqzGnGPOYheoYS8eEleT5ZVNYNy8JawjaNZY= -github.com/charmbracelet/x/termios v0.1.1/go.mod h1:rB7fnv1TgOPOyyKRJ9o+AsTU/vK5WHJ2ivHeut/Pcwo= -github.com/charmbracelet/x/xpty v0.1.2 h1:Pqmu4TEJ8KeA9uSkISKMU3f+C1F6OGBn8ABuGlqCbtI= -github.com/charmbracelet/x/xpty v0.1.2/go.mod h1:XK2Z0id5rtLWcpeNiMYBccNNBrP2IJnzHI0Lq13Xzq4= -github.com/clipperhouse/displaywidth v0.7.0 h1:QNv1GYsnLX9QBrcWUtMlogpTXuM5FVnBwKWp1O5NwmE= -github.com/clipperhouse/displaywidth v0.7.0/go.mod h1:R+kHuzaYWFkTm7xoMmK1lFydbci4X2CicfbGstSGg0o= -github.com/clipperhouse/stringish v0.1.1 h1:+NSqMOr3GR6k1FdRhhnXrLfztGzuG+VuFDfatpWHKCs= -github.com/clipperhouse/stringish v0.1.1/go.mod h1:v/WhFtE1q0ovMta2+m+UbpZ+2/HEXNWYXQgCt4hdOzA= -github.com/clipperhouse/uax29/v2 v2.4.0 h1:RXqE/l5EiAbA4u97giimKNlmpvkmz+GrBVTelsoXy9g= -github.com/clipperhouse/uax29/v2 v2.4.0/go.mod h1:Wn1g7MK6OoeDT0vL+Q0SQLDz/KpfsVRgg6W7ihQeh4g= -github.com/cloudflare/circl v1.6.3 h1:9GPOhQGF9MCYUeXyMYlqTR6a5gTrgR/fBLXvUgtVcg8= -github.com/cloudflare/circl v1.6.3/go.mod h1:2eXP6Qfat4O/Yhh8BznvKnJ+uzEoTQ6jVKJRn81BiS4= -github.com/coder/websocket v1.8.14 h1:9L0p0iKiNOibykf283eHkKUHHrpG7f65OE3BhhO7v9g= -github.com/coder/websocket v1.8.14/go.mod h1:NX3SzP+inril6yawo5CQXx8+fk145lPDC6pumgx0mVg= -github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkXar0TQ1gf3U= -github.com/containerd/console v1.0.5 h1:R0ymNeydRqH2DmakFNdmjR2k0t7UPuiOV/N/27/qqsc= -github.com/containerd/console v1.0.5/go.mod h1:YynlIjWYF8myEu6sdkwKIvGQq+cOckRm6So2avqoYAk= -github.com/creack/pty v1.1.24 h1:bJrF4RRfyJnbTJqzRLHzcGaZK1NeM5kTC9jGgovnR1s= -github.com/creack/pty v1.1.24/go.mod h1:08sCNb52WyoAwi2QDyzUCTgcvVFhUzewun7wtTfvcwE= -github.com/cyphar/filepath-securejoin v0.6.1 h1:5CeZ1jPXEiYt3+Z6zqprSAgSWiggmpVyciv8syjIpVE= -github.com/cyphar/filepath-securejoin v0.6.1/go.mod h1:A8hd4EnAeyujCJRrICiOWqjS1AX0a9kM5XL+NwKoYSc= -github.com/danieljoos/wincred v1.2.3 h1:v7dZC2x32Ut3nEfRH+vhoZGvN72+dQ/snVXo/vMFLdQ= -github.com/danieljoos/wincred v1.2.3/go.mod h1:6qqX0WNrS4RzPZ1tnroDzq9kY3fu1KwE7MRLQK4X0bs= -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= -github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/dlclark/regexp2 v1.11.5 h1:Q/sSnsKerHeCkc/jSTNq1oCm7KiVgUMZRDUoRu0JQZQ= -github.com/dlclark/regexp2 v1.11.5/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= -github.com/dominikbraun/graph v0.23.0 h1:TdZB4pPqCLFxYhdyMFb1TBdFxp8XLcJfTTBQucVPgCo= -github.com/dominikbraun/graph v0.23.0/go.mod h1:yOjYyogZLY1LSG9E33JWZJiq5k83Qy2C6POAuiViluc= -github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= -github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= -github.com/ebitengine/purego v0.9.1 h1:a/k2f2HQU3Pi399RPW1MOaZyhKJL9w/xFpKAg4q1s0A= -github.com/ebitengine/purego v0.9.1/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ= -github.com/elazarl/goproxy v1.7.2 h1:Y2o6urb7Eule09PjlhQRGNsqRfPmYI3KKQLFpCAV3+o= -github.com/elazarl/goproxy v1.7.2/go.mod h1:82vkLNir0ALaW14Rc399OTTjyNREgmdL2cVoIbS6XaE= -github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc= -github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ= -github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f h1:Y/CXytFA4m6baUTXGLOoWe4PQhGxaX0KpnayAqC48p4= -github.com/erikgeiser/coninput v0.0.0-20211004153227-1c3628e74d0f/go.mod h1:vw97MGsxSvLiUE2X8qFplwetxpGLQrlU1Q9AUEIzCaM= -github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM= -github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU= -github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= -github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= -github.com/gliderlabs/ssh v0.3.8 h1:a4YXD1V7xMF9g5nTkdfnja3Sxy1PVDCj1Zg4Wb8vY6c= -github.com/gliderlabs/ssh v0.3.8/go.mod h1:xYoytBv1sV0aL3CavoDuJIQNURXkkfPA/wxQ1pL1fAU= -github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI= -github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmSxCcxctByoQdvwPiA7DTK7jaaFDBTtu0ic= -github.com/go-git/go-billy/v5 v5.7.0 h1:83lBUJhGWhYp0ngzCMSgllhUSuoHP1iEWYjsPl9nwqM= -github.com/go-git/go-billy/v5 v5.7.0/go.mod h1:/1IUejTKH8xipsAcdfcSAlUlo2J7lkYV8GTKxAT/L3E= -github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399 h1:eMje31YglSBqCdIqdhKBW8lokaMrL3uTkpGYlE2OOT4= -github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399/go.mod h1:1OCfN199q1Jm3HZlxleg+Dw/mwps2Wbk9frAWm+4FII= -github.com/go-git/go-git/v5 v5.16.4 h1:7ajIEZHZJULcyJebDLo99bGgS0jRrOxzZG4uCk2Yb2Y= -github.com/go-git/go-git/v5 v5.16.4/go.mod h1:4Ge4alE/5gPs30F2H1esi2gPd69R0C39lolkucHBOp8= -github.com/go-json-experiment/json v0.0.0-20251027170946-4849db3c2f7e h1:Lf/gRkoycfOBPa42vU2bbgPurFong6zXeFtPoxholzU= -github.com/go-json-experiment/json v0.0.0-20251027170946-4849db3c2f7e/go.mod h1:uNVvRXArCGbZ508SxYYTC5v1JWoz2voff5pm25jU1Ok= -github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= -github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE= -github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78= -github.com/go-quicktest/qt v1.101.0 h1:O1K29Txy5P2OK0dGo59b7b0LR6wKfIhttaAhHUyn7eI= -github.com/go-quicktest/qt v1.101.0/go.mod h1:14Bz/f7NwaXPtdYEgzsx46kqSxVwTbzVZsDC26tQJow= -github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI= -github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= -github.com/go-task/template v0.2.0 h1:xW7ek0o65FUSTbKcSNeg2Vyf/I7wYXFgLUznptvviBE= -github.com/go-task/template v0.2.0/go.mod h1:dbdoUb6qKnHQi1y6o+IdIrs0J4o/SEhSTA6bbzZmdtc= -github.com/gobwas/glob v0.2.3 h1:A4xDbljILXROh+kObIiy5kIaPYD8e96x1tgBhUI5J+Y= -github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8= -github.com/godbus/dbus/v5 v5.2.2 h1:TUR3TgtSVDmjiXOgAAyaZbYmIeP3DPkld3jgKGV8mXQ= -github.com/godbus/dbus/v5 v5.2.2/go.mod h1:3AAv2+hPq5rdnr5txxxRwiGjPXamgoIHgz9FPBfOp3c= -github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 h1:f+oWsMOmNPc8JmEHVZIycC7hBoQxHH9pNKQORJNozsQ= -github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8/go.mod h1:wcDNUvekVysuuOpQKo3191zZyTpiI6se1N1ULghS0sw= -github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= -github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= -github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e h1:ijClszYn+mADRFY17kjQEVQ1XRhq2/JR1M3sGqeJoxs= -github.com/google/pprof v0.0.0-20250317173921-a4b03ec1a45e/go.mod h1:boTsfXsheKC2y+lKOCMpSfarhxDeIzfZG1jqGcPl3cA= -github.com/google/rpmpack v0.7.1 h1:YdWh1IpzOjBz60Wvdw0TU0A5NWP+JTVHA5poDqwMO2o= -github.com/google/rpmpack v0.7.1/go.mod h1:h1JL16sUTWCLI/c39ox1rDaTBo3BXUQGjczVJyK4toU= -github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= -github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= -github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= -github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/gookit/assert v0.1.1 h1:lh3GcawXe/p+cU7ESTZ5Ui3Sm/x8JWpIis4/1aF0mY0= -github.com/gookit/assert v0.1.1/go.mod h1:jS5bmIVQZTIwk42uXl4lyj4iaaxx32tqH16CFj0VX2E= -github.com/gookit/color v1.4.2/go.mod h1:fqRyamkC1W8uxl+lxCQxOT09l/vYfZ+QeiX3rKQHCoQ= -github.com/gookit/color v1.5.0/go.mod h1:43aQb+Zerm/BWh2GnrgOQm7ffz7tvQXEKV6BFMl7wAo= -github.com/gookit/color v1.6.0 h1:JjJXBTk1ETNyqyilJhkTXJYYigHG24TM9Xa2M1xAhRA= -github.com/gookit/color v1.6.0/go.mod h1:9ACFc7/1IpHGBW8RwuDm/0YEnhg3dwwXpoMsmtyHfjs= -github.com/gopherjs/gopherjs v1.17.2 h1:fQnZVsXk8uxXIStYb0N4bGk7jeyTalG/wsZjQ25dO0g= -github.com/gopherjs/gopherjs v1.17.2/go.mod h1:pRRIvn/QzFLrKfvEz3qUuEhtE/zLCWfreZ6J5gM2i+k= -github.com/goreleaser/chglog v0.7.4 h1:3pnNt/XCrUcAOq+KC91Azlgp5CRv4GHo1nl8Aws7OzI= -github.com/goreleaser/chglog v0.7.4/go.mod h1:dTVoZZagTz7hHdWaZ9OshHntKiF44HbWIHWxYJQ/h0Y= -github.com/goreleaser/fileglob v1.4.0 h1:Y7zcUnzQjT1gbntacGAkIIfLv+OwojxTXBFxjSFoBBs= -github.com/goreleaser/fileglob v1.4.0/go.mod h1:1pbHx7hhmJIxNZvm6fi6WVrnP0tndq6p3ayWdLn1Yf8= -github.com/goreleaser/nfpm/v2 v2.44.1 h1:g+QNjkEx+C2Zu8dB48t9da/VfV0CWS5TMjxT8HG1APY= -github.com/goreleaser/nfpm/v2 v2.44.1/go.mod h1:drIYLqkla9SaOLbSnaFOmSIv5LXGfhHcbK54st97b4s= -github.com/gorilla/css v1.0.1 h1:ntNaBIghp6JmvWnxbZKANoLyuXTPZ4cAMlo6RyhlbO8= -github.com/gorilla/css v1.0.1/go.mod h1:BvnYkspnSzMmwRK+b8/xgNPLiIuNZr6vbZBTPQ2A3b0= -github.com/gorilla/websocket v1.5.3 h1:saDtZ6Pbx/0u+bgYQ3q96pZgCzfhKXGPqt7kZ72aNNg= -github.com/gorilla/websocket v1.5.3/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= -github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k= -github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM= -github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM= -github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg= -github.com/huandu/xstrings v1.5.0 h1:2ag3IFq9ZDANvthTwTiqSSZLjDc+BedvHPAp5tJy2TI= -github.com/huandu/xstrings v1.5.0/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE= -github.com/jackmordaunt/icns/v2 v2.2.7 h1:K/RbfvuzjmjVY5y4g+XENRs8ZZatwz4YnLHypa2KwQg= -github.com/jackmordaunt/icns/v2 v2.2.7/go.mod h1:ovoTxGguSuoUGKMk5Nn3R7L7BgMQkylsO+bblBuI22A= -github.com/jaypipes/ghw v0.21.2 h1:woW0lqNMPbYk59sur6thOVM8YFP9Hxxr8PM+JtpUrNU= -github.com/jaypipes/ghw v0.21.2/go.mod h1:GPrvwbtPoxYUenr74+nAnWbardIZq600vJDD5HnPsPE= -github.com/jaypipes/pcidb v1.1.1 h1:QmPhpsbmmnCwZmHeYAATxEaoRuiMAJusKYkUncMC0ro= -github.com/jaypipes/pcidb v1.1.1/go.mod h1:x27LT2krrUgjf875KxQXKB0Ha/YXLdZRVmw6hH0G7g8= -github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A= -github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= -github.com/jchv/go-winloader v0.0.0-20250406163304-c1995be93bd1 h1:njuLRcjAuMKr7kI3D85AXWkw6/+v9PwtV6M6o11sWHQ= -github.com/jchv/go-winloader v0.0.0-20250406163304-c1995be93bd1/go.mod h1:alcuEEnZsY1WQsagKhZDsoPCRoOijYqhZvPwLG0kzVs= -github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= -github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= -github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= -github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= -github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= -github.com/kevinburke/ssh_config v1.4.0 h1:6xxtP5bZ2E4NF5tuQulISpTO2z8XbtH8cg1PWkxoFkQ= -github.com/kevinburke/ssh_config v1.4.0/go.mod h1:q2RIzfka+BXARoNexmF9gkxEX7DmvbW9P4hIVx2Kg4M= -github.com/klauspost/compress v1.18.3 h1:9PJRvfbmTabkOX8moIpXPbMMbYN60bWImDDU7L+/6zw= -github.com/klauspost/compress v1.18.3/go.mod h1:R0h/fSBs8DE4ENlcrlib3PsXS61voFxhIs2DeRhCvJ4= -github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= -github.com/klauspost/cpuid/v2 v2.0.10/go.mod h1:g2LTdtYhdyuGPqyWyv7qRAmj1WBqxuObKfj5c0PQa7c= -github.com/klauspost/cpuid/v2 v2.0.12/go.mod h1:g2LTdtYhdyuGPqyWyv7qRAmj1WBqxuObKfj5c0PQa7c= -github.com/klauspost/cpuid/v2 v2.3.0 h1:S4CRMLnYUhGeDFDqkGriYKdfoFlDnMtqTiI/sFzhA9Y= -github.com/klauspost/cpuid/v2 v2.3.0/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0= -github.com/klauspost/pgzip v1.2.6 h1:8RXeL5crjEUFnR2/Sn6GJNWtSQ3Dk8pq4CL3jvdDyjU= -github.com/klauspost/pgzip v1.2.6/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs= -github.com/konoui/go-qsort v0.1.0 h1:0Os/0X0Fce6B54jqN26aR+J5uOExN+0t7nb9zs6zzzE= -github.com/konoui/go-qsort v0.1.0/go.mod h1:UOsvdDPBzyQDk9Tb21hETK6KYXGYQTnoZB5qeKA1ARs= -github.com/konoui/lipo v0.10.0 h1:1P2VkBSB6I38kgmyznvAjy9gmAqybK22pJt9iyx5CgY= -github.com/konoui/lipo v0.10.0/go.mod h1:R+0EgDVrLKKS37SumAO8zhpEprjjoKEkrT3QqKQE35k= -github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= -github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= -github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= -github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= -github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/leaanthony/clir v1.0.4/go.mod h1:k/RBkdkFl18xkkACMCLt09bhiZnrGORoxmomeMvDpE0= -github.com/leaanthony/clir v1.7.0 h1:xiAnhl7ryPwuH3ERwPWZp/pCHk8wTeiwuAOt6MiNyAw= -github.com/leaanthony/clir v1.7.0/go.mod h1:k/RBkdkFl18xkkACMCLt09bhiZnrGORoxmomeMvDpE0= -github.com/leaanthony/debme v1.2.1 h1:9Tgwf+kjcrbMQ4WnPcEIUcQuIZYqdWftzZkBr+i/oOc= -github.com/leaanthony/debme v1.2.1/go.mod h1:3V+sCm5tYAgQymvSOfYQ5Xx2JCr+OXiD9Jkw3otUjiA= -github.com/leaanthony/go-ansi-parser v1.6.1 h1:xd8bzARK3dErqkPFtoF9F3/HgN8UQk0ed1YDKpEz01A= -github.com/leaanthony/go-ansi-parser v1.6.1/go.mod h1:+vva/2y4alzVmmIEpk9QDhA7vLC5zKDTRwfZGOp3IWU= -github.com/leaanthony/gosod v1.0.4 h1:YLAbVyd591MRffDgxUOU1NwLhT9T1/YiwjKZpkNFeaI= -github.com/leaanthony/gosod v1.0.4/go.mod h1:GKuIL0zzPj3O1SdWQOdgURSuhkF+Urizzxh26t9f1cw= -github.com/leaanthony/u v1.1.1 h1:TUFjwDGlNX+WuwVEzDqQwC2lOv0P4uhTQw7CMFdiK7M= -github.com/leaanthony/u v1.1.1/go.mod h1:9+o6hejoRljvZ3BzdYlVL0JYCwtnAsVuN9pVTQcaRfI= -github.com/leaanthony/winicon v1.0.0 h1:ZNt5U5dY71oEoKZ97UVwJRT4e+5xo5o/ieKuHuk8NqQ= -github.com/leaanthony/winicon v1.0.0/go.mod h1:en5xhijl92aphrJdmRPlh4NI1L6wq3gEm0LpXAPghjU= -github.com/lithammer/fuzzysearch v1.1.8 h1:/HIuJnjHuXS8bKaiTMeeDlW2/AyIWk2brx1V8LFgLN4= -github.com/lithammer/fuzzysearch v1.1.8/go.mod h1:IdqeyBClc3FFqSzYq/MXESsS4S0FsZ5ajtkr5xPLts4= -github.com/lmittmann/tint v1.1.2 h1:2CQzrL6rslrsyjqLDwD11bZ5OpLBPU+g3G/r5LSfS8w= -github.com/lmittmann/tint v1.1.2/go.mod h1:HIS3gSy7qNwGCj+5oRjAutErFBl4BzdQP6cJZ0NfMwE= -github.com/lucasb-eyer/go-colorful v1.3.0 h1:2/yBRLdWBZKrf7gB40FoiKfAWYQ0lqNcbuQwVHXptag= -github.com/lucasb-eyer/go-colorful v1.3.0/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= -github.com/matryer/is v1.4.0/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwMRU= -github.com/matryer/is v1.4.1 h1:55ehd8zaGABKLXQUe2awZ99BD/PTc2ls+KV/dXphgEQ= -github.com/matryer/is v1.4.1/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwMRU= -github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE= -github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8= -github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= -github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= -github.com/mattn/go-localereader v0.0.1 h1:ygSAOl7ZXTx4RdPYinUpg6W99U8jWvWi9Ye2JC/oIi4= -github.com/mattn/go-localereader v0.0.1/go.mod h1:8fBrzywKY7BI3czFoHkuzRoWE9C+EiG4R1k4Cjx5p88= -github.com/mattn/go-runewidth v0.0.12/go.mod h1:RAqKPSqVFrSLVXbA8x7dzmKdmGzieGRCM46jaSJTDAk= -github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= -github.com/mattn/go-runewidth v0.0.19 h1:v++JhqYnZuu5jSKrk9RbgF5v4CGUjqRfBm05byFGLdw= -github.com/mattn/go-runewidth v0.0.19/go.mod h1:XBkDxAl56ILZc9knddidhrOlY5R/pDhgLpndooCuJAs= -github.com/mattn/go-zglob v0.0.6 h1:mP8RnmCgho4oaUYDIDn6GNxYk+qJGUs8fJLn+twYj2A= -github.com/mattn/go-zglob v0.0.6/go.mod h1:MxxjyoXXnMxfIpxTK2GAkw1w8glPsQILx3N5wrKakiY= -github.com/microcosm-cc/bluemonday v1.0.27 h1:MpEUotklkwCSLeH+Qdx1VJgNqLlpY2KXwXFM08ygZfk= -github.com/microcosm-cc/bluemonday v1.0.27/go.mod h1:jFi9vgW+H7c3V0lb6nR74Ib/DIB5OBs92Dimizgw2cA= -github.com/mitchellh/copystructure v1.2.0 h1:vpKXTN4ewci03Vljg/q9QvCGUDttBOGBIa15WveJJGw= -github.com/mitchellh/copystructure v1.2.0/go.mod h1:qLl+cE2AmVv+CoeAwDPye/v+N2HKCj9FbZEVFJRxO9s= -github.com/mitchellh/hashstructure/v2 v2.0.2 h1:vGKWl0YJqUNxE8d+h8f6NJLcCJrgbhC4NcD46KavDd4= -github.com/mitchellh/hashstructure/v2 v2.0.2/go.mod h1:MG3aRVU/N29oo/V/IhBX8GR/zz4kQkprJgF2EVszyDE= -github.com/mitchellh/reflectwalk v1.0.2 h1:G2LzWKi524PWgd3mLHV8Y5k7s6XUvT0Gef6zxSIeXaQ= -github.com/mitchellh/reflectwalk v1.0.2/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw= -github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6 h1:ZK8zHtRHOkbHy6Mmr5D264iyp3TiX5OmNcI5cIARiQI= -github.com/muesli/ansi v0.0.0-20230316100256-276c6243b2f6/go.mod h1:CJlz5H+gyd6CUWT45Oy4q24RdLyn7Md9Vj2/ldJBSIo= -github.com/muesli/cancelreader v0.2.2 h1:3I4Kt4BQjOR54NavqnDogx/MIoWBFa0StPA8ELUXHmA= -github.com/muesli/cancelreader v0.2.2/go.mod h1:3XuTXfFS2VjM+HTLZY9Ak0l6eUKfijIfMUZ4EgX0QYo= -github.com/muesli/reflow v0.3.0 h1:IFsN6K9NfGtjeggFP+68I4chLZV2yIKsXJFNZ+eWh6s= -github.com/muesli/reflow v0.3.0/go.mod h1:pbwTDkVPibjO2kyvBQRBxTWEEGDGq0FlB1BIKtnHY/8= -github.com/muesli/termenv v0.16.0 h1:S5AlUN9dENB57rsbnkPyfdGuWIlkmzJjbFf0Tf5FWUc= -github.com/muesli/termenv v0.16.0/go.mod h1:ZRfOIKPFDYQoDFF4Olj7/QJbW60Ol/kL1pU3VfY/Cnk= -github.com/ncruces/go-strftime v1.0.0 h1:HMFp8mLCTPp341M/ZnA4qaf7ZlsbTc+miZjCLOFAw7w= -github.com/ncruces/go-strftime v1.0.0/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls= -github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 h1:zYyBkD/k9seD2A7fsi6Oo2LfFZAehjjQMERAvZLEDnQ= -github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8= -github.com/onsi/gomega v1.34.1 h1:EUMJIKUjM8sKjYbtxQI9A4z2o+rruxnzNvpknOXie6k= -github.com/onsi/gomega v1.34.1/go.mod h1:kU1QgUvBDLXBJq618Xvm2LUX6rSAfRaFRTcdOeDLwwY= -github.com/pjbgf/sha1cd v0.5.0 h1:a+UkboSi1znleCDUNT3M5YxjOnN1fz2FhN48FlwCxs0= -github.com/pjbgf/sha1cd v0.5.0/go.mod h1:lhpGlyHLpQZoxMv8HcgXvZEhcGs0PG/vsZnEJ7H0iCM= -github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmdv1U2eRNDiU2ErMBj1gwrq8eQ= -github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c/go.mod h1:7rwL4CYBLnjLxUqIJNnCWiEdr3bn6IUYi15bNlnbCCU= -github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= -github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= -github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/pterm/pterm v0.12.27/go.mod h1:PhQ89w4i95rhgE+xedAoqous6K9X+r6aSOI2eFF7DZI= -github.com/pterm/pterm v0.12.29/go.mod h1:WI3qxgvoQFFGKGjGnJR849gU0TsEOvKn5Q8LlY1U7lg= -github.com/pterm/pterm v0.12.30/go.mod h1:MOqLIyMOgmTDz9yorcYbcw+HsgoZo3BQfg2wtl3HEFE= -github.com/pterm/pterm v0.12.31/go.mod h1:32ZAWZVXD7ZfG0s8qqHXePte42kdz8ECtRyEejaWgXU= -github.com/pterm/pterm v0.12.33/go.mod h1:x+h2uL+n7CP/rel9+bImHD5lF3nM9vJj80k9ybiiTTE= -github.com/pterm/pterm v0.12.36/go.mod h1:NjiL09hFhT/vWjQHSj1athJpx6H8cjpHXNAK5bUw8T8= -github.com/pterm/pterm v0.12.40/go.mod h1:ffwPLwlbXxP+rxT0GsgDTzS3y3rmpAO1NMjUkGTYf8s= -github.com/pterm/pterm v0.12.82 h1:+D9wYhCaeaK0FIQoZtqbNQuNpe2lB2tajKKsTd5paVQ= -github.com/pterm/pterm v0.12.82/go.mod h1:TyuyrPjnxfwP+ccJdBTeWHtd/e0ybQHkOS/TakajZCw= -github.com/radovskyb/watcher v1.0.7 h1:AYePLih6dpmS32vlHfhCeli8127LzkIgwJGcwwe8tUE= -github.com/radovskyb/watcher v1.0.7/go.mod h1:78okwvY5wPdzcb1UYnip1pvrZNIVEIh/Cm+ZuvsUYIg= -github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE= -github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= -github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= -github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= -github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= -github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= -github.com/rjeczalik/notify v0.9.3 h1:6rJAzHTGKXGj76sbRgDiDcYj/HniypXmSJo1SWakZeY= -github.com/rjeczalik/notify v0.9.3/go.mod h1:gF3zSOrafR9DQEWSE8TjfI9NkooDxbyT4UgRGKZA0lc= -github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= -github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= -github.com/sajari/fuzzy v1.0.0 h1:+FmwVvJErsd0d0hAPlj4CxqxUtQY/fOoY0DwX4ykpRY= -github.com/sajari/fuzzy v1.0.0/go.mod h1:OjYR6KxoWOe9+dOlXeiCJd4dIbED4Oo8wpS89o0pwOo= -github.com/samber/lo v1.52.0 h1:Rvi+3BFHES3A8meP33VPAxiBZX/Aws5RxrschYGjomw= -github.com/samber/lo v1.52.0/go.mod h1:4+MXEGsJzbKGaUEQFKBq2xtfuznW9oz/WrgyzMzRoM0= -github.com/sassoftware/go-rpmutils v0.4.0 h1:ojND82NYBxgwrV+mX1CWsd5QJvvEZTKddtCdFLPWhpg= -github.com/sassoftware/go-rpmutils v0.4.0/go.mod h1:3goNWi7PGAT3/dlql2lv3+MSN5jNYPjT5mVcQcIsYzI= -github.com/sergi/go-diff v1.2.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM= -github.com/sergi/go-diff v1.4.0 h1:n/SP9D5ad1fORl+llWyN+D6qoUETXNZARKjyY2/KVCw= -github.com/sergi/go-diff v1.4.0/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4= -github.com/shopspring/decimal v1.4.0 h1:bxl37RwXBklmTi0C79JfXCEBD1cqqHt0bbgBAGFp81k= -github.com/shopspring/decimal v1.4.0/go.mod h1:gawqmDU56v4yIKSwfBSFip1HdCCXN8/+DMd9qYNcwME= -github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= -github.com/skeema/knownhosts v1.3.2 h1:EDL9mgf4NzwMXCTfaxSD/o/a5fxDw/xL9nkU28JjdBg= -github.com/skeema/knownhosts v1.3.2/go.mod h1:bEg3iQAuw+jyiw+484wwFJoKSLwcfd7fqRy+N0QTiow= -github.com/smarty/assertions v1.15.0 h1:cR//PqUBUiQRakZWqBiFFQ9wb8emQGDb0HeGdqGByCY= -github.com/smarty/assertions v1.15.0/go.mod h1:yABtdzeQs6l1brC900WlRNwj6ZR55d7B+E8C6HtKdec= -github.com/smartystreets/goconvey v1.8.1 h1:qGjIddxOk4grTu9JPOU31tVfq3cNdBlNa5sSznIX1xY= -github.com/smartystreets/goconvey v1.8.1/go.mod h1:+/u4qLyY6x1jReYOp7GOM2FSt8aP9CzCZL03bI28W60= -github.com/spf13/cast v1.10.0 h1:h2x0u2shc1QuLHfxi+cTJvs30+ZAHOGRic8uyGTDWxY= -github.com/spf13/cast v1.10.0/go.mod h1:jNfB8QC9IA6ZuY2ZjDp0KtFO2LZZlg4S/7bzP6qqeHo= -github.com/spf13/pflag v1.0.10 h1:4EBh2KAYBwaONj6b2Ye1GiHfwjqyROoF4RwYO+vPwFk= -github.com/spf13/pflag v1.0.10/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= -github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= -github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= -github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= -github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= -github.com/tc-hib/winres v0.3.1 h1:CwRjEGrKdbi5CvZ4ID+iyVhgyfatxFoizjPhzez9Io4= -github.com/tc-hib/winres v0.3.1/go.mod h1:C/JaNhH3KBvhNKVbvdlDWkbMDO9H4fKKDaN7/07SSuk= -github.com/ulikunitz/xz v0.5.15 h1:9DNdB5s+SgV3bQ2ApL10xRc35ck0DuIX/isZvIk+ubY= -github.com/ulikunitz/xz v0.5.15/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= -github.com/wailsapp/go-webview2 v1.0.23 h1:jmv8qhz1lHibCc79bMM/a/FqOnnzOGEisLav+a0b9P0= -github.com/wailsapp/go-webview2 v1.0.23/go.mod h1:qJmWAmAmaniuKGZPWwne+uor3AHMB5PFhqiK0Bbj8kc= -github.com/wailsapp/task/v3 v3.40.1-patched3 h1:i6O1WNdSur9CGaiMDIYGjsmj/qS4465zqv+WEs6sPRs= -github.com/wailsapp/task/v3 v3.40.1-patched3/go.mod h1:jIP48r8ftoSQNlxFP4+aEnkvGQqQXqCnRi/B7ROaecE= -github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM= -github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw= -github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 h1:nIPpBwaJSVYIxUFsDv3M8ofmx9yWTog9BfvIu0q41lo= -github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8/go.mod h1:HUYIGzjTL3rfEspMxjDjgmT5uz5wzYJKVo23qUhYTos= -github.com/xo/terminfo v0.0.0-20210125001918-ca9a967f8778/go.mod h1:2MuV+tbUrU1zIOPMxZ5EncGwgmMJsa+9ucAQZXxsObs= -github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e h1:JVG44RsyaB9T2KIHavMF/ppJZNG9ZpyihvCd0w101no= -github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e/go.mod h1:RbqR21r5mrJuqunuUZ/Dhy/avygyECGrLceyNeo4LiM= -github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= -github.com/yuin/goldmark v1.7.16 h1:n+CJdUxaFMiDUNnWC3dMWCIQJSkxH4uz3ZwQBkAlVNE= -github.com/yuin/goldmark v1.7.16/go.mod h1:ip/1k0VRfGynBgxOz0yCqHrbZXhcjxyuS66Brc7iBKg= -github.com/yuin/goldmark-emoji v1.0.6 h1:QWfF2FYaXwL74tfGOW5izeiZepUDroDJfWubQI9HTHs= -github.com/yuin/goldmark-emoji v1.0.6/go.mod h1:ukxJDKFpdFb5x0a5HqbdlcKtebh086iJpI31LTKmWuA= -github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0= -github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0= -github.com/zalando/go-keyring v0.2.6 h1:r7Yc3+H+Ux0+M72zacZoItR3UDxeWfKTcabvkI8ua9s= -github.com/zalando/go-keyring v0.2.6/go.mod h1:2TCrxYrbUNYfNS/Kgy/LSrkSQzZ5UPVH85RwfczwvcI= -github.com/zeebo/assert v1.3.0 h1:g7C04CbJuIDKNPFHmsk4hwZDO5O+kntRxzaUoNXj+IQ= -github.com/zeebo/assert v1.3.0/go.mod h1:Pq9JiuJQpG8JLJdtkwrJESF0Foym2/D9XMU5ciN/wJ0= -github.com/zeebo/xxh3 v1.1.0 h1:s7DLGDK45Dyfg7++yxI0khrfwq9661w9EN78eP/UZVs= -github.com/zeebo/xxh3 v1.1.0/go.mod h1:IisAie1LELR4xhVinxWS5+zf1lA4p0MW4T+w+W07F5s= -gitlab.com/digitalxero/go-conventional-commit v1.0.7 h1:8/dO6WWG+98PMhlZowt/YjuiKhqhGlOCwlIV8SqqGh8= -gitlab.com/digitalxero/go-conventional-commit v1.0.7/go.mod h1:05Xc2BFsSyC5tKhK0y+P3bs0AwUtNuTp+mTpbCU/DZ0= -go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc= -go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg= -golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= -golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.47.0 h1:V6e3FRj+n4dbpw86FJ8Fv7XVOql7TEwpHapKoMJ/GO8= -golang.org/x/crypto v0.47.0/go.mod h1:ff3Y9VzzKbwSSEzWqJsJVBnWmRwRSHt/6Op5n9bQc4A= -golang.org/x/exp v0.0.0-20260112195511-716be5621a96 h1:Z/6YuSHTLOHfNFdb8zVZomZr7cqNgTJvA8+Qz75D8gU= -golang.org/x/exp v0.0.0-20260112195511-716be5621a96/go.mod h1:nzimsREAkjBCIEFtHiYkrJyT+2uy9YZJB7H1k68CXZU= -golang.org/x/exp/typeparams v0.0.0-20260112195511-716be5621a96 h1:RMc8anw0hCPcg5CZYN2PEQ8nMwosk461R6vFwPrCFVg= -golang.org/x/exp/typeparams v0.0.0-20260112195511-716be5621a96/go.mod h1:4Mzdyp/6jzw9auFDJ3OMF5qksa7UvPnzKqTVGcb04ms= -golang.org/x/image v0.0.0-20200430140353-33d19683fad8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= -golang.org/x/image v0.35.0 h1:LKjiHdgMtO8z7Fh18nGY6KDcoEtVfsgLDPeLyguqb7I= -golang.org/x/image v0.35.0/go.mod h1:MwPLTVgvxSASsxdLzKrl8BRFuyqMyGhLwmC+TO1Sybk= -golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= -golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.32.0 h1:9F4d3PHLljb6x//jOyokMv3eX+YDeepZSEo3mFJy93c= -golang.org/x/mod v0.32.0/go.mod h1:SgipZ/3h2Ci89DlEtEXWUk/HteuRin+HHhN+WbNhguU= -golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= -golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= -golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= -golang.org/x/net v0.49.0 h1:eeHFmOGUTtaaPSGNmjBKpbng9MulQsJURQUAfUwY++o= -golang.org/x/net v0.49.0/go.mod h1:/ysNB2EvaqvesRkuLAyjI1ycPZlQHM3q01F02UY/MV8= -golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4= -golang.org/x/sync v0.19.0/go.mod h1:9KTHXmSnoGruLpwFjVSX0lNNA75CykiMECbovNTZqGI= -golang.org/x/sys v0.0.0-20180926160741-c2ed4eda69e7/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= -golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200810151505-1b9f1253b3ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210809222454-d867a43fc93e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211013075003-97ac67df715c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220319134239-a9b59b0215f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.40.0 h1:DBZZqJ2Rkml6QMQsZywtnjnnGvHza6BTfYFWY9kjEWQ= -golang.org/x/sys v0.40.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= -golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= -golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= -golang.org/x/term v0.39.0 h1:RclSuaJf32jOqZz74CkPA9qFuVTX7vhLlpfj/IGWlqY= -golang.org/x/term v0.39.0/go.mod h1:yxzUCTP/U+FzoxfdKmLaA0RV1WgE0VY7hXBwKtY/4ww= -golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= -golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= -golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= -golang.org/x/text v0.33.0 h1:B3njUFyqtHDUI5jMn1YIr5B0IE2U0qck04r6d4KPAxE= -golang.org/x/text v0.33.0/go.mod h1:LuMebE6+rBincTi9+xWTY8TztLzKHc/9C1uBCG27+q8= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= -golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= -golang.org/x/tools v0.41.0 h1:a9b8iMweWG+S0OBnlU36rzLp20z1Rp10w+IY2czHTQc= -golang.org/x/tools v0.41.0/go.mod h1:XSY6eDqxVNiYgezAVqqCeihT4j1U2CCsqvH3WhQpnlg= -golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= -gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME= -gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= -gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= -gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= -gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= -gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -howett.net/plist v1.0.2-0.20250314012144-ee69052608d9 h1:eeH1AIcPvSc0Z25ThsYF+Xoqbn0CI/YnXVYoTLFdGQw= -howett.net/plist v1.0.2-0.20250314012144-ee69052608d9/go.mod h1:fyFX5Hj5tP1Mpk8obqA9MZgXT416Q5711SDT7dQLTLk= -modernc.org/cc/v4 v4.27.1 h1:9W30zRlYrefrDV2JE2O8VDtJ1yPGownxciz5rrbQZis= -modernc.org/cc/v4 v4.27.1/go.mod h1:uVtb5OGqUKpoLWhqwNQo/8LwvoiEBLvZXIQ/SmO6mL0= -modernc.org/ccgo/v4 v4.30.1 h1:4r4U1J6Fhj98NKfSjnPUN7Ze2c6MnAdL0hWw6+LrJpc= -modernc.org/ccgo/v4 v4.30.1/go.mod h1:bIOeI1JL54Utlxn+LwrFyjCx2n2RDiYEaJVSrgdrRfM= -modernc.org/fileutil v1.3.40 h1:ZGMswMNc9JOCrcrakF1HrvmergNLAmxOPjizirpfqBA= -modernc.org/fileutil v1.3.40/go.mod h1:HxmghZSZVAz/LXcMNwZPA/DRrQZEVP9VX0V4LQGQFOc= -modernc.org/gc/v2 v2.6.5 h1:nyqdV8q46KvTpZlsw66kWqwXRHdjIlJOhG6kxiV/9xI= -modernc.org/gc/v2 v2.6.5/go.mod h1:YgIahr1ypgfe7chRuJi2gD7DBQiKSLMPgBQe9oIiito= -modernc.org/gc/v3 v3.1.1 h1:k8T3gkXWY9sEiytKhcgyiZ2L0DTyCQ/nvX+LoCljoRE= -modernc.org/gc/v3 v3.1.1/go.mod h1:HFK/6AGESC7Ex+EZJhJ2Gni6cTaYpSMmU/cT9RmlfYY= -modernc.org/goabi0 v0.2.0 h1:HvEowk7LxcPd0eq6mVOAEMai46V+i7Jrj13t4AzuNks= -modernc.org/goabi0 v0.2.0/go.mod h1:CEFRnnJhKvWT1c1JTI3Avm+tgOWbkOu5oPA8eH8LnMI= -modernc.org/libc v1.67.6 h1:eVOQvpModVLKOdT+LvBPjdQqfrZq+pC39BygcT+E7OI= -modernc.org/libc v1.67.6/go.mod h1:JAhxUVlolfYDErnwiqaLvUqc8nfb2r6S6slAgZOnaiE= -modernc.org/mathutil v1.7.1 h1:GCZVGXdaN8gTqB1Mf/usp1Y/hSqgI2vAGGP4jZMCxOU= -modernc.org/mathutil v1.7.1/go.mod h1:4p5IwJITfppl0G4sUEDtCr4DthTaT47/N3aT6MhfgJg= -modernc.org/memory v1.11.0 h1:o4QC8aMQzmcwCK3t3Ux/ZHmwFPzE6hf2Y5LbkRs+hbI= -modernc.org/memory v1.11.0/go.mod h1:/JP4VbVC+K5sU2wZi9bHoq2MAkCnrt2r98UGeSK7Mjw= -modernc.org/opt v0.1.4 h1:2kNGMRiUjrp4LcaPuLY2PzUfqM/w9N23quVwhKt5Qm8= -modernc.org/opt v0.1.4/go.mod h1:03fq9lsNfvkYSfxrfUhZCWPk1lm4cq4N+Bh//bEtgns= -modernc.org/sortutil v1.2.1 h1:+xyoGf15mM3NMlPDnFqrteY07klSFxLElE2PVuWIJ7w= -modernc.org/sortutil v1.2.1/go.mod h1:7ZI3a3REbai7gzCLcotuw9AC4VZVpYMjDzETGsSMqJE= -modernc.org/sqlite v1.44.3 h1:+39JvV/HWMcYslAwRxHb8067w+2zowvFOUrOWIy9PjY= -modernc.org/sqlite v1.44.3/go.mod h1:CzbrU2lSB1DKUusvwGz7rqEKIq+NUd8GWuBBZDs9/nA= -modernc.org/strutil v1.2.1 h1:UneZBkQA+DX2Rp35KcM69cSsNES9ly8mQWD71HKlOA0= -modernc.org/strutil v1.2.1/go.mod h1:EHkiggD70koQxjVdSBM3JKM7k6L0FbGE5eymy9i3B9A= -modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y= -modernc.org/token v1.1.0/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM= -mvdan.cc/sh/v3 v3.12.0 h1:ejKUR7ONP5bb+UGHGEG/k9V5+pRVIyD+LsZz7o8KHrI= -mvdan.cc/sh/v3 v3.12.0/go.mod h1:Se6Cj17eYSn+sNooLZiEUnNNmNxg0imoYlTu4CyaGyg= diff --git a/v3/internal/assetserver/asset_fileserver.go b/v3/internal/assetserver/asset_fileserver.go deleted file mode 100644 index 974bb582b..000000000 --- a/v3/internal/assetserver/asset_fileserver.go +++ /dev/null @@ -1,161 +0,0 @@ -package assetserver - -import ( - "bytes" - "context" - "embed" - "errors" - "fmt" - "io" - iofs "io/fs" - "net/http" - "os" - "path" - "strings" -) - -const ( - indexHTML = "index.html" -) - -type assetFileServer struct { - fs iofs.FS - err error -} - -func newAssetFileServerFS(vfs iofs.FS) http.Handler { - subDir, err := findPathToFile(vfs, indexHTML) - if err != nil { - if errors.Is(err, os.ErrNotExist) { - msg := "no `index.html` could be found in your Assets fs.FS" - if embedFs, isEmbedFs := vfs.(embed.FS); isEmbedFs { - rootFolder, _ := findEmbedRootPath(embedFs) - msg += fmt.Sprintf(", please make sure the embedded directory '%s' is correct and contains your assets", rootFolder) - } - - err = errors.New(msg) - } - } else { - vfs, err = iofs.Sub(vfs, path.Clean(subDir)) - } - - return &assetFileServer{fs: vfs, err: err} -} - -func (d *assetFileServer) ServeHTTP(rw http.ResponseWriter, req *http.Request) { - ctx := req.Context() - url := req.URL.Path - - err := d.err - if err == nil { - filename := path.Clean(strings.TrimPrefix(url, "/")) - d.logInfo(ctx, "Handling request", "url", url, "file", filename) - err = d.serveFSFile(rw, req, filename) - if os.IsNotExist(err) { - rw.WriteHeader(http.StatusNotFound) - return - } - } - - if err != nil { - d.logError(ctx, "Unable to handle request", "url", url, "err", err) - http.Error(rw, err.Error(), http.StatusInternalServerError) - } -} - -// serveFile will try to load the file from the fs.FS and write it to the response -func (d *assetFileServer) serveFSFile(rw http.ResponseWriter, req *http.Request, filename string) error { - if d.fs == nil { - return os.ErrNotExist - } - - file, err := d.fs.Open(filename) - if err != nil { - if s := path.Ext(filename); s == "" { - filename = filename + ".html" - file, err = d.fs.Open(filename) - if err != nil { - return err - } - } else { - return err - } - } - defer file.Close() - - statInfo, err := file.Stat() - if err != nil { - return err - } - - url := req.URL.Path - isDirectoryPath := url == "" || url[len(url)-1] == '/' - if statInfo.IsDir() { - if !isDirectoryPath { - // If the URL doesn't end in a slash normally a http.redirect should be done, but that currently doesn't work on - // WebKit WebViews (macOS/Linux). - // So we handle this as a specific error - return fmt.Errorf("a directory has been requested without a trailing slash, please add a trailing slash to your request") - } - - filename = path.Join(filename, indexHTML) - - file, err = d.fs.Open(filename) - if err != nil { - return err - } - defer file.Close() - - statInfo, err = file.Stat() - if err != nil { - return err - } - } else if isDirectoryPath { - return fmt.Errorf("a file has been requested with a trailing slash, please remove the trailing slash from your request") - } - - var buf [512]byte - var n int - if _, haveType := rw.Header()[HeaderContentType]; !haveType { - // Detect MimeType by sniffing the first 512 bytes - n, err = file.Read(buf[:]) - if err != nil && err != io.EOF { - return err - } - - // Do the custom MimeType sniffing even though http.ServeContent would do it in case - // of an io.ReadSeeker. We would like to have a consistent behaviour in both cases. - if contentType := GetMimetype(filename, buf[:n]); contentType != "" { - rw.Header().Set(HeaderContentType, contentType) - } - } - - if fileSeeker, _ := file.(io.ReadSeeker); fileSeeker != nil { - if _, err := fileSeeker.Seek(0, io.SeekStart); err != nil { - return fmt.Errorf("seeker can't seek") - } - - http.ServeContent(rw, req, statInfo.Name(), statInfo.ModTime(), fileSeeker) - return nil - } - - rw.Header().Set(HeaderContentLength, fmt.Sprintf("%d", statInfo.Size())) - - // Write the first 512 bytes used for MimeType sniffing - _, err = io.Copy(rw, bytes.NewReader(buf[:n])) - if err != nil { - return err - } - - // Copy the remaining content of the file - _, err = io.Copy(rw, file) - return err -} - -func (d *assetFileServer) logInfo(ctx context.Context, message string, args ...interface{}) { - logInfo(ctx, "[AssetFileServerFS] "+message, args...) -} - -func (d *assetFileServer) logError(ctx context.Context, message string, args ...interface{}) { - logError(ctx, "[AssetFileServerFS] "+message, args...) -} diff --git a/v3/internal/assetserver/assetserver.go b/v3/internal/assetserver/assetserver.go deleted file mode 100644 index 60b2fcbfb..000000000 --- a/v3/internal/assetserver/assetserver.go +++ /dev/null @@ -1,175 +0,0 @@ -package assetserver - -import ( - "fmt" - "net" - "net/http" - "net/url" - "strings" - "time" -) - -const ( - webViewRequestHeaderWindowId = "x-wails-window-id" - webViewRequestHeaderWindowName = "x-wails-window-name" - HeaderAcceptLanguage = "accept-language" -) - -type RuntimeHandler interface { - HandleRuntimeCall(w http.ResponseWriter, r *http.Request) -} - -type service struct { - Route string - Handler http.Handler -} - -type AssetServer struct { - options *Options - handler http.Handler - services []service - - assetServerWebView -} - -func NewAssetServer(options *Options) (*AssetServer, error) { - result := &AssetServer{ - options: options, - } - - userHandler := options.Handler - if userHandler == nil { - userHandler = http.NotFoundHandler() - } - - handler := http.Handler( - http.HandlerFunc( - func(w http.ResponseWriter, r *http.Request) { - result.serveHTTP(w, r, userHandler) - })) - - if middleware := options.Middleware; middleware != nil { - handler = middleware(handler) - } - - result.handler = handler - - return result, nil -} - -func (a *AssetServer) ServeHTTP(rw http.ResponseWriter, req *http.Request) { - start := time.Now() - wrapped := newContentTypeSniffer(rw) - defer func() { - if _, err := wrapped.complete(); err != nil { - a.options.Logger.Error("Error writing response data.", "uri", req.RequestURI, "error", err) - } - }() - - req = req.WithContext(contextWithLogger(req.Context(), a.options.Logger)) - a.handler.ServeHTTP(wrapped, req) - - a.options.Logger.Debug( - "Asset Request:", - "windowName", req.Header.Get(webViewRequestHeaderWindowName), - "windowID", req.Header.Get(webViewRequestHeaderWindowId), - "code", wrapped.status, - "method", req.Method, - "path", req.URL.EscapedPath(), - "duration", time.Since(start), - ) -} - -func (a *AssetServer) serveHTTP(rw http.ResponseWriter, req *http.Request, userHandler http.Handler) { - if isWebSocket(req) { - // WebSockets are not supported by the AssetServer - rw.WriteHeader(http.StatusNotImplemented) - return - } - - header := rw.Header() - // TODO: I don't think this is needed now? - //if a.servingFromDisk { - // header.Add(HeaderCacheControl, "no-cache") - //} - - reqPath := req.URL.Path - switch reqPath { - case "", "/", "/index.html": - // Cache the accept-language header - // before passing the request down the chain. - acceptLanguage := req.Header.Get(HeaderAcceptLanguage) - if acceptLanguage == "" { - acceptLanguage = "en" - } - - wrapped := &fallbackResponseWriter{ - rw: rw, - req: req, - fallback: http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) { - // Set content type for default index.html - header.Set(HeaderContentType, "text/html; charset=utf-8") - a.writeBlob(rw, indexHTML, defaultIndexHTML(acceptLanguage)) - }), - } - userHandler.ServeHTTP(wrapped, req) - - default: - // Check if the path matches a service route - for _, svc := range a.services { - if strings.HasPrefix(reqPath, svc.Route) { - req.URL.Path = strings.TrimPrefix(reqPath, svc.Route) - svc.Handler.ServeHTTP(rw, req) - return - } - } - - // Forward to the user-provided handler - userHandler.ServeHTTP(rw, req) - } -} - -func (a *AssetServer) AttachServiceHandler(route string, handler http.Handler) { - a.services = append(a.services, service{route, handler}) -} - -func (a *AssetServer) writeBlob(rw http.ResponseWriter, filename string, blob []byte) { - err := ServeFile(rw, filename, blob) - if err != nil { - a.serveError(rw, err, "Error writing file content.", "filename", filename) - } -} - -func (a *AssetServer) serveError(rw http.ResponseWriter, err error, msg string, args ...interface{}) { - args = append(args, "error", err) - a.options.Logger.Error(msg, args...) - rw.WriteHeader(http.StatusInternalServerError) -} - -func GetStartURL(userURL string) (string, error) { - devServerURL := GetDevServerURL() - startURL := baseURL.String() - if devServerURL != "" { - // Parse the port - parsedURL, err := url.Parse(devServerURL) - if err != nil { - return "", fmt.Errorf("error parsing environment variable `FRONTEND_DEVSERVER_URL`: %w. Please check your `Taskfile.yml` file", err) - } - port := parsedURL.Port() - if port != "" { - baseURL.Host = net.JoinHostPort(baseURL.Hostname(), port) - startURL = baseURL.String() - } - } - - if userURL != "" { - parsedURL, err := baseURL.Parse(userURL) - if err != nil { - return "", fmt.Errorf("error parsing URL: %w", err) - } - - startURL = parsedURL.String() - } - - return startURL, nil -} diff --git a/v3/internal/assetserver/assetserver_android.go b/v3/internal/assetserver/assetserver_android.go deleted file mode 100644 index ce616f47e..000000000 --- a/v3/internal/assetserver/assetserver_android.go +++ /dev/null @@ -1,12 +0,0 @@ -//go:build android - -package assetserver - -import "net/url" - -// Android uses https://wails.localhost as the base URL -// This matches the WebViewAssetLoader domain configuration -var baseURL = url.URL{ - Scheme: "https", - Host: "wails.localhost", -} diff --git a/v3/internal/assetserver/assetserver_bench_test.go b/v3/internal/assetserver/assetserver_bench_test.go deleted file mode 100644 index 59a55411b..000000000 --- a/v3/internal/assetserver/assetserver_bench_test.go +++ /dev/null @@ -1,242 +0,0 @@ -//go:build bench - -package assetserver - -import ( - "fmt" - "log/slog" - "net/http" - "net/http/httptest" - "os" - "sync" - "testing" -) - -// resetMimeCache clears the mime cache for benchmark isolation -func resetMimeCache() { - mimeCache = sync.Map{} -} - -// BenchmarkGetMimetype measures MIME type detection performance -func BenchmarkGetMimetype(b *testing.B) { - // Reset cache between runs - resetMimeCache() - - b.Run("ByExtension/JS", func(b *testing.B) { - data := []byte("function test() {}") - for b.Loop() { - _ = GetMimetype("script.js", data) - } - }) - - resetMimeCache() - b.Run("ByExtension/CSS", func(b *testing.B) { - data := []byte(".class { color: red; }") - for b.Loop() { - _ = GetMimetype("style.css", data) - } - }) - - resetMimeCache() - b.Run("ByExtension/HTML", func(b *testing.B) { - data := []byte("") - for b.Loop() { - _ = GetMimetype("index.html", data) - } - }) - - resetMimeCache() - b.Run("ByExtension/JSON", func(b *testing.B) { - data := []byte(`{"key": "value"}`) - for b.Loop() { - _ = GetMimetype("data.json", data) - } - }) - - resetMimeCache() - b.Run("Detection/Unknown", func(b *testing.B) { - data := []byte{0x00, 0x01, 0x02, 0x03, 0x04, 0x05} - for b.Loop() { - _ = GetMimetype("unknown.bin", data) - } - }) - - resetMimeCache() - b.Run("Detection/PNG", func(b *testing.B) { - // PNG magic bytes - data := []byte{0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A, 0x00, 0x00, 0x00} - for b.Loop() { - _ = GetMimetype("image.unknown", data) - } - }) - - resetMimeCache() - b.Run("CacheHit", func(b *testing.B) { - data := []byte{0x00, 0x01, 0x02} - // Prime the cache - _ = GetMimetype("cached.bin", data) - b.ResetTimer() - for b.Loop() { - _ = GetMimetype("cached.bin", data) - } - }) -} - -// BenchmarkGetMimetype_Concurrent tests concurrent MIME type lookups -func BenchmarkGetMimetype_Concurrent(b *testing.B) { - resetMimeCache() - data := []byte("function test() {}") - - b.RunParallel(func(pb *testing.PB) { - for pb.Next() { - _ = GetMimetype("script.js", data) - } - }) -} - -// BenchmarkAssetServerServeHTTP measures request handling overhead -func BenchmarkAssetServerServeHTTP(b *testing.B) { - logger := slog.New(slog.NewTextHandler(os.Stderr, &slog.HandlerOptions{Level: slog.LevelError + 1})) - - handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - w.Header().Set("Content-Type", "text/html") - w.WriteHeader(http.StatusOK) - _, _ = w.Write([]byte("Hello")) - }) - - server, err := NewAssetServer(&Options{ - Handler: handler, - Logger: logger, - }) - if err != nil { - b.Fatal(err) - } - - b.Run("SimpleRequest", func(b *testing.B) { - req := httptest.NewRequest("GET", "/index.html", nil) - for b.Loop() { - rr := httptest.NewRecorder() - server.ServeHTTP(rr, req) - } - }) - - b.Run("WithHeaders", func(b *testing.B) { - req := httptest.NewRequest("GET", "/index.html", nil) - req.Header.Set("x-wails-window-id", "1") - req.Header.Set("x-wails-window-name", "main") - req.Header.Set("Accept-Language", "en-US,en;q=0.9") - for b.Loop() { - rr := httptest.NewRecorder() - server.ServeHTTP(rr, req) - } - }) -} - -// BenchmarkAssetServerServeHTTP_Concurrent tests concurrent request handling -func BenchmarkAssetServerServeHTTP_Concurrent(b *testing.B) { - logger := slog.New(slog.NewTextHandler(os.Stderr, &slog.HandlerOptions{Level: slog.LevelError + 1})) - - handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - w.Header().Set("Content-Type", "text/html") - w.WriteHeader(http.StatusOK) - _, _ = w.Write([]byte("Hello")) - }) - - server, err := NewAssetServer(&Options{ - Handler: handler, - Logger: logger, - }) - if err != nil { - b.Fatal(err) - } - - b.RunParallel(func(pb *testing.PB) { - req := httptest.NewRequest("GET", "/index.html", nil) - for pb.Next() { - rr := httptest.NewRecorder() - server.ServeHTTP(rr, req) - } - }) -} - -// BenchmarkContentTypeSniffer measures the content type sniffer overhead -func BenchmarkContentTypeSniffer(b *testing.B) { - b.Run("SmallResponse", func(b *testing.B) { - data := []byte("Hello, World!") - for b.Loop() { - rr := httptest.NewRecorder() - sniffer := newContentTypeSniffer(rr) - _, _ = sniffer.Write(data) - _, _ = sniffer.complete() - } - }) - - b.Run("HTMLResponse", func(b *testing.B) { - data := []byte("Test

                    Hello

                    ") - for b.Loop() { - rr := httptest.NewRecorder() - sniffer := newContentTypeSniffer(rr) - _, _ = sniffer.Write(data) - _, _ = sniffer.complete() - } - }) - - b.Run("LargeResponse", func(b *testing.B) { - data := make([]byte, 64*1024) // 64KB - for i := range data { - data[i] = byte(i % 256) - } - for b.Loop() { - rr := httptest.NewRecorder() - sniffer := newContentTypeSniffer(rr) - _, _ = sniffer.Write(data) - _, _ = sniffer.complete() - } - }) -} - -// BenchmarkServiceRouting measures service route matching performance -func BenchmarkServiceRouting(b *testing.B) { - logger := slog.New(slog.NewTextHandler(os.Stderr, &slog.HandlerOptions{Level: slog.LevelError + 1})) - - dummyHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - w.WriteHeader(http.StatusOK) - }) - - server, err := NewAssetServer(&Options{ - Handler: dummyHandler, - Logger: logger, - }) - if err != nil { - b.Fatal(err) - } - - // Attach multiple service routes - for i := 0; i < 10; i++ { - server.AttachServiceHandler(fmt.Sprintf("/api/v%d/", i), dummyHandler) - } - - b.Run("FirstRoute", func(b *testing.B) { - req := httptest.NewRequest("GET", "/api/v0/users", nil) - for b.Loop() { - rr := httptest.NewRecorder() - server.ServeHTTP(rr, req) - } - }) - - b.Run("LastRoute", func(b *testing.B) { - req := httptest.NewRequest("GET", "/api/v9/users", nil) - for b.Loop() { - rr := httptest.NewRecorder() - server.ServeHTTP(rr, req) - } - }) - - b.Run("NoMatch", func(b *testing.B) { - req := httptest.NewRequest("GET", "/static/app.js", nil) - for b.Loop() { - rr := httptest.NewRecorder() - server.ServeHTTP(rr, req) - } - }) -} diff --git a/v3/internal/assetserver/assetserver_darwin.go b/v3/internal/assetserver/assetserver_darwin.go deleted file mode 100644 index d7c647103..000000000 --- a/v3/internal/assetserver/assetserver_darwin.go +++ /dev/null @@ -1,10 +0,0 @@ -//go:build darwin && !ios - -package assetserver - -import "net/url" - -var baseURL = url.URL{ - Scheme: "wails", - Host: "localhost", -} diff --git a/v3/internal/assetserver/assetserver_dev.go b/v3/internal/assetserver/assetserver_dev.go deleted file mode 100644 index e847ac480..000000000 --- a/v3/internal/assetserver/assetserver_dev.go +++ /dev/null @@ -1,50 +0,0 @@ -//go:build !production - -package assetserver - -import ( - "embed" - "io" - iofs "io/fs" -) - -//go:embed defaults -var defaultHTML embed.FS - -func defaultIndexHTML(language string) []byte { - result := []byte("index.html not found") - // Create an fs.Sub in the defaults directory - defaults, err := iofs.Sub(defaultHTML, "defaults") - if err != nil { - return result - } - // Get the 2 character language code - lang := "en" - if len(language) >= 2 { - lang = language[:2] - } - // Now we can read the index.html file in the format - // index..html. - - indexFile, err := defaults.Open("index." + lang + ".html") - if err != nil { - return result - } - - indexBytes, err := io.ReadAll(indexFile) - if err != nil { - return result - } - return indexBytes -} - -func (a *AssetServer) LogDetails() { - var info = []any{ - "middleware", a.options.Middleware != nil, - "handler", a.options.Handler != nil, - } - if devServerURL := GetDevServerURL(); devServerURL != "" { - info = append(info, "devServerURL", devServerURL) - } - a.options.Logger.Info("AssetServer Info:", info...) -} diff --git a/v3/internal/assetserver/assetserver_ios.go b/v3/internal/assetserver/assetserver_ios.go deleted file mode 100644 index afc05b221..000000000 --- a/v3/internal/assetserver/assetserver_ios.go +++ /dev/null @@ -1,10 +0,0 @@ -//go:build ios - -package assetserver - -import "net/url" - -var baseURL = url.URL{ - Scheme: "wails", - Host: "localhost", -} diff --git a/v3/internal/assetserver/assetserver_linux.go b/v3/internal/assetserver/assetserver_linux.go deleted file mode 100644 index ed579fad7..000000000 --- a/v3/internal/assetserver/assetserver_linux.go +++ /dev/null @@ -1,10 +0,0 @@ -//go:build linux && !android - -package assetserver - -import "net/url" - -var baseURL = url.URL{ - Scheme: "wails", - Host: "localhost", -} diff --git a/v3/internal/assetserver/assetserver_production.go b/v3/internal/assetserver/assetserver_production.go deleted file mode 100644 index f698fab40..000000000 --- a/v3/internal/assetserver/assetserver_production.go +++ /dev/null @@ -1,9 +0,0 @@ -//go:build production - -package assetserver - -func defaultIndexHTML(_ string) []byte { - return []byte("index.html not found") -} - -func (a *AssetServer) LogDetails() {} diff --git a/v3/internal/assetserver/assetserver_test.go b/v3/internal/assetserver/assetserver_test.go deleted file mode 100644 index 755ddf09c..000000000 --- a/v3/internal/assetserver/assetserver_test.go +++ /dev/null @@ -1,244 +0,0 @@ -package assetserver - -import ( - "fmt" - "log/slog" - "net/http" - "net/http/httptest" - "strconv" - "strings" - "testing" - _ "unsafe" - - "github.com/google/go-cmp/cmp" -) - -func TestContentSniffing(t *testing.T) { - longLead := strings.Repeat(" ", 512-6) - - tests := map[string]struct { - Expect string - Status int - Header map[string][]string - Body []string - }{ - "/simple": { - Expect: "text/html; charset=utf-8", - Body: []string{"Hello!"}, - }, - "/split": { - Expect: "text/html; charset=utf-8", - Body: []string{ - "Hello!", - "", - }, - }, - "/lead/short/simple": { - Expect: "text/html; charset=utf-8", - Body: []string{ - " " + "Hello!", - }, - }, - "/lead/short/split": { - Expect: "text/html; charset=utf-8", - Body: []string{ - " ", - "Hello!", - }, - }, - "/lead/long/simple": { - Expect: "text/html; charset=utf-8", - Body: []string{ - longLead + "Hello!", - }, - }, - "/lead/long/split": { - Expect: "text/html; charset=utf-8", - Body: []string{ - longLead, - "Hello!", - }, - }, - "/lead/toolong/simple": { - Expect: "text/plain; charset=utf-8", - Body: []string{ - "Hello" + longLead + "Hello!", - }, - }, - "/lead/toolong/split": { - Expect: "text/plain; charset=utf-8", - Body: []string{ - "Hello" + longLead, - "Hello!", - }, - }, - "/header": { - Expect: "text/html; charset=utf-8", - Status: http.StatusForbidden, - Header: map[string][]string{ - "X-Custom": {"CustomValue"}, - }, - Body: []string{"Hello!"}, - }, - "/custom": { - Expect: "text/plain;charset=utf-8", - Header: map[string][]string{ - "Content-Type": {"text/plain;charset=utf-8"}, - }, - Body: []string{"Hello!"}, - }, - } - - srv, err := NewAssetServer(&Options{ - Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - test, ok := tests[r.URL.Path] - if !ok { - w.WriteHeader(http.StatusNotFound) - return - } - - for key, values := range test.Header { - for _, value := range values { - w.Header().Add(key, value) - } - } - - if test.Status != 0 { - w.WriteHeader(test.Status) - } - - for _, chunk := range test.Body { - w.Write([]byte(chunk)) - } - }), - Logger: slog.Default(), - }) - if err != nil { - t.Fatal("AssetServer initialisation failed: ", err) - } - - for path, test := range tests { - t.Run(path[1:], func(t *testing.T) { - res := httptest.NewRecorder() - - req, err := http.NewRequest(http.MethodGet, path, nil) - if err != nil { - t.Fatal("http.NewRequest failed: ", err) - } - - srv.ServeHTTP(res, req) - - expectedStatus := http.StatusOK - if test.Status != 0 { - expectedStatus = test.Status - } - if res.Code != expectedStatus { - t.Errorf("Status code mismatch: want %d, got %d", expectedStatus, res.Code) - } - - if ct := res.Header().Get("Content-Type"); ct != test.Expect { - t.Errorf("Content type mismatch: want '%s', got '%s'", test.Expect, ct) - } - - for key, values := range test.Header { - if diff := cmp.Diff(values, res.Header().Values(key)); diff != "" { - t.Errorf("Header '%s' mismatch (-want +got):\n%s", key, diff) - } - } - - if diff := cmp.Diff(strings.Join(test.Body, ""), res.Body.String()); diff != "" { - t.Errorf("Response body mismatch (-want +got):\n%s", diff) - } - }) - } -} - -func TestIndexFallback(t *testing.T) { - // Paths to try and whether a 404 should trigger a fallback. - paths := map[string]bool{ - "": true, - "/": true, - "/index": false, - "/index.html": true, - "/other": false, - } - - statuses := []int{ - http.StatusOK, - http.StatusNotFound, - http.StatusForbidden, - } - - header := map[string][]string{ - "X-Custom": {"CustomValue"}, - } - body := "Hello!" - - srv, err := NewAssetServer(&Options{ - Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - for key, values := range header { - for _, value := range values { - w.Header().Add(key, value) - } - } - - status, err := strconv.Atoi(r.URL.Query().Get("status")) - if err == nil && status != 0 && status != http.StatusOK { - w.WriteHeader(status) - } - - w.Write([]byte(body)) - }), - Logger: slog.Default(), - }) - if err != nil { - t.Fatal("AssetServer initialisation failed: ", err) - } - - for path, fallback := range paths { - for _, status := range statuses { - key := "" - if len(path) > 0 { - key = path[1:] - } - - t.Run(fmt.Sprintf("%s/status=%d", key, status), func(t *testing.T) { - res := httptest.NewRecorder() - - req, err := http.NewRequest(http.MethodGet, fmt.Sprintf("%s?status=%d", path, status), nil) - if err != nil { - t.Fatal("http.NewRequest failed: ", err) - } - - srv.ServeHTTP(res, req) - - fallbackTriggered := false - if status == http.StatusNotFound && fallback { - status = http.StatusOK - fallbackTriggered = true - } - - if res.Code != status { - t.Errorf("Status code mismatch: want %d, got %d", status, res.Code) - } - - if fallbackTriggered { - if cmp.Equal(body, res.Body.String()) { - t.Errorf("Fallback response has the same body as not found response") - } - return - } else { - for key, values := range header { - if diff := cmp.Diff(values, res.Header().Values(key)); diff != "" { - t.Errorf("Header '%s' mismatch (-want +got):\n%s", key, diff) - } - } - - if diff := cmp.Diff(body, res.Body.String()); diff != "" { - t.Errorf("Response body mismatch (-want +got):\n%s", diff) - } - } - }) - } - } -} diff --git a/v3/internal/assetserver/assetserver_webview.go b/v3/internal/assetserver/assetserver_webview.go deleted file mode 100644 index 21c01ede2..000000000 --- a/v3/internal/assetserver/assetserver_webview.go +++ /dev/null @@ -1,198 +0,0 @@ -package assetserver - -import ( - "context" - "fmt" - "net/http" - "net/url" - "strconv" - "strings" - "sync" - - "github.com/wailsapp/wails/v3/internal/assetserver/webview" -) - -type assetServerWebView struct { - // ExpectedWebViewHost is checked against the Request Host of every WebViewRequest, other hosts won't be processed. - ExpectedWebViewHost string - - dispatchInit sync.Once - dispatchReqC chan<- webview.Request - dispatchWorkers int -} - -// ServeWebViewRequest processes the HTTP Request asynchronously by faking a golang HTTP Server. -// The request will be finished with a StatusNotImplemented code if no handler has written to the response. -// The AssetServer takes ownership of the request and the caller mustn't close it or access it in any other way. -func (a *AssetServer) ServeWebViewRequest(req webview.Request) { - a.dispatchInit.Do(func() { - workers := a.dispatchWorkers - if workers <= 0 { - return - } - - workerC := make(chan webview.Request, workers*2) - for i := 0; i < workers; i++ { - go func() { - for req := range workerC { - a.processWebViewRequest(req) - } - }() - } - - dispatchC := make(chan webview.Request) - go queueingDispatcher(50, dispatchC, workerC) - - a.dispatchReqC = dispatchC - }) - - if a.dispatchReqC == nil { - go a.processWebViewRequest(req) - } else { - a.dispatchReqC <- req - } -} - -func (a *AssetServer) processWebViewRequest(r webview.Request) { - uri, _ := r.URL() - a.processWebViewRequestInternal(r) - if err := r.Close(); err != nil { - a.options.Logger.Error("Unable to call close for request for uri.", "uri", uri) - } -} - -// processHTTPRequest processes the HTTP Request by faking a golang HTTP Server. -// The request will be finished with a StatusNotImplemented code if no handler has written to the response. -func (a *AssetServer) processWebViewRequestInternal(r webview.Request) { - uri := "unknown" - var err error - - wrw := r.Response() - defer func() { - if err := wrw.Finish(); err != nil { - a.options.Logger.Error("Error finishing request.", "uri", uri, "error", err) - } - }() - - rw := newContentTypeSniffer(wrw) // Make sure we have a Content-Type sniffer - defer func() { - if _, err := rw.complete(); err != nil { - a.options.Logger.Error("Error writing response data.", "uri", uri, "error", err) - } - }() - defer rw.WriteHeader(http.StatusNotImplemented) // This is a NOP when a handler has already written and set the status - - uri, err = r.URL() - if err != nil { - a.webviewRequestErrorHandler(uri, rw, fmt.Errorf("URL: %w", err)) - return - } - - method, err := r.Method() - if err != nil { - a.webviewRequestErrorHandler(uri, rw, fmt.Errorf("HTTP-Method: %w", err)) - return - } - - header, err := r.Header() - if err != nil { - a.webviewRequestErrorHandler(uri, rw, fmt.Errorf("HTTP-Header: %w", err)) - return - } - - body, err := r.Body() - if err != nil { - a.webviewRequestErrorHandler(uri, rw, fmt.Errorf("HTTP-Body: %w", err)) - return - } - - if body == nil { - body = http.NoBody - } - defer body.Close() - - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() - - req, err := http.NewRequestWithContext(ctx, method, uri, body) - if err != nil { - a.webviewRequestErrorHandler(uri, rw, fmt.Errorf("HTTP-Request: %w", err)) - return - } - - // For server requests, the URL is parsed from the URI supplied on the Request-Line as stored in RequestURI. For - // most requests, fields other than Path and RawQuery will be empty. (See RFC 7230, Section 5.3) - req.URL.Scheme = "" - req.URL.Host = "" - req.URL.Fragment = "" - req.URL.RawFragment = "" - - if requestURL := req.URL; req.RequestURI == "" && requestURL != nil { - req.RequestURI = requestURL.String() - } - - req.Header = header - - if req.RemoteAddr == "" { - // 192.0.2.0/24 is "TEST-NET" in RFC 5737 - req.RemoteAddr = "192.0.2.1:1234" - } - - if req.RequestURI == "" && req.URL != nil { - req.RequestURI = req.URL.String() - } - - if req.ContentLength == 0 { - req.ContentLength, _ = strconv.ParseInt(req.Header.Get(HeaderContentLength), 10, 64) - } else { - req.Header.Set(HeaderContentLength, fmt.Sprintf("%d", req.ContentLength)) - } - - if host := req.Header.Get(HeaderHost); host != "" { - req.Host = host - } - - // iOS uses "localhost" while other platforms might use different hosts - // Skip host check for iOS requests from wails:// scheme - if expectedHost := a.ExpectedWebViewHost; expectedHost != "" && expectedHost != req.Host && !strings.HasPrefix(uri, "wails://") { - a.webviewRequestErrorHandler(uri, rw, fmt.Errorf("expected host '%s' in request, but was '%s'", expectedHost, req.Host)) - return - } - - a.ServeHTTP(rw, req) -} - -func (a *AssetServer) webviewRequestErrorHandler(uri string, rw http.ResponseWriter, err error) { - logInfo := uri - if uri, err := url.ParseRequestURI(uri); err == nil { - logInfo = strings.Replace(logInfo, fmt.Sprintf("%s://%s", uri.Scheme, uri.Host), "", 1) - } - - a.options.Logger.Error("Error processing request (HttpResponse=500)", "details", logInfo, "error", err) - http.Error(rw, err.Error(), http.StatusInternalServerError) -} - -func queueingDispatcher[T any](minQueueSize uint, inC <-chan T, outC chan<- T) { - q := newRingqueue[T](minQueueSize) - for { - in, ok := <-inC - if !ok { - return - } - - q.Add(in) - for q.Len() != 0 { - out, _ := q.Peek() - select { - case outC <- out: - q.Remove() - case in, ok := <-inC: - if !ok { - return - } - - q.Add(in) - } - } - } -} diff --git a/v3/internal/assetserver/assetserver_windows.go b/v3/internal/assetserver/assetserver_windows.go deleted file mode 100644 index 22deda4d2..000000000 --- a/v3/internal/assetserver/assetserver_windows.go +++ /dev/null @@ -1,8 +0,0 @@ -package assetserver - -import "net/url" - -var baseURL = url.URL{ - Scheme: "http", - Host: "wails.localhost", -} diff --git a/v3/internal/assetserver/build_dev.go b/v3/internal/assetserver/build_dev.go deleted file mode 100644 index 7747a7142..000000000 --- a/v3/internal/assetserver/build_dev.go +++ /dev/null @@ -1,41 +0,0 @@ -//go:build !production - -package assetserver - -import ( - _ "embed" - "io/fs" - "net/http" - "net/http/httputil" - "net/url" - "os" -) - -func NewAssetFileServer(vfs fs.FS) http.Handler { - devServerURL := GetDevServerURL() - if devServerURL == "" { - return newAssetFileServerFS(vfs) - } - - parsedURL, err := url.Parse(devServerURL) - if err != nil { - return http.HandlerFunc( - func(rw http.ResponseWriter, req *http.Request) { - logError(req.Context(), "[ExternalAssetHandler] Invalid FRONTEND_DEVSERVER_URL. Should be valid URL", "error", err.Error()) - http.Error(rw, err.Error(), http.StatusInternalServerError) - }) - - } - - proxy := httputil.NewSingleHostReverseProxy(parsedURL) - proxy.ErrorHandler = func(rw http.ResponseWriter, r *http.Request, err error) { - logError(r.Context(), "[ExternalAssetHandler] Proxy error", "error", err.Error()) - rw.WriteHeader(http.StatusBadGateway) - } - - return proxy -} - -func GetDevServerURL() string { - return os.Getenv("FRONTEND_DEVSERVER_URL") -} diff --git a/v3/internal/assetserver/build_production.go b/v3/internal/assetserver/build_production.go deleted file mode 100644 index 98d5b4ffd..000000000 --- a/v3/internal/assetserver/build_production.go +++ /dev/null @@ -1,16 +0,0 @@ -//go:build production - -package assetserver - -import ( - "io/fs" - "net/http" -) - -func NewAssetFileServer(vfs fs.FS) http.Handler { - return newAssetFileServerFS(vfs) -} - -func GetDevServerURL() string { - return "" -} diff --git a/v3/internal/assetserver/bundled_assetserver.go b/v3/internal/assetserver/bundled_assetserver.go deleted file mode 100644 index 15297cd37..000000000 --- a/v3/internal/assetserver/bundled_assetserver.go +++ /dev/null @@ -1,33 +0,0 @@ -package assetserver - -import ( - "github.com/wailsapp/wails/v3/internal/assetserver/bundledassets" - "io/fs" - "net/http" - "strings" -) - -type BundledAssetServer struct { - handler http.Handler -} - -func NewBundledAssetFileServer(fs fs.FS) *BundledAssetServer { - return &BundledAssetServer{ - handler: NewAssetFileServer(fs), - } -} - -func (b *BundledAssetServer) ServeHTTP(rw http.ResponseWriter, req *http.Request) { - if strings.HasPrefix(req.URL.Path, "/wails/") { - // Strip the /wails prefix - req.URL.Path = req.URL.Path[6:] - switch req.URL.Path { - case "/runtime.js": - rw.Header().Set("Content-Type", "application/javascript") - rw.Write([]byte(bundledassets.RuntimeJS)) - return - } - return - } - b.handler.ServeHTTP(rw, req) -} diff --git a/v3/internal/assetserver/bundledassets/runtime.debug.js b/v3/internal/assetserver/bundledassets/runtime.debug.js deleted file mode 100644 index 5dfba7f59..000000000 --- a/v3/internal/assetserver/bundledassets/runtime.debug.js +++ /dev/null @@ -1,2774 +0,0 @@ -var __defProp = Object.defineProperty; -var __defProps = Object.defineProperties; -var __getOwnPropDescs = Object.getOwnPropertyDescriptors; -var __getOwnPropSymbols = Object.getOwnPropertySymbols; -var __hasOwnProp = Object.prototype.hasOwnProperty; -var __propIsEnum = Object.prototype.propertyIsEnumerable; -var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value; -var __spreadValues = (a, b) => { - for (var prop in b || (b = {})) - if (__hasOwnProp.call(b, prop)) - __defNormalProp(a, prop, b[prop]); - if (__getOwnPropSymbols) - for (var prop of __getOwnPropSymbols(b)) { - if (__propIsEnum.call(b, prop)) - __defNormalProp(a, prop, b[prop]); - } - return a; -}; -var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b)); -var __export = (target, all) => { - for (var name in all) - __defProp(target, name, { get: all[name], enumerable: true }); -}; - -// desktop/@wailsio/runtime/src/index.ts -var index_exports = {}; -__export(index_exports, { - Application: () => application_exports, - Browser: () => browser_exports, - Call: () => calls_exports, - CancelError: () => CancelError, - CancellablePromise: () => CancellablePromise, - CancelledRejectionError: () => CancelledRejectionError, - Clipboard: () => clipboard_exports, - Create: () => create_exports, - Dialogs: () => dialogs_exports, - Events: () => events_exports, - Flags: () => flags_exports, - IOS: () => ios_exports, - Screens: () => screens_exports, - System: () => system_exports, - WML: () => wml_exports, - Window: () => window_default, - clientId: () => clientId, - getTransport: () => getTransport, - loadOptionalScript: () => loadOptionalScript, - objectNames: () => objectNames, - setTransport: () => setTransport -}); - -// desktop/@wailsio/runtime/src/wml.ts -var wml_exports = {}; -__export(wml_exports, { - Enable: () => Enable, - Reload: () => Reload -}); - -// desktop/@wailsio/runtime/src/browser.ts -var browser_exports = {}; -__export(browser_exports, { - OpenURL: () => OpenURL -}); - -// desktop/@wailsio/runtime/src/nanoid.ts -var urlAlphabet = "useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict"; -function nanoid(size = 21) { - let id = ""; - let i = size | 0; - while (i--) { - id += urlAlphabet[Math.random() * 64 | 0]; - } - return id; -} - -// desktop/@wailsio/runtime/src/runtime.ts -var runtimeURL = window.location.origin + "/wails/runtime"; -var objectNames = Object.freeze({ - Call: 0, - Clipboard: 1, - Application: 2, - Events: 3, - ContextMenu: 4, - Dialog: 5, - Window: 6, - Screens: 7, - System: 8, - Browser: 9, - CancelCall: 10, - IOS: 11 -}); -var clientId = nanoid(); -var customTransport = null; -function setTransport(transport) { - customTransport = transport; -} -function getTransport() { - return customTransport; -} -function newRuntimeCaller(object, windowName = "") { - return function(method, args = null) { - return runtimeCallWithID(object, method, windowName, args); - }; -} -async function runtimeCallWithID(objectID, method, windowName, args) { - var _a2, _b; - if (customTransport) { - return customTransport.call(objectID, method, windowName, args); - } - let url = new URL(runtimeURL); - let body = { - object: objectID, - method - }; - if (args !== null && args !== void 0) { - body.args = args; - } - let headers = { - ["x-wails-client-id"]: clientId, - ["Content-Type"]: "application/json" - }; - if (windowName) { - headers["x-wails-window-name"] = windowName; - } - let response = await fetch(url, { - method: "POST", - headers, - body: JSON.stringify(body) - }); - if (!response.ok) { - throw new Error(await response.text()); - } - if (((_b = (_a2 = response.headers.get("Content-Type")) == null ? void 0 : _a2.indexOf("application/json")) != null ? _b : -1) !== -1) { - return response.json(); - } else { - return response.text(); - } -} - -// desktop/@wailsio/runtime/src/browser.ts -var call = newRuntimeCaller(objectNames.Browser); -var BrowserOpenURL = 0; -function OpenURL(url) { - return call(BrowserOpenURL, { url: url.toString() }); -} - -// desktop/@wailsio/runtime/src/dialogs.ts -var dialogs_exports = {}; -__export(dialogs_exports, { - Error: () => Error2, - Info: () => Info, - OpenFile: () => OpenFile, - Question: () => Question, - SaveFile: () => SaveFile, - Warning: () => Warning -}); -window._wails = window._wails || {}; -var call2 = newRuntimeCaller(objectNames.Dialog); -var DialogInfo = 0; -var DialogWarning = 1; -var DialogError = 2; -var DialogQuestion = 3; -var DialogOpenFile = 4; -var DialogSaveFile = 5; -function dialog(type, options = {}) { - return call2(type, options); -} -function Info(options) { - return dialog(DialogInfo, options); -} -function Warning(options) { - return dialog(DialogWarning, options); -} -function Error2(options) { - return dialog(DialogError, options); -} -function Question(options) { - return dialog(DialogQuestion, options); -} -function OpenFile(options) { - var _a2; - return (_a2 = dialog(DialogOpenFile, options)) != null ? _a2 : []; -} -function SaveFile(options) { - return dialog(DialogSaveFile, options); -} - -// desktop/@wailsio/runtime/src/events.ts -var events_exports = {}; -__export(events_exports, { - Emit: () => Emit, - Off: () => Off, - OffAll: () => OffAll, - On: () => On, - OnMultiple: () => OnMultiple, - Once: () => Once, - Types: () => Types, - WailsEvent: () => WailsEvent -}); - -// desktop/@wailsio/runtime/src/listener.ts -var eventListeners = /* @__PURE__ */ new Map(); -var Listener = class { - constructor(eventName, callback, maxCallbacks) { - this.eventName = eventName; - this.callback = callback; - this.maxCallbacks = maxCallbacks || -1; - } - dispatch(data) { - try { - this.callback(data); - } catch (err) { - console.error(err); - } - if (this.maxCallbacks === -1) return false; - this.maxCallbacks -= 1; - return this.maxCallbacks === 0; - } -}; -function listenerOff(listener) { - let listeners = eventListeners.get(listener.eventName); - if (!listeners) { - return; - } - listeners = listeners.filter((l) => l !== listener); - if (listeners.length === 0) { - eventListeners.delete(listener.eventName); - } else { - eventListeners.set(listener.eventName, listeners); - } -} - -// desktop/@wailsio/runtime/src/create.ts -var create_exports = {}; -__export(create_exports, { - Any: () => Any, - Array: () => Array2, - ByteSlice: () => ByteSlice, - Events: () => Events, - Map: () => Map2, - Nullable: () => Nullable, - Struct: () => Struct -}); -function Any(source) { - return source; -} -function ByteSlice(source) { - return source == null ? "" : source; -} -function Array2(element) { - if (element === Any) { - return (source) => source === null ? [] : source; - } - return (source) => { - if (source === null) { - return []; - } - for (let i = 0; i < source.length; i++) { - source[i] = element(source[i]); - } - return source; - }; -} -function Map2(key, value) { - if (value === Any) { - return (source) => source === null ? {} : source; - } - return (source) => { - if (source === null) { - return {}; - } - for (const key2 in source) { - source[key2] = value(source[key2]); - } - return source; - }; -} -function Nullable(element) { - if (element === Any) { - return Any; - } - return (source) => source === null ? null : element(source); -} -function Struct(createField) { - let allAny = true; - for (const name in createField) { - if (createField[name] !== Any) { - allAny = false; - break; - } - } - if (allAny) { - return Any; - } - return (source) => { - for (const name in createField) { - if (name in source) { - source[name] = createField[name](source[name]); - } - } - return source; - }; -} -var Events = {}; - -// desktop/@wailsio/runtime/src/event_types.ts -var Types = Object.freeze({ - Windows: Object.freeze({ - APMPowerSettingChange: "windows:APMPowerSettingChange", - APMPowerStatusChange: "windows:APMPowerStatusChange", - APMResumeAutomatic: "windows:APMResumeAutomatic", - APMResumeSuspend: "windows:APMResumeSuspend", - APMSuspend: "windows:APMSuspend", - ApplicationStarted: "windows:ApplicationStarted", - SystemThemeChanged: "windows:SystemThemeChanged", - WebViewNavigationCompleted: "windows:WebViewNavigationCompleted", - WindowActive: "windows:WindowActive", - WindowBackgroundErase: "windows:WindowBackgroundErase", - WindowClickActive: "windows:WindowClickActive", - WindowClosing: "windows:WindowClosing", - WindowDidMove: "windows:WindowDidMove", - WindowDidResize: "windows:WindowDidResize", - WindowDPIChanged: "windows:WindowDPIChanged", - WindowDragDrop: "windows:WindowDragDrop", - WindowDragEnter: "windows:WindowDragEnter", - WindowDragLeave: "windows:WindowDragLeave", - WindowDragOver: "windows:WindowDragOver", - WindowEndMove: "windows:WindowEndMove", - WindowEndResize: "windows:WindowEndResize", - WindowFullscreen: "windows:WindowFullscreen", - WindowHide: "windows:WindowHide", - WindowInactive: "windows:WindowInactive", - WindowKeyDown: "windows:WindowKeyDown", - WindowKeyUp: "windows:WindowKeyUp", - WindowKillFocus: "windows:WindowKillFocus", - WindowNonClientHit: "windows:WindowNonClientHit", - WindowNonClientMouseDown: "windows:WindowNonClientMouseDown", - WindowNonClientMouseLeave: "windows:WindowNonClientMouseLeave", - WindowNonClientMouseMove: "windows:WindowNonClientMouseMove", - WindowNonClientMouseUp: "windows:WindowNonClientMouseUp", - WindowPaint: "windows:WindowPaint", - WindowRestore: "windows:WindowRestore", - WindowSetFocus: "windows:WindowSetFocus", - WindowShow: "windows:WindowShow", - WindowStartMove: "windows:WindowStartMove", - WindowStartResize: "windows:WindowStartResize", - WindowUnFullscreen: "windows:WindowUnFullscreen", - WindowZOrderChanged: "windows:WindowZOrderChanged", - WindowMinimise: "windows:WindowMinimise", - WindowUnMinimise: "windows:WindowUnMinimise", - WindowMaximise: "windows:WindowMaximise", - WindowUnMaximise: "windows:WindowUnMaximise" - }), - Mac: Object.freeze({ - ApplicationDidBecomeActive: "mac:ApplicationDidBecomeActive", - ApplicationDidChangeBackingProperties: "mac:ApplicationDidChangeBackingProperties", - ApplicationDidChangeEffectiveAppearance: "mac:ApplicationDidChangeEffectiveAppearance", - ApplicationDidChangeIcon: "mac:ApplicationDidChangeIcon", - ApplicationDidChangeOcclusionState: "mac:ApplicationDidChangeOcclusionState", - ApplicationDidChangeScreenParameters: "mac:ApplicationDidChangeScreenParameters", - ApplicationDidChangeStatusBarFrame: "mac:ApplicationDidChangeStatusBarFrame", - ApplicationDidChangeStatusBarOrientation: "mac:ApplicationDidChangeStatusBarOrientation", - ApplicationDidChangeTheme: "mac:ApplicationDidChangeTheme", - ApplicationDidFinishLaunching: "mac:ApplicationDidFinishLaunching", - ApplicationDidHide: "mac:ApplicationDidHide", - ApplicationDidResignActive: "mac:ApplicationDidResignActive", - ApplicationDidUnhide: "mac:ApplicationDidUnhide", - ApplicationDidUpdate: "mac:ApplicationDidUpdate", - ApplicationShouldHandleReopen: "mac:ApplicationShouldHandleReopen", - ApplicationWillBecomeActive: "mac:ApplicationWillBecomeActive", - ApplicationWillFinishLaunching: "mac:ApplicationWillFinishLaunching", - ApplicationWillHide: "mac:ApplicationWillHide", - ApplicationWillResignActive: "mac:ApplicationWillResignActive", - ApplicationWillTerminate: "mac:ApplicationWillTerminate", - ApplicationWillUnhide: "mac:ApplicationWillUnhide", - ApplicationWillUpdate: "mac:ApplicationWillUpdate", - MenuDidAddItem: "mac:MenuDidAddItem", - MenuDidBeginTracking: "mac:MenuDidBeginTracking", - MenuDidClose: "mac:MenuDidClose", - MenuDidDisplayItem: "mac:MenuDidDisplayItem", - MenuDidEndTracking: "mac:MenuDidEndTracking", - MenuDidHighlightItem: "mac:MenuDidHighlightItem", - MenuDidOpen: "mac:MenuDidOpen", - MenuDidPopUp: "mac:MenuDidPopUp", - MenuDidRemoveItem: "mac:MenuDidRemoveItem", - MenuDidSendAction: "mac:MenuDidSendAction", - MenuDidSendActionToItem: "mac:MenuDidSendActionToItem", - MenuDidUpdate: "mac:MenuDidUpdate", - MenuWillAddItem: "mac:MenuWillAddItem", - MenuWillBeginTracking: "mac:MenuWillBeginTracking", - MenuWillDisplayItem: "mac:MenuWillDisplayItem", - MenuWillEndTracking: "mac:MenuWillEndTracking", - MenuWillHighlightItem: "mac:MenuWillHighlightItem", - MenuWillOpen: "mac:MenuWillOpen", - MenuWillPopUp: "mac:MenuWillPopUp", - MenuWillRemoveItem: "mac:MenuWillRemoveItem", - MenuWillSendAction: "mac:MenuWillSendAction", - MenuWillSendActionToItem: "mac:MenuWillSendActionToItem", - MenuWillUpdate: "mac:MenuWillUpdate", - WebViewDidCommitNavigation: "mac:WebViewDidCommitNavigation", - WebViewDidFinishNavigation: "mac:WebViewDidFinishNavigation", - WebViewDidReceiveServerRedirectForProvisionalNavigation: "mac:WebViewDidReceiveServerRedirectForProvisionalNavigation", - WebViewDidStartProvisionalNavigation: "mac:WebViewDidStartProvisionalNavigation", - WindowDidBecomeKey: "mac:WindowDidBecomeKey", - WindowDidBecomeMain: "mac:WindowDidBecomeMain", - WindowDidBeginSheet: "mac:WindowDidBeginSheet", - WindowDidChangeAlpha: "mac:WindowDidChangeAlpha", - WindowDidChangeBackingLocation: "mac:WindowDidChangeBackingLocation", - WindowDidChangeBackingProperties: "mac:WindowDidChangeBackingProperties", - WindowDidChangeCollectionBehavior: "mac:WindowDidChangeCollectionBehavior", - WindowDidChangeEffectiveAppearance: "mac:WindowDidChangeEffectiveAppearance", - WindowDidChangeOcclusionState: "mac:WindowDidChangeOcclusionState", - WindowDidChangeOrderingMode: "mac:WindowDidChangeOrderingMode", - WindowDidChangeScreen: "mac:WindowDidChangeScreen", - WindowDidChangeScreenParameters: "mac:WindowDidChangeScreenParameters", - WindowDidChangeScreenProfile: "mac:WindowDidChangeScreenProfile", - WindowDidChangeScreenSpace: "mac:WindowDidChangeScreenSpace", - WindowDidChangeScreenSpaceProperties: "mac:WindowDidChangeScreenSpaceProperties", - WindowDidChangeSharingType: "mac:WindowDidChangeSharingType", - WindowDidChangeSpace: "mac:WindowDidChangeSpace", - WindowDidChangeSpaceOrderingMode: "mac:WindowDidChangeSpaceOrderingMode", - WindowDidChangeTitle: "mac:WindowDidChangeTitle", - WindowDidChangeToolbar: "mac:WindowDidChangeToolbar", - WindowDidDeminiaturize: "mac:WindowDidDeminiaturize", - WindowDidEndSheet: "mac:WindowDidEndSheet", - WindowDidEnterFullScreen: "mac:WindowDidEnterFullScreen", - WindowDidEnterVersionBrowser: "mac:WindowDidEnterVersionBrowser", - WindowDidExitFullScreen: "mac:WindowDidExitFullScreen", - WindowDidExitVersionBrowser: "mac:WindowDidExitVersionBrowser", - WindowDidExpose: "mac:WindowDidExpose", - WindowDidFocus: "mac:WindowDidFocus", - WindowDidMiniaturize: "mac:WindowDidMiniaturize", - WindowDidMove: "mac:WindowDidMove", - WindowDidOrderOffScreen: "mac:WindowDidOrderOffScreen", - WindowDidOrderOnScreen: "mac:WindowDidOrderOnScreen", - WindowDidResignKey: "mac:WindowDidResignKey", - WindowDidResignMain: "mac:WindowDidResignMain", - WindowDidResize: "mac:WindowDidResize", - WindowDidUpdate: "mac:WindowDidUpdate", - WindowDidUpdateAlpha: "mac:WindowDidUpdateAlpha", - WindowDidUpdateCollectionBehavior: "mac:WindowDidUpdateCollectionBehavior", - WindowDidUpdateCollectionProperties: "mac:WindowDidUpdateCollectionProperties", - WindowDidUpdateShadow: "mac:WindowDidUpdateShadow", - WindowDidUpdateTitle: "mac:WindowDidUpdateTitle", - WindowDidUpdateToolbar: "mac:WindowDidUpdateToolbar", - WindowDidZoom: "mac:WindowDidZoom", - WindowFileDraggingEntered: "mac:WindowFileDraggingEntered", - WindowFileDraggingExited: "mac:WindowFileDraggingExited", - WindowFileDraggingPerformed: "mac:WindowFileDraggingPerformed", - WindowHide: "mac:WindowHide", - WindowMaximise: "mac:WindowMaximise", - WindowUnMaximise: "mac:WindowUnMaximise", - WindowMinimise: "mac:WindowMinimise", - WindowUnMinimise: "mac:WindowUnMinimise", - WindowShouldClose: "mac:WindowShouldClose", - WindowShow: "mac:WindowShow", - WindowWillBecomeKey: "mac:WindowWillBecomeKey", - WindowWillBecomeMain: "mac:WindowWillBecomeMain", - WindowWillBeginSheet: "mac:WindowWillBeginSheet", - WindowWillChangeOrderingMode: "mac:WindowWillChangeOrderingMode", - WindowWillClose: "mac:WindowWillClose", - WindowWillDeminiaturize: "mac:WindowWillDeminiaturize", - WindowWillEnterFullScreen: "mac:WindowWillEnterFullScreen", - WindowWillEnterVersionBrowser: "mac:WindowWillEnterVersionBrowser", - WindowWillExitFullScreen: "mac:WindowWillExitFullScreen", - WindowWillExitVersionBrowser: "mac:WindowWillExitVersionBrowser", - WindowWillFocus: "mac:WindowWillFocus", - WindowWillMiniaturize: "mac:WindowWillMiniaturize", - WindowWillMove: "mac:WindowWillMove", - WindowWillOrderOffScreen: "mac:WindowWillOrderOffScreen", - WindowWillOrderOnScreen: "mac:WindowWillOrderOnScreen", - WindowWillResignMain: "mac:WindowWillResignMain", - WindowWillResize: "mac:WindowWillResize", - WindowWillUnfocus: "mac:WindowWillUnfocus", - WindowWillUpdate: "mac:WindowWillUpdate", - WindowWillUpdateAlpha: "mac:WindowWillUpdateAlpha", - WindowWillUpdateCollectionBehavior: "mac:WindowWillUpdateCollectionBehavior", - WindowWillUpdateCollectionProperties: "mac:WindowWillUpdateCollectionProperties", - WindowWillUpdateShadow: "mac:WindowWillUpdateShadow", - WindowWillUpdateTitle: "mac:WindowWillUpdateTitle", - WindowWillUpdateToolbar: "mac:WindowWillUpdateToolbar", - WindowWillUpdateVisibility: "mac:WindowWillUpdateVisibility", - WindowWillUseStandardFrame: "mac:WindowWillUseStandardFrame", - WindowZoomIn: "mac:WindowZoomIn", - WindowZoomOut: "mac:WindowZoomOut", - WindowZoomReset: "mac:WindowZoomReset" - }), - Linux: Object.freeze({ - ApplicationStartup: "linux:ApplicationStartup", - SystemThemeChanged: "linux:SystemThemeChanged", - WindowDeleteEvent: "linux:WindowDeleteEvent", - WindowDidMove: "linux:WindowDidMove", - WindowDidResize: "linux:WindowDidResize", - WindowFocusIn: "linux:WindowFocusIn", - WindowFocusOut: "linux:WindowFocusOut", - WindowLoadStarted: "linux:WindowLoadStarted", - WindowLoadRedirected: "linux:WindowLoadRedirected", - WindowLoadCommitted: "linux:WindowLoadCommitted", - WindowLoadFinished: "linux:WindowLoadFinished" - }), - iOS: Object.freeze({ - ApplicationDidBecomeActive: "ios:ApplicationDidBecomeActive", - ApplicationDidEnterBackground: "ios:ApplicationDidEnterBackground", - ApplicationDidFinishLaunching: "ios:ApplicationDidFinishLaunching", - ApplicationDidReceiveMemoryWarning: "ios:ApplicationDidReceiveMemoryWarning", - ApplicationWillEnterForeground: "ios:ApplicationWillEnterForeground", - ApplicationWillResignActive: "ios:ApplicationWillResignActive", - ApplicationWillTerminate: "ios:ApplicationWillTerminate", - WindowDidLoad: "ios:WindowDidLoad", - WindowWillAppear: "ios:WindowWillAppear", - WindowDidAppear: "ios:WindowDidAppear", - WindowWillDisappear: "ios:WindowWillDisappear", - WindowDidDisappear: "ios:WindowDidDisappear", - WindowSafeAreaInsetsChanged: "ios:WindowSafeAreaInsetsChanged", - WindowOrientationChanged: "ios:WindowOrientationChanged", - WindowTouchBegan: "ios:WindowTouchBegan", - WindowTouchMoved: "ios:WindowTouchMoved", - WindowTouchEnded: "ios:WindowTouchEnded", - WindowTouchCancelled: "ios:WindowTouchCancelled", - WebViewDidStartNavigation: "ios:WebViewDidStartNavigation", - WebViewDidFinishNavigation: "ios:WebViewDidFinishNavigation", - WebViewDidFailNavigation: "ios:WebViewDidFailNavigation", - WebViewDecidePolicyForNavigationAction: "ios:WebViewDecidePolicyForNavigationAction" - }), - Common: Object.freeze({ - ApplicationOpenedWithFile: "common:ApplicationOpenedWithFile", - ApplicationStarted: "common:ApplicationStarted", - ApplicationLaunchedWithUrl: "common:ApplicationLaunchedWithUrl", - ThemeChanged: "common:ThemeChanged", - WindowClosing: "common:WindowClosing", - WindowDidMove: "common:WindowDidMove", - WindowDidResize: "common:WindowDidResize", - WindowDPIChanged: "common:WindowDPIChanged", - WindowFilesDropped: "common:WindowFilesDropped", - WindowFocus: "common:WindowFocus", - WindowFullscreen: "common:WindowFullscreen", - WindowHide: "common:WindowHide", - WindowLostFocus: "common:WindowLostFocus", - WindowMaximise: "common:WindowMaximise", - WindowMinimise: "common:WindowMinimise", - WindowToggleFrameless: "common:WindowToggleFrameless", - WindowRestore: "common:WindowRestore", - WindowRuntimeReady: "common:WindowRuntimeReady", - WindowShow: "common:WindowShow", - WindowUnFullscreen: "common:WindowUnFullscreen", - WindowUnMaximise: "common:WindowUnMaximise", - WindowUnMinimise: "common:WindowUnMinimise", - WindowZoom: "common:WindowZoom", - WindowZoomIn: "common:WindowZoomIn", - WindowZoomOut: "common:WindowZoomOut", - WindowZoomReset: "common:WindowZoomReset" - }) -}); - -// desktop/@wailsio/runtime/src/events.ts -window._wails = window._wails || {}; -window._wails.dispatchWailsEvent = dispatchWailsEvent; -var call3 = newRuntimeCaller(objectNames.Events); -var EmitMethod = 0; -var WailsEvent = class { - constructor(name, data) { - this.name = name; - this.data = data != null ? data : null; - } -}; -function dispatchWailsEvent(event) { - let listeners = eventListeners.get(event.name); - if (!listeners) { - return; - } - let wailsEvent = new WailsEvent( - event.name, - event.name in Events ? Events[event.name](event.data) : event.data - ); - if ("sender" in event) { - wailsEvent.sender = event.sender; - } - listeners = listeners.filter((listener) => !listener.dispatch(wailsEvent)); - if (listeners.length === 0) { - eventListeners.delete(event.name); - } else { - eventListeners.set(event.name, listeners); - } -} -function OnMultiple(eventName, callback, maxCallbacks) { - let listeners = eventListeners.get(eventName) || []; - const thisListener = new Listener(eventName, callback, maxCallbacks); - listeners.push(thisListener); - eventListeners.set(eventName, listeners); - return () => listenerOff(thisListener); -} -function On(eventName, callback) { - return OnMultiple(eventName, callback, -1); -} -function Once(eventName, callback) { - return OnMultiple(eventName, callback, 1); -} -function Off(...eventNames) { - eventNames.forEach((eventName) => eventListeners.delete(eventName)); -} -function OffAll() { - eventListeners.clear(); -} -function Emit(name, data) { - return call3(EmitMethod, new WailsEvent(name, data)); -} - -// desktop/@wailsio/runtime/src/utils.ts -function debugLog(message) { - console.log( - "%c wails3 %c " + message + " ", - "background: #aa0000; color: #fff; border-radius: 3px 0px 0px 3px; padding: 1px; font-size: 0.7rem", - "background: #009900; color: #fff; border-radius: 0px 3px 3px 0px; padding: 1px; font-size: 0.7rem" - ); -} -function canTrackButtons() { - return new MouseEvent("mousedown").buttons === 0; -} -function canAbortListeners() { - if (!EventTarget || !AbortSignal || !AbortController) - return false; - let result = true; - const target = new EventTarget(); - const controller = new AbortController(); - target.addEventListener("test", () => { - result = false; - }, { signal: controller.signal }); - controller.abort(); - target.dispatchEvent(new CustomEvent("test")); - return result; -} -function eventTarget(event) { - var _a2; - if (event.target instanceof HTMLElement) { - return event.target; - } else if (!(event.target instanceof HTMLElement) && event.target instanceof Node) { - return (_a2 = event.target.parentElement) != null ? _a2 : document.body; - } else { - return document.body; - } -} -var isReady = false; -document.addEventListener("DOMContentLoaded", () => { - isReady = true; -}); -function whenReady(callback) { - if (isReady || document.readyState === "complete") { - callback(); - } else { - document.addEventListener("DOMContentLoaded", callback); - } -} - -// desktop/@wailsio/runtime/src/window.ts -var DROP_TARGET_ATTRIBUTE = "data-file-drop-target"; -var DROP_TARGET_ACTIVE_CLASS = "file-drop-target-active"; -var currentDropTarget = null; -var PositionMethod = 0; -var CenterMethod = 1; -var CloseMethod = 2; -var DisableSizeConstraintsMethod = 3; -var EnableSizeConstraintsMethod = 4; -var FocusMethod = 5; -var ForceReloadMethod = 6; -var FullscreenMethod = 7; -var GetScreenMethod = 8; -var GetZoomMethod = 9; -var HeightMethod = 10; -var HideMethod = 11; -var IsFocusedMethod = 12; -var IsFullscreenMethod = 13; -var IsMaximisedMethod = 14; -var IsMinimisedMethod = 15; -var MaximiseMethod = 16; -var MinimiseMethod = 17; -var NameMethod = 18; -var OpenDevToolsMethod = 19; -var RelativePositionMethod = 20; -var ReloadMethod = 21; -var ResizableMethod = 22; -var RestoreMethod = 23; -var SetPositionMethod = 24; -var SetAlwaysOnTopMethod = 25; -var SetBackgroundColourMethod = 26; -var SetFramelessMethod = 27; -var SetFullscreenButtonEnabledMethod = 28; -var SetMaxSizeMethod = 29; -var SetMinSizeMethod = 30; -var SetRelativePositionMethod = 31; -var SetResizableMethod = 32; -var SetSizeMethod = 33; -var SetTitleMethod = 34; -var SetZoomMethod = 35; -var ShowMethod = 36; -var SizeMethod = 37; -var ToggleFullscreenMethod = 38; -var ToggleMaximiseMethod = 39; -var ToggleFramelessMethod = 40; -var UnFullscreenMethod = 41; -var UnMaximiseMethod = 42; -var UnMinimiseMethod = 43; -var WidthMethod = 44; -var ZoomMethod = 45; -var ZoomInMethod = 46; -var ZoomOutMethod = 47; -var ZoomResetMethod = 48; -var SnapAssistMethod = 49; -var FilesDropped = 50; -var PrintMethod = 51; -function getDropTargetElement(element) { - if (!element) { - return null; - } - return element.closest("[".concat(DROP_TARGET_ATTRIBUTE, "]")); -} -function canResolveFilePaths() { - var _a2, _b, _c, _d; - if (((_b = (_a2 = window.chrome) == null ? void 0 : _a2.webview) == null ? void 0 : _b.postMessageWithAdditionalObjects) == null) { - return false; - } - return ((_d = (_c = window._wails) == null ? void 0 : _c.flags) == null ? void 0 : _d.enableFileDrop) === true; -} -function resolveFilePaths(x, y, files) { - var _a2, _b; - if ((_b = (_a2 = window.chrome) == null ? void 0 : _a2.webview) == null ? void 0 : _b.postMessageWithAdditionalObjects) { - window.chrome.webview.postMessageWithAdditionalObjects("file:drop:".concat(x, ":").concat(y), files); - } -} -var nativeDragActive = false; -function cleanupNativeDrag() { - nativeDragActive = false; - if (currentDropTarget) { - currentDropTarget.classList.remove(DROP_TARGET_ACTIVE_CLASS); - currentDropTarget = null; - } -} -function handleDragEnter() { - var _a2, _b; - if (((_b = (_a2 = window._wails) == null ? void 0 : _a2.flags) == null ? void 0 : _b.enableFileDrop) === false) { - return; - } - nativeDragActive = true; -} -function handleDragLeave() { - cleanupNativeDrag(); -} -function handleDragOver(x, y) { - var _a2, _b; - if (!nativeDragActive) return; - if (((_b = (_a2 = window._wails) == null ? void 0 : _a2.flags) == null ? void 0 : _b.enableFileDrop) === false) { - return; - } - const targetElement = document.elementFromPoint(x, y); - const dropTarget = getDropTargetElement(targetElement); - if (currentDropTarget && currentDropTarget !== dropTarget) { - currentDropTarget.classList.remove(DROP_TARGET_ACTIVE_CLASS); - } - if (dropTarget) { - dropTarget.classList.add(DROP_TARGET_ACTIVE_CLASS); - currentDropTarget = dropTarget; - } else { - currentDropTarget = null; - } -} -var callerSym = /* @__PURE__ */ Symbol("caller"); -callerSym; -var _Window = class _Window { - /** - * Initialises a window object with the specified name. - * - * @private - * @param name - The name of the target window. - */ - constructor(name = "") { - this[callerSym] = newRuntimeCaller(objectNames.Window, name); - for (const method of Object.getOwnPropertyNames(_Window.prototype)) { - if (method !== "constructor" && typeof this[method] === "function") { - this[method] = this[method].bind(this); - } - } - } - /** - * Gets the specified window. - * - * @param name - The name of the window to get. - * @returns The corresponding window object. - */ - Get(name) { - return new _Window(name); - } - /** - * Returns the absolute position of the window. - * - * @returns The current absolute position of the window. - */ - Position() { - return this[callerSym](PositionMethod); - } - /** - * Centers the window on the screen. - */ - Center() { - return this[callerSym](CenterMethod); - } - /** - * Closes the window. - */ - Close() { - return this[callerSym](CloseMethod); - } - /** - * Disables min/max size constraints. - */ - DisableSizeConstraints() { - return this[callerSym](DisableSizeConstraintsMethod); - } - /** - * Enables min/max size constraints. - */ - EnableSizeConstraints() { - return this[callerSym](EnableSizeConstraintsMethod); - } - /** - * Focuses the window. - */ - Focus() { - return this[callerSym](FocusMethod); - } - /** - * Forces the window to reload the page assets. - */ - ForceReload() { - return this[callerSym](ForceReloadMethod); - } - /** - * Switches the window to fullscreen mode. - */ - Fullscreen() { - return this[callerSym](FullscreenMethod); - } - /** - * Returns the screen that the window is on. - * - * @returns The screen the window is currently on. - */ - GetScreen() { - return this[callerSym](GetScreenMethod); - } - /** - * Returns the current zoom level of the window. - * - * @returns The current zoom level. - */ - GetZoom() { - return this[callerSym](GetZoomMethod); - } - /** - * Returns the height of the window. - * - * @returns The current height of the window. - */ - Height() { - return this[callerSym](HeightMethod); - } - /** - * Hides the window. - */ - Hide() { - return this[callerSym](HideMethod); - } - /** - * Returns true if the window is focused. - * - * @returns Whether the window is currently focused. - */ - IsFocused() { - return this[callerSym](IsFocusedMethod); - } - /** - * Returns true if the window is fullscreen. - * - * @returns Whether the window is currently fullscreen. - */ - IsFullscreen() { - return this[callerSym](IsFullscreenMethod); - } - /** - * Returns true if the window is maximised. - * - * @returns Whether the window is currently maximised. - */ - IsMaximised() { - return this[callerSym](IsMaximisedMethod); - } - /** - * Returns true if the window is minimised. - * - * @returns Whether the window is currently minimised. - */ - IsMinimised() { - return this[callerSym](IsMinimisedMethod); - } - /** - * Maximises the window. - */ - Maximise() { - return this[callerSym](MaximiseMethod); - } - /** - * Minimises the window. - */ - Minimise() { - return this[callerSym](MinimiseMethod); - } - /** - * Returns the name of the window. - * - * @returns The name of the window. - */ - Name() { - return this[callerSym](NameMethod); - } - /** - * Opens the development tools pane. - */ - OpenDevTools() { - return this[callerSym](OpenDevToolsMethod); - } - /** - * Returns the relative position of the window to the screen. - * - * @returns The current relative position of the window. - */ - RelativePosition() { - return this[callerSym](RelativePositionMethod); - } - /** - * Reloads the page assets. - */ - Reload() { - return this[callerSym](ReloadMethod); - } - /** - * Returns true if the window is resizable. - * - * @returns Whether the window is currently resizable. - */ - Resizable() { - return this[callerSym](ResizableMethod); - } - /** - * Restores the window to its previous state if it was previously minimised, maximised or fullscreen. - */ - Restore() { - return this[callerSym](RestoreMethod); - } - /** - * Sets the absolute position of the window. - * - * @param x - The desired horizontal absolute position of the window. - * @param y - The desired vertical absolute position of the window. - */ - SetPosition(x, y) { - return this[callerSym](SetPositionMethod, { x, y }); - } - /** - * Sets the window to be always on top. - * - * @param alwaysOnTop - Whether the window should stay on top. - */ - SetAlwaysOnTop(alwaysOnTop) { - return this[callerSym](SetAlwaysOnTopMethod, { alwaysOnTop }); - } - /** - * Sets the background colour of the window. - * - * @param r - The desired red component of the window background. - * @param g - The desired green component of the window background. - * @param b - The desired blue component of the window background. - * @param a - The desired alpha component of the window background. - */ - SetBackgroundColour(r, g, b, a) { - return this[callerSym](SetBackgroundColourMethod, { r, g, b, a }); - } - /** - * Removes the window frame and title bar. - * - * @param frameless - Whether the window should be frameless. - */ - SetFrameless(frameless) { - return this[callerSym](SetFramelessMethod, { frameless }); - } - /** - * Disables the system fullscreen button. - * - * @param enabled - Whether the fullscreen button should be enabled. - */ - SetFullscreenButtonEnabled(enabled) { - return this[callerSym](SetFullscreenButtonEnabledMethod, { enabled }); - } - /** - * Sets the maximum size of the window. - * - * @param width - The desired maximum width of the window. - * @param height - The desired maximum height of the window. - */ - SetMaxSize(width, height) { - return this[callerSym](SetMaxSizeMethod, { width, height }); - } - /** - * Sets the minimum size of the window. - * - * @param width - The desired minimum width of the window. - * @param height - The desired minimum height of the window. - */ - SetMinSize(width, height) { - return this[callerSym](SetMinSizeMethod, { width, height }); - } - /** - * Sets the relative position of the window to the screen. - * - * @param x - The desired horizontal relative position of the window. - * @param y - The desired vertical relative position of the window. - */ - SetRelativePosition(x, y) { - return this[callerSym](SetRelativePositionMethod, { x, y }); - } - /** - * Sets whether the window is resizable. - * - * @param resizable - Whether the window should be resizable. - */ - SetResizable(resizable2) { - return this[callerSym](SetResizableMethod, { resizable: resizable2 }); - } - /** - * Sets the size of the window. - * - * @param width - The desired width of the window. - * @param height - The desired height of the window. - */ - SetSize(width, height) { - return this[callerSym](SetSizeMethod, { width, height }); - } - /** - * Sets the title of the window. - * - * @param title - The desired title of the window. - */ - SetTitle(title) { - return this[callerSym](SetTitleMethod, { title }); - } - /** - * Sets the zoom level of the window. - * - * @param zoom - The desired zoom level. - */ - SetZoom(zoom) { - return this[callerSym](SetZoomMethod, { zoom }); - } - /** - * Shows the window. - */ - Show() { - return this[callerSym](ShowMethod); - } - /** - * Returns the size of the window. - * - * @returns The current size of the window. - */ - Size() { - return this[callerSym](SizeMethod); - } - /** - * Toggles the window between fullscreen and normal. - */ - ToggleFullscreen() { - return this[callerSym](ToggleFullscreenMethod); - } - /** - * Toggles the window between maximised and normal. - */ - ToggleMaximise() { - return this[callerSym](ToggleMaximiseMethod); - } - /** - * Toggles the window between frameless and normal. - */ - ToggleFrameless() { - return this[callerSym](ToggleFramelessMethod); - } - /** - * Un-fullscreens the window. - */ - UnFullscreen() { - return this[callerSym](UnFullscreenMethod); - } - /** - * Un-maximises the window. - */ - UnMaximise() { - return this[callerSym](UnMaximiseMethod); - } - /** - * Un-minimises the window. - */ - UnMinimise() { - return this[callerSym](UnMinimiseMethod); - } - /** - * Returns the width of the window. - * - * @returns The current width of the window. - */ - Width() { - return this[callerSym](WidthMethod); - } - /** - * Zooms the window. - */ - Zoom() { - return this[callerSym](ZoomMethod); - } - /** - * Increases the zoom level of the webview content. - */ - ZoomIn() { - return this[callerSym](ZoomInMethod); - } - /** - * Decreases the zoom level of the webview content. - */ - ZoomOut() { - return this[callerSym](ZoomOutMethod); - } - /** - * Resets the zoom level of the webview content. - */ - ZoomReset() { - return this[callerSym](ZoomResetMethod); - } - /** - * Handles file drops originating from platform-specific code (e.g., macOS/Linux native drag-and-drop). - * Gathers information about the drop target element and sends it back to the Go backend. - * - * @param filenames - An array of file paths (strings) that were dropped. - * @param x - The x-coordinate of the drop event (CSS pixels). - * @param y - The y-coordinate of the drop event (CSS pixels). - */ - HandlePlatformFileDrop(filenames, x, y) { - var _a2, _b; - if (((_b = (_a2 = window._wails) == null ? void 0 : _a2.flags) == null ? void 0 : _b.enableFileDrop) === false) { - return; - } - const element = document.elementFromPoint(x, y); - const dropTarget = getDropTargetElement(element); - if (!dropTarget) { - return; - } - const elementDetails = { - id: dropTarget.id, - classList: Array.from(dropTarget.classList), - attributes: {} - }; - for (let i = 0; i < dropTarget.attributes.length; i++) { - const attr = dropTarget.attributes[i]; - elementDetails.attributes[attr.name] = attr.value; - } - const payload = { - filenames, - x, - y, - elementDetails - }; - this[callerSym](FilesDropped, payload); - cleanupNativeDrag(); - } - /* Triggers Windows 11 Snap Assist feature (Windows only). - * This is equivalent to pressing Win+Z and shows snap layout options. - */ - SnapAssist() { - return this[callerSym](SnapAssistMethod); - } - /** - * Opens the print dialog for the window. - */ - Print() { - return this[callerSym](PrintMethod); - } -}; -var Window = _Window; -var thisWindow = new Window(""); -function setupDropTargetListeners() { - const docElement = document.documentElement; - let dragEnterCounter = 0; - docElement.addEventListener("dragenter", (event) => { - var _a2, _b, _c; - if (!((_a2 = event.dataTransfer) == null ? void 0 : _a2.types.includes("Files"))) { - return; - } - event.preventDefault(); - if (((_c = (_b = window._wails) == null ? void 0 : _b.flags) == null ? void 0 : _c.enableFileDrop) === false) { - event.dataTransfer.dropEffect = "none"; - return; - } - dragEnterCounter++; - const targetElement = document.elementFromPoint(event.clientX, event.clientY); - const dropTarget = getDropTargetElement(targetElement); - if (currentDropTarget && currentDropTarget !== dropTarget) { - currentDropTarget.classList.remove(DROP_TARGET_ACTIVE_CLASS); - } - if (dropTarget) { - dropTarget.classList.add(DROP_TARGET_ACTIVE_CLASS); - event.dataTransfer.dropEffect = "copy"; - currentDropTarget = dropTarget; - } else { - event.dataTransfer.dropEffect = "none"; - currentDropTarget = null; - } - }, false); - docElement.addEventListener("dragover", (event) => { - var _a2, _b, _c; - if (!((_a2 = event.dataTransfer) == null ? void 0 : _a2.types.includes("Files"))) { - return; - } - event.preventDefault(); - if (((_c = (_b = window._wails) == null ? void 0 : _b.flags) == null ? void 0 : _c.enableFileDrop) === false) { - event.dataTransfer.dropEffect = "none"; - return; - } - const targetElement = document.elementFromPoint(event.clientX, event.clientY); - const dropTarget = getDropTargetElement(targetElement); - if (currentDropTarget && currentDropTarget !== dropTarget) { - currentDropTarget.classList.remove(DROP_TARGET_ACTIVE_CLASS); - } - if (dropTarget) { - if (!dropTarget.classList.contains(DROP_TARGET_ACTIVE_CLASS)) { - dropTarget.classList.add(DROP_TARGET_ACTIVE_CLASS); - } - event.dataTransfer.dropEffect = "copy"; - currentDropTarget = dropTarget; - } else { - event.dataTransfer.dropEffect = "none"; - currentDropTarget = null; - } - }, false); - docElement.addEventListener("dragleave", (event) => { - var _a2, _b, _c; - if (!((_a2 = event.dataTransfer) == null ? void 0 : _a2.types.includes("Files"))) { - return; - } - event.preventDefault(); - if (((_c = (_b = window._wails) == null ? void 0 : _b.flags) == null ? void 0 : _c.enableFileDrop) === false) { - return; - } - if (event.relatedTarget === null) { - return; - } - dragEnterCounter--; - if (dragEnterCounter === 0 || currentDropTarget && !currentDropTarget.contains(event.relatedTarget)) { - if (currentDropTarget) { - currentDropTarget.classList.remove(DROP_TARGET_ACTIVE_CLASS); - currentDropTarget = null; - } - dragEnterCounter = 0; - } - }, false); - docElement.addEventListener("drop", (event) => { - var _a2, _b, _c; - if (!((_a2 = event.dataTransfer) == null ? void 0 : _a2.types.includes("Files"))) { - return; - } - event.preventDefault(); - if (((_c = (_b = window._wails) == null ? void 0 : _b.flags) == null ? void 0 : _c.enableFileDrop) === false) { - return; - } - dragEnterCounter = 0; - if (currentDropTarget) { - currentDropTarget.classList.remove(DROP_TARGET_ACTIVE_CLASS); - currentDropTarget = null; - } - if (canResolveFilePaths()) { - const files = []; - if (event.dataTransfer.items) { - for (const item of event.dataTransfer.items) { - if (item.kind === "file") { - const file = item.getAsFile(); - if (file) files.push(file); - } - } - } else if (event.dataTransfer.files) { - for (const file of event.dataTransfer.files) { - files.push(file); - } - } - if (files.length > 0) { - resolveFilePaths(event.clientX, event.clientY, files); - } - } - }, false); -} -if (typeof window !== "undefined" && typeof document !== "undefined") { - setupDropTargetListeners(); -} -var window_default = thisWindow; - -// desktop/@wailsio/runtime/src/wml.ts -function sendEvent(eventName, data = null) { - Emit(eventName, data); -} -function callWindowMethod(windowName, methodName) { - const targetWindow = window_default.Get(windowName); - const method = targetWindow[methodName]; - if (typeof method !== "function") { - console.error("Window method '".concat(methodName, "' not found")); - return; - } - try { - method.call(targetWindow); - } catch (e) { - console.error("Error calling window method '".concat(methodName, "': "), e); - } -} -function onWMLTriggered(ev) { - const element = ev.currentTarget; - function runEffect(choice = "Yes") { - if (choice !== "Yes") - return; - const eventType = element.getAttribute("wml-event") || element.getAttribute("data-wml-event"); - const targetWindow = element.getAttribute("wml-target-window") || element.getAttribute("data-wml-target-window") || ""; - const windowMethod = element.getAttribute("wml-window") || element.getAttribute("data-wml-window"); - const url = element.getAttribute("wml-openurl") || element.getAttribute("data-wml-openurl"); - if (eventType !== null) - sendEvent(eventType); - if (windowMethod !== null) - callWindowMethod(targetWindow, windowMethod); - if (url !== null) - void OpenURL(url); - } - const confirm = element.getAttribute("wml-confirm") || element.getAttribute("data-wml-confirm"); - if (confirm) { - Question({ - Title: "Confirm", - Message: confirm, - Detached: false, - Buttons: [ - { Label: "Yes" }, - { Label: "No", IsDefault: true } - ] - }).then(runEffect); - } else { - runEffect(); - } -} -var controllerSym = /* @__PURE__ */ Symbol("controller"); -var triggerMapSym = /* @__PURE__ */ Symbol("triggerMap"); -var elementCountSym = /* @__PURE__ */ Symbol("elementCount"); -controllerSym; -var AbortControllerRegistry = class { - constructor() { - this[controllerSym] = new AbortController(); - } - /** - * Returns an options object for addEventListener that ties the listener - * to the AbortSignal from the current AbortController. - * - * @param element - An HTML element - * @param triggers - The list of active WML trigger events for the specified elements - */ - set(element, triggers) { - return { signal: this[controllerSym].signal }; - } - /** - * Removes all registered event listeners and resets the registry. - */ - reset() { - this[controllerSym].abort(); - this[controllerSym] = new AbortController(); - } -}; -triggerMapSym, elementCountSym; -var WeakMapRegistry = class { - constructor() { - this[triggerMapSym] = /* @__PURE__ */ new WeakMap(); - this[elementCountSym] = 0; - } - /** - * Sets active triggers for the specified element. - * - * @param element - An HTML element - * @param triggers - The list of active WML trigger events for the specified element - */ - set(element, triggers) { - if (!this[triggerMapSym].has(element)) { - this[elementCountSym]++; - } - this[triggerMapSym].set(element, triggers); - return {}; - } - /** - * Removes all registered event listeners. - */ - reset() { - if (this[elementCountSym] <= 0) - return; - for (const element of document.body.querySelectorAll("*")) { - if (this[elementCountSym] <= 0) - break; - const triggers = this[triggerMapSym].get(element); - if (triggers != null) { - this[elementCountSym]--; - } - for (const trigger of triggers || []) - element.removeEventListener(trigger, onWMLTriggered); - } - this[triggerMapSym] = /* @__PURE__ */ new WeakMap(); - this[elementCountSym] = 0; - } -}; -var triggerRegistry = canAbortListeners() ? new AbortControllerRegistry() : new WeakMapRegistry(); -function addWMLListeners(element) { - const triggerRegExp = /\S+/g; - const triggerAttr = element.getAttribute("wml-trigger") || element.getAttribute("data-wml-trigger") || "click"; - const triggers = []; - let match; - while ((match = triggerRegExp.exec(triggerAttr)) !== null) - triggers.push(match[0]); - const options = triggerRegistry.set(element, triggers); - for (const trigger of triggers) - element.addEventListener(trigger, onWMLTriggered, options); -} -function Enable() { - whenReady(Reload); -} -function Reload() { - triggerRegistry.reset(); - document.body.querySelectorAll("[wml-event], [wml-window], [wml-openurl], [data-wml-event], [data-wml-window], [data-wml-openurl]").forEach(addWMLListeners); -} - -// desktop/compiled/main.js -window.wails = index_exports; -Enable(); -if (true) { - debugLog("Wails Runtime Loaded"); -} - -// desktop/@wailsio/runtime/src/system.ts -var system_exports = {}; -__export(system_exports, { - Capabilities: () => Capabilities, - Environment: () => Environment, - IsAMD64: () => IsAMD64, - IsARM: () => IsARM, - IsARM64: () => IsARM64, - IsDarkMode: () => IsDarkMode, - IsDebug: () => IsDebug, - IsLinux: () => IsLinux, - IsMac: () => IsMac, - IsWindows: () => IsWindows, - invoke: () => invoke -}); -var call4 = newRuntimeCaller(objectNames.System); -var SystemIsDarkMode = 0; -var SystemEnvironment = 1; -var SystemCapabilities = 2; -var _invoke = (function() { - var _a2, _b, _c, _d, _e, _f; - try { - if ((_b = (_a2 = window.chrome) == null ? void 0 : _a2.webview) == null ? void 0 : _b.postMessage) { - return window.chrome.webview.postMessage.bind(window.chrome.webview); - } else if ((_e = (_d = (_c = window.webkit) == null ? void 0 : _c.messageHandlers) == null ? void 0 : _d["external"]) == null ? void 0 : _e.postMessage) { - return window.webkit.messageHandlers["external"].postMessage.bind(window.webkit.messageHandlers["external"]); - } else if ((_f = window.wails) == null ? void 0 : _f.invoke) { - return (msg) => window.wails.invoke(typeof msg === "string" ? msg : JSON.stringify(msg)); - } - } catch (e) { - } - console.warn( - "\n%c\u26A0\uFE0F Browser Environment Detected %c\n\n%cOnly UI previews are available in the browser. For full functionality, please run the application in desktop mode.\nMore information at: https://v3.wails.io/learn/build/#using-a-browser-for-development\n", - "background: #ffffff; color: #000000; font-weight: bold; padding: 4px 8px; border-radius: 4px; border: 2px solid #000000;", - "background: transparent;", - "color: #ffffff; font-style: italic; font-weight: bold;" - ); - return null; -})(); -function invoke(msg) { - _invoke == null ? void 0 : _invoke(msg); -} -function IsDarkMode() { - return call4(SystemIsDarkMode); -} -async function Capabilities() { - return call4(SystemCapabilities); -} -function Environment() { - return call4(SystemEnvironment); -} -function IsWindows() { - var _a2, _b; - return ((_b = (_a2 = window._wails) == null ? void 0 : _a2.environment) == null ? void 0 : _b.OS) === "windows"; -} -function IsLinux() { - var _a2, _b; - return ((_b = (_a2 = window._wails) == null ? void 0 : _a2.environment) == null ? void 0 : _b.OS) === "linux"; -} -function IsMac() { - var _a2, _b; - return ((_b = (_a2 = window._wails) == null ? void 0 : _a2.environment) == null ? void 0 : _b.OS) === "darwin"; -} -function IsAMD64() { - var _a2, _b; - return ((_b = (_a2 = window._wails) == null ? void 0 : _a2.environment) == null ? void 0 : _b.Arch) === "amd64"; -} -function IsARM() { - var _a2, _b; - return ((_b = (_a2 = window._wails) == null ? void 0 : _a2.environment) == null ? void 0 : _b.Arch) === "arm"; -} -function IsARM64() { - var _a2, _b; - return ((_b = (_a2 = window._wails) == null ? void 0 : _a2.environment) == null ? void 0 : _b.Arch) === "arm64"; -} -function IsDebug() { - var _a2, _b; - return Boolean((_b = (_a2 = window._wails) == null ? void 0 : _a2.environment) == null ? void 0 : _b.Debug); -} - -// desktop/@wailsio/runtime/src/contextmenu.ts -window.addEventListener("contextmenu", contextMenuHandler); -var call5 = newRuntimeCaller(objectNames.ContextMenu); -var ContextMenuOpen = 0; -function openContextMenu(id, x, y, data) { - void call5(ContextMenuOpen, { id, x, y, data }); -} -function contextMenuHandler(event) { - const target = eventTarget(event); - const customContextMenu = window.getComputedStyle(target).getPropertyValue("--custom-contextmenu").trim(); - if (customContextMenu) { - event.preventDefault(); - const data = window.getComputedStyle(target).getPropertyValue("--custom-contextmenu-data"); - openContextMenu(customContextMenu, event.clientX, event.clientY, data); - } else { - processDefaultContextMenu(event, target); - } -} -function processDefaultContextMenu(event, target) { - if (IsDebug()) { - return; - } - switch (window.getComputedStyle(target).getPropertyValue("--default-contextmenu").trim()) { - case "show": - return; - case "hide": - event.preventDefault(); - return; - } - if (target.isContentEditable) { - return; - } - const selection = window.getSelection(); - const hasSelection = selection && selection.toString().length > 0; - if (hasSelection) { - for (let i = 0; i < selection.rangeCount; i++) { - const range = selection.getRangeAt(i); - const rects = range.getClientRects(); - for (let j = 0; j < rects.length; j++) { - const rect = rects[j]; - if (document.elementFromPoint(rect.left, rect.top) === target) { - return; - } - } - } - } - if (target instanceof HTMLInputElement || target instanceof HTMLTextAreaElement) { - if (hasSelection || !target.readOnly && !target.disabled) { - return; - } - } - event.preventDefault(); -} - -// desktop/@wailsio/runtime/src/flags.ts -var flags_exports = {}; -__export(flags_exports, { - GetFlag: () => GetFlag -}); -function GetFlag(key) { - try { - return window._wails.flags[key]; - } catch (e) { - throw new Error("Unable to retrieve flag '" + key + "': " + e, { cause: e }); - } -} - -// desktop/@wailsio/runtime/src/drag.ts -var canDrag = false; -var dragging = false; -var resizable = false; -var canResize = false; -var resizing = false; -var resizeEdge = ""; -var defaultCursor = "auto"; -var buttons = 0; -var buttonsTracked = canTrackButtons(); -window._wails = window._wails || {}; -window._wails.setResizable = (value) => { - resizable = value; - if (!resizable) { - canResize = resizing = false; - setResize(); - } -}; -var dragInitDone = false; -function isMobile() { - var _a2, _b; - const os = (_b = (_a2 = window._wails) == null ? void 0 : _a2.environment) == null ? void 0 : _b.OS; - if (os === "ios" || os === "android") return true; - const ua = navigator.userAgent || navigator.vendor || window.opera || ""; - return /android|iphone|ipad|ipod|iemobile|wpdesktop/i.test(ua); -} -function tryInitDragHandlers() { - if (dragInitDone) return; - if (isMobile()) return; - window.addEventListener("mousedown", update, { capture: true }); - window.addEventListener("mousemove", update, { capture: true }); - window.addEventListener("mouseup", update, { capture: true }); - for (const ev of ["click", "contextmenu", "dblclick"]) { - window.addEventListener(ev, suppressEvent, { capture: true }); - } - dragInitDone = true; -} -tryInitDragHandlers(); -document.addEventListener("DOMContentLoaded", tryInitDragHandlers, { once: true }); -var dragEnvPolls = 0; -var dragEnvPoll = window.setInterval(() => { - if (dragInitDone) { - window.clearInterval(dragEnvPoll); - return; - } - tryInitDragHandlers(); - if (++dragEnvPolls > 100) { - window.clearInterval(dragEnvPoll); - } -}, 50); -function suppressEvent(event) { - if (dragging || resizing) { - event.stopImmediatePropagation(); - event.stopPropagation(); - event.preventDefault(); - } -} -var MouseDown = 0; -var MouseUp = 1; -var MouseMove = 2; -function update(event) { - let eventType, eventButtons = event.buttons; - switch (event.type) { - case "mousedown": - eventType = MouseDown; - if (!buttonsTracked) { - eventButtons = buttons | 1 << event.button; - } - break; - case "mouseup": - eventType = MouseUp; - if (!buttonsTracked) { - eventButtons = buttons & ~(1 << event.button); - } - break; - default: - eventType = MouseMove; - if (!buttonsTracked) { - eventButtons = buttons; - } - break; - } - let released = buttons & ~eventButtons; - let pressed = eventButtons & ~buttons; - buttons = eventButtons; - if (eventType === MouseDown && !(pressed & event.button)) { - released |= 1 << event.button; - pressed |= 1 << event.button; - } - if (eventType !== MouseMove && resizing || dragging && (eventType === MouseDown || event.button !== 0)) { - event.stopImmediatePropagation(); - event.stopPropagation(); - event.preventDefault(); - } - if (released & 1) { - primaryUp(event); - } - if (pressed & 1) { - primaryDown(event); - } - if (eventType === MouseMove) { - onMouseMove(event); - } - ; -} -function primaryDown(event) { - canDrag = false; - canResize = false; - if (!IsWindows()) { - if (event.type === "mousedown" && event.button === 0 && event.detail !== 1) { - return; - } - } - if (resizeEdge) { - canResize = true; - return; - } - const target = eventTarget(event); - const style = window.getComputedStyle(target); - canDrag = style.getPropertyValue("--wails-draggable").trim() === "drag" && (event.offsetX - parseFloat(style.paddingLeft) < target.clientWidth && event.offsetY - parseFloat(style.paddingTop) < target.clientHeight); -} -function primaryUp(event) { - canDrag = false; - dragging = false; - canResize = false; - resizing = false; -} -var cursorForEdge = Object.freeze({ - "se-resize": "nwse-resize", - "sw-resize": "nesw-resize", - "nw-resize": "nwse-resize", - "ne-resize": "nesw-resize", - "w-resize": "ew-resize", - "n-resize": "ns-resize", - "s-resize": "ns-resize", - "e-resize": "ew-resize" -}); -function setResize(edge) { - if (edge) { - if (!resizeEdge) { - defaultCursor = document.body.style.cursor; - } - document.body.style.cursor = cursorForEdge[edge]; - } else if (!edge && resizeEdge) { - document.body.style.cursor = defaultCursor; - } - resizeEdge = edge || ""; -} -function onMouseMove(event) { - if (canResize && resizeEdge) { - resizing = true; - invoke("wails:resize:" + resizeEdge); - } else if (canDrag) { - dragging = true; - invoke("wails:drag"); - } - if (dragging || resizing) { - canDrag = canResize = false; - return; - } - if (!resizable || !IsWindows()) { - if (resizeEdge) { - setResize(); - } - return; - } - const resizeHandleHeight = GetFlag("system.resizeHandleHeight") || 5; - const resizeHandleWidth = GetFlag("system.resizeHandleWidth") || 5; - const cornerExtra = GetFlag("resizeCornerExtra") || 10; - const rightBorder = window.outerWidth - event.clientX < resizeHandleWidth; - const leftBorder = event.clientX < resizeHandleWidth; - const topBorder = event.clientY < resizeHandleHeight; - const bottomBorder = window.outerHeight - event.clientY < resizeHandleHeight; - const rightCorner = window.outerWidth - event.clientX < resizeHandleWidth + cornerExtra; - const leftCorner = event.clientX < resizeHandleWidth + cornerExtra; - const topCorner = event.clientY < resizeHandleHeight + cornerExtra; - const bottomCorner = window.outerHeight - event.clientY < resizeHandleHeight + cornerExtra; - if (!leftCorner && !topCorner && !bottomCorner && !rightCorner) { - setResize(); - } else if (rightCorner && bottomCorner) setResize("se-resize"); - else if (leftCorner && bottomCorner) setResize("sw-resize"); - else if (leftCorner && topCorner) setResize("nw-resize"); - else if (topCorner && rightCorner) setResize("ne-resize"); - else if (leftBorder) setResize("w-resize"); - else if (topBorder) setResize("n-resize"); - else if (bottomBorder) setResize("s-resize"); - else if (rightBorder) setResize("e-resize"); - else setResize(); -} - -// desktop/@wailsio/runtime/src/application.ts -var application_exports = {}; -__export(application_exports, { - Hide: () => Hide, - Quit: () => Quit, - Show: () => Show -}); -var call6 = newRuntimeCaller(objectNames.Application); -var HideMethod2 = 0; -var ShowMethod2 = 1; -var QuitMethod = 2; -function Hide() { - return call6(HideMethod2); -} -function Show() { - return call6(ShowMethod2); -} -function Quit() { - return call6(QuitMethod); -} - -// desktop/@wailsio/runtime/src/calls.ts -var calls_exports = {}; -__export(calls_exports, { - ByID: () => ByID, - ByName: () => ByName, - Call: () => Call, - RuntimeError: () => RuntimeError -}); - -// desktop/@wailsio/runtime/src/callable.ts -var fnToStr = Function.prototype.toString; -var reflectApply = typeof Reflect === "object" && Reflect !== null && Reflect.apply; -var badArrayLike; -var isCallableMarker; -if (typeof reflectApply === "function" && typeof Object.defineProperty === "function") { - try { - badArrayLike = Object.defineProperty({}, "length", { - get: function() { - throw isCallableMarker; - } - }); - isCallableMarker = {}; - reflectApply(function() { - throw 42; - }, null, badArrayLike); - } catch (_) { - if (_ !== isCallableMarker) { - reflectApply = null; - } - } -} else { - reflectApply = null; -} -var constructorRegex = /^\s*class\b/; -var isES6ClassFn = function isES6ClassFunction(value) { - try { - var fnStr = fnToStr.call(value); - return constructorRegex.test(fnStr); - } catch (e) { - return false; - } -}; -var tryFunctionObject = function tryFunctionToStr(value) { - try { - if (isES6ClassFn(value)) { - return false; - } - fnToStr.call(value); - return true; - } catch (e) { - return false; - } -}; -var toStr = Object.prototype.toString; -var objectClass = "[object Object]"; -var fnClass = "[object Function]"; -var genClass = "[object GeneratorFunction]"; -var ddaClass = "[object HTMLAllCollection]"; -var ddaClass2 = "[object HTML document.all class]"; -var ddaClass3 = "[object HTMLCollection]"; -var hasToStringTag = typeof Symbol === "function" && !!Symbol.toStringTag; -var isIE68 = !(0 in [,]); -var isDDA = function isDocumentDotAll() { - return false; -}; -if (typeof document === "object") { - all = document.all; - if (toStr.call(all) === toStr.call(document.all)) { - isDDA = function isDocumentDotAll2(value) { - if ((isIE68 || !value) && (typeof value === "undefined" || typeof value === "object")) { - try { - var str = toStr.call(value); - return (str === ddaClass || str === ddaClass2 || str === ddaClass3 || str === objectClass) && value("") == null; - } catch (e) { - } - } - return false; - }; - } -} -var all; -function isCallableRefApply(value) { - if (isDDA(value)) { - return true; - } - if (!value) { - return false; - } - if (typeof value !== "function" && typeof value !== "object") { - return false; - } - try { - reflectApply(value, null, badArrayLike); - } catch (e) { - if (e !== isCallableMarker) { - return false; - } - } - return !isES6ClassFn(value) && tryFunctionObject(value); -} -function isCallableNoRefApply(value) { - if (isDDA(value)) { - return true; - } - if (!value) { - return false; - } - if (typeof value !== "function" && typeof value !== "object") { - return false; - } - if (hasToStringTag) { - return tryFunctionObject(value); - } - if (isES6ClassFn(value)) { - return false; - } - var strClass = toStr.call(value); - if (strClass !== fnClass && strClass !== genClass && !/^\[object HTML/.test(strClass)) { - return false; - } - return tryFunctionObject(value); -} -var callable_default = reflectApply ? isCallableRefApply : isCallableNoRefApply; - -// desktop/@wailsio/runtime/src/cancellable.ts -var CancelError = class extends Error { - /** - * Constructs a new `CancelError` instance. - * @param message - The error message. - * @param options - Options to be forwarded to the Error constructor. - */ - constructor(message, options) { - super(message, options); - this.name = "CancelError"; - } -}; -var CancelledRejectionError = class extends Error { - /** - * Constructs a new `CancelledRejectionError` instance. - * @param promise - The promise that caused the error originally. - * @param reason - The rejection reason. - * @param info - An optional informative message specifying the circumstances in which the error was thrown. - * Defaults to the string `"Unhandled rejection in cancelled promise."`. - */ - constructor(promise, reason, info) { - super((info != null ? info : "Unhandled rejection in cancelled promise.") + " Reason: " + errorMessage(reason), { cause: reason }); - this.promise = promise; - this.name = "CancelledRejectionError"; - } -}; -var barrierSym = /* @__PURE__ */ Symbol("barrier"); -var cancelImplSym = /* @__PURE__ */ Symbol("cancelImpl"); -var _a; -var species = (_a = Symbol.species) != null ? _a : /* @__PURE__ */ Symbol("speciesPolyfill"); -var CancellablePromise = class _CancellablePromise extends Promise { - /** - * Creates a new `CancellablePromise`. - * - * @param executor - A callback used to initialize the promise. This callback is passed two arguments: - * a `resolve` callback used to resolve the promise with a value - * or the result of another promise (possibly cancellable), - * and a `reject` callback used to reject the promise with a provided reason or error. - * If the value provided to the `resolve` callback is a thenable _and_ cancellable object - * (it has a `then` _and_ a `cancel` method), - * cancellation requests will be forwarded to that object and the oncancelled will not be invoked anymore. - * If any one of the two callbacks is called _after_ the promise has been cancelled, - * the provided values will be cancelled and resolved as usual, - * but their results will be discarded. - * However, if the resolution process ultimately ends up in a rejection - * that is not due to cancellation, the rejection reason - * will be wrapped in a {@link CancelledRejectionError} - * and bubbled up as an unhandled rejection. - * @param oncancelled - It is the caller's responsibility to ensure that any operation - * started by the executor is properly halted upon cancellation. - * This optional callback can be used to that purpose. - * It will be called _synchronously_ with a cancellation cause - * when cancellation is requested, _after_ the promise has already rejected - * with a {@link CancelError}, but _before_ - * any {@link then}/{@link catch}/{@link finally} callback runs. - * If the callback returns a thenable, the promise returned from {@link cancel} - * will only fulfill after the former has settled. - * Unhandled exceptions or rejections from the callback will be wrapped - * in a {@link CancelledRejectionError} and bubbled up as unhandled rejections. - * If the `resolve` callback is called before cancellation with a cancellable promise, - * cancellation requests on this promise will be diverted to that promise, - * and the original `oncancelled` callback will be discarded. - */ - constructor(executor, oncancelled) { - let resolve; - let reject; - super((res, rej) => { - resolve = res; - reject = rej; - }); - if (this.constructor[species] !== Promise) { - throw new TypeError("CancellablePromise does not support transparent subclassing. Please refrain from overriding the [Symbol.species] static property."); - } - let promise = { - promise: this, - resolve, - reject, - get oncancelled() { - return oncancelled != null ? oncancelled : null; - }, - set oncancelled(cb) { - oncancelled = cb != null ? cb : void 0; - } - }; - const state = { - get root() { - return state; - }, - resolving: false, - settled: false - }; - void Object.defineProperties(this, { - [barrierSym]: { - configurable: false, - enumerable: false, - writable: true, - value: null - }, - [cancelImplSym]: { - configurable: false, - enumerable: false, - writable: false, - value: cancellerFor(promise, state) - } - }); - const rejector = rejectorFor(promise, state); - try { - executor(resolverFor(promise, state), rejector); - } catch (err) { - if (state.resolving) { - console.log("Unhandled exception in CancellablePromise executor.", err); - } else { - rejector(err); - } - } - } - /** - * Cancels immediately the execution of the operation associated with this promise. - * The promise rejects with a {@link CancelError} instance as reason, - * with the {@link CancelError#cause} property set to the given argument, if any. - * - * Has no effect if called after the promise has already settled; - * repeated calls in particular are safe, but only the first one - * will set the cancellation cause. - * - * The `CancelError` exception _need not_ be handled explicitly _on the promises that are being cancelled:_ - * cancelling a promise with no attached rejection handler does not trigger an unhandled rejection event. - * Therefore, the following idioms are all equally correct: - * ```ts - * new CancellablePromise((resolve, reject) => { ... }).cancel(); - * new CancellablePromise((resolve, reject) => { ... }).then(...).cancel(); - * new CancellablePromise((resolve, reject) => { ... }).then(...).catch(...).cancel(); - * ``` - * Whenever some cancelled promise in a chain rejects with a `CancelError` - * with the same cancellation cause as itself, the error will be discarded silently. - * However, the `CancelError` _will still be delivered_ to all attached rejection handlers - * added by {@link then} and related methods: - * ```ts - * let cancellable = new CancellablePromise((resolve, reject) => { ... }); - * cancellable.then(() => { ... }).catch(console.log); - * cancellable.cancel(); // A CancelError is printed to the console. - * ``` - * If the `CancelError` is not handled downstream by the time it reaches - * a _non-cancelled_ promise, it _will_ trigger an unhandled rejection event, - * just like normal rejections would: - * ```ts - * let cancellable = new CancellablePromise((resolve, reject) => { ... }); - * let chained = cancellable.then(() => { ... }).then(() => { ... }); // No catch... - * cancellable.cancel(); // Unhandled rejection event on chained! - * ``` - * Therefore, it is important to either cancel whole promise chains from their tail, - * as shown in the correct idioms above, or take care of handling errors everywhere. - * - * @returns A cancellable promise that _fulfills_ after the cancel callback (if any) - * and all handlers attached up to the call to cancel have run. - * If the cancel callback returns a thenable, the promise returned by `cancel` - * will also wait for that thenable to settle. - * This enables callers to wait for the cancelled operation to terminate - * without being forced to handle potential errors at the call site. - * ```ts - * cancellable.cancel().then(() => { - * // Cleanup finished, it's safe to do something else. - * }, (err) => { - * // Unreachable: the promise returned from cancel will never reject. - * }); - * ``` - * Note that the returned promise will _not_ handle implicitly any rejection - * that might have occurred already in the cancelled chain. - * It will just track whether registered handlers have been executed or not. - * Therefore, unhandled rejections will never be silently handled by calling cancel. - */ - cancel(cause) { - return new _CancellablePromise((resolve) => { - Promise.all([ - this[cancelImplSym](new CancelError("Promise cancelled.", { cause })), - currentBarrier(this) - ]).then(() => resolve(), () => resolve()); - }); - } - /** - * Binds promise cancellation to the abort event of the given {@link AbortSignal}. - * If the signal has already aborted, the promise will be cancelled immediately. - * When either condition is verified, the cancellation cause will be set - * to the signal's abort reason (see {@link AbortSignal#reason}). - * - * Has no effect if called (or if the signal aborts) _after_ the promise has already settled. - * Only the first signal to abort will set the cancellation cause. - * - * For more details about the cancellation process, - * see {@link cancel} and the `CancellablePromise` constructor. - * - * This method enables `await`ing cancellable promises without having - * to store them for future cancellation, e.g.: - * ```ts - * await longRunningOperation().cancelOn(signal); - * ``` - * instead of: - * ```ts - * let promiseToBeCancelled = longRunningOperation(); - * await promiseToBeCancelled; - * ``` - * - * @returns This promise, for method chaining. - */ - cancelOn(signal) { - if (signal.aborted) { - void this.cancel(signal.reason); - } else { - signal.addEventListener("abort", () => void this.cancel(signal.reason), { capture: true }); - } - return this; - } - /** - * Attaches callbacks for the resolution and/or rejection of the `CancellablePromise`. - * - * The optional `oncancelled` argument will be invoked when the returned promise is cancelled, - * with the same semantics as the `oncancelled` argument of the constructor. - * When the parent promise rejects or is cancelled, the `onrejected` callback will run, - * _even after the returned promise has been cancelled:_ - * in that case, should it reject or throw, the reason will be wrapped - * in a {@link CancelledRejectionError} and bubbled up as an unhandled rejection. - * - * @param onfulfilled The callback to execute when the Promise is resolved. - * @param onrejected The callback to execute when the Promise is rejected. - * @returns A `CancellablePromise` for the completion of whichever callback is executed. - * The returned promise is hooked up to propagate cancellation requests up the chain, but not down: - * - * - if the parent promise is cancelled, the `onrejected` handler will be invoked with a `CancelError` - * and the returned promise _will resolve regularly_ with its result; - * - conversely, if the returned promise is cancelled, _the parent promise is cancelled too;_ - * the `onrejected` handler will still be invoked with the parent's `CancelError`, - * but its result will be discarded - * and the returned promise will reject with a `CancelError` as well. - * - * The promise returned from {@link cancel} will fulfill only after all attached handlers - * up the entire promise chain have been run. - * - * If either callback returns a cancellable promise, - * cancellation requests will be diverted to it, - * and the specified `oncancelled` callback will be discarded. - */ - then(onfulfilled, onrejected, oncancelled) { - if (!(this instanceof _CancellablePromise)) { - throw new TypeError("CancellablePromise.prototype.then called on an invalid object."); - } - if (!callable_default(onfulfilled)) { - onfulfilled = identity; - } - if (!callable_default(onrejected)) { - onrejected = thrower; - } - if (onfulfilled === identity && onrejected == thrower) { - return new _CancellablePromise((resolve) => resolve(this)); - } - const barrier = {}; - this[barrierSym] = barrier; - return new _CancellablePromise((resolve, reject) => { - void super.then( - (value) => { - var _a2; - if (this[barrierSym] === barrier) { - this[barrierSym] = null; - } - (_a2 = barrier.resolve) == null ? void 0 : _a2.call(barrier); - try { - resolve(onfulfilled(value)); - } catch (err) { - reject(err); - } - }, - (reason) => { - var _a2; - if (this[barrierSym] === barrier) { - this[barrierSym] = null; - } - (_a2 = barrier.resolve) == null ? void 0 : _a2.call(barrier); - try { - resolve(onrejected(reason)); - } catch (err) { - reject(err); - } - } - ); - }, async (cause) => { - try { - return oncancelled == null ? void 0 : oncancelled(cause); - } finally { - await this.cancel(cause); - } - }); - } - /** - * Attaches a callback for only the rejection of the Promise. - * - * The optional `oncancelled` argument will be invoked when the returned promise is cancelled, - * with the same semantics as the `oncancelled` argument of the constructor. - * When the parent promise rejects or is cancelled, the `onrejected` callback will run, - * _even after the returned promise has been cancelled:_ - * in that case, should it reject or throw, the reason will be wrapped - * in a {@link CancelledRejectionError} and bubbled up as an unhandled rejection. - * - * It is equivalent to - * ```ts - * cancellablePromise.then(undefined, onrejected, oncancelled); - * ``` - * and the same caveats apply. - * - * @returns A Promise for the completion of the callback. - * Cancellation requests on the returned promise - * will propagate up the chain to the parent promise, - * but not in the other direction. - * - * The promise returned from {@link cancel} will fulfill only after all attached handlers - * up the entire promise chain have been run. - * - * If `onrejected` returns a cancellable promise, - * cancellation requests will be diverted to it, - * and the specified `oncancelled` callback will be discarded. - * See {@link then} for more details. - */ - catch(onrejected, oncancelled) { - return this.then(void 0, onrejected, oncancelled); - } - /** - * Attaches a callback that is invoked when the CancellablePromise is settled (fulfilled or rejected). The - * resolved value cannot be accessed or modified from the callback. - * The returned promise will settle in the same state as the original one - * after the provided callback has completed execution, - * unless the callback throws or returns a rejecting promise, - * in which case the returned promise will reject as well. - * - * The optional `oncancelled` argument will be invoked when the returned promise is cancelled, - * with the same semantics as the `oncancelled` argument of the constructor. - * Once the parent promise settles, the `onfinally` callback will run, - * _even after the returned promise has been cancelled:_ - * in that case, should it reject or throw, the reason will be wrapped - * in a {@link CancelledRejectionError} and bubbled up as an unhandled rejection. - * - * This method is implemented in terms of {@link then} and the same caveats apply. - * It is polyfilled, hence available in every OS/webview version. - * - * @returns A Promise for the completion of the callback. - * Cancellation requests on the returned promise - * will propagate up the chain to the parent promise, - * but not in the other direction. - * - * The promise returned from {@link cancel} will fulfill only after all attached handlers - * up the entire promise chain have been run. - * - * If `onfinally` returns a cancellable promise, - * cancellation requests will be diverted to it, - * and the specified `oncancelled` callback will be discarded. - * See {@link then} for more details. - */ - finally(onfinally, oncancelled) { - if (!(this instanceof _CancellablePromise)) { - throw new TypeError("CancellablePromise.prototype.finally called on an invalid object."); - } - if (!callable_default(onfinally)) { - return this.then(onfinally, onfinally, oncancelled); - } - return this.then( - (value) => _CancellablePromise.resolve(onfinally()).then(() => value), - (reason) => _CancellablePromise.resolve(onfinally()).then(() => { - throw reason; - }), - oncancelled - ); - } - /** - * We use the `[Symbol.species]` static property, if available, - * to disable the built-in automatic subclassing features from {@link Promise}. - * It is critical for performance reasons that extenders do not override this. - * Once the proposal at https://github.com/tc39/proposal-rm-builtin-subclassing - * is either accepted or retired, this implementation will have to be revised accordingly. - * - * @ignore - * @internal - */ - static get [(barrierSym, cancelImplSym, species)]() { - return Promise; - } - static all(values) { - let collected = Array.from(values); - const promise = collected.length === 0 ? _CancellablePromise.resolve(collected) : new _CancellablePromise((resolve, reject) => { - void Promise.all(collected).then(resolve, reject); - }, (cause) => cancelAll(promise, collected, cause)); - return promise; - } - static allSettled(values) { - let collected = Array.from(values); - const promise = collected.length === 0 ? _CancellablePromise.resolve(collected) : new _CancellablePromise((resolve, reject) => { - void Promise.allSettled(collected).then(resolve, reject); - }, (cause) => cancelAll(promise, collected, cause)); - return promise; - } - static any(values) { - let collected = Array.from(values); - const promise = collected.length === 0 ? _CancellablePromise.resolve(collected) : new _CancellablePromise((resolve, reject) => { - void Promise.any(collected).then(resolve, reject); - }, (cause) => cancelAll(promise, collected, cause)); - return promise; - } - static race(values) { - let collected = Array.from(values); - const promise = new _CancellablePromise((resolve, reject) => { - void Promise.race(collected).then(resolve, reject); - }, (cause) => cancelAll(promise, collected, cause)); - return promise; - } - /** - * Creates a new cancelled CancellablePromise for the provided cause. - * - * @group Static Methods - */ - static cancel(cause) { - const p = new _CancellablePromise(() => { - }); - p.cancel(cause); - return p; - } - /** - * Creates a new CancellablePromise that cancels - * after the specified timeout, with the provided cause. - * - * If the {@link AbortSignal.timeout} factory method is available, - * it is used to base the timeout on _active_ time rather than _elapsed_ time. - * Otherwise, `timeout` falls back to {@link setTimeout}. - * - * @group Static Methods - */ - static timeout(milliseconds, cause) { - const promise = new _CancellablePromise(() => { - }); - if (AbortSignal && typeof AbortSignal === "function" && AbortSignal.timeout && typeof AbortSignal.timeout === "function") { - AbortSignal.timeout(milliseconds).addEventListener("abort", () => void promise.cancel(cause)); - } else { - setTimeout(() => void promise.cancel(cause), milliseconds); - } - return promise; - } - static sleep(milliseconds, value) { - return new _CancellablePromise((resolve) => { - setTimeout(() => resolve(value), milliseconds); - }); - } - /** - * Creates a new rejected CancellablePromise for the provided reason. - * - * @group Static Methods - */ - static reject(reason) { - return new _CancellablePromise((_, reject) => reject(reason)); - } - static resolve(value) { - if (value instanceof _CancellablePromise) { - return value; - } - return new _CancellablePromise((resolve) => resolve(value)); - } - /** - * Creates a new CancellablePromise and returns it in an object, along with its resolve and reject functions - * and a getter/setter for the cancellation callback. - * - * This method is polyfilled, hence available in every OS/webview version. - * - * @group Static Methods - */ - static withResolvers() { - let result = { oncancelled: null }; - result.promise = new _CancellablePromise((resolve, reject) => { - result.resolve = resolve; - result.reject = reject; - }, (cause) => { - var _a2; - (_a2 = result.oncancelled) == null ? void 0 : _a2.call(result, cause); - }); - return result; - } -}; -function cancellerFor(promise, state) { - let cancellationPromise = void 0; - return (reason) => { - if (!state.settled) { - state.settled = true; - state.reason = reason; - promise.reject(reason); - void Promise.prototype.then.call(promise.promise, void 0, (err) => { - if (err !== reason) { - throw err; - } - }); - } - if (!state.reason || !promise.oncancelled) { - return; - } - cancellationPromise = new Promise((resolve) => { - try { - resolve(promise.oncancelled(state.reason.cause)); - } catch (err) { - Promise.reject(new CancelledRejectionError(promise.promise, err, "Unhandled exception in oncancelled callback.")); - } - }).catch((reason2) => { - Promise.reject(new CancelledRejectionError(promise.promise, reason2, "Unhandled rejection in oncancelled callback.")); - }); - promise.oncancelled = null; - return cancellationPromise; - }; -} -function resolverFor(promise, state) { - return (value) => { - if (state.resolving) { - return; - } - state.resolving = true; - if (value === promise.promise) { - if (state.settled) { - return; - } - state.settled = true; - promise.reject(new TypeError("A promise cannot be resolved with itself.")); - return; - } - if (value != null && (typeof value === "object" || typeof value === "function")) { - let then; - try { - then = value.then; - } catch (err) { - state.settled = true; - promise.reject(err); - return; - } - if (callable_default(then)) { - try { - let cancel = value.cancel; - if (callable_default(cancel)) { - const oncancelled = (cause) => { - Reflect.apply(cancel, value, [cause]); - }; - if (state.reason) { - void cancellerFor(__spreadProps(__spreadValues({}, promise), { oncancelled }), state)(state.reason); - } else { - promise.oncancelled = oncancelled; - } - } - } catch (e) { - } - const newState = { - root: state.root, - resolving: false, - get settled() { - return this.root.settled; - }, - set settled(value2) { - this.root.settled = value2; - }, - get reason() { - return this.root.reason; - } - }; - const rejector = rejectorFor(promise, newState); - try { - Reflect.apply(then, value, [resolverFor(promise, newState), rejector]); - } catch (err) { - rejector(err); - } - return; - } - } - if (state.settled) { - return; - } - state.settled = true; - promise.resolve(value); - }; -} -function rejectorFor(promise, state) { - return (reason) => { - if (state.resolving) { - return; - } - state.resolving = true; - if (state.settled) { - try { - if (reason instanceof CancelError && state.reason instanceof CancelError && Object.is(reason.cause, state.reason.cause)) { - return; - } - } catch (e) { - } - void Promise.reject(new CancelledRejectionError(promise.promise, reason)); - } else { - state.settled = true; - promise.reject(reason); - } - }; -} -function cancelAll(parent, values, cause) { - const results = []; - for (const value of values) { - let cancel; - try { - if (!callable_default(value.then)) { - continue; - } - cancel = value.cancel; - if (!callable_default(cancel)) { - continue; - } - } catch (e) { - continue; - } - let result; - try { - result = Reflect.apply(cancel, value, [cause]); - } catch (err) { - Promise.reject(new CancelledRejectionError(parent, err, "Unhandled exception in cancel method.")); - continue; - } - if (!result) { - continue; - } - results.push( - (result instanceof Promise ? result : Promise.resolve(result)).catch((reason) => { - Promise.reject(new CancelledRejectionError(parent, reason, "Unhandled rejection in cancel method.")); - }) - ); - } - return Promise.all(results); -} -function identity(x) { - return x; -} -function thrower(reason) { - throw reason; -} -function errorMessage(err) { - try { - if (err instanceof Error || typeof err !== "object" || err.toString !== Object.prototype.toString) { - return "" + err; - } - } catch (e) { - } - try { - return JSON.stringify(err); - } catch (e) { - } - try { - return Object.prototype.toString.call(err); - } catch (e) { - } - return ""; -} -function currentBarrier(promise) { - var _a2; - let pwr = (_a2 = promise[barrierSym]) != null ? _a2 : {}; - if (!("promise" in pwr)) { - Object.assign(pwr, promiseWithResolvers()); - } - if (promise[barrierSym] == null) { - pwr.resolve(); - promise[barrierSym] = pwr; - } - return pwr.promise; -} -var promiseWithResolvers = Promise.withResolvers; -if (promiseWithResolvers && typeof promiseWithResolvers === "function") { - promiseWithResolvers = promiseWithResolvers.bind(Promise); -} else { - promiseWithResolvers = function() { - let resolve; - let reject; - const promise = new Promise((res, rej) => { - resolve = res; - reject = rej; - }); - return { promise, resolve, reject }; - }; -} - -// desktop/@wailsio/runtime/src/calls.ts -window._wails = window._wails || {}; -var call7 = newRuntimeCaller(objectNames.Call); -var cancelCall = newRuntimeCaller(objectNames.CancelCall); -var callResponses = /* @__PURE__ */ new Map(); -var CallBinding = 0; -var CancelMethod = 0; -var RuntimeError = class extends Error { - /** - * Constructs a new RuntimeError instance. - * @param message - The error message. - * @param options - Options to be forwarded to the Error constructor. - */ - constructor(message, options) { - super(message, options); - this.name = "RuntimeError"; - } -}; -function generateID() { - let result; - do { - result = nanoid(); - } while (callResponses.has(result)); - return result; -} -function Call(options) { - const id = generateID(); - const result = CancellablePromise.withResolvers(); - callResponses.set(id, { resolve: result.resolve, reject: result.reject }); - const request = call7(CallBinding, Object.assign({ "call-id": id }, options)); - let running = true; - request.then((res) => { - running = false; - callResponses.delete(id); - result.resolve(res); - }, (err) => { - running = false; - callResponses.delete(id); - result.reject(err); - }); - const cancel = () => { - callResponses.delete(id); - return cancelCall(CancelMethod, { "call-id": id }).catch((err) => { - console.error("Error while requesting binding call cancellation:", err); - }); - }; - result.oncancelled = () => { - if (running) { - return cancel(); - } else { - return request.then(cancel); - } - }; - return result.promise; -} -function ByName(methodName, ...args) { - return Call({ methodName, args }); -} -function ByID(methodID, ...args) { - return Call({ methodID, args }); -} - -// desktop/@wailsio/runtime/src/clipboard.ts -var clipboard_exports = {}; -__export(clipboard_exports, { - SetText: () => SetText, - Text: () => Text -}); -var call8 = newRuntimeCaller(objectNames.Clipboard); -var ClipboardSetText = 0; -var ClipboardText = 1; -function SetText(text) { - return call8(ClipboardSetText, { text }); -} -function Text() { - return call8(ClipboardText); -} - -// desktop/@wailsio/runtime/src/screens.ts -var screens_exports = {}; -__export(screens_exports, { - GetAll: () => GetAll, - GetCurrent: () => GetCurrent, - GetPrimary: () => GetPrimary -}); -var call9 = newRuntimeCaller(objectNames.Screens); -var getAll = 0; -var getPrimary = 1; -var getCurrent = 2; -function GetAll() { - return call9(getAll); -} -function GetPrimary() { - return call9(getPrimary); -} -function GetCurrent() { - return call9(getCurrent); -} - -// desktop/@wailsio/runtime/src/ios.ts -var ios_exports = {}; -__export(ios_exports, { - Device: () => Device, - Haptics: () => Haptics -}); -var call10 = newRuntimeCaller(objectNames.IOS); -var HapticsImpact = 0; -var DeviceInfo = 1; -var Haptics; -((Haptics2) => { - function Impact(style = "medium") { - return call10(HapticsImpact, { style }); - } - Haptics2.Impact = Impact; -})(Haptics || (Haptics = {})); -var Device; -((Device2) => { - function Info2() { - return call10(DeviceInfo); - } - Device2.Info = Info2; -})(Device || (Device = {})); - -// desktop/@wailsio/runtime/src/index.ts -window._wails = window._wails || {}; -window._wails.invoke = invoke; -window._wails.clientId = clientId; -window._wails.handlePlatformFileDrop = window_default.HandlePlatformFileDrop.bind(window_default); -window._wails.handleDragEnter = handleDragEnter; -window._wails.handleDragLeave = handleDragLeave; -window._wails.handleDragOver = handleDragOver; -invoke("wails:runtime:ready"); -function loadOptionalScript(url) { - return fetch(url, { method: "HEAD" }).then((response) => { - if (response.ok) { - const script = document.createElement("script"); - script.src = url; - document.head.appendChild(script); - } - }).catch(() => { - }); -} -loadOptionalScript("/wails/custom.js"); -export { - application_exports as Application, - browser_exports as Browser, - calls_exports as Call, - CancelError, - CancellablePromise, - CancelledRejectionError, - clipboard_exports as Clipboard, - create_exports as Create, - dialogs_exports as Dialogs, - events_exports as Events, - flags_exports as Flags, - ios_exports as IOS, - screens_exports as Screens, - system_exports as System, - wml_exports as WML, - window_default as Window, - clientId, - getTransport, - loadOptionalScript, - objectNames, - setTransport -}; -//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLi4vLi4vcnVudGltZS9kZXNrdG9wL0B3YWlsc2lvL3J1bnRpbWUvc3JjL2luZGV4LnRzIiwgIi4uLy4uL3J1bnRpbWUvZGVza3RvcC9Ad2FpbHNpby9ydW50aW1lL3NyYy93bWwudHMiLCAiLi4vLi4vcnVudGltZS9kZXNrdG9wL0B3YWlsc2lvL3J1bnRpbWUvc3JjL2Jyb3dzZXIudHMiLCAiLi4vLi4vcnVudGltZS9kZXNrdG9wL0B3YWlsc2lvL3J1bnRpbWUvc3JjL25hbm9pZC50cyIsICIuLi8uLi9ydW50aW1lL2Rlc2t0b3AvQHdhaWxzaW8vcnVudGltZS9zcmMvcnVudGltZS50cyIsICIuLi8uLi9ydW50aW1lL2Rlc2t0b3AvQHdhaWxzaW8vcnVudGltZS9zcmMvZGlhbG9ncy50cyIsICIuLi8uLi9ydW50aW1lL2Rlc2t0b3AvQHdhaWxzaW8vcnVudGltZS9zcmMvZXZlbnRzLnRzIiwgIi4uLy4uL3J1bnRpbWUvZGVza3RvcC9Ad2FpbHNpby9ydW50aW1lL3NyYy9saXN0ZW5lci50cyIsICIuLi8uLi9ydW50aW1lL2Rlc2t0b3AvQHdhaWxzaW8vcnVudGltZS9zcmMvY3JlYXRlLnRzIiwgIi4uLy4uL3J1bnRpbWUvZGVza3RvcC9Ad2FpbHNpby9ydW50aW1lL3NyYy9ldmVudF90eXBlcy50cyIsICIuLi8uLi9ydW50aW1lL2Rlc2t0b3AvQHdhaWxzaW8vcnVudGltZS9zcmMvdXRpbHMudHMiLCAiLi4vLi4vcnVudGltZS9kZXNrdG9wL0B3YWlsc2lvL3J1bnRpbWUvc3JjL3dpbmRvdy50cyIsICIuLi8uLi9ydW50aW1lL2Rlc2t0b3AvY29tcGlsZWQvbWFpbi5qcyIsICIuLi8uLi9ydW50aW1lL2Rlc2t0b3AvQHdhaWxzaW8vcnVudGltZS9zcmMvc3lzdGVtLnRzIiwgIi4uLy4uL3J1bnRpbWUvZGVza3RvcC9Ad2FpbHNpby9ydW50aW1lL3NyYy9jb250ZXh0bWVudS50cyIsICIuLi8uLi9ydW50aW1lL2Rlc2t0b3AvQHdhaWxzaW8vcnVudGltZS9zcmMvZmxhZ3MudHMiLCAiLi4vLi4vcnVudGltZS9kZXNrdG9wL0B3YWlsc2lvL3J1bnRpbWUvc3JjL2RyYWcudHMiLCAiLi4vLi4vcnVudGltZS9kZXNrdG9wL0B3YWlsc2lvL3J1bnRpbWUvc3JjL2FwcGxpY2F0aW9uLnRzIiwgIi4uLy4uL3J1bnRpbWUvZGVza3RvcC9Ad2FpbHNpby9ydW50aW1lL3NyYy9jYWxscy50cyIsICIuLi8uLi9ydW50aW1lL2Rlc2t0b3AvQHdhaWxzaW8vcnVudGltZS9zcmMvY2FsbGFibGUudHMiLCAiLi4vLi4vcnVudGltZS9kZXNrdG9wL0B3YWlsc2lvL3J1bnRpbWUvc3JjL2NhbmNlbGxhYmxlLnRzIiwgIi4uLy4uL3J1bnRpbWUvZGVza3RvcC9Ad2FpbHNpby9ydW50aW1lL3NyYy9jbGlwYm9hcmQudHMiLCAiLi4vLi4vcnVudGltZS9kZXNrdG9wL0B3YWlsc2lvL3J1bnRpbWUvc3JjL3NjcmVlbnMudHMiLCAiLi4vLi4vcnVudGltZS9kZXNrdG9wL0B3YWlsc2lvL3J1bnRpbWUvc3JjL2lvcy50cyJdLAogICJzb3VyY2VzQ29udGVudCI6IFsiLypcbiBfXHQgICBfX1x0ICBfIF9fXG58IHxcdCAvIC9fX18gXyhfKSAvX19fX1xufCB8IC98IC8gLyBfXyBgLyAvIC8gX19fL1xufCB8LyB8LyAvIC9fLyAvIC8gKF9fICApXG58X18vfF9fL1xcX18sXy9fL18vX19fXy9cblRoZSBlbGVjdHJvbiBhbHRlcm5hdGl2ZSBmb3IgR29cbihjKSBMZWEgQW50aG9ueSAyMDE5LXByZXNlbnRcbiovXG5cbi8vIFNldHVwXG53aW5kb3cuX3dhaWxzID0gd2luZG93Ll93YWlscyB8fCB7fTtcblxuaW1wb3J0IFwiLi9jb250ZXh0bWVudS5qc1wiO1xuaW1wb3J0IFwiLi9kcmFnLmpzXCI7XG5cbi8vIFJlLWV4cG9ydCBwdWJsaWMgQVBJXG5pbXBvcnQgKiBhcyBBcHBsaWNhdGlvbiBmcm9tIFwiLi9hcHBsaWNhdGlvbi5qc1wiO1xuaW1wb3J0ICogYXMgQnJvd3NlciBmcm9tIFwiLi9icm93c2VyLmpzXCI7XG5pbXBvcnQgKiBhcyBDYWxsIGZyb20gXCIuL2NhbGxzLmpzXCI7XG5pbXBvcnQgKiBhcyBDbGlwYm9hcmQgZnJvbSBcIi4vY2xpcGJvYXJkLmpzXCI7XG5pbXBvcnQgKiBhcyBDcmVhdGUgZnJvbSBcIi4vY3JlYXRlLmpzXCI7XG5pbXBvcnQgKiBhcyBEaWFsb2dzIGZyb20gXCIuL2RpYWxvZ3MuanNcIjtcbmltcG9ydCAqIGFzIEV2ZW50cyBmcm9tIFwiLi9ldmVudHMuanNcIjtcbmltcG9ydCAqIGFzIEZsYWdzIGZyb20gXCIuL2ZsYWdzLmpzXCI7XG5pbXBvcnQgKiBhcyBTY3JlZW5zIGZyb20gXCIuL3NjcmVlbnMuanNcIjtcbmltcG9ydCAqIGFzIFN5c3RlbSBmcm9tIFwiLi9zeXN0ZW0uanNcIjtcbmltcG9ydCAqIGFzIElPUyBmcm9tIFwiLi9pb3MuanNcIjtcbmltcG9ydCBXaW5kb3csIHsgaGFuZGxlRHJhZ0VudGVyLCBoYW5kbGVEcmFnTGVhdmUsIGhhbmRsZURyYWdPdmVyIH0gZnJvbSBcIi4vd2luZG93LmpzXCI7XG5pbXBvcnQgKiBhcyBXTUwgZnJvbSBcIi4vd21sLmpzXCI7XG5cbmV4cG9ydCB7XG4gICAgQXBwbGljYXRpb24sXG4gICAgQnJvd3NlcixcbiAgICBDYWxsLFxuICAgIENsaXBib2FyZCxcbiAgICBEaWFsb2dzLFxuICAgIEV2ZW50cyxcbiAgICBGbGFncyxcbiAgICBTY3JlZW5zLFxuICAgIFN5c3RlbSxcbiAgICBJT1MsXG4gICAgV2luZG93LFxuICAgIFdNTFxufTtcblxuLyoqXG4gKiBBbiBpbnRlcm5hbCB1dGlsaXR5IGNvbnN1bWVkIGJ5IHRoZSBiaW5kaW5nIGdlbmVyYXRvci5cbiAqXG4gKiBAaWdub3JlXG4gKi9cbmV4cG9ydCB7IENyZWF0ZSB9O1xuXG5leHBvcnQgKiBmcm9tIFwiLi9jYW5jZWxsYWJsZS5qc1wiO1xuXG4vLyBFeHBvcnQgdHJhbnNwb3J0IGludGVyZmFjZXMgYW5kIHV0aWxpdGllc1xuZXhwb3J0IHtcbiAgICBzZXRUcmFuc3BvcnQsXG4gICAgZ2V0VHJhbnNwb3J0LFxuICAgIHR5cGUgUnVudGltZVRyYW5zcG9ydCxcbiAgICBvYmplY3ROYW1lcyxcbiAgICBjbGllbnRJZCxcbn0gZnJvbSBcIi4vcnVudGltZS5qc1wiO1xuXG5pbXBvcnQgeyBjbGllbnRJZCB9IGZyb20gXCIuL3J1bnRpbWUuanNcIjtcblxuLy8gTm90aWZ5IGJhY2tlbmRcbndpbmRvdy5fd2FpbHMuaW52b2tlID0gU3lzdGVtLmludm9rZTtcbndpbmRvdy5fd2FpbHMuY2xpZW50SWQgPSBjbGllbnRJZDtcblxuLy8gUmVnaXN0ZXIgcGxhdGZvcm0gaGFuZGxlcnMgKGludGVybmFsIEFQSSlcbi8vIE5vdGU6IFdpbmRvdyBpcyB0aGUgdGhpc1dpbmRvdyBpbnN0YW5jZSAoZGVmYXVsdCBleHBvcnQgZnJvbSB3aW5kb3cudHMpXG4vLyBCaW5kaW5nIGVuc3VyZXMgJ3RoaXMnIGNvcnJlY3RseSByZWZlcnMgdG8gdGhlIGN1cnJlbnQgd2luZG93IGluc3RhbmNlXG53aW5kb3cuX3dhaWxzLmhhbmRsZVBsYXRmb3JtRmlsZURyb3AgPSBXaW5kb3cuSGFuZGxlUGxhdGZvcm1GaWxlRHJvcC5iaW5kKFdpbmRvdyk7XG5cbi8vIExpbnV4LXNwZWNpZmljIGRyYWcgaGFuZGxlcnMgKEdUSyBpbnRlcmNlcHRzIERPTSBkcmFnIGV2ZW50cylcbndpbmRvdy5fd2FpbHMuaGFuZGxlRHJhZ0VudGVyID0gaGFuZGxlRHJhZ0VudGVyO1xud2luZG93Ll93YWlscy5oYW5kbGVEcmFnTGVhdmUgPSBoYW5kbGVEcmFnTGVhdmU7XG53aW5kb3cuX3dhaWxzLmhhbmRsZURyYWdPdmVyID0gaGFuZGxlRHJhZ092ZXI7XG5cblN5c3RlbS5pbnZva2UoXCJ3YWlsczpydW50aW1lOnJlYWR5XCIpO1xuXG4vKipcbiAqIExvYWRzIGEgc2NyaXB0IGZyb20gdGhlIGdpdmVuIFVSTCBpZiBpdCBleGlzdHMuXG4gKiBVc2VzIEhFQUQgcmVxdWVzdCB0byBjaGVjayBleGlzdGVuY2UsIHRoZW4gaW5qZWN0cyBhIHNjcmlwdCB0YWcuXG4gKiBTaWxlbnRseSBpZ25vcmVzIGlmIHRoZSBzY3JpcHQgZG9lc24ndCBleGlzdC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGxvYWRPcHRpb25hbFNjcmlwdCh1cmw6IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuICAgIHJldHVybiBmZXRjaCh1cmwsIHsgbWV0aG9kOiAnSEVBRCcgfSlcbiAgICAgICAgLnRoZW4ocmVzcG9uc2UgPT4ge1xuICAgICAgICAgICAgaWYgKHJlc3BvbnNlLm9rKSB7XG4gICAgICAgICAgICAgICAgY29uc3Qgc2NyaXB0ID0gZG9jdW1lbnQuY3JlYXRlRWxlbWVudCgnc2NyaXB0Jyk7XG4gICAgICAgICAgICAgICAgc2NyaXB0LnNyYyA9IHVybDtcbiAgICAgICAgICAgICAgICBkb2N1bWVudC5oZWFkLmFwcGVuZENoaWxkKHNjcmlwdCk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pXG4gICAgICAgIC5jYXRjaCgoKSA9PiB7fSk7IC8vIFNpbGVudGx5IGlnbm9yZSAtIHNjcmlwdCBpcyBvcHRpb25hbFxufVxuXG4vLyBMb2FkIGN1c3RvbS5qcyBpZiBhdmFpbGFibGUgKHVzZWQgYnkgc2VydmVyIG1vZGUgZm9yIFdlYlNvY2tldCBldmVudHMsIGV0Yy4pXG5sb2FkT3B0aW9uYWxTY3JpcHQoJy93YWlscy9jdXN0b20uanMnKTtcbiIsICIvKlxuIF8gICAgIF9fICAgICBfIF9fXG58IHwgIC8gL19fXyBfKF8pIC9fX19fXG58IHwgL3wgLyAvIF9fIGAvIC8gLyBfX18vXG58IHwvIHwvIC8gL18vIC8gLyAoX18gIClcbnxfXy98X18vXFxfXyxfL18vXy9fX19fL1xuVGhlIGVsZWN0cm9uIGFsdGVybmF0aXZlIGZvciBHb1xuKGMpIExlYSBBbnRob255IDIwMTktcHJlc2VudFxuKi9cblxuaW1wb3J0IHsgT3BlblVSTCB9IGZyb20gXCIuL2Jyb3dzZXIuanNcIjtcbmltcG9ydCB7IFF1ZXN0aW9uIH0gZnJvbSBcIi4vZGlhbG9ncy5qc1wiO1xuaW1wb3J0IHsgRW1pdCB9IGZyb20gXCIuL2V2ZW50cy5qc1wiO1xuaW1wb3J0IHsgY2FuQWJvcnRMaXN0ZW5lcnMsIHdoZW5SZWFkeSB9IGZyb20gXCIuL3V0aWxzLmpzXCI7XG5pbXBvcnQgV2luZG93IGZyb20gXCIuL3dpbmRvdy5qc1wiO1xuXG4vKipcbiAqIFNlbmRzIGFuIGV2ZW50IHdpdGggdGhlIGdpdmVuIG5hbWUgYW5kIG9wdGlvbmFsIGRhdGEuXG4gKlxuICogQHBhcmFtIGV2ZW50TmFtZSAtIC0gVGhlIG5hbWUgb2YgdGhlIGV2ZW50IHRvIHNlbmQuXG4gKiBAcGFyYW0gW2RhdGE9bnVsbF0gLSAtIE9wdGlvbmFsIGRhdGEgdG8gc2VuZCBhbG9uZyB3aXRoIHRoZSBldmVudC5cbiAqL1xuZnVuY3Rpb24gc2VuZEV2ZW50KGV2ZW50TmFtZTogc3RyaW5nLCBkYXRhOiBhbnkgPSBudWxsKTogdm9pZCB7XG4gICAgRW1pdChldmVudE5hbWUsIGRhdGEpO1xufVxuXG4vKipcbiAqIENhbGxzIGEgbWV0aG9kIG9uIGEgc3BlY2lmaWVkIHdpbmRvdy5cbiAqXG4gKiBAcGFyYW0gd2luZG93TmFtZSAtIFRoZSBuYW1lIG9mIHRoZSB3aW5kb3cgdG8gY2FsbCB0aGUgbWV0aG9kIG9uLlxuICogQHBhcmFtIG1ldGhvZE5hbWUgLSBUaGUgbmFtZSBvZiB0aGUgbWV0aG9kIHRvIGNhbGwuXG4gKi9cbmZ1bmN0aW9uIGNhbGxXaW5kb3dNZXRob2Qod2luZG93TmFtZTogc3RyaW5nLCBtZXRob2ROYW1lOiBzdHJpbmcpIHtcbiAgICBjb25zdCB0YXJnZXRXaW5kb3cgPSBXaW5kb3cuR2V0KHdpbmRvd05hbWUpO1xuICAgIGNvbnN0IG1ldGhvZCA9ICh0YXJnZXRXaW5kb3cgYXMgYW55KVttZXRob2ROYW1lXTtcblxuICAgIGlmICh0eXBlb2YgbWV0aG9kICE9PSBcImZ1bmN0aW9uXCIpIHtcbiAgICAgICAgY29uc29sZS5lcnJvcihgV2luZG93IG1ldGhvZCAnJHttZXRob2ROYW1lfScgbm90IGZvdW5kYCk7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICB0cnkge1xuICAgICAgICBtZXRob2QuY2FsbCh0YXJnZXRXaW5kb3cpO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgY29uc29sZS5lcnJvcihgRXJyb3IgY2FsbGluZyB3aW5kb3cgbWV0aG9kICcke21ldGhvZE5hbWV9JzogYCwgZSk7XG4gICAgfVxufVxuXG4vKipcbiAqIFJlc3BvbmRzIHRvIGEgdHJpZ2dlcmluZyBldmVudCBieSBydW5uaW5nIGFwcHJvcHJpYXRlIFdNTCBhY3Rpb25zIGZvciB0aGUgY3VycmVudCB0YXJnZXQuXG4gKi9cbmZ1bmN0aW9uIG9uV01MVHJpZ2dlcmVkKGV2OiBFdmVudCk6IHZvaWQge1xuICAgIGNvbnN0IGVsZW1lbnQgPSBldi5jdXJyZW50VGFyZ2V0IGFzIEVsZW1lbnQ7XG5cbiAgICBmdW5jdGlvbiBydW5FZmZlY3QoY2hvaWNlID0gXCJZZXNcIikge1xuICAgICAgICBpZiAoY2hvaWNlICE9PSBcIlllc1wiKVxuICAgICAgICAgICAgcmV0dXJuO1xuXG4gICAgICAgIGNvbnN0IGV2ZW50VHlwZSA9IGVsZW1lbnQuZ2V0QXR0cmlidXRlKCd3bWwtZXZlbnQnKSB8fCBlbGVtZW50LmdldEF0dHJpYnV0ZSgnZGF0YS13bWwtZXZlbnQnKTtcbiAgICAgICAgY29uc3QgdGFyZ2V0V2luZG93ID0gZWxlbWVudC5nZXRBdHRyaWJ1dGUoJ3dtbC10YXJnZXQtd2luZG93JykgfHwgZWxlbWVudC5nZXRBdHRyaWJ1dGUoJ2RhdGEtd21sLXRhcmdldC13aW5kb3cnKSB8fCBcIlwiO1xuICAgICAgICBjb25zdCB3aW5kb3dNZXRob2QgPSBlbGVtZW50LmdldEF0dHJpYnV0ZSgnd21sLXdpbmRvdycpIHx8IGVsZW1lbnQuZ2V0QXR0cmlidXRlKCdkYXRhLXdtbC13aW5kb3cnKTtcbiAgICAgICAgY29uc3QgdXJsID0gZWxlbWVudC5nZXRBdHRyaWJ1dGUoJ3dtbC1vcGVudXJsJykgfHwgZWxlbWVudC5nZXRBdHRyaWJ1dGUoJ2RhdGEtd21sLW9wZW51cmwnKTtcblxuICAgICAgICBpZiAoZXZlbnRUeXBlICE9PSBudWxsKVxuICAgICAgICAgICAgc2VuZEV2ZW50KGV2ZW50VHlwZSk7XG4gICAgICAgIGlmICh3aW5kb3dNZXRob2QgIT09IG51bGwpXG4gICAgICAgICAgICBjYWxsV2luZG93TWV0aG9kKHRhcmdldFdpbmRvdywgd2luZG93TWV0aG9kKTtcbiAgICAgICAgaWYgKHVybCAhPT0gbnVsbClcbiAgICAgICAgICAgIHZvaWQgT3BlblVSTCh1cmwpO1xuICAgIH1cblxuICAgIGNvbnN0IGNvbmZpcm0gPSBlbGVtZW50LmdldEF0dHJpYnV0ZSgnd21sLWNvbmZpcm0nKSB8fCBlbGVtZW50LmdldEF0dHJpYnV0ZSgnZGF0YS13bWwtY29uZmlybScpO1xuXG4gICAgaWYgKGNvbmZpcm0pIHtcbiAgICAgICAgUXVlc3Rpb24oe1xuICAgICAgICAgICAgVGl0bGU6IFwiQ29uZmlybVwiLFxuICAgICAgICAgICAgTWVzc2FnZTogY29uZmlybSxcbiAgICAgICAgICAgIERldGFjaGVkOiBmYWxzZSxcbiAgICAgICAgICAgIEJ1dHRvbnM6IFtcbiAgICAgICAgICAgICAgICB7IExhYmVsOiBcIlllc1wiIH0sXG4gICAgICAgICAgICAgICAgeyBMYWJlbDogXCJOb1wiLCBJc0RlZmF1bHQ6IHRydWUgfVxuICAgICAgICAgICAgXVxuICAgICAgICB9KS50aGVuKHJ1bkVmZmVjdCk7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgcnVuRWZmZWN0KCk7XG4gICAgfVxufVxuXG4vLyBQcml2YXRlIGZpZWxkIG5hbWVzLlxuY29uc3QgY29udHJvbGxlclN5bSA9IFN5bWJvbChcImNvbnRyb2xsZXJcIik7XG5jb25zdCB0cmlnZ2VyTWFwU3ltID0gU3ltYm9sKFwidHJpZ2dlck1hcFwiKTtcbmNvbnN0IGVsZW1lbnRDb3VudFN5bSA9IFN5bWJvbChcImVsZW1lbnRDb3VudFwiKTtcblxuLyoqXG4gKiBBYm9ydENvbnRyb2xsZXJSZWdpc3RyeSBkb2VzIG5vdCBhY3R1YWxseSByZW1lbWJlciBhY3RpdmUgZXZlbnQgbGlzdGVuZXJzOiBpbnN0ZWFkXG4gKiBpdCB0aWVzIHRoZW0gdG8gYW4gQWJvcnRTaWduYWwgYW5kIHVzZXMgYW4gQWJvcnRDb250cm9sbGVyIHRvIHJlbW92ZSB0aGVtIGFsbCBhdCBvbmNlLlxuICovXG5jbGFzcyBBYm9ydENvbnRyb2xsZXJSZWdpc3RyeSB7XG4gICAgLy8gUHJpdmF0ZSBmaWVsZHMuXG4gICAgW2NvbnRyb2xsZXJTeW1dOiBBYm9ydENvbnRyb2xsZXI7XG5cbiAgICBjb25zdHJ1Y3RvcigpIHtcbiAgICAgICAgdGhpc1tjb250cm9sbGVyU3ltXSA9IG5ldyBBYm9ydENvbnRyb2xsZXIoKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIGFuIG9wdGlvbnMgb2JqZWN0IGZvciBhZGRFdmVudExpc3RlbmVyIHRoYXQgdGllcyB0aGUgbGlzdGVuZXJcbiAgICAgKiB0byB0aGUgQWJvcnRTaWduYWwgZnJvbSB0aGUgY3VycmVudCBBYm9ydENvbnRyb2xsZXIuXG4gICAgICpcbiAgICAgKiBAcGFyYW0gZWxlbWVudCAtIEFuIEhUTUwgZWxlbWVudFxuICAgICAqIEBwYXJhbSB0cmlnZ2VycyAtIFRoZSBsaXN0IG9mIGFjdGl2ZSBXTUwgdHJpZ2dlciBldmVudHMgZm9yIHRoZSBzcGVjaWZpZWQgZWxlbWVudHNcbiAgICAgKi9cbiAgICBzZXQoZWxlbWVudDogRWxlbWVudCwgdHJpZ2dlcnM6IHN0cmluZ1tdKTogQWRkRXZlbnRMaXN0ZW5lck9wdGlvbnMge1xuICAgICAgICByZXR1cm4geyBzaWduYWw6IHRoaXNbY29udHJvbGxlclN5bV0uc2lnbmFsIH07XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmVtb3ZlcyBhbGwgcmVnaXN0ZXJlZCBldmVudCBsaXN0ZW5lcnMgYW5kIHJlc2V0cyB0aGUgcmVnaXN0cnkuXG4gICAgICovXG4gICAgcmVzZXQoKTogdm9pZCB7XG4gICAgICAgIHRoaXNbY29udHJvbGxlclN5bV0uYWJvcnQoKTtcbiAgICAgICAgdGhpc1tjb250cm9sbGVyU3ltXSA9IG5ldyBBYm9ydENvbnRyb2xsZXIoKTtcbiAgICB9XG59XG5cbi8qKlxuICogV2Vha01hcFJlZ2lzdHJ5IG1hcHMgYWN0aXZlIHRyaWdnZXIgZXZlbnRzIHRvIGVhY2ggRE9NIGVsZW1lbnQgdGhyb3VnaCBhIFdlYWtNYXAuXG4gKiBUaGlzIGVuc3VyZXMgdGhhdCB0aGUgbWFwcGluZyByZW1haW5zIHByaXZhdGUgdG8gdGhpcyBtb2R1bGUsIHdoaWxlIHN0aWxsIGFsbG93aW5nIGdhcmJhZ2VcbiAqIGNvbGxlY3Rpb24gb2YgdGhlIGludm9sdmVkIGVsZW1lbnRzLlxuICovXG5jbGFzcyBXZWFrTWFwUmVnaXN0cnkge1xuICAgIC8qKiBTdG9yZXMgdGhlIGN1cnJlbnQgZWxlbWVudC10by10cmlnZ2VyIG1hcHBpbmcuICovXG4gICAgW3RyaWdnZXJNYXBTeW1dOiBXZWFrTWFwPEVsZW1lbnQsIHN0cmluZ1tdPjtcbiAgICAvKiogQ291bnRzIHRoZSBudW1iZXIgb2YgZWxlbWVudHMgd2l0aCBhY3RpdmUgV01MIHRyaWdnZXJzLiAqL1xuICAgIFtlbGVtZW50Q291bnRTeW1dOiBudW1iZXI7XG5cbiAgICBjb25zdHJ1Y3RvcigpIHtcbiAgICAgICAgdGhpc1t0cmlnZ2VyTWFwU3ltXSA9IG5ldyBXZWFrTWFwKCk7XG4gICAgICAgIHRoaXNbZWxlbWVudENvdW50U3ltXSA9IDA7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2V0cyBhY3RpdmUgdHJpZ2dlcnMgZm9yIHRoZSBzcGVjaWZpZWQgZWxlbWVudC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSBlbGVtZW50IC0gQW4gSFRNTCBlbGVtZW50XG4gICAgICogQHBhcmFtIHRyaWdnZXJzIC0gVGhlIGxpc3Qgb2YgYWN0aXZlIFdNTCB0cmlnZ2VyIGV2ZW50cyBmb3IgdGhlIHNwZWNpZmllZCBlbGVtZW50XG4gICAgICovXG4gICAgc2V0KGVsZW1lbnQ6IEVsZW1lbnQsIHRyaWdnZXJzOiBzdHJpbmdbXSk6IEFkZEV2ZW50TGlzdGVuZXJPcHRpb25zIHtcbiAgICAgICAgaWYgKCF0aGlzW3RyaWdnZXJNYXBTeW1dLmhhcyhlbGVtZW50KSkgeyB0aGlzW2VsZW1lbnRDb3VudFN5bV0rKzsgfVxuICAgICAgICB0aGlzW3RyaWdnZXJNYXBTeW1dLnNldChlbGVtZW50LCB0cmlnZ2Vycyk7XG4gICAgICAgIHJldHVybiB7fTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZW1vdmVzIGFsbCByZWdpc3RlcmVkIGV2ZW50IGxpc3RlbmVycy5cbiAgICAgKi9cbiAgICByZXNldCgpOiB2b2lkIHtcbiAgICAgICAgaWYgKHRoaXNbZWxlbWVudENvdW50U3ltXSA8PSAwKVxuICAgICAgICAgICAgcmV0dXJuO1xuXG4gICAgICAgIGZvciAoY29uc3QgZWxlbWVudCBvZiBkb2N1bWVudC5ib2R5LnF1ZXJ5U2VsZWN0b3JBbGwoJyonKSkge1xuICAgICAgICAgICAgaWYgKHRoaXNbZWxlbWVudENvdW50U3ltXSA8PSAwKVxuICAgICAgICAgICAgICAgIGJyZWFrO1xuXG4gICAgICAgICAgICBjb25zdCB0cmlnZ2VycyA9IHRoaXNbdHJpZ2dlck1hcFN5bV0uZ2V0KGVsZW1lbnQpO1xuICAgICAgICAgICAgaWYgKHRyaWdnZXJzICE9IG51bGwpIHsgdGhpc1tlbGVtZW50Q291bnRTeW1dLS07IH1cblxuICAgICAgICAgICAgZm9yIChjb25zdCB0cmlnZ2VyIG9mIHRyaWdnZXJzIHx8IFtdKVxuICAgICAgICAgICAgICAgIGVsZW1lbnQucmVtb3ZlRXZlbnRMaXN0ZW5lcih0cmlnZ2VyLCBvbldNTFRyaWdnZXJlZCk7XG4gICAgICAgIH1cblxuICAgICAgICB0aGlzW3RyaWdnZXJNYXBTeW1dID0gbmV3IFdlYWtNYXAoKTtcbiAgICAgICAgdGhpc1tlbGVtZW50Q291bnRTeW1dID0gMDtcbiAgICB9XG59XG5cbmNvbnN0IHRyaWdnZXJSZWdpc3RyeSA9IGNhbkFib3J0TGlzdGVuZXJzKCkgPyBuZXcgQWJvcnRDb250cm9sbGVyUmVnaXN0cnkoKSA6IG5ldyBXZWFrTWFwUmVnaXN0cnkoKTtcblxuLyoqXG4gKiBBZGRzIGV2ZW50IGxpc3RlbmVycyB0byB0aGUgc3BlY2lmaWVkIGVsZW1lbnQuXG4gKi9cbmZ1bmN0aW9uIGFkZFdNTExpc3RlbmVycyhlbGVtZW50OiBFbGVtZW50KTogdm9pZCB7XG4gICAgY29uc3QgdHJpZ2dlclJlZ0V4cCA9IC9cXFMrL2c7XG4gICAgY29uc3QgdHJpZ2dlckF0dHIgPSAoZWxlbWVudC5nZXRBdHRyaWJ1dGUoJ3dtbC10cmlnZ2VyJykgfHwgZWxlbWVudC5nZXRBdHRyaWJ1dGUoJ2RhdGEtd21sLXRyaWdnZXInKSB8fCBcImNsaWNrXCIpO1xuICAgIGNvbnN0IHRyaWdnZXJzOiBzdHJpbmdbXSA9IFtdO1xuXG4gICAgbGV0IG1hdGNoO1xuICAgIHdoaWxlICgobWF0Y2ggPSB0cmlnZ2VyUmVnRXhwLmV4ZWModHJpZ2dlckF0dHIpKSAhPT0gbnVsbClcbiAgICAgICAgdHJpZ2dlcnMucHVzaChtYXRjaFswXSk7XG5cbiAgICBjb25zdCBvcHRpb25zID0gdHJpZ2dlclJlZ2lzdHJ5LnNldChlbGVtZW50LCB0cmlnZ2Vycyk7XG4gICAgZm9yIChjb25zdCB0cmlnZ2VyIG9mIHRyaWdnZXJzKVxuICAgICAgICBlbGVtZW50LmFkZEV2ZW50TGlzdGVuZXIodHJpZ2dlciwgb25XTUxUcmlnZ2VyZWQsIG9wdGlvbnMpO1xufVxuXG4vKipcbiAqIFNjaGVkdWxlcyBhbiBhdXRvbWF0aWMgcmVsb2FkIG9mIFdNTCB0byBiZSBwZXJmb3JtZWQgYXMgc29vbiBhcyB0aGUgZG9jdW1lbnQgaXMgZnVsbHkgbG9hZGVkLlxuICovXG5leHBvcnQgZnVuY3Rpb24gRW5hYmxlKCk6IHZvaWQge1xuICAgIHdoZW5SZWFkeShSZWxvYWQpO1xufVxuXG4vKipcbiAqIFJlbG9hZHMgdGhlIFdNTCBwYWdlIGJ5IGFkZGluZyBuZWNlc3NhcnkgZXZlbnQgbGlzdGVuZXJzIGFuZCBicm93c2VyIGxpc3RlbmVycy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIFJlbG9hZCgpOiB2b2lkIHtcbiAgICB0cmlnZ2VyUmVnaXN0cnkucmVzZXQoKTtcbiAgICBkb2N1bWVudC5ib2R5LnF1ZXJ5U2VsZWN0b3JBbGwoJ1t3bWwtZXZlbnRdLCBbd21sLXdpbmRvd10sIFt3bWwtb3BlbnVybF0sIFtkYXRhLXdtbC1ldmVudF0sIFtkYXRhLXdtbC13aW5kb3ddLCBbZGF0YS13bWwtb3BlbnVybF0nKS5mb3JFYWNoKGFkZFdNTExpc3RlbmVycyk7XG59XG4iLCAiLypcbiBfXHQgICBfX1x0ICBfIF9fXG58IHxcdCAvIC9fX18gXyhfKSAvX19fX1xufCB8IC98IC8gLyBfXyBgLyAvIC8gX19fL1xufCB8LyB8LyAvIC9fLyAvIC8gKF9fICApXG58X18vfF9fL1xcX18sXy9fL18vX19fXy9cblRoZSBlbGVjdHJvbiBhbHRlcm5hdGl2ZSBmb3IgR29cbihjKSBMZWEgQW50aG9ueSAyMDE5LXByZXNlbnRcbiovXG5cbmltcG9ydCB7IG5ld1J1bnRpbWVDYWxsZXIsIG9iamVjdE5hbWVzIH0gZnJvbSBcIi4vcnVudGltZS5qc1wiO1xuXG5jb25zdCBjYWxsID0gbmV3UnVudGltZUNhbGxlcihvYmplY3ROYW1lcy5Ccm93c2VyKTtcblxuY29uc3QgQnJvd3Nlck9wZW5VUkwgPSAwO1xuXG4vKipcbiAqIE9wZW4gYSBicm93c2VyIHdpbmRvdyB0byB0aGUgZ2l2ZW4gVVJMLlxuICpcbiAqIEBwYXJhbSB1cmwgLSBUaGUgVVJMIHRvIG9wZW5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIE9wZW5VUkwodXJsOiBzdHJpbmcgfCBVUkwpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICByZXR1cm4gY2FsbChCcm93c2VyT3BlblVSTCwge3VybDogdXJsLnRvU3RyaW5nKCl9KTtcbn1cbiIsICIvLyBTb3VyY2U6IGh0dHBzOi8vZ2l0aHViLmNvbS9haS9uYW5vaWRcblxuLy8gVGhlIE1JVCBMaWNlbnNlIChNSVQpXG4vL1xuLy8gQ29weXJpZ2h0IDIwMTcgQW5kcmV5IFNpdG5payA8YW5kcmV5QHNpdG5pay5ydT5cbi8vXG4vLyBQZXJtaXNzaW9uIGlzIGhlcmVieSBncmFudGVkLCBmcmVlIG9mIGNoYXJnZSwgdG8gYW55IHBlcnNvbiBvYnRhaW5pbmcgYSBjb3B5IG9mXG4vLyB0aGlzIHNvZnR3YXJlIGFuZCBhc3NvY2lhdGVkIGRvY3VtZW50YXRpb24gZmlsZXMgKHRoZSBcIlNvZnR3YXJlXCIpLCB0byBkZWFsIGluXG4vLyB0aGUgU29mdHdhcmUgd2l0aG91dCByZXN0cmljdGlvbiwgaW5jbHVkaW5nIHdpdGhvdXQgbGltaXRhdGlvbiB0aGUgcmlnaHRzIHRvXG4vLyB1c2UsIGNvcHksIG1vZGlmeSwgbWVyZ2UsIHB1Ymxpc2gsIGRpc3RyaWJ1dGUsIHN1YmxpY2Vuc2UsIGFuZC9vciBzZWxsIGNvcGllcyBvZlxuLy8gdGhlIFNvZnR3YXJlLCBhbmQgdG8gcGVybWl0IHBlcnNvbnMgdG8gd2hvbSB0aGUgU29mdHdhcmUgaXMgZnVybmlzaGVkIHRvIGRvIHNvLFxuLy8gICAgIHN1YmplY3QgdG8gdGhlIGZvbGxvd2luZyBjb25kaXRpb25zOlxuLy9cbi8vICAgICBUaGUgYWJvdmUgY29weXJpZ2h0IG5vdGljZSBhbmQgdGhpcyBwZXJtaXNzaW9uIG5vdGljZSBzaGFsbCBiZSBpbmNsdWRlZCBpbiBhbGxcbi8vIGNvcGllcyBvciBzdWJzdGFudGlhbCBwb3J0aW9ucyBvZiB0aGUgU29mdHdhcmUuXG4vL1xuLy8gICAgIFRIRSBTT0ZUV0FSRSBJUyBQUk9WSURFRCBcIkFTIElTXCIsIFdJVEhPVVQgV0FSUkFOVFkgT0YgQU5ZIEtJTkQsIEVYUFJFU1MgT1Jcbi8vIElNUExJRUQsIElOQ0xVRElORyBCVVQgTk9UIExJTUlURUQgVE8gVEhFIFdBUlJBTlRJRVMgT0YgTUVSQ0hBTlRBQklMSVRZLCBGSVRORVNTXG4vLyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UgQU5EIE5PTklORlJJTkdFTUVOVC4gSU4gTk8gRVZFTlQgU0hBTEwgVEhFIEFVVEhPUlMgT1Jcbi8vIENPUFlSSUdIVCBIT0xERVJTIEJFIExJQUJMRSBGT1IgQU5ZIENMQUlNLCBEQU1BR0VTIE9SIE9USEVSIExJQUJJTElUWSwgV0hFVEhFUlxuLy8gSU4gQU4gQUNUSU9OIE9GIENPTlRSQUNULCBUT1JUIE9SIE9USEVSV0lTRSwgQVJJU0lORyBGUk9NLCBPVVQgT0YgT1IgSU5cbi8vIENPTk5FQ1RJT04gV0lUSCBUSEUgU09GVFdBUkUgT1IgVEhFIFVTRSBPUiBPVEhFUiBERUFMSU5HUyBJTiBUSEUgU09GVFdBUkUuXG5cbi8vIFRoaXMgYWxwaGFiZXQgdXNlcyBgQS1aYS16MC05Xy1gIHN5bWJvbHMuXG4vLyBUaGUgb3JkZXIgb2YgY2hhcmFjdGVycyBpcyBvcHRpbWl6ZWQgZm9yIGJldHRlciBnemlwIGFuZCBicm90bGkgY29tcHJlc3Npb24uXG4vLyBSZWZlcmVuY2VzIHRvIHRoZSBzYW1lIGZpbGUgKHdvcmtzIGJvdGggZm9yIGd6aXAgYW5kIGJyb3RsaSk6XG4vLyBgJ3VzZWAsIGBhbmRvbWAsIGFuZCBgcmljdCdgXG4vLyBSZWZlcmVuY2VzIHRvIHRoZSBicm90bGkgZGVmYXVsdCBkaWN0aW9uYXJ5OlxuLy8gYC0yNlRgLCBgMTk4M2AsIGA0MHB4YCwgYDc1cHhgLCBgYnVzaGAsIGBqYWNrYCwgYG1pbmRgLCBgdmVyeWAsIGFuZCBgd29sZmBcbmNvbnN0IHVybEFscGhhYmV0ID1cbiAgICAndXNlYW5kb20tMjZUMTk4MzQwUFg3NXB4SkFDS1ZFUllNSU5EQlVTSFdPTEZfR1FaYmZnaGprbHF2d3l6cmljdCdcblxuZXhwb3J0IGZ1bmN0aW9uIG5hbm9pZChzaXplOiBudW1iZXIgPSAyMSk6IHN0cmluZyB7XG4gICAgbGV0IGlkID0gJydcbiAgICAvLyBBIGNvbXBhY3QgYWx0ZXJuYXRpdmUgZm9yIGBmb3IgKHZhciBpID0gMDsgaSA8IHN0ZXA7IGkrKylgLlxuICAgIGxldCBpID0gc2l6ZSB8IDBcbiAgICB3aGlsZSAoaS0tKSB7XG4gICAgICAgIC8vIGB8IDBgIGlzIG1vcmUgY29tcGFjdCBhbmQgZmFzdGVyIHRoYW4gYE1hdGguZmxvb3IoKWAuXG4gICAgICAgIGlkICs9IHVybEFscGhhYmV0WyhNYXRoLnJhbmRvbSgpICogNjQpIHwgMF1cbiAgICB9XG4gICAgcmV0dXJuIGlkXG59XG4iLCAiLypcbiBfICAgICBfXyAgICAgXyBfX1xufCB8ICAvIC9fX18gXyhfKSAvX19fX1xufCB8IC98IC8gLyBfXyBgLyAvIC8gX19fL1xufCB8LyB8LyAvIC9fLyAvIC8gKF9fICApXG58X18vfF9fL1xcX18sXy9fL18vX19fXy9cblRoZSBlbGVjdHJvbiBhbHRlcm5hdGl2ZSBmb3IgR29cbihjKSBMZWEgQW50aG9ueSAyMDE5LXByZXNlbnRcbiovXG5cbmltcG9ydCB7IG5hbm9pZCB9IGZyb20gXCIuL25hbm9pZC5qc1wiO1xuXG5jb25zdCBydW50aW1lVVJMID0gd2luZG93LmxvY2F0aW9uLm9yaWdpbiArIFwiL3dhaWxzL3J1bnRpbWVcIjtcblxuLy8gUmUtZXhwb3J0IG5hbm9pZCBmb3IgY3VzdG9tIHRyYW5zcG9ydCBpbXBsZW1lbnRhdGlvbnNcbmV4cG9ydCB7IG5hbm9pZCB9O1xuXG4vLyBPYmplY3QgTmFtZXNcbmV4cG9ydCBjb25zdCBvYmplY3ROYW1lcyA9IE9iamVjdC5mcmVlemUoe1xuICAgIENhbGw6IDAsXG4gICAgQ2xpcGJvYXJkOiAxLFxuICAgIEFwcGxpY2F0aW9uOiAyLFxuICAgIEV2ZW50czogMyxcbiAgICBDb250ZXh0TWVudTogNCxcbiAgICBEaWFsb2c6IDUsXG4gICAgV2luZG93OiA2LFxuICAgIFNjcmVlbnM6IDcsXG4gICAgU3lzdGVtOiA4LFxuICAgIEJyb3dzZXI6IDksXG4gICAgQ2FuY2VsQ2FsbDogMTAsXG4gICAgSU9TOiAxMSxcbn0pO1xuZXhwb3J0IGxldCBjbGllbnRJZCA9IG5hbm9pZCgpO1xuXG4vKipcbiAqIFJ1bnRpbWVUcmFuc3BvcnQgZGVmaW5lcyB0aGUgaW50ZXJmYWNlIGZvciBjdXN0b20gSVBDIHRyYW5zcG9ydCBpbXBsZW1lbnRhdGlvbnMuXG4gKiBJbXBsZW1lbnQgdGhpcyBpbnRlcmZhY2UgdG8gdXNlIFdlYlNvY2tldHMsIGN1c3RvbSBwcm90b2NvbHMsIG9yIGFueSBvdGhlclxuICogdHJhbnNwb3J0IG1lY2hhbmlzbSBpbnN0ZWFkIG9mIHRoZSBkZWZhdWx0IEhUVFAgZmV0Y2guXG4gKi9cbmV4cG9ydCBpbnRlcmZhY2UgUnVudGltZVRyYW5zcG9ydCB7XG4gICAgLyoqXG4gICAgICogU2VuZCBhIHJ1bnRpbWUgY2FsbCBhbmQgcmV0dXJuIHRoZSByZXNwb25zZS5cbiAgICAgKlxuICAgICAqIEBwYXJhbSBvYmplY3RJRCAtIFRoZSBXYWlscyBvYmplY3QgSUQgKDA9Q2FsbCwgMT1DbGlwYm9hcmQsIGV0Yy4pXG4gICAgICogQHBhcmFtIG1ldGhvZCAtIFRoZSBtZXRob2QgSUQgdG8gY2FsbFxuICAgICAqIEBwYXJhbSB3aW5kb3dOYW1lIC0gT3B0aW9uYWwgd2luZG93IG5hbWVcbiAgICAgKiBAcGFyYW0gYXJncyAtIEFyZ3VtZW50cyB0byBwYXNzICh3aWxsIGJlIEpTT04gc3RyaW5naWZpZWQgaWYgcHJlc2VudClcbiAgICAgKiBAcmV0dXJucyBQcm9taXNlIHRoYXQgcmVzb2x2ZXMgd2l0aCB0aGUgcmVzcG9uc2UgZGF0YVxuICAgICAqL1xuICAgIGNhbGwob2JqZWN0SUQ6IG51bWJlciwgbWV0aG9kOiBudW1iZXIsIHdpbmRvd05hbWU6IHN0cmluZywgYXJnczogYW55KTogUHJvbWlzZTxhbnk+O1xufVxuXG4vKipcbiAqIEN1c3RvbSB0cmFuc3BvcnQgaW1wbGVtZW50YXRpb24gKGNhbiBiZSBzZXQgYnkgdXNlcilcbiAqL1xubGV0IGN1c3RvbVRyYW5zcG9ydDogUnVudGltZVRyYW5zcG9ydCB8IG51bGwgPSBudWxsO1xuXG4vKipcbiAqIFNldCBhIGN1c3RvbSB0cmFuc3BvcnQgZm9yIGFsbCBXYWlscyBydW50aW1lIGNhbGxzLlxuICogVGhpcyBhbGxvd3MgeW91IHRvIHJlcGxhY2UgdGhlIGRlZmF1bHQgSFRUUCBmZXRjaCB0cmFuc3BvcnQgd2l0aFxuICogV2ViU29ja2V0cywgY3VzdG9tIHByb3RvY29scywgb3IgYW55IG90aGVyIG1lY2hhbmlzbS5cbiAqXG4gKiBAcGFyYW0gdHJhbnNwb3J0IC0gWW91ciBjdXN0b20gdHJhbnNwb3J0IGltcGxlbWVudGF0aW9uXG4gKlxuICogQGV4YW1wbGVcbiAqIGBgYHR5cGVzY3JpcHRcbiAqIGltcG9ydCB7IHNldFRyYW5zcG9ydCB9IGZyb20gJy93YWlscy9ydW50aW1lLmpzJztcbiAqXG4gKiBjb25zdCB3c1RyYW5zcG9ydCA9IHtcbiAqICAgY2FsbDogYXN5bmMgKG9iamVjdElELCBtZXRob2QsIHdpbmRvd05hbWUsIGFyZ3MpID0+IHtcbiAqICAgICAvLyBZb3VyIFdlYlNvY2tldCBpbXBsZW1lbnRhdGlvblxuICogICB9XG4gKiB9O1xuICpcbiAqIHNldFRyYW5zcG9ydCh3c1RyYW5zcG9ydCk7XG4gKiBgYGBcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHNldFRyYW5zcG9ydCh0cmFuc3BvcnQ6IFJ1bnRpbWVUcmFuc3BvcnQgfCBudWxsKTogdm9pZCB7XG4gICAgY3VzdG9tVHJhbnNwb3J0ID0gdHJhbnNwb3J0O1xufVxuXG4vKipcbiAqIEdldCB0aGUgY3VycmVudCB0cmFuc3BvcnQgKHVzZWZ1bCBmb3IgZXh0ZW5kaW5nL3dyYXBwaW5nKVxuICovXG5leHBvcnQgZnVuY3Rpb24gZ2V0VHJhbnNwb3J0KCk6IFJ1bnRpbWVUcmFuc3BvcnQgfCBudWxsIHtcbiAgICByZXR1cm4gY3VzdG9tVHJhbnNwb3J0O1xufVxuXG4vKipcbiAqIENyZWF0ZXMgYSBuZXcgcnVudGltZSBjYWxsZXIgd2l0aCBzcGVjaWZpZWQgSUQuXG4gKlxuICogQHBhcmFtIG9iamVjdCAtIFRoZSBvYmplY3QgdG8gaW52b2tlIHRoZSBtZXRob2Qgb24uXG4gKiBAcGFyYW0gd2luZG93TmFtZSAtIFRoZSBuYW1lIG9mIHRoZSB3aW5kb3cuXG4gKiBAcmV0dXJuIFRoZSBuZXcgcnVudGltZSBjYWxsZXIgZnVuY3Rpb24uXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBuZXdSdW50aW1lQ2FsbGVyKG9iamVjdDogbnVtYmVyLCB3aW5kb3dOYW1lOiBzdHJpbmcgPSAnJykge1xuICAgIHJldHVybiBmdW5jdGlvbiAobWV0aG9kOiBudW1iZXIsIGFyZ3M6IGFueSA9IG51bGwpIHtcbiAgICAgICAgcmV0dXJuIHJ1bnRpbWVDYWxsV2l0aElEKG9iamVjdCwgbWV0aG9kLCB3aW5kb3dOYW1lLCBhcmdzKTtcbiAgICB9O1xufVxuXG5hc3luYyBmdW5jdGlvbiBydW50aW1lQ2FsbFdpdGhJRChvYmplY3RJRDogbnVtYmVyLCBtZXRob2Q6IG51bWJlciwgd2luZG93TmFtZTogc3RyaW5nLCBhcmdzOiBhbnkpOiBQcm9taXNlPGFueT4ge1xuICAgIC8vIFVzZSBjdXN0b20gdHJhbnNwb3J0IGlmIGF2YWlsYWJsZVxuICAgIGlmIChjdXN0b21UcmFuc3BvcnQpIHtcbiAgICAgICAgcmV0dXJuIGN1c3RvbVRyYW5zcG9ydC5jYWxsKG9iamVjdElELCBtZXRob2QsIHdpbmRvd05hbWUsIGFyZ3MpO1xuICAgIH1cblxuICAgIC8vIERlZmF1bHQgSFRUUCBmZXRjaCB0cmFuc3BvcnRcbiAgICBsZXQgdXJsID0gbmV3IFVSTChydW50aW1lVVJMKTtcblxuICAgIGxldCBib2R5OiB7IG9iamVjdDogbnVtYmVyOyBtZXRob2Q6IG51bWJlciwgYXJncz86IGFueSB9ID0ge1xuICAgICAgb2JqZWN0OiBvYmplY3RJRCxcbiAgICAgIG1ldGhvZFxuICAgIH1cbiAgICBpZiAoYXJncyAhPT0gbnVsbCAmJiBhcmdzICE9PSB1bmRlZmluZWQpIHtcbiAgICAgIGJvZHkuYXJncyA9IGFyZ3M7XG4gICAgfVxuXG4gICAgbGV0IGhlYWRlcnM6IFJlY29yZDxzdHJpbmcsIHN0cmluZz4gPSB7XG4gICAgICAgIFtcIngtd2FpbHMtY2xpZW50LWlkXCJdOiBjbGllbnRJZCxcbiAgICAgICAgW1wiQ29udGVudC1UeXBlXCJdOiBcImFwcGxpY2F0aW9uL2pzb25cIlxuICAgIH1cbiAgICBpZiAod2luZG93TmFtZSkge1xuICAgICAgICBoZWFkZXJzW1wieC13YWlscy13aW5kb3ctbmFtZVwiXSA9IHdpbmRvd05hbWU7XG4gICAgfVxuXG4gICAgbGV0IHJlc3BvbnNlID0gYXdhaXQgZmV0Y2godXJsLCB7XG4gICAgICBtZXRob2Q6ICdQT1NUJyxcbiAgICAgIGhlYWRlcnMsXG4gICAgICBib2R5OiBKU09OLnN0cmluZ2lmeShib2R5KVxuICAgIH0pO1xuICAgIGlmICghcmVzcG9uc2Uub2spIHtcbiAgICAgICAgdGhyb3cgbmV3IEVycm9yKGF3YWl0IHJlc3BvbnNlLnRleHQoKSk7XG4gICAgfVxuXG4gICAgaWYgKChyZXNwb25zZS5oZWFkZXJzLmdldChcIkNvbnRlbnQtVHlwZVwiKT8uaW5kZXhPZihcImFwcGxpY2F0aW9uL2pzb25cIikgPz8gLTEpICE9PSAtMSkge1xuICAgICAgICByZXR1cm4gcmVzcG9uc2UuanNvbigpO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiByZXNwb25zZS50ZXh0KCk7XG4gICAgfVxufVxuIiwgIi8qXG4gX1x0ICAgX19cdCAgXyBfX1xufCB8XHQgLyAvX19fIF8oXykgL19fX19cbnwgfCAvfCAvIC8gX18gYC8gLyAvIF9fXy9cbnwgfC8gfC8gLyAvXy8gLyAvIChfXyAgKVxufF9fL3xfXy9cXF9fLF8vXy9fL19fX18vXG5UaGUgZWxlY3Ryb24gYWx0ZXJuYXRpdmUgZm9yIEdvXG4oYykgTGVhIEFudGhvbnkgMjAxOS1wcmVzZW50XG4qL1xuXG5pbXBvcnQge25ld1J1bnRpbWVDYWxsZXIsIG9iamVjdE5hbWVzfSBmcm9tIFwiLi9ydW50aW1lLmpzXCI7XG5cbi8vIHNldHVwXG53aW5kb3cuX3dhaWxzID0gd2luZG93Ll93YWlscyB8fCB7fTtcblxuY29uc3QgY2FsbCA9IG5ld1J1bnRpbWVDYWxsZXIob2JqZWN0TmFtZXMuRGlhbG9nKTtcblxuLy8gRGVmaW5lIGNvbnN0YW50cyBmcm9tIHRoZSBgbWV0aG9kc2Agb2JqZWN0IGluIFRpdGxlIENhc2VcbmNvbnN0IERpYWxvZ0luZm8gPSAwO1xuY29uc3QgRGlhbG9nV2FybmluZyA9IDE7XG5jb25zdCBEaWFsb2dFcnJvciA9IDI7XG5jb25zdCBEaWFsb2dRdWVzdGlvbiA9IDM7XG5jb25zdCBEaWFsb2dPcGVuRmlsZSA9IDQ7XG5jb25zdCBEaWFsb2dTYXZlRmlsZSA9IDU7XG5cbmV4cG9ydCBpbnRlcmZhY2UgT3BlbkZpbGVEaWFsb2dPcHRpb25zIHtcbiAgICAvKiogSW5kaWNhdGVzIGlmIGRpcmVjdG9yaWVzIGNhbiBiZSBjaG9zZW4uICovXG4gICAgQ2FuQ2hvb3NlRGlyZWN0b3JpZXM/OiBib29sZWFuO1xuICAgIC8qKiBJbmRpY2F0ZXMgaWYgZmlsZXMgY2FuIGJlIGNob3Nlbi4gKi9cbiAgICBDYW5DaG9vc2VGaWxlcz86IGJvb2xlYW47XG4gICAgLyoqIEluZGljYXRlcyBpZiBkaXJlY3RvcmllcyBjYW4gYmUgY3JlYXRlZC4gKi9cbiAgICBDYW5DcmVhdGVEaXJlY3Rvcmllcz86IGJvb2xlYW47XG4gICAgLyoqIEluZGljYXRlcyBpZiBoaWRkZW4gZmlsZXMgc2hvdWxkIGJlIHNob3duLiAqL1xuICAgIFNob3dIaWRkZW5GaWxlcz86IGJvb2xlYW47XG4gICAgLyoqIEluZGljYXRlcyBpZiBhbGlhc2VzIHNob3VsZCBiZSByZXNvbHZlZC4gKi9cbiAgICBSZXNvbHZlc0FsaWFzZXM/OiBib29sZWFuO1xuICAgIC8qKiBJbmRpY2F0ZXMgaWYgbXVsdGlwbGUgc2VsZWN0aW9uIGlzIGFsbG93ZWQuICovXG4gICAgQWxsb3dzTXVsdGlwbGVTZWxlY3Rpb24/OiBib29sZWFuO1xuICAgIC8qKiBJbmRpY2F0ZXMgaWYgdGhlIGV4dGVuc2lvbiBzaG91bGQgYmUgaGlkZGVuLiAqL1xuICAgIEhpZGVFeHRlbnNpb24/OiBib29sZWFuO1xuICAgIC8qKiBJbmRpY2F0ZXMgaWYgaGlkZGVuIGV4dGVuc2lvbnMgY2FuIGJlIHNlbGVjdGVkLiAqL1xuICAgIENhblNlbGVjdEhpZGRlbkV4dGVuc2lvbj86IGJvb2xlYW47XG4gICAgLyoqIEluZGljYXRlcyBpZiBmaWxlIHBhY2thZ2VzIHNob3VsZCBiZSB0cmVhdGVkIGFzIGRpcmVjdG9yaWVzLiAqL1xuICAgIFRyZWF0c0ZpbGVQYWNrYWdlc0FzRGlyZWN0b3JpZXM/OiBib29sZWFuO1xuICAgIC8qKiBJbmRpY2F0ZXMgaWYgb3RoZXIgZmlsZSB0eXBlcyBhcmUgYWxsb3dlZC4gKi9cbiAgICBBbGxvd3NPdGhlckZpbGV0eXBlcz86IGJvb2xlYW47XG4gICAgLyoqIEFycmF5IG9mIGZpbGUgZmlsdGVycy4gKi9cbiAgICBGaWx0ZXJzPzogRmlsZUZpbHRlcltdO1xuICAgIC8qKiBUaXRsZSBvZiB0aGUgZGlhbG9nLiAqL1xuICAgIFRpdGxlPzogc3RyaW5nO1xuICAgIC8qKiBNZXNzYWdlIHRvIHNob3cgaW4gdGhlIGRpYWxvZy4gKi9cbiAgICBNZXNzYWdlPzogc3RyaW5nO1xuICAgIC8qKiBUZXh0IHRvIGRpc3BsYXkgb24gdGhlIGJ1dHRvbi4gKi9cbiAgICBCdXR0b25UZXh0Pzogc3RyaW5nO1xuICAgIC8qKiBEaXJlY3RvcnkgdG8gb3BlbiBpbiB0aGUgZGlhbG9nLiAqL1xuICAgIERpcmVjdG9yeT86IHN0cmluZztcbiAgICAvKiogSW5kaWNhdGVzIGlmIHRoZSBkaWFsb2cgc2hvdWxkIGFwcGVhciBkZXRhY2hlZCBmcm9tIHRoZSBtYWluIHdpbmRvdy4gKi9cbiAgICBEZXRhY2hlZD86IGJvb2xlYW47XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgU2F2ZUZpbGVEaWFsb2dPcHRpb25zIHtcbiAgICAvKiogRGVmYXVsdCBmaWxlbmFtZSB0byB1c2UgaW4gdGhlIGRpYWxvZy4gKi9cbiAgICBGaWxlbmFtZT86IHN0cmluZztcbiAgICAvKiogSW5kaWNhdGVzIGlmIGRpcmVjdG9yaWVzIGNhbiBiZSBjaG9zZW4uICovXG4gICAgQ2FuQ2hvb3NlRGlyZWN0b3JpZXM/OiBib29sZWFuO1xuICAgIC8qKiBJbmRpY2F0ZXMgaWYgZmlsZXMgY2FuIGJlIGNob3Nlbi4gKi9cbiAgICBDYW5DaG9vc2VGaWxlcz86IGJvb2xlYW47XG4gICAgLyoqIEluZGljYXRlcyBpZiBkaXJlY3RvcmllcyBjYW4gYmUgY3JlYXRlZC4gKi9cbiAgICBDYW5DcmVhdGVEaXJlY3Rvcmllcz86IGJvb2xlYW47XG4gICAgLyoqIEluZGljYXRlcyBpZiBoaWRkZW4gZmlsZXMgc2hvdWxkIGJlIHNob3duLiAqL1xuICAgIFNob3dIaWRkZW5GaWxlcz86IGJvb2xlYW47XG4gICAgLyoqIEluZGljYXRlcyBpZiBhbGlhc2VzIHNob3VsZCBiZSByZXNvbHZlZC4gKi9cbiAgICBSZXNvbHZlc0FsaWFzZXM/OiBib29sZWFuO1xuICAgIC8qKiBJbmRpY2F0ZXMgaWYgdGhlIGV4dGVuc2lvbiBzaG91bGQgYmUgaGlkZGVuLiAqL1xuICAgIEhpZGVFeHRlbnNpb24/OiBib29sZWFuO1xuICAgIC8qKiBJbmRpY2F0ZXMgaWYgaGlkZGVuIGV4dGVuc2lvbnMgY2FuIGJlIHNlbGVjdGVkLiAqL1xuICAgIENhblNlbGVjdEhpZGRlbkV4dGVuc2lvbj86IGJvb2xlYW47XG4gICAgLyoqIEluZGljYXRlcyBpZiBmaWxlIHBhY2thZ2VzIHNob3VsZCBiZSB0cmVhdGVkIGFzIGRpcmVjdG9yaWVzLiAqL1xuICAgIFRyZWF0c0ZpbGVQYWNrYWdlc0FzRGlyZWN0b3JpZXM/OiBib29sZWFuO1xuICAgIC8qKiBJbmRpY2F0ZXMgaWYgb3RoZXIgZmlsZSB0eXBlcyBhcmUgYWxsb3dlZC4gKi9cbiAgICBBbGxvd3NPdGhlckZpbGV0eXBlcz86IGJvb2xlYW47XG4gICAgLyoqIEFycmF5IG9mIGZpbGUgZmlsdGVycy4gKi9cbiAgICBGaWx0ZXJzPzogRmlsZUZpbHRlcltdO1xuICAgIC8qKiBUaXRsZSBvZiB0aGUgZGlhbG9nLiAqL1xuICAgIFRpdGxlPzogc3RyaW5nO1xuICAgIC8qKiBNZXNzYWdlIHRvIHNob3cgaW4gdGhlIGRpYWxvZy4gKi9cbiAgICBNZXNzYWdlPzogc3RyaW5nO1xuICAgIC8qKiBUZXh0IHRvIGRpc3BsYXkgb24gdGhlIGJ1dHRvbi4gKi9cbiAgICBCdXR0b25UZXh0Pzogc3RyaW5nO1xuICAgIC8qKiBEaXJlY3RvcnkgdG8gb3BlbiBpbiB0aGUgZGlhbG9nLiAqL1xuICAgIERpcmVjdG9yeT86IHN0cmluZztcbiAgICAvKiogSW5kaWNhdGVzIGlmIHRoZSBkaWFsb2cgc2hvdWxkIGFwcGVhciBkZXRhY2hlZCBmcm9tIHRoZSBtYWluIHdpbmRvdy4gKi9cbiAgICBEZXRhY2hlZD86IGJvb2xlYW47XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgTWVzc2FnZURpYWxvZ09wdGlvbnMge1xuICAgIC8qKiBUaGUgdGl0bGUgb2YgdGhlIGRpYWxvZyB3aW5kb3cuICovXG4gICAgVGl0bGU/OiBzdHJpbmc7XG4gICAgLyoqIFRoZSBtYWluIG1lc3NhZ2UgdG8gc2hvdyBpbiB0aGUgZGlhbG9nLiAqL1xuICAgIE1lc3NhZ2U/OiBzdHJpbmc7XG4gICAgLyoqIEFycmF5IG9mIGJ1dHRvbiBvcHRpb25zIHRvIHNob3cgaW4gdGhlIGRpYWxvZy4gKi9cbiAgICBCdXR0b25zPzogQnV0dG9uW107XG4gICAgLyoqIFRydWUgaWYgdGhlIGRpYWxvZyBzaG91bGQgYXBwZWFyIGRldGFjaGVkIGZyb20gdGhlIG1haW4gd2luZG93IChpZiBhcHBsaWNhYmxlKS4gKi9cbiAgICBEZXRhY2hlZD86IGJvb2xlYW47XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgQnV0dG9uIHtcbiAgICAvKiogVGV4dCB0aGF0IGFwcGVhcnMgd2l0aGluIHRoZSBidXR0b24uICovXG4gICAgTGFiZWw/OiBzdHJpbmc7XG4gICAgLyoqIFRydWUgaWYgdGhlIGJ1dHRvbiBzaG91bGQgY2FuY2VsIGFuIG9wZXJhdGlvbiB3aGVuIGNsaWNrZWQuICovXG4gICAgSXNDYW5jZWw/OiBib29sZWFuO1xuICAgIC8qKiBUcnVlIGlmIHRoZSBidXR0b24gc2hvdWxkIGJlIHRoZSBkZWZhdWx0IGFjdGlvbiB3aGVuIHRoZSB1c2VyIHByZXNzZXMgZW50ZXIuICovXG4gICAgSXNEZWZhdWx0PzogYm9vbGVhbjtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBGaWxlRmlsdGVyIHtcbiAgICAvKiogRGlzcGxheSBuYW1lIGZvciB0aGUgZmlsdGVyLCBpdCBjb3VsZCBiZSBcIlRleHQgRmlsZXNcIiwgXCJJbWFnZXNcIiBldGMuICovXG4gICAgRGlzcGxheU5hbWU/OiBzdHJpbmc7XG4gICAgLyoqIFBhdHRlcm4gdG8gbWF0Y2ggZm9yIHRoZSBmaWx0ZXIsIGUuZy4gXCIqLnR4dDsqLm1kXCIgZm9yIHRleHQgbWFya2Rvd24gZmlsZXMuICovXG4gICAgUGF0dGVybj86IHN0cmluZztcbn1cblxuLyoqXG4gKiBQcmVzZW50cyBhIGRpYWxvZyBvZiBzcGVjaWZpZWQgdHlwZSB3aXRoIHRoZSBnaXZlbiBvcHRpb25zLlxuICpcbiAqIEBwYXJhbSB0eXBlIC0gRGlhbG9nIHR5cGUuXG4gKiBAcGFyYW0gb3B0aW9ucyAtIE9wdGlvbnMgZm9yIHRoZSBkaWFsb2cuXG4gKiBAcmV0dXJucyBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB3aXRoIHJlc3VsdCBvZiBkaWFsb2cuXG4gKi9cbmZ1bmN0aW9uIGRpYWxvZyh0eXBlOiBudW1iZXIsIG9wdGlvbnM6IE1lc3NhZ2VEaWFsb2dPcHRpb25zIHwgT3BlbkZpbGVEaWFsb2dPcHRpb25zIHwgU2F2ZUZpbGVEaWFsb2dPcHRpb25zID0ge30pOiBQcm9taXNlPGFueT4ge1xuICAgIHJldHVybiBjYWxsKHR5cGUsIG9wdGlvbnMpO1xufVxuXG4vKipcbiAqIFByZXNlbnRzIGFuIGluZm8gZGlhbG9nLlxuICpcbiAqIEBwYXJhbSBvcHRpb25zIC0gRGlhbG9nIG9wdGlvbnNcbiAqIEByZXR1cm5zIEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHdpdGggdGhlIGxhYmVsIG9mIHRoZSBjaG9zZW4gYnV0dG9uLlxuICovXG5leHBvcnQgZnVuY3Rpb24gSW5mbyhvcHRpb25zOiBNZXNzYWdlRGlhbG9nT3B0aW9ucyk6IFByb21pc2U8c3RyaW5nPiB7IHJldHVybiBkaWFsb2coRGlhbG9nSW5mbywgb3B0aW9ucyk7IH1cblxuLyoqXG4gKiBQcmVzZW50cyBhIHdhcm5pbmcgZGlhbG9nLlxuICpcbiAqIEBwYXJhbSBvcHRpb25zIC0gRGlhbG9nIG9wdGlvbnMuXG4gKiBAcmV0dXJucyBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB3aXRoIHRoZSBsYWJlbCBvZiB0aGUgY2hvc2VuIGJ1dHRvbi5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIFdhcm5pbmcob3B0aW9uczogTWVzc2FnZURpYWxvZ09wdGlvbnMpOiBQcm9taXNlPHN0cmluZz4geyByZXR1cm4gZGlhbG9nKERpYWxvZ1dhcm5pbmcsIG9wdGlvbnMpOyB9XG5cbi8qKlxuICogUHJlc2VudHMgYW4gZXJyb3IgZGlhbG9nLlxuICpcbiAqIEBwYXJhbSBvcHRpb25zIC0gRGlhbG9nIG9wdGlvbnMuXG4gKiBAcmV0dXJucyBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB3aXRoIHRoZSBsYWJlbCBvZiB0aGUgY2hvc2VuIGJ1dHRvbi5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIEVycm9yKG9wdGlvbnM6IE1lc3NhZ2VEaWFsb2dPcHRpb25zKTogUHJvbWlzZTxzdHJpbmc+IHsgcmV0dXJuIGRpYWxvZyhEaWFsb2dFcnJvciwgb3B0aW9ucyk7IH1cblxuLyoqXG4gKiBQcmVzZW50cyBhIHF1ZXN0aW9uIGRpYWxvZy5cbiAqXG4gKiBAcGFyYW0gb3B0aW9ucyAtIERpYWxvZyBvcHRpb25zLlxuICogQHJldHVybnMgQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgd2l0aCB0aGUgbGFiZWwgb2YgdGhlIGNob3NlbiBidXR0b24uXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBRdWVzdGlvbihvcHRpb25zOiBNZXNzYWdlRGlhbG9nT3B0aW9ucyk6IFByb21pc2U8c3RyaW5nPiB7IHJldHVybiBkaWFsb2coRGlhbG9nUXVlc3Rpb24sIG9wdGlvbnMpOyB9XG5cbi8qKlxuICogUHJlc2VudHMgYSBmaWxlIHNlbGVjdGlvbiBkaWFsb2cgdG8gcGljayBvbmUgb3IgbW9yZSBmaWxlcyB0byBvcGVuLlxuICpcbiAqIEBwYXJhbSBvcHRpb25zIC0gRGlhbG9nIG9wdGlvbnMuXG4gKiBAcmV0dXJucyBTZWxlY3RlZCBmaWxlIG9yIGxpc3Qgb2YgZmlsZXMsIG9yIGEgYmxhbmsgc3RyaW5nL2VtcHR5IGxpc3QgaWYgbm8gZmlsZSBoYXMgYmVlbiBzZWxlY3RlZC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIE9wZW5GaWxlKG9wdGlvbnM6IE9wZW5GaWxlRGlhbG9nT3B0aW9ucyAmIHsgQWxsb3dzTXVsdGlwbGVTZWxlY3Rpb246IHRydWUgfSk6IFByb21pc2U8c3RyaW5nW10+O1xuZXhwb3J0IGZ1bmN0aW9uIE9wZW5GaWxlKG9wdGlvbnM6IE9wZW5GaWxlRGlhbG9nT3B0aW9ucyAmIHsgQWxsb3dzTXVsdGlwbGVTZWxlY3Rpb24/OiBmYWxzZSB8IHVuZGVmaW5lZCB9KTogUHJvbWlzZTxzdHJpbmc+O1xuZXhwb3J0IGZ1bmN0aW9uIE9wZW5GaWxlKG9wdGlvbnM6IE9wZW5GaWxlRGlhbG9nT3B0aW9ucyk6IFByb21pc2U8c3RyaW5nIHwgc3RyaW5nW10+O1xuZXhwb3J0IGZ1bmN0aW9uIE9wZW5GaWxlKG9wdGlvbnM6IE9wZW5GaWxlRGlhbG9nT3B0aW9ucyk6IFByb21pc2U8c3RyaW5nIHwgc3RyaW5nW10+IHsgcmV0dXJuIGRpYWxvZyhEaWFsb2dPcGVuRmlsZSwgb3B0aW9ucykgPz8gW107IH1cblxuLyoqXG4gKiBQcmVzZW50cyBhIGZpbGUgc2VsZWN0aW9uIGRpYWxvZyB0byBwaWNrIGEgZmlsZSB0byBzYXZlLlxuICpcbiAqIEBwYXJhbSBvcHRpb25zIC0gRGlhbG9nIG9wdGlvbnMuXG4gKiBAcmV0dXJucyBTZWxlY3RlZCBmaWxlLCBvciBhIGJsYW5rIHN0cmluZyBpZiBubyBmaWxlIGhhcyBiZWVuIHNlbGVjdGVkLlxuICovXG5leHBvcnQgZnVuY3Rpb24gU2F2ZUZpbGUob3B0aW9uczogU2F2ZUZpbGVEaWFsb2dPcHRpb25zKTogUHJvbWlzZTxzdHJpbmc+IHsgcmV0dXJuIGRpYWxvZyhEaWFsb2dTYXZlRmlsZSwgb3B0aW9ucyk7IH1cbiIsICIvKlxuIF9cdCAgIF9fXHQgIF8gX19cbnwgfFx0IC8gL19fXyBfKF8pIC9fX19fXG58IHwgL3wgLyAvIF9fIGAvIC8gLyBfX18vXG58IHwvIHwvIC8gL18vIC8gLyAoX18gIClcbnxfXy98X18vXFxfXyxfL18vXy9fX19fL1xuVGhlIGVsZWN0cm9uIGFsdGVybmF0aXZlIGZvciBHb1xuKGMpIExlYSBBbnRob255IDIwMTktcHJlc2VudFxuKi9cblxuaW1wb3J0IHsgbmV3UnVudGltZUNhbGxlciwgb2JqZWN0TmFtZXMgfSBmcm9tIFwiLi9ydW50aW1lLmpzXCI7XG5pbXBvcnQgeyBldmVudExpc3RlbmVycywgTGlzdGVuZXIsIGxpc3RlbmVyT2ZmIH0gZnJvbSBcIi4vbGlzdGVuZXIuanNcIjtcbmltcG9ydCB7IEV2ZW50cyBhcyBDcmVhdGUgfSBmcm9tIFwiLi9jcmVhdGUuanNcIjtcbmltcG9ydCB7IFR5cGVzIH0gZnJvbSBcIi4vZXZlbnRfdHlwZXMuanNcIjtcblxuLy8gU2V0dXBcbndpbmRvdy5fd2FpbHMgPSB3aW5kb3cuX3dhaWxzIHx8IHt9O1xud2luZG93Ll93YWlscy5kaXNwYXRjaFdhaWxzRXZlbnQgPSBkaXNwYXRjaFdhaWxzRXZlbnQ7XG5cbmNvbnN0IGNhbGwgPSBuZXdSdW50aW1lQ2FsbGVyKG9iamVjdE5hbWVzLkV2ZW50cyk7XG5jb25zdCBFbWl0TWV0aG9kID0gMDtcblxuZXhwb3J0ICogZnJvbSBcIi4vZXZlbnRfdHlwZXMuanNcIjtcblxuLyoqXG4gKiBBIHRhYmxlIG9mIGRhdGEgdHlwZXMgZm9yIGFsbCBrbm93biBldmVudHMuXG4gKiBXaWxsIGJlIG1vbmtleS1wYXRjaGVkIGJ5IHRoZSBiaW5kaW5nIGdlbmVyYXRvci5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBDdXN0b21FdmVudHMge31cblxuLyoqXG4gKiBFaXRoZXIgYSBrbm93biBldmVudCBuYW1lIG9yIGFuIGFyYml0cmFyeSBzdHJpbmcuXG4gKi9cbmV4cG9ydCB0eXBlIFdhaWxzRXZlbnROYW1lPEUgZXh0ZW5kcyBrZXlvZiBDdXN0b21FdmVudHMgPSBrZXlvZiBDdXN0b21FdmVudHM+ID0gRSB8IChzdHJpbmcgJiB7fSk7XG5cbi8qKlxuICogVW5pb24gb2YgYWxsIGtub3duIHN5c3RlbSBldmVudCBuYW1lcy5cbiAqL1xudHlwZSBTeXN0ZW1FdmVudE5hbWUgPSB7XG4gICAgW0sgaW4ga2V5b2YgKHR5cGVvZiBUeXBlcyldOiAodHlwZW9mIFR5cGVzKVtLXVtrZXlvZiAoKHR5cGVvZiBUeXBlcylbS10pXVxufSBleHRlbmRzIChpbmZlciBNKSA/IE1ba2V5b2YgTV0gOiBuZXZlcjtcblxuLyoqXG4gKiBUaGUgZGF0YSB0eXBlIGFzc29jaWF0ZWQgdG8gYSBnaXZlbiBldmVudC5cbiAqL1xuZXhwb3J0IHR5cGUgV2FpbHNFdmVudERhdGE8RSBleHRlbmRzIFdhaWxzRXZlbnROYW1lID0gV2FpbHNFdmVudE5hbWU+ID1cbiAgICBFIGV4dGVuZHMga2V5b2YgQ3VzdG9tRXZlbnRzID8gQ3VzdG9tRXZlbnRzW0VdIDogKEUgZXh0ZW5kcyBTeXN0ZW1FdmVudE5hbWUgPyB2b2lkIDogYW55KTtcblxuLyoqXG4gKiBUaGUgdHlwZSBvZiBoYW5kbGVycyBmb3IgYSBnaXZlbiBldmVudC5cbiAqL1xuZXhwb3J0IHR5cGUgV2FpbHNFdmVudENhbGxiYWNrPEUgZXh0ZW5kcyBXYWlsc0V2ZW50TmFtZSA9IFdhaWxzRXZlbnROYW1lPiA9IChldjogV2FpbHNFdmVudDxFPikgPT4gdm9pZDtcblxuLyoqXG4gKiBSZXByZXNlbnRzIGEgc3lzdGVtIGV2ZW50IG9yIGEgY3VzdG9tIGV2ZW50IGVtaXR0ZWQgdGhyb3VnaCB3YWlscy1wcm92aWRlZCBmYWNpbGl0aWVzLlxuICovXG5leHBvcnQgY2xhc3MgV2FpbHNFdmVudDxFIGV4dGVuZHMgV2FpbHNFdmVudE5hbWUgPSBXYWlsc0V2ZW50TmFtZT4ge1xuICAgIC8qKlxuICAgICAqIFRoZSBuYW1lIG9mIHRoZSBldmVudC5cbiAgICAgKi9cbiAgICBuYW1lOiBFO1xuXG4gICAgLyoqXG4gICAgICogT3B0aW9uYWwgZGF0YSBhc3NvY2lhdGVkIHdpdGggdGhlIGVtaXR0ZWQgZXZlbnQuXG4gICAgICovXG4gICAgZGF0YTogV2FpbHNFdmVudERhdGE8RT47XG5cbiAgICAvKipcbiAgICAgKiBOYW1lIG9mIHRoZSBvcmlnaW5hdGluZyB3aW5kb3cuIE9taXR0ZWQgZm9yIGFwcGxpY2F0aW9uIGV2ZW50cy5cbiAgICAgKiBXaWxsIGJlIG92ZXJyaWRkZW4gaWYgc2V0IG1hbnVhbGx5LlxuICAgICAqL1xuICAgIHNlbmRlcj86IHN0cmluZztcblxuICAgIGNvbnN0cnVjdG9yKG5hbWU6IEUsIGRhdGE6IFdhaWxzRXZlbnREYXRhPEU+KTtcbiAgICBjb25zdHJ1Y3RvcihuYW1lOiBXYWlsc0V2ZW50RGF0YTxFPiBleHRlbmRzIG51bGwgfCB2b2lkID8gRSA6IG5ldmVyKVxuICAgIGNvbnN0cnVjdG9yKG5hbWU6IEUsIGRhdGE/OiBhbnkpIHtcbiAgICAgICAgdGhpcy5uYW1lID0gbmFtZTtcbiAgICAgICAgdGhpcy5kYXRhID0gZGF0YSA/PyBudWxsO1xuICAgIH1cbn1cblxuZnVuY3Rpb24gZGlzcGF0Y2hXYWlsc0V2ZW50KGV2ZW50OiBhbnkpIHtcbiAgICBsZXQgbGlzdGVuZXJzID0gZXZlbnRMaXN0ZW5lcnMuZ2V0KGV2ZW50Lm5hbWUpO1xuICAgIGlmICghbGlzdGVuZXJzKSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBsZXQgd2FpbHNFdmVudCA9IG5ldyBXYWlsc0V2ZW50KFxuICAgICAgICBldmVudC5uYW1lLFxuICAgICAgICAoZXZlbnQubmFtZSBpbiBDcmVhdGUpID8gQ3JlYXRlW2V2ZW50Lm5hbWVdKGV2ZW50LmRhdGEpIDogZXZlbnQuZGF0YVxuICAgICk7XG4gICAgaWYgKCdzZW5kZXInIGluIGV2ZW50KSB7XG4gICAgICAgIHdhaWxzRXZlbnQuc2VuZGVyID0gZXZlbnQuc2VuZGVyO1xuICAgIH1cblxuICAgIGxpc3RlbmVycyA9IGxpc3RlbmVycy5maWx0ZXIobGlzdGVuZXIgPT4gIWxpc3RlbmVyLmRpc3BhdGNoKHdhaWxzRXZlbnQpKTtcbiAgICBpZiAobGlzdGVuZXJzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgICBldmVudExpc3RlbmVycy5kZWxldGUoZXZlbnQubmFtZSk7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgZXZlbnRMaXN0ZW5lcnMuc2V0KGV2ZW50Lm5hbWUsIGxpc3RlbmVycyk7XG4gICAgfVxufVxuXG4vKipcbiAqIFJlZ2lzdGVyIGEgY2FsbGJhY2sgZnVuY3Rpb24gdG8gYmUgY2FsbGVkIG11bHRpcGxlIHRpbWVzIGZvciBhIHNwZWNpZmljIGV2ZW50LlxuICpcbiAqIEBwYXJhbSBldmVudE5hbWUgLSBUaGUgbmFtZSBvZiB0aGUgZXZlbnQgdG8gcmVnaXN0ZXIgdGhlIGNhbGxiYWNrIGZvci5cbiAqIEBwYXJhbSBjYWxsYmFjayAtIFRoZSBjYWxsYmFjayBmdW5jdGlvbiB0byBiZSBjYWxsZWQgd2hlbiB0aGUgZXZlbnQgaXMgdHJpZ2dlcmVkLlxuICogQHBhcmFtIG1heENhbGxiYWNrcyAtIFRoZSBtYXhpbXVtIG51bWJlciBvZiB0aW1lcyB0aGUgY2FsbGJhY2sgY2FuIGJlIGNhbGxlZCBmb3IgdGhlIGV2ZW50LiBPbmNlIHRoZSBtYXhpbXVtIG51bWJlciBpcyByZWFjaGVkLCB0aGUgY2FsbGJhY2sgd2lsbCBubyBsb25nZXIgYmUgY2FsbGVkLlxuICogQHJldHVybnMgQSBmdW5jdGlvbiB0aGF0LCB3aGVuIGNhbGxlZCwgd2lsbCB1bnJlZ2lzdGVyIHRoZSBjYWxsYmFjayBmcm9tIHRoZSBldmVudC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIE9uTXVsdGlwbGU8RSBleHRlbmRzIFdhaWxzRXZlbnROYW1lID0gV2FpbHNFdmVudE5hbWU+KGV2ZW50TmFtZTogRSwgY2FsbGJhY2s6IFdhaWxzRXZlbnRDYWxsYmFjazxFPiwgbWF4Q2FsbGJhY2tzOiBudW1iZXIpIHtcbiAgICBsZXQgbGlzdGVuZXJzID0gZXZlbnRMaXN0ZW5lcnMuZ2V0KGV2ZW50TmFtZSkgfHwgW107XG4gICAgY29uc3QgdGhpc0xpc3RlbmVyID0gbmV3IExpc3RlbmVyKGV2ZW50TmFtZSwgY2FsbGJhY2ssIG1heENhbGxiYWNrcyk7XG4gICAgbGlzdGVuZXJzLnB1c2godGhpc0xpc3RlbmVyKTtcbiAgICBldmVudExpc3RlbmVycy5zZXQoZXZlbnROYW1lLCBsaXN0ZW5lcnMpO1xuICAgIHJldHVybiAoKSA9PiBsaXN0ZW5lck9mZih0aGlzTGlzdGVuZXIpO1xufVxuXG4vKipcbiAqIFJlZ2lzdGVycyBhIGNhbGxiYWNrIGZ1bmN0aW9uIHRvIGJlIGV4ZWN1dGVkIHdoZW4gdGhlIHNwZWNpZmllZCBldmVudCBvY2N1cnMuXG4gKlxuICogQHBhcmFtIGV2ZW50TmFtZSAtIFRoZSBuYW1lIG9mIHRoZSBldmVudCB0byByZWdpc3RlciB0aGUgY2FsbGJhY2sgZm9yLlxuICogQHBhcmFtIGNhbGxiYWNrIC0gVGhlIGNhbGxiYWNrIGZ1bmN0aW9uIHRvIGJlIGNhbGxlZCB3aGVuIHRoZSBldmVudCBpcyB0cmlnZ2VyZWQuXG4gKiBAcmV0dXJucyBBIGZ1bmN0aW9uIHRoYXQsIHdoZW4gY2FsbGVkLCB3aWxsIHVucmVnaXN0ZXIgdGhlIGNhbGxiYWNrIGZyb20gdGhlIGV2ZW50LlxuICovXG5leHBvcnQgZnVuY3Rpb24gT248RSBleHRlbmRzIFdhaWxzRXZlbnROYW1lID0gV2FpbHNFdmVudE5hbWU+KGV2ZW50TmFtZTogRSwgY2FsbGJhY2s6IFdhaWxzRXZlbnRDYWxsYmFjazxFPik6ICgpID0+IHZvaWQge1xuICAgIHJldHVybiBPbk11bHRpcGxlKGV2ZW50TmFtZSwgY2FsbGJhY2ssIC0xKTtcbn1cblxuLyoqXG4gKiBSZWdpc3RlcnMgYSBjYWxsYmFjayBmdW5jdGlvbiB0byBiZSBleGVjdXRlZCBvbmx5IG9uY2UgZm9yIHRoZSBzcGVjaWZpZWQgZXZlbnQuXG4gKlxuICogQHBhcmFtIGV2ZW50TmFtZSAtIFRoZSBuYW1lIG9mIHRoZSBldmVudCB0byByZWdpc3RlciB0aGUgY2FsbGJhY2sgZm9yLlxuICogQHBhcmFtIGNhbGxiYWNrIC0gVGhlIGNhbGxiYWNrIGZ1bmN0aW9uIHRvIGJlIGNhbGxlZCB3aGVuIHRoZSBldmVudCBpcyB0cmlnZ2VyZWQuXG4gKiBAcmV0dXJucyBBIGZ1bmN0aW9uIHRoYXQsIHdoZW4gY2FsbGVkLCB3aWxsIHVucmVnaXN0ZXIgdGhlIGNhbGxiYWNrIGZyb20gdGhlIGV2ZW50LlxuICovXG5leHBvcnQgZnVuY3Rpb24gT25jZTxFIGV4dGVuZHMgV2FpbHNFdmVudE5hbWUgPSBXYWlsc0V2ZW50TmFtZT4oZXZlbnROYW1lOiBFLCBjYWxsYmFjazogV2FpbHNFdmVudENhbGxiYWNrPEU+KTogKCkgPT4gdm9pZCB7XG4gICAgcmV0dXJuIE9uTXVsdGlwbGUoZXZlbnROYW1lLCBjYWxsYmFjaywgMSk7XG59XG5cbi8qKlxuICogUmVtb3ZlcyBldmVudCBsaXN0ZW5lcnMgZm9yIHRoZSBzcGVjaWZpZWQgZXZlbnQgbmFtZXMuXG4gKlxuICogQHBhcmFtIGV2ZW50TmFtZXMgLSBUaGUgbmFtZSBvZiB0aGUgZXZlbnRzIHRvIHJlbW92ZSBsaXN0ZW5lcnMgZm9yLlxuICovXG5leHBvcnQgZnVuY3Rpb24gT2ZmKC4uLmV2ZW50TmFtZXM6IFtXYWlsc0V2ZW50TmFtZSwgLi4uV2FpbHNFdmVudE5hbWVbXV0pOiB2b2lkIHtcbiAgICBldmVudE5hbWVzLmZvckVhY2goZXZlbnROYW1lID0+IGV2ZW50TGlzdGVuZXJzLmRlbGV0ZShldmVudE5hbWUpKTtcbn1cblxuLyoqXG4gKiBSZW1vdmVzIGFsbCBldmVudCBsaXN0ZW5lcnMuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBPZmZBbGwoKTogdm9pZCB7XG4gICAgZXZlbnRMaXN0ZW5lcnMuY2xlYXIoKTtcbn1cblxuLyoqXG4gKiBFbWl0cyBhbiBldmVudC5cbiAqXG4gKiBAcmV0dXJucyBBIHByb21pc2UgdGhhdCB3aWxsIGJlIGZ1bGZpbGxlZCBvbmNlIHRoZSBldmVudCBoYXMgYmVlbiBlbWl0dGVkLiAgUmVzb2x2ZXMgdG8gdHJ1ZSBpZiB0aGUgZXZlbnQgd2FzIGNhbmNlbGxlZC5cbiAqIEBwYXJhbSBuYW1lIC0gVGhlIG5hbWUgb2YgdGhlIGV2ZW50IHRvIGVtaXRcbiAqIEBwYXJhbSBkYXRhIC0gVGhlIGRhdGEgdGhhdCB3aWxsIGJlIHNlbnQgd2l0aCB0aGUgZXZlbnRcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIEVtaXQ8RSBleHRlbmRzIFdhaWxzRXZlbnROYW1lID0gV2FpbHNFdmVudE5hbWU+KG5hbWU6IEUsIGRhdGE6IFdhaWxzRXZlbnREYXRhPEU+KTogUHJvbWlzZTxib29sZWFuPlxuZXhwb3J0IGZ1bmN0aW9uIEVtaXQ8RSBleHRlbmRzIFdhaWxzRXZlbnROYW1lID0gV2FpbHNFdmVudE5hbWU+KG5hbWU6IFdhaWxzRXZlbnREYXRhPEU+IGV4dGVuZHMgbnVsbCB8IHZvaWQgPyBFIDogbmV2ZXIpOiBQcm9taXNlPGJvb2xlYW4+XG5leHBvcnQgZnVuY3Rpb24gRW1pdDxFIGV4dGVuZHMgV2FpbHNFdmVudE5hbWUgPSBXYWlsc0V2ZW50TmFtZT4obmFtZTogV2FpbHNFdmVudERhdGE8RT4sIGRhdGE/OiBhbnkpOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICByZXR1cm4gY2FsbChFbWl0TWV0aG9kLCAgbmV3IFdhaWxzRXZlbnQobmFtZSwgZGF0YSkpXG59XG5cbiIsICIvKlxuIF9cdCAgIF9fXHQgIF8gX19cbnwgfFx0IC8gL19fXyBfKF8pIC9fX19fXG58IHwgL3wgLyAvIF9fIGAvIC8gLyBfX18vXG58IHwvIHwvIC8gL18vIC8gLyAoX18gIClcbnxfXy98X18vXFxfXyxfL18vXy9fX19fL1xuVGhlIGVsZWN0cm9uIGFsdGVybmF0aXZlIGZvciBHb1xuKGMpIExlYSBBbnRob255IDIwMTktcHJlc2VudFxuKi9cblxuLy8gVGhlIGZvbGxvd2luZyB1dGlsaXRpZXMgaGF2ZSBiZWVuIGZhY3RvcmVkIG91dCBvZiAuL2V2ZW50cy50c1xuLy8gZm9yIHRlc3RpbmcgcHVycG9zZXMuXG5cbmV4cG9ydCBjb25zdCBldmVudExpc3RlbmVycyA9IG5ldyBNYXA8c3RyaW5nLCBMaXN0ZW5lcltdPigpO1xuXG5leHBvcnQgY2xhc3MgTGlzdGVuZXIge1xuICAgIGV2ZW50TmFtZTogc3RyaW5nO1xuICAgIGNhbGxiYWNrOiAoZGF0YTogYW55KSA9PiB2b2lkO1xuICAgIG1heENhbGxiYWNrczogbnVtYmVyO1xuXG4gICAgY29uc3RydWN0b3IoZXZlbnROYW1lOiBzdHJpbmcsIGNhbGxiYWNrOiAoZGF0YTogYW55KSA9PiB2b2lkLCBtYXhDYWxsYmFja3M6IG51bWJlcikge1xuICAgICAgICB0aGlzLmV2ZW50TmFtZSA9IGV2ZW50TmFtZTtcbiAgICAgICAgdGhpcy5jYWxsYmFjayA9IGNhbGxiYWNrO1xuICAgICAgICB0aGlzLm1heENhbGxiYWNrcyA9IG1heENhbGxiYWNrcyB8fCAtMTtcbiAgICB9XG5cbiAgICBkaXNwYXRjaChkYXRhOiBhbnkpOiBib29sZWFuIHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIHRoaXMuY2FsbGJhY2soZGF0YSk7XG4gICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgICAgY29uc29sZS5lcnJvcihlcnIpO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHRoaXMubWF4Q2FsbGJhY2tzID09PSAtMSkgcmV0dXJuIGZhbHNlO1xuICAgICAgICB0aGlzLm1heENhbGxiYWNrcyAtPSAxO1xuICAgICAgICByZXR1cm4gdGhpcy5tYXhDYWxsYmFja3MgPT09IDA7XG4gICAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24gbGlzdGVuZXJPZmYobGlzdGVuZXI6IExpc3RlbmVyKTogdm9pZCB7XG4gICAgbGV0IGxpc3RlbmVycyA9IGV2ZW50TGlzdGVuZXJzLmdldChsaXN0ZW5lci5ldmVudE5hbWUpO1xuICAgIGlmICghbGlzdGVuZXJzKSB7XG4gICAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBsaXN0ZW5lcnMgPSBsaXN0ZW5lcnMuZmlsdGVyKGwgPT4gbCAhPT0gbGlzdGVuZXIpO1xuICAgIGlmIChsaXN0ZW5lcnMubGVuZ3RoID09PSAwKSB7XG4gICAgICAgIGV2ZW50TGlzdGVuZXJzLmRlbGV0ZShsaXN0ZW5lci5ldmVudE5hbWUpO1xuICAgIH0gZWxzZSB7XG4gICAgICAgIGV2ZW50TGlzdGVuZXJzLnNldChsaXN0ZW5lci5ldmVudE5hbWUsIGxpc3RlbmVycyk7XG4gICAgfVxufVxuIiwgIi8qXG4gX1x0ICAgX19cdCAgXyBfX1xufCB8XHQgLyAvX19fIF8oXykgL19fX19cbnwgfCAvfCAvIC8gX18gYC8gLyAvIF9fXy9cbnwgfC8gfC8gLyAvXy8gLyAvIChfXyAgKVxufF9fL3xfXy9cXF9fLF8vXy9fL19fX18vXG5UaGUgZWxlY3Ryb24gYWx0ZXJuYXRpdmUgZm9yIEdvXG4oYykgTGVhIEFudGhvbnkgMjAxOS1wcmVzZW50XG4qL1xuXG4vKipcbiAqIEFueSBpcyBhIGR1bW15IGNyZWF0aW9uIGZ1bmN0aW9uIGZvciBzaW1wbGUgb3IgdW5rbm93biB0eXBlcy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIEFueTxUID0gYW55Pihzb3VyY2U6IGFueSk6IFQge1xuICAgIHJldHVybiBzb3VyY2U7XG59XG5cbi8qKlxuICogQnl0ZVNsaWNlIGlzIGEgY3JlYXRpb24gZnVuY3Rpb24gdGhhdCByZXBsYWNlc1xuICogbnVsbCBzdHJpbmdzIHdpdGggZW1wdHkgc3RyaW5ncy5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIEJ5dGVTbGljZShzb3VyY2U6IGFueSk6IHN0cmluZyB7XG4gICAgcmV0dXJuICgoc291cmNlID09IG51bGwpID8gXCJcIiA6IHNvdXJjZSk7XG59XG5cbi8qKlxuICogQXJyYXkgdGFrZXMgYSBjcmVhdGlvbiBmdW5jdGlvbiBmb3IgYW4gYXJiaXRyYXJ5IHR5cGVcbiAqIGFuZCByZXR1cm5zIGFuIGluLXBsYWNlIGNyZWF0aW9uIGZ1bmN0aW9uIGZvciBhbiBhcnJheVxuICogd2hvc2UgZWxlbWVudHMgYXJlIG9mIHRoYXQgdHlwZS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIEFycmF5PFQgPSBhbnk+KGVsZW1lbnQ6IChzb3VyY2U6IGFueSkgPT4gVCk6IChzb3VyY2U6IGFueSkgPT4gVFtdIHtcbiAgICBpZiAoZWxlbWVudCA9PT0gQW55KSB7XG4gICAgICAgIHJldHVybiAoc291cmNlKSA9PiAoc291cmNlID09PSBudWxsID8gW10gOiBzb3VyY2UpO1xuICAgIH1cblxuICAgIHJldHVybiAoc291cmNlKSA9PiB7XG4gICAgICAgIGlmIChzb3VyY2UgPT09IG51bGwpIHtcbiAgICAgICAgICAgIHJldHVybiBbXTtcbiAgICAgICAgfVxuICAgICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHNvdXJjZS5sZW5ndGg7IGkrKykge1xuICAgICAgICAgICAgc291cmNlW2ldID0gZWxlbWVudChzb3VyY2VbaV0pO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBzb3VyY2U7XG4gICAgfTtcbn1cblxuLyoqXG4gKiBNYXAgdGFrZXMgY3JlYXRpb24gZnVuY3Rpb25zIGZvciB0d28gYXJiaXRyYXJ5IHR5cGVzXG4gKiBhbmQgcmV0dXJucyBhbiBpbi1wbGFjZSBjcmVhdGlvbiBmdW5jdGlvbiBmb3IgYW4gb2JqZWN0XG4gKiB3aG9zZSBrZXlzIGFuZCB2YWx1ZXMgYXJlIG9mIHRob3NlIHR5cGVzLlxuICovXG5leHBvcnQgZnVuY3Rpb24gTWFwPEsgZXh0ZW5kcyBQcm9wZXJ0eUtleSA9IGFueSwgViA9IGFueT4oa2V5OiAoc291cmNlOiBhbnkpID0+IEssIHZhbHVlOiAoc291cmNlOiBhbnkpID0+IFYpOiAoc291cmNlOiBhbnkpID0+IFJlY29yZDxLLCBWPiB7XG4gICAgaWYgKHZhbHVlID09PSBBbnkpIHtcbiAgICAgICAgcmV0dXJuIChzb3VyY2UpID0+IChzb3VyY2UgPT09IG51bGwgPyB7fSA6IHNvdXJjZSk7XG4gICAgfVxuXG4gICAgcmV0dXJuIChzb3VyY2UpID0+IHtcbiAgICAgICAgaWYgKHNvdXJjZSA9PT0gbnVsbCkge1xuICAgICAgICAgICAgcmV0dXJuIHt9O1xuICAgICAgICB9XG4gICAgICAgIGZvciAoY29uc3Qga2V5IGluIHNvdXJjZSkge1xuICAgICAgICAgICAgc291cmNlW2tleV0gPSB2YWx1ZShzb3VyY2Vba2V5XSk7XG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHNvdXJjZTtcbiAgICB9O1xufVxuXG4vKipcbiAqIE51bGxhYmxlIHRha2VzIGEgY3JlYXRpb24gZnVuY3Rpb24gZm9yIGFuIGFyYml0cmFyeSB0eXBlXG4gKiBhbmQgcmV0dXJucyBhIGNyZWF0aW9uIGZ1bmN0aW9uIGZvciBhIG51bGxhYmxlIHZhbHVlIG9mIHRoYXQgdHlwZS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIE51bGxhYmxlPFQgPSBhbnk+KGVsZW1lbnQ6IChzb3VyY2U6IGFueSkgPT4gVCk6IChzb3VyY2U6IGFueSkgPT4gKFQgfCBudWxsKSB7XG4gICAgaWYgKGVsZW1lbnQgPT09IEFueSkge1xuICAgICAgICByZXR1cm4gQW55O1xuICAgIH1cblxuICAgIHJldHVybiAoc291cmNlKSA9PiAoc291cmNlID09PSBudWxsID8gbnVsbCA6IGVsZW1lbnQoc291cmNlKSk7XG59XG5cbi8qKlxuICogU3RydWN0IHRha2VzIGFuIG9iamVjdCBtYXBwaW5nIGZpZWxkIG5hbWVzIHRvIGNyZWF0aW9uIGZ1bmN0aW9uc1xuICogYW5kIHJldHVybnMgYW4gaW4tcGxhY2UgY3JlYXRpb24gZnVuY3Rpb24gZm9yIGEgc3RydWN0LlxuICovXG5leHBvcnQgZnVuY3Rpb24gU3RydWN0KGNyZWF0ZUZpZWxkOiBSZWNvcmQ8c3RyaW5nLCAoc291cmNlOiBhbnkpID0+IGFueT4pOlxuICAgIDxVIGV4dGVuZHMgUmVjb3JkPHN0cmluZywgYW55PiA9IGFueT4oc291cmNlOiBhbnkpID0+IFVcbntcbiAgICBsZXQgYWxsQW55ID0gdHJ1ZTtcbiAgICBmb3IgKGNvbnN0IG5hbWUgaW4gY3JlYXRlRmllbGQpIHtcbiAgICAgICAgaWYgKGNyZWF0ZUZpZWxkW25hbWVdICE9PSBBbnkpIHtcbiAgICAgICAgICAgIGFsbEFueSA9IGZhbHNlO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICB9XG4gICAgaWYgKGFsbEFueSkge1xuICAgICAgICByZXR1cm4gQW55O1xuICAgIH1cblxuICAgIHJldHVybiAoc291cmNlKSA9PiB7XG4gICAgICAgIGZvciAoY29uc3QgbmFtZSBpbiBjcmVhdGVGaWVsZCkge1xuICAgICAgICAgICAgaWYgKG5hbWUgaW4gc291cmNlKSB7XG4gICAgICAgICAgICAgICAgc291cmNlW25hbWVdID0gY3JlYXRlRmllbGRbbmFtZV0oc291cmNlW25hbWVdKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gc291cmNlO1xuICAgIH07XG59XG5cbi8qKlxuICogTWFwcyBrbm93biBldmVudCBuYW1lcyB0byBjcmVhdGlvbiBmdW5jdGlvbnMgZm9yIHRoZWlyIGRhdGEgdHlwZXMuXG4gKiBXaWxsIGJlIG1vbmtleS1wYXRjaGVkIGJ5IHRoZSBiaW5kaW5nIGdlbmVyYXRvci5cbiAqL1xuZXhwb3J0IGNvbnN0IEV2ZW50czogUmVjb3JkPHN0cmluZywgKHNvdXJjZTogYW55KSA9PiBhbnk+ID0ge307XG4iLCAiLypcbiBfXHQgICBfX1x0ICBfIF9fXG58IHxcdCAvIC9fX18gXyhfKSAvX19fX1xufCB8IC98IC8gLyBfXyBgLyAvIC8gX19fL1xufCB8LyB8LyAvIC9fLyAvIC8gKF9fICApXG58X18vfF9fL1xcX18sXy9fL18vX19fXy9cblRoZSBlbGVjdHJvbiBhbHRlcm5hdGl2ZSBmb3IgR29cbihjKSBMZWEgQW50aG9ueSAyMDE5LXByZXNlbnRcbiovXG5cbi8vIEN5bmh5cmNod3lkIHkgZmZlaWwgaG9uIHluIGF3dG9tYXRpZy4gUEVJRElXQ0ggXHUwMEMyIE1PRElXTFxuLy8gVGhpcyBmaWxlIGlzIGF1dG9tYXRpY2FsbHkgZ2VuZXJhdGVkLiBETyBOT1QgRURJVFxuXG5leHBvcnQgY29uc3QgVHlwZXMgPSBPYmplY3QuZnJlZXplKHtcblx0V2luZG93czogT2JqZWN0LmZyZWV6ZSh7XG5cdFx0QVBNUG93ZXJTZXR0aW5nQ2hhbmdlOiBcIndpbmRvd3M6QVBNUG93ZXJTZXR0aW5nQ2hhbmdlXCIsXG5cdFx0QVBNUG93ZXJTdGF0dXNDaGFuZ2U6IFwid2luZG93czpBUE1Qb3dlclN0YXR1c0NoYW5nZVwiLFxuXHRcdEFQTVJlc3VtZUF1dG9tYXRpYzogXCJ3aW5kb3dzOkFQTVJlc3VtZUF1dG9tYXRpY1wiLFxuXHRcdEFQTVJlc3VtZVN1c3BlbmQ6IFwid2luZG93czpBUE1SZXN1bWVTdXNwZW5kXCIsXG5cdFx0QVBNU3VzcGVuZDogXCJ3aW5kb3dzOkFQTVN1c3BlbmRcIixcblx0XHRBcHBsaWNhdGlvblN0YXJ0ZWQ6IFwid2luZG93czpBcHBsaWNhdGlvblN0YXJ0ZWRcIixcblx0XHRTeXN0ZW1UaGVtZUNoYW5nZWQ6IFwid2luZG93czpTeXN0ZW1UaGVtZUNoYW5nZWRcIixcblx0XHRXZWJWaWV3TmF2aWdhdGlvbkNvbXBsZXRlZDogXCJ3aW5kb3dzOldlYlZpZXdOYXZpZ2F0aW9uQ29tcGxldGVkXCIsXG5cdFx0V2luZG93QWN0aXZlOiBcIndpbmRvd3M6V2luZG93QWN0aXZlXCIsXG5cdFx0V2luZG93QmFja2dyb3VuZEVyYXNlOiBcIndpbmRvd3M6V2luZG93QmFja2dyb3VuZEVyYXNlXCIsXG5cdFx0V2luZG93Q2xpY2tBY3RpdmU6IFwid2luZG93czpXaW5kb3dDbGlja0FjdGl2ZVwiLFxuXHRcdFdpbmRvd0Nsb3Npbmc6IFwid2luZG93czpXaW5kb3dDbG9zaW5nXCIsXG5cdFx0V2luZG93RGlkTW92ZTogXCJ3aW5kb3dzOldpbmRvd0RpZE1vdmVcIixcblx0XHRXaW5kb3dEaWRSZXNpemU6IFwid2luZG93czpXaW5kb3dEaWRSZXNpemVcIixcblx0XHRXaW5kb3dEUElDaGFuZ2VkOiBcIndpbmRvd3M6V2luZG93RFBJQ2hhbmdlZFwiLFxuXHRcdFdpbmRvd0RyYWdEcm9wOiBcIndpbmRvd3M6V2luZG93RHJhZ0Ryb3BcIixcblx0XHRXaW5kb3dEcmFnRW50ZXI6IFwid2luZG93czpXaW5kb3dEcmFnRW50ZXJcIixcblx0XHRXaW5kb3dEcmFnTGVhdmU6IFwid2luZG93czpXaW5kb3dEcmFnTGVhdmVcIixcblx0XHRXaW5kb3dEcmFnT3ZlcjogXCJ3aW5kb3dzOldpbmRvd0RyYWdPdmVyXCIsXG5cdFx0V2luZG93RW5kTW92ZTogXCJ3aW5kb3dzOldpbmRvd0VuZE1vdmVcIixcblx0XHRXaW5kb3dFbmRSZXNpemU6IFwid2luZG93czpXaW5kb3dFbmRSZXNpemVcIixcblx0XHRXaW5kb3dGdWxsc2NyZWVuOiBcIndpbmRvd3M6V2luZG93RnVsbHNjcmVlblwiLFxuXHRcdFdpbmRvd0hpZGU6IFwid2luZG93czpXaW5kb3dIaWRlXCIsXG5cdFx0V2luZG93SW5hY3RpdmU6IFwid2luZG93czpXaW5kb3dJbmFjdGl2ZVwiLFxuXHRcdFdpbmRvd0tleURvd246IFwid2luZG93czpXaW5kb3dLZXlEb3duXCIsXG5cdFx0V2luZG93S2V5VXA6IFwid2luZG93czpXaW5kb3dLZXlVcFwiLFxuXHRcdFdpbmRvd0tpbGxGb2N1czogXCJ3aW5kb3dzOldpbmRvd0tpbGxGb2N1c1wiLFxuXHRcdFdpbmRvd05vbkNsaWVudEhpdDogXCJ3aW5kb3dzOldpbmRvd05vbkNsaWVudEhpdFwiLFxuXHRcdFdpbmRvd05vbkNsaWVudE1vdXNlRG93bjogXCJ3aW5kb3dzOldpbmRvd05vbkNsaWVudE1vdXNlRG93blwiLFxuXHRcdFdpbmRvd05vbkNsaWVudE1vdXNlTGVhdmU6IFwid2luZG93czpXaW5kb3dOb25DbGllbnRNb3VzZUxlYXZlXCIsXG5cdFx0V2luZG93Tm9uQ2xpZW50TW91c2VNb3ZlOiBcIndpbmRvd3M6V2luZG93Tm9uQ2xpZW50TW91c2VNb3ZlXCIsXG5cdFx0V2luZG93Tm9uQ2xpZW50TW91c2VVcDogXCJ3aW5kb3dzOldpbmRvd05vbkNsaWVudE1vdXNlVXBcIixcblx0XHRXaW5kb3dQYWludDogXCJ3aW5kb3dzOldpbmRvd1BhaW50XCIsXG5cdFx0V2luZG93UmVzdG9yZTogXCJ3aW5kb3dzOldpbmRvd1Jlc3RvcmVcIixcblx0XHRXaW5kb3dTZXRGb2N1czogXCJ3aW5kb3dzOldpbmRvd1NldEZvY3VzXCIsXG5cdFx0V2luZG93U2hvdzogXCJ3aW5kb3dzOldpbmRvd1Nob3dcIixcblx0XHRXaW5kb3dTdGFydE1vdmU6IFwid2luZG93czpXaW5kb3dTdGFydE1vdmVcIixcblx0XHRXaW5kb3dTdGFydFJlc2l6ZTogXCJ3aW5kb3dzOldpbmRvd1N0YXJ0UmVzaXplXCIsXG5cdFx0V2luZG93VW5GdWxsc2NyZWVuOiBcIndpbmRvd3M6V2luZG93VW5GdWxsc2NyZWVuXCIsXG5cdFx0V2luZG93Wk9yZGVyQ2hhbmdlZDogXCJ3aW5kb3dzOldpbmRvd1pPcmRlckNoYW5nZWRcIixcblx0XHRXaW5kb3dNaW5pbWlzZTogXCJ3aW5kb3dzOldpbmRvd01pbmltaXNlXCIsXG5cdFx0V2luZG93VW5NaW5pbWlzZTogXCJ3aW5kb3dzOldpbmRvd1VuTWluaW1pc2VcIixcblx0XHRXaW5kb3dNYXhpbWlzZTogXCJ3aW5kb3dzOldpbmRvd01heGltaXNlXCIsXG5cdFx0V2luZG93VW5NYXhpbWlzZTogXCJ3aW5kb3dzOldpbmRvd1VuTWF4aW1pc2VcIixcblx0fSksXG5cdE1hYzogT2JqZWN0LmZyZWV6ZSh7XG5cdFx0QXBwbGljYXRpb25EaWRCZWNvbWVBY3RpdmU6IFwibWFjOkFwcGxpY2F0aW9uRGlkQmVjb21lQWN0aXZlXCIsXG5cdFx0QXBwbGljYXRpb25EaWRDaGFuZ2VCYWNraW5nUHJvcGVydGllczogXCJtYWM6QXBwbGljYXRpb25EaWRDaGFuZ2VCYWNraW5nUHJvcGVydGllc1wiLFxuXHRcdEFwcGxpY2F0aW9uRGlkQ2hhbmdlRWZmZWN0aXZlQXBwZWFyYW5jZTogXCJtYWM6QXBwbGljYXRpb25EaWRDaGFuZ2VFZmZlY3RpdmVBcHBlYXJhbmNlXCIsXG5cdFx0QXBwbGljYXRpb25EaWRDaGFuZ2VJY29uOiBcIm1hYzpBcHBsaWNhdGlvbkRpZENoYW5nZUljb25cIixcblx0XHRBcHBsaWNhdGlvbkRpZENoYW5nZU9jY2x1c2lvblN0YXRlOiBcIm1hYzpBcHBsaWNhdGlvbkRpZENoYW5nZU9jY2x1c2lvblN0YXRlXCIsXG5cdFx0QXBwbGljYXRpb25EaWRDaGFuZ2VTY3JlZW5QYXJhbWV0ZXJzOiBcIm1hYzpBcHBsaWNhdGlvbkRpZENoYW5nZVNjcmVlblBhcmFtZXRlcnNcIixcblx0XHRBcHBsaWNhdGlvbkRpZENoYW5nZVN0YXR1c0JhckZyYW1lOiBcIm1hYzpBcHBsaWNhdGlvbkRpZENoYW5nZVN0YXR1c0JhckZyYW1lXCIsXG5cdFx0QXBwbGljYXRpb25EaWRDaGFuZ2VTdGF0dXNCYXJPcmllbnRhdGlvbjogXCJtYWM6QXBwbGljYXRpb25EaWRDaGFuZ2VTdGF0dXNCYXJPcmllbnRhdGlvblwiLFxuXHRcdEFwcGxpY2F0aW9uRGlkQ2hhbmdlVGhlbWU6IFwibWFjOkFwcGxpY2F0aW9uRGlkQ2hhbmdlVGhlbWVcIixcblx0XHRBcHBsaWNhdGlvbkRpZEZpbmlzaExhdW5jaGluZzogXCJtYWM6QXBwbGljYXRpb25EaWRGaW5pc2hMYXVuY2hpbmdcIixcblx0XHRBcHBsaWNhdGlvbkRpZEhpZGU6IFwibWFjOkFwcGxpY2F0aW9uRGlkSGlkZVwiLFxuXHRcdEFwcGxpY2F0aW9uRGlkUmVzaWduQWN0aXZlOiBcIm1hYzpBcHBsaWNhdGlvbkRpZFJlc2lnbkFjdGl2ZVwiLFxuXHRcdEFwcGxpY2F0aW9uRGlkVW5oaWRlOiBcIm1hYzpBcHBsaWNhdGlvbkRpZFVuaGlkZVwiLFxuXHRcdEFwcGxpY2F0aW9uRGlkVXBkYXRlOiBcIm1hYzpBcHBsaWNhdGlvbkRpZFVwZGF0ZVwiLFxuXHRcdEFwcGxpY2F0aW9uU2hvdWxkSGFuZGxlUmVvcGVuOiBcIm1hYzpBcHBsaWNhdGlvblNob3VsZEhhbmRsZVJlb3BlblwiLFxuXHRcdEFwcGxpY2F0aW9uV2lsbEJlY29tZUFjdGl2ZTogXCJtYWM6QXBwbGljYXRpb25XaWxsQmVjb21lQWN0aXZlXCIsXG5cdFx0QXBwbGljYXRpb25XaWxsRmluaXNoTGF1bmNoaW5nOiBcIm1hYzpBcHBsaWNhdGlvbldpbGxGaW5pc2hMYXVuY2hpbmdcIixcblx0XHRBcHBsaWNhdGlvbldpbGxIaWRlOiBcIm1hYzpBcHBsaWNhdGlvbldpbGxIaWRlXCIsXG5cdFx0QXBwbGljYXRpb25XaWxsUmVzaWduQWN0aXZlOiBcIm1hYzpBcHBsaWNhdGlvbldpbGxSZXNpZ25BY3RpdmVcIixcblx0XHRBcHBsaWNhdGlvbldpbGxUZXJtaW5hdGU6IFwibWFjOkFwcGxpY2F0aW9uV2lsbFRlcm1pbmF0ZVwiLFxuXHRcdEFwcGxpY2F0aW9uV2lsbFVuaGlkZTogXCJtYWM6QXBwbGljYXRpb25XaWxsVW5oaWRlXCIsXG5cdFx0QXBwbGljYXRpb25XaWxsVXBkYXRlOiBcIm1hYzpBcHBsaWNhdGlvbldpbGxVcGRhdGVcIixcblx0XHRNZW51RGlkQWRkSXRlbTogXCJtYWM6TWVudURpZEFkZEl0ZW1cIixcblx0XHRNZW51RGlkQmVnaW5UcmFja2luZzogXCJtYWM6TWVudURpZEJlZ2luVHJhY2tpbmdcIixcblx0XHRNZW51RGlkQ2xvc2U6IFwibWFjOk1lbnVEaWRDbG9zZVwiLFxuXHRcdE1lbnVEaWREaXNwbGF5SXRlbTogXCJtYWM6TWVudURpZERpc3BsYXlJdGVtXCIsXG5cdFx0TWVudURpZEVuZFRyYWNraW5nOiBcIm1hYzpNZW51RGlkRW5kVHJhY2tpbmdcIixcblx0XHRNZW51RGlkSGlnaGxpZ2h0SXRlbTogXCJtYWM6TWVudURpZEhpZ2hsaWdodEl0ZW1cIixcblx0XHRNZW51RGlkT3BlbjogXCJtYWM6TWVudURpZE9wZW5cIixcblx0XHRNZW51RGlkUG9wVXA6IFwibWFjOk1lbnVEaWRQb3BVcFwiLFxuXHRcdE1lbnVEaWRSZW1vdmVJdGVtOiBcIm1hYzpNZW51RGlkUmVtb3ZlSXRlbVwiLFxuXHRcdE1lbnVEaWRTZW5kQWN0aW9uOiBcIm1hYzpNZW51RGlkU2VuZEFjdGlvblwiLFxuXHRcdE1lbnVEaWRTZW5kQWN0aW9uVG9JdGVtOiBcIm1hYzpNZW51RGlkU2VuZEFjdGlvblRvSXRlbVwiLFxuXHRcdE1lbnVEaWRVcGRhdGU6IFwibWFjOk1lbnVEaWRVcGRhdGVcIixcblx0XHRNZW51V2lsbEFkZEl0ZW06IFwibWFjOk1lbnVXaWxsQWRkSXRlbVwiLFxuXHRcdE1lbnVXaWxsQmVnaW5UcmFja2luZzogXCJtYWM6TWVudVdpbGxCZWdpblRyYWNraW5nXCIsXG5cdFx0TWVudVdpbGxEaXNwbGF5SXRlbTogXCJtYWM6TWVudVdpbGxEaXNwbGF5SXRlbVwiLFxuXHRcdE1lbnVXaWxsRW5kVHJhY2tpbmc6IFwibWFjOk1lbnVXaWxsRW5kVHJhY2tpbmdcIixcblx0XHRNZW51V2lsbEhpZ2hsaWdodEl0ZW06IFwibWFjOk1lbnVXaWxsSGlnaGxpZ2h0SXRlbVwiLFxuXHRcdE1lbnVXaWxsT3BlbjogXCJtYWM6TWVudVdpbGxPcGVuXCIsXG5cdFx0TWVudVdpbGxQb3BVcDogXCJtYWM6TWVudVdpbGxQb3BVcFwiLFxuXHRcdE1lbnVXaWxsUmVtb3ZlSXRlbTogXCJtYWM6TWVudVdpbGxSZW1vdmVJdGVtXCIsXG5cdFx0TWVudVdpbGxTZW5kQWN0aW9uOiBcIm1hYzpNZW51V2lsbFNlbmRBY3Rpb25cIixcblx0XHRNZW51V2lsbFNlbmRBY3Rpb25Ub0l0ZW06IFwibWFjOk1lbnVXaWxsU2VuZEFjdGlvblRvSXRlbVwiLFxuXHRcdE1lbnVXaWxsVXBkYXRlOiBcIm1hYzpNZW51V2lsbFVwZGF0ZVwiLFxuXHRcdFdlYlZpZXdEaWRDb21taXROYXZpZ2F0aW9uOiBcIm1hYzpXZWJWaWV3RGlkQ29tbWl0TmF2aWdhdGlvblwiLFxuXHRcdFdlYlZpZXdEaWRGaW5pc2hOYXZpZ2F0aW9uOiBcIm1hYzpXZWJWaWV3RGlkRmluaXNoTmF2aWdhdGlvblwiLFxuXHRcdFdlYlZpZXdEaWRSZWNlaXZlU2VydmVyUmVkaXJlY3RGb3JQcm92aXNpb25hbE5hdmlnYXRpb246IFwibWFjOldlYlZpZXdEaWRSZWNlaXZlU2VydmVyUmVkaXJlY3RGb3JQcm92aXNpb25hbE5hdmlnYXRpb25cIixcblx0XHRXZWJWaWV3RGlkU3RhcnRQcm92aXNpb25hbE5hdmlnYXRpb246IFwibWFjOldlYlZpZXdEaWRTdGFydFByb3Zpc2lvbmFsTmF2aWdhdGlvblwiLFxuXHRcdFdpbmRvd0RpZEJlY29tZUtleTogXCJtYWM6V2luZG93RGlkQmVjb21lS2V5XCIsXG5cdFx0V2luZG93RGlkQmVjb21lTWFpbjogXCJtYWM6V2luZG93RGlkQmVjb21lTWFpblwiLFxuXHRcdFdpbmRvd0RpZEJlZ2luU2hlZXQ6IFwibWFjOldpbmRvd0RpZEJlZ2luU2hlZXRcIixcblx0XHRXaW5kb3dEaWRDaGFuZ2VBbHBoYTogXCJtYWM6V2luZG93RGlkQ2hhbmdlQWxwaGFcIixcblx0XHRXaW5kb3dEaWRDaGFuZ2VCYWNraW5nTG9jYXRpb246IFwibWFjOldpbmRvd0RpZENoYW5nZUJhY2tpbmdMb2NhdGlvblwiLFxuXHRcdFdpbmRvd0RpZENoYW5nZUJhY2tpbmdQcm9wZXJ0aWVzOiBcIm1hYzpXaW5kb3dEaWRDaGFuZ2VCYWNraW5nUHJvcGVydGllc1wiLFxuXHRcdFdpbmRvd0RpZENoYW5nZUNvbGxlY3Rpb25CZWhhdmlvcjogXCJtYWM6V2luZG93RGlkQ2hhbmdlQ29sbGVjdGlvbkJlaGF2aW9yXCIsXG5cdFx0V2luZG93RGlkQ2hhbmdlRWZmZWN0aXZlQXBwZWFyYW5jZTogXCJtYWM6V2luZG93RGlkQ2hhbmdlRWZmZWN0aXZlQXBwZWFyYW5jZVwiLFxuXHRcdFdpbmRvd0RpZENoYW5nZU9jY2x1c2lvblN0YXRlOiBcIm1hYzpXaW5kb3dEaWRDaGFuZ2VPY2NsdXNpb25TdGF0ZVwiLFxuXHRcdFdpbmRvd0RpZENoYW5nZU9yZGVyaW5nTW9kZTogXCJtYWM6V2luZG93RGlkQ2hhbmdlT3JkZXJpbmdNb2RlXCIsXG5cdFx0V2luZG93RGlkQ2hhbmdlU2NyZWVuOiBcIm1hYzpXaW5kb3dEaWRDaGFuZ2VTY3JlZW5cIixcblx0XHRXaW5kb3dEaWRDaGFuZ2VTY3JlZW5QYXJhbWV0ZXJzOiBcIm1hYzpXaW5kb3dEaWRDaGFuZ2VTY3JlZW5QYXJhbWV0ZXJzXCIsXG5cdFx0V2luZG93RGlkQ2hhbmdlU2NyZWVuUHJvZmlsZTogXCJtYWM6V2luZG93RGlkQ2hhbmdlU2NyZWVuUHJvZmlsZVwiLFxuXHRcdFdpbmRvd0RpZENoYW5nZVNjcmVlblNwYWNlOiBcIm1hYzpXaW5kb3dEaWRDaGFuZ2VTY3JlZW5TcGFjZVwiLFxuXHRcdFdpbmRvd0RpZENoYW5nZVNjcmVlblNwYWNlUHJvcGVydGllczogXCJtYWM6V2luZG93RGlkQ2hhbmdlU2NyZWVuU3BhY2VQcm9wZXJ0aWVzXCIsXG5cdFx0V2luZG93RGlkQ2hhbmdlU2hhcmluZ1R5cGU6IFwibWFjOldpbmRvd0RpZENoYW5nZVNoYXJpbmdUeXBlXCIsXG5cdFx0V2luZG93RGlkQ2hhbmdlU3BhY2U6IFwibWFjOldpbmRvd0RpZENoYW5nZVNwYWNlXCIsXG5cdFx0V2luZG93RGlkQ2hhbmdlU3BhY2VPcmRlcmluZ01vZGU6IFwibWFjOldpbmRvd0RpZENoYW5nZVNwYWNlT3JkZXJpbmdNb2RlXCIsXG5cdFx0V2luZG93RGlkQ2hhbmdlVGl0bGU6IFwibWFjOldpbmRvd0RpZENoYW5nZVRpdGxlXCIsXG5cdFx0V2luZG93RGlkQ2hhbmdlVG9vbGJhcjogXCJtYWM6V2luZG93RGlkQ2hhbmdlVG9vbGJhclwiLFxuXHRcdFdpbmRvd0RpZERlbWluaWF0dXJpemU6IFwibWFjOldpbmRvd0RpZERlbWluaWF0dXJpemVcIixcblx0XHRXaW5kb3dEaWRFbmRTaGVldDogXCJtYWM6V2luZG93RGlkRW5kU2hlZXRcIixcblx0XHRXaW5kb3dEaWRFbnRlckZ1bGxTY3JlZW46IFwibWFjOldpbmRvd0RpZEVudGVyRnVsbFNjcmVlblwiLFxuXHRcdFdpbmRvd0RpZEVudGVyVmVyc2lvbkJyb3dzZXI6IFwibWFjOldpbmRvd0RpZEVudGVyVmVyc2lvbkJyb3dzZXJcIixcblx0XHRXaW5kb3dEaWRFeGl0RnVsbFNjcmVlbjogXCJtYWM6V2luZG93RGlkRXhpdEZ1bGxTY3JlZW5cIixcblx0XHRXaW5kb3dEaWRFeGl0VmVyc2lvbkJyb3dzZXI6IFwibWFjOldpbmRvd0RpZEV4aXRWZXJzaW9uQnJvd3NlclwiLFxuXHRcdFdpbmRvd0RpZEV4cG9zZTogXCJtYWM6V2luZG93RGlkRXhwb3NlXCIsXG5cdFx0V2luZG93RGlkRm9jdXM6IFwibWFjOldpbmRvd0RpZEZvY3VzXCIsXG5cdFx0V2luZG93RGlkTWluaWF0dXJpemU6IFwibWFjOldpbmRvd0RpZE1pbmlhdHVyaXplXCIsXG5cdFx0V2luZG93RGlkTW92ZTogXCJtYWM6V2luZG93RGlkTW92ZVwiLFxuXHRcdFdpbmRvd0RpZE9yZGVyT2ZmU2NyZWVuOiBcIm1hYzpXaW5kb3dEaWRPcmRlck9mZlNjcmVlblwiLFxuXHRcdFdpbmRvd0RpZE9yZGVyT25TY3JlZW46IFwibWFjOldpbmRvd0RpZE9yZGVyT25TY3JlZW5cIixcblx0XHRXaW5kb3dEaWRSZXNpZ25LZXk6IFwibWFjOldpbmRvd0RpZFJlc2lnbktleVwiLFxuXHRcdFdpbmRvd0RpZFJlc2lnbk1haW46IFwibWFjOldpbmRvd0RpZFJlc2lnbk1haW5cIixcblx0XHRXaW5kb3dEaWRSZXNpemU6IFwibWFjOldpbmRvd0RpZFJlc2l6ZVwiLFxuXHRcdFdpbmRvd0RpZFVwZGF0ZTogXCJtYWM6V2luZG93RGlkVXBkYXRlXCIsXG5cdFx0V2luZG93RGlkVXBkYXRlQWxwaGE6IFwibWFjOldpbmRvd0RpZFVwZGF0ZUFscGhhXCIsXG5cdFx0V2luZG93RGlkVXBkYXRlQ29sbGVjdGlvbkJlaGF2aW9yOiBcIm1hYzpXaW5kb3dEaWRVcGRhdGVDb2xsZWN0aW9uQmVoYXZpb3JcIixcblx0XHRXaW5kb3dEaWRVcGRhdGVDb2xsZWN0aW9uUHJvcGVydGllczogXCJtYWM6V2luZG93RGlkVXBkYXRlQ29sbGVjdGlvblByb3BlcnRpZXNcIixcblx0XHRXaW5kb3dEaWRVcGRhdGVTaGFkb3c6IFwibWFjOldpbmRvd0RpZFVwZGF0ZVNoYWRvd1wiLFxuXHRcdFdpbmRvd0RpZFVwZGF0ZVRpdGxlOiBcIm1hYzpXaW5kb3dEaWRVcGRhdGVUaXRsZVwiLFxuXHRcdFdpbmRvd0RpZFVwZGF0ZVRvb2xiYXI6IFwibWFjOldpbmRvd0RpZFVwZGF0ZVRvb2xiYXJcIixcblx0XHRXaW5kb3dEaWRab29tOiBcIm1hYzpXaW5kb3dEaWRab29tXCIsXG5cdFx0V2luZG93RmlsZURyYWdnaW5nRW50ZXJlZDogXCJtYWM6V2luZG93RmlsZURyYWdnaW5nRW50ZXJlZFwiLFxuXHRcdFdpbmRvd0ZpbGVEcmFnZ2luZ0V4aXRlZDogXCJtYWM6V2luZG93RmlsZURyYWdnaW5nRXhpdGVkXCIsXG5cdFx0V2luZG93RmlsZURyYWdnaW5nUGVyZm9ybWVkOiBcIm1hYzpXaW5kb3dGaWxlRHJhZ2dpbmdQZXJmb3JtZWRcIixcblx0XHRXaW5kb3dIaWRlOiBcIm1hYzpXaW5kb3dIaWRlXCIsXG5cdFx0V2luZG93TWF4aW1pc2U6IFwibWFjOldpbmRvd01heGltaXNlXCIsXG5cdFx0V2luZG93VW5NYXhpbWlzZTogXCJtYWM6V2luZG93VW5NYXhpbWlzZVwiLFxuXHRcdFdpbmRvd01pbmltaXNlOiBcIm1hYzpXaW5kb3dNaW5pbWlzZVwiLFxuXHRcdFdpbmRvd1VuTWluaW1pc2U6IFwibWFjOldpbmRvd1VuTWluaW1pc2VcIixcblx0XHRXaW5kb3dTaG91bGRDbG9zZTogXCJtYWM6V2luZG93U2hvdWxkQ2xvc2VcIixcblx0XHRXaW5kb3dTaG93OiBcIm1hYzpXaW5kb3dTaG93XCIsXG5cdFx0V2luZG93V2lsbEJlY29tZUtleTogXCJtYWM6V2luZG93V2lsbEJlY29tZUtleVwiLFxuXHRcdFdpbmRvd1dpbGxCZWNvbWVNYWluOiBcIm1hYzpXaW5kb3dXaWxsQmVjb21lTWFpblwiLFxuXHRcdFdpbmRvd1dpbGxCZWdpblNoZWV0OiBcIm1hYzpXaW5kb3dXaWxsQmVnaW5TaGVldFwiLFxuXHRcdFdpbmRvd1dpbGxDaGFuZ2VPcmRlcmluZ01vZGU6IFwibWFjOldpbmRvd1dpbGxDaGFuZ2VPcmRlcmluZ01vZGVcIixcblx0XHRXaW5kb3dXaWxsQ2xvc2U6IFwibWFjOldpbmRvd1dpbGxDbG9zZVwiLFxuXHRcdFdpbmRvd1dpbGxEZW1pbmlhdHVyaXplOiBcIm1hYzpXaW5kb3dXaWxsRGVtaW5pYXR1cml6ZVwiLFxuXHRcdFdpbmRvd1dpbGxFbnRlckZ1bGxTY3JlZW46IFwibWFjOldpbmRvd1dpbGxFbnRlckZ1bGxTY3JlZW5cIixcblx0XHRXaW5kb3dXaWxsRW50ZXJWZXJzaW9uQnJvd3NlcjogXCJtYWM6V2luZG93V2lsbEVudGVyVmVyc2lvbkJyb3dzZXJcIixcblx0XHRXaW5kb3dXaWxsRXhpdEZ1bGxTY3JlZW46IFwibWFjOldpbmRvd1dpbGxFeGl0RnVsbFNjcmVlblwiLFxuXHRcdFdpbmRvd1dpbGxFeGl0VmVyc2lvbkJyb3dzZXI6IFwibWFjOldpbmRvd1dpbGxFeGl0VmVyc2lvbkJyb3dzZXJcIixcblx0XHRXaW5kb3dXaWxsRm9jdXM6IFwibWFjOldpbmRvd1dpbGxGb2N1c1wiLFxuXHRcdFdpbmRvd1dpbGxNaW5pYXR1cml6ZTogXCJtYWM6V2luZG93V2lsbE1pbmlhdHVyaXplXCIsXG5cdFx0V2luZG93V2lsbE1vdmU6IFwibWFjOldpbmRvd1dpbGxNb3ZlXCIsXG5cdFx0V2luZG93V2lsbE9yZGVyT2ZmU2NyZWVuOiBcIm1hYzpXaW5kb3dXaWxsT3JkZXJPZmZTY3JlZW5cIixcblx0XHRXaW5kb3dXaWxsT3JkZXJPblNjcmVlbjogXCJtYWM6V2luZG93V2lsbE9yZGVyT25TY3JlZW5cIixcblx0XHRXaW5kb3dXaWxsUmVzaWduTWFpbjogXCJtYWM6V2luZG93V2lsbFJlc2lnbk1haW5cIixcblx0XHRXaW5kb3dXaWxsUmVzaXplOiBcIm1hYzpXaW5kb3dXaWxsUmVzaXplXCIsXG5cdFx0V2luZG93V2lsbFVuZm9jdXM6IFwibWFjOldpbmRvd1dpbGxVbmZvY3VzXCIsXG5cdFx0V2luZG93V2lsbFVwZGF0ZTogXCJtYWM6V2luZG93V2lsbFVwZGF0ZVwiLFxuXHRcdFdpbmRvd1dpbGxVcGRhdGVBbHBoYTogXCJtYWM6V2luZG93V2lsbFVwZGF0ZUFscGhhXCIsXG5cdFx0V2luZG93V2lsbFVwZGF0ZUNvbGxlY3Rpb25CZWhhdmlvcjogXCJtYWM6V2luZG93V2lsbFVwZGF0ZUNvbGxlY3Rpb25CZWhhdmlvclwiLFxuXHRcdFdpbmRvd1dpbGxVcGRhdGVDb2xsZWN0aW9uUHJvcGVydGllczogXCJtYWM6V2luZG93V2lsbFVwZGF0ZUNvbGxlY3Rpb25Qcm9wZXJ0aWVzXCIsXG5cdFx0V2luZG93V2lsbFVwZGF0ZVNoYWRvdzogXCJtYWM6V2luZG93V2lsbFVwZGF0ZVNoYWRvd1wiLFxuXHRcdFdpbmRvd1dpbGxVcGRhdGVUaXRsZTogXCJtYWM6V2luZG93V2lsbFVwZGF0ZVRpdGxlXCIsXG5cdFx0V2luZG93V2lsbFVwZGF0ZVRvb2xiYXI6IFwibWFjOldpbmRvd1dpbGxVcGRhdGVUb29sYmFyXCIsXG5cdFx0V2luZG93V2lsbFVwZGF0ZVZpc2liaWxpdHk6IFwibWFjOldpbmRvd1dpbGxVcGRhdGVWaXNpYmlsaXR5XCIsXG5cdFx0V2luZG93V2lsbFVzZVN0YW5kYXJkRnJhbWU6IFwibWFjOldpbmRvd1dpbGxVc2VTdGFuZGFyZEZyYW1lXCIsXG5cdFx0V2luZG93Wm9vbUluOiBcIm1hYzpXaW5kb3dab29tSW5cIixcblx0XHRXaW5kb3dab29tT3V0OiBcIm1hYzpXaW5kb3dab29tT3V0XCIsXG5cdFx0V2luZG93Wm9vbVJlc2V0OiBcIm1hYzpXaW5kb3dab29tUmVzZXRcIixcblx0fSksXG5cdExpbnV4OiBPYmplY3QuZnJlZXplKHtcblx0XHRBcHBsaWNhdGlvblN0YXJ0dXA6IFwibGludXg6QXBwbGljYXRpb25TdGFydHVwXCIsXG5cdFx0U3lzdGVtVGhlbWVDaGFuZ2VkOiBcImxpbnV4OlN5c3RlbVRoZW1lQ2hhbmdlZFwiLFxuXHRcdFdpbmRvd0RlbGV0ZUV2ZW50OiBcImxpbnV4OldpbmRvd0RlbGV0ZUV2ZW50XCIsXG5cdFx0V2luZG93RGlkTW92ZTogXCJsaW51eDpXaW5kb3dEaWRNb3ZlXCIsXG5cdFx0V2luZG93RGlkUmVzaXplOiBcImxpbnV4OldpbmRvd0RpZFJlc2l6ZVwiLFxuXHRcdFdpbmRvd0ZvY3VzSW46IFwibGludXg6V2luZG93Rm9jdXNJblwiLFxuXHRcdFdpbmRvd0ZvY3VzT3V0OiBcImxpbnV4OldpbmRvd0ZvY3VzT3V0XCIsXG5cdFx0V2luZG93TG9hZFN0YXJ0ZWQ6IFwibGludXg6V2luZG93TG9hZFN0YXJ0ZWRcIixcblx0XHRXaW5kb3dMb2FkUmVkaXJlY3RlZDogXCJsaW51eDpXaW5kb3dMb2FkUmVkaXJlY3RlZFwiLFxuXHRcdFdpbmRvd0xvYWRDb21taXR0ZWQ6IFwibGludXg6V2luZG93TG9hZENvbW1pdHRlZFwiLFxuXHRcdFdpbmRvd0xvYWRGaW5pc2hlZDogXCJsaW51eDpXaW5kb3dMb2FkRmluaXNoZWRcIixcblx0fSksXG5cdGlPUzogT2JqZWN0LmZyZWV6ZSh7XG5cdFx0QXBwbGljYXRpb25EaWRCZWNvbWVBY3RpdmU6IFwiaW9zOkFwcGxpY2F0aW9uRGlkQmVjb21lQWN0aXZlXCIsXG5cdFx0QXBwbGljYXRpb25EaWRFbnRlckJhY2tncm91bmQ6IFwiaW9zOkFwcGxpY2F0aW9uRGlkRW50ZXJCYWNrZ3JvdW5kXCIsXG5cdFx0QXBwbGljYXRpb25EaWRGaW5pc2hMYXVuY2hpbmc6IFwiaW9zOkFwcGxpY2F0aW9uRGlkRmluaXNoTGF1bmNoaW5nXCIsXG5cdFx0QXBwbGljYXRpb25EaWRSZWNlaXZlTWVtb3J5V2FybmluZzogXCJpb3M6QXBwbGljYXRpb25EaWRSZWNlaXZlTWVtb3J5V2FybmluZ1wiLFxuXHRcdEFwcGxpY2F0aW9uV2lsbEVudGVyRm9yZWdyb3VuZDogXCJpb3M6QXBwbGljYXRpb25XaWxsRW50ZXJGb3JlZ3JvdW5kXCIsXG5cdFx0QXBwbGljYXRpb25XaWxsUmVzaWduQWN0aXZlOiBcImlvczpBcHBsaWNhdGlvbldpbGxSZXNpZ25BY3RpdmVcIixcblx0XHRBcHBsaWNhdGlvbldpbGxUZXJtaW5hdGU6IFwiaW9zOkFwcGxpY2F0aW9uV2lsbFRlcm1pbmF0ZVwiLFxuXHRcdFdpbmRvd0RpZExvYWQ6IFwiaW9zOldpbmRvd0RpZExvYWRcIixcblx0XHRXaW5kb3dXaWxsQXBwZWFyOiBcImlvczpXaW5kb3dXaWxsQXBwZWFyXCIsXG5cdFx0V2luZG93RGlkQXBwZWFyOiBcImlvczpXaW5kb3dEaWRBcHBlYXJcIixcblx0XHRXaW5kb3dXaWxsRGlzYXBwZWFyOiBcImlvczpXaW5kb3dXaWxsRGlzYXBwZWFyXCIsXG5cdFx0V2luZG93RGlkRGlzYXBwZWFyOiBcImlvczpXaW5kb3dEaWREaXNhcHBlYXJcIixcblx0XHRXaW5kb3dTYWZlQXJlYUluc2V0c0NoYW5nZWQ6IFwiaW9zOldpbmRvd1NhZmVBcmVhSW5zZXRzQ2hhbmdlZFwiLFxuXHRcdFdpbmRvd09yaWVudGF0aW9uQ2hhbmdlZDogXCJpb3M6V2luZG93T3JpZW50YXRpb25DaGFuZ2VkXCIsXG5cdFx0V2luZG93VG91Y2hCZWdhbjogXCJpb3M6V2luZG93VG91Y2hCZWdhblwiLFxuXHRcdFdpbmRvd1RvdWNoTW92ZWQ6IFwiaW9zOldpbmRvd1RvdWNoTW92ZWRcIixcblx0XHRXaW5kb3dUb3VjaEVuZGVkOiBcImlvczpXaW5kb3dUb3VjaEVuZGVkXCIsXG5cdFx0V2luZG93VG91Y2hDYW5jZWxsZWQ6IFwiaW9zOldpbmRvd1RvdWNoQ2FuY2VsbGVkXCIsXG5cdFx0V2ViVmlld0RpZFN0YXJ0TmF2aWdhdGlvbjogXCJpb3M6V2ViVmlld0RpZFN0YXJ0TmF2aWdhdGlvblwiLFxuXHRcdFdlYlZpZXdEaWRGaW5pc2hOYXZpZ2F0aW9uOiBcImlvczpXZWJWaWV3RGlkRmluaXNoTmF2aWdhdGlvblwiLFxuXHRcdFdlYlZpZXdEaWRGYWlsTmF2aWdhdGlvbjogXCJpb3M6V2ViVmlld0RpZEZhaWxOYXZpZ2F0aW9uXCIsXG5cdFx0V2ViVmlld0RlY2lkZVBvbGljeUZvck5hdmlnYXRpb25BY3Rpb246IFwiaW9zOldlYlZpZXdEZWNpZGVQb2xpY3lGb3JOYXZpZ2F0aW9uQWN0aW9uXCIsXG5cdH0pLFxuXHRDb21tb246IE9iamVjdC5mcmVlemUoe1xuXHRcdEFwcGxpY2F0aW9uT3BlbmVkV2l0aEZpbGU6IFwiY29tbW9uOkFwcGxpY2F0aW9uT3BlbmVkV2l0aEZpbGVcIixcblx0XHRBcHBsaWNhdGlvblN0YXJ0ZWQ6IFwiY29tbW9uOkFwcGxpY2F0aW9uU3RhcnRlZFwiLFxuXHRcdEFwcGxpY2F0aW9uTGF1bmNoZWRXaXRoVXJsOiBcImNvbW1vbjpBcHBsaWNhdGlvbkxhdW5jaGVkV2l0aFVybFwiLFxuXHRcdFRoZW1lQ2hhbmdlZDogXCJjb21tb246VGhlbWVDaGFuZ2VkXCIsXG5cdFx0V2luZG93Q2xvc2luZzogXCJjb21tb246V2luZG93Q2xvc2luZ1wiLFxuXHRcdFdpbmRvd0RpZE1vdmU6IFwiY29tbW9uOldpbmRvd0RpZE1vdmVcIixcblx0XHRXaW5kb3dEaWRSZXNpemU6IFwiY29tbW9uOldpbmRvd0RpZFJlc2l6ZVwiLFxuXHRcdFdpbmRvd0RQSUNoYW5nZWQ6IFwiY29tbW9uOldpbmRvd0RQSUNoYW5nZWRcIixcblx0XHRXaW5kb3dGaWxlc0Ryb3BwZWQ6IFwiY29tbW9uOldpbmRvd0ZpbGVzRHJvcHBlZFwiLFxuXHRcdFdpbmRvd0ZvY3VzOiBcImNvbW1vbjpXaW5kb3dGb2N1c1wiLFxuXHRcdFdpbmRvd0Z1bGxzY3JlZW46IFwiY29tbW9uOldpbmRvd0Z1bGxzY3JlZW5cIixcblx0XHRXaW5kb3dIaWRlOiBcImNvbW1vbjpXaW5kb3dIaWRlXCIsXG5cdFx0V2luZG93TG9zdEZvY3VzOiBcImNvbW1vbjpXaW5kb3dMb3N0Rm9jdXNcIixcblx0XHRXaW5kb3dNYXhpbWlzZTogXCJjb21tb246V2luZG93TWF4aW1pc2VcIixcblx0XHRXaW5kb3dNaW5pbWlzZTogXCJjb21tb246V2luZG93TWluaW1pc2VcIixcblx0XHRXaW5kb3dUb2dnbGVGcmFtZWxlc3M6IFwiY29tbW9uOldpbmRvd1RvZ2dsZUZyYW1lbGVzc1wiLFxuXHRcdFdpbmRvd1Jlc3RvcmU6IFwiY29tbW9uOldpbmRvd1Jlc3RvcmVcIixcblx0XHRXaW5kb3dSdW50aW1lUmVhZHk6IFwiY29tbW9uOldpbmRvd1J1bnRpbWVSZWFkeVwiLFxuXHRcdFdpbmRvd1Nob3c6IFwiY29tbW9uOldpbmRvd1Nob3dcIixcblx0XHRXaW5kb3dVbkZ1bGxzY3JlZW46IFwiY29tbW9uOldpbmRvd1VuRnVsbHNjcmVlblwiLFxuXHRcdFdpbmRvd1VuTWF4aW1pc2U6IFwiY29tbW9uOldpbmRvd1VuTWF4aW1pc2VcIixcblx0XHRXaW5kb3dVbk1pbmltaXNlOiBcImNvbW1vbjpXaW5kb3dVbk1pbmltaXNlXCIsXG5cdFx0V2luZG93Wm9vbTogXCJjb21tb246V2luZG93Wm9vbVwiLFxuXHRcdFdpbmRvd1pvb21JbjogXCJjb21tb246V2luZG93Wm9vbUluXCIsXG5cdFx0V2luZG93Wm9vbU91dDogXCJjb21tb246V2luZG93Wm9vbU91dFwiLFxuXHRcdFdpbmRvd1pvb21SZXNldDogXCJjb21tb246V2luZG93Wm9vbVJlc2V0XCIsXG5cdH0pLFxufSk7XG4iLCAiLypcbiBfICAgICBfXyAgICAgXyBfX1xufCB8ICAvIC9fX18gXyhfKSAvX19fX1xufCB8IC98IC8gLyBfXyBgLyAvIC8gX19fL1xufCB8LyB8LyAvIC9fLyAvIC8gKF9fICApXG58X18vfF9fL1xcX18sXy9fL18vX19fXy9cblRoZSBlbGVjdHJvbiBhbHRlcm5hdGl2ZSBmb3IgR29cbihjKSBMZWEgQW50aG9ueSAyMDE5LXByZXNlbnRcbiovXG5cbi8qKlxuICogTG9ncyBhIG1lc3NhZ2UgdG8gdGhlIGNvbnNvbGUgd2l0aCBjdXN0b20gZm9ybWF0dGluZy5cbiAqXG4gKiBAcGFyYW0gbWVzc2FnZSAtIFRoZSBtZXNzYWdlIHRvIGJlIGxvZ2dlZC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGRlYnVnTG9nKG1lc3NhZ2U6IGFueSkge1xuICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZVxuICAgIGNvbnNvbGUubG9nKFxuICAgICAgICAnJWMgd2FpbHMzICVjICcgKyBtZXNzYWdlICsgJyAnLFxuICAgICAgICAnYmFja2dyb3VuZDogI2FhMDAwMDsgY29sb3I6ICNmZmY7IGJvcmRlci1yYWRpdXM6IDNweCAwcHggMHB4IDNweDsgcGFkZGluZzogMXB4OyBmb250LXNpemU6IDAuN3JlbScsXG4gICAgICAgICdiYWNrZ3JvdW5kOiAjMDA5OTAwOyBjb2xvcjogI2ZmZjsgYm9yZGVyLXJhZGl1czogMHB4IDNweCAzcHggMHB4OyBwYWRkaW5nOiAxcHg7IGZvbnQtc2l6ZTogMC43cmVtJ1xuICAgICk7XG59XG5cbi8qKlxuICogQ2hlY2tzIHdoZXRoZXIgdGhlIHdlYnZpZXcgc3VwcG9ydHMgdGhlIHtAbGluayBNb3VzZUV2ZW50I2J1dHRvbnN9IHByb3BlcnR5LlxuICogTG9va2luZyBhdCB5b3UgbWFjT1MgSGlnaCBTaWVycmEhXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBjYW5UcmFja0J1dHRvbnMoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIChuZXcgTW91c2VFdmVudCgnbW91c2Vkb3duJykpLmJ1dHRvbnMgPT09IDA7XG59XG5cbi8qKlxuICogQ2hlY2tzIHdoZXRoZXIgdGhlIGJyb3dzZXIgc3VwcG9ydHMgcmVtb3ZpbmcgbGlzdGVuZXJzIGJ5IHRyaWdnZXJpbmcgYW4gQWJvcnRTaWduYWxcbiAqIChzZWUgaHR0cHM6Ly9kZXZlbG9wZXIubW96aWxsYS5vcmcvZW4tVVMvZG9jcy9XZWIvQVBJL0V2ZW50VGFyZ2V0L2FkZEV2ZW50TGlzdGVuZXIjc2lnbmFsKS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGNhbkFib3J0TGlzdGVuZXJzKCkge1xuICAgIGlmICghRXZlbnRUYXJnZXQgfHwgIUFib3J0U2lnbmFsIHx8ICFBYm9ydENvbnRyb2xsZXIpXG4gICAgICAgIHJldHVybiBmYWxzZTtcblxuICAgIGxldCByZXN1bHQgPSB0cnVlO1xuXG4gICAgY29uc3QgdGFyZ2V0ID0gbmV3IEV2ZW50VGFyZ2V0KCk7XG4gICAgY29uc3QgY29udHJvbGxlciA9IG5ldyBBYm9ydENvbnRyb2xsZXIoKTtcbiAgICB0YXJnZXQuYWRkRXZlbnRMaXN0ZW5lcigndGVzdCcsICgpID0+IHsgcmVzdWx0ID0gZmFsc2U7IH0sIHsgc2lnbmFsOiBjb250cm9sbGVyLnNpZ25hbCB9KTtcbiAgICBjb250cm9sbGVyLmFib3J0KCk7XG4gICAgdGFyZ2V0LmRpc3BhdGNoRXZlbnQobmV3IEN1c3RvbUV2ZW50KCd0ZXN0JykpO1xuXG4gICAgcmV0dXJuIHJlc3VsdDtcbn1cblxuLyoqXG4gKiBSZXNvbHZlcyB0aGUgY2xvc2VzdCBIVE1MRWxlbWVudCBhbmNlc3RvciBvZiBhbiBldmVudCdzIHRhcmdldC5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGV2ZW50VGFyZ2V0KGV2ZW50OiBFdmVudCk6IEhUTUxFbGVtZW50IHtcbiAgICBpZiAoZXZlbnQudGFyZ2V0IGluc3RhbmNlb2YgSFRNTEVsZW1lbnQpIHtcbiAgICAgICAgcmV0dXJuIGV2ZW50LnRhcmdldDtcbiAgICB9IGVsc2UgaWYgKCEoZXZlbnQudGFyZ2V0IGluc3RhbmNlb2YgSFRNTEVsZW1lbnQpICYmIGV2ZW50LnRhcmdldCBpbnN0YW5jZW9mIE5vZGUpIHtcbiAgICAgICAgcmV0dXJuIGV2ZW50LnRhcmdldC5wYXJlbnRFbGVtZW50ID8/IGRvY3VtZW50LmJvZHk7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIGRvY3VtZW50LmJvZHk7XG4gICAgfVxufVxuXG4vKioqXG4gVGhpcyB0ZWNobmlxdWUgZm9yIHByb3BlciBsb2FkIGRldGVjdGlvbiBpcyB0YWtlbiBmcm9tIEhUTVg6XG5cbiBCU0QgMi1DbGF1c2UgTGljZW5zZVxuXG4gQ29weXJpZ2h0IChjKSAyMDIwLCBCaWcgU2t5IFNvZnR3YXJlXG4gQWxsIHJpZ2h0cyByZXNlcnZlZC5cblxuIFJlZGlzdHJpYnV0aW9uIGFuZCB1c2UgaW4gc291cmNlIGFuZCBiaW5hcnkgZm9ybXMsIHdpdGggb3Igd2l0aG91dFxuIG1vZGlmaWNhdGlvbiwgYXJlIHBlcm1pdHRlZCBwcm92aWRlZCB0aGF0IHRoZSBmb2xsb3dpbmcgY29uZGl0aW9ucyBhcmUgbWV0OlxuXG4gMS4gUmVkaXN0cmlidXRpb25zIG9mIHNvdXJjZSBjb2RlIG11c3QgcmV0YWluIHRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlLCB0aGlzXG4gbGlzdCBvZiBjb25kaXRpb25zIGFuZCB0aGUgZm9sbG93aW5nIGRpc2NsYWltZXIuXG5cbiAyLiBSZWRpc3RyaWJ1dGlvbnMgaW4gYmluYXJ5IGZvcm0gbXVzdCByZXByb2R1Y2UgdGhlIGFib3ZlIGNvcHlyaWdodCBub3RpY2UsXG4gdGhpcyBsaXN0IG9mIGNvbmRpdGlvbnMgYW5kIHRoZSBmb2xsb3dpbmcgZGlzY2xhaW1lciBpbiB0aGUgZG9jdW1lbnRhdGlvblxuIGFuZC9vciBvdGhlciBtYXRlcmlhbHMgcHJvdmlkZWQgd2l0aCB0aGUgZGlzdHJpYnV0aW9uLlxuXG4gVEhJUyBTT0ZUV0FSRSBJUyBQUk9WSURFRCBCWSBUSEUgQ09QWVJJR0hUIEhPTERFUlMgQU5EIENPTlRSSUJVVE9SUyBcIkFTIElTXCJcbiBBTkQgQU5ZIEVYUFJFU1MgT1IgSU1QTElFRCBXQVJSQU5USUVTLCBJTkNMVURJTkcsIEJVVCBOT1QgTElNSVRFRCBUTywgVEhFXG4gSU1QTElFRCBXQVJSQU5USUVTIE9GIE1FUkNIQU5UQUJJTElUWSBBTkQgRklUTkVTUyBGT1IgQSBQQVJUSUNVTEFSIFBVUlBPU0UgQVJFXG4gRElTQ0xBSU1FRC4gSU4gTk8gRVZFTlQgU0hBTEwgVEhFIENPUFlSSUdIVCBIT0xERVIgT1IgQ09OVFJJQlVUT1JTIEJFIExJQUJMRVxuIEZPUiBBTlkgRElSRUNULCBJTkRJUkVDVCwgSU5DSURFTlRBTCwgU1BFQ0lBTCwgRVhFTVBMQVJZLCBPUiBDT05TRVFVRU5USUFMXG4gREFNQUdFUyAoSU5DTFVESU5HLCBCVVQgTk9UIExJTUlURUQgVE8sIFBST0NVUkVNRU5UIE9GIFNVQlNUSVRVVEUgR09PRFMgT1JcbiBTRVJWSUNFUzsgTE9TUyBPRiBVU0UsIERBVEEsIE9SIFBST0ZJVFM7IE9SIEJVU0lORVNTIElOVEVSUlVQVElPTikgSE9XRVZFUlxuIENBVVNFRCBBTkQgT04gQU5ZIFRIRU9SWSBPRiBMSUFCSUxJVFksIFdIRVRIRVIgSU4gQ09OVFJBQ1QsIFNUUklDVCBMSUFCSUxJVFksXG4gT1IgVE9SVCAoSU5DTFVESU5HIE5FR0xJR0VOQ0UgT1IgT1RIRVJXSVNFKSBBUklTSU5HIElOIEFOWSBXQVkgT1VUIE9GIFRIRSBVU0VcbiBPRiBUSElTIFNPRlRXQVJFLCBFVkVOIElGIEFEVklTRUQgT0YgVEhFIFBPU1NJQklMSVRZIE9GIFNVQ0ggREFNQUdFLlxuXG4gKioqL1xuXG5sZXQgaXNSZWFkeSA9IGZhbHNlO1xuZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcignRE9NQ29udGVudExvYWRlZCcsICgpID0+IHsgaXNSZWFkeSA9IHRydWUgfSk7XG5cbmV4cG9ydCBmdW5jdGlvbiB3aGVuUmVhZHkoY2FsbGJhY2s6ICgpID0+IHZvaWQpIHtcbiAgICBpZiAoaXNSZWFkeSB8fCBkb2N1bWVudC5yZWFkeVN0YXRlID09PSAnY29tcGxldGUnKSB7XG4gICAgICAgIGNhbGxiYWNrKCk7XG4gICAgfSBlbHNlIHtcbiAgICAgICAgZG9jdW1lbnQuYWRkRXZlbnRMaXN0ZW5lcignRE9NQ29udGVudExvYWRlZCcsIGNhbGxiYWNrKTtcbiAgICB9XG59XG4iLCAiLypcbiBfXHQgICBfX1x0ICBfIF9fXG58IHxcdCAvIC9fX18gXyhfKSAvX19fX1xufCB8IC98IC8gLyBfXyBgLyAvIC8gX19fL1xufCB8LyB8LyAvIC9fLyAvIC8gKF9fICApXG58X18vfF9fL1xcX18sXy9fL18vX19fXy9cblRoZSBlbGVjdHJvbiBhbHRlcm5hdGl2ZSBmb3IgR29cbihjKSBMZWEgQW50aG9ueSAyMDE5LXByZXNlbnRcbiovXG5cbmltcG9ydCB7bmV3UnVudGltZUNhbGxlciwgb2JqZWN0TmFtZXN9IGZyb20gXCIuL3J1bnRpbWUuanNcIjtcbmltcG9ydCB0eXBlIHsgU2NyZWVuIH0gZnJvbSBcIi4vc2NyZWVucy5qc1wiO1xuXG4vLyBEcm9wIHRhcmdldCBjb25zdGFudHNcbmNvbnN0IERST1BfVEFSR0VUX0FUVFJJQlVURSA9ICdkYXRhLWZpbGUtZHJvcC10YXJnZXQnO1xuY29uc3QgRFJPUF9UQVJHRVRfQUNUSVZFX0NMQVNTID0gJ2ZpbGUtZHJvcC10YXJnZXQtYWN0aXZlJztcbmxldCBjdXJyZW50RHJvcFRhcmdldDogRWxlbWVudCB8IG51bGwgPSBudWxsO1xuXG5jb25zdCBQb3NpdGlvbk1ldGhvZCAgICAgICAgICAgICAgICAgICAgPSAwO1xuY29uc3QgQ2VudGVyTWV0aG9kICAgICAgICAgICAgICAgICAgICAgID0gMTtcbmNvbnN0IENsb3NlTWV0aG9kICAgICAgICAgICAgICAgICAgICAgICA9IDI7XG5jb25zdCBEaXNhYmxlU2l6ZUNvbnN0cmFpbnRzTWV0aG9kICAgICAgPSAzO1xuY29uc3QgRW5hYmxlU2l6ZUNvbnN0cmFpbnRzTWV0aG9kICAgICAgID0gNDtcbmNvbnN0IEZvY3VzTWV0aG9kICAgICAgICAgICAgICAgICAgICAgICA9IDU7XG5jb25zdCBGb3JjZVJlbG9hZE1ldGhvZCAgICAgICAgICAgICAgICAgPSA2O1xuY29uc3QgRnVsbHNjcmVlbk1ldGhvZCAgICAgICAgICAgICAgICAgID0gNztcbmNvbnN0IEdldFNjcmVlbk1ldGhvZCAgICAgICAgICAgICAgICAgICA9IDg7XG5jb25zdCBHZXRab29tTWV0aG9kICAgICAgICAgICAgICAgICAgICAgPSA5O1xuY29uc3QgSGVpZ2h0TWV0aG9kICAgICAgICAgICAgICAgICAgICAgID0gMTA7XG5jb25zdCBIaWRlTWV0aG9kICAgICAgICAgICAgICAgICAgICAgICAgPSAxMTtcbmNvbnN0IElzRm9jdXNlZE1ldGhvZCAgICAgICAgICAgICAgICAgICA9IDEyO1xuY29uc3QgSXNGdWxsc2NyZWVuTWV0aG9kICAgICAgICAgICAgICAgID0gMTM7XG5jb25zdCBJc01heGltaXNlZE1ldGhvZCAgICAgICAgICAgICAgICAgPSAxNDtcbmNvbnN0IElzTWluaW1pc2VkTWV0aG9kICAgICAgICAgICAgICAgICA9IDE1O1xuY29uc3QgTWF4aW1pc2VNZXRob2QgICAgICAgICAgICAgICAgICAgID0gMTY7XG5jb25zdCBNaW5pbWlzZU1ldGhvZCAgICAgICAgICAgICAgICAgICAgPSAxNztcbmNvbnN0IE5hbWVNZXRob2QgICAgICAgICAgICAgICAgICAgICAgICA9IDE4O1xuY29uc3QgT3BlbkRldlRvb2xzTWV0aG9kICAgICAgICAgICAgICAgID0gMTk7XG5jb25zdCBSZWxhdGl2ZVBvc2l0aW9uTWV0aG9kICAgICAgICAgICAgPSAyMDtcbmNvbnN0IFJlbG9hZE1ldGhvZCAgICAgICAgICAgICAgICAgICAgICA9IDIxO1xuY29uc3QgUmVzaXphYmxlTWV0aG9kICAgICAgICAgICAgICAgICAgID0gMjI7XG5jb25zdCBSZXN0b3JlTWV0aG9kICAgICAgICAgICAgICAgICAgICAgPSAyMztcbmNvbnN0IFNldFBvc2l0aW9uTWV0aG9kICAgICAgICAgICAgICAgICA9IDI0O1xuY29uc3QgU2V0QWx3YXlzT25Ub3BNZXRob2QgICAgICAgICAgICAgID0gMjU7XG5jb25zdCBTZXRCYWNrZ3JvdW5kQ29sb3VyTWV0aG9kICAgICAgICAgPSAyNjtcbmNvbnN0IFNldEZyYW1lbGVzc01ldGhvZCAgICAgICAgICAgICAgICA9IDI3O1xuY29uc3QgU2V0RnVsbHNjcmVlbkJ1dHRvbkVuYWJsZWRNZXRob2QgID0gMjg7XG5jb25zdCBTZXRNYXhTaXplTWV0aG9kICAgICAgICAgICAgICAgICAgPSAyOTtcbmNvbnN0IFNldE1pblNpemVNZXRob2QgICAgICAgICAgICAgICAgICA9IDMwO1xuY29uc3QgU2V0UmVsYXRpdmVQb3NpdGlvbk1ldGhvZCAgICAgICAgID0gMzE7XG5jb25zdCBTZXRSZXNpemFibGVNZXRob2QgICAgICAgICAgICAgICAgPSAzMjtcbmNvbnN0IFNldFNpemVNZXRob2QgICAgICAgICAgICAgICAgICAgICA9IDMzO1xuY29uc3QgU2V0VGl0bGVNZXRob2QgICAgICAgICAgICAgICAgICAgID0gMzQ7XG5jb25zdCBTZXRab29tTWV0aG9kICAgICAgICAgICAgICAgICAgICAgPSAzNTtcbmNvbnN0IFNob3dNZXRob2QgICAgICAgICAgICAgICAgICAgICAgICA9IDM2O1xuY29uc3QgU2l6ZU1ldGhvZCAgICAgICAgICAgICAgICAgICAgICAgID0gMzc7XG5jb25zdCBUb2dnbGVGdWxsc2NyZWVuTWV0aG9kICAgICAgICAgICAgPSAzODtcbmNvbnN0IFRvZ2dsZU1heGltaXNlTWV0aG9kICAgICAgICAgICAgICA9IDM5O1xuY29uc3QgVG9nZ2xlRnJhbWVsZXNzTWV0aG9kICAgICAgICAgICAgID0gNDA7IFxuY29uc3QgVW5GdWxsc2NyZWVuTWV0aG9kICAgICAgICAgICAgICAgID0gNDE7XG5jb25zdCBVbk1heGltaXNlTWV0aG9kICAgICAgICAgICAgICAgICAgPSA0MjtcbmNvbnN0IFVuTWluaW1pc2VNZXRob2QgICAgICAgICAgICAgICAgICA9IDQzO1xuY29uc3QgV2lkdGhNZXRob2QgICAgICAgICAgICAgICAgICAgICAgID0gNDQ7XG5jb25zdCBab29tTWV0aG9kICAgICAgICAgICAgICAgICAgICAgICAgPSA0NTtcbmNvbnN0IFpvb21Jbk1ldGhvZCAgICAgICAgICAgICAgICAgICAgICA9IDQ2O1xuY29uc3QgWm9vbU91dE1ldGhvZCAgICAgICAgICAgICAgICAgICAgID0gNDc7XG5jb25zdCBab29tUmVzZXRNZXRob2QgICAgICAgICAgICAgICAgICAgPSA0ODtcbmNvbnN0IFNuYXBBc3Npc3RNZXRob2QgICAgICAgICAgICAgICAgICA9IDQ5O1xuY29uc3QgRmlsZXNEcm9wcGVkICAgICAgICAgICAgICAgICAgICAgID0gNTA7XG5jb25zdCBQcmludE1ldGhvZCAgICAgICAgICAgICAgICAgICAgICAgPSA1MTtcblxuLyoqXG4gKiBGaW5kcyB0aGUgbmVhcmVzdCBkcm9wIHRhcmdldCBlbGVtZW50IGJ5IHdhbGtpbmcgdXAgdGhlIERPTSB0cmVlLlxuICovXG5mdW5jdGlvbiBnZXREcm9wVGFyZ2V0RWxlbWVudChlbGVtZW50OiBFbGVtZW50IHwgbnVsbCk6IEVsZW1lbnQgfCBudWxsIHtcbiAgICBpZiAoIWVsZW1lbnQpIHtcbiAgICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuICAgIHJldHVybiBlbGVtZW50LmNsb3Nlc3QoYFske0RST1BfVEFSR0VUX0FUVFJJQlVURX1dYCk7XG59XG5cbi8qKlxuICogQ2hlY2sgaWYgd2UgY2FuIHVzZSBXZWJWaWV3MidzIHBvc3RNZXNzYWdlV2l0aEFkZGl0aW9uYWxPYmplY3RzIChXaW5kb3dzKVxuICogQWxzbyBjaGVja3MgdGhhdCBFbmFibGVGaWxlRHJvcCBpcyB0cnVlIGZvciB0aGlzIHdpbmRvdy5cbiAqL1xuZnVuY3Rpb24gY2FuUmVzb2x2ZUZpbGVQYXRocygpOiBib29sZWFuIHtcbiAgICAvLyBNdXN0IGhhdmUgV2ViVmlldzIncyBwb3N0TWVzc2FnZVdpdGhBZGRpdGlvbmFsT2JqZWN0cyBBUEkgKFdpbmRvd3Mgb25seSlcbiAgICBpZiAoKHdpbmRvdyBhcyBhbnkpLmNocm9tZT8ud2Vidmlldz8ucG9zdE1lc3NhZ2VXaXRoQWRkaXRpb25hbE9iamVjdHMgPT0gbnVsbCkge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuICAgIC8vIE11c3QgaGF2ZSBFbmFibGVGaWxlRHJvcCBzZXQgdG8gdHJ1ZSBmb3IgdGhpcyB3aW5kb3dcbiAgICAvLyBUaGlzIGZsYWcgaXMgc2V0IGJ5IHRoZSBHbyBiYWNrZW5kIGR1cmluZyBydW50aW1lIGluaXRpYWxpemF0aW9uXG4gICAgcmV0dXJuICh3aW5kb3cgYXMgYW55KS5fd2FpbHM/LmZsYWdzPy5lbmFibGVGaWxlRHJvcCA9PT0gdHJ1ZTtcbn1cblxuLyoqXG4gKiBTZW5kIGZpbGUgZHJvcCB0byBiYWNrZW5kIHZpYSBXZWJWaWV3MiAoV2luZG93cyBvbmx5KVxuICovXG5mdW5jdGlvbiByZXNvbHZlRmlsZVBhdGhzKHg6IG51bWJlciwgeTogbnVtYmVyLCBmaWxlczogRmlsZVtdKTogdm9pZCB7XG4gICAgaWYgKCh3aW5kb3cgYXMgYW55KS5jaHJvbWU/LndlYnZpZXc/LnBvc3RNZXNzYWdlV2l0aEFkZGl0aW9uYWxPYmplY3RzKSB7XG4gICAgICAgICh3aW5kb3cgYXMgYW55KS5jaHJvbWUud2Vidmlldy5wb3N0TWVzc2FnZVdpdGhBZGRpdGlvbmFsT2JqZWN0cyhgZmlsZTpkcm9wOiR7eH06JHt5fWAsIGZpbGVzKTtcbiAgICB9XG59XG5cbi8vIE5hdGl2ZSBkcmFnIHN0YXRlIChMaW51eC9tYWNPUyBpbnRlcmNlcHQgRE9NIGRyYWcgZXZlbnRzKVxubGV0IG5hdGl2ZURyYWdBY3RpdmUgPSBmYWxzZTtcblxuLyoqXG4gKiBDbGVhbnMgdXAgbmF0aXZlIGRyYWcgc3RhdGUgYW5kIGhvdmVyIGVmZmVjdHMuXG4gKiBDYWxsZWQgb24gZHJvcCBvciB3aGVuIGRyYWcgbGVhdmVzIHRoZSB3aW5kb3cuXG4gKi9cbmZ1bmN0aW9uIGNsZWFudXBOYXRpdmVEcmFnKCk6IHZvaWQge1xuICAgIG5hdGl2ZURyYWdBY3RpdmUgPSBmYWxzZTtcbiAgICBpZiAoY3VycmVudERyb3BUYXJnZXQpIHtcbiAgICAgICAgY3VycmVudERyb3BUYXJnZXQuY2xhc3NMaXN0LnJlbW92ZShEUk9QX1RBUkdFVF9BQ1RJVkVfQ0xBU1MpO1xuICAgICAgICBjdXJyZW50RHJvcFRhcmdldCA9IG51bGw7XG4gICAgfVxufVxuXG4vKipcbiAqIENhbGxlZCBmcm9tIEdvIHdoZW4gYSBmaWxlIGRyYWcgZW50ZXJzIHRoZSB3aW5kb3cgb24gTGludXgvbWFjT1MuXG4gKi9cbmZ1bmN0aW9uIGhhbmRsZURyYWdFbnRlcigpOiB2b2lkIHtcbiAgICAvLyBDaGVjayBpZiBmaWxlIGRyb3BzIGFyZSBlbmFibGVkIGZvciB0aGlzIHdpbmRvd1xuICAgIGlmICgod2luZG93IGFzIGFueSkuX3dhaWxzPy5mbGFncz8uZW5hYmxlRmlsZURyb3AgPT09IGZhbHNlKSB7XG4gICAgICAgIHJldHVybjsgLy8gRmlsZSBkcm9wcyBkaXNhYmxlZCwgZG9uJ3QgYWN0aXZhdGUgZHJhZyBzdGF0ZVxuICAgIH1cbiAgICBuYXRpdmVEcmFnQWN0aXZlID0gdHJ1ZTtcbn1cblxuLyoqXG4gKiBDYWxsZWQgZnJvbSBHbyB3aGVuIGEgZmlsZSBkcmFnIGxlYXZlcyB0aGUgd2luZG93IG9uIExpbnV4L21hY09TLlxuICovXG5mdW5jdGlvbiBoYW5kbGVEcmFnTGVhdmUoKTogdm9pZCB7XG4gICAgY2xlYW51cE5hdGl2ZURyYWcoKTtcbn1cblxuLyoqXG4gKiBDYWxsZWQgZnJvbSBHbyBkdXJpbmcgZmlsZSBkcmFnIHRvIHVwZGF0ZSBob3ZlciBzdGF0ZSBvbiBMaW51eC9tYWNPUy5cbiAqIEBwYXJhbSB4IC0gWCBjb29yZGluYXRlIGluIENTUyBwaXhlbHNcbiAqIEBwYXJhbSB5IC0gWSBjb29yZGluYXRlIGluIENTUyBwaXhlbHNcbiAqL1xuZnVuY3Rpb24gaGFuZGxlRHJhZ092ZXIoeDogbnVtYmVyLCB5OiBudW1iZXIpOiB2b2lkIHtcbiAgICBpZiAoIW5hdGl2ZURyYWdBY3RpdmUpIHJldHVybjtcbiAgICBcbiAgICAvLyBDaGVjayBpZiBmaWxlIGRyb3BzIGFyZSBlbmFibGVkIGZvciB0aGlzIHdpbmRvd1xuICAgIGlmICgod2luZG93IGFzIGFueSkuX3dhaWxzPy5mbGFncz8uZW5hYmxlRmlsZURyb3AgPT09IGZhbHNlKSB7XG4gICAgICAgIHJldHVybjsgLy8gRmlsZSBkcm9wcyBkaXNhYmxlZCwgZG9uJ3Qgc2hvdyBob3ZlciBlZmZlY3RzXG4gICAgfVxuICAgIFxuICAgIGNvbnN0IHRhcmdldEVsZW1lbnQgPSBkb2N1bWVudC5lbGVtZW50RnJvbVBvaW50KHgsIHkpO1xuICAgIGNvbnN0IGRyb3BUYXJnZXQgPSBnZXREcm9wVGFyZ2V0RWxlbWVudCh0YXJnZXRFbGVtZW50KTtcbiAgICBcbiAgICBpZiAoY3VycmVudERyb3BUYXJnZXQgJiYgY3VycmVudERyb3BUYXJnZXQgIT09IGRyb3BUYXJnZXQpIHtcbiAgICAgICAgY3VycmVudERyb3BUYXJnZXQuY2xhc3NMaXN0LnJlbW92ZShEUk9QX1RBUkdFVF9BQ1RJVkVfQ0xBU1MpO1xuICAgIH1cbiAgICBcbiAgICBpZiAoZHJvcFRhcmdldCkge1xuICAgICAgICBkcm9wVGFyZ2V0LmNsYXNzTGlzdC5hZGQoRFJPUF9UQVJHRVRfQUNUSVZFX0NMQVNTKTtcbiAgICAgICAgY3VycmVudERyb3BUYXJnZXQgPSBkcm9wVGFyZ2V0O1xuICAgIH0gZWxzZSB7XG4gICAgICAgIGN1cnJlbnREcm9wVGFyZ2V0ID0gbnVsbDtcbiAgICB9XG59XG5cblxuXG4vLyBFeHBvcnQgdGhlIGhhbmRsZXJzIGZvciB1c2UgYnkgR28gdmlhIGluZGV4LnRzXG5leHBvcnQgeyBoYW5kbGVEcmFnRW50ZXIsIGhhbmRsZURyYWdMZWF2ZSwgaGFuZGxlRHJhZ092ZXIgfTtcblxuLyoqXG4gKiBBIHJlY29yZCBkZXNjcmliaW5nIHRoZSBwb3NpdGlvbiBvZiBhIHdpbmRvdy5cbiAqL1xuaW50ZXJmYWNlIFBvc2l0aW9uIHtcbiAgICAvKiogVGhlIGhvcml6b250YWwgcG9zaXRpb24gb2YgdGhlIHdpbmRvdy4gKi9cbiAgICB4OiBudW1iZXI7XG4gICAgLyoqIFRoZSB2ZXJ0aWNhbCBwb3NpdGlvbiBvZiB0aGUgd2luZG93LiAqL1xuICAgIHk6IG51bWJlcjtcbn1cblxuLyoqXG4gKiBBIHJlY29yZCBkZXNjcmliaW5nIHRoZSBzaXplIG9mIGEgd2luZG93LlxuICovXG5pbnRlcmZhY2UgU2l6ZSB7XG4gICAgLyoqIFRoZSB3aWR0aCBvZiB0aGUgd2luZG93LiAqL1xuICAgIHdpZHRoOiBudW1iZXI7XG4gICAgLyoqIFRoZSBoZWlnaHQgb2YgdGhlIHdpbmRvdy4gKi9cbiAgICBoZWlnaHQ6IG51bWJlcjtcbn1cblxuLy8gUHJpdmF0ZSBmaWVsZCBuYW1lcy5cbmNvbnN0IGNhbGxlclN5bSA9IFN5bWJvbChcImNhbGxlclwiKTtcblxuY2xhc3MgV2luZG93IHtcbiAgICAvLyBQcml2YXRlIGZpZWxkcy5cbiAgICBwcml2YXRlIFtjYWxsZXJTeW1dOiAobWVzc2FnZTogbnVtYmVyLCBhcmdzPzogYW55KSA9PiBQcm9taXNlPGFueT47XG5cbiAgICAvKipcbiAgICAgKiBJbml0aWFsaXNlcyBhIHdpbmRvdyBvYmplY3Qgd2l0aCB0aGUgc3BlY2lmaWVkIG5hbWUuXG4gICAgICpcbiAgICAgKiBAcHJpdmF0ZVxuICAgICAqIEBwYXJhbSBuYW1lIC0gVGhlIG5hbWUgb2YgdGhlIHRhcmdldCB3aW5kb3cuXG4gICAgICovXG4gICAgY29uc3RydWN0b3IobmFtZTogc3RyaW5nID0gJycpIHtcbiAgICAgICAgdGhpc1tjYWxsZXJTeW1dID0gbmV3UnVudGltZUNhbGxlcihvYmplY3ROYW1lcy5XaW5kb3csIG5hbWUpXG5cbiAgICAgICAgLy8gYmluZCBpbnN0YW5jZSBtZXRob2QgdG8gbWFrZSB0aGVtIGVhc2lseSB1c2FibGUgaW4gZXZlbnQgaGFuZGxlcnNcbiAgICAgICAgZm9yIChjb25zdCBtZXRob2Qgb2YgT2JqZWN0LmdldE93blByb3BlcnR5TmFtZXMoV2luZG93LnByb3RvdHlwZSkpIHtcbiAgICAgICAgICAgIGlmIChcbiAgICAgICAgICAgICAgICBtZXRob2QgIT09IFwiY29uc3RydWN0b3JcIlxuICAgICAgICAgICAgICAgICYmIHR5cGVvZiAodGhpcyBhcyBhbnkpW21ldGhvZF0gPT09IFwiZnVuY3Rpb25cIlxuICAgICAgICAgICAgKSB7XG4gICAgICAgICAgICAgICAgKHRoaXMgYXMgYW55KVttZXRob2RdID0gKHRoaXMgYXMgYW55KVttZXRob2RdLmJpbmQodGhpcyk7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBHZXRzIHRoZSBzcGVjaWZpZWQgd2luZG93LlxuICAgICAqXG4gICAgICogQHBhcmFtIG5hbWUgLSBUaGUgbmFtZSBvZiB0aGUgd2luZG93IHRvIGdldC5cbiAgICAgKiBAcmV0dXJucyBUaGUgY29ycmVzcG9uZGluZyB3aW5kb3cgb2JqZWN0LlxuICAgICAqL1xuICAgIEdldChuYW1lOiBzdHJpbmcpOiBXaW5kb3cge1xuICAgICAgICByZXR1cm4gbmV3IFdpbmRvdyhuYW1lKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIHRoZSBhYnNvbHV0ZSBwb3NpdGlvbiBvZiB0aGUgd2luZG93LlxuICAgICAqXG4gICAgICogQHJldHVybnMgVGhlIGN1cnJlbnQgYWJzb2x1dGUgcG9zaXRpb24gb2YgdGhlIHdpbmRvdy5cbiAgICAgKi9cbiAgICBQb3NpdGlvbigpOiBQcm9taXNlPFBvc2l0aW9uPiB7XG4gICAgICAgIHJldHVybiB0aGlzW2NhbGxlclN5bV0oUG9zaXRpb25NZXRob2QpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENlbnRlcnMgdGhlIHdpbmRvdyBvbiB0aGUgc2NyZWVuLlxuICAgICAqL1xuICAgIENlbnRlcigpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgcmV0dXJuIHRoaXNbY2FsbGVyU3ltXShDZW50ZXJNZXRob2QpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENsb3NlcyB0aGUgd2luZG93LlxuICAgICAqL1xuICAgIENsb3NlKCk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICByZXR1cm4gdGhpc1tjYWxsZXJTeW1dKENsb3NlTWV0aG9kKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBEaXNhYmxlcyBtaW4vbWF4IHNpemUgY29uc3RyYWludHMuXG4gICAgICovXG4gICAgRGlzYWJsZVNpemVDb25zdHJhaW50cygpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgcmV0dXJuIHRoaXNbY2FsbGVyU3ltXShEaXNhYmxlU2l6ZUNvbnN0cmFpbnRzTWV0aG9kKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBFbmFibGVzIG1pbi9tYXggc2l6ZSBjb25zdHJhaW50cy5cbiAgICAgKi9cbiAgICBFbmFibGVTaXplQ29uc3RyYWludHMoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIHJldHVybiB0aGlzW2NhbGxlclN5bV0oRW5hYmxlU2l6ZUNvbnN0cmFpbnRzTWV0aG9kKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBGb2N1c2VzIHRoZSB3aW5kb3cuXG4gICAgICovXG4gICAgRm9jdXMoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIHJldHVybiB0aGlzW2NhbGxlclN5bV0oRm9jdXNNZXRob2QpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEZvcmNlcyB0aGUgd2luZG93IHRvIHJlbG9hZCB0aGUgcGFnZSBhc3NldHMuXG4gICAgICovXG4gICAgRm9yY2VSZWxvYWQoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIHJldHVybiB0aGlzW2NhbGxlclN5bV0oRm9yY2VSZWxvYWRNZXRob2QpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFN3aXRjaGVzIHRoZSB3aW5kb3cgdG8gZnVsbHNjcmVlbiBtb2RlLlxuICAgICAqL1xuICAgIEZ1bGxzY3JlZW4oKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIHJldHVybiB0aGlzW2NhbGxlclN5bV0oRnVsbHNjcmVlbk1ldGhvZCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyB0aGUgc2NyZWVuIHRoYXQgdGhlIHdpbmRvdyBpcyBvbi5cbiAgICAgKlxuICAgICAqIEByZXR1cm5zIFRoZSBzY3JlZW4gdGhlIHdpbmRvdyBpcyBjdXJyZW50bHkgb24uXG4gICAgICovXG4gICAgR2V0U2NyZWVuKCk6IFByb21pc2U8U2NyZWVuPiB7XG4gICAgICAgIHJldHVybiB0aGlzW2NhbGxlclN5bV0oR2V0U2NyZWVuTWV0aG9kKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIHRoZSBjdXJyZW50IHpvb20gbGV2ZWwgb2YgdGhlIHdpbmRvdy5cbiAgICAgKlxuICAgICAqIEByZXR1cm5zIFRoZSBjdXJyZW50IHpvb20gbGV2ZWwuXG4gICAgICovXG4gICAgR2V0Wm9vbSgpOiBQcm9taXNlPG51bWJlcj4ge1xuICAgICAgICByZXR1cm4gdGhpc1tjYWxsZXJTeW1dKEdldFpvb21NZXRob2QpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgdGhlIGhlaWdodCBvZiB0aGUgd2luZG93LlxuICAgICAqXG4gICAgICogQHJldHVybnMgVGhlIGN1cnJlbnQgaGVpZ2h0IG9mIHRoZSB3aW5kb3cuXG4gICAgICovXG4gICAgSGVpZ2h0KCk6IFByb21pc2U8bnVtYmVyPiB7XG4gICAgICAgIHJldHVybiB0aGlzW2NhbGxlclN5bV0oSGVpZ2h0TWV0aG9kKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBIaWRlcyB0aGUgd2luZG93LlxuICAgICAqL1xuICAgIEhpZGUoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIHJldHVybiB0aGlzW2NhbGxlclN5bV0oSGlkZU1ldGhvZCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyB0cnVlIGlmIHRoZSB3aW5kb3cgaXMgZm9jdXNlZC5cbiAgICAgKlxuICAgICAqIEByZXR1cm5zIFdoZXRoZXIgdGhlIHdpbmRvdyBpcyBjdXJyZW50bHkgZm9jdXNlZC5cbiAgICAgKi9cbiAgICBJc0ZvY3VzZWQoKTogUHJvbWlzZTxib29sZWFuPiB7XG4gICAgICAgIHJldHVybiB0aGlzW2NhbGxlclN5bV0oSXNGb2N1c2VkTWV0aG9kKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIHRydWUgaWYgdGhlIHdpbmRvdyBpcyBmdWxsc2NyZWVuLlxuICAgICAqXG4gICAgICogQHJldHVybnMgV2hldGhlciB0aGUgd2luZG93IGlzIGN1cnJlbnRseSBmdWxsc2NyZWVuLlxuICAgICAqL1xuICAgIElzRnVsbHNjcmVlbigpOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICAgICAgcmV0dXJuIHRoaXNbY2FsbGVyU3ltXShJc0Z1bGxzY3JlZW5NZXRob2QpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgdHJ1ZSBpZiB0aGUgd2luZG93IGlzIG1heGltaXNlZC5cbiAgICAgKlxuICAgICAqIEByZXR1cm5zIFdoZXRoZXIgdGhlIHdpbmRvdyBpcyBjdXJyZW50bHkgbWF4aW1pc2VkLlxuICAgICAqL1xuICAgIElzTWF4aW1pc2VkKCk6IFByb21pc2U8Ym9vbGVhbj4ge1xuICAgICAgICByZXR1cm4gdGhpc1tjYWxsZXJTeW1dKElzTWF4aW1pc2VkTWV0aG9kKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIHRydWUgaWYgdGhlIHdpbmRvdyBpcyBtaW5pbWlzZWQuXG4gICAgICpcbiAgICAgKiBAcmV0dXJucyBXaGV0aGVyIHRoZSB3aW5kb3cgaXMgY3VycmVudGx5IG1pbmltaXNlZC5cbiAgICAgKi9cbiAgICBJc01pbmltaXNlZCgpOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICAgICAgcmV0dXJuIHRoaXNbY2FsbGVyU3ltXShJc01pbmltaXNlZE1ldGhvZCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogTWF4aW1pc2VzIHRoZSB3aW5kb3cuXG4gICAgICovXG4gICAgTWF4aW1pc2UoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIHJldHVybiB0aGlzW2NhbGxlclN5bV0oTWF4aW1pc2VNZXRob2QpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIE1pbmltaXNlcyB0aGUgd2luZG93LlxuICAgICAqL1xuICAgIE1pbmltaXNlKCk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICByZXR1cm4gdGhpc1tjYWxsZXJTeW1dKE1pbmltaXNlTWV0aG9kKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIHRoZSBuYW1lIG9mIHRoZSB3aW5kb3cuXG4gICAgICpcbiAgICAgKiBAcmV0dXJucyBUaGUgbmFtZSBvZiB0aGUgd2luZG93LlxuICAgICAqL1xuICAgIE5hbWUoKTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgICAgICAgcmV0dXJuIHRoaXNbY2FsbGVyU3ltXShOYW1lTWV0aG9kKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBPcGVucyB0aGUgZGV2ZWxvcG1lbnQgdG9vbHMgcGFuZS5cbiAgICAgKi9cbiAgICBPcGVuRGV2VG9vbHMoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIHJldHVybiB0aGlzW2NhbGxlclN5bV0oT3BlbkRldlRvb2xzTWV0aG9kKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIHRoZSByZWxhdGl2ZSBwb3NpdGlvbiBvZiB0aGUgd2luZG93IHRvIHRoZSBzY3JlZW4uXG4gICAgICpcbiAgICAgKiBAcmV0dXJucyBUaGUgY3VycmVudCByZWxhdGl2ZSBwb3NpdGlvbiBvZiB0aGUgd2luZG93LlxuICAgICAqL1xuICAgIFJlbGF0aXZlUG9zaXRpb24oKTogUHJvbWlzZTxQb3NpdGlvbj4ge1xuICAgICAgICByZXR1cm4gdGhpc1tjYWxsZXJTeW1dKFJlbGF0aXZlUG9zaXRpb25NZXRob2QpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJlbG9hZHMgdGhlIHBhZ2UgYXNzZXRzLlxuICAgICAqL1xuICAgIFJlbG9hZCgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgcmV0dXJuIHRoaXNbY2FsbGVyU3ltXShSZWxvYWRNZXRob2QpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJldHVybnMgdHJ1ZSBpZiB0aGUgd2luZG93IGlzIHJlc2l6YWJsZS5cbiAgICAgKlxuICAgICAqIEByZXR1cm5zIFdoZXRoZXIgdGhlIHdpbmRvdyBpcyBjdXJyZW50bHkgcmVzaXphYmxlLlxuICAgICAqL1xuICAgIFJlc2l6YWJsZSgpOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICAgICAgcmV0dXJuIHRoaXNbY2FsbGVyU3ltXShSZXNpemFibGVNZXRob2QpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJlc3RvcmVzIHRoZSB3aW5kb3cgdG8gaXRzIHByZXZpb3VzIHN0YXRlIGlmIGl0IHdhcyBwcmV2aW91c2x5IG1pbmltaXNlZCwgbWF4aW1pc2VkIG9yIGZ1bGxzY3JlZW4uXG4gICAgICovXG4gICAgUmVzdG9yZSgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgcmV0dXJuIHRoaXNbY2FsbGVyU3ltXShSZXN0b3JlTWV0aG9kKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTZXRzIHRoZSBhYnNvbHV0ZSBwb3NpdGlvbiBvZiB0aGUgd2luZG93LlxuICAgICAqXG4gICAgICogQHBhcmFtIHggLSBUaGUgZGVzaXJlZCBob3Jpem9udGFsIGFic29sdXRlIHBvc2l0aW9uIG9mIHRoZSB3aW5kb3cuXG4gICAgICogQHBhcmFtIHkgLSBUaGUgZGVzaXJlZCB2ZXJ0aWNhbCBhYnNvbHV0ZSBwb3NpdGlvbiBvZiB0aGUgd2luZG93LlxuICAgICAqL1xuICAgIFNldFBvc2l0aW9uKHg6IG51bWJlciwgeTogbnVtYmVyKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIHJldHVybiB0aGlzW2NhbGxlclN5bV0oU2V0UG9zaXRpb25NZXRob2QsIHsgeCwgeSB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTZXRzIHRoZSB3aW5kb3cgdG8gYmUgYWx3YXlzIG9uIHRvcC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSBhbHdheXNPblRvcCAtIFdoZXRoZXIgdGhlIHdpbmRvdyBzaG91bGQgc3RheSBvbiB0b3AuXG4gICAgICovXG4gICAgU2V0QWx3YXlzT25Ub3AoYWx3YXlzT25Ub3A6IGJvb2xlYW4pOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgcmV0dXJuIHRoaXNbY2FsbGVyU3ltXShTZXRBbHdheXNPblRvcE1ldGhvZCwgeyBhbHdheXNPblRvcCB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTZXRzIHRoZSBiYWNrZ3JvdW5kIGNvbG91ciBvZiB0aGUgd2luZG93LlxuICAgICAqXG4gICAgICogQHBhcmFtIHIgLSBUaGUgZGVzaXJlZCByZWQgY29tcG9uZW50IG9mIHRoZSB3aW5kb3cgYmFja2dyb3VuZC5cbiAgICAgKiBAcGFyYW0gZyAtIFRoZSBkZXNpcmVkIGdyZWVuIGNvbXBvbmVudCBvZiB0aGUgd2luZG93IGJhY2tncm91bmQuXG4gICAgICogQHBhcmFtIGIgLSBUaGUgZGVzaXJlZCBibHVlIGNvbXBvbmVudCBvZiB0aGUgd2luZG93IGJhY2tncm91bmQuXG4gICAgICogQHBhcmFtIGEgLSBUaGUgZGVzaXJlZCBhbHBoYSBjb21wb25lbnQgb2YgdGhlIHdpbmRvdyBiYWNrZ3JvdW5kLlxuICAgICAqL1xuICAgIFNldEJhY2tncm91bmRDb2xvdXIocjogbnVtYmVyLCBnOiBudW1iZXIsIGI6IG51bWJlciwgYTogbnVtYmVyKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIHJldHVybiB0aGlzW2NhbGxlclN5bV0oU2V0QmFja2dyb3VuZENvbG91ck1ldGhvZCwgeyByLCBnLCBiLCBhIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFJlbW92ZXMgdGhlIHdpbmRvdyBmcmFtZSBhbmQgdGl0bGUgYmFyLlxuICAgICAqXG4gICAgICogQHBhcmFtIGZyYW1lbGVzcyAtIFdoZXRoZXIgdGhlIHdpbmRvdyBzaG91bGQgYmUgZnJhbWVsZXNzLlxuICAgICAqL1xuICAgIFNldEZyYW1lbGVzcyhmcmFtZWxlc3M6IGJvb2xlYW4pOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgcmV0dXJuIHRoaXNbY2FsbGVyU3ltXShTZXRGcmFtZWxlc3NNZXRob2QsIHsgZnJhbWVsZXNzIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIERpc2FibGVzIHRoZSBzeXN0ZW0gZnVsbHNjcmVlbiBidXR0b24uXG4gICAgICpcbiAgICAgKiBAcGFyYW0gZW5hYmxlZCAtIFdoZXRoZXIgdGhlIGZ1bGxzY3JlZW4gYnV0dG9uIHNob3VsZCBiZSBlbmFibGVkLlxuICAgICAqL1xuICAgIFNldEZ1bGxzY3JlZW5CdXR0b25FbmFibGVkKGVuYWJsZWQ6IGJvb2xlYW4pOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgcmV0dXJuIHRoaXNbY2FsbGVyU3ltXShTZXRGdWxsc2NyZWVuQnV0dG9uRW5hYmxlZE1ldGhvZCwgeyBlbmFibGVkIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNldHMgdGhlIG1heGltdW0gc2l6ZSBvZiB0aGUgd2luZG93LlxuICAgICAqXG4gICAgICogQHBhcmFtIHdpZHRoIC0gVGhlIGRlc2lyZWQgbWF4aW11bSB3aWR0aCBvZiB0aGUgd2luZG93LlxuICAgICAqIEBwYXJhbSBoZWlnaHQgLSBUaGUgZGVzaXJlZCBtYXhpbXVtIGhlaWdodCBvZiB0aGUgd2luZG93LlxuICAgICAqL1xuICAgIFNldE1heFNpemUod2lkdGg6IG51bWJlciwgaGVpZ2h0OiBudW1iZXIpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgcmV0dXJuIHRoaXNbY2FsbGVyU3ltXShTZXRNYXhTaXplTWV0aG9kLCB7IHdpZHRoLCBoZWlnaHQgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2V0cyB0aGUgbWluaW11bSBzaXplIG9mIHRoZSB3aW5kb3cuXG4gICAgICpcbiAgICAgKiBAcGFyYW0gd2lkdGggLSBUaGUgZGVzaXJlZCBtaW5pbXVtIHdpZHRoIG9mIHRoZSB3aW5kb3cuXG4gICAgICogQHBhcmFtIGhlaWdodCAtIFRoZSBkZXNpcmVkIG1pbmltdW0gaGVpZ2h0IG9mIHRoZSB3aW5kb3cuXG4gICAgICovXG4gICAgU2V0TWluU2l6ZSh3aWR0aDogbnVtYmVyLCBoZWlnaHQ6IG51bWJlcik6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICByZXR1cm4gdGhpc1tjYWxsZXJTeW1dKFNldE1pblNpemVNZXRob2QsIHsgd2lkdGgsIGhlaWdodCB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTZXRzIHRoZSByZWxhdGl2ZSBwb3NpdGlvbiBvZiB0aGUgd2luZG93IHRvIHRoZSBzY3JlZW4uXG4gICAgICpcbiAgICAgKiBAcGFyYW0geCAtIFRoZSBkZXNpcmVkIGhvcml6b250YWwgcmVsYXRpdmUgcG9zaXRpb24gb2YgdGhlIHdpbmRvdy5cbiAgICAgKiBAcGFyYW0geSAtIFRoZSBkZXNpcmVkIHZlcnRpY2FsIHJlbGF0aXZlIHBvc2l0aW9uIG9mIHRoZSB3aW5kb3cuXG4gICAgICovXG4gICAgU2V0UmVsYXRpdmVQb3NpdGlvbih4OiBudW1iZXIsIHk6IG51bWJlcik6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICByZXR1cm4gdGhpc1tjYWxsZXJTeW1dKFNldFJlbGF0aXZlUG9zaXRpb25NZXRob2QsIHsgeCwgeSB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTZXRzIHdoZXRoZXIgdGhlIHdpbmRvdyBpcyByZXNpemFibGUuXG4gICAgICpcbiAgICAgKiBAcGFyYW0gcmVzaXphYmxlIC0gV2hldGhlciB0aGUgd2luZG93IHNob3VsZCBiZSByZXNpemFibGUuXG4gICAgICovXG4gICAgU2V0UmVzaXphYmxlKHJlc2l6YWJsZTogYm9vbGVhbik6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICByZXR1cm4gdGhpc1tjYWxsZXJTeW1dKFNldFJlc2l6YWJsZU1ldGhvZCwgeyByZXNpemFibGUgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2V0cyB0aGUgc2l6ZSBvZiB0aGUgd2luZG93LlxuICAgICAqXG4gICAgICogQHBhcmFtIHdpZHRoIC0gVGhlIGRlc2lyZWQgd2lkdGggb2YgdGhlIHdpbmRvdy5cbiAgICAgKiBAcGFyYW0gaGVpZ2h0IC0gVGhlIGRlc2lyZWQgaGVpZ2h0IG9mIHRoZSB3aW5kb3cuXG4gICAgICovXG4gICAgU2V0U2l6ZSh3aWR0aDogbnVtYmVyLCBoZWlnaHQ6IG51bWJlcik6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICByZXR1cm4gdGhpc1tjYWxsZXJTeW1dKFNldFNpemVNZXRob2QsIHsgd2lkdGgsIGhlaWdodCB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBTZXRzIHRoZSB0aXRsZSBvZiB0aGUgd2luZG93LlxuICAgICAqXG4gICAgICogQHBhcmFtIHRpdGxlIC0gVGhlIGRlc2lyZWQgdGl0bGUgb2YgdGhlIHdpbmRvdy5cbiAgICAgKi9cbiAgICBTZXRUaXRsZSh0aXRsZTogc3RyaW5nKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIHJldHVybiB0aGlzW2NhbGxlclN5bV0oU2V0VGl0bGVNZXRob2QsIHsgdGl0bGUgfSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogU2V0cyB0aGUgem9vbSBsZXZlbCBvZiB0aGUgd2luZG93LlxuICAgICAqXG4gICAgICogQHBhcmFtIHpvb20gLSBUaGUgZGVzaXJlZCB6b29tIGxldmVsLlxuICAgICAqL1xuICAgIFNldFpvb20oem9vbTogbnVtYmVyKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIHJldHVybiB0aGlzW2NhbGxlclN5bV0oU2V0Wm9vbU1ldGhvZCwgeyB6b29tIH0pO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFNob3dzIHRoZSB3aW5kb3cuXG4gICAgICovXG4gICAgU2hvdygpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgcmV0dXJuIHRoaXNbY2FsbGVyU3ltXShTaG93TWV0aG9kKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBSZXR1cm5zIHRoZSBzaXplIG9mIHRoZSB3aW5kb3cuXG4gICAgICpcbiAgICAgKiBAcmV0dXJucyBUaGUgY3VycmVudCBzaXplIG9mIHRoZSB3aW5kb3cuXG4gICAgICovXG4gICAgU2l6ZSgpOiBQcm9taXNlPFNpemU+IHtcbiAgICAgICAgcmV0dXJuIHRoaXNbY2FsbGVyU3ltXShTaXplTWV0aG9kKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUb2dnbGVzIHRoZSB3aW5kb3cgYmV0d2VlbiBmdWxsc2NyZWVuIGFuZCBub3JtYWwuXG4gICAgICovXG4gICAgVG9nZ2xlRnVsbHNjcmVlbigpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgcmV0dXJuIHRoaXNbY2FsbGVyU3ltXShUb2dnbGVGdWxsc2NyZWVuTWV0aG9kKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBUb2dnbGVzIHRoZSB3aW5kb3cgYmV0d2VlbiBtYXhpbWlzZWQgYW5kIG5vcm1hbC5cbiAgICAgKi9cbiAgICBUb2dnbGVNYXhpbWlzZSgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgcmV0dXJuIHRoaXNbY2FsbGVyU3ltXShUb2dnbGVNYXhpbWlzZU1ldGhvZCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVG9nZ2xlcyB0aGUgd2luZG93IGJldHdlZW4gZnJhbWVsZXNzIGFuZCBub3JtYWwuXG4gICAgICovXG4gICAgVG9nZ2xlRnJhbWVsZXNzKCk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICByZXR1cm4gdGhpc1tjYWxsZXJTeW1dKFRvZ2dsZUZyYW1lbGVzc01ldGhvZCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVW4tZnVsbHNjcmVlbnMgdGhlIHdpbmRvdy5cbiAgICAgKi9cbiAgICBVbkZ1bGxzY3JlZW4oKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIHJldHVybiB0aGlzW2NhbGxlclN5bV0oVW5GdWxsc2NyZWVuTWV0aG9kKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBVbi1tYXhpbWlzZXMgdGhlIHdpbmRvdy5cbiAgICAgKi9cbiAgICBVbk1heGltaXNlKCk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICByZXR1cm4gdGhpc1tjYWxsZXJTeW1dKFVuTWF4aW1pc2VNZXRob2QpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIFVuLW1pbmltaXNlcyB0aGUgd2luZG93LlxuICAgICAqL1xuICAgIFVuTWluaW1pc2UoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIHJldHVybiB0aGlzW2NhbGxlclN5bV0oVW5NaW5pbWlzZU1ldGhvZCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmV0dXJucyB0aGUgd2lkdGggb2YgdGhlIHdpbmRvdy5cbiAgICAgKlxuICAgICAqIEByZXR1cm5zIFRoZSBjdXJyZW50IHdpZHRoIG9mIHRoZSB3aW5kb3cuXG4gICAgICovXG4gICAgV2lkdGgoKTogUHJvbWlzZTxudW1iZXI+IHtcbiAgICAgICAgcmV0dXJuIHRoaXNbY2FsbGVyU3ltXShXaWR0aE1ldGhvZCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogWm9vbXMgdGhlIHdpbmRvdy5cbiAgICAgKi9cbiAgICBab29tKCk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICByZXR1cm4gdGhpc1tjYWxsZXJTeW1dKFpvb21NZXRob2QpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEluY3JlYXNlcyB0aGUgem9vbSBsZXZlbCBvZiB0aGUgd2VidmlldyBjb250ZW50LlxuICAgICAqL1xuICAgIFpvb21JbigpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgcmV0dXJuIHRoaXNbY2FsbGVyU3ltXShab29tSW5NZXRob2QpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIERlY3JlYXNlcyB0aGUgem9vbSBsZXZlbCBvZiB0aGUgd2VidmlldyBjb250ZW50LlxuICAgICAqL1xuICAgIFpvb21PdXQoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIHJldHVybiB0aGlzW2NhbGxlclN5bV0oWm9vbU91dE1ldGhvZCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogUmVzZXRzIHRoZSB6b29tIGxldmVsIG9mIHRoZSB3ZWJ2aWV3IGNvbnRlbnQuXG4gICAgICovXG4gICAgWm9vbVJlc2V0KCk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICByZXR1cm4gdGhpc1tjYWxsZXJTeW1dKFpvb21SZXNldE1ldGhvZCk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogSGFuZGxlcyBmaWxlIGRyb3BzIG9yaWdpbmF0aW5nIGZyb20gcGxhdGZvcm0tc3BlY2lmaWMgY29kZSAoZS5nLiwgbWFjT1MvTGludXggbmF0aXZlIGRyYWctYW5kLWRyb3ApLlxuICAgICAqIEdhdGhlcnMgaW5mb3JtYXRpb24gYWJvdXQgdGhlIGRyb3AgdGFyZ2V0IGVsZW1lbnQgYW5kIHNlbmRzIGl0IGJhY2sgdG8gdGhlIEdvIGJhY2tlbmQuXG4gICAgICpcbiAgICAgKiBAcGFyYW0gZmlsZW5hbWVzIC0gQW4gYXJyYXkgb2YgZmlsZSBwYXRocyAoc3RyaW5ncykgdGhhdCB3ZXJlIGRyb3BwZWQuXG4gICAgICogQHBhcmFtIHggLSBUaGUgeC1jb29yZGluYXRlIG9mIHRoZSBkcm9wIGV2ZW50IChDU1MgcGl4ZWxzKS5cbiAgICAgKiBAcGFyYW0geSAtIFRoZSB5LWNvb3JkaW5hdGUgb2YgdGhlIGRyb3AgZXZlbnQgKENTUyBwaXhlbHMpLlxuICAgICAqL1xuICAgIEhhbmRsZVBsYXRmb3JtRmlsZURyb3AoZmlsZW5hbWVzOiBzdHJpbmdbXSwgeDogbnVtYmVyLCB5OiBudW1iZXIpOiB2b2lkIHtcbiAgICAgICAgLy8gQ2hlY2sgaWYgZmlsZSBkcm9wcyBhcmUgZW5hYmxlZCBmb3IgdGhpcyB3aW5kb3dcbiAgICAgICAgaWYgKCh3aW5kb3cgYXMgYW55KS5fd2FpbHM/LmZsYWdzPy5lbmFibGVGaWxlRHJvcCA9PT0gZmFsc2UpIHtcbiAgICAgICAgICAgIHJldHVybjsgLy8gRmlsZSBkcm9wcyBkaXNhYmxlZCwgaWdub3JlIHRoZSBkcm9wXG4gICAgICAgIH1cbiAgICAgICAgXG4gICAgICAgIGNvbnN0IGVsZW1lbnQgPSBkb2N1bWVudC5lbGVtZW50RnJvbVBvaW50KHgsIHkpO1xuICAgICAgICBjb25zdCBkcm9wVGFyZ2V0ID0gZ2V0RHJvcFRhcmdldEVsZW1lbnQoZWxlbWVudCk7XG5cbiAgICAgICAgaWYgKCFkcm9wVGFyZ2V0KSB7XG4gICAgICAgICAgICAvLyBEcm9wIHdhcyBub3Qgb24gYSBkZXNpZ25hdGVkIGRyb3AgdGFyZ2V0IC0gaWdub3JlXG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBlbGVtZW50RGV0YWlscyA9IHtcbiAgICAgICAgICAgIGlkOiBkcm9wVGFyZ2V0LmlkLFxuICAgICAgICAgICAgY2xhc3NMaXN0OiBBcnJheS5mcm9tKGRyb3BUYXJnZXQuY2xhc3NMaXN0KSxcbiAgICAgICAgICAgIGF0dHJpYnV0ZXM6IHt9IGFzIHsgW2tleTogc3RyaW5nXTogc3RyaW5nIH0sXG4gICAgICAgIH07XG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgZHJvcFRhcmdldC5hdHRyaWJ1dGVzLmxlbmd0aDsgaSsrKSB7XG4gICAgICAgICAgICBjb25zdCBhdHRyID0gZHJvcFRhcmdldC5hdHRyaWJ1dGVzW2ldO1xuICAgICAgICAgICAgZWxlbWVudERldGFpbHMuYXR0cmlidXRlc1thdHRyLm5hbWVdID0gYXR0ci52YWx1ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IHBheWxvYWQgPSB7XG4gICAgICAgICAgICBmaWxlbmFtZXMsXG4gICAgICAgICAgICB4LFxuICAgICAgICAgICAgeSxcbiAgICAgICAgICAgIGVsZW1lbnREZXRhaWxzLFxuICAgICAgICB9O1xuXG4gICAgICAgIHRoaXNbY2FsbGVyU3ltXShGaWxlc0Ryb3BwZWQsIHBheWxvYWQpO1xuICAgICAgICBcbiAgICAgICAgLy8gQ2xlYW4gdXAgbmF0aXZlIGRyYWcgc3RhdGUgYWZ0ZXIgZHJvcFxuICAgICAgICBjbGVhbnVwTmF0aXZlRHJhZygpO1xuICAgIH1cbiAgXG4gICAgLyogVHJpZ2dlcnMgV2luZG93cyAxMSBTbmFwIEFzc2lzdCBmZWF0dXJlIChXaW5kb3dzIG9ubHkpLlxuICAgICAqIFRoaXMgaXMgZXF1aXZhbGVudCB0byBwcmVzc2luZyBXaW4rWiBhbmQgc2hvd3Mgc25hcCBsYXlvdXQgb3B0aW9ucy5cbiAgICAgKi9cbiAgICBTbmFwQXNzaXN0KCk6IFByb21pc2U8dm9pZD4ge1xuICAgICAgICByZXR1cm4gdGhpc1tjYWxsZXJTeW1dKFNuYXBBc3Npc3RNZXRob2QpO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIE9wZW5zIHRoZSBwcmludCBkaWFsb2cgZm9yIHRoZSB3aW5kb3cuXG4gICAgICovXG4gICAgUHJpbnQoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgICAgIHJldHVybiB0aGlzW2NhbGxlclN5bV0oUHJpbnRNZXRob2QpO1xuICAgIH1cbn1cblxuLyoqXG4gKiBUaGUgd2luZG93IHdpdGhpbiB3aGljaCB0aGUgc2NyaXB0IGlzIHJ1bm5pbmcuXG4gKi9cbmNvbnN0IHRoaXNXaW5kb3cgPSBuZXcgV2luZG93KCcnKTtcblxuLyoqXG4gKiBTZXRzIHVwIGdsb2JhbCBkcmFnIGFuZCBkcm9wIGV2ZW50IGxpc3RlbmVycyBmb3IgZmlsZSBkcm9wcy5cbiAqIEhhbmRsZXMgdmlzdWFsIGZlZWRiYWNrIChob3ZlciBzdGF0ZSkgYW5kIGZpbGUgZHJvcCBwcm9jZXNzaW5nLlxuICovXG5mdW5jdGlvbiBzZXR1cERyb3BUYXJnZXRMaXN0ZW5lcnMoKSB7XG4gICAgY29uc3QgZG9jRWxlbWVudCA9IGRvY3VtZW50LmRvY3VtZW50RWxlbWVudDtcbiAgICBsZXQgZHJhZ0VudGVyQ291bnRlciA9IDA7XG5cbiAgICBkb2NFbGVtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ2RyYWdlbnRlcicsIChldmVudCkgPT4ge1xuICAgICAgICBpZiAoIWV2ZW50LmRhdGFUcmFuc2Zlcj8udHlwZXMuaW5jbHVkZXMoJ0ZpbGVzJykpIHtcbiAgICAgICAgICAgIHJldHVybjsgLy8gT25seSBoYW5kbGUgZmlsZSBkcmFncywgbGV0IG90aGVyIGRyYWdzIHBhc3MgdGhyb3VnaFxuICAgICAgICB9XG4gICAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7IC8vIEFsd2F5cyBwcmV2ZW50IGRlZmF1bHQgdG8gc3RvcCBicm93c2VyIG5hdmlnYXRpb25cbiAgICAgICAgLy8gT24gV2luZG93cywgY2hlY2sgaWYgZmlsZSBkcm9wcyBhcmUgZW5hYmxlZCBmb3IgdGhpcyB3aW5kb3dcbiAgICAgICAgaWYgKCh3aW5kb3cgYXMgYW55KS5fd2FpbHM/LmZsYWdzPy5lbmFibGVGaWxlRHJvcCA9PT0gZmFsc2UpIHtcbiAgICAgICAgICAgIGV2ZW50LmRhdGFUcmFuc2Zlci5kcm9wRWZmZWN0ID0gJ25vbmUnOyAvLyBTaG93IFwibm8gZHJvcFwiIGN1cnNvclxuICAgICAgICAgICAgcmV0dXJuOyAvLyBGaWxlIGRyb3BzIGRpc2FibGVkLCBkb24ndCBzaG93IGhvdmVyIGVmZmVjdHNcbiAgICAgICAgfVxuICAgICAgICBkcmFnRW50ZXJDb3VudGVyKys7XG4gICAgICAgIFxuICAgICAgICBjb25zdCB0YXJnZXRFbGVtZW50ID0gZG9jdW1lbnQuZWxlbWVudEZyb21Qb2ludChldmVudC5jbGllbnRYLCBldmVudC5jbGllbnRZKTtcbiAgICAgICAgY29uc3QgZHJvcFRhcmdldCA9IGdldERyb3BUYXJnZXRFbGVtZW50KHRhcmdldEVsZW1lbnQpO1xuXG4gICAgICAgIC8vIFVwZGF0ZSBob3ZlciBzdGF0ZVxuICAgICAgICBpZiAoY3VycmVudERyb3BUYXJnZXQgJiYgY3VycmVudERyb3BUYXJnZXQgIT09IGRyb3BUYXJnZXQpIHtcbiAgICAgICAgICAgIGN1cnJlbnREcm9wVGFyZ2V0LmNsYXNzTGlzdC5yZW1vdmUoRFJPUF9UQVJHRVRfQUNUSVZFX0NMQVNTKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChkcm9wVGFyZ2V0KSB7XG4gICAgICAgICAgICBkcm9wVGFyZ2V0LmNsYXNzTGlzdC5hZGQoRFJPUF9UQVJHRVRfQUNUSVZFX0NMQVNTKTtcbiAgICAgICAgICAgIGV2ZW50LmRhdGFUcmFuc2Zlci5kcm9wRWZmZWN0ID0gJ2NvcHknO1xuICAgICAgICAgICAgY3VycmVudERyb3BUYXJnZXQgPSBkcm9wVGFyZ2V0O1xuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgZXZlbnQuZGF0YVRyYW5zZmVyLmRyb3BFZmZlY3QgPSAnbm9uZSc7XG4gICAgICAgICAgICBjdXJyZW50RHJvcFRhcmdldCA9IG51bGw7XG4gICAgICAgIH1cbiAgICB9LCBmYWxzZSk7XG5cbiAgICBkb2NFbGVtZW50LmFkZEV2ZW50TGlzdGVuZXIoJ2RyYWdvdmVyJywgKGV2ZW50KSA9PiB7XG4gICAgICAgIGlmICghZXZlbnQuZGF0YVRyYW5zZmVyPy50eXBlcy5pbmNsdWRlcygnRmlsZXMnKSkge1xuICAgICAgICAgICAgcmV0dXJuOyAvLyBPbmx5IGhhbmRsZSBmaWxlIGRyYWdzXG4gICAgICAgIH1cbiAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTsgLy8gQWx3YXlzIHByZXZlbnQgZGVmYXVsdCB0byBzdG9wIGJyb3dzZXIgbmF2aWdhdGlvblxuICAgICAgICAvLyBPbiBXaW5kb3dzLCBjaGVjayBpZiBmaWxlIGRyb3BzIGFyZSBlbmFibGVkIGZvciB0aGlzIHdpbmRvd1xuICAgICAgICBpZiAoKHdpbmRvdyBhcyBhbnkpLl93YWlscz8uZmxhZ3M/LmVuYWJsZUZpbGVEcm9wID09PSBmYWxzZSkge1xuICAgICAgICAgICAgZXZlbnQuZGF0YVRyYW5zZmVyLmRyb3BFZmZlY3QgPSAnbm9uZSc7IC8vIFNob3cgXCJubyBkcm9wXCIgY3Vyc29yXG4gICAgICAgICAgICByZXR1cm47IC8vIEZpbGUgZHJvcHMgZGlzYWJsZWQsIGRvbid0IHNob3cgaG92ZXIgZWZmZWN0c1xuICAgICAgICB9XG4gICAgICAgIFxuICAgICAgICAvLyBVcGRhdGUgZHJvcCB0YXJnZXQgYXMgY3Vyc29yIG1vdmVzXG4gICAgICAgIGNvbnN0IHRhcmdldEVsZW1lbnQgPSBkb2N1bWVudC5lbGVtZW50RnJvbVBvaW50KGV2ZW50LmNsaWVudFgsIGV2ZW50LmNsaWVudFkpO1xuICAgICAgICBjb25zdCBkcm9wVGFyZ2V0ID0gZ2V0RHJvcFRhcmdldEVsZW1lbnQodGFyZ2V0RWxlbWVudCk7XG4gICAgICAgIFxuICAgICAgICBpZiAoY3VycmVudERyb3BUYXJnZXQgJiYgY3VycmVudERyb3BUYXJnZXQgIT09IGRyb3BUYXJnZXQpIHtcbiAgICAgICAgICAgIGN1cnJlbnREcm9wVGFyZ2V0LmNsYXNzTGlzdC5yZW1vdmUoRFJPUF9UQVJHRVRfQUNUSVZFX0NMQVNTKTtcbiAgICAgICAgfVxuICAgICAgICBcbiAgICAgICAgaWYgKGRyb3BUYXJnZXQpIHtcbiAgICAgICAgICAgIGlmICghZHJvcFRhcmdldC5jbGFzc0xpc3QuY29udGFpbnMoRFJPUF9UQVJHRVRfQUNUSVZFX0NMQVNTKSkge1xuICAgICAgICAgICAgICAgIGRyb3BUYXJnZXQuY2xhc3NMaXN0LmFkZChEUk9QX1RBUkdFVF9BQ1RJVkVfQ0xBU1MpO1xuICAgICAgICAgICAgfVxuICAgICAgICAgICAgZXZlbnQuZGF0YVRyYW5zZmVyLmRyb3BFZmZlY3QgPSAnY29weSc7XG4gICAgICAgICAgICBjdXJyZW50RHJvcFRhcmdldCA9IGRyb3BUYXJnZXQ7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBldmVudC5kYXRhVHJhbnNmZXIuZHJvcEVmZmVjdCA9ICdub25lJztcbiAgICAgICAgICAgIGN1cnJlbnREcm9wVGFyZ2V0ID0gbnVsbDtcbiAgICAgICAgfVxuICAgIH0sIGZhbHNlKTtcblxuICAgIGRvY0VsZW1lbnQuYWRkRXZlbnRMaXN0ZW5lcignZHJhZ2xlYXZlJywgKGV2ZW50KSA9PiB7XG4gICAgICAgIGlmICghZXZlbnQuZGF0YVRyYW5zZmVyPy50eXBlcy5pbmNsdWRlcygnRmlsZXMnKSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7IC8vIEFsd2F5cyBwcmV2ZW50IGRlZmF1bHQgdG8gc3RvcCBicm93c2VyIG5hdmlnYXRpb25cbiAgICAgICAgLy8gT24gV2luZG93cywgY2hlY2sgaWYgZmlsZSBkcm9wcyBhcmUgZW5hYmxlZCBmb3IgdGhpcyB3aW5kb3dcbiAgICAgICAgaWYgKCh3aW5kb3cgYXMgYW55KS5fd2FpbHM/LmZsYWdzPy5lbmFibGVGaWxlRHJvcCA9PT0gZmFsc2UpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBcbiAgICAgICAgLy8gT24gTGludXgvV2ViS2l0R1RLIGFuZCBtYWNPUywgZHJhZ2xlYXZlIGZpcmVzIGltbWVkaWF0ZWx5IHdpdGggcmVsYXRlZFRhcmdldD1udWxsIHdoZW4gbmF0aXZlXG4gICAgICAgIC8vIGRyYWcgaGFuZGxpbmcgaXMgaW52b2x2ZWQuIElnbm9yZSB0aGVzZSBzcHVyaW91cyBldmVudHMgLSB3ZSdsbCBjbGVhbiB1cCBvbiBkcm9wIGluc3RlYWQuXG4gICAgICAgIGlmIChldmVudC5yZWxhdGVkVGFyZ2V0ID09PSBudWxsKSB7XG4gICAgICAgICAgICByZXR1cm47XG4gICAgICAgIH1cbiAgICAgICAgXG4gICAgICAgIGRyYWdFbnRlckNvdW50ZXItLTtcbiAgICAgICAgXG4gICAgICAgIGlmIChkcmFnRW50ZXJDb3VudGVyID09PSAwIHx8IFxuICAgICAgICAgICAgKGN1cnJlbnREcm9wVGFyZ2V0ICYmICFjdXJyZW50RHJvcFRhcmdldC5jb250YWlucyhldmVudC5yZWxhdGVkVGFyZ2V0IGFzIE5vZGUpKSkge1xuICAgICAgICAgICAgaWYgKGN1cnJlbnREcm9wVGFyZ2V0KSB7XG4gICAgICAgICAgICAgICAgY3VycmVudERyb3BUYXJnZXQuY2xhc3NMaXN0LnJlbW92ZShEUk9QX1RBUkdFVF9BQ1RJVkVfQ0xBU1MpO1xuICAgICAgICAgICAgICAgIGN1cnJlbnREcm9wVGFyZ2V0ID0gbnVsbDtcbiAgICAgICAgICAgIH1cbiAgICAgICAgICAgIGRyYWdFbnRlckNvdW50ZXIgPSAwO1xuICAgICAgICB9XG4gICAgfSwgZmFsc2UpO1xuXG4gICAgZG9jRWxlbWVudC5hZGRFdmVudExpc3RlbmVyKCdkcm9wJywgKGV2ZW50KSA9PiB7XG4gICAgICAgIGlmICghZXZlbnQuZGF0YVRyYW5zZmVyPy50eXBlcy5pbmNsdWRlcygnRmlsZXMnKSkge1xuICAgICAgICAgICAgcmV0dXJuOyAvLyBPbmx5IGhhbmRsZSBmaWxlIGRyb3BzXG4gICAgICAgIH1cbiAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTsgLy8gQWx3YXlzIHByZXZlbnQgZGVmYXVsdCB0byBzdG9wIGJyb3dzZXIgbmF2aWdhdGlvblxuICAgICAgICAvLyBPbiBXaW5kb3dzLCBjaGVjayBpZiBmaWxlIGRyb3BzIGFyZSBlbmFibGVkIGZvciB0aGlzIHdpbmRvd1xuICAgICAgICBpZiAoKHdpbmRvdyBhcyBhbnkpLl93YWlscz8uZmxhZ3M/LmVuYWJsZUZpbGVEcm9wID09PSBmYWxzZSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgICAgIGRyYWdFbnRlckNvdW50ZXIgPSAwO1xuICAgICAgICBcbiAgICAgICAgaWYgKGN1cnJlbnREcm9wVGFyZ2V0KSB7XG4gICAgICAgICAgICBjdXJyZW50RHJvcFRhcmdldC5jbGFzc0xpc3QucmVtb3ZlKERST1BfVEFSR0VUX0FDVElWRV9DTEFTUyk7XG4gICAgICAgICAgICBjdXJyZW50RHJvcFRhcmdldCA9IG51bGw7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBPbiBXaW5kb3dzLCBoYW5kbGUgZmlsZSBkcm9wcyB2aWEgSmF2YVNjcmlwdFxuICAgICAgICAvLyBPbiBtYWNPUy9MaW51eCwgbmF0aXZlIGNvZGUgd2lsbCBjYWxsIEhhbmRsZVBsYXRmb3JtRmlsZURyb3BcbiAgICAgICAgaWYgKGNhblJlc29sdmVGaWxlUGF0aHMoKSkge1xuICAgICAgICAgICAgY29uc3QgZmlsZXM6IEZpbGVbXSA9IFtdO1xuICAgICAgICAgICAgaWYgKGV2ZW50LmRhdGFUcmFuc2Zlci5pdGVtcykge1xuICAgICAgICAgICAgICAgIGZvciAoY29uc3QgaXRlbSBvZiBldmVudC5kYXRhVHJhbnNmZXIuaXRlbXMpIHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKGl0ZW0ua2luZCA9PT0gJ2ZpbGUnKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBmaWxlID0gaXRlbS5nZXRBc0ZpbGUoKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIGlmIChmaWxlKSBmaWxlcy5wdXNoKGZpbGUpO1xuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSBlbHNlIGlmIChldmVudC5kYXRhVHJhbnNmZXIuZmlsZXMpIHtcbiAgICAgICAgICAgICAgICBmb3IgKGNvbnN0IGZpbGUgb2YgZXZlbnQuZGF0YVRyYW5zZmVyLmZpbGVzKSB7XG4gICAgICAgICAgICAgICAgICAgIGZpbGVzLnB1c2goZmlsZSk7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgXG4gICAgICAgICAgICBpZiAoZmlsZXMubGVuZ3RoID4gMCkge1xuICAgICAgICAgICAgICAgIHJlc29sdmVGaWxlUGF0aHMoZXZlbnQuY2xpZW50WCwgZXZlbnQuY2xpZW50WSwgZmlsZXMpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfSwgZmFsc2UpO1xufVxuXG4vLyBJbml0aWFsaXplIGxpc3RlbmVycyB3aGVuIHRoZSBzY3JpcHQgbG9hZHNcbmlmICh0eXBlb2Ygd2luZG93ICE9PSBcInVuZGVmaW5lZFwiICYmIHR5cGVvZiBkb2N1bWVudCAhPT0gXCJ1bmRlZmluZWRcIikge1xuICAgIHNldHVwRHJvcFRhcmdldExpc3RlbmVycygpO1xufVxuXG5leHBvcnQgZGVmYXVsdCB0aGlzV2luZG93O1xuIiwgIi8qXG4gX1x0ICAgX19cdCAgXyBfX1xufCB8XHQgLyAvX19fIF8oXykgL19fX19cbnwgfCAvfCAvIC8gX18gYC8gLyAvIF9fXy9cbnwgfC8gfC8gLyAvXy8gLyAvIChfXyAgKVxufF9fL3xfXy9cXF9fLF8vXy9fL19fX18vXG5UaGUgZWxlY3Ryb24gYWx0ZXJuYXRpdmUgZm9yIEdvXG4oYykgTGVhIEFudGhvbnkgMjAxOS1wcmVzZW50XG4qL1xuXG5pbXBvcnQgKiBhcyBSdW50aW1lIGZyb20gXCIuLi9Ad2FpbHNpby9ydW50aW1lL3NyY1wiO1xuXG4vLyBOT1RFOiB0aGUgZm9sbG93aW5nIG1ldGhvZHMgTVVTVCBiZSBpbXBvcnRlZCBleHBsaWNpdGx5IGJlY2F1c2Ugb2YgaG93IGVzYnVpbGQgaW5qZWN0aW9uIHdvcmtzXG5pbXBvcnQgeyBFbmFibGUgYXMgRW5hYmxlV01MIH0gZnJvbSBcIi4uL0B3YWlsc2lvL3J1bnRpbWUvc3JjL3dtbFwiO1xuaW1wb3J0IHsgZGVidWdMb2cgfSBmcm9tIFwiLi4vQHdhaWxzaW8vcnVudGltZS9zcmMvdXRpbHNcIjtcblxud2luZG93LndhaWxzID0gUnVudGltZTtcbkVuYWJsZVdNTCgpO1xuXG5pZiAoREVCVUcpIHtcbiAgICBkZWJ1Z0xvZyhcIldhaWxzIFJ1bnRpbWUgTG9hZGVkXCIpXG59XG4iLCAiLypcbiBfXHQgICBfX1x0ICBfIF9fXG58IHxcdCAvIC9fX18gXyhfKSAvX19fX1xufCB8IC98IC8gLyBfXyBgLyAvIC8gX19fL1xufCB8LyB8LyAvIC9fLyAvIC8gKF9fICApXG58X18vfF9fL1xcX18sXy9fL18vX19fXy9cblRoZSBlbGVjdHJvbiBhbHRlcm5hdGl2ZSBmb3IgR29cbihjKSBMZWEgQW50aG9ueSAyMDE5LXByZXNlbnRcbiovXG5cbmltcG9ydCB7IG5ld1J1bnRpbWVDYWxsZXIsIG9iamVjdE5hbWVzIH0gZnJvbSBcIi4vcnVudGltZS5qc1wiO1xuXG5jb25zdCBjYWxsID0gbmV3UnVudGltZUNhbGxlcihvYmplY3ROYW1lcy5TeXN0ZW0pO1xuXG5jb25zdCBTeXN0ZW1Jc0RhcmtNb2RlID0gMDtcbmNvbnN0IFN5c3RlbUVudmlyb25tZW50ID0gMTtcbmNvbnN0IFN5c3RlbUNhcGFiaWxpdGllcyA9IDI7XG5cbmNvbnN0IF9pbnZva2UgPSAoZnVuY3Rpb24gKCkge1xuICAgIHRyeSB7XG4gICAgICAgIC8vIFdpbmRvd3MgV2ViVmlldzJcbiAgICAgICAgaWYgKCh3aW5kb3cgYXMgYW55KS5jaHJvbWU/LndlYnZpZXc/LnBvc3RNZXNzYWdlKSB7XG4gICAgICAgICAgICByZXR1cm4gKHdpbmRvdyBhcyBhbnkpLmNocm9tZS53ZWJ2aWV3LnBvc3RNZXNzYWdlLmJpbmQoKHdpbmRvdyBhcyBhbnkpLmNocm9tZS53ZWJ2aWV3KTtcbiAgICAgICAgfVxuICAgICAgICAvLyBtYWNPUy9pT1MgV0tXZWJWaWV3XG4gICAgICAgIGVsc2UgaWYgKCh3aW5kb3cgYXMgYW55KS53ZWJraXQ/Lm1lc3NhZ2VIYW5kbGVycz8uWydleHRlcm5hbCddPy5wb3N0TWVzc2FnZSkge1xuICAgICAgICAgICAgcmV0dXJuICh3aW5kb3cgYXMgYW55KS53ZWJraXQubWVzc2FnZUhhbmRsZXJzWydleHRlcm5hbCddLnBvc3RNZXNzYWdlLmJpbmQoKHdpbmRvdyBhcyBhbnkpLndlYmtpdC5tZXNzYWdlSGFuZGxlcnNbJ2V4dGVybmFsJ10pO1xuICAgICAgICB9XG4gICAgICAgIC8vIEFuZHJvaWQgV2ViVmlldyAtIHVzZXMgYWRkSmF2YXNjcmlwdEludGVyZmFjZSB3aGljaCBleHBvc2VzIHdpbmRvdy53YWlscy5pbnZva2VcbiAgICAgICAgZWxzZSBpZiAoKHdpbmRvdyBhcyBhbnkpLndhaWxzPy5pbnZva2UpIHtcbiAgICAgICAgICAgIHJldHVybiAobXNnOiBhbnkpID0+ICh3aW5kb3cgYXMgYW55KS53YWlscy5pbnZva2UodHlwZW9mIG1zZyA9PT0gJ3N0cmluZycgPyBtc2cgOiBKU09OLnN0cmluZ2lmeShtc2cpKTtcbiAgICAgICAgfVxuICAgIH0gY2F0Y2goZSkge31cblxuICAgIGNvbnNvbGUud2FybignXFxuJWNcdTI2QTBcdUZFMEYgQnJvd3NlciBFbnZpcm9ubWVudCBEZXRlY3RlZCAlY1xcblxcbiVjT25seSBVSSBwcmV2aWV3cyBhcmUgYXZhaWxhYmxlIGluIHRoZSBicm93c2VyLiBGb3IgZnVsbCBmdW5jdGlvbmFsaXR5LCBwbGVhc2UgcnVuIHRoZSBhcHBsaWNhdGlvbiBpbiBkZXNrdG9wIG1vZGUuXFxuTW9yZSBpbmZvcm1hdGlvbiBhdDogaHR0cHM6Ly92My53YWlscy5pby9sZWFybi9idWlsZC8jdXNpbmctYS1icm93c2VyLWZvci1kZXZlbG9wbWVudFxcbicsXG4gICAgICAgICdiYWNrZ3JvdW5kOiAjZmZmZmZmOyBjb2xvcjogIzAwMDAwMDsgZm9udC13ZWlnaHQ6IGJvbGQ7IHBhZGRpbmc6IDRweCA4cHg7IGJvcmRlci1yYWRpdXM6IDRweDsgYm9yZGVyOiAycHggc29saWQgIzAwMDAwMDsnLFxuICAgICAgICAnYmFja2dyb3VuZDogdHJhbnNwYXJlbnQ7JyxcbiAgICAgICAgJ2NvbG9yOiAjZmZmZmZmOyBmb250LXN0eWxlOiBpdGFsaWM7IGZvbnQtd2VpZ2h0OiBib2xkOycpO1xuICAgIHJldHVybiBudWxsO1xufSkoKTtcblxuZXhwb3J0IGZ1bmN0aW9uIGludm9rZShtc2c6IGFueSk6IHZvaWQge1xuICAgIF9pbnZva2U/Lihtc2cpO1xufVxuXG4vKipcbiAqIFJldHJpZXZlcyB0aGUgc3lzdGVtIGRhcmsgbW9kZSBzdGF0dXMuXG4gKlxuICogQHJldHVybnMgQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgdG8gYSBib29sZWFuIHZhbHVlIGluZGljYXRpbmcgaWYgdGhlIHN5c3RlbSBpcyBpbiBkYXJrIG1vZGUuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBJc0RhcmtNb2RlKCk6IFByb21pc2U8Ym9vbGVhbj4ge1xuICAgIHJldHVybiBjYWxsKFN5c3RlbUlzRGFya01vZGUpO1xufVxuXG4vKipcbiAqIEZldGNoZXMgdGhlIGNhcGFiaWxpdGllcyBvZiB0aGUgYXBwbGljYXRpb24gZnJvbSB0aGUgc2VydmVyLlxuICpcbiAqIEByZXR1cm5zIEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHRvIGFuIG9iamVjdCBjb250YWluaW5nIHRoZSBjYXBhYmlsaXRpZXMuXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBDYXBhYmlsaXRpZXMoKTogUHJvbWlzZTxSZWNvcmQ8c3RyaW5nLCBhbnk+PiB7XG4gICAgcmV0dXJuIGNhbGwoU3lzdGVtQ2FwYWJpbGl0aWVzKTtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBPU0luZm8ge1xuICAgIC8qKiBUaGUgYnJhbmRpbmcgb2YgdGhlIE9TLiAqL1xuICAgIEJyYW5kaW5nOiBzdHJpbmc7XG4gICAgLyoqIFRoZSBJRCBvZiB0aGUgT1MuICovXG4gICAgSUQ6IHN0cmluZztcbiAgICAvKiogVGhlIG5hbWUgb2YgdGhlIE9TLiAqL1xuICAgIE5hbWU6IHN0cmluZztcbiAgICAvKiogVGhlIHZlcnNpb24gb2YgdGhlIE9TLiAqL1xuICAgIFZlcnNpb246IHN0cmluZztcbn1cblxuZXhwb3J0IGludGVyZmFjZSBFbnZpcm9ubWVudEluZm8ge1xuICAgIC8qKiBUaGUgYXJjaGl0ZWN0dXJlIG9mIHRoZSBzeXN0ZW0uICovXG4gICAgQXJjaDogc3RyaW5nO1xuICAgIC8qKiBUcnVlIGlmIHRoZSBhcHBsaWNhdGlvbiBpcyBydW5uaW5nIGluIGRlYnVnIG1vZGUsIG90aGVyd2lzZSBmYWxzZS4gKi9cbiAgICBEZWJ1ZzogYm9vbGVhbjtcbiAgICAvKiogVGhlIG9wZXJhdGluZyBzeXN0ZW0gaW4gdXNlLiAqL1xuICAgIE9TOiBzdHJpbmc7XG4gICAgLyoqIERldGFpbHMgb2YgdGhlIG9wZXJhdGluZyBzeXN0ZW0uICovXG4gICAgT1NJbmZvOiBPU0luZm87XG4gICAgLyoqIEFkZGl0aW9uYWwgcGxhdGZvcm0gaW5mb3JtYXRpb24uICovXG4gICAgUGxhdGZvcm1JbmZvOiBSZWNvcmQ8c3RyaW5nLCBhbnk+O1xufVxuXG4vKipcbiAqIFJldHJpZXZlcyBlbnZpcm9ubWVudCBkZXRhaWxzLlxuICpcbiAqIEByZXR1cm5zIEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHRvIGFuIG9iamVjdCBjb250YWluaW5nIE9TIGFuZCBzeXN0ZW0gYXJjaGl0ZWN0dXJlLlxuICovXG5leHBvcnQgZnVuY3Rpb24gRW52aXJvbm1lbnQoKTogUHJvbWlzZTxFbnZpcm9ubWVudEluZm8+IHtcbiAgICByZXR1cm4gY2FsbChTeXN0ZW1FbnZpcm9ubWVudCk7XG59XG5cbi8qKlxuICogQ2hlY2tzIGlmIHRoZSBjdXJyZW50IG9wZXJhdGluZyBzeXN0ZW0gaXMgV2luZG93cy5cbiAqXG4gKiBAcmV0dXJuIFRydWUgaWYgdGhlIG9wZXJhdGluZyBzeXN0ZW0gaXMgV2luZG93cywgb3RoZXJ3aXNlIGZhbHNlLlxuICovXG5leHBvcnQgZnVuY3Rpb24gSXNXaW5kb3dzKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiAod2luZG93IGFzIGFueSkuX3dhaWxzPy5lbnZpcm9ubWVudD8uT1MgPT09IFwid2luZG93c1wiO1xufVxuXG4vKipcbiAqIENoZWNrcyBpZiB0aGUgY3VycmVudCBvcGVyYXRpbmcgc3lzdGVtIGlzIExpbnV4LlxuICpcbiAqIEByZXR1cm5zIFJldHVybnMgdHJ1ZSBpZiB0aGUgY3VycmVudCBvcGVyYXRpbmcgc3lzdGVtIGlzIExpbnV4LCBmYWxzZSBvdGhlcndpc2UuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBJc0xpbnV4KCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiAod2luZG93IGFzIGFueSkuX3dhaWxzPy5lbnZpcm9ubWVudD8uT1MgPT09IFwibGludXhcIjtcbn1cblxuLyoqXG4gKiBDaGVja3MgaWYgdGhlIGN1cnJlbnQgZW52aXJvbm1lbnQgaXMgYSBtYWNPUyBvcGVyYXRpbmcgc3lzdGVtLlxuICpcbiAqIEByZXR1cm5zIFRydWUgaWYgdGhlIGVudmlyb25tZW50IGlzIG1hY09TLCBmYWxzZSBvdGhlcndpc2UuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBJc01hYygpOiBib29sZWFuIHtcbiAgICByZXR1cm4gKHdpbmRvdyBhcyBhbnkpLl93YWlscz8uZW52aXJvbm1lbnQ/Lk9TID09PSBcImRhcndpblwiO1xufVxuXG4vKipcbiAqIENoZWNrcyBpZiB0aGUgY3VycmVudCBlbnZpcm9ubWVudCBhcmNoaXRlY3R1cmUgaXMgQU1ENjQuXG4gKlxuICogQHJldHVybnMgVHJ1ZSBpZiB0aGUgY3VycmVudCBlbnZpcm9ubWVudCBhcmNoaXRlY3R1cmUgaXMgQU1ENjQsIGZhbHNlIG90aGVyd2lzZS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIElzQU1ENjQoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuICh3aW5kb3cgYXMgYW55KS5fd2FpbHM/LmVudmlyb25tZW50Py5BcmNoID09PSBcImFtZDY0XCI7XG59XG5cbi8qKlxuICogQ2hlY2tzIGlmIHRoZSBjdXJyZW50IGFyY2hpdGVjdHVyZSBpcyBBUk0uXG4gKlxuICogQHJldHVybnMgVHJ1ZSBpZiB0aGUgY3VycmVudCBhcmNoaXRlY3R1cmUgaXMgQVJNLCBmYWxzZSBvdGhlcndpc2UuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBJc0FSTSgpOiBib29sZWFuIHtcbiAgICByZXR1cm4gKHdpbmRvdyBhcyBhbnkpLl93YWlscz8uZW52aXJvbm1lbnQ/LkFyY2ggPT09IFwiYXJtXCI7XG59XG5cbi8qKlxuICogQ2hlY2tzIGlmIHRoZSBjdXJyZW50IGVudmlyb25tZW50IGlzIEFSTTY0IGFyY2hpdGVjdHVyZS5cbiAqXG4gKiBAcmV0dXJucyBSZXR1cm5zIHRydWUgaWYgdGhlIGVudmlyb25tZW50IGlzIEFSTTY0IGFyY2hpdGVjdHVyZSwgb3RoZXJ3aXNlIHJldHVybnMgZmFsc2UuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBJc0FSTTY0KCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiAod2luZG93IGFzIGFueSkuX3dhaWxzPy5lbnZpcm9ubWVudD8uQXJjaCA9PT0gXCJhcm02NFwiO1xufVxuXG4vKipcbiAqIFJlcG9ydHMgd2hldGhlciB0aGUgYXBwIGlzIGJlaW5nIHJ1biBpbiBkZWJ1ZyBtb2RlLlxuICpcbiAqIEByZXR1cm5zIFRydWUgaWYgdGhlIGFwcCBpcyBiZWluZyBydW4gaW4gZGVidWcgbW9kZS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIElzRGVidWcoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIEJvb2xlYW4oKHdpbmRvdyBhcyBhbnkpLl93YWlscz8uZW52aXJvbm1lbnQ/LkRlYnVnKTtcbn1cblxuIiwgIi8qXG4gX1x0ICAgX19cdCAgXyBfX1xufCB8XHQgLyAvX19fIF8oXykgL19fX19cbnwgfCAvfCAvIC8gX18gYC8gLyAvIF9fXy9cbnwgfC8gfC8gLyAvXy8gLyAvIChfXyAgKVxufF9fL3xfXy9cXF9fLF8vXy9fL19fX18vXG5UaGUgZWxlY3Ryb24gYWx0ZXJuYXRpdmUgZm9yIEdvXG4oYykgTGVhIEFudGhvbnkgMjAxOS1wcmVzZW50XG4qL1xuXG5pbXBvcnQgeyBuZXdSdW50aW1lQ2FsbGVyLCBvYmplY3ROYW1lcyB9IGZyb20gXCIuL3J1bnRpbWUuanNcIjtcbmltcG9ydCB7IElzRGVidWcgfSBmcm9tIFwiLi9zeXN0ZW0uanNcIjtcbmltcG9ydCB7IGV2ZW50VGFyZ2V0IH0gZnJvbSBcIi4vdXRpbHMuanNcIjtcblxuLy8gc2V0dXBcbndpbmRvdy5hZGRFdmVudExpc3RlbmVyKCdjb250ZXh0bWVudScsIGNvbnRleHRNZW51SGFuZGxlcik7XG5cbmNvbnN0IGNhbGwgPSBuZXdSdW50aW1lQ2FsbGVyKG9iamVjdE5hbWVzLkNvbnRleHRNZW51KTtcblxuY29uc3QgQ29udGV4dE1lbnVPcGVuID0gMDtcblxuZnVuY3Rpb24gb3BlbkNvbnRleHRNZW51KGlkOiBzdHJpbmcsIHg6IG51bWJlciwgeTogbnVtYmVyLCBkYXRhOiBhbnkpOiB2b2lkIHtcbiAgICB2b2lkIGNhbGwoQ29udGV4dE1lbnVPcGVuLCB7aWQsIHgsIHksIGRhdGF9KTtcbn1cblxuZnVuY3Rpb24gY29udGV4dE1lbnVIYW5kbGVyKGV2ZW50OiBNb3VzZUV2ZW50KSB7XG4gICAgY29uc3QgdGFyZ2V0ID0gZXZlbnRUYXJnZXQoZXZlbnQpO1xuXG4gICAgLy8gQ2hlY2sgZm9yIGN1c3RvbSBjb250ZXh0IG1lbnVcbiAgICBjb25zdCBjdXN0b21Db250ZXh0TWVudSA9IHdpbmRvdy5nZXRDb21wdXRlZFN0eWxlKHRhcmdldCkuZ2V0UHJvcGVydHlWYWx1ZShcIi0tY3VzdG9tLWNvbnRleHRtZW51XCIpLnRyaW0oKTtcblxuICAgIGlmIChjdXN0b21Db250ZXh0TWVudSkge1xuICAgICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICBjb25zdCBkYXRhID0gd2luZG93LmdldENvbXB1dGVkU3R5bGUodGFyZ2V0KS5nZXRQcm9wZXJ0eVZhbHVlKFwiLS1jdXN0b20tY29udGV4dG1lbnUtZGF0YVwiKTtcbiAgICAgICAgb3BlbkNvbnRleHRNZW51KGN1c3RvbUNvbnRleHRNZW51LCBldmVudC5jbGllbnRYLCBldmVudC5jbGllbnRZLCBkYXRhKTtcbiAgICB9IGVsc2Uge1xuICAgICAgICBwcm9jZXNzRGVmYXVsdENvbnRleHRNZW51KGV2ZW50LCB0YXJnZXQpO1xuICAgIH1cbn1cblxuXG4vKlxuLS1kZWZhdWx0LWNvbnRleHRtZW51OiBhdXRvOyAoZGVmYXVsdCkgd2lsbCBzaG93IHRoZSBkZWZhdWx0IGNvbnRleHQgbWVudSBpZiBjb250ZW50RWRpdGFibGUgaXMgdHJ1ZSBPUiB0ZXh0IGhhcyBiZWVuIHNlbGVjdGVkIE9SIGVsZW1lbnQgaXMgaW5wdXQgb3IgdGV4dGFyZWFcbi0tZGVmYXVsdC1jb250ZXh0bWVudTogc2hvdzsgd2lsbCBhbHdheXMgc2hvdyB0aGUgZGVmYXVsdCBjb250ZXh0IG1lbnVcbi0tZGVmYXVsdC1jb250ZXh0bWVudTogaGlkZTsgd2lsbCBhbHdheXMgaGlkZSB0aGUgZGVmYXVsdCBjb250ZXh0IG1lbnVcblxuVGhpcyBydWxlIGlzIGluaGVyaXRlZCBsaWtlIG5vcm1hbCBDU1MgcnVsZXMsIHNvIG5lc3Rpbmcgd29ya3MgYXMgZXhwZWN0ZWRcbiovXG5mdW5jdGlvbiBwcm9jZXNzRGVmYXVsdENvbnRleHRNZW51KGV2ZW50OiBNb3VzZUV2ZW50LCB0YXJnZXQ6IEhUTUxFbGVtZW50KSB7XG4gICAgLy8gRGVidWcgYnVpbGRzIGFsd2F5cyBzaG93IHRoZSBtZW51XG4gICAgaWYgKElzRGVidWcoKSkge1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgLy8gUHJvY2VzcyBkZWZhdWx0IGNvbnRleHQgbWVudVxuICAgIHN3aXRjaCAod2luZG93LmdldENvbXB1dGVkU3R5bGUodGFyZ2V0KS5nZXRQcm9wZXJ0eVZhbHVlKFwiLS1kZWZhdWx0LWNvbnRleHRtZW51XCIpLnRyaW0oKSkge1xuICAgICAgICBjYXNlICdzaG93JzpcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgY2FzZSAnaGlkZSc6XG4gICAgICAgICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIC8vIENoZWNrIGlmIGNvbnRlbnRFZGl0YWJsZSBpcyB0cnVlXG4gICAgaWYgKHRhcmdldC5pc0NvbnRlbnRFZGl0YWJsZSkge1xuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgLy8gQ2hlY2sgaWYgdGV4dCBoYXMgYmVlbiBzZWxlY3RlZFxuICAgIGNvbnN0IHNlbGVjdGlvbiA9IHdpbmRvdy5nZXRTZWxlY3Rpb24oKTtcbiAgICBjb25zdCBoYXNTZWxlY3Rpb24gPSBzZWxlY3Rpb24gJiYgc2VsZWN0aW9uLnRvU3RyaW5nKCkubGVuZ3RoID4gMDtcbiAgICBpZiAoaGFzU2VsZWN0aW9uKSB7XG4gICAgICAgIGZvciAobGV0IGkgPSAwOyBpIDwgc2VsZWN0aW9uLnJhbmdlQ291bnQ7IGkrKykge1xuICAgICAgICAgICAgY29uc3QgcmFuZ2UgPSBzZWxlY3Rpb24uZ2V0UmFuZ2VBdChpKTtcbiAgICAgICAgICAgIGNvbnN0IHJlY3RzID0gcmFuZ2UuZ2V0Q2xpZW50UmVjdHMoKTtcbiAgICAgICAgICAgIGZvciAobGV0IGogPSAwOyBqIDwgcmVjdHMubGVuZ3RoOyBqKyspIHtcbiAgICAgICAgICAgICAgICBjb25zdCByZWN0ID0gcmVjdHNbal07XG4gICAgICAgICAgICAgICAgaWYgKGRvY3VtZW50LmVsZW1lbnRGcm9tUG9pbnQocmVjdC5sZWZ0LCByZWN0LnRvcCkgPT09IHRhcmdldCkge1xuICAgICAgICAgICAgICAgICAgICByZXR1cm47XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfVxuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy8gQ2hlY2sgaWYgdGFnIGlzIGlucHV0IG9yIHRleHRhcmVhLlxuICAgIGlmICh0YXJnZXQgaW5zdGFuY2VvZiBIVE1MSW5wdXRFbGVtZW50IHx8IHRhcmdldCBpbnN0YW5jZW9mIEhUTUxUZXh0QXJlYUVsZW1lbnQpIHtcbiAgICAgICAgaWYgKGhhc1NlbGVjdGlvbiB8fCAoIXRhcmdldC5yZWFkT25seSAmJiAhdGFyZ2V0LmRpc2FibGVkKSkge1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG4gICAgfVxuXG4gICAgLy8gaGlkZSBkZWZhdWx0IGNvbnRleHQgbWVudVxuICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG59XG4iLCAiLypcbiBfXHQgICBfX1x0ICBfIF9fXG58IHxcdCAvIC9fX18gXyhfKSAvX19fX1xufCB8IC98IC8gLyBfXyBgLyAvIC8gX19fL1xufCB8LyB8LyAvIC9fLyAvIC8gKF9fICApXG58X18vfF9fL1xcX18sXy9fL18vX19fXy9cblRoZSBlbGVjdHJvbiBhbHRlcm5hdGl2ZSBmb3IgR29cbihjKSBMZWEgQW50aG9ueSAyMDE5LXByZXNlbnRcbiovXG5cbi8qKlxuICogUmV0cmlldmVzIHRoZSB2YWx1ZSBhc3NvY2lhdGVkIHdpdGggdGhlIHNwZWNpZmllZCBrZXkgZnJvbSB0aGUgZmxhZyBtYXAuXG4gKlxuICogQHBhcmFtIGtleSAtIFRoZSBrZXkgdG8gcmV0cmlldmUgdGhlIHZhbHVlIGZvci5cbiAqIEByZXR1cm4gVGhlIHZhbHVlIGFzc29jaWF0ZWQgd2l0aCB0aGUgc3BlY2lmaWVkIGtleS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIEdldEZsYWcoa2V5OiBzdHJpbmcpOiBhbnkge1xuICAgIHRyeSB7XG4gICAgICAgIHJldHVybiB3aW5kb3cuX3dhaWxzLmZsYWdzW2tleV07XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJVbmFibGUgdG8gcmV0cmlldmUgZmxhZyAnXCIgKyBrZXkgKyBcIic6IFwiICsgZSwgeyBjYXVzZTogZSB9KTtcbiAgICB9XG59XG4iLCAiLypcbiBfXHQgICBfX1x0ICBfIF9fXG58IHxcdCAvIC9fX18gXyhfKSAvX19fX1xufCB8IC98IC8gLyBfXyBgLyAvIC8gX19fL1xufCB8LyB8LyAvIC9fLyAvIC8gKF9fICApXG58X18vfF9fL1xcX18sXy9fL18vX19fXy9cblRoZSBlbGVjdHJvbiBhbHRlcm5hdGl2ZSBmb3IgR29cbihjKSBMZWEgQW50aG9ueSAyMDE5LXByZXNlbnRcbiovXG5cbmltcG9ydCB7IGludm9rZSwgSXNXaW5kb3dzIH0gZnJvbSBcIi4vc3lzdGVtLmpzXCI7XG5pbXBvcnQgeyBHZXRGbGFnIH0gZnJvbSBcIi4vZmxhZ3MuanNcIjtcbmltcG9ydCB7IGNhblRyYWNrQnV0dG9ucywgZXZlbnRUYXJnZXQgfSBmcm9tIFwiLi91dGlscy5qc1wiO1xuXG4vLyBTZXR1cFxubGV0IGNhbkRyYWcgPSBmYWxzZTtcbmxldCBkcmFnZ2luZyA9IGZhbHNlO1xuXG5sZXQgcmVzaXphYmxlID0gZmFsc2U7XG5sZXQgY2FuUmVzaXplID0gZmFsc2U7XG5sZXQgcmVzaXppbmcgPSBmYWxzZTtcbmxldCByZXNpemVFZGdlOiBzdHJpbmcgPSBcIlwiO1xubGV0IGRlZmF1bHRDdXJzb3IgPSBcImF1dG9cIjtcblxubGV0IGJ1dHRvbnMgPSAwO1xuY29uc3QgYnV0dG9uc1RyYWNrZWQgPSBjYW5UcmFja0J1dHRvbnMoKTtcblxud2luZG93Ll93YWlscyA9IHdpbmRvdy5fd2FpbHMgfHwge307XG53aW5kb3cuX3dhaWxzLnNldFJlc2l6YWJsZSA9ICh2YWx1ZTogYm9vbGVhbik6IHZvaWQgPT4ge1xuICAgIHJlc2l6YWJsZSA9IHZhbHVlO1xuICAgIGlmICghcmVzaXphYmxlKSB7XG4gICAgICAgIC8vIFN0b3AgcmVzaXppbmcgaWYgaW4gcHJvZ3Jlc3MuXG4gICAgICAgIGNhblJlc2l6ZSA9IHJlc2l6aW5nID0gZmFsc2U7XG4gICAgICAgIHNldFJlc2l6ZSgpO1xuICAgIH1cbn07XG5cbi8vIERlZmVyIGF0dGFjaGluZyBtb3VzZSBsaXN0ZW5lcnMgdW50aWwgd2Uga25vdyB3ZSdyZSBub3Qgb24gbW9iaWxlLlxubGV0IGRyYWdJbml0RG9uZSA9IGZhbHNlO1xuZnVuY3Rpb24gaXNNb2JpbGUoKTogYm9vbGVhbiB7XG4gICAgY29uc3Qgb3MgPSAod2luZG93IGFzIGFueSkuX3dhaWxzPy5lbnZpcm9ubWVudD8uT1M7XG4gICAgaWYgKG9zID09PSBcImlvc1wiIHx8IG9zID09PSBcImFuZHJvaWRcIikgcmV0dXJuIHRydWU7XG4gICAgLy8gRmFsbGJhY2sgaGV1cmlzdGljIGlmIGVudmlyb25tZW50IG5vdCB5ZXQgc2V0XG4gICAgY29uc3QgdWEgPSBuYXZpZ2F0b3IudXNlckFnZW50IHx8IG5hdmlnYXRvci52ZW5kb3IgfHwgKHdpbmRvdyBhcyBhbnkpLm9wZXJhIHx8IFwiXCI7XG4gICAgcmV0dXJuIC9hbmRyb2lkfGlwaG9uZXxpcGFkfGlwb2R8aWVtb2JpbGV8d3BkZXNrdG9wL2kudGVzdCh1YSk7XG59XG5mdW5jdGlvbiB0cnlJbml0RHJhZ0hhbmRsZXJzKCk6IHZvaWQge1xuICAgIGlmIChkcmFnSW5pdERvbmUpIHJldHVybjtcbiAgICBpZiAoaXNNb2JpbGUoKSkgcmV0dXJuO1xuICAgIHdpbmRvdy5hZGRFdmVudExpc3RlbmVyKCdtb3VzZWRvd24nLCB1cGRhdGUsIHsgY2FwdHVyZTogdHJ1ZSB9KTtcbiAgICB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcignbW91c2Vtb3ZlJywgdXBkYXRlLCB7IGNhcHR1cmU6IHRydWUgfSk7XG4gICAgd2luZG93LmFkZEV2ZW50TGlzdGVuZXIoJ21vdXNldXAnLCB1cGRhdGUsIHsgY2FwdHVyZTogdHJ1ZSB9KTtcbiAgICBmb3IgKGNvbnN0IGV2IG9mIFsnY2xpY2snLCAnY29udGV4dG1lbnUnLCAnZGJsY2xpY2snXSkge1xuICAgICAgICB3aW5kb3cuYWRkRXZlbnRMaXN0ZW5lcihldiwgc3VwcHJlc3NFdmVudCwgeyBjYXB0dXJlOiB0cnVlIH0pO1xuICAgIH1cbiAgICBkcmFnSW5pdERvbmUgPSB0cnVlO1xufVxuLy8gQXR0ZW1wdCBpbW1lZGlhdGUgaW5pdCAoaW4gY2FzZSBlbnZpcm9ubWVudCBhbHJlYWR5IHByZXNlbnQpXG50cnlJbml0RHJhZ0hhbmRsZXJzKCk7XG4vLyBBbHNvIGF0dGVtcHQgb24gRE9NIHJlYWR5XG5kb2N1bWVudC5hZGRFdmVudExpc3RlbmVyKCdET01Db250ZW50TG9hZGVkJywgdHJ5SW5pdERyYWdIYW5kbGVycywgeyBvbmNlOiB0cnVlIH0pO1xuLy8gQXMgYSBsYXN0IHJlc29ydCwgcG9sbCBmb3IgZW52aXJvbm1lbnQgZm9yIGEgc2hvcnQgcGVyaW9kXG5sZXQgZHJhZ0VudlBvbGxzID0gMDtcbmNvbnN0IGRyYWdFbnZQb2xsID0gd2luZG93LnNldEludGVydmFsKCgpID0+IHtcbiAgICBpZiAoZHJhZ0luaXREb25lKSB7IHdpbmRvdy5jbGVhckludGVydmFsKGRyYWdFbnZQb2xsKTsgcmV0dXJuOyB9XG4gICAgdHJ5SW5pdERyYWdIYW5kbGVycygpO1xuICAgIGlmICgrK2RyYWdFbnZQb2xscyA+IDEwMCkgeyB3aW5kb3cuY2xlYXJJbnRlcnZhbChkcmFnRW52UG9sbCk7IH1cbn0sIDUwKTtcblxuZnVuY3Rpb24gc3VwcHJlc3NFdmVudChldmVudDogRXZlbnQpIHtcbiAgICAvLyBTdXBwcmVzcyBjbGljayBldmVudHMgd2hpbGUgcmVzaXppbmcgb3IgZHJhZ2dpbmcuXG4gICAgaWYgKGRyYWdnaW5nIHx8IHJlc2l6aW5nKSB7XG4gICAgICAgIGV2ZW50LnN0b3BJbW1lZGlhdGVQcm9wYWdhdGlvbigpO1xuICAgICAgICBldmVudC5zdG9wUHJvcGFnYXRpb24oKTtcbiAgICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTtcbiAgICB9XG59XG5cbi8vIFVzZSBjb25zdGFudHMgdG8gYXZvaWQgY29tcGFyaW5nIHN0cmluZ3MgbXVsdGlwbGUgdGltZXMuXG5jb25zdCBNb3VzZURvd24gPSAwO1xuY29uc3QgTW91c2VVcCAgID0gMTtcbmNvbnN0IE1vdXNlTW92ZSA9IDI7XG5cbmZ1bmN0aW9uIHVwZGF0ZShldmVudDogTW91c2VFdmVudCkge1xuICAgIC8vIFdpbmRvd3Mgc3VwcHJlc3NlcyBtb3VzZSBldmVudHMgYXQgdGhlIGVuZCBvZiBkcmFnZ2luZyBvciByZXNpemluZyxcbiAgICAvLyBzbyB3ZSBuZWVkIHRvIGJlIHNtYXJ0IGFuZCBzeW50aGVzaXplIGJ1dHRvbiBldmVudHMuXG5cbiAgICBsZXQgZXZlbnRUeXBlOiBudW1iZXIsIGV2ZW50QnV0dG9ucyA9IGV2ZW50LmJ1dHRvbnM7XG4gICAgc3dpdGNoIChldmVudC50eXBlKSB7XG4gICAgICAgIGNhc2UgJ21vdXNlZG93bic6XG4gICAgICAgICAgICBldmVudFR5cGUgPSBNb3VzZURvd247XG4gICAgICAgICAgICBpZiAoIWJ1dHRvbnNUcmFja2VkKSB7IGV2ZW50QnV0dG9ucyA9IGJ1dHRvbnMgfCAoMSA8PCBldmVudC5idXR0b24pOyB9XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgY2FzZSAnbW91c2V1cCc6XG4gICAgICAgICAgICBldmVudFR5cGUgPSBNb3VzZVVwO1xuICAgICAgICAgICAgaWYgKCFidXR0b25zVHJhY2tlZCkgeyBldmVudEJ1dHRvbnMgPSBidXR0b25zICYgfigxIDw8IGV2ZW50LmJ1dHRvbik7IH1cbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICBkZWZhdWx0OlxuICAgICAgICAgICAgZXZlbnRUeXBlID0gTW91c2VNb3ZlO1xuICAgICAgICAgICAgaWYgKCFidXR0b25zVHJhY2tlZCkgeyBldmVudEJ1dHRvbnMgPSBidXR0b25zOyB9XG4gICAgICAgICAgICBicmVhaztcbiAgICB9XG5cbiAgICBsZXQgcmVsZWFzZWQgPSBidXR0b25zICYgfmV2ZW50QnV0dG9ucztcbiAgICBsZXQgcHJlc3NlZCA9IGV2ZW50QnV0dG9ucyAmIH5idXR0b25zO1xuXG4gICAgYnV0dG9ucyA9IGV2ZW50QnV0dG9ucztcblxuICAgIC8vIFN5bnRoZXNpemUgYSByZWxlYXNlLXByZXNzIHNlcXVlbmNlIGlmIHdlIGRldGVjdCBhIHByZXNzIG9mIGFuIGFscmVhZHkgcHJlc3NlZCBidXR0b24uXG4gICAgaWYgKGV2ZW50VHlwZSA9PT0gTW91c2VEb3duICYmICEocHJlc3NlZCAmIGV2ZW50LmJ1dHRvbikpIHtcbiAgICAgICAgcmVsZWFzZWQgfD0gKDEgPDwgZXZlbnQuYnV0dG9uKTtcbiAgICAgICAgcHJlc3NlZCB8PSAoMSA8PCBldmVudC5idXR0b24pO1xuICAgIH1cblxuICAgIC8vIFN1cHByZXNzIGFsbCBidXR0b24gZXZlbnRzIGR1cmluZyBkcmFnZ2luZyBhbmQgcmVzaXppbmcsXG4gICAgLy8gdW5sZXNzIHRoaXMgaXMgYSBtb3VzZXVwIGV2ZW50IHRoYXQgaXMgZW5kaW5nIGEgZHJhZyBhY3Rpb24uXG4gICAgaWYgKFxuICAgICAgICBldmVudFR5cGUgIT09IE1vdXNlTW92ZSAvLyBGYXN0IHBhdGggZm9yIG1vdXNlbW92ZVxuICAgICAgICAmJiByZXNpemluZ1xuICAgICAgICB8fCAoXG4gICAgICAgICAgICBkcmFnZ2luZ1xuICAgICAgICAgICAgJiYgKFxuICAgICAgICAgICAgICAgIGV2ZW50VHlwZSA9PT0gTW91c2VEb3duXG4gICAgICAgICAgICAgICAgfHwgZXZlbnQuYnV0dG9uICE9PSAwXG4gICAgICAgICAgICApXG4gICAgICAgIClcbiAgICApIHtcbiAgICAgICAgZXZlbnQuc3RvcEltbWVkaWF0ZVByb3BhZ2F0aW9uKCk7XG4gICAgICAgIGV2ZW50LnN0b3BQcm9wYWdhdGlvbigpO1xuICAgICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgIH1cblxuICAgIC8vIEhhbmRsZSByZWxlYXNlc1xuICAgIGlmIChyZWxlYXNlZCAmIDEpIHsgcHJpbWFyeVVwKGV2ZW50KTsgfVxuICAgIC8vIEhhbmRsZSBwcmVzc2VzXG4gICAgaWYgKHByZXNzZWQgJiAxKSB7IHByaW1hcnlEb3duKGV2ZW50KTsgfVxuXG4gICAgLy8gSGFuZGxlIG1vdXNlbW92ZVxuICAgIGlmIChldmVudFR5cGUgPT09IE1vdXNlTW92ZSkgeyBvbk1vdXNlTW92ZShldmVudCk7IH07XG59XG5cbmZ1bmN0aW9uIHByaW1hcnlEb3duKGV2ZW50OiBNb3VzZUV2ZW50KTogdm9pZCB7XG4gICAgLy8gUmVzZXQgcmVhZGluZXNzIHN0YXRlLlxuICAgIGNhbkRyYWcgPSBmYWxzZTtcbiAgICBjYW5SZXNpemUgPSBmYWxzZTtcblxuICAgIC8vIElnbm9yZSByZXBlYXRlZCBjbGlja3Mgb24gbWFjT1MgYW5kIExpbnV4LlxuICAgIGlmICghSXNXaW5kb3dzKCkpIHtcbiAgICAgICAgaWYgKGV2ZW50LnR5cGUgPT09ICdtb3VzZWRvd24nICYmIGV2ZW50LmJ1dHRvbiA9PT0gMCAmJiBldmVudC5kZXRhaWwgIT09IDEpIHtcbiAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgIH1cblxuICAgIGlmIChyZXNpemVFZGdlKSB7XG4gICAgICAgIC8vIFJlYWR5IHRvIHJlc2l6ZSBpZiB0aGUgcHJpbWFyeSBidXR0b24gd2FzIHByZXNzZWQgZm9yIHRoZSBmaXJzdCB0aW1lLlxuICAgICAgICBjYW5SZXNpemUgPSB0cnVlO1xuICAgICAgICAvLyBEbyBub3Qgc3RhcnQgZHJhZyBvcGVyYXRpb25zIHdoZW4gb24gcmVzaXplIGVkZ2VzLlxuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgLy8gUmV0cmlldmUgdGFyZ2V0IGVsZW1lbnRcbiAgICBjb25zdCB0YXJnZXQgPSBldmVudFRhcmdldChldmVudCk7XG5cbiAgICAvLyBSZWFkeSB0byBkcmFnIGlmIHRoZSBwcmltYXJ5IGJ1dHRvbiB3YXMgcHJlc3NlZCBmb3IgdGhlIGZpcnN0IHRpbWUgb24gYSBkcmFnZ2FibGUgZWxlbWVudC5cbiAgICAvLyBJZ25vcmUgY2xpY2tzIG9uIHRoZSBzY3JvbGxiYXIuXG4gICAgY29uc3Qgc3R5bGUgPSB3aW5kb3cuZ2V0Q29tcHV0ZWRTdHlsZSh0YXJnZXQpO1xuICAgIGNhbkRyYWcgPSAoXG4gICAgICAgIHN0eWxlLmdldFByb3BlcnR5VmFsdWUoXCItLXdhaWxzLWRyYWdnYWJsZVwiKS50cmltKCkgPT09IFwiZHJhZ1wiXG4gICAgICAgICYmIChcbiAgICAgICAgICAgIGV2ZW50Lm9mZnNldFggLSBwYXJzZUZsb2F0KHN0eWxlLnBhZGRpbmdMZWZ0KSA8IHRhcmdldC5jbGllbnRXaWR0aFxuICAgICAgICAgICAgJiYgZXZlbnQub2Zmc2V0WSAtIHBhcnNlRmxvYXQoc3R5bGUucGFkZGluZ1RvcCkgPCB0YXJnZXQuY2xpZW50SGVpZ2h0XG4gICAgICAgIClcbiAgICApO1xufVxuXG5mdW5jdGlvbiBwcmltYXJ5VXAoZXZlbnQ6IE1vdXNlRXZlbnQpIHtcbiAgICAvLyBTdG9wIGRyYWdnaW5nIGFuZCByZXNpemluZy5cbiAgICBjYW5EcmFnID0gZmFsc2U7XG4gICAgZHJhZ2dpbmcgPSBmYWxzZTtcbiAgICBjYW5SZXNpemUgPSBmYWxzZTtcbiAgICByZXNpemluZyA9IGZhbHNlO1xufVxuXG5jb25zdCBjdXJzb3JGb3JFZGdlID0gT2JqZWN0LmZyZWV6ZSh7XG4gICAgXCJzZS1yZXNpemVcIjogXCJud3NlLXJlc2l6ZVwiLFxuICAgIFwic3ctcmVzaXplXCI6IFwibmVzdy1yZXNpemVcIixcbiAgICBcIm53LXJlc2l6ZVwiOiBcIm53c2UtcmVzaXplXCIsXG4gICAgXCJuZS1yZXNpemVcIjogXCJuZXN3LXJlc2l6ZVwiLFxuICAgIFwidy1yZXNpemVcIjogXCJldy1yZXNpemVcIixcbiAgICBcIm4tcmVzaXplXCI6IFwibnMtcmVzaXplXCIsXG4gICAgXCJzLXJlc2l6ZVwiOiBcIm5zLXJlc2l6ZVwiLFxuICAgIFwiZS1yZXNpemVcIjogXCJldy1yZXNpemVcIixcbn0pXG5cbmZ1bmN0aW9uIHNldFJlc2l6ZShlZGdlPzoga2V5b2YgdHlwZW9mIGN1cnNvckZvckVkZ2UpOiB2b2lkIHtcbiAgICBpZiAoZWRnZSkge1xuICAgICAgICBpZiAoIXJlc2l6ZUVkZ2UpIHsgZGVmYXVsdEN1cnNvciA9IGRvY3VtZW50LmJvZHkuc3R5bGUuY3Vyc29yOyB9XG4gICAgICAgIGRvY3VtZW50LmJvZHkuc3R5bGUuY3Vyc29yID0gY3Vyc29yRm9yRWRnZVtlZGdlXTtcbiAgICB9IGVsc2UgaWYgKCFlZGdlICYmIHJlc2l6ZUVkZ2UpIHtcbiAgICAgICAgZG9jdW1lbnQuYm9keS5zdHlsZS5jdXJzb3IgPSBkZWZhdWx0Q3Vyc29yO1xuICAgIH1cblxuICAgIHJlc2l6ZUVkZ2UgPSBlZGdlIHx8IFwiXCI7XG59XG5cbmZ1bmN0aW9uIG9uTW91c2VNb3ZlKGV2ZW50OiBNb3VzZUV2ZW50KTogdm9pZCB7XG4gICAgaWYgKGNhblJlc2l6ZSAmJiByZXNpemVFZGdlKSB7XG4gICAgICAgIC8vIFN0YXJ0IHJlc2l6aW5nLlxuICAgICAgICByZXNpemluZyA9IHRydWU7XG4gICAgICAgIGludm9rZShcIndhaWxzOnJlc2l6ZTpcIiArIHJlc2l6ZUVkZ2UpO1xuICAgIH0gZWxzZSBpZiAoY2FuRHJhZykge1xuICAgICAgICAvLyBTdGFydCBkcmFnZ2luZy5cbiAgICAgICAgZHJhZ2dpbmcgPSB0cnVlO1xuICAgICAgICBpbnZva2UoXCJ3YWlsczpkcmFnXCIpO1xuICAgIH1cblxuICAgIGlmIChkcmFnZ2luZyB8fCByZXNpemluZykge1xuICAgICAgICAvLyBFaXRoZXIgZHJhZyBvciByZXNpemUgaXMgb25nb2luZyxcbiAgICAgICAgLy8gcmVzZXQgcmVhZGluZXNzIGFuZCBzdG9wIHByb2Nlc3NpbmcuXG4gICAgICAgIGNhbkRyYWcgPSBjYW5SZXNpemUgPSBmYWxzZTtcbiAgICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGlmICghcmVzaXphYmxlIHx8ICFJc1dpbmRvd3MoKSkge1xuICAgICAgICBpZiAocmVzaXplRWRnZSkgeyBzZXRSZXNpemUoKTsgfVxuICAgICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgY29uc3QgcmVzaXplSGFuZGxlSGVpZ2h0ID0gR2V0RmxhZyhcInN5c3RlbS5yZXNpemVIYW5kbGVIZWlnaHRcIikgfHwgNTtcbiAgICBjb25zdCByZXNpemVIYW5kbGVXaWR0aCA9IEdldEZsYWcoXCJzeXN0ZW0ucmVzaXplSGFuZGxlV2lkdGhcIikgfHwgNTtcblxuICAgIC8vIEV4dHJhIHBpeGVscyBmb3IgdGhlIGNvcm5lciBhcmVhcy5cbiAgICBjb25zdCBjb3JuZXJFeHRyYSA9IEdldEZsYWcoXCJyZXNpemVDb3JuZXJFeHRyYVwiKSB8fCAxMDtcblxuICAgIGNvbnN0IHJpZ2h0Qm9yZGVyID0gKHdpbmRvdy5vdXRlcldpZHRoIC0gZXZlbnQuY2xpZW50WCkgPCByZXNpemVIYW5kbGVXaWR0aDtcbiAgICBjb25zdCBsZWZ0Qm9yZGVyID0gZXZlbnQuY2xpZW50WCA8IHJlc2l6ZUhhbmRsZVdpZHRoO1xuICAgIGNvbnN0IHRvcEJvcmRlciA9IGV2ZW50LmNsaWVudFkgPCByZXNpemVIYW5kbGVIZWlnaHQ7XG4gICAgY29uc3QgYm90dG9tQm9yZGVyID0gKHdpbmRvdy5vdXRlckhlaWdodCAtIGV2ZW50LmNsaWVudFkpIDwgcmVzaXplSGFuZGxlSGVpZ2h0O1xuXG4gICAgLy8gQWRqdXN0IGZvciBjb3JuZXIgYXJlYXMuXG4gICAgY29uc3QgcmlnaHRDb3JuZXIgPSAod2luZG93Lm91dGVyV2lkdGggLSBldmVudC5jbGllbnRYKSA8IChyZXNpemVIYW5kbGVXaWR0aCArIGNvcm5lckV4dHJhKTtcbiAgICBjb25zdCBsZWZ0Q29ybmVyID0gZXZlbnQuY2xpZW50WCA8IChyZXNpemVIYW5kbGVXaWR0aCArIGNvcm5lckV4dHJhKTtcbiAgICBjb25zdCB0b3BDb3JuZXIgPSBldmVudC5jbGllbnRZIDwgKHJlc2l6ZUhhbmRsZUhlaWdodCArIGNvcm5lckV4dHJhKTtcbiAgICBjb25zdCBib3R0b21Db3JuZXIgPSAod2luZG93Lm91dGVySGVpZ2h0IC0gZXZlbnQuY2xpZW50WSkgPCAocmVzaXplSGFuZGxlSGVpZ2h0ICsgY29ybmVyRXh0cmEpO1xuXG4gICAgaWYgKCFsZWZ0Q29ybmVyICYmICF0b3BDb3JuZXIgJiYgIWJvdHRvbUNvcm5lciAmJiAhcmlnaHRDb3JuZXIpIHtcbiAgICAgICAgLy8gT3B0aW1pc2F0aW9uOiBvdXQgb2YgYWxsIGNvcm5lciBhcmVhcyBpbXBsaWVzIG91dCBvZiBib3JkZXJzLlxuICAgICAgICBzZXRSZXNpemUoKTtcbiAgICB9XG4gICAgLy8gRGV0ZWN0IGNvcm5lcnMuXG4gICAgZWxzZSBpZiAocmlnaHRDb3JuZXIgJiYgYm90dG9tQ29ybmVyKSBzZXRSZXNpemUoXCJzZS1yZXNpemVcIik7XG4gICAgZWxzZSBpZiAobGVmdENvcm5lciAmJiBib3R0b21Db3JuZXIpIHNldFJlc2l6ZShcInN3LXJlc2l6ZVwiKTtcbiAgICBlbHNlIGlmIChsZWZ0Q29ybmVyICYmIHRvcENvcm5lcikgc2V0UmVzaXplKFwibnctcmVzaXplXCIpO1xuICAgIGVsc2UgaWYgKHRvcENvcm5lciAmJiByaWdodENvcm5lcikgc2V0UmVzaXplKFwibmUtcmVzaXplXCIpO1xuICAgIC8vIERldGVjdCBib3JkZXJzLlxuICAgIGVsc2UgaWYgKGxlZnRCb3JkZXIpIHNldFJlc2l6ZShcInctcmVzaXplXCIpO1xuICAgIGVsc2UgaWYgKHRvcEJvcmRlcikgc2V0UmVzaXplKFwibi1yZXNpemVcIik7XG4gICAgZWxzZSBpZiAoYm90dG9tQm9yZGVyKSBzZXRSZXNpemUoXCJzLXJlc2l6ZVwiKTtcbiAgICBlbHNlIGlmIChyaWdodEJvcmRlcikgc2V0UmVzaXplKFwiZS1yZXNpemVcIik7XG4gICAgLy8gT3V0IG9mIGJvcmRlciBhcmVhLlxuICAgIGVsc2Ugc2V0UmVzaXplKCk7XG59XG4iLCAiLypcbiBfXHQgICBfX1x0ICBfIF9fXG58IHxcdCAvIC9fX18gXyhfKSAvX19fX1xufCB8IC98IC8gLyBfXyBgLyAvIC8gX19fL1xufCB8LyB8LyAvIC9fLyAvIC8gKF9fICApXG58X18vfF9fL1xcX18sXy9fL18vX19fXy9cblRoZSBlbGVjdHJvbiBhbHRlcm5hdGl2ZSBmb3IgR29cbihjKSBMZWEgQW50aG9ueSAyMDE5LXByZXNlbnRcbiovXG5cbmltcG9ydCB7IG5ld1J1bnRpbWVDYWxsZXIsIG9iamVjdE5hbWVzIH0gZnJvbSBcIi4vcnVudGltZS5qc1wiO1xuY29uc3QgY2FsbCA9IG5ld1J1bnRpbWVDYWxsZXIob2JqZWN0TmFtZXMuQXBwbGljYXRpb24pO1xuXG5jb25zdCBIaWRlTWV0aG9kID0gMDtcbmNvbnN0IFNob3dNZXRob2QgPSAxO1xuY29uc3QgUXVpdE1ldGhvZCA9IDI7XG5cbi8qKlxuICogSGlkZXMgYSBjZXJ0YWluIG1ldGhvZCBieSBjYWxsaW5nIHRoZSBIaWRlTWV0aG9kIGZ1bmN0aW9uLlxuICovXG5leHBvcnQgZnVuY3Rpb24gSGlkZSgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICByZXR1cm4gY2FsbChIaWRlTWV0aG9kKTtcbn1cblxuLyoqXG4gKiBDYWxscyB0aGUgU2hvd01ldGhvZCBhbmQgcmV0dXJucyB0aGUgcmVzdWx0LlxuICovXG5leHBvcnQgZnVuY3Rpb24gU2hvdygpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICByZXR1cm4gY2FsbChTaG93TWV0aG9kKTtcbn1cblxuLyoqXG4gKiBDYWxscyB0aGUgUXVpdE1ldGhvZCB0byB0ZXJtaW5hdGUgdGhlIHByb2dyYW0uXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBRdWl0KCk6IFByb21pc2U8dm9pZD4ge1xuICAgIHJldHVybiBjYWxsKFF1aXRNZXRob2QpO1xufVxuIiwgIi8qXG4gX1x0ICAgX19cdCAgXyBfX1xufCB8XHQgLyAvX19fIF8oXykgL19fX19cbnwgfCAvfCAvIC8gX18gYC8gLyAvIF9fXy9cbnwgfC8gfC8gLyAvXy8gLyAvIChfXyAgKVxufF9fL3xfXy9cXF9fLF8vXy9fL19fX18vXG5UaGUgZWxlY3Ryb24gYWx0ZXJuYXRpdmUgZm9yIEdvXG4oYykgTGVhIEFudGhvbnkgMjAxOS1wcmVzZW50XG4qL1xuXG5pbXBvcnQgeyBDYW5jZWxsYWJsZVByb21pc2UsIHR5cGUgQ2FuY2VsbGFibGVQcm9taXNlV2l0aFJlc29sdmVycyB9IGZyb20gXCIuL2NhbmNlbGxhYmxlLmpzXCI7XG5pbXBvcnQgeyBuZXdSdW50aW1lQ2FsbGVyLCBvYmplY3ROYW1lcyB9IGZyb20gXCIuL3J1bnRpbWUuanNcIjtcbmltcG9ydCB7IG5hbm9pZCB9IGZyb20gXCIuL25hbm9pZC5qc1wiO1xuXG4vLyBTZXR1cFxud2luZG93Ll93YWlscyA9IHdpbmRvdy5fd2FpbHMgfHwge307XG5cbnR5cGUgUHJvbWlzZVJlc29sdmVycyA9IE9taXQ8Q2FuY2VsbGFibGVQcm9taXNlV2l0aFJlc29sdmVyczxhbnk+LCBcInByb21pc2VcIiB8IFwib25jYW5jZWxsZWRcIj5cblxuY29uc3QgY2FsbCA9IG5ld1J1bnRpbWVDYWxsZXIob2JqZWN0TmFtZXMuQ2FsbCk7XG5jb25zdCBjYW5jZWxDYWxsID0gbmV3UnVudGltZUNhbGxlcihvYmplY3ROYW1lcy5DYW5jZWxDYWxsKTtcbmNvbnN0IGNhbGxSZXNwb25zZXMgPSBuZXcgTWFwPHN0cmluZywgUHJvbWlzZVJlc29sdmVycz4oKTtcblxuY29uc3QgQ2FsbEJpbmRpbmcgPSAwO1xuY29uc3QgQ2FuY2VsTWV0aG9kID0gMFxuXG4vKipcbiAqIEhvbGRzIGFsbCByZXF1aXJlZCBpbmZvcm1hdGlvbiBmb3IgYSBiaW5kaW5nIGNhbGwuXG4gKiBNYXkgcHJvdmlkZSBlaXRoZXIgYSBtZXRob2QgSUQgb3IgYSBtZXRob2QgbmFtZSwgYnV0IG5vdCBib3RoLlxuICovXG5leHBvcnQgdHlwZSBDYWxsT3B0aW9ucyA9IHtcbiAgICAvKiogVGhlIG51bWVyaWMgSUQgb2YgdGhlIGJvdW5kIG1ldGhvZCB0byBjYWxsLiAqL1xuICAgIG1ldGhvZElEOiBudW1iZXI7XG4gICAgLyoqIFRoZSBmdWxseSBxdWFsaWZpZWQgbmFtZSBvZiB0aGUgYm91bmQgbWV0aG9kIHRvIGNhbGwuICovXG4gICAgbWV0aG9kTmFtZT86IG5ldmVyO1xuICAgIC8qKiBBcmd1bWVudHMgdG8gYmUgcGFzc2VkIGludG8gdGhlIGJvdW5kIG1ldGhvZC4gKi9cbiAgICBhcmdzOiBhbnlbXTtcbn0gfCB7XG4gICAgLyoqIFRoZSBudW1lcmljIElEIG9mIHRoZSBib3VuZCBtZXRob2QgdG8gY2FsbC4gKi9cbiAgICBtZXRob2RJRD86IG5ldmVyO1xuICAgIC8qKiBUaGUgZnVsbHkgcXVhbGlmaWVkIG5hbWUgb2YgdGhlIGJvdW5kIG1ldGhvZCB0byBjYWxsLiAqL1xuICAgIG1ldGhvZE5hbWU6IHN0cmluZztcbiAgICAvKiogQXJndW1lbnRzIHRvIGJlIHBhc3NlZCBpbnRvIHRoZSBib3VuZCBtZXRob2QuICovXG4gICAgYXJnczogYW55W107XG59O1xuXG4vKipcbiAqIEV4Y2VwdGlvbiBjbGFzcyB0aGF0IHdpbGwgYmUgdGhyb3duIGluIGNhc2UgdGhlIGJvdW5kIG1ldGhvZCByZXR1cm5zIGFuIGVycm9yLlxuICogVGhlIHZhbHVlIG9mIHRoZSB7QGxpbmsgUnVudGltZUVycm9yI25hbWV9IHByb3BlcnR5IGlzIFwiUnVudGltZUVycm9yXCIuXG4gKi9cbmV4cG9ydCBjbGFzcyBSdW50aW1lRXJyb3IgZXh0ZW5kcyBFcnJvciB7XG4gICAgLyoqXG4gICAgICogQ29uc3RydWN0cyBhIG5ldyBSdW50aW1lRXJyb3IgaW5zdGFuY2UuXG4gICAgICogQHBhcmFtIG1lc3NhZ2UgLSBUaGUgZXJyb3IgbWVzc2FnZS5cbiAgICAgKiBAcGFyYW0gb3B0aW9ucyAtIE9wdGlvbnMgdG8gYmUgZm9yd2FyZGVkIHRvIHRoZSBFcnJvciBjb25zdHJ1Y3Rvci5cbiAgICAgKi9cbiAgICBjb25zdHJ1Y3RvcihtZXNzYWdlPzogc3RyaW5nLCBvcHRpb25zPzogRXJyb3JPcHRpb25zKSB7XG4gICAgICAgIHN1cGVyKG1lc3NhZ2UsIG9wdGlvbnMpO1xuICAgICAgICB0aGlzLm5hbWUgPSBcIlJ1bnRpbWVFcnJvclwiO1xuICAgIH1cbn1cblxuLyoqXG4gKiBHZW5lcmF0ZXMgYSB1bmlxdWUgSUQgdXNpbmcgdGhlIG5hbm9pZCBsaWJyYXJ5LlxuICpcbiAqIEByZXR1cm5zIEEgdW5pcXVlIElEIHRoYXQgZG9lcyBub3QgZXhpc3QgaW4gdGhlIGNhbGxSZXNwb25zZXMgc2V0LlxuICovXG5mdW5jdGlvbiBnZW5lcmF0ZUlEKCk6IHN0cmluZyB7XG4gICAgbGV0IHJlc3VsdDtcbiAgICBkbyB7XG4gICAgICAgIHJlc3VsdCA9IG5hbm9pZCgpO1xuICAgIH0gd2hpbGUgKGNhbGxSZXNwb25zZXMuaGFzKHJlc3VsdCkpO1xuICAgIHJldHVybiByZXN1bHQ7XG59XG5cbi8qKlxuICogQ2FsbCBhIGJvdW5kIG1ldGhvZCBhY2NvcmRpbmcgdG8gdGhlIGdpdmVuIGNhbGwgb3B0aW9ucy5cbiAqXG4gKiBJbiBjYXNlIG9mIGZhaWx1cmUsIHRoZSByZXR1cm5lZCBwcm9taXNlIHdpbGwgcmVqZWN0IHdpdGggYW4gZXhjZXB0aW9uXG4gKiBhbW9uZyBSZWZlcmVuY2VFcnJvciAodW5rbm93biBtZXRob2QpLCBUeXBlRXJyb3IgKHdyb25nIGFyZ3VtZW50IGNvdW50IG9yIHR5cGUpLFxuICoge0BsaW5rIFJ1bnRpbWVFcnJvcn0gKG1ldGhvZCByZXR1cm5lZCBhbiBlcnJvciksIG9yIG90aGVyIChuZXR3b3JrIG9yIGludGVybmFsIGVycm9ycykuXG4gKiBUaGUgZXhjZXB0aW9uIG1pZ2h0IGhhdmUgYSBcImNhdXNlXCIgZmllbGQgd2l0aCB0aGUgdmFsdWUgcmV0dXJuZWRcbiAqIGJ5IHRoZSBhcHBsaWNhdGlvbi0gb3Igc2VydmljZS1sZXZlbCBlcnJvciBtYXJzaGFsaW5nIGZ1bmN0aW9ucy5cbiAqXG4gKiBAcGFyYW0gb3B0aW9ucyAtIEEgbWV0aG9kIGNhbGwgZGVzY3JpcHRvci5cbiAqIEByZXR1cm5zIFRoZSByZXN1bHQgb2YgdGhlIGNhbGwuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBDYWxsKG9wdGlvbnM6IENhbGxPcHRpb25zKTogQ2FuY2VsbGFibGVQcm9taXNlPGFueT4ge1xuICAgIGNvbnN0IGlkID0gZ2VuZXJhdGVJRCgpO1xuXG4gICAgY29uc3QgcmVzdWx0ID0gQ2FuY2VsbGFibGVQcm9taXNlLndpdGhSZXNvbHZlcnM8YW55PigpO1xuICAgIGNhbGxSZXNwb25zZXMuc2V0KGlkLCB7IHJlc29sdmU6IHJlc3VsdC5yZXNvbHZlLCByZWplY3Q6IHJlc3VsdC5yZWplY3QgfSk7XG5cbiAgICBjb25zdCByZXF1ZXN0ID0gY2FsbChDYWxsQmluZGluZywgT2JqZWN0LmFzc2lnbih7IFwiY2FsbC1pZFwiOiBpZCB9LCBvcHRpb25zKSk7XG4gICAgbGV0IHJ1bm5pbmcgPSB0cnVlO1xuXG4gICAgcmVxdWVzdC50aGVuKChyZXMpID0+IHtcbiAgICAgICAgcnVubmluZyA9IGZhbHNlO1xuICAgICAgICBjYWxsUmVzcG9uc2VzLmRlbGV0ZShpZCk7XG4gICAgICAgIHJlc3VsdC5yZXNvbHZlKHJlcyk7XG4gICAgfSwgKGVycikgPT4ge1xuICAgICAgICBydW5uaW5nID0gZmFsc2U7XG4gICAgICAgIGNhbGxSZXNwb25zZXMuZGVsZXRlKGlkKTtcbiAgICAgICAgcmVzdWx0LnJlamVjdChlcnIpO1xuICAgIH0pO1xuXG4gICAgY29uc3QgY2FuY2VsID0gKCkgPT4ge1xuICAgICAgICBjYWxsUmVzcG9uc2VzLmRlbGV0ZShpZCk7XG4gICAgICAgIHJldHVybiBjYW5jZWxDYWxsKENhbmNlbE1ldGhvZCwge1wiY2FsbC1pZFwiOiBpZH0pLmNhdGNoKChlcnIpID0+IHtcbiAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoXCJFcnJvciB3aGlsZSByZXF1ZXN0aW5nIGJpbmRpbmcgY2FsbCBjYW5jZWxsYXRpb246XCIsIGVycik7XG4gICAgICAgIH0pO1xuICAgIH07XG5cbiAgICByZXN1bHQub25jYW5jZWxsZWQgPSAoKSA9PiB7XG4gICAgICAgIGlmIChydW5uaW5nKSB7XG4gICAgICAgICAgICByZXR1cm4gY2FuY2VsKCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gcmVxdWVzdC50aGVuKGNhbmNlbCk7XG4gICAgICAgIH1cbiAgICB9O1xuXG4gICAgcmV0dXJuIHJlc3VsdC5wcm9taXNlO1xufVxuXG4vKipcbiAqIENhbGxzIGEgYm91bmQgbWV0aG9kIGJ5IG5hbWUgd2l0aCB0aGUgc3BlY2lmaWVkIGFyZ3VtZW50cy5cbiAqIFNlZSB7QGxpbmsgQ2FsbH0gZm9yIGRldGFpbHMuXG4gKlxuICogQHBhcmFtIG1ldGhvZE5hbWUgLSBUaGUgbmFtZSBvZiB0aGUgbWV0aG9kIGluIHRoZSBmb3JtYXQgJ3BhY2thZ2Uuc3RydWN0Lm1ldGhvZCcuXG4gKiBAcGFyYW0gYXJncyAtIFRoZSBhcmd1bWVudHMgdG8gcGFzcyB0byB0aGUgbWV0aG9kLlxuICogQHJldHVybnMgVGhlIHJlc3VsdCBvZiB0aGUgbWV0aG9kIGNhbGwuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBCeU5hbWUobWV0aG9kTmFtZTogc3RyaW5nLCAuLi5hcmdzOiBhbnlbXSk6IENhbmNlbGxhYmxlUHJvbWlzZTxhbnk+IHtcbiAgICByZXR1cm4gQ2FsbCh7IG1ldGhvZE5hbWUsIGFyZ3MgfSk7XG59XG5cbi8qKlxuICogQ2FsbHMgYSBtZXRob2QgYnkgaXRzIG51bWVyaWMgSUQgd2l0aCB0aGUgc3BlY2lmaWVkIGFyZ3VtZW50cy5cbiAqIFNlZSB7QGxpbmsgQ2FsbH0gZm9yIGRldGFpbHMuXG4gKlxuICogQHBhcmFtIG1ldGhvZElEIC0gVGhlIElEIG9mIHRoZSBtZXRob2QgdG8gY2FsbC5cbiAqIEBwYXJhbSBhcmdzIC0gVGhlIGFyZ3VtZW50cyB0byBwYXNzIHRvIHRoZSBtZXRob2QuXG4gKiBAcmV0dXJuIFRoZSByZXN1bHQgb2YgdGhlIG1ldGhvZCBjYWxsLlxuICovXG5leHBvcnQgZnVuY3Rpb24gQnlJRChtZXRob2RJRDogbnVtYmVyLCAuLi5hcmdzOiBhbnlbXSk6IENhbmNlbGxhYmxlUHJvbWlzZTxhbnk+IHtcbiAgICByZXR1cm4gQ2FsbCh7IG1ldGhvZElELCBhcmdzIH0pO1xufVxuIiwgIi8vIFNvdXJjZTogaHR0cHM6Ly9naXRodWIuY29tL2luc3BlY3QtanMvaXMtY2FsbGFibGVcblxuLy8gVGhlIE1JVCBMaWNlbnNlIChNSVQpXG4vL1xuLy8gQ29weXJpZ2h0IChjKSAyMDE1IEpvcmRhbiBIYXJiYW5kXG4vL1xuLy8gUGVybWlzc2lvbiBpcyBoZXJlYnkgZ3JhbnRlZCwgZnJlZSBvZiBjaGFyZ2UsIHRvIGFueSBwZXJzb24gb2J0YWluaW5nIGEgY29weVxuLy8gb2YgdGhpcyBzb2Z0d2FyZSBhbmQgYXNzb2NpYXRlZCBkb2N1bWVudGF0aW9uIGZpbGVzICh0aGUgXCJTb2Z0d2FyZVwiKSwgdG8gZGVhbFxuLy8gaW4gdGhlIFNvZnR3YXJlIHdpdGhvdXQgcmVzdHJpY3Rpb24sIGluY2x1ZGluZyB3aXRob3V0IGxpbWl0YXRpb24gdGhlIHJpZ2h0c1xuLy8gdG8gdXNlLCBjb3B5LCBtb2RpZnksIG1lcmdlLCBwdWJsaXNoLCBkaXN0cmlidXRlLCBzdWJsaWNlbnNlLCBhbmQvb3Igc2VsbFxuLy8gY29waWVzIG9mIHRoZSBTb2Z0d2FyZSwgYW5kIHRvIHBlcm1pdCBwZXJzb25zIHRvIHdob20gdGhlIFNvZnR3YXJlIGlzXG4vLyBmdXJuaXNoZWQgdG8gZG8gc28sIHN1YmplY3QgdG8gdGhlIGZvbGxvd2luZyBjb25kaXRpb25zOlxuLy9cbi8vIFRoZSBhYm92ZSBjb3B5cmlnaHQgbm90aWNlIGFuZCB0aGlzIHBlcm1pc3Npb24gbm90aWNlIHNoYWxsIGJlIGluY2x1ZGVkIGluIGFsbFxuLy8gY29waWVzIG9yIHN1YnN0YW50aWFsIHBvcnRpb25zIG9mIHRoZSBTb2Z0d2FyZS5cbi8vXG4vLyBUSEUgU09GVFdBUkUgSVMgUFJPVklERUQgXCJBUyBJU1wiLCBXSVRIT1VUIFdBUlJBTlRZIE9GIEFOWSBLSU5ELCBFWFBSRVNTIE9SXG4vLyBJTVBMSUVELCBJTkNMVURJTkcgQlVUIE5PVCBMSU1JVEVEIFRPIFRIRSBXQVJSQU5USUVTIE9GIE1FUkNIQU5UQUJJTElUWSxcbi8vIEZJVE5FU1MgRk9SIEEgUEFSVElDVUxBUiBQVVJQT1NFIEFORCBOT05JTkZSSU5HRU1FTlQuIElOIE5PIEVWRU5UIFNIQUxMIFRIRVxuLy8gQVVUSE9SUyBPUiBDT1BZUklHSFQgSE9MREVSUyBCRSBMSUFCTEUgRk9SIEFOWSBDTEFJTSwgREFNQUdFUyBPUiBPVEhFUlxuLy8gTElBQklMSVRZLCBXSEVUSEVSIElOIEFOIEFDVElPTiBPRiBDT05UUkFDVCwgVE9SVCBPUiBPVEhFUldJU0UsIEFSSVNJTkcgRlJPTSxcbi8vIE9VVCBPRiBPUiBJTiBDT05ORUNUSU9OIFdJVEggVEhFIFNPRlRXQVJFIE9SIFRIRSBVU0UgT1IgT1RIRVIgREVBTElOR1MgSU4gVEhFXG4vLyBTT0ZUV0FSRS5cblxudmFyIGZuVG9TdHIgPSBGdW5jdGlvbi5wcm90b3R5cGUudG9TdHJpbmc7XG52YXIgcmVmbGVjdEFwcGx5OiB0eXBlb2YgUmVmbGVjdC5hcHBseSB8IGZhbHNlIHwgbnVsbCA9IHR5cGVvZiBSZWZsZWN0ID09PSAnb2JqZWN0JyAmJiBSZWZsZWN0ICE9PSBudWxsICYmIFJlZmxlY3QuYXBwbHk7XG52YXIgYmFkQXJyYXlMaWtlOiBhbnk7XG52YXIgaXNDYWxsYWJsZU1hcmtlcjogYW55O1xuaWYgKHR5cGVvZiByZWZsZWN0QXBwbHkgPT09ICdmdW5jdGlvbicgJiYgdHlwZW9mIE9iamVjdC5kZWZpbmVQcm9wZXJ0eSA9PT0gJ2Z1bmN0aW9uJykge1xuICAgIHRyeSB7XG4gICAgICAgIGJhZEFycmF5TGlrZSA9IE9iamVjdC5kZWZpbmVQcm9wZXJ0eSh7fSwgJ2xlbmd0aCcsIHtcbiAgICAgICAgICAgIGdldDogZnVuY3Rpb24gKCkge1xuICAgICAgICAgICAgICAgIHRocm93IGlzQ2FsbGFibGVNYXJrZXI7XG4gICAgICAgICAgICB9XG4gICAgICAgIH0pO1xuICAgICAgICBpc0NhbGxhYmxlTWFya2VyID0ge307XG4gICAgICAgIC8vIGVzbGludC1kaXNhYmxlLW5leHQtbGluZSBuby10aHJvdy1saXRlcmFsXG4gICAgICAgIHJlZmxlY3RBcHBseShmdW5jdGlvbiAoKSB7IHRocm93IDQyOyB9LCBudWxsLCBiYWRBcnJheUxpa2UpO1xuICAgIH0gY2F0Y2ggKF8pIHtcbiAgICAgICAgaWYgKF8gIT09IGlzQ2FsbGFibGVNYXJrZXIpIHtcbiAgICAgICAgICAgIHJlZmxlY3RBcHBseSA9IG51bGw7XG4gICAgICAgIH1cbiAgICB9XG59IGVsc2Uge1xuICAgIHJlZmxlY3RBcHBseSA9IG51bGw7XG59XG5cbnZhciBjb25zdHJ1Y3RvclJlZ2V4ID0gL15cXHMqY2xhc3NcXGIvO1xudmFyIGlzRVM2Q2xhc3NGbiA9IGZ1bmN0aW9uIGlzRVM2Q2xhc3NGdW5jdGlvbih2YWx1ZTogYW55KTogYm9vbGVhbiB7XG4gICAgdHJ5IHtcbiAgICAgICAgdmFyIGZuU3RyID0gZm5Ub1N0ci5jYWxsKHZhbHVlKTtcbiAgICAgICAgcmV0dXJuIGNvbnN0cnVjdG9yUmVnZXgudGVzdChmblN0cik7XG4gICAgfSBjYXRjaCAoZSkge1xuICAgICAgICByZXR1cm4gZmFsc2U7IC8vIG5vdCBhIGZ1bmN0aW9uXG4gICAgfVxufTtcblxudmFyIHRyeUZ1bmN0aW9uT2JqZWN0ID0gZnVuY3Rpb24gdHJ5RnVuY3Rpb25Ub1N0cih2YWx1ZTogYW55KTogYm9vbGVhbiB7XG4gICAgdHJ5IHtcbiAgICAgICAgaWYgKGlzRVM2Q2xhc3NGbih2YWx1ZSkpIHsgcmV0dXJuIGZhbHNlOyB9XG4gICAgICAgIGZuVG9TdHIuY2FsbCh2YWx1ZSk7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgIH0gY2F0Y2ggKGUpIHtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cbn07XG52YXIgdG9TdHIgPSBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nO1xudmFyIG9iamVjdENsYXNzID0gJ1tvYmplY3QgT2JqZWN0XSc7XG52YXIgZm5DbGFzcyA9ICdbb2JqZWN0IEZ1bmN0aW9uXSc7XG52YXIgZ2VuQ2xhc3MgPSAnW29iamVjdCBHZW5lcmF0b3JGdW5jdGlvbl0nO1xudmFyIGRkYUNsYXNzID0gJ1tvYmplY3QgSFRNTEFsbENvbGxlY3Rpb25dJzsgLy8gSUUgMTFcbnZhciBkZGFDbGFzczIgPSAnW29iamVjdCBIVE1MIGRvY3VtZW50LmFsbCBjbGFzc10nO1xudmFyIGRkYUNsYXNzMyA9ICdbb2JqZWN0IEhUTUxDb2xsZWN0aW9uXSc7IC8vIElFIDktMTBcbnZhciBoYXNUb1N0cmluZ1RhZyA9IHR5cGVvZiBTeW1ib2wgPT09ICdmdW5jdGlvbicgJiYgISFTeW1ib2wudG9TdHJpbmdUYWc7IC8vIGJldHRlcjogdXNlIGBoYXMtdG9zdHJpbmd0YWdgXG5cbnZhciBpc0lFNjggPSAhKDAgaW4gWyxdKTsgLy8gZXNsaW50LWRpc2FibGUtbGluZSBuby1zcGFyc2UtYXJyYXlzLCBjb21tYS1zcGFjaW5nXG5cbnZhciBpc0REQTogKHZhbHVlOiBhbnkpID0+IGJvb2xlYW4gPSBmdW5jdGlvbiBpc0RvY3VtZW50RG90QWxsKCkgeyByZXR1cm4gZmFsc2U7IH07XG5pZiAodHlwZW9mIGRvY3VtZW50ID09PSAnb2JqZWN0Jykge1xuICAgIC8vIEZpcmVmb3ggMyBjYW5vbmljYWxpemVzIEREQSB0byB1bmRlZmluZWQgd2hlbiBpdCdzIG5vdCBhY2Nlc3NlZCBkaXJlY3RseVxuICAgIHZhciBhbGwgPSBkb2N1bWVudC5hbGw7XG4gICAgaWYgKHRvU3RyLmNhbGwoYWxsKSA9PT0gdG9TdHIuY2FsbChkb2N1bWVudC5hbGwpKSB7XG4gICAgICAgIGlzRERBID0gZnVuY3Rpb24gaXNEb2N1bWVudERvdEFsbCh2YWx1ZSkge1xuICAgICAgICAgICAgLyogZ2xvYmFscyBkb2N1bWVudDogZmFsc2UgKi9cbiAgICAgICAgICAgIC8vIGluIElFIDYtOCwgdHlwZW9mIGRvY3VtZW50LmFsbCBpcyBcIm9iamVjdFwiIGFuZCBpdCdzIHRydXRoeVxuICAgICAgICAgICAgaWYgKChpc0lFNjggfHwgIXZhbHVlKSAmJiAodHlwZW9mIHZhbHVlID09PSAndW5kZWZpbmVkJyB8fCB0eXBlb2YgdmFsdWUgPT09ICdvYmplY3QnKSkge1xuICAgICAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgICAgIHZhciBzdHIgPSB0b1N0ci5jYWxsKHZhbHVlKTtcbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuIChcbiAgICAgICAgICAgICAgICAgICAgICAgIHN0ciA9PT0gZGRhQ2xhc3NcbiAgICAgICAgICAgICAgICAgICAgICAgIHx8IHN0ciA9PT0gZGRhQ2xhc3MyXG4gICAgICAgICAgICAgICAgICAgICAgICB8fCBzdHIgPT09IGRkYUNsYXNzMyAvLyBvcGVyYSAxMi4xNlxuICAgICAgICAgICAgICAgICAgICAgICAgfHwgc3RyID09PSBvYmplY3RDbGFzcyAvLyBJRSA2LThcbiAgICAgICAgICAgICAgICAgICAgKSAmJiB2YWx1ZSgnJykgPT0gbnVsbDsgLy8gZXNsaW50LWRpc2FibGUtbGluZSBlcWVxZXFcbiAgICAgICAgICAgICAgICB9IGNhdGNoIChlKSB7IC8qKi8gfVxuICAgICAgICAgICAgfVxuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgICB9O1xuICAgIH1cbn1cblxuZnVuY3Rpb24gaXNDYWxsYWJsZVJlZkFwcGx5PFQ+KHZhbHVlOiBUIHwgdW5rbm93bik6IHZhbHVlIGlzICguLi5hcmdzOiBhbnlbXSkgPT4gYW55ICB7XG4gICAgaWYgKGlzRERBKHZhbHVlKSkgeyByZXR1cm4gdHJ1ZTsgfVxuICAgIGlmICghdmFsdWUpIHsgcmV0dXJuIGZhbHNlOyB9XG4gICAgaWYgKHR5cGVvZiB2YWx1ZSAhPT0gJ2Z1bmN0aW9uJyAmJiB0eXBlb2YgdmFsdWUgIT09ICdvYmplY3QnKSB7IHJldHVybiBmYWxzZTsgfVxuICAgIHRyeSB7XG4gICAgICAgIChyZWZsZWN0QXBwbHkgYXMgYW55KSh2YWx1ZSwgbnVsbCwgYmFkQXJyYXlMaWtlKTtcbiAgICB9IGNhdGNoIChlKSB7XG4gICAgICAgIGlmIChlICE9PSBpc0NhbGxhYmxlTWFya2VyKSB7IHJldHVybiBmYWxzZTsgfVxuICAgIH1cbiAgICByZXR1cm4gIWlzRVM2Q2xhc3NGbih2YWx1ZSkgJiYgdHJ5RnVuY3Rpb25PYmplY3QodmFsdWUpO1xufVxuXG5mdW5jdGlvbiBpc0NhbGxhYmxlTm9SZWZBcHBseTxUPih2YWx1ZTogVCB8IHVua25vd24pOiB2YWx1ZSBpcyAoLi4uYXJnczogYW55W10pID0+IGFueSB7XG4gICAgaWYgKGlzRERBKHZhbHVlKSkgeyByZXR1cm4gdHJ1ZTsgfVxuICAgIGlmICghdmFsdWUpIHsgcmV0dXJuIGZhbHNlOyB9XG4gICAgaWYgKHR5cGVvZiB2YWx1ZSAhPT0gJ2Z1bmN0aW9uJyAmJiB0eXBlb2YgdmFsdWUgIT09ICdvYmplY3QnKSB7IHJldHVybiBmYWxzZTsgfVxuICAgIGlmIChoYXNUb1N0cmluZ1RhZykgeyByZXR1cm4gdHJ5RnVuY3Rpb25PYmplY3QodmFsdWUpOyB9XG4gICAgaWYgKGlzRVM2Q2xhc3NGbih2YWx1ZSkpIHsgcmV0dXJuIGZhbHNlOyB9XG4gICAgdmFyIHN0ckNsYXNzID0gdG9TdHIuY2FsbCh2YWx1ZSk7XG4gICAgaWYgKHN0ckNsYXNzICE9PSBmbkNsYXNzICYmIHN0ckNsYXNzICE9PSBnZW5DbGFzcyAmJiAhKC9eXFxbb2JqZWN0IEhUTUwvKS50ZXN0KHN0ckNsYXNzKSkgeyByZXR1cm4gZmFsc2U7IH1cbiAgICByZXR1cm4gdHJ5RnVuY3Rpb25PYmplY3QodmFsdWUpO1xufTtcblxuZXhwb3J0IGRlZmF1bHQgcmVmbGVjdEFwcGx5ID8gaXNDYWxsYWJsZVJlZkFwcGx5IDogaXNDYWxsYWJsZU5vUmVmQXBwbHk7XG4iLCAiLypcbiBfXHQgICBfX1x0ICBfIF9fXG58IHxcdCAvIC9fX18gXyhfKSAvX19fX1xufCB8IC98IC8gLyBfXyBgLyAvIC8gX19fL1xufCB8LyB8LyAvIC9fLyAvIC8gKF9fICApXG58X18vfF9fL1xcX18sXy9fL18vX19fXy9cblRoZSBlbGVjdHJvbiBhbHRlcm5hdGl2ZSBmb3IgR29cbihjKSBMZWEgQW50aG9ueSAyMDE5LXByZXNlbnRcbiovXG5cbmltcG9ydCBpc0NhbGxhYmxlIGZyb20gXCIuL2NhbGxhYmxlLmpzXCI7XG5cbi8qKlxuICogRXhjZXB0aW9uIGNsYXNzIHRoYXQgd2lsbCBiZSB1c2VkIGFzIHJlamVjdGlvbiByZWFzb25cbiAqIGluIGNhc2UgYSB7QGxpbmsgQ2FuY2VsbGFibGVQcm9taXNlfSBpcyBjYW5jZWxsZWQgc3VjY2Vzc2Z1bGx5LlxuICpcbiAqIFRoZSB2YWx1ZSBvZiB0aGUge0BsaW5rIG5hbWV9IHByb3BlcnR5IGlzIHRoZSBzdHJpbmcgYFwiQ2FuY2VsRXJyb3JcImAuXG4gKiBUaGUgdmFsdWUgb2YgdGhlIHtAbGluayBjYXVzZX0gcHJvcGVydHkgaXMgdGhlIGNhdXNlIHBhc3NlZCB0byB0aGUgY2FuY2VsIG1ldGhvZCwgaWYgYW55LlxuICovXG5leHBvcnQgY2xhc3MgQ2FuY2VsRXJyb3IgZXh0ZW5kcyBFcnJvciB7XG4gICAgLyoqXG4gICAgICogQ29uc3RydWN0cyBhIG5ldyBgQ2FuY2VsRXJyb3JgIGluc3RhbmNlLlxuICAgICAqIEBwYXJhbSBtZXNzYWdlIC0gVGhlIGVycm9yIG1lc3NhZ2UuXG4gICAgICogQHBhcmFtIG9wdGlvbnMgLSBPcHRpb25zIHRvIGJlIGZvcndhcmRlZCB0byB0aGUgRXJyb3IgY29uc3RydWN0b3IuXG4gICAgICovXG4gICAgY29uc3RydWN0b3IobWVzc2FnZT86IHN0cmluZywgb3B0aW9ucz86IEVycm9yT3B0aW9ucykge1xuICAgICAgICBzdXBlcihtZXNzYWdlLCBvcHRpb25zKTtcbiAgICAgICAgdGhpcy5uYW1lID0gXCJDYW5jZWxFcnJvclwiO1xuICAgIH1cbn1cblxuLyoqXG4gKiBFeGNlcHRpb24gY2xhc3MgdGhhdCB3aWxsIGJlIHJlcG9ydGVkIGFzIGFuIHVuaGFuZGxlZCByZWplY3Rpb25cbiAqIGluIGNhc2UgYSB7QGxpbmsgQ2FuY2VsbGFibGVQcm9taXNlfSByZWplY3RzIGFmdGVyIGJlaW5nIGNhbmNlbGxlZCxcbiAqIG9yIHdoZW4gdGhlIGBvbmNhbmNlbGxlZGAgY2FsbGJhY2sgdGhyb3dzIG9yIHJlamVjdHMuXG4gKlxuICogVGhlIHZhbHVlIG9mIHRoZSB7QGxpbmsgbmFtZX0gcHJvcGVydHkgaXMgdGhlIHN0cmluZyBgXCJDYW5jZWxsZWRSZWplY3Rpb25FcnJvclwiYC5cbiAqIFRoZSB2YWx1ZSBvZiB0aGUge0BsaW5rIGNhdXNlfSBwcm9wZXJ0eSBpcyB0aGUgcmVhc29uIHRoZSBwcm9taXNlIHJlamVjdGVkIHdpdGguXG4gKlxuICogQmVjYXVzZSB0aGUgb3JpZ2luYWwgcHJvbWlzZSB3YXMgY2FuY2VsbGVkLFxuICogYSB3cmFwcGVyIHByb21pc2Ugd2lsbCBiZSBwYXNzZWQgdG8gdGhlIHVuaGFuZGxlZCByZWplY3Rpb24gbGlzdGVuZXIgaW5zdGVhZC5cbiAqIFRoZSB7QGxpbmsgcHJvbWlzZX0gcHJvcGVydHkgaG9sZHMgYSByZWZlcmVuY2UgdG8gdGhlIG9yaWdpbmFsIHByb21pc2UuXG4gKi9cbmV4cG9ydCBjbGFzcyBDYW5jZWxsZWRSZWplY3Rpb25FcnJvciBleHRlbmRzIEVycm9yIHtcbiAgICAvKipcbiAgICAgKiBIb2xkcyBhIHJlZmVyZW5jZSB0byB0aGUgcHJvbWlzZSB0aGF0IHdhcyBjYW5jZWxsZWQgYW5kIHRoZW4gcmVqZWN0ZWQuXG4gICAgICovXG4gICAgcHJvbWlzZTogQ2FuY2VsbGFibGVQcm9taXNlPHVua25vd24+O1xuXG4gICAgLyoqXG4gICAgICogQ29uc3RydWN0cyBhIG5ldyBgQ2FuY2VsbGVkUmVqZWN0aW9uRXJyb3JgIGluc3RhbmNlLlxuICAgICAqIEBwYXJhbSBwcm9taXNlIC0gVGhlIHByb21pc2UgdGhhdCBjYXVzZWQgdGhlIGVycm9yIG9yaWdpbmFsbHkuXG4gICAgICogQHBhcmFtIHJlYXNvbiAtIFRoZSByZWplY3Rpb24gcmVhc29uLlxuICAgICAqIEBwYXJhbSBpbmZvIC0gQW4gb3B0aW9uYWwgaW5mb3JtYXRpdmUgbWVzc2FnZSBzcGVjaWZ5aW5nIHRoZSBjaXJjdW1zdGFuY2VzIGluIHdoaWNoIHRoZSBlcnJvciB3YXMgdGhyb3duLlxuICAgICAqICAgICAgICAgICAgICAgRGVmYXVsdHMgdG8gdGhlIHN0cmluZyBgXCJVbmhhbmRsZWQgcmVqZWN0aW9uIGluIGNhbmNlbGxlZCBwcm9taXNlLlwiYC5cbiAgICAgKi9cbiAgICBjb25zdHJ1Y3Rvcihwcm9taXNlOiBDYW5jZWxsYWJsZVByb21pc2U8dW5rbm93bj4sIHJlYXNvbj86IGFueSwgaW5mbz86IHN0cmluZykge1xuICAgICAgICBzdXBlcigoaW5mbyA/PyBcIlVuaGFuZGxlZCByZWplY3Rpb24gaW4gY2FuY2VsbGVkIHByb21pc2UuXCIpICsgXCIgUmVhc29uOiBcIiArIGVycm9yTWVzc2FnZShyZWFzb24pLCB7IGNhdXNlOiByZWFzb24gfSk7XG4gICAgICAgIHRoaXMucHJvbWlzZSA9IHByb21pc2U7XG4gICAgICAgIHRoaXMubmFtZSA9IFwiQ2FuY2VsbGVkUmVqZWN0aW9uRXJyb3JcIjtcbiAgICB9XG59XG5cbnR5cGUgQ2FuY2VsbGFibGVQcm9taXNlUmVzb2x2ZXI8VD4gPSAodmFsdWU6IFQgfCBQcm9taXNlTGlrZTxUPiB8IENhbmNlbGxhYmxlUHJvbWlzZUxpa2U8VD4pID0+IHZvaWQ7XG50eXBlIENhbmNlbGxhYmxlUHJvbWlzZVJlamVjdG9yID0gKHJlYXNvbj86IGFueSkgPT4gdm9pZDtcbnR5cGUgQ2FuY2VsbGFibGVQcm9taXNlQ2FuY2VsbGVyID0gKGNhdXNlPzogYW55KSA9PiB2b2lkIHwgUHJvbWlzZUxpa2U8dm9pZD47XG50eXBlIENhbmNlbGxhYmxlUHJvbWlzZUV4ZWN1dG9yPFQ+ID0gKHJlc29sdmU6IENhbmNlbGxhYmxlUHJvbWlzZVJlc29sdmVyPFQ+LCByZWplY3Q6IENhbmNlbGxhYmxlUHJvbWlzZVJlamVjdG9yKSA9PiB2b2lkO1xuXG5leHBvcnQgaW50ZXJmYWNlIENhbmNlbGxhYmxlUHJvbWlzZUxpa2U8VD4ge1xuICAgIHRoZW48VFJlc3VsdDEgPSBULCBUUmVzdWx0MiA9IG5ldmVyPihvbmZ1bGZpbGxlZD86ICgodmFsdWU6IFQpID0+IFRSZXN1bHQxIHwgUHJvbWlzZUxpa2U8VFJlc3VsdDE+IHwgQ2FuY2VsbGFibGVQcm9taXNlTGlrZTxUUmVzdWx0MT4pIHwgdW5kZWZpbmVkIHwgbnVsbCwgb25yZWplY3RlZD86ICgocmVhc29uOiBhbnkpID0+IFRSZXN1bHQyIHwgUHJvbWlzZUxpa2U8VFJlc3VsdDI+IHwgQ2FuY2VsbGFibGVQcm9taXNlTGlrZTxUUmVzdWx0Mj4pIHwgdW5kZWZpbmVkIHwgbnVsbCk6IENhbmNlbGxhYmxlUHJvbWlzZUxpa2U8VFJlc3VsdDEgfCBUUmVzdWx0Mj47XG4gICAgY2FuY2VsKGNhdXNlPzogYW55KTogdm9pZCB8IFByb21pc2VMaWtlPHZvaWQ+O1xufVxuXG4vKipcbiAqIFdyYXBzIGEgY2FuY2VsbGFibGUgcHJvbWlzZSBhbG9uZyB3aXRoIGl0cyByZXNvbHV0aW9uIG1ldGhvZHMuXG4gKiBUaGUgYG9uY2FuY2VsbGVkYCBmaWVsZCB3aWxsIGJlIG51bGwgaW5pdGlhbGx5IGJ1dCBtYXkgYmUgc2V0IHRvIHByb3ZpZGUgYSBjdXN0b20gY2FuY2VsbGF0aW9uIGZ1bmN0aW9uLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIENhbmNlbGxhYmxlUHJvbWlzZVdpdGhSZXNvbHZlcnM8VD4ge1xuICAgIHByb21pc2U6IENhbmNlbGxhYmxlUHJvbWlzZTxUPjtcbiAgICByZXNvbHZlOiBDYW5jZWxsYWJsZVByb21pc2VSZXNvbHZlcjxUPjtcbiAgICByZWplY3Q6IENhbmNlbGxhYmxlUHJvbWlzZVJlamVjdG9yO1xuICAgIG9uY2FuY2VsbGVkOiBDYW5jZWxsYWJsZVByb21pc2VDYW5jZWxsZXIgfCBudWxsO1xufVxuXG5pbnRlcmZhY2UgQ2FuY2VsbGFibGVQcm9taXNlU3RhdGUge1xuICAgIHJlYWRvbmx5IHJvb3Q6IENhbmNlbGxhYmxlUHJvbWlzZVN0YXRlO1xuICAgIHJlc29sdmluZzogYm9vbGVhbjtcbiAgICBzZXR0bGVkOiBib29sZWFuO1xuICAgIHJlYXNvbj86IENhbmNlbEVycm9yO1xufVxuXG4vLyBQcml2YXRlIGZpZWxkIG5hbWVzLlxuY29uc3QgYmFycmllclN5bSA9IFN5bWJvbChcImJhcnJpZXJcIik7XG5jb25zdCBjYW5jZWxJbXBsU3ltID0gU3ltYm9sKFwiY2FuY2VsSW1wbFwiKTtcbmNvbnN0IHNwZWNpZXM6IHR5cGVvZiBTeW1ib2wuc3BlY2llcyA9IFN5bWJvbC5zcGVjaWVzID8/IFN5bWJvbChcInNwZWNpZXNQb2x5ZmlsbFwiKTtcblxuLyoqXG4gKiBBIHByb21pc2Ugd2l0aCBhbiBhdHRhY2hlZCBtZXRob2QgZm9yIGNhbmNlbGxpbmcgbG9uZy1ydW5uaW5nIG9wZXJhdGlvbnMgKHNlZSB7QGxpbmsgQ2FuY2VsbGFibGVQcm9taXNlI2NhbmNlbH0pLlxuICogQ2FuY2VsbGF0aW9uIGNhbiBvcHRpb25hbGx5IGJlIGJvdW5kIHRvIGFuIHtAbGluayBBYm9ydFNpZ25hbH1cbiAqIGZvciBiZXR0ZXIgY29tcG9zYWJpbGl0eSAoc2VlIHtAbGluayBDYW5jZWxsYWJsZVByb21pc2UjY2FuY2VsT259KS5cbiAqXG4gKiBDYW5jZWxsaW5nIGEgcGVuZGluZyBwcm9taXNlIHdpbGwgcmVzdWx0IGluIGFuIGltbWVkaWF0ZSByZWplY3Rpb25cbiAqIHdpdGggYW4gaW5zdGFuY2Ugb2Yge0BsaW5rIENhbmNlbEVycm9yfSBhcyByZWFzb24sXG4gKiBidXQgd2hvZXZlciBzdGFydGVkIHRoZSBwcm9taXNlIHdpbGwgYmUgcmVzcG9uc2libGVcbiAqIGZvciBhY3R1YWxseSBhYm9ydGluZyB0aGUgdW5kZXJseWluZyBvcGVyYXRpb24uXG4gKiBUbyB0aGlzIHB1cnBvc2UsIHRoZSBjb25zdHJ1Y3RvciBhbmQgYWxsIGNoYWluaW5nIG1ldGhvZHNcbiAqIGFjY2VwdCBvcHRpb25hbCBjYW5jZWxsYXRpb24gY2FsbGJhY2tzLlxuICpcbiAqIElmIGEgYENhbmNlbGxhYmxlUHJvbWlzZWAgc3RpbGwgcmVzb2x2ZXMgYWZ0ZXIgaGF2aW5nIGJlZW4gY2FuY2VsbGVkLFxuICogdGhlIHJlc3VsdCB3aWxsIGJlIGRpc2NhcmRlZC4gSWYgaXQgcmVqZWN0cywgdGhlIHJlYXNvblxuICogd2lsbCBiZSByZXBvcnRlZCBhcyBhbiB1bmhhbmRsZWQgcmVqZWN0aW9uLFxuICogd3JhcHBlZCBpbiBhIHtAbGluayBDYW5jZWxsZWRSZWplY3Rpb25FcnJvcn0gaW5zdGFuY2UuXG4gKiBUbyBmYWNpbGl0YXRlIHRoZSBoYW5kbGluZyBvZiBjYW5jZWxsYXRpb24gcmVxdWVzdHMsXG4gKiBjYW5jZWxsZWQgYENhbmNlbGxhYmxlUHJvbWlzZWBzIHdpbGwgX25vdF8gcmVwb3J0IHVuaGFuZGxlZCBgQ2FuY2VsRXJyb3Jgc1xuICogd2hvc2UgYGNhdXNlYCBmaWVsZCBpcyB0aGUgc2FtZSBhcyB0aGUgb25lIHdpdGggd2hpY2ggdGhlIGN1cnJlbnQgcHJvbWlzZSB3YXMgY2FuY2VsbGVkLlxuICpcbiAqIEFsbCB1c3VhbCBwcm9taXNlIG1ldGhvZHMgYXJlIGRlZmluZWQgYW5kIHJldHVybiBhIGBDYW5jZWxsYWJsZVByb21pc2VgXG4gKiB3aG9zZSBjYW5jZWwgbWV0aG9kIHdpbGwgY2FuY2VsIHRoZSBwYXJlbnQgb3BlcmF0aW9uIGFzIHdlbGwsIHByb3BhZ2F0aW5nIHRoZSBjYW5jZWxsYXRpb24gcmVhc29uXG4gKiB1cHdhcmRzIHRocm91Z2ggcHJvbWlzZSBjaGFpbnMuXG4gKiBDb252ZXJzZWx5LCBjYW5jZWxsaW5nIGEgcHJvbWlzZSB3aWxsIG5vdCBhdXRvbWF0aWNhbGx5IGNhbmNlbCBkZXBlbmRlbnQgcHJvbWlzZXMgZG93bnN0cmVhbTpcbiAqIGBgYHRzXG4gKiBsZXQgcm9vdCA9IG5ldyBDYW5jZWxsYWJsZVByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4geyAuLi4gfSk7XG4gKiBsZXQgY2hpbGQxID0gcm9vdC50aGVuKCgpID0+IHsgLi4uIH0pO1xuICogbGV0IGNoaWxkMiA9IGNoaWxkMS50aGVuKCgpID0+IHsgLi4uIH0pO1xuICogbGV0IGNoaWxkMyA9IHJvb3QuY2F0Y2goKCkgPT4geyAuLi4gfSk7XG4gKiBjaGlsZDEuY2FuY2VsKCk7IC8vIENhbmNlbHMgY2hpbGQxIGFuZCByb290LCBidXQgbm90IGNoaWxkMiBvciBjaGlsZDNcbiAqIGBgYFxuICogQ2FuY2VsbGluZyBhIHByb21pc2UgdGhhdCBoYXMgYWxyZWFkeSBzZXR0bGVkIGlzIHNhZmUgYW5kIGhhcyBubyBjb25zZXF1ZW5jZS5cbiAqXG4gKiBUaGUgYGNhbmNlbGAgbWV0aG9kIHJldHVybnMgYSBwcm9taXNlIHRoYXQgX2Fsd2F5cyBmdWxmaWxsc19cbiAqIGFmdGVyIHRoZSB3aG9sZSBjaGFpbiBoYXMgcHJvY2Vzc2VkIHRoZSBjYW5jZWwgcmVxdWVzdFxuICogYW5kIGFsbCBhdHRhY2hlZCBjYWxsYmFja3MgdXAgdG8gdGhhdCBtb21lbnQgaGF2ZSBydW4uXG4gKlxuICogQWxsIEVTMjAyNCBwcm9taXNlIG1ldGhvZHMgKHN0YXRpYyBhbmQgaW5zdGFuY2UpIGFyZSBkZWZpbmVkIG9uIENhbmNlbGxhYmxlUHJvbWlzZSxcbiAqIGJ1dCBhY3R1YWwgYXZhaWxhYmlsaXR5IG1heSB2YXJ5IHdpdGggT1Mvd2VidmlldyB2ZXJzaW9uLlxuICpcbiAqIEluIGxpbmUgd2l0aCB0aGUgcHJvcG9zYWwgYXQgaHR0cHM6Ly9naXRodWIuY29tL3RjMzkvcHJvcG9zYWwtcm0tYnVpbHRpbi1zdWJjbGFzc2luZyxcbiAqIGBDYW5jZWxsYWJsZVByb21pc2VgIGRvZXMgbm90IHN1cHBvcnQgdHJhbnNwYXJlbnQgc3ViY2xhc3NpbmcuXG4gKiBFeHRlbmRlcnMgc2hvdWxkIHRha2UgY2FyZSB0byBwcm92aWRlIHRoZWlyIG93biBtZXRob2QgaW1wbGVtZW50YXRpb25zLlxuICogVGhpcyBtaWdodCBiZSByZWNvbnNpZGVyZWQgaW4gY2FzZSB0aGUgcHJvcG9zYWwgaXMgcmV0aXJlZC5cbiAqXG4gKiBDYW5jZWxsYWJsZVByb21pc2UgaXMgYSB3cmFwcGVyIGFyb3VuZCB0aGUgRE9NIFByb21pc2Ugb2JqZWN0XG4gKiBhbmQgaXMgY29tcGxpYW50IHdpdGggdGhlIFtQcm9taXNlcy9BKyBzcGVjaWZpY2F0aW9uXShodHRwczovL3Byb21pc2VzYXBsdXMuY29tLylcbiAqIChpdCBwYXNzZXMgdGhlIFtjb21wbGlhbmNlIHN1aXRlXShodHRwczovL2dpdGh1Yi5jb20vcHJvbWlzZXMtYXBsdXMvcHJvbWlzZXMtdGVzdHMpKVxuICogaWYgc28gaXMgdGhlIHVuZGVybHlpbmcgaW1wbGVtZW50YXRpb24uXG4gKi9cbmV4cG9ydCBjbGFzcyBDYW5jZWxsYWJsZVByb21pc2U8VD4gZXh0ZW5kcyBQcm9taXNlPFQ+IGltcGxlbWVudHMgUHJvbWlzZUxpa2U8VD4sIENhbmNlbGxhYmxlUHJvbWlzZUxpa2U8VD4ge1xuICAgIC8vIFByaXZhdGUgZmllbGRzLlxuICAgIC8qKiBAaW50ZXJuYWwgKi9cbiAgICBwcml2YXRlIFtiYXJyaWVyU3ltXSE6IFBhcnRpYWw8UHJvbWlzZVdpdGhSZXNvbHZlcnM8dm9pZD4+IHwgbnVsbDtcbiAgICAvKiogQGludGVybmFsICovXG4gICAgcHJpdmF0ZSByZWFkb25seSBbY2FuY2VsSW1wbFN5bV0hOiAocmVhc29uOiBDYW5jZWxFcnJvcikgPT4gdm9pZCB8IFByb21pc2VMaWtlPHZvaWQ+O1xuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIG5ldyBgQ2FuY2VsbGFibGVQcm9taXNlYC5cbiAgICAgKlxuICAgICAqIEBwYXJhbSBleGVjdXRvciAtIEEgY2FsbGJhY2sgdXNlZCB0byBpbml0aWFsaXplIHRoZSBwcm9taXNlLiBUaGlzIGNhbGxiYWNrIGlzIHBhc3NlZCB0d28gYXJndW1lbnRzOlxuICAgICAqICAgICAgICAgICAgICAgICAgIGEgYHJlc29sdmVgIGNhbGxiYWNrIHVzZWQgdG8gcmVzb2x2ZSB0aGUgcHJvbWlzZSB3aXRoIGEgdmFsdWVcbiAgICAgKiAgICAgICAgICAgICAgICAgICBvciB0aGUgcmVzdWx0IG9mIGFub3RoZXIgcHJvbWlzZSAocG9zc2libHkgY2FuY2VsbGFibGUpLFxuICAgICAqICAgICAgICAgICAgICAgICAgIGFuZCBhIGByZWplY3RgIGNhbGxiYWNrIHVzZWQgdG8gcmVqZWN0IHRoZSBwcm9taXNlIHdpdGggYSBwcm92aWRlZCByZWFzb24gb3IgZXJyb3IuXG4gICAgICogICAgICAgICAgICAgICAgICAgSWYgdGhlIHZhbHVlIHByb3ZpZGVkIHRvIHRoZSBgcmVzb2x2ZWAgY2FsbGJhY2sgaXMgYSB0aGVuYWJsZSBfYW5kXyBjYW5jZWxsYWJsZSBvYmplY3RcbiAgICAgKiAgICAgICAgICAgICAgICAgICAoaXQgaGFzIGEgYHRoZW5gIF9hbmRfIGEgYGNhbmNlbGAgbWV0aG9kKSxcbiAgICAgKiAgICAgICAgICAgICAgICAgICBjYW5jZWxsYXRpb24gcmVxdWVzdHMgd2lsbCBiZSBmb3J3YXJkZWQgdG8gdGhhdCBvYmplY3QgYW5kIHRoZSBvbmNhbmNlbGxlZCB3aWxsIG5vdCBiZSBpbnZva2VkIGFueW1vcmUuXG4gICAgICogICAgICAgICAgICAgICAgICAgSWYgYW55IG9uZSBvZiB0aGUgdHdvIGNhbGxiYWNrcyBpcyBjYWxsZWQgX2FmdGVyXyB0aGUgcHJvbWlzZSBoYXMgYmVlbiBjYW5jZWxsZWQsXG4gICAgICogICAgICAgICAgICAgICAgICAgdGhlIHByb3ZpZGVkIHZhbHVlcyB3aWxsIGJlIGNhbmNlbGxlZCBhbmQgcmVzb2x2ZWQgYXMgdXN1YWwsXG4gICAgICogICAgICAgICAgICAgICAgICAgYnV0IHRoZWlyIHJlc3VsdHMgd2lsbCBiZSBkaXNjYXJkZWQuXG4gICAgICogICAgICAgICAgICAgICAgICAgSG93ZXZlciwgaWYgdGhlIHJlc29sdXRpb24gcHJvY2VzcyB1bHRpbWF0ZWx5IGVuZHMgdXAgaW4gYSByZWplY3Rpb25cbiAgICAgKiAgICAgICAgICAgICAgICAgICB0aGF0IGlzIG5vdCBkdWUgdG8gY2FuY2VsbGF0aW9uLCB0aGUgcmVqZWN0aW9uIHJlYXNvblxuICAgICAqICAgICAgICAgICAgICAgICAgIHdpbGwgYmUgd3JhcHBlZCBpbiBhIHtAbGluayBDYW5jZWxsZWRSZWplY3Rpb25FcnJvcn1cbiAgICAgKiAgICAgICAgICAgICAgICAgICBhbmQgYnViYmxlZCB1cCBhcyBhbiB1bmhhbmRsZWQgcmVqZWN0aW9uLlxuICAgICAqIEBwYXJhbSBvbmNhbmNlbGxlZCAtIEl0IGlzIHRoZSBjYWxsZXIncyByZXNwb25zaWJpbGl0eSB0byBlbnN1cmUgdGhhdCBhbnkgb3BlcmF0aW9uXG4gICAgICogICAgICAgICAgICAgICAgICAgICAgc3RhcnRlZCBieSB0aGUgZXhlY3V0b3IgaXMgcHJvcGVybHkgaGFsdGVkIHVwb24gY2FuY2VsbGF0aW9uLlxuICAgICAqICAgICAgICAgICAgICAgICAgICAgIFRoaXMgb3B0aW9uYWwgY2FsbGJhY2sgY2FuIGJlIHVzZWQgdG8gdGhhdCBwdXJwb3NlLlxuICAgICAqICAgICAgICAgICAgICAgICAgICAgIEl0IHdpbGwgYmUgY2FsbGVkIF9zeW5jaHJvbm91c2x5XyB3aXRoIGEgY2FuY2VsbGF0aW9uIGNhdXNlXG4gICAgICogICAgICAgICAgICAgICAgICAgICAgd2hlbiBjYW5jZWxsYXRpb24gaXMgcmVxdWVzdGVkLCBfYWZ0ZXJfIHRoZSBwcm9taXNlIGhhcyBhbHJlYWR5IHJlamVjdGVkXG4gICAgICogICAgICAgICAgICAgICAgICAgICAgd2l0aCBhIHtAbGluayBDYW5jZWxFcnJvcn0sIGJ1dCBfYmVmb3JlX1xuICAgICAqICAgICAgICAgICAgICAgICAgICAgIGFueSB7QGxpbmsgdGhlbn0ve0BsaW5rIGNhdGNofS97QGxpbmsgZmluYWxseX0gY2FsbGJhY2sgcnVucy5cbiAgICAgKiAgICAgICAgICAgICAgICAgICAgICBJZiB0aGUgY2FsbGJhY2sgcmV0dXJucyBhIHRoZW5hYmxlLCB0aGUgcHJvbWlzZSByZXR1cm5lZCBmcm9tIHtAbGluayBjYW5jZWx9XG4gICAgICogICAgICAgICAgICAgICAgICAgICAgd2lsbCBvbmx5IGZ1bGZpbGwgYWZ0ZXIgdGhlIGZvcm1lciBoYXMgc2V0dGxlZC5cbiAgICAgKiAgICAgICAgICAgICAgICAgICAgICBVbmhhbmRsZWQgZXhjZXB0aW9ucyBvciByZWplY3Rpb25zIGZyb20gdGhlIGNhbGxiYWNrIHdpbGwgYmUgd3JhcHBlZFxuICAgICAqICAgICAgICAgICAgICAgICAgICAgIGluIGEge0BsaW5rIENhbmNlbGxlZFJlamVjdGlvbkVycm9yfSBhbmQgYnViYmxlZCB1cCBhcyB1bmhhbmRsZWQgcmVqZWN0aW9ucy5cbiAgICAgKiAgICAgICAgICAgICAgICAgICAgICBJZiB0aGUgYHJlc29sdmVgIGNhbGxiYWNrIGlzIGNhbGxlZCBiZWZvcmUgY2FuY2VsbGF0aW9uIHdpdGggYSBjYW5jZWxsYWJsZSBwcm9taXNlLFxuICAgICAqICAgICAgICAgICAgICAgICAgICAgIGNhbmNlbGxhdGlvbiByZXF1ZXN0cyBvbiB0aGlzIHByb21pc2Ugd2lsbCBiZSBkaXZlcnRlZCB0byB0aGF0IHByb21pc2UsXG4gICAgICogICAgICAgICAgICAgICAgICAgICAgYW5kIHRoZSBvcmlnaW5hbCBgb25jYW5jZWxsZWRgIGNhbGxiYWNrIHdpbGwgYmUgZGlzY2FyZGVkLlxuICAgICAqL1xuICAgIGNvbnN0cnVjdG9yKGV4ZWN1dG9yOiBDYW5jZWxsYWJsZVByb21pc2VFeGVjdXRvcjxUPiwgb25jYW5jZWxsZWQ/OiBDYW5jZWxsYWJsZVByb21pc2VDYW5jZWxsZXIpIHtcbiAgICAgICAgbGV0IHJlc29sdmUhOiAodmFsdWU6IFQgfCBQcm9taXNlTGlrZTxUPikgPT4gdm9pZDtcbiAgICAgICAgbGV0IHJlamVjdCE6IChyZWFzb24/OiBhbnkpID0+IHZvaWQ7XG4gICAgICAgIHN1cGVyKChyZXMsIHJlaikgPT4geyByZXNvbHZlID0gcmVzOyByZWplY3QgPSByZWo7IH0pO1xuXG4gICAgICAgIGlmICgodGhpcy5jb25zdHJ1Y3RvciBhcyBhbnkpW3NwZWNpZXNdICE9PSBQcm9taXNlKSB7XG4gICAgICAgICAgICB0aHJvdyBuZXcgVHlwZUVycm9yKFwiQ2FuY2VsbGFibGVQcm9taXNlIGRvZXMgbm90IHN1cHBvcnQgdHJhbnNwYXJlbnQgc3ViY2xhc3NpbmcuIFBsZWFzZSByZWZyYWluIGZyb20gb3ZlcnJpZGluZyB0aGUgW1N5bWJvbC5zcGVjaWVzXSBzdGF0aWMgcHJvcGVydHkuXCIpO1xuICAgICAgICB9XG5cbiAgICAgICAgbGV0IHByb21pc2U6IENhbmNlbGxhYmxlUHJvbWlzZVdpdGhSZXNvbHZlcnM8VD4gPSB7XG4gICAgICAgICAgICBwcm9taXNlOiB0aGlzLFxuICAgICAgICAgICAgcmVzb2x2ZSxcbiAgICAgICAgICAgIHJlamVjdCxcbiAgICAgICAgICAgIGdldCBvbmNhbmNlbGxlZCgpIHsgcmV0dXJuIG9uY2FuY2VsbGVkID8/IG51bGw7IH0sXG4gICAgICAgICAgICBzZXQgb25jYW5jZWxsZWQoY2IpIHsgb25jYW5jZWxsZWQgPSBjYiA/PyB1bmRlZmluZWQ7IH1cbiAgICAgICAgfTtcblxuICAgICAgICBjb25zdCBzdGF0ZTogQ2FuY2VsbGFibGVQcm9taXNlU3RhdGUgPSB7XG4gICAgICAgICAgICBnZXQgcm9vdCgpIHsgcmV0dXJuIHN0YXRlOyB9LFxuICAgICAgICAgICAgcmVzb2x2aW5nOiBmYWxzZSxcbiAgICAgICAgICAgIHNldHRsZWQ6IGZhbHNlXG4gICAgICAgIH07XG5cbiAgICAgICAgLy8gU2V0dXAgY2FuY2VsbGF0aW9uIHN5c3RlbS5cbiAgICAgICAgdm9pZCBPYmplY3QuZGVmaW5lUHJvcGVydGllcyh0aGlzLCB7XG4gICAgICAgICAgICBbYmFycmllclN5bV06IHtcbiAgICAgICAgICAgICAgICBjb25maWd1cmFibGU6IGZhbHNlLFxuICAgICAgICAgICAgICAgIGVudW1lcmFibGU6IGZhbHNlLFxuICAgICAgICAgICAgICAgIHdyaXRhYmxlOiB0cnVlLFxuICAgICAgICAgICAgICAgIHZhbHVlOiBudWxsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgW2NhbmNlbEltcGxTeW1dOiB7XG4gICAgICAgICAgICAgICAgY29uZmlndXJhYmxlOiBmYWxzZSxcbiAgICAgICAgICAgICAgICBlbnVtZXJhYmxlOiBmYWxzZSxcbiAgICAgICAgICAgICAgICB3cml0YWJsZTogZmFsc2UsXG4gICAgICAgICAgICAgICAgdmFsdWU6IGNhbmNlbGxlckZvcihwcm9taXNlLCBzdGF0ZSlcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSk7XG5cbiAgICAgICAgLy8gUnVuIHRoZSBhY3R1YWwgZXhlY3V0b3IuXG4gICAgICAgIGNvbnN0IHJlamVjdG9yID0gcmVqZWN0b3JGb3IocHJvbWlzZSwgc3RhdGUpO1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgZXhlY3V0b3IocmVzb2x2ZXJGb3IocHJvbWlzZSwgc3RhdGUpLCByZWplY3Rvcik7XG4gICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgICAgaWYgKHN0YXRlLnJlc29sdmluZykge1xuICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKFwiVW5oYW5kbGVkIGV4Y2VwdGlvbiBpbiBDYW5jZWxsYWJsZVByb21pc2UgZXhlY3V0b3IuXCIsIGVycik7XG4gICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgIHJlamVjdG9yKGVycik7XG4gICAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDYW5jZWxzIGltbWVkaWF0ZWx5IHRoZSBleGVjdXRpb24gb2YgdGhlIG9wZXJhdGlvbiBhc3NvY2lhdGVkIHdpdGggdGhpcyBwcm9taXNlLlxuICAgICAqIFRoZSBwcm9taXNlIHJlamVjdHMgd2l0aCBhIHtAbGluayBDYW5jZWxFcnJvcn0gaW5zdGFuY2UgYXMgcmVhc29uLFxuICAgICAqIHdpdGggdGhlIHtAbGluayBDYW5jZWxFcnJvciNjYXVzZX0gcHJvcGVydHkgc2V0IHRvIHRoZSBnaXZlbiBhcmd1bWVudCwgaWYgYW55LlxuICAgICAqXG4gICAgICogSGFzIG5vIGVmZmVjdCBpZiBjYWxsZWQgYWZ0ZXIgdGhlIHByb21pc2UgaGFzIGFscmVhZHkgc2V0dGxlZDtcbiAgICAgKiByZXBlYXRlZCBjYWxscyBpbiBwYXJ0aWN1bGFyIGFyZSBzYWZlLCBidXQgb25seSB0aGUgZmlyc3Qgb25lXG4gICAgICogd2lsbCBzZXQgdGhlIGNhbmNlbGxhdGlvbiBjYXVzZS5cbiAgICAgKlxuICAgICAqIFRoZSBgQ2FuY2VsRXJyb3JgIGV4Y2VwdGlvbiBfbmVlZCBub3RfIGJlIGhhbmRsZWQgZXhwbGljaXRseSBfb24gdGhlIHByb21pc2VzIHRoYXQgYXJlIGJlaW5nIGNhbmNlbGxlZDpfXG4gICAgICogY2FuY2VsbGluZyBhIHByb21pc2Ugd2l0aCBubyBhdHRhY2hlZCByZWplY3Rpb24gaGFuZGxlciBkb2VzIG5vdCB0cmlnZ2VyIGFuIHVuaGFuZGxlZCByZWplY3Rpb24gZXZlbnQuXG4gICAgICogVGhlcmVmb3JlLCB0aGUgZm9sbG93aW5nIGlkaW9tcyBhcmUgYWxsIGVxdWFsbHkgY29ycmVjdDpcbiAgICAgKiBgYGB0c1xuICAgICAqIG5ldyBDYW5jZWxsYWJsZVByb21pc2UoKHJlc29sdmUsIHJlamVjdCkgPT4geyAuLi4gfSkuY2FuY2VsKCk7XG4gICAgICogbmV3IENhbmNlbGxhYmxlUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7IC4uLiB9KS50aGVuKC4uLikuY2FuY2VsKCk7XG4gICAgICogbmV3IENhbmNlbGxhYmxlUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7IC4uLiB9KS50aGVuKC4uLikuY2F0Y2goLi4uKS5jYW5jZWwoKTtcbiAgICAgKiBgYGBcbiAgICAgKiBXaGVuZXZlciBzb21lIGNhbmNlbGxlZCBwcm9taXNlIGluIGEgY2hhaW4gcmVqZWN0cyB3aXRoIGEgYENhbmNlbEVycm9yYFxuICAgICAqIHdpdGggdGhlIHNhbWUgY2FuY2VsbGF0aW9uIGNhdXNlIGFzIGl0c2VsZiwgdGhlIGVycm9yIHdpbGwgYmUgZGlzY2FyZGVkIHNpbGVudGx5LlxuICAgICAqIEhvd2V2ZXIsIHRoZSBgQ2FuY2VsRXJyb3JgIF93aWxsIHN0aWxsIGJlIGRlbGl2ZXJlZF8gdG8gYWxsIGF0dGFjaGVkIHJlamVjdGlvbiBoYW5kbGVyc1xuICAgICAqIGFkZGVkIGJ5IHtAbGluayB0aGVufSBhbmQgcmVsYXRlZCBtZXRob2RzOlxuICAgICAqIGBgYHRzXG4gICAgICogbGV0IGNhbmNlbGxhYmxlID0gbmV3IENhbmNlbGxhYmxlUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7IC4uLiB9KTtcbiAgICAgKiBjYW5jZWxsYWJsZS50aGVuKCgpID0+IHsgLi4uIH0pLmNhdGNoKGNvbnNvbGUubG9nKTtcbiAgICAgKiBjYW5jZWxsYWJsZS5jYW5jZWwoKTsgLy8gQSBDYW5jZWxFcnJvciBpcyBwcmludGVkIHRvIHRoZSBjb25zb2xlLlxuICAgICAqIGBgYFxuICAgICAqIElmIHRoZSBgQ2FuY2VsRXJyb3JgIGlzIG5vdCBoYW5kbGVkIGRvd25zdHJlYW0gYnkgdGhlIHRpbWUgaXQgcmVhY2hlc1xuICAgICAqIGEgX25vbi1jYW5jZWxsZWRfIHByb21pc2UsIGl0IF93aWxsXyB0cmlnZ2VyIGFuIHVuaGFuZGxlZCByZWplY3Rpb24gZXZlbnQsXG4gICAgICoganVzdCBsaWtlIG5vcm1hbCByZWplY3Rpb25zIHdvdWxkOlxuICAgICAqIGBgYHRzXG4gICAgICogbGV0IGNhbmNlbGxhYmxlID0gbmV3IENhbmNlbGxhYmxlUHJvbWlzZSgocmVzb2x2ZSwgcmVqZWN0KSA9PiB7IC4uLiB9KTtcbiAgICAgKiBsZXQgY2hhaW5lZCA9IGNhbmNlbGxhYmxlLnRoZW4oKCkgPT4geyAuLi4gfSkudGhlbigoKSA9PiB7IC4uLiB9KTsgLy8gTm8gY2F0Y2guLi5cbiAgICAgKiBjYW5jZWxsYWJsZS5jYW5jZWwoKTsgLy8gVW5oYW5kbGVkIHJlamVjdGlvbiBldmVudCBvbiBjaGFpbmVkIVxuICAgICAqIGBgYFxuICAgICAqIFRoZXJlZm9yZSwgaXQgaXMgaW1wb3J0YW50IHRvIGVpdGhlciBjYW5jZWwgd2hvbGUgcHJvbWlzZSBjaGFpbnMgZnJvbSB0aGVpciB0YWlsLFxuICAgICAqIGFzIHNob3duIGluIHRoZSBjb3JyZWN0IGlkaW9tcyBhYm92ZSwgb3IgdGFrZSBjYXJlIG9mIGhhbmRsaW5nIGVycm9ycyBldmVyeXdoZXJlLlxuICAgICAqXG4gICAgICogQHJldHVybnMgQSBjYW5jZWxsYWJsZSBwcm9taXNlIHRoYXQgX2Z1bGZpbGxzXyBhZnRlciB0aGUgY2FuY2VsIGNhbGxiYWNrIChpZiBhbnkpXG4gICAgICogYW5kIGFsbCBoYW5kbGVycyBhdHRhY2hlZCB1cCB0byB0aGUgY2FsbCB0byBjYW5jZWwgaGF2ZSBydW4uXG4gICAgICogSWYgdGhlIGNhbmNlbCBjYWxsYmFjayByZXR1cm5zIGEgdGhlbmFibGUsIHRoZSBwcm9taXNlIHJldHVybmVkIGJ5IGBjYW5jZWxgXG4gICAgICogd2lsbCBhbHNvIHdhaXQgZm9yIHRoYXQgdGhlbmFibGUgdG8gc2V0dGxlLlxuICAgICAqIFRoaXMgZW5hYmxlcyBjYWxsZXJzIHRvIHdhaXQgZm9yIHRoZSBjYW5jZWxsZWQgb3BlcmF0aW9uIHRvIHRlcm1pbmF0ZVxuICAgICAqIHdpdGhvdXQgYmVpbmcgZm9yY2VkIHRvIGhhbmRsZSBwb3RlbnRpYWwgZXJyb3JzIGF0IHRoZSBjYWxsIHNpdGUuXG4gICAgICogYGBgdHNcbiAgICAgKiBjYW5jZWxsYWJsZS5jYW5jZWwoKS50aGVuKCgpID0+IHtcbiAgICAgKiAgICAgLy8gQ2xlYW51cCBmaW5pc2hlZCwgaXQncyBzYWZlIHRvIGRvIHNvbWV0aGluZyBlbHNlLlxuICAgICAqIH0sIChlcnIpID0+IHtcbiAgICAgKiAgICAgLy8gVW5yZWFjaGFibGU6IHRoZSBwcm9taXNlIHJldHVybmVkIGZyb20gY2FuY2VsIHdpbGwgbmV2ZXIgcmVqZWN0LlxuICAgICAqIH0pO1xuICAgICAqIGBgYFxuICAgICAqIE5vdGUgdGhhdCB0aGUgcmV0dXJuZWQgcHJvbWlzZSB3aWxsIF9ub3RfIGhhbmRsZSBpbXBsaWNpdGx5IGFueSByZWplY3Rpb25cbiAgICAgKiB0aGF0IG1pZ2h0IGhhdmUgb2NjdXJyZWQgYWxyZWFkeSBpbiB0aGUgY2FuY2VsbGVkIGNoYWluLlxuICAgICAqIEl0IHdpbGwganVzdCB0cmFjayB3aGV0aGVyIHJlZ2lzdGVyZWQgaGFuZGxlcnMgaGF2ZSBiZWVuIGV4ZWN1dGVkIG9yIG5vdC5cbiAgICAgKiBUaGVyZWZvcmUsIHVuaGFuZGxlZCByZWplY3Rpb25zIHdpbGwgbmV2ZXIgYmUgc2lsZW50bHkgaGFuZGxlZCBieSBjYWxsaW5nIGNhbmNlbC5cbiAgICAgKi9cbiAgICBjYW5jZWwoY2F1c2U/OiBhbnkpOiBDYW5jZWxsYWJsZVByb21pc2U8dm9pZD4ge1xuICAgICAgICByZXR1cm4gbmV3IENhbmNlbGxhYmxlUHJvbWlzZTx2b2lkPigocmVzb2x2ZSkgPT4ge1xuICAgICAgICAgICAgLy8gSU5WQVJJQU5UOiB0aGUgcmVzdWx0IG9mIHRoaXNbY2FuY2VsSW1wbFN5bV0gYW5kIHRoZSBiYXJyaWVyIGRvIG5vdCBldmVyIHJlamVjdC5cbiAgICAgICAgICAgIC8vIFVuZm9ydHVuYXRlbHkgbWFjT1MgSGlnaCBTaWVycmEgZG9lcyBub3Qgc3VwcG9ydCBQcm9taXNlLmFsbFNldHRsZWQuXG4gICAgICAgICAgICBQcm9taXNlLmFsbChbXG4gICAgICAgICAgICAgICAgdGhpc1tjYW5jZWxJbXBsU3ltXShuZXcgQ2FuY2VsRXJyb3IoXCJQcm9taXNlIGNhbmNlbGxlZC5cIiwgeyBjYXVzZSB9KSksXG4gICAgICAgICAgICAgICAgY3VycmVudEJhcnJpZXIodGhpcylcbiAgICAgICAgICAgIF0pLnRoZW4oKCkgPT4gcmVzb2x2ZSgpLCAoKSA9PiByZXNvbHZlKCkpO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBCaW5kcyBwcm9taXNlIGNhbmNlbGxhdGlvbiB0byB0aGUgYWJvcnQgZXZlbnQgb2YgdGhlIGdpdmVuIHtAbGluayBBYm9ydFNpZ25hbH0uXG4gICAgICogSWYgdGhlIHNpZ25hbCBoYXMgYWxyZWFkeSBhYm9ydGVkLCB0aGUgcHJvbWlzZSB3aWxsIGJlIGNhbmNlbGxlZCBpbW1lZGlhdGVseS5cbiAgICAgKiBXaGVuIGVpdGhlciBjb25kaXRpb24gaXMgdmVyaWZpZWQsIHRoZSBjYW5jZWxsYXRpb24gY2F1c2Ugd2lsbCBiZSBzZXRcbiAgICAgKiB0byB0aGUgc2lnbmFsJ3MgYWJvcnQgcmVhc29uIChzZWUge0BsaW5rIEFib3J0U2lnbmFsI3JlYXNvbn0pLlxuICAgICAqXG4gICAgICogSGFzIG5vIGVmZmVjdCBpZiBjYWxsZWQgKG9yIGlmIHRoZSBzaWduYWwgYWJvcnRzKSBfYWZ0ZXJfIHRoZSBwcm9taXNlIGhhcyBhbHJlYWR5IHNldHRsZWQuXG4gICAgICogT25seSB0aGUgZmlyc3Qgc2lnbmFsIHRvIGFib3J0IHdpbGwgc2V0IHRoZSBjYW5jZWxsYXRpb24gY2F1c2UuXG4gICAgICpcbiAgICAgKiBGb3IgbW9yZSBkZXRhaWxzIGFib3V0IHRoZSBjYW5jZWxsYXRpb24gcHJvY2VzcyxcbiAgICAgKiBzZWUge0BsaW5rIGNhbmNlbH0gYW5kIHRoZSBgQ2FuY2VsbGFibGVQcm9taXNlYCBjb25zdHJ1Y3Rvci5cbiAgICAgKlxuICAgICAqIFRoaXMgbWV0aG9kIGVuYWJsZXMgYGF3YWl0YGluZyBjYW5jZWxsYWJsZSBwcm9taXNlcyB3aXRob3V0IGhhdmluZ1xuICAgICAqIHRvIHN0b3JlIHRoZW0gZm9yIGZ1dHVyZSBjYW5jZWxsYXRpb24sIGUuZy46XG4gICAgICogYGBgdHNcbiAgICAgKiBhd2FpdCBsb25nUnVubmluZ09wZXJhdGlvbigpLmNhbmNlbE9uKHNpZ25hbCk7XG4gICAgICogYGBgXG4gICAgICogaW5zdGVhZCBvZjpcbiAgICAgKiBgYGB0c1xuICAgICAqIGxldCBwcm9taXNlVG9CZUNhbmNlbGxlZCA9IGxvbmdSdW5uaW5nT3BlcmF0aW9uKCk7XG4gICAgICogYXdhaXQgcHJvbWlzZVRvQmVDYW5jZWxsZWQ7XG4gICAgICogYGBgXG4gICAgICpcbiAgICAgKiBAcmV0dXJucyBUaGlzIHByb21pc2UsIGZvciBtZXRob2QgY2hhaW5pbmcuXG4gICAgICovXG4gICAgY2FuY2VsT24oc2lnbmFsOiBBYm9ydFNpZ25hbCk6IENhbmNlbGxhYmxlUHJvbWlzZTxUPiB7XG4gICAgICAgIGlmIChzaWduYWwuYWJvcnRlZCkge1xuICAgICAgICAgICAgdm9pZCB0aGlzLmNhbmNlbChzaWduYWwucmVhc29uKVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgc2lnbmFsLmFkZEV2ZW50TGlzdGVuZXIoJ2Fib3J0JywgKCkgPT4gdm9pZCB0aGlzLmNhbmNlbChzaWduYWwucmVhc29uKSwge2NhcHR1cmU6IHRydWV9KTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB0aGlzO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIEF0dGFjaGVzIGNhbGxiYWNrcyBmb3IgdGhlIHJlc29sdXRpb24gYW5kL29yIHJlamVjdGlvbiBvZiB0aGUgYENhbmNlbGxhYmxlUHJvbWlzZWAuXG4gICAgICpcbiAgICAgKiBUaGUgb3B0aW9uYWwgYG9uY2FuY2VsbGVkYCBhcmd1bWVudCB3aWxsIGJlIGludm9rZWQgd2hlbiB0aGUgcmV0dXJuZWQgcHJvbWlzZSBpcyBjYW5jZWxsZWQsXG4gICAgICogd2l0aCB0aGUgc2FtZSBzZW1hbnRpY3MgYXMgdGhlIGBvbmNhbmNlbGxlZGAgYXJndW1lbnQgb2YgdGhlIGNvbnN0cnVjdG9yLlxuICAgICAqIFdoZW4gdGhlIHBhcmVudCBwcm9taXNlIHJlamVjdHMgb3IgaXMgY2FuY2VsbGVkLCB0aGUgYG9ucmVqZWN0ZWRgIGNhbGxiYWNrIHdpbGwgcnVuLFxuICAgICAqIF9ldmVuIGFmdGVyIHRoZSByZXR1cm5lZCBwcm9taXNlIGhhcyBiZWVuIGNhbmNlbGxlZDpfXG4gICAgICogaW4gdGhhdCBjYXNlLCBzaG91bGQgaXQgcmVqZWN0IG9yIHRocm93LCB0aGUgcmVhc29uIHdpbGwgYmUgd3JhcHBlZFxuICAgICAqIGluIGEge0BsaW5rIENhbmNlbGxlZFJlamVjdGlvbkVycm9yfSBhbmQgYnViYmxlZCB1cCBhcyBhbiB1bmhhbmRsZWQgcmVqZWN0aW9uLlxuICAgICAqXG4gICAgICogQHBhcmFtIG9uZnVsZmlsbGVkIFRoZSBjYWxsYmFjayB0byBleGVjdXRlIHdoZW4gdGhlIFByb21pc2UgaXMgcmVzb2x2ZWQuXG4gICAgICogQHBhcmFtIG9ucmVqZWN0ZWQgVGhlIGNhbGxiYWNrIHRvIGV4ZWN1dGUgd2hlbiB0aGUgUHJvbWlzZSBpcyByZWplY3RlZC5cbiAgICAgKiBAcmV0dXJucyBBIGBDYW5jZWxsYWJsZVByb21pc2VgIGZvciB0aGUgY29tcGxldGlvbiBvZiB3aGljaGV2ZXIgY2FsbGJhY2sgaXMgZXhlY3V0ZWQuXG4gICAgICogVGhlIHJldHVybmVkIHByb21pc2UgaXMgaG9va2VkIHVwIHRvIHByb3BhZ2F0ZSBjYW5jZWxsYXRpb24gcmVxdWVzdHMgdXAgdGhlIGNoYWluLCBidXQgbm90IGRvd246XG4gICAgICpcbiAgICAgKiAgIC0gaWYgdGhlIHBhcmVudCBwcm9taXNlIGlzIGNhbmNlbGxlZCwgdGhlIGBvbnJlamVjdGVkYCBoYW5kbGVyIHdpbGwgYmUgaW52b2tlZCB3aXRoIGEgYENhbmNlbEVycm9yYFxuICAgICAqICAgICBhbmQgdGhlIHJldHVybmVkIHByb21pc2UgX3dpbGwgcmVzb2x2ZSByZWd1bGFybHlfIHdpdGggaXRzIHJlc3VsdDtcbiAgICAgKiAgIC0gY29udmVyc2VseSwgaWYgdGhlIHJldHVybmVkIHByb21pc2UgaXMgY2FuY2VsbGVkLCBfdGhlIHBhcmVudCBwcm9taXNlIGlzIGNhbmNlbGxlZCB0b287X1xuICAgICAqICAgICB0aGUgYG9ucmVqZWN0ZWRgIGhhbmRsZXIgd2lsbCBzdGlsbCBiZSBpbnZva2VkIHdpdGggdGhlIHBhcmVudCdzIGBDYW5jZWxFcnJvcmAsXG4gICAgICogICAgIGJ1dCBpdHMgcmVzdWx0IHdpbGwgYmUgZGlzY2FyZGVkXG4gICAgICogICAgIGFuZCB0aGUgcmV0dXJuZWQgcHJvbWlzZSB3aWxsIHJlamVjdCB3aXRoIGEgYENhbmNlbEVycm9yYCBhcyB3ZWxsLlxuICAgICAqXG4gICAgICogVGhlIHByb21pc2UgcmV0dXJuZWQgZnJvbSB7QGxpbmsgY2FuY2VsfSB3aWxsIGZ1bGZpbGwgb25seSBhZnRlciBhbGwgYXR0YWNoZWQgaGFuZGxlcnNcbiAgICAgKiB1cCB0aGUgZW50aXJlIHByb21pc2UgY2hhaW4gaGF2ZSBiZWVuIHJ1bi5cbiAgICAgKlxuICAgICAqIElmIGVpdGhlciBjYWxsYmFjayByZXR1cm5zIGEgY2FuY2VsbGFibGUgcHJvbWlzZSxcbiAgICAgKiBjYW5jZWxsYXRpb24gcmVxdWVzdHMgd2lsbCBiZSBkaXZlcnRlZCB0byBpdCxcbiAgICAgKiBhbmQgdGhlIHNwZWNpZmllZCBgb25jYW5jZWxsZWRgIGNhbGxiYWNrIHdpbGwgYmUgZGlzY2FyZGVkLlxuICAgICAqL1xuICAgIHRoZW48VFJlc3VsdDEgPSBULCBUUmVzdWx0MiA9IG5ldmVyPihvbmZ1bGZpbGxlZD86ICgodmFsdWU6IFQpID0+IFRSZXN1bHQxIHwgUHJvbWlzZUxpa2U8VFJlc3VsdDE+IHwgQ2FuY2VsbGFibGVQcm9taXNlTGlrZTxUUmVzdWx0MT4pIHwgdW5kZWZpbmVkIHwgbnVsbCwgb25yZWplY3RlZD86ICgocmVhc29uOiBhbnkpID0+IFRSZXN1bHQyIHwgUHJvbWlzZUxpa2U8VFJlc3VsdDI+IHwgQ2FuY2VsbGFibGVQcm9taXNlTGlrZTxUUmVzdWx0Mj4pIHwgdW5kZWZpbmVkIHwgbnVsbCwgb25jYW5jZWxsZWQ/OiBDYW5jZWxsYWJsZVByb21pc2VDYW5jZWxsZXIpOiBDYW5jZWxsYWJsZVByb21pc2U8VFJlc3VsdDEgfCBUUmVzdWx0Mj4ge1xuICAgICAgICBpZiAoISh0aGlzIGluc3RhbmNlb2YgQ2FuY2VsbGFibGVQcm9taXNlKSkge1xuICAgICAgICAgICAgdGhyb3cgbmV3IFR5cGVFcnJvcihcIkNhbmNlbGxhYmxlUHJvbWlzZS5wcm90b3R5cGUudGhlbiBjYWxsZWQgb24gYW4gaW52YWxpZCBvYmplY3QuXCIpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gTk9URTogVHlwZVNjcmlwdCdzIGJ1aWx0LWluIHR5cGUgZm9yIHRoZW4gaXMgYnJva2VuLFxuICAgICAgICAvLyBhcyBpdCBhbGxvd3Mgc3BlY2lmeWluZyBhbiBhcmJpdHJhcnkgVFJlc3VsdDEgIT0gVCBldmVuIHdoZW4gb25mdWxmaWxsZWQgaXMgbm90IGEgZnVuY3Rpb24uXG4gICAgICAgIC8vIFdlIGNhbm5vdCBmaXggaXQgaWYgd2Ugd2FudCB0byBDYW5jZWxsYWJsZVByb21pc2UgdG8gaW1wbGVtZW50IFByb21pc2VMaWtlPFQ+LlxuXG4gICAgICAgIGlmICghaXNDYWxsYWJsZShvbmZ1bGZpbGxlZCkpIHsgb25mdWxmaWxsZWQgPSBpZGVudGl0eSBhcyBhbnk7IH1cbiAgICAgICAgaWYgKCFpc0NhbGxhYmxlKG9ucmVqZWN0ZWQpKSB7IG9ucmVqZWN0ZWQgPSB0aHJvd2VyOyB9XG5cbiAgICAgICAgaWYgKG9uZnVsZmlsbGVkID09PSBpZGVudGl0eSAmJiBvbnJlamVjdGVkID09IHRocm93ZXIpIHtcbiAgICAgICAgICAgIC8vIFNob3J0Y3V0IGZvciB0cml2aWFsIGFyZ3VtZW50cy5cbiAgICAgICAgICAgIHJldHVybiBuZXcgQ2FuY2VsbGFibGVQcm9taXNlKChyZXNvbHZlKSA9PiByZXNvbHZlKHRoaXMgYXMgYW55KSk7XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBiYXJyaWVyOiBQYXJ0aWFsPFByb21pc2VXaXRoUmVzb2x2ZXJzPHZvaWQ+PiA9IHt9O1xuICAgICAgICB0aGlzW2JhcnJpZXJTeW1dID0gYmFycmllcjtcblxuICAgICAgICByZXR1cm4gbmV3IENhbmNlbGxhYmxlUHJvbWlzZTxUUmVzdWx0MSB8IFRSZXN1bHQyPigocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICB2b2lkIHN1cGVyLnRoZW4oXG4gICAgICAgICAgICAgICAgKHZhbHVlKSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGlmICh0aGlzW2JhcnJpZXJTeW1dID09PSBiYXJyaWVyKSB7IHRoaXNbYmFycmllclN5bV0gPSBudWxsOyB9XG4gICAgICAgICAgICAgICAgICAgIGJhcnJpZXIucmVzb2x2ZT8uKCk7XG5cbiAgICAgICAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc29sdmUob25mdWxmaWxsZWQhKHZhbHVlKSk7XG4gICAgICAgICAgICAgICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KGVycik7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIChyZWFzb24/KSA9PiB7XG4gICAgICAgICAgICAgICAgICAgIGlmICh0aGlzW2JhcnJpZXJTeW1dID09PSBiYXJyaWVyKSB7IHRoaXNbYmFycmllclN5bV0gPSBudWxsOyB9XG4gICAgICAgICAgICAgICAgICAgIGJhcnJpZXIucmVzb2x2ZT8uKCk7XG5cbiAgICAgICAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICAgICAgICAgIHJlc29sdmUob25yZWplY3RlZCEocmVhc29uKSk7XG4gICAgICAgICAgICAgICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgICAgICAgICAgICAgICAgcmVqZWN0KGVycik7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICApO1xuICAgICAgICB9LCBhc3luYyAoY2F1c2U/KSA9PiB7XG4gICAgICAgICAgICAvL2NhbmNlbGxlZCA9IHRydWU7XG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgIHJldHVybiBvbmNhbmNlbGxlZD8uKGNhdXNlKTtcbiAgICAgICAgICAgIH0gZmluYWxseSB7XG4gICAgICAgICAgICAgICAgYXdhaXQgdGhpcy5jYW5jZWwoY2F1c2UpO1xuICAgICAgICAgICAgfVxuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBBdHRhY2hlcyBhIGNhbGxiYWNrIGZvciBvbmx5IHRoZSByZWplY3Rpb24gb2YgdGhlIFByb21pc2UuXG4gICAgICpcbiAgICAgKiBUaGUgb3B0aW9uYWwgYG9uY2FuY2VsbGVkYCBhcmd1bWVudCB3aWxsIGJlIGludm9rZWQgd2hlbiB0aGUgcmV0dXJuZWQgcHJvbWlzZSBpcyBjYW5jZWxsZWQsXG4gICAgICogd2l0aCB0aGUgc2FtZSBzZW1hbnRpY3MgYXMgdGhlIGBvbmNhbmNlbGxlZGAgYXJndW1lbnQgb2YgdGhlIGNvbnN0cnVjdG9yLlxuICAgICAqIFdoZW4gdGhlIHBhcmVudCBwcm9taXNlIHJlamVjdHMgb3IgaXMgY2FuY2VsbGVkLCB0aGUgYG9ucmVqZWN0ZWRgIGNhbGxiYWNrIHdpbGwgcnVuLFxuICAgICAqIF9ldmVuIGFmdGVyIHRoZSByZXR1cm5lZCBwcm9taXNlIGhhcyBiZWVuIGNhbmNlbGxlZDpfXG4gICAgICogaW4gdGhhdCBjYXNlLCBzaG91bGQgaXQgcmVqZWN0IG9yIHRocm93LCB0aGUgcmVhc29uIHdpbGwgYmUgd3JhcHBlZFxuICAgICAqIGluIGEge0BsaW5rIENhbmNlbGxlZFJlamVjdGlvbkVycm9yfSBhbmQgYnViYmxlZCB1cCBhcyBhbiB1bmhhbmRsZWQgcmVqZWN0aW9uLlxuICAgICAqXG4gICAgICogSXQgaXMgZXF1aXZhbGVudCB0b1xuICAgICAqIGBgYHRzXG4gICAgICogY2FuY2VsbGFibGVQcm9taXNlLnRoZW4odW5kZWZpbmVkLCBvbnJlamVjdGVkLCBvbmNhbmNlbGxlZCk7XG4gICAgICogYGBgXG4gICAgICogYW5kIHRoZSBzYW1lIGNhdmVhdHMgYXBwbHkuXG4gICAgICpcbiAgICAgKiBAcmV0dXJucyBBIFByb21pc2UgZm9yIHRoZSBjb21wbGV0aW9uIG9mIHRoZSBjYWxsYmFjay5cbiAgICAgKiBDYW5jZWxsYXRpb24gcmVxdWVzdHMgb24gdGhlIHJldHVybmVkIHByb21pc2VcbiAgICAgKiB3aWxsIHByb3BhZ2F0ZSB1cCB0aGUgY2hhaW4gdG8gdGhlIHBhcmVudCBwcm9taXNlLFxuICAgICAqIGJ1dCBub3QgaW4gdGhlIG90aGVyIGRpcmVjdGlvbi5cbiAgICAgKlxuICAgICAqIFRoZSBwcm9taXNlIHJldHVybmVkIGZyb20ge0BsaW5rIGNhbmNlbH0gd2lsbCBmdWxmaWxsIG9ubHkgYWZ0ZXIgYWxsIGF0dGFjaGVkIGhhbmRsZXJzXG4gICAgICogdXAgdGhlIGVudGlyZSBwcm9taXNlIGNoYWluIGhhdmUgYmVlbiBydW4uXG4gICAgICpcbiAgICAgKiBJZiBgb25yZWplY3RlZGAgcmV0dXJucyBhIGNhbmNlbGxhYmxlIHByb21pc2UsXG4gICAgICogY2FuY2VsbGF0aW9uIHJlcXVlc3RzIHdpbGwgYmUgZGl2ZXJ0ZWQgdG8gaXQsXG4gICAgICogYW5kIHRoZSBzcGVjaWZpZWQgYG9uY2FuY2VsbGVkYCBjYWxsYmFjayB3aWxsIGJlIGRpc2NhcmRlZC5cbiAgICAgKiBTZWUge0BsaW5rIHRoZW59IGZvciBtb3JlIGRldGFpbHMuXG4gICAgICovXG4gICAgY2F0Y2g8VFJlc3VsdCA9IG5ldmVyPihvbnJlamVjdGVkPzogKChyZWFzb246IGFueSkgPT4gKFByb21pc2VMaWtlPFRSZXN1bHQ+IHwgVFJlc3VsdCkpIHwgdW5kZWZpbmVkIHwgbnVsbCwgb25jYW5jZWxsZWQ/OiBDYW5jZWxsYWJsZVByb21pc2VDYW5jZWxsZXIpOiBDYW5jZWxsYWJsZVByb21pc2U8VCB8IFRSZXN1bHQ+IHtcbiAgICAgICAgcmV0dXJuIHRoaXMudGhlbih1bmRlZmluZWQsIG9ucmVqZWN0ZWQsIG9uY2FuY2VsbGVkKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBBdHRhY2hlcyBhIGNhbGxiYWNrIHRoYXQgaXMgaW52b2tlZCB3aGVuIHRoZSBDYW5jZWxsYWJsZVByb21pc2UgaXMgc2V0dGxlZCAoZnVsZmlsbGVkIG9yIHJlamVjdGVkKS4gVGhlXG4gICAgICogcmVzb2x2ZWQgdmFsdWUgY2Fubm90IGJlIGFjY2Vzc2VkIG9yIG1vZGlmaWVkIGZyb20gdGhlIGNhbGxiYWNrLlxuICAgICAqIFRoZSByZXR1cm5lZCBwcm9taXNlIHdpbGwgc2V0dGxlIGluIHRoZSBzYW1lIHN0YXRlIGFzIHRoZSBvcmlnaW5hbCBvbmVcbiAgICAgKiBhZnRlciB0aGUgcHJvdmlkZWQgY2FsbGJhY2sgaGFzIGNvbXBsZXRlZCBleGVjdXRpb24sXG4gICAgICogdW5sZXNzIHRoZSBjYWxsYmFjayB0aHJvd3Mgb3IgcmV0dXJucyBhIHJlamVjdGluZyBwcm9taXNlLFxuICAgICAqIGluIHdoaWNoIGNhc2UgdGhlIHJldHVybmVkIHByb21pc2Ugd2lsbCByZWplY3QgYXMgd2VsbC5cbiAgICAgKlxuICAgICAqIFRoZSBvcHRpb25hbCBgb25jYW5jZWxsZWRgIGFyZ3VtZW50IHdpbGwgYmUgaW52b2tlZCB3aGVuIHRoZSByZXR1cm5lZCBwcm9taXNlIGlzIGNhbmNlbGxlZCxcbiAgICAgKiB3aXRoIHRoZSBzYW1lIHNlbWFudGljcyBhcyB0aGUgYG9uY2FuY2VsbGVkYCBhcmd1bWVudCBvZiB0aGUgY29uc3RydWN0b3IuXG4gICAgICogT25jZSB0aGUgcGFyZW50IHByb21pc2Ugc2V0dGxlcywgdGhlIGBvbmZpbmFsbHlgIGNhbGxiYWNrIHdpbGwgcnVuLFxuICAgICAqIF9ldmVuIGFmdGVyIHRoZSByZXR1cm5lZCBwcm9taXNlIGhhcyBiZWVuIGNhbmNlbGxlZDpfXG4gICAgICogaW4gdGhhdCBjYXNlLCBzaG91bGQgaXQgcmVqZWN0IG9yIHRocm93LCB0aGUgcmVhc29uIHdpbGwgYmUgd3JhcHBlZFxuICAgICAqIGluIGEge0BsaW5rIENhbmNlbGxlZFJlamVjdGlvbkVycm9yfSBhbmQgYnViYmxlZCB1cCBhcyBhbiB1bmhhbmRsZWQgcmVqZWN0aW9uLlxuICAgICAqXG4gICAgICogVGhpcyBtZXRob2QgaXMgaW1wbGVtZW50ZWQgaW4gdGVybXMgb2Yge0BsaW5rIHRoZW59IGFuZCB0aGUgc2FtZSBjYXZlYXRzIGFwcGx5LlxuICAgICAqIEl0IGlzIHBvbHlmaWxsZWQsIGhlbmNlIGF2YWlsYWJsZSBpbiBldmVyeSBPUy93ZWJ2aWV3IHZlcnNpb24uXG4gICAgICpcbiAgICAgKiBAcmV0dXJucyBBIFByb21pc2UgZm9yIHRoZSBjb21wbGV0aW9uIG9mIHRoZSBjYWxsYmFjay5cbiAgICAgKiBDYW5jZWxsYXRpb24gcmVxdWVzdHMgb24gdGhlIHJldHVybmVkIHByb21pc2VcbiAgICAgKiB3aWxsIHByb3BhZ2F0ZSB1cCB0aGUgY2hhaW4gdG8gdGhlIHBhcmVudCBwcm9taXNlLFxuICAgICAqIGJ1dCBub3QgaW4gdGhlIG90aGVyIGRpcmVjdGlvbi5cbiAgICAgKlxuICAgICAqIFRoZSBwcm9taXNlIHJldHVybmVkIGZyb20ge0BsaW5rIGNhbmNlbH0gd2lsbCBmdWxmaWxsIG9ubHkgYWZ0ZXIgYWxsIGF0dGFjaGVkIGhhbmRsZXJzXG4gICAgICogdXAgdGhlIGVudGlyZSBwcm9taXNlIGNoYWluIGhhdmUgYmVlbiBydW4uXG4gICAgICpcbiAgICAgKiBJZiBgb25maW5hbGx5YCByZXR1cm5zIGEgY2FuY2VsbGFibGUgcHJvbWlzZSxcbiAgICAgKiBjYW5jZWxsYXRpb24gcmVxdWVzdHMgd2lsbCBiZSBkaXZlcnRlZCB0byBpdCxcbiAgICAgKiBhbmQgdGhlIHNwZWNpZmllZCBgb25jYW5jZWxsZWRgIGNhbGxiYWNrIHdpbGwgYmUgZGlzY2FyZGVkLlxuICAgICAqIFNlZSB7QGxpbmsgdGhlbn0gZm9yIG1vcmUgZGV0YWlscy5cbiAgICAgKi9cbiAgICBmaW5hbGx5KG9uZmluYWxseT86ICgoKSA9PiB2b2lkKSB8IHVuZGVmaW5lZCB8IG51bGwsIG9uY2FuY2VsbGVkPzogQ2FuY2VsbGFibGVQcm9taXNlQ2FuY2VsbGVyKTogQ2FuY2VsbGFibGVQcm9taXNlPFQ+IHtcbiAgICAgICAgaWYgKCEodGhpcyBpbnN0YW5jZW9mIENhbmNlbGxhYmxlUHJvbWlzZSkpIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoXCJDYW5jZWxsYWJsZVByb21pc2UucHJvdG90eXBlLmZpbmFsbHkgY2FsbGVkIG9uIGFuIGludmFsaWQgb2JqZWN0LlwiKTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghaXNDYWxsYWJsZShvbmZpbmFsbHkpKSB7XG4gICAgICAgICAgICByZXR1cm4gdGhpcy50aGVuKG9uZmluYWxseSwgb25maW5hbGx5LCBvbmNhbmNlbGxlZCk7XG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4gdGhpcy50aGVuKFxuICAgICAgICAgICAgKHZhbHVlKSA9PiBDYW5jZWxsYWJsZVByb21pc2UucmVzb2x2ZShvbmZpbmFsbHkoKSkudGhlbigoKSA9PiB2YWx1ZSksXG4gICAgICAgICAgICAocmVhc29uPykgPT4gQ2FuY2VsbGFibGVQcm9taXNlLnJlc29sdmUob25maW5hbGx5KCkpLnRoZW4oKCkgPT4geyB0aHJvdyByZWFzb247IH0pLFxuICAgICAgICAgICAgb25jYW5jZWxsZWQsXG4gICAgICAgICk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogV2UgdXNlIHRoZSBgW1N5bWJvbC5zcGVjaWVzXWAgc3RhdGljIHByb3BlcnR5LCBpZiBhdmFpbGFibGUsXG4gICAgICogdG8gZGlzYWJsZSB0aGUgYnVpbHQtaW4gYXV0b21hdGljIHN1YmNsYXNzaW5nIGZlYXR1cmVzIGZyb20ge0BsaW5rIFByb21pc2V9LlxuICAgICAqIEl0IGlzIGNyaXRpY2FsIGZvciBwZXJmb3JtYW5jZSByZWFzb25zIHRoYXQgZXh0ZW5kZXJzIGRvIG5vdCBvdmVycmlkZSB0aGlzLlxuICAgICAqIE9uY2UgdGhlIHByb3Bvc2FsIGF0IGh0dHBzOi8vZ2l0aHViLmNvbS90YzM5L3Byb3Bvc2FsLXJtLWJ1aWx0aW4tc3ViY2xhc3NpbmdcbiAgICAgKiBpcyBlaXRoZXIgYWNjZXB0ZWQgb3IgcmV0aXJlZCwgdGhpcyBpbXBsZW1lbnRhdGlvbiB3aWxsIGhhdmUgdG8gYmUgcmV2aXNlZCBhY2NvcmRpbmdseS5cbiAgICAgKlxuICAgICAqIEBpZ25vcmVcbiAgICAgKiBAaW50ZXJuYWxcbiAgICAgKi9cbiAgICBzdGF0aWMgZ2V0IFtzcGVjaWVzXSgpIHtcbiAgICAgICAgcmV0dXJuIFByb21pc2U7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIENhbmNlbGxhYmxlUHJvbWlzZSB0aGF0IGlzIHJlc29sdmVkIHdpdGggYW4gYXJyYXkgb2YgcmVzdWx0c1xuICAgICAqIHdoZW4gYWxsIG9mIHRoZSBwcm92aWRlZCBQcm9taXNlcyByZXNvbHZlLCBvciByZWplY3RlZCB3aGVuIGFueSBQcm9taXNlIGlzIHJlamVjdGVkLlxuICAgICAqXG4gICAgICogRXZlcnkgb25lIG9mIHRoZSBwcm92aWRlZCBvYmplY3RzIHRoYXQgaXMgYSB0aGVuYWJsZSBfYW5kXyBjYW5jZWxsYWJsZSBvYmplY3RcbiAgICAgKiB3aWxsIGJlIGNhbmNlbGxlZCB3aGVuIHRoZSByZXR1cm5lZCBwcm9taXNlIGlzIGNhbmNlbGxlZCwgd2l0aCB0aGUgc2FtZSBjYXVzZS5cbiAgICAgKlxuICAgICAqIEBncm91cCBTdGF0aWMgTWV0aG9kc1xuICAgICAqL1xuICAgIHN0YXRpYyBhbGw8VD4odmFsdWVzOiBJdGVyYWJsZTxUIHwgUHJvbWlzZUxpa2U8VD4+KTogQ2FuY2VsbGFibGVQcm9taXNlPEF3YWl0ZWQ8VD5bXT47XG4gICAgc3RhdGljIGFsbDxUIGV4dGVuZHMgcmVhZG9ubHkgdW5rbm93bltdIHwgW10+KHZhbHVlczogVCk6IENhbmNlbGxhYmxlUHJvbWlzZTx7IC1yZWFkb25seSBbUCBpbiBrZXlvZiBUXTogQXdhaXRlZDxUW1BdPjsgfT47XG4gICAgc3RhdGljIGFsbDxUIGV4dGVuZHMgSXRlcmFibGU8dW5rbm93bj4gfCBBcnJheUxpa2U8dW5rbm93bj4+KHZhbHVlczogVCk6IENhbmNlbGxhYmxlUHJvbWlzZTx1bmtub3duPiB7XG4gICAgICAgIGxldCBjb2xsZWN0ZWQgPSBBcnJheS5mcm9tKHZhbHVlcyk7XG4gICAgICAgIGNvbnN0IHByb21pc2UgPSBjb2xsZWN0ZWQubGVuZ3RoID09PSAwXG4gICAgICAgICAgICA/IENhbmNlbGxhYmxlUHJvbWlzZS5yZXNvbHZlKGNvbGxlY3RlZClcbiAgICAgICAgICAgIDogbmV3IENhbmNlbGxhYmxlUHJvbWlzZTx1bmtub3duPigocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICAgICAgdm9pZCBQcm9taXNlLmFsbChjb2xsZWN0ZWQpLnRoZW4ocmVzb2x2ZSwgcmVqZWN0KTtcbiAgICAgICAgICAgIH0sIChjYXVzZT8pOiBQcm9taXNlPHZvaWQ+ID0+IGNhbmNlbEFsbChwcm9taXNlLCBjb2xsZWN0ZWQsIGNhdXNlKSk7XG4gICAgICAgIHJldHVybiBwcm9taXNlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBDYW5jZWxsYWJsZVByb21pc2UgdGhhdCBpcyByZXNvbHZlZCB3aXRoIGFuIGFycmF5IG9mIHJlc3VsdHNcbiAgICAgKiB3aGVuIGFsbCBvZiB0aGUgcHJvdmlkZWQgUHJvbWlzZXMgcmVzb2x2ZSBvciByZWplY3QuXG4gICAgICpcbiAgICAgKiBFdmVyeSBvbmUgb2YgdGhlIHByb3ZpZGVkIG9iamVjdHMgdGhhdCBpcyBhIHRoZW5hYmxlIF9hbmRfIGNhbmNlbGxhYmxlIG9iamVjdFxuICAgICAqIHdpbGwgYmUgY2FuY2VsbGVkIHdoZW4gdGhlIHJldHVybmVkIHByb21pc2UgaXMgY2FuY2VsbGVkLCB3aXRoIHRoZSBzYW1lIGNhdXNlLlxuICAgICAqXG4gICAgICogQGdyb3VwIFN0YXRpYyBNZXRob2RzXG4gICAgICovXG4gICAgc3RhdGljIGFsbFNldHRsZWQ8VD4odmFsdWVzOiBJdGVyYWJsZTxUIHwgUHJvbWlzZUxpa2U8VD4+KTogQ2FuY2VsbGFibGVQcm9taXNlPFByb21pc2VTZXR0bGVkUmVzdWx0PEF3YWl0ZWQ8VD4+W10+O1xuICAgIHN0YXRpYyBhbGxTZXR0bGVkPFQgZXh0ZW5kcyByZWFkb25seSB1bmtub3duW10gfCBbXT4odmFsdWVzOiBUKTogQ2FuY2VsbGFibGVQcm9taXNlPHsgLXJlYWRvbmx5IFtQIGluIGtleW9mIFRdOiBQcm9taXNlU2V0dGxlZFJlc3VsdDxBd2FpdGVkPFRbUF0+PjsgfT47XG4gICAgc3RhdGljIGFsbFNldHRsZWQ8VCBleHRlbmRzIEl0ZXJhYmxlPHVua25vd24+IHwgQXJyYXlMaWtlPHVua25vd24+Pih2YWx1ZXM6IFQpOiBDYW5jZWxsYWJsZVByb21pc2U8dW5rbm93bj4ge1xuICAgICAgICBsZXQgY29sbGVjdGVkID0gQXJyYXkuZnJvbSh2YWx1ZXMpO1xuICAgICAgICBjb25zdCBwcm9taXNlID0gY29sbGVjdGVkLmxlbmd0aCA9PT0gMFxuICAgICAgICAgICAgPyBDYW5jZWxsYWJsZVByb21pc2UucmVzb2x2ZShjb2xsZWN0ZWQpXG4gICAgICAgICAgICA6IG5ldyBDYW5jZWxsYWJsZVByb21pc2U8dW5rbm93bj4oKHJlc29sdmUsIHJlamVjdCkgPT4ge1xuICAgICAgICAgICAgICAgIHZvaWQgUHJvbWlzZS5hbGxTZXR0bGVkKGNvbGxlY3RlZCkudGhlbihyZXNvbHZlLCByZWplY3QpO1xuICAgICAgICAgICAgfSwgKGNhdXNlPyk6IFByb21pc2U8dm9pZD4gPT4gY2FuY2VsQWxsKHByb21pc2UsIGNvbGxlY3RlZCwgY2F1c2UpKTtcbiAgICAgICAgcmV0dXJuIHByb21pc2U7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogVGhlIGFueSBmdW5jdGlvbiByZXR1cm5zIGEgcHJvbWlzZSB0aGF0IGlzIGZ1bGZpbGxlZCBieSB0aGUgZmlyc3QgZ2l2ZW4gcHJvbWlzZSB0byBiZSBmdWxmaWxsZWQsXG4gICAgICogb3IgcmVqZWN0ZWQgd2l0aCBhbiBBZ2dyZWdhdGVFcnJvciBjb250YWluaW5nIGFuIGFycmF5IG9mIHJlamVjdGlvbiByZWFzb25zXG4gICAgICogaWYgYWxsIG9mIHRoZSBnaXZlbiBwcm9taXNlcyBhcmUgcmVqZWN0ZWQuXG4gICAgICogSXQgcmVzb2x2ZXMgYWxsIGVsZW1lbnRzIG9mIHRoZSBwYXNzZWQgaXRlcmFibGUgdG8gcHJvbWlzZXMgYXMgaXQgcnVucyB0aGlzIGFsZ29yaXRobS5cbiAgICAgKlxuICAgICAqIEV2ZXJ5IG9uZSBvZiB0aGUgcHJvdmlkZWQgb2JqZWN0cyB0aGF0IGlzIGEgdGhlbmFibGUgX2FuZF8gY2FuY2VsbGFibGUgb2JqZWN0XG4gICAgICogd2lsbCBiZSBjYW5jZWxsZWQgd2hlbiB0aGUgcmV0dXJuZWQgcHJvbWlzZSBpcyBjYW5jZWxsZWQsIHdpdGggdGhlIHNhbWUgY2F1c2UuXG4gICAgICpcbiAgICAgKiBAZ3JvdXAgU3RhdGljIE1ldGhvZHNcbiAgICAgKi9cbiAgICBzdGF0aWMgYW55PFQ+KHZhbHVlczogSXRlcmFibGU8VCB8IFByb21pc2VMaWtlPFQ+Pik6IENhbmNlbGxhYmxlUHJvbWlzZTxBd2FpdGVkPFQ+PjtcbiAgICBzdGF0aWMgYW55PFQgZXh0ZW5kcyByZWFkb25seSB1bmtub3duW10gfCBbXT4odmFsdWVzOiBUKTogQ2FuY2VsbGFibGVQcm9taXNlPEF3YWl0ZWQ8VFtudW1iZXJdPj47XG4gICAgc3RhdGljIGFueTxUIGV4dGVuZHMgSXRlcmFibGU8dW5rbm93bj4gfCBBcnJheUxpa2U8dW5rbm93bj4+KHZhbHVlczogVCk6IENhbmNlbGxhYmxlUHJvbWlzZTx1bmtub3duPiB7XG4gICAgICAgIGxldCBjb2xsZWN0ZWQgPSBBcnJheS5mcm9tKHZhbHVlcyk7XG4gICAgICAgIGNvbnN0IHByb21pc2UgPSBjb2xsZWN0ZWQubGVuZ3RoID09PSAwXG4gICAgICAgICAgICA/IENhbmNlbGxhYmxlUHJvbWlzZS5yZXNvbHZlKGNvbGxlY3RlZClcbiAgICAgICAgICAgIDogbmV3IENhbmNlbGxhYmxlUHJvbWlzZTx1bmtub3duPigocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICAgICAgICAgICAgdm9pZCBQcm9taXNlLmFueShjb2xsZWN0ZWQpLnRoZW4ocmVzb2x2ZSwgcmVqZWN0KTtcbiAgICAgICAgICAgIH0sIChjYXVzZT8pOiBQcm9taXNlPHZvaWQ+ID0+IGNhbmNlbEFsbChwcm9taXNlLCBjb2xsZWN0ZWQsIGNhdXNlKSk7XG4gICAgICAgIHJldHVybiBwcm9taXNlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBQcm9taXNlIHRoYXQgaXMgcmVzb2x2ZWQgb3IgcmVqZWN0ZWQgd2hlbiBhbnkgb2YgdGhlIHByb3ZpZGVkIFByb21pc2VzIGFyZSByZXNvbHZlZCBvciByZWplY3RlZC5cbiAgICAgKlxuICAgICAqIEV2ZXJ5IG9uZSBvZiB0aGUgcHJvdmlkZWQgb2JqZWN0cyB0aGF0IGlzIGEgdGhlbmFibGUgX2FuZF8gY2FuY2VsbGFibGUgb2JqZWN0XG4gICAgICogd2lsbCBiZSBjYW5jZWxsZWQgd2hlbiB0aGUgcmV0dXJuZWQgcHJvbWlzZSBpcyBjYW5jZWxsZWQsIHdpdGggdGhlIHNhbWUgY2F1c2UuXG4gICAgICpcbiAgICAgKiBAZ3JvdXAgU3RhdGljIE1ldGhvZHNcbiAgICAgKi9cbiAgICBzdGF0aWMgcmFjZTxUPih2YWx1ZXM6IEl0ZXJhYmxlPFQgfCBQcm9taXNlTGlrZTxUPj4pOiBDYW5jZWxsYWJsZVByb21pc2U8QXdhaXRlZDxUPj47XG4gICAgc3RhdGljIHJhY2U8VCBleHRlbmRzIHJlYWRvbmx5IHVua25vd25bXSB8IFtdPih2YWx1ZXM6IFQpOiBDYW5jZWxsYWJsZVByb21pc2U8QXdhaXRlZDxUW251bWJlcl0+PjtcbiAgICBzdGF0aWMgcmFjZTxUIGV4dGVuZHMgSXRlcmFibGU8dW5rbm93bj4gfCBBcnJheUxpa2U8dW5rbm93bj4+KHZhbHVlczogVCk6IENhbmNlbGxhYmxlUHJvbWlzZTx1bmtub3duPiB7XG4gICAgICAgIGxldCBjb2xsZWN0ZWQgPSBBcnJheS5mcm9tKHZhbHVlcyk7XG4gICAgICAgIGNvbnN0IHByb21pc2UgPSBuZXcgQ2FuY2VsbGFibGVQcm9taXNlPHVua25vd24+KChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIHZvaWQgUHJvbWlzZS5yYWNlKGNvbGxlY3RlZCkudGhlbihyZXNvbHZlLCByZWplY3QpO1xuICAgICAgICB9LCAoY2F1c2U/KTogUHJvbWlzZTx2b2lkPiA9PiBjYW5jZWxBbGwocHJvbWlzZSwgY29sbGVjdGVkLCBjYXVzZSkpO1xuICAgICAgICByZXR1cm4gcHJvbWlzZTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgbmV3IGNhbmNlbGxlZCBDYW5jZWxsYWJsZVByb21pc2UgZm9yIHRoZSBwcm92aWRlZCBjYXVzZS5cbiAgICAgKlxuICAgICAqIEBncm91cCBTdGF0aWMgTWV0aG9kc1xuICAgICAqL1xuICAgIHN0YXRpYyBjYW5jZWw8VCA9IG5ldmVyPihjYXVzZT86IGFueSk6IENhbmNlbGxhYmxlUHJvbWlzZTxUPiB7XG4gICAgICAgIGNvbnN0IHAgPSBuZXcgQ2FuY2VsbGFibGVQcm9taXNlPFQ+KCgpID0+IHt9KTtcbiAgICAgICAgcC5jYW5jZWwoY2F1c2UpO1xuICAgICAgICByZXR1cm4gcDtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgbmV3IENhbmNlbGxhYmxlUHJvbWlzZSB0aGF0IGNhbmNlbHNcbiAgICAgKiBhZnRlciB0aGUgc3BlY2lmaWVkIHRpbWVvdXQsIHdpdGggdGhlIHByb3ZpZGVkIGNhdXNlLlxuICAgICAqXG4gICAgICogSWYgdGhlIHtAbGluayBBYm9ydFNpZ25hbC50aW1lb3V0fSBmYWN0b3J5IG1ldGhvZCBpcyBhdmFpbGFibGUsXG4gICAgICogaXQgaXMgdXNlZCB0byBiYXNlIHRoZSB0aW1lb3V0IG9uIF9hY3RpdmVfIHRpbWUgcmF0aGVyIHRoYW4gX2VsYXBzZWRfIHRpbWUuXG4gICAgICogT3RoZXJ3aXNlLCBgdGltZW91dGAgZmFsbHMgYmFjayB0byB7QGxpbmsgc2V0VGltZW91dH0uXG4gICAgICpcbiAgICAgKiBAZ3JvdXAgU3RhdGljIE1ldGhvZHNcbiAgICAgKi9cbiAgICBzdGF0aWMgdGltZW91dDxUID0gbmV2ZXI+KG1pbGxpc2Vjb25kczogbnVtYmVyLCBjYXVzZT86IGFueSk6IENhbmNlbGxhYmxlUHJvbWlzZTxUPiB7XG4gICAgICAgIGNvbnN0IHByb21pc2UgPSBuZXcgQ2FuY2VsbGFibGVQcm9taXNlPFQ+KCgpID0+IHt9KTtcbiAgICAgICAgaWYgKEFib3J0U2lnbmFsICYmIHR5cGVvZiBBYm9ydFNpZ25hbCA9PT0gJ2Z1bmN0aW9uJyAmJiBBYm9ydFNpZ25hbC50aW1lb3V0ICYmIHR5cGVvZiBBYm9ydFNpZ25hbC50aW1lb3V0ID09PSAnZnVuY3Rpb24nKSB7XG4gICAgICAgICAgICBBYm9ydFNpZ25hbC50aW1lb3V0KG1pbGxpc2Vjb25kcykuYWRkRXZlbnRMaXN0ZW5lcignYWJvcnQnLCAoKSA9PiB2b2lkIHByb21pc2UuY2FuY2VsKGNhdXNlKSk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBzZXRUaW1lb3V0KCgpID0+IHZvaWQgcHJvbWlzZS5jYW5jZWwoY2F1c2UpLCBtaWxsaXNlY29uZHMpO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBwcm9taXNlO1xuICAgIH1cblxuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBuZXcgQ2FuY2VsbGFibGVQcm9taXNlIHRoYXQgcmVzb2x2ZXMgYWZ0ZXIgdGhlIHNwZWNpZmllZCB0aW1lb3V0LlxuICAgICAqIFRoZSByZXR1cm5lZCBwcm9taXNlIGNhbiBiZSBjYW5jZWxsZWQgd2l0aG91dCBjb25zZXF1ZW5jZXMuXG4gICAgICpcbiAgICAgKiBAZ3JvdXAgU3RhdGljIE1ldGhvZHNcbiAgICAgKi9cbiAgICBzdGF0aWMgc2xlZXAobWlsbGlzZWNvbmRzOiBudW1iZXIpOiBDYW5jZWxsYWJsZVByb21pc2U8dm9pZD47XG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIG5ldyBDYW5jZWxsYWJsZVByb21pc2UgdGhhdCByZXNvbHZlcyBhZnRlclxuICAgICAqIHRoZSBzcGVjaWZpZWQgdGltZW91dCwgd2l0aCB0aGUgcHJvdmlkZWQgdmFsdWUuXG4gICAgICogVGhlIHJldHVybmVkIHByb21pc2UgY2FuIGJlIGNhbmNlbGxlZCB3aXRob3V0IGNvbnNlcXVlbmNlcy5cbiAgICAgKlxuICAgICAqIEBncm91cCBTdGF0aWMgTWV0aG9kc1xuICAgICAqL1xuICAgIHN0YXRpYyBzbGVlcDxUPihtaWxsaXNlY29uZHM6IG51bWJlciwgdmFsdWU6IFQpOiBDYW5jZWxsYWJsZVByb21pc2U8VD47XG4gICAgc3RhdGljIHNsZWVwPFQgPSB2b2lkPihtaWxsaXNlY29uZHM6IG51bWJlciwgdmFsdWU/OiBUKTogQ2FuY2VsbGFibGVQcm9taXNlPFQ+IHtcbiAgICAgICAgcmV0dXJuIG5ldyBDYW5jZWxsYWJsZVByb21pc2U8VD4oKHJlc29sdmUpID0+IHtcbiAgICAgICAgICAgIHNldFRpbWVvdXQoKCkgPT4gcmVzb2x2ZSh2YWx1ZSEpLCBtaWxsaXNlY29uZHMpO1xuICAgICAgICB9KTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgbmV3IHJlamVjdGVkIENhbmNlbGxhYmxlUHJvbWlzZSBmb3IgdGhlIHByb3ZpZGVkIHJlYXNvbi5cbiAgICAgKlxuICAgICAqIEBncm91cCBTdGF0aWMgTWV0aG9kc1xuICAgICAqL1xuICAgIHN0YXRpYyByZWplY3Q8VCA9IG5ldmVyPihyZWFzb24/OiBhbnkpOiBDYW5jZWxsYWJsZVByb21pc2U8VD4ge1xuICAgICAgICByZXR1cm4gbmV3IENhbmNlbGxhYmxlUHJvbWlzZTxUPigoXywgcmVqZWN0KSA9PiByZWplY3QocmVhc29uKSk7XG4gICAgfVxuXG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIG5ldyByZXNvbHZlZCBDYW5jZWxsYWJsZVByb21pc2UuXG4gICAgICpcbiAgICAgKiBAZ3JvdXAgU3RhdGljIE1ldGhvZHNcbiAgICAgKi9cbiAgICBzdGF0aWMgcmVzb2x2ZSgpOiBDYW5jZWxsYWJsZVByb21pc2U8dm9pZD47XG4gICAgLyoqXG4gICAgICogQ3JlYXRlcyBhIG5ldyByZXNvbHZlZCBDYW5jZWxsYWJsZVByb21pc2UgZm9yIHRoZSBwcm92aWRlZCB2YWx1ZS5cbiAgICAgKlxuICAgICAqIEBncm91cCBTdGF0aWMgTWV0aG9kc1xuICAgICAqL1xuICAgIHN0YXRpYyByZXNvbHZlPFQ+KHZhbHVlOiBUKTogQ2FuY2VsbGFibGVQcm9taXNlPEF3YWl0ZWQ8VD4+O1xuICAgIC8qKlxuICAgICAqIENyZWF0ZXMgYSBuZXcgcmVzb2x2ZWQgQ2FuY2VsbGFibGVQcm9taXNlIGZvciB0aGUgcHJvdmlkZWQgdmFsdWUuXG4gICAgICpcbiAgICAgKiBAZ3JvdXAgU3RhdGljIE1ldGhvZHNcbiAgICAgKi9cbiAgICBzdGF0aWMgcmVzb2x2ZTxUPih2YWx1ZTogVCB8IFByb21pc2VMaWtlPFQ+KTogQ2FuY2VsbGFibGVQcm9taXNlPEF3YWl0ZWQ8VD4+O1xuICAgIHN0YXRpYyByZXNvbHZlPFQgPSB2b2lkPih2YWx1ZT86IFQgfCBQcm9taXNlTGlrZTxUPik6IENhbmNlbGxhYmxlUHJvbWlzZTxBd2FpdGVkPFQ+PiB7XG4gICAgICAgIGlmICh2YWx1ZSBpbnN0YW5jZW9mIENhbmNlbGxhYmxlUHJvbWlzZSkge1xuICAgICAgICAgICAgLy8gT3B0aW1pc2UgZm9yIGNhbmNlbGxhYmxlIHByb21pc2VzLlxuICAgICAgICAgICAgcmV0dXJuIHZhbHVlO1xuICAgICAgICB9XG4gICAgICAgIHJldHVybiBuZXcgQ2FuY2VsbGFibGVQcm9taXNlPGFueT4oKHJlc29sdmUpID0+IHJlc29sdmUodmFsdWUpKTtcbiAgICB9XG5cbiAgICAvKipcbiAgICAgKiBDcmVhdGVzIGEgbmV3IENhbmNlbGxhYmxlUHJvbWlzZSBhbmQgcmV0dXJucyBpdCBpbiBhbiBvYmplY3QsIGFsb25nIHdpdGggaXRzIHJlc29sdmUgYW5kIHJlamVjdCBmdW5jdGlvbnNcbiAgICAgKiBhbmQgYSBnZXR0ZXIvc2V0dGVyIGZvciB0aGUgY2FuY2VsbGF0aW9uIGNhbGxiYWNrLlxuICAgICAqXG4gICAgICogVGhpcyBtZXRob2QgaXMgcG9seWZpbGxlZCwgaGVuY2UgYXZhaWxhYmxlIGluIGV2ZXJ5IE9TL3dlYnZpZXcgdmVyc2lvbi5cbiAgICAgKlxuICAgICAqIEBncm91cCBTdGF0aWMgTWV0aG9kc1xuICAgICAqL1xuICAgIHN0YXRpYyB3aXRoUmVzb2x2ZXJzPFQ+KCk6IENhbmNlbGxhYmxlUHJvbWlzZVdpdGhSZXNvbHZlcnM8VD4ge1xuICAgICAgICBsZXQgcmVzdWx0OiBDYW5jZWxsYWJsZVByb21pc2VXaXRoUmVzb2x2ZXJzPFQ+ID0geyBvbmNhbmNlbGxlZDogbnVsbCB9IGFzIGFueTtcbiAgICAgICAgcmVzdWx0LnByb21pc2UgPSBuZXcgQ2FuY2VsbGFibGVQcm9taXNlPFQ+KChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgICAgICAgIHJlc3VsdC5yZXNvbHZlID0gcmVzb2x2ZTtcbiAgICAgICAgICAgIHJlc3VsdC5yZWplY3QgPSByZWplY3Q7XG4gICAgICAgIH0sIChjYXVzZT86IGFueSkgPT4geyByZXN1bHQub25jYW5jZWxsZWQ/LihjYXVzZSk7IH0pO1xuICAgICAgICByZXR1cm4gcmVzdWx0O1xuICAgIH1cbn1cblxuLyoqXG4gKiBSZXR1cm5zIGEgY2FsbGJhY2sgdGhhdCBpbXBsZW1lbnRzIHRoZSBjYW5jZWxsYXRpb24gYWxnb3JpdGhtIGZvciB0aGUgZ2l2ZW4gY2FuY2VsbGFibGUgcHJvbWlzZS5cbiAqIFRoZSBwcm9taXNlIHJldHVybmVkIGZyb20gdGhlIHJlc3VsdGluZyBmdW5jdGlvbiBkb2VzIG5vdCByZWplY3QuXG4gKi9cbmZ1bmN0aW9uIGNhbmNlbGxlckZvcjxUPihwcm9taXNlOiBDYW5jZWxsYWJsZVByb21pc2VXaXRoUmVzb2x2ZXJzPFQ+LCBzdGF0ZTogQ2FuY2VsbGFibGVQcm9taXNlU3RhdGUpIHtcbiAgICBsZXQgY2FuY2VsbGF0aW9uUHJvbWlzZTogdm9pZCB8IFByb21pc2VMaWtlPHZvaWQ+ID0gdW5kZWZpbmVkO1xuXG4gICAgcmV0dXJuIChyZWFzb246IENhbmNlbEVycm9yKTogdm9pZCB8IFByb21pc2VMaWtlPHZvaWQ+ID0+IHtcbiAgICAgICAgaWYgKCFzdGF0ZS5zZXR0bGVkKSB7XG4gICAgICAgICAgICBzdGF0ZS5zZXR0bGVkID0gdHJ1ZTtcbiAgICAgICAgICAgIHN0YXRlLnJlYXNvbiA9IHJlYXNvbjtcbiAgICAgICAgICAgIHByb21pc2UucmVqZWN0KHJlYXNvbik7XG5cbiAgICAgICAgICAgIC8vIEF0dGFjaCBhbiBlcnJvciBoYW5kbGVyIHRoYXQgaWdub3JlcyB0aGlzIHNwZWNpZmljIHJlamVjdGlvbiByZWFzb24gYW5kIG5vdGhpbmcgZWxzZS5cbiAgICAgICAgICAgIC8vIEluIHRoZW9yeSwgYSBzYW5lIHVuZGVybHlpbmcgaW1wbGVtZW50YXRpb24gYXQgdGhpcyBwb2ludFxuICAgICAgICAgICAgLy8gc2hvdWxkIGFsd2F5cyByZWplY3Qgd2l0aCBvdXIgY2FuY2VsbGF0aW9uIHJlYXNvbixcbiAgICAgICAgICAgIC8vIGhlbmNlIHRoZSBoYW5kbGVyIHdpbGwgbmV2ZXIgdGhyb3cuXG4gICAgICAgICAgICB2b2lkIFByb21pc2UucHJvdG90eXBlLnRoZW4uY2FsbChwcm9taXNlLnByb21pc2UsIHVuZGVmaW5lZCwgKGVycikgPT4ge1xuICAgICAgICAgICAgICAgIGlmIChlcnIgIT09IHJlYXNvbikge1xuICAgICAgICAgICAgICAgICAgICB0aHJvdyBlcnI7XG4gICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgfSk7XG4gICAgICAgIH1cblxuICAgICAgICAvLyBJZiByZWFzb24gaXMgbm90IHNldCwgdGhlIHByb21pc2UgcmVzb2x2ZWQgcmVndWxhcmx5LCBoZW5jZSB3ZSBtdXN0IG5vdCBjYWxsIG9uY2FuY2VsbGVkLlxuICAgICAgICAvLyBJZiBvbmNhbmNlbGxlZCBpcyB1bnNldCwgbm8gbmVlZCB0byBnbyBhbnkgZnVydGhlci5cbiAgICAgICAgaWYgKCFzdGF0ZS5yZWFzb24gfHwgIXByb21pc2Uub25jYW5jZWxsZWQpIHsgcmV0dXJuOyB9XG5cbiAgICAgICAgY2FuY2VsbGF0aW9uUHJvbWlzZSA9IG5ldyBQcm9taXNlPHZvaWQ+KChyZXNvbHZlKSA9PiB7XG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgIHJlc29sdmUocHJvbWlzZS5vbmNhbmNlbGxlZCEoc3RhdGUucmVhc29uIS5jYXVzZSkpO1xuICAgICAgICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgICAgICAgUHJvbWlzZS5yZWplY3QobmV3IENhbmNlbGxlZFJlamVjdGlvbkVycm9yKHByb21pc2UucHJvbWlzZSwgZXJyLCBcIlVuaGFuZGxlZCBleGNlcHRpb24gaW4gb25jYW5jZWxsZWQgY2FsbGJhY2suXCIpKTtcbiAgICAgICAgICAgIH1cbiAgICAgICAgfSkuY2F0Y2goKHJlYXNvbj8pID0+IHtcbiAgICAgICAgICAgIFByb21pc2UucmVqZWN0KG5ldyBDYW5jZWxsZWRSZWplY3Rpb25FcnJvcihwcm9taXNlLnByb21pc2UsIHJlYXNvbiwgXCJVbmhhbmRsZWQgcmVqZWN0aW9uIGluIG9uY2FuY2VsbGVkIGNhbGxiYWNrLlwiKSk7XG4gICAgICAgIH0pO1xuXG4gICAgICAgIC8vIFVuc2V0IG9uY2FuY2VsbGVkIHRvIHByZXZlbnQgcmVwZWF0ZWQgY2FsbHMuXG4gICAgICAgIHByb21pc2Uub25jYW5jZWxsZWQgPSBudWxsO1xuXG4gICAgICAgIHJldHVybiBjYW5jZWxsYXRpb25Qcm9taXNlO1xuICAgIH1cbn1cblxuLyoqXG4gKiBSZXR1cm5zIGEgY2FsbGJhY2sgdGhhdCBpbXBsZW1lbnRzIHRoZSByZXNvbHV0aW9uIGFsZ29yaXRobSBmb3IgdGhlIGdpdmVuIGNhbmNlbGxhYmxlIHByb21pc2UuXG4gKi9cbmZ1bmN0aW9uIHJlc29sdmVyRm9yPFQ+KHByb21pc2U6IENhbmNlbGxhYmxlUHJvbWlzZVdpdGhSZXNvbHZlcnM8VD4sIHN0YXRlOiBDYW5jZWxsYWJsZVByb21pc2VTdGF0ZSk6IENhbmNlbGxhYmxlUHJvbWlzZVJlc29sdmVyPFQ+IHtcbiAgICByZXR1cm4gKHZhbHVlKSA9PiB7XG4gICAgICAgIGlmIChzdGF0ZS5yZXNvbHZpbmcpIHsgcmV0dXJuOyB9XG4gICAgICAgIHN0YXRlLnJlc29sdmluZyA9IHRydWU7XG5cbiAgICAgICAgaWYgKHZhbHVlID09PSBwcm9taXNlLnByb21pc2UpIHtcbiAgICAgICAgICAgIGlmIChzdGF0ZS5zZXR0bGVkKSB7IHJldHVybjsgfVxuICAgICAgICAgICAgc3RhdGUuc2V0dGxlZCA9IHRydWU7XG4gICAgICAgICAgICBwcm9taXNlLnJlamVjdChuZXcgVHlwZUVycm9yKFwiQSBwcm9taXNlIGNhbm5vdCBiZSByZXNvbHZlZCB3aXRoIGl0c2VsZi5cIikpO1xuICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICB9XG5cbiAgICAgICAgaWYgKHZhbHVlICE9IG51bGwgJiYgKHR5cGVvZiB2YWx1ZSA9PT0gJ29iamVjdCcgfHwgdHlwZW9mIHZhbHVlID09PSAnZnVuY3Rpb24nKSkge1xuICAgICAgICAgICAgbGV0IHRoZW46IGFueTtcbiAgICAgICAgICAgIHRyeSB7XG4gICAgICAgICAgICAgICAgdGhlbiA9ICh2YWx1ZSBhcyBhbnkpLnRoZW47XG4gICAgICAgICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgICAgICAgICBzdGF0ZS5zZXR0bGVkID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICBwcm9taXNlLnJlamVjdChlcnIpO1xuICAgICAgICAgICAgICAgIHJldHVybjtcbiAgICAgICAgICAgIH1cblxuICAgICAgICAgICAgaWYgKGlzQ2FsbGFibGUodGhlbikpIHtcbiAgICAgICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgICAgICBsZXQgY2FuY2VsID0gKHZhbHVlIGFzIGFueSkuY2FuY2VsO1xuICAgICAgICAgICAgICAgICAgICBpZiAoaXNDYWxsYWJsZShjYW5jZWwpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zdCBvbmNhbmNlbGxlZCA9IChjYXVzZT86IGFueSkgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIFJlZmxlY3QuYXBwbHkoY2FuY2VsLCB2YWx1ZSwgW2NhdXNlXSk7XG4gICAgICAgICAgICAgICAgICAgICAgICB9O1xuICAgICAgICAgICAgICAgICAgICAgICAgaWYgKHN0YXRlLnJlYXNvbikge1xuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIElmIGFscmVhZHkgY2FuY2VsbGVkLCBwcm9wYWdhdGUgY2FuY2VsbGF0aW9uLlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgIC8vIFRoZSBwcm9taXNlIHJldHVybmVkIGZyb20gdGhlIGNhbmNlbGxlciBhbGdvcml0aG0gZG9lcyBub3QgcmVqZWN0XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgLy8gc28gaXQgY2FuIGJlIGRpc2NhcmRlZCBzYWZlbHkuXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgdm9pZCBjYW5jZWxsZXJGb3IoeyAuLi5wcm9taXNlLCBvbmNhbmNlbGxlZCB9LCBzdGF0ZSkoc3RhdGUucmVhc29uKTtcbiAgICAgICAgICAgICAgICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgcHJvbWlzZS5vbmNhbmNlbGxlZCA9IG9uY2FuY2VsbGVkO1xuICAgICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgfSBjYXRjaCB7fVxuXG4gICAgICAgICAgICAgICAgY29uc3QgbmV3U3RhdGU6IENhbmNlbGxhYmxlUHJvbWlzZVN0YXRlID0ge1xuICAgICAgICAgICAgICAgICAgICByb290OiBzdGF0ZS5yb290LFxuICAgICAgICAgICAgICAgICAgICByZXNvbHZpbmc6IGZhbHNlLFxuICAgICAgICAgICAgICAgICAgICBnZXQgc2V0dGxlZCgpIHsgcmV0dXJuIHRoaXMucm9vdC5zZXR0bGVkIH0sXG4gICAgICAgICAgICAgICAgICAgIHNldCBzZXR0bGVkKHZhbHVlKSB7IHRoaXMucm9vdC5zZXR0bGVkID0gdmFsdWU7IH0sXG4gICAgICAgICAgICAgICAgICAgIGdldCByZWFzb24oKSB7IHJldHVybiB0aGlzLnJvb3QucmVhc29uIH1cbiAgICAgICAgICAgICAgICB9O1xuXG4gICAgICAgICAgICAgICAgY29uc3QgcmVqZWN0b3IgPSByZWplY3RvckZvcihwcm9taXNlLCBuZXdTdGF0ZSk7XG4gICAgICAgICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgICAgICAgICAgUmVmbGVjdC5hcHBseSh0aGVuLCB2YWx1ZSwgW3Jlc29sdmVyRm9yKHByb21pc2UsIG5ld1N0YXRlKSwgcmVqZWN0b3JdKTtcbiAgICAgICAgICAgICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgICAgICAgICAgICAgcmVqZWN0b3IoZXJyKTtcbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgcmV0dXJuOyAvLyBJTVBPUlRBTlQhXG4gICAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICBpZiAoc3RhdGUuc2V0dGxlZCkgeyByZXR1cm47IH1cbiAgICAgICAgc3RhdGUuc2V0dGxlZCA9IHRydWU7XG4gICAgICAgIHByb21pc2UucmVzb2x2ZSh2YWx1ZSk7XG4gICAgfTtcbn1cblxuLyoqXG4gKiBSZXR1cm5zIGEgY2FsbGJhY2sgdGhhdCBpbXBsZW1lbnRzIHRoZSByZWplY3Rpb24gYWxnb3JpdGhtIGZvciB0aGUgZ2l2ZW4gY2FuY2VsbGFibGUgcHJvbWlzZS5cbiAqL1xuZnVuY3Rpb24gcmVqZWN0b3JGb3I8VD4ocHJvbWlzZTogQ2FuY2VsbGFibGVQcm9taXNlV2l0aFJlc29sdmVyczxUPiwgc3RhdGU6IENhbmNlbGxhYmxlUHJvbWlzZVN0YXRlKTogQ2FuY2VsbGFibGVQcm9taXNlUmVqZWN0b3Ige1xuICAgIHJldHVybiAocmVhc29uPykgPT4ge1xuICAgICAgICBpZiAoc3RhdGUucmVzb2x2aW5nKSB7IHJldHVybjsgfVxuICAgICAgICBzdGF0ZS5yZXNvbHZpbmcgPSB0cnVlO1xuXG4gICAgICAgIGlmIChzdGF0ZS5zZXR0bGVkKSB7XG4gICAgICAgICAgICB0cnkge1xuICAgICAgICAgICAgICAgIGlmIChyZWFzb24gaW5zdGFuY2VvZiBDYW5jZWxFcnJvciAmJiBzdGF0ZS5yZWFzb24gaW5zdGFuY2VvZiBDYW5jZWxFcnJvciAmJiBPYmplY3QuaXMocmVhc29uLmNhdXNlLCBzdGF0ZS5yZWFzb24uY2F1c2UpKSB7XG4gICAgICAgICAgICAgICAgICAgIC8vIFN3YWxsb3cgbGF0ZSByZWplY3Rpb25zIHRoYXQgYXJlIENhbmNlbEVycm9ycyB3aG9zZSBjYW5jZWxsYXRpb24gY2F1c2UgaXMgdGhlIHNhbWUgYXMgb3Vycy5cbiAgICAgICAgICAgICAgICAgICAgcmV0dXJuO1xuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIH0gY2F0Y2gge31cblxuICAgICAgICAgICAgdm9pZCBQcm9taXNlLnJlamVjdChuZXcgQ2FuY2VsbGVkUmVqZWN0aW9uRXJyb3IocHJvbWlzZS5wcm9taXNlLCByZWFzb24pKTtcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHN0YXRlLnNldHRsZWQgPSB0cnVlO1xuICAgICAgICAgICAgcHJvbWlzZS5yZWplY3QocmVhc29uKTtcbiAgICAgICAgfVxuICAgIH1cbn1cblxuLyoqXG4gKiBDYW5jZWxzIGFsbCB2YWx1ZXMgaW4gYW4gYXJyYXkgdGhhdCBsb29rIGxpa2UgY2FuY2VsbGFibGUgdGhlbmFibGVzLlxuICogUmV0dXJucyBhIHByb21pc2UgdGhhdCBmdWxmaWxscyBvbmNlIGFsbCBjYW5jZWxsYXRpb24gcHJvY2VkdXJlcyBmb3IgdGhlIGdpdmVuIHZhbHVlcyBoYXZlIHNldHRsZWQuXG4gKi9cbmZ1bmN0aW9uIGNhbmNlbEFsbChwYXJlbnQ6IENhbmNlbGxhYmxlUHJvbWlzZTx1bmtub3duPiwgdmFsdWVzOiBhbnlbXSwgY2F1c2U/OiBhbnkpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBjb25zdCByZXN1bHRzOiBQcm9taXNlPHZvaWQ+W10gPSBbXTtcblxuICAgIGZvciAoY29uc3QgdmFsdWUgb2YgdmFsdWVzKSB7XG4gICAgICAgIGxldCBjYW5jZWw6IENhbmNlbGxhYmxlUHJvbWlzZUNhbmNlbGxlcjtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIGlmICghaXNDYWxsYWJsZSh2YWx1ZS50aGVuKSkgeyBjb250aW51ZTsgfVxuICAgICAgICAgICAgY2FuY2VsID0gdmFsdWUuY2FuY2VsO1xuICAgICAgICAgICAgaWYgKCFpc0NhbGxhYmxlKGNhbmNlbCkpIHsgY29udGludWU7IH1cbiAgICAgICAgfSBjYXRjaCB7IGNvbnRpbnVlOyB9XG5cbiAgICAgICAgbGV0IHJlc3VsdDogdm9pZCB8IFByb21pc2VMaWtlPHZvaWQ+O1xuICAgICAgICB0cnkge1xuICAgICAgICAgICAgcmVzdWx0ID0gUmVmbGVjdC5hcHBseShjYW5jZWwsIHZhbHVlLCBbY2F1c2VdKTtcbiAgICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgICBQcm9taXNlLnJlamVjdChuZXcgQ2FuY2VsbGVkUmVqZWN0aW9uRXJyb3IocGFyZW50LCBlcnIsIFwiVW5oYW5kbGVkIGV4Y2VwdGlvbiBpbiBjYW5jZWwgbWV0aG9kLlwiKSk7XG4gICAgICAgICAgICBjb250aW51ZTtcbiAgICAgICAgfVxuXG4gICAgICAgIGlmICghcmVzdWx0KSB7IGNvbnRpbnVlOyB9XG4gICAgICAgIHJlc3VsdHMucHVzaChcbiAgICAgICAgICAgIChyZXN1bHQgaW5zdGFuY2VvZiBQcm9taXNlICA/IHJlc3VsdCA6IFByb21pc2UucmVzb2x2ZShyZXN1bHQpKS5jYXRjaCgocmVhc29uPykgPT4ge1xuICAgICAgICAgICAgICAgIFByb21pc2UucmVqZWN0KG5ldyBDYW5jZWxsZWRSZWplY3Rpb25FcnJvcihwYXJlbnQsIHJlYXNvbiwgXCJVbmhhbmRsZWQgcmVqZWN0aW9uIGluIGNhbmNlbCBtZXRob2QuXCIpKTtcbiAgICAgICAgICAgIH0pXG4gICAgICAgICk7XG4gICAgfVxuXG4gICAgcmV0dXJuIFByb21pc2UuYWxsKHJlc3VsdHMpIGFzIGFueTtcbn1cblxuLyoqXG4gKiBSZXR1cm5zIGl0cyBhcmd1bWVudC5cbiAqL1xuZnVuY3Rpb24gaWRlbnRpdHk8VD4oeDogVCk6IFQge1xuICAgIHJldHVybiB4O1xufVxuXG4vKipcbiAqIFRocm93cyBpdHMgYXJndW1lbnQuXG4gKi9cbmZ1bmN0aW9uIHRocm93ZXIocmVhc29uPzogYW55KTogbmV2ZXIge1xuICAgIHRocm93IHJlYXNvbjtcbn1cblxuLyoqXG4gKiBBdHRlbXB0cyB2YXJpb3VzIHN0cmF0ZWdpZXMgdG8gY29udmVydCBhbiBlcnJvciB0byBhIHN0cmluZy5cbiAqL1xuZnVuY3Rpb24gZXJyb3JNZXNzYWdlKGVycjogYW55KTogc3RyaW5nIHtcbiAgICB0cnkge1xuICAgICAgICBpZiAoZXJyIGluc3RhbmNlb2YgRXJyb3IgfHwgdHlwZW9mIGVyciAhPT0gJ29iamVjdCcgfHwgZXJyLnRvU3RyaW5nICE9PSBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nKSB7XG4gICAgICAgICAgICByZXR1cm4gXCJcIiArIGVycjtcbiAgICAgICAgfVxuICAgIH0gY2F0Y2gge31cblxuICAgIHRyeSB7XG4gICAgICAgIHJldHVybiBKU09OLnN0cmluZ2lmeShlcnIpO1xuICAgIH0gY2F0Y2gge31cblxuICAgIHRyeSB7XG4gICAgICAgIHJldHVybiBPYmplY3QucHJvdG90eXBlLnRvU3RyaW5nLmNhbGwoZXJyKTtcbiAgICB9IGNhdGNoIHt9XG5cbiAgICByZXR1cm4gXCI8Y291bGQgbm90IGNvbnZlcnQgZXJyb3IgdG8gc3RyaW5nPlwiO1xufVxuXG4vKipcbiAqIEdldHMgdGhlIGN1cnJlbnQgYmFycmllciBwcm9taXNlIGZvciB0aGUgZ2l2ZW4gY2FuY2VsbGFibGUgcHJvbWlzZS4gSWYgbmVjZXNzYXJ5LCBpbml0aWFsaXNlcyB0aGUgYmFycmllci5cbiAqL1xuZnVuY3Rpb24gY3VycmVudEJhcnJpZXI8VD4ocHJvbWlzZTogQ2FuY2VsbGFibGVQcm9taXNlPFQ+KTogUHJvbWlzZTx2b2lkPiB7XG4gICAgbGV0IHB3cjogUGFydGlhbDxQcm9taXNlV2l0aFJlc29sdmVyczx2b2lkPj4gPSBwcm9taXNlW2JhcnJpZXJTeW1dID8/IHt9O1xuICAgIGlmICghKCdwcm9taXNlJyBpbiBwd3IpKSB7XG4gICAgICAgIE9iamVjdC5hc3NpZ24ocHdyLCBwcm9taXNlV2l0aFJlc29sdmVyczx2b2lkPigpKTtcbiAgICB9XG4gICAgaWYgKHByb21pc2VbYmFycmllclN5bV0gPT0gbnVsbCkge1xuICAgICAgICBwd3IucmVzb2x2ZSEoKTtcbiAgICAgICAgcHJvbWlzZVtiYXJyaWVyU3ltXSA9IHB3cjtcbiAgICB9XG4gICAgcmV0dXJuIHB3ci5wcm9taXNlITtcbn1cblxuLy8gUG9seWZpbGwgUHJvbWlzZS53aXRoUmVzb2x2ZXJzLlxubGV0IHByb21pc2VXaXRoUmVzb2x2ZXJzID0gUHJvbWlzZS53aXRoUmVzb2x2ZXJzO1xuaWYgKHByb21pc2VXaXRoUmVzb2x2ZXJzICYmIHR5cGVvZiBwcm9taXNlV2l0aFJlc29sdmVycyA9PT0gJ2Z1bmN0aW9uJykge1xuICAgIHByb21pc2VXaXRoUmVzb2x2ZXJzID0gcHJvbWlzZVdpdGhSZXNvbHZlcnMuYmluZChQcm9taXNlKTtcbn0gZWxzZSB7XG4gICAgcHJvbWlzZVdpdGhSZXNvbHZlcnMgPSBmdW5jdGlvbiA8VD4oKTogUHJvbWlzZVdpdGhSZXNvbHZlcnM8VD4ge1xuICAgICAgICBsZXQgcmVzb2x2ZSE6ICh2YWx1ZTogVCB8IFByb21pc2VMaWtlPFQ+KSA9PiB2b2lkO1xuICAgICAgICBsZXQgcmVqZWN0ITogKHJlYXNvbj86IGFueSkgPT4gdm9pZDtcbiAgICAgICAgY29uc3QgcHJvbWlzZSA9IG5ldyBQcm9taXNlPFQ+KChyZXMsIHJlaikgPT4geyByZXNvbHZlID0gcmVzOyByZWplY3QgPSByZWo7IH0pO1xuICAgICAgICByZXR1cm4geyBwcm9taXNlLCByZXNvbHZlLCByZWplY3QgfTtcbiAgICB9XG59XG4iLCAiLypcbiBfXHQgICBfX1x0ICBfIF9fXG58IHxcdCAvIC9fX18gXyhfKSAvX19fX1xufCB8IC98IC8gLyBfXyBgLyAvIC8gX19fL1xufCB8LyB8LyAvIC9fLyAvIC8gKF9fICApXG58X18vfF9fL1xcX18sXy9fL18vX19fXy9cblRoZSBlbGVjdHJvbiBhbHRlcm5hdGl2ZSBmb3IgR29cbihjKSBMZWEgQW50aG9ueSAyMDE5LXByZXNlbnRcbiovXG5cbmltcG9ydCB7bmV3UnVudGltZUNhbGxlciwgb2JqZWN0TmFtZXN9IGZyb20gXCIuL3J1bnRpbWUuanNcIjtcblxuY29uc3QgY2FsbCA9IG5ld1J1bnRpbWVDYWxsZXIob2JqZWN0TmFtZXMuQ2xpcGJvYXJkKTtcblxuY29uc3QgQ2xpcGJvYXJkU2V0VGV4dCA9IDA7XG5jb25zdCBDbGlwYm9hcmRUZXh0ID0gMTtcblxuLyoqXG4gKiBTZXRzIHRoZSB0ZXh0IHRvIHRoZSBDbGlwYm9hcmQuXG4gKlxuICogQHBhcmFtIHRleHQgLSBUaGUgdGV4dCB0byBiZSBzZXQgdG8gdGhlIENsaXBib2FyZC5cbiAqIEByZXR1cm4gQSBQcm9taXNlIHRoYXQgcmVzb2x2ZXMgd2hlbiB0aGUgb3BlcmF0aW9uIGlzIHN1Y2Nlc3NmdWwuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBTZXRUZXh0KHRleHQ6IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuICAgIHJldHVybiBjYWxsKENsaXBib2FyZFNldFRleHQsIHt0ZXh0fSk7XG59XG5cbi8qKlxuICogR2V0IHRoZSBDbGlwYm9hcmQgdGV4dFxuICpcbiAqIEByZXR1cm5zIEEgcHJvbWlzZSB0aGF0IHJlc29sdmVzIHdpdGggdGhlIHRleHQgZnJvbSB0aGUgQ2xpcGJvYXJkLlxuICovXG5leHBvcnQgZnVuY3Rpb24gVGV4dCgpOiBQcm9taXNlPHN0cmluZz4ge1xuICAgIHJldHVybiBjYWxsKENsaXBib2FyZFRleHQpO1xufVxuIiwgIi8qXG4gX1x0ICAgX19cdCAgXyBfX1xufCB8XHQgLyAvX19fIF8oXykgL19fX19cbnwgfCAvfCAvIC8gX18gYC8gLyAvIF9fXy9cbnwgfC8gfC8gLyAvXy8gLyAvIChfXyAgKVxufF9fL3xfXy9cXF9fLF8vXy9fL19fX18vXG5UaGUgZWxlY3Ryb24gYWx0ZXJuYXRpdmUgZm9yIEdvXG4oYykgTGVhIEFudGhvbnkgMjAxOS1wcmVzZW50XG4qL1xuXG5leHBvcnQgaW50ZXJmYWNlIFNpemUge1xuICAgIC8qKiBUaGUgd2lkdGggb2YgYSByZWN0YW5ndWxhciBhcmVhLiAqL1xuICAgIFdpZHRoOiBudW1iZXI7XG4gICAgLyoqIFRoZSBoZWlnaHQgb2YgYSByZWN0YW5ndWxhciBhcmVhLiAqL1xuICAgIEhlaWdodDogbnVtYmVyO1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFJlY3Qge1xuICAgIC8qKiBUaGUgWCBjb29yZGluYXRlIG9mIHRoZSBvcmlnaW4uICovXG4gICAgWDogbnVtYmVyO1xuICAgIC8qKiBUaGUgWSBjb29yZGluYXRlIG9mIHRoZSBvcmlnaW4uICovXG4gICAgWTogbnVtYmVyO1xuICAgIC8qKiBUaGUgd2lkdGggb2YgdGhlIHJlY3RhbmdsZS4gKi9cbiAgICBXaWR0aDogbnVtYmVyO1xuICAgIC8qKiBUaGUgaGVpZ2h0IG9mIHRoZSByZWN0YW5nbGUuICovXG4gICAgSGVpZ2h0OiBudW1iZXI7XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgU2NyZWVuIHtcbiAgICAvKiogVW5pcXVlIGlkZW50aWZpZXIgZm9yIHRoZSBzY3JlZW4uICovXG4gICAgSUQ6IHN0cmluZztcbiAgICAvKiogSHVtYW4tcmVhZGFibGUgbmFtZSBvZiB0aGUgc2NyZWVuLiAqL1xuICAgIE5hbWU6IHN0cmluZztcbiAgICAvKiogVGhlIHNjYWxlIGZhY3RvciBvZiB0aGUgc2NyZWVuIChEUEkvOTYpLiAxID0gc3RhbmRhcmQgRFBJLCAyID0gSGlEUEkgKFJldGluYSksIGV0Yy4gKi9cbiAgICBTY2FsZUZhY3RvcjogbnVtYmVyO1xuICAgIC8qKiBUaGUgWCBjb29yZGluYXRlIG9mIHRoZSBzY3JlZW4uICovXG4gICAgWDogbnVtYmVyO1xuICAgIC8qKiBUaGUgWSBjb29yZGluYXRlIG9mIHRoZSBzY3JlZW4uICovXG4gICAgWTogbnVtYmVyO1xuICAgIC8qKiBDb250YWlucyB0aGUgd2lkdGggYW5kIGhlaWdodCBvZiB0aGUgc2NyZWVuLiAqL1xuICAgIFNpemU6IFNpemU7XG4gICAgLyoqIENvbnRhaW5zIHRoZSBib3VuZHMgb2YgdGhlIHNjcmVlbiBpbiB0ZXJtcyBvZiBYLCBZLCBXaWR0aCwgYW5kIEhlaWdodC4gKi9cbiAgICBCb3VuZHM6IFJlY3Q7XG4gICAgLyoqIENvbnRhaW5zIHRoZSBwaHlzaWNhbCBib3VuZHMgb2YgdGhlIHNjcmVlbiBpbiB0ZXJtcyBvZiBYLCBZLCBXaWR0aCwgYW5kIEhlaWdodCAoYmVmb3JlIHNjYWxpbmcpLiAqL1xuICAgIFBoeXNpY2FsQm91bmRzOiBSZWN0O1xuICAgIC8qKiBDb250YWlucyB0aGUgYXJlYSBvZiB0aGUgc2NyZWVuIHRoYXQgaXMgYWN0dWFsbHkgdXNhYmxlIChleGNsdWRpbmcgdGFza2JhciBhbmQgb3RoZXIgc3lzdGVtIFVJKS4gKi9cbiAgICBXb3JrQXJlYTogUmVjdDtcbiAgICAvKiogQ29udGFpbnMgdGhlIHBoeXNpY2FsIFdvcmtBcmVhIG9mIHRoZSBzY3JlZW4gKGJlZm9yZSBzY2FsaW5nKS4gKi9cbiAgICBQaHlzaWNhbFdvcmtBcmVhOiBSZWN0O1xuICAgIC8qKiBUcnVlIGlmIHRoaXMgaXMgdGhlIHByaW1hcnkgbW9uaXRvciBzZWxlY3RlZCBieSB0aGUgdXNlciBpbiB0aGUgb3BlcmF0aW5nIHN5c3RlbS4gKi9cbiAgICBJc1ByaW1hcnk6IGJvb2xlYW47XG4gICAgLyoqIFRoZSByb3RhdGlvbiBvZiB0aGUgc2NyZWVuLiAqL1xuICAgIFJvdGF0aW9uOiBudW1iZXI7XG59XG5cbmltcG9ydCB7IG5ld1J1bnRpbWVDYWxsZXIsIG9iamVjdE5hbWVzIH0gZnJvbSBcIi4vcnVudGltZS5qc1wiO1xuY29uc3QgY2FsbCA9IG5ld1J1bnRpbWVDYWxsZXIob2JqZWN0TmFtZXMuU2NyZWVucyk7XG5cbmNvbnN0IGdldEFsbCA9IDA7XG5jb25zdCBnZXRQcmltYXJ5ID0gMTtcbmNvbnN0IGdldEN1cnJlbnQgPSAyO1xuXG4vKipcbiAqIEdldHMgYWxsIHNjcmVlbnMuXG4gKlxuICogQHJldHVybnMgQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgdG8gYW4gYXJyYXkgb2YgU2NyZWVuIG9iamVjdHMuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBHZXRBbGwoKTogUHJvbWlzZTxTY3JlZW5bXT4ge1xuICAgIHJldHVybiBjYWxsKGdldEFsbCk7XG59XG5cbi8qKlxuICogR2V0cyB0aGUgcHJpbWFyeSBzY3JlZW4uXG4gKlxuICogQHJldHVybnMgQSBwcm9taXNlIHRoYXQgcmVzb2x2ZXMgdG8gdGhlIHByaW1hcnkgc2NyZWVuLlxuICovXG5leHBvcnQgZnVuY3Rpb24gR2V0UHJpbWFyeSgpOiBQcm9taXNlPFNjcmVlbj4ge1xuICAgIHJldHVybiBjYWxsKGdldFByaW1hcnkpO1xufVxuXG4vKipcbiAqIEdldHMgdGhlIGN1cnJlbnQgYWN0aXZlIHNjcmVlbi5cbiAqXG4gKiBAcmV0dXJucyBBIHByb21pc2UgdGhhdCByZXNvbHZlcyB3aXRoIHRoZSBjdXJyZW50IGFjdGl2ZSBzY3JlZW4uXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBHZXRDdXJyZW50KCk6IFByb21pc2U8U2NyZWVuPiB7XG4gICAgcmV0dXJuIGNhbGwoZ2V0Q3VycmVudCk7XG59XG4iLCAiLypcbiBfICAgICBfXyAgICAgXyBfX1xufCB8ICAvIC9fX18gXyhfKSAvX19fX1xufCB8IC98IC8gLyBfXyBgLyAvIC8gX19fL1xufCB8LyB8LyAvIC9fLyAvIC8gKF9fICApXG58X18vfF9fL1xcX18sXy9fL18vX19fXy9cblRoZSBlbGVjdHJvbiBhbHRlcm5hdGl2ZSBmb3IgR29cbihjKSBMZWEgQW50aG9ueSAyMDE5LXByZXNlbnRcbiovXG5cbmltcG9ydCB7IG5ld1J1bnRpbWVDYWxsZXIsIG9iamVjdE5hbWVzIH0gZnJvbSBcIi4vcnVudGltZS5qc1wiO1xuXG5jb25zdCBjYWxsID0gbmV3UnVudGltZUNhbGxlcihvYmplY3ROYW1lcy5JT1MpO1xuXG4vLyBNZXRob2QgSURzXG5jb25zdCBIYXB0aWNzSW1wYWN0ID0gMDtcbmNvbnN0IERldmljZUluZm8gPSAxO1xuXG5leHBvcnQgbmFtZXNwYWNlIEhhcHRpY3Mge1xuICAgIGV4cG9ydCB0eXBlIEltcGFjdFN0eWxlID0gXCJsaWdodFwifFwibWVkaXVtXCJ8XCJoZWF2eVwifFwic29mdFwifFwicmlnaWRcIjtcbiAgICBleHBvcnQgZnVuY3Rpb24gSW1wYWN0KHN0eWxlOiBJbXBhY3RTdHlsZSA9IFwibWVkaXVtXCIpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICAgICAgcmV0dXJuIGNhbGwoSGFwdGljc0ltcGFjdCwgeyBzdHlsZSB9KTtcbiAgICB9XG59XG5cbmV4cG9ydCBuYW1lc3BhY2UgRGV2aWNlIHtcbiAgICBleHBvcnQgaW50ZXJmYWNlIEluZm8ge1xuICAgICAgICBtb2RlbDogc3RyaW5nO1xuICAgICAgICBzeXN0ZW1OYW1lOiBzdHJpbmc7XG4gICAgICAgIHN5c3RlbVZlcnNpb246IHN0cmluZztcbiAgICAgICAgaXNTaW11bGF0b3I6IGJvb2xlYW47XG4gICAgfVxuICAgIGV4cG9ydCBmdW5jdGlvbiBJbmZvKCk6IFByb21pc2U8SW5mbz4ge1xuICAgICAgICByZXR1cm4gY2FsbChEZXZpY2VJbmZvKTtcbiAgICB9XG59XG4iXSwKICAibWFwcGluZ3MiOiAiOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBOzs7QUNBQTtBQUFBO0FBQUE7QUFBQTtBQUFBOzs7QUNBQTtBQUFBO0FBQUE7QUFBQTs7O0FDNkJBLElBQU0sY0FDRjtBQUVHLFNBQVMsT0FBTyxPQUFlLElBQVk7QUFDOUMsTUFBSSxLQUFLO0FBRVQsTUFBSSxJQUFJLE9BQU87QUFDZixTQUFPLEtBQUs7QUFFUixVQUFNLFlBQWEsS0FBSyxPQUFPLElBQUksS0FBTSxDQUFDO0FBQUEsRUFDOUM7QUFDQSxTQUFPO0FBQ1g7OztBQzdCQSxJQUFNLGFBQWEsT0FBTyxTQUFTLFNBQVM7QUFNckMsSUFBTSxjQUFjLE9BQU8sT0FBTztBQUFBLEVBQ3JDLE1BQU07QUFBQSxFQUNOLFdBQVc7QUFBQSxFQUNYLGFBQWE7QUFBQSxFQUNiLFFBQVE7QUFBQSxFQUNSLGFBQWE7QUFBQSxFQUNiLFFBQVE7QUFBQSxFQUNSLFFBQVE7QUFBQSxFQUNSLFNBQVM7QUFBQSxFQUNULFFBQVE7QUFBQSxFQUNSLFNBQVM7QUFBQSxFQUNULFlBQVk7QUFBQSxFQUNaLEtBQUs7QUFDVCxDQUFDO0FBQ00sSUFBSSxXQUFXLE9BQU87QUF1QjdCLElBQUksa0JBQTJDO0FBc0J4QyxTQUFTLGFBQWEsV0FBMEM7QUFDbkUsb0JBQWtCO0FBQ3RCO0FBS08sU0FBUyxlQUF3QztBQUNwRCxTQUFPO0FBQ1g7QUFTTyxTQUFTLGlCQUFpQixRQUFnQixhQUFxQixJQUFJO0FBQ3RFLFNBQU8sU0FBVSxRQUFnQixPQUFZLE1BQU07QUFDL0MsV0FBTyxrQkFBa0IsUUFBUSxRQUFRLFlBQVksSUFBSTtBQUFBLEVBQzdEO0FBQ0o7QUFFQSxlQUFlLGtCQUFrQixVQUFrQixRQUFnQixZQUFvQixNQUF5QjtBQXJHaEgsTUFBQUEsS0FBQTtBQXVHSSxNQUFJLGlCQUFpQjtBQUNqQixXQUFPLGdCQUFnQixLQUFLLFVBQVUsUUFBUSxZQUFZLElBQUk7QUFBQSxFQUNsRTtBQUdBLE1BQUksTUFBTSxJQUFJLElBQUksVUFBVTtBQUU1QixNQUFJLE9BQXVEO0FBQUEsSUFDekQsUUFBUTtBQUFBLElBQ1I7QUFBQSxFQUNGO0FBQ0EsTUFBSSxTQUFTLFFBQVEsU0FBUyxRQUFXO0FBQ3ZDLFNBQUssT0FBTztBQUFBLEVBQ2Q7QUFFQSxNQUFJLFVBQWtDO0FBQUEsSUFDbEMsQ0FBQyxtQkFBbUIsR0FBRztBQUFBLElBQ3ZCLENBQUMsY0FBYyxHQUFHO0FBQUEsRUFDdEI7QUFDQSxNQUFJLFlBQVk7QUFDWixZQUFRLHFCQUFxQixJQUFJO0FBQUEsRUFDckM7QUFFQSxNQUFJLFdBQVcsTUFBTSxNQUFNLEtBQUs7QUFBQSxJQUM5QixRQUFRO0FBQUEsSUFDUjtBQUFBLElBQ0EsTUFBTSxLQUFLLFVBQVUsSUFBSTtBQUFBLEVBQzNCLENBQUM7QUFDRCxNQUFJLENBQUMsU0FBUyxJQUFJO0FBQ2QsVUFBTSxJQUFJLE1BQU0sTUFBTSxTQUFTLEtBQUssQ0FBQztBQUFBLEVBQ3pDO0FBRUEsUUFBSyxNQUFBQSxNQUFBLFNBQVMsUUFBUSxJQUFJLGNBQWMsTUFBbkMsZ0JBQUFBLElBQXNDLFFBQVEsd0JBQTlDLFlBQXFFLFFBQVEsSUFBSTtBQUNsRixXQUFPLFNBQVMsS0FBSztBQUFBLEVBQ3pCLE9BQU87QUFDSCxXQUFPLFNBQVMsS0FBSztBQUFBLEVBQ3pCO0FBQ0o7OztBRmhJQSxJQUFNLE9BQU8saUJBQWlCLFlBQVksT0FBTztBQUVqRCxJQUFNLGlCQUFpQjtBQU9oQixTQUFTLFFBQVEsS0FBa0M7QUFDdEQsU0FBTyxLQUFLLGdCQUFnQixFQUFDLEtBQUssSUFBSSxTQUFTLEVBQUMsQ0FBQztBQUNyRDs7O0FHdkJBO0FBQUE7QUFBQSxlQUFBQztBQUFBLEVBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBYUEsT0FBTyxTQUFTLE9BQU8sVUFBVSxDQUFDO0FBRWxDLElBQU1DLFFBQU8saUJBQWlCLFlBQVksTUFBTTtBQUdoRCxJQUFNLGFBQWE7QUFDbkIsSUFBTSxnQkFBZ0I7QUFDdEIsSUFBTSxjQUFjO0FBQ3BCLElBQU0saUJBQWlCO0FBQ3ZCLElBQU0saUJBQWlCO0FBQ3ZCLElBQU0saUJBQWlCO0FBMEd2QixTQUFTLE9BQU8sTUFBYyxVQUFnRixDQUFDLEdBQWlCO0FBQzVILFNBQU9BLE1BQUssTUFBTSxPQUFPO0FBQzdCO0FBUU8sU0FBUyxLQUFLLFNBQWdEO0FBQUUsU0FBTyxPQUFPLFlBQVksT0FBTztBQUFHO0FBUXBHLFNBQVMsUUFBUSxTQUFnRDtBQUFFLFNBQU8sT0FBTyxlQUFlLE9BQU87QUFBRztBQVExRyxTQUFTQyxPQUFNLFNBQWdEO0FBQUUsU0FBTyxPQUFPLGFBQWEsT0FBTztBQUFHO0FBUXRHLFNBQVMsU0FBUyxTQUFnRDtBQUFFLFNBQU8sT0FBTyxnQkFBZ0IsT0FBTztBQUFHO0FBVzVHLFNBQVMsU0FBUyxTQUE0RDtBQTlLckYsTUFBQUM7QUE4S3VGLFVBQU9BLE1BQUEsT0FBTyxnQkFBZ0IsT0FBTyxNQUE5QixPQUFBQSxNQUFtQyxDQUFDO0FBQUc7QUFROUgsU0FBUyxTQUFTLFNBQWlEO0FBQUUsU0FBTyxPQUFPLGdCQUFnQixPQUFPO0FBQUc7OztBQ3RMcEg7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTs7O0FDYU8sSUFBTSxpQkFBaUIsb0JBQUksSUFBd0I7QUFFbkQsSUFBTSxXQUFOLE1BQWU7QUFBQSxFQUtsQixZQUFZLFdBQW1CLFVBQStCLGNBQXNCO0FBQ2hGLFNBQUssWUFBWTtBQUNqQixTQUFLLFdBQVc7QUFDaEIsU0FBSyxlQUFlLGdCQUFnQjtBQUFBLEVBQ3hDO0FBQUEsRUFFQSxTQUFTLE1BQW9CO0FBQ3pCLFFBQUk7QUFDQSxXQUFLLFNBQVMsSUFBSTtBQUFBLElBQ3RCLFNBQVMsS0FBSztBQUNWLGNBQVEsTUFBTSxHQUFHO0FBQUEsSUFDckI7QUFFQSxRQUFJLEtBQUssaUJBQWlCLEdBQUksUUFBTztBQUNyQyxTQUFLLGdCQUFnQjtBQUNyQixXQUFPLEtBQUssaUJBQWlCO0FBQUEsRUFDakM7QUFDSjtBQUVPLFNBQVMsWUFBWSxVQUEwQjtBQUNsRCxNQUFJLFlBQVksZUFBZSxJQUFJLFNBQVMsU0FBUztBQUNyRCxNQUFJLENBQUMsV0FBVztBQUNaO0FBQUEsRUFDSjtBQUVBLGNBQVksVUFBVSxPQUFPLE9BQUssTUFBTSxRQUFRO0FBQ2hELE1BQUksVUFBVSxXQUFXLEdBQUc7QUFDeEIsbUJBQWUsT0FBTyxTQUFTLFNBQVM7QUFBQSxFQUM1QyxPQUFPO0FBQ0gsbUJBQWUsSUFBSSxTQUFTLFdBQVcsU0FBUztBQUFBLEVBQ3BEO0FBQ0o7OztBQ25EQTtBQUFBO0FBQUE7QUFBQSxlQUFBQztBQUFBLEVBQUE7QUFBQTtBQUFBLGFBQUFDO0FBQUEsRUFBQTtBQUFBO0FBQUE7QUFhTyxTQUFTLElBQWEsUUFBZ0I7QUFDekMsU0FBTztBQUNYO0FBTU8sU0FBUyxVQUFVLFFBQXFCO0FBQzNDLFNBQVMsVUFBVSxPQUFRLEtBQUs7QUFDcEM7QUFPTyxTQUFTQyxPQUFlLFNBQW1EO0FBQzlFLE1BQUksWUFBWSxLQUFLO0FBQ2pCLFdBQU8sQ0FBQyxXQUFZLFdBQVcsT0FBTyxDQUFDLElBQUk7QUFBQSxFQUMvQztBQUVBLFNBQU8sQ0FBQyxXQUFXO0FBQ2YsUUFBSSxXQUFXLE1BQU07QUFDakIsYUFBTyxDQUFDO0FBQUEsSUFDWjtBQUNBLGFBQVMsSUFBSSxHQUFHLElBQUksT0FBTyxRQUFRLEtBQUs7QUFDcEMsYUFBTyxDQUFDLElBQUksUUFBUSxPQUFPLENBQUMsQ0FBQztBQUFBLElBQ2pDO0FBQ0EsV0FBTztBQUFBLEVBQ1g7QUFDSjtBQU9PLFNBQVNDLEtBQTBDLEtBQXlCLE9BQTBEO0FBQ3pJLE1BQUksVUFBVSxLQUFLO0FBQ2YsV0FBTyxDQUFDLFdBQVksV0FBVyxPQUFPLENBQUMsSUFBSTtBQUFBLEVBQy9DO0FBRUEsU0FBTyxDQUFDLFdBQVc7QUFDZixRQUFJLFdBQVcsTUFBTTtBQUNqQixhQUFPLENBQUM7QUFBQSxJQUNaO0FBQ0EsZUFBV0MsUUFBTyxRQUFRO0FBQ3RCLGFBQU9BLElBQUcsSUFBSSxNQUFNLE9BQU9BLElBQUcsQ0FBQztBQUFBLElBQ25DO0FBQ0EsV0FBTztBQUFBLEVBQ1g7QUFDSjtBQU1PLFNBQVMsU0FBa0IsU0FBMEQ7QUFDeEYsTUFBSSxZQUFZLEtBQUs7QUFDakIsV0FBTztBQUFBLEVBQ1g7QUFFQSxTQUFPLENBQUMsV0FBWSxXQUFXLE9BQU8sT0FBTyxRQUFRLE1BQU07QUFDL0Q7QUFNTyxTQUFTLE9BQU8sYUFFdkI7QUFDSSxNQUFJLFNBQVM7QUFDYixhQUFXLFFBQVEsYUFBYTtBQUM1QixRQUFJLFlBQVksSUFBSSxNQUFNLEtBQUs7QUFDM0IsZUFBUztBQUNUO0FBQUEsSUFDSjtBQUFBLEVBQ0o7QUFDQSxNQUFJLFFBQVE7QUFDUixXQUFPO0FBQUEsRUFDWDtBQUVBLFNBQU8sQ0FBQyxXQUFXO0FBQ2YsZUFBVyxRQUFRLGFBQWE7QUFDNUIsVUFBSSxRQUFRLFFBQVE7QUFDaEIsZUFBTyxJQUFJLElBQUksWUFBWSxJQUFJLEVBQUUsT0FBTyxJQUFJLENBQUM7QUFBQSxNQUNqRDtBQUFBLElBQ0o7QUFDQSxXQUFPO0FBQUEsRUFDWDtBQUNKO0FBTU8sSUFBTSxTQUErQyxDQUFDOzs7QUNsR3RELElBQU0sUUFBUSxPQUFPLE9BQU87QUFBQSxFQUNsQyxTQUFTLE9BQU8sT0FBTztBQUFBLElBQ3RCLHVCQUF1QjtBQUFBLElBQ3ZCLHNCQUFzQjtBQUFBLElBQ3RCLG9CQUFvQjtBQUFBLElBQ3BCLGtCQUFrQjtBQUFBLElBQ2xCLFlBQVk7QUFBQSxJQUNaLG9CQUFvQjtBQUFBLElBQ3BCLG9CQUFvQjtBQUFBLElBQ3BCLDRCQUE0QjtBQUFBLElBQzVCLGNBQWM7QUFBQSxJQUNkLHVCQUF1QjtBQUFBLElBQ3ZCLG1CQUFtQjtBQUFBLElBQ25CLGVBQWU7QUFBQSxJQUNmLGVBQWU7QUFBQSxJQUNmLGlCQUFpQjtBQUFBLElBQ2pCLGtCQUFrQjtBQUFBLElBQ2xCLGdCQUFnQjtBQUFBLElBQ2hCLGlCQUFpQjtBQUFBLElBQ2pCLGlCQUFpQjtBQUFBLElBQ2pCLGdCQUFnQjtBQUFBLElBQ2hCLGVBQWU7QUFBQSxJQUNmLGlCQUFpQjtBQUFBLElBQ2pCLGtCQUFrQjtBQUFBLElBQ2xCLFlBQVk7QUFBQSxJQUNaLGdCQUFnQjtBQUFBLElBQ2hCLGVBQWU7QUFBQSxJQUNmLGFBQWE7QUFBQSxJQUNiLGlCQUFpQjtBQUFBLElBQ2pCLG9CQUFvQjtBQUFBLElBQ3BCLDBCQUEwQjtBQUFBLElBQzFCLDJCQUEyQjtBQUFBLElBQzNCLDBCQUEwQjtBQUFBLElBQzFCLHdCQUF3QjtBQUFBLElBQ3hCLGFBQWE7QUFBQSxJQUNiLGVBQWU7QUFBQSxJQUNmLGdCQUFnQjtBQUFBLElBQ2hCLFlBQVk7QUFBQSxJQUNaLGlCQUFpQjtBQUFBLElBQ2pCLG1CQUFtQjtBQUFBLElBQ25CLG9CQUFvQjtBQUFBLElBQ3BCLHFCQUFxQjtBQUFBLElBQ3JCLGdCQUFnQjtBQUFBLElBQ2hCLGtCQUFrQjtBQUFBLElBQ2xCLGdCQUFnQjtBQUFBLElBQ2hCLGtCQUFrQjtBQUFBLEVBQ25CLENBQUM7QUFBQSxFQUNELEtBQUssT0FBTyxPQUFPO0FBQUEsSUFDbEIsNEJBQTRCO0FBQUEsSUFDNUIsdUNBQXVDO0FBQUEsSUFDdkMseUNBQXlDO0FBQUEsSUFDekMsMEJBQTBCO0FBQUEsSUFDMUIsb0NBQW9DO0FBQUEsSUFDcEMsc0NBQXNDO0FBQUEsSUFDdEMsb0NBQW9DO0FBQUEsSUFDcEMsMENBQTBDO0FBQUEsSUFDMUMsMkJBQTJCO0FBQUEsSUFDM0IsK0JBQStCO0FBQUEsSUFDL0Isb0JBQW9CO0FBQUEsSUFDcEIsNEJBQTRCO0FBQUEsSUFDNUIsc0JBQXNCO0FBQUEsSUFDdEIsc0JBQXNCO0FBQUEsSUFDdEIsK0JBQStCO0FBQUEsSUFDL0IsNkJBQTZCO0FBQUEsSUFDN0IsZ0NBQWdDO0FBQUEsSUFDaEMscUJBQXFCO0FBQUEsSUFDckIsNkJBQTZCO0FBQUEsSUFDN0IsMEJBQTBCO0FBQUEsSUFDMUIsdUJBQXVCO0FBQUEsSUFDdkIsdUJBQXVCO0FBQUEsSUFDdkIsZ0JBQWdCO0FBQUEsSUFDaEIsc0JBQXNCO0FBQUEsSUFDdEIsY0FBYztBQUFBLElBQ2Qsb0JBQW9CO0FBQUEsSUFDcEIsb0JBQW9CO0FBQUEsSUFDcEIsc0JBQXNCO0FBQUEsSUFDdEIsYUFBYTtBQUFBLElBQ2IsY0FBYztBQUFBLElBQ2QsbUJBQW1CO0FBQUEsSUFDbkIsbUJBQW1CO0FBQUEsSUFDbkIseUJBQXlCO0FBQUEsSUFDekIsZUFBZTtBQUFBLElBQ2YsaUJBQWlCO0FBQUEsSUFDakIsdUJBQXVCO0FBQUEsSUFDdkIscUJBQXFCO0FBQUEsSUFDckIscUJBQXFCO0FBQUEsSUFDckIsdUJBQXVCO0FBQUEsSUFDdkIsY0FBYztBQUFBLElBQ2QsZUFBZTtBQUFBLElBQ2Ysb0JBQW9CO0FBQUEsSUFDcEIsb0JBQW9CO0FBQUEsSUFDcEIsMEJBQTBCO0FBQUEsSUFDMUIsZ0JBQWdCO0FBQUEsSUFDaEIsNEJBQTRCO0FBQUEsSUFDNUIsNEJBQTRCO0FBQUEsSUFDNUIseURBQXlEO0FBQUEsSUFDekQsc0NBQXNDO0FBQUEsSUFDdEMsb0JBQW9CO0FBQUEsSUFDcEIscUJBQXFCO0FBQUEsSUFDckIscUJBQXFCO0FBQUEsSUFDckIsc0JBQXNCO0FBQUEsSUFDdEIsZ0NBQWdDO0FBQUEsSUFDaEMsa0NBQWtDO0FBQUEsSUFDbEMsbUNBQW1DO0FBQUEsSUFDbkMsb0NBQW9DO0FBQUEsSUFDcEMsK0JBQStCO0FBQUEsSUFDL0IsNkJBQTZCO0FBQUEsSUFDN0IsdUJBQXVCO0FBQUEsSUFDdkIsaUNBQWlDO0FBQUEsSUFDakMsOEJBQThCO0FBQUEsSUFDOUIsNEJBQTRCO0FBQUEsSUFDNUIsc0NBQXNDO0FBQUEsSUFDdEMsNEJBQTRCO0FBQUEsSUFDNUIsc0JBQXNCO0FBQUEsSUFDdEIsa0NBQWtDO0FBQUEsSUFDbEMsc0JBQXNCO0FBQUEsSUFDdEIsd0JBQXdCO0FBQUEsSUFDeEIsd0JBQXdCO0FBQUEsSUFDeEIsbUJBQW1CO0FBQUEsSUFDbkIsMEJBQTBCO0FBQUEsSUFDMUIsOEJBQThCO0FBQUEsSUFDOUIseUJBQXlCO0FBQUEsSUFDekIsNkJBQTZCO0FBQUEsSUFDN0IsaUJBQWlCO0FBQUEsSUFDakIsZ0JBQWdCO0FBQUEsSUFDaEIsc0JBQXNCO0FBQUEsSUFDdEIsZUFBZTtBQUFBLElBQ2YseUJBQXlCO0FBQUEsSUFDekIsd0JBQXdCO0FBQUEsSUFDeEIsb0JBQW9CO0FBQUEsSUFDcEIscUJBQXFCO0FBQUEsSUFDckIsaUJBQWlCO0FBQUEsSUFDakIsaUJBQWlCO0FBQUEsSUFDakIsc0JBQXNCO0FBQUEsSUFDdEIsbUNBQW1DO0FBQUEsSUFDbkMscUNBQXFDO0FBQUEsSUFDckMsdUJBQXVCO0FBQUEsSUFDdkIsc0JBQXNCO0FBQUEsSUFDdEIsd0JBQXdCO0FBQUEsSUFDeEIsZUFBZTtBQUFBLElBQ2YsMkJBQTJCO0FBQUEsSUFDM0IsMEJBQTBCO0FBQUEsSUFDMUIsNkJBQTZCO0FBQUEsSUFDN0IsWUFBWTtBQUFBLElBQ1osZ0JBQWdCO0FBQUEsSUFDaEIsa0JBQWtCO0FBQUEsSUFDbEIsZ0JBQWdCO0FBQUEsSUFDaEIsa0JBQWtCO0FBQUEsSUFDbEIsbUJBQW1CO0FBQUEsSUFDbkIsWUFBWTtBQUFBLElBQ1oscUJBQXFCO0FBQUEsSUFDckIsc0JBQXNCO0FBQUEsSUFDdEIsc0JBQXNCO0FBQUEsSUFDdEIsOEJBQThCO0FBQUEsSUFDOUIsaUJBQWlCO0FBQUEsSUFDakIseUJBQXlCO0FBQUEsSUFDekIsMkJBQTJCO0FBQUEsSUFDM0IsK0JBQStCO0FBQUEsSUFDL0IsMEJBQTBCO0FBQUEsSUFDMUIsOEJBQThCO0FBQUEsSUFDOUIsaUJBQWlCO0FBQUEsSUFDakIsdUJBQXVCO0FBQUEsSUFDdkIsZ0JBQWdCO0FBQUEsSUFDaEIsMEJBQTBCO0FBQUEsSUFDMUIseUJBQXlCO0FBQUEsSUFDekIsc0JBQXNCO0FBQUEsSUFDdEIsa0JBQWtCO0FBQUEsSUFDbEIsbUJBQW1CO0FBQUEsSUFDbkIsa0JBQWtCO0FBQUEsSUFDbEIsdUJBQXVCO0FBQUEsSUFDdkIsb0NBQW9DO0FBQUEsSUFDcEMsc0NBQXNDO0FBQUEsSUFDdEMsd0JBQXdCO0FBQUEsSUFDeEIsdUJBQXVCO0FBQUEsSUFDdkIseUJBQXlCO0FBQUEsSUFDekIsNEJBQTRCO0FBQUEsSUFDNUIsNEJBQTRCO0FBQUEsSUFDNUIsY0FBYztBQUFBLElBQ2QsZUFBZTtBQUFBLElBQ2YsaUJBQWlCO0FBQUEsRUFDbEIsQ0FBQztBQUFBLEVBQ0QsT0FBTyxPQUFPLE9BQU87QUFBQSxJQUNwQixvQkFBb0I7QUFBQSxJQUNwQixvQkFBb0I7QUFBQSxJQUNwQixtQkFBbUI7QUFBQSxJQUNuQixlQUFlO0FBQUEsSUFDZixpQkFBaUI7QUFBQSxJQUNqQixlQUFlO0FBQUEsSUFDZixnQkFBZ0I7QUFBQSxJQUNoQixtQkFBbUI7QUFBQSxJQUNuQixzQkFBc0I7QUFBQSxJQUN0QixxQkFBcUI7QUFBQSxJQUNyQixvQkFBb0I7QUFBQSxFQUNyQixDQUFDO0FBQUEsRUFDRCxLQUFLLE9BQU8sT0FBTztBQUFBLElBQ2xCLDRCQUE0QjtBQUFBLElBQzVCLCtCQUErQjtBQUFBLElBQy9CLCtCQUErQjtBQUFBLElBQy9CLG9DQUFvQztBQUFBLElBQ3BDLGdDQUFnQztBQUFBLElBQ2hDLDZCQUE2QjtBQUFBLElBQzdCLDBCQUEwQjtBQUFBLElBQzFCLGVBQWU7QUFBQSxJQUNmLGtCQUFrQjtBQUFBLElBQ2xCLGlCQUFpQjtBQUFBLElBQ2pCLHFCQUFxQjtBQUFBLElBQ3JCLG9CQUFvQjtBQUFBLElBQ3BCLDZCQUE2QjtBQUFBLElBQzdCLDBCQUEwQjtBQUFBLElBQzFCLGtCQUFrQjtBQUFBLElBQ2xCLGtCQUFrQjtBQUFBLElBQ2xCLGtCQUFrQjtBQUFBLElBQ2xCLHNCQUFzQjtBQUFBLElBQ3RCLDJCQUEyQjtBQUFBLElBQzNCLDRCQUE0QjtBQUFBLElBQzVCLDBCQUEwQjtBQUFBLElBQzFCLHdDQUF3QztBQUFBLEVBQ3pDLENBQUM7QUFBQSxFQUNELFFBQVEsT0FBTyxPQUFPO0FBQUEsSUFDckIsMkJBQTJCO0FBQUEsSUFDM0Isb0JBQW9CO0FBQUEsSUFDcEIsNEJBQTRCO0FBQUEsSUFDNUIsY0FBYztBQUFBLElBQ2QsZUFBZTtBQUFBLElBQ2YsZUFBZTtBQUFBLElBQ2YsaUJBQWlCO0FBQUEsSUFDakIsa0JBQWtCO0FBQUEsSUFDbEIsb0JBQW9CO0FBQUEsSUFDcEIsYUFBYTtBQUFBLElBQ2Isa0JBQWtCO0FBQUEsSUFDbEIsWUFBWTtBQUFBLElBQ1osaUJBQWlCO0FBQUEsSUFDakIsZ0JBQWdCO0FBQUEsSUFDaEIsZ0JBQWdCO0FBQUEsSUFDaEIsdUJBQXVCO0FBQUEsSUFDdkIsZUFBZTtBQUFBLElBQ2Ysb0JBQW9CO0FBQUEsSUFDcEIsWUFBWTtBQUFBLElBQ1osb0JBQW9CO0FBQUEsSUFDcEIsa0JBQWtCO0FBQUEsSUFDbEIsa0JBQWtCO0FBQUEsSUFDbEIsWUFBWTtBQUFBLElBQ1osY0FBYztBQUFBLElBQ2QsZUFBZTtBQUFBLElBQ2YsaUJBQWlCO0FBQUEsRUFDbEIsQ0FBQztBQUNGLENBQUM7OztBSG5QRCxPQUFPLFNBQVMsT0FBTyxVQUFVLENBQUM7QUFDbEMsT0FBTyxPQUFPLHFCQUFxQjtBQUVuQyxJQUFNQyxRQUFPLGlCQUFpQixZQUFZLE1BQU07QUFDaEQsSUFBTSxhQUFhO0FBb0NaLElBQU0sYUFBTixNQUE0RDtBQUFBLEVBbUIvRCxZQUFZLE1BQVMsTUFBWTtBQUM3QixTQUFLLE9BQU87QUFDWixTQUFLLE9BQU8sc0JBQVE7QUFBQSxFQUN4QjtBQUNKO0FBRUEsU0FBUyxtQkFBbUIsT0FBWTtBQUNwQyxNQUFJLFlBQVksZUFBZSxJQUFJLE1BQU0sSUFBSTtBQUM3QyxNQUFJLENBQUMsV0FBVztBQUNaO0FBQUEsRUFDSjtBQUVBLE1BQUksYUFBYSxJQUFJO0FBQUEsSUFDakIsTUFBTTtBQUFBLElBQ0wsTUFBTSxRQUFRLFNBQVUsT0FBTyxNQUFNLElBQUksRUFBRSxNQUFNLElBQUksSUFBSSxNQUFNO0FBQUEsRUFDcEU7QUFDQSxNQUFJLFlBQVksT0FBTztBQUNuQixlQUFXLFNBQVMsTUFBTTtBQUFBLEVBQzlCO0FBRUEsY0FBWSxVQUFVLE9BQU8sY0FBWSxDQUFDLFNBQVMsU0FBUyxVQUFVLENBQUM7QUFDdkUsTUFBSSxVQUFVLFdBQVcsR0FBRztBQUN4QixtQkFBZSxPQUFPLE1BQU0sSUFBSTtBQUFBLEVBQ3BDLE9BQU87QUFDSCxtQkFBZSxJQUFJLE1BQU0sTUFBTSxTQUFTO0FBQUEsRUFDNUM7QUFDSjtBQVVPLFNBQVMsV0FBc0QsV0FBYyxVQUFpQyxjQUFzQjtBQUN2SSxNQUFJLFlBQVksZUFBZSxJQUFJLFNBQVMsS0FBSyxDQUFDO0FBQ2xELFFBQU0sZUFBZSxJQUFJLFNBQVMsV0FBVyxVQUFVLFlBQVk7QUFDbkUsWUFBVSxLQUFLLFlBQVk7QUFDM0IsaUJBQWUsSUFBSSxXQUFXLFNBQVM7QUFDdkMsU0FBTyxNQUFNLFlBQVksWUFBWTtBQUN6QztBQVNPLFNBQVMsR0FBOEMsV0FBYyxVQUE2QztBQUNySCxTQUFPLFdBQVcsV0FBVyxVQUFVLEVBQUU7QUFDN0M7QUFTTyxTQUFTLEtBQWdELFdBQWMsVUFBNkM7QUFDdkgsU0FBTyxXQUFXLFdBQVcsVUFBVSxDQUFDO0FBQzVDO0FBT08sU0FBUyxPQUFPLFlBQXlEO0FBQzVFLGFBQVcsUUFBUSxlQUFhLGVBQWUsT0FBTyxTQUFTLENBQUM7QUFDcEU7QUFLTyxTQUFTLFNBQWU7QUFDM0IsaUJBQWUsTUFBTTtBQUN6QjtBQVdPLFNBQVMsS0FBZ0QsTUFBeUIsTUFBOEI7QUFDbkgsU0FBT0EsTUFBSyxZQUFhLElBQUksV0FBVyxNQUFNLElBQUksQ0FBQztBQUN2RDs7O0FJekpPLFNBQVMsU0FBUyxTQUFjO0FBRW5DLFVBQVE7QUFBQSxJQUNKLGtCQUFrQixVQUFVO0FBQUEsSUFDNUI7QUFBQSxJQUNBO0FBQUEsRUFDSjtBQUNKO0FBTU8sU0FBUyxrQkFBMkI7QUFDdkMsU0FBUSxJQUFJLFdBQVcsV0FBVyxFQUFHLFlBQVk7QUFDckQ7QUFNTyxTQUFTLG9CQUFvQjtBQUNoQyxNQUFJLENBQUMsZUFBZSxDQUFDLGVBQWUsQ0FBQztBQUNqQyxXQUFPO0FBRVgsTUFBSSxTQUFTO0FBRWIsUUFBTSxTQUFTLElBQUksWUFBWTtBQUMvQixRQUFNLGFBQWEsSUFBSSxnQkFBZ0I7QUFDdkMsU0FBTyxpQkFBaUIsUUFBUSxNQUFNO0FBQUUsYUFBUztBQUFBLEVBQU8sR0FBRyxFQUFFLFFBQVEsV0FBVyxPQUFPLENBQUM7QUFDeEYsYUFBVyxNQUFNO0FBQ2pCLFNBQU8sY0FBYyxJQUFJLFlBQVksTUFBTSxDQUFDO0FBRTVDLFNBQU87QUFDWDtBQUtPLFNBQVMsWUFBWSxPQUEyQjtBQXREdkQsTUFBQUM7QUF1REksTUFBSSxNQUFNLGtCQUFrQixhQUFhO0FBQ3JDLFdBQU8sTUFBTTtBQUFBLEVBQ2pCLFdBQVcsRUFBRSxNQUFNLGtCQUFrQixnQkFBZ0IsTUFBTSxrQkFBa0IsTUFBTTtBQUMvRSxZQUFPQSxNQUFBLE1BQU0sT0FBTyxrQkFBYixPQUFBQSxNQUE4QixTQUFTO0FBQUEsRUFDbEQsT0FBTztBQUNILFdBQU8sU0FBUztBQUFBLEVBQ3BCO0FBQ0o7QUFpQ0EsSUFBSSxVQUFVO0FBQ2QsU0FBUyxpQkFBaUIsb0JBQW9CLE1BQU07QUFBRSxZQUFVO0FBQUssQ0FBQztBQUUvRCxTQUFTLFVBQVUsVUFBc0I7QUFDNUMsTUFBSSxXQUFXLFNBQVMsZUFBZSxZQUFZO0FBQy9DLGFBQVM7QUFBQSxFQUNiLE9BQU87QUFDSCxhQUFTLGlCQUFpQixvQkFBb0IsUUFBUTtBQUFBLEVBQzFEO0FBQ0o7OztBQzFGQSxJQUFNLHdCQUF3QjtBQUM5QixJQUFNLDJCQUEyQjtBQUNqQyxJQUFJLG9CQUFvQztBQUV4QyxJQUFNLGlCQUFvQztBQUMxQyxJQUFNLGVBQW9DO0FBQzFDLElBQU0sY0FBb0M7QUFDMUMsSUFBTSwrQkFBb0M7QUFDMUMsSUFBTSw4QkFBb0M7QUFDMUMsSUFBTSxjQUFvQztBQUMxQyxJQUFNLG9CQUFvQztBQUMxQyxJQUFNLG1CQUFvQztBQUMxQyxJQUFNLGtCQUFvQztBQUMxQyxJQUFNLGdCQUFvQztBQUMxQyxJQUFNLGVBQW9DO0FBQzFDLElBQU0sYUFBb0M7QUFDMUMsSUFBTSxrQkFBb0M7QUFDMUMsSUFBTSxxQkFBb0M7QUFDMUMsSUFBTSxvQkFBb0M7QUFDMUMsSUFBTSxvQkFBb0M7QUFDMUMsSUFBTSxpQkFBb0M7QUFDMUMsSUFBTSxpQkFBb0M7QUFDMUMsSUFBTSxhQUFvQztBQUMxQyxJQUFNLHFCQUFvQztBQUMxQyxJQUFNLHlCQUFvQztBQUMxQyxJQUFNLGVBQW9DO0FBQzFDLElBQU0sa0JBQW9DO0FBQzFDLElBQU0sZ0JBQW9DO0FBQzFDLElBQU0sb0JBQW9DO0FBQzFDLElBQU0sdUJBQW9DO0FBQzFDLElBQU0sNEJBQW9DO0FBQzFDLElBQU0scUJBQW9DO0FBQzFDLElBQU0sbUNBQW9DO0FBQzFDLElBQU0sbUJBQW9DO0FBQzFDLElBQU0sbUJBQW9DO0FBQzFDLElBQU0sNEJBQW9DO0FBQzFDLElBQU0scUJBQW9DO0FBQzFDLElBQU0sZ0JBQW9DO0FBQzFDLElBQU0saUJBQW9DO0FBQzFDLElBQU0sZ0JBQW9DO0FBQzFDLElBQU0sYUFBb0M7QUFDMUMsSUFBTSxhQUFvQztBQUMxQyxJQUFNLHlCQUFvQztBQUMxQyxJQUFNLHVCQUFvQztBQUMxQyxJQUFNLHdCQUFvQztBQUMxQyxJQUFNLHFCQUFvQztBQUMxQyxJQUFNLG1CQUFvQztBQUMxQyxJQUFNLG1CQUFvQztBQUMxQyxJQUFNLGNBQW9DO0FBQzFDLElBQU0sYUFBb0M7QUFDMUMsSUFBTSxlQUFvQztBQUMxQyxJQUFNLGdCQUFvQztBQUMxQyxJQUFNLGtCQUFvQztBQUMxQyxJQUFNLG1CQUFvQztBQUMxQyxJQUFNLGVBQW9DO0FBQzFDLElBQU0sY0FBb0M7QUFLMUMsU0FBUyxxQkFBcUIsU0FBeUM7QUFDbkUsTUFBSSxDQUFDLFNBQVM7QUFDVixXQUFPO0FBQUEsRUFDWDtBQUNBLFNBQU8sUUFBUSxRQUFRLElBQUksOEJBQXFCLElBQUc7QUFDdkQ7QUFNQSxTQUFTLHNCQUErQjtBQXJGeEMsTUFBQUMsS0FBQTtBQXVGSSxRQUFLLE1BQUFBLE1BQUEsT0FBZSxXQUFmLGdCQUFBQSxJQUF1QixZQUF2QixtQkFBZ0MscUNBQW9DLE1BQU07QUFDM0UsV0FBTztBQUFBLEVBQ1g7QUFHQSxXQUFRLGtCQUFlLFdBQWYsbUJBQXVCLFVBQXZCLG1CQUE4QixvQkFBbUI7QUFDN0Q7QUFLQSxTQUFTLGlCQUFpQixHQUFXLEdBQVcsT0FBcUI7QUFsR3JFLE1BQUFBLEtBQUE7QUFtR0ksT0FBSyxNQUFBQSxNQUFBLE9BQWUsV0FBZixnQkFBQUEsSUFBdUIsWUFBdkIsbUJBQWdDLGtDQUFrQztBQUNuRSxJQUFDLE9BQWUsT0FBTyxRQUFRLGlDQUFpQyxhQUFhLFVBQUMsS0FBSSxXQUFLLEtBQUs7QUFBQSxFQUNoRztBQUNKO0FBR0EsSUFBSSxtQkFBbUI7QUFNdkIsU0FBUyxvQkFBMEI7QUFDL0IscUJBQW1CO0FBQ25CLE1BQUksbUJBQW1CO0FBQ25CLHNCQUFrQixVQUFVLE9BQU8sd0JBQXdCO0FBQzNELHdCQUFvQjtBQUFBLEVBQ3hCO0FBQ0o7QUFLQSxTQUFTLGtCQUF3QjtBQTFIakMsTUFBQUEsS0FBQTtBQTRISSxRQUFLLE1BQUFBLE1BQUEsT0FBZSxXQUFmLGdCQUFBQSxJQUF1QixVQUF2QixtQkFBOEIsb0JBQW1CLE9BQU87QUFDekQ7QUFBQSxFQUNKO0FBQ0EscUJBQW1CO0FBQ3ZCO0FBS0EsU0FBUyxrQkFBd0I7QUFDN0Isb0JBQWtCO0FBQ3RCO0FBT0EsU0FBUyxlQUFlLEdBQVcsR0FBaUI7QUE5SXBELE1BQUFBLEtBQUE7QUErSUksTUFBSSxDQUFDLGlCQUFrQjtBQUd2QixRQUFLLE1BQUFBLE1BQUEsT0FBZSxXQUFmLGdCQUFBQSxJQUF1QixVQUF2QixtQkFBOEIsb0JBQW1CLE9BQU87QUFDekQ7QUFBQSxFQUNKO0FBRUEsUUFBTSxnQkFBZ0IsU0FBUyxpQkFBaUIsR0FBRyxDQUFDO0FBQ3BELFFBQU0sYUFBYSxxQkFBcUIsYUFBYTtBQUVyRCxNQUFJLHFCQUFxQixzQkFBc0IsWUFBWTtBQUN2RCxzQkFBa0IsVUFBVSxPQUFPLHdCQUF3QjtBQUFBLEVBQy9EO0FBRUEsTUFBSSxZQUFZO0FBQ1osZUFBVyxVQUFVLElBQUksd0JBQXdCO0FBQ2pELHdCQUFvQjtBQUFBLEVBQ3hCLE9BQU87QUFDSCx3QkFBb0I7QUFBQSxFQUN4QjtBQUNKO0FBNEJBLElBQU0sWUFBWSx1QkFBTyxRQUFRO0FBSXBCO0FBRmIsSUFBTSxVQUFOLE1BQU0sUUFBTztBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLEVBVVQsWUFBWSxPQUFlLElBQUk7QUFDM0IsU0FBSyxTQUFTLElBQUksaUJBQWlCLFlBQVksUUFBUSxJQUFJO0FBRzNELGVBQVcsVUFBVSxPQUFPLG9CQUFvQixRQUFPLFNBQVMsR0FBRztBQUMvRCxVQUNJLFdBQVcsaUJBQ1IsT0FBUSxLQUFhLE1BQU0sTUFBTSxZQUN0QztBQUNFLFFBQUMsS0FBYSxNQUFNLElBQUssS0FBYSxNQUFNLEVBQUUsS0FBSyxJQUFJO0FBQUEsTUFDM0Q7QUFBQSxJQUNKO0FBQUEsRUFDSjtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLEVBUUEsSUFBSSxNQUFzQjtBQUN0QixXQUFPLElBQUksUUFBTyxJQUFJO0FBQUEsRUFDMUI7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsRUFPQSxXQUE4QjtBQUMxQixXQUFPLEtBQUssU0FBUyxFQUFFLGNBQWM7QUFBQSxFQUN6QztBQUFBO0FBQUE7QUFBQTtBQUFBLEVBS0EsU0FBd0I7QUFDcEIsV0FBTyxLQUFLLFNBQVMsRUFBRSxZQUFZO0FBQUEsRUFDdkM7QUFBQTtBQUFBO0FBQUE7QUFBQSxFQUtBLFFBQXVCO0FBQ25CLFdBQU8sS0FBSyxTQUFTLEVBQUUsV0FBVztBQUFBLEVBQ3RDO0FBQUE7QUFBQTtBQUFBO0FBQUEsRUFLQSx5QkFBd0M7QUFDcEMsV0FBTyxLQUFLLFNBQVMsRUFBRSw0QkFBNEI7QUFBQSxFQUN2RDtBQUFBO0FBQUE7QUFBQTtBQUFBLEVBS0Esd0JBQXVDO0FBQ25DLFdBQU8sS0FBSyxTQUFTLEVBQUUsMkJBQTJCO0FBQUEsRUFDdEQ7QUFBQTtBQUFBO0FBQUE7QUFBQSxFQUtBLFFBQXVCO0FBQ25CLFdBQU8sS0FBSyxTQUFTLEVBQUUsV0FBVztBQUFBLEVBQ3RDO0FBQUE7QUFBQTtBQUFBO0FBQUEsRUFLQSxjQUE2QjtBQUN6QixXQUFPLEtBQUssU0FBUyxFQUFFLGlCQUFpQjtBQUFBLEVBQzVDO0FBQUE7QUFBQTtBQUFBO0FBQUEsRUFLQSxhQUE0QjtBQUN4QixXQUFPLEtBQUssU0FBUyxFQUFFLGdCQUFnQjtBQUFBLEVBQzNDO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLEVBT0EsWUFBNkI7QUFDekIsV0FBTyxLQUFLLFNBQVMsRUFBRSxlQUFlO0FBQUEsRUFDMUM7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsRUFPQSxVQUEyQjtBQUN2QixXQUFPLEtBQUssU0FBUyxFQUFFLGFBQWE7QUFBQSxFQUN4QztBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSxFQU9BLFNBQTBCO0FBQ3RCLFdBQU8sS0FBSyxTQUFTLEVBQUUsWUFBWTtBQUFBLEVBQ3ZDO0FBQUE7QUFBQTtBQUFBO0FBQUEsRUFLQSxPQUFzQjtBQUNsQixXQUFPLEtBQUssU0FBUyxFQUFFLFVBQVU7QUFBQSxFQUNyQztBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSxFQU9BLFlBQThCO0FBQzFCLFdBQU8sS0FBSyxTQUFTLEVBQUUsZUFBZTtBQUFBLEVBQzFDO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLEVBT0EsZUFBaUM7QUFDN0IsV0FBTyxLQUFLLFNBQVMsRUFBRSxrQkFBa0I7QUFBQSxFQUM3QztBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSxFQU9BLGNBQWdDO0FBQzVCLFdBQU8sS0FBSyxTQUFTLEVBQUUsaUJBQWlCO0FBQUEsRUFDNUM7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsRUFPQSxjQUFnQztBQUM1QixXQUFPLEtBQUssU0FBUyxFQUFFLGlCQUFpQjtBQUFBLEVBQzVDO0FBQUE7QUFBQTtBQUFBO0FBQUEsRUFLQSxXQUEwQjtBQUN0QixXQUFPLEtBQUssU0FBUyxFQUFFLGNBQWM7QUFBQSxFQUN6QztBQUFBO0FBQUE7QUFBQTtBQUFBLEVBS0EsV0FBMEI7QUFDdEIsV0FBTyxLQUFLLFNBQVMsRUFBRSxjQUFjO0FBQUEsRUFDekM7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsRUFPQSxPQUF3QjtBQUNwQixXQUFPLEtBQUssU0FBUyxFQUFFLFVBQVU7QUFBQSxFQUNyQztBQUFBO0FBQUE7QUFBQTtBQUFBLEVBS0EsZUFBOEI7QUFDMUIsV0FBTyxLQUFLLFNBQVMsRUFBRSxrQkFBa0I7QUFBQSxFQUM3QztBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSxFQU9BLG1CQUFzQztBQUNsQyxXQUFPLEtBQUssU0FBUyxFQUFFLHNCQUFzQjtBQUFBLEVBQ2pEO0FBQUE7QUFBQTtBQUFBO0FBQUEsRUFLQSxTQUF3QjtBQUNwQixXQUFPLEtBQUssU0FBUyxFQUFFLFlBQVk7QUFBQSxFQUN2QztBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSxFQU9BLFlBQThCO0FBQzFCLFdBQU8sS0FBSyxTQUFTLEVBQUUsZUFBZTtBQUFBLEVBQzFDO0FBQUE7QUFBQTtBQUFBO0FBQUEsRUFLQSxVQUF5QjtBQUNyQixXQUFPLEtBQUssU0FBUyxFQUFFLGFBQWE7QUFBQSxFQUN4QztBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLEVBUUEsWUFBWSxHQUFXLEdBQTBCO0FBQzdDLFdBQU8sS0FBSyxTQUFTLEVBQUUsbUJBQW1CLEVBQUUsR0FBRyxFQUFFLENBQUM7QUFBQSxFQUN0RDtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSxFQU9BLGVBQWUsYUFBcUM7QUFDaEQsV0FBTyxLQUFLLFNBQVMsRUFBRSxzQkFBc0IsRUFBRSxZQUFZLENBQUM7QUFBQSxFQUNoRTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSxFQVVBLG9CQUFvQixHQUFXLEdBQVcsR0FBVyxHQUEwQjtBQUMzRSxXQUFPLEtBQUssU0FBUyxFQUFFLDJCQUEyQixFQUFFLEdBQUcsR0FBRyxHQUFHLEVBQUUsQ0FBQztBQUFBLEVBQ3BFO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLEVBT0EsYUFBYSxXQUFtQztBQUM1QyxXQUFPLEtBQUssU0FBUyxFQUFFLG9CQUFvQixFQUFFLFVBQVUsQ0FBQztBQUFBLEVBQzVEO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLEVBT0EsMkJBQTJCLFNBQWlDO0FBQ3hELFdBQU8sS0FBSyxTQUFTLEVBQUUsa0NBQWtDLEVBQUUsUUFBUSxDQUFDO0FBQUEsRUFDeEU7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSxFQVFBLFdBQVcsT0FBZSxRQUErQjtBQUNyRCxXQUFPLEtBQUssU0FBUyxFQUFFLGtCQUFrQixFQUFFLE9BQU8sT0FBTyxDQUFDO0FBQUEsRUFDOUQ7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSxFQVFBLFdBQVcsT0FBZSxRQUErQjtBQUNyRCxXQUFPLEtBQUssU0FBUyxFQUFFLGtCQUFrQixFQUFFLE9BQU8sT0FBTyxDQUFDO0FBQUEsRUFDOUQ7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSxFQVFBLG9CQUFvQixHQUFXLEdBQTBCO0FBQ3JELFdBQU8sS0FBSyxTQUFTLEVBQUUsMkJBQTJCLEVBQUUsR0FBRyxFQUFFLENBQUM7QUFBQSxFQUM5RDtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSxFQU9BLGFBQWFDLFlBQW1DO0FBQzVDLFdBQU8sS0FBSyxTQUFTLEVBQUUsb0JBQW9CLEVBQUUsV0FBQUEsV0FBVSxDQUFDO0FBQUEsRUFDNUQ7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSxFQVFBLFFBQVEsT0FBZSxRQUErQjtBQUNsRCxXQUFPLEtBQUssU0FBUyxFQUFFLGVBQWUsRUFBRSxPQUFPLE9BQU8sQ0FBQztBQUFBLEVBQzNEO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLEVBT0EsU0FBUyxPQUE4QjtBQUNuQyxXQUFPLEtBQUssU0FBUyxFQUFFLGdCQUFnQixFQUFFLE1BQU0sQ0FBQztBQUFBLEVBQ3BEO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLEVBT0EsUUFBUSxNQUE2QjtBQUNqQyxXQUFPLEtBQUssU0FBUyxFQUFFLGVBQWUsRUFBRSxLQUFLLENBQUM7QUFBQSxFQUNsRDtBQUFBO0FBQUE7QUFBQTtBQUFBLEVBS0EsT0FBc0I7QUFDbEIsV0FBTyxLQUFLLFNBQVMsRUFBRSxVQUFVO0FBQUEsRUFDckM7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsRUFPQSxPQUFzQjtBQUNsQixXQUFPLEtBQUssU0FBUyxFQUFFLFVBQVU7QUFBQSxFQUNyQztBQUFBO0FBQUE7QUFBQTtBQUFBLEVBS0EsbUJBQWtDO0FBQzlCLFdBQU8sS0FBSyxTQUFTLEVBQUUsc0JBQXNCO0FBQUEsRUFDakQ7QUFBQTtBQUFBO0FBQUE7QUFBQSxFQUtBLGlCQUFnQztBQUM1QixXQUFPLEtBQUssU0FBUyxFQUFFLG9CQUFvQjtBQUFBLEVBQy9DO0FBQUE7QUFBQTtBQUFBO0FBQUEsRUFLQSxrQkFBaUM7QUFDN0IsV0FBTyxLQUFLLFNBQVMsRUFBRSxxQkFBcUI7QUFBQSxFQUNoRDtBQUFBO0FBQUE7QUFBQTtBQUFBLEVBS0EsZUFBOEI7QUFDMUIsV0FBTyxLQUFLLFNBQVMsRUFBRSxrQkFBa0I7QUFBQSxFQUM3QztBQUFBO0FBQUE7QUFBQTtBQUFBLEVBS0EsYUFBNEI7QUFDeEIsV0FBTyxLQUFLLFNBQVMsRUFBRSxnQkFBZ0I7QUFBQSxFQUMzQztBQUFBO0FBQUE7QUFBQTtBQUFBLEVBS0EsYUFBNEI7QUFDeEIsV0FBTyxLQUFLLFNBQVMsRUFBRSxnQkFBZ0I7QUFBQSxFQUMzQztBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSxFQU9BLFFBQXlCO0FBQ3JCLFdBQU8sS0FBSyxTQUFTLEVBQUUsV0FBVztBQUFBLEVBQ3RDO0FBQUE7QUFBQTtBQUFBO0FBQUEsRUFLQSxPQUFzQjtBQUNsQixXQUFPLEtBQUssU0FBUyxFQUFFLFVBQVU7QUFBQSxFQUNyQztBQUFBO0FBQUE7QUFBQTtBQUFBLEVBS0EsU0FBd0I7QUFDcEIsV0FBTyxLQUFLLFNBQVMsRUFBRSxZQUFZO0FBQUEsRUFDdkM7QUFBQTtBQUFBO0FBQUE7QUFBQSxFQUtBLFVBQXlCO0FBQ3JCLFdBQU8sS0FBSyxTQUFTLEVBQUUsYUFBYTtBQUFBLEVBQ3hDO0FBQUE7QUFBQTtBQUFBO0FBQUEsRUFLQSxZQUEyQjtBQUN2QixXQUFPLEtBQUssU0FBUyxFQUFFLGVBQWU7QUFBQSxFQUMxQztBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSxFQVVBLHVCQUF1QixXQUFxQixHQUFXLEdBQWlCO0FBNW5CNUUsUUFBQUMsS0FBQTtBQThuQlEsVUFBSyxNQUFBQSxNQUFBLE9BQWUsV0FBZixnQkFBQUEsSUFBdUIsVUFBdkIsbUJBQThCLG9CQUFtQixPQUFPO0FBQ3pEO0FBQUEsSUFDSjtBQUVBLFVBQU0sVUFBVSxTQUFTLGlCQUFpQixHQUFHLENBQUM7QUFDOUMsVUFBTSxhQUFhLHFCQUFxQixPQUFPO0FBRS9DLFFBQUksQ0FBQyxZQUFZO0FBRWI7QUFBQSxJQUNKO0FBRUEsVUFBTSxpQkFBaUI7QUFBQSxNQUNuQixJQUFJLFdBQVc7QUFBQSxNQUNmLFdBQVcsTUFBTSxLQUFLLFdBQVcsU0FBUztBQUFBLE1BQzFDLFlBQVksQ0FBQztBQUFBLElBQ2pCO0FBQ0EsYUFBUyxJQUFJLEdBQUcsSUFBSSxXQUFXLFdBQVcsUUFBUSxLQUFLO0FBQ25ELFlBQU0sT0FBTyxXQUFXLFdBQVcsQ0FBQztBQUNwQyxxQkFBZSxXQUFXLEtBQUssSUFBSSxJQUFJLEtBQUs7QUFBQSxJQUNoRDtBQUVBLFVBQU0sVUFBVTtBQUFBLE1BQ1o7QUFBQSxNQUNBO0FBQUEsTUFDQTtBQUFBLE1BQ0E7QUFBQSxJQUNKO0FBRUEsU0FBSyxTQUFTLEVBQUUsY0FBYyxPQUFPO0FBR3JDLHNCQUFrQjtBQUFBLEVBQ3RCO0FBQUE7QUFBQTtBQUFBO0FBQUEsRUFLQSxhQUE0QjtBQUN4QixXQUFPLEtBQUssU0FBUyxFQUFFLGdCQUFnQjtBQUFBLEVBQzNDO0FBQUE7QUFBQTtBQUFBO0FBQUEsRUFLQSxRQUF1QjtBQUNuQixXQUFPLEtBQUssU0FBUyxFQUFFLFdBQVc7QUFBQSxFQUN0QztBQUNKO0FBN2VBLElBQU0sU0FBTjtBQWtmQSxJQUFNLGFBQWEsSUFBSSxPQUFPLEVBQUU7QUFNaEMsU0FBUywyQkFBMkI7QUFDaEMsUUFBTSxhQUFhLFNBQVM7QUFDNUIsTUFBSSxtQkFBbUI7QUFFdkIsYUFBVyxpQkFBaUIsYUFBYSxDQUFDLFVBQVU7QUE3ckJ4RCxRQUFBQSxLQUFBO0FBOHJCUSxRQUFJLEdBQUNBLE1BQUEsTUFBTSxpQkFBTixnQkFBQUEsSUFBb0IsTUFBTSxTQUFTLFdBQVU7QUFDOUM7QUFBQSxJQUNKO0FBQ0EsVUFBTSxlQUFlO0FBRXJCLFVBQUssa0JBQWUsV0FBZixtQkFBdUIsVUFBdkIsbUJBQThCLG9CQUFtQixPQUFPO0FBQ3pELFlBQU0sYUFBYSxhQUFhO0FBQ2hDO0FBQUEsSUFDSjtBQUNBO0FBRUEsVUFBTSxnQkFBZ0IsU0FBUyxpQkFBaUIsTUFBTSxTQUFTLE1BQU0sT0FBTztBQUM1RSxVQUFNLGFBQWEscUJBQXFCLGFBQWE7QUFHckQsUUFBSSxxQkFBcUIsc0JBQXNCLFlBQVk7QUFDdkQsd0JBQWtCLFVBQVUsT0FBTyx3QkFBd0I7QUFBQSxJQUMvRDtBQUVBLFFBQUksWUFBWTtBQUNaLGlCQUFXLFVBQVUsSUFBSSx3QkFBd0I7QUFDakQsWUFBTSxhQUFhLGFBQWE7QUFDaEMsMEJBQW9CO0FBQUEsSUFDeEIsT0FBTztBQUNILFlBQU0sYUFBYSxhQUFhO0FBQ2hDLDBCQUFvQjtBQUFBLElBQ3hCO0FBQUEsRUFDSixHQUFHLEtBQUs7QUFFUixhQUFXLGlCQUFpQixZQUFZLENBQUMsVUFBVTtBQTN0QnZELFFBQUFBLEtBQUE7QUE0dEJRLFFBQUksR0FBQ0EsTUFBQSxNQUFNLGlCQUFOLGdCQUFBQSxJQUFvQixNQUFNLFNBQVMsV0FBVTtBQUM5QztBQUFBLElBQ0o7QUFDQSxVQUFNLGVBQWU7QUFFckIsVUFBSyxrQkFBZSxXQUFmLG1CQUF1QixVQUF2QixtQkFBOEIsb0JBQW1CLE9BQU87QUFDekQsWUFBTSxhQUFhLGFBQWE7QUFDaEM7QUFBQSxJQUNKO0FBR0EsVUFBTSxnQkFBZ0IsU0FBUyxpQkFBaUIsTUFBTSxTQUFTLE1BQU0sT0FBTztBQUM1RSxVQUFNLGFBQWEscUJBQXFCLGFBQWE7QUFFckQsUUFBSSxxQkFBcUIsc0JBQXNCLFlBQVk7QUFDdkQsd0JBQWtCLFVBQVUsT0FBTyx3QkFBd0I7QUFBQSxJQUMvRDtBQUVBLFFBQUksWUFBWTtBQUNaLFVBQUksQ0FBQyxXQUFXLFVBQVUsU0FBUyx3QkFBd0IsR0FBRztBQUMxRCxtQkFBVyxVQUFVLElBQUksd0JBQXdCO0FBQUEsTUFDckQ7QUFDQSxZQUFNLGFBQWEsYUFBYTtBQUNoQywwQkFBb0I7QUFBQSxJQUN4QixPQUFPO0FBQ0gsWUFBTSxhQUFhLGFBQWE7QUFDaEMsMEJBQW9CO0FBQUEsSUFDeEI7QUFBQSxFQUNKLEdBQUcsS0FBSztBQUVSLGFBQVcsaUJBQWlCLGFBQWEsQ0FBQyxVQUFVO0FBMXZCeEQsUUFBQUEsS0FBQTtBQTJ2QlEsUUFBSSxHQUFDQSxNQUFBLE1BQU0saUJBQU4sZ0JBQUFBLElBQW9CLE1BQU0sU0FBUyxXQUFVO0FBQzlDO0FBQUEsSUFDSjtBQUNBLFVBQU0sZUFBZTtBQUVyQixVQUFLLGtCQUFlLFdBQWYsbUJBQXVCLFVBQXZCLG1CQUE4QixvQkFBbUIsT0FBTztBQUN6RDtBQUFBLElBQ0o7QUFJQSxRQUFJLE1BQU0sa0JBQWtCLE1BQU07QUFDOUI7QUFBQSxJQUNKO0FBRUE7QUFFQSxRQUFJLHFCQUFxQixLQUNwQixxQkFBcUIsQ0FBQyxrQkFBa0IsU0FBUyxNQUFNLGFBQXFCLEdBQUk7QUFDakYsVUFBSSxtQkFBbUI7QUFDbkIsMEJBQWtCLFVBQVUsT0FBTyx3QkFBd0I7QUFDM0QsNEJBQW9CO0FBQUEsTUFDeEI7QUFDQSx5QkFBbUI7QUFBQSxJQUN2QjtBQUFBLEVBQ0osR0FBRyxLQUFLO0FBRVIsYUFBVyxpQkFBaUIsUUFBUSxDQUFDLFVBQVU7QUF0eEJuRCxRQUFBQSxLQUFBO0FBdXhCUSxRQUFJLEdBQUNBLE1BQUEsTUFBTSxpQkFBTixnQkFBQUEsSUFBb0IsTUFBTSxTQUFTLFdBQVU7QUFDOUM7QUFBQSxJQUNKO0FBQ0EsVUFBTSxlQUFlO0FBRXJCLFVBQUssa0JBQWUsV0FBZixtQkFBdUIsVUFBdkIsbUJBQThCLG9CQUFtQixPQUFPO0FBQ3pEO0FBQUEsSUFDSjtBQUNBLHVCQUFtQjtBQUVuQixRQUFJLG1CQUFtQjtBQUNuQix3QkFBa0IsVUFBVSxPQUFPLHdCQUF3QjtBQUMzRCwwQkFBb0I7QUFBQSxJQUN4QjtBQUlBLFFBQUksb0JBQW9CLEdBQUc7QUFDdkIsWUFBTSxRQUFnQixDQUFDO0FBQ3ZCLFVBQUksTUFBTSxhQUFhLE9BQU87QUFDMUIsbUJBQVcsUUFBUSxNQUFNLGFBQWEsT0FBTztBQUN6QyxjQUFJLEtBQUssU0FBUyxRQUFRO0FBQ3RCLGtCQUFNLE9BQU8sS0FBSyxVQUFVO0FBQzVCLGdCQUFJLEtBQU0sT0FBTSxLQUFLLElBQUk7QUFBQSxVQUM3QjtBQUFBLFFBQ0o7QUFBQSxNQUNKLFdBQVcsTUFBTSxhQUFhLE9BQU87QUFDakMsbUJBQVcsUUFBUSxNQUFNLGFBQWEsT0FBTztBQUN6QyxnQkFBTSxLQUFLLElBQUk7QUFBQSxRQUNuQjtBQUFBLE1BQ0o7QUFFQSxVQUFJLE1BQU0sU0FBUyxHQUFHO0FBQ2xCLHlCQUFpQixNQUFNLFNBQVMsTUFBTSxTQUFTLEtBQUs7QUFBQSxNQUN4RDtBQUFBLElBQ0o7QUFBQSxFQUNKLEdBQUcsS0FBSztBQUNaO0FBR0EsSUFBSSxPQUFPLFdBQVcsZUFBZSxPQUFPLGFBQWEsYUFBYTtBQUNsRSwyQkFBeUI7QUFDN0I7QUFFQSxJQUFPLGlCQUFROzs7QVY3eUJmLFNBQVMsVUFBVSxXQUFtQixPQUFZLE1BQVk7QUFDMUQsT0FBSyxXQUFXLElBQUk7QUFDeEI7QUFRQSxTQUFTLGlCQUFpQixZQUFvQixZQUFvQjtBQUM5RCxRQUFNLGVBQWUsZUFBTyxJQUFJLFVBQVU7QUFDMUMsUUFBTSxTQUFVLGFBQXFCLFVBQVU7QUFFL0MsTUFBSSxPQUFPLFdBQVcsWUFBWTtBQUM5QixZQUFRLE1BQU0sa0JBQWtCLG1CQUFVLGNBQWE7QUFDdkQ7QUFBQSxFQUNKO0FBRUEsTUFBSTtBQUNBLFdBQU8sS0FBSyxZQUFZO0FBQUEsRUFDNUIsU0FBUyxHQUFHO0FBQ1IsWUFBUSxNQUFNLGdDQUFnQyxtQkFBVSxRQUFPLENBQUM7QUFBQSxFQUNwRTtBQUNKO0FBS0EsU0FBUyxlQUFlLElBQWlCO0FBQ3JDLFFBQU0sVUFBVSxHQUFHO0FBRW5CLFdBQVMsVUFBVSxTQUFTLE9BQU87QUFDL0IsUUFBSSxXQUFXO0FBQ1g7QUFFSixVQUFNLFlBQVksUUFBUSxhQUFhLFdBQVcsS0FBSyxRQUFRLGFBQWEsZ0JBQWdCO0FBQzVGLFVBQU0sZUFBZSxRQUFRLGFBQWEsbUJBQW1CLEtBQUssUUFBUSxhQUFhLHdCQUF3QixLQUFLO0FBQ3BILFVBQU0sZUFBZSxRQUFRLGFBQWEsWUFBWSxLQUFLLFFBQVEsYUFBYSxpQkFBaUI7QUFDakcsVUFBTSxNQUFNLFFBQVEsYUFBYSxhQUFhLEtBQUssUUFBUSxhQUFhLGtCQUFrQjtBQUUxRixRQUFJLGNBQWM7QUFDZCxnQkFBVSxTQUFTO0FBQ3ZCLFFBQUksaUJBQWlCO0FBQ2pCLHVCQUFpQixjQUFjLFlBQVk7QUFDL0MsUUFBSSxRQUFRO0FBQ1IsV0FBSyxRQUFRLEdBQUc7QUFBQSxFQUN4QjtBQUVBLFFBQU0sVUFBVSxRQUFRLGFBQWEsYUFBYSxLQUFLLFFBQVEsYUFBYSxrQkFBa0I7QUFFOUYsTUFBSSxTQUFTO0FBQ1QsYUFBUztBQUFBLE1BQ0wsT0FBTztBQUFBLE1BQ1AsU0FBUztBQUFBLE1BQ1QsVUFBVTtBQUFBLE1BQ1YsU0FBUztBQUFBLFFBQ0wsRUFBRSxPQUFPLE1BQU07QUFBQSxRQUNmLEVBQUUsT0FBTyxNQUFNLFdBQVcsS0FBSztBQUFBLE1BQ25DO0FBQUEsSUFDSixDQUFDLEVBQUUsS0FBSyxTQUFTO0FBQUEsRUFDckIsT0FBTztBQUNILGNBQVU7QUFBQSxFQUNkO0FBQ0o7QUFHQSxJQUFNLGdCQUFnQix1QkFBTyxZQUFZO0FBQ3pDLElBQU0sZ0JBQWdCLHVCQUFPLFlBQVk7QUFDekMsSUFBTSxrQkFBa0IsdUJBQU8sY0FBYztBQVF4QztBQUZMLElBQU0sMEJBQU4sTUFBOEI7QUFBQSxFQUkxQixjQUFjO0FBQ1YsU0FBSyxhQUFhLElBQUksSUFBSSxnQkFBZ0I7QUFBQSxFQUM5QztBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsRUFTQSxJQUFJLFNBQWtCLFVBQTZDO0FBQy9ELFdBQU8sRUFBRSxRQUFRLEtBQUssYUFBYSxFQUFFLE9BQU87QUFBQSxFQUNoRDtBQUFBO0FBQUE7QUFBQTtBQUFBLEVBS0EsUUFBYztBQUNWLFNBQUssYUFBYSxFQUFFLE1BQU07QUFDMUIsU0FBSyxhQUFhLElBQUksSUFBSSxnQkFBZ0I7QUFBQSxFQUM5QztBQUNKO0FBU0ssZUFFQTtBQUpMLElBQU0sa0JBQU4sTUFBc0I7QUFBQSxFQU1sQixjQUFjO0FBQ1YsU0FBSyxhQUFhLElBQUksb0JBQUksUUFBUTtBQUNsQyxTQUFLLGVBQWUsSUFBSTtBQUFBLEVBQzVCO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsRUFRQSxJQUFJLFNBQWtCLFVBQTZDO0FBQy9ELFFBQUksQ0FBQyxLQUFLLGFBQWEsRUFBRSxJQUFJLE9BQU8sR0FBRztBQUFFLFdBQUssZUFBZTtBQUFBLElBQUs7QUFDbEUsU0FBSyxhQUFhLEVBQUUsSUFBSSxTQUFTLFFBQVE7QUFDekMsV0FBTyxDQUFDO0FBQUEsRUFDWjtBQUFBO0FBQUE7QUFBQTtBQUFBLEVBS0EsUUFBYztBQUNWLFFBQUksS0FBSyxlQUFlLEtBQUs7QUFDekI7QUFFSixlQUFXLFdBQVcsU0FBUyxLQUFLLGlCQUFpQixHQUFHLEdBQUc7QUFDdkQsVUFBSSxLQUFLLGVBQWUsS0FBSztBQUN6QjtBQUVKLFlBQU0sV0FBVyxLQUFLLGFBQWEsRUFBRSxJQUFJLE9BQU87QUFDaEQsVUFBSSxZQUFZLE1BQU07QUFBRSxhQUFLLGVBQWU7QUFBQSxNQUFLO0FBRWpELGlCQUFXLFdBQVcsWUFBWSxDQUFDO0FBQy9CLGdCQUFRLG9CQUFvQixTQUFTLGNBQWM7QUFBQSxJQUMzRDtBQUVBLFNBQUssYUFBYSxJQUFJLG9CQUFJLFFBQVE7QUFDbEMsU0FBSyxlQUFlLElBQUk7QUFBQSxFQUM1QjtBQUNKO0FBRUEsSUFBTSxrQkFBa0Isa0JBQWtCLElBQUksSUFBSSx3QkFBd0IsSUFBSSxJQUFJLGdCQUFnQjtBQUtsRyxTQUFTLGdCQUFnQixTQUF3QjtBQUM3QyxRQUFNLGdCQUFnQjtBQUN0QixRQUFNLGNBQWUsUUFBUSxhQUFhLGFBQWEsS0FBSyxRQUFRLGFBQWEsa0JBQWtCLEtBQUs7QUFDeEcsUUFBTSxXQUFxQixDQUFDO0FBRTVCLE1BQUk7QUFDSixVQUFRLFFBQVEsY0FBYyxLQUFLLFdBQVcsT0FBTztBQUNqRCxhQUFTLEtBQUssTUFBTSxDQUFDLENBQUM7QUFFMUIsUUFBTSxVQUFVLGdCQUFnQixJQUFJLFNBQVMsUUFBUTtBQUNyRCxhQUFXLFdBQVc7QUFDbEIsWUFBUSxpQkFBaUIsU0FBUyxnQkFBZ0IsT0FBTztBQUNqRTtBQUtPLFNBQVMsU0FBZTtBQUMzQixZQUFVLE1BQU07QUFDcEI7QUFLTyxTQUFTLFNBQWU7QUFDM0Isa0JBQWdCLE1BQU07QUFDdEIsV0FBUyxLQUFLLGlCQUFpQixtR0FBbUcsRUFBRSxRQUFRLGVBQWU7QUFDL0o7OztBV2hNQSxPQUFPLFFBQVE7QUFDZixPQUFVO0FBRVYsSUFBSSxNQUFPO0FBQ1AsV0FBUyxzQkFBc0I7QUFDbkM7OztBQ3JCQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBWUEsSUFBTUMsUUFBTyxpQkFBaUIsWUFBWSxNQUFNO0FBRWhELElBQU0sbUJBQW1CO0FBQ3pCLElBQU0sb0JBQW9CO0FBQzFCLElBQU0scUJBQXFCO0FBRTNCLElBQU0sV0FBVyxXQUFZO0FBbEI3QixNQUFBQyxLQUFBO0FBbUJJLE1BQUk7QUFFQSxTQUFLLE1BQUFBLE1BQUEsT0FBZSxXQUFmLGdCQUFBQSxJQUF1QixZQUF2QixtQkFBZ0MsYUFBYTtBQUM5QyxhQUFRLE9BQWUsT0FBTyxRQUFRLFlBQVksS0FBTSxPQUFlLE9BQU8sT0FBTztBQUFBLElBQ3pGLFlBRVUsd0JBQWUsV0FBZixtQkFBdUIsb0JBQXZCLG1CQUF5QyxnQkFBekMsbUJBQXNELGFBQWE7QUFDekUsYUFBUSxPQUFlLE9BQU8sZ0JBQWdCLFVBQVUsRUFBRSxZQUFZLEtBQU0sT0FBZSxPQUFPLGdCQUFnQixVQUFVLENBQUM7QUFBQSxJQUNqSSxZQUVVLFlBQWUsVUFBZixtQkFBc0IsUUFBUTtBQUNwQyxhQUFPLENBQUMsUUFBYyxPQUFlLE1BQU0sT0FBTyxPQUFPLFFBQVEsV0FBVyxNQUFNLEtBQUssVUFBVSxHQUFHLENBQUM7QUFBQSxJQUN6RztBQUFBLEVBQ0osU0FBUSxHQUFHO0FBQUEsRUFBQztBQUVaLFVBQVE7QUFBQSxJQUFLO0FBQUEsSUFDVDtBQUFBLElBQ0E7QUFBQSxJQUNBO0FBQUEsRUFBd0Q7QUFDNUQsU0FBTztBQUNYLEdBQUc7QUFFSSxTQUFTLE9BQU8sS0FBZ0I7QUFDbkMscUNBQVU7QUFDZDtBQU9PLFNBQVMsYUFBK0I7QUFDM0MsU0FBT0QsTUFBSyxnQkFBZ0I7QUFDaEM7QUFPQSxlQUFzQixlQUE2QztBQUMvRCxTQUFPQSxNQUFLLGtCQUFrQjtBQUNsQztBQStCTyxTQUFTLGNBQXdDO0FBQ3BELFNBQU9BLE1BQUssaUJBQWlCO0FBQ2pDO0FBT08sU0FBUyxZQUFxQjtBQXJHckMsTUFBQUMsS0FBQTtBQXNHSSxXQUFRLE1BQUFBLE1BQUEsT0FBZSxXQUFmLGdCQUFBQSxJQUF1QixnQkFBdkIsbUJBQW9DLFFBQU87QUFDdkQ7QUFPTyxTQUFTLFVBQW1CO0FBOUduQyxNQUFBQSxLQUFBO0FBK0dJLFdBQVEsTUFBQUEsTUFBQSxPQUFlLFdBQWYsZ0JBQUFBLElBQXVCLGdCQUF2QixtQkFBb0MsUUFBTztBQUN2RDtBQU9PLFNBQVMsUUFBaUI7QUF2SGpDLE1BQUFBLEtBQUE7QUF3SEksV0FBUSxNQUFBQSxNQUFBLE9BQWUsV0FBZixnQkFBQUEsSUFBdUIsZ0JBQXZCLG1CQUFvQyxRQUFPO0FBQ3ZEO0FBT08sU0FBUyxVQUFtQjtBQWhJbkMsTUFBQUEsS0FBQTtBQWlJSSxXQUFRLE1BQUFBLE1BQUEsT0FBZSxXQUFmLGdCQUFBQSxJQUF1QixnQkFBdkIsbUJBQW9DLFVBQVM7QUFDekQ7QUFPTyxTQUFTLFFBQWlCO0FBeklqQyxNQUFBQSxLQUFBO0FBMElJLFdBQVEsTUFBQUEsTUFBQSxPQUFlLFdBQWYsZ0JBQUFBLElBQXVCLGdCQUF2QixtQkFBb0MsVUFBUztBQUN6RDtBQU9PLFNBQVMsVUFBbUI7QUFsSm5DLE1BQUFBLEtBQUE7QUFtSkksV0FBUSxNQUFBQSxNQUFBLE9BQWUsV0FBZixnQkFBQUEsSUFBdUIsZ0JBQXZCLG1CQUFvQyxVQUFTO0FBQ3pEO0FBT08sU0FBUyxVQUFtQjtBQTNKbkMsTUFBQUEsS0FBQTtBQTRKSSxTQUFPLFNBQVMsTUFBQUEsTUFBQSxPQUFlLFdBQWYsZ0JBQUFBLElBQXVCLGdCQUF2QixtQkFBb0MsS0FBSztBQUM3RDs7O0FDOUlBLE9BQU8saUJBQWlCLGVBQWUsa0JBQWtCO0FBRXpELElBQU1DLFFBQU8saUJBQWlCLFlBQVksV0FBVztBQUVyRCxJQUFNLGtCQUFrQjtBQUV4QixTQUFTLGdCQUFnQixJQUFZLEdBQVcsR0FBVyxNQUFpQjtBQUN4RSxPQUFLQSxNQUFLLGlCQUFpQixFQUFDLElBQUksR0FBRyxHQUFHLEtBQUksQ0FBQztBQUMvQztBQUVBLFNBQVMsbUJBQW1CLE9BQW1CO0FBQzNDLFFBQU0sU0FBUyxZQUFZLEtBQUs7QUFHaEMsUUFBTSxvQkFBb0IsT0FBTyxpQkFBaUIsTUFBTSxFQUFFLGlCQUFpQixzQkFBc0IsRUFBRSxLQUFLO0FBRXhHLE1BQUksbUJBQW1CO0FBQ25CLFVBQU0sZUFBZTtBQUNyQixVQUFNLE9BQU8sT0FBTyxpQkFBaUIsTUFBTSxFQUFFLGlCQUFpQiwyQkFBMkI7QUFDekYsb0JBQWdCLG1CQUFtQixNQUFNLFNBQVMsTUFBTSxTQUFTLElBQUk7QUFBQSxFQUN6RSxPQUFPO0FBQ0gsOEJBQTBCLE9BQU8sTUFBTTtBQUFBLEVBQzNDO0FBQ0o7QUFVQSxTQUFTLDBCQUEwQixPQUFtQixRQUFxQjtBQUV2RSxNQUFJLFFBQVEsR0FBRztBQUNYO0FBQUEsRUFDSjtBQUdBLFVBQVEsT0FBTyxpQkFBaUIsTUFBTSxFQUFFLGlCQUFpQix1QkFBdUIsRUFBRSxLQUFLLEdBQUc7QUFBQSxJQUN0RixLQUFLO0FBQ0Q7QUFBQSxJQUNKLEtBQUs7QUFDRCxZQUFNLGVBQWU7QUFDckI7QUFBQSxFQUNSO0FBR0EsTUFBSSxPQUFPLG1CQUFtQjtBQUMxQjtBQUFBLEVBQ0o7QUFHQSxRQUFNLFlBQVksT0FBTyxhQUFhO0FBQ3RDLFFBQU0sZUFBZSxhQUFhLFVBQVUsU0FBUyxFQUFFLFNBQVM7QUFDaEUsTUFBSSxjQUFjO0FBQ2QsYUFBUyxJQUFJLEdBQUcsSUFBSSxVQUFVLFlBQVksS0FBSztBQUMzQyxZQUFNLFFBQVEsVUFBVSxXQUFXLENBQUM7QUFDcEMsWUFBTSxRQUFRLE1BQU0sZUFBZTtBQUNuQyxlQUFTLElBQUksR0FBRyxJQUFJLE1BQU0sUUFBUSxLQUFLO0FBQ25DLGNBQU0sT0FBTyxNQUFNLENBQUM7QUFDcEIsWUFBSSxTQUFTLGlCQUFpQixLQUFLLE1BQU0sS0FBSyxHQUFHLE1BQU0sUUFBUTtBQUMzRDtBQUFBLFFBQ0o7QUFBQSxNQUNKO0FBQUEsSUFDSjtBQUFBLEVBQ0o7QUFHQSxNQUFJLGtCQUFrQixvQkFBb0Isa0JBQWtCLHFCQUFxQjtBQUM3RSxRQUFJLGdCQUFpQixDQUFDLE9BQU8sWUFBWSxDQUFDLE9BQU8sVUFBVztBQUN4RDtBQUFBLElBQ0o7QUFBQSxFQUNKO0FBR0EsUUFBTSxlQUFlO0FBQ3pCOzs7QUM3RkE7QUFBQTtBQUFBO0FBQUE7QUFnQk8sU0FBUyxRQUFRLEtBQWtCO0FBQ3RDLE1BQUk7QUFDQSxXQUFPLE9BQU8sT0FBTyxNQUFNLEdBQUc7QUFBQSxFQUNsQyxTQUFTLEdBQUc7QUFDUixVQUFNLElBQUksTUFBTSw4QkFBOEIsTUFBTSxRQUFRLEdBQUcsRUFBRSxPQUFPLEVBQUUsQ0FBQztBQUFBLEVBQy9FO0FBQ0o7OztBQ1BBLElBQUksVUFBVTtBQUNkLElBQUksV0FBVztBQUVmLElBQUksWUFBWTtBQUNoQixJQUFJLFlBQVk7QUFDaEIsSUFBSSxXQUFXO0FBQ2YsSUFBSSxhQUFxQjtBQUN6QixJQUFJLGdCQUFnQjtBQUVwQixJQUFJLFVBQVU7QUFDZCxJQUFNLGlCQUFpQixnQkFBZ0I7QUFFdkMsT0FBTyxTQUFTLE9BQU8sVUFBVSxDQUFDO0FBQ2xDLE9BQU8sT0FBTyxlQUFlLENBQUMsVUFBeUI7QUFDbkQsY0FBWTtBQUNaLE1BQUksQ0FBQyxXQUFXO0FBRVosZ0JBQVksV0FBVztBQUN2QixjQUFVO0FBQUEsRUFDZDtBQUNKO0FBR0EsSUFBSSxlQUFlO0FBQ25CLFNBQVMsV0FBb0I7QUF2QzdCLE1BQUFDLEtBQUE7QUF3Q0ksUUFBTSxNQUFNLE1BQUFBLE1BQUEsT0FBZSxXQUFmLGdCQUFBQSxJQUF1QixnQkFBdkIsbUJBQW9DO0FBQ2hELE1BQUksT0FBTyxTQUFTLE9BQU8sVUFBVyxRQUFPO0FBRTdDLFFBQU0sS0FBSyxVQUFVLGFBQWEsVUFBVSxVQUFXLE9BQWUsU0FBUztBQUMvRSxTQUFPLCtDQUErQyxLQUFLLEVBQUU7QUFDakU7QUFDQSxTQUFTLHNCQUE0QjtBQUNqQyxNQUFJLGFBQWM7QUFDbEIsTUFBSSxTQUFTLEVBQUc7QUFDaEIsU0FBTyxpQkFBaUIsYUFBYSxRQUFRLEVBQUUsU0FBUyxLQUFLLENBQUM7QUFDOUQsU0FBTyxpQkFBaUIsYUFBYSxRQUFRLEVBQUUsU0FBUyxLQUFLLENBQUM7QUFDOUQsU0FBTyxpQkFBaUIsV0FBVyxRQUFRLEVBQUUsU0FBUyxLQUFLLENBQUM7QUFDNUQsYUFBVyxNQUFNLENBQUMsU0FBUyxlQUFlLFVBQVUsR0FBRztBQUNuRCxXQUFPLGlCQUFpQixJQUFJLGVBQWUsRUFBRSxTQUFTLEtBQUssQ0FBQztBQUFBLEVBQ2hFO0FBQ0EsaUJBQWU7QUFDbkI7QUFFQSxvQkFBb0I7QUFFcEIsU0FBUyxpQkFBaUIsb0JBQW9CLHFCQUFxQixFQUFFLE1BQU0sS0FBSyxDQUFDO0FBRWpGLElBQUksZUFBZTtBQUNuQixJQUFNLGNBQWMsT0FBTyxZQUFZLE1BQU07QUFDekMsTUFBSSxjQUFjO0FBQUUsV0FBTyxjQUFjLFdBQVc7QUFBRztBQUFBLEVBQVE7QUFDL0Qsc0JBQW9CO0FBQ3BCLE1BQUksRUFBRSxlQUFlLEtBQUs7QUFBRSxXQUFPLGNBQWMsV0FBVztBQUFBLEVBQUc7QUFDbkUsR0FBRyxFQUFFO0FBRUwsU0FBUyxjQUFjLE9BQWM7QUFFakMsTUFBSSxZQUFZLFVBQVU7QUFDdEIsVUFBTSx5QkFBeUI7QUFDL0IsVUFBTSxnQkFBZ0I7QUFDdEIsVUFBTSxlQUFlO0FBQUEsRUFDekI7QUFDSjtBQUdBLElBQU0sWUFBWTtBQUNsQixJQUFNLFVBQVk7QUFDbEIsSUFBTSxZQUFZO0FBRWxCLFNBQVMsT0FBTyxPQUFtQjtBQUkvQixNQUFJLFdBQW1CLGVBQWUsTUFBTTtBQUM1QyxVQUFRLE1BQU0sTUFBTTtBQUFBLElBQ2hCLEtBQUs7QUFDRCxrQkFBWTtBQUNaLFVBQUksQ0FBQyxnQkFBZ0I7QUFBRSx1QkFBZSxVQUFXLEtBQUssTUFBTTtBQUFBLE1BQVM7QUFDckU7QUFBQSxJQUNKLEtBQUs7QUFDRCxrQkFBWTtBQUNaLFVBQUksQ0FBQyxnQkFBZ0I7QUFBRSx1QkFBZSxVQUFVLEVBQUUsS0FBSyxNQUFNO0FBQUEsTUFBUztBQUN0RTtBQUFBLElBQ0o7QUFDSSxrQkFBWTtBQUNaLFVBQUksQ0FBQyxnQkFBZ0I7QUFBRSx1QkFBZTtBQUFBLE1BQVM7QUFDL0M7QUFBQSxFQUNSO0FBRUEsTUFBSSxXQUFXLFVBQVUsQ0FBQztBQUMxQixNQUFJLFVBQVUsZUFBZSxDQUFDO0FBRTlCLFlBQVU7QUFHVixNQUFJLGNBQWMsYUFBYSxFQUFFLFVBQVUsTUFBTSxTQUFTO0FBQ3RELGdCQUFhLEtBQUssTUFBTTtBQUN4QixlQUFZLEtBQUssTUFBTTtBQUFBLEVBQzNCO0FBSUEsTUFDSSxjQUFjLGFBQ1gsWUFFQyxhQUVJLGNBQWMsYUFDWCxNQUFNLFdBQVcsSUFHOUI7QUFDRSxVQUFNLHlCQUF5QjtBQUMvQixVQUFNLGdCQUFnQjtBQUN0QixVQUFNLGVBQWU7QUFBQSxFQUN6QjtBQUdBLE1BQUksV0FBVyxHQUFHO0FBQUUsY0FBVSxLQUFLO0FBQUEsRUFBRztBQUV0QyxNQUFJLFVBQVUsR0FBRztBQUFFLGdCQUFZLEtBQUs7QUFBQSxFQUFHO0FBR3ZDLE1BQUksY0FBYyxXQUFXO0FBQUUsZ0JBQVksS0FBSztBQUFBLEVBQUc7QUFBQztBQUN4RDtBQUVBLFNBQVMsWUFBWSxPQUF5QjtBQUUxQyxZQUFVO0FBQ1YsY0FBWTtBQUdaLE1BQUksQ0FBQyxVQUFVLEdBQUc7QUFDZCxRQUFJLE1BQU0sU0FBUyxlQUFlLE1BQU0sV0FBVyxLQUFLLE1BQU0sV0FBVyxHQUFHO0FBQ3hFO0FBQUEsSUFDSjtBQUFBLEVBQ0o7QUFFQSxNQUFJLFlBQVk7QUFFWixnQkFBWTtBQUVaO0FBQUEsRUFDSjtBQUdBLFFBQU0sU0FBUyxZQUFZLEtBQUs7QUFJaEMsUUFBTSxRQUFRLE9BQU8saUJBQWlCLE1BQU07QUFDNUMsWUFDSSxNQUFNLGlCQUFpQixtQkFBbUIsRUFBRSxLQUFLLE1BQU0sV0FFbkQsTUFBTSxVQUFVLFdBQVcsTUFBTSxXQUFXLElBQUksT0FBTyxlQUNwRCxNQUFNLFVBQVUsV0FBVyxNQUFNLFVBQVUsSUFBSSxPQUFPO0FBR3JFO0FBRUEsU0FBUyxVQUFVLE9BQW1CO0FBRWxDLFlBQVU7QUFDVixhQUFXO0FBQ1gsY0FBWTtBQUNaLGFBQVc7QUFDZjtBQUVBLElBQU0sZ0JBQWdCLE9BQU8sT0FBTztBQUFBLEVBQ2hDLGFBQWE7QUFBQSxFQUNiLGFBQWE7QUFBQSxFQUNiLGFBQWE7QUFBQSxFQUNiLGFBQWE7QUFBQSxFQUNiLFlBQVk7QUFBQSxFQUNaLFlBQVk7QUFBQSxFQUNaLFlBQVk7QUFBQSxFQUNaLFlBQVk7QUFDaEIsQ0FBQztBQUVELFNBQVMsVUFBVSxNQUF5QztBQUN4RCxNQUFJLE1BQU07QUFDTixRQUFJLENBQUMsWUFBWTtBQUFFLHNCQUFnQixTQUFTLEtBQUssTUFBTTtBQUFBLElBQVE7QUFDL0QsYUFBUyxLQUFLLE1BQU0sU0FBUyxjQUFjLElBQUk7QUFBQSxFQUNuRCxXQUFXLENBQUMsUUFBUSxZQUFZO0FBQzVCLGFBQVMsS0FBSyxNQUFNLFNBQVM7QUFBQSxFQUNqQztBQUVBLGVBQWEsUUFBUTtBQUN6QjtBQUVBLFNBQVMsWUFBWSxPQUF5QjtBQUMxQyxNQUFJLGFBQWEsWUFBWTtBQUV6QixlQUFXO0FBQ1gsV0FBTyxrQkFBa0IsVUFBVTtBQUFBLEVBQ3ZDLFdBQVcsU0FBUztBQUVoQixlQUFXO0FBQ1gsV0FBTyxZQUFZO0FBQUEsRUFDdkI7QUFFQSxNQUFJLFlBQVksVUFBVTtBQUd0QixjQUFVLFlBQVk7QUFDdEI7QUFBQSxFQUNKO0FBRUEsTUFBSSxDQUFDLGFBQWEsQ0FBQyxVQUFVLEdBQUc7QUFDNUIsUUFBSSxZQUFZO0FBQUUsZ0JBQVU7QUFBQSxJQUFHO0FBQy9CO0FBQUEsRUFDSjtBQUVBLFFBQU0scUJBQXFCLFFBQVEsMkJBQTJCLEtBQUs7QUFDbkUsUUFBTSxvQkFBb0IsUUFBUSwwQkFBMEIsS0FBSztBQUdqRSxRQUFNLGNBQWMsUUFBUSxtQkFBbUIsS0FBSztBQUVwRCxRQUFNLGNBQWUsT0FBTyxhQUFhLE1BQU0sVUFBVztBQUMxRCxRQUFNLGFBQWEsTUFBTSxVQUFVO0FBQ25DLFFBQU0sWUFBWSxNQUFNLFVBQVU7QUFDbEMsUUFBTSxlQUFnQixPQUFPLGNBQWMsTUFBTSxVQUFXO0FBRzVELFFBQU0sY0FBZSxPQUFPLGFBQWEsTUFBTSxVQUFZLG9CQUFvQjtBQUMvRSxRQUFNLGFBQWEsTUFBTSxVQUFXLG9CQUFvQjtBQUN4RCxRQUFNLFlBQVksTUFBTSxVQUFXLHFCQUFxQjtBQUN4RCxRQUFNLGVBQWdCLE9BQU8sY0FBYyxNQUFNLFVBQVkscUJBQXFCO0FBRWxGLE1BQUksQ0FBQyxjQUFjLENBQUMsYUFBYSxDQUFDLGdCQUFnQixDQUFDLGFBQWE7QUFFNUQsY0FBVTtBQUFBLEVBQ2QsV0FFUyxlQUFlLGFBQWMsV0FBVSxXQUFXO0FBQUEsV0FDbEQsY0FBYyxhQUFjLFdBQVUsV0FBVztBQUFBLFdBQ2pELGNBQWMsVUFBVyxXQUFVLFdBQVc7QUFBQSxXQUM5QyxhQUFhLFlBQWEsV0FBVSxXQUFXO0FBQUEsV0FFL0MsV0FBWSxXQUFVLFVBQVU7QUFBQSxXQUNoQyxVQUFXLFdBQVUsVUFBVTtBQUFBLFdBQy9CLGFBQWMsV0FBVSxVQUFVO0FBQUEsV0FDbEMsWUFBYSxXQUFVLFVBQVU7QUFBQSxNQUVyQyxXQUFVO0FBQ25COzs7QUNyUUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBV0EsSUFBTUMsUUFBTyxpQkFBaUIsWUFBWSxXQUFXO0FBRXJELElBQU1DLGNBQWE7QUFDbkIsSUFBTUMsY0FBYTtBQUNuQixJQUFNLGFBQWE7QUFLWixTQUFTLE9BQXNCO0FBQ2xDLFNBQU9GLE1BQUtDLFdBQVU7QUFDMUI7QUFLTyxTQUFTLE9BQXNCO0FBQ2xDLFNBQU9ELE1BQUtFLFdBQVU7QUFDMUI7QUFLTyxTQUFTLE9BQXNCO0FBQ2xDLFNBQU9GLE1BQUssVUFBVTtBQUMxQjs7O0FDcENBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBOzs7QUN3QkEsSUFBSSxVQUFVLFNBQVMsVUFBVTtBQUNqQyxJQUFJLGVBQW9ELE9BQU8sWUFBWSxZQUFZLFlBQVksUUFBUSxRQUFRO0FBQ25ILElBQUk7QUFDSixJQUFJO0FBQ0osSUFBSSxPQUFPLGlCQUFpQixjQUFjLE9BQU8sT0FBTyxtQkFBbUIsWUFBWTtBQUNuRixNQUFJO0FBQ0EsbUJBQWUsT0FBTyxlQUFlLENBQUMsR0FBRyxVQUFVO0FBQUEsTUFDL0MsS0FBSyxXQUFZO0FBQ2IsY0FBTTtBQUFBLE1BQ1Y7QUFBQSxJQUNKLENBQUM7QUFDRCx1QkFBbUIsQ0FBQztBQUVwQixpQkFBYSxXQUFZO0FBQUUsWUFBTTtBQUFBLElBQUksR0FBRyxNQUFNLFlBQVk7QUFBQSxFQUM5RCxTQUFTLEdBQUc7QUFDUixRQUFJLE1BQU0sa0JBQWtCO0FBQ3hCLHFCQUFlO0FBQUEsSUFDbkI7QUFBQSxFQUNKO0FBQ0osT0FBTztBQUNILGlCQUFlO0FBQ25CO0FBRUEsSUFBSSxtQkFBbUI7QUFDdkIsSUFBSSxlQUFlLFNBQVMsbUJBQW1CLE9BQXFCO0FBQ2hFLE1BQUk7QUFDQSxRQUFJLFFBQVEsUUFBUSxLQUFLLEtBQUs7QUFDOUIsV0FBTyxpQkFBaUIsS0FBSyxLQUFLO0FBQUEsRUFDdEMsU0FBUyxHQUFHO0FBQ1IsV0FBTztBQUFBLEVBQ1g7QUFDSjtBQUVBLElBQUksb0JBQW9CLFNBQVMsaUJBQWlCLE9BQXFCO0FBQ25FLE1BQUk7QUFDQSxRQUFJLGFBQWEsS0FBSyxHQUFHO0FBQUUsYUFBTztBQUFBLElBQU87QUFDekMsWUFBUSxLQUFLLEtBQUs7QUFDbEIsV0FBTztBQUFBLEVBQ1gsU0FBUyxHQUFHO0FBQ1IsV0FBTztBQUFBLEVBQ1g7QUFDSjtBQUNBLElBQUksUUFBUSxPQUFPLFVBQVU7QUFDN0IsSUFBSSxjQUFjO0FBQ2xCLElBQUksVUFBVTtBQUNkLElBQUksV0FBVztBQUNmLElBQUksV0FBVztBQUNmLElBQUksWUFBWTtBQUNoQixJQUFJLFlBQVk7QUFDaEIsSUFBSSxpQkFBaUIsT0FBTyxXQUFXLGNBQWMsQ0FBQyxDQUFDLE9BQU87QUFFOUQsSUFBSSxTQUFTLEVBQUUsS0FBSyxDQUFDLENBQUM7QUFFdEIsSUFBSSxRQUFpQyxTQUFTLG1CQUFtQjtBQUFFLFNBQU87QUFBTztBQUNqRixJQUFJLE9BQU8sYUFBYSxVQUFVO0FBRTFCLFFBQU0sU0FBUztBQUNuQixNQUFJLE1BQU0sS0FBSyxHQUFHLE1BQU0sTUFBTSxLQUFLLFNBQVMsR0FBRyxHQUFHO0FBQzlDLFlBQVEsU0FBU0csa0JBQWlCLE9BQU87QUFHckMsV0FBSyxVQUFVLENBQUMsV0FBVyxPQUFPLFVBQVUsZUFBZSxPQUFPLFVBQVUsV0FBVztBQUNuRixZQUFJO0FBQ0EsY0FBSSxNQUFNLE1BQU0sS0FBSyxLQUFLO0FBQzFCLGtCQUNJLFFBQVEsWUFDTCxRQUFRLGFBQ1IsUUFBUSxhQUNSLFFBQVEsZ0JBQ1YsTUFBTSxFQUFFLEtBQUs7QUFBQSxRQUN0QixTQUFTLEdBQUc7QUFBQSxRQUFPO0FBQUEsTUFDdkI7QUFDQSxhQUFPO0FBQUEsSUFDWDtBQUFBLEVBQ0o7QUFDSjtBQW5CUTtBQXFCUixTQUFTLG1CQUFzQixPQUF1RDtBQUNsRixNQUFJLE1BQU0sS0FBSyxHQUFHO0FBQUUsV0FBTztBQUFBLEVBQU07QUFDakMsTUFBSSxDQUFDLE9BQU87QUFBRSxXQUFPO0FBQUEsRUFBTztBQUM1QixNQUFJLE9BQU8sVUFBVSxjQUFjLE9BQU8sVUFBVSxVQUFVO0FBQUUsV0FBTztBQUFBLEVBQU87QUFDOUUsTUFBSTtBQUNBLElBQUMsYUFBcUIsT0FBTyxNQUFNLFlBQVk7QUFBQSxFQUNuRCxTQUFTLEdBQUc7QUFDUixRQUFJLE1BQU0sa0JBQWtCO0FBQUUsYUFBTztBQUFBLElBQU87QUFBQSxFQUNoRDtBQUNBLFNBQU8sQ0FBQyxhQUFhLEtBQUssS0FBSyxrQkFBa0IsS0FBSztBQUMxRDtBQUVBLFNBQVMscUJBQXdCLE9BQXNEO0FBQ25GLE1BQUksTUFBTSxLQUFLLEdBQUc7QUFBRSxXQUFPO0FBQUEsRUFBTTtBQUNqQyxNQUFJLENBQUMsT0FBTztBQUFFLFdBQU87QUFBQSxFQUFPO0FBQzVCLE1BQUksT0FBTyxVQUFVLGNBQWMsT0FBTyxVQUFVLFVBQVU7QUFBRSxXQUFPO0FBQUEsRUFBTztBQUM5RSxNQUFJLGdCQUFnQjtBQUFFLFdBQU8sa0JBQWtCLEtBQUs7QUFBQSxFQUFHO0FBQ3ZELE1BQUksYUFBYSxLQUFLLEdBQUc7QUFBRSxXQUFPO0FBQUEsRUFBTztBQUN6QyxNQUFJLFdBQVcsTUFBTSxLQUFLLEtBQUs7QUFDL0IsTUFBSSxhQUFhLFdBQVcsYUFBYSxZQUFZLENBQUUsaUJBQWtCLEtBQUssUUFBUSxHQUFHO0FBQUUsV0FBTztBQUFBLEVBQU87QUFDekcsU0FBTyxrQkFBa0IsS0FBSztBQUNsQztBQUVBLElBQU8sbUJBQVEsZUFBZSxxQkFBcUI7OztBQ3pHNUMsSUFBTSxjQUFOLGNBQTBCLE1BQU07QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsRUFNbkMsWUFBWSxTQUFrQixTQUF3QjtBQUNsRCxVQUFNLFNBQVMsT0FBTztBQUN0QixTQUFLLE9BQU87QUFBQSxFQUNoQjtBQUNKO0FBY08sSUFBTSwwQkFBTixjQUFzQyxNQUFNO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSxFQWEvQyxZQUFZLFNBQXNDLFFBQWMsTUFBZTtBQUMzRSxXQUFPLHNCQUFRLCtDQUErQyxjQUFjLGFBQWEsTUFBTSxHQUFHLEVBQUUsT0FBTyxPQUFPLENBQUM7QUFDbkgsU0FBSyxVQUFVO0FBQ2YsU0FBSyxPQUFPO0FBQUEsRUFDaEI7QUFDSjtBQStCQSxJQUFNLGFBQWEsdUJBQU8sU0FBUztBQUNuQyxJQUFNLGdCQUFnQix1QkFBTyxZQUFZO0FBN0Z6QztBQThGQSxJQUFNLFdBQWlDLFlBQU8sWUFBUCxZQUFrQix1QkFBTyxpQkFBaUI7QUFvRDFFLElBQU0scUJBQU4sTUFBTSw0QkFBOEIsUUFBZ0U7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsRUF1Q3ZHLFlBQVksVUFBeUMsYUFBMkM7QUFDNUYsUUFBSTtBQUNKLFFBQUk7QUFDSixVQUFNLENBQUMsS0FBSyxRQUFRO0FBQUUsZ0JBQVU7QUFBSyxlQUFTO0FBQUEsSUFBSyxDQUFDO0FBRXBELFFBQUssS0FBSyxZQUFvQixPQUFPLE1BQU0sU0FBUztBQUNoRCxZQUFNLElBQUksVUFBVSxtSUFBbUk7QUFBQSxJQUMzSjtBQUVBLFFBQUksVUFBOEM7QUFBQSxNQUM5QyxTQUFTO0FBQUEsTUFDVDtBQUFBLE1BQ0E7QUFBQSxNQUNBLElBQUksY0FBYztBQUFFLGVBQU8sb0NBQWU7QUFBQSxNQUFNO0FBQUEsTUFDaEQsSUFBSSxZQUFZLElBQUk7QUFBRSxzQkFBYyxrQkFBTTtBQUFBLE1BQVc7QUFBQSxJQUN6RDtBQUVBLFVBQU0sUUFBaUM7QUFBQSxNQUNuQyxJQUFJLE9BQU87QUFBRSxlQUFPO0FBQUEsTUFBTztBQUFBLE1BQzNCLFdBQVc7QUFBQSxNQUNYLFNBQVM7QUFBQSxJQUNiO0FBR0EsU0FBSyxPQUFPLGlCQUFpQixNQUFNO0FBQUEsTUFDL0IsQ0FBQyxVQUFVLEdBQUc7QUFBQSxRQUNWLGNBQWM7QUFBQSxRQUNkLFlBQVk7QUFBQSxRQUNaLFVBQVU7QUFBQSxRQUNWLE9BQU87QUFBQSxNQUNYO0FBQUEsTUFDQSxDQUFDLGFBQWEsR0FBRztBQUFBLFFBQ2IsY0FBYztBQUFBLFFBQ2QsWUFBWTtBQUFBLFFBQ1osVUFBVTtBQUFBLFFBQ1YsT0FBTyxhQUFhLFNBQVMsS0FBSztBQUFBLE1BQ3RDO0FBQUEsSUFDSixDQUFDO0FBR0QsVUFBTSxXQUFXLFlBQVksU0FBUyxLQUFLO0FBQzNDLFFBQUk7QUFDQSxlQUFTLFlBQVksU0FBUyxLQUFLLEdBQUcsUUFBUTtBQUFBLElBQ2xELFNBQVMsS0FBSztBQUNWLFVBQUksTUFBTSxXQUFXO0FBQ2pCLGdCQUFRLElBQUksdURBQXVELEdBQUc7QUFBQSxNQUMxRSxPQUFPO0FBQ0gsaUJBQVMsR0FBRztBQUFBLE1BQ2hCO0FBQUEsSUFDSjtBQUFBLEVBQ0o7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLEVBeURBLE9BQU8sT0FBdUM7QUFDMUMsV0FBTyxJQUFJLG9CQUF5QixDQUFDLFlBQVk7QUFHN0MsY0FBUSxJQUFJO0FBQUEsUUFDUixLQUFLLGFBQWEsRUFBRSxJQUFJLFlBQVksc0JBQXNCLEVBQUUsTUFBTSxDQUFDLENBQUM7QUFBQSxRQUNwRSxlQUFlLElBQUk7QUFBQSxNQUN2QixDQUFDLEVBQUUsS0FBSyxNQUFNLFFBQVEsR0FBRyxNQUFNLFFBQVEsQ0FBQztBQUFBLElBQzVDLENBQUM7QUFBQSxFQUNMO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSxFQTJCQSxTQUFTLFFBQTRDO0FBQ2pELFFBQUksT0FBTyxTQUFTO0FBQ2hCLFdBQUssS0FBSyxPQUFPLE9BQU8sTUFBTTtBQUFBLElBQ2xDLE9BQU87QUFDSCxhQUFPLGlCQUFpQixTQUFTLE1BQU0sS0FBSyxLQUFLLE9BQU8sT0FBTyxNQUFNLEdBQUcsRUFBQyxTQUFTLEtBQUksQ0FBQztBQUFBLElBQzNGO0FBRUEsV0FBTztBQUFBLEVBQ1g7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsRUErQkEsS0FBcUMsYUFBc0gsWUFBd0gsYUFBb0Y7QUFDblcsUUFBSSxFQUFFLGdCQUFnQixzQkFBcUI7QUFDdkMsWUFBTSxJQUFJLFVBQVUsZ0VBQWdFO0FBQUEsSUFDeEY7QUFNQSxRQUFJLENBQUMsaUJBQVcsV0FBVyxHQUFHO0FBQUUsb0JBQWM7QUFBQSxJQUFpQjtBQUMvRCxRQUFJLENBQUMsaUJBQVcsVUFBVSxHQUFHO0FBQUUsbUJBQWE7QUFBQSxJQUFTO0FBRXJELFFBQUksZ0JBQWdCLFlBQVksY0FBYyxTQUFTO0FBRW5ELGFBQU8sSUFBSSxvQkFBbUIsQ0FBQyxZQUFZLFFBQVEsSUFBVyxDQUFDO0FBQUEsSUFDbkU7QUFFQSxVQUFNLFVBQStDLENBQUM7QUFDdEQsU0FBSyxVQUFVLElBQUk7QUFFbkIsV0FBTyxJQUFJLG9CQUF3QyxDQUFDLFNBQVMsV0FBVztBQUNwRSxXQUFLLE1BQU07QUFBQSxRQUNQLENBQUMsVUFBVTtBQXJZM0IsY0FBQUM7QUFzWW9CLGNBQUksS0FBSyxVQUFVLE1BQU0sU0FBUztBQUFFLGlCQUFLLFVBQVUsSUFBSTtBQUFBLFVBQU07QUFDN0QsV0FBQUEsTUFBQSxRQUFRLFlBQVIsZ0JBQUFBLElBQUE7QUFFQSxjQUFJO0FBQ0Esb0JBQVEsWUFBYSxLQUFLLENBQUM7QUFBQSxVQUMvQixTQUFTLEtBQUs7QUFDVixtQkFBTyxHQUFHO0FBQUEsVUFDZDtBQUFBLFFBQ0o7QUFBQSxRQUNBLENBQUMsV0FBWTtBQS9ZN0IsY0FBQUE7QUFnWm9CLGNBQUksS0FBSyxVQUFVLE1BQU0sU0FBUztBQUFFLGlCQUFLLFVBQVUsSUFBSTtBQUFBLFVBQU07QUFDN0QsV0FBQUEsTUFBQSxRQUFRLFlBQVIsZ0JBQUFBLElBQUE7QUFFQSxjQUFJO0FBQ0Esb0JBQVEsV0FBWSxNQUFNLENBQUM7QUFBQSxVQUMvQixTQUFTLEtBQUs7QUFDVixtQkFBTyxHQUFHO0FBQUEsVUFDZDtBQUFBLFFBQ0o7QUFBQSxNQUNKO0FBQUEsSUFDSixHQUFHLE9BQU8sVUFBVztBQUVqQixVQUFJO0FBQ0EsZUFBTywyQ0FBYztBQUFBLE1BQ3pCLFVBQUU7QUFDRSxjQUFNLEtBQUssT0FBTyxLQUFLO0FBQUEsTUFDM0I7QUFBQSxJQUNKLENBQUM7QUFBQSxFQUNMO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLEVBK0JBLE1BQXVCLFlBQXFGLGFBQTRFO0FBQ3BMLFdBQU8sS0FBSyxLQUFLLFFBQVcsWUFBWSxXQUFXO0FBQUEsRUFDdkQ7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLEVBaUNBLFFBQVEsV0FBNkMsYUFBa0U7QUFDbkgsUUFBSSxFQUFFLGdCQUFnQixzQkFBcUI7QUFDdkMsWUFBTSxJQUFJLFVBQVUsbUVBQW1FO0FBQUEsSUFDM0Y7QUFFQSxRQUFJLENBQUMsaUJBQVcsU0FBUyxHQUFHO0FBQ3hCLGFBQU8sS0FBSyxLQUFLLFdBQVcsV0FBVyxXQUFXO0FBQUEsSUFDdEQ7QUFFQSxXQUFPLEtBQUs7QUFBQSxNQUNSLENBQUMsVUFBVSxvQkFBbUIsUUFBUSxVQUFVLENBQUMsRUFBRSxLQUFLLE1BQU0sS0FBSztBQUFBLE1BQ25FLENBQUMsV0FBWSxvQkFBbUIsUUFBUSxVQUFVLENBQUMsRUFBRSxLQUFLLE1BQU07QUFBRSxjQUFNO0FBQUEsTUFBUSxDQUFDO0FBQUEsTUFDakY7QUFBQSxJQUNKO0FBQUEsRUFDSjtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsRUFZQSxhQXpXUyxZQUVTLGVBdVdOLFFBQU8sSUFBSTtBQUNuQixXQUFPO0FBQUEsRUFDWDtBQUFBLEVBYUEsT0FBTyxJQUFzRCxRQUF3QztBQUNqRyxRQUFJLFlBQVksTUFBTSxLQUFLLE1BQU07QUFDakMsVUFBTSxVQUFVLFVBQVUsV0FBVyxJQUMvQixvQkFBbUIsUUFBUSxTQUFTLElBQ3BDLElBQUksb0JBQTRCLENBQUMsU0FBUyxXQUFXO0FBQ25ELFdBQUssUUFBUSxJQUFJLFNBQVMsRUFBRSxLQUFLLFNBQVMsTUFBTTtBQUFBLElBQ3BELEdBQUcsQ0FBQyxVQUEwQixVQUFVLFNBQVMsV0FBVyxLQUFLLENBQUM7QUFDdEUsV0FBTztBQUFBLEVBQ1g7QUFBQSxFQWFBLE9BQU8sV0FBNkQsUUFBd0M7QUFDeEcsUUFBSSxZQUFZLE1BQU0sS0FBSyxNQUFNO0FBQ2pDLFVBQU0sVUFBVSxVQUFVLFdBQVcsSUFDL0Isb0JBQW1CLFFBQVEsU0FBUyxJQUNwQyxJQUFJLG9CQUE0QixDQUFDLFNBQVMsV0FBVztBQUNuRCxXQUFLLFFBQVEsV0FBVyxTQUFTLEVBQUUsS0FBSyxTQUFTLE1BQU07QUFBQSxJQUMzRCxHQUFHLENBQUMsVUFBMEIsVUFBVSxTQUFTLFdBQVcsS0FBSyxDQUFDO0FBQ3RFLFdBQU87QUFBQSxFQUNYO0FBQUEsRUFlQSxPQUFPLElBQXNELFFBQXdDO0FBQ2pHLFFBQUksWUFBWSxNQUFNLEtBQUssTUFBTTtBQUNqQyxVQUFNLFVBQVUsVUFBVSxXQUFXLElBQy9CLG9CQUFtQixRQUFRLFNBQVMsSUFDcEMsSUFBSSxvQkFBNEIsQ0FBQyxTQUFTLFdBQVc7QUFDbkQsV0FBSyxRQUFRLElBQUksU0FBUyxFQUFFLEtBQUssU0FBUyxNQUFNO0FBQUEsSUFDcEQsR0FBRyxDQUFDLFVBQTBCLFVBQVUsU0FBUyxXQUFXLEtBQUssQ0FBQztBQUN0RSxXQUFPO0FBQUEsRUFDWDtBQUFBLEVBWUEsT0FBTyxLQUF1RCxRQUF3QztBQUNsRyxRQUFJLFlBQVksTUFBTSxLQUFLLE1BQU07QUFDakMsVUFBTSxVQUFVLElBQUksb0JBQTRCLENBQUMsU0FBUyxXQUFXO0FBQ2pFLFdBQUssUUFBUSxLQUFLLFNBQVMsRUFBRSxLQUFLLFNBQVMsTUFBTTtBQUFBLElBQ3JELEdBQUcsQ0FBQyxVQUEwQixVQUFVLFNBQVMsV0FBVyxLQUFLLENBQUM7QUFDbEUsV0FBTztBQUFBLEVBQ1g7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsRUFPQSxPQUFPLE9BQWtCLE9BQW9DO0FBQ3pELFVBQU0sSUFBSSxJQUFJLG9CQUFzQixNQUFNO0FBQUEsSUFBQyxDQUFDO0FBQzVDLE1BQUUsT0FBTyxLQUFLO0FBQ2QsV0FBTztBQUFBLEVBQ1g7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLEVBWUEsT0FBTyxRQUFtQixjQUFzQixPQUFvQztBQUNoRixVQUFNLFVBQVUsSUFBSSxvQkFBc0IsTUFBTTtBQUFBLElBQUMsQ0FBQztBQUNsRCxRQUFJLGVBQWUsT0FBTyxnQkFBZ0IsY0FBYyxZQUFZLFdBQVcsT0FBTyxZQUFZLFlBQVksWUFBWTtBQUN0SCxrQkFBWSxRQUFRLFlBQVksRUFBRSxpQkFBaUIsU0FBUyxNQUFNLEtBQUssUUFBUSxPQUFPLEtBQUssQ0FBQztBQUFBLElBQ2hHLE9BQU87QUFDSCxpQkFBVyxNQUFNLEtBQUssUUFBUSxPQUFPLEtBQUssR0FBRyxZQUFZO0FBQUEsSUFDN0Q7QUFDQSxXQUFPO0FBQUEsRUFDWDtBQUFBLEVBaUJBLE9BQU8sTUFBZ0IsY0FBc0IsT0FBa0M7QUFDM0UsV0FBTyxJQUFJLG9CQUFzQixDQUFDLFlBQVk7QUFDMUMsaUJBQVcsTUFBTSxRQUFRLEtBQU0sR0FBRyxZQUFZO0FBQUEsSUFDbEQsQ0FBQztBQUFBLEVBQ0w7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUEsRUFPQSxPQUFPLE9BQWtCLFFBQXFDO0FBQzFELFdBQU8sSUFBSSxvQkFBc0IsQ0FBQyxHQUFHLFdBQVcsT0FBTyxNQUFNLENBQUM7QUFBQSxFQUNsRTtBQUFBLEVBb0JBLE9BQU8sUUFBa0IsT0FBNEQ7QUFDakYsUUFBSSxpQkFBaUIscUJBQW9CO0FBRXJDLGFBQU87QUFBQSxJQUNYO0FBQ0EsV0FBTyxJQUFJLG9CQUF3QixDQUFDLFlBQVksUUFBUSxLQUFLLENBQUM7QUFBQSxFQUNsRTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQSxFQVVBLE9BQU8sZ0JBQXVEO0FBQzFELFFBQUksU0FBNkMsRUFBRSxhQUFhLEtBQUs7QUFDckUsV0FBTyxVQUFVLElBQUksb0JBQXNCLENBQUMsU0FBUyxXQUFXO0FBQzVELGFBQU8sVUFBVTtBQUNqQixhQUFPLFNBQVM7QUFBQSxJQUNwQixHQUFHLENBQUMsVUFBZ0I7QUF6ckI1QixVQUFBQTtBQXlyQjhCLE9BQUFBLE1BQUEsT0FBTyxnQkFBUCxnQkFBQUEsSUFBQSxhQUFxQjtBQUFBLElBQVEsQ0FBQztBQUNwRCxXQUFPO0FBQUEsRUFDWDtBQUNKO0FBTUEsU0FBUyxhQUFnQixTQUE2QyxPQUFnQztBQUNsRyxNQUFJLHNCQUFnRDtBQUVwRCxTQUFPLENBQUMsV0FBa0Q7QUFDdEQsUUFBSSxDQUFDLE1BQU0sU0FBUztBQUNoQixZQUFNLFVBQVU7QUFDaEIsWUFBTSxTQUFTO0FBQ2YsY0FBUSxPQUFPLE1BQU07QUFNckIsV0FBSyxRQUFRLFVBQVUsS0FBSyxLQUFLLFFBQVEsU0FBUyxRQUFXLENBQUMsUUFBUTtBQUNsRSxZQUFJLFFBQVEsUUFBUTtBQUNoQixnQkFBTTtBQUFBLFFBQ1Y7QUFBQSxNQUNKLENBQUM7QUFBQSxJQUNMO0FBSUEsUUFBSSxDQUFDLE1BQU0sVUFBVSxDQUFDLFFBQVEsYUFBYTtBQUFFO0FBQUEsSUFBUTtBQUVyRCwwQkFBc0IsSUFBSSxRQUFjLENBQUMsWUFBWTtBQUNqRCxVQUFJO0FBQ0EsZ0JBQVEsUUFBUSxZQUFhLE1BQU0sT0FBUSxLQUFLLENBQUM7QUFBQSxNQUNyRCxTQUFTLEtBQUs7QUFDVixnQkFBUSxPQUFPLElBQUksd0JBQXdCLFFBQVEsU0FBUyxLQUFLLDhDQUE4QyxDQUFDO0FBQUEsTUFDcEg7QUFBQSxJQUNKLENBQUMsRUFBRSxNQUFNLENBQUNDLFlBQVk7QUFDbEIsY0FBUSxPQUFPLElBQUksd0JBQXdCLFFBQVEsU0FBU0EsU0FBUSw4Q0FBOEMsQ0FBQztBQUFBLElBQ3ZILENBQUM7QUFHRCxZQUFRLGNBQWM7QUFFdEIsV0FBTztBQUFBLEVBQ1g7QUFDSjtBQUtBLFNBQVMsWUFBZSxTQUE2QyxPQUErRDtBQUNoSSxTQUFPLENBQUMsVUFBVTtBQUNkLFFBQUksTUFBTSxXQUFXO0FBQUU7QUFBQSxJQUFRO0FBQy9CLFVBQU0sWUFBWTtBQUVsQixRQUFJLFVBQVUsUUFBUSxTQUFTO0FBQzNCLFVBQUksTUFBTSxTQUFTO0FBQUU7QUFBQSxNQUFRO0FBQzdCLFlBQU0sVUFBVTtBQUNoQixjQUFRLE9BQU8sSUFBSSxVQUFVLDJDQUEyQyxDQUFDO0FBQ3pFO0FBQUEsSUFDSjtBQUVBLFFBQUksU0FBUyxTQUFTLE9BQU8sVUFBVSxZQUFZLE9BQU8sVUFBVSxhQUFhO0FBQzdFLFVBQUk7QUFDSixVQUFJO0FBQ0EsZUFBUSxNQUFjO0FBQUEsTUFDMUIsU0FBUyxLQUFLO0FBQ1YsY0FBTSxVQUFVO0FBQ2hCLGdCQUFRLE9BQU8sR0FBRztBQUNsQjtBQUFBLE1BQ0o7QUFFQSxVQUFJLGlCQUFXLElBQUksR0FBRztBQUNsQixZQUFJO0FBQ0EsY0FBSSxTQUFVLE1BQWM7QUFDNUIsY0FBSSxpQkFBVyxNQUFNLEdBQUc7QUFDcEIsa0JBQU0sY0FBYyxDQUFDLFVBQWdCO0FBQ2pDLHNCQUFRLE1BQU0sUUFBUSxPQUFPLENBQUMsS0FBSyxDQUFDO0FBQUEsWUFDeEM7QUFDQSxnQkFBSSxNQUFNLFFBQVE7QUFJZCxtQkFBSyxhQUFhLGlDQUFLLFVBQUwsRUFBYyxZQUFZLElBQUcsS0FBSyxFQUFFLE1BQU0sTUFBTTtBQUFBLFlBQ3RFLE9BQU87QUFDSCxzQkFBUSxjQUFjO0FBQUEsWUFDMUI7QUFBQSxVQUNKO0FBQUEsUUFDSixTQUFRO0FBQUEsUUFBQztBQUVULGNBQU0sV0FBb0M7QUFBQSxVQUN0QyxNQUFNLE1BQU07QUFBQSxVQUNaLFdBQVc7QUFBQSxVQUNYLElBQUksVUFBVTtBQUFFLG1CQUFPLEtBQUssS0FBSztBQUFBLFVBQVE7QUFBQSxVQUN6QyxJQUFJLFFBQVFDLFFBQU87QUFBRSxpQkFBSyxLQUFLLFVBQVVBO0FBQUEsVUFBTztBQUFBLFVBQ2hELElBQUksU0FBUztBQUFFLG1CQUFPLEtBQUssS0FBSztBQUFBLFVBQU87QUFBQSxRQUMzQztBQUVBLGNBQU0sV0FBVyxZQUFZLFNBQVMsUUFBUTtBQUM5QyxZQUFJO0FBQ0Esa0JBQVEsTUFBTSxNQUFNLE9BQU8sQ0FBQyxZQUFZLFNBQVMsUUFBUSxHQUFHLFFBQVEsQ0FBQztBQUFBLFFBQ3pFLFNBQVMsS0FBSztBQUNWLG1CQUFTLEdBQUc7QUFBQSxRQUNoQjtBQUNBO0FBQUEsTUFDSjtBQUFBLElBQ0o7QUFFQSxRQUFJLE1BQU0sU0FBUztBQUFFO0FBQUEsSUFBUTtBQUM3QixVQUFNLFVBQVU7QUFDaEIsWUFBUSxRQUFRLEtBQUs7QUFBQSxFQUN6QjtBQUNKO0FBS0EsU0FBUyxZQUFlLFNBQTZDLE9BQTREO0FBQzdILFNBQU8sQ0FBQyxXQUFZO0FBQ2hCLFFBQUksTUFBTSxXQUFXO0FBQUU7QUFBQSxJQUFRO0FBQy9CLFVBQU0sWUFBWTtBQUVsQixRQUFJLE1BQU0sU0FBUztBQUNmLFVBQUk7QUFDQSxZQUFJLGtCQUFrQixlQUFlLE1BQU0sa0JBQWtCLGVBQWUsT0FBTyxHQUFHLE9BQU8sT0FBTyxNQUFNLE9BQU8sS0FBSyxHQUFHO0FBRXJIO0FBQUEsUUFDSjtBQUFBLE1BQ0osU0FBUTtBQUFBLE1BQUM7QUFFVCxXQUFLLFFBQVEsT0FBTyxJQUFJLHdCQUF3QixRQUFRLFNBQVMsTUFBTSxDQUFDO0FBQUEsSUFDNUUsT0FBTztBQUNILFlBQU0sVUFBVTtBQUNoQixjQUFRLE9BQU8sTUFBTTtBQUFBLElBQ3pCO0FBQUEsRUFDSjtBQUNKO0FBTUEsU0FBUyxVQUFVLFFBQXFDLFFBQWUsT0FBNEI7QUFDL0YsUUFBTSxVQUEyQixDQUFDO0FBRWxDLGFBQVcsU0FBUyxRQUFRO0FBQ3hCLFFBQUk7QUFDSixRQUFJO0FBQ0EsVUFBSSxDQUFDLGlCQUFXLE1BQU0sSUFBSSxHQUFHO0FBQUU7QUFBQSxNQUFVO0FBQ3pDLGVBQVMsTUFBTTtBQUNmLFVBQUksQ0FBQyxpQkFBVyxNQUFNLEdBQUc7QUFBRTtBQUFBLE1BQVU7QUFBQSxJQUN6QyxTQUFRO0FBQUU7QUFBQSxJQUFVO0FBRXBCLFFBQUk7QUFDSixRQUFJO0FBQ0EsZUFBUyxRQUFRLE1BQU0sUUFBUSxPQUFPLENBQUMsS0FBSyxDQUFDO0FBQUEsSUFDakQsU0FBUyxLQUFLO0FBQ1YsY0FBUSxPQUFPLElBQUksd0JBQXdCLFFBQVEsS0FBSyx1Q0FBdUMsQ0FBQztBQUNoRztBQUFBLElBQ0o7QUFFQSxRQUFJLENBQUMsUUFBUTtBQUFFO0FBQUEsSUFBVTtBQUN6QixZQUFRO0FBQUEsT0FDSCxrQkFBa0IsVUFBVyxTQUFTLFFBQVEsUUFBUSxNQUFNLEdBQUcsTUFBTSxDQUFDLFdBQVk7QUFDL0UsZ0JBQVEsT0FBTyxJQUFJLHdCQUF3QixRQUFRLFFBQVEsdUNBQXVDLENBQUM7QUFBQSxNQUN2RyxDQUFDO0FBQUEsSUFDTDtBQUFBLEVBQ0o7QUFFQSxTQUFPLFFBQVEsSUFBSSxPQUFPO0FBQzlCO0FBS0EsU0FBUyxTQUFZLEdBQVM7QUFDMUIsU0FBTztBQUNYO0FBS0EsU0FBUyxRQUFRLFFBQXFCO0FBQ2xDLFFBQU07QUFDVjtBQUtBLFNBQVMsYUFBYSxLQUFrQjtBQUNwQyxNQUFJO0FBQ0EsUUFBSSxlQUFlLFNBQVMsT0FBTyxRQUFRLFlBQVksSUFBSSxhQUFhLE9BQU8sVUFBVSxVQUFVO0FBQy9GLGFBQU8sS0FBSztBQUFBLElBQ2hCO0FBQUEsRUFDSixTQUFRO0FBQUEsRUFBQztBQUVULE1BQUk7QUFDQSxXQUFPLEtBQUssVUFBVSxHQUFHO0FBQUEsRUFDN0IsU0FBUTtBQUFBLEVBQUM7QUFFVCxNQUFJO0FBQ0EsV0FBTyxPQUFPLFVBQVUsU0FBUyxLQUFLLEdBQUc7QUFBQSxFQUM3QyxTQUFRO0FBQUEsRUFBQztBQUVULFNBQU87QUFDWDtBQUtBLFNBQVMsZUFBa0IsU0FBK0M7QUE5NEIxRSxNQUFBRjtBQSs0QkksTUFBSSxPQUEyQ0EsTUFBQSxRQUFRLFVBQVUsTUFBbEIsT0FBQUEsTUFBdUIsQ0FBQztBQUN2RSxNQUFJLEVBQUUsYUFBYSxNQUFNO0FBQ3JCLFdBQU8sT0FBTyxLQUFLLHFCQUEyQixDQUFDO0FBQUEsRUFDbkQ7QUFDQSxNQUFJLFFBQVEsVUFBVSxLQUFLLE1BQU07QUFDN0IsUUFBSSxRQUFTO0FBQ2IsWUFBUSxVQUFVLElBQUk7QUFBQSxFQUMxQjtBQUNBLFNBQU8sSUFBSTtBQUNmO0FBR0EsSUFBSSx1QkFBdUIsUUFBUTtBQUNuQyxJQUFJLHdCQUF3QixPQUFPLHlCQUF5QixZQUFZO0FBQ3BFLHlCQUF1QixxQkFBcUIsS0FBSyxPQUFPO0FBQzVELE9BQU87QUFDSCx5QkFBdUIsV0FBd0M7QUFDM0QsUUFBSTtBQUNKLFFBQUk7QUFDSixVQUFNLFVBQVUsSUFBSSxRQUFXLENBQUMsS0FBSyxRQUFRO0FBQUUsZ0JBQVU7QUFBSyxlQUFTO0FBQUEsSUFBSyxDQUFDO0FBQzdFLFdBQU8sRUFBRSxTQUFTLFNBQVMsT0FBTztBQUFBLEVBQ3RDO0FBQ0o7OztBRnQ1QkEsT0FBTyxTQUFTLE9BQU8sVUFBVSxDQUFDO0FBSWxDLElBQU1HLFFBQU8saUJBQWlCLFlBQVksSUFBSTtBQUM5QyxJQUFNLGFBQWEsaUJBQWlCLFlBQVksVUFBVTtBQUMxRCxJQUFNLGdCQUFnQixvQkFBSSxJQUE4QjtBQUV4RCxJQUFNLGNBQWM7QUFDcEIsSUFBTSxlQUFlO0FBMEJkLElBQU0sZUFBTixjQUEyQixNQUFNO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFBQTtBQUFBLEVBTXBDLFlBQVksU0FBa0IsU0FBd0I7QUFDbEQsVUFBTSxTQUFTLE9BQU87QUFDdEIsU0FBSyxPQUFPO0FBQUEsRUFDaEI7QUFDSjtBQU9BLFNBQVMsYUFBcUI7QUFDMUIsTUFBSTtBQUNKLEtBQUc7QUFDQyxhQUFTLE9BQU87QUFBQSxFQUNwQixTQUFTLGNBQWMsSUFBSSxNQUFNO0FBQ2pDLFNBQU87QUFDWDtBQWNPLFNBQVMsS0FBSyxTQUErQztBQUNoRSxRQUFNLEtBQUssV0FBVztBQUV0QixRQUFNLFNBQVMsbUJBQW1CLGNBQW1CO0FBQ3JELGdCQUFjLElBQUksSUFBSSxFQUFFLFNBQVMsT0FBTyxTQUFTLFFBQVEsT0FBTyxPQUFPLENBQUM7QUFFeEUsUUFBTSxVQUFVQSxNQUFLLGFBQWEsT0FBTyxPQUFPLEVBQUUsV0FBVyxHQUFHLEdBQUcsT0FBTyxDQUFDO0FBQzNFLE1BQUksVUFBVTtBQUVkLFVBQVEsS0FBSyxDQUFDLFFBQVE7QUFDbEIsY0FBVTtBQUNWLGtCQUFjLE9BQU8sRUFBRTtBQUN2QixXQUFPLFFBQVEsR0FBRztBQUFBLEVBQ3RCLEdBQUcsQ0FBQyxRQUFRO0FBQ1IsY0FBVTtBQUNWLGtCQUFjLE9BQU8sRUFBRTtBQUN2QixXQUFPLE9BQU8sR0FBRztBQUFBLEVBQ3JCLENBQUM7QUFFRCxRQUFNLFNBQVMsTUFBTTtBQUNqQixrQkFBYyxPQUFPLEVBQUU7QUFDdkIsV0FBTyxXQUFXLGNBQWMsRUFBQyxXQUFXLEdBQUUsQ0FBQyxFQUFFLE1BQU0sQ0FBQyxRQUFRO0FBQzVELGNBQVEsTUFBTSxxREFBcUQsR0FBRztBQUFBLElBQzFFLENBQUM7QUFBQSxFQUNMO0FBRUEsU0FBTyxjQUFjLE1BQU07QUFDdkIsUUFBSSxTQUFTO0FBQ1QsYUFBTyxPQUFPO0FBQUEsSUFDbEIsT0FBTztBQUNILGFBQU8sUUFBUSxLQUFLLE1BQU07QUFBQSxJQUM5QjtBQUFBLEVBQ0o7QUFFQSxTQUFPLE9BQU87QUFDbEI7QUFVTyxTQUFTLE9BQU8sZUFBdUIsTUFBc0M7QUFDaEYsU0FBTyxLQUFLLEVBQUUsWUFBWSxLQUFLLENBQUM7QUFDcEM7QUFVTyxTQUFTLEtBQUssYUFBcUIsTUFBc0M7QUFDNUUsU0FBTyxLQUFLLEVBQUUsVUFBVSxLQUFLLENBQUM7QUFDbEM7OztBR2xKQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBWUEsSUFBTUMsUUFBTyxpQkFBaUIsWUFBWSxTQUFTO0FBRW5ELElBQU0sbUJBQW1CO0FBQ3pCLElBQU0sZ0JBQWdCO0FBUWYsU0FBUyxRQUFRLE1BQTZCO0FBQ2pELFNBQU9BLE1BQUssa0JBQWtCLEVBQUMsS0FBSSxDQUFDO0FBQ3hDO0FBT08sU0FBUyxPQUF3QjtBQUNwQyxTQUFPQSxNQUFLLGFBQWE7QUFDN0I7OztBQ2xDQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUF3REEsSUFBTUMsUUFBTyxpQkFBaUIsWUFBWSxPQUFPO0FBRWpELElBQU0sU0FBUztBQUNmLElBQU0sYUFBYTtBQUNuQixJQUFNLGFBQWE7QUFPWixTQUFTLFNBQTRCO0FBQ3hDLFNBQU9BLE1BQUssTUFBTTtBQUN0QjtBQU9PLFNBQVMsYUFBOEI7QUFDMUMsU0FBT0EsTUFBSyxVQUFVO0FBQzFCO0FBT08sU0FBUyxhQUE4QjtBQUMxQyxTQUFPQSxNQUFLLFVBQVU7QUFDMUI7OztBQ3ZGQTtBQUFBO0FBQUE7QUFBQTtBQUFBO0FBWUEsSUFBTUMsU0FBTyxpQkFBaUIsWUFBWSxHQUFHO0FBRzdDLElBQU0sZ0JBQWdCO0FBQ3RCLElBQU0sYUFBYTtBQUVaLElBQVU7QUFBQSxDQUFWLENBQVVDLGFBQVY7QUFFSSxXQUFTLE9BQU8sUUFBcUIsVUFBeUI7QUFDakUsV0FBT0QsT0FBSyxlQUFlLEVBQUUsTUFBTSxDQUFDO0FBQUEsRUFDeEM7QUFGTyxFQUFBQyxTQUFTO0FBQUEsR0FGSDtBQU9WLElBQVU7QUFBQSxDQUFWLENBQVVDLFlBQVY7QUFPSSxXQUFTQyxRQUFzQjtBQUNsQyxXQUFPSCxPQUFLLFVBQVU7QUFBQSxFQUMxQjtBQUZPLEVBQUFFLFFBQVMsT0FBQUM7QUFBQSxHQVBIOzs7QXZCZGpCLE9BQU8sU0FBUyxPQUFPLFVBQVUsQ0FBQztBQXdEbEMsT0FBTyxPQUFPLFNBQWdCO0FBQzlCLE9BQU8sT0FBTyxXQUFXO0FBS3pCLE9BQU8sT0FBTyx5QkFBeUIsZUFBTyx1QkFBdUIsS0FBSyxjQUFNO0FBR2hGLE9BQU8sT0FBTyxrQkFBa0I7QUFDaEMsT0FBTyxPQUFPLGtCQUFrQjtBQUNoQyxPQUFPLE9BQU8saUJBQWlCO0FBRXhCLE9BQU8scUJBQXFCO0FBTzVCLFNBQVMsbUJBQW1CLEtBQTRCO0FBQzNELFNBQU8sTUFBTSxLQUFLLEVBQUUsUUFBUSxPQUFPLENBQUMsRUFDL0IsS0FBSyxjQUFZO0FBQ2QsUUFBSSxTQUFTLElBQUk7QUFDYixZQUFNLFNBQVMsU0FBUyxjQUFjLFFBQVE7QUFDOUMsYUFBTyxNQUFNO0FBQ2IsZUFBUyxLQUFLLFlBQVksTUFBTTtBQUFBLElBQ3BDO0FBQUEsRUFDSixDQUFDLEVBQ0EsTUFBTSxNQUFNO0FBQUEsRUFBQyxDQUFDO0FBQ3ZCO0FBR0EsbUJBQW1CLGtCQUFrQjsiLAogICJuYW1lcyI6IFsiX2EiLCAiRXJyb3IiLCAiY2FsbCIsICJFcnJvciIsICJfYSIsICJBcnJheSIsICJNYXAiLCAiQXJyYXkiLCAiTWFwIiwgImtleSIsICJjYWxsIiwgIl9hIiwgIl9hIiwgInJlc2l6YWJsZSIsICJfYSIsICJjYWxsIiwgIl9hIiwgImNhbGwiLCAiX2EiLCAiY2FsbCIsICJIaWRlTWV0aG9kIiwgIlNob3dNZXRob2QiLCAiaXNEb2N1bWVudERvdEFsbCIsICJfYSIsICJyZWFzb24iLCAidmFsdWUiLCAiY2FsbCIsICJjYWxsIiwgImNhbGwiLCAiY2FsbCIsICJIYXB0aWNzIiwgIkRldmljZSIsICJJbmZvIl0KfQo= diff --git a/v3/internal/assetserver/bundledassets/runtime.js b/v3/internal/assetserver/bundledassets/runtime.js deleted file mode 100644 index 593720e1d..000000000 --- a/v3/internal/assetserver/bundledassets/runtime.js +++ /dev/null @@ -1 +0,0 @@ -var _e=Object.defineProperty,Pn=Object.defineProperties;var Tn=Object.getOwnPropertyDescriptors;var Ze=Object.getOwnPropertySymbols;var Mn=Object.prototype.hasOwnProperty,Sn=Object.prototype.propertyIsEnumerable;var Ke=(n,e,i)=>e in n?_e(n,e,{enumerable:!0,configurable:!0,writable:!0,value:i}):n[e]=i,Ge=(n,e)=>{for(var i in e||(e={}))Mn.call(e,i)&&Ke(n,i,e[i]);if(Ze)for(var i of Ze(e))Sn.call(e,i)&&Ke(n,i,e[i]);return n},Ye=(n,e)=>Pn(n,Tn(e));var p=(n,e)=>{for(var i in e)_e(n,i,{get:e[i],enumerable:!0})};var fe={};p(fe,{Application:()=>xe,Browser:()=>ie,Call:()=>Ue,CancelError:()=>L,CancellablePromise:()=>H,CancelledRejectionError:()=>v,Clipboard:()=>ze,Create:()=>re,Dialogs:()=>te,Events:()=>le,Flags:()=>ve,IOS:()=>Ve,Screens:()=>je,System:()=>be,WML:()=>pe,Window:()=>E,clientId:()=>I,getTransport:()=>Qe,loadOptionalScript:()=>Cn,objectNames:()=>m,setTransport:()=>Xe});var pe={};p(pe,{Enable:()=>we,Reload:()=>dn});var ie={};p(ie,{OpenURL:()=>ne});var En="useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict";function Z(n=21){let e="",i=n|0;for(;i--;)e+=En[Math.random()*64|0];return e}var xn=window.location.origin+"/wails/runtime";var m=Object.freeze({Call:0,Clipboard:1,Application:2,Events:3,ContextMenu:4,Dialog:5,Window:6,Screens:7,System:8,Browser:9,CancelCall:10,IOS:11}),I=Z(),K=null;function Xe(n){K=n}function Qe(){return K}function u(n,e=""){return function(i,o=null){return An(n,i,e,o)}}async function An(n,e,i,o){var d,w;if(K)return K.call(n,e,i,o);let t=new URL(xn),r={object:n,method:e};o!=null&&(r.args=o);let a={"x-wails-client-id":I,"Content-Type":"application/json"};i&&(a["x-wails-window-name"]=i);let l=await fetch(t,{method:"POST",headers:a,body:JSON.stringify(r)});if(!l.ok)throw new Error(await l.text());return((w=(d=l.headers.get("Content-Type"))==null?void 0:d.indexOf("application/json"))!=null?w:-1)!==-1?l.json():l.text()}var Rn=u(m.Browser),Fn=0;function ne(n){return Rn(Fn,{url:n.toString()})}var te={};p(te,{Error:()=>Hn,Info:()=>jn,OpenFile:()=>Vn,Question:()=>oe,SaveFile:()=>Zn,Warning:()=>Bn});window._wails=window._wails||{};var On=u(m.Dialog),kn=0,Ln=1,In=2,Un=3,zn=4,Nn=5;function S(n,e={}){return On(n,e)}function jn(n){return S(kn,n)}function Bn(n){return S(Ln,n)}function Hn(n){return S(In,n)}function oe(n){return S(Un,n)}function Vn(n){var e;return(e=S(zn,n))!=null?e:[]}function Zn(n){return S(Nn,n)}var le={};p(le,{Emit:()=>se,Off:()=>ii,OffAll:()=>oi,On:()=>ei,OnMultiple:()=>ae,Once:()=>ni,Types:()=>Qn,WailsEvent:()=>U});var g=new Map,_=class{constructor(e,i,o){this.eventName=e,this.callback=i,this.maxCallbacks=o||-1}dispatch(e){try{this.callback(e)}catch(i){}return this.maxCallbacks===-1?!1:(this.maxCallbacks-=1,this.maxCallbacks===0)}};function qe(n){let e=g.get(n.eventName);e&&(e=e.filter(i=>i!==n),e.length===0?g.delete(n.eventName):g.set(n.eventName,e))}var re={};p(re,{Any:()=>D,Array:()=>_n,ByteSlice:()=>Kn,Events:()=>G,Map:()=>Gn,Nullable:()=>Yn,Struct:()=>Xn});function D(n){return n}function Kn(n){return n==null?"":n}function _n(n){return n===D?e=>e===null?[]:e:e=>{if(e===null)return[];for(let i=0;ii===null?{}:i:i=>{if(i===null)return{};for(let o in i)i[o]=e(i[o]);return i}}function Yn(n){return n===D?D:e=>e===null?null:n(e)}function Xn(n){let e=!0;for(let i in n)if(n[i]!==D){e=!1;break}return e?D:i=>{for(let o in n)o in i&&(i[o]=n[o](i[o]));return i}}var G={};var Qn=Object.freeze({Windows:Object.freeze({APMPowerSettingChange:"windows:APMPowerSettingChange",APMPowerStatusChange:"windows:APMPowerStatusChange",APMResumeAutomatic:"windows:APMResumeAutomatic",APMResumeSuspend:"windows:APMResumeSuspend",APMSuspend:"windows:APMSuspend",ApplicationStarted:"windows:ApplicationStarted",SystemThemeChanged:"windows:SystemThemeChanged",WebViewNavigationCompleted:"windows:WebViewNavigationCompleted",WindowActive:"windows:WindowActive",WindowBackgroundErase:"windows:WindowBackgroundErase",WindowClickActive:"windows:WindowClickActive",WindowClosing:"windows:WindowClosing",WindowDidMove:"windows:WindowDidMove",WindowDidResize:"windows:WindowDidResize",WindowDPIChanged:"windows:WindowDPIChanged",WindowDragDrop:"windows:WindowDragDrop",WindowDragEnter:"windows:WindowDragEnter",WindowDragLeave:"windows:WindowDragLeave",WindowDragOver:"windows:WindowDragOver",WindowEndMove:"windows:WindowEndMove",WindowEndResize:"windows:WindowEndResize",WindowFullscreen:"windows:WindowFullscreen",WindowHide:"windows:WindowHide",WindowInactive:"windows:WindowInactive",WindowKeyDown:"windows:WindowKeyDown",WindowKeyUp:"windows:WindowKeyUp",WindowKillFocus:"windows:WindowKillFocus",WindowNonClientHit:"windows:WindowNonClientHit",WindowNonClientMouseDown:"windows:WindowNonClientMouseDown",WindowNonClientMouseLeave:"windows:WindowNonClientMouseLeave",WindowNonClientMouseMove:"windows:WindowNonClientMouseMove",WindowNonClientMouseUp:"windows:WindowNonClientMouseUp",WindowPaint:"windows:WindowPaint",WindowRestore:"windows:WindowRestore",WindowSetFocus:"windows:WindowSetFocus",WindowShow:"windows:WindowShow",WindowStartMove:"windows:WindowStartMove",WindowStartResize:"windows:WindowStartResize",WindowUnFullscreen:"windows:WindowUnFullscreen",WindowZOrderChanged:"windows:WindowZOrderChanged",WindowMinimise:"windows:WindowMinimise",WindowUnMinimise:"windows:WindowUnMinimise",WindowMaximise:"windows:WindowMaximise",WindowUnMaximise:"windows:WindowUnMaximise"}),Mac:Object.freeze({ApplicationDidBecomeActive:"mac:ApplicationDidBecomeActive",ApplicationDidChangeBackingProperties:"mac:ApplicationDidChangeBackingProperties",ApplicationDidChangeEffectiveAppearance:"mac:ApplicationDidChangeEffectiveAppearance",ApplicationDidChangeIcon:"mac:ApplicationDidChangeIcon",ApplicationDidChangeOcclusionState:"mac:ApplicationDidChangeOcclusionState",ApplicationDidChangeScreenParameters:"mac:ApplicationDidChangeScreenParameters",ApplicationDidChangeStatusBarFrame:"mac:ApplicationDidChangeStatusBarFrame",ApplicationDidChangeStatusBarOrientation:"mac:ApplicationDidChangeStatusBarOrientation",ApplicationDidChangeTheme:"mac:ApplicationDidChangeTheme",ApplicationDidFinishLaunching:"mac:ApplicationDidFinishLaunching",ApplicationDidHide:"mac:ApplicationDidHide",ApplicationDidResignActive:"mac:ApplicationDidResignActive",ApplicationDidUnhide:"mac:ApplicationDidUnhide",ApplicationDidUpdate:"mac:ApplicationDidUpdate",ApplicationShouldHandleReopen:"mac:ApplicationShouldHandleReopen",ApplicationWillBecomeActive:"mac:ApplicationWillBecomeActive",ApplicationWillFinishLaunching:"mac:ApplicationWillFinishLaunching",ApplicationWillHide:"mac:ApplicationWillHide",ApplicationWillResignActive:"mac:ApplicationWillResignActive",ApplicationWillTerminate:"mac:ApplicationWillTerminate",ApplicationWillUnhide:"mac:ApplicationWillUnhide",ApplicationWillUpdate:"mac:ApplicationWillUpdate",MenuDidAddItem:"mac:MenuDidAddItem",MenuDidBeginTracking:"mac:MenuDidBeginTracking",MenuDidClose:"mac:MenuDidClose",MenuDidDisplayItem:"mac:MenuDidDisplayItem",MenuDidEndTracking:"mac:MenuDidEndTracking",MenuDidHighlightItem:"mac:MenuDidHighlightItem",MenuDidOpen:"mac:MenuDidOpen",MenuDidPopUp:"mac:MenuDidPopUp",MenuDidRemoveItem:"mac:MenuDidRemoveItem",MenuDidSendAction:"mac:MenuDidSendAction",MenuDidSendActionToItem:"mac:MenuDidSendActionToItem",MenuDidUpdate:"mac:MenuDidUpdate",MenuWillAddItem:"mac:MenuWillAddItem",MenuWillBeginTracking:"mac:MenuWillBeginTracking",MenuWillDisplayItem:"mac:MenuWillDisplayItem",MenuWillEndTracking:"mac:MenuWillEndTracking",MenuWillHighlightItem:"mac:MenuWillHighlightItem",MenuWillOpen:"mac:MenuWillOpen",MenuWillPopUp:"mac:MenuWillPopUp",MenuWillRemoveItem:"mac:MenuWillRemoveItem",MenuWillSendAction:"mac:MenuWillSendAction",MenuWillSendActionToItem:"mac:MenuWillSendActionToItem",MenuWillUpdate:"mac:MenuWillUpdate",WebViewDidCommitNavigation:"mac:WebViewDidCommitNavigation",WebViewDidFinishNavigation:"mac:WebViewDidFinishNavigation",WebViewDidReceiveServerRedirectForProvisionalNavigation:"mac:WebViewDidReceiveServerRedirectForProvisionalNavigation",WebViewDidStartProvisionalNavigation:"mac:WebViewDidStartProvisionalNavigation",WindowDidBecomeKey:"mac:WindowDidBecomeKey",WindowDidBecomeMain:"mac:WindowDidBecomeMain",WindowDidBeginSheet:"mac:WindowDidBeginSheet",WindowDidChangeAlpha:"mac:WindowDidChangeAlpha",WindowDidChangeBackingLocation:"mac:WindowDidChangeBackingLocation",WindowDidChangeBackingProperties:"mac:WindowDidChangeBackingProperties",WindowDidChangeCollectionBehavior:"mac:WindowDidChangeCollectionBehavior",WindowDidChangeEffectiveAppearance:"mac:WindowDidChangeEffectiveAppearance",WindowDidChangeOcclusionState:"mac:WindowDidChangeOcclusionState",WindowDidChangeOrderingMode:"mac:WindowDidChangeOrderingMode",WindowDidChangeScreen:"mac:WindowDidChangeScreen",WindowDidChangeScreenParameters:"mac:WindowDidChangeScreenParameters",WindowDidChangeScreenProfile:"mac:WindowDidChangeScreenProfile",WindowDidChangeScreenSpace:"mac:WindowDidChangeScreenSpace",WindowDidChangeScreenSpaceProperties:"mac:WindowDidChangeScreenSpaceProperties",WindowDidChangeSharingType:"mac:WindowDidChangeSharingType",WindowDidChangeSpace:"mac:WindowDidChangeSpace",WindowDidChangeSpaceOrderingMode:"mac:WindowDidChangeSpaceOrderingMode",WindowDidChangeTitle:"mac:WindowDidChangeTitle",WindowDidChangeToolbar:"mac:WindowDidChangeToolbar",WindowDidDeminiaturize:"mac:WindowDidDeminiaturize",WindowDidEndSheet:"mac:WindowDidEndSheet",WindowDidEnterFullScreen:"mac:WindowDidEnterFullScreen",WindowDidEnterVersionBrowser:"mac:WindowDidEnterVersionBrowser",WindowDidExitFullScreen:"mac:WindowDidExitFullScreen",WindowDidExitVersionBrowser:"mac:WindowDidExitVersionBrowser",WindowDidExpose:"mac:WindowDidExpose",WindowDidFocus:"mac:WindowDidFocus",WindowDidMiniaturize:"mac:WindowDidMiniaturize",WindowDidMove:"mac:WindowDidMove",WindowDidOrderOffScreen:"mac:WindowDidOrderOffScreen",WindowDidOrderOnScreen:"mac:WindowDidOrderOnScreen",WindowDidResignKey:"mac:WindowDidResignKey",WindowDidResignMain:"mac:WindowDidResignMain",WindowDidResize:"mac:WindowDidResize",WindowDidUpdate:"mac:WindowDidUpdate",WindowDidUpdateAlpha:"mac:WindowDidUpdateAlpha",WindowDidUpdateCollectionBehavior:"mac:WindowDidUpdateCollectionBehavior",WindowDidUpdateCollectionProperties:"mac:WindowDidUpdateCollectionProperties",WindowDidUpdateShadow:"mac:WindowDidUpdateShadow",WindowDidUpdateTitle:"mac:WindowDidUpdateTitle",WindowDidUpdateToolbar:"mac:WindowDidUpdateToolbar",WindowDidZoom:"mac:WindowDidZoom",WindowFileDraggingEntered:"mac:WindowFileDraggingEntered",WindowFileDraggingExited:"mac:WindowFileDraggingExited",WindowFileDraggingPerformed:"mac:WindowFileDraggingPerformed",WindowHide:"mac:WindowHide",WindowMaximise:"mac:WindowMaximise",WindowUnMaximise:"mac:WindowUnMaximise",WindowMinimise:"mac:WindowMinimise",WindowUnMinimise:"mac:WindowUnMinimise",WindowShouldClose:"mac:WindowShouldClose",WindowShow:"mac:WindowShow",WindowWillBecomeKey:"mac:WindowWillBecomeKey",WindowWillBecomeMain:"mac:WindowWillBecomeMain",WindowWillBeginSheet:"mac:WindowWillBeginSheet",WindowWillChangeOrderingMode:"mac:WindowWillChangeOrderingMode",WindowWillClose:"mac:WindowWillClose",WindowWillDeminiaturize:"mac:WindowWillDeminiaturize",WindowWillEnterFullScreen:"mac:WindowWillEnterFullScreen",WindowWillEnterVersionBrowser:"mac:WindowWillEnterVersionBrowser",WindowWillExitFullScreen:"mac:WindowWillExitFullScreen",WindowWillExitVersionBrowser:"mac:WindowWillExitVersionBrowser",WindowWillFocus:"mac:WindowWillFocus",WindowWillMiniaturize:"mac:WindowWillMiniaturize",WindowWillMove:"mac:WindowWillMove",WindowWillOrderOffScreen:"mac:WindowWillOrderOffScreen",WindowWillOrderOnScreen:"mac:WindowWillOrderOnScreen",WindowWillResignMain:"mac:WindowWillResignMain",WindowWillResize:"mac:WindowWillResize",WindowWillUnfocus:"mac:WindowWillUnfocus",WindowWillUpdate:"mac:WindowWillUpdate",WindowWillUpdateAlpha:"mac:WindowWillUpdateAlpha",WindowWillUpdateCollectionBehavior:"mac:WindowWillUpdateCollectionBehavior",WindowWillUpdateCollectionProperties:"mac:WindowWillUpdateCollectionProperties",WindowWillUpdateShadow:"mac:WindowWillUpdateShadow",WindowWillUpdateTitle:"mac:WindowWillUpdateTitle",WindowWillUpdateToolbar:"mac:WindowWillUpdateToolbar",WindowWillUpdateVisibility:"mac:WindowWillUpdateVisibility",WindowWillUseStandardFrame:"mac:WindowWillUseStandardFrame",WindowZoomIn:"mac:WindowZoomIn",WindowZoomOut:"mac:WindowZoomOut",WindowZoomReset:"mac:WindowZoomReset"}),Linux:Object.freeze({ApplicationStartup:"linux:ApplicationStartup",SystemThemeChanged:"linux:SystemThemeChanged",WindowDeleteEvent:"linux:WindowDeleteEvent",WindowDidMove:"linux:WindowDidMove",WindowDidResize:"linux:WindowDidResize",WindowFocusIn:"linux:WindowFocusIn",WindowFocusOut:"linux:WindowFocusOut",WindowLoadStarted:"linux:WindowLoadStarted",WindowLoadRedirected:"linux:WindowLoadRedirected",WindowLoadCommitted:"linux:WindowLoadCommitted",WindowLoadFinished:"linux:WindowLoadFinished"}),iOS:Object.freeze({ApplicationDidBecomeActive:"ios:ApplicationDidBecomeActive",ApplicationDidEnterBackground:"ios:ApplicationDidEnterBackground",ApplicationDidFinishLaunching:"ios:ApplicationDidFinishLaunching",ApplicationDidReceiveMemoryWarning:"ios:ApplicationDidReceiveMemoryWarning",ApplicationWillEnterForeground:"ios:ApplicationWillEnterForeground",ApplicationWillResignActive:"ios:ApplicationWillResignActive",ApplicationWillTerminate:"ios:ApplicationWillTerminate",WindowDidLoad:"ios:WindowDidLoad",WindowWillAppear:"ios:WindowWillAppear",WindowDidAppear:"ios:WindowDidAppear",WindowWillDisappear:"ios:WindowWillDisappear",WindowDidDisappear:"ios:WindowDidDisappear",WindowSafeAreaInsetsChanged:"ios:WindowSafeAreaInsetsChanged",WindowOrientationChanged:"ios:WindowOrientationChanged",WindowTouchBegan:"ios:WindowTouchBegan",WindowTouchMoved:"ios:WindowTouchMoved",WindowTouchEnded:"ios:WindowTouchEnded",WindowTouchCancelled:"ios:WindowTouchCancelled",WebViewDidStartNavigation:"ios:WebViewDidStartNavigation",WebViewDidFinishNavigation:"ios:WebViewDidFinishNavigation",WebViewDidFailNavigation:"ios:WebViewDidFailNavigation",WebViewDecidePolicyForNavigationAction:"ios:WebViewDecidePolicyForNavigationAction"}),Common:Object.freeze({ApplicationOpenedWithFile:"common:ApplicationOpenedWithFile",ApplicationStarted:"common:ApplicationStarted",ApplicationLaunchedWithUrl:"common:ApplicationLaunchedWithUrl",ThemeChanged:"common:ThemeChanged",WindowClosing:"common:WindowClosing",WindowDidMove:"common:WindowDidMove",WindowDidResize:"common:WindowDidResize",WindowDPIChanged:"common:WindowDPIChanged",WindowFilesDropped:"common:WindowFilesDropped",WindowFocus:"common:WindowFocus",WindowFullscreen:"common:WindowFullscreen",WindowHide:"common:WindowHide",WindowLostFocus:"common:WindowLostFocus",WindowMaximise:"common:WindowMaximise",WindowMinimise:"common:WindowMinimise",WindowToggleFrameless:"common:WindowToggleFrameless",WindowRestore:"common:WindowRestore",WindowRuntimeReady:"common:WindowRuntimeReady",WindowShow:"common:WindowShow",WindowUnFullscreen:"common:WindowUnFullscreen",WindowUnMaximise:"common:WindowUnMaximise",WindowUnMinimise:"common:WindowUnMinimise",WindowZoom:"common:WindowZoom",WindowZoomIn:"common:WindowZoomIn",WindowZoomOut:"common:WindowZoomOut",WindowZoomReset:"common:WindowZoomReset"})});window._wails=window._wails||{};window._wails.dispatchWailsEvent=Jn;var qn=u(m.Events),$n=0,U=class{constructor(e,i){this.name=e,this.data=i!=null?i:null}};function Jn(n){let e=g.get(n.name);if(!e)return;let i=new U(n.name,n.name in G?G[n.name](n.data):n.data);"sender"in n&&(i.sender=n.sender),e=e.filter(o=>!o.dispatch(i)),e.length===0?g.delete(n.name):g.set(n.name,e)}function ae(n,e,i){let o=g.get(n)||[],t=new _(n,e,i);return o.push(t),g.set(n,o),()=>qe(t)}function ei(n,e){return ae(n,e,-1)}function ni(n,e){return ae(n,e,1)}function ii(...n){n.forEach(e=>g.delete(e))}function oi(){g.clear()}function se(n,e){return qn($n,new U(n,e))}function $e(){return new MouseEvent("mousedown").buttons===0}function Je(){if(!EventTarget||!AbortSignal||!AbortController)return!1;let n=!0,e=new EventTarget,i=new AbortController;return e.addEventListener("test",()=>{n=!1},{signal:i.signal}),i.abort(),e.dispatchEvent(new CustomEvent("test")),n}function Y(n){var e;return n.target instanceof HTMLElement?n.target:!(n.target instanceof HTMLElement)&&n.target instanceof Node&&(e=n.target.parentElement)!=null?e:document.body}var en=!1;document.addEventListener("DOMContentLoaded",()=>{en=!0});function nn(n){en||document.readyState==="complete"?n():document.addEventListener("DOMContentLoaded",n)}var ti="data-file-drop-target",h="file-drop-target-active",c=null,ri=0,ai=1,si=2,li=3,di=4,ci=5,mi=6,ui=7,wi=8,pi=9,fi=10,gi=11,hi=12,Wi=13,bi=14,vi=15,yi=16,Di=17,Ci=18,Pi=19,Ti=20,Mi=21,Si=22,Ei=23,xi=24,Ai=25,Ri=26,Fi=27,Oi=28,ki=29,Li=30,Ii=31,Ui=32,zi=33,Ni=34,ji=35,Bi=36,Hi=37,Vi=38,Zi=39,Ki=40,_i=41,Gi=42,Yi=43,Xi=44,Qi=45,qi=46,$i=47,Ji=48,eo=49,no=50,io=51;function X(n){return n?n.closest("[".concat(ti,"]")):null}function oo(){var n,e,i,o;return((e=(n=window.chrome)==null?void 0:n.webview)==null?void 0:e.postMessageWithAdditionalObjects)==null?!1:((o=(i=window._wails)==null?void 0:i.flags)==null?void 0:o.enableFileDrop)===!0}function to(n,e,i){var o,t;(t=(o=window.chrome)==null?void 0:o.webview)!=null&&t.postMessageWithAdditionalObjects&&window.chrome.webview.postMessageWithAdditionalObjects("file:drop:".concat(n,":").concat(e),i)}var ce=!1;function on(){ce=!1,c&&(c.classList.remove(h),c=null)}function tn(){var n,e;((e=(n=window._wails)==null?void 0:n.flags)==null?void 0:e.enableFileDrop)!==!1&&(ce=!0)}function rn(){on()}function an(n,e){var t,r;if(!ce||((r=(t=window._wails)==null?void 0:t.flags)==null?void 0:r.enableFileDrop)===!1)return;let i=document.elementFromPoint(n,e),o=X(i);c&&c!==o&&c.classList.remove(h),o?(o.classList.add(h),c=o):c=null}var s=Symbol("caller"),Q=class Q{constructor(e=""){this[s]=u(m.Window,e);for(let i of Object.getOwnPropertyNames(Q.prototype))i!=="constructor"&&typeof this[i]=="function"&&(this[i]=this[i].bind(this))}Get(e){return new Q(e)}Position(){return this[s](ri)}Center(){return this[s](ai)}Close(){return this[s](si)}DisableSizeConstraints(){return this[s](li)}EnableSizeConstraints(){return this[s](di)}Focus(){return this[s](ci)}ForceReload(){return this[s](mi)}Fullscreen(){return this[s](ui)}GetScreen(){return this[s](wi)}GetZoom(){return this[s](pi)}Height(){return this[s](fi)}Hide(){return this[s](gi)}IsFocused(){return this[s](hi)}IsFullscreen(){return this[s](Wi)}IsMaximised(){return this[s](bi)}IsMinimised(){return this[s](vi)}Maximise(){return this[s](yi)}Minimise(){return this[s](Di)}Name(){return this[s](Ci)}OpenDevTools(){return this[s](Pi)}RelativePosition(){return this[s](Ti)}Reload(){return this[s](Mi)}Resizable(){return this[s](Si)}Restore(){return this[s](Ei)}SetPosition(e,i){return this[s](xi,{x:e,y:i})}SetAlwaysOnTop(e){return this[s](Ai,{alwaysOnTop:e})}SetBackgroundColour(e,i,o,t){return this[s](Ri,{r:e,g:i,b:o,a:t})}SetFrameless(e){return this[s](Fi,{frameless:e})}SetFullscreenButtonEnabled(e){return this[s](Oi,{enabled:e})}SetMaxSize(e,i){return this[s](ki,{width:e,height:i})}SetMinSize(e,i){return this[s](Li,{width:e,height:i})}SetRelativePosition(e,i){return this[s](Ii,{x:e,y:i})}SetResizable(e){return this[s](Ui,{resizable:e})}SetSize(e,i){return this[s](zi,{width:e,height:i})}SetTitle(e){return this[s](Ni,{title:e})}SetZoom(e){return this[s](ji,{zoom:e})}Show(){return this[s](Bi)}Size(){return this[s](Hi)}ToggleFullscreen(){return this[s](Vi)}ToggleMaximise(){return this[s](Zi)}ToggleFrameless(){return this[s](Ki)}UnFullscreen(){return this[s](_i)}UnMaximise(){return this[s](Gi)}UnMinimise(){return this[s](Yi)}Width(){return this[s](Xi)}Zoom(){return this[s](Qi)}ZoomIn(){return this[s](qi)}ZoomOut(){return this[s]($i)}ZoomReset(){return this[s](Ji)}HandlePlatformFileDrop(e,i,o){var d,w;if(((w=(d=window._wails)==null?void 0:d.flags)==null?void 0:w.enableFileDrop)===!1)return;let t=document.elementFromPoint(i,o),r=X(t);if(!r)return;let a={id:r.id,classList:Array.from(r.classList),attributes:{}};for(let y=0;y{var r,a,l;if(!((r=i.dataTransfer)!=null&&r.types.includes("Files")))return;if(i.preventDefault(),((l=(a=window._wails)==null?void 0:a.flags)==null?void 0:l.enableFileDrop)===!1){i.dataTransfer.dropEffect="none";return}e++;let o=document.elementFromPoint(i.clientX,i.clientY),t=X(o);c&&c!==t&&c.classList.remove(h),t?(t.classList.add(h),i.dataTransfer.dropEffect="copy",c=t):(i.dataTransfer.dropEffect="none",c=null)},!1),n.addEventListener("dragover",i=>{var r,a,l;if(!((r=i.dataTransfer)!=null&&r.types.includes("Files")))return;if(i.preventDefault(),((l=(a=window._wails)==null?void 0:a.flags)==null?void 0:l.enableFileDrop)===!1){i.dataTransfer.dropEffect="none";return}let o=document.elementFromPoint(i.clientX,i.clientY),t=X(o);c&&c!==t&&c.classList.remove(h),t?(t.classList.contains(h)||t.classList.add(h),i.dataTransfer.dropEffect="copy",c=t):(i.dataTransfer.dropEffect="none",c=null)},!1),n.addEventListener("dragleave",i=>{var o,t,r;(o=i.dataTransfer)!=null&&o.types.includes("Files")&&(i.preventDefault(),((r=(t=window._wails)==null?void 0:t.flags)==null?void 0:r.enableFileDrop)!==!1&&i.relatedTarget!==null&&(e--,(e===0||c&&!c.contains(i.relatedTarget))&&(c&&(c.classList.remove(h),c=null),e=0)))},!1),n.addEventListener("drop",i=>{var o,t,r;if((o=i.dataTransfer)!=null&&o.types.includes("Files")&&(i.preventDefault(),((r=(t=window._wails)==null?void 0:t.flags)==null?void 0:r.enableFileDrop)!==!1&&(e=0,c&&(c.classList.remove(h),c=null),oo()))){let a=[];if(i.dataTransfer.items){for(let l of i.dataTransfer.items)if(l.kind==="file"){let d=l.getAsFile();d&&a.push(d)}}else if(i.dataTransfer.files)for(let l of i.dataTransfer.files)a.push(l);a.length>0&&to(i.clientX,i.clientY,a)}},!1)}typeof window<"u"&&typeof document<"u"&&ao();var E=ro;function so(n,e=null){se(n,e)}function lo(n,e){let i=E.Get(n),o=i[e];if(typeof o=="function")try{o.call(i)}catch(t){}}function sn(n){let e=n.currentTarget;function i(t="Yes"){if(t!=="Yes")return;let r=e.getAttribute("wml-event")||e.getAttribute("data-wml-event"),a=e.getAttribute("wml-target-window")||e.getAttribute("data-wml-target-window")||"",l=e.getAttribute("wml-window")||e.getAttribute("data-wml-window"),d=e.getAttribute("wml-openurl")||e.getAttribute("data-wml-openurl");r!==null&&so(r),l!==null&&lo(a,l),d!==null&&ne(d)}let o=e.getAttribute("wml-confirm")||e.getAttribute("data-wml-confirm");o?oe({Title:"Confirm",Message:o,Detached:!1,Buttons:[{Label:"Yes"},{Label:"No",IsDefault:!0}]}).then(i):i()}var z=Symbol("controller"),x=Symbol("triggerMap"),C=Symbol("elementCount"),me=class{constructor(){this[z]=new AbortController}set(e,i){return{signal:this[z].signal}}reset(){this[z].abort(),this[z]=new AbortController}},ue=class{constructor(){this[x]=new WeakMap,this[C]=0}set(e,i){return this[x].has(e)||this[C]++,this[x].set(e,i),{}}reset(){if(!(this[C]<=0)){for(let e of document.body.querySelectorAll("*")){if(this[C]<=0)break;let i=this[x].get(e);i!=null&&this[C]--;for(let o of i||[])e.removeEventListener(o,sn)}this[x]=new WeakMap,this[C]=0}}},ln=Je()?new me:new ue;function co(n){let e=/\S+/g,i=n.getAttribute("wml-trigger")||n.getAttribute("data-wml-trigger")||"click",o=[],t;for(;(t=e.exec(i))!==null;)o.push(t[0]);let r=ln.set(n,o);for(let a of o)n.addEventListener(a,sn,r)}function we(){nn(dn)}function dn(){ln.reset(),document.body.querySelectorAll("[wml-event], [wml-window], [wml-openurl], [data-wml-event], [data-wml-window], [data-wml-openurl]").forEach(co)}window.wails=fe;we();var be={};p(be,{Capabilities:()=>fo,Environment:()=>go,IsAMD64:()=>bo,IsARM:()=>vo,IsARM64:()=>yo,IsDarkMode:()=>po,IsDebug:()=>We,IsLinux:()=>ho,IsMac:()=>Wo,IsWindows:()=>q,invoke:()=>P});var he=u(m.System),mo=0,uo=1,wo=2,ge=(function(){var n,e,i,o,t,r;try{if((e=(n=window.chrome)==null?void 0:n.webview)!=null&&e.postMessage)return window.chrome.webview.postMessage.bind(window.chrome.webview);if((t=(o=(i=window.webkit)==null?void 0:i.messageHandlers)==null?void 0:o.external)!=null&&t.postMessage)return window.webkit.messageHandlers.external.postMessage.bind(window.webkit.messageHandlers.external);if((r=window.wails)!=null&&r.invoke)return a=>window.wails.invoke(typeof a=="string"?a:JSON.stringify(a))}catch(a){}return null})();function P(n){ge==null||ge(n)}function po(){return he(mo)}async function fo(){return he(wo)}function go(){return he(uo)}function q(){var n,e;return((e=(n=window._wails)==null?void 0:n.environment)==null?void 0:e.OS)==="windows"}function ho(){var n,e;return((e=(n=window._wails)==null?void 0:n.environment)==null?void 0:e.OS)==="linux"}function Wo(){var n,e;return((e=(n=window._wails)==null?void 0:n.environment)==null?void 0:e.OS)==="darwin"}function bo(){var n,e;return((e=(n=window._wails)==null?void 0:n.environment)==null?void 0:e.Arch)==="amd64"}function vo(){var n,e;return((e=(n=window._wails)==null?void 0:n.environment)==null?void 0:e.Arch)==="arm"}function yo(){var n,e;return((e=(n=window._wails)==null?void 0:n.environment)==null?void 0:e.Arch)==="arm64"}function We(){var n,e;return!!((e=(n=window._wails)==null?void 0:n.environment)!=null&&e.Debug)}window.addEventListener("contextmenu",To);var Do=u(m.ContextMenu),Co=0;function Po(n,e,i,o){Do(Co,{id:n,x:e,y:i,data:o})}function To(n){let e=Y(n),i=window.getComputedStyle(e).getPropertyValue("--custom-contextmenu").trim();if(i){n.preventDefault();let o=window.getComputedStyle(e).getPropertyValue("--custom-contextmenu-data");Po(i,n.clientX,n.clientY,o)}else Mo(n,e)}function Mo(n,e){if(We())return;switch(window.getComputedStyle(e).getPropertyValue("--default-contextmenu").trim()){case"show":return;case"hide":n.preventDefault();return}if(e.isContentEditable)return;let i=window.getSelection(),o=i&&i.toString().length>0;if(o)for(let t=0;tN});function N(n){try{return window._wails.flags[n]}catch(e){throw new Error("Unable to retrieve flag '"+n+"': "+e,{cause:e})}}var j=!1,B=!1,Te=!1,R=!1,F=!1,T="",cn="auto",A=0,ye=$e();window._wails=window._wails||{};window._wails.setResizable=n=>{Te=n,Te||(R=F=!1,f())};var Me=!1;function So(){var i,o;let n=(o=(i=window._wails)==null?void 0:i.environment)==null?void 0:o.OS;if(n==="ios"||n==="android")return!0;let e=navigator.userAgent||navigator.vendor||window.opera||"";return/android|iphone|ipad|ipod|iemobile|wpdesktop/i.test(e)}function Se(){if(!Me&&!So()){window.addEventListener("mousedown",Pe,{capture:!0}),window.addEventListener("mousemove",Pe,{capture:!0}),window.addEventListener("mouseup",Pe,{capture:!0});for(let n of["click","contextmenu","dblclick"])window.addEventListener(n,xo,{capture:!0});Me=!0}}Se();document.addEventListener("DOMContentLoaded",Se,{once:!0});var Eo=0,mn=window.setInterval(()=>{if(Me){window.clearInterval(mn);return}Se(),++Eo>100&&window.clearInterval(mn)},50);function xo(n){(B||F)&&(n.stopImmediatePropagation(),n.stopPropagation(),n.preventDefault())}var De=0,Ao=1,Ce=2;function Pe(n){let e,i=n.buttons;switch(n.type){case"mousedown":e=De,ye||(i=A|1<zo,Quit:()=>jo,Show:()=>No});var Ee=u(m.Application),Lo=0,Io=1,Uo=2;function zo(){return Ee(Lo)}function No(){return Ee(Io)}function jo(){return Ee(Uo)}var Ue={};p(Ue,{ByID:()=>at,ByName:()=>rt,Call:()=>Ie,RuntimeError:()=>Le});var wn=Function.prototype.toString,O=typeof Reflect=="object"&&Reflect!==null&&Reflect.apply,Ae,$;if(typeof O=="function"&&typeof Object.defineProperty=="function")try{Ae=Object.defineProperty({},"length",{get:function(){throw $}}),$={},O(function(){throw 42},null,Ae)}catch(n){n!==$&&(O=null)}else O=null;var Bo=/^\s*class\b/,Fe=function(e){try{var i=wn.call(e);return Bo.test(i)}catch(o){return!1}},Re=function(e){try{return Fe(e)?!1:(wn.call(e),!0)}catch(i){return!1}},J=Object.prototype.toString,Ho="[object Object]",Vo="[object Function]",Zo="[object GeneratorFunction]",Ko="[object HTMLAllCollection]",_o="[object HTML document.all class]",Go="[object HTMLCollection]",Yo=typeof Symbol=="function"&&!!Symbol.toStringTag,Xo=!(0 in[,]),Oe=function(){return!1};typeof document=="object"&&(un=document.all,J.call(un)===J.call(document.all)&&(Oe=function(e){if((Xo||!e)&&(typeof e>"u"||typeof e=="object"))try{var i=J.call(e);return(i===Ko||i===_o||i===Go||i===Ho)&&e("")==null}catch(o){}return!1}));var un;function Qo(n){if(Oe(n))return!0;if(!n||typeof n!="function"&&typeof n!="object")return!1;try{O(n,null,Ae)}catch(e){if(e!==$)return!1}return!Fe(n)&&Re(n)}function qo(n){if(Oe(n))return!0;if(!n||typeof n!="function"&&typeof n!="object")return!1;if(Yo)return Re(n);if(Fe(n))return!1;var e=J.call(n);return e!==Vo&&e!==Zo&&!/^\[object HTML/.test(e)?!1:Re(n)}var b=O?Qo:qo;var L=class extends Error{constructor(e,i){super(e,i),this.name="CancelError"}},v=class extends Error{constructor(e,i,o){super((o!=null?o:"Unhandled rejection in cancelled promise.")+" Reason: "+$o(i),{cause:i}),this.promise=e,this.name="CancelledRejectionError"}},W=Symbol("barrier"),ke=Symbol("cancelImpl"),hn,pn=(hn=Symbol.species)!=null?hn:Symbol("speciesPolyfill"),H=class n extends Promise{constructor(e,i){let o,t;if(super((d,w)=>{o=d,t=w}),this.constructor[pn]!==Promise)throw new TypeError("CancellablePromise does not support transparent subclassing. Please refrain from overriding the [Symbol.species] static property.");let r={promise:this,resolve:o,reject:t,get oncancelled(){return i!=null?i:null},set oncancelled(d){i=d!=null?d:void 0}},a={get root(){return a},resolving:!1,settled:!1};Object.defineProperties(this,{[W]:{configurable:!1,enumerable:!1,writable:!0,value:null},[ke]:{configurable:!1,enumerable:!1,writable:!1,value:Wn(r,a)}});let l=vn(r,a);try{e(bn(r,a),l)}catch(d){a.resolving||l(d)}}cancel(e){return new n(i=>{Promise.all([this[ke](new L("Promise cancelled.",{cause:e})),Jo(this)]).then(()=>i(),()=>i())})}cancelOn(e){return e.aborted?this.cancel(e.reason):e.addEventListener("abort",()=>{this.cancel(e.reason)},{capture:!0}),this}then(e,i,o){if(!(this instanceof n))throw new TypeError("CancellablePromise.prototype.then called on an invalid object.");if(b(e)||(e=fn),b(i)||(i=gn),e===fn&&i==gn)return new n(r=>r(this));let t={};return this[W]=t,new n((r,a)=>{super.then(l=>{var d;this[W]===t&&(this[W]=null),(d=t.resolve)==null||d.call(t);try{r(e(l))}catch(w){a(w)}},l=>{var d;this[W]===t&&(this[W]=null),(d=t.resolve)==null||d.call(t);try{r(i(l))}catch(w){a(w)}})},async r=>{try{return o==null?void 0:o(r)}finally{await this.cancel(r)}})}catch(e,i){return this.then(void 0,e,i)}finally(e,i){if(!(this instanceof n))throw new TypeError("CancellablePromise.prototype.finally called on an invalid object.");return b(e)?this.then(o=>n.resolve(e()).then(()=>o),o=>n.resolve(e()).then(()=>{throw o}),i):this.then(e,e,i)}static get[(W,ke,pn)](){return Promise}static all(e){let i=Array.from(e),o=i.length===0?n.resolve(i):new n((t,r)=>{Promise.all(i).then(t,r)},t=>ee(o,i,t));return o}static allSettled(e){let i=Array.from(e),o=i.length===0?n.resolve(i):new n((t,r)=>{Promise.allSettled(i).then(t,r)},t=>ee(o,i,t));return o}static any(e){let i=Array.from(e),o=i.length===0?n.resolve(i):new n((t,r)=>{Promise.any(i).then(t,r)},t=>ee(o,i,t));return o}static race(e){let i=Array.from(e),o=new n((t,r)=>{Promise.race(i).then(t,r)},t=>ee(o,i,t));return o}static cancel(e){let i=new n(()=>{});return i.cancel(e),i}static timeout(e,i){let o=new n(()=>{});return AbortSignal&&typeof AbortSignal=="function"&&AbortSignal.timeout&&typeof AbortSignal.timeout=="function"?AbortSignal.timeout(e).addEventListener("abort",()=>{o.cancel(i)}):setTimeout(()=>{o.cancel(i)},e),o}static sleep(e,i){return new n(o=>{setTimeout(()=>o(i),e)})}static reject(e){return new n((i,o)=>o(e))}static resolve(e){return e instanceof n?e:new n(i=>i(e))}static withResolvers(){let e={oncancelled:null};return e.promise=new n((i,o)=>{e.resolve=i,e.reject=o},i=>{var o;(o=e.oncancelled)==null||o.call(e,i)}),e}};function Wn(n,e){let i;return o=>{if(e.settled||(e.settled=!0,e.reason=o,n.reject(o),Promise.prototype.then.call(n.promise,void 0,t=>{if(t!==o)throw t})),!(!e.reason||!n.oncancelled))return i=new Promise(t=>{try{t(n.oncancelled(e.reason.cause))}catch(r){Promise.reject(new v(n.promise,r,"Unhandled exception in oncancelled callback."))}}).catch(t=>{Promise.reject(new v(n.promise,t,"Unhandled rejection in oncancelled callback."))}),n.oncancelled=null,i}}function bn(n,e){return i=>{if(!e.resolving){if(e.resolving=!0,i===n.promise){if(e.settled)return;e.settled=!0,n.reject(new TypeError("A promise cannot be resolved with itself."));return}if(i!=null&&(typeof i=="object"||typeof i=="function")){let o;try{o=i.then}catch(t){e.settled=!0,n.reject(t);return}if(b(o)){try{let a=i.cancel;if(b(a)){let l=d=>{Reflect.apply(a,i,[d])};e.reason?Wn(Ye(Ge({},n),{oncancelled:l}),e)(e.reason):n.oncancelled=l}}catch(a){}let t={root:e.root,resolving:!1,get settled(){return this.root.settled},set settled(a){this.root.settled=a},get reason(){return this.root.reason}},r=vn(n,t);try{Reflect.apply(o,i,[bn(n,t),r])}catch(a){r(a)}return}}e.settled||(e.settled=!0,n.resolve(i))}}}function vn(n,e){return i=>{if(!e.resolving)if(e.resolving=!0,e.settled){try{if(i instanceof L&&e.reason instanceof L&&Object.is(i.cause,e.reason.cause))return}catch(o){}Promise.reject(new v(n.promise,i))}else e.settled=!0,n.reject(i)}}function ee(n,e,i){let o=[];for(let t of e){let r;try{if(!b(t.then)||(r=t.cancel,!b(r)))continue}catch(l){continue}let a;try{a=Reflect.apply(r,t,[i])}catch(l){Promise.reject(new v(n,l,"Unhandled exception in cancel method."));continue}a&&o.push((a instanceof Promise?a:Promise.resolve(a)).catch(l=>{Promise.reject(new v(n,l,"Unhandled rejection in cancel method."))}))}return Promise.all(o)}function fn(n){return n}function gn(n){throw n}function $o(n){try{if(n instanceof Error||typeof n!="object"||n.toString!==Object.prototype.toString)return""+n}catch(e){}try{return JSON.stringify(n)}catch(e){}try{return Object.prototype.toString.call(n)}catch(e){}return""}function Jo(n){var i;let e=(i=n[W])!=null?i:{};return"promise"in e||Object.assign(e,k()),n[W]==null&&(e.resolve(),n[W]=e),e.promise}var k=Promise.withResolvers;k&&typeof k=="function"?k=k.bind(Promise):k=function(){let n,e;return{promise:new Promise((o,t)=>{n=o,e=t}),resolve:n,reject:e}};window._wails=window._wails||{};var et=u(m.Call),nt=u(m.CancelCall),V=new Map,it=0,ot=0,Le=class extends Error{constructor(e,i){super(e,i),this.name="RuntimeError"}};function tt(){let n;do n=Z();while(V.has(n));return n}function Ie(n){let e=tt(),i=H.withResolvers();V.set(e,{resolve:i.resolve,reject:i.reject});let o=et(it,Object.assign({"call-id":e},n)),t=!0;o.then(a=>{t=!1,V.delete(e),i.resolve(a)},a=>{t=!1,V.delete(e),i.reject(a)});let r=()=>(V.delete(e),nt(ot,{"call-id":e}).catch(a=>{}));return i.oncancelled=()=>t?r():o.then(r),i.promise}function rt(n,...e){return Ie({methodName:n,args:e})}function at(n,...e){return Ie({methodID:n,args:e})}var ze={};p(ze,{SetText:()=>dt,Text:()=>ct});var yn=u(m.Clipboard),st=0,lt=1;function dt(n){return yn(st,{text:n})}function ct(){return yn(lt)}var je={};p(je,{GetAll:()=>pt,GetCurrent:()=>gt,GetPrimary:()=>ft});var Ne=u(m.Screens),mt=0,ut=1,wt=2;function pt(){return Ne(mt)}function ft(){return Ne(ut)}function gt(){return Ne(wt)}var Ve={};p(Ve,{Device:()=>He,Haptics:()=>Be});var Dn=u(m.IOS),ht=0,Wt=1,Be;(e=>{function n(i="medium"){return Dn(ht,{style:i})}e.Impact=n})(Be||(Be={}));var He;(e=>{function n(){return Dn(Wt)}e.Info=n})(He||(He={}));window._wails=window._wails||{};window._wails.invoke=P;window._wails.clientId=I;window._wails.handlePlatformFileDrop=E.HandlePlatformFileDrop.bind(E);window._wails.handleDragEnter=tn;window._wails.handleDragLeave=rn;window._wails.handleDragOver=an;P("wails:runtime:ready");function Cn(n){return fetch(n,{method:"HEAD"}).then(e=>{if(e.ok){let i=document.createElement("script");i.src=n,document.head.appendChild(i)}}).catch(()=>{})}Cn("/wails/custom.js");export{xe as Application,ie as Browser,Ue as Call,L as CancelError,H as CancellablePromise,v as CancelledRejectionError,ze as Clipboard,re as Create,te as Dialogs,le as Events,ve as Flags,Ve as IOS,je as Screens,be as System,pe as WML,E as Window,I as clientId,Qe as getTransport,Cn as loadOptionalScript,m as objectNames,Xe as setTransport}; diff --git a/v3/internal/assetserver/bundledassets/runtime_dev.go b/v3/internal/assetserver/bundledassets/runtime_dev.go deleted file mode 100644 index 2c9621a66..000000000 --- a/v3/internal/assetserver/bundledassets/runtime_dev.go +++ /dev/null @@ -1,8 +0,0 @@ -//go:build !production - -package bundledassets - -import _ "embed" - -//go:embed runtime.debug.js -var RuntimeJS []byte diff --git a/v3/internal/assetserver/bundledassets/runtime_production.go b/v3/internal/assetserver/bundledassets/runtime_production.go deleted file mode 100644 index 9614a7b13..000000000 --- a/v3/internal/assetserver/bundledassets/runtime_production.go +++ /dev/null @@ -1,8 +0,0 @@ -//go:build production - -package bundledassets - -import _ "embed" - -//go:embed runtime.js -var RuntimeJS []byte diff --git a/v3/internal/assetserver/common.go b/v3/internal/assetserver/common.go deleted file mode 100644 index a41139dff..000000000 --- a/v3/internal/assetserver/common.go +++ /dev/null @@ -1,66 +0,0 @@ -package assetserver - -import ( - "context" - "fmt" - "log/slog" - "net/http" - "strings" -) - -const ( - HeaderHost = "Host" - HeaderContentType = "Content-Type" - HeaderContentLength = "Content-Length" - HeaderUserAgent = "User-Agent" - // TODO: Is this needed? - HeaderCacheControl = "Cache-Control" - HeaderUpgrade = "Upgrade" - - WailsUserAgentValue = "wails.io" -) - -type assetServerLogger struct{} - -var assetServerLoggerKey assetServerLogger - -// ServeFile writes the provided blob to rw as an HTTP 200 response, ensuring appropriate -// Content-Length and Content-Type headers are set. -// -// If the Content-Type header is not already present, ServeFile determines an appropriate -// MIME type from the filename and blob and sets the Content-Type header. It then writes -// the 200 status and the blob body to the response, returning any error encountered while -// writing the body. -func ServeFile(rw http.ResponseWriter, filename string, blob []byte) error { - header := rw.Header() - header.Set(HeaderContentLength, fmt.Sprintf("%d", len(blob))) - if mimeType := header.Get(HeaderContentType); mimeType == "" { - mimeType = GetMimetype(filename, blob) - header.Set(HeaderContentType, mimeType) - } - - rw.WriteHeader(http.StatusOK) - _, err := rw.Write(blob) - return err -} - -func isWebSocket(req *http.Request) bool { - upgrade := req.Header.Get(HeaderUpgrade) - return strings.EqualFold(upgrade, "websocket") -} - -func contextWithLogger(ctx context.Context, logger *slog.Logger) context.Context { - return context.WithValue(ctx, assetServerLoggerKey, logger) -} - -func logInfo(ctx context.Context, message string, args ...interface{}) { - if logger, _ := ctx.Value(assetServerLoggerKey).(*slog.Logger); logger != nil { - logger.Info(message, args...) - } -} - -func logError(ctx context.Context, message string, args ...interface{}) { - if logger, _ := ctx.Value(assetServerLoggerKey).(*slog.Logger); logger != nil { - logger.Error(message, args...) - } -} \ No newline at end of file diff --git a/v3/internal/assetserver/content_type_sniffer.go b/v3/internal/assetserver/content_type_sniffer.go deleted file mode 100644 index fd51a6101..000000000 --- a/v3/internal/assetserver/content_type_sniffer.go +++ /dev/null @@ -1,142 +0,0 @@ -package assetserver - -import ( - "net/http" -) - -// newContentTypeSniffer creates a contentTypeSniffer that wraps the provided http.ResponseWriter. -// The returned sniffer does not allocate a close notification channel; it will be initialized lazily by CloseNotify. -func newContentTypeSniffer(rw http.ResponseWriter) *contentTypeSniffer { - return &contentTypeSniffer{ - rw: rw, - } -} - -type contentTypeSniffer struct { - rw http.ResponseWriter - prefix []byte - closeChannel chan bool // lazily allocated only if CloseNotify is called - status int - headerCommitted bool - headerWritten bool -} - -// Unwrap returns the wrapped [http.ResponseWriter] for use with [http.ResponseController]. -func (rw *contentTypeSniffer) Unwrap() http.ResponseWriter { - return rw.rw -} - -func (rw *contentTypeSniffer) Header() http.Header { - return rw.rw.Header() -} - -func (rw *contentTypeSniffer) Write(chunk []byte) (int, error) { - if !rw.headerCommitted { - rw.WriteHeader(http.StatusOK) - } - - if rw.headerWritten { - return rw.rw.Write(chunk) - } - - if len(chunk) == 0 { - return 0, nil - } - - // Cut away at most 512 bytes from chunk, and not less than 0. - cut := max(min(len(chunk), 512-len(rw.prefix)), 0) - if cut >= 512 { - // Avoid copying data if a full prefix is available on first non-zero write. - cut = len(chunk) - rw.prefix = chunk - chunk = nil - } else if cut > 0 { - // First write had less than 512 bytes -- copy data to the prefix buffer. - if rw.prefix == nil { - // Preallocate space for the prefix to be used for sniffing. - rw.prefix = make([]byte, 0, 512) - } - rw.prefix = append(rw.prefix, chunk[:cut]...) - chunk = chunk[cut:] - } - - if len(rw.prefix) < 512 { - return cut, nil - } - - if _, err := rw.complete(); err != nil { - return cut, err - } - - n, err := rw.rw.Write(chunk) - return cut + n, err -} - -func (rw *contentTypeSniffer) WriteHeader(code int) { - if rw.headerCommitted { - return - } - - rw.status = code - rw.headerCommitted = true - - if _, hasType := rw.Header()[HeaderContentType]; hasType { - rw.rw.WriteHeader(rw.status) - rw.headerWritten = true - } -} - -// sniff sniffs the content type from the stored prefix if necessary, -// then writes the header. -func (rw *contentTypeSniffer) sniff() { - if rw.headerWritten || !rw.headerCommitted { - return - } - - m := rw.Header() - if _, hasType := m[HeaderContentType]; !hasType { - m.Set(HeaderContentType, http.DetectContentType(rw.prefix)) - } - - rw.rw.WriteHeader(rw.status) - rw.headerWritten = true -} - -// complete sniffs the content type if necessary, writes the header -// and sends the data prefix that has been stored for sniffing. -// -// Whoever creates a contentTypeSniffer instance -// is responsible for calling complete after the nested handler has returned. -func (rw *contentTypeSniffer) complete() (n int, err error) { - rw.sniff() - - if rw.headerWritten && len(rw.prefix) > 0 { - n, err = rw.rw.Write(rw.prefix) - rw.prefix = nil - } - - return -} - -// CloseNotify implements the http.CloseNotifier interface. -// The channel is lazily allocated to avoid allocation overhead for requests -// that don't use this deprecated interface. -func (rw *contentTypeSniffer) CloseNotify() <-chan bool { - if rw.closeChannel == nil { - rw.closeChannel = make(chan bool, 1) - } - return rw.closeChannel -} - -func (rw *contentTypeSniffer) closeClient() { - if rw.closeChannel != nil { - rw.closeChannel <- true - } -} - -// Flush implements the http.Flusher interface. -func (rw *contentTypeSniffer) Flush() { - if f, ok := rw.rw.(http.Flusher); ok { - f.Flush() - } -} \ No newline at end of file diff --git a/v3/internal/assetserver/defaults/index.en.html b/v3/internal/assetserver/defaults/index.en.html deleted file mode 100644 index 72c0f567d..000000000 --- a/v3/internal/assetserver/defaults/index.en.html +++ /dev/null @@ -1,350 +0,0 @@ - - - - - - Page Not Found - Wails - - - -
                    - -
                    - -
                    - - -
                    -
                    -
                    -
                    ⚠️
                    - Missing index.html file -
                    -
                    -

                    No index.html file was found in the embedded assets. This page appears when the WebView window cannot find HTML content to display.

                    -
                      -
                    • - 1 - - If you are using the Assets option in your application, ensure you have an index.html file in your project's embedded assets directory. -
                      - View Example → -
                      -//go:embed all:frontend/dist -var assets embed.FS - -func main() { - // ... - app := application.New(application.Options{ - // ... - Assets: application.AssetOptions{ - Handler: application.AssetFileServerFS(assets), - }, - }) - // ... -} -
                      -
                      -
                      -
                    • -
                    • - 2 - If the file doesn't exist but should, verify that your build process is configured to correctly include the HTML file in the embedded assets directory. -
                    • -
                    • - 3 - - An alternative solution is to use the HTML option in the WebviewWindow Options. -
                      - View Example → -
                      -func main() { - - // ... - - app.NewWebviewWindowWithOptions(application.WebviewWindowOptions{ - // ... - HTML: "<h1>Hello World!<h1>", - }) - // ... -} -
                      -
                      -
                      -
                    • -
                    -
                    - -
                    - - -
                    -
                    -
                    - - - -
                    - - \ No newline at end of file diff --git a/v3/internal/assetserver/defaults/index.zh.html b/v3/internal/assetserver/defaults/index.zh.html deleted file mode 100644 index 45e5fb93c..000000000 --- a/v3/internal/assetserver/defaults/index.zh.html +++ /dev/null @@ -1,302 +0,0 @@ - - - - - - 页面未找到 - Wails - - - -
                    - -
                    - -
                    - - -
                    -
                    -
                    -
                    - 未找到 index.html 文件 -
                    请按照以下步骤解决此问题
                    -
                    -
                    -

                    - 系统提示:在嵌入资源中未能找到 index.html 文件。 -
                    - 不用担心,这个问题很容易解决。 -

                    -
                      -
                    • - 1 - - 如果您在应用程序中使用了 Assets 选项,请确保您的项目嵌入资源目录中有 index.html 文件。 -
                      - 查看示例 ➜ -
                      -//go:embed all:frontend/dist -var assets embed.FS - -func main() { - // ... - app := application.New(application.Options{ - // ... - Assets: application.AssetOptions{ - Handler: application.AssetFileServerFS(assets), - }, - }) - // ... -} -
                      -
                      -
                      -
                    • -
                    • - 2 - 如果文件应该存在但不存在,请验证您的构建过程是否配置正确,以确保 HTML 文件包含在嵌入资源目录中。 -
                    • -
                    • - 3 - - 另一种解决方案是在 WebviewWindow 选项中使用 HTML 选项。 -
                      - 查看示例 ➜ -
                      -func main() { - - // ... - - app.NewWebviewWindowWithOptions(application.WebviewWindowOptions{ - // ... - HTML: "<h1>Hello World!<h1>", - }) - // ... -} -
                      -
                      -
                      -
                    • -
                    -
                    - -
                    - - -
                    -
                    -
                    - - -
                    -

                    需要帮助?查看我们的文档或加入我们的社区

                    -
                    -
                    - - diff --git a/v3/internal/assetserver/fallback_response_writer.go b/v3/internal/assetserver/fallback_response_writer.go deleted file mode 100644 index c26d3cc52..000000000 --- a/v3/internal/assetserver/fallback_response_writer.go +++ /dev/null @@ -1,80 +0,0 @@ -package assetserver - -import ( - "maps" - "net/http" -) - -// fallbackResponseWriter wraps a [http.ResponseWriter]. -// If the main handler returns status code 404, -// its response is discarded -// and the request is forwarded to the fallback handler. -type fallbackResponseWriter struct { - rw http.ResponseWriter - req *http.Request - fallback http.Handler - - header http.Header - headerWritten bool - complete bool -} - -// Unwrap returns the wrapped [http.ResponseWriter] for use with [http.ResponseController]. -func (fw *fallbackResponseWriter) Unwrap() http.ResponseWriter { - return fw.rw -} - -func (fw *fallbackResponseWriter) Header() http.Header { - if fw.header == nil { - // Preserve original header in case we get a 404 response. - fw.header = fw.rw.Header().Clone() - } - return fw.header -} - -func (fw *fallbackResponseWriter) Write(chunk []byte) (int, error) { - if fw.complete { - // Fallback triggered, discard further writes. - return len(chunk), nil - } - - if !fw.headerWritten { - fw.WriteHeader(http.StatusOK) - } - - return fw.rw.Write(chunk) -} - -func (fw *fallbackResponseWriter) WriteHeader(statusCode int) { - if fw.headerWritten { - return - } - fw.headerWritten = true - - if statusCode == http.StatusNotFound { - // Protect fallback header from external modifications. - if fw.header == nil { - fw.header = fw.rw.Header().Clone() - } - - // Invoke fallback handler. - fw.complete = true - fw.fallback.ServeHTTP(fw.rw, fw.req) - return - } - - if fw.header != nil { - // Apply headers and forward original map to the main handler. - maps.Copy(fw.rw.Header(), fw.header) - fw.header = fw.rw.Header() - } - - fw.rw.WriteHeader(statusCode) -} - -// Flush implements the http.Flusher interface. -func (rw *fallbackResponseWriter) Flush() { - if f, ok := rw.rw.(http.Flusher); ok { - f.Flush() - } -} diff --git a/v3/internal/assetserver/fs.go b/v3/internal/assetserver/fs.go deleted file mode 100644 index 20ccf3fab..000000000 --- a/v3/internal/assetserver/fs.go +++ /dev/null @@ -1,76 +0,0 @@ -package assetserver - -import ( - "embed" - "errors" - "fmt" - "io/fs" - "os" - "path/filepath" - "strings" -) - -// findEmbedRootPath finds the root path in the embed FS. It's the directory which contains all the files. -func findEmbedRootPath(fileSystem embed.FS) (string, error) { - stopErr := errors.New("files or multiple dirs found") - - fPath := "" - err := fs.WalkDir(fileSystem, ".", func(path string, d fs.DirEntry, err error) error { - if err != nil { - return err - } - - if d.IsDir() { - fPath = path - if entries, dErr := fs.ReadDir(fileSystem, path); dErr != nil { - return dErr - } else if len(entries) <= 1 { - return nil - } - } - - return stopErr - }) - - if err != nil && !errors.Is(err, stopErr) { - return "", err - } - - return fPath, nil -} - -func findPathToFile(fileSystem fs.FS, file string) (string, error) { - stat, _ := fs.Stat(fileSystem, file) - if stat != nil { - return ".", nil - } - var indexFiles []string - err := fs.WalkDir(fileSystem, ".", func(path string, d fs.DirEntry, err error) error { - if err != nil { - return err - } - if strings.HasSuffix(path, file) { - indexFiles = append(indexFiles, path) - } - return nil - }) - if err != nil { - return "", err - } - - if len(indexFiles) > 1 { - selected := indexFiles[0] - for _, f := range indexFiles { - if len(f) < len(selected) { - selected = f - } - } - path, _ := filepath.Split(selected) - return path, nil - } - if len(indexFiles) > 0 { - path, _ := filepath.Split(indexFiles[0]) - return path, nil - } - return "", fmt.Errorf("%s: %w", file, os.ErrNotExist) -} diff --git a/v3/internal/assetserver/middleware.go b/v3/internal/assetserver/middleware.go deleted file mode 100644 index b3826ab7d..000000000 --- a/v3/internal/assetserver/middleware.go +++ /dev/null @@ -1,20 +0,0 @@ -package assetserver - -import ( - "net/http" -) - -// Middleware defines a HTTP middleware that can be applied to the AssetServer. -// The handler passed as next is the next handler in the chain. One can decide to call the next handler -// or implement a specialized handling. -type Middleware func(next http.Handler) http.Handler - -// ChainMiddleware allows chaining multiple middlewares to one middleware. -func ChainMiddleware(middleware ...Middleware) Middleware { - return func(h http.Handler) http.Handler { - for i := len(middleware) - 1; i >= 0; i-- { - h = middleware[i](h) - } - return h - } -} diff --git a/v3/internal/assetserver/mimecache.go b/v3/internal/assetserver/mimecache.go deleted file mode 100644 index 9034a4a0f..000000000 --- a/v3/internal/assetserver/mimecache.go +++ /dev/null @@ -1,116 +0,0 @@ -package assetserver - -import ( - "net/http" - "path/filepath" - "sync" -) - -var ( - // mimeCache uses sync.Map for better concurrent read performance - // since reads are far more common than writes - mimeCache sync.Map - - // mimeTypesByExt maps file extensions to MIME types for common web formats. - // This approach is preferred over content-based detection because: - // 1. Extension-based lookup is O(1) vs O(n) content scanning - // 2. Web assets typically have correct extensions - // 3. stdlib's http.DetectContentType handles remaining cases adequately - // 4. Saves ~208KB binary size by not using github.com/wailsapp/mimetype - mimeTypesByExt = map[string]string{ - // HTML - ".htm": "text/html; charset=utf-8", - ".html": "text/html; charset=utf-8", - - // CSS/JS - ".css": "text/css; charset=utf-8", - ".js": "text/javascript; charset=utf-8", - ".mjs": "text/javascript; charset=utf-8", - ".ts": "application/x-typescript; charset=utf-8", - ".tsx": "application/x-typescript; charset=utf-8", - ".jsx": "text/javascript; charset=utf-8", - - // Data formats - ".json": "application/json", - ".xml": "text/xml; charset=utf-8", - ".yaml": "text/yaml; charset=utf-8", - ".yml": "text/yaml; charset=utf-8", - ".toml": "text/toml; charset=utf-8", - - // Images - ".png": "image/png", - ".jpg": "image/jpeg", - ".jpeg": "image/jpeg", - ".gif": "image/gif", - ".webp": "image/webp", - ".avif": "image/avif", - ".svg": "image/svg+xml", - ".ico": "image/x-icon", - ".bmp": "image/bmp", - ".tiff": "image/tiff", - ".tif": "image/tiff", - - // Fonts - ".woff": "font/woff", - ".woff2": "font/woff2", - ".ttf": "font/ttf", - ".otf": "font/otf", - ".eot": "application/vnd.ms-fontobject", - - // Audio - ".mp3": "audio/mpeg", - ".wav": "audio/wav", - ".ogg": "audio/ogg", - ".m4a": "audio/mp4", - ".aac": "audio/aac", - ".flac": "audio/flac", - ".opus": "audio/opus", - - // Video - ".mp4": "video/mp4", - ".webm": "video/webm", - ".ogv": "video/ogg", - ".mov": "video/quicktime", - ".avi": "video/x-msvideo", - ".mkv": "video/x-matroska", - ".m4v": "video/mp4", - - // Documents - ".pdf": "application/pdf", - ".txt": "text/plain; charset=utf-8", - ".md": "text/markdown; charset=utf-8", - - // Archives - ".zip": "application/zip", - ".gz": "application/gzip", - ".tar": "application/x-tar", - - // WebAssembly - ".wasm": "application/wasm", - - // Source maps - ".map": "application/json", - } -) - -// "application/octet-stream". -func GetMimetype(filename string, data []byte) string { - // Fast path: check extension map first (no lock needed) - if result := mimeTypesByExt[filepath.Ext(filename)]; result != "" { - return result - } - - // Check cache (lock-free read) - if cached, ok := mimeCache.Load(filename); ok { - return cached.(string) - } - - // Slow path: use stdlib content-based detection and cache - result := http.DetectContentType(data) - if result == "" { - result = "application/octet-stream" - } - - mimeCache.Store(filename, result) - return result -} \ No newline at end of file diff --git a/v3/internal/assetserver/mimecache_test.go b/v3/internal/assetserver/mimecache_test.go deleted file mode 100644 index 48e5943fa..000000000 --- a/v3/internal/assetserver/mimecache_test.go +++ /dev/null @@ -1,46 +0,0 @@ -package assetserver - -import ( - "testing" -) - -func TestGetMimetype(t *testing.T) { - type args struct { - filename string - data []byte - } - bomUTF8 := []byte{0xef, 0xbb, 0xbf} - var emptyMsg []byte - css := []byte("body{margin:0;padding:0;background-color:#d579b2}#app{font-family:Avenir,Helvetica,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;text-align:center;color:#2c3e50;background-color:#ededed}#nav{padding:30px}#nav a{font-weight:700;color:#2c\n3e50}#nav a.router-link-exact-active{color:#42b983}.hello[data-v-4e26ad49]{margin:10px 0}") - html := []byte("title") - bomHtml := append(bomUTF8, html...) - svg := []byte("") - svgWithComment := append([]byte(""), svg...) - svgWithCommentAndControlChars := append([]byte(" \r\n "), svgWithComment...) - svgWithBomCommentAndControlChars := append(bomUTF8, append([]byte(" \r\n "), svgWithComment...)...) - - tests := []struct { - name string - args args - want string - }{ - {"nil data", args{"nil.svg", nil}, "image/svg+xml"}, - {"empty data", args{"empty.html", emptyMsg}, "text/html; charset=utf-8"}, - {"css", args{"test.css", css}, "text/css; charset=utf-8"}, - {"js", args{"test.js", []byte("let foo = 'bar'; console.log(foo);")}, "text/javascript; charset=utf-8"}, - {"mjs", args{"test.mjs", []byte("let foo = 'bar'; console.log(foo);")}, "text/javascript; charset=utf-8"}, - {"html-utf8", args{"test_utf8.html", html}, "text/html; charset=utf-8"}, - {"html-bom-utf8", args{"test_bom_utf8.html", bomHtml}, "text/html; charset=utf-8"}, - {"svg", args{"test.svg", svg}, "image/svg+xml"}, - {"svg-w-comment", args{"test_comment.svg", svgWithComment}, "image/svg+xml"}, - {"svg-w-control-comment", args{"test_control_comment.svg", svgWithCommentAndControlChars}, "image/svg+xml"}, - {"svg-w-bom-control-comment", args{"test_bom_control_comment.svg", svgWithBomCommentAndControlChars}, "image/svg+xml"}, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - if got := GetMimetype(tt.args.filename, tt.args.data); got != tt.want { - t.Errorf("GetMimetype() = '%v', want '%v'", got, tt.want) - } - }) - } -} diff --git a/v3/internal/assetserver/mimetype_stdlib_test.go b/v3/internal/assetserver/mimetype_stdlib_test.go deleted file mode 100644 index 18a20131d..000000000 --- a/v3/internal/assetserver/mimetype_stdlib_test.go +++ /dev/null @@ -1,277 +0,0 @@ -package assetserver - -import ( - "net/http" - "path/filepath" - "strings" - "testing" -) - -// TestMimeTypeDetection_WebFormats validates that extension-based detection -// plus stdlib fallback correctly handles all common web asset formats. -// This test ensures we can safely remove the github.com/wailsapp/mimetype dependency. -func TestMimeTypeDetection_WebFormats(t *testing.T) { - // webMimeTests covers all common web formats that Wails applications typically serve - webMimeTests := []struct { - name string - filename string - data []byte - wantPrefix string // Use prefix matching since charset may vary - }{ - // === TEXT FORMATS (extension-based) === - {"HTML file", "index.html", []byte(""), "text/html"}, - {"HTM file", "page.htm", []byte(""), "text/html"}, - {"CSS file", "styles.css", []byte(".class { color: red; }"), "text/css"}, - {"JavaScript file", "app.js", []byte("function test() {}"), "text/javascript"}, - {"ES Module file", "module.mjs", []byte("export default {}"), "text/javascript"}, - {"JSON file", "data.json", []byte(`{"key": "value"}`), "application/json"}, - {"XML file", "data.xml", []byte(""), "text/xml"}, - - // === IMAGE FORMATS (extension-based) === - {"PNG file", "image.png", pngData, "image/png"}, - {"JPEG file", "photo.jpg", jpegData, "image/jpeg"}, - {"JPEG alt ext", "photo.jpeg", jpegData, "image/jpeg"}, - {"GIF file", "anim.gif", gifData, "image/gif"}, - {"WebP file", "image.webp", webpData, "image/webp"}, - {"AVIF file", "image.avif", avifData, "image/avif"}, - {"SVG file", "icon.svg", []byte(""), "image/svg+xml"}, - {"PDF file", "doc.pdf", pdfData, "application/pdf"}, - - // === WASM (extension-based) === - {"WASM file", "app.wasm", wasmData, "application/wasm"}, - - // === FONT FORMATS (need detection or extension map) === - {"WOFF file", "font.woff", woffData, "font/woff"}, - {"WOFF2 file", "font.woff2", woff2Data, "font/woff2"}, - {"TTF file", "font.ttf", ttfData, "font/ttf"}, - {"OTF file", "font.otf", otfData, "font/otf"}, - {"EOT file", "font.eot", eotData, "application/vnd.ms-fontobject"}, - - // === AUDIO/VIDEO (common web formats) === - {"MP3 file", "audio.mp3", mp3Data, "audio/mpeg"}, - {"MP4 file", "video.mp4", mp4Data, "video/mp4"}, - {"WebM file", "video.webm", webmData, "video/webm"}, - {"OGG file", "audio.ogg", oggData, "audio/ogg"}, - - // === ARCHIVES (sometimes served by web apps) === - {"ZIP file", "archive.zip", zipData, "application/zip"}, - {"GZIP file", "data.gz", gzipData, "application/"}, - - // === SOURCE MAPS (common in dev mode) === - {"Source map", "app.js.map", []byte(`{"version":3}`), "application/json"}, - - // === ICO (favicon) === - {"ICO file", "favicon.ico", icoData, "image/"}, - - // === FALLBACK TESTS === - {"Unknown binary", "data.bin", []byte{0x00, 0x01, 0x02, 0x03}, "application/octet-stream"}, - {"Plain text (no ext)", "readme", []byte("Hello World"), "text/plain"}, - } - - for _, tt := range webMimeTests { - t.Run(tt.name, func(t *testing.T) { - got := getMimeTypeStdlib(tt.filename, tt.data) - if !hasPrefix(got, tt.wantPrefix) { - t.Errorf("getMimeTypeStdlib(%q) = %q, want prefix %q", tt.filename, got, tt.wantPrefix) - } - }) - } -} - -// getMimeTypeStdlib is the proposed replacement that uses only stdlib -func getMimeTypeStdlib(filename string, data []byte) string { - // Fast path: check extension map first - if result := extMimeTypes[filepath.Ext(filename)]; result != "" { - return result - } - - // Fallback to stdlib content-based detection - result := http.DetectContentType(data) - if result == "" { - result = "application/octet-stream" - } - return result -} - -// extMimeTypes is an expanded map covering all common web formats -// This replaces the need for the mimetype library for web assets -var extMimeTypes = map[string]string{ - // HTML - ".htm": "text/html; charset=utf-8", - ".html": "text/html; charset=utf-8", - - // CSS/JS - ".css": "text/css; charset=utf-8", - ".js": "text/javascript; charset=utf-8", - ".mjs": "text/javascript; charset=utf-8", - ".ts": "application/x-typescript; charset=utf-8", - ".tsx": "application/x-typescript; charset=utf-8", - ".jsx": "text/javascript; charset=utf-8", - - // Data formats - ".json": "application/json", - ".xml": "text/xml; charset=utf-8", - ".yaml": "text/yaml; charset=utf-8", - ".yml": "text/yaml; charset=utf-8", - ".toml": "text/toml; charset=utf-8", - - // Images - ".png": "image/png", - ".jpg": "image/jpeg", - ".jpeg": "image/jpeg", - ".gif": "image/gif", - ".webp": "image/webp", - ".avif": "image/avif", - ".svg": "image/svg+xml", - ".ico": "image/x-icon", - ".bmp": "image/bmp", - ".tiff": "image/tiff", - ".tif": "image/tiff", - - // Fonts - ".woff": "font/woff", - ".woff2": "font/woff2", - ".ttf": "font/ttf", - ".otf": "font/otf", - ".eot": "application/vnd.ms-fontobject", - - // Audio - ".mp3": "audio/mpeg", - ".wav": "audio/wav", - ".ogg": "audio/ogg", - ".m4a": "audio/mp4", - ".aac": "audio/aac", - ".flac": "audio/flac", - ".opus": "audio/opus", - - // Video - ".mp4": "video/mp4", - ".webm": "video/webm", - ".ogv": "video/ogg", - ".mov": "video/quicktime", - ".avi": "video/x-msvideo", - ".mkv": "video/x-matroska", - ".m4v": "video/mp4", - - // Documents - ".pdf": "application/pdf", - ".txt": "text/plain; charset=utf-8", - ".md": "text/markdown; charset=utf-8", - - // Archives - ".zip": "application/zip", - ".gz": "application/gzip", - ".tar": "application/x-tar", - - // WebAssembly - ".wasm": "application/wasm", - - // Source maps - ".map": "application/json", -} - -func hasPrefix(s, prefix string) bool { - return len(s) >= len(prefix) && s[:len(prefix)] == prefix -} - -// Magic bytes for various formats -var ( - // PNG: 89 50 4E 47 0D 0A 1A 0A - pngData = []byte{0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A, 0x00, 0x00, 0x00, 0x0D} - - // JPEG: FF D8 FF - jpegData = []byte{0xFF, 0xD8, 0xFF, 0xE0, 0x00, 0x10, 0x4A, 0x46, 0x49, 0x46} - - // GIF: 47 49 46 38 - gifData = []byte{0x47, 0x49, 0x46, 0x38, 0x39, 0x61} - - // WebP: 52 49 46 46 ... 57 45 42 50 - webpData = []byte{0x52, 0x49, 0x46, 0x46, 0x00, 0x00, 0x00, 0x00, 0x57, 0x45, 0x42, 0x50} - - // AVIF: ... ftypavif or ftypavis - avifData = []byte{0x00, 0x00, 0x00, 0x1C, 0x66, 0x74, 0x79, 0x70, 0x61, 0x76, 0x69, 0x66} - - // PDF: 25 50 44 46 - pdfData = []byte{0x25, 0x50, 0x44, 0x46, 0x2D, 0x31, 0x2E} - - // WASM: 00 61 73 6D - wasmData = []byte{0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00} - - // WOFF: 77 4F 46 46 - woffData = []byte{0x77, 0x4F, 0x46, 0x46, 0x00, 0x01, 0x00, 0x00} - - // WOFF2: 77 4F 46 32 - woff2Data = []byte{0x77, 0x4F, 0x46, 0x32, 0x00, 0x01, 0x00, 0x00} - - // TTF: 00 01 00 00 - ttfData = []byte{0x00, 0x01, 0x00, 0x00, 0x00} - - // OTF: 4F 54 54 4F (OTTO) - otfData = []byte{0x4F, 0x54, 0x54, 0x4F, 0x00} - - // EOT: varies, but starts with size bytes then magic - eotData = []byte{0x00, 0x00, 0x01, 0x00, 0x00, 0x00} - - // MP3: FF FB or FF FA or ID3 - mp3Data = []byte{0xFF, 0xFB, 0x90, 0x00} - - // MP4: ... ftyp - mp4Data = []byte{0x00, 0x00, 0x00, 0x1C, 0x66, 0x74, 0x79, 0x70, 0x69, 0x73, 0x6F, 0x6D} - - // WebM: 1A 45 DF A3 (EBML header) - webmData = []byte{0x1A, 0x45, 0xDF, 0xA3} - - // OGG: 4F 67 67 53 - oggData = []byte{0x4F, 0x67, 0x67, 0x53, 0x00, 0x02} - - // ZIP: 50 4B 03 04 - zipData = []byte{0x50, 0x4B, 0x03, 0x04} - - // GZIP: 1F 8B - gzipData = []byte{0x1F, 0x8B, 0x08} - - // ICO: 00 00 01 00 - icoData = []byte{0x00, 0x00, 0x01, 0x00, 0x01, 0x00} -) - -// TestMimeTypeExtensionMapCompleteness checks that all extensions in the -// original mimeTypesByExt are covered by the expanded extMimeTypes -func TestMimeTypeExtensionMapCompleteness(t *testing.T) { - for ext, mime := range mimeTypesByExt { - if newMime, ok := extMimeTypes[ext]; !ok { - t.Errorf("extension %q missing from extMimeTypes (was: %q)", ext, mime) - } else if newMime != mime { - // Allow differences as long as they're equivalent (compare base MIME type) - mimeBase := mime - if idx := strings.Index(mime, ";"); idx > 0 { - mimeBase = mime[:idx] - } - if !hasPrefix(newMime, mimeBase) { - t.Logf("extension %q changed: %q -> %q (verify this is correct)", ext, mime, newMime) - } - } - } -} - -// BenchmarkMimeType_StdlibOnly benchmarks the stdlib-only implementation -func BenchmarkMimeType_StdlibOnly(b *testing.B) { - testCases := []struct { - name string - filename string - data []byte - }{ - {"ExtHit_JS", "app.js", []byte("function() {}")}, - {"ExtHit_CSS", "styles.css", []byte(".class { }")}, - {"ExtHit_PNG", "image.png", pngData}, - {"ExtMiss_Binary", "data.bin", []byte{0x00, 0x01, 0x02}}, - {"ContentDetect_PNG", "unknown", pngData}, - } - - for _, tc := range testCases { - b.Run(tc.name, func(b *testing.B) { - for b.Loop() { - _ = getMimeTypeStdlib(tc.filename, tc.data) - } - }) - } -} diff --git a/v3/internal/assetserver/options.go b/v3/internal/assetserver/options.go deleted file mode 100644 index ae0570880..000000000 --- a/v3/internal/assetserver/options.go +++ /dev/null @@ -1,38 +0,0 @@ -package assetserver - -import ( - "errors" - "log/slog" - "net/http" -) - -// Options defines the configuration of the AssetServer. -type Options struct { - // Handler which serves all the content to the WebView. - Handler http.Handler - - // Middleware is a HTTP Middleware which allows to hook into the AssetServer request chain. It allows to skip the default - // request handler dynamically, e.g. implement specialized Routing etc. - // The Middleware is called to build a new `http.Handler` used by the AssetSever and it also receives the default - // handler used by the AssetServer as an argument. - // - // This middleware injects itself before any of Wails internal middlewares. - // - // If not defined, the default AssetServer request chain is executed. - // - // Multiple Middlewares can be chained together with: - // ChainMiddleware(middleware ...Middleware) Middleware - Middleware Middleware - - // Logger is the logger used by the AssetServer. If not defined, no logging will be done. - Logger *slog.Logger -} - -// Validate the options -func (o Options) Validate() error { - if o.Handler == nil && o.Middleware == nil { - return errors.New("AssetServer options invalid: either Handler or Middleware must be set") - } - - return nil -} diff --git a/v3/internal/assetserver/ringqueue.go b/v3/internal/assetserver/ringqueue.go deleted file mode 100644 index b94e7cd5c..000000000 --- a/v3/internal/assetserver/ringqueue.go +++ /dev/null @@ -1,101 +0,0 @@ -// Code from https://github.com/erikdubbelboer/ringqueue -/* -The MIT License (MIT) - -Copyright (c) 2015 Erik Dubbelboer - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. -*/ -package assetserver - -type ringqueue[T any] struct { - nodes []T - head int - tail int - cnt int - - minSize int -} - -func newRingqueue[T any](minSize uint) *ringqueue[T] { - if minSize < 2 { - minSize = 2 - } - return &ringqueue[T]{ - nodes: make([]T, minSize), - minSize: int(minSize), - } -} - -func (q *ringqueue[T]) resize(n int) { - nodes := make([]T, n) - if q.head < q.tail { - copy(nodes, q.nodes[q.head:q.tail]) - } else { - copy(nodes, q.nodes[q.head:]) - copy(nodes[len(q.nodes)-q.head:], q.nodes[:q.tail]) - } - - q.tail = q.cnt % n - q.head = 0 - q.nodes = nodes -} - -func (q *ringqueue[T]) Add(i T) { - if q.cnt == len(q.nodes) { - // Also tested a grow rate of 1.5, see: http://stackoverflow.com/questions/2269063/buffer-growth-strategy - // In Go this resulted in a higher memory usage. - q.resize(q.cnt * 2) - } - q.nodes[q.tail] = i - q.tail = (q.tail + 1) % len(q.nodes) - q.cnt++ -} - -func (q *ringqueue[T]) Peek() (T, bool) { - if q.cnt == 0 { - var none T - return none, false - } - return q.nodes[q.head], true -} - -func (q *ringqueue[T]) Remove() (T, bool) { - if q.cnt == 0 { - var none T - return none, false - } - i := q.nodes[q.head] - q.head = (q.head + 1) % len(q.nodes) - q.cnt-- - - if n := len(q.nodes) / 2; n > q.minSize && q.cnt <= n { - q.resize(n) - } - - return i, true -} - -func (q *ringqueue[T]) Cap() int { - return cap(q.nodes) -} - -func (q *ringqueue[T]) Len() int { - return q.cnt -} diff --git a/v3/internal/assetserver/webview/request.go b/v3/internal/assetserver/webview/request.go deleted file mode 100644 index 18ff29890..000000000 --- a/v3/internal/assetserver/webview/request.go +++ /dev/null @@ -1,17 +0,0 @@ -package webview - -import ( - "io" - "net/http" -) - -type Request interface { - URL() (string, error) - Method() (string, error) - Header() (http.Header, error) - Body() (io.ReadCloser, error) - - Response() ResponseWriter - - Close() error -} diff --git a/v3/internal/assetserver/webview/request_android.go b/v3/internal/assetserver/webview/request_android.go deleted file mode 100644 index aabe2aacb..000000000 --- a/v3/internal/assetserver/webview/request_android.go +++ /dev/null @@ -1,102 +0,0 @@ -//go:build android - -package webview - -import ( - "bytes" - "io" - "net/http" -) - -// Request interface for Android asset requests -// On Android, requests are handled via JNI from Java's WebViewAssetLoader - -// androidRequest implements the Request interface for Android -type androidRequest struct { - url string - method string - headers http.Header - body io.ReadCloser - rw *androidResponseWriter -} - -// NewRequestFromJNI creates a new request from JNI parameters -func NewRequestFromJNI(url string, method string, headersJSON string) Request { - return &androidRequest{ - url: url, - method: method, - headers: http.Header{}, - body: http.NoBody, - } -} - -func (r *androidRequest) URL() (string, error) { - return r.url, nil -} - -func (r *androidRequest) Method() (string, error) { - return r.method, nil -} - -func (r *androidRequest) Header() (http.Header, error) { - return r.headers, nil -} - -func (r *androidRequest) Body() (io.ReadCloser, error) { - return r.body, nil -} - -func (r *androidRequest) Response() ResponseWriter { - if r.rw == nil { - r.rw = &androidResponseWriter{} - } - return r.rw -} - -func (r *androidRequest) Close() error { - if r.body != nil { - return r.body.Close() - } - return nil -} - -// androidResponseWriter implements ResponseWriter for Android -type androidResponseWriter struct { - statusCode int - headers http.Header - body bytes.Buffer - finished bool -} - -func (w *androidResponseWriter) Header() http.Header { - if w.headers == nil { - w.headers = http.Header{} - } - return w.headers -} - -func (w *androidResponseWriter) Write(data []byte) (int, error) { - return w.body.Write(data) -} - -func (w *androidResponseWriter) WriteHeader(statusCode int) { - w.statusCode = statusCode -} - -func (w *androidResponseWriter) Finish() error { - w.finished = true - return nil -} - -// Code returns the HTTP status code of the response -func (w *androidResponseWriter) Code() int { - if w.statusCode == 0 { - return 200 - } - return w.statusCode -} - -// GetResponseData returns the response data for JNI -func (w *androidResponseWriter) GetResponseData() []byte { - return w.body.Bytes() -} diff --git a/v3/internal/assetserver/webview/request_darwin.go b/v3/internal/assetserver/webview/request_darwin.go deleted file mode 100644 index dd2d0232a..000000000 --- a/v3/internal/assetserver/webview/request_darwin.go +++ /dev/null @@ -1,250 +0,0 @@ -//go:build darwin && !ios - -package webview - -/* -#cgo CFLAGS: -x objective-c -#cgo LDFLAGS: -framework Foundation -framework WebKit - -#import -#import -#include - -static void URLSchemeTaskRetain(void *wkUrlSchemeTask) { - id urlSchemeTask = (id) wkUrlSchemeTask; - [urlSchemeTask retain]; -} - -static void URLSchemeTaskRelease(void *wkUrlSchemeTask) { - id urlSchemeTask = (id) wkUrlSchemeTask; - [urlSchemeTask release]; -} - -static const char * URLSchemeTaskRequestURL(void *wkUrlSchemeTask) { - id urlSchemeTask = (id) wkUrlSchemeTask; - @autoreleasepool { - return [urlSchemeTask.request.URL.absoluteString UTF8String]; - } -} - -static const char * URLSchemeTaskRequestMethod(void *wkUrlSchemeTask) { - id urlSchemeTask = (id) wkUrlSchemeTask; - @autoreleasepool { - return [urlSchemeTask.request.HTTPMethod UTF8String]; - } -} - -static const char * URLSchemeTaskRequestHeadersJSON(void *wkUrlSchemeTask) { - id urlSchemeTask = (id) wkUrlSchemeTask; - @autoreleasepool { - NSData *headerData = [NSJSONSerialization dataWithJSONObject: urlSchemeTask.request.allHTTPHeaderFields options:0 error: nil]; - if (!headerData) { - return nil; - } - - NSString* headerString = [[[NSString alloc] initWithData:headerData encoding:NSUTF8StringEncoding] autorelease]; - const char * headerJSON = [headerString UTF8String]; - - return strdup(headerJSON); - } -} - -static bool URLSchemeTaskRequestBodyBytes(void *wkUrlSchemeTask, const void **body, int *bodyLen) { - id urlSchemeTask = (id) wkUrlSchemeTask; - @autoreleasepool { - if (!urlSchemeTask.request.HTTPBody) { - return false; - } - - *body = urlSchemeTask.request.HTTPBody.bytes; - *bodyLen = urlSchemeTask.request.HTTPBody.length; - return true; - } -} - -static bool URLSchemeTaskRequestBodyStreamOpen(void *wkUrlSchemeTask) { - id urlSchemeTask = (id) wkUrlSchemeTask; - @autoreleasepool { - if (!urlSchemeTask.request.HTTPBodyStream) { - return false; - } - - [urlSchemeTask.request.HTTPBodyStream open]; - return true; - } -} - -static void URLSchemeTaskRequestBodyStreamClose(void *wkUrlSchemeTask) { - id urlSchemeTask = (id) wkUrlSchemeTask; - @autoreleasepool { - if (!urlSchemeTask.request.HTTPBodyStream) { - return; - } - - [urlSchemeTask.request.HTTPBodyStream close]; - } -} - -static int URLSchemeTaskRequestBodyStreamRead(void *wkUrlSchemeTask, void *buf, int bufLen) { - id urlSchemeTask = (id) wkUrlSchemeTask; - - @autoreleasepool { - NSInputStream *stream = urlSchemeTask.request.HTTPBodyStream; - if (!stream) { - return -2; - } - - NSStreamStatus status = stream.streamStatus; - if (status == NSStreamStatusAtEnd || !stream.hasBytesAvailable) { - return 0; - } else if (status != NSStreamStatusOpen) { - return -3; - } - - return [stream read:buf maxLength:bufLen]; - } -} -*/ -import "C" - -import ( - "bytes" - "errors" - "fmt" - "io" - "net/http" - "unsafe" - - "encoding/json" -) - -// NewRequest creates as new WebViewRequest based on a pointer to an `id` -func NewRequest(wkURLSchemeTask unsafe.Pointer) Request { - C.URLSchemeTaskRetain(wkURLSchemeTask) - return newRequestFinalizer(&request{task: wkURLSchemeTask}) -} - -var _ Request = &request{} - -type request struct { - task unsafe.Pointer - - header http.Header - body io.ReadCloser - rw *responseWriter -} - -func (r *request) URL() (string, error) { - return C.GoString(C.URLSchemeTaskRequestURL(r.task)), nil -} - -func (r *request) Method() (string, error) { - return C.GoString(C.URLSchemeTaskRequestMethod(r.task)), nil -} - -func (r *request) Header() (http.Header, error) { - if r.header != nil { - return r.header, nil - } - - header := http.Header{} - if cHeaders := C.URLSchemeTaskRequestHeadersJSON(r.task); cHeaders != nil { - if headers := C.GoString(cHeaders); headers != "" { - var h map[string]string - if err := json.Unmarshal([]byte(headers), &h); err != nil { - return nil, fmt.Errorf("unable to unmarshal request headers: %s", err) - } - - for k, v := range h { - header.Add(k, v) - } - } - C.free(unsafe.Pointer(cHeaders)) - } - r.header = header - return header, nil -} - -func (r *request) Body() (io.ReadCloser, error) { - if r.body != nil { - return r.body, nil - } - - var body unsafe.Pointer - var bodyLen C.int - if C.URLSchemeTaskRequestBodyBytes(r.task, &body, &bodyLen) { - if body != nil && bodyLen > 0 { - r.body = io.NopCloser(bytes.NewReader(C.GoBytes(body, bodyLen))) - } else { - r.body = http.NoBody - } - } else if C.URLSchemeTaskRequestBodyStreamOpen(r.task) { - r.body = &requestBodyStreamReader{task: r.task} - } - - return r.body, nil -} - -func (r *request) Response() ResponseWriter { - if r.rw != nil { - return r.rw - } - - r.rw = &responseWriter{r: r} - return r.rw -} - -func (r *request) Close() error { - var err error - if r.body != nil { - err = r.body.Close() - } - r.Response().Finish() - C.URLSchemeTaskRelease(r.task) - return err -} - -var _ io.ReadCloser = &requestBodyStreamReader{} - -type requestBodyStreamReader struct { - task unsafe.Pointer - closed bool -} - -// Read implements io.Reader -func (r *requestBodyStreamReader) Read(p []byte) (n int, err error) { - var content unsafe.Pointer - var contentLen int - if p != nil { - content = unsafe.Pointer(&p[0]) - contentLen = len(p) - } - - res := C.URLSchemeTaskRequestBodyStreamRead(r.task, content, C.int(contentLen)) - if res > 0 { - return int(res), nil - } - - switch res { - case 0: - return 0, io.EOF - case -1: - return 0, errors.New("body: stream error") - case -2: - return 0, errors.New("body: no stream defined") - case -3: - return 0, io.ErrClosedPipe - default: - return 0, fmt.Errorf("body: unknown error %d", res) - } -} - -func (r *requestBodyStreamReader) Close() error { - if r.closed { - return nil - } - r.closed = true - - C.URLSchemeTaskRequestBodyStreamClose(r.task) - return nil -} diff --git a/v3/internal/assetserver/webview/request_finalizer.go b/v3/internal/assetserver/webview/request_finalizer.go deleted file mode 100644 index 6a8c6a928..000000000 --- a/v3/internal/assetserver/webview/request_finalizer.go +++ /dev/null @@ -1,40 +0,0 @@ -package webview - -import ( - "runtime" - "sync/atomic" -) - -var _ Request = &requestFinalizer{} - -type requestFinalizer struct { - Request - closed int32 -} - -// newRequestFinalizer returns a request with a runtime finalizer to make sure it will be closed from the finalizer -// if it has not been already closed. -// It also makes sure Close() of the wrapping request is only called once. -func newRequestFinalizer(r Request) Request { - rf := &requestFinalizer{Request: r} - // Make sure to async release since it might block the finalizer goroutine for a longer period - runtime.SetFinalizer(rf, func(obj *requestFinalizer) { rf.close(true) }) - return rf -} - -func (r *requestFinalizer) Close() error { - return r.close(false) -} - -func (r *requestFinalizer) close(asyncRelease bool) error { - if atomic.CompareAndSwapInt32(&r.closed, 0, 1) { - runtime.SetFinalizer(r, nil) - if asyncRelease { - go r.Request.Close() - return nil - } else { - return r.Request.Close() - } - } - return nil -} diff --git a/v3/internal/assetserver/webview/request_ios.go b/v3/internal/assetserver/webview/request_ios.go deleted file mode 100644 index 81d23b0bc..000000000 --- a/v3/internal/assetserver/webview/request_ios.go +++ /dev/null @@ -1,248 +0,0 @@ -//go:build ios - -package webview - -/* -#cgo CFLAGS: -x objective-c -fobjc-arc -#cgo LDFLAGS: -framework Foundation -framework WebKit -framework CoreFoundation - -#import -#import -#import -#include - -static void URLSchemeTaskRetain(void *wkUrlSchemeTask) { - id urlSchemeTask = (__bridge id) wkUrlSchemeTask; - CFRetain((CFTypeRef)urlSchemeTask); -} - -static void URLSchemeTaskRelease(void *wkUrlSchemeTask) { - id urlSchemeTask = (__bridge id) wkUrlSchemeTask; - CFRelease((CFTypeRef)urlSchemeTask); -} - -static const char * URLSchemeTaskRequestURL(void *wkUrlSchemeTask) { - id urlSchemeTask = (__bridge id) wkUrlSchemeTask; - @autoreleasepool { - return [urlSchemeTask.request.URL.absoluteString UTF8String]; - } -} - -static const char * URLSchemeTaskRequestMethod(void *wkUrlSchemeTask) { - id urlSchemeTask = (__bridge id) wkUrlSchemeTask; - @autoreleasepool { - return [urlSchemeTask.request.HTTPMethod UTF8String]; - } -} - -static const char * URLSchemeTaskRequestHeadersJSON(void *wkUrlSchemeTask) { - id urlSchemeTask = (__bridge id) wkUrlSchemeTask; - @autoreleasepool { - NSData *headerData = [NSJSONSerialization dataWithJSONObject:urlSchemeTask.request.allHTTPHeaderFields options:0 error:nil]; - if (!headerData) { - return nil; - } - NSString *headerString = [[NSString alloc] initWithData:headerData encoding:NSUTF8StringEncoding]; - const char *headerJSON = [headerString UTF8String]; - return strdup(headerJSON); - } -} - -static bool URLSchemeTaskRequestBodyBytes(void *wkUrlSchemeTask, const void **body, int *bodyLen) { - id urlSchemeTask = (__bridge id) wkUrlSchemeTask; - @autoreleasepool { - if (!urlSchemeTask.request.HTTPBody) { - return false; - } - *body = urlSchemeTask.request.HTTPBody.bytes; - *bodyLen = urlSchemeTask.request.HTTPBody.length; - return true; - } -} - -static bool URLSchemeTaskRequestBodyStreamOpen(void *wkUrlSchemeTask) { - id urlSchemeTask = (__bridge id) wkUrlSchemeTask; - @autoreleasepool { - if (!urlSchemeTask.request.HTTPBodyStream) { - return false; - } - - [urlSchemeTask.request.HTTPBodyStream open]; - return true; - } -} - -static void URLSchemeTaskRequestBodyStreamClose(void *wkUrlSchemeTask) { - id urlSchemeTask = (__bridge id) wkUrlSchemeTask; - @autoreleasepool { - if (!urlSchemeTask.request.HTTPBodyStream) { - return; - } - - [urlSchemeTask.request.HTTPBodyStream close]; - } -} - -static int URLSchemeTaskRequestBodyStreamRead(void *wkUrlSchemeTask, void *buf, int bufLen) { - id urlSchemeTask = (__bridge id) wkUrlSchemeTask; - - @autoreleasepool { - NSInputStream *stream = urlSchemeTask.request.HTTPBodyStream; - if (!stream) { - return -2; - } - - NSStreamStatus status = stream.streamStatus; - if (status == NSStreamStatusAtEnd || !stream.hasBytesAvailable) { - return 0; - } else if (status != NSStreamStatusOpen) { - return -3; - } - - return [stream read:buf maxLength:bufLen]; - } -} -*/ -import "C" - -import ( - "bytes" - "errors" - "fmt" - "io" - "net/http" - "unsafe" - - "encoding/json" -) - -// NewRequest creates as new WebViewRequest based on a pointer to an `id` -func NewRequest(wkURLSchemeTask unsafe.Pointer) Request { - C.URLSchemeTaskRetain(wkURLSchemeTask) - return newRequestFinalizer(&request{task: wkURLSchemeTask}) -} - -var _ Request = &request{} - -type request struct { - task unsafe.Pointer - - header http.Header - body io.ReadCloser - rw *responseWriter -} - -func (r *request) URL() (string, error) { - return C.GoString(C.URLSchemeTaskRequestURL(r.task)), nil -} - -func (r *request) Method() (string, error) { - return C.GoString(C.URLSchemeTaskRequestMethod(r.task)), nil -} - -func (r *request) Header() (http.Header, error) { - if r.header != nil { - return r.header, nil - } - - header := http.Header{} - if cHeaders := C.URLSchemeTaskRequestHeadersJSON(r.task); cHeaders != nil { - if headers := C.GoString(cHeaders); headers != "" { - var h map[string]string - if err := json.Unmarshal([]byte(headers), &h); err != nil { - return nil, fmt.Errorf("unable to unmarshal request headers: %s", err) - } - - for k, v := range h { - header.Add(k, v) - } - } - C.free(unsafe.Pointer(cHeaders)) - } - r.header = header - return header, nil -} - -func (r *request) Body() (io.ReadCloser, error) { - if r.body != nil { - return r.body, nil - } - - var body unsafe.Pointer - var bodyLen C.int - if C.URLSchemeTaskRequestBodyBytes(r.task, &body, &bodyLen) { - if body != nil && bodyLen > 0 { - r.body = io.NopCloser(bytes.NewReader(C.GoBytes(body, bodyLen))) - } else { - r.body = http.NoBody - } - } else if C.URLSchemeTaskRequestBodyStreamOpen(r.task) { - r.body = &requestBodyStreamReader{task: r.task} - } - - return r.body, nil -} - -func (r *request) Response() ResponseWriter { - if r.rw != nil { - return r.rw - } - - r.rw = &responseWriter{r: r} - return r.rw -} - -func (r *request) Close() error { - var err error - if r.body != nil { - err = r.body.Close() - } - r.Response().Finish() - C.URLSchemeTaskRelease(r.task) - return err -} - -var _ io.ReadCloser = &requestBodyStreamReader{} - -type requestBodyStreamReader struct { - task unsafe.Pointer - closed bool -} - -// Read implements io.Reader -func (r *requestBodyStreamReader) Read(p []byte) (n int, err error) { - var content unsafe.Pointer - var contentLen int - if p != nil { - content = unsafe.Pointer(&p[0]) - contentLen = len(p) - } - - res := C.URLSchemeTaskRequestBodyStreamRead(r.task, content, C.int(contentLen)) - if res > 0 { - return int(res), nil - } - - switch res { - case 0: - return 0, io.EOF - case -1: - return 0, errors.New("body: stream error") - case -2: - return 0, errors.New("body: no stream defined") - case -3: - return 0, io.ErrClosedPipe - default: - return 0, fmt.Errorf("body: unknown error %d", res) - } -} - -func (r *requestBodyStreamReader) Close() error { - if r.closed { - return nil - } - r.closed = true - - C.URLSchemeTaskRequestBodyStreamClose(r.task) - return nil -} diff --git a/v3/internal/assetserver/webview/request_linux.go b/v3/internal/assetserver/webview/request_linux.go deleted file mode 100644 index 559a7d66e..000000000 --- a/v3/internal/assetserver/webview/request_linux.go +++ /dev/null @@ -1,82 +0,0 @@ -//go:build linux && cgo && !gtk4 && !android - -package webview - -/* -#cgo linux pkg-config: gtk+-3.0 webkit2gtk-4.1 gio-unix-2.0 - -#include "gtk/gtk.h" -#include "webkit2/webkit2.h" -*/ -import "C" - -import ( - "io" - "net/http" - "unsafe" -) - -// NewRequest creates as new WebViewRequest based on a pointer to an `WebKitURISchemeRequest` -func NewRequest(webKitURISchemeRequest unsafe.Pointer) Request { - webkitReq := (*C.WebKitURISchemeRequest)(webKitURISchemeRequest) - C.g_object_ref(C.gpointer(webkitReq)) - - req := &request{req: webkitReq} - return newRequestFinalizer(req) -} - -var _ Request = &request{} - -type request struct { - req *C.WebKitURISchemeRequest - - header http.Header - body io.ReadCloser - rw *responseWriter -} - -func (r *request) URL() (string, error) { - return C.GoString(C.webkit_uri_scheme_request_get_uri(r.req)), nil -} - -func (r *request) Method() (string, error) { - return webkit_uri_scheme_request_get_http_method(r.req), nil -} - -func (r *request) Header() (http.Header, error) { - if r.header != nil { - return r.header, nil - } - - r.header = webkit_uri_scheme_request_get_http_headers(r.req) - return r.header, nil -} - -func (r *request) Body() (io.ReadCloser, error) { - if r.body != nil { - return r.body, nil - } - - r.body = webkit_uri_scheme_request_get_http_body(r.req) - - return r.body, nil -} - -func (r *request) Response() ResponseWriter { - if r.rw != nil { - return r.rw - } - - r.rw = &responseWriter{req: r.req} - return r.rw -} - -func (r *request) Close() error { - var err error - if r.body != nil { - err = r.body.Close() - } - r.Response().Finish() - C.g_object_unref(C.gpointer(r.req)) - return err -} diff --git a/v3/internal/assetserver/webview/request_linux_gtk4.go b/v3/internal/assetserver/webview/request_linux_gtk4.go deleted file mode 100644 index 8c9bf53ac..000000000 --- a/v3/internal/assetserver/webview/request_linux_gtk4.go +++ /dev/null @@ -1,81 +0,0 @@ -//go:build linux && cgo && gtk4 && !android - -package webview - -/* -#cgo linux pkg-config: gtk4 webkitgtk-6.0 gio-unix-2.0 - -#include -#include -*/ -import "C" - -import ( - "io" - "net/http" - "unsafe" -) - -func NewRequest(webKitURISchemeRequest unsafe.Pointer) Request { - webkitReq := (*C.WebKitURISchemeRequest)(webKitURISchemeRequest) - C.g_object_ref(C.gpointer(webkitReq)) - - req := &request{req: webkitReq} - return newRequestFinalizer(req) -} - -var _ Request = &request{} - -type request struct { - req *C.WebKitURISchemeRequest - - header http.Header - body io.ReadCloser - rw *responseWriter -} - -func (r *request) URL() (string, error) { - return C.GoString(C.webkit_uri_scheme_request_get_uri(r.req)), nil -} - -func (r *request) Method() (string, error) { - return webkit_uri_scheme_request_get_http_method(r.req), nil -} - -func (r *request) Header() (http.Header, error) { - if r.header != nil { - return r.header, nil - } - - r.header = webkit_uri_scheme_request_get_http_headers(r.req) - return r.header, nil -} - -func (r *request) Body() (io.ReadCloser, error) { - if r.body != nil { - return r.body, nil - } - - r.body = webkit_uri_scheme_request_get_http_body(r.req) - - return r.body, nil -} - -func (r *request) Response() ResponseWriter { - if r.rw != nil { - return r.rw - } - - r.rw = &responseWriter{req: r.req} - return r.rw -} - -func (r *request) Close() error { - var err error - if r.body != nil { - err = r.body.Close() - } - r.Response().Finish() - C.g_object_unref(C.gpointer(r.req)) - return err -} diff --git a/v3/internal/assetserver/webview/request_linux_purego.go b/v3/internal/assetserver/webview/request_linux_purego.go deleted file mode 100644 index 34937d25f..000000000 --- a/v3/internal/assetserver/webview/request_linux_purego.go +++ /dev/null @@ -1,93 +0,0 @@ -//go:build linux && purego && !android - -package webview - -import ( - "io" - "net/http" - - "github.com/ebitengine/purego" -) - -// NewRequest creates as new WebViewRequest based on a pointer to an `WebKitURISchemeRequest` -// -// Please make sure to call Release() when finished using the request. -func NewRequest(webKitURISchemeRequest uintptr) Request { - webkitReq := webKitURISchemeRequest - req := &request{req: webkitReq} - req.AddRef() - return req -} - -var _ Request = &request{} - -type request struct { - req uintptr - - header http.Header - body io.ReadCloser - rw *responseWriter -} - -func (r *request) AddRef() error { - var objectRef func(uintptr) - purego.RegisterLibFunc(&objectRef, gtk, "g_object_ref") - objectRef(r.req) - return nil -} - -func (r *request) Release() error { - var objectUnref func(uintptr) - purego.RegisterLibFunc(&objectUnref, gtk, "g_object_unref") - objectUnref(r.req) - return nil -} - -func (r *request) URL() (string, error) { - var getUri func(uintptr) string - purego.RegisterLibFunc(&getUri, webkit, "webkit_uri_scheme_request_get_uri") - return getUri(r.req), nil -} - -func (r *request) Method() (string, error) { - return webkit_uri_scheme_request_get_http_method(r.req), nil -} - -func (r *request) Header() (http.Header, error) { - if r.header != nil { - return r.header, nil - } - - r.header = webkit_uri_scheme_request_get_http_headers(r.req) - return r.header, nil -} - -func (r *request) Body() (io.ReadCloser, error) { - if r.body != nil { - return r.body, nil - } - - // WebKit2GTK has currently no support for request bodies. - r.body = http.NoBody - - return r.body, nil -} - -func (r *request) Response() ResponseWriter { - if r.rw != nil { - return r.rw - } - - r.rw = &responseWriter{req: r.req} - return r.rw -} - -func (r *request) Close() error { - var err error - if r.body != nil { - err = r.body.Close() - } - r.Response().Finish() - r.Release() - return err -} diff --git a/v3/internal/assetserver/webview/request_windows.go b/v3/internal/assetserver/webview/request_windows.go deleted file mode 100644 index 9f68af2e1..000000000 --- a/v3/internal/assetserver/webview/request_windows.go +++ /dev/null @@ -1,218 +0,0 @@ -//go:build windows - -package webview - -import ( - "errors" - "fmt" - "io" - "net/http" - - "github.com/wailsapp/go-webview2/pkg/edge" -) - -// NewRequest creates as new WebViewRequest for chromium. This Method must be called from the Main-Thread! -func NewRequest(env *edge.ICoreWebView2Environment, args *edge.ICoreWebView2WebResourceRequestedEventArgs, invokeSync func(fn func())) (Request, error) { - req, err := args.GetRequest() - if err != nil { - return nil, fmt.Errorf("GetRequest failed: %s", err) - } - defer req.Release() - - r := &request{ - invokeSync: invokeSync, - } - - code := http.StatusInternalServerError - r.response, err = env.CreateWebResourceResponse(nil, code, http.StatusText(code), "") - if err != nil { - return nil, fmt.Errorf("CreateWebResourceResponse failed: %s", err) - } - - if err := args.PutResponse(r.response); err != nil { - r.finishResponse() - return nil, fmt.Errorf("PutResponse failed: %s", err) - } - - r.deferral, err = args.GetDeferral() - if err != nil { - r.finishResponse() - return nil, fmt.Errorf("GetDeferral failed: %s", err) - } - - r.url, r.urlErr = req.GetUri() - r.method, r.methodErr = req.GetMethod() - r.header, r.headerErr = getHeaders(req) - - if content, err := req.GetContent(); err != nil { - r.bodyErr = err - } else if content != nil { - // It is safe to access Content from another Thread: https://learn.microsoft.com/en-us/microsoft-edge/webview2/concepts/threading-model#thread-safety - r.body = &iStreamReleaseCloser{stream: content} - } - - return r, nil -} - -var _ Request = &request{} - -type request struct { - response *edge.ICoreWebView2WebResourceResponse - deferral *edge.ICoreWebView2Deferral - - url string - urlErr error - - method string - methodErr error - - header http.Header - headerErr error - - body io.ReadCloser - bodyErr error - rw *responseWriter - - invokeSync func(fn func()) -} - -func (r *request) URL() (string, error) { - return r.url, r.urlErr -} - -func (r *request) Method() (string, error) { - return r.method, r.methodErr -} - -func (r *request) Header() (http.Header, error) { - return r.header, r.headerErr -} - -func (r *request) Body() (io.ReadCloser, error) { - return r.body, r.bodyErr -} - -func (r *request) Response() ResponseWriter { - if r.rw != nil { - return r.rw - } - - r.rw = &responseWriter{req: r} - return r.rw -} - -func (r *request) Close() error { - var errs []error - if r.body != nil { - if err := r.body.Close(); err != nil { - errs = append(errs, err) - } - r.body = nil - } - - if err := r.Response().Finish(); err != nil { - errs = append(errs, err) - } - - return combineErrs(errs) -} - -// finishResponse must be called on the main-thread -func (r *request) finishResponse() error { - var errs []error - if r.response != nil { - if err := r.response.Release(); err != nil { - errs = append(errs, err) - } - r.response = nil - } - if r.deferral != nil { - if err := r.deferral.Complete(); err != nil { - errs = append(errs, err) - } - - if err := r.deferral.Release(); err != nil { - errs = append(errs, err) - } - r.deferral = nil - } - return combineErrs(errs) -} - -type iStreamReleaseCloser struct { - stream *edge.IStream - closed bool -} - -func (i *iStreamReleaseCloser) Read(p []byte) (int, error) { - if i.closed { - return 0, io.ErrClosedPipe - } - return i.stream.Read(p) -} - -func (i *iStreamReleaseCloser) Close() error { - if i.closed { - return nil - } - i.closed = true - return i.stream.Release() -} - -func getHeaders(req *edge.ICoreWebView2WebResourceRequest) (http.Header, error) { - header := http.Header{} - headers, err := req.GetHeaders() - if err != nil { - return nil, fmt.Errorf("GetHeaders Error: %s", err) - } - defer headers.Release() - - headersIt, err := headers.GetIterator() - if err != nil { - return nil, fmt.Errorf("GetIterator Error: %s", err) - } - defer headersIt.Release() - - for { - has, err := headersIt.HasCurrentHeader() - if err != nil { - return nil, fmt.Errorf("HasCurrentHeader Error: %s", err) - } - if !has { - break - } - - name, value, err := headersIt.GetCurrentHeader() - if err != nil { - return nil, fmt.Errorf("GetCurrentHeader Error: %s", err) - } - - header.Set(name, value) - if _, err := headersIt.MoveNext(); err != nil { - return nil, fmt.Errorf("MoveNext Error: %s", err) - } - } - - // WebView2 has problems when a request returns a 304 status code and the WebView2 is going to hang for other - // requests including IPC calls. - // So prevent 304 status codes by removing the headers that are used in combinationwith caching. - header.Del("If-Modified-Since") - header.Del("If-None-Match") - return header, nil -} - -func combineErrs(errs []error) error { - err := errors.Join(errs...) - - if err != nil { - // errors.Join wraps even a single error. - // Check the filtered error list, - // and if it has just one element return it directly. - errs = err.(interface{ Unwrap() []error }).Unwrap() - if len(errs) == 1 { - return errs[0] - } - } - - return err -} diff --git a/v3/internal/assetserver/webview/responsewriter.go b/v3/internal/assetserver/webview/responsewriter.go deleted file mode 100644 index 2fc7ede51..000000000 --- a/v3/internal/assetserver/webview/responsewriter.go +++ /dev/null @@ -1,28 +0,0 @@ -package webview - -import ( - "errors" - "net/http" -) - -const ( - HeaderContentLength = "Content-Length" - HeaderContentType = "Content-Type" -) - -var ( - errRequestStopped = errors.New("request has been stopped") - errResponseFinished = errors.New("response has been finished") -) - -// A ResponseWriter interface is used by an HTTP handler to -// construct an HTTP response for the WebView. -type ResponseWriter interface { - http.ResponseWriter - - // Finish the response and flush all data. A Finish after the request has already been finished has no effect. - Finish() error - - // Code returns the HTTP status code of the response - Code() int -} diff --git a/v3/internal/assetserver/webview/responsewriter_darwin.go b/v3/internal/assetserver/webview/responsewriter_darwin.go deleted file mode 100644 index ff29a08bb..000000000 --- a/v3/internal/assetserver/webview/responsewriter_darwin.go +++ /dev/null @@ -1,156 +0,0 @@ -//go:build darwin && !ios - -package webview - -/* -#cgo CFLAGS: -x objective-c -#cgo LDFLAGS: -framework Foundation -framework WebKit - -#import -#import - -typedef void (^schemeTaskCaller)(id); - -static bool urlSchemeTaskCall(void *wkUrlSchemeTask, schemeTaskCaller fn) { - id urlSchemeTask = (id) wkUrlSchemeTask; - if (urlSchemeTask == nil) { - return false; - } - - @autoreleasepool { - @try { - fn(urlSchemeTask); - } @catch (NSException *exception) { - // This is very bad to detect a stopped schemeTask this should be implemented in a better way - // But it seems to be very tricky to not deadlock when keeping a lock curing executing fn() - // It seems like those call switch the thread back to the main thread and then deadlocks when they reentrant want - // to get the lock again to start another request or stop it. - if ([exception.reason isEqualToString: @"This task has already been stopped"]) { - return false; - } - - @throw exception; - } - - return true; - } -} - -static bool URLSchemeTaskDidReceiveData(void *wkUrlSchemeTask, void* data, int datalength) { - return urlSchemeTaskCall( - wkUrlSchemeTask, - ^(id urlSchemeTask) { - NSData *nsdata = [NSData dataWithBytes:data length:datalength]; - [urlSchemeTask didReceiveData:nsdata]; - }); -} - -static bool URLSchemeTaskDidFinish(void *wkUrlSchemeTask) { - return urlSchemeTaskCall( - wkUrlSchemeTask, - ^(id urlSchemeTask) { - [urlSchemeTask didFinish]; - }); -} - -static bool URLSchemeTaskDidReceiveResponse(void *wkUrlSchemeTask, int statusCode, void *headersString, int headersStringLength) { - return urlSchemeTaskCall( - wkUrlSchemeTask, - ^(id urlSchemeTask) { - NSData *nsHeadersJSON = [NSData dataWithBytes:headersString length:headersStringLength]; - NSDictionary *headerFields = [NSJSONSerialization JSONObjectWithData:nsHeadersJSON options: NSJSONReadingMutableContainers error: nil]; - NSHTTPURLResponse *response = [[[NSHTTPURLResponse alloc] initWithURL:urlSchemeTask.request.URL statusCode:statusCode HTTPVersion:@"HTTP/1.1" headerFields:headerFields] autorelease]; - - [urlSchemeTask didReceiveResponse:response]; - }); -} -*/ -import "C" - -import ( - "net/http" - "unsafe" - - "encoding/json" -) - -var _ ResponseWriter = &responseWriter{} - -type responseWriter struct { - r *request - - header http.Header - wroteHeader bool - code int - - finished bool -} - -func (rw *responseWriter) Header() http.Header { - if rw.header == nil { - rw.header = http.Header{} - } - return rw.header -} - -func (rw *responseWriter) Write(buf []byte) (int, error) { - if rw.finished { - return 0, errResponseFinished - } - - rw.WriteHeader(http.StatusOK) - - var content unsafe.Pointer - var contentLen int - if buf != nil && len(buf) > 0 { - content = unsafe.Pointer(&buf[0]) - contentLen = len(buf) - } - - if !C.URLSchemeTaskDidReceiveData(rw.r.task, content, C.int(contentLen)) { - return 0, errRequestStopped - } - return contentLen, nil -} - -func (rw *responseWriter) WriteHeader(code int) { - rw.code = code - if rw.wroteHeader || rw.finished { - return - } - rw.wroteHeader = true - - header := map[string]string{} - for k := range rw.Header() { - header[k] = rw.Header().Get(k) - } - headerData, _ := json.Marshal(header) - - var headers unsafe.Pointer - var headersLen int - if len(headerData) != 0 { - headers = unsafe.Pointer(&headerData[0]) - headersLen = len(headerData) - } - - C.URLSchemeTaskDidReceiveResponse(rw.r.task, C.int(code), headers, C.int(headersLen)) -} - -func (rw *responseWriter) Finish() error { - if !rw.wroteHeader { - rw.WriteHeader(http.StatusNotImplemented) - } - - if rw.finished { - return nil - } - rw.finished = true - - C.URLSchemeTaskDidFinish(rw.r.task) - - return nil -} - -func (rw *responseWriter) Code() int { - return rw.code -} diff --git a/v3/internal/assetserver/webview/responsewriter_ios.go b/v3/internal/assetserver/webview/responsewriter_ios.go deleted file mode 100644 index 119ef1628..000000000 --- a/v3/internal/assetserver/webview/responsewriter_ios.go +++ /dev/null @@ -1,172 +0,0 @@ -//go:build ios - -package webview - -/* -#cgo CFLAGS: -x objective-c -fobjc-arc -#cgo LDFLAGS: -framework Foundation -framework WebKit - -#import -#import - -typedef void (^schemeTaskCaller)(id); - -static bool urlSchemeTaskCall(void *wkUrlSchemeTask, schemeTaskCaller fn) { - id urlSchemeTask = (__bridge id) wkUrlSchemeTask; - if (urlSchemeTask == nil) { - return false; - } - - @autoreleasepool { - @try { - fn(urlSchemeTask); - } @catch (NSException *exception) { - // This is very bad to detect a stopped schemeTask this should be implemented in a better way - // But it seems to be very tricky to not deadlock when keeping a lock curing executing fn() - // It seems like those call switch the thread back to the main thread and then deadlocks when they reentrant want - // to get the lock again to start another request or stop it. - if ([exception.reason isEqualToString: @"This task has already been stopped"]) { - return false; - } - - @throw exception; - } - - return true; - } -} - -static bool URLSchemeTaskDidReceiveData(void *wkUrlSchemeTask, void* data, int datalength) { - return urlSchemeTaskCall( - wkUrlSchemeTask, - ^(id urlSchemeTask) { - NSData *nsdata = [NSData dataWithBytes:data length:datalength]; - [urlSchemeTask didReceiveData:nsdata]; - }); -} - -static bool URLSchemeTaskDidFinish(void *wkUrlSchemeTask) { - return urlSchemeTaskCall( - wkUrlSchemeTask, - ^(id urlSchemeTask) { - [urlSchemeTask didFinish]; - }); -} - -static bool URLSchemeTaskDidReceiveResponse(void *wkUrlSchemeTask, int statusCode, void *headersString, int headersStringLength) { - return urlSchemeTaskCall( - wkUrlSchemeTask, - ^(id urlSchemeTask) { - NSData *nsHeadersJSON = [NSData dataWithBytes:headersString length:headersStringLength]; - NSDictionary *headerFields = [NSJSONSerialization JSONObjectWithData:nsHeadersJSON options:NSJSONReadingMutableContainers error:nil]; - NSHTTPURLResponse *response = [[NSHTTPURLResponse alloc] initWithURL:urlSchemeTask.request.URL statusCode:statusCode HTTPVersion:nil headerFields:headerFields]; - - [urlSchemeTask didReceiveResponse:response]; - }); -} -*/ -import "C" - -import ( - "fmt" - "net/http" - "strings" - "unsafe" - - "encoding/json" -) - -var _ ResponseWriter = &responseWriter{} - -type responseWriter struct { - r *request - - header http.Header - wroteHeader bool - code int - - finished bool -} - -func (rw *responseWriter) Header() http.Header { - if rw.header == nil { - rw.header = http.Header{} - } - return rw.header -} - -func (rw *responseWriter) Write(buf []byte) (int, error) { - if rw.finished { - return 0, errResponseFinished - } - - rw.WriteHeader(http.StatusOK) - - // Debug logging for CSS files - if url, err := rw.r.URL(); err == nil && (strings.Contains(url, ".css") || strings.Contains(url, "style")) { - preview := string(buf) - if len(preview) > 100 { - preview = preview[:100] + "..." - } - fmt.Printf("🎨 CSS Write: URL=%s Size=%d Preview=%s\n", url, len(buf), preview) - } - - var content unsafe.Pointer - var contentLen int - if buf != nil { - content = unsafe.Pointer(&buf[0]) - contentLen = len(buf) - } - - if !C.URLSchemeTaskDidReceiveData(rw.r.task, content, C.int(contentLen)) { - return 0, errRequestStopped - } - return contentLen, nil -} - -func (rw *responseWriter) WriteHeader(code int) { - rw.code = code - if rw.wroteHeader || rw.finished { - return - } - rw.wroteHeader = true - - header := map[string]string{} - for k := range rw.Header() { - header[k] = rw.Header().Get(k) - } - headerData, _ := json.Marshal(header) - - // Debug logging for CSS files - if url, err := rw.r.URL(); err == nil && (strings.Contains(url, ".css") || strings.Contains(url, "style")) { - fmt.Printf("🎨 CSS Response: URL=%s Code=%d Headers=%s\n", url, code, string(headerData)) - } - - var headers unsafe.Pointer - var headersLen int - if len(headerData) != 0 { - headers = unsafe.Pointer(&headerData[0]) - headersLen = len(headerData) - } - - C.URLSchemeTaskDidReceiveResponse(rw.r.task, C.int(code), headers, C.int(headersLen)) -} - -func (rw *responseWriter) Finish() error { - if !rw.wroteHeader { - rw.WriteHeader(http.StatusNotImplemented) - } - - if rw.finished { - return nil - } - rw.finished = true - - C.URLSchemeTaskDidFinish(rw.r.task) - - return nil -} - -func (rw *responseWriter) Code() int { - return rw.code -} diff --git a/v3/internal/assetserver/webview/responsewriter_linux.go b/v3/internal/assetserver/webview/responsewriter_linux.go deleted file mode 100644 index f62a4f8cc..000000000 --- a/v3/internal/assetserver/webview/responsewriter_linux.go +++ /dev/null @@ -1,135 +0,0 @@ -//go:build linux && cgo && !gtk4 && !android - -package webview - -/* -#cgo linux pkg-config: gtk+-3.0 webkit2gtk-4.1 gio-unix-2.0 - -#include "gtk/gtk.h" -#include "webkit2/webkit2.h" -#include "gio/gunixinputstream.h" - -*/ -import "C" -import ( - "fmt" - "io" - "net/http" - "os" - "strconv" - "syscall" - "unsafe" -) - -type responseWriter struct { - req *C.WebKitURISchemeRequest - - header http.Header - wroteHeader bool - finished bool - code int - - w io.WriteCloser - wErr error -} - -func (rw *responseWriter) Code() int { - return rw.code -} - -func (rw *responseWriter) Header() http.Header { - if rw.header == nil { - rw.header = http.Header{} - } - return rw.header -} - -func (rw *responseWriter) Write(buf []byte) (int, error) { - if rw.finished { - return 0, errResponseFinished - } - - rw.WriteHeader(http.StatusOK) - if rw.wErr != nil { - return 0, rw.wErr - } - return rw.w.Write(buf) -} - -func (rw *responseWriter) WriteHeader(code int) { - rw.code = code - if rw.wroteHeader || rw.finished { - return - } - rw.wroteHeader = true - - contentLength := int64(-1) - if sLen := rw.Header().Get(HeaderContentLength); sLen != "" { - if pLen, _ := strconv.ParseInt(sLen, 10, 64); pLen > 0 { - contentLength = pLen - } - } - - // We can't use os.Pipe here, because that returns files with a finalizer for closing the FD. But the control over the - // read FD is given to the InputStream and will be closed there. - // Furthermore we especially don't want to have the FD_CLOEXEC - rFD, w, err := pipe() - if err != nil { - rw.finishWithError(http.StatusInternalServerError, fmt.Errorf("unable to open pipe: %s", err)) - return - } - rw.w = w - - stream := C.g_unix_input_stream_new(C.int(rFD), C.gboolean(1)) - defer C.g_object_unref(C.gpointer(stream)) - - if err := webkit_uri_scheme_request_finish(rw.req, code, rw.Header(), stream, contentLength); err != nil { - rw.finishWithError(http.StatusInternalServerError, fmt.Errorf("unable to finish request: %s", err)) - return - } -} - -func (rw *responseWriter) Finish() error { - if !rw.wroteHeader { - rw.WriteHeader(http.StatusNotImplemented) - } - - if rw.finished { - return nil - } - rw.finished = true - if rw.w != nil { - rw.w.Close() - } - return nil -} - -func (rw *responseWriter) finishWithError(code int, err error) { - if rw.w != nil { - rw.w.Close() - rw.w = &nopCloser{io.Discard} - } - rw.wErr = err - - msg := C.CString(err.Error()) - gerr := C.g_error_new_literal(C.g_quark_from_string(msg), C.int(code), msg) - C.webkit_uri_scheme_request_finish_error(rw.req, gerr) - C.g_error_free(gerr) - C.free(unsafe.Pointer(msg)) -} - -type nopCloser struct { - io.Writer -} - -func (nopCloser) Close() error { return nil } - -func pipe() (r int, w *os.File, err error) { - var p [2]int - e := syscall.Pipe2(p[0:], 0) - if e != nil { - return 0, nil, fmt.Errorf("pipe2: %s", e) - } - - return p[0], os.NewFile(uintptr(p[1]), "|1"), nil -} diff --git a/v3/internal/assetserver/webview/responsewriter_linux_gtk4.go b/v3/internal/assetserver/webview/responsewriter_linux_gtk4.go deleted file mode 100644 index 3a6a6cb81..000000000 --- a/v3/internal/assetserver/webview/responsewriter_linux_gtk4.go +++ /dev/null @@ -1,132 +0,0 @@ -//go:build linux && cgo && gtk4 && !android - -package webview - -/* -#cgo linux pkg-config: gtk4 webkitgtk-6.0 gio-unix-2.0 - -#include -#include -#include - -*/ -import "C" -import ( - "fmt" - "io" - "net/http" - "os" - "strconv" - "syscall" - "unsafe" -) - -type responseWriter struct { - req *C.WebKitURISchemeRequest - - header http.Header - wroteHeader bool - finished bool - code int - - w io.WriteCloser - wErr error -} - -func (rw *responseWriter) Code() int { - return rw.code -} - -func (rw *responseWriter) Header() http.Header { - if rw.header == nil { - rw.header = http.Header{} - } - return rw.header -} - -func (rw *responseWriter) Write(buf []byte) (int, error) { - if rw.finished { - return 0, errResponseFinished - } - - rw.WriteHeader(http.StatusOK) - if rw.wErr != nil { - return 0, rw.wErr - } - return rw.w.Write(buf) -} - -func (rw *responseWriter) WriteHeader(code int) { - rw.code = code - if rw.wroteHeader || rw.finished { - return - } - rw.wroteHeader = true - - contentLength := int64(-1) - if sLen := rw.Header().Get(HeaderContentLength); sLen != "" { - if pLen, _ := strconv.ParseInt(sLen, 10, 64); pLen > 0 { - contentLength = pLen - } - } - - rFD, w, err := pipe() - if err != nil { - rw.finishWithError(http.StatusInternalServerError, fmt.Errorf("unable to open pipe: %s", err)) - return - } - rw.w = w - - stream := C.g_unix_input_stream_new(C.int(rFD), C.gboolean(1)) - defer C.g_object_unref(C.gpointer(stream)) - - if err := webkit_uri_scheme_request_finish(rw.req, code, rw.Header(), stream, contentLength); err != nil { - rw.finishWithError(http.StatusInternalServerError, fmt.Errorf("unable to finish request: %s", err)) - return - } -} - -func (rw *responseWriter) Finish() error { - if !rw.wroteHeader { - rw.WriteHeader(http.StatusNotImplemented) - } - - if rw.finished { - return nil - } - rw.finished = true - if rw.w != nil { - rw.w.Close() - } - return nil -} - -func (rw *responseWriter) finishWithError(code int, err error) { - if rw.w != nil { - rw.w.Close() - rw.w = &nopCloser{io.Discard} - } - rw.wErr = err - - msg := C.CString(err.Error()) - gerr := C.g_error_new_literal(C.g_quark_from_string(msg), C.int(code), msg) - C.webkit_uri_scheme_request_finish_error(rw.req, gerr) - C.g_error_free(gerr) - C.free(unsafe.Pointer(msg)) -} - -type nopCloser struct { - io.Writer -} - -func (nopCloser) Close() error { return nil } - -func pipe() (r int, w *os.File, err error) { - var p [2]int - e := syscall.Pipe2(p[0:], 0) - if e != nil { - return 0, nil, fmt.Errorf("pipe2: %s", e) - } - - return p[0], os.NewFile(uintptr(p[1]), "|1"), nil -} diff --git a/v3/internal/assetserver/webview/responsewriter_linux_purego.go b/v3/internal/assetserver/webview/responsewriter_linux_purego.go deleted file mode 100644 index 804765226..000000000 --- a/v3/internal/assetserver/webview/responsewriter_linux_purego.go +++ /dev/null @@ -1,179 +0,0 @@ -//go:build linux && purego && !android - -package webview - -import ( - "fmt" - "io" - "net/http" - "os" - "strconv" - "syscall" - - "github.com/ebitengine/purego" -) - -const ( - gtk3 = "libgtk-3.so" - gtk4 = "libgtk-4.so" -) - -var ( - gtk uintptr - webkit uintptr - version int -) - -func init() { - var err error - // gtk, err = purego.Dlopen(gtk4, purego.RTLD_NOW|purego.RTLD_GLOBAL) - // if err == nil { - // version = 4 - // return - // } - // log.Println("Failed to open GTK4: Falling back to GTK3") - gtk, err = purego.Dlopen(gtk3, purego.RTLD_NOW|purego.RTLD_GLOBAL) - if err != nil { - panic(err) - } - version = 3 - - var webkit4 string = "libwebkit2gtk-4.1.so" - webkit, err = purego.Dlopen(webkit4, purego.RTLD_NOW|purego.RTLD_GLOBAL) - if err != nil { - panic(err) - } -} - -type responseWriter struct { - req uintptr - - header http.Header - wroteHeader bool - finished bool - code int - w io.WriteCloser - wErr error -} - -func (rw *responseWriter) Code() int { - return rw.code -} - -func (rw *responseWriter) Header() http.Header { - if rw.header == nil { - rw.header = http.Header{} - } - return rw.header -} - -func (rw *responseWriter) Write(buf []byte) (int, error) { - if rw.finished { - return 0, errResponseFinished - } - - rw.WriteHeader(http.StatusOK) - if rw.wErr != nil { - return 0, rw.wErr - } - return rw.w.Write(buf) -} - -func (rw *responseWriter) WriteHeader(code int) { - rw.code = code - - // TODO? Is this ever called? I don't think so! - if rw.wroteHeader || rw.finished { - return - } - rw.wroteHeader = true - - contentLength := int64(-1) - if sLen := rw.Header().Get(HeaderContentLength); sLen != "" { - if pLen, _ := strconv.ParseInt(sLen, 10, 64); pLen > 0 { - contentLength = pLen - } - } - // We can't use os.Pipe here, because that returns files with a finalizer for closing the FD. But the control over the - // read FD is given to the InputStream and will be closed there. - // Furthermore we especially don't want to have the FD_CLOEXEC - rFD, w, err := pipe() - if err != nil { - rw.finishWithError(http.StatusInternalServerError, fmt.Errorf("unable to open pipe: %s", err)) - return - } - rw.w = w - - var newStream func(int, bool) uintptr - purego.RegisterLibFunc(&newStream, gtk, "g_unix_input_stream_new") - var unRef func(uintptr) - purego.RegisterLibFunc(&unRef, gtk, "g_object_unref") - stream := newStream(rFD, true) - - /* var reqFinish func(uintptr, uintptr, uintptr, uintptr, int64) int - purego.RegisterLibFunc(&reqFinish, webkit, "webkit_uri_scheme_request_finish") - - header := rw.Header() - defer unRef(stream) - if err := reqFinish(rw.req, code, header, stream, contentLength); err != nil { - rw.finishWithError(http.StatusInternalServerError, fmt.Errorf("unable to finish request: %s", err)) - } - */ - if err := webkit_uri_scheme_request_finish(rw.req, code, rw.Header(), stream, contentLength); err != nil { - rw.finishWithError(http.StatusInternalServerError, fmt.Errorf("unable to finish request: %s", err)) - return - } -} - -func (rw *responseWriter) Finish() { - if !rw.wroteHeader { - rw.WriteHeader(http.StatusNotImplemented) - } - - if rw.finished { - return - } - rw.finished = true - if rw.w != nil { - rw.w.Close() - } -} - -func (rw *responseWriter) finishWithError(code int, err error) { - if rw.w != nil { - rw.w.Close() - rw.w = &nopCloser{io.Discard} - } - rw.wErr = err - - var newLiteral func(uint32, string, int, string) uintptr // is this correct? - purego.RegisterLibFunc(&newLiteral, gtk, "g_error_new_literal") - var newQuark func(string) uintptr - purego.RegisterLibFunc(&newQuark, gtk, "g_quark_from_string") - var freeError func(uintptr) - purego.RegisterLibFunc(&freeError, gtk, "g_error_free") - var finishError func(uintptr, uintptr) - purego.RegisterLibFunc(&finishError, webkit, "webkit_uri_scheme_request_finish_error") - - msg := string(err.Error()) - //gquark := newQuark(msg) - gerr := newLiteral(1, msg, code, msg) - finishError(rw.req, gerr) - freeError(gerr) -} - -type nopCloser struct { - io.Writer -} - -func (nopCloser) Close() error { return nil } - -func pipe() (r int, w *os.File, err error) { - var p [2]int - e := syscall.Pipe2(p[0:], 0) - if e != nil { - return 0, nil, fmt.Errorf("pipe2: %s", e) - } - - return p[0], os.NewFile(uintptr(p[1]), "|1"), nil -} diff --git a/v3/internal/assetserver/webview/responsewriter_windows.go b/v3/internal/assetserver/webview/responsewriter_windows.go deleted file mode 100644 index c003f00bd..000000000 --- a/v3/internal/assetserver/webview/responsewriter_windows.go +++ /dev/null @@ -1,109 +0,0 @@ -//go:build windows - -package webview - -import ( - "bytes" - "errors" - "fmt" - "net/http" - "strings" -) - -var _ http.ResponseWriter = &responseWriter{} - -type responseWriter struct { - req *request - - header http.Header - wroteHeader bool - code int - body *bytes.Buffer - - finished bool -} - -func (rw *responseWriter) Header() http.Header { - if rw.header == nil { - rw.header = http.Header{} - } - return rw.header -} - -func (rw *responseWriter) Write(buf []byte) (int, error) { - if rw.finished { - return 0, errResponseFinished - } - - rw.WriteHeader(http.StatusOK) - - return rw.body.Write(buf) -} - -func (rw *responseWriter) WriteHeader(code int) { - if rw.wroteHeader || rw.finished { - return - } - rw.wroteHeader = true - - if rw.body == nil { - rw.body = &bytes.Buffer{} - } - - rw.code = code -} - -func (rw *responseWriter) Finish() error { - if !rw.wroteHeader { - rw.WriteHeader(http.StatusNotImplemented) - } - - if rw.finished { - return nil - } - rw.finished = true - - var errs []error - - code := rw.code - if code == http.StatusNotModified { - // WebView2 has problems when a request returns a 304 status code and the WebView2 is going to hang for other - // requests including IPC calls. - errs = append(errs, errors.New("AssetServer returned 304 - StatusNotModified which are going to hang WebView2, changed code to 505 - StatusInternalServerError")) - code = http.StatusInternalServerError - } - - rw.req.invokeSync(func() { - resp := rw.req.response - - hdrs, err := resp.GetHeaders() - if err != nil { - errs = append(errs, fmt.Errorf("Resp.GetHeaders failed: %s", err)) - } else { - for k, v := range rw.header { - if err := hdrs.AppendHeader(k, strings.Join(v, ",")); err != nil { - errs = append(errs, fmt.Errorf("Resp.AppendHeader failed: %s", err)) - } - } - hdrs.Release() - } - - if err := resp.PutStatusCode(code); err != nil { - errs = append(errs, fmt.Errorf("Resp.PutStatusCode failed: %s", err)) - } - - if err := resp.PutByteContent(rw.body.Bytes()); err != nil { - errs = append(errs, fmt.Errorf("Resp.PutByteContent failed: %s", err)) - } - - if err := rw.req.finishResponse(); err != nil { - errs = append(errs, fmt.Errorf("Resp.finishResponse failed: %s", err)) - } - }) - - return combineErrs(errs) -} - -func (rw *responseWriter) Code() int { - return rw.code -} diff --git a/v3/internal/assetserver/webview/webkit2.go b/v3/internal/assetserver/webview/webkit2.go deleted file mode 100644 index 295db3fff..000000000 --- a/v3/internal/assetserver/webview/webkit2.go +++ /dev/null @@ -1,137 +0,0 @@ -//go:build linux && cgo && !gtk4 && !android - -package webview - -/* -#cgo linux pkg-config: gtk+-3.0 webkit2gtk-4.1 libsoup-3.0 - -#include "gtk/gtk.h" -#include "webkit2/webkit2.h" -#include "libsoup/soup.h" -*/ -import "C" - -import ( - "fmt" - "io" - "net/http" - "strings" - "unsafe" -) - -const Webkit2MinMinorVersion = 40 - -func webkit_uri_scheme_request_get_http_method(req *C.WebKitURISchemeRequest) string { - method := C.GoString(C.webkit_uri_scheme_request_get_http_method(req)) - return strings.ToUpper(method) -} - -func webkit_uri_scheme_request_get_http_headers(req *C.WebKitURISchemeRequest) http.Header { - hdrs := C.webkit_uri_scheme_request_get_http_headers(req) - - var iter C.SoupMessageHeadersIter - C.soup_message_headers_iter_init(&iter, hdrs) - - var name *C.char - var value *C.char - - h := http.Header{} - for C.soup_message_headers_iter_next(&iter, &name, &value) != 0 { - h.Add(C.GoString(name), C.GoString(value)) - } - - return h -} - -func webkit_uri_scheme_request_finish(req *C.WebKitURISchemeRequest, code int, header http.Header, stream *C.GInputStream, streamLength int64) error { - resp := C.webkit_uri_scheme_response_new(stream, C.gint64(streamLength)) - defer C.g_object_unref(C.gpointer(resp)) - - cReason := C.CString(http.StatusText(code)) - C.webkit_uri_scheme_response_set_status(resp, C.guint(code), cReason) - C.free(unsafe.Pointer(cReason)) - - cMimeType := C.CString(header.Get(HeaderContentType)) - C.webkit_uri_scheme_response_set_content_type(resp, cMimeType) - C.free(unsafe.Pointer(cMimeType)) - - hdrs := C.soup_message_headers_new(C.SOUP_MESSAGE_HEADERS_RESPONSE) - for name, values := range header { - cName := C.CString(name) - for _, value := range values { - cValue := C.CString(value) - C.soup_message_headers_append(hdrs, cName, cValue) - C.free(unsafe.Pointer(cValue)) - } - C.free(unsafe.Pointer(cName)) - } - - C.webkit_uri_scheme_response_set_http_headers(resp, hdrs) - - C.webkit_uri_scheme_request_finish_with_response(req, resp) - return nil -} - -func webkit_uri_scheme_request_get_http_body(req *C.WebKitURISchemeRequest) io.ReadCloser { - stream := C.webkit_uri_scheme_request_get_http_body(req) - if stream == nil { - return http.NoBody - } - return &webkitRequestBody{stream: stream} -} - -type webkitRequestBody struct { - stream *C.GInputStream - closed bool -} - -// Read implements io.Reader -func (r *webkitRequestBody) Read(p []byte) (int, error) { - if r.closed { - return 0, io.ErrClosedPipe - } - - var content unsafe.Pointer - var contentLen int - if p != nil { - content = unsafe.Pointer(&p[0]) - contentLen = len(p) - } - - var n C.gsize - var gErr *C.GError - res := C.g_input_stream_read_all(r.stream, content, C.gsize(contentLen), &n, nil, &gErr) - if res == 0 { - return 0, formatGError("stream read failed", gErr) - } else if n == 0 { - return 0, io.EOF - } - return int(n), nil -} - -func (r *webkitRequestBody) Close() error { - if r.closed { - return nil - } - r.closed = true - - // https://docs.gtk.org/gio/method.InputStream.close.html - // Streams will be automatically closed when the last reference is dropped, but you might want to call this function - // to make sure resources are released as early as possible. - var err error - var gErr *C.GError - if C.g_input_stream_close(r.stream, nil, &gErr) == 0 { - err = formatGError("stream close failed", gErr) - } - C.g_object_unref(C.gpointer(r.stream)) - r.stream = nil - return err -} - -func formatGError(msg string, gErr *C.GError, args ...any) error { - if gErr != nil && gErr.message != nil { - msg += ": " + C.GoString(gErr.message) - C.g_error_free(gErr) - } - return fmt.Errorf(msg, args...) -} diff --git a/v3/internal/assetserver/webview/webkit2_purego.go b/v3/internal/assetserver/webview/webkit2_purego.go deleted file mode 100644 index 28832c8bd..000000000 --- a/v3/internal/assetserver/webview/webkit2_purego.go +++ /dev/null @@ -1,158 +0,0 @@ -//go:build linux && purego - -package webview - -import ( - "net/http" - "strings" - - "github.com/ebitengine/purego" -) - -func webkit_uri_scheme_request_get_http_method(req uintptr) string { - var getMethod func(uintptr) string - purego.RegisterLibFunc(&getMethod, gtk, "webkit_uri_scheme_request_get_http_method") - return strings.ToUpper(getMethod(req)) -} - -func webkit_uri_scheme_request_get_http_headers(req uintptr) http.Header { - var getHeaders func(uintptr) uintptr - purego.RegisterLibFunc(&getUri, webkit, "webkit_uri_scheme_request_get_http_headers") - - hdrs := getHeaders(req) - - var headersIterInit func(uintptr, uintptr) uintptr - purego.RegisterLibFunc(&headersIterInit, gtk, "soup_message_headers_iter_init") - - // TODO: How do we get a struct? - /* - typedef struct { - SoupMessageHeaders *hdrs; - int index_common; - int index_uncommon; - } SoupMessageHeadersIterReal; - */ - iter := make([]byte, 12) - headersIterInit(&iter, hdrs) - - var iterNext func(uintptr, *string, *string) int - purego.RegisterLibFunc(&iterNext, gtk, "soup_message_headers_iter_next") - - var name string - var value string - h := http.Header{} - - for iterNext(&iter, &name, &value) != 0 { - h.Add(name, value) - } - - return h -} - -func webkit_uri_scheme_request_finish(req uintptr, code int, header http.Header, stream uintptr, streamLength int64) error { - - var newResponse func(uintptr, int64) string - purego.RegisterLibFunc(&newResponse, webkit, "webkit_uri_scheme_response_new") - var unRef func(uintptr) - purego.RegisterLibFunc(&unRef, gtk, "g_object_unref") - - resp := newResponse(stream, streamLength) - defer unRef(resp) - - var setStatus func(uintptr, int, string) - purego.RegisterLibFunc(&unRef, webkit, "webkit_uri_scheme_response_set_status") - - setStatus(resp, code, cReason) - - var setContentType func(uintptr, string) - purego.RegisterLibFunc(&unRef, webkit, "webkit_uri_scheme_response_set_content_type") - - setContentType(resp, header.Get(HeaderContentType)) - - soup := gtk - var soupHeadersNew func(int) uintptr - purego.RegisterLibFunc(&unRef, soup, "soup_message_headers_new") - var soupHeadersAppend func(uintptr, string, string) - purego.RegisterLibFunc(&unRef, soup, "soup_message_headers_append") - - hdrs := soupHeadersNew(SOUP_MESSAGE_HEADERS_RESPONSE) - for name, values := range header { - for _, value := range values { - soupHeadersAppend(hdrs, name, value) - } - } - - var setHttpHeaders func(uintptr, uintptr) - purego.RegisterLibFunc(&unRef, webkit, "webkit_uri_scheme_response_set_http_headers") - - setHttpHeaders(resp, hdrs) - var finishWithResponse func(uintptr, uintptr) - purego.RegisterLibFunc(&unRef, webkit, "webkit_uri_scheme_request_finish_with_response") - finishWithResponse(req, resp) - - return nil -} - -func webkit_uri_scheme_request_get_http_body(req *C.WebKitURISchemeRequest) io.ReadCloser { - stream := C.webkit_uri_scheme_request_get_http_body(req) - if stream == nil { - return http.NoBody - } - return &webkitRequestBody{stream: stream} -} - -type webkitRequestBody struct { - stream *C.GInputStream - closed bool -} - -// Read implements io.Reader -func (r *webkitRequestBody) Read(p []byte) (int, error) { - if r.closed { - return 0, io.ErrClosedPipe - } - - var content unsafe.Pointer - var contentLen int - if p != nil { - content = unsafe.Pointer(&p[0]) - contentLen = len(p) - } - - var n C.gsize - var gErr *C.GError - res := C.g_input_stream_read_all(r.stream, content, C.gsize(contentLen), &n, nil, &gErr) - if res == 0 { - return 0, formatGError("stream read failed", gErr) - } else if n == 0 { - return 0, io.EOF - } - return int(n), nil -} - -func (r *webkitRequestBody) Close() error { - if r.closed { - return nil - } - r.closed = true - - // https://docs.gtk.org/gio/method.InputStream.close.html - // Streams will be automatically closed when the last reference is dropped, but you might want to call this function - // to make sure resources are released as early as possible. - var err error - var gErr *C.GError - if C.g_input_stream_close(r.stream, nil, &gErr) == 0 { - err = formatGError("stream close failed", gErr) - } - C.g_object_unref(C.gpointer(r.stream)) - r.stream = nil - return err -} - -func formatGError(msg string, gErr *C.GError, args ...any) error { - if gErr != nil && gErr.message != nil { - msg += ": " + C.GoString(gErr.message) - C.g_error_free(gErr) - } - return fmt.Errorf(msg, args...) -} diff --git a/v3/internal/assetserver/webview/webkit6.go b/v3/internal/assetserver/webview/webkit6.go deleted file mode 100644 index 22c19ff9f..000000000 --- a/v3/internal/assetserver/webview/webkit6.go +++ /dev/null @@ -1,133 +0,0 @@ -//go:build linux && cgo && gtk4 && !android - -package webview - -/* -#cgo linux pkg-config: gtk4 webkitgtk-6.0 libsoup-3.0 - -#include -#include -#include -*/ -import "C" - -import ( - "fmt" - "io" - "net/http" - "strings" - "unsafe" -) - -const Webkit2MinMinorVersion = 0 - -func webkit_uri_scheme_request_get_http_method(req *C.WebKitURISchemeRequest) string { - method := C.GoString(C.webkit_uri_scheme_request_get_http_method(req)) - return strings.ToUpper(method) -} - -func webkit_uri_scheme_request_get_http_headers(req *C.WebKitURISchemeRequest) http.Header { - hdrs := C.webkit_uri_scheme_request_get_http_headers(req) - - var iter C.SoupMessageHeadersIter - C.soup_message_headers_iter_init(&iter, hdrs) - - var name *C.char - var value *C.char - - h := http.Header{} - for C.soup_message_headers_iter_next(&iter, &name, &value) != 0 { - h.Add(C.GoString(name), C.GoString(value)) - } - - return h -} - -func webkit_uri_scheme_request_finish(req *C.WebKitURISchemeRequest, code int, header http.Header, stream *C.GInputStream, streamLength int64) error { - resp := C.webkit_uri_scheme_response_new(stream, C.gint64(streamLength)) - defer C.g_object_unref(C.gpointer(resp)) - - cReason := C.CString(http.StatusText(code)) - C.webkit_uri_scheme_response_set_status(resp, C.guint(code), cReason) - C.free(unsafe.Pointer(cReason)) - - cMimeType := C.CString(header.Get(HeaderContentType)) - C.webkit_uri_scheme_response_set_content_type(resp, cMimeType) - C.free(unsafe.Pointer(cMimeType)) - - hdrs := C.soup_message_headers_new(C.SOUP_MESSAGE_HEADERS_RESPONSE) - for name, values := range header { - cName := C.CString(name) - for _, value := range values { - cValue := C.CString(value) - C.soup_message_headers_append(hdrs, cName, cValue) - C.free(unsafe.Pointer(cValue)) - } - C.free(unsafe.Pointer(cName)) - } - - C.webkit_uri_scheme_response_set_http_headers(resp, hdrs) - - C.webkit_uri_scheme_request_finish_with_response(req, resp) - return nil -} - -func webkit_uri_scheme_request_get_http_body(req *C.WebKitURISchemeRequest) io.ReadCloser { - stream := C.webkit_uri_scheme_request_get_http_body(req) - if stream == nil { - return http.NoBody - } - return &webkitRequestBody{stream: stream} -} - -type webkitRequestBody struct { - stream *C.GInputStream - closed bool -} - -func (r *webkitRequestBody) Read(p []byte) (int, error) { - if r.closed { - return 0, io.ErrClosedPipe - } - - var content unsafe.Pointer - var contentLen int - if p != nil { - content = unsafe.Pointer(&p[0]) - contentLen = len(p) - } - - var n C.gsize - var gErr *C.GError - res := C.g_input_stream_read_all(r.stream, content, C.gsize(contentLen), &n, nil, &gErr) - if res == 0 { - return 0, formatGError("stream read failed", gErr) - } else if n == 0 { - return 0, io.EOF - } - return int(n), nil -} - -func (r *webkitRequestBody) Close() error { - if r.closed { - return nil - } - r.closed = true - - var err error - var gErr *C.GError - if C.g_input_stream_close(r.stream, nil, &gErr) == 0 { - err = formatGError("stream close failed", gErr) - } - C.g_object_unref(C.gpointer(r.stream)) - r.stream = nil - return err -} - -func formatGError(msg string, gErr *C.GError, args ...any) error { - if gErr != nil && gErr.message != nil { - msg += ": " + C.GoString(gErr.message) - C.g_error_free(gErr) - } - return fmt.Errorf(msg, args...) -} diff --git a/v3/internal/buildinfo/buildinfo.go b/v3/internal/buildinfo/buildinfo.go deleted file mode 100644 index 930831f1f..000000000 --- a/v3/internal/buildinfo/buildinfo.go +++ /dev/null @@ -1,40 +0,0 @@ -package buildinfo - -import ( - "fmt" - "runtime/debug" - "slices" - - "github.com/samber/lo" -) - -type Info struct { - Development bool - Version string - BuildSettings map[string]string - wailsPackage *debug.Module -} - -func Get() (*Info, error) { - - var result Info - - // BuildInfo contains the build info for the application - var BuildInfo *debug.BuildInfo - - var ok bool - BuildInfo, ok = debug.ReadBuildInfo() - if !ok { - return nil, fmt.Errorf("could not read build info from binary") - } - result.BuildSettings = lo.Associate(BuildInfo.Settings, func(setting debug.BuildSetting) (string, string) { - return setting.Key, setting.Value - }) - result.Version = BuildInfo.Main.Version - result.Development = -1 != slices.IndexFunc(BuildInfo.Settings, func(setting debug.BuildSetting) bool { - return setting.Key == "vcs" && setting.Value == "git" - }) - - return &result, nil - -} diff --git a/v3/internal/buildinfo/buildinfo_test.go b/v3/internal/buildinfo/buildinfo_test.go deleted file mode 100644 index ab79f63f8..000000000 --- a/v3/internal/buildinfo/buildinfo_test.go +++ /dev/null @@ -1,13 +0,0 @@ -package buildinfo - -import ( - "testing" -) - -func TestGet(t *testing.T) { - result, err := Get() - if err != nil { - t.Error(err) - } - _ = result -} diff --git a/v3/internal/capabilities/capabilities.go b/v3/internal/capabilities/capabilities.go deleted file mode 100644 index 248f0fb99..000000000 --- a/v3/internal/capabilities/capabilities.go +++ /dev/null @@ -1,18 +0,0 @@ -package capabilities - -import "encoding/json" - -type Capabilities struct { - HasNativeDrag bool - GTKVersion int - WebKitVersion string -} - -func (c Capabilities) AsBytes() []byte { - // JSON encode - result, err := json.Marshal(c) - if err != nil { - return []byte("{}") - } - return result -} diff --git a/v3/internal/capabilities/capabilities_darwin.go b/v3/internal/capabilities/capabilities_darwin.go deleted file mode 100644 index 5cd0b600c..000000000 --- a/v3/internal/capabilities/capabilities_darwin.go +++ /dev/null @@ -1,9 +0,0 @@ -//go:build darwin - -package capabilities - -func newCapabilities(_ string) Capabilities { - c := Capabilities{} - c.HasNativeDrag = false - return c -} diff --git a/v3/internal/capabilities/capabilities_linux.go b/v3/internal/capabilities/capabilities_linux.go deleted file mode 100644 index b2cae5f96..000000000 --- a/v3/internal/capabilities/capabilities_linux.go +++ /dev/null @@ -1,11 +0,0 @@ -//go:build linux && !gtk4 - -package capabilities - -func NewCapabilities() Capabilities { - return Capabilities{ - HasNativeDrag: true, - GTKVersion: 3, - WebKitVersion: "4.1", - } -} diff --git a/v3/internal/capabilities/capabilities_linux_gtk4.go b/v3/internal/capabilities/capabilities_linux_gtk4.go deleted file mode 100644 index 7ebe43b66..000000000 --- a/v3/internal/capabilities/capabilities_linux_gtk4.go +++ /dev/null @@ -1,11 +0,0 @@ -//go:build linux && gtk4 - -package capabilities - -func NewCapabilities() Capabilities { - return Capabilities{ - HasNativeDrag: true, - GTKVersion: 4, - WebKitVersion: "6.0", - } -} diff --git a/v3/internal/capabilities/capabilities_windows.go b/v3/internal/capabilities/capabilities_windows.go deleted file mode 100644 index 78591dcf6..000000000 --- a/v3/internal/capabilities/capabilities_windows.go +++ /dev/null @@ -1,22 +0,0 @@ -//go:build windows - -package capabilities - -import "github.com/wailsapp/go-webview2/webviewloader" - -type version string - -func (v version) IsAtLeast(input string) bool { - result, err := webviewloader.CompareBrowserVersions(string(v), input) - if err != nil { - return false - } - return result >= 0 -} - -func NewCapabilities(webview2version string) Capabilities { - webview2 := version(webview2version) - c := Capabilities{} - c.HasNativeDrag = webview2.IsAtLeast("113.0.0.0") - return c -} diff --git a/v3/internal/changelog/changelog.go b/v3/internal/changelog/changelog.go deleted file mode 100644 index 2690ea674..000000000 --- a/v3/internal/changelog/changelog.go +++ /dev/null @@ -1,80 +0,0 @@ -package changelog - -import ( - "fmt" - "io" - "os" - "strings" -) - -// ProcessorResult contains the results of processing a changelog file -type ProcessorResult struct { - Entry *ChangelogEntry - ValidationResult ValidationResult - HasContent bool -} - -// Processor handles the complete changelog processing pipeline -type Processor struct { - parser *Parser - validator *Validator -} - -// NewProcessor creates a new changelog processor with parser and validator -func NewProcessor() *Processor { - return &Processor{ - parser: NewParser(), - validator: NewValidator(), - } -} - -// ProcessFile processes a changelog file and returns the parsed and validated entry -func (p *Processor) ProcessFile(filePath string) (*ProcessorResult, error) { - file, err := os.Open(filePath) - if err != nil { - return nil, fmt.Errorf("failed to open changelog file %s: %w", filePath, err) - } - defer file.Close() - - return p.ProcessReader(file) -} - -// ProcessReader processes changelog content from a reader -func (p *Processor) ProcessReader(reader io.Reader) (*ProcessorResult, error) { - // Parse the content - entry, err := p.parser.ParseContent(reader) - if err != nil { - return nil, fmt.Errorf("failed to parse changelog content: %w", err) - } - - // Validate the parsed entry - validationResult := p.validator.ValidateEntry(entry) - - result := &ProcessorResult{ - Entry: entry, - ValidationResult: validationResult, - HasContent: entry.HasContent(), - } - - return result, nil -} - -// ProcessString processes changelog content from a string -func (p *Processor) ProcessString(content string) (*ProcessorResult, error) { - return p.ProcessReader(strings.NewReader(content)) -} - -// ValidateFile validates a changelog file without parsing it into an entry -func (p *Processor) ValidateFile(filePath string) (ValidationResult, error) { - content, err := os.ReadFile(filePath) - if err != nil { - return ValidationResult{Valid: false}, fmt.Errorf("failed to read changelog file %s: %w", filePath, err) - } - - return p.validator.ValidateContent(string(content)), nil -} - -// ValidateString validates changelog content from a string -func (p *Processor) ValidateString(content string) ValidationResult { - return p.validator.ValidateContent(content) -} diff --git a/v3/internal/changelog/changelog_test.go b/v3/internal/changelog/changelog_test.go deleted file mode 100644 index 88a2ddbd0..000000000 --- a/v3/internal/changelog/changelog_test.go +++ /dev/null @@ -1,296 +0,0 @@ -package changelog - -import ( - "os" - "path/filepath" - "strings" - "testing" -) - -func TestNewProcessor(t *testing.T) { - processor := NewProcessor() - if processor == nil { - t.Fatal("NewProcessor() returned nil") - } - if processor.parser == nil { - t.Error("parser not initialized") - } - if processor.validator == nil { - t.Error("validator not initialized") - } -} - -func TestProcessString_ValidContent(t *testing.T) { - processor := NewProcessor() - content := `# Unreleased Changes - -## Added -- Add support for custom window icons in application options -- Add new SetWindowIcon() method to runtime API (#1234) - -## Fixed -- Fix memory leak in event system during window close operations (#5678)` - - result, err := processor.ProcessString(content) - if err != nil { - t.Fatalf("ProcessString() returned error: %v", err) - } - - if !result.HasContent { - t.Error("Result should have content") - } - - if !result.ValidationResult.Valid { - t.Errorf("Validation should pass, got errors: %s", result.ValidationResult.GetValidationSummary()) - } - - // Check parsed content - if len(result.Entry.Added) != 2 { - t.Errorf("Expected 2 Added items, got %d", len(result.Entry.Added)) - } - if len(result.Entry.Fixed) != 1 { - t.Errorf("Expected 1 Fixed item, got %d", len(result.Entry.Fixed)) - } -} - -func TestProcessString_InvalidContent(t *testing.T) { - processor := NewProcessor() - content := `# Unreleased Changes - -## Added -- Short -- TODO: add proper description - -## InvalidSection -- This section is invalid` - - result, err := processor.ProcessString(content) - if err != nil { - t.Fatalf("ProcessString() returned error: %v", err) - } - - if result.ValidationResult.Valid { - t.Error("Validation should fail for invalid content") - } - - // The parser will parse the Added section correctly (2 items) - // The InvalidSection won't be parsed since it's not a valid section name - if len(result.Entry.Added) != 2 { - t.Errorf("Expected 2 Added items, got %d", len(result.Entry.Added)) - } - - // Should have validation errors - if len(result.ValidationResult.Errors) == 0 { - t.Error("Should have validation errors") - } -} - -func TestProcessString_EmptyContent(t *testing.T) { - processor := NewProcessor() - content := `# Unreleased Changes - -## Added - - -## Changed -` - - result, err := processor.ProcessString(content) - if err != nil { - t.Fatalf("ProcessString() returned error: %v", err) - } - - if result.HasContent { - t.Error("Result should not have content") - } - - if result.ValidationResult.Valid { - t.Error("Validation should fail for empty content") - } -} - -func TestProcessFile_ValidFile(t *testing.T) { - processor := NewProcessor() - - // Create a temporary file - tmpDir := t.TempDir() - filePath := filepath.Join(tmpDir, "test_changelog.md") - - content := `# Unreleased Changes - -## Added -- Add support for custom window icons in application options -- Add new SetWindowIcon() method to runtime API (#1234) - -## Fixed -- Fix memory leak in event system during window close operations (#5678)` - - err := os.WriteFile(filePath, []byte(content), 0644) - if err != nil { - t.Fatalf("Failed to create test file: %v", err) - } - - result, err := processor.ProcessFile(filePath) - if err != nil { - t.Fatalf("ProcessFile() returned error: %v", err) - } - - if !result.HasContent { - t.Error("Result should have content") - } - - if !result.ValidationResult.Valid { - t.Errorf("Validation should pass, got errors: %s", result.ValidationResult.GetValidationSummary()) - } - - // Check parsed content - if len(result.Entry.Added) != 2 { - t.Errorf("Expected 2 Added items, got %d", len(result.Entry.Added)) - } - if len(result.Entry.Fixed) != 1 { - t.Errorf("Expected 1 Fixed item, got %d", len(result.Entry.Fixed)) - } -} - -func TestProcessFile_NonexistentFile(t *testing.T) { - processor := NewProcessor() - - result, err := processor.ProcessFile("/nonexistent/file.md") - if err == nil { - t.Error("ProcessFile() should return error for nonexistent file") - } - if result != nil { - t.Error("ProcessFile() should return nil result for nonexistent file") - } -} - -func TestValidateString_ValidContent(t *testing.T) { - processor := NewProcessor() - content := `# Unreleased Changes - -## Added -- Add support for custom window icons in application options - -## Fixed -- Fix memory leak in event system during window close operations` - - result := processor.ValidateString(content) - if !result.Valid { - t.Errorf("ValidateString() should be valid, got errors: %s", result.GetValidationSummary()) - } -} - -func TestValidateString_InvalidContent(t *testing.T) { - processor := NewProcessor() - content := `# Unreleased Changes - -## InvalidSection -- This section is invalid - -- Bullet point outside section` - - result := processor.ValidateString(content) - if result.Valid { - t.Error("ValidateString() should be invalid") - } - - if len(result.Errors) == 0 { - t.Error("ValidateString() should return validation errors") - } -} - -func TestValidateFile_ValidFile(t *testing.T) { - processor := NewProcessor() - - // Create a temporary file - tmpDir := t.TempDir() - filePath := filepath.Join(tmpDir, "test_changelog.md") - - content := `# Unreleased Changes - -## Added -- Add support for custom window icons in application options - -## Fixed -- Fix memory leak in event system during window close operations` - - err := os.WriteFile(filePath, []byte(content), 0644) - if err != nil { - t.Fatalf("Failed to create test file: %v", err) - } - - result, err := processor.ValidateFile(filePath) - if err != nil { - t.Fatalf("ValidateFile() returned error: %v", err) - } - - if !result.Valid { - t.Errorf("ValidateFile() should be valid, got errors: %s", result.GetValidationSummary()) - } -} - -func TestValidateFile_NonexistentFile(t *testing.T) { - processor := NewProcessor() - - result, err := processor.ValidateFile("/nonexistent/file.md") - if err == nil { - t.Error("ValidateFile() should return error for nonexistent file") - } - if result.Valid { - t.Error("ValidateFile() should return invalid result for nonexistent file") - } -} - -func TestProcessorResult_Integration(t *testing.T) { - processor := NewProcessor() - content := `# Unreleased Changes - -## Added -- Add comprehensive changelog processing system -- Add validation for Keep a Changelog format compliance - -## Changed -- Update changelog workflow to use automated processing - -## Fixed -- Fix parsing issues with various markdown bullet styles -- Fix validation edge cases for empty content sections` - - result, err := processor.ProcessString(content) - if err != nil { - t.Fatalf("ProcessString() returned error: %v", err) - } - - // Test that we can format the result for different outputs - changelogFormat := result.Entry.FormatForChangelog() - if !strings.Contains(changelogFormat, "### Added") { - t.Error("FormatForChangelog() should contain Added section") - } - if !strings.Contains(changelogFormat, "### Changed") { - t.Error("FormatForChangelog() should contain Changed section") - } - if !strings.Contains(changelogFormat, "### Fixed") { - t.Error("FormatForChangelog() should contain Fixed section") - } - - releaseFormat := result.Entry.FormatForRelease() - if !strings.Contains(releaseFormat, "## ✨ Added") { - t.Error("FormatForRelease() should contain Added section with emoji") - } - if !strings.Contains(releaseFormat, "## 🔄 Changed") { - t.Error("FormatForRelease() should contain Changed section with emoji") - } - if !strings.Contains(releaseFormat, "## 🐛 Fixed") { - t.Error("FormatForRelease() should contain Fixed section with emoji") - } - - // Test validation summary - if !result.ValidationResult.Valid { - t.Errorf("Validation should pass, got: %s", result.ValidationResult.GetValidationSummary()) - } - - summary := result.ValidationResult.GetValidationSummary() - if !strings.Contains(summary, "Validation passed") { - t.Errorf("Validation summary should indicate success, got: %s", summary) - } -} diff --git a/v3/internal/changelog/parser.go b/v3/internal/changelog/parser.go deleted file mode 100644 index 3557e26a0..000000000 --- a/v3/internal/changelog/parser.go +++ /dev/null @@ -1,239 +0,0 @@ -package changelog - -import ( - "bufio" - "fmt" - "io" - "regexp" - "strings" - "time" -) - -// ChangelogEntry represents a parsed changelog entry following Keep a Changelog format -type ChangelogEntry struct { - Version string `json:"version"` - Date time.Time `json:"date"` - Added []string `json:"added"` - Changed []string `json:"changed"` - Fixed []string `json:"fixed"` - Deprecated []string `json:"deprecated"` - Removed []string `json:"removed"` - Security []string `json:"security"` -} - -// Parser handles parsing of UNRELEASED_CHANGELOG.md files -type Parser struct { - // sectionRegex matches section headers like "## Added", "## Changed", etc. - sectionRegex *regexp.Regexp - // bulletRegex matches bullet points (- or *) - bulletRegex *regexp.Regexp -} - -// NewParser creates a new changelog parser -func NewParser() *Parser { - return &Parser{ - sectionRegex: regexp.MustCompile(`^##\s+(Added|Changed|Fixed|Deprecated|Removed|Security)\s*$`), - bulletRegex: regexp.MustCompile(`^[\s]*[-*]\s+(.+)$`), - } -} - -// ParseContent parses changelog content from a reader and returns a ChangelogEntry -func (p *Parser) ParseContent(reader io.Reader) (*ChangelogEntry, error) { - entry := &ChangelogEntry{ - Added: []string{}, - Changed: []string{}, - Fixed: []string{}, - Deprecated: []string{}, - Removed: []string{}, - Security: []string{}, - } - - scanner := bufio.NewScanner(reader) - var currentSection string - var inExampleSection bool - - for scanner.Scan() { - line := strings.TrimSpace(scanner.Text()) - - // Skip empty lines and comments - if line == "" || strings.HasPrefix(line, "") { - continue - } - - // Skip the main title - if strings.HasPrefix(line, "# Unreleased Changes") { - continue - } - - // Check if we're entering the example section - if strings.HasPrefix(line, "---") || strings.HasPrefix(line, "### Example Entries") { - inExampleSection = true - continue - } - - // Skip example section content - if inExampleSection { - continue - } - - // Check for section headers - if strings.HasPrefix(line, "##") { - if matches := p.sectionRegex.FindStringSubmatch(line); len(matches) > 1 { - currentSection = strings.ToLower(matches[1]) - } else { - // Invalid section header - reset current section - currentSection = "" - } - continue - } - - // Parse bullet points - if matches := p.bulletRegex.FindStringSubmatch(line); len(matches) > 1 { - content := strings.TrimSpace(matches[1]) - if content == "" { - continue - } - - switch currentSection { - case "added": - entry.Added = append(entry.Added, content) - case "changed": - entry.Changed = append(entry.Changed, content) - case "fixed": - entry.Fixed = append(entry.Fixed, content) - case "deprecated": - entry.Deprecated = append(entry.Deprecated, content) - case "removed": - entry.Removed = append(entry.Removed, content) - case "security": - entry.Security = append(entry.Security, content) - } - } - } - - if err := scanner.Err(); err != nil { - return nil, fmt.Errorf("error reading changelog content: %w", err) - } - - return entry, nil -} - -// HasContent checks if the changelog entry contains any actual content -func (entry *ChangelogEntry) HasContent() bool { - return len(entry.Added) > 0 || - len(entry.Changed) > 0 || - len(entry.Fixed) > 0 || - len(entry.Deprecated) > 0 || - len(entry.Removed) > 0 || - len(entry.Security) > 0 -} - -// FormatForChangelog formats the entry for insertion into the main changelog -func (entry *ChangelogEntry) FormatForChangelog() string { - var builder strings.Builder - - if len(entry.Added) > 0 { - builder.WriteString("### Added\n") - for _, item := range entry.Added { - builder.WriteString(fmt.Sprintf("- %s\n", item)) - } - builder.WriteString("\n") - } - - if len(entry.Changed) > 0 { - builder.WriteString("### Changed\n") - for _, item := range entry.Changed { - builder.WriteString(fmt.Sprintf("- %s\n", item)) - } - builder.WriteString("\n") - } - - if len(entry.Fixed) > 0 { - builder.WriteString("### Fixed\n") - for _, item := range entry.Fixed { - builder.WriteString(fmt.Sprintf("- %s\n", item)) - } - builder.WriteString("\n") - } - - if len(entry.Deprecated) > 0 { - builder.WriteString("### Deprecated\n") - for _, item := range entry.Deprecated { - builder.WriteString(fmt.Sprintf("- %s\n", item)) - } - builder.WriteString("\n") - } - - if len(entry.Removed) > 0 { - builder.WriteString("### Removed\n") - for _, item := range entry.Removed { - builder.WriteString(fmt.Sprintf("- %s\n", item)) - } - builder.WriteString("\n") - } - - if len(entry.Security) > 0 { - builder.WriteString("### Security\n") - for _, item := range entry.Security { - builder.WriteString(fmt.Sprintf("- %s\n", item)) - } - builder.WriteString("\n") - } - - return strings.TrimSpace(builder.String()) -} - -// FormatForRelease formats the entry for GitHub release notes -func (entry *ChangelogEntry) FormatForRelease() string { - var builder strings.Builder - - if len(entry.Added) > 0 { - builder.WriteString("## ✨ Added\n") - for _, item := range entry.Added { - builder.WriteString(fmt.Sprintf("- %s\n", item)) - } - builder.WriteString("\n") - } - - if len(entry.Changed) > 0 { - builder.WriteString("## 🔄 Changed\n") - for _, item := range entry.Changed { - builder.WriteString(fmt.Sprintf("- %s\n", item)) - } - builder.WriteString("\n") - } - - if len(entry.Fixed) > 0 { - builder.WriteString("## 🐛 Fixed\n") - for _, item := range entry.Fixed { - builder.WriteString(fmt.Sprintf("- %s\n", item)) - } - builder.WriteString("\n") - } - - if len(entry.Deprecated) > 0 { - builder.WriteString("## ⚠️ Deprecated\n") - for _, item := range entry.Deprecated { - builder.WriteString(fmt.Sprintf("- %s\n", item)) - } - builder.WriteString("\n") - } - - if len(entry.Removed) > 0 { - builder.WriteString("## 🗑️ Removed\n") - for _, item := range entry.Removed { - builder.WriteString(fmt.Sprintf("- %s\n", item)) - } - builder.WriteString("\n") - } - - if len(entry.Security) > 0 { - builder.WriteString("## 🔒 Security\n") - for _, item := range entry.Security { - builder.WriteString(fmt.Sprintf("- %s\n", item)) - } - builder.WriteString("\n") - } - - return strings.TrimSpace(builder.String()) -} diff --git a/v3/internal/changelog/parser_test.go b/v3/internal/changelog/parser_test.go deleted file mode 100644 index fbdb35c8c..000000000 --- a/v3/internal/changelog/parser_test.go +++ /dev/null @@ -1,468 +0,0 @@ -package changelog - -import ( - "strings" - "testing" -) - -func TestNewParser(t *testing.T) { - parser := NewParser() - if parser == nil { - t.Fatal("NewParser() returned nil") - } - if parser.sectionRegex == nil { - t.Error("sectionRegex not initialized") - } - if parser.bulletRegex == nil { - t.Error("bulletRegex not initialized") - } -} - -func TestParseContent_EmptyContent(t *testing.T) { - parser := NewParser() - reader := strings.NewReader("") - - entry, err := parser.ParseContent(reader) - if err != nil { - t.Fatalf("ParseContent() returned error: %v", err) - } - - if entry.HasContent() { - t.Error("Empty content should not have content") - } -} - -func TestParseContent_OnlyComments(t *testing.T) { - parser := NewParser() - content := `# Unreleased Changes - - - - -## Added - - -## Changed -` - - reader := strings.NewReader(content) - entry, err := parser.ParseContent(reader) - if err != nil { - t.Fatalf("ParseContent() returned error: %v", err) - } - - if entry.HasContent() { - t.Error("Content with only comments should not have content") - } -} - -func TestParseContent_BasicSections(t *testing.T) { - parser := NewParser() - content := `# Unreleased Changes - -## Added -- New feature A -- New feature B - -## Changed -- Changed feature C - -## Fixed -- Fixed bug D -- Fixed bug E - -## Deprecated -- Deprecated feature F - -## Removed -- Removed feature G - -## Security -- Security fix H` - - reader := strings.NewReader(content) - entry, err := parser.ParseContent(reader) - if err != nil { - t.Fatalf("ParseContent() returned error: %v", err) - } - - // Test Added section - if len(entry.Added) != 2 { - t.Errorf("Expected 2 Added items, got %d", len(entry.Added)) - } - if entry.Added[0] != "New feature A" { - t.Errorf("Expected 'New feature A', got '%s'", entry.Added[0]) - } - if entry.Added[1] != "New feature B" { - t.Errorf("Expected 'New feature B', got '%s'", entry.Added[1]) - } - - // Test Changed section - if len(entry.Changed) != 1 { - t.Errorf("Expected 1 Changed item, got %d", len(entry.Changed)) - } - if entry.Changed[0] != "Changed feature C" { - t.Errorf("Expected 'Changed feature C', got '%s'", entry.Changed[0]) - } - - // Test Fixed section - if len(entry.Fixed) != 2 { - t.Errorf("Expected 2 Fixed items, got %d", len(entry.Fixed)) - } - if entry.Fixed[0] != "Fixed bug D" { - t.Errorf("Expected 'Fixed bug D', got '%s'", entry.Fixed[0]) - } - if entry.Fixed[1] != "Fixed bug E" { - t.Errorf("Expected 'Fixed bug E', got '%s'", entry.Fixed[1]) - } - - // Test Deprecated section - if len(entry.Deprecated) != 1 { - t.Errorf("Expected 1 Deprecated item, got %d", len(entry.Deprecated)) - } - if entry.Deprecated[0] != "Deprecated feature F" { - t.Errorf("Expected 'Deprecated feature F', got '%s'", entry.Deprecated[0]) - } - - // Test Removed section - if len(entry.Removed) != 1 { - t.Errorf("Expected 1 Removed item, got %d", len(entry.Removed)) - } - if entry.Removed[0] != "Removed feature G" { - t.Errorf("Expected 'Removed feature G', got '%s'", entry.Removed[0]) - } - - // Test Security section - if len(entry.Security) != 1 { - t.Errorf("Expected 1 Security item, got %d", len(entry.Security)) - } - if entry.Security[0] != "Security fix H" { - t.Errorf("Expected 'Security fix H', got '%s'", entry.Security[0]) - } - - // Test HasContent - if !entry.HasContent() { - t.Error("Entry should have content") - } -} - -func TestParseContent_WithExampleSection(t *testing.T) { - parser := NewParser() - content := `# Unreleased Changes - -## Added -- Real feature A - -## Changed -- Real change B - ---- - -### Example Entries: - -**Added:** -- Example feature that should be ignored -- Another example that should be ignored - -**Fixed:** -- Example fix that should be ignored` - - reader := strings.NewReader(content) - entry, err := parser.ParseContent(reader) - if err != nil { - t.Fatalf("ParseContent() returned error: %v", err) - } - - // Should only have the real entries, not the examples - if len(entry.Added) != 1 { - t.Errorf("Expected 1 Added item, got %d", len(entry.Added)) - } - if entry.Added[0] != "Real feature A" { - t.Errorf("Expected 'Real feature A', got '%s'", entry.Added[0]) - } - - if len(entry.Changed) != 1 { - t.Errorf("Expected 1 Changed item, got %d", len(entry.Changed)) - } - if entry.Changed[0] != "Real change B" { - t.Errorf("Expected 'Real change B', got '%s'", entry.Changed[0]) - } - - // Should not have any Fixed items from examples - if len(entry.Fixed) != 0 { - t.Errorf("Expected 0 Fixed items, got %d", len(entry.Fixed)) - } -} - -func TestParseContent_DifferentBulletStyles(t *testing.T) { - parser := NewParser() - content := `# Unreleased Changes - -## Added -- Feature with dash -* Feature with asterisk - - Indented feature with dash - * Indented feature with asterisk - -## Fixed -- Feature with extra spaces -* Another with extra spaces` - - reader := strings.NewReader(content) - entry, err := parser.ParseContent(reader) - if err != nil { - t.Fatalf("ParseContent() returned error: %v", err) - } - - expectedAdded := []string{ - "Feature with dash", - "Feature with asterisk", - "Indented feature with dash", - "Indented feature with asterisk", - } - - if len(entry.Added) != len(expectedAdded) { - t.Errorf("Expected %d Added items, got %d", len(expectedAdded), len(entry.Added)) - } - - for i, expected := range expectedAdded { - if i >= len(entry.Added) || entry.Added[i] != expected { - t.Errorf("Expected Added[%d] to be '%s', got '%s'", i, expected, entry.Added[i]) - } - } - - expectedFixed := []string{ - "Feature with extra spaces", - "Another with extra spaces", - } - - if len(entry.Fixed) != len(expectedFixed) { - t.Errorf("Expected %d Fixed items, got %d", len(expectedFixed), len(entry.Fixed)) - } - - for i, expected := range expectedFixed { - if i >= len(entry.Fixed) || entry.Fixed[i] != expected { - t.Errorf("Expected Fixed[%d] to be '%s', got '%s'", i, expected, entry.Fixed[i]) - } - } -} - -func TestParseContent_EmptyBulletPoints(t *testing.T) { - parser := NewParser() - content := `# Unreleased Changes - -## Added -- Valid feature -- -- -- Another valid feature - -## Fixed -- -- Valid fix` - - reader := strings.NewReader(content) - entry, err := parser.ParseContent(reader) - if err != nil { - t.Fatalf("ParseContent() returned error: %v", err) - } - - // Should skip empty bullet points - expectedAdded := []string{ - "Valid feature", - "Another valid feature", - } - - if len(entry.Added) != len(expectedAdded) { - t.Errorf("Expected %d Added items, got %d", len(expectedAdded), len(entry.Added)) - } - - for i, expected := range expectedAdded { - if i >= len(entry.Added) || entry.Added[i] != expected { - t.Errorf("Expected Added[%d] to be '%s', got '%s'", i, expected, entry.Added[i]) - } - } - - expectedFixed := []string{"Valid fix"} - if len(entry.Fixed) != len(expectedFixed) { - t.Errorf("Expected %d Fixed items, got %d", len(expectedFixed), len(entry.Fixed)) - } - if entry.Fixed[0] != "Valid fix" { - t.Errorf("Expected 'Valid fix', got '%s'", entry.Fixed[0]) - } -} - -func TestHasContent(t *testing.T) { - tests := []struct { - name string - entry ChangelogEntry - expected bool - }{ - { - name: "Empty entry", - entry: ChangelogEntry{}, - expected: false, - }, - { - name: "Entry with Added items", - entry: ChangelogEntry{ - Added: []string{"Feature A"}, - }, - expected: true, - }, - { - name: "Entry with Changed items", - entry: ChangelogEntry{ - Changed: []string{"Change A"}, - }, - expected: true, - }, - { - name: "Entry with Fixed items", - entry: ChangelogEntry{ - Fixed: []string{"Fix A"}, - }, - expected: true, - }, - { - name: "Entry with Deprecated items", - entry: ChangelogEntry{ - Deprecated: []string{"Deprecated A"}, - }, - expected: true, - }, - { - name: "Entry with Removed items", - entry: ChangelogEntry{ - Removed: []string{"Removed A"}, - }, - expected: true, - }, - { - name: "Entry with Security items", - entry: ChangelogEntry{ - Security: []string{"Security A"}, - }, - expected: true, - }, - { - name: "Entry with multiple sections", - entry: ChangelogEntry{ - Added: []string{"Feature A"}, - Fixed: []string{"Fix A"}, - Changed: []string{"Change A"}, - }, - expected: true, - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - if got := tt.entry.HasContent(); got != tt.expected { - t.Errorf("HasContent() = %v, want %v", got, tt.expected) - } - }) - } -} - -func TestFormatForChangelog(t *testing.T) { - entry := ChangelogEntry{ - Added: []string{"New feature A", "New feature B"}, - Changed: []string{"Changed feature C"}, - Fixed: []string{"Fixed bug D"}, - Deprecated: []string{"Deprecated feature E"}, - Removed: []string{"Removed feature F"}, - Security: []string{"Security fix G"}, - } - - result := entry.FormatForChangelog() - - expected := `### Added -- New feature A -- New feature B - -### Changed -- Changed feature C - -### Fixed -- Fixed bug D - -### Deprecated -- Deprecated feature E - -### Removed -- Removed feature F - -### Security -- Security fix G` - - if result != expected { - t.Errorf("FormatForChangelog() mismatch.\nExpected:\n%s\n\nGot:\n%s", expected, result) - } -} - -func TestFormatForChangelog_PartialSections(t *testing.T) { - entry := ChangelogEntry{ - Added: []string{"New feature A"}, - Fixed: []string{"Fixed bug B"}, - // Other sections empty - } - - result := entry.FormatForChangelog() - - expected := `### Added -- New feature A - -### Fixed -- Fixed bug B` - - if result != expected { - t.Errorf("FormatForChangelog() mismatch.\nExpected:\n%s\n\nGot:\n%s", expected, result) - } -} - -func TestFormatForRelease(t *testing.T) { - entry := ChangelogEntry{ - Added: []string{"New feature A", "New feature B"}, - Changed: []string{"Changed feature C"}, - Fixed: []string{"Fixed bug D"}, - Deprecated: []string{"Deprecated feature E"}, - Removed: []string{"Removed feature F"}, - Security: []string{"Security fix G"}, - } - - result := entry.FormatForRelease() - - expected := `## ✨ Added -- New feature A -- New feature B - -## 🔄 Changed -- Changed feature C - -## 🐛 Fixed -- Fixed bug D - -## ⚠️ Deprecated -- Deprecated feature E - -## 🗑️ Removed -- Removed feature F - -## 🔒 Security -- Security fix G` - - if result != expected { - t.Errorf("FormatForRelease() mismatch.\nExpected:\n%s\n\nGot:\n%s", expected, result) - } -} - -func TestFormatForRelease_EmptyEntry(t *testing.T) { - entry := ChangelogEntry{} - - result := entry.FormatForRelease() - - if result != "" { - t.Errorf("FormatForRelease() for empty entry should return empty string, got: %s", result) - } -} diff --git a/v3/internal/changelog/validator.go b/v3/internal/changelog/validator.go deleted file mode 100644 index 20bff9ac3..000000000 --- a/v3/internal/changelog/validator.go +++ /dev/null @@ -1,316 +0,0 @@ -package changelog - -import ( - "fmt" - "regexp" - "strings" -) - -// ValidationError represents a validation error with context -type ValidationError struct { - Field string - Message string - Line int -} - -func (e ValidationError) Error() string { - if e.Line > 0 { - return fmt.Sprintf("validation error at line %d in %s: %s", e.Line, e.Field, e.Message) - } - return fmt.Sprintf("validation error in %s: %s", e.Field, e.Message) -} - -// ValidationResult contains the results of validation -type ValidationResult struct { - Valid bool - Errors []ValidationError -} - -// Validator handles validation of changelog content and entries -type Validator struct { - // Regex patterns for validation - sectionHeaderRegex *regexp.Regexp - bulletPointRegex *regexp.Regexp - urlRegex *regexp.Regexp - issueRefRegex *regexp.Regexp -} - -// NewValidator creates a new changelog validator -func NewValidator() *Validator { - return &Validator{ - sectionHeaderRegex: regexp.MustCompile(`^##\s+(Added|Changed|Fixed|Deprecated|Removed|Security)\s*$`), - bulletPointRegex: regexp.MustCompile(`^[\s]*[-*]\s+(.+)$`), - urlRegex: regexp.MustCompile(`https?://[^\s]+`), - issueRefRegex: regexp.MustCompile(`#\d+`), - } -} - -// ValidateContent validates raw changelog content for proper formatting -func (v *Validator) ValidateContent(content string) ValidationResult { - result := ValidationResult{ - Valid: true, - Errors: []ValidationError{}, - } - - lines := strings.Split(content, "\n") - var currentSection string - var hasValidSections bool - var inExampleSection bool - lineNum := 0 - - for _, line := range lines { - lineNum++ - trimmedLine := strings.TrimSpace(line) - - // Skip empty lines and comments - if trimmedLine == "" || strings.HasPrefix(trimmedLine, "") { - continue - } - - // Skip the main title - if strings.HasPrefix(trimmedLine, "# Unreleased Changes") { - continue - } - - // Check if we're entering the example section - if strings.HasPrefix(trimmedLine, "---") || strings.HasPrefix(trimmedLine, "### Example Entries") { - inExampleSection = true - continue - } - - // Skip example section content - if inExampleSection { - continue - } - - // Check for section headers - if strings.HasPrefix(trimmedLine, "##") { - if matches := v.sectionHeaderRegex.FindStringSubmatch(trimmedLine); len(matches) > 1 { - currentSection = strings.ToLower(matches[1]) - hasValidSections = true - } else { - result.Valid = false - result.Errors = append(result.Errors, ValidationError{ - Field: "section_header", - Message: fmt.Sprintf("invalid section header format: '%s'. Expected format: '## SectionName'", trimmedLine), - Line: lineNum, - }) - } - continue - } - - // Check bullet points - if strings.HasPrefix(trimmedLine, "-") || strings.HasPrefix(trimmedLine, "*") { - if currentSection == "" { - result.Valid = false - result.Errors = append(result.Errors, ValidationError{ - Field: "bullet_point", - Message: "bullet point found outside of any section", - Line: lineNum, - }) - continue - } - - // Check for empty bullet points first (just "-" or "*" with optional whitespace) - if trimmedLine == "-" || trimmedLine == "*" || strings.TrimSpace(trimmedLine[1:]) == "" { - result.Valid = false - result.Errors = append(result.Errors, ValidationError{ - Field: "bullet_point", - Message: "empty bullet point content", - Line: lineNum, - }) - continue - } - - if matches := v.bulletPointRegex.FindStringSubmatch(trimmedLine); len(matches) > 1 { - content := strings.TrimSpace(matches[1]) - if content == "" { - result.Valid = false - result.Errors = append(result.Errors, ValidationError{ - Field: "bullet_point", - Message: "empty bullet point content", - Line: lineNum, - }) - } else { - // Validate bullet point content - v.validateBulletPointContent(content, lineNum, &result) - } - } else { - result.Valid = false - result.Errors = append(result.Errors, ValidationError{ - Field: "bullet_point", - Message: fmt.Sprintf("malformed bullet point: '%s'", trimmedLine), - Line: lineNum, - }) - } - continue - } - - // Check for unexpected content - if trimmedLine != "" && !strings.HasPrefix(trimmedLine, " - - - - - - - - - - - - - diff --git a/v3/internal/commands/build_assets/android/app/src/main/java/com/wails/app/MainActivity.java b/v3/internal/commands/build_assets/android/app/src/main/java/com/wails/app/MainActivity.java deleted file mode 100644 index 3067fee09..000000000 --- a/v3/internal/commands/build_assets/android/app/src/main/java/com/wails/app/MainActivity.java +++ /dev/null @@ -1,198 +0,0 @@ -package com.wails.app; - -import android.annotation.SuppressLint; -import android.os.Bundle; -import android.util.Log; -import android.webkit.WebResourceRequest; -import android.webkit.WebResourceResponse; -import android.webkit.WebSettings; -import android.webkit.WebView; -import android.webkit.WebViewClient; - -import androidx.annotation.Nullable; -import androidx.appcompat.app.AppCompatActivity; -import androidx.webkit.WebViewAssetLoader; -import com.wails.app.BuildConfig; - -/** - * MainActivity hosts the WebView and manages the Wails application lifecycle. - * It uses WebViewAssetLoader to serve assets from the Go library without - * requiring a network server. - */ -public class MainActivity extends AppCompatActivity { - private static final String TAG = "WailsActivity"; - private static final String WAILS_SCHEME = "https"; - private static final String WAILS_HOST = "wails.localhost"; - - private WebView webView; - private WailsBridge bridge; - private WebViewAssetLoader assetLoader; - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - setContentView(R.layout.activity_main); - - // Initialize the native Go library - bridge = new WailsBridge(this); - bridge.initialize(); - - // Set up WebView - setupWebView(); - - // Load the application - loadApplication(); - } - - @SuppressLint("SetJavaScriptEnabled") - private void setupWebView() { - webView = findViewById(R.id.webview); - - // Configure WebView settings - WebSettings settings = webView.getSettings(); - settings.setJavaScriptEnabled(true); - settings.setDomStorageEnabled(true); - settings.setDatabaseEnabled(true); - settings.setAllowFileAccess(false); - settings.setAllowContentAccess(false); - settings.setMediaPlaybackRequiresUserGesture(false); - settings.setMixedContentMode(WebSettings.MIXED_CONTENT_NEVER_ALLOW); - - // Enable debugging in debug builds - if (BuildConfig.DEBUG) { - WebView.setWebContentsDebuggingEnabled(true); - } - - // Set up asset loader for serving local assets - assetLoader = new WebViewAssetLoader.Builder() - .setDomain(WAILS_HOST) - .addPathHandler("/", new WailsPathHandler(bridge)) - .build(); - - // Set up WebView client to intercept requests - webView.setWebViewClient(new WebViewClient() { - @Nullable - @Override - public WebResourceResponse shouldInterceptRequest(WebView view, WebResourceRequest request) { - String url = request.getUrl().toString(); - Log.d(TAG, "Intercepting request: " + url); - - // Handle wails.localhost requests - if (request.getUrl().getHost() != null && - request.getUrl().getHost().equals(WAILS_HOST)) { - - // For wails API calls (runtime, capabilities, etc.), we need to pass the full URL - // including query string because WebViewAssetLoader.PathHandler strips query params - String path = request.getUrl().getPath(); - if (path != null && path.startsWith("/wails/")) { - // Get full path with query string for runtime calls - String fullPath = path; - String query = request.getUrl().getQuery(); - if (query != null && !query.isEmpty()) { - fullPath = path + "?" + query; - } - Log.d(TAG, "Wails API call detected, full path: " + fullPath); - - // Call bridge directly with full path - byte[] data = bridge.serveAsset(fullPath, request.getMethod(), "{}"); - if (data != null && data.length > 0) { - java.io.InputStream inputStream = new java.io.ByteArrayInputStream(data); - java.util.Map headers = new java.util.HashMap<>(); - headers.put("Access-Control-Allow-Origin", "*"); - headers.put("Cache-Control", "no-cache"); - headers.put("Content-Type", "application/json"); - - return new WebResourceResponse( - "application/json", - "UTF-8", - 200, - "OK", - headers, - inputStream - ); - } - // Return error response if data is null - return new WebResourceResponse( - "application/json", - "UTF-8", - 500, - "Internal Error", - new java.util.HashMap<>(), - new java.io.ByteArrayInputStream("{}".getBytes()) - ); - } - - // For regular assets, use the asset loader - return assetLoader.shouldInterceptRequest(request.getUrl()); - } - - return super.shouldInterceptRequest(view, request); - } - - @Override - public void onPageFinished(WebView view, String url) { - super.onPageFinished(view, url); - Log.d(TAG, "Page loaded: " + url); - // Inject Wails runtime - bridge.injectRuntime(webView, url); - } - }); - - // Add JavaScript interface for Go communication - webView.addJavascriptInterface(new WailsJSBridge(bridge, webView), "wails"); - } - - private void loadApplication() { - // Load the main page from the asset server - String url = WAILS_SCHEME + "://" + WAILS_HOST + "/"; - Log.d(TAG, "Loading URL: " + url); - webView.loadUrl(url); - } - - /** - * Execute JavaScript in the WebView from the Go side - */ - public void executeJavaScript(final String js) { - runOnUiThread(() -> { - if (webView != null) { - webView.evaluateJavascript(js, null); - } - }); - } - - @Override - protected void onResume() { - super.onResume(); - if (bridge != null) { - bridge.onResume(); - } - } - - @Override - protected void onPause() { - super.onPause(); - if (bridge != null) { - bridge.onPause(); - } - } - - @Override - protected void onDestroy() { - super.onDestroy(); - if (bridge != null) { - bridge.shutdown(); - } - if (webView != null) { - webView.destroy(); - } - } - - @Override - public void onBackPressed() { - if (webView != null && webView.canGoBack()) { - webView.goBack(); - } else { - super.onBackPressed(); - } - } -} diff --git a/v3/internal/commands/build_assets/android/app/src/main/java/com/wails/app/WailsBridge.java b/v3/internal/commands/build_assets/android/app/src/main/java/com/wails/app/WailsBridge.java deleted file mode 100644 index 3dab65247..000000000 --- a/v3/internal/commands/build_assets/android/app/src/main/java/com/wails/app/WailsBridge.java +++ /dev/null @@ -1,214 +0,0 @@ -package com.wails.app; - -import android.content.Context; -import android.util.Log; -import android.webkit.WebView; - -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.atomic.AtomicInteger; - -/** - * WailsBridge manages the connection between the Java/Android side and the Go native library. - * It handles: - * - Loading and initializing the native Go library - * - Serving asset requests from Go - * - Passing messages between JavaScript and Go - * - Managing callbacks for async operations - */ -public class WailsBridge { - private static final String TAG = "WailsBridge"; - - static { - // Load the native Go library - System.loadLibrary("wails"); - } - - private final Context context; - private final AtomicInteger callbackIdGenerator = new AtomicInteger(0); - private final ConcurrentHashMap pendingAssetCallbacks = new ConcurrentHashMap<>(); - private final ConcurrentHashMap pendingMessageCallbacks = new ConcurrentHashMap<>(); - private WebView webView; - private volatile boolean initialized = false; - - // Native methods - implemented in Go - private static native void nativeInit(WailsBridge bridge); - private static native void nativeShutdown(); - private static native void nativeOnResume(); - private static native void nativeOnPause(); - private static native void nativeOnPageFinished(String url); - private static native byte[] nativeServeAsset(String path, String method, String headers); - private static native String nativeHandleMessage(String message); - private static native String nativeGetAssetMimeType(String path); - - public WailsBridge(Context context) { - this.context = context; - } - - /** - * Initialize the native Go library - */ - public void initialize() { - if (initialized) { - return; - } - - Log.i(TAG, "Initializing Wails bridge..."); - try { - nativeInit(this); - initialized = true; - Log.i(TAG, "Wails bridge initialized successfully"); - } catch (Exception e) { - Log.e(TAG, "Failed to initialize Wails bridge", e); - } - } - - /** - * Shutdown the native Go library - */ - public void shutdown() { - if (!initialized) { - return; - } - - Log.i(TAG, "Shutting down Wails bridge..."); - try { - nativeShutdown(); - initialized = false; - } catch (Exception e) { - Log.e(TAG, "Error during shutdown", e); - } - } - - /** - * Called when the activity resumes - */ - public void onResume() { - if (initialized) { - nativeOnResume(); - } - } - - /** - * Called when the activity pauses - */ - public void onPause() { - if (initialized) { - nativeOnPause(); - } - } - - /** - * Serve an asset from the Go asset server - * @param path The URL path requested - * @param method The HTTP method - * @param headers The request headers as JSON - * @return The asset data, or null if not found - */ - public byte[] serveAsset(String path, String method, String headers) { - if (!initialized) { - Log.w(TAG, "Bridge not initialized, cannot serve asset: " + path); - return null; - } - - Log.d(TAG, "Serving asset: " + path); - try { - return nativeServeAsset(path, method, headers); - } catch (Exception e) { - Log.e(TAG, "Error serving asset: " + path, e); - return null; - } - } - - /** - * Get the MIME type for an asset - * @param path The asset path - * @return The MIME type string - */ - public String getAssetMimeType(String path) { - if (!initialized) { - return "application/octet-stream"; - } - - try { - String mimeType = nativeGetAssetMimeType(path); - return mimeType != null ? mimeType : "application/octet-stream"; - } catch (Exception e) { - Log.e(TAG, "Error getting MIME type for: " + path, e); - return "application/octet-stream"; - } - } - - /** - * Handle a message from JavaScript - * @param message The message from JavaScript (JSON) - * @return The response to send back to JavaScript (JSON) - */ - public String handleMessage(String message) { - if (!initialized) { - Log.w(TAG, "Bridge not initialized, cannot handle message"); - return "{\"error\":\"Bridge not initialized\"}"; - } - - Log.d(TAG, "Handling message from JS: " + message); - try { - return nativeHandleMessage(message); - } catch (Exception e) { - Log.e(TAG, "Error handling message", e); - return "{\"error\":\"" + e.getMessage() + "\"}"; - } - } - - /** - * Inject the Wails runtime JavaScript into the WebView. - * Called when the page finishes loading. - * @param webView The WebView to inject into - * @param url The URL that finished loading - */ - public void injectRuntime(WebView webView, String url) { - this.webView = webView; - // Notify Go side that page has finished loading so it can inject the runtime - Log.d(TAG, "Page finished loading: " + url + ", notifying Go side"); - if (initialized) { - nativeOnPageFinished(url); - } - } - - /** - * Execute JavaScript in the WebView (called from Go side) - * @param js The JavaScript code to execute - */ - public void executeJavaScript(String js) { - if (webView != null) { - webView.post(() -> webView.evaluateJavascript(js, null)); - } - } - - /** - * Called from Go when an event needs to be emitted to JavaScript - * @param eventName The event name - * @param eventData The event data (JSON) - */ - public void emitEvent(String eventName, String eventData) { - String js = String.format("window.wails && window.wails._emit('%s', %s);", - escapeJsString(eventName), eventData); - executeJavaScript(js); - } - - private String escapeJsString(String str) { - return str.replace("\\", "\\\\") - .replace("'", "\\'") - .replace("\n", "\\n") - .replace("\r", "\\r"); - } - - // Callback interfaces - public interface AssetCallback { - void onAssetReady(byte[] data, String mimeType); - void onAssetError(String error); - } - - public interface MessageCallback { - void onResponse(String response); - void onError(String error); - } -} diff --git a/v3/internal/commands/build_assets/android/app/src/main/java/com/wails/app/WailsJSBridge.java b/v3/internal/commands/build_assets/android/app/src/main/java/com/wails/app/WailsJSBridge.java deleted file mode 100644 index 98ae5b247..000000000 --- a/v3/internal/commands/build_assets/android/app/src/main/java/com/wails/app/WailsJSBridge.java +++ /dev/null @@ -1,142 +0,0 @@ -package com.wails.app; - -import android.util.Log; -import android.webkit.JavascriptInterface; -import android.webkit.WebView; -import com.wails.app.BuildConfig; - -/** - * WailsJSBridge provides the JavaScript interface that allows the web frontend - * to communicate with the Go backend. This is exposed to JavaScript as the - * `window.wails` object. - * - * Similar to iOS's WKScriptMessageHandler but using Android's addJavascriptInterface. - */ -public class WailsJSBridge { - private static final String TAG = "WailsJSBridge"; - - private final WailsBridge bridge; - private final WebView webView; - - public WailsJSBridge(WailsBridge bridge, WebView webView) { - this.bridge = bridge; - this.webView = webView; - } - - /** - * Send a message to Go and return the response synchronously. - * Called from JavaScript: wails.invoke(message) - * - * @param message The message to send (JSON string) - * @return The response from Go (JSON string) - */ - @JavascriptInterface - public String invoke(String message) { - Log.d(TAG, "Invoke called: " + message); - return bridge.handleMessage(message); - } - - /** - * Send a message to Go asynchronously. - * The response will be sent back via a callback. - * Called from JavaScript: wails.invokeAsync(callbackId, message) - * - * @param callbackId The callback ID to use for the response - * @param message The message to send (JSON string) - */ - @JavascriptInterface - public void invokeAsync(final String callbackId, final String message) { - Log.d(TAG, "InvokeAsync called: " + message); - - // Handle in background thread to not block JavaScript - new Thread(() -> { - try { - String response = bridge.handleMessage(message); - sendCallback(callbackId, response, null); - } catch (Exception e) { - Log.e(TAG, "Error in async invoke", e); - sendCallback(callbackId, null, e.getMessage()); - } - }).start(); - } - - /** - * Log a message from JavaScript to Android's logcat - * Called from JavaScript: wails.log(level, message) - * - * @param level The log level (debug, info, warn, error) - * @param message The message to log - */ - @JavascriptInterface - public void log(String level, String message) { - switch (level.toLowerCase()) { - case "debug": - Log.d(TAG + "/JS", message); - break; - case "info": - Log.i(TAG + "/JS", message); - break; - case "warn": - Log.w(TAG + "/JS", message); - break; - case "error": - Log.e(TAG + "/JS", message); - break; - default: - Log.v(TAG + "/JS", message); - break; - } - } - - /** - * Get the platform name - * Called from JavaScript: wails.platform() - * - * @return "android" - */ - @JavascriptInterface - public String platform() { - return "android"; - } - - /** - * Check if we're running in debug mode - * Called from JavaScript: wails.isDebug() - * - * @return true if debug build, false otherwise - */ - @JavascriptInterface - public boolean isDebug() { - return BuildConfig.DEBUG; - } - - /** - * Send a callback response to JavaScript - */ - private void sendCallback(String callbackId, String result, String error) { - final String js; - if (error != null) { - js = String.format( - "window.wails && window.wails._callback('%s', null, '%s');", - escapeJsString(callbackId), - escapeJsString(error) - ); - } else { - js = String.format( - "window.wails && window.wails._callback('%s', %s, null);", - escapeJsString(callbackId), - result != null ? result : "null" - ); - } - - webView.post(() -> webView.evaluateJavascript(js, null)); - } - - private String escapeJsString(String str) { - if (str == null) return ""; - return str.replace("\\", "\\\\") - .replace("'", "\\'") - .replace("\n", "\\n") - .replace("\r", "\\r"); - } -} diff --git a/v3/internal/commands/build_assets/android/app/src/main/java/com/wails/app/WailsPathHandler.java b/v3/internal/commands/build_assets/android/app/src/main/java/com/wails/app/WailsPathHandler.java deleted file mode 100644 index 326fa9b4d..000000000 --- a/v3/internal/commands/build_assets/android/app/src/main/java/com/wails/app/WailsPathHandler.java +++ /dev/null @@ -1,118 +0,0 @@ -package com.wails.app; - -import android.net.Uri; -import android.util.Log; -import android.webkit.WebResourceResponse; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.webkit.WebViewAssetLoader; - -import java.io.ByteArrayInputStream; -import java.io.InputStream; -import java.util.HashMap; -import java.util.Map; - -/** - * WailsPathHandler implements WebViewAssetLoader.PathHandler to serve assets - * from the Go asset server. This allows the WebView to load assets without - * using a network server, similar to iOS's WKURLSchemeHandler. - */ -public class WailsPathHandler implements WebViewAssetLoader.PathHandler { - private static final String TAG = "WailsPathHandler"; - - private final WailsBridge bridge; - - public WailsPathHandler(WailsBridge bridge) { - this.bridge = bridge; - } - - @Nullable - @Override - public WebResourceResponse handle(@NonNull String path) { - Log.d(TAG, "Handling path: " + path); - - // Normalize path - if (path.isEmpty() || path.equals("/")) { - path = "/index.html"; - } - - // Get asset from Go - byte[] data = bridge.serveAsset(path, "GET", "{}"); - - if (data == null || data.length == 0) { - Log.w(TAG, "Asset not found: " + path); - return null; // Return null to let WebView handle 404 - } - - // Determine MIME type - String mimeType = bridge.getAssetMimeType(path); - Log.d(TAG, "Serving " + path + " with type " + mimeType + " (" + data.length + " bytes)"); - - // Create response - InputStream inputStream = new ByteArrayInputStream(data); - Map headers = new HashMap<>(); - headers.put("Access-Control-Allow-Origin", "*"); - headers.put("Cache-Control", "no-cache"); - - return new WebResourceResponse( - mimeType, - "UTF-8", - 200, - "OK", - headers, - inputStream - ); - } - - /** - * Determine MIME type from file extension - */ - private String getMimeType(String path) { - String lowerPath = path.toLowerCase(); - - if (lowerPath.endsWith(".html") || lowerPath.endsWith(".htm")) { - return "text/html"; - } else if (lowerPath.endsWith(".js") || lowerPath.endsWith(".mjs")) { - return "application/javascript"; - } else if (lowerPath.endsWith(".css")) { - return "text/css"; - } else if (lowerPath.endsWith(".json")) { - return "application/json"; - } else if (lowerPath.endsWith(".png")) { - return "image/png"; - } else if (lowerPath.endsWith(".jpg") || lowerPath.endsWith(".jpeg")) { - return "image/jpeg"; - } else if (lowerPath.endsWith(".gif")) { - return "image/gif"; - } else if (lowerPath.endsWith(".svg")) { - return "image/svg+xml"; - } else if (lowerPath.endsWith(".ico")) { - return "image/x-icon"; - } else if (lowerPath.endsWith(".woff")) { - return "font/woff"; - } else if (lowerPath.endsWith(".woff2")) { - return "font/woff2"; - } else if (lowerPath.endsWith(".ttf")) { - return "font/ttf"; - } else if (lowerPath.endsWith(".eot")) { - return "application/vnd.ms-fontobject"; - } else if (lowerPath.endsWith(".xml")) { - return "application/xml"; - } else if (lowerPath.endsWith(".txt")) { - return "text/plain"; - } else if (lowerPath.endsWith(".wasm")) { - return "application/wasm"; - } else if (lowerPath.endsWith(".mp3")) { - return "audio/mpeg"; - } else if (lowerPath.endsWith(".mp4")) { - return "video/mp4"; - } else if (lowerPath.endsWith(".webm")) { - return "video/webm"; - } else if (lowerPath.endsWith(".webp")) { - return "image/webp"; - } - - return "application/octet-stream"; - } -} diff --git a/v3/internal/commands/build_assets/android/app/src/main/res/layout/activity_main.xml b/v3/internal/commands/build_assets/android/app/src/main/res/layout/activity_main.xml deleted file mode 100644 index f278384c7..000000000 --- a/v3/internal/commands/build_assets/android/app/src/main/res/layout/activity_main.xml +++ /dev/null @@ -1,12 +0,0 @@ - - - - - - diff --git a/v3/internal/commands/build_assets/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/v3/internal/commands/build_assets/android/app/src/main/res/mipmap-hdpi/ic_launcher.png deleted file mode 100644 index 9409abebe..000000000 Binary files a/v3/internal/commands/build_assets/android/app/src/main/res/mipmap-hdpi/ic_launcher.png and /dev/null differ diff --git a/v3/internal/commands/build_assets/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png b/v3/internal/commands/build_assets/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png deleted file mode 100644 index 9409abebe..000000000 Binary files a/v3/internal/commands/build_assets/android/app/src/main/res/mipmap-hdpi/ic_launcher_round.png and /dev/null differ diff --git a/v3/internal/commands/build_assets/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/v3/internal/commands/build_assets/android/app/src/main/res/mipmap-mdpi/ic_launcher.png deleted file mode 100644 index 5b6acc048..000000000 Binary files a/v3/internal/commands/build_assets/android/app/src/main/res/mipmap-mdpi/ic_launcher.png and /dev/null differ diff --git a/v3/internal/commands/build_assets/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png b/v3/internal/commands/build_assets/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png deleted file mode 100644 index 5b6acc048..000000000 Binary files a/v3/internal/commands/build_assets/android/app/src/main/res/mipmap-mdpi/ic_launcher_round.png and /dev/null differ diff --git a/v3/internal/commands/build_assets/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/v3/internal/commands/build_assets/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png deleted file mode 100644 index 1c2c66452..000000000 Binary files a/v3/internal/commands/build_assets/android/app/src/main/res/mipmap-xhdpi/ic_launcher.png and /dev/null differ diff --git a/v3/internal/commands/build_assets/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/v3/internal/commands/build_assets/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png deleted file mode 100644 index 1c2c66452..000000000 Binary files a/v3/internal/commands/build_assets/android/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png and /dev/null differ diff --git a/v3/internal/commands/build_assets/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/v3/internal/commands/build_assets/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png deleted file mode 100644 index be557d897..000000000 Binary files a/v3/internal/commands/build_assets/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png and /dev/null differ diff --git a/v3/internal/commands/build_assets/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/v3/internal/commands/build_assets/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png deleted file mode 100644 index be557d897..000000000 Binary files a/v3/internal/commands/build_assets/android/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png and /dev/null differ diff --git a/v3/internal/commands/build_assets/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/v3/internal/commands/build_assets/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png deleted file mode 100644 index 4507f32a5..000000000 Binary files a/v3/internal/commands/build_assets/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png and /dev/null differ diff --git a/v3/internal/commands/build_assets/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/v3/internal/commands/build_assets/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png deleted file mode 100644 index 4507f32a5..000000000 Binary files a/v3/internal/commands/build_assets/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png and /dev/null differ diff --git a/v3/internal/commands/build_assets/android/app/src/main/res/values/colors.xml b/v3/internal/commands/build_assets/android/app/src/main/res/values/colors.xml deleted file mode 100644 index dd33f3b7d..000000000 --- a/v3/internal/commands/build_assets/android/app/src/main/res/values/colors.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - #3574D4 - #2C5FB8 - #1B2636 - #FFFFFFFF - #FF000000 - diff --git a/v3/internal/commands/build_assets/android/app/src/main/res/values/strings.xml b/v3/internal/commands/build_assets/android/app/src/main/res/values/strings.xml deleted file mode 100644 index 3ed9e4717..000000000 --- a/v3/internal/commands/build_assets/android/app/src/main/res/values/strings.xml +++ /dev/null @@ -1,4 +0,0 @@ - - - Wails App - diff --git a/v3/internal/commands/build_assets/android/app/src/main/res/values/themes.xml b/v3/internal/commands/build_assets/android/app/src/main/res/values/themes.xml deleted file mode 100644 index be8a282b2..000000000 --- a/v3/internal/commands/build_assets/android/app/src/main/res/values/themes.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - diff --git a/v3/internal/commands/build_assets/android/build.gradle b/v3/internal/commands/build_assets/android/build.gradle deleted file mode 100644 index d7fbab39a..000000000 --- a/v3/internal/commands/build_assets/android/build.gradle +++ /dev/null @@ -1,4 +0,0 @@ -// Top-level build file where you can add configuration options common to all sub-projects/modules. -plugins { - id 'com.android.application' version '8.7.3' apply false -} diff --git a/v3/internal/commands/build_assets/android/gradle.properties b/v3/internal/commands/build_assets/android/gradle.properties deleted file mode 100644 index b9d4426d5..000000000 --- a/v3/internal/commands/build_assets/android/gradle.properties +++ /dev/null @@ -1,26 +0,0 @@ -# Project-wide Gradle settings. -# IDE (e.g. Android Studio) users: -# Gradle settings configured through the IDE *will override* -# any settings specified in this file. - -# For more details on how to configure your build environment visit -# http://www.gradle.org/docs/current/userguide/build_environment.html - -# Specifies the JVM arguments used for the daemon process. -# The setting is particularly useful for tweaking memory settings. -org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8 - -# When configured, Gradle will run in incubating parallel mode. -# This option should only be used with decoupled projects. For more details, visit -# https://developer.android.com/build/optimize-your-build#parallel -# org.gradle.parallel=true - -# AndroidX package structure to make it clearer which packages are bundled with the -# Android operating system, and which are packaged with your app's APK -# https://developer.android.com/topic/libraries/support-library/androidx-rn -android.useAndroidX=true - -# Enables namespacing of each library's R class so that its R class includes only the -# resources declared in the library itself and none from the library's dependencies, -# thereby reducing the size of the R class for that library -android.nonTransitiveRClass=true diff --git a/v3/internal/commands/build_assets/android/gradle/wrapper/gradle-wrapper.jar b/v3/internal/commands/build_assets/android/gradle/wrapper/gradle-wrapper.jar deleted file mode 100644 index f8e1ee312..000000000 Binary files a/v3/internal/commands/build_assets/android/gradle/wrapper/gradle-wrapper.jar and /dev/null differ diff --git a/v3/internal/commands/build_assets/android/gradle/wrapper/gradle-wrapper.properties b/v3/internal/commands/build_assets/android/gradle/wrapper/gradle-wrapper.properties deleted file mode 100644 index 23449a2b5..000000000 --- a/v3/internal/commands/build_assets/android/gradle/wrapper/gradle-wrapper.properties +++ /dev/null @@ -1,7 +0,0 @@ -distributionBase=GRADLE_USER_HOME -distributionPath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-9.2.1-bin.zip -networkTimeout=10000 -validateDistributionUrl=true -zipStoreBase=GRADLE_USER_HOME -zipStorePath=wrapper/dists diff --git a/v3/internal/commands/build_assets/android/gradlew b/v3/internal/commands/build_assets/android/gradlew deleted file mode 100755 index adff685a0..000000000 --- a/v3/internal/commands/build_assets/android/gradlew +++ /dev/null @@ -1,248 +0,0 @@ -#!/bin/sh - -# -# Copyright © 2015 the original authors. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# https://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -# SPDX-License-Identifier: Apache-2.0 -# - -############################################################################## -# -# Gradle start up script for POSIX generated by Gradle. -# -# Important for running: -# -# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is -# noncompliant, but you have some other compliant shell such as ksh or -# bash, then to run this script, type that shell name before the whole -# command line, like: -# -# ksh Gradle -# -# Busybox and similar reduced shells will NOT work, because this script -# requires all of these POSIX shell features: -# * functions; -# * expansions «$var», «${var}», «${var:-default}», «${var+SET}», -# «${var#prefix}», «${var%suffix}», and «$( cmd )»; -# * compound commands having a testable exit status, especially «case»; -# * various built-in commands including «command», «set», and «ulimit». -# -# Important for patching: -# -# (2) This script targets any POSIX shell, so it avoids extensions provided -# by Bash, Ksh, etc; in particular arrays are avoided. -# -# The "traditional" practice of packing multiple parameters into a -# space-separated string is a well documented source of bugs and security -# problems, so this is (mostly) avoided, by progressively accumulating -# options in "$@", and eventually passing that to Java. -# -# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS, -# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly; -# see the in-line comments for details. -# -# There are tweaks for specific operating systems such as AIX, CygWin, -# Darwin, MinGW, and NonStop. -# -# (3) This script is generated from the Groovy template -# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt -# within the Gradle project. -# -# You can find Gradle at https://github.com/gradle/gradle/. -# -############################################################################## - -# Attempt to set APP_HOME - -# Resolve links: $0 may be a link -app_path=$0 - -# Need this for daisy-chained symlinks. -while - APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path - [ -h "$app_path" ] -do - ls=$( ls -ld "$app_path" ) - link=${ls#*' -> '} - case $link in #( - /*) app_path=$link ;; #( - *) app_path=$APP_HOME$link ;; - esac -done - -# This is normally unused -# shellcheck disable=SC2034 -APP_BASE_NAME=${0##*/} -# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) -APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit - -# Use the maximum available, or set MAX_FD != -1 to use that value. -MAX_FD=maximum - -warn () { - echo "$*" -} >&2 - -die () { - echo - echo "$*" - echo - exit 1 -} >&2 - -# OS specific support (must be 'true' or 'false'). -cygwin=false -msys=false -darwin=false -nonstop=false -case "$( uname )" in #( - CYGWIN* ) cygwin=true ;; #( - Darwin* ) darwin=true ;; #( - MSYS* | MINGW* ) msys=true ;; #( - NONSTOP* ) nonstop=true ;; -esac - - - -# Determine the Java command to use to start the JVM. -if [ -n "$JAVA_HOME" ] ; then - if [ -x "$JAVA_HOME/jre/sh/java" ] ; then - # IBM's JDK on AIX uses strange locations for the executables - JAVACMD=$JAVA_HOME/jre/sh/java - else - JAVACMD=$JAVA_HOME/bin/java - fi - if [ ! -x "$JAVACMD" ] ; then - die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." - fi -else - JAVACMD=java - if ! command -v java >/dev/null 2>&1 - then - die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. - -Please set the JAVA_HOME variable in your environment to match the -location of your Java installation." - fi -fi - -# Increase the maximum file descriptors if we can. -if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then - case $MAX_FD in #( - max*) - # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC2039,SC3045 - MAX_FD=$( ulimit -H -n ) || - warn "Could not query maximum file descriptor limit" - esac - case $MAX_FD in #( - '' | soft) :;; #( - *) - # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. - # shellcheck disable=SC2039,SC3045 - ulimit -n "$MAX_FD" || - warn "Could not set maximum file descriptor limit to $MAX_FD" - esac -fi - -# Collect all arguments for the java command, stacking in reverse order: -# * args from the command line -# * the main class name -# * -classpath -# * -D...appname settings -# * --module-path (only if needed) -# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables. - -# For Cygwin or MSYS, switch paths to Windows format before running java -if "$cygwin" || "$msys" ; then - APP_HOME=$( cygpath --path --mixed "$APP_HOME" ) - - JAVACMD=$( cygpath --unix "$JAVACMD" ) - - # Now convert the arguments - kludge to limit ourselves to /bin/sh - for arg do - if - case $arg in #( - -*) false ;; # don't mess with options #( - /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath - [ -e "$t" ] ;; #( - *) false ;; - esac - then - arg=$( cygpath --path --ignore --mixed "$arg" ) - fi - # Roll the args list around exactly as many times as the number of - # args, so each arg winds up back in the position where it started, but - # possibly modified. - # - # NB: a `for` loop captures its iteration list before it begins, so - # changing the positional parameters here affects neither the number of - # iterations, nor the values presented in `arg`. - shift # remove old arg - set -- "$@" "$arg" # push replacement arg - done -fi - - -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' - -# Collect all arguments for the java command: -# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, -# and any embedded shellness will be escaped. -# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be -# treated as '${Hostname}' itself on the command line. - -set -- \ - "-Dorg.gradle.appname=$APP_BASE_NAME" \ - -jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \ - "$@" - -# Stop when "xargs" is not available. -if ! command -v xargs >/dev/null 2>&1 -then - die "xargs is not available" -fi - -# Use "xargs" to parse quoted args. -# -# With -n1 it outputs one arg per line, with the quotes and backslashes removed. -# -# In Bash we could simply go: -# -# readarray ARGS < <( xargs -n1 <<<"$var" ) && -# set -- "${ARGS[@]}" "$@" -# -# but POSIX shell has neither arrays nor command substitution, so instead we -# post-process each arg (as a line of input to sed) to backslash-escape any -# character that might be a shell metacharacter, then use eval to reverse -# that process (while maintaining the separation between arguments), and wrap -# the whole thing up as a single "set" statement. -# -# This will of course break if any of these variables contains a newline or -# an unmatched quote. -# - -eval "set -- $( - printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" | - xargs -n1 | - sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' | - tr '\n' ' ' - )" '"$@"' - -exec "$JAVACMD" "$@" diff --git a/v3/internal/commands/build_assets/android/gradlew.bat b/v3/internal/commands/build_assets/android/gradlew.bat deleted file mode 100644 index e509b2dd8..000000000 --- a/v3/internal/commands/build_assets/android/gradlew.bat +++ /dev/null @@ -1,93 +0,0 @@ -@rem -@rem Copyright 2015 the original author or authors. -@rem -@rem Licensed under the Apache License, Version 2.0 (the "License"); -@rem you may not use this file except in compliance with the License. -@rem You may obtain a copy of the License at -@rem -@rem https://www.apache.org/licenses/LICENSE-2.0 -@rem -@rem Unless required by applicable law or agreed to in writing, software -@rem distributed under the License is distributed on an "AS IS" BASIS, -@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -@rem See the License for the specific language governing permissions and -@rem limitations under the License. -@rem -@rem SPDX-License-Identifier: Apache-2.0 -@rem - -@if "%DEBUG%"=="" @echo off -@rem ########################################################################## -@rem -@rem Gradle startup script for Windows -@rem -@rem ########################################################################## - -@rem Set local scope for the variables with windows NT shell -if "%OS%"=="Windows_NT" setlocal - -set DIRNAME=%~dp0 -if "%DIRNAME%"=="" set DIRNAME=. -@rem This is normally unused -set APP_BASE_NAME=%~n0 -set APP_HOME=%DIRNAME% - -@rem Resolve any "." and ".." in APP_HOME to make it shorter. -for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi - -@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" - -@rem Find java.exe -if defined JAVA_HOME goto findJavaFromJavaHome - -set JAVA_EXE=java.exe -%JAVA_EXE% -version >NUL 2>&1 -if %ERRORLEVEL% equ 0 goto execute - -echo. 1>&2 -echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2 -echo. 1>&2 -echo Please set the JAVA_HOME variable in your environment to match the 1>&2 -echo location of your Java installation. 1>&2 - -goto fail - -:findJavaFromJavaHome -set JAVA_HOME=%JAVA_HOME:"=% -set JAVA_EXE=%JAVA_HOME%/bin/java.exe - -if exist "%JAVA_EXE%" goto execute - -echo. 1>&2 -echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2 -echo. 1>&2 -echo Please set the JAVA_HOME variable in your environment to match the 1>&2 -echo location of your Java installation. 1>&2 - -goto fail - -:execute -@rem Setup the command line - - - -@rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %* - -:end -@rem End local scope for the variables with windows NT shell -if %ERRORLEVEL% equ 0 goto mainEnd - -:fail -rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of -rem the _cmd.exe /c_ return code! -set EXIT_CODE=%ERRORLEVEL% -if %EXIT_CODE% equ 0 set EXIT_CODE=1 -if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% -exit /b %EXIT_CODE% - -:mainEnd -if "%OS%"=="Windows_NT" endlocal - -:omega diff --git a/v3/internal/commands/build_assets/android/main_android.go b/v3/internal/commands/build_assets/android/main_android.go deleted file mode 100644 index 70a716473..000000000 --- a/v3/internal/commands/build_assets/android/main_android.go +++ /dev/null @@ -1,11 +0,0 @@ -//go:build android - -package main - -import "github.com/wailsapp/wails/v3/pkg/application" - -func init() { - // Register main function to be called when the Android app initializes - // This is necessary because in c-shared build mode, main() is not automatically called - application.RegisterAndroidMain(main) -} diff --git a/v3/internal/commands/build_assets/android/scripts/deps/install_deps.go b/v3/internal/commands/build_assets/android/scripts/deps/install_deps.go deleted file mode 100644 index d9dfedf80..000000000 --- a/v3/internal/commands/build_assets/android/scripts/deps/install_deps.go +++ /dev/null @@ -1,151 +0,0 @@ -package main - -import ( - "fmt" - "os" - "os/exec" - "path/filepath" - "runtime" - "strings" -) - -func main() { - fmt.Println("Checking Android development dependencies...") - fmt.Println() - - errors := []string{} - - // Check Go - if !checkCommand("go", "version") { - errors = append(errors, "Go is not installed. Install from https://go.dev/dl/") - } else { - fmt.Println("✓ Go is installed") - } - - // Check ANDROID_HOME - androidHome := os.Getenv("ANDROID_HOME") - if androidHome == "" { - androidHome = os.Getenv("ANDROID_SDK_ROOT") - } - if androidHome == "" { - // Try common default locations - home, _ := os.UserHomeDir() - possiblePaths := []string{ - filepath.Join(home, "Android", "Sdk"), - filepath.Join(home, "Library", "Android", "sdk"), - "/usr/local/share/android-sdk", - } - for _, p := range possiblePaths { - if _, err := os.Stat(p); err == nil { - androidHome = p - break - } - } - } - - if androidHome == "" { - errors = append(errors, "ANDROID_HOME not set. Install Android Studio and set ANDROID_HOME environment variable") - } else { - fmt.Printf("✓ ANDROID_HOME: %s\n", androidHome) - } - - // Check adb - if !checkCommand("adb", "version") { - if androidHome != "" { - platformTools := filepath.Join(androidHome, "platform-tools") - errors = append(errors, fmt.Sprintf("adb not found. Add %s to PATH", platformTools)) - } else { - errors = append(errors, "adb not found. Install Android SDK Platform-Tools") - } - } else { - fmt.Println("✓ adb is installed") - } - - // Check emulator - if !checkCommand("emulator", "-list-avds") { - if androidHome != "" { - emulatorPath := filepath.Join(androidHome, "emulator") - errors = append(errors, fmt.Sprintf("emulator not found. Add %s to PATH", emulatorPath)) - } else { - errors = append(errors, "emulator not found. Install Android Emulator via SDK Manager") - } - } else { - fmt.Println("✓ Android Emulator is installed") - } - - // Check NDK - ndkHome := os.Getenv("ANDROID_NDK_HOME") - if ndkHome == "" && androidHome != "" { - // Look for NDK in default location - ndkDir := filepath.Join(androidHome, "ndk") - if entries, err := os.ReadDir(ndkDir); err == nil { - for _, entry := range entries { - if entry.IsDir() { - ndkHome = filepath.Join(ndkDir, entry.Name()) - break - } - } - } - } - - if ndkHome == "" { - errors = append(errors, "Android NDK not found. Install NDK via Android Studio > SDK Manager > SDK Tools > NDK (Side by side)") - } else { - fmt.Printf("✓ Android NDK: %s\n", ndkHome) - } - - // Check Java - if !checkCommand("java", "-version") { - errors = append(errors, "Java not found. Install JDK 11+ (OpenJDK recommended)") - } else { - fmt.Println("✓ Java is installed") - } - - // Check for AVD (Android Virtual Device) - if checkCommand("emulator", "-list-avds") { - cmd := exec.Command("emulator", "-list-avds") - output, err := cmd.Output() - if err == nil && len(strings.TrimSpace(string(output))) > 0 { - avds := strings.Split(strings.TrimSpace(string(output)), "\n") - fmt.Printf("✓ Found %d Android Virtual Device(s)\n", len(avds)) - } else { - fmt.Println("⚠ No Android Virtual Devices found. Create one via Android Studio > Tools > Device Manager") - } - } - - fmt.Println() - - if len(errors) > 0 { - fmt.Println("❌ Missing dependencies:") - for _, err := range errors { - fmt.Printf(" - %s\n", err) - } - fmt.Println() - fmt.Println("Setup instructions:") - fmt.Println("1. Install Android Studio: https://developer.android.com/studio") - fmt.Println("2. Open SDK Manager and install:") - fmt.Println(" - Android SDK Platform (API 34)") - fmt.Println(" - Android SDK Build-Tools") - fmt.Println(" - Android SDK Platform-Tools") - fmt.Println(" - Android Emulator") - fmt.Println(" - NDK (Side by side)") - fmt.Println("3. Set environment variables:") - if runtime.GOOS == "darwin" { - fmt.Println(" export ANDROID_HOME=$HOME/Library/Android/sdk") - } else { - fmt.Println(" export ANDROID_HOME=$HOME/Android/Sdk") - } - fmt.Println(" export PATH=$PATH:$ANDROID_HOME/platform-tools:$ANDROID_HOME/emulator") - fmt.Println("4. Create an AVD via Android Studio > Tools > Device Manager") - os.Exit(1) - } - - fmt.Println("✓ All Android development dependencies are installed!") -} - -func checkCommand(name string, args ...string) bool { - cmd := exec.Command(name, args...) - cmd.Stdout = nil - cmd.Stderr = nil - return cmd.Run() == nil -} diff --git a/v3/internal/commands/build_assets/android/settings.gradle b/v3/internal/commands/build_assets/android/settings.gradle deleted file mode 100644 index a3f3ec3d4..000000000 --- a/v3/internal/commands/build_assets/android/settings.gradle +++ /dev/null @@ -1,18 +0,0 @@ -pluginManagement { - repositories { - google() - mavenCentral() - gradlePluginPortal() - } -} - -dependencyResolutionManagement { - repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) - repositories { - google() - mavenCentral() - } -} - -rootProject.name = "WailsApp" -include ':app' diff --git a/v3/internal/commands/build_assets/appicon.icon/Assets/wails_icon_vector.svg b/v3/internal/commands/build_assets/appicon.icon/Assets/wails_icon_vector.svg deleted file mode 100644 index b099222f2..000000000 --- a/v3/internal/commands/build_assets/appicon.icon/Assets/wails_icon_vector.svg +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/v3/internal/commands/build_assets/appicon.icon/icon.json b/v3/internal/commands/build_assets/appicon.icon/icon.json deleted file mode 100644 index ecf18497c..000000000 --- a/v3/internal/commands/build_assets/appicon.icon/icon.json +++ /dev/null @@ -1,51 +0,0 @@ -{ - "fill" : { - "automatic-gradient" : "extended-gray:1.00000,1.00000" - }, - "groups" : [ - { - "layers" : [ - { - "fill-specializations" : [ - { - "appearance" : "dark", - "value" : { - "solid" : "srgb:0.92143,0.92145,0.92144,1.00000" - } - }, - { - "appearance" : "tinted", - "value" : { - "solid" : "srgb:0.83742,0.83744,0.83743,1.00000" - } - } - ], - "image-name" : "wails_icon_vector.svg", - "name" : "wails_icon_vector", - "position" : { - "scale" : 1.25, - "translation-in-points" : [ - 36.890625, - 4.96875 - ] - } - } - ], - "shadow" : { - "kind" : "neutral", - "opacity" : 0.5 - }, - "specular" : true, - "translucency" : { - "enabled" : true, - "value" : 0.5 - } - } - ], - "supported-platforms" : { - "circles" : [ - "watchOS" - ], - "squares" : "shared" - } -} \ No newline at end of file diff --git a/v3/internal/commands/build_assets/appicon.png b/v3/internal/commands/build_assets/appicon.png deleted file mode 100644 index 63617fe4f..000000000 Binary files a/v3/internal/commands/build_assets/appicon.png and /dev/null differ diff --git a/v3/internal/commands/build_assets/config.yml b/v3/internal/commands/build_assets/config.yml deleted file mode 100644 index 03cbfa9dd..000000000 --- a/v3/internal/commands/build_assets/config.yml +++ /dev/null @@ -1,78 +0,0 @@ -# This file contains the configuration for this project. -# When you update `info` or `fileAssociations`, run `wails3 task common:update:build-assets` to update the assets. -# Note that this will overwrite any changes you have made to the assets. -version: '3' - -# This information is used to generate the build assets. -info: - companyName: "My Company" # The name of the company - productName: "My Product" # The name of the application - productIdentifier: "com.mycompany.myproduct" # The unique product identifier - description: "A program that does X" # The application description - copyright: "(c) 2025, My Company" # Copyright text - comments: "Some Product Comments" # Comments - version: "0.0.1" # The application version - # cfBundleIconName: "appicon" # The macOS icon name in Assets.car icon bundles (optional) - # # Should match the name of your .icon file without the extension - # # If not set and Assets.car exists, defaults to "appicon" - -# iOS build configuration (uncomment to customise iOS project generation) -# Note: Keys under `ios` OVERRIDE values under `info` when set. -# ios: -# # The iOS bundle identifier used in the generated Xcode project (CFBundleIdentifier) -# bundleID: "com.mycompany.myproduct" -# # The display name shown under the app icon (CFBundleDisplayName/CFBundleName) -# displayName: "My Product" -# # The app version to embed in Info.plist (CFBundleShortVersionString/CFBundleVersion) -# version: "0.0.1" -# # The company/organisation name for templates and project settings -# company: "My Company" -# # Additional comments to embed in Info.plist metadata -# comments: "Some Product Comments" - -# Dev mode configuration -dev_mode: - root_path: . - log_level: warn - debounce: 1000 - ignore: - dir: - - .git - - node_modules - - frontend - - bin - file: - - .DS_Store - - .gitignore - - .gitkeep - watched_extension: - - "*.go" - - "*.js" # Watch for changes to JS/TS files included using the //wails:include directive. - - "*.ts" # The frontend directory will be excluded entirely by the setting above. - git_ignore: true - executes: - - cmd: wails3 build DEV=true - type: blocking - - cmd: wails3 task common:dev:frontend - type: background - - cmd: wails3 task run - type: primary - -# File Associations -# More information at: https://v3.wails.io/noit/done/yet -fileAssociations: -# - ext: wails -# name: Wails -# description: Wails Application File -# iconName: wailsFileIcon -# role: Editor -# - ext: jpg -# name: JPEG -# description: Image File -# iconName: jpegFileIcon -# role: Editor -# mimeType: image/jpeg # (optional) - -# Other data -other: - - name: My Other Data \ No newline at end of file diff --git a/v3/internal/commands/build_assets/darwin/Assets.car b/v3/internal/commands/build_assets/darwin/Assets.car deleted file mode 100644 index 4def9c322..000000000 Binary files a/v3/internal/commands/build_assets/darwin/Assets.car and /dev/null differ diff --git a/v3/internal/commands/build_assets/darwin/Taskfile.yml b/v3/internal/commands/build_assets/darwin/Taskfile.yml deleted file mode 100644 index 041bd2091..000000000 --- a/v3/internal/commands/build_assets/darwin/Taskfile.yml +++ /dev/null @@ -1,207 +0,0 @@ -version: '3' - -includes: - common: ../Taskfile.yml - -vars: - # Signing configuration - edit these values for your project - # SIGN_IDENTITY: "Developer ID Application: Your Company (TEAMID)" - # KEYCHAIN_PROFILE: "my-notarize-profile" - # ENTITLEMENTS: "build/darwin/entitlements.plist" - - # Docker image for cross-compilation (used when building on non-macOS) - CROSS_IMAGE: wails-cross - -tasks: - build: - summary: Builds the application - cmds: - - task: '{{if eq OS "darwin"}}build:native{{else}}build:docker{{end}}' - vars: - ARCH: '{{.ARCH}}' - DEV: '{{.DEV}}' - OUTPUT: '{{.OUTPUT}}' - vars: - DEFAULT_OUTPUT: '{{.BIN_DIR}}/{{.APP_NAME}}' - OUTPUT: '{{ .OUTPUT | default .DEFAULT_OUTPUT }}' - - build:native: - summary: Builds the application natively on macOS - internal: true - deps: - - task: common:go:mod:tidy - - task: common:build:frontend - vars: - BUILD_FLAGS: - ref: .BUILD_FLAGS - DEV: - ref: .DEV - - task: common:generate:icons - cmds: - - go build {{.BUILD_FLAGS}} -o {{.OUTPUT}} - vars: - BUILD_FLAGS: '{{if eq .DEV "true"}}-buildvcs=false -gcflags=all="-l"{{else}}-tags production -trimpath -buildvcs=false -ldflags="-w -s"{{end}}' - DEFAULT_OUTPUT: '{{.BIN_DIR}}/{{.APP_NAME}}' - OUTPUT: '{{ .OUTPUT | default .DEFAULT_OUTPUT }}' - env: - GOOS: darwin - CGO_ENABLED: 1 - GOARCH: '{{.ARCH | default ARCH}}' - CGO_CFLAGS: "-mmacosx-version-min=10.15" - CGO_LDFLAGS: "-mmacosx-version-min=10.15" - MACOSX_DEPLOYMENT_TARGET: "10.15" - - build:docker: - summary: Cross-compiles for macOS using Docker (for Linux/Windows hosts) - internal: true - deps: - - task: common:build:frontend - - task: common:generate:icons - preconditions: - - sh: docker info > /dev/null 2>&1 - msg: "Docker is required for cross-compilation. Please install Docker." - - sh: docker image inspect {{.CROSS_IMAGE}} > /dev/null 2>&1 - msg: | - Docker image '{{.CROSS_IMAGE}}' not found. - Build it first: wails3 task setup:docker - cmds: - - docker run --rm -v "{{.ROOT_DIR}}:/app" {{.GO_CACHE_MOUNT}} {{.REPLACE_MOUNTS}} -e APP_NAME="{{.APP_NAME}}" {{.CROSS_IMAGE}} darwin {{.DOCKER_ARCH}} - - docker run --rm -v "{{.ROOT_DIR}}:/app" alpine chown -R $(id -u):$(id -g) /app/bin - - mkdir -p {{.BIN_DIR}} - - mv "bin/{{.APP_NAME}}-darwin-{{.DOCKER_ARCH}}" "{{.OUTPUT}}" - vars: - DOCKER_ARCH: '{{if eq .ARCH "arm64"}}arm64{{else if eq .ARCH "amd64"}}amd64{{else}}arm64{{end}}' - DEFAULT_OUTPUT: '{{.BIN_DIR}}/{{.APP_NAME}}' - OUTPUT: '{{ .OUTPUT | default .DEFAULT_OUTPUT }}' - # Mount Go module cache for faster builds - GO_CACHE_MOUNT: - sh: 'echo "-v ${GOPATH:-$HOME/go}/pkg/mod:/go/pkg/mod"' - # Extract replace directives from go.mod and create -v mounts for each - # Handles both relative (=> ../) and absolute (=> /) paths - REPLACE_MOUNTS: - sh: | - grep -E '^replace .* => ' go.mod 2>/dev/null | while read -r line; do - path=$(echo "$line" | sed -E 's/^replace .* => //' | tr -d '\r') - # Convert relative paths to absolute - if [ "${path#/}" = "$path" ]; then - path="$(cd "$(dirname "$path")" 2>/dev/null && pwd)/$(basename "$path")" - fi - # Only mount if directory exists - if [ -d "$path" ]; then - echo "-v $path:$path:ro" - fi - done | tr '\n' ' ' - - build:universal: - summary: Builds darwin universal binary (arm64 + amd64) - deps: - - task: build - vars: - ARCH: amd64 - OUTPUT: "{{.BIN_DIR}}/{{.APP_NAME}}-amd64" - - task: build - vars: - ARCH: arm64 - OUTPUT: "{{.BIN_DIR}}/{{.APP_NAME}}-arm64" - cmds: - - task: '{{if eq OS "darwin"}}build:universal:lipo:native{{else}}build:universal:lipo:go{{end}}' - - build:universal:lipo:native: - summary: Creates universal binary using native lipo (macOS) - internal: true - cmds: - - lipo -create -output "{{.BIN_DIR}}/{{.APP_NAME}}" "{{.BIN_DIR}}/{{.APP_NAME}}-amd64" "{{.BIN_DIR}}/{{.APP_NAME}}-arm64" - - rm "{{.BIN_DIR}}/{{.APP_NAME}}-amd64" "{{.BIN_DIR}}/{{.APP_NAME}}-arm64" - - build:universal:lipo:go: - summary: Creates universal binary using wails3 tool lipo (Linux/Windows) - internal: true - cmds: - - wails3 tool lipo -output "{{.BIN_DIR}}/{{.APP_NAME}}" -input "{{.BIN_DIR}}/{{.APP_NAME}}-amd64" -input "{{.BIN_DIR}}/{{.APP_NAME}}-arm64" - - rm -f "{{.BIN_DIR}}/{{.APP_NAME}}-amd64" "{{.BIN_DIR}}/{{.APP_NAME}}-arm64" - - package: - summary: Packages the application into a `.app` bundle - deps: - - task: build - cmds: - - task: create:app:bundle - - package:universal: - summary: Packages darwin universal binary (arm64 + amd64) - deps: - - task: build:universal - cmds: - - task: create:app:bundle - - - create:app:bundle: - summary: Creates an `.app` bundle - cmds: - - mkdir -p "{{.BIN_DIR}}/{{.APP_NAME}}.app/Contents/MacOS" - - mkdir -p "{{.BIN_DIR}}/{{.APP_NAME}}.app/Contents/Resources" - - cp build/darwin/icons.icns "{{.BIN_DIR}}/{{.APP_NAME}}.app/Contents/Resources" - - | - if [ -f build/darwin/Assets.car ]; then - cp build/darwin/Assets.car "{{.BIN_DIR}}/{{.APP_NAME}}.app/Contents/Resources" - fi - - cp "{{.BIN_DIR}}/{{.APP_NAME}}" "{{.BIN_DIR}}/{{.APP_NAME}}.app/Contents/MacOS" - - cp build/darwin/Info.plist "{{.BIN_DIR}}/{{.APP_NAME}}.app/Contents" - - task: '{{if eq OS "darwin"}}codesign:adhoc{{else}}codesign:skip{{end}}' - - codesign:adhoc: - summary: Ad-hoc signs the app bundle (macOS only) - internal: true - cmds: - - codesign --force --deep --sign - "{{.BIN_DIR}}/{{.APP_NAME}}.app" - - codesign:skip: - summary: Skips codesigning when cross-compiling - internal: true - cmds: - - 'echo "Skipping codesign (not available on {{OS}}). Sign the .app on macOS before distribution."' - - run: - cmds: - - mkdir -p "{{.BIN_DIR}}/{{.APP_NAME}}.dev.app/Contents/MacOS" - - mkdir -p "{{.BIN_DIR}}/{{.APP_NAME}}.dev.app/Contents/Resources" - - cp build/darwin/icons.icns "{{.BIN_DIR}}/{{.APP_NAME}}.dev.app/Contents/Resources" - - | - if [ -f build/darwin/Assets.car ]; then - cp build/darwin/Assets.car "{{.BIN_DIR}}/{{.APP_NAME}}.dev.app/Contents/Resources" - fi - - cp "{{.BIN_DIR}}/{{.APP_NAME}}" "{{.BIN_DIR}}/{{.APP_NAME}}.dev.app/Contents/MacOS" - - cp "build/darwin/Info.dev.plist" "{{.BIN_DIR}}/{{.APP_NAME}}.dev.app/Contents/Info.plist" - - codesign --force --deep --sign - "{{.BIN_DIR}}/{{.APP_NAME}}.dev.app" - - '{{.BIN_DIR}}/{{.APP_NAME}}.dev.app/Contents/MacOS/{{.APP_NAME}}' - - sign: - summary: Signs the application bundle with Developer ID - desc: | - Signs the .app bundle for distribution. - Configure SIGN_IDENTITY in the vars section at the top of this file. - deps: - - task: package - cmds: - - wails3 tool sign --input "{{.BIN_DIR}}/{{.APP_NAME}}.app" --identity "{{.SIGN_IDENTITY}}" {{if .ENTITLEMENTS}}--entitlements {{.ENTITLEMENTS}}{{end}} - preconditions: - - sh: '[ -n "{{.SIGN_IDENTITY}}" ]' - msg: "SIGN_IDENTITY is required. Set it in the vars section at the top of build/darwin/Taskfile.yml" - - sign:notarize: - summary: Signs and notarizes the application bundle - desc: | - Signs the .app bundle and submits it for notarization. - Configure SIGN_IDENTITY and KEYCHAIN_PROFILE in the vars section at the top of this file. - - Setup (one-time): - wails3 signing credentials --apple-id "you@email.com" --team-id "TEAMID" --password "app-specific-password" --profile "my-profile" - deps: - - task: package - cmds: - - wails3 tool sign --input "{{.BIN_DIR}}/{{.APP_NAME}}.app" --identity "{{.SIGN_IDENTITY}}" {{if .ENTITLEMENTS}}--entitlements {{.ENTITLEMENTS}}{{end}} --notarize --keychain-profile {{.KEYCHAIN_PROFILE}} - preconditions: - - sh: '[ -n "{{.SIGN_IDENTITY}}" ]' - msg: "SIGN_IDENTITY is required. Set it in the vars section at the top of build/darwin/Taskfile.yml" - - sh: '[ -n "{{.KEYCHAIN_PROFILE}}" ]' - msg: "KEYCHAIN_PROFILE is required. Set it in the vars section at the top of build/darwin/Taskfile.yml" diff --git a/v3/internal/commands/build_assets/darwin/icons.icns b/v3/internal/commands/build_assets/darwin/icons.icns deleted file mode 100644 index 458ce1992..000000000 Binary files a/v3/internal/commands/build_assets/darwin/icons.icns and /dev/null differ diff --git a/v3/internal/commands/build_assets/docker/Dockerfile.cross b/v3/internal/commands/build_assets/docker/Dockerfile.cross deleted file mode 100644 index ddae7aa03..000000000 --- a/v3/internal/commands/build_assets/docker/Dockerfile.cross +++ /dev/null @@ -1,198 +0,0 @@ -# Cross-compile Wails v3 apps to any platform -# -# Darwin: Zig + macOS SDK -# Linux: Native GCC when host matches target, Zig for cross-arch -# Windows: Zig + bundled mingw -# -# Usage: -# docker build -t wails-cross -f Dockerfile.cross . -# docker run --rm -v $(pwd):/app wails-cross darwin arm64 -# docker run --rm -v $(pwd):/app wails-cross darwin amd64 -# docker run --rm -v $(pwd):/app wails-cross linux amd64 -# docker run --rm -v $(pwd):/app wails-cross linux arm64 -# docker run --rm -v $(pwd):/app wails-cross windows amd64 -# docker run --rm -v $(pwd):/app wails-cross windows arm64 - -FROM golang:1.25-bookworm - -ARG TARGETARCH - -# Install base tools, GCC, and GTK/WebKit dev packages -RUN apt-get update && apt-get install -y --no-install-recommends \ - curl xz-utils nodejs npm pkg-config gcc libc6-dev \ - libgtk-3-dev libwebkit2gtk-4.1-dev \ - libgtk-4-dev libwebkitgtk-6.0-dev \ - && rm -rf /var/lib/apt/lists/* - -# Install Zig - automatically selects correct binary for host architecture -ARG ZIG_VERSION=0.14.0 -RUN ZIG_ARCH=$(case "${TARGETARCH}" in arm64) echo "aarch64" ;; *) echo "x86_64" ;; esac) && \ - curl -L "https://ziglang.org/download/${ZIG_VERSION}/zig-linux-${ZIG_ARCH}-${ZIG_VERSION}.tar.xz" \ - | tar -xJ -C /opt \ - && ln -s /opt/zig-linux-${ZIG_ARCH}-${ZIG_VERSION}/zig /usr/local/bin/zig - -# Download macOS SDK (required for darwin targets) -ARG MACOS_SDK_VERSION=14.5 -RUN curl -L "https://github.com/joseluisq/macosx-sdks/releases/download/${MACOS_SDK_VERSION}/MacOSX${MACOS_SDK_VERSION}.sdk.tar.xz" \ - | tar -xJ -C /opt \ - && mv /opt/MacOSX${MACOS_SDK_VERSION}.sdk /opt/macos-sdk - -ENV MACOS_SDK_PATH=/opt/macos-sdk - -# Create Zig CC wrappers for cross-compilation targets -# Darwin and Windows use Zig; Linux uses native GCC (run with --platform for cross-arch) - -# Darwin arm64 -COPY <<'ZIGWRAP' /usr/local/bin/zcc-darwin-arm64 -#!/bin/sh -ARGS="" -SKIP_NEXT=0 -for arg in "$@"; do - if [ $SKIP_NEXT -eq 1 ]; then - SKIP_NEXT=0 - continue - fi - case "$arg" in - -target) SKIP_NEXT=1 ;; - -mmacosx-version-min=*) ;; - *) ARGS="$ARGS $arg" ;; - esac -done -exec zig cc -fno-sanitize=all -target aarch64-macos-none -isysroot /opt/macos-sdk -I/opt/macos-sdk/usr/include -L/opt/macos-sdk/usr/lib -F/opt/macos-sdk/System/Library/Frameworks -w $ARGS -ZIGWRAP -RUN chmod +x /usr/local/bin/zcc-darwin-arm64 - -# Darwin amd64 -COPY <<'ZIGWRAP' /usr/local/bin/zcc-darwin-amd64 -#!/bin/sh -ARGS="" -SKIP_NEXT=0 -for arg in "$@"; do - if [ $SKIP_NEXT -eq 1 ]; then - SKIP_NEXT=0 - continue - fi - case "$arg" in - -target) SKIP_NEXT=1 ;; - -mmacosx-version-min=*) ;; - *) ARGS="$ARGS $arg" ;; - esac -done -exec zig cc -fno-sanitize=all -target x86_64-macos-none -isysroot /opt/macos-sdk -I/opt/macos-sdk/usr/include -L/opt/macos-sdk/usr/lib -F/opt/macos-sdk/System/Library/Frameworks -w $ARGS -ZIGWRAP -RUN chmod +x /usr/local/bin/zcc-darwin-amd64 - -# Windows amd64 - uses Zig's bundled mingw -COPY <<'ZIGWRAP' /usr/local/bin/zcc-windows-amd64 -#!/bin/sh -ARGS="" -SKIP_NEXT=0 -for arg in "$@"; do - if [ $SKIP_NEXT -eq 1 ]; then - SKIP_NEXT=0 - continue - fi - case "$arg" in - -target) SKIP_NEXT=1 ;; - -Wl,*) ;; - *) ARGS="$ARGS $arg" ;; - esac -done -exec zig cc -target x86_64-windows-gnu $ARGS -ZIGWRAP -RUN chmod +x /usr/local/bin/zcc-windows-amd64 - -# Windows arm64 - uses Zig's bundled mingw -COPY <<'ZIGWRAP' /usr/local/bin/zcc-windows-arm64 -#!/bin/sh -ARGS="" -SKIP_NEXT=0 -for arg in "$@"; do - if [ $SKIP_NEXT -eq 1 ]; then - SKIP_NEXT=0 - continue - fi - case "$arg" in - -target) SKIP_NEXT=1 ;; - -Wl,*) ;; - *) ARGS="$ARGS $arg" ;; - esac -done -exec zig cc -target aarch64-windows-gnu $ARGS -ZIGWRAP -RUN chmod +x /usr/local/bin/zcc-windows-arm64 - -# Build script -COPY <<'SCRIPT' /usr/local/bin/build.sh -#!/bin/sh -set -e - -OS=${1:-darwin} -ARCH=${2:-arm64} - -case "${OS}-${ARCH}" in - darwin-arm64|darwin-aarch64) - export CC=zcc-darwin-arm64 - export GOARCH=arm64 - export GOOS=darwin - ;; - darwin-amd64|darwin-x86_64) - export CC=zcc-darwin-amd64 - export GOARCH=amd64 - export GOOS=darwin - ;; - linux-arm64|linux-aarch64) - export CC=gcc - export GOARCH=arm64 - export GOOS=linux - ;; - linux-amd64|linux-x86_64) - export CC=gcc - export GOARCH=amd64 - export GOOS=linux - ;; - windows-arm64|windows-aarch64) - export CC=zcc-windows-arm64 - export GOARCH=arm64 - export GOOS=windows - ;; - windows-amd64|windows-x86_64) - export CC=zcc-windows-amd64 - export GOARCH=amd64 - export GOOS=windows - ;; - *) - echo "Usage: " - echo " os: darwin, linux, windows" - echo " arch: amd64, arm64" - exit 1 - ;; -esac - -export CGO_ENABLED=1 -export CGO_CFLAGS="-w" - -# Build frontend if exists and not already built (host may have built it) -if [ -d "frontend" ] && [ -f "frontend/package.json" ] && [ ! -d "frontend/dist" ]; then - (cd frontend && npm install --silent && npm run build --silent) -fi - -# Build -APP=${APP_NAME:-$(basename $(pwd))} -mkdir -p bin - -EXT="" -LDFLAGS="-s -w" -if [ "$GOOS" = "windows" ]; then - EXT=".exe" - LDFLAGS="-s -w -H windowsgui" -fi - -go build -ldflags="$LDFLAGS" -o bin/${APP}-${GOOS}-${GOARCH}${EXT} . -echo "Built: bin/${APP}-${GOOS}-${GOARCH}${EXT}" -SCRIPT -RUN chmod +x /usr/local/bin/build.sh - -WORKDIR /app -ENTRYPOINT ["/usr/local/bin/build.sh"] -CMD ["darwin", "arm64"] diff --git a/v3/internal/commands/build_assets/docker/Dockerfile.server b/v3/internal/commands/build_assets/docker/Dockerfile.server deleted file mode 100644 index 58fb64f76..000000000 --- a/v3/internal/commands/build_assets/docker/Dockerfile.server +++ /dev/null @@ -1,41 +0,0 @@ -# Wails Server Mode Dockerfile -# Multi-stage build for minimal image size - -# Build stage -FROM golang:alpine AS builder - -WORKDIR /app - -# Install build dependencies -RUN apk add --no-cache git - -# Copy source code -COPY . . - -# Remove local replace directive if present (for production builds) -RUN sed -i '/^replace/d' go.mod || true - -# Download dependencies -RUN go mod tidy - -# Build the server binary -RUN go build -tags server -ldflags="-s -w" -o server . - -# Runtime stage - minimal image -FROM gcr.io/distroless/static-debian12 - -# Copy the binary -COPY --from=builder /app/server /server - -# Copy frontend assets -COPY --from=builder /app/frontend/dist /frontend/dist - -# Expose the default port -EXPOSE 8080 - -# Bind to all interfaces (required for Docker) -# Can be overridden at runtime with -e WAILS_SERVER_HOST=... -ENV WAILS_SERVER_HOST=0.0.0.0 - -# Run the server -ENTRYPOINT ["/server"] diff --git a/v3/internal/commands/build_assets/ios/Taskfile.yml b/v3/internal/commands/build_assets/ios/Taskfile.yml deleted file mode 100644 index 8c27f0894..000000000 --- a/v3/internal/commands/build_assets/ios/Taskfile.yml +++ /dev/null @@ -1,293 +0,0 @@ -version: '3' - -includes: - common: ../Taskfile.yml - -vars: - BUNDLE_ID: '{{.BUNDLE_ID | default "com.wails.app"}}' - # SDK_PATH is computed lazily at task-level to avoid errors on non-macOS systems - # Each task that needs it defines SDK_PATH in its own vars section - -tasks: - install:deps: - summary: Check and install iOS development dependencies - cmds: - - go run build/ios/scripts/deps/install_deps.go - env: - TASK_FORCE_YES: '{{if .YES}}true{{else}}false{{end}}' - prompt: This will check and install iOS development dependencies. Continue? - - # Note: Bindings generation may show CGO warnings for iOS C imports. - # These warnings are harmless and don't affect the generated bindings, - # as the generator only needs to parse Go types, not C implementations. - build: - summary: Creates a build of the application for iOS - deps: - - task: generate:ios:overlay - - task: generate:ios:xcode - - task: common:go:mod:tidy - - task: generate:ios:bindings - vars: - BUILD_FLAGS: - ref: .BUILD_FLAGS - - task: common:build:frontend - vars: - BUILD_FLAGS: - ref: .BUILD_FLAGS - PRODUCTION: - ref: .PRODUCTION - - task: common:generate:icons - cmds: - - echo "Building iOS app {{.APP_NAME}}..." - - go build -buildmode=c-archive -overlay build/ios/xcode/overlay.json {{.BUILD_FLAGS}} -o {{.OUTPUT}}.a - vars: - BUILD_FLAGS: '{{if eq .PRODUCTION "true"}}-tags production,ios -trimpath -buildvcs=false -ldflags="-w -s"{{else}}-tags ios,debug -buildvcs=false -gcflags=all="-l"{{end}}' - DEFAULT_OUTPUT: '{{.BIN_DIR}}/{{.APP_NAME}}' - OUTPUT: '{{ .OUTPUT | default .DEFAULT_OUTPUT }}' - SDK_PATH: - sh: xcrun --sdk iphonesimulator --show-sdk-path - env: - GOOS: ios - CGO_ENABLED: 1 - GOARCH: '{{.ARCH | default "arm64"}}' - PRODUCTION: '{{.PRODUCTION | default "false"}}' - CGO_CFLAGS: '-isysroot {{.SDK_PATH}} -target arm64-apple-ios15.0-simulator -mios-simulator-version-min=15.0' - CGO_LDFLAGS: '-isysroot {{.SDK_PATH}} -target arm64-apple-ios15.0-simulator' - - compile:objc: - summary: Compile Objective-C iOS wrapper - vars: - SDK_PATH: - sh: xcrun --sdk iphonesimulator --show-sdk-path - cmds: - - xcrun -sdk iphonesimulator clang -target arm64-apple-ios15.0-simulator -isysroot {{.SDK_PATH}} -framework Foundation -framework UIKit -framework WebKit -o {{.BIN_DIR}}/{{.APP_NAME}} build/ios/main.m - - codesign --force --sign - "{{.BIN_DIR}}/{{.APP_NAME}}" - - package: - summary: Packages a production build of the application into a `.app` bundle - deps: - - task: build - vars: - PRODUCTION: "true" - cmds: - - task: create:app:bundle - - create:app:bundle: - summary: Creates an iOS `.app` bundle - cmds: - - rm -rf "{{.BIN_DIR}}/{{.APP_NAME}}.app" - - mkdir -p "{{.BIN_DIR}}/{{.APP_NAME}}.app" - - cp "{{.BIN_DIR}}/{{.APP_NAME}}" "{{.BIN_DIR}}/{{.APP_NAME}}.app/" - - cp build/ios/Info.plist "{{.BIN_DIR}}/{{.APP_NAME}}.app/" - - | - # Compile asset catalog and embed icons in the app bundle - APP_BUNDLE="{{.BIN_DIR}}/{{.APP_NAME}}.app" - AC_IN="build/ios/xcode/main/Assets.xcassets" - if [ -d "$AC_IN" ]; then - TMP_AC=$(mktemp -d) - xcrun actool \ - --compile "$TMP_AC" \ - --app-icon AppIcon \ - --platform iphonesimulator \ - --minimum-deployment-target 15.0 \ - --product-type com.apple.product-type.application \ - --target-device iphone \ - --target-device ipad \ - --output-partial-info-plist "$APP_BUNDLE/assetcatalog_generated_info.plist" \ - "$AC_IN" - if [ -f "$TMP_AC/Assets.car" ]; then - cp -f "$TMP_AC/Assets.car" "$APP_BUNDLE/Assets.car" - fi - rm -rf "$TMP_AC" - if [ -f "$APP_BUNDLE/assetcatalog_generated_info.plist" ]; then - /usr/libexec/PlistBuddy -c "Merge $APP_BUNDLE/assetcatalog_generated_info.plist" "$APP_BUNDLE/Info.plist" || true - fi - fi - - codesign --force --sign - "{{.BIN_DIR}}/{{.APP_NAME}}.app" - - deploy-simulator: - summary: Deploy to iOS Simulator - deps: [package] - cmds: - - xcrun simctl terminate booted {{.BUNDLE_ID}} 2>/dev/null || true - - xcrun simctl uninstall booted {{.BUNDLE_ID}} 2>/dev/null || true - - xcrun simctl install booted "{{.BIN_DIR}}/{{.APP_NAME}}.app" - - xcrun simctl launch booted {{.BUNDLE_ID}} - - compile:ios: - summary: Compile the iOS executable from Go archive and main.m - deps: - - task: build - vars: - SDK_PATH: - sh: xcrun --sdk iphonesimulator --show-sdk-path - cmds: - - | - MAIN_M=build/ios/xcode/main/main.m - if [ ! -f "$MAIN_M" ]; then - MAIN_M=build/ios/main.m - fi - xcrun -sdk iphonesimulator clang \ - -target arm64-apple-ios15.0-simulator \ - -isysroot {{.SDK_PATH}} \ - -framework Foundation -framework UIKit -framework WebKit \ - -framework Security -framework CoreFoundation \ - -lresolv \ - -o "{{.BIN_DIR}}/{{.APP_NAME | lower}}" \ - "$MAIN_M" "{{.BIN_DIR}}/{{.APP_NAME}}.a" - - generate:ios:bindings: - internal: true - summary: Generates bindings for iOS with proper CGO flags - sources: - - "**/*.go" - - go.mod - - go.sum - generates: - - frontend/bindings/**/* - vars: - SDK_PATH: - sh: xcrun --sdk iphonesimulator --show-sdk-path - cmds: - - wails3 generate bindings -f '{{.BUILD_FLAGS}}' -clean=true - env: - GOOS: ios - CGO_ENABLED: 1 - GOARCH: '{{.ARCH | default "arm64"}}' - CGO_CFLAGS: '-isysroot {{.SDK_PATH}} -target arm64-apple-ios15.0-simulator -mios-simulator-version-min=15.0' - CGO_LDFLAGS: '-isysroot {{.SDK_PATH}} -target arm64-apple-ios15.0-simulator' - - ensure-simulator: - internal: true - summary: Ensure iOS Simulator is running and booted - silent: true - cmds: - - | - if ! xcrun simctl list devices booted | grep -q "Booted"; then - echo "Starting iOS Simulator..." - # Get first available iPhone device - DEVICE_ID=$(xcrun simctl list devices available | grep "iPhone" | head -1 | grep -o "[A-F0-9-]\{36\}" || true) - if [ -z "$DEVICE_ID" ]; then - echo "No iPhone simulator found. Creating one..." - RUNTIME=$(xcrun simctl list runtimes | grep iOS | tail -1 | awk '{print $NF}') - DEVICE_ID=$(xcrun simctl create "iPhone 15 Pro" "iPhone 15 Pro" "$RUNTIME") - fi - # Boot the device - echo "Booting device $DEVICE_ID..." - xcrun simctl boot "$DEVICE_ID" 2>/dev/null || true - # Open Simulator app - open -a Simulator - # Wait for boot (max 30 seconds) - for i in {1..30}; do - if xcrun simctl list devices booted | grep -q "Booted"; then - echo "Simulator booted successfully" - break - fi - sleep 1 - done - # Final check - if ! xcrun simctl list devices booted | grep -q "Booted"; then - echo "Failed to boot simulator after 30 seconds" - exit 1 - fi - fi - preconditions: - - sh: command -v xcrun - msg: "xcrun not found. Please run 'wails3 task ios:install:deps' to install iOS development dependencies" - - generate:ios:overlay: - internal: true - summary: Generate Go build overlay and iOS shim - sources: - - build/config.yml - generates: - - build/ios/xcode/overlay.json - - build/ios/xcode/gen/main_ios.gen.go - cmds: - - wails3 ios overlay:gen -out build/ios/xcode/overlay.json -config build/config.yml - - generate:ios:xcode: - internal: true - summary: Generate iOS Xcode project structure and assets - sources: - - build/config.yml - - build/appicon.png - generates: - - build/ios/xcode/main/main.m - - build/ios/xcode/main/Assets.xcassets/**/* - - build/ios/xcode/project.pbxproj - cmds: - - wails3 ios xcode:gen -outdir build/ios/xcode -config build/config.yml - - run: - summary: Run the application in iOS Simulator - deps: - - task: ensure-simulator - - task: compile:ios - cmds: - - rm -rf "{{.BIN_DIR}}/{{.APP_NAME}}.dev.app" - - mkdir -p "{{.BIN_DIR}}/{{.APP_NAME}}.dev.app" - - cp "{{.BIN_DIR}}/{{.APP_NAME | lower}}" "{{.BIN_DIR}}/{{.APP_NAME}}.dev.app/{{.APP_NAME | lower}}" - - cp build/ios/Info.dev.plist "{{.BIN_DIR}}/{{.APP_NAME}}.dev.app/Info.plist" - - | - # Compile asset catalog and embed icons for dev bundle - APP_BUNDLE="{{.BIN_DIR}}/{{.APP_NAME}}.dev.app" - AC_IN="build/ios/xcode/main/Assets.xcassets" - if [ -d "$AC_IN" ]; then - TMP_AC=$(mktemp -d) - xcrun actool \ - --compile "$TMP_AC" \ - --app-icon AppIcon \ - --platform iphonesimulator \ - --minimum-deployment-target 15.0 \ - --product-type com.apple.product-type.application \ - --target-device iphone \ - --target-device ipad \ - --output-partial-info-plist "$APP_BUNDLE/assetcatalog_generated_info.plist" \ - "$AC_IN" - if [ -f "$TMP_AC/Assets.car" ]; then - cp -f "$TMP_AC/Assets.car" "$APP_BUNDLE/Assets.car" - fi - rm -rf "$TMP_AC" - if [ -f "$APP_BUNDLE/assetcatalog_generated_info.plist" ]; then - /usr/libexec/PlistBuddy -c "Merge $APP_BUNDLE/assetcatalog_generated_info.plist" "$APP_BUNDLE/Info.plist" || true - fi - fi - - codesign --force --sign - "{{.BIN_DIR}}/{{.APP_NAME}}.dev.app" - - xcrun simctl terminate booted "com.wails.{{.APP_NAME | lower}}.dev" 2>/dev/null || true - - xcrun simctl uninstall booted "com.wails.{{.APP_NAME | lower}}.dev" 2>/dev/null || true - - xcrun simctl install booted "{{.BIN_DIR}}/{{.APP_NAME}}.dev.app" - - xcrun simctl launch booted "com.wails.{{.APP_NAME | lower}}.dev" - - xcode: - summary: Open the generated Xcode project for this app - cmds: - - task: generate:ios:xcode - - open build/ios/xcode/main.xcodeproj - - logs: - summary: Stream iOS Simulator logs filtered to this app - cmds: - - | - xcrun simctl spawn booted log stream \ - --level debug \ - --style compact \ - --predicate 'senderImagePath CONTAINS[c] "{{.APP_NAME | lower}}.app/" OR composedMessage CONTAINS[c] "{{.APP_NAME | lower}}" OR eventMessage CONTAINS[c] "{{.APP_NAME | lower}}" OR process == "{{.APP_NAME | lower}}" OR category CONTAINS[c] "{{.APP_NAME | lower}}"' - - logs:dev: - summary: Stream logs for the dev bundle (used by `task ios:run`) - cmds: - - | - xcrun simctl spawn booted log stream \ - --level debug \ - --style compact \ - --predicate 'senderImagePath CONTAINS[c] ".dev.app/" OR subsystem == "com.wails.{{.APP_NAME | lower}}.dev" OR process == "{{.APP_NAME | lower}}"' - - logs:wide: - summary: Wide log stream to help discover the exact process/bundle identifiers - cmds: - - | - xcrun simctl spawn booted log stream \ - --level debug \ - --style compact \ - --predicate 'senderImagePath CONTAINS[c] ".app/"' \ No newline at end of file diff --git a/v3/internal/commands/build_assets/ios/app_options_default.go b/v3/internal/commands/build_assets/ios/app_options_default.go deleted file mode 100644 index 04e4f1bc9..000000000 --- a/v3/internal/commands/build_assets/ios/app_options_default.go +++ /dev/null @@ -1,10 +0,0 @@ -//go:build !ios - -package main - -import "github.com/wailsapp/wails/v3/pkg/application" - -// modifyOptionsForIOS is a no-op on non-iOS platforms -func modifyOptionsForIOS(opts *application.Options) { - // No modifications needed for non-iOS platforms -} \ No newline at end of file diff --git a/v3/internal/commands/build_assets/ios/app_options_ios.go b/v3/internal/commands/build_assets/ios/app_options_ios.go deleted file mode 100644 index 8f6ac3170..000000000 --- a/v3/internal/commands/build_assets/ios/app_options_ios.go +++ /dev/null @@ -1,11 +0,0 @@ -//go:build ios - -package main - -import "github.com/wailsapp/wails/v3/pkg/application" - -// modifyOptionsForIOS adjusts the application options for iOS -func modifyOptionsForIOS(opts *application.Options) { - // Disable signal handlers on iOS to prevent crashes - opts.DisableDefaultSignalHandler = true -} \ No newline at end of file diff --git a/v3/internal/commands/build_assets/ios/icon.png b/v3/internal/commands/build_assets/ios/icon.png deleted file mode 100644 index be7d59173..000000000 --- a/v3/internal/commands/build_assets/ios/icon.png +++ /dev/null @@ -1,3 +0,0 @@ -# iOS Icon Placeholder -# This file should be replaced with the actual app icon (1024x1024 PNG) -# The build process will generate all required icon sizes from this base icon \ No newline at end of file diff --git a/v3/internal/commands/build_assets/ios/main.m b/v3/internal/commands/build_assets/ios/main.m deleted file mode 100644 index 366767a62..000000000 --- a/v3/internal/commands/build_assets/ios/main.m +++ /dev/null @@ -1,23 +0,0 @@ -//go:build ios -// Minimal bootstrap: delegate comes from Go archive (WailsAppDelegate) -#import -#include - -// External Go initialization function from the c-archive (declare before use) -extern void WailsIOSMain(); - -int main(int argc, char * argv[]) { - @autoreleasepool { - // Disable buffering so stdout/stderr from Go log.Printf flush immediately - setvbuf(stdout, NULL, _IONBF, 0); - setvbuf(stderr, NULL, _IONBF, 0); - - // Start Go runtime on a background queue to avoid blocking main thread/UI - dispatch_async(dispatch_get_global_queue(QOS_CLASS_USER_INITIATED, 0), ^{ - WailsIOSMain(); - }); - - // Run UIApplicationMain using WailsAppDelegate provided by the Go archive - return UIApplicationMain(argc, argv, nil, @"WailsAppDelegate"); - } -} \ No newline at end of file diff --git a/v3/internal/commands/build_assets/ios/main_ios.go b/v3/internal/commands/build_assets/ios/main_ios.go deleted file mode 100644 index b75a40321..000000000 --- a/v3/internal/commands/build_assets/ios/main_ios.go +++ /dev/null @@ -1,24 +0,0 @@ -//go:build ios - -package main - -import ( - "C" -) - -// For iOS builds, we need to export a function that can be called from Objective-C -// This wrapper allows us to keep the original main.go unmodified - -//export WailsIOSMain -func WailsIOSMain() { - // DO NOT lock the goroutine to the current OS thread on iOS! - // This causes signal handling issues: - // "signal 16 received on thread with no signal stack" - // "fatal error: non-Go code disabled sigaltstack" - // iOS apps run in a sandboxed environment where the Go runtime's - // signal handling doesn't work the same way as desktop platforms. - - // Call the actual main function from main.go - // This ensures all the user's code is executed - main() -} \ No newline at end of file diff --git a/v3/internal/commands/build_assets/ios/scripts/deps/install_deps.go b/v3/internal/commands/build_assets/ios/scripts/deps/install_deps.go deleted file mode 100644 index 88ed47a4a..000000000 --- a/v3/internal/commands/build_assets/ios/scripts/deps/install_deps.go +++ /dev/null @@ -1,319 +0,0 @@ -// install_deps.go - iOS development dependency checker -// This script checks for required iOS development tools. -// It's designed to be portable across different shells by using Go instead of shell scripts. -// -// Usage: -// go run install_deps.go # Interactive mode -// TASK_FORCE_YES=true go run install_deps.go # Auto-accept prompts -// CI=true go run install_deps.go # CI mode (auto-accept) - -package main - -import ( - "bufio" - "fmt" - "os" - "os/exec" - "strings" -) - -type Dependency struct { - Name string - CheckFunc func() (bool, string) // Returns (success, details) - Required bool - InstallCmd []string - InstallMsg string - SuccessMsg string - FailureMsg string -} - -func main() { - fmt.Println("Checking iOS development dependencies...") - fmt.Println("=" + strings.Repeat("=", 50)) - fmt.Println() - - hasErrors := false - dependencies := []Dependency{ - { - Name: "Xcode", - CheckFunc: func() (bool, string) { - // Check if xcodebuild exists - if !checkCommand([]string{"xcodebuild", "-version"}) { - return false, "" - } - // Get version info - out, err := exec.Command("xcodebuild", "-version").Output() - if err != nil { - return false, "" - } - lines := strings.Split(string(out), "\n") - if len(lines) > 0 { - return true, strings.TrimSpace(lines[0]) - } - return true, "" - }, - Required: true, - InstallMsg: "Please install Xcode from the Mac App Store:\n https://apps.apple.com/app/xcode/id497799835\n Xcode is REQUIRED for iOS development (includes iOS SDKs, simulators, and frameworks)", - SuccessMsg: "✅ Xcode found", - FailureMsg: "❌ Xcode not found (REQUIRED)", - }, - { - Name: "Xcode Developer Path", - CheckFunc: func() (bool, string) { - // Check if xcode-select points to a valid Xcode path - out, err := exec.Command("xcode-select", "-p").Output() - if err != nil { - return false, "xcode-select not configured" - } - path := strings.TrimSpace(string(out)) - - // Check if path exists and is in Xcode.app - if _, err := os.Stat(path); err != nil { - return false, "Invalid Xcode path" - } - - // Verify it's pointing to Xcode.app (not just Command Line Tools) - if !strings.Contains(path, "Xcode.app") { - return false, fmt.Sprintf("Points to %s (should be Xcode.app)", path) - } - - return true, path - }, - Required: true, - InstallCmd: []string{"sudo", "xcode-select", "-s", "/Applications/Xcode.app/Contents/Developer"}, - InstallMsg: "Xcode developer path needs to be configured", - SuccessMsg: "✅ Xcode developer path configured", - FailureMsg: "❌ Xcode developer path not configured correctly", - }, - { - Name: "iOS SDK", - CheckFunc: func() (bool, string) { - // Get the iOS Simulator SDK path - cmd := exec.Command("xcrun", "--sdk", "iphonesimulator", "--show-sdk-path") - output, err := cmd.Output() - if err != nil { - return false, "Cannot find iOS SDK" - } - sdkPath := strings.TrimSpace(string(output)) - - // Check if the SDK path exists - if _, err := os.Stat(sdkPath); err != nil { - return false, "iOS SDK path not found" - } - - // Check for UIKit framework (essential for iOS development) - uikitPath := fmt.Sprintf("%s/System/Library/Frameworks/UIKit.framework", sdkPath) - if _, err := os.Stat(uikitPath); err != nil { - return false, "UIKit.framework not found" - } - - // Get SDK version - versionCmd := exec.Command("xcrun", "--sdk", "iphonesimulator", "--show-sdk-version") - versionOut, _ := versionCmd.Output() - version := strings.TrimSpace(string(versionOut)) - - return true, fmt.Sprintf("iOS %s SDK", version) - }, - Required: true, - InstallMsg: "iOS SDK comes with Xcode. Please ensure Xcode is properly installed.", - SuccessMsg: "✅ iOS SDK found with UIKit framework", - FailureMsg: "❌ iOS SDK not found or incomplete", - }, - { - Name: "iOS Simulator Runtime", - CheckFunc: func() (bool, string) { - if !checkCommand([]string{"xcrun", "simctl", "help"}) { - return false, "" - } - // Check if we can list runtimes - out, err := exec.Command("xcrun", "simctl", "list", "runtimes").Output() - if err != nil { - return false, "Cannot access simulator" - } - // Count iOS runtimes - lines := strings.Split(string(out), "\n") - count := 0 - var versions []string - for _, line := range lines { - if strings.Contains(line, "iOS") && !strings.Contains(line, "unavailable") { - count++ - // Extract version number - if parts := strings.Fields(line); len(parts) > 2 { - for _, part := range parts { - if strings.HasPrefix(part, "(") && strings.HasSuffix(part, ")") { - versions = append(versions, strings.Trim(part, "()")) - break - } - } - } - } - } - if count > 0 { - return true, fmt.Sprintf("%d runtime(s): %s", count, strings.Join(versions, ", ")) - } - return false, "No iOS runtimes installed" - }, - Required: true, - InstallMsg: "iOS Simulator runtimes come with Xcode. You may need to download them:\n Xcode → Settings → Platforms → iOS", - SuccessMsg: "✅ iOS Simulator runtime available", - FailureMsg: "❌ iOS Simulator runtime not available", - }, - } - - // Check each dependency - for _, dep := range dependencies { - success, details := dep.CheckFunc() - if success { - msg := dep.SuccessMsg - if details != "" { - msg = fmt.Sprintf("%s (%s)", dep.SuccessMsg, details) - } - fmt.Println(msg) - } else { - fmt.Println(dep.FailureMsg) - if details != "" { - fmt.Printf(" Details: %s\n", details) - } - if dep.Required { - hasErrors = true - if len(dep.InstallCmd) > 0 { - fmt.Println() - fmt.Println(" " + dep.InstallMsg) - fmt.Printf(" Fix command: %s\n", strings.Join(dep.InstallCmd, " ")) - if promptUser("Do you want to run this command?") { - fmt.Println("Running command...") - cmd := exec.Command(dep.InstallCmd[0], dep.InstallCmd[1:]...) - cmd.Stdout = os.Stdout - cmd.Stderr = os.Stderr - cmd.Stdin = os.Stdin - if err := cmd.Run(); err != nil { - fmt.Printf("Command failed: %v\n", err) - os.Exit(1) - } - fmt.Println("✅ Command completed. Please run this check again.") - } else { - fmt.Printf(" Please run manually: %s\n", strings.Join(dep.InstallCmd, " ")) - } - } else { - fmt.Println(" " + dep.InstallMsg) - } - } - } - } - - // Check for iPhone simulators - fmt.Println() - fmt.Println("Checking for iPhone simulator devices...") - if !checkCommand([]string{"xcrun", "simctl", "list", "devices"}) { - fmt.Println("❌ Cannot check for iPhone simulators") - hasErrors = true - } else { - out, err := exec.Command("xcrun", "simctl", "list", "devices").Output() - if err != nil { - fmt.Println("❌ Failed to list simulator devices") - hasErrors = true - } else if !strings.Contains(string(out), "iPhone") { - fmt.Println("⚠️ No iPhone simulator devices found") - fmt.Println() - - // Get the latest iOS runtime - runtimeOut, err := exec.Command("xcrun", "simctl", "list", "runtimes").Output() - if err != nil { - fmt.Println(" Failed to get iOS runtimes:", err) - } else { - lines := strings.Split(string(runtimeOut), "\n") - var latestRuntime string - for _, line := range lines { - if strings.Contains(line, "iOS") && !strings.Contains(line, "unavailable") { - // Extract runtime identifier - parts := strings.Fields(line) - if len(parts) > 0 { - latestRuntime = parts[len(parts)-1] - } - } - } - - if latestRuntime == "" { - fmt.Println(" No iOS runtime found. Please install iOS simulators in Xcode:") - fmt.Println(" Xcode → Settings → Platforms → iOS") - } else { - fmt.Println(" Would you like to create an iPhone 15 Pro simulator?") - createCmd := []string{"xcrun", "simctl", "create", "iPhone 15 Pro", "iPhone 15 Pro", latestRuntime} - fmt.Printf(" Command: %s\n", strings.Join(createCmd, " ")) - if promptUser("Create simulator?") { - cmd := exec.Command(createCmd[0], createCmd[1:]...) - cmd.Stdout = os.Stdout - cmd.Stderr = os.Stderr - if err := cmd.Run(); err != nil { - fmt.Printf(" Failed to create simulator: %v\n", err) - } else { - fmt.Println(" ✅ iPhone 15 Pro simulator created") - } - } else { - fmt.Println(" Skipping simulator creation") - fmt.Printf(" Create manually: %s\n", strings.Join(createCmd, " ")) - } - } - } - } else { - // Count iPhone devices - count := 0 - lines := strings.Split(string(out), "\n") - for _, line := range lines { - if strings.Contains(line, "iPhone") && !strings.Contains(line, "unavailable") { - count++ - } - } - fmt.Printf("✅ %d iPhone simulator device(s) available\n", count) - } - } - - // Final summary - fmt.Println() - fmt.Println("=" + strings.Repeat("=", 50)) - if hasErrors { - fmt.Println("❌ Some required dependencies are missing or misconfigured.") - fmt.Println() - fmt.Println("Quick setup guide:") - fmt.Println("1. Install Xcode from Mac App Store (if not installed)") - fmt.Println("2. Open Xcode once and agree to the license") - fmt.Println("3. Install additional components when prompted") - fmt.Println("4. Run: sudo xcode-select -s /Applications/Xcode.app/Contents/Developer") - fmt.Println("5. Download iOS simulators: Xcode → Settings → Platforms → iOS") - fmt.Println("6. Run this check again") - os.Exit(1) - } else { - fmt.Println("✅ All required dependencies are installed!") - fmt.Println(" You're ready for iOS development with Wails!") - } -} - -func checkCommand(args []string) bool { - if len(args) == 0 { - return false - } - cmd := exec.Command(args[0], args[1:]...) - cmd.Stdout = nil - cmd.Stderr = nil - err := cmd.Run() - return err == nil -} - -func promptUser(question string) bool { - // Check if we're in a non-interactive environment - if os.Getenv("CI") != "" || os.Getenv("TASK_FORCE_YES") == "true" { - fmt.Printf("%s [y/N]: y (auto-accepted)\n", question) - return true - } - - reader := bufio.NewReader(os.Stdin) - fmt.Printf("%s [y/N]: ", question) - - response, err := reader.ReadString('\n') - if err != nil { - return false - } - - response = strings.ToLower(strings.TrimSpace(response)) - return response == "y" || response == "yes" -} \ No newline at end of file diff --git a/v3/internal/commands/build_assets/linux/Taskfile.yml b/v3/internal/commands/build_assets/linux/Taskfile.yml deleted file mode 100644 index 12854847f..000000000 --- a/v3/internal/commands/build_assets/linux/Taskfile.yml +++ /dev/null @@ -1,225 +0,0 @@ -version: '3' - -includes: - common: ../Taskfile.yml - -vars: - # Signing configuration - edit these values for your project - # PGP_KEY: "path/to/signing-key.asc" - # SIGN_ROLE: "builder" # Options: origin, maint, archive, builder - # - # Password is stored securely in system keychain. Run: wails3 setup signing - - # Docker image for cross-compilation (used when building on non-Linux or no CC available) - CROSS_IMAGE: wails-cross - -tasks: - build: - summary: Builds the application for Linux - cmds: - # Linux requires CGO - use Docker when: - # 1. Cross-compiling from non-Linux, OR - # 2. No C compiler is available, OR - # 3. Target architecture differs from host architecture (cross-arch compilation) - - task: '{{if and (eq OS "linux") (eq .HAS_CC "true") (eq .TARGET_ARCH ARCH)}}build:native{{else}}build:docker{{end}}' - vars: - ARCH: '{{.ARCH}}' - DEV: '{{.DEV}}' - OUTPUT: '{{.OUTPUT}}' - vars: - DEFAULT_OUTPUT: '{{.BIN_DIR}}/{{.APP_NAME}}' - OUTPUT: '{{ .OUTPUT | default .DEFAULT_OUTPUT }}' - # Determine target architecture (defaults to host ARCH if not specified) - TARGET_ARCH: '{{.ARCH | default ARCH}}' - # Check if a C compiler is available (gcc or clang) - HAS_CC: - sh: '(command -v gcc >/dev/null 2>&1 || command -v clang >/dev/null 2>&1) && echo "true" || echo "false"' - - build:native: - summary: Builds the application natively on Linux - internal: true - deps: - - task: common:go:mod:tidy - - task: common:build:frontend - vars: - BUILD_FLAGS: - ref: .BUILD_FLAGS - DEV: - ref: .DEV - - task: common:generate:icons - - task: generate:dotdesktop - cmds: - - go build {{.BUILD_FLAGS}} -o {{.OUTPUT}} - vars: - BUILD_FLAGS: '{{if eq .DEV "true"}}-buildvcs=false -gcflags=all="-l"{{else}}-tags production -trimpath -buildvcs=false -ldflags="-w -s"{{end}}' - DEFAULT_OUTPUT: '{{.BIN_DIR}}/{{.APP_NAME}}' - OUTPUT: '{{ .OUTPUT | default .DEFAULT_OUTPUT }}' - env: - GOOS: linux - CGO_ENABLED: 1 - GOARCH: '{{.ARCH | default ARCH}}' - - build:docker: - summary: Builds for Linux using Docker (for non-Linux hosts or when no C compiler available) - internal: true - deps: - - task: common:build:frontend - - task: common:generate:icons - - task: generate:dotdesktop - preconditions: - - sh: docker info > /dev/null 2>&1 - msg: "Docker is required for cross-compilation to Linux. Please install Docker." - - sh: docker image inspect {{.CROSS_IMAGE}} > /dev/null 2>&1 - msg: | - Docker image '{{.CROSS_IMAGE}}' not found. - Build it first: wails3 task setup:docker - cmds: - - docker run --rm -v "{{.ROOT_DIR}}:/app" {{.GO_CACHE_MOUNT}} {{.REPLACE_MOUNTS}} -e APP_NAME="{{.APP_NAME}}" "{{.CROSS_IMAGE}}" linux {{.DOCKER_ARCH}} - - docker run --rm -v "{{.ROOT_DIR}}:/app" alpine chown -R $(id -u):$(id -g) /app/bin - - mkdir -p {{.BIN_DIR}} - - mv "bin/{{.APP_NAME}}-linux-{{.DOCKER_ARCH}}" "{{.OUTPUT}}" - vars: - DOCKER_ARCH: '{{.ARCH | default "amd64"}}' - DEFAULT_OUTPUT: '{{.BIN_DIR}}/{{.APP_NAME}}' - OUTPUT: '{{ .OUTPUT | default .DEFAULT_OUTPUT }}' - # Mount Go module cache for faster builds - GO_CACHE_MOUNT: - sh: 'echo "-v ${GOPATH:-$HOME/go}/pkg/mod:/go/pkg/mod"' - # Extract replace directives from go.mod and create -v mounts for each - REPLACE_MOUNTS: - sh: | - grep -E '^replace .* => ' go.mod 2>/dev/null | while read -r line; do - path=$(echo "$line" | sed -E 's/^replace .* => //' | tr -d '\r') - # Convert relative paths to absolute - if [ "${path#/}" = "$path" ]; then - path="$(cd "$(dirname "$path")" 2>/dev/null && pwd)/$(basename "$path")" - fi - # Only mount if directory exists - if [ -d "$path" ]; then - echo "-v $path:$path:ro" - fi - done | tr '\n' ' ' - - package: - summary: Packages the application for Linux - deps: - - task: build - cmds: - - task: create:appimage - - task: create:deb - - task: create:rpm - - task: create:aur - - create:appimage: - summary: Creates an AppImage - dir: build/linux/appimage - deps: - - task: build - - task: generate:dotdesktop - cmds: - - cp "{{.APP_BINARY}}" "{{.APP_NAME}}" - - cp ../../appicon.png "{{.APP_NAME}}.png" - - wails3 generate appimage -binary "{{.APP_NAME}}" -icon {{.ICON}} -desktopfile {{.DESKTOP_FILE}} -outputdir {{.OUTPUT_DIR}} -builddir {{.ROOT_DIR}}/build/linux/appimage/build - vars: - APP_NAME: '{{.APP_NAME}}' - APP_BINARY: '../../../bin/{{.APP_NAME}}' - ICON: '{{.APP_NAME}}.png' - DESKTOP_FILE: '../{{.APP_NAME}}.desktop' - OUTPUT_DIR: '../../../bin' - - create:deb: - summary: Creates a deb package - deps: - - task: build - cmds: - - task: generate:dotdesktop - - task: generate:deb - - create:rpm: - summary: Creates a rpm package - deps: - - task: build - cmds: - - task: generate:dotdesktop - - task: generate:rpm - - create:aur: - summary: Creates a arch linux packager package - deps: - - task: build - cmds: - - task: generate:dotdesktop - - task: generate:aur - - generate:deb: - summary: Creates a deb package - cmds: - - wails3 tool package -name "{{.APP_NAME}}" -format deb -config ./build/linux/nfpm/nfpm.yaml -out {{.ROOT_DIR}}/bin - - generate:rpm: - summary: Creates a rpm package - cmds: - - wails3 tool package -name "{{.APP_NAME}}" -format rpm -config ./build/linux/nfpm/nfpm.yaml -out {{.ROOT_DIR}}/bin - - generate:aur: - summary: Creates a arch linux packager package - cmds: - - wails3 tool package -name "{{.APP_NAME}}" -format archlinux -config ./build/linux/nfpm/nfpm.yaml -out {{.ROOT_DIR}}/bin - - generate:dotdesktop: - summary: Generates a `.desktop` file - dir: build - cmds: - - mkdir -p {{.ROOT_DIR}}/build/linux/appimage - - wails3 generate .desktop -name "{{.APP_NAME}}" -exec "{{.EXEC}}" -icon "{{.ICON}}" -outputfile "{{.ROOT_DIR}}/build/linux/{{.APP_NAME}}.desktop" -categories "{{.CATEGORIES}}" - vars: - APP_NAME: '{{.APP_NAME}}' - EXEC: '{{.APP_NAME}}' - ICON: '{{.APP_NAME}}' - CATEGORIES: 'Development;' - OUTPUTFILE: '{{.ROOT_DIR}}/build/linux/{{.APP_NAME}}.desktop' - - run: - cmds: - - '{{.BIN_DIR}}/{{.APP_NAME}}' - - sign:deb: - summary: Signs the DEB package - desc: | - Signs the .deb package with a PGP key. - Configure PGP_KEY in the vars section at the top of this file. - Password is retrieved from system keychain (run: wails3 setup signing) - deps: - - task: create:deb - cmds: - - wails3 tool sign --input "{{.BIN_DIR}}/{{.APP_NAME}}*.deb" --pgp-key {{.PGP_KEY}} {{if .SIGN_ROLE}}--role {{.SIGN_ROLE}}{{end}} - preconditions: - - sh: '[ -n "{{.PGP_KEY}}" ]' - msg: "PGP_KEY is required. Set it in the vars section at the top of build/linux/Taskfile.yml" - - sign:rpm: - summary: Signs the RPM package - desc: | - Signs the .rpm package with a PGP key. - Configure PGP_KEY in the vars section at the top of this file. - Password is retrieved from system keychain (run: wails3 setup signing) - deps: - - task: create:rpm - cmds: - - wails3 tool sign --input "{{.BIN_DIR}}/{{.APP_NAME}}*.rpm" --pgp-key {{.PGP_KEY}} - preconditions: - - sh: '[ -n "{{.PGP_KEY}}" ]' - msg: "PGP_KEY is required. Set it in the vars section at the top of build/linux/Taskfile.yml" - - sign:packages: - summary: Signs all Linux packages (DEB and RPM) - desc: | - Signs both .deb and .rpm packages with a PGP key. - Configure PGP_KEY in the vars section at the top of this file. - Password is retrieved from system keychain (run: wails3 setup signing) - cmds: - - task: sign:deb - - task: sign:rpm - preconditions: - - sh: '[ -n "{{.PGP_KEY}}" ]' - msg: "PGP_KEY is required. Set it in the vars section at the top of build/linux/Taskfile.yml" diff --git a/v3/internal/commands/build_assets/linux/appimage/build.sh b/v3/internal/commands/build_assets/linux/appimage/build.sh deleted file mode 100644 index 85901c34e..000000000 --- a/v3/internal/commands/build_assets/linux/appimage/build.sh +++ /dev/null @@ -1,35 +0,0 @@ -#!/usr/bin/env bash -# Copyright (c) 2018-Present Lea Anthony -# SPDX-License-Identifier: MIT - -# Fail script on any error -set -euxo pipefail - -# Define variables -APP_DIR="${APP_NAME}.AppDir" - -# Create AppDir structure -mkdir -p "${APP_DIR}/usr/bin" -cp -r "${APP_BINARY}" "${APP_DIR}/usr/bin/" -cp "${ICON_PATH}" "${APP_DIR}/" -cp "${DESKTOP_FILE}" "${APP_DIR}/" - -if [[ $(uname -m) == *x86_64* ]]; then - # Download linuxdeploy and make it executable - wget -q -4 -N https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-x86_64.AppImage - chmod +x linuxdeploy-x86_64.AppImage - - # Run linuxdeploy to bundle the application - ./linuxdeploy-x86_64.AppImage --appdir "${APP_DIR}" --output appimage -else - # Download linuxdeploy and make it executable (arm64) - wget -q -4 -N https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-aarch64.AppImage - chmod +x linuxdeploy-aarch64.AppImage - - # Run linuxdeploy to bundle the application (arm64) - ./linuxdeploy-aarch64.AppImage --appdir "${APP_DIR}" --output appimage -fi - -# Rename the generated AppImage -mv "${APP_NAME}*.AppImage" "${APP_NAME}.AppImage" - diff --git a/v3/internal/commands/build_assets/linux/nfpm/scripts/postinstall.sh b/v3/internal/commands/build_assets/linux/nfpm/scripts/postinstall.sh deleted file mode 100644 index 4bbb815a3..000000000 --- a/v3/internal/commands/build_assets/linux/nfpm/scripts/postinstall.sh +++ /dev/null @@ -1,21 +0,0 @@ -#!/bin/sh - -# Update desktop database for .desktop file changes -# This makes the application appear in application menus and registers its capabilities. -if command -v update-desktop-database >/dev/null 2>&1; then - echo "Updating desktop database..." - update-desktop-database -q /usr/share/applications -else - echo "Warning: update-desktop-database command not found. Desktop file may not be immediately recognized." >&2 -fi - -# Update MIME database for custom URL schemes (x-scheme-handler) -# This ensures the system knows how to handle your custom protocols. -if command -v update-mime-database >/dev/null 2>&1; then - echo "Updating MIME database..." - update-mime-database -n /usr/share/mime -else - echo "Warning: update-mime-database command not found. Custom URL schemes may not be immediately recognized." >&2 -fi - -exit 0 diff --git a/v3/internal/commands/build_assets/linux/nfpm/scripts/postremove.sh b/v3/internal/commands/build_assets/linux/nfpm/scripts/postremove.sh deleted file mode 100644 index a9bf588e2..000000000 --- a/v3/internal/commands/build_assets/linux/nfpm/scripts/postremove.sh +++ /dev/null @@ -1 +0,0 @@ -#!/bin/bash diff --git a/v3/internal/commands/build_assets/linux/nfpm/scripts/preinstall.sh b/v3/internal/commands/build_assets/linux/nfpm/scripts/preinstall.sh deleted file mode 100644 index a9bf588e2..000000000 --- a/v3/internal/commands/build_assets/linux/nfpm/scripts/preinstall.sh +++ /dev/null @@ -1 +0,0 @@ -#!/bin/bash diff --git a/v3/internal/commands/build_assets/linux/nfpm/scripts/preremove.sh b/v3/internal/commands/build_assets/linux/nfpm/scripts/preremove.sh deleted file mode 100644 index a9bf588e2..000000000 --- a/v3/internal/commands/build_assets/linux/nfpm/scripts/preremove.sh +++ /dev/null @@ -1 +0,0 @@ -#!/bin/bash diff --git a/v3/internal/commands/build_assets/windows/Taskfile.yml b/v3/internal/commands/build_assets/windows/Taskfile.yml deleted file mode 100644 index 77b620b7d..000000000 --- a/v3/internal/commands/build_assets/windows/Taskfile.yml +++ /dev/null @@ -1,183 +0,0 @@ -version: '3' - -includes: - common: ../Taskfile.yml - -vars: - # Signing configuration - edit these values for your project - # SIGN_CERTIFICATE: "path/to/certificate.pfx" - # SIGN_THUMBPRINT: "certificate-thumbprint" # Alternative to SIGN_CERTIFICATE - # TIMESTAMP_SERVER: "http://timestamp.digicert.com" - # - # Password is stored securely in system keychain. Run: wails3 setup signing - - # Docker image for cross-compilation with CGO (used when CGO_ENABLED=1 on non-Windows) - CROSS_IMAGE: wails-cross - -tasks: - build: - summary: Builds the application for Windows - cmds: - # Auto-detect CGO: if CGO_ENABLED=1, use Docker; otherwise use native Go cross-compile - - task: '{{if and (ne OS "windows") (eq .CGO_ENABLED "1")}}build:docker{{else}}build:native{{end}}' - vars: - ARCH: '{{.ARCH}}' - DEV: '{{.DEV}}' - vars: - # Default to CGO_ENABLED=0 if not explicitly set - CGO_ENABLED: '{{.CGO_ENABLED | default "0"}}' - - build:native: - summary: Builds the application using native Go cross-compilation - internal: true - deps: - - task: common:go:mod:tidy - - task: common:build:frontend - vars: - BUILD_FLAGS: - ref: .BUILD_FLAGS - DEV: - ref: .DEV - - task: common:generate:icons - cmds: - - task: generate:syso - - go build {{.BUILD_FLAGS}} -o "{{.BIN_DIR}}/{{.APP_NAME}}.exe" - - cmd: powershell Remove-item *.syso - platforms: [windows] - - cmd: rm -f *.syso - platforms: [linux, darwin] - vars: - BUILD_FLAGS: '{{if eq .DEV "true"}}-buildvcs=false -gcflags=all="-l"{{else}}-tags production -trimpath -buildvcs=false -ldflags="-w -s -H windowsgui"{{end}}' - env: - GOOS: windows - CGO_ENABLED: '{{.CGO_ENABLED | default "0"}}' - GOARCH: '{{.ARCH | default ARCH}}' - - build:docker: - summary: Cross-compiles for Windows using Docker with Zig (for CGO builds on non-Windows) - internal: true - deps: - - task: common:build:frontend - - task: common:generate:icons - preconditions: - - sh: docker info > /dev/null 2>&1 - msg: "Docker is required for CGO cross-compilation. Please install Docker." - - sh: docker image inspect {{.CROSS_IMAGE}} > /dev/null 2>&1 - msg: | - Docker image '{{.CROSS_IMAGE}}' not found. - Build it first: wails3 task setup:docker - cmds: - - task: generate:syso - - docker run --rm -v "{{.ROOT_DIR}}:/app" {{.GO_CACHE_MOUNT}} {{.REPLACE_MOUNTS}} -e APP_NAME="{{.APP_NAME}}" {{.CROSS_IMAGE}} windows {{.DOCKER_ARCH}} - - docker run --rm -v "{{.ROOT_DIR}}:/app" alpine chown -R $(id -u):$(id -g) /app/bin - - rm -f *.syso - vars: - DOCKER_ARCH: '{{.ARCH | default "amd64"}}' - # Mount Go module cache for faster builds - GO_CACHE_MOUNT: - sh: 'echo "-v ${GOPATH:-$HOME/go}/pkg/mod:/go/pkg/mod"' - # Extract replace directives from go.mod and create -v mounts for each - REPLACE_MOUNTS: - sh: | - grep -E '^replace .* => ' go.mod 2>/dev/null | while read -r line; do - path=$(echo "$line" | sed -E 's/^replace .* => //' | tr -d '\r') - # Convert relative paths to absolute - if [ "${path#/}" = "$path" ]; then - path="$(cd "$(dirname "$path")" 2>/dev/null && pwd)/$(basename "$path")" - fi - # Only mount if directory exists - if [ -d "$path" ]; then - echo "-v $path:$path:ro" - fi - done | tr '\n' ' ' - - package: - summary: Packages the application - cmds: - - task: '{{if eq (.FORMAT | default "nsis") "msix"}}create:msix:package{{else}}create:nsis:installer{{end}}' - vars: - FORMAT: '{{.FORMAT | default "nsis"}}' - - generate:syso: - summary: Generates Windows `.syso` file - dir: build - cmds: - - wails3 generate syso -arch {{.ARCH}} -icon windows/icon.ico -manifest windows/wails.exe.manifest -info windows/info.json -out ../wails_windows_{{.ARCH}}.syso - vars: - ARCH: '{{.ARCH | default ARCH}}' - - create:nsis:installer: - summary: Creates an NSIS installer - dir: build/windows/nsis - deps: - - task: build - cmds: - # Create the Microsoft WebView2 bootstrapper if it doesn't exist - - wails3 generate webview2bootstrapper -dir "{{.ROOT_DIR}}/build/windows/nsis" - - | - {{if eq OS "windows"}} - makensis -DARG_WAILS_{{.ARG_FLAG}}_BINARY="{{.ROOT_DIR}}\{{.BIN_DIR}}\{{.APP_NAME}}.exe" project.nsi - {{else}} - makensis -DARG_WAILS_{{.ARG_FLAG}}_BINARY="{{.ROOT_DIR}}/{{.BIN_DIR}}/{{.APP_NAME}}.exe" project.nsi - {{end}} - vars: - ARCH: '{{.ARCH | default ARCH}}' - ARG_FLAG: '{{if eq .ARCH "amd64"}}AMD64{{else}}ARM64{{end}}' - - create:msix:package: - summary: Creates an MSIX package - deps: - - task: build - cmds: - - |- - wails3 tool msix \ - --config "{{.ROOT_DIR}}/wails.json" \ - --name "{{.APP_NAME}}" \ - --executable "{{.ROOT_DIR}}/{{.BIN_DIR}}/{{.APP_NAME}}.exe" \ - --arch "{{.ARCH}}" \ - --out "{{.ROOT_DIR}}/{{.BIN_DIR}}/{{.APP_NAME}}-{{.ARCH}}.msix" \ - {{if .CERT_PATH}}--cert "{{.CERT_PATH}}"{{end}} \ - {{if .PUBLISHER}}--publisher "{{.PUBLISHER}}"{{end}} \ - {{if .USE_MSIX_TOOL}}--use-msix-tool{{else}}--use-makeappx{{end}} - vars: - ARCH: '{{.ARCH | default ARCH}}' - CERT_PATH: '{{.CERT_PATH | default ""}}' - PUBLISHER: '{{.PUBLISHER | default ""}}' - USE_MSIX_TOOL: '{{.USE_MSIX_TOOL | default "false"}}' - - install:msix:tools: - summary: Installs tools required for MSIX packaging - cmds: - - wails3 tool msix-install-tools - - run: - cmds: - - '{{.BIN_DIR}}/{{.APP_NAME}}.exe' - - sign: - summary: Signs the Windows executable - desc: | - Signs the .exe with an Authenticode certificate. - Configure SIGN_CERTIFICATE or SIGN_THUMBPRINT in the vars section at the top of this file. - Password is retrieved from system keychain (run: wails3 setup signing) - deps: - - task: build - cmds: - - wails3 tool sign --input "{{.BIN_DIR}}/{{.APP_NAME}}.exe" {{if .SIGN_CERTIFICATE}}--certificate {{.SIGN_CERTIFICATE}}{{end}} {{if .SIGN_THUMBPRINT}}--thumbprint {{.SIGN_THUMBPRINT}}{{end}} {{if .TIMESTAMP_SERVER}}--timestamp {{.TIMESTAMP_SERVER}}{{end}} - preconditions: - - sh: '[ -n "{{.SIGN_CERTIFICATE}}" ] || [ -n "{{.SIGN_THUMBPRINT}}" ]' - msg: "Either SIGN_CERTIFICATE or SIGN_THUMBPRINT is required. Set it in the vars section at the top of build/windows/Taskfile.yml" - - sign:installer: - summary: Signs the NSIS installer - desc: | - Creates and signs the NSIS installer. - Configure SIGN_CERTIFICATE or SIGN_THUMBPRINT in the vars section at the top of this file. - Password is retrieved from system keychain (run: wails3 setup signing) - deps: - - task: create:nsis:installer - cmds: - - wails3 tool sign --input "build/windows/nsis/{{.APP_NAME}}-installer.exe" {{if .SIGN_CERTIFICATE}}--certificate {{.SIGN_CERTIFICATE}}{{end}} {{if .SIGN_THUMBPRINT}}--thumbprint {{.SIGN_THUMBPRINT}}{{end}} {{if .TIMESTAMP_SERVER}}--timestamp {{.TIMESTAMP_SERVER}}{{end}} - preconditions: - - sh: '[ -n "{{.SIGN_CERTIFICATE}}" ] || [ -n "{{.SIGN_THUMBPRINT}}" ]' - msg: "Either SIGN_CERTIFICATE or SIGN_THUMBPRINT is required. Set it in the vars section at the top of build/windows/Taskfile.yml" diff --git a/v3/internal/commands/build_assets/windows/icon.ico b/v3/internal/commands/build_assets/windows/icon.ico deleted file mode 100644 index bfa0690b7..000000000 Binary files a/v3/internal/commands/build_assets/windows/icon.ico and /dev/null differ diff --git a/v3/internal/commands/build_assets/windows/msix/app_manifest.xml.tmpl b/v3/internal/commands/build_assets/windows/msix/app_manifest.xml.tmpl deleted file mode 100644 index 430f8c3a9..000000000 --- a/v3/internal/commands/build_assets/windows/msix/app_manifest.xml.tmpl +++ /dev/null @@ -1,76 +0,0 @@ - - - - - - - {{.ProductName}} - {{.ProductCompany}} - {{.ProductDescription}} - Assets\StoreLogo.png - - - - - - - - - - - - - - - - - - - - {{if .FileAssociations}} - - - {{.ProductName}} - Assets\FileIcon.png - {{.ProductName}} File - - {{range .FileAssociations}} - .{{.Ext}} - {{end}} - - - - {{end}} - {{range .Protocols}} - - - {{.Description}} - - - {{end}} - - - - - - - {{if .FileAssociations}} - - {{end}} - - diff --git a/v3/internal/commands/build_assets/windows/msix/template.xml.tmpl b/v3/internal/commands/build_assets/windows/msix/template.xml.tmpl deleted file mode 100644 index 92f217499..000000000 --- a/v3/internal/commands/build_assets/windows/msix/template.xml.tmpl +++ /dev/null @@ -1,68 +0,0 @@ - - - - - - - - - - {{if .FileAssociations}} - - {{end}} - - - - {{if .FileAssociations}} - - - - {{range .FileAssociations}} - - .{{.Ext}} - - {{end}} - - - - {{end}} - - - - - - - - - - false - {{.ProductName}} - {{.ProductCompany}} - {{.ProductDescription}} - Assets\AppIcon.png - - - - - {{.CertificatePath}} - - diff --git a/v3/internal/commands/build_assets/windows/nsis/project.nsi.tmpl b/v3/internal/commands/build_assets/windows/nsis/project.nsi.tmpl deleted file mode 100644 index df4bd5438..000000000 --- a/v3/internal/commands/build_assets/windows/nsis/project.nsi.tmpl +++ /dev/null @@ -1,114 +0,0 @@ -Unicode true - -#### -## Please note: Template replacements don't work in this file. They are provided with default defines like -## mentioned underneath. -## If the keyword is not defined, "wails_tools.nsh" will populate them. -## If they are defined here, "wails_tools.nsh" will not touch them. This allows you to use this project.nsi manually -## from outside of Wails for debugging and development of the installer. -## -## For development first make a wails nsis build to populate the "wails_tools.nsh": -## > wails build --target windows/amd64 --nsis -## Then you can call makensis on this file with specifying the path to your binary: -## For a AMD64 only installer: -## > makensis -DARG_WAILS_AMD64_BINARY=..\..\bin\app.exe -## For a ARM64 only installer: -## > makensis -DARG_WAILS_ARM64_BINARY=..\..\bin\app.exe -## For a installer with both architectures: -## > makensis -DARG_WAILS_AMD64_BINARY=..\..\bin\app-amd64.exe -DARG_WAILS_ARM64_BINARY=..\..\bin\app-arm64.exe -#### -## The following information is taken from the wails_tools.nsh file, but they can be overwritten here. -#### -## !define INFO_PROJECTNAME "my-project" # Default "{{.Name}}" -## !define INFO_COMPANYNAME "My Company" # Default "{{.ProductCompany}}" -## !define INFO_PRODUCTNAME "My Product Name" # Default "{{.ProductName}}" -## !define INFO_PRODUCTVERSION "1.0.0" # Default "{{.ProductVersion}}" -## !define INFO_COPYRIGHT "(c) Now, My Company" # Default "{{.ProductCopyright}}" -### -## !define PRODUCT_EXECUTABLE "Application.exe" # Default "${INFO_PROJECTNAME}.exe" -## !define UNINST_KEY_NAME "UninstKeyInRegistry" # Default "${INFO_COMPANYNAME}${INFO_PRODUCTNAME}" -#### -## !define REQUEST_EXECUTION_LEVEL "admin" # Default "admin" see also https://nsis.sourceforge.io/Docs/Chapter4.html -#### -## Include the wails tools -#### -!include "wails_tools.nsh" - -# The version information for this two must consist of 4 parts -VIProductVersion "${INFO_PRODUCTVERSION}.0" -VIFileVersion "${INFO_PRODUCTVERSION}.0" - -VIAddVersionKey "CompanyName" "${INFO_COMPANYNAME}" -VIAddVersionKey "FileDescription" "${INFO_PRODUCTNAME} Installer" -VIAddVersionKey "ProductVersion" "${INFO_PRODUCTVERSION}" -VIAddVersionKey "FileVersion" "${INFO_PRODUCTVERSION}" -VIAddVersionKey "LegalCopyright" "${INFO_COPYRIGHT}" -VIAddVersionKey "ProductName" "${INFO_PRODUCTNAME}" - -# Enable HiDPI support. https://nsis.sourceforge.io/Reference/ManifestDPIAware -ManifestDPIAware true - -!include "MUI.nsh" - -!define MUI_ICON "..\icon.ico" -!define MUI_UNICON "..\icon.ico" -# !define MUI_WELCOMEFINISHPAGE_BITMAP "resources\leftimage.bmp" #Include this to add a bitmap on the left side of the Welcome Page. Must be a size of 164x314 -!define MUI_FINISHPAGE_NOAUTOCLOSE # Wait on the INSTFILES page so the user can take a look into the details of the installation steps -!define MUI_ABORTWARNING # This will warn the user if they exit from the installer. - -!insertmacro MUI_PAGE_WELCOME # Welcome to the installer page. -# !insertmacro MUI_PAGE_LICENSE "resources\eula.txt" # Adds a EULA page to the installer -!insertmacro MUI_PAGE_DIRECTORY # In which folder install page. -!insertmacro MUI_PAGE_INSTFILES # Installing page. -!insertmacro MUI_PAGE_FINISH # Finished installation page. - -!insertmacro MUI_UNPAGE_INSTFILES # Uninstalling page - -!insertmacro MUI_LANGUAGE "English" # Set the Language of the installer - -## The following two statements can be used to sign the installer and the uninstaller. The path to the binaries are provided in %1 -#!uninstfinalize 'signtool --file "%1"' -#!finalize 'signtool --file "%1"' - -Name "${INFO_PRODUCTNAME}" -OutFile "..\..\..\bin\${INFO_PROJECTNAME}-${ARCH}-installer.exe" # Name of the installer's file. -InstallDir "$PROGRAMFILES64\${INFO_COMPANYNAME}\${INFO_PRODUCTNAME}" # Default installing folder ($PROGRAMFILES is Program Files folder). -ShowInstDetails show # This will always show the installation details. - -Function .onInit - !insertmacro wails.checkArchitecture -FunctionEnd - -Section - !insertmacro wails.setShellContext - - !insertmacro wails.webview2runtime - - SetOutPath $INSTDIR - - !insertmacro wails.files - - CreateShortcut "$SMPROGRAMS\${INFO_PRODUCTNAME}.lnk" "$INSTDIR\${PRODUCT_EXECUTABLE}" - CreateShortCut "$DESKTOP\${INFO_PRODUCTNAME}.lnk" "$INSTDIR\${PRODUCT_EXECUTABLE}" - - !insertmacro wails.associateFiles - !insertmacro wails.associateCustomProtocols - - !insertmacro wails.writeUninstaller -SectionEnd - -Section "uninstall" - !insertmacro wails.setShellContext - - RMDir /r "$AppData\${PRODUCT_EXECUTABLE}" # Remove the WebView2 DataPath - - RMDir /r $INSTDIR - - Delete "$SMPROGRAMS\${INFO_PRODUCTNAME}.lnk" - Delete "$DESKTOP\${INFO_PRODUCTNAME}.lnk" - - !insertmacro wails.unassociateFiles - !insertmacro wails.unassociateCustomProtocols - - !insertmacro wails.deleteUninstaller -SectionEnd diff --git a/v3/internal/commands/capabilities.go b/v3/internal/commands/capabilities.go deleted file mode 100644 index 37a04c7bc..000000000 --- a/v3/internal/commands/capabilities.go +++ /dev/null @@ -1,75 +0,0 @@ -package commands - -import ( - "fmt" - "os/exec" - "runtime" - - "github.com/pterm/pterm" -) - -type LinuxCapabilities struct { - GTK4Available bool `json:"gtk4_available"` - GTK3Available bool `json:"gtk3_available"` - WebKitGTK6Available bool `json:"webkitgtk_6_available"` - WebKit2GTK4Available bool `json:"webkit2gtk_4_1_available"` - Recommended string `json:"recommended"` -} - -type Capabilities struct { - Platform string `json:"platform"` - Arch string `json:"arch"` - Linux *LinuxCapabilities `json:"linux,omitempty"` -} - -type ToolCapabilitiesOptions struct{} - -func ToolCapabilities(_ *ToolCapabilitiesOptions) error { - caps := Capabilities{ - Platform: runtime.GOOS, - Arch: runtime.GOARCH, - } - - switch runtime.GOOS { - case "linux": - caps.Linux = detectLinuxCapabilities() - } - - pterm.Println(capsToJSON(caps)) - return nil -} - -func detectLinuxCapabilities() *LinuxCapabilities { - caps := &LinuxCapabilities{} - - caps.GTK4Available = pkgConfigExists("gtk4") - caps.WebKitGTK6Available = pkgConfigExists("webkitgtk-6.0") - caps.GTK3Available = pkgConfigExists("gtk+-3.0") - caps.WebKit2GTK4Available = pkgConfigExists("webkit2gtk-4.1") - - if caps.GTK4Available && caps.WebKitGTK6Available { - caps.Recommended = "gtk4" - } else if caps.GTK3Available && caps.WebKit2GTK4Available { - caps.Recommended = "gtk3" - } else { - caps.Recommended = "none" - } - - return caps -} - -func pkgConfigExists(pkg string) bool { - cmd := exec.Command("pkg-config", "--exists", pkg) - return cmd.Run() == nil -} - -func capsToJSON(caps Capabilities) string { - result := fmt.Sprintf(`{"platform":"%s","arch":"%s"`, caps.Platform, caps.Arch) - if caps.Linux != nil { - l := caps.Linux - result += fmt.Sprintf(`,"linux":{"gtk4_available":%t,"gtk3_available":%t,"webkitgtk_6_available":%t,"webkit2gtk_4_1_available":%t,"recommended":"%s"}`, - l.GTK4Available, l.GTK3Available, l.WebKitGTK6Available, l.WebKit2GTK4Available, l.Recommended) - } - result += "}" - return result -} diff --git a/v3/internal/commands/constants.go b/v3/internal/commands/constants.go deleted file mode 100644 index 729d7e027..000000000 --- a/v3/internal/commands/constants.go +++ /dev/null @@ -1,27 +0,0 @@ -package commands - -import ( - "os" - - "github.com/wailsapp/wails/v3/internal/generator" -) - -type GenerateConstantsOptions struct { - ConstantsFilename string `name:"f" description:"The filename for the models file" default:"constants.go"` - OutputFilename string `name:"o" description:"The output file" default:"constants.js"` -} - -func GenerateConstants(options *GenerateConstantsOptions) error { - DisableFooter = true - goData, err := os.ReadFile(options.ConstantsFilename) - if err != nil { - return err - } - - result, err := generator.GenerateConstants(goData) - if err != nil { - return err - } - - return os.WriteFile(options.OutputFilename, []byte(result), 0644) -} diff --git a/v3/internal/commands/dev.go b/v3/internal/commands/dev.go deleted file mode 100644 index f7053e377..000000000 --- a/v3/internal/commands/dev.go +++ /dev/null @@ -1,58 +0,0 @@ -package commands - -import ( - "fmt" - "net" - "os" - "strconv" - - "github.com/wailsapp/wails/v3/internal/flags" -) - -const defaultVitePort = 9245 -const wailsVitePort = "WAILS_VITE_PORT" - -type DevOptions struct { - flags.Common - - Config string `description:"The config file including path" default:"./build/config.yml"` - VitePort int `name:"port" description:"Specify the vite dev server port"` - Secure bool `name:"s" description:"Enable HTTPS"` -} - -func Dev(options *DevOptions) error { - host := "localhost" - - // flag takes precedence over environment variable - var port int - if options.VitePort != 0 { - port = options.VitePort - } else if p, err := strconv.Atoi(os.Getenv(wailsVitePort)); err == nil { - port = p - } else { - port = defaultVitePort - } - - // check if port is already in use - l, err := net.Listen("tcp", fmt.Sprintf("%s:%d", host, port)) - if err != nil { - return err - } - if err = l.Close(); err != nil { - return err - } - - // Set environment variable for the dev:frontend task - os.Setenv(wailsVitePort, strconv.Itoa(port)) - - // Set url of frontend dev server - if options.Secure { - os.Setenv("FRONTEND_DEVSERVER_URL", fmt.Sprintf("https://%s:%d", host, port)) - } else { - os.Setenv("FRONTEND_DEVSERVER_URL", fmt.Sprintf("http://%s:%d", host, port)) - } - - return Watcher(&WatcherOptions{ - Config: options.Config, - }) -} diff --git a/v3/internal/commands/dmg/dmg.go b/v3/internal/commands/dmg/dmg.go deleted file mode 100644 index 7ba2de572..000000000 --- a/v3/internal/commands/dmg/dmg.go +++ /dev/null @@ -1,157 +0,0 @@ -package dmg - -import ( - "fmt" - "os" - "os/exec" - "path/filepath" - "runtime" - "strings" -) - -// Creator handles DMG creation -type Creator struct { - sourcePath string - outputPath string - appName string - backgroundImage string - iconPositions map[string]Position -} - -// Position represents icon coordinates in the DMG -type Position struct { - X, Y int -} - -// New creates a new DMG creator -func New(sourcePath, outputPath, appName string) (*Creator, error) { - if runtime.GOOS != "darwin" { - return nil, fmt.Errorf("DMG creation is only supported on macOS") - } - - // Check if source exists - if _, err := os.Stat(sourcePath); os.IsNotExist(err) { - return nil, fmt.Errorf("source path does not exist: %s", sourcePath) - } - - return &Creator{ - sourcePath: sourcePath, - outputPath: outputPath, - appName: appName, - iconPositions: make(map[string]Position), - }, nil -} - -// SetBackgroundImage sets the background image for the DMG -func (c *Creator) SetBackgroundImage(imagePath string) error { - if _, err := os.Stat(imagePath); os.IsNotExist(err) { - return fmt.Errorf("background image does not exist: %s", imagePath) - } - c.backgroundImage = imagePath - return nil -} - -// AddIconPosition adds an icon position for the DMG layout -func (c *Creator) AddIconPosition(filename string, x, y int) { - c.iconPositions[filename] = Position{X: x, Y: y} -} - -// Create creates the DMG file -func (c *Creator) Create() error { - // Remove existing DMG if it exists - if _, err := os.Stat(c.outputPath); err == nil { - if err := os.Remove(c.outputPath); err != nil { - return fmt.Errorf("failed to remove existing DMG: %w", err) - } - } - - // Create a temporary directory for DMG content - tempDir, err := os.MkdirTemp("", "dmg-*") - if err != nil { - return fmt.Errorf("failed to create temp directory: %w", err) - } - defer os.RemoveAll(tempDir) - - // Copy the app bundle to temp directory - appName := filepath.Base(c.sourcePath) - tempAppPath := filepath.Join(tempDir, appName) - if err := c.copyDir(c.sourcePath, tempAppPath); err != nil { - return fmt.Errorf("failed to copy app bundle: %w", err) - } - - // Create Applications symlink - applicationsLink := filepath.Join(tempDir, "Applications") - if err := os.Symlink("/Applications", applicationsLink); err != nil { - return fmt.Errorf("failed to create Applications symlink: %w", err) - } - - // Copy background image if provided - if c.backgroundImage != "" { - bgName := filepath.Base(c.backgroundImage) - bgPath := filepath.Join(tempDir, bgName) - if err := c.copyFile(c.backgroundImage, bgPath); err != nil { - return fmt.Errorf("failed to copy background image: %w", err) - } - } - - // Create DMG using hdiutil - if err := c.createDMGWithHdiutil(tempDir); err != nil { - return fmt.Errorf("failed to create DMG with hdiutil: %w", err) - } - - return nil -} - -// copyDir recursively copies a directory -func (c *Creator) copyDir(src, dst string) error { - cmd := exec.Command("cp", "-R", src, dst) - if err := cmd.Run(); err != nil { - return fmt.Errorf("failed to copy directory: %w", err) - } - return nil -} - -// copyFile copies a file -func (c *Creator) copyFile(src, dst string) error { - cmd := exec.Command("cp", src, dst) - if err := cmd.Run(); err != nil { - return fmt.Errorf("failed to copy file: %w", err) - } - return nil -} - -// createDMGWithHdiutil creates the DMG using macOS hdiutil -func (c *Creator) createDMGWithHdiutil(sourceDir string) error { - // Calculate size needed for DMG (roughly 2x the source size for safety) - sizeCmd := exec.Command("du", "-sk", sourceDir) - output, err := sizeCmd.Output() - if err != nil { - return fmt.Errorf("failed to calculate directory size: %w", err) - } - - // Parse size and add padding - sizeStr := strings.Fields(string(output))[0] - - // Create DMG with hdiutil - args := []string{ - "create", - "-srcfolder", sourceDir, - "-format", "UDZO", - "-volname", c.appName, - c.outputPath, - } - - // Add size if we could determine it - if sizeStr != "" { - // Add 50% padding to the calculated size - args = append([]string{"create", "-size", sizeStr + "k"}, args[1:]...) - args[0] = "create" - } - - cmd := exec.Command("hdiutil", args...) - if output, err := cmd.CombinedOutput(); err != nil { - return fmt.Errorf("hdiutil failed: %w\nOutput: %s", err, string(output)) - } - - return nil -} diff --git a/v3/internal/commands/doctor.go b/v3/internal/commands/doctor.go deleted file mode 100644 index 08a3da2a2..000000000 --- a/v3/internal/commands/doctor.go +++ /dev/null @@ -1,11 +0,0 @@ -package commands - -import ( - "github.com/wailsapp/wails/v3/internal/doctor" -) - -type DoctorOptions struct{} - -func Doctor(_ *DoctorOptions) error { - return doctor.Run() -} diff --git a/v3/internal/commands/doctor_ng.go b/v3/internal/commands/doctor_ng.go deleted file mode 100644 index 9d3399e97..000000000 --- a/v3/internal/commands/doctor_ng.go +++ /dev/null @@ -1,19 +0,0 @@ -package commands - -import ( - "github.com/wailsapp/wails/v3/pkg/doctor-ng/tui" -) - -type DoctorNgOptions struct { - NonInteractive bool `name:"n" description:"Run in non-interactive mode (no TUI)"` -} - -func DoctorNg(options *DoctorNgOptions) error { - DisableFooter = true - - if options.NonInteractive { - return tui.RunNonInteractive() - } - - return tui.RunSimple() -} diff --git a/v3/internal/commands/dot_desktop.go b/v3/internal/commands/dot_desktop.go deleted file mode 100644 index de3ed6c01..000000000 --- a/v3/internal/commands/dot_desktop.go +++ /dev/null @@ -1,80 +0,0 @@ -package commands - -import ( - "bytes" - "fmt" - "os" -) - -type DotDesktopOptions struct { - OutputFile string `description:"The output file to write to"` - Type string `description:"The type of the desktop entry" default:"Application"` - Name string `description:"The name of the application"` - Exec string `description:"The binary name + args to execute"` - Icon string `description:"The icon name or path for the application"` - Categories string `description:"Categories in which the application should be shown e.g. 'Development;IDE;'"` - Comment string `description:"A brief description of the application"` - Terminal bool `description:"Whether the application runs in a terminal" default:"false"` - Keywords string `description:"Keywords associated with the application e.g. 'Editor;Image;'" default:"wails"` - Version string `description:"The version of the Desktop Entry Specification" default:"1.0"` - GenericName string `description:"A generic name for the application"` - StartupNotify bool `description:"If true, the app will send a notification when starting" default:"false"` - MimeType string `description:"The MIME types the application can handle e.g. 'image/gif;image/jpeg;'"` - //Actions []string `description:"Additional actions offered by the application"` -} - -func (d *DotDesktopOptions) asBytes() []byte { - var buf bytes.Buffer - // Mandatory fields - buf.WriteString("[Desktop Entry]\n") - buf.WriteString(fmt.Sprintf("Type=%s\n", d.Type)) - buf.WriteString(fmt.Sprintf("Name=%s\n", d.Name)) - buf.WriteString(fmt.Sprintf("Exec=%s\n", d.Exec)) - - // Optional fields with checks - if d.Icon != "" { - buf.WriteString(fmt.Sprintf("Icon=%s\n", d.Icon)) - } - buf.WriteString(fmt.Sprintf("Categories=%s\n", d.Categories)) - if d.Comment != "" { - buf.WriteString(fmt.Sprintf("Comment=%s\n", d.Comment)) - } - buf.WriteString(fmt.Sprintf("Terminal=%t\n", d.Terminal)) - if d.Keywords != "" { - buf.WriteString(fmt.Sprintf("Keywords=%s\n", d.Keywords)) - } - if d.Version != "" { - buf.WriteString(fmt.Sprintf("Version=%s\n", d.Version)) - } - if d.GenericName != "" { - buf.WriteString(fmt.Sprintf("GenericName=%s\n", d.GenericName)) - } - buf.WriteString(fmt.Sprintf("StartupNotify=%t\n", d.StartupNotify)) - if d.MimeType != "" { - buf.WriteString(fmt.Sprintf("MimeType=%s\n", d.MimeType)) - } - return buf.Bytes() -} - -func GenerateDotDesktop(options *DotDesktopOptions) error { - DisableFooter = true - - if options.Name == "" { - return fmt.Errorf("name is required") - } - - options.Name = normaliseName(options.Name) - - if options.Exec == "" { - return fmt.Errorf("exec is required") - } - - if options.OutputFile == "" { - options.OutputFile = options.Name + ".desktop" - } - - // Write to file - err := os.WriteFile(options.OutputFile, options.asBytes(), 0755) - - return err -} diff --git a/v3/internal/commands/entitlements_setup.go b/v3/internal/commands/entitlements_setup.go deleted file mode 100644 index 44633189d..000000000 --- a/v3/internal/commands/entitlements_setup.go +++ /dev/null @@ -1,241 +0,0 @@ -package commands - -import ( - "fmt" - "os" - "path/filepath" - "strings" - - "github.com/charmbracelet/huh" - "github.com/pterm/pterm" - "github.com/wailsapp/wails/v3/internal/flags" -) - -// Entitlement represents a macOS entitlement -type Entitlement struct { - Key string - Name string - Description string - Category string -} - -// Common macOS entitlements organized by category -var availableEntitlements = []Entitlement{ - // Hardened Runtime - Code Execution - {Key: "com.apple.security.cs.allow-jit", Name: "Allow JIT", Description: "Allow creating writable/executable memory using MAP_JIT (most secure option for JIT)", Category: "Code Execution"}, - {Key: "com.apple.security.cs.allow-unsigned-executable-memory", Name: "Allow Unsigned Executable Memory", Description: "Allow writable/executable memory without MAP_JIT restrictions", Category: "Code Execution"}, - {Key: "com.apple.security.cs.disable-executable-page-protection", Name: "Disable Executable Page Protection", Description: "Disable all executable memory protections (least secure)", Category: "Code Execution"}, - {Key: "com.apple.security.cs.disable-library-validation", Name: "Disable Library Validation", Description: "Allow loading unsigned or differently-signed libraries/frameworks", Category: "Code Execution"}, - {Key: "com.apple.security.cs.allow-dyld-environment-variables", Name: "Allow DYLD Environment Variables", Description: "Allow DYLD_* environment variables to modify library loading", Category: "Code Execution"}, - - // Hardened Runtime - Resource Access - {Key: "com.apple.security.device.audio-input", Name: "Audio Input (Microphone)", Description: "Access to audio input devices", Category: "Resource Access"}, - {Key: "com.apple.security.device.camera", Name: "Camera", Description: "Access to the camera", Category: "Resource Access"}, - {Key: "com.apple.security.personal-information.location", Name: "Location", Description: "Access to location services", Category: "Resource Access"}, - {Key: "com.apple.security.personal-information.addressbook", Name: "Address Book", Description: "Access to contacts", Category: "Resource Access"}, - {Key: "com.apple.security.personal-information.calendars", Name: "Calendars", Description: "Access to calendar data", Category: "Resource Access"}, - {Key: "com.apple.security.personal-information.photos-library", Name: "Photos Library", Description: "Access to the Photos library", Category: "Resource Access"}, - {Key: "com.apple.security.automation.apple-events", Name: "Apple Events", Description: "Send Apple Events to other apps (AppleScript)", Category: "Resource Access"}, - - // App Sandbox - Basic - {Key: "com.apple.security.app-sandbox", Name: "Enable App Sandbox", Description: "Enable the App Sandbox (required for Mac App Store)", Category: "App Sandbox"}, - - // App Sandbox - Network - {Key: "com.apple.security.network.client", Name: "Outgoing Network Connections", Description: "Allow outgoing network connections (client)", Category: "Network"}, - {Key: "com.apple.security.network.server", Name: "Incoming Network Connections", Description: "Allow incoming network connections (server)", Category: "Network"}, - - // App Sandbox - Files - {Key: "com.apple.security.files.user-selected.read-only", Name: "User-Selected Files (Read)", Description: "Read access to files the user selects", Category: "File Access"}, - {Key: "com.apple.security.files.user-selected.read-write", Name: "User-Selected Files (Read/Write)", Description: "Read/write access to files the user selects", Category: "File Access"}, - {Key: "com.apple.security.files.downloads.read-only", Name: "Downloads Folder (Read)", Description: "Read access to the Downloads folder", Category: "File Access"}, - {Key: "com.apple.security.files.downloads.read-write", Name: "Downloads Folder (Read/Write)", Description: "Read/write access to the Downloads folder", Category: "File Access"}, - - // Development - {Key: "com.apple.security.get-task-allow", Name: "Debugging", Description: "Allow debugging (disable for production)", Category: "Development"}, -} - -// EntitlementsSetup runs the interactive entitlements configuration wizard -func EntitlementsSetup(options *flags.EntitlementsSetup) error { - pterm.DefaultHeader.Println("macOS Entitlements Setup") - fmt.Println() - - // Build all options for custom selection - var allOptions []huh.Option[string] - for _, e := range availableEntitlements { - label := fmt.Sprintf("[%s] %s", e.Category, e.Name) - allOptions = append(allOptions, huh.NewOption(label, e.Key)) - } - - // Show quick presets first - var preset string - presetForm := huh.NewForm( - huh.NewGroup( - huh.NewSelect[string](). - Title("Which entitlements profile?"). - Description("Development and production use separate files"). - Options( - huh.NewOption("Development (entitlements.dev.plist)", "dev"), - huh.NewOption("Production (entitlements.plist)", "prod"), - huh.NewOption("Both (recommended)", "both"), - huh.NewOption("App Store (entitlements.plist with sandbox)", "appstore"), - huh.NewOption("Custom", "custom"), - ). - Value(&preset), - ), - ) - - if err := presetForm.Run(); err != nil { - return err - } - - devEntitlements := []string{ - "com.apple.security.cs.allow-jit", - "com.apple.security.cs.allow-unsigned-executable-memory", - "com.apple.security.cs.disable-library-validation", - "com.apple.security.get-task-allow", - "com.apple.security.network.client", - } - - prodEntitlements := []string{ - "com.apple.security.network.client", - } - - appStoreEntitlements := []string{ - "com.apple.security.app-sandbox", - "com.apple.security.network.client", - "com.apple.security.files.user-selected.read-write", - } - - baseDir := "build/darwin" - if options.Output != "" { - baseDir = filepath.Dir(options.Output) - } - - switch preset { - case "dev": - return writeEntitlementsFile(filepath.Join(baseDir, "entitlements.dev.plist"), devEntitlements) - - case "prod": - return writeEntitlementsFile(filepath.Join(baseDir, "entitlements.plist"), prodEntitlements) - - case "both": - if err := writeEntitlementsFile(filepath.Join(baseDir, "entitlements.dev.plist"), devEntitlements); err != nil { - return err - } - return writeEntitlementsFile(filepath.Join(baseDir, "entitlements.plist"), prodEntitlements) - - case "appstore": - return writeEntitlementsFile(filepath.Join(baseDir, "entitlements.plist"), appStoreEntitlements) - - case "custom": - // Let user choose which file and entitlements - var targetFile string - var selected []string - - customForm := huh.NewForm( - huh.NewGroup( - huh.NewSelect[string](). - Title("Target file"). - Options( - huh.NewOption("entitlements.plist (production)", "entitlements.plist"), - huh.NewOption("entitlements.dev.plist (development)", "entitlements.dev.plist"), - ). - Value(&targetFile), - ), - huh.NewGroup( - huh.NewMultiSelect[string](). - Title("Select entitlements"). - Description("Use space to select, enter to confirm"). - Options(allOptions...). - Value(&selected), - ), - ) - - if err := customForm.Run(); err != nil { - return err - } - - return writeEntitlementsFile(filepath.Join(baseDir, targetFile), selected) - } - - return nil -} - -func writeEntitlementsFile(path string, entitlements []string) error { - // Ensure directory exists - dir := filepath.Dir(path) - if err := os.MkdirAll(dir, 0755); err != nil { - return fmt.Errorf("failed to create directory: %w", err) - } - - // Generate and write the plist - plist := generateEntitlementsPlist(entitlements) - if err := os.WriteFile(path, []byte(plist), 0644); err != nil { - return fmt.Errorf("failed to write entitlements file: %w", err) - } - - pterm.Success.Printfln("Wrote %s", path) - - // Show summary - pterm.Info.Println("Entitlements:") - for _, key := range entitlements { - for _, e := range availableEntitlements { - if e.Key == key { - fmt.Printf(" - %s\n", e.Name) - break - } - } - } - fmt.Println() - - return nil -} - -func parseExistingEntitlements(path string) (map[string]bool, error) { - content, err := os.ReadFile(path) - if err != nil { - return nil, err - } - - result := make(map[string]bool) - lines := strings.Split(string(content), "\n") - - for i, line := range lines { - line = strings.TrimSpace(line) - if strings.HasPrefix(line, "") && strings.HasSuffix(line, "") { - key := strings.TrimPrefix(line, "") - key = strings.TrimSuffix(key, "") - - // Check if next line is - if i+1 < len(lines) { - nextLine := strings.TrimSpace(lines[i+1]) - if nextLine == "" { - result[key] = true - } - } - } - } - - return result, nil -} - -func generateEntitlementsPlist(entitlements []string) string { - var sb strings.Builder - - sb.WriteString(` - - - -`) - - for _, key := range entitlements { - sb.WriteString(fmt.Sprintf("\t%s\n", key)) - sb.WriteString("\t\n") - } - - sb.WriteString(` - -`) - - return sb.String() -} diff --git a/v3/internal/commands/generate_template.go b/v3/internal/commands/generate_template.go deleted file mode 100644 index 8903b5069..000000000 --- a/v3/internal/commands/generate_template.go +++ /dev/null @@ -1,9 +0,0 @@ -package commands - -import ( - "github.com/wailsapp/wails/v3/internal/templates" -) - -func GenerateTemplate(options *templates.BaseTemplate) error { - return templates.GenerateTemplate(options) -} diff --git a/v3/internal/commands/generate_webview2.go b/v3/internal/commands/generate_webview2.go deleted file mode 100644 index 60ec33a42..000000000 --- a/v3/internal/commands/generate_webview2.go +++ /dev/null @@ -1,43 +0,0 @@ -package commands - -import ( - _ "embed" - "fmt" - "github.com/wailsapp/wails/v3/internal/term" - "os" - "path/filepath" -) - -//go:embed webview2/MicrosoftEdgeWebview2Setup.exe -var webview2Bootstrapper []byte - -type GenerateWebView2Options struct { - Directory string `name:"dir" json:"directory"` -} - -func GenerateWebView2Bootstrapper(options *GenerateWebView2Options) error { - println("options.Directory", options.Directory) - options.Directory = filepath.Clean(options.Directory) - println("cleaned options.Directory", options.Directory) - - // If the file already exists, exit early - if _, err := os.Stat(filepath.Join(options.Directory, "MicrosoftEdgeWebview2Setup.exe")); err == nil { - return nil - } - - // Create target directory if it doesn't exist - err := os.MkdirAll(options.Directory, 0755) - if err != nil { - return fmt.Errorf("failed to create target directory: %w", err) - } - - // Write to target directory - targetPath := filepath.Join(options.Directory, "MicrosoftEdgeWebview2Setup.exe") - err = os.WriteFile(targetPath, webview2Bootstrapper, 0644) - if err != nil { - return fmt.Errorf("failed to write WebView2 bootstrapper: %w", err) - } - - term.Success("Generated WebView2 bootstrapper at: " + targetPath + "\n") - return nil -} diff --git a/v3/internal/commands/icons.go b/v3/internal/commands/icons.go deleted file mode 100644 index a25482d74..000000000 --- a/v3/internal/commands/icons.go +++ /dev/null @@ -1,359 +0,0 @@ -package commands - -import ( - "bytes" - "errors" - "fmt" - "image" - "image/color" - "image/png" - "os" - "os/exec" - "path/filepath" - "runtime" - "strconv" - "strings" - - "github.com/jackmordaunt/icns/v2" - "github.com/leaanthony/winicon" - "github.com/wailsapp/wails/v3/internal/operatingsystem" - "howett.net/plist" -) - -// ErrMacAssetNotSupported is returned by generateMacAsset when mac asset generation -// is not supported on the current platform (e.g., non-macOS systems). -var ErrMacAssetNotSupported = errors.New("mac asset generation is only supported on macOS") - -type IconsOptions struct { - Example bool `description:"Generate example icon file (appicon.png) in the current directory"` - Input string `description:"The input image file"` - Sizes string `description:"The sizes to generate in .ico file (comma separated)" default:"256,128,64,48,32,16"` - WindowsFilename string `description:"The output filename for the Windows icon"` - MacFilename string `description:"The output filename for the Mac icon bundle"` - IconComposerInput string `description:"The input Icon Composer file (.icon)"` - MacAssetDir string `description:"The output directory for the Mac assets (Assets.car and icons.icns)"` -} - -func GenerateIcons(options *IconsOptions) error { - DisableFooter = true - - if options.Example { - return generateExampleIcon() - } - - if options.Input == "" && options.IconComposerInput == "" { - return fmt.Errorf("either input or icon composer input is required") - } - - if options.Input != "" && options.WindowsFilename == "" && options.MacFilename == "" { - return fmt.Errorf("either windows filename or mac filename is required") - } - - if options.IconComposerInput != "" && options.MacAssetDir == "" { - return fmt.Errorf("mac asset directory is required") - } - - // Parse sizes - var sizes = []int{256, 128, 64, 48, 32, 16} - var err error - if options.Sizes != "" { - sizes, err = parseSizes(options.Sizes) - if err != nil { - return err - } - } - - // Generate Icons from Icon Composer input - macIconsGenerated := false - if options.IconComposerInput != "" { - if options.MacAssetDir != "" { - err := generateMacAsset(options) - if err != nil { - if errors.Is(err, ErrMacAssetNotSupported) { - // No fallback: Icon Composer path requires macOS; return so callers see unsupported-platform failure - if options.Input == "" { - return fmt.Errorf("icon composer input requires macOS for mac asset generation: %w", err) - } - // Fallback to input-based generation will run below - } else { - return err - } - } else { - macIconsGenerated = true - } - } - } - - // Generate Icons from input image - if options.Input != "" { - iconData, err := os.ReadFile(options.Input) - if err != nil { - return err - } - - if options.WindowsFilename != "" { - err := generateWindowsIcon(iconData, sizes, options) - if err != nil { - return err - } - } - - // Generate Icons from input image if no Mac icons were generated from Icon Composer input - if options.MacFilename != "" && !macIconsGenerated { - err := generateMacIcon(iconData, options) - if err != nil { - return err - } - } - } - - return nil -} - -func generateExampleIcon() error { - appIcon, err := buildAssets.ReadFile("build_assets/appicon.png") - if err != nil { - return err - } - return os.WriteFile("appicon.png", appIcon, 0644) -} - -func parseSizes(sizes string) ([]int, error) { - // split the input string by comma and confirm that each one is an integer - parsedSizes := strings.Split(sizes, ",") - var result []int - for _, size := range parsedSizes { - s, err := strconv.Atoi(size) - if err != nil { - return nil, err - } - if s == 0 { - continue - } - result = append(result, s) - } - - // put all integers in a slice and return - return result, nil -} - -func generateMacIcon(iconData []byte, options *IconsOptions) error { - - srcImg, _, err := image.Decode(bytes.NewBuffer(iconData)) - if err != nil { - return err - } - - dest, err := os.Create(options.MacFilename) - if err != nil { - return err - - } - defer func() { - err = dest.Close() - if err == nil { - return - } - }() - return icns.Encode(dest, srcImg) -} - -func generateMacAsset(options *IconsOptions) error { - //Check if running on darwin (macOS), because this will only run on a mac - if runtime.GOOS != "darwin" { - return ErrMacAssetNotSupported - } - // Get system info, because this will only run on macOS 26 or later - info, err := operatingsystem.Info() - if err != nil { - return ErrMacAssetNotSupported - } - majorStr, _, found := strings.Cut(info.Version, ".") - if !found { - return ErrMacAssetNotSupported - } - major, err := strconv.Atoi(majorStr) - if err != nil { - return ErrMacAssetNotSupported - } - if major < 26 { - return ErrMacAssetNotSupported - } - - cmd := exec.Command("/usr/bin/actool", "--version") - versionPlist, err := cmd.Output() - if err != nil { - return ErrMacAssetNotSupported - } - - // Parse the plist to extract short-bundle-version - var plistData map[string]any - if _, err := plist.Unmarshal(versionPlist, &plistData); err != nil { - return ErrMacAssetNotSupported - } - - // Navigate to com.apple.actool.version -> short-bundle-version - actoolVersion, ok := plistData["com.apple.actool.version"].(map[string]any) - if !ok { - return ErrMacAssetNotSupported - } - - shortVersion, ok := actoolVersion["short-bundle-version"].(string) - if !ok { - return ErrMacAssetNotSupported - } - - // Parse the major version number (e.g., "26.2" -> 26) - actoolMajorStr, _, _ := strings.Cut(shortVersion, ".") - actoolMajor, err := strconv.Atoi(actoolMajorStr) - if err != nil { - return ErrMacAssetNotSupported - } - - if actoolMajor < 26 { - return ErrMacAssetNotSupported - } - - // Convert paths to absolute paths (required for actool) - iconComposerPath, err := filepath.Abs(options.IconComposerInput) - if err != nil { - return fmt.Errorf("failed to get absolute path for icon composer input: %w", err) - } - macAssetDirPath, err := filepath.Abs(options.MacAssetDir) - if err != nil { - return fmt.Errorf("failed to get absolute path for mac asset directory: %w", err) - } - - // Get Filename from Icon Composer input without extension - iconComposerFilename := filepath.Base(iconComposerPath) - iconComposerFilename = strings.TrimSuffix(iconComposerFilename, filepath.Ext(iconComposerFilename)) - - cmd = exec.Command("/usr/bin/actool", iconComposerPath, - "--compile", macAssetDirPath, - "--notices", "--warnings", "--errors", - "--output-partial-info-plist", filepath.Join(macAssetDirPath, "temp.plist"), - "--app-icon", iconComposerFilename, - "--enable-on-demand-resources", "NO", - "--development-region", "en", - "--target-device", "mac", - "--minimum-deployment-target", "26.0", - "--platform", "macosx") - out, err := cmd.Output() - if err != nil { - return fmt.Errorf("failed to run actool: %w", err) - } - - // Parse the plist output to verify compilation results - var compilationResults map[string]any - if _, err := plist.Unmarshal(out, &compilationResults); err != nil { - return fmt.Errorf("failed to parse actool compilation results: %w", err) - } - - // Navigate to com.apple.actool.compilation-results -> output-files - compilationData, ok := compilationResults["com.apple.actool.compilation-results"].(map[string]any) - if !ok { - return fmt.Errorf("failed to find com.apple.actool.compilation-results in plist") - } - - outputFiles, ok := compilationData["output-files"].([]any) - if !ok { - return fmt.Errorf("failed to find output-files array in compilation results") - } - - // Check that we have one .car file and one .plist file - var carFile, plistFile, icnsFile string - for _, file := range outputFiles { - filePath, ok := file.(string) - if !ok { - return fmt.Errorf("output file is not a string: %v", file) - } - ext := filepath.Ext(filePath) - switch ext { - case ".car": - carFile = filePath - case ".plist": - plistFile = filePath - case ".icns": - icnsFile = filePath - // Ignore other output files that may be added in future actool versions - } - } - - if carFile == "" { - return fmt.Errorf("no .car file found in output files") - } - if plistFile == "" { - return fmt.Errorf("no .plist file found in output files") - } - if icnsFile == "" { - return fmt.Errorf("no .icns file found in output files") - } - - // Remove the temporary plist file since compilation was successful - if err := os.Remove(plistFile); err != nil { - return fmt.Errorf("failed to remove temporary plist file: %w", err) - } - - // Rename the .icns file to icons.icns - if err := os.Rename(icnsFile, filepath.Join(macAssetDirPath, "icons.icns")); err != nil { - return fmt.Errorf("failed to rename .icns file to icons.icns: %w", err) - } - - return nil -} - -func generateWindowsIcon(iconData []byte, sizes []int, options *IconsOptions) error { - - var output bytes.Buffer - - err := winicon.GenerateIcon(bytes.NewBuffer(iconData), &output, sizes) - if err != nil { - return err - } - - err = os.WriteFile(options.WindowsFilename, output.Bytes(), 0644) - if err != nil { - return err - } - return nil -} - -func GenerateTemplateIcon(data []byte, outputFilename string) (err error) { - // Decode the input file as a PNG - buffer := bytes.NewBuffer(data) - var img image.Image - img, err = png.Decode(buffer) - if err != nil { - return fmt.Errorf("failed to decode input file as PNG: %w", err) - } - - // Create a new image with the same dimensions and RGBA color model - bounds := img.Bounds() - iconImg := image.NewRGBA(bounds) - - // Iterate over each pixel of the input image - for y := bounds.Min.Y; y < bounds.Max.Y; y++ { - for x := bounds.Min.X; x < bounds.Max.X; x++ { - // Get the alpha of the pixel - _, _, _, a := img.At(x, y).RGBA() - iconImg.SetRGBA(x, y, color.RGBA{R: 0, G: 0, B: 0, A: uint8(a)}) - } - } - - // Create the output file - var outFile *os.File - outFile, err = os.Create(outputFilename) - if err != nil { - return fmt.Errorf("failed to create output file: %w", err) - } - defer func() { - err = outFile.Close() - }() - - // Encode the template icon image as a PNG and write it to the output file - if err = png.Encode(outFile, iconImg); err != nil { - return fmt.Errorf("failed to encode output image as PNG: %w", err) - } - - return nil -} diff --git a/v3/internal/commands/icons_test.go b/v3/internal/commands/icons_test.go deleted file mode 100644 index b13823e92..000000000 --- a/v3/internal/commands/icons_test.go +++ /dev/null @@ -1,335 +0,0 @@ -package commands - -import ( - "fmt" - "os" - "path/filepath" - "runtime" - "testing" -) - -func TestGenerateIcon(t *testing.T) { - tests := []struct { - name string - setup func() *IconsOptions - wantErr bool - requireDarwin bool - test func() error - }{ - { - name: "should generate an icon when using the `example` flag", - setup: func() *IconsOptions { - return &IconsOptions{ - Example: true, - } - }, - wantErr: false, - test: func() error { - // the file `appicon.png` should be created in the current directory - // check for the existence of the file - f, err := os.Stat("appicon.png") - if err != nil { - return err - } - defer func() { - err := os.Remove("appicon.png") - if err != nil { - panic(err) - } - }() - if f.IsDir() { - return fmt.Errorf("appicon.png is a directory") - } - if f.Size() == 0 { - return fmt.Errorf("appicon.png is empty") - } - return nil - }, - }, - { - name: "should generate a .ico file when using the `input` flag and `windowsfilename` flag", - setup: func() *IconsOptions { - // Get the directory of this file - _, thisFile, _, _ := runtime.Caller(1) - localDir := filepath.Dir(thisFile) - // Get the path to the example icon - exampleIcon := filepath.Join(localDir, "build_assets", "appicon.png") - return &IconsOptions{ - Input: exampleIcon, - WindowsFilename: "appicon.ico", - } - }, - wantErr: false, - test: func() error { - // the file `appicon.ico` should be created in the current directory - // check for the existence of the file - f, err := os.Stat("appicon.ico") - if err != nil { - return err - } - defer func() { - // Remove the file - _ = os.Remove("appicon.ico") - }() - if f.IsDir() { - return fmt.Errorf("appicon.ico is a directory") - } - if f.Size() == 0 { - return fmt.Errorf("appicon.ico is empty") - } - // Remove the file - err = os.Remove("appicon.ico") - if err != nil { - return err - } - return nil - }, - }, - { - name: "should generate a .icns file when using the `input` flag and `macfilename` flag", - setup: func() *IconsOptions { - // Get the directory of this file - _, thisFile, _, _ := runtime.Caller(1) - localDir := filepath.Dir(thisFile) - // Get the path to the example icon - exampleIcon := filepath.Join(localDir, "build_assets", "appicon.png") - return &IconsOptions{ - Input: exampleIcon, - MacFilename: "appicon.icns", - } - }, - wantErr: false, - test: func() error { - // the file `appicon.icns` should be created in the current directory - // check for the existence of the file - f, err := os.Stat("appicon.icns") - if err != nil { - return err - } - defer func() { - // Remove the file - err = os.Remove("appicon.icns") - if err != nil { - panic(err) - } - }() - if f.IsDir() { - return fmt.Errorf("appicon.icns is a directory") - } - if f.Size() == 0 { - return fmt.Errorf("appicon.icns is empty") - } - // Remove the file - - return nil - }, - }, - - { - name: "should generate a Assets.car and icons.icns file when using the `IconComposerInput` flag and `MacAssetDir` flag", - requireDarwin: true, - setup: func() *IconsOptions { - // Get the directory of this file - _, thisFile, _, _ := runtime.Caller(1) - localDir := filepath.Dir(thisFile) - // Get the path to the example icon - exampleIcon := filepath.Join(localDir, "build_assets", "appicon.icon") - return &IconsOptions{ - IconComposerInput: exampleIcon, - MacAssetDir: localDir, - } - }, - wantErr: false, - test: func() error { - _, thisFile, _, _ := runtime.Caller(1) - localDir := filepath.Dir(thisFile) - carPath := filepath.Join(localDir, "Assets.car") - icnsPath := filepath.Join(localDir, "icons.icns") - defer func() { - _ = os.Remove(carPath) - _ = os.Remove(icnsPath) - }() - f, err := os.Stat(carPath) - if err != nil { - return err - } - if f.IsDir() { - return fmt.Errorf("Assets.car is a directory") - } - if f.Size() == 0 { - return fmt.Errorf("Assets.car is empty") - } - f, err = os.Stat(icnsPath) - if err != nil { - return err - } - if f.IsDir() { - return fmt.Errorf("icons.icns is a directory") - } - if f.Size() == 0 { - return fmt.Errorf("icons.icns is empty") - } - return nil - }, - }, - { - name: "should generate a small .ico file when using the `input` flag and `sizes` flag", - setup: func() *IconsOptions { - // Get the directory of this file - _, thisFile, _, _ := runtime.Caller(1) - localDir := filepath.Dir(thisFile) - // Get the path to the example icon - exampleIcon := filepath.Join(localDir, "build_assets", "appicon.png") - return &IconsOptions{ - Input: exampleIcon, - Sizes: "16", - WindowsFilename: "appicon.ico", - } - }, - wantErr: false, - test: func() error { - // the file `appicon.ico` should be created in the current directory - // check for the existence of the file - f, err := os.Stat("appicon.ico") - if err != nil { - return err - } - defer func() { - err := os.Remove("appicon.ico") - if err != nil { - panic(err) - } - }() - // The size of the file should be 571 bytes - if f.Size() != 571 { - return fmt.Errorf("appicon.ico is not the correct size. Got %d", f.Size()) - } - if f.IsDir() { - return fmt.Errorf("appicon.ico is a directory") - } - if f.Size() == 0 { - return fmt.Errorf("appicon.ico is empty") - } - return nil - }, - }, - { - name: "should error if no input file is provided", - setup: func() *IconsOptions { - return &IconsOptions{} - }, - wantErr: true, - }, - { - name: "should error if neither mac or windows filename is provided", - setup: func() *IconsOptions { - // Get the directory of this file - _, thisFile, _, _ := runtime.Caller(1) - localDir := filepath.Dir(thisFile) - // Get the path to the example icon - exampleIcon := filepath.Join(localDir, "build_assets", "appicon.png") - return &IconsOptions{ - Input: exampleIcon, - } - }, - wantErr: true, - }, - { - name: "should error if bad sizes provided", - setup: func() *IconsOptions { - // Get the directory of this file - _, thisFile, _, _ := runtime.Caller(1) - localDir := filepath.Dir(thisFile) - // Get the path to the example icon - exampleIcon := filepath.Join(localDir, "build_assets", "appicon.png") - return &IconsOptions{ - Input: exampleIcon, - WindowsFilename: "appicon.ico", - Sizes: "bad", - } - }, - wantErr: true, - }, - { - name: "should ignore 0 size", - setup: func() *IconsOptions { - // Get the directory of this file - _, thisFile, _, _ := runtime.Caller(1) - localDir := filepath.Dir(thisFile) - // Get the path to the example icon - exampleIcon := filepath.Join(localDir, "build_assets", "appicon.png") - return &IconsOptions{ - Input: exampleIcon, - WindowsFilename: "appicon.ico", - Sizes: "0,16", - } - }, - wantErr: false, - test: func() error { - // Test the file exists and has 571 bytes - f, err := os.Stat("appicon.ico") - if err != nil { - return err - } - defer func() { - err := os.Remove("appicon.ico") - if err != nil { - panic(err) - } - }() - if f.Size() != 571 { - return fmt.Errorf("appicon.ico is not the correct size. Got %d", f.Size()) - } - if f.IsDir() { - return fmt.Errorf("appicon.ico is a directory") - } - if f.Size() == 0 { - return fmt.Errorf("appicon.ico is empty") - } - return nil - }, - }, - { - name: "should error if the input file does not exist", - setup: func() *IconsOptions { - return &IconsOptions{ - Input: "doesnotexist.png", - WindowsFilename: "appicon.ico", - } - }, - wantErr: true, - }, - { - name: "should error if the input file is not a png", - setup: func() *IconsOptions { - // Get the directory of this file - _, thisFile, _, _ := runtime.Caller(1) - return &IconsOptions{ - Input: thisFile, - WindowsFilename: "appicon.ico", - } - }, - wantErr: true, - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - if tt.requireDarwin && (runtime.GOOS != "darwin" || os.Getenv("CI") != "") { - t.Skip("Assets.car generation is only supported on macOS and not in CI") - } - - options := tt.setup() - err := GenerateIcons(options) - if (err != nil) != tt.wantErr { - t.Errorf("GenerateIcon() error = %v, wantErr %v", err, tt.wantErr) - return - } - if tt.test != nil { - if err := tt.test(); err != nil { - t.Errorf("GenerateIcon() test error = %v", err) - } - } - }) - } -} diff --git a/v3/internal/commands/init.go b/v3/internal/commands/init.go deleted file mode 100644 index 3f827d1b7..000000000 --- a/v3/internal/commands/init.go +++ /dev/null @@ -1,237 +0,0 @@ -package commands - -import ( - "errors" - "fmt" - "net/url" - "os" - "path/filepath" - "regexp" - "strings" - - "github.com/go-git/go-git/v5/config" - "github.com/wailsapp/wails/v3/internal/defaults" - "github.com/wailsapp/wails/v3/internal/term" - - "github.com/go-git/go-git/v5" - "github.com/pterm/pterm" - "github.com/wailsapp/wails/v3/internal/flags" - "github.com/wailsapp/wails/v3/internal/templates" -) - -var DisableFooter bool - -// See https://github.com/git/git/blob/master/Documentation/urls.adoc -var ( - gitProtocolFormat = regexp.MustCompile(`^(?:ssh|git|https?|ftps?|file)://`) - gitScpLikeGuard = regexp.MustCompile(`^[^/:]+:`) - gitScpLikeFormat = regexp.MustCompile(`^(?:([^@/:]+)@)?([^@/:]+):([^\\].*)$`) -) - -// gitURLToModulePath converts a git URL to a Go module name by removing common prefixes -// and suffixes. It handles HTTPS, SSH, Git protocol, and filesystem URLs. -func gitURLToModulePath(gitURL string) string { - var path string - - if gitProtocolFormat.MatchString(gitURL) { - // Standard URL - parsed, err := url.Parse(gitURL) - if err != nil { - term.Warningf("invalid Git repository URL: %s; module path will default to 'changeme'", err) - return "changeme" - } - - path = parsed.Host + parsed.Path - } else if gitScpLikeGuard.MatchString(gitURL) { - // SCP-like URL - match := gitScpLikeFormat.FindStringSubmatch(gitURL) - if match != nil { - sep := "" - if !strings.HasPrefix(match[3], "/") { - // Add slash between host and path if missing - sep = "/" - } - - path = match[2] + sep + match[3] - } - } - - if path == "" { - // Filesystem path - path = gitURL - } - - if strings.HasSuffix(path, ".git") { - path = path[:len(path)-4] - } - - // Remove leading forward slash for file system paths - return strings.TrimPrefix(path, "/") -} - -func initGitRepository(projectDir string, gitURL string) error { - // Initialize repository - repo, err := git.PlainInit(projectDir, false) - if err != nil { - return fmt.Errorf("failed to initialize git repository: %w", err) - } - - // Create remote - _, err = repo.CreateRemote(&config.RemoteConfig{ - Name: "origin", - URLs: []string{gitURL}, - }) - if err != nil { - return fmt.Errorf("failed to create git remote: %w", err) - } - - // Stage all files - worktree, err := repo.Worktree() - if err != nil { - return fmt.Errorf("failed to get git worktree: %w", err) - } - - _, err = worktree.Add(".") - if err != nil { - return fmt.Errorf("failed to stage files: %w", err) - } - - return nil -} - -// applyGlobalDefaults applies global defaults to init options if they are using default values -func applyGlobalDefaults(options *flags.Init, globalDefaults defaults.GlobalDefaults) { - // Apply template default if using the built-in default - if options.TemplateName == "vanilla" && globalDefaults.Project.DefaultTemplate != "" { - options.TemplateName = globalDefaults.Project.DefaultTemplate - } - - // Apply company default if using the built-in default - if options.ProductCompany == "My Company" && globalDefaults.Author.Company != "" { - options.ProductCompany = globalDefaults.Author.Company - } - - // Apply copyright from global defaults if using the built-in default - if options.ProductCopyright == "\u00a9 now, My Company" { - options.ProductCopyright = globalDefaults.GenerateCopyright() - } - - // Apply product identifier from global defaults if not explicitly set - if options.ProductIdentifier == "" && globalDefaults.Project.ProductIdentifierPrefix != "" { - options.ProductIdentifier = globalDefaults.GenerateProductIdentifier(options.ProjectName) - } - - // Apply description from global defaults if using the built-in default - if options.ProductDescription == "My Product Description" && globalDefaults.Project.DescriptionTemplate != "" { - options.ProductDescription = globalDefaults.GenerateDescription(options.ProjectName) - } - - // Apply version from global defaults if using the built-in default - if options.ProductVersion == "0.1.0" && globalDefaults.Project.DefaultVersion != "" { - options.ProductVersion = globalDefaults.GetDefaultVersion() - } -} - -func Init(options *flags.Init) error { - if options.List { - term.Header("Available templates") - return printTemplates() - } - - if options.Quiet { - term.DisableOutput() - } - term.Header("Init project") - - // Check if the template is a typescript template - isTypescript := false - if strings.HasSuffix(options.TemplateName, "-ts") { - isTypescript = true - } - - if options.ProjectName == "" { - return errors.New("please use the -n flag to specify a project name") - } - - options.ProjectName = sanitizeFileName(options.ProjectName) - - // Load and apply global defaults - globalDefaults, err := defaults.Load() - if err != nil { - // Log warning but continue - global defaults are optional - term.Warningf("Could not load global defaults: %v\n", err) - } else { - applyGlobalDefaults(options, globalDefaults) - } - - if options.ModulePath == "" { - if options.Git == "" { - options.ModulePath = "changeme" - } else { - options.ModulePath = gitURLToModulePath(options.Git) - } - } - - err = templates.Install(options) - if err != nil { - return err - } - - // Rename gitignore to .gitignore - err = os.Rename(filepath.Join(options.ProjectDir, "gitignore"), filepath.Join(options.ProjectDir, ".gitignore")) - if err != nil { - return err - } - - // Generate build assets - buildAssetsOptions := &BuildAssetsOptions{ - Name: options.ProjectName, - Dir: filepath.Join(options.ProjectDir, "build"), - Silent: true, - ProductCompany: options.ProductCompany, - ProductName: options.ProductName, - ProductDescription: options.ProductDescription, - ProductVersion: options.ProductVersion, - ProductIdentifier: options.ProductIdentifier, - ProductCopyright: options.ProductCopyright, - ProductComments: options.ProductComments, - Typescript: isTypescript, - } - err = GenerateBuildAssets(buildAssetsOptions) - if err != nil { - return err - } - // Initialize git repository if URL is provided - if options.Git != "" { - err = initGitRepository(options.ProjectDir, options.Git) - if err != nil { - return err - } - if !options.Quiet { - term.Infof("Initialized git repository with remote: %s\n", options.Git) - } - } - return nil -} - -func printTemplates() error { - defaultTemplates := templates.GetDefaultTemplates() - - pterm.Println() - table := pterm.TableData{{"Name", "Description"}} - for _, template := range defaultTemplates { - table = append(table, []string{template.Name, template.Description}) - } - err := pterm.DefaultTable.WithHasHeader(true).WithBoxed(true).WithData(table).Render() - pterm.Println() - return err -} - -func sanitizeFileName(fileName string) string { - // Regular expression to match non-allowed characters in file names - // You can adjust this based on the specific requirements of your file system - reg := regexp.MustCompile(`[^a-zA-Z0-9_.-]`) - - // Replace matched characters with an underscore or any other safe character - return reg.ReplaceAllString(fileName, "_") -} diff --git a/v3/internal/commands/init_test.go b/v3/internal/commands/init_test.go deleted file mode 100644 index cb1b30d48..000000000 --- a/v3/internal/commands/init_test.go +++ /dev/null @@ -1,116 +0,0 @@ -package commands - -import ( - "testing" -) - -func TestGitURLToModulePath(t *testing.T) { - tests := []struct { - name string - gitURL string - want string - }{ - { - name: "Simple GitHub URL", - gitURL: "github.com/username/project", - want: "github.com/username/project", - }, - { - name: "GitHub URL with .git suffix", - gitURL: "github.com/username/project.git", - want: "github.com/username/project", - }, - { - name: "HTTPS GitHub URL", - gitURL: "https://github.com/username/project", - want: "github.com/username/project", - }, - { - name: "HTTPS GitHub URL with .git suffix", - gitURL: "https://github.com/username/project.git", - want: "github.com/username/project", - }, - { - name: "HTTP GitHub URL", - gitURL: "http://github.com/username/project", - want: "github.com/username/project", - }, - { - name: "HTTP GitHub URL with .git suffix", - gitURL: "http://github.com/username/project.git", - want: "github.com/username/project", - }, - { - name: "SSH GitHub URL", - gitURL: "git@github.com:username/project", - want: "github.com/username/project", - }, - { - name: "SSH GitHub URL with .git suffix", - gitURL: "git@github.com:username/project.git", - want: "github.com/username/project", - }, - { - name: "Alternative SSH URL format", - gitURL: "ssh://git@github.com/username/project.git", - want: "github.com/username/project", - }, - { - name: "Git protocol URL", - gitURL: "git://github.com/username/project.git", - want: "github.com/username/project", - }, - { - name: "File system URL", - gitURL: "file:///path/to/project.git", - want: "path/to/project", - }, - { - name: "SSH GitLab URL", - gitURL: "git@gitlab.com:username/project.git", - want: "gitlab.com/username/project", - }, - { - name: "SSH Custom Domain", - gitURL: "git@git.company.com:username/project.git", - want: "git.company.com/username/project", - }, - { - name: "GitLab URL", - gitURL: "gitlab.com/username/project", - want: "gitlab.com/username/project", - }, - { - name: "BitBucket URL", - gitURL: "bitbucket.org/username/project", - want: "bitbucket.org/username/project", - }, - { - name: "Custom domain", - gitURL: "git.company.com/username/project", - want: "git.company.com/username/project", - }, - { - name: "Custom domain with HTTPS and .git", - gitURL: "https://git.company.com/username/project.git", - want: "git.company.com/username/project", - }, - { - name: "Empty string", - gitURL: "", - want: "", - }, - { - name: "Just .git suffix", - gitURL: ".git", - want: "", - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - if got := gitURLToModulePath(tt.gitURL); got != tt.want { - t.Errorf("gitURLToModulePath() = %v, want %v", got, tt.want) - } - }) - } -} diff --git a/v3/internal/commands/ios_overlay_gen.go b/v3/internal/commands/ios_overlay_gen.go deleted file mode 100644 index 918fc0dab..000000000 --- a/v3/internal/commands/ios_overlay_gen.go +++ /dev/null @@ -1,115 +0,0 @@ -package commands - -import ( - "encoding/json" - "errors" - "fmt" - "io/fs" - "os" - "path/filepath" -) - -// IOSOverlayGenOptions holds parameters for overlay generation. -type IOSOverlayGenOptions struct { - Out string `description:"Path to write overlay.json" default:"build/ios/xcode/overlay.json"` - Config string `description:"Path to build/config.yml (optional)" default:"build/config.yml"` -} - -// IOSOverlayGen generates a Go build overlay JSON that injects a generated -// main_ios.gen.go exporting WailsIOSMain() which calls main(). -// -// It writes: -// - : overlay JSON file -// - /gen/main_ios.gen.go : the generated Go file referenced by the overlay -// -// The overlay maps /main_ios.gen.go -> /gen/main_ios.gen.go -func IOSOverlayGen(options *IOSOverlayGenOptions) error { // options currently unused beyond defaults - out := options.Out - - if out == "" { - return errors.New("--out is required (path to write overlay.json)") - } - - absOut, err := filepath.Abs(out) - if err != nil { - return err - } - targetDir := filepath.Dir(absOut) - if err := os.MkdirAll(targetDir, 0o755); err != nil { - return err - } - - // Locate the internal template file to source content - root, err := repoRoot() - if err != nil { - return err - } - tmplPath := filepath.Join(root, "v3", "internal", "commands", "build_assets", "ios", "main_ios.go") - content, err := os.ReadFile(tmplPath) - if err != nil { - return fmt.Errorf("read template %s: %w", tmplPath, err) - } - - genDir := filepath.Join(targetDir, "gen") - if err := os.MkdirAll(genDir, 0o755); err != nil { - return err - } - genGo := filepath.Join(genDir, "main_ios.gen.go") - if err := os.WriteFile(genGo, content, 0o644); err != nil { - return err - } - - // Determine app dir (current working directory) - appDir, err := os.Getwd() - if err != nil { - return err - } - virtual := filepath.Join(appDir, "main_ios.gen.go") - - type overlay struct { - Replace map[string]string `json:"Replace"` - } - ov := overlay{Replace: map[string]string{virtual: genGo}} - data, err := json.MarshalIndent(ov, "", " ") - if err != nil { - return err - } - if err := os.WriteFile(absOut, data, 0o644); err != nil { - return err - } - return nil -} - -// IOSOverlayGenCmd is a CLI entry compatible with NewSubCommandFunction. -// Defaults: -// config: ./build/config.yml (optional) -// out: ./build/ios/xcode/overlay.json -func IOSOverlayGenCmd() error { - // Default paths relative to CWD - out := filepath.Join("build", "ios", "xcode", "overlay.json") - cfg := filepath.Join("build", "config.yml") - return IOSOverlayGen(&IOSOverlayGenOptions{Out: out, Config: cfg}) -} - -// repoRoot attempts to find the repository root relative to this file location. -func repoRoot() (string, error) { - // Resolve based on the location of this source at build time if possible. - self, err := os.Getwd() - if err != nil { - return "", err - } - // Walk up until we find a directory containing v3/internal/commands - probe := self - for i := 0; i < 10; i++ { - p := filepath.Join(probe, "v3", "internal", "commands") - if st, err := os.Stat(p); err == nil && st.IsDir() { - return probe, nil - } - next := filepath.Dir(probe) - if next == probe { - break - } - probe = next - } - return "", fs.ErrNotExist -} diff --git a/v3/internal/commands/ios_xcode_gen.go b/v3/internal/commands/ios_xcode_gen.go deleted file mode 100644 index 1f883a12f..000000000 --- a/v3/internal/commands/ios_xcode_gen.go +++ /dev/null @@ -1,298 +0,0 @@ -package commands - -import ( - "bytes" - "fmt" - "image" - "image/png" - "io" - "io/fs" - "os" - "path/filepath" - "text/template" - - "golang.org/x/image/draw" - "gopkg.in/yaml.v3" -) - -// IOSXcodeGenOptions holds parameters for Xcode project generation. -type IOSXcodeGenOptions struct { - OutDir string `description:"Output directory for generated Xcode project" default:"build/ios/xcode"` - Config string `description:"Path to build/config.yml (optional)" default:"build/config.yml"` -} - -// generateIOSAppIcons creates required iOS AppIcon PNGs into appIconsetDir using inputIcon PNG. -func generateIOSAppIcons(inputIcon string, appIconsetDir string) error { - in, err := os.Open(inputIcon) - if err != nil { - return err - } - defer in.Close() - return generateIOSAppIconsFromReader(in, appIconsetDir) -} - -// generateIOSAppIconsFromReader decodes an image source and writes all required sizes. -func generateIOSAppIconsFromReader(r io.Reader, appIconsetDir string) error { - src, _, err := image.Decode(r) - if err != nil { - return fmt.Errorf("decode appicon: %w", err) - } - - // Mapping: filename -> size(px) (unique keys only) - sizes := map[string]int{ - "icon-20.png": 20, - "icon-20@2x.png": 40, - "icon-20@3x.png": 60, - "icon-29.png": 29, - "icon-29@2x.png": 58, - "icon-29@3x.png": 87, - "icon-40.png": 40, - "icon-40@2x.png": 80, - "icon-40@3x.png": 120, - "icon-60@2x.png": 120, - "icon-60@3x.png": 180, - "icon-76.png": 76, - "icon-76@2x.png": 152, - "icon-83.5@2x.png": 167, - "icon-1024.png": 1024, - } - - // To avoid duplicate work, use a small cache of resized images by dimension - cache := map[int]image.Image{} - resize := func(dim int) image.Image { - if img, ok := cache[dim]; ok { - return img - } - dst := image.NewRGBA(image.Rect(0, 0, dim, dim)) - draw.CatmullRom.Scale(dst, dst.Bounds(), src, src.Bounds(), draw.Over, nil) - cache[dim] = dst - return dst - } - - for filename, dim := range sizes { - // Create output file - outPath := filepath.Join(appIconsetDir, filename) - f, err := os.Create(outPath) - if err != nil { - return err - } - if err := png.Encode(f, resize(dim)); err != nil { - _ = f.Close() - return fmt.Errorf("encode %s: %w", filename, err) - } - if err := f.Close(); err != nil { - return err - } - } - return nil -} - -// iosBuildYAML is a permissive schema used to populate iOS project config from build/config.yml. -type iosBuildYAML struct { - IOS struct { - BundleID string `yaml:"bundleID"` - DisplayName string `yaml:"displayName"` - Version string `yaml:"version"` - Company string `yaml:"company"` - Comments string `yaml:"comments"` - } `yaml:"ios"` - Info struct { - ProductName string `yaml:"productName"` - ProductIdentifier string `yaml:"productIdentifier"` - Version string `yaml:"version"` - CompanyName string `yaml:"companyName"` - Comments string `yaml:"comments"` - Copyright string `yaml:"copyright"` - Description string `yaml:"description"` - } `yaml:"info"` -} - -// loadIOSProjectConfig merges defaults with values from build/config.yml if present. -func loadIOSProjectConfig(configPath string, cfg *iOSProjectConfig) error { - if configPath == "" { - return nil - } - if _, err := os.Stat(configPath); os.IsNotExist(err) { - return nil - } - data, err := os.ReadFile(configPath) - if err != nil { - return err - } - var in iosBuildYAML - if err := yaml.Unmarshal(data, &in); err != nil { - return err - } - // Prefer ios.* if set, otherwise fall back to info.* where applicable - if in.IOS.DisplayName != "" { - cfg.ProductName = in.IOS.DisplayName - } else if in.Info.ProductName != "" { - cfg.ProductName = in.Info.ProductName - } - if in.IOS.BundleID != "" { - cfg.ProductIdentifier = in.IOS.BundleID - } else if in.Info.ProductIdentifier != "" { - cfg.ProductIdentifier = in.Info.ProductIdentifier - } - if in.IOS.Version != "" { - cfg.ProductVersion = in.IOS.Version - } else if in.Info.Version != "" { - cfg.ProductVersion = in.Info.Version - } - if in.IOS.Company != "" { - cfg.ProductCompany = in.IOS.Company - } else if in.Info.CompanyName != "" { - cfg.ProductCompany = in.Info.CompanyName - } - if in.IOS.Comments != "" { - cfg.ProductComments = in.IOS.Comments - } else if in.Info.Comments != "" { - cfg.ProductComments = in.Info.Comments - } - // Copyright comes from info.* for now (no iOS override defined yet) - if in.Info.Copyright != "" { - cfg.ProductCopyright = in.Info.Copyright - } - // Description comes from info.* for now (no iOS override defined yet) - if in.Info.Description != "" { - cfg.ProductDescription = in.Info.Description - } - // BinaryName remains default unless we later add config support - return nil -} - -// iOSProjectConfig is a minimal config used to fill templates. Extend later to read build/config.yml. -type iOSProjectConfig struct { - ProductName string - BinaryName string - ProductIdentifier string - ProductVersion string - ProductCompany string - ProductComments string - ProductCopyright string - ProductDescription string -} - -// IOSXcodeGen generates an Xcode project skeleton for the current app. -func IOSXcodeGen(options *IOSXcodeGenOptions) error { - outDir := options.OutDir - if outDir == "" { - outDir = filepath.Join("build", "ios", "xcode") - } - if err := os.MkdirAll(outDir, 0o755); err != nil { - return err - } - - // Create standard layout - mainDir := filepath.Join(outDir, "main") - if err := os.MkdirAll(mainDir, 0o755); err != nil { - return err - } - // Create placeholder .xcodeproj dir - xcodeprojDir := filepath.Join(outDir, "main.xcodeproj") - if err := os.MkdirAll(xcodeprojDir, 0o755); err != nil { - return err - } - - // Prepare config with defaults, then merge from build/config.yml if present - cfg := iOSProjectConfig{ - ProductName: "Wails App", - BinaryName: "wailsapp", - ProductIdentifier: "com.wails.app", - ProductVersion: "0.1.0", - ProductCompany: "", - ProductComments: "", - ProductCopyright: "", - ProductDescription: "", - } - if err := loadIOSProjectConfig(options.Config, &cfg); err != nil { - return fmt.Errorf("parse config: %w", err) - } - - // Render Info.plist - if err := renderTemplateTo(updatableBuildAssets, "updatable_build_assets/ios/Info.plist.tmpl", filepath.Join(mainDir, "Info.plist"), cfg); err != nil { - return fmt.Errorf("render Info.plist: %w", err) - } - // Render LaunchScreen.storyboard - if err := renderTemplateTo(updatableBuildAssets, "updatable_build_assets/ios/LaunchScreen.storyboard.tmpl", filepath.Join(mainDir, "LaunchScreen.storyboard"), cfg); err != nil { - return fmt.Errorf("render LaunchScreen.storyboard: %w", err) - } - - // Copy main.m from assets (lives under build_assets) - if err := copyEmbeddedFile(buildAssets, "build_assets/ios/main.m", filepath.Join(mainDir, "main.m")); err != nil { - return fmt.Errorf("copy main.m: %w", err) - } - - // Create Assets.xcassets/AppIcon.appiconset and Contents.json - assetsDir := filepath.Join(mainDir, "Assets.xcassets", "AppIcon.appiconset") - if err := os.MkdirAll(assetsDir, 0o755); err != nil { - return err - } - if err := renderTemplateTo(updatableBuildAssets, "updatable_build_assets/ios/Assets.xcassets.tmpl", filepath.Join(assetsDir, "Contents.json"), cfg); err != nil { - return fmt.Errorf("render AppIcon Contents.json: %w", err) - } - - // Generate iOS AppIcon PNGs from build/appicon.png if present; otherwise use embedded default - inputIcon := filepath.Join("build", "appicon.png") - if _, err := os.Stat(inputIcon); err == nil { - if err := generateIOSAppIcons(inputIcon, assetsDir); err != nil { - return fmt.Errorf("generate iOS icons: %w", err) - } - } else { - if data, rerr := buildAssets.ReadFile("build_assets/appicon.png"); rerr == nil { - if err := generateIOSAppIconsFromReader(bytes.NewReader(data), assetsDir); err != nil { - return fmt.Errorf("generate default iOS icons: %w", err) - } - } - } - - // Render project.pbxproj from template - projectPbxproj := filepath.Join(xcodeprojDir, "project.pbxproj") - if err := renderTemplateTo(updatableBuildAssets, "updatable_build_assets/ios/project.pbxproj.tmpl", projectPbxproj, cfg); err != nil { - return fmt.Errorf("render project.pbxproj: %w", err) - } - return nil -} - -// renderTemplateTo reads a template file from an embed FS and writes it to dest using data. -func renderTemplateTo(efs fs.FS, templatePath, dest string, data any) error { - raw, err := fs.ReadFile(efs, templatePath) - if err != nil { - return err - } - if err := os.MkdirAll(filepath.Dir(dest), 0o755); err != nil { - return err - } - t, err := template.New(filepath.Base(templatePath)).Parse(string(raw)) - if err != nil { - return err - } - f, err := os.Create(dest) - if err != nil { - return err - } - defer func() { _ = f.Close() }() - return t.Execute(f, data) -} - -// copyEmbeddedFile writes a file from an embed FS path to dest. -func copyEmbeddedFile(efs fs.FS, src, dest string) error { - data, err := fs.ReadFile(efs, src) - if err != nil { - return err - } - if err := os.MkdirAll(filepath.Dir(dest), 0o755); err != nil { - return err - } - return os.WriteFile(dest, data, 0o644) -} - -// IOSXcodeGenCmd is a CLI entry compatible with NewSubCommandFunction. -// Defaults: -// config: ./build/config.yml (optional) -// out: ./build/ios/xcode -func IOSXcodeGenCmd() error { - out := filepath.Join("build", "ios", "xcode") - cfg := filepath.Join("build", "config.yml") - return IOSXcodeGen(&IOSXcodeGenOptions{OutDir: out, Config: cfg}) -} diff --git a/v3/internal/commands/linuxdeploy-plugin-gtk.sh b/v3/internal/commands/linuxdeploy-plugin-gtk.sh deleted file mode 100644 index 51c1231dd..000000000 --- a/v3/internal/commands/linuxdeploy-plugin-gtk.sh +++ /dev/null @@ -1,376 +0,0 @@ -#! /usr/bin/env bash - -# Source: https://raw.githubusercontent.com/linuxdeploy/linuxdeploy-plugin-gtk/master/linuxdeploy-plugin-gtk.sh -# License: MIT (https://github.com/linuxdeploy/linuxdeploy-plugin-gtk/blob/master/LICENSE.txt) - -# GTK3 environment variables: https://developer.gnome.org/gtk3/stable/gtk-running.html -# GTK4 environment variables: https://developer.gnome.org/gtk4/stable/gtk-running.html - -# abort on all errors -set -e - -if [ "$DEBUG" != "" ]; then - set -x - verbose="--verbose" -fi - -SCRIPT="$(basename "$(readlink -f "$0")")" - -show_usage() { - echo "Usage: $SCRIPT --appdir " - echo - echo "Bundles resources for applications that use GTK into an AppDir" - echo - echo "Required variables:" - echo " LINUXDEPLOY=\".../linuxdeploy\" path to linuxdeploy (e.g., AppImage); set automatically when plugin is run directly by linuxdeploy" - echo - echo "Optional variables:" - echo " DEPLOY_GTK_VERSION (major version of GTK to deploy, e.g. '2', '3' or '4'; auto-detect by default)" -} - -variable_is_true() { - local var="$1" - - if [ -n "$var" ] && { [ "$var" == "true" ] || [ "$var" -gt 0 ]; } 2> /dev/null; then - return 0 # true - else - return 1 # false - fi -} - -get_pkgconf_variable() { - local variable="$1" - local library="$2" - local default_value="$3" - - pkgconfig_ret="$("$PKG_CONFIG" --variable="$variable" "$library")" - if [ -n "$pkgconfig_ret" ]; then - echo "$pkgconfig_ret" - elif [ -n "$default_value" ]; then - echo "$default_value" - else - echo "$0: there is no '$variable' variable for '$library' library." > /dev/stderr - echo "Please check the '$library.pc' file is present in \$PKG_CONFIG_PATH (you may need to install the appropriate -dev/-devel package)." > /dev/stderr - exit 1 - fi -} - -copy_tree() { - local src=("${@:1:$#-1}") - local dst="${*:$#}" - - for elem in "${src[@]}"; do - mkdir -p "${dst::-1}$elem" - cp "$elem" --archive --parents --target-directory="$dst" $verbose - done -} - -copy_lib_tree() { - # The source lib directory could be /usr/lib, /usr/lib64, or /usr/lib/x86_64-linux-gnu - # Therefore, when copying lib directories, we need to transform that target path - # to a consistent /usr/lib - local src=("${@:1:$#-1}") - local dst="${*:$#}" - - for elem in "${src[@]}"; do - mkdir -p "${dst::-1}${elem/$LD_GTK_LIBRARY_PATH//usr/lib}" - pushd "$LD_GTK_LIBRARY_PATH" - cp "$(realpath --relative-to="$LD_GTK_LIBRARY_PATH" "$elem")" --archive --parents --target-directory="$dst/usr/lib" $verbose - popd - done -} - -get_triplet_path() { - if command -v dpkg-architecture > /dev/null; then - echo "/usr/lib/$(dpkg-architecture -qDEB_HOST_MULTIARCH)" - fi -} - - - -search_library_path() { - PATH_ARRAY=( - "$(get_triplet_path)" - "/usr/lib64" - "/usr/lib" - ) - - for path in "${PATH_ARRAY[@]}"; do - if [ -d "$path" ]; then - echo "$path" - return 0 - fi - done -} - -search_tool() { - local tool="$1" - local directory="$2" - - if command -v "$tool"; then - return 0 - fi - - PATH_ARRAY=( - "$(get_triplet_path)/$directory/$tool" - "/usr/lib64/$directory/$tool" - "/usr/lib/$directory/$tool" - "/usr/bin/$tool" - "/usr/bin/$tool-64" - "/usr/bin/$tool-32" - ) - - for path in "${PATH_ARRAY[@]}"; do - if [ -x "$path" ]; then - echo "$path" - return 0 - fi - done -} - -DEPLOY_GTK_VERSION="${DEPLOY_GTK_VERSION:-0}" # When not set by user, this variable use the integer '0' as a sentinel value -APPDIR= - -while [ "$1" != "" ]; do - case "$1" in - --plugin-api-version) - echo "0" - exit 0 - ;; - --appdir) - APPDIR="$2" - shift - shift - ;; - --help) - show_usage - exit 0 - ;; - *) - echo "Invalid argument: $1" - echo - show_usage - exit 1 - ;; - esac -done - -if [ "$APPDIR" == "" ]; then - show_usage - exit 1 -fi - -APPDIR="$(realpath "$APPDIR")" -mkdir -p "$APPDIR" - -. /etc/os-release -if [ "$ID" = "debian" ] || [ "$ID" = "ubuntu" ]; then - if ! command -v dpkg-architecture &>/dev/null; then - echo -e "$0: dpkg-architecture not found.\nInstall dpkg-dev then re-run the plugin." - exit 1 - fi -fi - -if command -v pkgconf > /dev/null; then - PKG_CONFIG="pkgconf" -elif command -v pkg-config > /dev/null; then - PKG_CONFIG="pkg-config" -else - echo "$0: pkg-config/pkgconf not found in PATH, aborting" - exit 1 -fi - -# GTK's library path *must not* have a trailing slash for later parameter substitution to work properly -LD_GTK_LIBRARY_PATH="$(realpath "${LD_GTK_LIBRARY_PATH:-$(search_library_path)}")" - -if ! command -v find &>/dev/null && ! type find &>/dev/null; then - echo -e "$0: find not found.\nInstall findutils then re-run the plugin." - exit 1 -fi - -if [ -z "$LINUXDEPLOY" ]; then - echo -e "$0: LINUXDEPLOY environment variable is not set.\nDownload a suitable linuxdeploy AppImage, set the environment variable and re-run the plugin." - exit 1 -fi - -gtk_versions=0 # Count major versions of GTK when auto-detect GTK version -if [ "$DEPLOY_GTK_VERSION" -eq 0 ]; then - echo "Determining which GTK version to deploy" - while IFS= read -r -d '' file; do - if [ "$DEPLOY_GTK_VERSION" -ne 2 ] && ldd "$file" | grep -q "libgtk-x11-2.0.so"; then - DEPLOY_GTK_VERSION=2 - gtk_versions="$((gtk_versions+1))" - fi - if [ "$DEPLOY_GTK_VERSION" -ne 3 ] && ldd "$file" | grep -q "libgtk-3.so"; then - DEPLOY_GTK_VERSION=3 - gtk_versions="$((gtk_versions+1))" - fi - if [ "$DEPLOY_GTK_VERSION" -ne 4 ] && ldd "$file" | grep -q "libgtk-4.so"; then - DEPLOY_GTK_VERSION=4 - gtk_versions="$((gtk_versions+1))" - fi - done < <(find "$APPDIR/usr/bin" -executable -type f -print0) -fi - -if [ "$gtk_versions" -gt 1 ]; then - echo "$0: can not deploy multiple GTK versions at the same time." - echo "Please set DEPLOY_GTK_VERSION to {2, 3, 4}." - exit 1 -elif [ "$DEPLOY_GTK_VERSION" -eq 0 ]; then - echo "$0: failed to auto-detect GTK version." - echo "Please set DEPLOY_GTK_VERSION to {2, 3, 4}." - exit 1 -fi - -echo "Installing AppRun hook" -HOOKSDIR="$APPDIR/apprun-hooks" -HOOKFILE="$HOOKSDIR/linuxdeploy-plugin-gtk.sh" -mkdir -p "$HOOKSDIR" -cat > "$HOOKFILE" <<\EOF -#! /usr/bin/env bash - -COLOR_SCHEME="$(dbus-send --session --dest=org.freedesktop.portal.Desktop --type=method_call --print-reply --reply-timeout=1000 /org/freedesktop/portal/desktop org.freedesktop.portal.Settings.Read 'string:org.freedesktop.appearance' 'string:color-scheme' 2> /dev/null | tail -n1 | cut -b35- | cut -d' ' -f2 || printf '')" -if [ -z "$COLOR_SCHEME" ]; then - COLOR_SCHEME="$(gsettings get org.gnome.desktop.interface color-scheme 2> /dev/null || printf '')" -fi -case "$COLOR_SCHEME" in - "1"|"'prefer-dark'") GTK_THEME_VARIANT="dark";; - "2"|"'prefer-light'") GTK_THEME_VARIANT="light";; - *) GTK_THEME_VARIANT="light";; -esac -APPIMAGE_GTK_THEME="${APPIMAGE_GTK_THEME:-"Adwaita:$GTK_THEME_VARIANT"}" # Allow user to override theme (discouraged) - -export APPDIR="${APPDIR:-"$(dirname "$(realpath "$0")")"}" # Workaround to run extracted AppImage -export GTK_DATA_PREFIX="$APPDIR" -export GTK_THEME="$APPIMAGE_GTK_THEME" # Custom themes are broken -export GDK_BACKEND=x11 # Crash with Wayland backend on Wayland -export XDG_DATA_DIRS="$APPDIR/usr/share:/usr/share:$XDG_DATA_DIRS" # g_get_system_data_dirs() from GLib -EOF - -echo "Installing GLib schemas" -# Note: schemasdir is undefined on Ubuntu 16.04 -glib_schemasdir="$(get_pkgconf_variable "schemasdir" "gio-2.0" "/usr/share/glib-2.0/schemas")" -copy_tree "$glib_schemasdir" "$APPDIR/" -glib-compile-schemas "$APPDIR/$glib_schemasdir" -cat >> "$HOOKFILE" <> "$HOOKFILE" <> "$HOOKFILE" < "$APPDIR/${gtk3_immodules_cache_file/$LD_GTK_LIBRARY_PATH//usr/lib}" - else - echo "WARNING: gtk-query-immodules-3.0 not found" - fi - if [ ! -f "$APPDIR/${gtk3_immodules_cache_file/$LD_GTK_LIBRARY_PATH//usr/lib}" ]; then - echo "WARNING: immodules.cache file is missing" - fi - sed -i "s|$gtk3_libdir/3.0.0/immodules/||g" "$APPDIR/${gtk3_immodules_cache_file/$LD_GTK_LIBRARY_PATH//usr/lib}" - ;; - 4) - echo "Installing GTK 4.0 modules" - gtk4_exec_prefix="$(get_pkgconf_variable "exec_prefix" "gtk4" "/usr")" - gtk4_libdir="$(get_pkgconf_variable "libdir" "gtk4")/gtk-4.0" - gtk4_path="$gtk4_libdir" - copy_lib_tree "$gtk4_libdir" "$APPDIR/" - cat >> "$HOOKFILE" <> "$HOOKFILE" < "$APPDIR/${gdk_pixbuf_cache_file/$LD_GTK_LIBRARY_PATH//usr/lib}" -else - echo "WARNING: gdk-pixbuf-query-loaders not found" -fi -if [ ! -f "$APPDIR/${gdk_pixbuf_cache_file/$LD_GTK_LIBRARY_PATH//usr/lib}" ]; then - echo "WARNING: loaders.cache file is missing" -fi -sed -i "s|$gdk_pixbuf_moduledir/||g" "$APPDIR/${gdk_pixbuf_cache_file/$LD_GTK_LIBRARY_PATH//usr/lib}" - -echo "Copying more libraries" -gobject_libdir="$(get_pkgconf_variable "libdir" "gobject-2.0" "$LD_GTK_LIBRARY_PATH")" -gio_libdir="$(get_pkgconf_variable "libdir" "gio-2.0" "$LD_GTK_LIBRARY_PATH")" -librsvg_libdir="$(get_pkgconf_variable "libdir" "librsvg-2.0" "$LD_GTK_LIBRARY_PATH")" -pango_libdir="$(get_pkgconf_variable "libdir" "pango" "$LD_GTK_LIBRARY_PATH")" -pangocairo_libdir="$(get_pkgconf_variable "libdir" "pangocairo" "$LD_GTK_LIBRARY_PATH")" -pangoft2_libdir="$(get_pkgconf_variable "libdir" "pangoft2" "$LD_GTK_LIBRARY_PATH")" -FIND_ARRAY=( - "$gdk_libdir" "libgdk_pixbuf-*.so*" - "$gobject_libdir" "libgobject-*.so*" - "$gio_libdir" "libgio-*.so*" - "$librsvg_libdir" "librsvg-*.so*" - "$pango_libdir" "libpango-*.so*" - "$pangocairo_libdir" "libpangocairo-*.so*" - "$pangoft2_libdir" "libpangoft2-*.so*" -) -LIBRARIES=() -for (( i=0; i<${#FIND_ARRAY[@]}; i+=2 )); do - directory=${FIND_ARRAY[i]} - library=${FIND_ARRAY[i+1]} - while IFS= read -r -d '' file; do - LIBRARIES+=( "--library=$file" ) - done < <(find "$directory" \( -type l -o -type f \) -name "$library" -print0) -done - -env LINUXDEPLOY_PLUGIN_MODE=1 "$LINUXDEPLOY" --appdir="$APPDIR" "${LIBRARIES[@]}" - -# Create symbolic links as a workaround -# Details: https://github.com/linuxdeploy/linuxdeploy-plugin-gtk/issues/24#issuecomment-1030026529 -echo "Manually setting rpath for GTK modules" -PATCH_ARRAY=( - "$gtk3_immodulesdir" - "$gtk3_printbackendsdir" - "$gdk_pixbuf_moduledir" -) -for directory in "${PATCH_ARRAY[@]}"; do - while IFS= read -r -d '' file; do - ln $verbose -sf "${file/$LD_GTK_LIBRARY_PATH\//}" "$APPDIR/usr/lib" - done < <(find "$directory" -name '*.so' -print0) -done \ No newline at end of file diff --git a/v3/internal/commands/msix.go b/v3/internal/commands/msix.go deleted file mode 100644 index 6c803e6d8..000000000 --- a/v3/internal/commands/msix.go +++ /dev/null @@ -1,485 +0,0 @@ -package commands - -import ( - "embed" - "encoding/json" - "fmt" - "os" - "os/exec" - "path/filepath" - "runtime" - "text/template" - - "github.com/wailsapp/wails/v3/internal/flags" -) - -//go:embed build_assets/windows/msix/* -var msixAssets embed.FS - -// MSIXOptions represents the configuration for MSIX packaging -type MSIXOptions struct { - // Info from project config - Info struct { - CompanyName string `json:"companyName"` - ProductName string `json:"productName"` - ProductVersion string `json:"version"` - ProductIdentifier string `json:"productIdentifier"` - Description string `json:"description"` - Copyright string `json:"copyright"` - Comments string `json:"comments"` - } - // File associations - FileAssociations []struct { - Ext string `json:"ext"` - Name string `json:"name"` - Description string `json:"description"` - IconName string `json:"iconName"` - Role string `json:"role"` - MimeType string `json:"mimeType,omitempty"` - } `json:"fileAssociations"` - // MSIX specific options - Publisher string `json:"publisher"` - CertificatePath string `json:"certificatePath"` - CertificatePassword string `json:"certificatePassword,omitempty"` - ProcessorArchitecture string `json:"processorArchitecture"` - ExecutableName string `json:"executableName"` - ExecutablePath string `json:"executablePath"` - OutputPath string `json:"outputPath"` - UseMsixPackagingTool bool `json:"useMsixPackagingTool"` - UseMakeAppx bool `json:"useMakeAppx"` -} - -// ToolMSIX creates an MSIX package for Windows applications -func ToolMSIX(options *flags.ToolMSIX) error { - DisableFooter = true - - if runtime.GOOS != "windows" { - return fmt.Errorf("MSIX packaging is only supported on Windows") - } - - // Check if required tools are installed - if err := checkMSIXTools(options); err != nil { - return err - } - - // Load project configuration - configPath := options.ConfigPath - if configPath == "" { - configPath = "wails.json" - } - - // Read the config file - configData, err := os.ReadFile(configPath) - if err != nil { - return fmt.Errorf("error reading config file: %w", err) - } - - // Parse the config - var config struct { - Info map[string]interface{} `json:"info"` - FileAssociations []map[string]interface{} `json:"fileAssociations"` - } - if err := json.Unmarshal(configData, &config); err != nil { - return fmt.Errorf("error parsing config file: %w", err) - } - - // Create MSIX options - msixOptions := MSIXOptions{ - Publisher: options.Publisher, - CertificatePath: options.CertificatePath, - CertificatePassword: options.CertificatePassword, - ProcessorArchitecture: options.Arch, - ExecutableName: options.ExecutableName, - ExecutablePath: options.ExecutablePath, - OutputPath: options.OutputPath, - UseMsixPackagingTool: options.UseMsixPackagingTool, - UseMakeAppx: options.UseMakeAppx, - } - - // Copy info from config - infoBytes, err := json.Marshal(config.Info) - if err != nil { - return fmt.Errorf("error marshaling info: %w", err) - } - if err := json.Unmarshal(infoBytes, &msixOptions.Info); err != nil { - return fmt.Errorf("error unmarshaling info: %w", err) - } - - // Copy file associations from config - if len(config.FileAssociations) > 0 { - faBytes, err := json.Marshal(config.FileAssociations) - if err != nil { - return fmt.Errorf("error marshaling file associations: %w", err) - } - if err := json.Unmarshal(faBytes, &msixOptions.FileAssociations); err != nil { - return fmt.Errorf("error unmarshaling file associations: %w", err) - } - } - - // Validate options - if err := validateMSIXOptions(&msixOptions); err != nil { - return err - } - - // Create MSIX package - if msixOptions.UseMsixPackagingTool { - return createMSIXWithPackagingTool(&msixOptions) - } else if msixOptions.UseMakeAppx { - return createMSIXWithMakeAppx(&msixOptions) - } - - // Default to MakeAppx if neither is specified - return createMSIXWithMakeAppx(&msixOptions) -} - -// checkMSIXTools checks if the required tools for MSIX packaging are installed -func checkMSIXTools(options *flags.ToolMSIX) error { - // Check if MsixPackagingTool is installed if requested - if options.UseMsixPackagingTool { - cmd := exec.Command("powershell", "-Command", "Get-AppxPackage -Name Microsoft.MsixPackagingTool") - if err := cmd.Run(); err != nil { - return fmt.Errorf("Microsoft MSIX Packaging Tool is not installed. Please install it from the Microsoft Store") - } - } - - // Check if MakeAppx is available if requested - if options.UseMakeAppx { - cmd := exec.Command("where", "MakeAppx.exe") - if err := cmd.Run(); err != nil { - return fmt.Errorf("MakeAppx.exe is not found in PATH. Please install the Windows SDK") - } - } - - // If neither is specified, check for MakeAppx as the default - if !options.UseMsixPackagingTool && !options.UseMakeAppx { - cmd := exec.Command("where", "MakeAppx.exe") - if err := cmd.Run(); err != nil { - return fmt.Errorf("MakeAppx.exe is not found in PATH. Please install the Windows SDK") - } - } - - // Check if signtool is available for signing - if options.CertificatePath != "" { - cmd := exec.Command("where", "signtool.exe") - if err := cmd.Run(); err != nil { - return fmt.Errorf("signtool.exe is not found in PATH. Please install the Windows SDK") - } - } - - return nil -} - -// validateMSIXOptions validates the MSIX options -func validateMSIXOptions(options *MSIXOptions) error { - // Check required fields - if options.Info.ProductName == "" { - return fmt.Errorf("product name is required") - } - if options.Info.ProductIdentifier == "" { - return fmt.Errorf("product identifier is required") - } - if options.Info.CompanyName == "" { - return fmt.Errorf("company name is required") - } - if options.ExecutableName == "" { - return fmt.Errorf("executable name is required") - } - if options.ExecutablePath == "" { - return fmt.Errorf("executable path is required") - } - - // Validate executable path - if _, err := os.Stat(options.ExecutablePath); os.IsNotExist(err) { - return fmt.Errorf("executable file not found: %s", options.ExecutablePath) - } - - // Validate certificate path if provided - if options.CertificatePath != "" { - if _, err := os.Stat(options.CertificatePath); os.IsNotExist(err) { - return fmt.Errorf("certificate file not found: %s", options.CertificatePath) - } - } - - // Set default processor architecture if not provided - if options.ProcessorArchitecture == "" { - options.ProcessorArchitecture = "x64" - } - - // Set default publisher if not provided - if options.Publisher == "" { - options.Publisher = fmt.Sprintf("CN=%s", options.Info.CompanyName) - } - - // Set default output path if not provided - if options.OutputPath == "" { - options.OutputPath = filepath.Join(".", fmt.Sprintf("%s.msix", options.Info.ProductName)) - } - - return nil -} - -// createMSIXWithPackagingTool creates an MSIX package using the Microsoft MSIX Packaging Tool -func createMSIXWithPackagingTool(options *MSIXOptions) error { - // Create a temporary directory for the template - tempDir, err := os.MkdirTemp("", "wails-msix-") - if err != nil { - return fmt.Errorf("error creating temporary directory: %w", err) - } - defer os.RemoveAll(tempDir) - - // Generate the template file - templatePath := filepath.Join(tempDir, "template.xml") - if err := generateMSIXTemplate(options, templatePath); err != nil { - return fmt.Errorf("error generating MSIX template: %w", err) - } - - // Create the MSIX package - fmt.Println("Creating MSIX package using Microsoft MSIX Packaging Tool...") - args := []string{"create-package", "--template", templatePath} - - // Add certificate password if provided - if options.CertificatePassword != "" { - args = append(args, "--certPassword", options.CertificatePassword) - } - - cmd := exec.Command("MsixPackagingTool.exe", args...) - cmd.Stdout = os.Stdout - cmd.Stderr = os.Stderr - if err := cmd.Run(); err != nil { - return fmt.Errorf("error creating MSIX package: %w", err) - } - - fmt.Printf("MSIX package created successfully: %s\n", options.OutputPath) - return nil -} - -// createMSIXWithMakeAppx creates an MSIX package using MakeAppx.exe -func createMSIXWithMakeAppx(options *MSIXOptions) error { - // Create a temporary directory for the package structure - tempDir, err := os.MkdirTemp("", "wails-msix-") - if err != nil { - return fmt.Errorf("error creating temporary directory: %w", err) - } - defer os.RemoveAll(tempDir) - - // Create the package structure - if err := createMSIXPackageStructure(options, tempDir); err != nil { - return fmt.Errorf("error creating MSIX package structure: %w", err) - } - - // Create the MSIX package - fmt.Println("Creating MSIX package using MakeAppx.exe...") - cmd := exec.Command("MakeAppx.exe", "pack", "/d", tempDir, "/p", options.OutputPath) - cmd.Stdout = os.Stdout - cmd.Stderr = os.Stderr - if err := cmd.Run(); err != nil { - return fmt.Errorf("error creating MSIX package: %w", err) - } - - // Sign the package if certificate is provided - if options.CertificatePath != "" { - fmt.Println("Signing MSIX package...") - signArgs := []string{"sign", "/fd", "SHA256", "/a", "/f", options.CertificatePath} - - // Add certificate password if provided - if options.CertificatePassword != "" { - signArgs = append(signArgs, "/p", options.CertificatePassword) - } - - signArgs = append(signArgs, options.OutputPath) - - cmd = exec.Command("signtool.exe", signArgs...) - cmd.Stdout = os.Stdout - cmd.Stderr = os.Stderr - if err := cmd.Run(); err != nil { - return fmt.Errorf("error signing MSIX package: %w", err) - } - } - - fmt.Printf("MSIX package created successfully: %s\n", options.OutputPath) - return nil -} - -// generateMSIXTemplate generates the MSIX template file for the Microsoft MSIX Packaging Tool -func generateMSIXTemplate(options *MSIXOptions, outputPath string) error { - // Read the template file - templateData, err := msixAssets.ReadFile("build_assets/windows/msix/template.xml.tmpl") - if err != nil { - return fmt.Errorf("error reading template file: %w", err) - } - - // Parse the template - tmpl, err := template.New("msix-template").Parse(string(templateData)) - if err != nil { - return fmt.Errorf("error parsing template: %w", err) - } - - // Create the output file - file, err := os.Create(outputPath) - if err != nil { - return fmt.Errorf("error creating output file: %w", err) - } - defer file.Close() - - // Execute the template - if err := tmpl.Execute(file, options); err != nil { - return fmt.Errorf("error executing template: %w", err) - } - - return nil -} - -// createMSIXPackageStructure creates the MSIX package structure for MakeAppx.exe -func createMSIXPackageStructure(options *MSIXOptions, outputDir string) error { - // Create the Assets directory - assetsDir := filepath.Join(outputDir, "Assets") - if err := os.MkdirAll(assetsDir, 0755); err != nil { - return fmt.Errorf("error creating Assets directory: %w", err) - } - - // Generate the AppxManifest.xml file - manifestPath := filepath.Join(outputDir, "AppxManifest.xml") - if err := generateAppxManifest(options, manifestPath); err != nil { - return fmt.Errorf("error generating AppxManifest.xml: %w", err) - } - - // Copy the executable - executableDest := filepath.Join(outputDir, filepath.Base(options.ExecutablePath)) - if err := copyFile(options.ExecutablePath, executableDest); err != nil { - return fmt.Errorf("error copying executable: %w", err) - } - - // Copy any additional files needed for the application - // This would include DLLs, resources, etc. - // For now, we'll just copy the executable - - // Generate placeholder assets - assets := []string{ - "Square150x150Logo.png", - "Square44x44Logo.png", - "Wide310x150Logo.png", - "SplashScreen.png", - "StoreLogo.png", - } - - // Add FileIcon.png if there are file associations - if len(options.FileAssociations) > 0 { - assets = append(assets, "FileIcon.png") - } - - // Generate placeholder assets - for _, asset := range assets { - assetPath := filepath.Join(assetsDir, asset) - if err := generatePlaceholderImage(assetPath); err != nil { - return fmt.Errorf("error generating placeholder image %s: %w", asset, err) - } - } - - return nil -} - -// generateAppxManifest generates the AppxManifest.xml file -func generateAppxManifest(options *MSIXOptions, outputPath string) error { - // Read the template file - templateData, err := msixAssets.ReadFile("build_assets/windows/msix/app_manifest.xml.tmpl") - if err != nil { - return fmt.Errorf("error reading template file: %w", err) - } - - // Parse the template - tmpl, err := template.New("appx-manifest").Parse(string(templateData)) - if err != nil { - return fmt.Errorf("error parsing template: %w", err) - } - - // Create the output file - file, err := os.Create(outputPath) - if err != nil { - return fmt.Errorf("error creating output file: %w", err) - } - defer file.Close() - - // Execute the template - if err := tmpl.Execute(file, options); err != nil { - return fmt.Errorf("error executing template: %w", err) - } - - return nil -} - -// generatePlaceholderImage generates a placeholder image file -func generatePlaceholderImage(outputPath string) error { - // For now, we'll create a simple 1x1 transparent PNG - // In a real implementation, we would generate proper icons based on the application icon - - // Create a minimal valid PNG file (1x1 transparent pixel) - pngData := []byte{ - 0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A, 0x00, 0x00, 0x00, 0x0D, - 0x49, 0x48, 0x44, 0x52, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01, - 0x08, 0x06, 0x00, 0x00, 0x00, 0x1F, 0x15, 0xC4, 0x89, 0x00, 0x00, 0x00, - 0x0A, 0x49, 0x44, 0x41, 0x54, 0x78, 0x9C, 0x63, 0x00, 0x01, 0x00, 0x00, - 0x05, 0x00, 0x01, 0x0D, 0x0A, 0x2D, 0xB4, 0x00, 0x00, 0x00, 0x00, 0x49, - 0x45, 0x4E, 0x44, 0xAE, 0x42, 0x60, 0x82, - } - - return os.WriteFile(outputPath, pngData, 0644) -} - -// copyFile copies a file from src to dst -func copyFile(src, dst string) error { - // Read the source file - data, err := os.ReadFile(src) - if err != nil { - return err - } - - // Write the destination file - return os.WriteFile(dst, data, 0644) -} - -// InstallMSIXTools installs the required tools for MSIX packaging -func InstallMSIXTools() error { - // Check if running on Windows - if runtime.GOOS != "windows" { - return fmt.Errorf("MSIX packaging is only supported on Windows") - } - - fmt.Println("Installing MSIX packaging tools...") - - // Install MSIX Packaging Tool from Microsoft Store - fmt.Println("Installing Microsoft MSIX Packaging Tool from Microsoft Store...") - cmd := exec.Command("powershell", "-Command", "Start-Process ms-windows-store://pdp/?ProductId=9N5R1TQPJVBP") - if err := cmd.Run(); err != nil { - return fmt.Errorf("error launching Microsoft Store: %w", err) - } - - // Check if Windows SDK is installed - fmt.Println("Checking for Windows SDK...") - sdkInstalled := false - cmd = exec.Command("where", "MakeAppx.exe") - if err := cmd.Run(); err == nil { - sdkInstalled = true - fmt.Println("Windows SDK is already installed.") - } - - // Install Windows SDK if not installed - if !sdkInstalled { - fmt.Println("Windows SDK is not installed. Please download and install from:") - fmt.Println("https://developer.microsoft.com/en-us/windows/downloads/windows-sdk/") - - // Open the download page - cmd = exec.Command("powershell", "-Command", "Start-Process https://developer.microsoft.com/en-us/windows/downloads/windows-sdk/") - if err := cmd.Run(); err != nil { - return fmt.Errorf("error opening Windows SDK download page: %w", err) - } - } - - fmt.Println("MSIX packaging tools installation initiated. Please complete the installation process in the opened windows.") - return nil -} - -// init registers the MSIX command -func init() { - // Register the MSIX command in the CLI - // This will be called by the CLI framework -} diff --git a/v3/internal/commands/myapp.ARCHLINUX b/v3/internal/commands/myapp.ARCHLINUX deleted file mode 100644 index 8dfb9fa69..000000000 Binary files a/v3/internal/commands/myapp.ARCHLINUX and /dev/null differ diff --git a/v3/internal/commands/myapp.DEB b/v3/internal/commands/myapp.DEB deleted file mode 100644 index 7361bdc19..000000000 Binary files a/v3/internal/commands/myapp.DEB and /dev/null differ diff --git a/v3/internal/commands/myapp.RPM b/v3/internal/commands/myapp.RPM deleted file mode 100644 index 16a2d484e..000000000 Binary files a/v3/internal/commands/myapp.RPM and /dev/null differ diff --git a/v3/internal/commands/releasenotes.go b/v3/internal/commands/releasenotes.go deleted file mode 100644 index a90c7cb1b..000000000 --- a/v3/internal/commands/releasenotes.go +++ /dev/null @@ -1,34 +0,0 @@ -package commands - -import ( - "github.com/wailsapp/wails/v3/internal/github" - "github.com/wailsapp/wails/v3/internal/term" - "github.com/wailsapp/wails/v3/internal/version" -) - -type ReleaseNotesOptions struct { - Version string `name:"v" description:"The version to show release notes for"` - NoColour bool `name:"n" description:"Disable colour output"` -} - -func ReleaseNotes(options *ReleaseNotesOptions) error { - if options.NoColour { - term.DisableColor() - } - - term.Header("Release Notes") - - if version.IsDev() { - term.Println("Release notes are not available for development builds") - return nil - } - - currentVersion := version.String() - if options.Version != "" { - currentVersion = options.Version - } - - releaseNotes := github.GetReleaseNotes(currentVersion, options.NoColour) - term.Println(releaseNotes) - return nil -} diff --git a/v3/internal/commands/runtime.go b/v3/internal/commands/runtime.go deleted file mode 100644 index 7414c8b32..000000000 --- a/v3/internal/commands/runtime.go +++ /dev/null @@ -1,47 +0,0 @@ -package commands - -import ( - "io" - "os" - "path/filepath" - "runtime" -) - -type RuntimeOptions struct { - Directory string `name:"d" description:"Directory to generate runtime file in" default:"."` -} - -func GenerateRuntime(options *RuntimeOptions) error { - DisableFooter = true - _, thisFile, _, _ := runtime.Caller(0) - localDir := filepath.Dir(thisFile) - bundledAssetsDir := filepath.Join(localDir, "..", "assetserver", "bundledassets") - runtimeJS := filepath.Join(bundledAssetsDir, "runtime.js") - err := CopyFile(runtimeJS, filepath.Join(options.Directory, "runtime.js")) - if err != nil { - return err - } - runtimeDebugJS := filepath.Join(bundledAssetsDir, "runtime.debug.js") - err = CopyFile(runtimeDebugJS, filepath.Join(options.Directory, "runtime-debug.js")) - if err != nil { - return err - } - return nil -} - -func CopyFile(source string, target string) error { - s, err := os.Open(source) - if err != nil { - return err - } - defer s.Close() - d, err := os.Create(target) - if err != nil { - return err - } - if _, err := io.Copy(d, s); err != nil { - d.Close() - return err - } - return d.Close() -} diff --git a/v3/internal/commands/service.go b/v3/internal/commands/service.go deleted file mode 100644 index 8f5a6bd0a..000000000 --- a/v3/internal/commands/service.go +++ /dev/null @@ -1,44 +0,0 @@ -package commands - -import ( - "github.com/wailsapp/wails/v3/internal/flags" - "github.com/wailsapp/wails/v3/internal/service" - "github.com/wailsapp/wails/v3/internal/term" - "strings" -) - -func toCamelCasePlugin(s string) string { - var camelCase string - var capitalize = true - - for _, c := range s { - if c >= 'a' && c <= 'z' || c >= '0' && c <= '9' { - if capitalize { - camelCase += strings.ToUpper(string(c)) - capitalize = false - } else { - camelCase += string(c) - } - } else if c >= 'A' && c <= 'Z' { - camelCase += string(c) - capitalize = false - } else { - capitalize = true - } - } - - return camelCase + "Plugin" -} - -func ServiceInit(options *flags.ServiceInit) error { - - if options.Quiet { - term.DisableOutput() - } - - if options.PackageName == "" { - options.PackageName = toCamelCasePlugin(options.Name) - } - - return service.Install(options) -} diff --git a/v3/internal/commands/setup.go b/v3/internal/commands/setup.go deleted file mode 100644 index f1a04274b..000000000 --- a/v3/internal/commands/setup.go +++ /dev/null @@ -1,13 +0,0 @@ -package commands - -import ( - "github.com/wailsapp/wails/v3/internal/setupwizard" -) - -type SetupOptions struct{} - -func Setup(_ *SetupOptions) error { - DisableFooter = true - wizard := setupwizard.New() - return wizard.Run() -} diff --git a/v3/internal/commands/sign.go b/v3/internal/commands/sign.go deleted file mode 100644 index b862f83fa..000000000 --- a/v3/internal/commands/sign.go +++ /dev/null @@ -1,396 +0,0 @@ -package commands - -import ( - "fmt" - "os" - "os/exec" - "path/filepath" - "runtime" - "strings" - - "github.com/pterm/pterm" - "github.com/wailsapp/wails/v3/internal/flags" - "github.com/wailsapp/wails/v3/internal/keychain" -) - -// Sign signs a binary or package -func Sign(options *flags.Sign) error { - if options.Input == "" { - return fmt.Errorf("--input is required") - } - - // Check input file exists - info, err := os.Stat(options.Input) - if err != nil { - return fmt.Errorf("input file not found: %w", err) - } - - // Determine what type of signing to do based on file extension and flags - ext := strings.ToLower(filepath.Ext(options.Input)) - - // macOS app bundle (directory) - if info.IsDir() && strings.HasSuffix(options.Input, ".app") { - return signMacOSApp(options) - } - - // macOS binary or Windows executable - if ext == ".exe" || ext == ".msi" || ext == ".msix" || ext == ".appx" { - return signWindows(options) - } - - // Linux packages - if ext == ".deb" { - return signDEB(options) - } - if ext == ".rpm" { - return signRPM(options) - } - - // macOS binary (no extension typically) - if runtime.GOOS == "darwin" && options.Identity != "" { - return signMacOSBinary(options) - } - - return fmt.Errorf("unsupported file type: %s", ext) -} - -func signMacOSApp(options *flags.Sign) error { - if options.Identity == "" { - return fmt.Errorf("--identity is required for macOS signing") - } - - if options.Verbose { - pterm.Info.Printfln("Signing macOS app bundle: %s", options.Input) - } - - // Build codesign command - args := []string{ - "--force", - "--deep", - "--sign", options.Identity, - } - - if options.Entitlements != "" { - args = append(args, "--entitlements", options.Entitlements) - } - - if options.HardenedRuntime || options.Notarize { - args = append(args, "--options", "runtime") - } - - args = append(args, options.Input) - - cmd := exec.Command("codesign", args...) - cmd.Stdout = os.Stdout - cmd.Stderr = os.Stderr - - if err := cmd.Run(); err != nil { - return fmt.Errorf("codesign failed: %w", err) - } - - pterm.Success.Printfln("Signed: %s", options.Input) - - // Notarize if requested - if options.Notarize { - return notarizeMacOSApp(options) - } - - return nil -} - -func signMacOSBinary(options *flags.Sign) error { - if options.Identity == "" { - return fmt.Errorf("--identity is required for macOS signing") - } - - if options.Verbose { - pterm.Info.Printfln("Signing macOS binary: %s", options.Input) - } - - args := []string{ - "--force", - "--sign", options.Identity, - } - - if options.Entitlements != "" { - args = append(args, "--entitlements", options.Entitlements) - } - - if options.HardenedRuntime { - args = append(args, "--options", "runtime") - } - - args = append(args, options.Input) - - cmd := exec.Command("codesign", args...) - cmd.Stdout = os.Stdout - cmd.Stderr = os.Stderr - - if err := cmd.Run(); err != nil { - return fmt.Errorf("codesign failed: %w", err) - } - - pterm.Success.Printfln("Signed: %s", options.Input) - return nil -} - -func notarizeMacOSApp(options *flags.Sign) error { - if options.KeychainProfile == "" { - return fmt.Errorf("--keychain-profile is required for notarization") - } - - if options.Verbose { - pterm.Info.Println("Submitting for notarization...") - } - - // Create a zip for notarization - zipPath := options.Input + ".zip" - zipCmd := exec.Command("ditto", "-c", "-k", "--keepParent", options.Input, zipPath) - if err := zipCmd.Run(); err != nil { - return fmt.Errorf("failed to create zip for notarization: %w", err) - } - defer os.Remove(zipPath) - - // Submit for notarization - args := []string{ - "notarytool", "submit", - zipPath, - "--keychain-profile", options.KeychainProfile, - "--wait", - } - - cmd := exec.Command("xcrun", args...) - cmd.Stdout = os.Stdout - cmd.Stderr = os.Stderr - - if err := cmd.Run(); err != nil { - return fmt.Errorf("notarization failed: %w", err) - } - - // Staple the ticket - stapleCmd := exec.Command("xcrun", "stapler", "staple", options.Input) - stapleCmd.Stdout = os.Stdout - stapleCmd.Stderr = os.Stderr - - if err := stapleCmd.Run(); err != nil { - return fmt.Errorf("stapling failed: %w", err) - } - - pterm.Success.Println("Notarization complete and ticket stapled") - return nil -} - -func signWindows(options *flags.Sign) error { - // Get password from keychain if not provided - password := options.Password - if password == "" && options.Certificate != "" { - var err error - password, err = keychain.Get(keychain.KeyWindowsCertPassword) - if err != nil { - pterm.Warning.Printfln("Could not get password from keychain: %v", err) - // Continue without password - might work for some certificates - } - } - - if options.Verbose { - pterm.Info.Printfln("Signing Windows executable: %s", options.Input) - } - - // Try native signtool first on Windows - if runtime.GOOS == "windows" { - err := signWindowsNative(options, password) - if err == nil { - return nil - } - if options.Verbose { - pterm.Warning.Printfln("Native signing failed, trying built-in: %v", err) - } - } - - // Use built-in signing (works cross-platform) - return signWindowsBuiltin(options, password) -} - -func signWindowsNative(options *flags.Sign, password string) error { - // Find signtool.exe - signtool, err := findSigntool() - if err != nil { - return err - } - - args := []string{"sign"} - - if options.Certificate != "" { - args = append(args, "/f", options.Certificate) - if password != "" { - args = append(args, "/p", password) - } - } else if options.Thumbprint != "" { - args = append(args, "/sha1", options.Thumbprint) - } else { - return fmt.Errorf("either --certificate or --thumbprint is required") - } - - // Add timestamp server - timestamp := options.Timestamp - if timestamp == "" { - timestamp = "http://timestamp.digicert.com" - } - args = append(args, "/tr", timestamp, "/td", "SHA256", "/fd", "SHA256") - - args = append(args, options.Input) - - cmd := exec.Command(signtool, args...) - cmd.Stdout = os.Stdout - cmd.Stderr = os.Stderr - - if err := cmd.Run(); err != nil { - return fmt.Errorf("signtool failed: %w", err) - } - - pterm.Success.Printfln("Signed: %s", options.Input) - return nil -} - -func findSigntool() (string, error) { - // Check if signtool is in PATH - path, err := exec.LookPath("signtool.exe") - if err == nil { - return path, nil - } - - // Common Windows SDK locations - sdkPaths := []string{ - `C:\Program Files (x86)\Windows Kits\10\bin\10.0.22621.0\x64\signtool.exe`, - `C:\Program Files (x86)\Windows Kits\10\bin\10.0.19041.0\x64\signtool.exe`, - `C:\Program Files (x86)\Windows Kits\10\bin\x64\signtool.exe`, - } - - for _, p := range sdkPaths { - if _, err := os.Stat(p); err == nil { - return p, nil - } - } - - return "", fmt.Errorf("signtool.exe not found") -} - -func signWindowsBuiltin(options *flags.Sign, password string) error { - // This would use a Go library for Authenticode signing - // For now, we'll return an error indicating it needs implementation - // In a full implementation, you'd use something like: - // - github.com/AkarinLiu/osslsigncode-go - // - or implement PE signing directly - - if options.Certificate == "" { - return fmt.Errorf("--certificate is required for cross-platform signing") - } - - return fmt.Errorf("built-in Windows signing not yet implemented - please use signtool.exe on Windows, or install osslsigncode") -} - -func signDEB(options *flags.Sign) error { - if options.PGPKey == "" { - return fmt.Errorf("--pgp-key is required for DEB signing") - } - - // Get password from keychain if not provided - password := options.PGPPassword - if password == "" { - var err error - password, err = keychain.Get(keychain.KeyPGPPassword) - if err != nil { - // Password might not be required if key is unencrypted - if options.Verbose { - pterm.Warning.Printfln("Could not get PGP password from keychain: %v", err) - } - } - } - - if options.Verbose { - pterm.Info.Printfln("Signing DEB package: %s", options.Input) - } - - role := options.Role - if role == "" { - role = "builder" - } - - // Use dpkg-sig for signing - args := []string{ - "-k", options.PGPKey, - "--sign", role, - } - - if password != "" { - // dpkg-sig reads from GPG_TTY or gpg-agent - // For scripted use, we need to use gpg with passphrase - args = append(args, "--gpg-options", fmt.Sprintf("--batch --passphrase %s", password)) - } - - args = append(args, options.Input) - - cmd := exec.Command("dpkg-sig", args...) - cmd.Stdout = os.Stdout - cmd.Stderr = os.Stderr - - if err := cmd.Run(); err != nil { - // Fallback: try using gpg directly to sign - return signDEBWithGPG(options, password, role) - } - - pterm.Success.Printfln("Signed: %s", options.Input) - return nil -} - -func signDEBWithGPG(options *flags.Sign, password, role string) error { - // Alternative approach using ar and gpg directly - // This is more portable but more complex - return fmt.Errorf("dpkg-sig not found - please install dpkg-sig or use a Linux system") -} - -func signRPM(options *flags.Sign) error { - if options.PGPKey == "" { - return fmt.Errorf("--pgp-key is required for RPM signing") - } - - // Get password from keychain if not provided - password := options.PGPPassword - if password == "" { - var err error - password, err = keychain.Get(keychain.KeyPGPPassword) - if err != nil { - if options.Verbose { - pterm.Warning.Printfln("Could not get PGP password from keychain: %v", err) - } - } - } - - if options.Verbose { - pterm.Info.Printfln("Signing RPM package: %s", options.Input) - } - - // RPM signing requires the key to be imported to GPG keyring - // and uses rpmsign command - args := []string{ - "--addsign", - options.Input, - } - - cmd := exec.Command("rpmsign", args...) - - // Set up passphrase via environment if needed - if password != "" { - cmd.Env = append(os.Environ(), fmt.Sprintf("GPG_PASSPHRASE=%s", password)) - } - - cmd.Stdout = os.Stdout - cmd.Stderr = os.Stderr - - if err := cmd.Run(); err != nil { - return fmt.Errorf("rpmsign failed: %w", err) - } - - pterm.Success.Printfln("Signed: %s", options.Input) - return nil -} diff --git a/v3/internal/commands/signing_setup.go b/v3/internal/commands/signing_setup.go deleted file mode 100644 index 7bbe64817..000000000 --- a/v3/internal/commands/signing_setup.go +++ /dev/null @@ -1,588 +0,0 @@ -package commands - -import ( - "fmt" - "os" - "os/exec" - "path/filepath" - "runtime" - "strings" - - "github.com/ProtonMail/go-crypto/openpgp" - "github.com/ProtonMail/go-crypto/openpgp/armor" - "github.com/ProtonMail/go-crypto/openpgp/packet" - "github.com/charmbracelet/huh" - "github.com/pterm/pterm" - "github.com/wailsapp/wails/v3/internal/flags" - "github.com/wailsapp/wails/v3/internal/keychain" -) - -// SigningSetup configures signing variables in platform Taskfiles -func SigningSetup(options *flags.SigningSetup) error { - // Determine which platforms to configure - platforms := options.Platforms - if len(platforms) == 0 { - // Auto-detect based on existing Taskfiles - platforms = detectPlatforms() - if len(platforms) == 0 { - return fmt.Errorf("no platform Taskfiles found in build/ directory") - } - } - - for _, platform := range platforms { - var err error - switch platform { - case "darwin": - err = setupDarwinSigning() - case "windows": - err = setupWindowsSigning() - case "linux": - err = setupLinuxSigning() - default: - pterm.Warning.Printfln("Unknown platform: %s", platform) - continue - } - if err != nil { - return err - } - } - - return nil -} - -func detectPlatforms() []string { - var platforms []string - for _, p := range []string{"darwin", "windows", "linux"} { - taskfile := filepath.Join("build", p, "Taskfile.yml") - if _, err := os.Stat(taskfile); err == nil { - platforms = append(platforms, p) - } - } - return platforms -} - -func setupDarwinSigning() error { - pterm.DefaultHeader.Println("macOS Code Signing Setup") - fmt.Println() - - // Get available signing identities - identities, err := getMacOSSigningIdentities() - if err != nil { - pterm.Warning.Printfln("Could not list signing identities: %v", err) - identities = []string{} - } - - var signIdentity string - var keychainProfile string - var entitlements string - var configureNotarization bool - - // Build identity options - var identityOptions []huh.Option[string] - for _, id := range identities { - identityOptions = append(identityOptions, huh.NewOption(id, id)) - } - identityOptions = append(identityOptions, huh.NewOption("Enter manually...", "manual")) - - form := huh.NewForm( - huh.NewGroup( - huh.NewSelect[string](). - Title("Select signing identity"). - Description("Choose your Developer ID certificate"). - Options(identityOptions...). - Value(&signIdentity), - ).WithHideFunc(func() bool { - return len(identities) == 0 - }), - - huh.NewGroup( - huh.NewInput(). - Title("Signing identity"). - Description("e.g., Developer ID Application: Your Company (TEAMID)"). - Placeholder("Developer ID Application: ..."). - Value(&signIdentity), - ).WithHideFunc(func() bool { - return len(identities) > 0 && signIdentity != "manual" - }), - - huh.NewGroup( - huh.NewConfirm(). - Title("Configure notarization?"). - Description("Required for distributing apps outside the App Store"). - Value(&configureNotarization), - ), - - huh.NewGroup( - huh.NewInput(). - Title("Keychain profile name"). - Description("The profile name used with 'wails3 signing credentials'"). - Placeholder("my-notarize-profile"). - Value(&keychainProfile), - ).WithHideFunc(func() bool { - return !configureNotarization - }), - - huh.NewGroup( - huh.NewInput(). - Title("Entitlements file (optional)"). - Description("Path to entitlements plist, leave empty to skip"). - Placeholder("build/darwin/entitlements.plist"). - Value(&entitlements), - ), - ) - - err = form.Run() - if err != nil { - return err - } - - // Handle manual entry - if signIdentity == "manual" { - signIdentity = "" - } - - // Update Taskfile - taskfilePath := filepath.Join("build", "darwin", "Taskfile.yml") - err = updateTaskfileVars(taskfilePath, map[string]string{ - "SIGN_IDENTITY": signIdentity, - "KEYCHAIN_PROFILE": keychainProfile, - "ENTITLEMENTS": entitlements, - }) - if err != nil { - return err - } - - pterm.Success.Printfln("Updated %s", taskfilePath) - - if configureNotarization && keychainProfile != "" { - fmt.Println() - pterm.Info.Println("Next step: Store your notarization credentials:") - fmt.Println() - pterm.Println(pterm.LightBlue(fmt.Sprintf(` wails3 signing credentials \ - --apple-id "your@email.com" \ - --team-id "TEAMID" \ - --password "app-specific-password" \ - --profile "%s"`, keychainProfile))) - fmt.Println() - } - - return nil -} - -func setupWindowsSigning() error { - pterm.DefaultHeader.Println("Windows Code Signing Setup") - fmt.Println() - - var certSource string - var certPath string - var certPassword string - var thumbprint string - var timestampServer string - - form := huh.NewForm( - huh.NewGroup( - huh.NewSelect[string](). - Title("Certificate source"). - Options( - huh.NewOption("Certificate file (.pfx/.p12)", "file"), - huh.NewOption("Windows certificate store (thumbprint)", "store"), - ). - Value(&certSource), - ), - - huh.NewGroup( - huh.NewInput(). - Title("Certificate path"). - Description("Path to your .pfx or .p12 file"). - Placeholder("certs/signing.pfx"). - Value(&certPath), - - huh.NewInput(). - Title("Certificate password"). - Description("Stored securely in system keychain"). - EchoMode(huh.EchoModePassword). - Value(&certPassword), - ).WithHideFunc(func() bool { - return certSource != "file" - }), - - huh.NewGroup( - huh.NewInput(). - Title("Certificate thumbprint"). - Description("SHA-1 thumbprint of the certificate in Windows store"). - Placeholder("ABC123DEF456..."). - Value(&thumbprint), - ).WithHideFunc(func() bool { - return certSource != "store" - }), - - huh.NewGroup( - huh.NewInput(). - Title("Timestamp server (optional)"). - Description("Leave empty for default: http://timestamp.digicert.com"). - Placeholder("http://timestamp.digicert.com"). - Value(×tampServer), - ), - ) - - err := form.Run() - if err != nil { - return err - } - - // Store password in keychain if provided - if certPassword != "" { - err = keychain.Set(keychain.KeyWindowsCertPassword, certPassword) - if err != nil { - return fmt.Errorf("failed to store password in keychain: %w", err) - } - pterm.Success.Println("Certificate password stored in system keychain") - } - - // Update Taskfile (no passwords stored here) - taskfilePath := filepath.Join("build", "windows", "Taskfile.yml") - vars := map[string]string{ - "TIMESTAMP_SERVER": timestampServer, - } - - if certSource == "file" { - vars["SIGN_CERTIFICATE"] = certPath - } else { - vars["SIGN_THUMBPRINT"] = thumbprint - } - - err = updateTaskfileVars(taskfilePath, vars) - if err != nil { - return err - } - - pterm.Success.Printfln("Updated %s", taskfilePath) - return nil -} - -func setupLinuxSigning() error { - pterm.DefaultHeader.Println("Linux Package Signing Setup") - fmt.Println() - - var keySource string - var keyPath string - var keyPassword string - var signRole string - - // For key generation - var genName string - var genEmail string - var genPassword string - - form := huh.NewForm( - huh.NewGroup( - huh.NewSelect[string](). - Title("PGP key source"). - Options( - huh.NewOption("Use existing key", "existing"), - huh.NewOption("Generate new key", "generate"), - ). - Value(&keySource), - ), - - // Existing key options - huh.NewGroup( - huh.NewInput(). - Title("PGP private key path"). - Description("Path to your ASCII-armored private key file"). - Placeholder("signing-key.asc"). - Value(&keyPath), - - huh.NewInput(). - Title("Key password (if encrypted)"). - Description("Stored securely in system keychain"). - EchoMode(huh.EchoModePassword). - Value(&keyPassword), - ).WithHideFunc(func() bool { - return keySource != "existing" - }), - - // Key generation options - huh.NewGroup( - huh.NewInput(). - Title("Name"). - Description("Name for the PGP key"). - Placeholder("Your Name"). - Value(&genName). - Validate(func(s string) error { - if keySource == "generate" && s == "" { - return fmt.Errorf("name is required") - } - return nil - }), - - huh.NewInput(). - Title("Email"). - Description("Email for the PGP key"). - Placeholder("you@example.com"). - Value(&genEmail). - Validate(func(s string) error { - if keySource == "generate" && s == "" { - return fmt.Errorf("email is required") - } - return nil - }), - - huh.NewInput(). - Title("Key password (optional but recommended)"). - Description("Stored securely in system keychain"). - EchoMode(huh.EchoModePassword). - Value(&genPassword), - ).WithHideFunc(func() bool { - return keySource != "generate" - }), - - huh.NewGroup( - huh.NewSelect[string](). - Title("DEB signing role"). - Description("Role for signing Debian packages"). - Options( - huh.NewOption("builder (default)", "builder"), - huh.NewOption("origin", "origin"), - huh.NewOption("maint", "maint"), - huh.NewOption("archive", "archive"), - ). - Value(&signRole), - ), - ) - - err := form.Run() - if err != nil { - return err - } - - // Generate key if requested - if keySource == "generate" { - keyPath = "signing-key.asc" - pubKeyPath := "signing-key.pub.asc" - - pterm.Info.Println("Generating PGP key pair...") - - // Call the key generation - err = generatePGPKeyForSetup(genName, genEmail, genPassword, keyPath, pubKeyPath) - if err != nil { - return fmt.Errorf("failed to generate key: %w", err) - } - - keyPassword = genPassword - - pterm.Success.Printfln("Generated %s and %s", keyPath, pubKeyPath) - fmt.Println() - pterm.Info.Println("Distribute the public key to users so they can verify your packages:") - pterm.Println(pterm.LightBlue(fmt.Sprintf(" # For apt: sudo cp %s /etc/apt/trusted.gpg.d/", pubKeyPath))) - pterm.Println(pterm.LightBlue(fmt.Sprintf(" # For rpm: sudo rpm --import %s", pubKeyPath))) - fmt.Println() - } - - // Store password in keychain if provided - if keyPassword != "" { - err = keychain.Set(keychain.KeyPGPPassword, keyPassword) - if err != nil { - return fmt.Errorf("failed to store password in keychain: %w", err) - } - pterm.Success.Println("PGP key password stored in system keychain") - } - - // Update Taskfile (no passwords stored here) - taskfilePath := filepath.Join("build", "linux", "Taskfile.yml") - vars := map[string]string{ - "PGP_KEY": keyPath, - } - if signRole != "" && signRole != "builder" { - vars["SIGN_ROLE"] = signRole - } - - err = updateTaskfileVars(taskfilePath, vars) - if err != nil { - return err - } - - pterm.Success.Printfln("Updated %s", taskfilePath) - return nil -} - -// getMacOSSigningIdentities returns available signing identities on macOS -func getMacOSSigningIdentities() ([]string, error) { - if runtime.GOOS != "darwin" { - return nil, fmt.Errorf("not running on macOS") - } - - // Run security find-identity to get available codesigning identities - cmd := exec.Command("security", "find-identity", "-v", "-p", "codesigning") - output, err := cmd.Output() - if err != nil { - return nil, fmt.Errorf("failed to run security find-identity: %w", err) - } - - var identities []string - lines := strings.Split(string(output), "\n") - for _, line := range lines { - // Lines look like: 1) ABC123... "Developer ID Application: Company Name (TEAMID)" - // We want to extract the quoted part - if strings.Contains(line, "\"") { - start := strings.Index(line, "\"") - end := strings.LastIndex(line, "\"") - if start != -1 && end > start { - identity := line[start+1 : end] - // Filter for Developer ID certificates (most useful for distribution) - if strings.Contains(identity, "Developer ID") { - identities = append(identities, identity) - } - } - } - } - - return identities, nil -} - -// updateTaskfileVars updates the vars section of a Taskfile -func updateTaskfileVars(path string, vars map[string]string) error { - content, err := os.ReadFile(path) - if err != nil { - return fmt.Errorf("failed to read %s: %w", path, err) - } - - lines := strings.Split(string(content), "\n") - var result []string - inVars := false - varsInserted := false - remainingVars := make(map[string]string) - for k, v := range vars { - remainingVars[k] = v - } - - for i, line := range lines { - trimmed := strings.TrimSpace(line) - - // Detect vars section - if trimmed == "vars:" { - inVars = true - result = append(result, line) - continue - } - - // Detect end of vars section (next top-level key or tasks:) - if inVars && len(line) > 0 && line[0] != ' ' && line[0] != '\t' && !strings.HasPrefix(trimmed, "#") { - // Insert any remaining vars before leaving vars section - for k, v := range remainingVars { - if v != "" { - result = append(result, fmt.Sprintf(" %s: %q", k, v)) - } - } - remainingVars = make(map[string]string) - varsInserted = true - inVars = false - } - - if inVars { - // Check if this line is a var we want to update - updated := false - for k, v := range remainingVars { - commentedKey := "# " + k + ":" - uncommentedKey := k + ":" - - if strings.Contains(trimmed, commentedKey) || strings.HasPrefix(trimmed, uncommentedKey) { - if v != "" { - // Uncomment and set value - result = append(result, fmt.Sprintf(" %s: %q", k, v)) - } else { - // Keep as comment - result = append(result, line) - } - delete(remainingVars, k) - updated = true - break - } - } - if !updated { - result = append(result, line) - } - } else { - result = append(result, line) - } - - // If we're at the end and haven't inserted vars yet, we need to add vars section - if i == len(lines)-1 && !varsInserted && len(remainingVars) > 0 { - // Find where to insert (after includes, before tasks) - // For simplicity, just append warning - pterm.Warning.Println("Could not find vars section in Taskfile, please add manually") - } - } - - return os.WriteFile(path, []byte(strings.Join(result, "\n")), 0644) -} - -// generatePGPKeyForSetup generates a PGP key pair for signing packages -func generatePGPKeyForSetup(name, email, password, privatePath, publicPath string) error { - // Create a new entity (key pair) - config := &packet.Config{ - DefaultHash: 0, // Use default - DefaultCipher: 0, // Use default - DefaultCompressionAlgo: 0, // Use default - } - - entity, err := openpgp.NewEntity(name, "", email, config) - if err != nil { - return fmt.Errorf("failed to create PGP entity: %w", err) - } - - // Encrypt the private key if password is provided - if password != "" { - err = entity.PrivateKey.Encrypt([]byte(password)) - if err != nil { - return fmt.Errorf("failed to encrypt private key: %w", err) - } - // Also encrypt subkeys - for _, subkey := range entity.Subkeys { - if subkey.PrivateKey != nil { - err = subkey.PrivateKey.Encrypt([]byte(password)) - if err != nil { - return fmt.Errorf("failed to encrypt subkey: %w", err) - } - } - } - } - - // Write private key - privateFile, err := os.Create(privatePath) - if err != nil { - return fmt.Errorf("failed to create private key file: %w", err) - } - defer privateFile.Close() - - privateArmor, err := armor.Encode(privateFile, openpgp.PrivateKeyType, nil) - if err != nil { - return fmt.Errorf("failed to create armor encoder: %w", err) - } - - err = entity.SerializePrivate(privateArmor, config) - if err != nil { - return fmt.Errorf("failed to serialize private key: %w", err) - } - privateArmor.Close() - - // Write public key - publicFile, err := os.Create(publicPath) - if err != nil { - return fmt.Errorf("failed to create public key file: %w", err) - } - defer publicFile.Close() - - publicArmor, err := armor.Encode(publicFile, openpgp.PublicKeyType, nil) - if err != nil { - return fmt.Errorf("failed to create armor encoder: %w", err) - } - - err = entity.Serialize(publicArmor) - if err != nil { - return fmt.Errorf("failed to serialize public key: %w", err) - } - publicArmor.Close() - - return nil -} diff --git a/v3/internal/commands/syso.go b/v3/internal/commands/syso.go deleted file mode 100644 index 03f41c80d..000000000 --- a/v3/internal/commands/syso.go +++ /dev/null @@ -1,115 +0,0 @@ -package commands - -import ( - "fmt" - "github.com/pkg/errors" - "os" - "runtime" - - "github.com/tc-hib/winres" - "github.com/tc-hib/winres/version" -) - -type SysoOptions struct { - Manifest string `description:"The manifest file"` - Info string `description:"The info.json file"` - Icon string `description:"The icon file"` - Out string `description:"The output filename for the syso file"` - Arch string `description:"The target architecture"` -} - -func (i *SysoOptions) Default() *SysoOptions { - return &SysoOptions{ - Arch: runtime.GOARCH, - } -} - -func GenerateSyso(options *SysoOptions) (err error) { - - DisableFooter = true - - if options.Manifest == "" { - return fmt.Errorf("manifest is required") - } - if options.Icon == "" { - return fmt.Errorf("icon is required") - } - - rs := winres.ResourceSet{} - - // Process Icon - iconFile, err := os.Open(options.Icon) - if err != nil { - return err - } - defer func() { - err2 := iconFile.Close() - if err == nil && err2 != nil { - err = errors.Wrap(err, "error closing icon file: "+err2.Error()) - } - }() - ico, err := winres.LoadICO(iconFile) - if err != nil { - return fmt.Errorf("couldn't load icon '%s': %v", options.Icon, err) - } - err = rs.SetIcon(winres.RT_ICON, ico) - if err != nil { - return err - } - - // Process Manifest - manifestData, err := os.ReadFile(options.Manifest) - if err != nil { - return err - } - - xmlData, err := winres.AppManifestFromXML(manifestData) - if err != nil { - return err - } - rs.SetManifest(xmlData) - - if options.Info != "" { - var infoData []byte - infoData, err = os.ReadFile(options.Info) - if err != nil { - return err - } - if len(infoData) != 0 { - var v version.Info - if err := v.UnmarshalJSON(infoData); err != nil { - return err - } - rs.SetVersionInfo(v) - } - } - - targetFile := options.Out - if targetFile == "" { - targetFile = "rsrc_windows_" + options.Arch + ".syso" - } - var outputFile *os.File - outputFile, err = os.Create(targetFile) - if err != nil { - return err - } - defer func() { - err = outputFile.Close() - }() - - architecture := map[string]winres.Arch{ - "amd64": winres.ArchAMD64, - "arm64": winres.ArchARM64, - "386": winres.ArchI386, - } - targetArch, supported := architecture[options.Arch] - if !supported { - return fmt.Errorf("arch '%s' not supported", options.Arch) - } - - err = rs.WriteObject(outputFile, targetArch) - if err != nil { - return err - } - return nil -} diff --git a/v3/internal/commands/syso_test.go b/v3/internal/commands/syso_test.go deleted file mode 100644 index a7f94c553..000000000 --- a/v3/internal/commands/syso_test.go +++ /dev/null @@ -1,139 +0,0 @@ -package commands - -import ( - "path/filepath" - "runtime" - "testing" -) - -func TestGenerateSyso(t *testing.T) { - tests := []struct { - name string - setup func() *SysoOptions - wantErr bool - test func() error - }{ - { - name: "should error if manifest filename is not provided", - setup: func() *SysoOptions { - return &SysoOptions{ - Manifest: "", - } - }, - wantErr: true, - }, - { - name: "should error if icon filename is not provided", - setup: func() *SysoOptions { - return &SysoOptions{ - Manifest: "test.manifest", - Icon: "", - } - }, - wantErr: true, - }, - { - name: "should error if icon filename does not exist", - setup: func() *SysoOptions { - return &SysoOptions{ - Manifest: "test.manifest", - Icon: "icon.ico", - } - }, - wantErr: true, - }, - { - name: "should error if icon is wrong format", - setup: func() *SysoOptions { - _, thisFile, _, _ := runtime.Caller(1) - return &SysoOptions{ - Manifest: "test.manifest", - Icon: thisFile, - } - }, - wantErr: true, - }, - { - name: "should error if manifest filename does not exist", - setup: func() *SysoOptions { - // Get the directory of this file - _, thisFile, _, _ := runtime.Caller(1) - localDir := filepath.Dir(thisFile) - // Get the path to the example icon - exampleIcon := filepath.Join(localDir, "examples", "icon.ico") - return &SysoOptions{ - Manifest: "test.manifest", - Icon: exampleIcon, - } - }, - wantErr: true, - }, - { - name: "should error if manifest is wrong format", - setup: func() *SysoOptions { - // Get the directory of this file - _, thisFile, _, _ := runtime.Caller(1) - localDir := filepath.Dir(thisFile) - // Get the path to the example icon - exampleIcon := filepath.Join(localDir, "examples", "icon.ico") - return &SysoOptions{ - Manifest: exampleIcon, - Icon: exampleIcon, - } - }, - wantErr: true, - }, - { - name: "should error if info file does not exist", - setup: func() *SysoOptions { - // Get the directory of this file - _, thisFile, _, _ := runtime.Caller(1) - localDir := filepath.Dir(thisFile) - // Get the path to the example icon - exampleIcon := filepath.Join(localDir, "examples", "icon.ico") - // Get the path to the example manifest - exampleManifest := filepath.Join(localDir, "examples", "wails.exe.manifest") - return &SysoOptions{ - Manifest: exampleManifest, - Icon: exampleIcon, - Info: "doesnotexist.json", - } - }, - wantErr: true, - }, - { - name: "should error if info file is wrong format", - setup: func() *SysoOptions { - // Get the directory of this file - _, thisFile, _, _ := runtime.Caller(1) - localDir := filepath.Dir(thisFile) - // Get the path to the example icon - exampleIcon := filepath.Join(localDir, "examples", "icon.ico") - // Get the path to the example manifest - exampleManifest := filepath.Join(localDir, "examples", "wails.exe.manifest") - return &SysoOptions{ - Manifest: exampleManifest, - Icon: exampleIcon, - Info: thisFile, - } - }, - wantErr: true, - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - options := tt.setup() - err := GenerateSyso(options) - if (err == nil) && tt.wantErr { - t.Errorf("GenerateSyso() error = %v, wantErr %v", err, tt.wantErr) - return - } - if tt.test != nil { - if err := tt.test(); err != nil { - t.Errorf("GenerateSyso() test error = %v", err) - } - } - }) - } -} diff --git a/v3/internal/commands/task.go b/v3/internal/commands/task.go deleted file mode 100644 index 98f2e6dca..000000000 --- a/v3/internal/commands/task.go +++ /dev/null @@ -1,185 +0,0 @@ -package commands - -import ( - "context" - "fmt" - "github.com/wailsapp/wails/v3/internal/term" - "os" - "path/filepath" - "strings" - "time" - - "github.com/wailsapp/task/v3" - "github.com/wailsapp/task/v3/taskfile/ast" -) - -// BuildSettings contains the CLI build settings -var BuildSettings = map[string]string{} - -func fatal(message string) { - term.Error(message) - os.Exit(1) -} - -type RunTaskOptions struct { - Name string `pos:"1"` - Help bool `name:"h" description:"shows Task usage"` - Init bool `name:"i" description:"creates a new Taskfile.yml"` - List bool `name:"list" description:"tasks with description of current Taskfile"` - ListAll bool `name:"list-all" description:"lists tasks with or without a description"` - ListJSON bool `name:"json" description:"formats task list as json"` - Status bool `name:"status" description:"exits with non-zero exit code if any of the given tasks is not up-to-date"` - Force bool `name:"f" description:"forces execution even when the task is up-to-date"` - Watch bool `name:"w" description:"enables watch of the given task"` - Verbose bool `name:"v" description:"enables verbose mode"` - Version bool `name:"version" description:"prints version"` - Silent bool `name:"s" description:"disables echoing"` - Parallel bool `name:"p" description:"executes tasks provided on command line in parallel"` - Dry bool `name:"dry" description:"compiles and prints tasks in the order that they would be run, without executing them"` - Summary bool `name:"summary" description:"show summary about a task"` - ExitCode bool `name:"x" description:"pass-through the exit code of the task command"` - Dir string `name:"dir" description:"sets directory of execution"` - EntryPoint string `name:"taskfile" description:"choose which Taskfile to run."` - OutputName string `name:"output" description:"sets output style: [interleaved|group|prefixed]"` - OutputGroupBegin string `name:"output-group-begin" description:"message template to print before a task's grouped output"` - OutputGroupEnd string `name:"output-group-end" description:"message template to print after a task's grouped output"` - Color bool `name:"c" description:"colored output. Enabled by default. Set flag to false or use NO_COLOR=1 to disable" default:"true"` - Concurrency int `name:"C" description:"limit number tasks to run concurrently"` - Interval int64 `name:"interval" description:"interval to watch for changes"` -} - -func RunTask(options *RunTaskOptions, otherArgs []string) error { - - if options.Version { - ver := BuildSettings["mod.github.com/wailsapp/task/v3"] - fmt.Println("Task Version:", ver) - return nil - } - - if options.Init { - wd, err := os.Getwd() - if err != nil { - return err - } - return task.InitTaskfile(os.Stdout, wd) - } - - if options.Dir != "" && options.EntryPoint != "" { - return fmt.Errorf("task: You can't set both --dir and --taskfile") - } - - if options.EntryPoint != "" { - options.Dir = filepath.Dir(options.EntryPoint) - options.EntryPoint = filepath.Base(options.EntryPoint) - } - - if options.OutputName != "group" { - if options.OutputGroupBegin != "" { - return fmt.Errorf("task: You can't set --output-group-begin without --output=group") - } - if options.OutputGroupEnd != "" { - return fmt.Errorf("task: You can't set --output-group-end without --output=group") - } - } - - e := task.Executor{ - Force: options.Force, - Watch: options.Watch, - Verbose: options.Verbose, - Silent: options.Silent, - Dir: options.Dir, - Dry: options.Dry, - Entrypoint: options.EntryPoint, - Summary: options.Summary, - Parallel: options.Parallel, - Color: options.Color, - Concurrency: options.Concurrency, - Interval: time.Duration(options.Interval) * time.Second, - DisableVersionCheck: true, - - Stdin: os.Stdin, - Stdout: os.Stdout, - Stderr: os.Stderr, - } - - listOptions := task.NewListOptions(options.List, options.ListAll, options.ListJSON, false) - if err := listOptions.Validate(); err != nil { - fatal(err.Error()) - } - - if listOptions.ShouldListTasks() && options.Silent { - e.ListTaskNames(options.ListAll) - return nil - } - - if err := e.Setup(); err != nil { - fatal(err.Error()) - } - - if listOptions.ShouldListTasks() { - if foundTasks, err := e.ListTasks(listOptions); !foundTasks || err != nil { - os.Exit(1) - } - return nil - } - - // Parse task name and CLI variables from otherArgs or os.Args - var tasksAndVars []string - - // Check if we have a task name specified in options - if options.Name != "" { - // If task name is provided via options, use it and treat otherArgs as CLI variables - tasksAndVars = append([]string{options.Name}, otherArgs...) - } else if len(otherArgs) > 0 { - // Use otherArgs directly if provided - tasksAndVars = otherArgs - } else { - // Fall back to parsing os.Args for backward compatibility - var index int - var arg string - for index, arg = range os.Args[2:] { - if !strings.HasPrefix(arg, "-") { - break - } - } - - for _, taskAndVar := range os.Args[index+2:] { - if taskAndVar == "--" { - break - } - tasksAndVars = append(tasksAndVars, taskAndVar) - } - } - - // Default task - if len(tasksAndVars) == 0 { - tasksAndVars = []string{"default"} - } - - // Parse task name and CLI variables - taskName := tasksAndVars[0] - cliVars := tasksAndVars[1:] - - // Create call with CLI variables - call := &ast.Call{ - Task: taskName, - Vars: &ast.Vars{}, - } - - // Parse CLI variables (format: KEY=VALUE) - for _, v := range cliVars { - if strings.Contains(v, "=") { - parts := strings.SplitN(v, "=", 2) - if len(parts) == 2 { - call.Vars.Set(parts[0], ast.Var{ - Value: parts[1], - }) - } - } - } - - if err := e.RunTask(context.Background(), call); err != nil { - fatal(err.Error()) - } - return nil -} diff --git a/v3/internal/commands/task_integration_test.go b/v3/internal/commands/task_integration_test.go deleted file mode 100644 index c13d73162..000000000 --- a/v3/internal/commands/task_integration_test.go +++ /dev/null @@ -1,342 +0,0 @@ -package commands - -import ( - "bytes" - "os" - "path/filepath" - "runtime" - "strings" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - "github.com/wailsapp/task/v3/taskfile/ast" -) - -func TestTaskParameterPassing(t *testing.T) { - // Skip if running in CI without proper environment - if os.Getenv("CI") == "true" && os.Getenv("SKIP_INTEGRATION_TESTS") == "true" { - t.Skip("Skipping integration test in CI") - } - - // Create a temporary directory for test - tmpDir, err := os.MkdirTemp("", "wails-task-test-*") - require.NoError(t, err) - defer os.RemoveAll(tmpDir) - - // Create a test Taskfile - taskfileContent := `version: '3' - -tasks: - build: - cmds: - - echo "PLATFORM={{.PLATFORM | default "default-platform"}}" - - echo "CONFIG={{.CONFIG | default "default-config"}}" - silent: true - - package: - cmds: - - echo "VERSION={{.VERSION | default "1.0.0"}}" - - echo "OUTPUT={{.OUTPUT | default "output.pkg"}}" - silent: true - - test: - cmds: - - echo "ENV={{.ENV | default "test"}}" - - echo "FLAGS={{.FLAGS | default "none"}}" - silent: true -` - - taskfilePath := filepath.Join(tmpDir, "Taskfile.yml") - err = os.WriteFile(taskfilePath, []byte(taskfileContent), 0644) - require.NoError(t, err) - - // Save current directory - originalWd, err := os.Getwd() - require.NoError(t, err) - defer os.Chdir(originalWd) - - // Change to test directory - err = os.Chdir(tmpDir) - require.NoError(t, err) - - tests := []struct { - name string - options *RunTaskOptions - otherArgs []string - expectedOutput []string - }{ - { - name: "Build task with parameters", - options: &RunTaskOptions{Name: "build"}, - otherArgs: []string{"PLATFORM=linux", "CONFIG=production"}, - expectedOutput: []string{ - "PLATFORM=linux", - "CONFIG=production", - }, - }, - { - name: "Package task with parameters", - options: &RunTaskOptions{Name: "package"}, - otherArgs: []string{"VERSION=2.5.0", "OUTPUT=myapp.pkg"}, - expectedOutput: []string{ - "VERSION=2.5.0", - "OUTPUT=myapp.pkg", - }, - }, - { - name: "Task with default values", - options: &RunTaskOptions{Name: "build"}, - otherArgs: []string{}, - expectedOutput: []string{ - "PLATFORM=default-platform", - "CONFIG=default-config", - }, - }, - { - name: "Task with partial parameters", - options: &RunTaskOptions{Name: "test"}, - otherArgs: []string{"ENV=staging"}, - expectedOutput: []string{ - "ENV=staging", - "FLAGS=none", - }, - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - // Capture output - output := captureTaskOutput(t, tt.options, tt.otherArgs) - - // Verify expected output - for _, expected := range tt.expectedOutput { - assert.Contains(t, output, expected, "Output should contain: %s", expected) - } - }) - } -} - -func TestCLIParameterFormats(t *testing.T) { - tests := []struct { - name string - otherArgs []string - expectError bool - expectedVars map[string]string - }{ - { - name: "Standard KEY=VALUE format", - otherArgs: []string{"build", "KEY1=value1", "KEY2=value2"}, - expectedVars: map[string]string{ - "KEY1": "value1", - "KEY2": "value2", - }, - }, - { - name: "Values with equals signs", - otherArgs: []string{"build", "URL=https://example.com?key=value", "FORMULA=a=b+c"}, - expectedVars: map[string]string{ - "URL": "https://example.com?key=value", - "FORMULA": "a=b+c", - }, - }, - { - name: "Values with spaces (quoted)", - otherArgs: []string{"build", "MESSAGE=Hello World", "PATH=/usr/local/bin"}, - expectedVars: map[string]string{ - "MESSAGE": "Hello World", - "PATH": "/usr/local/bin", - }, - }, - { - name: "Mixed valid and invalid arguments", - otherArgs: []string{"build", "VALID=yes", "invalid-arg", "ANOTHER=value", "--flag"}, - expectedVars: map[string]string{ - "VALID": "yes", - "ANOTHER": "value", - }, - }, - { - name: "Empty value", - otherArgs: []string{"build", "EMPTY=", "KEY=value"}, - expectedVars: map[string]string{ - "EMPTY": "", - "KEY": "value", - }, - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - call := parseTaskCall(&RunTaskOptions{}, tt.otherArgs) - - // Verify variables - for key, expectedValue := range tt.expectedVars { - var actualValue string - found := false - if call.Vars != nil { - call.Vars.Range(func(k string, v ast.Var) error { - if k == key { - actualValue = v.Value.(string) - found = true - } - return nil - }) - } - assert.True(t, found, "Variable %s not found", key) - assert.Equal(t, expectedValue, actualValue, "Variable %s mismatch", key) - } - }) - } -} - -// Helper function to capture task output -func captureTaskOutput(t *testing.T, options *RunTaskOptions, otherArgs []string) string { - // Save original stdout and stderr - oldStdout := os.Stdout - oldStderr := os.Stderr - defer func() { - os.Stdout = oldStdout - os.Stderr = oldStderr - }() - - // Create pipe to capture output - r, w, err := os.Pipe() - require.NoError(t, err) - - os.Stdout = w - os.Stderr = w - - // Run task in a goroutine - done := make(chan bool) - var taskErr error - go func() { - // Note: This is a simplified version for testing - // In real tests, you might want to mock the Task executor - taskErr = RunTask(options, otherArgs) - w.Close() - done <- true - }() - - // Read output - var buf bytes.Buffer - _, err = buf.ReadFrom(r) - require.NoError(t, err) - - // Wait for task to complete - <-done - - // Check for errors (might be expected in some tests) - if taskErr != nil && !strings.Contains(taskErr.Error(), "expected") { - t.Logf("Task error (might be expected): %v", taskErr) - } - - return buf.String() -} - -func TestBackwardCompatibility(t *testing.T) { - // Test that the old way of calling tasks still works - tests := []struct { - name string - osArgs []string - expectedTask string - expectedVars map[string]string - }{ - { - name: "Legacy os.Args parsing", - osArgs: []string{"wails3", "task", "build", "PLATFORM=windows"}, - expectedTask: "build", - expectedVars: map[string]string{ - "PLATFORM": "windows", - }, - }, - { - name: "Legacy with flags before task", - osArgs: []string{"wails3", "task", "--verbose", "test", "ENV=prod"}, - expectedTask: "test", - expectedVars: map[string]string{ - "ENV": "prod", - }, - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - // Save original os.Args - originalArgs := os.Args - defer func() { os.Args = originalArgs }() - - os.Args = tt.osArgs - - // Parse using the backward compatibility path - call := parseTaskCall(&RunTaskOptions{}, []string{}) - - assert.Equal(t, tt.expectedTask, call.Task) - - for key, expectedValue := range tt.expectedVars { - var actualValue string - if call.Vars != nil { - call.Vars.Range(func(k string, v ast.Var) error { - if k == key { - actualValue = v.Value.(string) - } - return nil - }) - } - assert.Equal(t, expectedValue, actualValue, "Variable %s mismatch", key) - } - }) - } -} - -func TestMkdirWithSpacesInPath(t *testing.T) { - if runtime.GOOS != "darwin" { - t.Skip("Skipping: macOS app bundle test only applies to darwin") - } - if os.Getenv("CI") == "true" && os.Getenv("SKIP_INTEGRATION_TESTS") == "true" { - t.Skip("Skipping integration test in CI") - } - - tmpDir, err := os.MkdirTemp("", "wails task test with spaces-*") - require.NoError(t, err) - defer os.RemoveAll(tmpDir) - - taskfileContent := `version: '3' - -vars: - BIN_DIR: "` + tmpDir + `/bin" - APP_NAME: "My App" - -tasks: - create-bundle: - cmds: - - mkdir -p "{{.BIN_DIR}}/{{.APP_NAME}}.app/Contents/MacOS" - - mkdir -p "{{.BIN_DIR}}/{{.APP_NAME}}.app/Contents/Resources" -` - - taskfilePath := filepath.Join(tmpDir, "Taskfile.yml") - err = os.WriteFile(taskfilePath, []byte(taskfileContent), 0644) - require.NoError(t, err) - - originalWd, err := os.Getwd() - require.NoError(t, err) - defer os.Chdir(originalWd) - - err = os.Chdir(tmpDir) - require.NoError(t, err) - - err = RunTask(&RunTaskOptions{Name: "create-bundle"}, []string{}) - require.NoError(t, err) - - appContentsDir := filepath.Join(tmpDir, "bin", "My App.app", "Contents") - - macOSDir := filepath.Join(appContentsDir, "MacOS") - info, err := os.Stat(macOSDir) - require.NoError(t, err, "MacOS directory should exist") - assert.True(t, info.IsDir(), "MacOS should be a directory") - - resourcesDir := filepath.Join(appContentsDir, "Resources") - info, err = os.Stat(resourcesDir) - require.NoError(t, err, "Resources directory should exist") - assert.True(t, info.IsDir(), "Resources should be a directory") -} diff --git a/v3/internal/commands/task_test.go b/v3/internal/commands/task_test.go deleted file mode 100644 index dadee8647..000000000 --- a/v3/internal/commands/task_test.go +++ /dev/null @@ -1,188 +0,0 @@ -package commands - -import ( - "os" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - "github.com/wailsapp/task/v3/taskfile/ast" -) - -func TestParseTaskAndVars(t *testing.T) { - tests := []struct { - name string - options *RunTaskOptions - otherArgs []string - osArgs []string - expectedTask string - expectedVars map[string]string - }{ - { - name: "Task name in options with CLI variables", - options: &RunTaskOptions{Name: "build"}, - otherArgs: []string{"PLATFORM=linux", "CONFIG=production"}, - expectedTask: "build", - expectedVars: map[string]string{ - "PLATFORM": "linux", - "CONFIG": "production", - }, - }, - { - name: "Task name and variables in otherArgs", - options: &RunTaskOptions{}, - otherArgs: []string{"test", "ENV=staging", "DEBUG=true"}, - expectedTask: "test", - expectedVars: map[string]string{ - "ENV": "staging", - "DEBUG": "true", - }, - }, - { - name: "Only task name, no variables", - options: &RunTaskOptions{}, - otherArgs: []string{"deploy"}, - expectedTask: "deploy", - expectedVars: map[string]string{}, - }, - { - name: "Default task when no args provided", - options: &RunTaskOptions{}, - otherArgs: []string{}, - osArgs: []string{"wails3", "task"}, // Set explicit os.Args to avoid test framework interference - expectedTask: "default", - expectedVars: map[string]string{}, - }, - { - name: "Variables with equals signs in values", - options: &RunTaskOptions{Name: "build"}, - otherArgs: []string{"URL=https://example.com?key=value", "CONFIG=key1=val1,key2=val2"}, - expectedTask: "build", - expectedVars: map[string]string{ - "URL": "https://example.com?key=value", - "CONFIG": "key1=val1,key2=val2", - }, - }, - { - name: "Skip non-variable arguments", - options: &RunTaskOptions{Name: "build"}, - otherArgs: []string{"PLATFORM=linux", "some-arg", "CONFIG=debug", "--flag"}, - expectedTask: "build", - expectedVars: map[string]string{ - "PLATFORM": "linux", - "CONFIG": "debug", - }, - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - // Save original os.Args - originalArgs := os.Args - defer func() { os.Args = originalArgs }() - - if tt.osArgs != nil { - os.Args = tt.osArgs - } - - // Parse the task and variables - call := parseTaskCall(tt.options, tt.otherArgs) - - // Verify task name - assert.Equal(t, tt.expectedTask, call.Task) - - // Verify variables - if len(tt.expectedVars) > 0 { - require.NotNil(t, call.Vars) - - // Check each expected variable - for key, expectedValue := range tt.expectedVars { - var actualValue string - call.Vars.Range(func(k string, v ast.Var) error { - if k == key { - actualValue = v.Value.(string) - } - return nil - }) - assert.Equal(t, expectedValue, actualValue, "Variable %s mismatch", key) - } - } else if call.Vars != nil { - // Ensure no variables were set when none expected - count := 0 - call.Vars.Range(func(k string, v ast.Var) error { - count++ - return nil - }) - assert.Equal(t, 0, count, "Expected no variables but found %d", count) - } - }) - } -} - -// Helper function to extract the task parsing logic for testing -func parseTaskCall(options *RunTaskOptions, otherArgs []string) *ast.Call { - var tasksAndVars []string - - // Check if we have a task name specified in options - if options.Name != "" { - // If task name is provided via options, use it and treat otherArgs as CLI variables - tasksAndVars = append([]string{options.Name}, otherArgs...) - } else if len(otherArgs) > 0 { - // Use otherArgs directly if provided - tasksAndVars = otherArgs - } else { - // Fall back to parsing os.Args for backward compatibility - var index int - var arg string - for index, arg = range os.Args[2:] { - if len(arg) > 0 && arg[0] != '-' { - break - } - } - - for _, taskAndVar := range os.Args[index+2:] { - if taskAndVar == "--" { - break - } - tasksAndVars = append(tasksAndVars, taskAndVar) - } - } - - // Default task - if len(tasksAndVars) == 0 { - tasksAndVars = []string{"default"} - } - - // Parse task name and CLI variables - taskName := tasksAndVars[0] - cliVars := tasksAndVars[1:] - - // Create call with CLI variables - call := &ast.Call{ - Task: taskName, - Vars: &ast.Vars{}, - } - - // Parse CLI variables (format: KEY=VALUE) - for _, v := range cliVars { - if idx := findEquals(v); idx != -1 { - key := v[:idx] - value := v[idx+1:] - call.Vars.Set(key, ast.Var{ - Value: value, - }) - } - } - - return call -} - -// Helper to find the first equals sign -func findEquals(s string) int { - for i, r := range s { - if r == '=' { - return i - } - } - return -1 -} \ No newline at end of file diff --git a/v3/internal/commands/task_wrapper.go b/v3/internal/commands/task_wrapper.go deleted file mode 100644 index 908c0e53c..000000000 --- a/v3/internal/commands/task_wrapper.go +++ /dev/null @@ -1,73 +0,0 @@ -package commands - -import ( - "os" - "runtime" - "strings" - - "github.com/wailsapp/wails/v3/internal/flags" -) - -// runTaskFunc is a variable to allow mocking in tests -var runTaskFunc = RunTask - -// validPlatforms for GOOS -var validPlatforms = map[string]bool{ - "windows": true, - "darwin": true, - "linux": true, -} - -func Build(_ *flags.Build, otherArgs []string) error { - return wrapTask("build", otherArgs) -} - -func Package(_ *flags.Package, otherArgs []string) error { - return wrapTask("package", otherArgs) -} - -func SignWrapper(_ *flags.SignWrapper, otherArgs []string) error { - return wrapTask("sign", otherArgs) -} - -func wrapTask(action string, otherArgs []string) error { - // Check environment first, then allow args to override - goos := os.Getenv("GOOS") - if goos == "" { - goos = runtime.GOOS - } - goarch := os.Getenv("GOARCH") - if goarch == "" { - goarch = runtime.GOARCH - } - - var remainingArgs []string - - // Args override environment - for _, arg := range otherArgs { - switch { - case strings.HasPrefix(arg, "GOOS="): - goos = strings.TrimPrefix(arg, "GOOS=") - case strings.HasPrefix(arg, "GOARCH="): - goarch = strings.TrimPrefix(arg, "GOARCH=") - default: - remainingArgs = append(remainingArgs, arg) - } - } - - // Determine task name based on GOOS - taskName := action - if validPlatforms[goos] { - taskName = goos + ":" + action - } - - // Pass ARCH to task (always set, defaults to current architecture) - remainingArgs = append(remainingArgs, "ARCH="+goarch) - - // Rebuild os.Args to include the command and all additional arguments - newArgs := []string{"wails3", "task", taskName} - newArgs = append(newArgs, remainingArgs...) - os.Args = newArgs - // Pass the task name via options and remainingArgs as CLI variables - return runTaskFunc(&RunTaskOptions{Name: taskName}, remainingArgs) -} diff --git a/v3/internal/commands/task_wrapper_test.go b/v3/internal/commands/task_wrapper_test.go deleted file mode 100644 index 5a7d8c3a0..000000000 --- a/v3/internal/commands/task_wrapper_test.go +++ /dev/null @@ -1,296 +0,0 @@ -package commands - -import ( - "os" - "runtime" - "testing" - - "github.com/stretchr/testify/assert" - "github.com/wailsapp/wails/v3/internal/flags" -) - -func TestWrapTask(t *testing.T) { - // Get current platform info for expected values - currentOS := runtime.GOOS - currentArch := runtime.GOARCH - - tests := []struct { - name string - command string - otherArgs []string - envGOOS string - envGOARCH string - expectedTaskName string - expectedArgs []string - expectedOsArgs []string - }{ - { - name: "Build with parameters uses current platform", - command: "build", - otherArgs: []string{"CONFIG=debug"}, - expectedTaskName: currentOS + ":build", - expectedArgs: []string{"CONFIG=debug", "ARCH=" + currentArch}, - expectedOsArgs: []string{"wails3", "task", currentOS + ":build", "CONFIG=debug", "ARCH=" + currentArch}, - }, - { - name: "Package with parameters uses current platform", - command: "package", - otherArgs: []string{"VERSION=1.0.0", "OUTPUT=app.pkg"}, - expectedTaskName: currentOS + ":package", - expectedArgs: []string{"VERSION=1.0.0", "OUTPUT=app.pkg", "ARCH=" + currentArch}, - expectedOsArgs: []string{"wails3", "task", currentOS + ":package", "VERSION=1.0.0", "OUTPUT=app.pkg", "ARCH=" + currentArch}, - }, - { - name: "Build without parameters", - command: "build", - otherArgs: []string{}, - expectedTaskName: currentOS + ":build", - expectedArgs: []string{"ARCH=" + currentArch}, - expectedOsArgs: []string{"wails3", "task", currentOS + ":build", "ARCH=" + currentArch}, - }, - { - name: "GOOS override changes task prefix", - command: "build", - otherArgs: []string{"GOOS=darwin", "CONFIG=release"}, - expectedTaskName: "darwin:build", - expectedArgs: []string{"CONFIG=release", "ARCH=" + currentArch}, - expectedOsArgs: []string{"wails3", "task", "darwin:build", "CONFIG=release", "ARCH=" + currentArch}, - }, - { - name: "GOARCH override changes ARCH arg", - command: "build", - otherArgs: []string{"GOARCH=arm64"}, - expectedTaskName: currentOS + ":build", - expectedArgs: []string{"ARCH=arm64"}, - expectedOsArgs: []string{"wails3", "task", currentOS + ":build", "ARCH=arm64"}, - }, - { - name: "Both GOOS and GOARCH override", - command: "package", - otherArgs: []string{"GOOS=windows", "GOARCH=386", "VERSION=2.0"}, - expectedTaskName: "windows:package", - expectedArgs: []string{"VERSION=2.0", "ARCH=386"}, - expectedOsArgs: []string{"wails3", "task", "windows:package", "VERSION=2.0", "ARCH=386"}, - }, - { - name: "Environment GOOS is used when no arg override", - command: "build", - otherArgs: []string{"CONFIG=debug"}, - envGOOS: "darwin", - expectedTaskName: "darwin:build", - expectedArgs: []string{"CONFIG=debug", "ARCH=" + currentArch}, - expectedOsArgs: []string{"wails3", "task", "darwin:build", "CONFIG=debug", "ARCH=" + currentArch}, - }, - { - name: "Arg GOOS overrides environment GOOS", - command: "build", - otherArgs: []string{"GOOS=linux"}, - envGOOS: "darwin", - expectedTaskName: "linux:build", - expectedArgs: []string{"ARCH=" + currentArch}, - expectedOsArgs: []string{"wails3", "task", "linux:build", "ARCH=" + currentArch}, - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - // Save and restore os.Args - originalArgs := os.Args - defer func() { os.Args = originalArgs }() - - // Save and restore environment variables - originalGOOS := os.Getenv("GOOS") - originalGOARCH := os.Getenv("GOARCH") - defer func() { - if originalGOOS == "" { - os.Unsetenv("GOOS") - } else { - os.Setenv("GOOS", originalGOOS) - } - if originalGOARCH == "" { - os.Unsetenv("GOARCH") - } else { - os.Setenv("GOARCH", originalGOARCH) - } - }() - - // Set test environment - if tt.envGOOS != "" { - os.Setenv("GOOS", tt.envGOOS) - } else { - os.Unsetenv("GOOS") - } - if tt.envGOARCH != "" { - os.Setenv("GOARCH", tt.envGOARCH) - } else { - os.Unsetenv("GOARCH") - } - - // Mock RunTask to capture the arguments - originalRunTask := runTaskFunc - var capturedOptions *RunTaskOptions - var capturedOtherArgs []string - runTaskFunc = func(options *RunTaskOptions, otherArgs []string) error { - capturedOptions = options - capturedOtherArgs = otherArgs - return nil - } - defer func() { runTaskFunc = originalRunTask }() - - // Execute wrapTask - err := wrapTask(tt.command, tt.otherArgs) - assert.NoError(t, err) - - // Verify os.Args was set correctly - assert.Equal(t, tt.expectedOsArgs, os.Args) - - // Verify RunTask was called with correct parameters - assert.Equal(t, tt.expectedTaskName, capturedOptions.Name) - assert.Equal(t, tt.expectedArgs, capturedOtherArgs) - }) - } -} - -func TestBuildCommand(t *testing.T) { - currentOS := runtime.GOOS - currentArch := runtime.GOARCH - - // Save original RunTask - originalRunTask := runTaskFunc - defer func() { runTaskFunc = originalRunTask }() - - // Mock RunTask to capture the arguments - var capturedOptions *RunTaskOptions - var capturedOtherArgs []string - runTaskFunc = func(options *RunTaskOptions, otherArgs []string) error { - capturedOptions = options - capturedOtherArgs = otherArgs - return nil - } - - // Save original os.Args and environment - originalArgs := os.Args - defer func() { os.Args = originalArgs }() - - originalGOOS := os.Getenv("GOOS") - originalGOARCH := os.Getenv("GOARCH") - defer func() { - if originalGOOS == "" { - os.Unsetenv("GOOS") - } else { - os.Setenv("GOOS", originalGOOS) - } - if originalGOARCH == "" { - os.Unsetenv("GOARCH") - } else { - os.Setenv("GOARCH", originalGOARCH) - } - }() - os.Unsetenv("GOOS") - os.Unsetenv("GOARCH") - - // Test Build command - buildFlags := &flags.Build{} - otherArgs := []string{"CONFIG=release"} - - err := Build(buildFlags, otherArgs) - assert.NoError(t, err) - assert.Equal(t, currentOS+":build", capturedOptions.Name) - assert.Equal(t, []string{"CONFIG=release", "ARCH=" + currentArch}, capturedOtherArgs) -} - -func TestPackageCommand(t *testing.T) { - currentOS := runtime.GOOS - currentArch := runtime.GOARCH - - // Save original RunTask - originalRunTask := runTaskFunc - defer func() { runTaskFunc = originalRunTask }() - - // Mock RunTask to capture the arguments - var capturedOptions *RunTaskOptions - var capturedOtherArgs []string - runTaskFunc = func(options *RunTaskOptions, otherArgs []string) error { - capturedOptions = options - capturedOtherArgs = otherArgs - return nil - } - - // Save original os.Args and environment - originalArgs := os.Args - defer func() { os.Args = originalArgs }() - - originalGOOS := os.Getenv("GOOS") - originalGOARCH := os.Getenv("GOARCH") - defer func() { - if originalGOOS == "" { - os.Unsetenv("GOOS") - } else { - os.Setenv("GOOS", originalGOOS) - } - if originalGOARCH == "" { - os.Unsetenv("GOARCH") - } else { - os.Setenv("GOARCH", originalGOARCH) - } - }() - os.Unsetenv("GOOS") - os.Unsetenv("GOARCH") - - // Test Package command - packageFlags := &flags.Package{} - otherArgs := []string{"VERSION=2.0.0", "OUTPUT=myapp.dmg"} - - err := Package(packageFlags, otherArgs) - assert.NoError(t, err) - assert.Equal(t, currentOS+":package", capturedOptions.Name) - assert.Equal(t, []string{"VERSION=2.0.0", "OUTPUT=myapp.dmg", "ARCH=" + currentArch}, capturedOtherArgs) -} - -func TestSignWrapperCommand(t *testing.T) { - currentOS := runtime.GOOS - currentArch := runtime.GOARCH - - // Save original RunTask - originalRunTask := runTaskFunc - defer func() { runTaskFunc = originalRunTask }() - - // Mock RunTask to capture the arguments - var capturedOptions *RunTaskOptions - var capturedOtherArgs []string - runTaskFunc = func(options *RunTaskOptions, otherArgs []string) error { - capturedOptions = options - capturedOtherArgs = otherArgs - return nil - } - - // Save original os.Args and environment - originalArgs := os.Args - defer func() { os.Args = originalArgs }() - - originalGOOS := os.Getenv("GOOS") - originalGOARCH := os.Getenv("GOARCH") - defer func() { - if originalGOOS == "" { - os.Unsetenv("GOOS") - } else { - os.Setenv("GOOS", originalGOOS) - } - if originalGOARCH == "" { - os.Unsetenv("GOARCH") - } else { - os.Setenv("GOARCH", originalGOARCH) - } - }() - os.Unsetenv("GOOS") - os.Unsetenv("GOARCH") - - // Test SignWrapper command - signFlags := &flags.SignWrapper{} - otherArgs := []string{"IDENTITY=Developer ID"} - - err := SignWrapper(signFlags, otherArgs) - assert.NoError(t, err) - assert.Equal(t, currentOS+":sign", capturedOptions.Name) - assert.Equal(t, []string{"IDENTITY=Developer ID", "ARCH=" + currentArch}, capturedOtherArgs) -} diff --git a/v3/internal/commands/tool_buildinfo.go b/v3/internal/commands/tool_buildinfo.go deleted file mode 100644 index d8547d8ce..000000000 --- a/v3/internal/commands/tool_buildinfo.go +++ /dev/null @@ -1,18 +0,0 @@ -package commands - -import ( - "fmt" - "github.com/wailsapp/wails/v3/internal/buildinfo" -) - -type BuildInfoOptions struct{} - -func BuildInfo(_ *BuildInfoOptions) error { - - info, err := buildinfo.Get() - if err != nil { - return err - } - fmt.Printf("%+v\n", info) - return nil -} diff --git a/v3/internal/commands/tool_checkport.go b/v3/internal/commands/tool_checkport.go deleted file mode 100644 index f0ba75bc4..000000000 --- a/v3/internal/commands/tool_checkport.go +++ /dev/null @@ -1,57 +0,0 @@ -package commands - -import ( - "fmt" - "net" - "net/url" - "strconv" - "time" -) - -type ToolCheckPortOptions struct { - URL string `name:"u" description:"URL to check"` - Host string `name:"h" description:"Host to check" default:"localhost"` - Port int `name:"p" description:"Port to check"` -} - -func isPortOpen(ip string, port int) bool { - timeout := time.Second - conn, err := net.DialTimeout("tcp", net.JoinHostPort(ip, fmt.Sprintf("%d", port)), timeout) - if err != nil { - return false - } - - // If there's no error, close the connection and return true. - if conn != nil { - _ = conn.Close() - } - return true -} - -func ToolCheckPort(options *ToolCheckPortOptions) error { - DisableFooter = true - - if options.URL != "" { - // Parse URL - u, err := url.Parse(options.URL) - if err != nil { - return err - } - options.Host = u.Hostname() - options.Port, err = strconv.Atoi(u.Port()) - if err != nil { - return err - } - } else { - if options.Port == 0 { - return fmt.Errorf("please use the -p flag to specify a port") - } - if !isPortOpen(options.Host, options.Port) { - return fmt.Errorf("port %d is not open on %s", options.Port, options.Host) - } - } - if !isPortOpen(options.Host, options.Port) { - return fmt.Errorf("port %d is not open on %s", options.Port, options.Host) - } - return nil -} diff --git a/v3/internal/commands/tool_cp.go b/v3/internal/commands/tool_cp.go deleted file mode 100644 index 5e0a1526a..000000000 --- a/v3/internal/commands/tool_cp.go +++ /dev/null @@ -1,40 +0,0 @@ -package commands - -import ( - "fmt" - "os" - "path/filepath" -) - -type CpOptions struct{} - -func Cp(_ *CpOptions) error { - DisableFooter = true - - // extract the source and destination from os.Args - if len(os.Args) != 5 { - return fmt.Errorf("cp requires a source and destination") - } - // Extract source - source := os.Args[3] - for _, destination := range os.Args[4:] { - src, err := filepath.Abs(source) - if err != nil { - return err - } - dst, err := filepath.Abs(destination) - if err != nil { - return err - } - input, err := os.ReadFile(src) - if err != nil { - return err - } - - err = os.WriteFile(dst, input, 0644) - if err != nil { - return fmt.Errorf("error creating %s: %s", dst, err.Error()) - } - } - return nil -} diff --git a/v3/internal/commands/tool_lipo.go b/v3/internal/commands/tool_lipo.go deleted file mode 100644 index a33ebd777..000000000 --- a/v3/internal/commands/tool_lipo.go +++ /dev/null @@ -1,31 +0,0 @@ -package commands - -import ( - "fmt" - - "github.com/konoui/lipo/pkg/lipo" - "github.com/wailsapp/wails/v3/internal/flags" -) - -func ToolLipo(options *flags.Lipo) error { - DisableFooter = true - - if len(options.Inputs) < 2 { - return fmt.Errorf("lipo requires at least 2 input files") - } - - if options.Output == "" { - return fmt.Errorf("output file is required (-output)") - } - - l := lipo.New( - lipo.WithInputs(options.Inputs...), - lipo.WithOutput(options.Output), - ) - - if err := l.Create(); err != nil { - return fmt.Errorf("failed to create universal binary: %w", err) - } - - return nil -} diff --git a/v3/internal/commands/tool_package.go b/v3/internal/commands/tool_package.go deleted file mode 100644 index a7d8cfd52..000000000 --- a/v3/internal/commands/tool_package.go +++ /dev/null @@ -1,116 +0,0 @@ -package commands - -import ( - "fmt" - "os" - "path/filepath" - "runtime" - "strings" - - // "github.com/wailsapp/wails/v3/internal/commands/dmg" // TODO: Missing package - "github.com/wailsapp/wails/v3/internal/flags" - "github.com/wailsapp/wails/v3/internal/packager" -) - -// ToolPackage generates a package in the specified format -func ToolPackage(options *flags.ToolPackage) error { - DisableFooter = true - - // Check if we're creating a DMG - isDMG := strings.ToLower(options.Format) == "dmg" || options.CreateDMG - - // Config file is required for Linux packages but optional for DMG - if options.ConfigPath == "" && !isDMG { - return fmt.Errorf("please provide a config file using the -config flag") - } - - if options.ExecutableName == "" { - return fmt.Errorf("please provide an executable name using the -name flag") - } - - // Handle DMG creation for macOS - if isDMG { - if runtime.GOOS != "darwin" { - return fmt.Errorf("DMG creation is only supported on macOS") - } - - // For DMG, we expect the .app bundle to already exist - appPath := filepath.Join(options.Out, fmt.Sprintf("%s.app", options.ExecutableName)) - if _, err := os.Stat(appPath); os.IsNotExist(err) { - return fmt.Errorf("application bundle not found: %s", appPath) - } - - // Create output path for DMG - dmgPath := filepath.Join(options.Out, fmt.Sprintf("%s.dmg", options.ExecutableName)) - - // DMG creation temporarily disabled - missing dmg package - _ = dmgPath // avoid unused variable warning - return fmt.Errorf("DMG creation is temporarily disabled due to missing dmg package") - - // // Create DMG creator - // dmgCreator, err := dmg.New(appPath, dmgPath, options.ExecutableName) - // if err != nil { - // return fmt.Errorf("error creating DMG: %w", err) - // } - - // // Set background image if provided - // if options.BackgroundImage != "" { - // if err := dmgCreator.SetBackgroundImage(options.BackgroundImage); err != nil { - // return fmt.Errorf("error setting background image: %w", err) - // } - // } - - // // Set default icon positions - // dmgCreator.AddIconPosition(filepath.Base(appPath), 150, 175) - // dmgCreator.AddIconPosition("Applications", 450, 175) - - // // Create the DMG - // if err := dmgCreator.Create(); err != nil { - // return fmt.Errorf("error creating DMG: %w", err) - // } - - // fmt.Printf("DMG created successfully: %s\n", dmgPath) - // return nil - } - - // For Linux packages, continue with existing logic - var pkgType packager.PackageType - switch strings.ToLower(options.Format) { - case "deb": - pkgType = packager.DEB - case "rpm": - pkgType = packager.RPM - case "archlinux": - pkgType = packager.ARCH - default: - return fmt.Errorf("unsupported package format '%s'. Supported formats: deb, rpm, archlinux, dmg", options.Format) - } - - // Get absolute path of config file - configPath, err := filepath.Abs(options.ConfigPath) - if err != nil { - return fmt.Errorf("error getting absolute path of config file: %w", err) - } - - // Check if config file exists - if info, err := os.Stat(configPath); err != nil { - return fmt.Errorf("config file not found: %s", configPath) - } else if info.Mode().Perm()&0444 == 0 { - return fmt.Errorf("config file is not readable: %s", configPath) - } - - // Generate output filename based on format - if options.Format == "archlinux" { - // Arch linux packages are not .archlinux files, they are .pkg.tar.zst - options.Format = "pkg.tar.zst" - } - outputFile := filepath.Join(options.Out, fmt.Sprintf("%s.%s", options.ExecutableName, options.Format)) - - // Create the package - err = packager.CreatePackageFromConfig(pkgType, configPath, outputFile) - if err != nil { - return fmt.Errorf("error creating package: %w", err) - } - - return nil -} diff --git a/v3/internal/commands/tool_package_test.go b/v3/internal/commands/tool_package_test.go deleted file mode 100644 index 21d52962d..000000000 --- a/v3/internal/commands/tool_package_test.go +++ /dev/null @@ -1,143 +0,0 @@ -package commands - -import ( - "os" - "path/filepath" - "strings" - "testing" - - "github.com/wailsapp/wails/v3/internal/flags" -) - -func TestToolPackage(t *testing.T) { - tests := []struct { - name string - setup func() (*flags.ToolPackage, func()) - wantErr bool - errMsg string - }{ - { - name: "should fail with invalid format", - setup: func() (*flags.ToolPackage, func()) { - return &flags.ToolPackage{ - Format: "invalid", - ConfigPath: "config.yaml", - ExecutableName: "myapp", - }, func() {} - }, - wantErr: true, - errMsg: "unsupported package format", - }, - { - name: "should fail with missing config file", - setup: func() (*flags.ToolPackage, func()) { - return &flags.ToolPackage{ - Format: "deb", - ConfigPath: "nonexistent.yaml", - ExecutableName: "myapp", - }, func() {} - }, - wantErr: true, - errMsg: "config file not found", - }, - { - name: "should handle case-insensitive format (DEB)", - setup: func() (*flags.ToolPackage, func()) { - // Create a temporary config file - dir := t.TempDir() - configPath := filepath.Join(dir, "config.yaml") - err := os.WriteFile(configPath, []byte("name: test"), 0644) - if err != nil { - t.Fatal(err) - } - - // Create bin directory - err = os.MkdirAll(filepath.Join(dir, "bin"), 0755) - if err != nil { - t.Fatal(err) - } - - return &flags.ToolPackage{ - Format: "DEB", - ConfigPath: configPath, - ExecutableName: "myapp", - }, func() { - os.RemoveAll(filepath.Join(dir, "bin")) - } - }, - wantErr: false, - }, - { - name: "should handle case-insensitive format (RPM)", - setup: func() (*flags.ToolPackage, func()) { - // Create a temporary config file - dir := t.TempDir() - configPath := filepath.Join(dir, "config.yaml") - err := os.WriteFile(configPath, []byte("name: test"), 0644) - if err != nil { - t.Fatal(err) - } - - // Create bin directory - err = os.MkdirAll(filepath.Join(dir, "bin"), 0755) - if err != nil { - t.Fatal(err) - } - - return &flags.ToolPackage{ - Format: "RPM", - ConfigPath: configPath, - ExecutableName: "myapp", - }, func() { - os.RemoveAll(filepath.Join(dir, "bin")) - } - }, - wantErr: false, - }, - { - name: "should handle case-insensitive format (ARCHLINUX)", - setup: func() (*flags.ToolPackage, func()) { - // Create a temporary config file - dir := t.TempDir() - configPath := filepath.Join(dir, "config.yaml") - err := os.WriteFile(configPath, []byte("name: test"), 0644) - if err != nil { - t.Fatal(err) - } - - // Create bin directory - err = os.MkdirAll(filepath.Join(dir, "bin"), 0755) - if err != nil { - t.Fatal(err) - } - - return &flags.ToolPackage{ - Format: "ARCHLINUX", - ConfigPath: configPath, - ExecutableName: "myapp", - }, func() { - os.RemoveAll(filepath.Join(dir, "bin")) - } - }, - wantErr: false, - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - options, cleanup := tt.setup() - defer cleanup() - - err := ToolPackage(options) - - if (err != nil) != tt.wantErr { - t.Errorf("ToolPackage() error = %v, wantErr %v", err, tt.wantErr) - return - } - - if tt.wantErr && !strings.Contains(err.Error(), tt.errMsg) { - t.Errorf("ToolPackage() error = %v, want error containing %v", err, tt.errMsg) - } - }) - } -} diff --git a/v3/internal/commands/tool_version.go b/v3/internal/commands/tool_version.go deleted file mode 100644 index fe0deb5ec..000000000 --- a/v3/internal/commands/tool_version.go +++ /dev/null @@ -1,123 +0,0 @@ -package commands - -import ( - "fmt" - "strconv" - "strings" - - "github.com/wailsapp/wails/v3/internal/github" -) - -type ToolVersionOptions struct { - Version string `name:"v" description:"Current version to bump"` - Major bool `name:"major" description:"Bump major version"` - Minor bool `name:"minor" description:"Bump minor version"` - Patch bool `name:"patch" description:"Bump patch version"` - Prerelease bool `name:"prerelease" description:"Bump prerelease version (e.g., alpha.5 to alpha.6)"` -} - -// bumpPrerelease increments the numeric part of a prerelease string -// For example, "alpha.5" becomes "alpha.6" -func bumpPrerelease(prerelease string) string { - // If prerelease is empty, return it as is - if prerelease == "" { - return prerelease - } - - // Split the prerelease string by dots - parts := strings.Split(prerelease, ".") - - // If there's only one part (e.g., "alpha"), return it as is - if len(parts) == 1 { - return prerelease - } - - // Try to parse the last part as a number - lastPart := parts[len(parts)-1] - num, err := strconv.Atoi(lastPart) - if err != nil { - // If the last part is not a number, return the prerelease as is - return prerelease - } - - // Increment the number - num++ - - // Replace the last part with the incremented number - parts[len(parts)-1] = strconv.Itoa(num) - - // Join the parts back together - return strings.Join(parts, ".") -} - -// ToolVersion bumps a semantic version based on the provided flags -func ToolVersion(options *ToolVersionOptions) error { - DisableFooter = true - - if options.Version == "" { - return fmt.Errorf("please provide a version using the -v flag") - } - - // Check if the version has a "v" prefix - hasVPrefix := false - versionStr := options.Version - if len(versionStr) > 0 && versionStr[0] == 'v' { - hasVPrefix = true - versionStr = versionStr[1:] - } - - // Parse the current version - semver, err := github.NewSemanticVersion(versionStr) - if err != nil { - return fmt.Errorf("invalid version format: %v", err) - } - - // Get the current version components - major := semver.Version.Major() - minor := semver.Version.Minor() - patch := semver.Version.Patch() - prerelease := semver.Version.Prerelease() - metadata := semver.Version.Metadata() - - // Check if at least one flag is specified - if !options.Major && !options.Minor && !options.Patch && !options.Prerelease { - return fmt.Errorf("please specify one of -major, -minor, -patch, or -prerelease") - } - - // Bump the version based on the flags (major takes precedence over minor, which takes precedence over patch) - if options.Major { - major++ - minor = 0 - patch = 0 - } else if options.Minor { - minor++ - patch = 0 - } else if options.Patch { - patch++ - } else if options.Prerelease { - // If only prerelease flag is specified, bump the prerelease version - if prerelease == "" { - return fmt.Errorf("cannot bump prerelease version: no prerelease part in the version") - } - prerelease = bumpPrerelease(prerelease) - } - - // Format the new version - newVersion := fmt.Sprintf("%d.%d.%d", major, minor, patch) - if prerelease != "" { - newVersion += "-" + prerelease - } - if metadata != "" { - newVersion += "+" + metadata - } - - // Add the "v" prefix back if it was present in the input - if hasVPrefix { - newVersion = "v" + newVersion - } - - // Print the new version - fmt.Println(newVersion) - - return nil -} diff --git a/v3/internal/commands/tool_version_test.go b/v3/internal/commands/tool_version_test.go deleted file mode 100644 index 1da58585f..000000000 --- a/v3/internal/commands/tool_version_test.go +++ /dev/null @@ -1,231 +0,0 @@ -package commands - -import ( - "bytes" - "io" - "os" - "strings" - "testing" -) - -func TestToolVersion(t *testing.T) { - // Create a table of test cases - testCases := []struct { - name string - options ToolVersionOptions - expectedOutput string - expectedError bool - }{ - { - name: "Bump major version", - options: ToolVersionOptions{ - Version: "1.2.3", - Major: true, - }, - expectedOutput: "2.0.0", - expectedError: false, - }, - { - name: "Bump minor version", - options: ToolVersionOptions{ - Version: "1.2.3", - Minor: true, - }, - expectedOutput: "1.3.0", - expectedError: false, - }, - { - name: "Bump patch version", - options: ToolVersionOptions{ - Version: "1.2.3", - Patch: true, - }, - expectedOutput: "1.2.4", - expectedError: false, - }, - { - name: "Bump major version with v prefix", - options: ToolVersionOptions{ - Version: "v1.2.3", - Major: true, - }, - expectedOutput: "v2.0.0", - expectedError: false, - }, - { - name: "Bump minor version with v prefix", - options: ToolVersionOptions{ - Version: "v1.2.3", - Minor: true, - }, - expectedOutput: "v1.3.0", - expectedError: false, - }, - { - name: "Bump patch version with v prefix", - options: ToolVersionOptions{ - Version: "v1.2.3", - Patch: true, - }, - expectedOutput: "v1.2.4", - expectedError: false, - }, - { - name: "Bump version with prerelease", - options: ToolVersionOptions{ - Version: "1.2.3-alpha", - Patch: true, - }, - expectedOutput: "1.2.4-alpha", - expectedError: false, - }, - { - name: "Bump version with metadata", - options: ToolVersionOptions{ - Version: "1.2.3+build123", - Patch: true, - }, - expectedOutput: "1.2.4+build123", - expectedError: false, - }, - { - name: "Bump version with prerelease and metadata", - options: ToolVersionOptions{ - Version: "1.2.3-alpha+build123", - Patch: true, - }, - expectedOutput: "1.2.4-alpha+build123", - expectedError: false, - }, - { - name: "Bump version with v prefix, prerelease and metadata", - options: ToolVersionOptions{ - Version: "v1.2.3-alpha+build123", - Patch: true, - }, - expectedOutput: "v1.2.4-alpha+build123", - expectedError: false, - }, - { - name: "No version provided", - options: ToolVersionOptions{ - Major: true, - }, - expectedOutput: "", - expectedError: true, - }, - { - name: "No bump flag provided", - options: ToolVersionOptions{ - Version: "1.2.3", - }, - expectedOutput: "", - expectedError: true, - }, - { - name: "Invalid version format", - options: ToolVersionOptions{ - Version: "invalid", - Major: true, - }, - expectedOutput: "", - expectedError: true, - }, - { - name: "Bump prerelease version with numeric component", - options: ToolVersionOptions{ - Version: "1.2.3-alpha.5", - Prerelease: true, - }, - expectedOutput: "1.2.3-alpha.6", - expectedError: false, - }, - { - name: "Bump prerelease version with v prefix", - options: ToolVersionOptions{ - Version: "v1.2.3-alpha.5", - Prerelease: true, - }, - expectedOutput: "v1.2.3-alpha.6", - expectedError: false, - }, - { - name: "Bump prerelease version with metadata", - options: ToolVersionOptions{ - Version: "1.2.3-alpha.5+build123", - Prerelease: true, - }, - expectedOutput: "1.2.3-alpha.6+build123", - expectedError: false, - }, - { - name: "Bump prerelease version without numeric component", - options: ToolVersionOptions{ - Version: "1.2.3-alpha", - Prerelease: true, - }, - expectedOutput: "1.2.3-alpha", - expectedError: false, - }, - { - name: "Bump prerelease version when no prerelease part exists", - options: ToolVersionOptions{ - Version: "1.2.3", - Prerelease: true, - }, - expectedOutput: "", - expectedError: true, - }, - { - name: "Bump prerelease version for issue example v3.0.0-alpha.5", - options: ToolVersionOptions{ - Version: "v3.0.0-alpha.5", - Prerelease: true, - }, - expectedOutput: "v3.0.0-alpha.6", - expectedError: false, - }, - } - - // Run each test case - for _, tc := range testCases { - t.Run(tc.name, func(t *testing.T) { - // Capture stdout - oldStdout := os.Stdout - r, w, _ := os.Pipe() - os.Stdout = w - - // Call the function - err := ToolVersion(&tc.options) - - // Restore stdout - err2 := w.Close() - if err2 != nil { - t.Fail() - } - os.Stdout = oldStdout - - // Read captured output - var buf bytes.Buffer - _, err2 = io.Copy(&buf, r) - if err2 != nil { - t.Fail() - } - - output := strings.TrimSpace(buf.String()) - - // Check error - if tc.expectedError && err == nil { - t.Errorf("Expected error but got none") - } - if !tc.expectedError && err != nil { - t.Errorf("Expected no error but got: %v", err) - } - - // Check output - if !tc.expectedError && output != tc.expectedOutput { - t.Errorf("Expected output '%s' but got '%s'", tc.expectedOutput, output) - } - }) - } -} diff --git a/v3/internal/commands/updatable_build_assets/darwin/Info.dev.plist.tmpl b/v3/internal/commands/updatable_build_assets/darwin/Info.dev.plist.tmpl deleted file mode 100644 index 151629739..000000000 --- a/v3/internal/commands/updatable_build_assets/darwin/Info.dev.plist.tmpl +++ /dev/null @@ -1,74 +0,0 @@ - - - - CFBundlePackageType - APPL - CFBundleName - {{.ProductName}} - CFBundleExecutable - {{.BinaryName}} - CFBundleIdentifier - {{.ProductIdentifier}} - CFBundleVersion - {{.ProductVersion}} - CFBundleGetInfoString - {{.ProductComments}} - CFBundleShortVersionString - {{.ProductVersion}} - CFBundleIconFile - icons - {{- if .CFBundleIconName}} - CFBundleIconName - {{.CFBundleIconName}} - {{- end}} - LSMinimumSystemVersion - 10.15.0 - NSHighResolutionCapable - true - NSHumanReadableCopyright - {{.ProductCopyright}} - {{- if .FileAssociations}} - CFBundleDocumentTypes - - {{- range .FileAssociations}} - - CFBundleTypeExtensions - - {{.Ext}} - - CFBundleTypeName - {{.Name}} - CFBundleTypeRole - {{.Role}} - CFBundleTypeIconFile - {{.IconName}} - {{- if .MimeType}} - CFBundleTypeMimeType - {{.MimeType}} - {{- end}} - - {{- end}} - - {{- end}} - NSAppTransportSecurity - - NSAllowsLocalNetworking - - - {{- if .Protocols}} - CFBundleURLTypes - - {{- range .Protocols}} - - CFBundleURLName - wails.com.{{.Scheme}} - CFBundleURLSchemes - - {{.Scheme}} - - - {{- end}} - - {{- end}} - - \ No newline at end of file diff --git a/v3/internal/commands/updatable_build_assets/darwin/Info.plist.tmpl b/v3/internal/commands/updatable_build_assets/darwin/Info.plist.tmpl deleted file mode 100644 index 5792cbf93..000000000 --- a/v3/internal/commands/updatable_build_assets/darwin/Info.plist.tmpl +++ /dev/null @@ -1,69 +0,0 @@ - - - - CFBundlePackageType - APPL - CFBundleName - {{.ProductName}} - CFBundleExecutable - {{.BinaryName}} - CFBundleIdentifier - {{.ProductIdentifier}} - CFBundleVersion - {{.ProductVersion}} - CFBundleGetInfoString - {{.ProductComments}} - CFBundleShortVersionString - {{.ProductVersion}} - CFBundleIconFile - icons - {{- if .CFBundleIconName}} - CFBundleIconName - {{.CFBundleIconName}} - {{- end}} - LSMinimumSystemVersion - 10.15.0 - NSHighResolutionCapable - true - NSHumanReadableCopyright - {{.ProductCopyright}} - {{- if .FileAssociations}} - CFBundleDocumentTypes - - {{- range .FileAssociations}} - - CFBundleTypeExtensions - - {{.Ext}} - - CFBundleTypeName - {{.Name}} - CFBundleTypeRole - {{.Role}} - CFBundleTypeIconFile - {{.IconName}} - {{- if .MimeType}} - CFBundleTypeMimeType - {{.MimeType}} - {{- end}} - - {{- end}} - - {{- end}} - {{- if .Protocols}} - CFBundleURLTypes - - {{- range .Protocols}} - - CFBundleURLName - wails.com.{{.Scheme}} - CFBundleURLSchemes - - {{.Scheme}} - - - {{- end}} - - {{- end}} - - \ No newline at end of file diff --git a/v3/internal/commands/updatable_build_assets/ios/Assets.xcassets.tmpl b/v3/internal/commands/updatable_build_assets/ios/Assets.xcassets.tmpl deleted file mode 100644 index 46fbb8787..000000000 --- a/v3/internal/commands/updatable_build_assets/ios/Assets.xcassets.tmpl +++ /dev/null @@ -1,116 +0,0 @@ -{ - "info" : { - "author" : "xcode", - "version" : 1 - }, - "images" : [ - { - "filename" : "icon-20@2x.png", - "idiom" : "iphone", - "scale" : "2x", - "size" : "20x20" - }, - { - "filename" : "icon-20@3x.png", - "idiom" : "iphone", - "scale" : "3x", - "size" : "20x20" - }, - { - "filename" : "icon-29@2x.png", - "idiom" : "iphone", - "scale" : "2x", - "size" : "29x29" - }, - { - "filename" : "icon-29@3x.png", - "idiom" : "iphone", - "scale" : "3x", - "size" : "29x29" - }, - { - "filename" : "icon-40@2x.png", - "idiom" : "iphone", - "scale" : "2x", - "size" : "40x40" - }, - { - "filename" : "icon-40@3x.png", - "idiom" : "iphone", - "scale" : "3x", - "size" : "40x40" - }, - { - "filename" : "icon-60@2x.png", - "idiom" : "iphone", - "scale" : "2x", - "size" : "60x60" - }, - { - "filename" : "icon-60@3x.png", - "idiom" : "iphone", - "scale" : "3x", - "size" : "60x60" - }, - { - "filename" : "icon-20.png", - "idiom" : "ipad", - "scale" : "1x", - "size" : "20x20" - }, - { - "filename" : "icon-20@2x.png", - "idiom" : "ipad", - "scale" : "2x", - "size" : "20x20" - }, - { - "filename" : "icon-29.png", - "idiom" : "ipad", - "scale" : "1x", - "size" : "29x29" - }, - { - "filename" : "icon-29@2x.png", - "idiom" : "ipad", - "scale" : "2x", - "size" : "29x29" - }, - { - "filename" : "icon-40.png", - "idiom" : "ipad", - "scale" : "1x", - "size" : "40x40" - }, - { - "filename" : "icon-40@2x.png", - "idiom" : "ipad", - "scale" : "2x", - "size" : "40x40" - }, - { - "filename" : "icon-76.png", - "idiom" : "ipad", - "scale" : "1x", - "size" : "76x76" - }, - { - "filename" : "icon-76@2x.png", - "idiom" : "ipad", - "scale" : "2x", - "size" : "76x76" - }, - { - "filename" : "icon-83.5@2x.png", - "idiom" : "ipad", - "scale" : "2x", - "size" : "83.5x83.5" - }, - { - "filename" : "icon-1024.png", - "idiom" : "ios-marketing", - "scale" : "1x", - "size" : "1024x1024" - } - ] -} \ No newline at end of file diff --git a/v3/internal/commands/updatable_build_assets/ios/Info.dev.plist.tmpl b/v3/internal/commands/updatable_build_assets/ios/Info.dev.plist.tmpl deleted file mode 100644 index 92810cb32..000000000 --- a/v3/internal/commands/updatable_build_assets/ios/Info.dev.plist.tmpl +++ /dev/null @@ -1,62 +0,0 @@ - - - - - CFBundleExecutable - {{.BinaryName}} - CFBundleIdentifier - {{.ProductIdentifier}}.dev - CFBundleName - {{.ProductName}} (Dev) - CFBundleDisplayName - {{.ProductName}} (Dev) - CFBundlePackageType - APPL - CFBundleShortVersionString - {{.ProductVersion}}-dev - CFBundleVersion - {{.ProductVersion}} - LSRequiresIPhoneOS - - MinimumOSVersion - 15.0 - UILaunchStoryboardName - LaunchScreen - UIRequiredDeviceCapabilities - - armv7 - arm64 - - UISupportedInterfaceOrientations - - UIInterfaceOrientationPortrait - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - UISupportedInterfaceOrientations~ipad - - UIInterfaceOrientationPortrait - UIInterfaceOrientationPortraitUpsideDown - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - NSAppTransportSecurity - - NSAllowsArbitraryLoads - - NSAllowsLocalNetworking - - - - WailsDevelopmentMode - - {{if .ProductCopyright}} - NSHumanReadableCopyright - {{.ProductCopyright}} - {{end}} - {{if .ProductComments}} - CFBundleGetInfoString - {{.ProductComments}} - {{end}} - - \ No newline at end of file diff --git a/v3/internal/commands/updatable_build_assets/ios/Info.plist.tmpl b/v3/internal/commands/updatable_build_assets/ios/Info.plist.tmpl deleted file mode 100644 index d4b5ca517..000000000 --- a/v3/internal/commands/updatable_build_assets/ios/Info.plist.tmpl +++ /dev/null @@ -1,59 +0,0 @@ - - - - - CFBundleExecutable - {{.BinaryName}} - CFBundleIdentifier - {{.ProductIdentifier}} - CFBundleName - {{.ProductName}} - CFBundleDisplayName - {{.ProductName}} - CFBundlePackageType - APPL - CFBundleShortVersionString - {{.ProductVersion}} - CFBundleVersion - {{.ProductVersion}} - LSRequiresIPhoneOS - - MinimumOSVersion - 15.0 - UILaunchStoryboardName - LaunchScreen - UIRequiredDeviceCapabilities - - armv7 - arm64 - - UISupportedInterfaceOrientations - - UIInterfaceOrientationPortrait - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - UISupportedInterfaceOrientations~ipad - - UIInterfaceOrientationPortrait - UIInterfaceOrientationPortraitUpsideDown - UIInterfaceOrientationLandscapeLeft - UIInterfaceOrientationLandscapeRight - - NSAppTransportSecurity - - NSAllowsArbitraryLoads - - NSAllowsLocalNetworking - - - {{if .ProductCopyright}} - NSHumanReadableCopyright - {{.ProductCopyright}} - {{end}} - {{if .ProductComments}} - CFBundleGetInfoString - {{.ProductComments}} - {{end}} - - \ No newline at end of file diff --git a/v3/internal/commands/updatable_build_assets/ios/LaunchScreen.storyboard.tmpl b/v3/internal/commands/updatable_build_assets/ios/LaunchScreen.storyboard.tmpl deleted file mode 100644 index e3e28f38c..000000000 --- a/v3/internal/commands/updatable_build_assets/ios/LaunchScreen.storyboard.tmpl +++ /dev/null @@ -1,53 +0,0 @@ - - - - - - - - - - - - - - - - - - - - {{if .ProductDescription}} - - {{end}} - - - - - - - - {{if .ProductDescription}} - - - - {{end}} - - - - - - - - - \ No newline at end of file diff --git a/v3/internal/commands/updatable_build_assets/ios/build.sh.tmpl b/v3/internal/commands/updatable_build_assets/ios/build.sh.tmpl deleted file mode 100644 index 26b0cbaf3..000000000 --- a/v3/internal/commands/updatable_build_assets/ios/build.sh.tmpl +++ /dev/null @@ -1,72 +0,0 @@ -#!/bin/bash -set -e - -# Build configuration -APP_NAME="{{.BinaryName}}" -BUNDLE_ID="{{.ProductIdentifier}}" -VERSION="{{.ProductVersion}}" -BUILD_NUMBER="{{.ProductVersion}}" -BUILD_DIR="build/ios" -TARGET="simulator" - -echo "Building iOS app: $APP_NAME" -echo "Bundle ID: $BUNDLE_ID" -echo "Version: $VERSION ($BUILD_NUMBER)" -echo "Target: $TARGET" - -# Ensure build directory exists -mkdir -p "$BUILD_DIR" - -# Determine SDK and target architecture -if [ "$TARGET" = "simulator" ]; then - SDK="iphonesimulator" - ARCH="arm64-apple-ios15.0-simulator" -elif [ "$TARGET" = "device" ]; then - SDK="iphoneos" - ARCH="arm64-apple-ios15.0" -else - echo "Unknown target: $TARGET" - exit 1 -fi - -# Get SDK path -SDK_PATH=$(xcrun --sdk $SDK --show-sdk-path) - -# Compile the application -echo "Compiling with SDK: $SDK" -xcrun -sdk $SDK clang \ - -target $ARCH \ - -isysroot "$SDK_PATH" \ - -framework Foundation \ - -framework UIKit \ - -framework WebKit \ - -framework CoreGraphics \ - -o "$BUILD_DIR/$APP_NAME" \ - "$BUILD_DIR/main.m" - -# Create app bundle -echo "Creating app bundle..." -APP_BUNDLE="$BUILD_DIR/$APP_NAME.app" -rm -rf "$APP_BUNDLE" -mkdir -p "$APP_BUNDLE" - -# Move executable -mv "$BUILD_DIR/$APP_NAME" "$APP_BUNDLE/" - -# Copy Info.plist -cp "$BUILD_DIR/Info.plist" "$APP_BUNDLE/" - -# Sign the app -echo "Signing app..." -codesign --force --sign - "$APP_BUNDLE" - -echo "Build complete: $APP_BUNDLE" - -# Deploy to simulator if requested -if [ "$TARGET" = "simulator" ]; then - echo "Deploying to simulator..." - xcrun simctl terminate booted "$BUNDLE_ID" 2>/dev/null || true - xcrun simctl install booted "$APP_BUNDLE" - xcrun simctl launch booted "$BUNDLE_ID" - echo "App launched on simulator" -fi \ No newline at end of file diff --git a/v3/internal/commands/updatable_build_assets/ios/entitlements.plist.tmpl b/v3/internal/commands/updatable_build_assets/ios/entitlements.plist.tmpl deleted file mode 100644 index cc5d9582b..000000000 --- a/v3/internal/commands/updatable_build_assets/ios/entitlements.plist.tmpl +++ /dev/null @@ -1,21 +0,0 @@ - - - - - - get-task-allow - - - - com.apple.security.app-sandbox - - - - com.apple.security.network.client - - - - com.apple.security.files.user-selected.read-only - - - \ No newline at end of file diff --git a/v3/internal/commands/updatable_build_assets/ios/project.pbxproj.tmpl b/v3/internal/commands/updatable_build_assets/ios/project.pbxproj.tmpl deleted file mode 100644 index 5c9944b24..000000000 --- a/v3/internal/commands/updatable_build_assets/ios/project.pbxproj.tmpl +++ /dev/null @@ -1,222 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = {}; - objectVersion = 56; - objects = { - -/* Begin PBXBuildFile section */ - C0DEBEEF0000000000000001 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = C0DEBEEF0000000000000002 /* main.m */; }; - C0DEBEEF00000000000000F1 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C0DEBEEF0000000000000101 /* UIKit.framework */; }; - C0DEBEEF00000000000000F2 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C0DEBEEF0000000000000102 /* Foundation.framework */; }; - C0DEBEEF00000000000000F3 /* WebKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C0DEBEEF0000000000000103 /* WebKit.framework */; }; - C0DEBEEF00000000000000F4 /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C0DEBEEF0000000000000104 /* Security.framework */; }; - C0DEBEEF00000000000000F5 /* CoreFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C0DEBEEF0000000000000105 /* CoreFoundation.framework */; }; - C0DEBEEF00000000000000F6 /* libresolv.tbd in Frameworks */ = {isa = PBXBuildFile; fileRef = C0DEBEEF0000000000000106 /* libresolv.tbd */; }; - C0DEBEEF00000000000000F7 /* {{.ProductName}}.a in Frameworks */ = {isa = PBXBuildFile; fileRef = C0DEBEEF0000000000000107 /* {{.ProductName}}.a */; }; -/* End PBXBuildFile section */ - -/* Begin PBXFileReference section */ - C0DEBEEF0000000000000002 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; - C0DEBEEF0000000000000003 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - C0DEBEEF0000000000000004 /* {{.ProductName}}.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "{{.ProductName}}.app"; sourceTree = BUILT_PRODUCTS_DIR; }; - C0DEBEEF0000000000000101 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; - C0DEBEEF0000000000000102 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; - C0DEBEEF0000000000000103 /* WebKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WebKit.framework; path = System/Library/Frameworks/WebKit.framework; sourceTree = SDKROOT; }; - C0DEBEEF0000000000000104 /* Security.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Security.framework; path = System/Library/Frameworks/Security.framework; sourceTree = SDKROOT; }; - C0DEBEEF0000000000000105 /* CoreFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreFoundation.framework; path = System/Library/Frameworks/CoreFoundation.framework; sourceTree = SDKROOT; }; - C0DEBEEF0000000000000106 /* libresolv.tbd */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.text-based-dylib-definition; name = libresolv.tbd; path = usr/lib/libresolv.tbd; sourceTree = SDKROOT; }; - C0DEBEEF0000000000000107 /* {{.ProductName}}.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = "{{.ProductName}}.a"; path = ../../../bin/{{.ProductName}}.a; sourceTree = SOURCE_ROOT; }; -/* End PBXFileReference section */ - -/* Begin PBXGroup section */ - C0DEBEEF0000000000000010 = { - isa = PBXGroup; - children = ( - C0DEBEEF0000000000000020 /* Products */, - C0DEBEEF0000000000000045 /* Frameworks */, - C0DEBEEF0000000000000030 /* main */, - ); - sourceTree = ""; - }; - C0DEBEEF0000000000000020 /* Products */ = { - isa = PBXGroup; - children = ( - C0DEBEEF0000000000000004 /* {{.ProductName}}.app */, - ); - name = Products; - sourceTree = ""; - }; - C0DEBEEF0000000000000030 /* main */ = { - isa = PBXGroup; - children = ( - C0DEBEEF0000000000000002 /* main.m */, - C0DEBEEF0000000000000003 /* Info.plist */, - ); - path = main; - sourceTree = SOURCE_ROOT; - }; - C0DEBEEF0000000000000045 /* Frameworks */ = { - isa = PBXGroup; - children = ( - C0DEBEEF0000000000000101 /* UIKit.framework */, - C0DEBEEF0000000000000102 /* Foundation.framework */, - C0DEBEEF0000000000000103 /* WebKit.framework */, - C0DEBEEF0000000000000104 /* Security.framework */, - C0DEBEEF0000000000000105 /* CoreFoundation.framework */, - C0DEBEEF0000000000000106 /* libresolv.tbd */, - C0DEBEEF0000000000000107 /* {{.ProductName}}.a */, - ); - name = Frameworks; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXNativeTarget section */ - C0DEBEEF0000000000000040 /* {{.ProductName}} */ = { - isa = PBXNativeTarget; - buildConfigurationList = C0DEBEEF0000000000000070 /* Build configuration list for PBXNativeTarget "{{.ProductName}}" */; - buildPhases = ( - C0DEBEEF0000000000000055 /* Prebuild: Wails Go Archive */, - C0DEBEEF0000000000000050 /* Sources */, - C0DEBEEF0000000000000056 /* Frameworks */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = "{{.ProductName}}"; - productName = "{{.ProductName}}"; - productReference = C0DEBEEF0000000000000004 /* {{.ProductName}}.app */; - productType = "com.apple.product-type.application"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - C0DEBEEF0000000000000060 /* Project object */ = { - isa = PBXProject; - attributes = { - LastUpgradeCheck = 1500; - ORGANIZATIONNAME = "{{.ProductCompany}}"; - TargetAttributes = { - C0DEBEEF0000000000000040 = { - CreatedOnToolsVersion = 15.0; - }; - }; - }; - buildConfigurationList = C0DEBEEF0000000000000080 /* Build configuration list for PBXProject "main" */; - compatibilityVersion = "Xcode 15.0"; - developmentRegion = en; - hasScannedForEncodings = 0; - knownRegions = ( - en, - ); - mainGroup = C0DEBEEF0000000000000010; - productRefGroup = C0DEBEEF0000000000000020 /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - C0DEBEEF0000000000000040 /* {{.ProductName}} */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXFrameworksBuildPhase section */ - C0DEBEEF0000000000000056 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - C0DEBEEF00000000000000F7 /* {{.ProductName}}.a in Frameworks */, - C0DEBEEF00000000000000F1 /* UIKit.framework in Frameworks */, - C0DEBEEF00000000000000F2 /* Foundation.framework in Frameworks */, - C0DEBEEF00000000000000F3 /* WebKit.framework in Frameworks */, - C0DEBEEF00000000000000F4 /* Security.framework in Frameworks */, - C0DEBEEF00000000000000F5 /* CoreFoundation.framework in Frameworks */, - C0DEBEEF00000000000000F6 /* libresolv.tbd in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXShellScriptBuildPhase section */ - C0DEBEEF0000000000000055 /* Prebuild: Wails Go Archive */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputFileListPaths = ( - ); - inputPaths = ( - ); - name = "Prebuild: Wails Go Archive"; - outputFileListPaths = ( - ); - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "set -e\nAPP_ROOT=\"${PROJECT_DIR}/../../..\"\nSDK_PATH=$(xcrun --sdk iphonesimulator --show-sdk-path)\nexport GOOS=ios\nexport GOARCH=arm64\nexport CGO_ENABLED=1\nexport CGO_CFLAGS=\"-isysroot ${SDK_PATH} -target arm64-apple-ios15.0-simulator -mios-simulator-version-min=15.0\"\nexport CGO_LDFLAGS=\"-isysroot ${SDK_PATH} -target arm64-apple-ios15.0-simulator\"\ncd \"${APP_ROOT}\"\n# Ensure overlay exists\nif [ ! -f build/ios/xcode/overlay.json ]; then\n wails3 ios overlay:gen -out build/ios/xcode/overlay.json -config build/config.yml || true\nfi\n# Build Go c-archive if missing or older than sources\nif [ ! -f bin/{{.ProductName}}.a ]; then\n echo \"Building Go c-archive...\"\n go build -buildmode=c-archive -overlay build/ios/xcode/overlay.json -o bin/{{.ProductName}}.a\nfi\n"; - }; -/* End PBXShellScriptBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - C0DEBEEF0000000000000050 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - C0DEBEEF0000000000000001 /* main.m in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin XCBuildConfiguration section */ - C0DEBEEF0000000000000090 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - INFOPLIST_FILE = main/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 15.0; - PRODUCT_BUNDLE_IDENTIFIER = "{{.ProductIdentifier}}"; - PRODUCT_NAME = "{{.ProductName}}"; - CODE_SIGNING_ALLOWED = NO; - SDKROOT = iphonesimulator; - }; - name = Debug; - }; - C0DEBEEF00000000000000A0 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - INFOPLIST_FILE = main/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 15.0; - PRODUCT_BUNDLE_IDENTIFIER = "{{.ProductIdentifier}}"; - PRODUCT_NAME = "{{.ProductName}}"; - CODE_SIGNING_ALLOWED = NO; - SDKROOT = iphonesimulator; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - C0DEBEEF0000000000000070 /* Build configuration list for PBXNativeTarget "{{.ProductName}}" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - C0DEBEEF0000000000000090 /* Debug */, - C0DEBEEF00000000000000A0 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Debug; - }; - C0DEBEEF0000000000000080 /* Build configuration list for PBXProject "main" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - C0DEBEEF0000000000000090 /* Debug */, - C0DEBEEF00000000000000A0 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Debug; - }; -/* End XCConfigurationList section */ - }; - rootObject = C0DEBEEF0000000000000060 /* Project object */; -} diff --git a/v3/internal/commands/updatable_build_assets/linux/desktop.tmpl b/v3/internal/commands/updatable_build_assets/linux/desktop.tmpl deleted file mode 100644 index ab22e2be4..000000000 --- a/v3/internal/commands/updatable_build_assets/linux/desktop.tmpl +++ /dev/null @@ -1,15 +0,0 @@ -[Desktop Entry] -Version=1.0 -Name={{.ProductName}} -Comment={{.ProductDescription}} -# The Exec line includes %u to pass the URL to the application -Exec=/usr/local/bin/{{.BinaryName}} %u -Terminal=false -Type=Application -Icon={{.BinaryName}} -Categories=Utility; -StartupWMClass={{.BinaryName}} - -{{if .Protocols -}} -MimeType={{range $index, $protocol := .Protocols}}x-scheme-handler/{{$protocol.Scheme}};{{end}} -{{- end}} diff --git a/v3/internal/commands/updatable_build_assets/linux/nfpm/nfpm.yaml.tmpl b/v3/internal/commands/updatable_build_assets/linux/nfpm/nfpm.yaml.tmpl deleted file mode 100644 index 06ad22120..000000000 --- a/v3/internal/commands/updatable_build_assets/linux/nfpm/nfpm.yaml.tmpl +++ /dev/null @@ -1,67 +0,0 @@ -# Feel free to remove those if you don't want/need to use them. -# Make sure to check the documentation at https://nfpm.goreleaser.com -# -# The lines below are called `modelines`. See `:help modeline` - -name: "{{.BinaryName}}" -arch: ${GOARCH} -platform: "linux" -version: "{{.ProductVersion}}" -section: "default" -priority: "extra" -maintainer: ${GIT_COMMITTER_NAME} <${GIT_COMMITTER_EMAIL}> -description: "{{.ProductDescription}}" -vendor: "{{.ProductCompany}}" -homepage: "https://wails.io" -license: "MIT" -release: "1" - -contents: - - src: "./bin/{{.BinaryName}}" - dst: "/usr/local/bin/{{.BinaryName}}" - - src: "./build/appicon.png" - dst: "/usr/share/icons/hicolor/128x128/apps/{{.BinaryName}}.png" - - src: "./build/linux/{{.BinaryName}}.desktop" - dst: "/usr/share/applications/{{.BinaryName}}.desktop" - -# Default dependencies for Debian 12/Ubuntu 22.04+ with WebKit 4.1 -depends: - - libgtk-3-0 - - libwebkit2gtk-4.1-0 - -# Distribution-specific overrides for different package formats and WebKit versions -overrides: - # RPM packages for RHEL/CentOS/AlmaLinux/Rocky Linux (WebKit 4.0) - rpm: - depends: - - gtk3 - - webkit2gtk4.1 - - # Arch Linux packages (WebKit 4.1) - archlinux: - depends: - - gtk3 - - webkit2gtk-4.1 - -# scripts section to ensure desktop database is updated after install -scripts: - postinstall: "./build/linux/nfpm/scripts/postinstall.sh" - # You can also add preremove, postremove if needed - # preremove: "./build/linux/nfpm/scripts/preremove.sh" - # postremove: "./build/linux/nfpm/scripts/postremove.sh" - -# replaces: -# - foobar -# provides: -# - bar -# depends: -# - gtk3 -# - libwebkit2gtk -# recommends: -# - whatever -# suggests: -# - something-else -# conflicts: -# - not-foo -# - not-bar -# changelog: "changelog.yaml" diff --git a/v3/internal/commands/updatable_build_assets/windows/info.json.tmpl b/v3/internal/commands/updatable_build_assets/windows/info.json.tmpl deleted file mode 100644 index c3423b2dd..000000000 --- a/v3/internal/commands/updatable_build_assets/windows/info.json.tmpl +++ /dev/null @@ -1,15 +0,0 @@ -{ - "fixed": { - "file_version": "{{.ProductVersion}}" - }, - "info": { - "0000": { - "ProductVersion": "{{.ProductVersion}}", - "CompanyName": "{{.ProductCompany}}", - "FileDescription": "{{.ProductDescription}}", - "LegalCopyright": "{{.ProductCopyright}}", - "ProductName": "{{.ProductName}}", - "Comments": "{{.ProductComments}}" - } - } -} \ No newline at end of file diff --git a/v3/internal/commands/updatable_build_assets/windows/nsis/wails_tools.nsh.tmpl b/v3/internal/commands/updatable_build_assets/windows/nsis/wails_tools.nsh.tmpl deleted file mode 100644 index b4b0c2b4e..000000000 --- a/v3/internal/commands/updatable_build_assets/windows/nsis/wails_tools.nsh.tmpl +++ /dev/null @@ -1,246 +0,0 @@ -# DO NOT EDIT - Generated automatically by `wails build` - -!include "x64.nsh" -!include "WinVer.nsh" -!include "FileFunc.nsh" - -!ifndef INFO_PROJECTNAME - !define INFO_PROJECTNAME "{{.Name}}" -!endif -!ifndef INFO_COMPANYNAME - !define INFO_COMPANYNAME "{{.ProductCompany}}" -!endif -!ifndef INFO_PRODUCTNAME - !define INFO_PRODUCTNAME "{{.ProductName}}" -!endif -!ifndef INFO_PRODUCTVERSION - !define INFO_PRODUCTVERSION "{{.ProductVersion}}" -!endif -!ifndef INFO_COPYRIGHT - !define INFO_COPYRIGHT "{{.ProductCopyright}}" -!endif -!ifndef PRODUCT_EXECUTABLE - !define PRODUCT_EXECUTABLE "${INFO_PROJECTNAME}.exe" -!endif -!ifndef UNINST_KEY_NAME - !define UNINST_KEY_NAME "${INFO_COMPANYNAME}${INFO_PRODUCTNAME}" -!endif -!define UNINST_KEY "Software\Microsoft\Windows\CurrentVersion\Uninstall\${UNINST_KEY_NAME}" - -!ifndef REQUEST_EXECUTION_LEVEL - !define REQUEST_EXECUTION_LEVEL "admin" -!endif - -RequestExecutionLevel "${REQUEST_EXECUTION_LEVEL}" - -!ifdef ARG_WAILS_AMD64_BINARY - !define SUPPORTS_AMD64 -!endif - -!ifdef ARG_WAILS_ARM64_BINARY - !define SUPPORTS_ARM64 -!endif - -!ifdef SUPPORTS_AMD64 - !ifdef SUPPORTS_ARM64 - !define ARCH "amd64_arm64" - !else - !define ARCH "amd64" - !endif -!else - !ifdef SUPPORTS_ARM64 - !define ARCH "arm64" - !else - !error "Wails: Undefined ARCH, please provide at least one of ARG_WAILS_AMD64_BINARY or ARG_WAILS_ARM64_BINARY" - !endif -!endif - -!macro wails.checkArchitecture - !ifndef WAILS_WIN10_REQUIRED - !define WAILS_WIN10_REQUIRED "This product is only supported on Windows 10 (Server 2016) and later." - !endif - - !ifndef WAILS_ARCHITECTURE_NOT_SUPPORTED - !define WAILS_ARCHITECTURE_NOT_SUPPORTED "This product can't be installed on the current Windows architecture. Supports: ${ARCH}" - !endif - - ${If} ${AtLeastWin10} - !ifdef SUPPORTS_AMD64 - ${if} ${IsNativeAMD64} - Goto ok - ${EndIf} - !endif - - !ifdef SUPPORTS_ARM64 - ${if} ${IsNativeARM64} - Goto ok - ${EndIf} - !endif - - IfSilent silentArch notSilentArch - silentArch: - SetErrorLevel 65 - Abort - notSilentArch: - MessageBox MB_OK "${WAILS_ARCHITECTURE_NOT_SUPPORTED}" - Quit - ${else} - IfSilent silentWin notSilentWin - silentWin: - SetErrorLevel 64 - Abort - notSilentWin: - MessageBox MB_OK "${WAILS_WIN10_REQUIRED}" - Quit - ${EndIf} - - ok: -!macroend - -!macro wails.files - !ifdef SUPPORTS_AMD64 - ${if} ${IsNativeAMD64} - File "/oname=${PRODUCT_EXECUTABLE}" "${ARG_WAILS_AMD64_BINARY}" - ${EndIf} - !endif - - !ifdef SUPPORTS_ARM64 - ${if} ${IsNativeARM64} - File "/oname=${PRODUCT_EXECUTABLE}" "${ARG_WAILS_ARM64_BINARY}" - ${EndIf} - !endif -!macroend - -!macro wails.writeUninstaller - WriteUninstaller "$INSTDIR\uninstall.exe" - - SetRegView 64 - WriteRegStr HKLM "${UNINST_KEY}" "Publisher" "${INFO_COMPANYNAME}" - WriteRegStr HKLM "${UNINST_KEY}" "DisplayName" "${INFO_PRODUCTNAME}" - WriteRegStr HKLM "${UNINST_KEY}" "DisplayVersion" "${INFO_PRODUCTVERSION}" - WriteRegStr HKLM "${UNINST_KEY}" "DisplayIcon" "$INSTDIR\${PRODUCT_EXECUTABLE}" - WriteRegStr HKLM "${UNINST_KEY}" "UninstallString" "$\"$INSTDIR\uninstall.exe$\"" - WriteRegStr HKLM "${UNINST_KEY}" "QuietUninstallString" "$\"$INSTDIR\uninstall.exe$\" /S" - - ${GetSize} "$INSTDIR" "/S=0K" $0 $1 $2 - IntFmt $0 "0x%08X" $0 - WriteRegDWORD HKLM "${UNINST_KEY}" "EstimatedSize" "$0" -!macroend - -!macro wails.deleteUninstaller - Delete "$INSTDIR\uninstall.exe" - - SetRegView 64 - DeleteRegKey HKLM "${UNINST_KEY}" -!macroend - -!macro wails.setShellContext - ${If} ${REQUEST_EXECUTION_LEVEL} == "admin" - SetShellVarContext all - ${else} - SetShellVarContext current - ${EndIf} -!macroend - -# Install webview2 by launching the bootstrapper -# See https://docs.microsoft.com/en-us/microsoft-edge/webview2/concepts/distribution#online-only-deployment -!macro wails.webview2runtime - !ifndef WAILS_INSTALL_WEBVIEW_DETAILPRINT - !define WAILS_INSTALL_WEBVIEW_DETAILPRINT "Installing: WebView2 Runtime" - !endif - - SetRegView 64 - # If the admin key exists and is not empty then webview2 is already installed - ReadRegStr $0 HKLM "SOFTWARE\WOW6432Node\Microsoft\EdgeUpdate\Clients\{F3017226-FE2A-4295-8BDF-00C3A9A7E4C5}" "pv" - ${If} $0 != "" - Goto ok - ${EndIf} - - ${If} ${REQUEST_EXECUTION_LEVEL} == "user" - # If the installer is run in user level, check the user specific key exists and is not empty then webview2 is already installed - ReadRegStr $0 HKCU "Software\Microsoft\EdgeUpdate\Clients\{F3017226-FE2A-4295-8BDF-00C3A9A7E4C5}" "pv" - ${If} $0 != "" - Goto ok - ${EndIf} - ${EndIf} - - SetDetailsPrint both - DetailPrint "${WAILS_INSTALL_WEBVIEW_DETAILPRINT}" - SetDetailsPrint listonly - - InitPluginsDir - CreateDirectory "$pluginsdir\webview2bootstrapper" - SetOutPath "$pluginsdir\webview2bootstrapper" - File "MicrosoftEdgeWebview2Setup.exe" - ExecWait '"$pluginsdir\webview2bootstrapper\MicrosoftEdgeWebview2Setup.exe" /silent /install' - - SetDetailsPrint both - ok: -!macroend - -# Copy of APP_ASSOCIATE and APP_UNASSOCIATE macros from here https://gist.github.com/nikku/281d0ef126dbc215dd58bfd5b3a5cd5b -!macro APP_ASSOCIATE EXT FILECLASS DESCRIPTION ICON COMMANDTEXT COMMAND - ; Backup the previously associated file class - ReadRegStr $R0 SHELL_CONTEXT "Software\Classes\.${EXT}" "" - WriteRegStr SHELL_CONTEXT "Software\Classes\.${EXT}" "${FILECLASS}_backup" "$R0" - - WriteRegStr SHELL_CONTEXT "Software\Classes\.${EXT}" "" "${FILECLASS}" - - WriteRegStr SHELL_CONTEXT "Software\Classes\${FILECLASS}" "" `${DESCRIPTION}` - WriteRegStr SHELL_CONTEXT "Software\Classes\${FILECLASS}\DefaultIcon" "" `${ICON}` - WriteRegStr SHELL_CONTEXT "Software\Classes\${FILECLASS}\shell" "" "open" - WriteRegStr SHELL_CONTEXT "Software\Classes\${FILECLASS}\shell\open" "" `${COMMANDTEXT}` - WriteRegStr SHELL_CONTEXT "Software\Classes\${FILECLASS}\shell\open\command" "" `${COMMAND}` -!macroend - -!macro APP_UNASSOCIATE EXT FILECLASS - ; Backup the previously associated file class - ReadRegStr $R0 SHELL_CONTEXT "Software\Classes\.${EXT}" `${FILECLASS}_backup` - WriteRegStr SHELL_CONTEXT "Software\Classes\.${EXT}" "" "$R0" - - DeleteRegKey SHELL_CONTEXT `Software\Classes\${FILECLASS}` -!macroend - -!macro wails.associateFiles - ; Create file associations - {{range .FileAssociations}} - !insertmacro APP_ASSOCIATE "{{.Ext}}" "{{.Name}}" "{{.Description}}" "$INSTDIR\{{.IconName}}.ico" "Open with ${INFO_PRODUCTNAME}" "$INSTDIR\${PRODUCT_EXECUTABLE} $\"%1$\"" - File "..\{{.IconName}}.ico" - {{end}} -!macroend - -!macro wails.unassociateFiles - ; Delete app associations - {{range .FileAssociations}} - !insertmacro APP_UNASSOCIATE "{{.Ext}}" "{{.Name}}" - Delete "$INSTDIR\{{.IconName}}.ico" - {{end}} -!macroend - -!macro CUSTOM_PROTOCOL_ASSOCIATE PROTOCOL DESCRIPTION ICON COMMAND - DeleteRegKey SHELL_CONTEXT "Software\Classes\${PROTOCOL}" - WriteRegStr SHELL_CONTEXT "Software\Classes\${PROTOCOL}" "" "${DESCRIPTION}" - WriteRegStr SHELL_CONTEXT "Software\Classes\${PROTOCOL}" "URL Protocol" "" - WriteRegStr SHELL_CONTEXT "Software\Classes\${PROTOCOL}\DefaultIcon" "" "${ICON}" - WriteRegStr SHELL_CONTEXT "Software\Classes\${PROTOCOL}\shell" "" "" - WriteRegStr SHELL_CONTEXT "Software\Classes\${PROTOCOL}\shell\open" "" "" - WriteRegStr SHELL_CONTEXT "Software\Classes\${PROTOCOL}\shell\open\command" "" "${COMMAND}" -!macroend - -!macro CUSTOM_PROTOCOL_UNASSOCIATE PROTOCOL - DeleteRegKey SHELL_CONTEXT "Software\Classes\${PROTOCOL}" -!macroend - -!macro wails.associateCustomProtocols - ; Create custom protocols associations - {{range .Protocols}} - !insertmacro CUSTOM_PROTOCOL_ASSOCIATE "{{.Scheme}}" "{{.Description}}" "$INSTDIR\${PRODUCT_EXECUTABLE},0" "$INSTDIR\${PRODUCT_EXECUTABLE} $\"%1$\"" - {{end}} -!macroend - -!macro wails.unassociateCustomProtocols - ; Delete app custom protocol associations - {{range .Protocols}} - !insertmacro CUSTOM_PROTOCOL_UNASSOCIATE "{{.Scheme}}" - {{end}} -!macroend \ No newline at end of file diff --git a/v3/internal/commands/updatable_build_assets/windows/wails.exe.manifest.tmpl b/v3/internal/commands/updatable_build_assets/windows/wails.exe.manifest.tmpl deleted file mode 100644 index 54fb9f41a..000000000 --- a/v3/internal/commands/updatable_build_assets/windows/wails.exe.manifest.tmpl +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - - - - - true/pm - permonitorv2,permonitor - - - - - - - - - - \ No newline at end of file diff --git a/v3/internal/commands/update_cli.go b/v3/internal/commands/update_cli.go deleted file mode 100644 index a7f51796f..000000000 --- a/v3/internal/commands/update_cli.go +++ /dev/null @@ -1,178 +0,0 @@ -package commands - -import ( - "fmt" - "os" - "os/exec" - "path/filepath" - - "github.com/pterm/pterm" - "github.com/wailsapp/wails/v3/internal/debug" - "github.com/wailsapp/wails/v3/internal/github" - "github.com/wailsapp/wails/v3/internal/term" - "github.com/wailsapp/wails/v3/internal/version" -) - -type UpdateCLIOptions struct { - NoColour bool `name:"n" description:"Disable colour output"` - PreRelease bool `name:"pre" description:"Update to the latest pre-release (eg beta)"` - Version string `name:"version" description:"Update to a specific version (eg v3.0.0)"` - Latest bool `name:"latest" description:"Install the latest stable release"` -} - -func UpdateCLI(options *UpdateCLIOptions) error { - if options.NoColour { - term.DisableColor() - } - - term.Header("Update CLI") - - // Check if this CLI has been installed from vcs - if debug.LocalModulePath != "" && !options.Latest { - v3Path := filepath.ToSlash(debug.LocalModulePath + "/v3") - term.Println("This Wails CLI has been installed from source. To update to the latest stable release, run the following commands in the `" + v3Path + "` directory:") - term.Println(" - git pull") - term.Println(" - wails3 task install") - term.Println("") - term.Println("If you want to install the latest release, please run `wails3 update cli -latest`") - return nil - } - - if options.Latest { - latestVersion, err := github.GetLatestStableRelease() - if err != nil { - return err - } - return updateToVersion(latestVersion, true, version.String()) - } - - term.Println("Checking for updates...") - - var desiredVersion *github.SemanticVersion - var err error - var valid bool - - if len(options.Version) > 0 { - // Check if this is a valid version - valid, err = github.IsValidTag(options.Version) - if err == nil { - if !valid { - err = fmt.Errorf("version '%s' is invalid", options.Version) - } else { - desiredVersion, err = github.NewSemanticVersion(options.Version) - } - } - } else { - if options.PreRelease { - desiredVersion, err = github.GetLatestPreRelease() - } else { - desiredVersion, err = github.GetLatestStableRelease() - if err != nil { - pterm.Println("") - pterm.Println("No stable release found for this major version. To update to the latest pre-release (eg beta), run:") - pterm.Println(" wails3 update cli -pre") - return nil - } - } - } - if err != nil { - return err - } - pterm.Println() - - currentVersion := version.String() - pterm.Printf(" Current Version : %s\n", currentVersion) - - if len(options.Version) > 0 { - fmt.Printf(" Desired Version : v%s\n", desiredVersion) - } else { - if options.PreRelease { - fmt.Printf(" Latest Prerelease : v%s\n", desiredVersion) - } else { - fmt.Printf(" Latest Release : v%s\n", desiredVersion) - } - } - - return updateToVersion(desiredVersion, len(options.Version) > 0, currentVersion) -} - -func updateToVersion(targetVersion *github.SemanticVersion, force bool, currentVersion string) error { - targetVersionString := "v" + targetVersion.String() - - if targetVersionString == currentVersion { - pterm.Println("\nLooks like you're up to date!") - return nil - } - - var desiredVersion string - - if !force { - compareVersion := currentVersion - - currentVersion, err := github.NewSemanticVersion(compareVersion) - if err != nil { - return err - } - - var success bool - - // Release -> Pre-Release = Massage current version to prerelease format - if targetVersion.IsPreRelease() && currentVersion.IsRelease() { - testVersion, err := github.NewSemanticVersion(compareVersion + "-0") - if err != nil { - return err - } - success, _ = targetVersion.IsGreaterThan(testVersion) - } - // Pre-Release -> Release = Massage target version to prerelease format - if targetVersion.IsRelease() && currentVersion.IsPreRelease() { - mainversion := currentVersion.MainVersion() - targetVersion, err = github.NewSemanticVersion(targetVersion.String()) - if err != nil { - return err - } - success, _ = targetVersion.IsGreaterThanOrEqual(mainversion) - } - - // Release -> Release = Standard check - if (targetVersion.IsRelease() && currentVersion.IsRelease()) || - (targetVersion.IsPreRelease() && currentVersion.IsPreRelease()) { - success, _ = targetVersion.IsGreaterThan(currentVersion) - } - - // Compare - if !success { - pterm.Println("Error: The requested version is lower than the current version.") - pterm.Printf("If this is what you really want to do, use `wails3 update cli -version %s`\n", targetVersionString) - return nil - } - - desiredVersion = "v" + targetVersion.String() - } else { - desiredVersion = "v" + targetVersion.String() - } - - pterm.Println() - pterm.Print("Installing Wails CLI " + desiredVersion + "...") - - // Run command in non module directory - homeDir, err := os.UserHomeDir() - if err != nil { - return fmt.Errorf("cannot find home directory: %w", err) - } - - cmd := exec.Command("go", "install", "github.com/wailsapp/wails/v3/cmd/wails@"+desiredVersion) - cmd.Dir = homeDir - sout, serr := cmd.CombinedOutput() - if err := cmd.Run(); err != nil { - pterm.Println("Failed.") - pterm.Error.Println(string(sout) + "\n" + serr.Error()) - return err - } - pterm.Println("Done.") - pterm.Println("\nMake sure you update your project go.mod file to use " + desiredVersion + ":") - pterm.Println(" require github.com/wailsapp/wails/v3 " + desiredVersion) - pterm.Println("\nTo view the release notes, please run `wails3 releasenotes`") - - return nil -} diff --git a/v3/internal/commands/version.go b/v3/internal/commands/version.go deleted file mode 100644 index 65bf66113..000000000 --- a/v3/internal/commands/version.go +++ /dev/null @@ -1,14 +0,0 @@ -package commands - -import ( - _ "embed" - "github.com/wailsapp/wails/v3/internal/version" -) - -type VersionOptions struct{} - -func Version(_ *VersionOptions) error { - DisableFooter = true - println(version.String()) - return nil -} diff --git a/v3/internal/commands/watcher.go b/v3/internal/commands/watcher.go deleted file mode 100644 index 13f83ad61..000000000 --- a/v3/internal/commands/watcher.go +++ /dev/null @@ -1,65 +0,0 @@ -package commands - -import ( - "github.com/atterpac/refresh/engine" - "github.com/wailsapp/wails/v3/internal/signal" - "gopkg.in/yaml.v3" - "os" -) - -type WatcherOptions struct { - Config string `description:"The config file including path" default:"."` -} - -func Watcher(options *WatcherOptions) error { - stopChan := make(chan struct{}) - - // Parse the config file - type devConfig struct { - Config engine.Config `yaml:"dev_mode"` - } - - var devconfig devConfig - - // Parse the config file - c, err := os.ReadFile(options.Config) - if err != nil { - return err - } - err = yaml.Unmarshal(c, &devconfig) - if err != nil { - return err - } - - watcherEngine, err := engine.NewEngineFromConfig(devconfig.Config) - if err != nil { - return err - } - - // Setup cleanup function that stops the engine - cleanup := func() { - watcherEngine.Stop() - } - defer cleanup() - - // Signal handler needs to notify when to stop - signalCleanup := func() { - cleanup() - stopChan <- struct{}{} - } - - signalHandler := signal.NewSignalHandler(signalCleanup) - signalHandler.ExitMessage = func(sig os.Signal) string { - return "" - } - signalHandler.Start() - - // Start the engine - err = watcherEngine.Start() - if err != nil { - return err - } - - <-stopChan - return nil -} diff --git a/v3/internal/commands/webview2/MicrosoftEdgeWebview2Setup.exe b/v3/internal/commands/webview2/MicrosoftEdgeWebview2Setup.exe deleted file mode 100644 index 89a56ec16..000000000 Binary files a/v3/internal/commands/webview2/MicrosoftEdgeWebview2Setup.exe and /dev/null differ diff --git a/v3/internal/dbus/DbusMenu.xml b/v3/internal/dbus/DbusMenu.xml deleted file mode 100644 index db6959845..000000000 --- a/v3/internal/dbus/DbusMenu.xml +++ /dev/null @@ -1,60 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/v3/internal/dbus/README.md b/v3/internal/dbus/README.md deleted file mode 100644 index d2cfce105..000000000 --- a/v3/internal/dbus/README.md +++ /dev/null @@ -1,5 +0,0 @@ -//Note that you need to have github.com/knightpp/dbus-codegen-go installed from "custom" branch - -//go:generate dbus-codegen-go -prefix org.kde -package notifier -output internal/generated/notifier/status_notifier_item.go internal/StatusNotifierItem.xml -//go:generate dbus-codegen-go -prefix com.canonical -package menu -output internal/generated/menu/dbus_menu.go internal/DbusMenu.xml - diff --git a/v3/internal/dbus/StatusNotifierItem.xml b/v3/internal/dbus/StatusNotifierItem.xml deleted file mode 100644 index 1093d3d18..000000000 --- a/v3/internal/dbus/StatusNotifierItem.xml +++ /dev/null @@ -1,85 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/v3/internal/dbus/dbus.go b/v3/internal/dbus/dbus.go deleted file mode 100644 index 4e4a3adbd..000000000 --- a/v3/internal/dbus/dbus.go +++ /dev/null @@ -1,4 +0,0 @@ -package dbus - -//go:generate dbus-codegen-go -prefix org.kde -package notifier -output notifier/status_notifier_item.go StatusNotifierItem.xml -//go:generate dbus-codegen-go -prefix com.canonical -package menu -output menu/dbus_menu.go DbusMenu.xml diff --git a/v3/internal/dbus/generate.sh b/v3/internal/dbus/generate.sh deleted file mode 100755 index 03716e522..000000000 --- a/v3/internal/dbus/generate.sh +++ /dev/null @@ -1,2 +0,0 @@ -dbus-codegen-go -prefix com.canonical -package menu -output dbus_menu.go DbusMenu.xml -dbus-codegen-go -prefix org.kde -package notifier -output status_notifier_item.go StatusNotifierItem.xml diff --git a/v3/internal/dbus/menu/.keep b/v3/internal/dbus/menu/.keep deleted file mode 100644 index e69de29bb..000000000 diff --git a/v3/internal/dbus/menu/dbus_menu.go b/v3/internal/dbus/menu/dbus_menu.go deleted file mode 100644 index cbf4fd320..000000000 --- a/v3/internal/dbus/menu/dbus_menu.go +++ /dev/null @@ -1,483 +0,0 @@ -// Code generated by dbus-codegen-go DO NOT EDIT. -package menu - -import ( - "context" - "errors" - "fmt" - "github.com/godbus/dbus/v5" - "github.com/godbus/dbus/v5/introspect" -) - -var ( - // Introspection for com.canonical.dbusmenu - IntrospectDataDbusmenu = introspect.Interface{ - Name: "com.canonical.dbusmenu", - Methods: []introspect.Method{{Name: "GetLayout", Args: []introspect.Arg{ - {Name: "parentId", Type: "i", Direction: "in"}, - {Name: "recursionDepth", Type: "i", Direction: "in"}, - {Name: "propertyNames", Type: "as", Direction: "in"}, - {Name: "revision", Type: "u", Direction: "out"}, - {Name: "layout", Type: "(ia{sv}av)", Direction: "out"}, - }}, - {Name: "GetGroupProperties", Args: []introspect.Arg{ - {Name: "ids", Type: "ai", Direction: "in"}, - {Name: "propertyNames", Type: "as", Direction: "in"}, - {Name: "properties", Type: "a(ia{sv})", Direction: "out"}, - }}, - {Name: "GetProperty", Args: []introspect.Arg{ - {Name: "id", Type: "i", Direction: "in"}, - {Name: "name", Type: "s", Direction: "in"}, - {Name: "value", Type: "v", Direction: "out"}, - }}, - {Name: "Event", Args: []introspect.Arg{ - {Name: "id", Type: "i", Direction: "in"}, - {Name: "eventId", Type: "s", Direction: "in"}, - {Name: "data", Type: "v", Direction: "in"}, - {Name: "timestamp", Type: "u", Direction: "in"}, - }}, - {Name: "EventGroup", Args: []introspect.Arg{ - {Name: "events", Type: "a(isvu)", Direction: "in"}, - {Name: "idErrors", Type: "ai", Direction: "out"}, - }}, - {Name: "AboutToShow", Args: []introspect.Arg{ - {Name: "id", Type: "i", Direction: "in"}, - {Name: "needUpdate", Type: "b", Direction: "out"}, - }}, - {Name: "AboutToShowGroup", Args: []introspect.Arg{ - {Name: "ids", Type: "ai", Direction: "in"}, - {Name: "updatesNeeded", Type: "ai", Direction: "out"}, - {Name: "idErrors", Type: "ai", Direction: "out"}, - }}, - }, - Signals: []introspect.Signal{{Name: "ItemsPropertiesUpdated", Args: []introspect.Arg{ - {Name: "updatedProps", Type: "a(ia{sv})", Direction: "out"}, - {Name: "removedProps", Type: "a(ias)", Direction: "out"}, - }}, - {Name: "LayoutUpdated", Args: []introspect.Arg{ - {Name: "revision", Type: "u", Direction: "out"}, - {Name: "parent", Type: "i", Direction: "out"}, - }}, - {Name: "ItemActivationRequested", Args: []introspect.Arg{ - {Name: "id", Type: "i", Direction: "out"}, - {Name: "timestamp", Type: "u", Direction: "out"}, - }}, - }, - Properties: []introspect.Property{{Name: "Version", Type: "u", Access: "read"}, - {Name: "TextDirection", Type: "s", Access: "read"}, - {Name: "Status", Type: "s", Access: "read"}, - {Name: "IconThemePath", Type: "as", Access: "read"}, - }, - Annotations: []introspect.Annotation{}, - } -) - -// Signal is a common interface for all signals. -type Signal interface { - Name() string - Interface() string - Sender() string - - path() dbus.ObjectPath - values() []interface{} -} - -// Emit sends the given signal to the bus. -func Emit(conn *dbus.Conn, s Signal) error { - return conn.Emit(s.path(), s.Interface()+"."+s.Name(), s.values()...) -} - -// ErrUnknownSignal is returned by LookupSignal when a signal cannot be resolved. -var ErrUnknownSignal = errors.New("unknown signal") - -// LookupSignal converts the given raw D-Bus signal with variable body -// into one with typed structured body or returns ErrUnknownSignal error. -func LookupSignal(signal *dbus.Signal) (Signal, error) { - switch signal.Name { - case InterfaceDbusmenu + "." + "ItemsPropertiesUpdated": - v0, ok := signal.Body[0].([]struct { - V0 int32 - V1 map[string]dbus.Variant - }) - if !ok { - return nil, fmt.Errorf("prop .UpdatedProps is %T, not []struct {V0 int32;V1 map[string]dbus.Variant}", signal.Body[0]) - } - v1, ok := signal.Body[1].([]struct { - V0 int32 - V1 []string - }) - if !ok { - return nil, fmt.Errorf("prop .RemovedProps is %T, not []struct {V0 int32;V1 []string}", signal.Body[1]) - } - return &Dbusmenu_ItemsPropertiesUpdatedSignal{ - sender: signal.Sender, - Path: signal.Path, - Body: &Dbusmenu_ItemsPropertiesUpdatedSignalBody{ - UpdatedProps: v0, - RemovedProps: v1, - }, - }, nil - case InterfaceDbusmenu + "." + "LayoutUpdated": - v0, ok := signal.Body[0].(uint32) - if !ok { - return nil, fmt.Errorf("prop .Revision is %T, not uint32", signal.Body[0]) - } - v1, ok := signal.Body[1].(int32) - if !ok { - return nil, fmt.Errorf("prop .Parent is %T, not int32", signal.Body[1]) - } - return &Dbusmenu_LayoutUpdatedSignal{ - sender: signal.Sender, - Path: signal.Path, - Body: &Dbusmenu_LayoutUpdatedSignalBody{ - Revision: v0, - Parent: v1, - }, - }, nil - case InterfaceDbusmenu + "." + "ItemActivationRequested": - v0, ok := signal.Body[0].(int32) - if !ok { - return nil, fmt.Errorf("prop .Id is %T, not int32", signal.Body[0]) - } - v1, ok := signal.Body[1].(uint32) - if !ok { - return nil, fmt.Errorf("prop .Timestamp is %T, not uint32", signal.Body[1]) - } - return &Dbusmenu_ItemActivationRequestedSignal{ - sender: signal.Sender, - Path: signal.Path, - Body: &Dbusmenu_ItemActivationRequestedSignalBody{ - Id: v0, - Timestamp: v1, - }, - }, nil - default: - return nil, ErrUnknownSignal - } -} - -// AddMatchSignal registers a match rule for the given signal, -// opts are appended to the automatically generated signal's rules. -func AddMatchSignal(conn *dbus.Conn, s Signal, opts ...dbus.MatchOption) error { - return conn.AddMatchSignal(append([]dbus.MatchOption{ - dbus.WithMatchInterface(s.Interface()), - dbus.WithMatchMember(s.Name()), - }, opts...)...) -} - -// RemoveMatchSignal unregisters the previously registered subscription. -func RemoveMatchSignal(conn *dbus.Conn, s Signal, opts ...dbus.MatchOption) error { - return conn.RemoveMatchSignal(append([]dbus.MatchOption{ - dbus.WithMatchInterface(s.Interface()), - dbus.WithMatchMember(s.Name()), - }, opts...)...) -} - -// Interface name constants. -const ( - InterfaceDbusmenu = "com.canonical.dbusmenu" -) - -// Dbusmenuer is com.canonical.dbusmenu interface. -type Dbusmenuer interface { - // GetLayout is com.canonical.dbusmenu.GetLayout method. - GetLayout(parentId int32, recursionDepth int32, propertyNames []string) (revision uint32, layout struct { - V0 int32 - V1 map[string]dbus.Variant - V2 []dbus.Variant - }, err *dbus.Error) - // GetGroupProperties is com.canonical.dbusmenu.GetGroupProperties method. - GetGroupProperties(ids []int32, propertyNames []string) (properties []struct { - V0 int32 - V1 map[string]dbus.Variant - }, err *dbus.Error) - // GetProperty is com.canonical.dbusmenu.GetProperty method. - GetProperty(id int32, name string) (value dbus.Variant, err *dbus.Error) - // Event is com.canonical.dbusmenu.Event method. - Event(id int32, eventId string, data dbus.Variant, timestamp uint32) (err *dbus.Error) - // EventGroup is com.canonical.dbusmenu.EventGroup method. - EventGroup(events []struct { - V0 int32 - V1 string - V2 dbus.Variant - V3 uint32 - }) (idErrors []int32, err *dbus.Error) - // AboutToShow is com.canonical.dbusmenu.AboutToShow method. - AboutToShow(id int32) (needUpdate bool, err *dbus.Error) - // AboutToShowGroup is com.canonical.dbusmenu.AboutToShowGroup method. - AboutToShowGroup(ids []int32) (updatesNeeded []int32, idErrors []int32, err *dbus.Error) -} - -// ExportDbusmenu exports the given object that implements com.canonical.dbusmenu on the bus. -func ExportDbusmenu(conn *dbus.Conn, path dbus.ObjectPath, v Dbusmenuer) error { - return conn.ExportSubtreeMethodTable(map[string]interface{}{ - "GetLayout": v.GetLayout, - "GetGroupProperties": v.GetGroupProperties, - "GetProperty": v.GetProperty, - "Event": v.Event, - "EventGroup": v.EventGroup, - "AboutToShow": v.AboutToShow, - "AboutToShowGroup": v.AboutToShowGroup, - }, path, InterfaceDbusmenu) -} - -// UnexportDbusmenu unexports com.canonical.dbusmenu interface on the named path. -func UnexportDbusmenu(conn *dbus.Conn, path dbus.ObjectPath) error { - return conn.Export(nil, path, InterfaceDbusmenu) -} - -// UnimplementedDbusmenu can be embedded to have forward compatible server implementations. -type UnimplementedDbusmenu struct{} - -func (*UnimplementedDbusmenu) iface() string { - return InterfaceDbusmenu -} - -func (*UnimplementedDbusmenu) GetLayout(parentId int32, recursionDepth int32, propertyNames []string) (revision uint32, layout struct { - V0 int32 - V1 map[string]dbus.Variant - V2 []dbus.Variant -}, err *dbus.Error) { - err = &dbus.ErrMsgUnknownMethod - return -} - -func (*UnimplementedDbusmenu) GetGroupProperties(ids []int32, propertyNames []string) (properties []struct { - V0 int32 - V1 map[string]dbus.Variant -}, err *dbus.Error) { - err = &dbus.ErrMsgUnknownMethod - return -} - -func (*UnimplementedDbusmenu) GetProperty(id int32, name string) (value dbus.Variant, err *dbus.Error) { - err = &dbus.ErrMsgUnknownMethod - return -} - -func (*UnimplementedDbusmenu) Event(id int32, eventId string, data dbus.Variant, timestamp uint32) (err *dbus.Error) { - err = &dbus.ErrMsgUnknownMethod - return -} - -func (*UnimplementedDbusmenu) EventGroup(events []struct { - V0 int32 - V1 string - V2 dbus.Variant - V3 uint32 -}) (idErrors []int32, err *dbus.Error) { - err = &dbus.ErrMsgUnknownMethod - return -} - -func (*UnimplementedDbusmenu) AboutToShow(id int32) (needUpdate bool, err *dbus.Error) { - err = &dbus.ErrMsgUnknownMethod - return -} - -func (*UnimplementedDbusmenu) AboutToShowGroup(ids []int32) (updatesNeeded []int32, idErrors []int32, err *dbus.Error) { - err = &dbus.ErrMsgUnknownMethod - return -} - -// NewDbusmenu creates and allocates com.canonical.dbusmenu. -func NewDbusmenu(object dbus.BusObject) *Dbusmenu { - return &Dbusmenu{object} -} - -// Dbusmenu implements com.canonical.dbusmenu D-Bus interface. -type Dbusmenu struct { - object dbus.BusObject -} - -// GetLayout calls com.canonical.dbusmenu.GetLayout method. -func (o *Dbusmenu) GetLayout(ctx context.Context, parentId int32, recursionDepth int32, propertyNames []string) (revision uint32, layout struct { - V0 int32 - V1 map[string]dbus.Variant - V2 []dbus.Variant -}, err error) { - err = o.object.CallWithContext(ctx, InterfaceDbusmenu+".GetLayout", 0, parentId, recursionDepth, propertyNames).Store(&revision, &layout) - return -} - -// GetGroupProperties calls com.canonical.dbusmenu.GetGroupProperties method. -func (o *Dbusmenu) GetGroupProperties(ctx context.Context, ids []int32, propertyNames []string) (properties []struct { - V0 int32 - V1 map[string]dbus.Variant -}, err error) { - err = o.object.CallWithContext(ctx, InterfaceDbusmenu+".GetGroupProperties", 0, ids, propertyNames).Store(&properties) - return -} - -// GetProperty calls com.canonical.dbusmenu.GetProperty method. -func (o *Dbusmenu) GetProperty(ctx context.Context, id int32, name string) (value dbus.Variant, err error) { - err = o.object.CallWithContext(ctx, InterfaceDbusmenu+".GetProperty", 0, id, name).Store(&value) - return -} - -// Event calls com.canonical.dbusmenu.Event method. -func (o *Dbusmenu) Event(ctx context.Context, id int32, eventId string, data dbus.Variant, timestamp uint32) (err error) { - err = o.object.CallWithContext(ctx, InterfaceDbusmenu+".Event", 0, id, eventId, data, timestamp).Store() - return -} - -// EventGroup calls com.canonical.dbusmenu.EventGroup method. -func (o *Dbusmenu) EventGroup(ctx context.Context, events []struct { - V0 int32 - V1 string - V2 dbus.Variant - V3 uint32 -}) (idErrors []int32, err error) { - err = o.object.CallWithContext(ctx, InterfaceDbusmenu+".EventGroup", 0, events).Store(&idErrors) - return -} - -// AboutToShow calls com.canonical.dbusmenu.AboutToShow method. -func (o *Dbusmenu) AboutToShow(ctx context.Context, id int32) (needUpdate bool, err error) { - err = o.object.CallWithContext(ctx, InterfaceDbusmenu+".AboutToShow", 0, id).Store(&needUpdate) - return -} - -// AboutToShowGroup calls com.canonical.dbusmenu.AboutToShowGroup method. -func (o *Dbusmenu) AboutToShowGroup(ctx context.Context, ids []int32) (updatesNeeded []int32, idErrors []int32, err error) { - err = o.object.CallWithContext(ctx, InterfaceDbusmenu+".AboutToShowGroup", 0, ids).Store(&updatesNeeded, &idErrors) - return -} - -// GetVersion gets com.canonical.dbusmenu.Version property. -func (o *Dbusmenu) GetVersion(ctx context.Context) (version uint32, err error) { - err = o.object.CallWithContext(ctx, "org.freedesktop.DBus.Properties.Get", 0, InterfaceDbusmenu, "Version").Store(&version) - return -} - -// GetTextDirection gets com.canonical.dbusmenu.TextDirection property. -func (o *Dbusmenu) GetTextDirection(ctx context.Context) (textDirection string, err error) { - err = o.object.CallWithContext(ctx, "org.freedesktop.DBus.Properties.Get", 0, InterfaceDbusmenu, "TextDirection").Store(&textDirection) - return -} - -// GetStatus gets com.canonical.dbusmenu.Status property. -func (o *Dbusmenu) GetStatus(ctx context.Context) (status string, err error) { - err = o.object.CallWithContext(ctx, "org.freedesktop.DBus.Properties.Get", 0, InterfaceDbusmenu, "Status").Store(&status) - return -} - -// GetIconThemePath gets com.canonical.dbusmenu.IconThemePath property. -func (o *Dbusmenu) GetIconThemePath(ctx context.Context) (iconThemePath []string, err error) { - err = o.object.CallWithContext(ctx, "org.freedesktop.DBus.Properties.Get", 0, InterfaceDbusmenu, "IconThemePath").Store(&iconThemePath) - return -} - -// Dbusmenu_ItemsPropertiesUpdatedSignal represents com.canonical.dbusmenu.ItemsPropertiesUpdated signal. -type Dbusmenu_ItemsPropertiesUpdatedSignal struct { - sender string - Path dbus.ObjectPath - Body *Dbusmenu_ItemsPropertiesUpdatedSignalBody -} - -// Name returns the signal's name. -func (s *Dbusmenu_ItemsPropertiesUpdatedSignal) Name() string { - return "ItemsPropertiesUpdated" -} - -// Interface returns the signal's interface. -func (s *Dbusmenu_ItemsPropertiesUpdatedSignal) Interface() string { - return InterfaceDbusmenu -} - -// Sender returns the signal's sender unique name. -func (s *Dbusmenu_ItemsPropertiesUpdatedSignal) Sender() string { - return s.sender -} - -func (s *Dbusmenu_ItemsPropertiesUpdatedSignal) path() dbus.ObjectPath { - return s.Path -} - -func (s *Dbusmenu_ItemsPropertiesUpdatedSignal) values() []interface{} { - return []interface{}{s.Body.UpdatedProps, s.Body.RemovedProps} -} - -// Dbusmenu_ItemsPropertiesUpdatedSignalBody is body container. -type Dbusmenu_ItemsPropertiesUpdatedSignalBody struct { - UpdatedProps []struct { - V0 int32 - V1 map[string]dbus.Variant - } - RemovedProps []struct { - V0 int32 - V1 []string - } -} - -// Dbusmenu_LayoutUpdatedSignal represents com.canonical.dbusmenu.LayoutUpdated signal. -type Dbusmenu_LayoutUpdatedSignal struct { - sender string - Path dbus.ObjectPath - Body *Dbusmenu_LayoutUpdatedSignalBody -} - -// Name returns the signal's name. -func (s *Dbusmenu_LayoutUpdatedSignal) Name() string { - return "LayoutUpdated" -} - -// Interface returns the signal's interface. -func (s *Dbusmenu_LayoutUpdatedSignal) Interface() string { - return InterfaceDbusmenu -} - -// Sender returns the signal's sender unique name. -func (s *Dbusmenu_LayoutUpdatedSignal) Sender() string { - return s.sender -} - -func (s *Dbusmenu_LayoutUpdatedSignal) path() dbus.ObjectPath { - return s.Path -} - -func (s *Dbusmenu_LayoutUpdatedSignal) values() []interface{} { - return []interface{}{s.Body.Revision, s.Body.Parent} -} - -// Dbusmenu_LayoutUpdatedSignalBody is body container. -type Dbusmenu_LayoutUpdatedSignalBody struct { - Revision uint32 - Parent int32 -} - -// Dbusmenu_ItemActivationRequestedSignal represents com.canonical.dbusmenu.ItemActivationRequested signal. -type Dbusmenu_ItemActivationRequestedSignal struct { - sender string - Path dbus.ObjectPath - Body *Dbusmenu_ItemActivationRequestedSignalBody -} - -// Name returns the signal's name. -func (s *Dbusmenu_ItemActivationRequestedSignal) Name() string { - return "ItemActivationRequested" -} - -// Interface returns the signal's interface. -func (s *Dbusmenu_ItemActivationRequestedSignal) Interface() string { - return InterfaceDbusmenu -} - -// Sender returns the signal's sender unique name. -func (s *Dbusmenu_ItemActivationRequestedSignal) Sender() string { - return s.sender -} - -func (s *Dbusmenu_ItemActivationRequestedSignal) path() dbus.ObjectPath { - return s.Path -} - -func (s *Dbusmenu_ItemActivationRequestedSignal) values() []interface{} { - return []interface{}{s.Body.Id, s.Body.Timestamp} -} - -// Dbusmenu_ItemActivationRequestedSignalBody is body container. -type Dbusmenu_ItemActivationRequestedSignalBody struct { - Id int32 - Timestamp uint32 -} diff --git a/v3/internal/dbus/notifier/.keep b/v3/internal/dbus/notifier/.keep deleted file mode 100644 index e69de29bb..000000000 diff --git a/v3/internal/dbus/notifier/status_notifier_item.go b/v3/internal/dbus/notifier/status_notifier_item.go deleted file mode 100644 index 998916440..000000000 --- a/v3/internal/dbus/notifier/status_notifier_item.go +++ /dev/null @@ -1,636 +0,0 @@ -// Code generated by dbus-codegen-go DO NOT EDIT. -package notifier - -import ( - "context" - "errors" - "fmt" - "github.com/godbus/dbus/v5" - "github.com/godbus/dbus/v5/introspect" -) - -var ( - // Introspection for org.kde.StatusNotifierItem - IntrospectDataStatusNotifierItem = introspect.Interface{ - Name: "org.kde.StatusNotifierItem", - Methods: []introspect.Method{{Name: "ContextMenu", Args: []introspect.Arg{ - {Name: "x", Type: "i", Direction: "in"}, - {Name: "y", Type: "i", Direction: "in"}, - }}, - {Name: "Activate", Args: []introspect.Arg{ - {Name: "x", Type: "i", Direction: "in"}, - {Name: "y", Type: "i", Direction: "in"}, - }}, - {Name: "SecondaryActivate", Args: []introspect.Arg{ - {Name: "x", Type: "i", Direction: "in"}, - {Name: "y", Type: "i", Direction: "in"}, - }}, - {Name: "Scroll", Args: []introspect.Arg{ - {Name: "delta", Type: "i", Direction: "in"}, - {Name: "orientation", Type: "s", Direction: "in"}, - }}, - }, - Signals: []introspect.Signal{{Name: "NewTitle"}, - {Name: "NewIcon"}, - {Name: "NewAttentionIcon"}, - {Name: "NewOverlayIcon"}, - {Name: "NewStatus", Args: []introspect.Arg{ - {Name: "status", Type: "s", Direction: ""}, - }}, - {Name: "NewIconThemePath", Args: []introspect.Arg{ - {Name: "icon_theme_path", Type: "s", Direction: "out"}, - }}, - {Name: "NewMenu"}, - }, - Properties: []introspect.Property{{Name: "Category", Type: "s", Access: "read"}, - {Name: "Id", Type: "s", Access: "read"}, - {Name: "Title", Type: "s", Access: "read"}, - {Name: "Status", Type: "s", Access: "read"}, - {Name: "WindowId", Type: "i", Access: "read"}, - {Name: "IconThemePath", Type: "s", Access: "read"}, - {Name: "Menu", Type: "o", Access: "read"}, - {Name: "ItemIsMenu", Type: "b", Access: "read"}, - {Name: "IconName", Type: "s", Access: "read"}, - {Name: "IconPixmap", Type: "a(iiay)", Access: "read", Annotations: []introspect.Annotation{ - {Name: "org.qtproject.QtDBus.QtTypeName", Value: "KDbusImageVector"}, - }}, - {Name: "OverlayIconName", Type: "s", Access: "read"}, - {Name: "OverlayIconPixmap", Type: "a(iiay)", Access: "read", Annotations: []introspect.Annotation{ - {Name: "org.qtproject.QtDBus.QtTypeName", Value: "KDbusImageVector"}, - }}, - {Name: "AttentionIconName", Type: "s", Access: "read"}, - {Name: "AttentionIconPixmap", Type: "a(iiay)", Access: "read", Annotations: []introspect.Annotation{ - {Name: "org.qtproject.QtDBus.QtTypeName", Value: "KDbusImageVector"}, - }}, - {Name: "AttentionMovieName", Type: "s", Access: "read"}, - {Name: "ToolTip", Type: "(sa(iiay)ss)", Access: "read", Annotations: []introspect.Annotation{ - {Name: "org.qtproject.QtDBus.QtTypeName", Value: "KDbusToolTipStruct"}, - }}, - }, - Annotations: []introspect.Annotation{}, - } -) - -// Signal is a common interface for all signals. -type Signal interface { - Name() string - Interface() string - Sender() string - - path() dbus.ObjectPath - values() []interface{} -} - -// Emit sends the given signal to the bus. -func Emit(conn *dbus.Conn, s Signal) error { - return conn.Emit(s.path(), s.Interface()+"."+s.Name(), s.values()...) -} - -// ErrUnknownSignal is returned by LookupSignal when a signal cannot be resolved. -var ErrUnknownSignal = errors.New("unknown signal") - -// LookupSignal converts the given raw D-Bus signal with variable body -// into one with typed structured body or returns ErrUnknownSignal error. -func LookupSignal(signal *dbus.Signal) (Signal, error) { - switch signal.Name { - case InterfaceStatusNotifierItem + "." + "NewTitle": - return &StatusNotifierItem_NewTitleSignal{ - sender: signal.Sender, - Path: signal.Path, - Body: &StatusNotifierItem_NewTitleSignalBody{}, - }, nil - case InterfaceStatusNotifierItem + "." + "NewIcon": - return &StatusNotifierItem_NewIconSignal{ - sender: signal.Sender, - Path: signal.Path, - Body: &StatusNotifierItem_NewIconSignalBody{}, - }, nil - case InterfaceStatusNotifierItem + "." + "NewAttentionIcon": - return &StatusNotifierItem_NewAttentionIconSignal{ - sender: signal.Sender, - Path: signal.Path, - Body: &StatusNotifierItem_NewAttentionIconSignalBody{}, - }, nil - case InterfaceStatusNotifierItem + "." + "NewOverlayIcon": - return &StatusNotifierItem_NewOverlayIconSignal{ - sender: signal.Sender, - Path: signal.Path, - Body: &StatusNotifierItem_NewOverlayIconSignalBody{}, - }, nil - case InterfaceStatusNotifierItem + "." + "NewStatus": - v0, ok := signal.Body[0].(string) - if !ok { - return nil, fmt.Errorf("prop .Status is %T, not string", signal.Body[0]) - } - return &StatusNotifierItem_NewStatusSignal{ - sender: signal.Sender, - Path: signal.Path, - Body: &StatusNotifierItem_NewStatusSignalBody{ - Status: v0, - }, - }, nil - case InterfaceStatusNotifierItem + "." + "NewIconThemePath": - v0, ok := signal.Body[0].(string) - if !ok { - return nil, fmt.Errorf("prop .IconThemePath is %T, not string", signal.Body[0]) - } - return &StatusNotifierItem_NewIconThemePathSignal{ - sender: signal.Sender, - Path: signal.Path, - Body: &StatusNotifierItem_NewIconThemePathSignalBody{ - IconThemePath: v0, - }, - }, nil - case InterfaceStatusNotifierItem + "." + "NewMenu": - return &StatusNotifierItem_NewMenuSignal{ - sender: signal.Sender, - Path: signal.Path, - Body: &StatusNotifierItem_NewMenuSignalBody{}, - }, nil - default: - return nil, ErrUnknownSignal - } -} - -// AddMatchSignal registers a match rule for the given signal, -// opts are appended to the automatically generated signal's rules. -func AddMatchSignal(conn *dbus.Conn, s Signal, opts ...dbus.MatchOption) error { - return conn.AddMatchSignal(append([]dbus.MatchOption{ - dbus.WithMatchInterface(s.Interface()), - dbus.WithMatchMember(s.Name()), - }, opts...)...) -} - -// RemoveMatchSignal unregisters the previously registered subscription. -func RemoveMatchSignal(conn *dbus.Conn, s Signal, opts ...dbus.MatchOption) error { - return conn.RemoveMatchSignal(append([]dbus.MatchOption{ - dbus.WithMatchInterface(s.Interface()), - dbus.WithMatchMember(s.Name()), - }, opts...)...) -} - -// Interface name constants. -const ( - InterfaceStatusNotifierItem = "org.kde.StatusNotifierItem" -) - -// StatusNotifierItemer is org.kde.StatusNotifierItem interface. -type StatusNotifierItemer interface { - // ContextMenu is org.kde.StatusNotifierItem.ContextMenu method. - ContextMenu(x int32, y int32) (err *dbus.Error) - // Activate is org.kde.StatusNotifierItem.Activate method. - Activate(x int32, y int32) (err *dbus.Error) - // SecondaryActivate is org.kde.StatusNotifierItem.SecondaryActivate method. - SecondaryActivate(x int32, y int32) (err *dbus.Error) - // Scroll is org.kde.StatusNotifierItem.Scroll method. - Scroll(delta int32, orientation string) (err *dbus.Error) -} - -// ExportStatusNotifierItem exports the given object that implements org.kde.StatusNotifierItem on the bus. -func ExportStatusNotifierItem(conn *dbus.Conn, path dbus.ObjectPath, v StatusNotifierItemer) error { - return conn.ExportSubtreeMethodTable(map[string]interface{}{ - "ContextMenu": v.ContextMenu, - "Activate": v.Activate, - "SecondaryActivate": v.SecondaryActivate, - "Scroll": v.Scroll, - }, path, InterfaceStatusNotifierItem) -} - -// UnexportStatusNotifierItem unexports org.kde.StatusNotifierItem interface on the named path. -func UnexportStatusNotifierItem(conn *dbus.Conn, path dbus.ObjectPath) error { - return conn.Export(nil, path, InterfaceStatusNotifierItem) -} - -// UnimplementedStatusNotifierItem can be embedded to have forward compatible server implementations. -type UnimplementedStatusNotifierItem struct{} - -func (*UnimplementedStatusNotifierItem) iface() string { - return InterfaceStatusNotifierItem -} - -func (*UnimplementedStatusNotifierItem) ContextMenu(x int32, y int32) (err *dbus.Error) { - err = &dbus.ErrMsgUnknownMethod - return -} - -func (*UnimplementedStatusNotifierItem) Activate(x int32, y int32) (err *dbus.Error) { - err = &dbus.ErrMsgUnknownMethod - return -} - -func (*UnimplementedStatusNotifierItem) SecondaryActivate(x int32, y int32) (err *dbus.Error) { - err = &dbus.ErrMsgUnknownMethod - return -} - -func (*UnimplementedStatusNotifierItem) Scroll(delta int32, orientation string) (err *dbus.Error) { - err = &dbus.ErrMsgUnknownMethod - return -} - -// NewStatusNotifierItem creates and allocates org.kde.StatusNotifierItem. -func NewStatusNotifierItem(object dbus.BusObject) *StatusNotifierItem { - return &StatusNotifierItem{object} -} - -// StatusNotifierItem implements org.kde.StatusNotifierItem D-Bus interface. -type StatusNotifierItem struct { - object dbus.BusObject -} - -// ContextMenu calls org.kde.StatusNotifierItem.ContextMenu method. -func (o *StatusNotifierItem) ContextMenu(ctx context.Context, x int32, y int32) (err error) { - err = o.object.CallWithContext(ctx, InterfaceStatusNotifierItem+".ContextMenu", 0, x, y).Store() - return -} - -// Activate calls org.kde.StatusNotifierItem.Activate method. -func (o *StatusNotifierItem) Activate(ctx context.Context, x int32, y int32) (err error) { - err = o.object.CallWithContext(ctx, InterfaceStatusNotifierItem+".Activate", 0, x, y).Store() - return -} - -// SecondaryActivate calls org.kde.StatusNotifierItem.SecondaryActivate method. -func (o *StatusNotifierItem) SecondaryActivate(ctx context.Context, x int32, y int32) (err error) { - err = o.object.CallWithContext(ctx, InterfaceStatusNotifierItem+".SecondaryActivate", 0, x, y).Store() - return -} - -// Scroll calls org.kde.StatusNotifierItem.Scroll method. -func (o *StatusNotifierItem) Scroll(ctx context.Context, delta int32, orientation string) (err error) { - err = o.object.CallWithContext(ctx, InterfaceStatusNotifierItem+".Scroll", 0, delta, orientation).Store() - return -} - -// GetCategory gets org.kde.StatusNotifierItem.Category property. -func (o *StatusNotifierItem) GetCategory(ctx context.Context) (category string, err error) { - err = o.object.CallWithContext(ctx, "org.freedesktop.DBus.Properties.Get", 0, InterfaceStatusNotifierItem, "Category").Store(&category) - return -} - -// GetId gets org.kde.StatusNotifierItem.Id property. -func (o *StatusNotifierItem) GetId(ctx context.Context) (id string, err error) { - err = o.object.CallWithContext(ctx, "org.freedesktop.DBus.Properties.Get", 0, InterfaceStatusNotifierItem, "Id").Store(&id) - return -} - -// GetTitle gets org.kde.StatusNotifierItem.Title property. -func (o *StatusNotifierItem) GetTitle(ctx context.Context) (title string, err error) { - err = o.object.CallWithContext(ctx, "org.freedesktop.DBus.Properties.Get", 0, InterfaceStatusNotifierItem, "Title").Store(&title) - return -} - -// GetStatus gets org.kde.StatusNotifierItem.Status property. -func (o *StatusNotifierItem) GetStatus(ctx context.Context) (status string, err error) { - err = o.object.CallWithContext(ctx, "org.freedesktop.DBus.Properties.Get", 0, InterfaceStatusNotifierItem, "Status").Store(&status) - return -} - -// GetWindowId gets org.kde.StatusNotifierItem.WindowId property. -func (o *StatusNotifierItem) GetWindowId(ctx context.Context) (windowId int32, err error) { - err = o.object.CallWithContext(ctx, "org.freedesktop.DBus.Properties.Get", 0, InterfaceStatusNotifierItem, "WindowId").Store(&windowId) - return -} - -// GetIconThemePath gets org.kde.StatusNotifierItem.IconThemePath property. -func (o *StatusNotifierItem) GetIconThemePath(ctx context.Context) (iconThemePath string, err error) { - err = o.object.CallWithContext(ctx, "org.freedesktop.DBus.Properties.Get", 0, InterfaceStatusNotifierItem, "IconThemePath").Store(&iconThemePath) - return -} - -// GetMenu gets org.kde.StatusNotifierItem.Menu property. -func (o *StatusNotifierItem) GetMenu(ctx context.Context) (menu dbus.ObjectPath, err error) { - err = o.object.CallWithContext(ctx, "org.freedesktop.DBus.Properties.Get", 0, InterfaceStatusNotifierItem, "Menu").Store(&menu) - return -} - -// GetItemIsMenu gets org.kde.StatusNotifierItem.ItemIsMenu property. -func (o *StatusNotifierItem) GetItemIsMenu(ctx context.Context) (itemIsMenu bool, err error) { - err = o.object.CallWithContext(ctx, "org.freedesktop.DBus.Properties.Get", 0, InterfaceStatusNotifierItem, "ItemIsMenu").Store(&itemIsMenu) - return -} - -// GetIconName gets org.kde.StatusNotifierItem.IconName property. -func (o *StatusNotifierItem) GetIconName(ctx context.Context) (iconName string, err error) { - err = o.object.CallWithContext(ctx, "org.freedesktop.DBus.Properties.Get", 0, InterfaceStatusNotifierItem, "IconName").Store(&iconName) - return -} - -// GetIconPixmap gets org.kde.StatusNotifierItem.IconPixmap property. -// -// Annotations: -// -// @org.qtproject.QtDBus.QtTypeName = KDbusImageVector -func (o *StatusNotifierItem) GetIconPixmap(ctx context.Context) (iconPixmap []struct { - V0 int32 - V1 int32 - V2 []byte -}, err error) { - err = o.object.CallWithContext(ctx, "org.freedesktop.DBus.Properties.Get", 0, InterfaceStatusNotifierItem, "IconPixmap").Store(&iconPixmap) - return -} - -// GetOverlayIconName gets org.kde.StatusNotifierItem.OverlayIconName property. -func (o *StatusNotifierItem) GetOverlayIconName(ctx context.Context) (overlayIconName string, err error) { - err = o.object.CallWithContext(ctx, "org.freedesktop.DBus.Properties.Get", 0, InterfaceStatusNotifierItem, "OverlayIconName").Store(&overlayIconName) - return -} - -// GetOverlayIconPixmap gets org.kde.StatusNotifierItem.OverlayIconPixmap property. -// -// Annotations: -// -// @org.qtproject.QtDBus.QtTypeName = KDbusImageVector -func (o *StatusNotifierItem) GetOverlayIconPixmap(ctx context.Context) (overlayIconPixmap []struct { - V0 int32 - V1 int32 - V2 []byte -}, err error) { - err = o.object.CallWithContext(ctx, "org.freedesktop.DBus.Properties.Get", 0, InterfaceStatusNotifierItem, "OverlayIconPixmap").Store(&overlayIconPixmap) - return -} - -// GetAttentionIconName gets org.kde.StatusNotifierItem.AttentionIconName property. -func (o *StatusNotifierItem) GetAttentionIconName(ctx context.Context) (attentionIconName string, err error) { - err = o.object.CallWithContext(ctx, "org.freedesktop.DBus.Properties.Get", 0, InterfaceStatusNotifierItem, "AttentionIconName").Store(&attentionIconName) - return -} - -// GetAttentionIconPixmap gets org.kde.StatusNotifierItem.AttentionIconPixmap property. -// -// Annotations: -// -// @org.qtproject.QtDBus.QtTypeName = KDbusImageVector -func (o *StatusNotifierItem) GetAttentionIconPixmap(ctx context.Context) (attentionIconPixmap []struct { - V0 int32 - V1 int32 - V2 []byte -}, err error) { - err = o.object.CallWithContext(ctx, "org.freedesktop.DBus.Properties.Get", 0, InterfaceStatusNotifierItem, "AttentionIconPixmap").Store(&attentionIconPixmap) - return -} - -// GetAttentionMovieName gets org.kde.StatusNotifierItem.AttentionMovieName property. -func (o *StatusNotifierItem) GetAttentionMovieName(ctx context.Context) (attentionMovieName string, err error) { - err = o.object.CallWithContext(ctx, "org.freedesktop.DBus.Properties.Get", 0, InterfaceStatusNotifierItem, "AttentionMovieName").Store(&attentionMovieName) - return -} - -// GetToolTip gets org.kde.StatusNotifierItem.ToolTip property. -// -// Annotations: -// -// @org.qtproject.QtDBus.QtTypeName = KDbusToolTipStruct -func (o *StatusNotifierItem) GetToolTip(ctx context.Context) (toolTip struct { - V0 string - V1 []struct { - V0 int32 - V1 int32 - V2 []byte - } - V2 string - V3 string -}, err error) { - err = o.object.CallWithContext(ctx, "org.freedesktop.DBus.Properties.Get", 0, InterfaceStatusNotifierItem, "ToolTip").Store(&toolTip) - return -} - -// StatusNotifierItem_NewTitleSignal represents org.kde.StatusNotifierItem.NewTitle signal. -type StatusNotifierItem_NewTitleSignal struct { - sender string - Path dbus.ObjectPath - Body *StatusNotifierItem_NewTitleSignalBody -} - -// Name returns the signal's name. -func (s *StatusNotifierItem_NewTitleSignal) Name() string { - return "NewTitle" -} - -// Interface returns the signal's interface. -func (s *StatusNotifierItem_NewTitleSignal) Interface() string { - return InterfaceStatusNotifierItem -} - -// Sender returns the signal's sender unique name. -func (s *StatusNotifierItem_NewTitleSignal) Sender() string { - return s.sender -} - -func (s *StatusNotifierItem_NewTitleSignal) path() dbus.ObjectPath { - return s.Path -} - -func (s *StatusNotifierItem_NewTitleSignal) values() []interface{} { - return []interface{}{} -} - -// StatusNotifierItem_NewTitleSignalBody is body container. -type StatusNotifierItem_NewTitleSignalBody struct { -} - -// StatusNotifierItem_NewIconSignal represents org.kde.StatusNotifierItem.NewIcon signal. -type StatusNotifierItem_NewIconSignal struct { - sender string - Path dbus.ObjectPath - Body *StatusNotifierItem_NewIconSignalBody -} - -// Name returns the signal's name. -func (s *StatusNotifierItem_NewIconSignal) Name() string { - return "NewIcon" -} - -// Interface returns the signal's interface. -func (s *StatusNotifierItem_NewIconSignal) Interface() string { - return InterfaceStatusNotifierItem -} - -// Sender returns the signal's sender unique name. -func (s *StatusNotifierItem_NewIconSignal) Sender() string { - return s.sender -} - -func (s *StatusNotifierItem_NewIconSignal) path() dbus.ObjectPath { - return s.Path -} - -func (s *StatusNotifierItem_NewIconSignal) values() []interface{} { - return []interface{}{} -} - -// StatusNotifierItem_NewIconSignalBody is body container. -type StatusNotifierItem_NewIconSignalBody struct { -} - -// StatusNotifierItem_NewAttentionIconSignal represents org.kde.StatusNotifierItem.NewAttentionIcon signal. -type StatusNotifierItem_NewAttentionIconSignal struct { - sender string - Path dbus.ObjectPath - Body *StatusNotifierItem_NewAttentionIconSignalBody -} - -// Name returns the signal's name. -func (s *StatusNotifierItem_NewAttentionIconSignal) Name() string { - return "NewAttentionIcon" -} - -// Interface returns the signal's interface. -func (s *StatusNotifierItem_NewAttentionIconSignal) Interface() string { - return InterfaceStatusNotifierItem -} - -// Sender returns the signal's sender unique name. -func (s *StatusNotifierItem_NewAttentionIconSignal) Sender() string { - return s.sender -} - -func (s *StatusNotifierItem_NewAttentionIconSignal) path() dbus.ObjectPath { - return s.Path -} - -func (s *StatusNotifierItem_NewAttentionIconSignal) values() []interface{} { - return []interface{}{} -} - -// StatusNotifierItem_NewAttentionIconSignalBody is body container. -type StatusNotifierItem_NewAttentionIconSignalBody struct { -} - -// StatusNotifierItem_NewOverlayIconSignal represents org.kde.StatusNotifierItem.NewOverlayIcon signal. -type StatusNotifierItem_NewOverlayIconSignal struct { - sender string - Path dbus.ObjectPath - Body *StatusNotifierItem_NewOverlayIconSignalBody -} - -// Name returns the signal's name. -func (s *StatusNotifierItem_NewOverlayIconSignal) Name() string { - return "NewOverlayIcon" -} - -// Interface returns the signal's interface. -func (s *StatusNotifierItem_NewOverlayIconSignal) Interface() string { - return InterfaceStatusNotifierItem -} - -// Sender returns the signal's sender unique name. -func (s *StatusNotifierItem_NewOverlayIconSignal) Sender() string { - return s.sender -} - -func (s *StatusNotifierItem_NewOverlayIconSignal) path() dbus.ObjectPath { - return s.Path -} - -func (s *StatusNotifierItem_NewOverlayIconSignal) values() []interface{} { - return []interface{}{} -} - -// StatusNotifierItem_NewOverlayIconSignalBody is body container. -type StatusNotifierItem_NewOverlayIconSignalBody struct { -} - -// StatusNotifierItem_NewStatusSignal represents org.kde.StatusNotifierItem.NewStatus signal. -type StatusNotifierItem_NewStatusSignal struct { - sender string - Path dbus.ObjectPath - Body *StatusNotifierItem_NewStatusSignalBody -} - -// Name returns the signal's name. -func (s *StatusNotifierItem_NewStatusSignal) Name() string { - return "NewStatus" -} - -// Interface returns the signal's interface. -func (s *StatusNotifierItem_NewStatusSignal) Interface() string { - return InterfaceStatusNotifierItem -} - -// Sender returns the signal's sender unique name. -func (s *StatusNotifierItem_NewStatusSignal) Sender() string { - return s.sender -} - -func (s *StatusNotifierItem_NewStatusSignal) path() dbus.ObjectPath { - return s.Path -} - -func (s *StatusNotifierItem_NewStatusSignal) values() []interface{} { - return []interface{}{s.Body.Status} -} - -// StatusNotifierItem_NewStatusSignalBody is body container. -type StatusNotifierItem_NewStatusSignalBody struct { - Status string -} - -// StatusNotifierItem_NewIconThemePathSignal represents org.kde.StatusNotifierItem.NewIconThemePath signal. -type StatusNotifierItem_NewIconThemePathSignal struct { - sender string - Path dbus.ObjectPath - Body *StatusNotifierItem_NewIconThemePathSignalBody -} - -// Name returns the signal's name. -func (s *StatusNotifierItem_NewIconThemePathSignal) Name() string { - return "NewIconThemePath" -} - -// Interface returns the signal's interface. -func (s *StatusNotifierItem_NewIconThemePathSignal) Interface() string { - return InterfaceStatusNotifierItem -} - -// Sender returns the signal's sender unique name. -func (s *StatusNotifierItem_NewIconThemePathSignal) Sender() string { - return s.sender -} - -func (s *StatusNotifierItem_NewIconThemePathSignal) path() dbus.ObjectPath { - return s.Path -} - -func (s *StatusNotifierItem_NewIconThemePathSignal) values() []interface{} { - return []interface{}{s.Body.IconThemePath} -} - -// StatusNotifierItem_NewIconThemePathSignalBody is body container. -type StatusNotifierItem_NewIconThemePathSignalBody struct { - IconThemePath string -} - -// StatusNotifierItem_NewMenuSignal represents org.kde.StatusNotifierItem.NewMenu signal. -type StatusNotifierItem_NewMenuSignal struct { - sender string - Path dbus.ObjectPath - Body *StatusNotifierItem_NewMenuSignalBody -} - -// Name returns the signal's name. -func (s *StatusNotifierItem_NewMenuSignal) Name() string { - return "NewMenu" -} - -// Interface returns the signal's interface. -func (s *StatusNotifierItem_NewMenuSignal) Interface() string { - return InterfaceStatusNotifierItem -} - -// Sender returns the signal's sender unique name. -func (s *StatusNotifierItem_NewMenuSignal) Sender() string { - return s.sender -} - -func (s *StatusNotifierItem_NewMenuSignal) path() dbus.ObjectPath { - return s.Path -} - -func (s *StatusNotifierItem_NewMenuSignal) values() []interface{} { - return []interface{}{} -} - -// StatusNotifierItem_NewMenuSignalBody is body container. -type StatusNotifierItem_NewMenuSignalBody struct { -} diff --git a/v3/internal/debug/debug.go b/v3/internal/debug/debug.go deleted file mode 100644 index 394688ce7..000000000 --- a/v3/internal/debug/debug.go +++ /dev/null @@ -1,42 +0,0 @@ -package debug - -import ( - "os" - "path/filepath" - "runtime" -) - -var LocalModulePath = "" - -func init() { - // Check if .git exists in the relative directory from here: ../../.. - // If it does, we are in a local build - gitDir := RelativePath("..", "..", "..", ".git") - if _, err := os.Stat(gitDir); err == nil { - modulePath := RelativePath("..", "..", "..") - LocalModulePath, _ = filepath.Abs(modulePath) - } -} - -// RelativePath returns a qualified path created by joining the -// directory of the calling file and the given relative path. -func RelativePath(relativepath string, optionalpaths ...string) string { - _, thisFile, _, _ := runtime.Caller(1) - localDir := filepath.Dir(thisFile) - - // If we have optional paths, join them to the relativepath - if len(optionalpaths) > 0 { - paths := []string{relativepath} - paths = append(paths, optionalpaths...) - relativepath = filepath.Join(paths...) - } - result, err := filepath.Abs(filepath.Join(localDir, relativepath)) - if err != nil { - // I'm allowing this for 1 reason only: It's fatal if the path - // supplied is wrong as it's only used internally in Wails. If we get - // that path wrong, we should know about it immediately. The other reason is - // that it cuts down a ton of unnecassary error handling. - panic(err) - } - return result -} diff --git a/v3/internal/defaults/defaults.go b/v3/internal/defaults/defaults.go deleted file mode 100644 index 69e99f3e6..000000000 --- a/v3/internal/defaults/defaults.go +++ /dev/null @@ -1,219 +0,0 @@ -// Package defaults provides functionality for loading and saving global default settings -// for Wails projects. Settings are stored in ~/.config/wails/defaults.yaml -package defaults - -import ( - "os" - "path/filepath" - "time" - - "gopkg.in/yaml.v3" -) - -// GlobalDefaults represents the user's default project settings -// These are stored in ~/.config/wails/defaults.yaml and used when creating new projects -type GlobalDefaults struct { - // Author information - Author AuthorDefaults `json:"author" yaml:"author"` - - // Default project settings - Project ProjectDefaults `json:"project" yaml:"project"` -} - -// AuthorDefaults contains the author's information -type AuthorDefaults struct { - Name string `json:"name" yaml:"name"` - Company string `json:"company" yaml:"company"` -} - -// ProjectDefaults contains default project settings -type ProjectDefaults struct { - // ProductIdentifierPrefix is the prefix for app identifiers (e.g., "com.mycompany") - ProductIdentifierPrefix string `json:"productIdentifierPrefix" yaml:"productIdentifierPrefix"` - - // DefaultTemplate is the default frontend template to use - DefaultTemplate string `json:"defaultTemplate" yaml:"defaultTemplate"` - - // Copyright template - can include {year} and {company} placeholders - CopyrightTemplate string `json:"copyrightTemplate" yaml:"copyrightTemplate"` - - // Description template for new projects - can include {name} placeholder - DescriptionTemplate string `json:"descriptionTemplate" yaml:"descriptionTemplate"` - - // Default product version for new projects - DefaultVersion string `json:"defaultVersion" yaml:"defaultVersion"` -} - -// Default returns sensible defaults for first-time users -func Default() GlobalDefaults { - return GlobalDefaults{ - Author: AuthorDefaults{ - Name: "", - Company: "", - }, - Project: ProjectDefaults{ - ProductIdentifierPrefix: "com.example", - DefaultTemplate: "vanilla", - CopyrightTemplate: "© {year}, {company}", - DescriptionTemplate: "A {name} application", - DefaultVersion: "0.1.0", - }, - } -} - -// GetConfigDir returns the path to the Wails config directory -func GetConfigDir() (string, error) { - // Use XDG_CONFIG_HOME if set, otherwise use ~/.config - configHome := os.Getenv("XDG_CONFIG_HOME") - if configHome == "" { - homeDir, err := os.UserHomeDir() - if err != nil { - return "", err - } - configHome = filepath.Join(homeDir, ".config") - } - return filepath.Join(configHome, "wails"), nil -} - -// GetDefaultsPath returns the path to the defaults.yaml file -func GetDefaultsPath() (string, error) { - configDir, err := GetConfigDir() - if err != nil { - return "", err - } - return filepath.Join(configDir, "defaults.yaml"), nil -} - -// Load loads the global defaults from the config file -// Returns default values if the file doesn't exist -func Load() (GlobalDefaults, error) { - defaults := Default() - - path, err := GetDefaultsPath() - if err != nil { - return defaults, err - } - - data, err := os.ReadFile(path) - if err != nil { - if os.IsNotExist(err) { - return defaults, nil - } - return defaults, err - } - - if err := yaml.Unmarshal(data, &defaults); err != nil { - return Default(), err - } - - return defaults, nil -} - -// Save saves the global defaults to the config file -func Save(defaults GlobalDefaults) error { - path, err := GetDefaultsPath() - if err != nil { - return err - } - - // Ensure the config directory exists - configDir := filepath.Dir(path) - if err := os.MkdirAll(configDir, 0755); err != nil { - return err - } - - data, err := yaml.Marshal(&defaults) - if err != nil { - return err - } - - return os.WriteFile(path, data, 0644) -} - -// GenerateCopyright generates a copyright string from the template -func (d *GlobalDefaults) GenerateCopyright() string { - template := d.Project.CopyrightTemplate - if template == "" { - template = "© {year}, {company}" - } - - year := time.Now().Format("2006") - company := d.Author.Company - if company == "" { - company = "My Company" - } - - result := template - result = replaceAll(result, "{year}", year) - result = replaceAll(result, "{company}", company) - return result -} - -// GenerateProductIdentifier generates a product identifier from prefix and project name -func (d *GlobalDefaults) GenerateProductIdentifier(projectName string) string { - prefix := d.Project.ProductIdentifierPrefix - if prefix == "" { - prefix = "com.example" - } - return prefix + "." + sanitizeIdentifier(projectName) -} - -// GenerateDescription generates a description string from the template -func (d *GlobalDefaults) GenerateDescription(projectName string) string { - template := d.Project.DescriptionTemplate - if template == "" { - template = "A {name} application" - } - return replaceAll(template, "{name}", projectName) -} - -// GetDefaultVersion returns the default version or the fallback -func (d *GlobalDefaults) GetDefaultVersion() string { - if d.Project.DefaultVersion != "" { - return d.Project.DefaultVersion - } - return "0.1.0" -} - -// replaceAll replaces all occurrences of old with new in s -func replaceAll(s, old, new string) string { - result := s - for { - newResult := replaceOnce(result, old, new) - if newResult == result { - break - } - result = newResult - } - return result -} - -func replaceOnce(s, old, new string) string { - for i := 0; i <= len(s)-len(old); i++ { - if s[i:i+len(old)] == old { - return s[:i] + new + s[i+len(old):] - } - } - return s -} - -// sanitizeIdentifier creates a valid identifier from a project name -func sanitizeIdentifier(name string) string { - var result []byte - for i := 0; i < len(name); i++ { - c := name[i] - if (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9') { - result = append(result, c) - } - } - if len(result) == 0 { - return "app" - } - // Lowercase the result - for i := range result { - if result[i] >= 'A' && result[i] <= 'Z' { - result[i] = result[i] + 32 - } - } - return string(result) -} diff --git a/v3/internal/doctor/diagnostics.go b/v3/internal/doctor/diagnostics.go deleted file mode 100644 index bc6b36670..000000000 --- a/v3/internal/doctor/diagnostics.go +++ /dev/null @@ -1,93 +0,0 @@ -package doctor - -import ( - "fmt" - "path/filepath" - "runtime" - "strings" -) - -// DiagnosticTest represents a single diagnostic test to be run -type DiagnosticTest struct { - Name string - Run func() (bool, string) // Returns success and error message if failed - HelpURL string -} - -// DiagnosticResult represents the result of a diagnostic test -type DiagnosticResult struct { - TestName string - ErrorMsg string - HelpURL string -} - -// platformDiagnostics maps platform names to their diagnostic tests -var platformDiagnostics = map[string][]DiagnosticTest{ - // Tests that run on all platforms - "all": { - { - Name: "Check Go installation", - Run: func() (bool, string) { - // This is just an example test for all platforms - if runtime.Version() == "" { - return false, "Go installation not found" - } - return true, "" - }, - HelpURL: "/getting-started/installation/", - }, - }, - // Platform specific tests - "darwin": { - { - Name: "Check for .syso file", - Run: func() (bool, string) { - // Check for .syso files in current directory - matches, err := filepath.Glob("*.syso") - if err != nil { - return false, "Error checking for .syso files" - } - if len(matches) > 0 { - return false, fmt.Sprintf("Found .syso file(s): %v. These may cause issues when building on macOS", strings.Join(matches, ", ")) - } - return true, "" - }, - HelpURL: "/troubleshooting/mac-syso", - }, - }, -} - -// RunDiagnostics executes all diagnostic tests for the current platform -func RunDiagnostics() []DiagnosticResult { - var results []DiagnosticResult - - // Run tests that apply to all platforms - if tests, exists := platformDiagnostics["all"]; exists { - for _, test := range tests { - success, errMsg := test.Run() - if !success { - results = append(results, DiagnosticResult{ - TestName: test.Name, - ErrorMsg: errMsg, - HelpURL: test.HelpURL, - }) - } - } - } - - // Run platform-specific tests - if tests, exists := platformDiagnostics[runtime.GOOS]; exists { - for _, test := range tests { - success, errMsg := test.Run() - if !success { - results = append(results, DiagnosticResult{ - TestName: test.Name, - ErrorMsg: errMsg, - HelpURL: test.HelpURL, - }) - } - } - } - - return results -} diff --git a/v3/internal/doctor/doctor.go b/v3/internal/doctor/doctor.go deleted file mode 100644 index a14fcf3b3..000000000 --- a/v3/internal/doctor/doctor.go +++ /dev/null @@ -1,274 +0,0 @@ -package doctor - -import ( - "bytes" - "fmt" - "os/exec" - "path/filepath" - "regexp" - "runtime" - "runtime/debug" - "slices" - "strconv" - "strings" - - "github.com/wailsapp/wails/v3/internal/term" - - "github.com/wailsapp/wails/v3/internal/buildinfo" - - "github.com/go-git/go-git/v5" - "github.com/jaypipes/ghw" - "github.com/pterm/pterm" - "github.com/samber/lo" - "github.com/wailsapp/wails/v3/internal/operatingsystem" - "github.com/wailsapp/wails/v3/internal/version" -) - -func Run() (err error) { - - get, err := buildinfo.Get() - if err != nil { - return err - } - _ = get - - term.Header("Wails Doctor") - - spinner, _ := pterm.DefaultSpinner.WithRemoveWhenDone().Start("Scanning system - Please wait (this may take a long time)...") - - defer func() { - if err != nil { - spinner.Fail() - } - }() - - /** Build **/ - - // BuildSettings contains the build settings for the application - var BuildSettings map[string]string - - // BuildInfo contains the build info for the application - var BuildInfo *debug.BuildInfo - - var ok bool - BuildInfo, ok = debug.ReadBuildInfo() - if !ok { - return fmt.Errorf("could not read build info from binary") - } - BuildSettings = lo.Associate(BuildInfo.Settings, func(setting debug.BuildSetting) (string, string) { - return setting.Key, setting.Value - }) - - /** Operating System **/ - - // Get system info - info, err := operatingsystem.Info() - if err != nil { - term.Error("Failed to get system information") - return err - } - - /** Wails **/ - - wailsPackage, _ := lo.Find(BuildInfo.Deps, func(dep *debug.Module) bool { - return dep.Path == "github.com/wailsapp/wails/v3" - }) - - wailsVersion := strings.TrimSpace(version.String()) - if wailsPackage != nil && wailsPackage.Replace != nil { - wailsVersion = "(local) => " + filepath.ToSlash(wailsPackage.Replace.Path) - // Get the latest commit hash - repo, err := git.PlainOpen(filepath.Join(wailsPackage.Replace.Path, "..")) - if err == nil { - head, err := repo.Head() - if err == nil { - wailsVersion += " (" + head.Hash().String()[:8] + ")" - } - } - } - - platformExtras, ok := getInfo() - - dependencies := make(map[string]string) - checkPlatformDependencies(dependencies, &ok) - - spinner.Success() - - /** Output **/ - - term.Section("System") - - systemTabledata := pterm.TableData{ - {pterm.Sprint("Name"), info.Name}, - {pterm.Sprint("Version"), info.Version}, - {pterm.Sprint("ID"), info.ID}, - {pterm.Sprint("Branding"), info.Branding}, - - {pterm.Sprint("Platform"), runtime.GOOS}, - {pterm.Sprint("Architecture"), runtime.GOARCH}, - } - - mapKeys := lo.Keys(platformExtras) - slices.Sort(mapKeys) - for _, key := range mapKeys { - systemTabledata = append(systemTabledata, []string{key, platformExtras[key]}) - } - - // Probe CPU - cpus, _ := ghw.CPU() - if cpus != nil { - prefix := "CPU" - for idx, cpu := range cpus.Processors { - if len(cpus.Processors) > 1 { - prefix = "CPU " + strconv.Itoa(idx+1) - } - systemTabledata = append(systemTabledata, []string{prefix, cpu.Model}) - } - } else { - systemTabledata = append(systemTabledata, []string{"CPU", "Unknown"}) - } - - // Probe GPU - gpu, _ := ghw.GPU(ghw.WithDisableWarnings()) - if gpu != nil { - for idx, card := range gpu.GraphicsCards { - details := "Unknown" - prefix := "GPU " + strconv.Itoa(idx+1) - if card.DeviceInfo != nil { - details = fmt.Sprintf("%s (%s) - Driver: %s ", card.DeviceInfo.Product.Name, card.DeviceInfo.Vendor.Name, card.DeviceInfo.Driver) - } - systemTabledata = append(systemTabledata, []string{prefix, details}) - } - } else { - if runtime.GOOS == "darwin" { - var numCoresValue string - cmd := exec.Command("sh", "-c", "ioreg -l | grep gpu-core-count") - output, err := cmd.Output() - if err == nil { - // Look for an `=` sign, optional spaces and then an integer - re := regexp.MustCompile(`= *(\d+)`) - matches := re.FindAllStringSubmatch(string(output), -1) - numCoresValue = "Unknown" - if len(matches) > 0 { - numCoresValue = matches[0][1] - } - - } - - // Run `system_profiler SPDisplaysDataType | grep Metal` - var metalSupport string - cmd = exec.Command("sh", "-c", "system_profiler SPDisplaysDataType | grep Metal") - output, err = cmd.Output() - if err == nil { - metalSupport = ", " + strings.TrimSpace(string(output)) - } - systemTabledata = append(systemTabledata, []string{"GPU", numCoresValue + " cores" + metalSupport}) - - } else { - systemTabledata = append(systemTabledata, []string{"GPU", "Unknown"}) - } - } - - memory, _ := ghw.Memory() - var memoryText = "Unknown" - if memory != nil { - memoryText = strconv.Itoa(int(memory.TotalPhysicalBytes/1024/1024/1024)) + "GB" - } else { - if runtime.GOOS == "darwin" { - cmd := exec.Command("sh", "-c", "system_profiler SPHardwareDataType | grep 'Memory'") - output, err := cmd.Output() - if err == nil { - output = bytes.Replace(output, []byte("Memory: "), []byte(""), 1) - memoryText = strings.TrimSpace(string(output)) - } - } - } - systemTabledata = append(systemTabledata, []string{"Memory", memoryText}) - - err = pterm.DefaultTable.WithBoxed().WithData(systemTabledata).Render() - if err != nil { - return err - } - - // Build Environment - - term.Section("Build Environment") - - tableData := pterm.TableData{ - {"Wails CLI", wailsVersion}, - {"Go Version", runtime.Version()}, - } - - if buildInfo, _ := debug.ReadBuildInfo(); buildInfo != nil { - buildSettingToName := map[string]string{ - "vcs.revision": "Revision", - "vcs.modified": "Modified", - } - for _, buildSetting := range buildInfo.Settings { - name := buildSettingToName[buildSetting.Key] - if name == "" { - continue - } - tableData = append(tableData, []string{name, buildSetting.Value}) - } - } - - mapKeys = lo.Keys(BuildSettings) - slices.Sort(mapKeys) - for _, key := range mapKeys { - tableData = append(tableData, []string{key, BuildSettings[key]}) - } - - err = pterm.DefaultTable.WithBoxed(true).WithData(tableData).Render() - if err != nil { - return err - } - - // Dependencies - term.Section("Dependencies") - dependenciesBox := pterm.DefaultBox.WithTitleBottomCenter().WithTitle(pterm.Gray("*") + " - Optional Dependency") - dependencyTableData := pterm.TableData{} - if len(dependencies) == 0 { - pterm.Info.Println("No dependencies found") - } else { - var optionals pterm.TableData - mapKeys = lo.Keys(dependencies) - for _, key := range mapKeys { - if strings.HasPrefix(dependencies[key], "*") { - optionals = append(optionals, []string{key, dependencies[key]}) - } else { - dependencyTableData = append(dependencyTableData, []string{key, dependencies[key]}) - } - } - dependencyTableData = append(dependencyTableData, optionals...) - dependenciesTableString, _ := pterm.DefaultTable.WithData(dependencyTableData).Srender() - dependenciesBox.Println(dependenciesTableString) - } - - // Run diagnostics after system info - term.Section("Checking for issues") - - diagnosticResults := RunDiagnostics() - if len(diagnosticResults) == 0 { - pterm.Success.Println("No issues found") - } else { - pterm.Warning.Println("Found potential issues:") - for _, result := range diagnosticResults { - pterm.Printf("• %s: %s\n", result.TestName, result.ErrorMsg) - url := result.HelpURL - if strings.HasPrefix(url, "/") { - url = "https://v3.wails.io" + url - } - pterm.Printf(" For more information: %s\n", term.Hyperlink(url, url)) - } - } - - term.Section("Diagnosis") - if !ok { - term.Warning("There are some items above that need addressing!") - } else { - term.Success("Your system is ready for Wails development!") - } - - return nil -} diff --git a/v3/internal/doctor/doctor_common.go b/v3/internal/doctor/doctor_common.go deleted file mode 100644 index dab765586..000000000 --- a/v3/internal/doctor/doctor_common.go +++ /dev/null @@ -1,61 +0,0 @@ -package doctor - -import ( - "bytes" - "os/exec" - "strconv" - "strings" -) - -func checkCommonDependencies(result map[string]string, ok *bool) { - // Check for npm - npmVersion := []byte("Not Installed. Requires npm >= 7.0.0") - npmVersion, err := exec.Command("npm", "-v").Output() - if err != nil { - *ok = false - } else { - npmVersion = bytes.TrimSpace(npmVersion) - // Check that it's at least version 7 by converting first byte to int and checking if it's >= 7 - // Parse the semver string - semver := strings.Split(string(npmVersion), ".") - if len(semver) > 0 { - major, _ := strconv.Atoi(semver[0]) - if major < 7 { - *ok = false - npmVersion = append(npmVersion, []byte(". Installed, but requires npm >= 7.0.0")...) - } else { - *ok = true - } - } - } - result["npm"] = string(npmVersion) - - // Check for Docker (optional - used for macOS cross-compilation from Linux) - checkDocker(result) -} - -func checkDocker(result map[string]string) { - dockerVersion, err := exec.Command("docker", "--version").Output() - if err != nil { - result["docker"] = "*Not installed (optional - for cross-compilation)" - return - } - - // Check if Docker daemon is running - _, err = exec.Command("docker", "info").Output() - if err != nil { - version := strings.TrimSpace(string(dockerVersion)) - result["docker"] = "*" + version + " (daemon not running)" - return - } - - version := strings.TrimSpace(string(dockerVersion)) - - // Check for the unified cross-compilation image - imageCheck, _ := exec.Command("docker", "image", "inspect", "wails-cross").Output() - if len(imageCheck) == 0 { - result["docker"] = "*" + version + " (wails-cross image not built - run: wails3 task setup:docker)" - } else { - result["docker"] = "*" + version + " (cross-compilation ready)" - } -} diff --git a/v3/internal/doctor/doctor_darwin.go b/v3/internal/doctor/doctor_darwin.go deleted file mode 100644 index 9ffb368f1..000000000 --- a/v3/internal/doctor/doctor_darwin.go +++ /dev/null @@ -1,63 +0,0 @@ -//go:build darwin - -package doctor - -import ( - "bytes" - "github.com/samber/lo" - "os/exec" - "strings" - "syscall" -) - -func getSysctl(name string) string { - value, err := syscall.Sysctl(name) - if err != nil { - return "unknown" - } - return value -} - -func getInfo() (map[string]string, bool) { - result := make(map[string]string) - ok := true - - // Determine if the app is running on Apple Silicon - // Credit: https://www.yellowduck.be/posts/detecting-apple-silicon-via-go/ - appleSilicon := "unknown" - r, err := syscall.Sysctl("sysctl.proc_translated") - if err == nil { - appleSilicon = lo.Ternary(r == "\x00\x00\x00" || r == "\x01\x00\x00", "true", "false") - } - result["Apple Silicon"] = appleSilicon - result["CPU"] = getSysctl("machdep.cpu.brand_string") - - return result, ok -} - -func checkPlatformDependencies(result map[string]string, ok *bool) { - - // Check for xcode command line tools - output, err := exec.Command("xcode-select", "-v").Output() - cliToolsVersion := "N/A. Install by running: `xcode-select --install`" - if err != nil { - *ok = false - } else { - cliToolsVersion = strings.TrimPrefix(string(output), "xcode-select version ") - cliToolsVersion = strings.TrimSpace(cliToolsVersion) - cliToolsVersion = strings.TrimSuffix(cliToolsVersion, ".") - } - result["Xcode cli tools"] = cliToolsVersion - - checkCommonDependencies(result, ok) - - // Check for nsis - nsisVersion := []byte("Not Installed. Install with `brew install makensis`.") - output, err = exec.Command("makensis", "-VERSION").Output() - if err == nil && output != nil { - nsisVersion = output - } - nsisVersion = bytes.TrimSpace(nsisVersion) - - result["*NSIS"] = string(nsisVersion) -} diff --git a/v3/internal/doctor/doctor_linux.go b/v3/internal/doctor/doctor_linux.go deleted file mode 100644 index 4952cffab..000000000 --- a/v3/internal/doctor/doctor_linux.go +++ /dev/null @@ -1,87 +0,0 @@ -//go:build linux - -package doctor - -import ( - "os" - "strings" - - "github.com/wailsapp/wails/v3/internal/doctor/packagemanager" - "github.com/wailsapp/wails/v3/internal/operatingsystem" -) - -func getInfo() (map[string]string, bool) { - result := make(map[string]string) - - // Check session type (X11/Wayland) - result["XDG_SESSION_TYPE"] = getSessionType() - - // Check desktop environment - result["Desktop Environment"] = getDesktopEnvironment() - - // Check for NVIDIA driver - result["NVIDIA Driver"] = getNvidiaDriverInfo() - - return result, true -} - -func getSessionType() string { - sessionType := os.Getenv("XDG_SESSION_TYPE") - if sessionType == "" { - return "unset" - } - return sessionType -} - -func getDesktopEnvironment() string { - de := os.Getenv("XDG_CURRENT_DESKTOP") - if de == "" { - return "unset" - } - return de -} - -func getNvidiaDriverInfo() string { - version, err := os.ReadFile("/sys/module/nvidia/version") - if err != nil { - return "N/A" - } - - versionStr := strings.TrimSpace(string(version)) - - srcVersion, err := os.ReadFile("/sys/module/nvidia/srcversion") - if err != nil { - return versionStr - } - - return versionStr + " (" + strings.TrimSpace(string(srcVersion)) + ")" -} - -func checkPlatformDependencies(result map[string]string, ok *bool) { - info, _ := operatingsystem.Info() - - pm := packagemanager.Find(info.ID) - deps, _ := packagemanager.Dependencies(pm) - for _, dep := range deps { - var status string - - switch true { - case !dep.Installed: - if dep.Optional { - status = "[Optional] " - } else { - *ok = false - } - status += "not installed." - if dep.InstallCommand != "" { - status += " Install with: " + dep.InstallCommand - } - case dep.Version != "": - status = dep.Version - } - - result[dep.Name] = status - } - - checkCommonDependencies(result, ok) -} diff --git a/v3/internal/doctor/doctor_test.go b/v3/internal/doctor/doctor_test.go deleted file mode 100644 index 98f4c3f8a..000000000 --- a/v3/internal/doctor/doctor_test.go +++ /dev/null @@ -1,10 +0,0 @@ -package doctor - -import "testing" - -func TestRun(t *testing.T) { - err := Run() - if err != nil { - t.Errorf("TestRun failed: %v", err) - } -} diff --git a/v3/internal/doctor/doctor_windows.go b/v3/internal/doctor/doctor_windows.go deleted file mode 100644 index 2ae1dd2c8..000000000 --- a/v3/internal/doctor/doctor_windows.go +++ /dev/null @@ -1,86 +0,0 @@ -//go:build windows - -package doctor - -import ( - "os/exec" - "strings" - - "github.com/samber/lo" - "github.com/wailsapp/go-webview2/webviewloader" -) - -func getInfo() (map[string]string, bool) { - ok := true - result := make(map[string]string) - result["Go WebView2Loader"] = lo.Ternary(webviewloader.UsingGoWebview2Loader, "true", "false") - webviewVersion, err := webviewloader.GetAvailableCoreWebView2BrowserVersionString("") - if err != nil { - ok = false - webviewVersion = "Error:" + err.Error() - } - result["WebView2 Version"] = webviewVersion - return result, ok -} - -func getNSISVersion() string { - // Execute nsis - output, err := exec.Command("makensis", "-VERSION").Output() - if err != nil { - return "Not Installed" - } - return string(output) -} - -func getMakeAppxVersion() string { - // Check if MakeAppx.exe is available (part of Windows SDK) - _, err := exec.LookPath("MakeAppx.exe") - if err != nil { - return "Not Installed" - } - return "Installed" -} - -func getMSIXPackagingToolVersion() string { - // Check if MSIX Packaging Tool is installed - // Use PowerShell to check if the app is installed from Microsoft Store - cmd := exec.Command("powershell", "-Command", "Get-AppxPackage -Name Microsoft.MSIXPackagingTool") - output, err := cmd.Output() - if err != nil || len(output) == 0 || !strings.Contains(string(output), "Microsoft.MSIXPackagingTool") { - return "Not Installed" - } - - if strings.Contains(string(output), "Version") { - lines := strings.Split(string(output), "\n") - for _, line := range lines { - if strings.Contains(line, "Version") { - parts := strings.Split(line, ":") - if len(parts) > 1 { - return strings.TrimSpace(parts[1]) - } - } - } - } - - return "Installed (Version Unknown)" -} - -func getSignToolVersion() string { - // Check if signtool.exe is available (part of Windows SDK) - _, err := exec.LookPath("signtool.exe") - if err != nil { - return "Not Installed" - } - return "Installed" -} - -func checkPlatformDependencies(result map[string]string, ok *bool) { - checkCommonDependencies(result, ok) - // add nsis - result["NSIS"] = getNSISVersion() - - // Add MSIX tooling checks - result["MakeAppx.exe (Windows SDK)"] = getMakeAppxVersion() - result["MSIX Packaging Tool"] = getMSIXPackagingToolVersion() - result["SignTool.exe (Windows SDK)"] = getSignToolVersion() -} diff --git a/v3/internal/doctor/packagemanager/apt.go b/v3/internal/doctor/packagemanager/apt.go deleted file mode 100644 index 97253bfed..000000000 --- a/v3/internal/doctor/packagemanager/apt.go +++ /dev/null @@ -1,101 +0,0 @@ -//go:build linux - -package packagemanager - -import ( - "regexp" - "strings" -) - -// Apt represents the Apt manager -type Apt struct { - name string - osid string -} - -// NewApt creates a new Apt instance -func NewApt(osid string) *Apt { - return &Apt{ - name: "apt", - osid: osid, - } -} - -// Packages returns the libraries that we need for Wails to compile -// They will potentially differ on different distributions or versions -func (a *Apt) Packages() Packagemap { - return Packagemap{ - "gtk3": []*Package{ - {Name: "libgtk-3-dev", SystemPackage: true, Library: true}, - }, - "webkit2gtk": []*Package{ - {Name: "libwebkit2gtk-4.1-dev", SystemPackage: true, Library: true}, - }, - "gtk4 (experimental)": []*Package{ - {Name: "libgtk-4-dev", SystemPackage: true, Library: true, Optional: true}, - }, - "webkitgtk-6.0 (experimental)": []*Package{ - {Name: "libwebkitgtk-6.0-dev", SystemPackage: true, Library: true, Optional: true}, - }, - "gcc": []*Package{ - {Name: "build-essential", SystemPackage: true}, - }, - "pkg-config": []*Package{ - {Name: "pkg-config", SystemPackage: true}, - }, - "npm": []*Package{ - {Name: "npm", SystemPackage: true}, - }, - } -} - -// Name returns the name of the package manager -func (a *Apt) Name() string { - return a.name -} - -func (a *Apt) listPackage(name string) (string, error) { - return execCmd("apt", "list", "-qq", name) -} - -// PackageInstalled tests if the given package name is installed -func (a *Apt) PackageInstalled(pkg *Package) (bool, error) { - if !pkg.SystemPackage { - if pkg.InstallCheck != nil { - return pkg.InstallCheck(), nil - } - return false, nil - } - output, err := a.listPackage(pkg.Name) - // apt list -qq returns "all" if you have packages installed globally and locally - return strings.Contains(output, "installed") || strings.Contains(output, " all"), err -} - -// PackageAvailable tests if the given package is available for installation -func (a *Apt) PackageAvailable(pkg *Package) (bool, error) { - if !pkg.SystemPackage { - return true, nil - } - output, err := a.listPackage(pkg.Name) - // We add a space to ensure we get a full match, not partial match - escapechars, _ := regexp.Compile(`\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])`) - escapechars.ReplaceAllString(output, "") - installed := strings.HasPrefix(output, pkg.Name) - a.getPackageVersion(pkg, output) - return installed, err -} - -// InstallCommand returns the package manager specific command to install a package -func (a *Apt) InstallCommand(pkg *Package) string { - if !pkg.SystemPackage { - return pkg.InstallCommand - } - return "sudo apt install " + pkg.Name -} - -func (a *Apt) getPackageVersion(pkg *Package, output string) { - splitOutput := strings.Split(output, " ") - if len(splitOutput) > 1 { - pkg.Version = splitOutput[1] - } -} diff --git a/v3/internal/doctor/packagemanager/dnf.go b/v3/internal/doctor/packagemanager/dnf.go deleted file mode 100644 index 2a06de1e7..000000000 --- a/v3/internal/doctor/packagemanager/dnf.go +++ /dev/null @@ -1,129 +0,0 @@ -//go:build linux - -package packagemanager - -import ( - "os/exec" - "strings" -) - -// Dnf represents the Dnf manager -type Dnf struct { - name string - osid string -} - -// NewDnf creates a new Dnf instance -func NewDnf(osid string) *Dnf { - return &Dnf{ - name: "dnf", - osid: osid, - } -} - -// Packages returns the libraries that we need for Wails to compile -// They will potentially differ on different distributions or versions -func (y *Dnf) Packages() Packagemap { - return Packagemap{ - "gtk3": []*Package{ - {Name: "gtk3-devel", SystemPackage: true, Library: true}, - }, - "webkit2gtk": []*Package{ - {Name: "webkit2gtk4.1-devel", SystemPackage: true, Library: true}, - {Name: "webkit2gtk3-devel", SystemPackage: true, Library: true}, - }, - "gtk4 (experimental)": []*Package{ - {Name: "gtk4-devel", SystemPackage: true, Library: true, Optional: true}, - }, - "webkitgtk-6.0 (experimental)": []*Package{ - {Name: "webkitgtk6.0-devel", SystemPackage: true, Library: true, Optional: true}, - }, - "gcc": []*Package{ - {Name: "gcc-c++", SystemPackage: true}, - }, - "pkg-config": []*Package{ - {Name: "pkgconf-pkg-config", SystemPackage: true}, - }, - "npm": []*Package{ - {Name: "npm", SystemPackage: true}, - {Name: "nodejs-npm", SystemPackage: true}, - }, - } -} - -// Name returns the name of the package manager -func (y *Dnf) Name() string { - return y.name -} - -// PackageInstalled tests if the given package name is installed -func (y *Dnf) PackageInstalled(pkg *Package) (bool, error) { - if !pkg.SystemPackage { - if pkg.InstallCheck != nil { - return pkg.InstallCheck(), nil - } - return false, nil - } - stdout, err := execCmd("dnf", "-q", "list", "--installed", pkg.Name) - if err != nil { - _, ok := err.(*exec.ExitError) - if ok { - return false, nil - } - return false, err - } - - // Output format: "package-name.arch version repo" - // e.g., "webkit2gtk4.0-devel.x86_64 2.46.5-1.fc41 @updates" - splitoutput := strings.Split(stdout, "\n") - for _, line := range splitoutput { - if strings.HasPrefix(line, pkg.Name) { - fields := strings.Fields(line) - if len(fields) >= 2 { - pkg.Version = fields[1] - } - return true, nil - } - } - - return false, nil -} - -// PackageAvailable tests if the given package is available for installation -func (y *Dnf) PackageAvailable(pkg *Package) (bool, error) { - if pkg.SystemPackage == false { - return false, nil - } - stdout, err := execCmd("dnf", "info", pkg.Name) - // We add a space to ensure we get a full match, not partial match - if err != nil { - _, ok := err.(*exec.ExitError) - if ok { - return false, nil - } - return false, err - } - splitoutput := strings.Split(stdout, "\n") - for _, line := range splitoutput { - if strings.HasPrefix(line, "Version") { - splitline := strings.Split(line, ":") - pkg.Version = strings.TrimSpace(splitline[1]) - } - } - return true, nil -} - -// InstallCommand returns the package manager specific command to install a package -func (y *Dnf) InstallCommand(pkg *Package) string { - if pkg.SystemPackage == false { - return pkg.InstallCommand - } - return "sudo dnf install " + pkg.Name -} - -func (y *Dnf) getPackageVersion(pkg *Package, output string) { - splitOutput := strings.Split(output, " ") - if len(splitOutput) > 0 { - pkg.Version = splitOutput[1] - } -} diff --git a/v3/internal/doctor/packagemanager/emerge.go b/v3/internal/doctor/packagemanager/emerge.go deleted file mode 100644 index 2f8be261a..000000000 --- a/v3/internal/doctor/packagemanager/emerge.go +++ /dev/null @@ -1,119 +0,0 @@ -//go:build linux - -package packagemanager - -import ( - "os/exec" - "regexp" - "strings" -) - -// Emerge represents the Emerge package manager -type Emerge struct { - name string - osid string -} - -// NewEmerge creates a new Emerge instance -func NewEmerge(osid string) *Emerge { - return &Emerge{ - name: "emerge", - osid: osid, - } -} - -// Packages returns the libraries that we need for Wails to compile -// They will potentially differ on different distributions or versions -func (e *Emerge) Packages() Packagemap { - return Packagemap{ - "gtk3": []*Package{ - {Name: "x11-libs/gtk+:3", SystemPackage: true, Library: true}, - }, - "webkit2gtk": []*Package{ - {Name: "net-libs/webkit-gtk:4.1", SystemPackage: true, Library: true}, - {Name: "net-libs/webkit-gtk:4", SystemPackage: true, Library: true}, - }, - "gtk4 (experimental)": []*Package{ - {Name: "gui-libs/gtk", SystemPackage: true, Library: true, Optional: true}, - }, - "webkitgtk-6.0 (experimental)": []*Package{ - {Name: "net-libs/webkit-gtk:6", SystemPackage: true, Library: true, Optional: true}, - }, - "gcc": []*Package{ - {Name: "sys-devel/gcc", SystemPackage: true}, - }, - "pkg-config": []*Package{ - {Name: "dev-util/pkgconf", SystemPackage: true}, - }, - "npm": []*Package{ - {Name: "net-libs/nodejs", SystemPackage: true}, - }, - } -} - -// Name returns the name of the package manager -func (e *Emerge) Name() string { - return e.name -} - -// PackageInstalled tests if the given package name is installed -func (e *Emerge) PackageInstalled(pkg *Package) (bool, error) { - if pkg.SystemPackage == false { - return false, nil - } - stdout, err := execCmd("emerge", "-s", pkg.Name+"$") - if err != nil { - _, ok := err.(*exec.ExitError) - if ok { - return false, nil - } - return false, err - } - - regex := `.*\*\s+` + regexp.QuoteMeta(pkg.Name) + `\n(?:\S|\s)+?Latest version installed: (.*)` - installedRegex := regexp.MustCompile(regex) - matches := installedRegex.FindStringSubmatch(stdout) - pkg.Version = "" - noOfMatches := len(matches) - installed := false - if noOfMatches > 1 && matches[1] != "[ Not Installed ]" { - installed = true - pkg.Version = strings.TrimSpace(matches[1]) - } - return installed, err -} - -// PackageAvailable tests if the given package is available for installation -func (e *Emerge) PackageAvailable(pkg *Package) (bool, error) { - if pkg.SystemPackage == false { - return false, nil - } - stdout, err := execCmd("emerge", "-s", pkg.Name+"$") - // We add a space to ensure we get a full match, not partial match - if err != nil { - _, ok := err.(*exec.ExitError) - if ok { - return false, nil - } - return false, err - } - - installedRegex := regexp.MustCompile(`.*\*\s+` + regexp.QuoteMeta(pkg.Name) + `\n(?:\S|\s)+?Latest version available: (.*)`) - matches := installedRegex.FindStringSubmatch(stdout) - pkg.Version = "" - noOfMatches := len(matches) - available := false - if noOfMatches > 1 { - available = true - pkg.Version = strings.TrimSpace(matches[1]) - } - return available, nil -} - -// InstallCommand returns the package manager specific command to install a package -func (e *Emerge) InstallCommand(pkg *Package) string { - if pkg.SystemPackage == false { - return pkg.InstallCommand - } - return "sudo emerge " + pkg.Name -} diff --git a/v3/internal/doctor/packagemanager/eopkg.go b/v3/internal/doctor/packagemanager/eopkg.go deleted file mode 100644 index 9654d08c8..000000000 --- a/v3/internal/doctor/packagemanager/eopkg.go +++ /dev/null @@ -1,117 +0,0 @@ -//go:build linux - -package packagemanager - -import ( - "regexp" - "strings" -) - -type Eopkg struct { - name string - osid string -} - -// NewEopkg creates a new Eopkg instance -func NewEopkg(osid string) *Eopkg { - result := &Eopkg{ - name: "eopkg", - osid: osid, - } - result.intialiseName() - return result -} - -// Packages returns the packages that we need for Wails to compile -// They will potentially differ on different distributions or versions -func (e *Eopkg) Packages() Packagemap { - return Packagemap{ - "gtk3": []*Package{ - {Name: "libgtk-3-devel", SystemPackage: true, Library: true}, - }, - "webkit2gtk": []*Package{ - {Name: "libwebkit-gtk-devel", SystemPackage: true, Library: true}, - }, - "gtk4 (experimental)": []*Package{ - {Name: "libgtk-4-devel", SystemPackage: true, Library: true, Optional: true}, - }, - "webkitgtk-6.0 (experimental)": []*Package{ - {Name: "libwebkit-gtk6-devel", SystemPackage: true, Library: true, Optional: true}, - }, - "gcc": []*Package{ - {Name: "gcc", SystemPackage: true}, - }, - "pkg-config": []*Package{ - {Name: "pkg-config", SystemPackage: true}, - }, - "npm": []*Package{ - {Name: "nodejs", SystemPackage: true}, - }, - } -} - -// Name returns the name of the package manager -func (e *Eopkg) Name() string { - return e.name -} - -// PackageInstalled tests if the given package is installed -func (e *Eopkg) PackageInstalled(pkg *Package) (bool, error) { - if !pkg.SystemPackage { - if pkg.InstallCheck != nil { - return pkg.InstallCheck(), nil - } - return false, nil - } - stdout, err := execCmd("eopkg", "info", pkg.Name) - return strings.HasPrefix(stdout, "Installed"), err -} - -// PackageAvailable tests if the given package is available for installation -func (e *Eopkg) PackageAvailable(pkg *Package) (bool, error) { - if pkg.SystemPackage == false { - return false, nil - } - stdout, err := execCmd("eopkg", "info", pkg.Name) - // We add a space to ensure we get a full match, not partial match - output := e.removeEscapeSequences(stdout) - installed := strings.Contains(output, "Package found in Solus repository") - e.getPackageVersion(pkg, output) - return installed, err -} - -// InstallCommand returns the package manager specific command to install a package -func (e *Eopkg) InstallCommand(pkg *Package) string { - if pkg.SystemPackage == false { - return pkg.InstallCommand - } - return "sudo eopkg it " + pkg.Name -} - -func (e *Eopkg) removeEscapeSequences(in string) string { - escapechars, _ := regexp.Compile(`\x1B(?:[@-Z\\-_]|\[[0-?]*[ -/]*[@-~])`) - return escapechars.ReplaceAllString(in, "") -} - -func (e *Eopkg) intialiseName() { - result := "eopkg" - stdout, err := execCmd("eopkg", "--version") - if err == nil { - result = strings.TrimSpace(stdout) - } - e.name = result -} - -func (e *Eopkg) getPackageVersion(pkg *Package, output string) { - - versionRegex := regexp.MustCompile(`.*Name.*version:\s+(.*)+, release: (.*)`) - matches := versionRegex.FindStringSubmatch(output) - pkg.Version = "" - noOfMatches := len(matches) - if noOfMatches > 1 { - pkg.Version = matches[1] - if noOfMatches > 2 { - pkg.Version += " (r" + matches[2] + ")" - } - } -} diff --git a/v3/internal/doctor/packagemanager/nixpkgs.go b/v3/internal/doctor/packagemanager/nixpkgs.go deleted file mode 100644 index c252f583c..000000000 --- a/v3/internal/doctor/packagemanager/nixpkgs.go +++ /dev/null @@ -1,159 +0,0 @@ -//go:build linux - -package packagemanager - -import ( - "encoding/json" -) - -// Nixpkgs represents the Nixpkgs manager -type Nixpkgs struct { - name string - osid string -} - -type NixPackageDetail struct { - Name string - Pname string - Version string -} - -var available map[string]NixPackageDetail - -// NewNixpkgs creates a new Nixpkgs instance -func NewNixpkgs(osid string) *Nixpkgs { - available = map[string]NixPackageDetail{} - - return &Nixpkgs{ - name: "nixpkgs", - osid: osid, - } -} - -// Packages returns the libraries that we need for Wails to compile -// They will potentially differ on different distributions or versions -func (n *Nixpkgs) Packages() Packagemap { - // Currently, only support checking the default channel. - channel := "nixpkgs" - if n.osid == "nixos" { - channel = "nixos" - } - - return Packagemap{ - // GTK3 + WebKitGTK 4.1 (default for Wails v3) - "gtk3": []*Package{ - {Name: channel + ".gtk3", SystemPackage: true, Library: true}, - }, - "webkit2gtk": []*Package{ - {Name: channel + ".webkitgtk", SystemPackage: true, Library: true}, - }, - // GTK4 + WebKitGTK 6.0 (experimental - requires -tags gtk4) - "gtk4 (experimental)": []*Package{ - {Name: channel + ".gtk4", SystemPackage: true, Library: true, Optional: true}, - }, - "webkitgtk-6.0 (experimental)": []*Package{ - {Name: channel + ".webkitgtk_6_0", SystemPackage: true, Library: true, Optional: true}, - }, - "gcc": []*Package{ - {Name: channel + ".gcc", SystemPackage: true}, - }, - "pkg-config": []*Package{ - {Name: channel + ".pkg-config", SystemPackage: true}, - }, - "npm": []*Package{ - {Name: channel + ".nodejs", SystemPackage: true}, - }, - } -} - -// Name returns the name of the package manager -func (n *Nixpkgs) Name() string { - return n.name -} - -// PackageInstalled tests if the given package name is installed -func (n *Nixpkgs) PackageInstalled(pkg *Package) (bool, error) { - if !pkg.SystemPackage { - if pkg.InstallCheck != nil { - return pkg.InstallCheck(), nil - } - return false, nil - } - - stdout, err := execCmd("nix-env", "--json", "-qA", pkg.Name) - if err != nil { - return false, nil - } - - var attributes map[string]NixPackageDetail - err = json.Unmarshal([]byte(stdout), &attributes) - if err != nil { - return false, err - } - - // Did we get one? - installed := false - for attribute, detail := range attributes { - if attribute == pkg.Name { - installed = true - pkg.Version = detail.Version - } - break - } - - // If on NixOS, package may be installed via system config, so check the nix store. - detail, ok := available[pkg.Name] - if !installed && n.osid == "nixos" && ok { - cmd := "nix-store --query --requisites /run/current-system | cut -d- -f2- | sort | uniq | grep '^" + detail.Pname + "'" - - if pkg.Library { - cmd += " | grep 'dev$'" - } - - stdout, err = execCmd("sh", "-c", cmd) - if err != nil { - return false, nil - } - - if len(stdout) > 0 { - installed = true - } - } - - return installed, nil -} - -// PackageAvailable tests if the given package is available for installation -func (n *Nixpkgs) PackageAvailable(pkg *Package) (bool, error) { - if pkg.SystemPackage == false { - return false, nil - } - - stdout, err := execCmd("nix-env", "--json", "-qaA", pkg.Name) - if err != nil { - return false, nil - } - - var attributes map[string]NixPackageDetail - err = json.Unmarshal([]byte(stdout), &attributes) - if err != nil { - return false, err - } - - // Grab first version. - for attribute, detail := range attributes { - pkg.Version = detail.Version - available[attribute] = detail - break - } - - return len(pkg.Version) > 0, nil -} - -// InstallCommand returns the package manager specific command to install a package -func (n *Nixpkgs) InstallCommand(pkg *Package) string { - if pkg.SystemPackage == false { - return pkg.InstallCommand - } - return "nix-env -iA " + pkg.Name -} diff --git a/v3/internal/doctor/packagemanager/packagemanager.go b/v3/internal/doctor/packagemanager/packagemanager.go deleted file mode 100644 index 800b05f7a..000000000 --- a/v3/internal/doctor/packagemanager/packagemanager.go +++ /dev/null @@ -1,169 +0,0 @@ -//go:build linux - -package packagemanager - -import ( - "bytes" - "os" - "os/exec" - "sort" - "strings" -) - -func execCmd(command string, args ...string) (string, error) { - cmd := exec.Command(command, args...) - var stdo, stde bytes.Buffer - cmd.Stdout = &stdo - cmd.Stderr = &stde - cmd.Env = append(os.Environ(), "LANGUAGE=en_US.utf-8") - err := cmd.Run() - return stdo.String(), err -} - -// A list of package manager commands -var pmcommands = []string{ - "eopkg", - "apt", - "dnf", - "pacman", - "emerge", - "zypper", - "nix-env", -} - -// commandExists returns true if the given command can be found on the shell -func commandExists(name string) bool { - _, err := exec.LookPath(name) - if err != nil { - return false - } - return true -} - -// Find will attempt to find the system package manager -func Find(osid string) PackageManager { - - // Loop over pmcommands - for _, pmname := range pmcommands { - if commandExists(pmname) { - return newPackageManager(pmname, osid) - } - } - return nil -} - -func newPackageManager(pmname string, osid string) PackageManager { - switch pmname { - case "eopkg": - return NewEopkg(osid) - case "apt": - return NewApt(osid) - case "dnf": - return NewDnf(osid) - case "pacman": - return NewPacman(osid) - case "emerge": - return NewEmerge(osid) - case "zypper": - return NewZypper(osid) - case "nix-env": - return NewNixpkgs(osid) - } - return nil -} - -// Dependencies scans the system for required dependencies -// Returns a list of dependencies search for, whether they were found -// and whether they were installed -func Dependencies(p PackageManager) (DependencyList, error) { - - var dependencies DependencyList - - for name, packages := range p.Packages() { - dependency := &Dependency{Name: name} - for _, pkg := range packages { - dependency.Optional = pkg.Optional - dependency.External = !pkg.SystemPackage - dependency.InstallCommand = p.InstallCommand(pkg) - packageavailable, err := p.PackageAvailable(pkg) - if err != nil { - return nil, err - } - if packageavailable { - dependency.Version = pkg.Version - dependency.PackageName = pkg.Name - installed, err := p.PackageInstalled(pkg) - if err != nil { - return nil, err - } - if installed { - dependency.Installed = true - dependency.Version = pkg.Version - if !pkg.SystemPackage { - dependency.Version = AppVersion(name) - } - } else { - dependency.InstallCommand = p.InstallCommand(pkg) - } - break - } - } - dependencies = append(dependencies, dependency) - } - - // Sort dependencies - sort.Slice(dependencies, func(i, j int) bool { - return dependencies[i].Name < dependencies[j].Name - }) - - return dependencies, nil -} - -// AppVersion returns the version for application related to the given package -func AppVersion(name string) string { - - if name == "gcc" { - return gccVersion() - } - - if name == "pkg-config" { - return pkgConfigVersion() - } - - if name == "npm" { - return npmVersion() - } - - return "" - -} - -func gccVersion() string { - - var version string - var err error - - // Try "-dumpfullversion" - version, err = execCmd("gcc", "-dumpfullversion") - if err != nil { - - // Try -dumpversion - // We ignore the error as this function is not for testing whether the - // application exists, only that we can get the version number - dumpversion, err := execCmd("gcc", "-dumpversion") - if err == nil { - version = dumpversion - } - } - return strings.TrimSpace(version) -} - -func pkgConfigVersion() string { - version, _ := execCmd("pkg-config", "--version") - return strings.TrimSpace(version) -} - -func npmVersion() string { - version, _ := execCmd("npm", "--version") - return strings.TrimSpace(version) -} diff --git a/v3/internal/doctor/packagemanager/pacman.go b/v3/internal/doctor/packagemanager/pacman.go deleted file mode 100644 index e225ef788..000000000 --- a/v3/internal/doctor/packagemanager/pacman.go +++ /dev/null @@ -1,119 +0,0 @@ -//go:build linux - -package packagemanager - -import ( - "os/exec" - "regexp" - "strings" -) - -// Pacman represents the Pacman package manager -type Pacman struct { - name string - osid string -} - -// NewPacman creates a new Pacman instance -func NewPacman(osid string) *Pacman { - return &Pacman{ - name: "pacman", - osid: osid, - } -} - -// Packages returns the libraries that we need for Wails to compile -// They will potentially differ on different distributions or versions -func (p *Pacman) Packages() Packagemap { - return Packagemap{ - "gtk3": []*Package{ - {Name: "gtk3", SystemPackage: true, Library: true}, - }, - "webkit2gtk": []*Package{ - {Name: "webkit2gtk-4.1", SystemPackage: true, Library: true}, - {Name: "webkit2gtk", SystemPackage: true, Library: true}, - }, - "gtk4 (experimental)": []*Package{ - {Name: "gtk4", SystemPackage: true, Library: true, Optional: true}, - }, - "webkitgtk-6.0 (experimental)": []*Package{ - {Name: "webkitgtk-6.0", SystemPackage: true, Library: true, Optional: true}, - }, - "gcc": []*Package{ - {Name: "gcc", SystemPackage: true}, - }, - "pkg-config": []*Package{ - {Name: "pkgconf", SystemPackage: true}, - }, - "npm": []*Package{ - {Name: "npm", SystemPackage: true}, - }, - } -} - -// Name returns the name of the package manager -func (p *Pacman) Name() string { - return p.name -} - -// PackageInstalled tests if the given package name is installed -func (p *Pacman) PackageInstalled(pkg *Package) (bool, error) { - if !pkg.SystemPackage { - if pkg.InstallCheck != nil { - return pkg.InstallCheck(), nil - } - return false, nil - } - stdout, err := execCmd("pacman", "-Q", pkg.Name) - if err != nil { - _, ok := err.(*exec.ExitError) - if ok { - return false, nil - } - return false, err - } - - splitoutput := strings.Split(stdout, "\n") - for _, line := range splitoutput { - if strings.HasPrefix(line, pkg.Name) { - splitline := strings.Split(line, " ") - pkg.Version = strings.TrimSpace(splitline[1]) - } - } - - return true, err -} - -// PackageAvailable tests if the given package is available for installation -func (p *Pacman) PackageAvailable(pkg *Package) (bool, error) { - if pkg.SystemPackage == false { - return false, nil - } - output, err := execCmd("pacman", "-Si", pkg.Name) - // We add a space to ensure we get a full match, not partial match - if err != nil { - _, ok := err.(*exec.ExitError) - if ok { - return false, nil - } - return false, err - } - - reg := regexp.MustCompile(`.*Version.*?:\s+(.*)`) - matches := reg.FindStringSubmatch(output) - pkg.Version = "" - noOfMatches := len(matches) - if noOfMatches > 1 { - pkg.Version = strings.TrimSpace(matches[1]) - } - - return true, nil -} - -// InstallCommand returns the package manager specific command to install a package -func (p *Pacman) InstallCommand(pkg *Package) string { - if pkg.SystemPackage == false { - return pkg.InstallCommand - } - return "sudo pacman -S " + pkg.Name -} diff --git a/v3/internal/doctor/packagemanager/pm.go b/v3/internal/doctor/packagemanager/pm.go deleted file mode 100644 index 6b6ced9c0..000000000 --- a/v3/internal/doctor/packagemanager/pm.go +++ /dev/null @@ -1,65 +0,0 @@ -//go:build linux - -package packagemanager - -// Package contains information about a system package -type Package struct { - Name string - Version string - InstallCommand string - InstallCheck func() bool - SystemPackage bool - Library bool - Optional bool -} - -type Packagemap = map[string][]*Package - -// PackageManager is a common interface across all package managers -type PackageManager interface { - Name() string - Packages() Packagemap - PackageInstalled(*Package) (bool, error) - PackageAvailable(*Package) (bool, error) - InstallCommand(*Package) string -} - -// Dependency represents a system package that we require -type Dependency struct { - Name string - PackageName string - Installed bool - InstallCommand string - Version string - Optional bool - External bool -} - -// DependencyList is a list of Dependency instances -type DependencyList []*Dependency - -// InstallAllRequiredCommand returns the command you need to use to install all required dependencies -func (d DependencyList) InstallAllRequiredCommand() string { - - result := "" - for _, dependency := range d { - if !dependency.Installed && !dependency.Optional { - result += " - " + dependency.Name + ": " + dependency.InstallCommand + "\n" - } - } - - return result -} - -// InstallAllOptionalCommand returns the command you need to use to install all optional dependencies -func (d DependencyList) InstallAllOptionalCommand() string { - - result := "" - for _, dependency := range d { - if !dependency.Installed && dependency.Optional { - result += " - " + dependency.Name + ": " + dependency.InstallCommand + "\n" - } - } - - return result -} diff --git a/v3/internal/doctor/packagemanager/zypper.go b/v3/internal/doctor/packagemanager/zypper.go deleted file mode 100644 index 1f89d4360..000000000 --- a/v3/internal/doctor/packagemanager/zypper.go +++ /dev/null @@ -1,127 +0,0 @@ -//go:build linux -// +build linux - -package packagemanager - -import ( - "os/exec" - "regexp" - "strings" -) - -// Zypper represents the Zypper package manager -type Zypper struct { - name string - osid string -} - -// NewZypper creates a new Zypper instance -func NewZypper(osid string) *Zypper { - return &Zypper{ - name: "zypper", - osid: osid, - } -} - -// Packages returns the libraries that we need for Wails to compile -// They will potentially differ on different distributions or versions -func (z *Zypper) Packages() Packagemap { - return Packagemap{ - "gtk3": []*Package{ - {Name: "gtk3-devel", SystemPackage: true, Library: true}, - }, - "webkit2gtk": []*Package{ - {Name: "webkit2gtk4_1-devel", SystemPackage: true, Library: true}, - {Name: "webkit2gtk3-soup2-devel", SystemPackage: true, Library: true}, - }, - "gtk4 (experimental)": []*Package{ - {Name: "gtk4-devel", SystemPackage: true, Library: true, Optional: true}, - }, - "webkitgtk-6.0 (experimental)": []*Package{ - {Name: "webkitgtk-6_0-devel", SystemPackage: true, Library: true, Optional: true}, - }, - "gcc": []*Package{ - {Name: "gcc-c++", SystemPackage: true}, - }, - "pkg-config": []*Package{ - {Name: "pkg-config", SystemPackage: true}, - {Name: "pkgconf-pkg-config", SystemPackage: true}, - }, - "npm": []*Package{ - {Name: "npm10", SystemPackage: true}, - }, - } -} - -// Name returns the name of the package manager -func (z *Zypper) Name() string { - return z.name -} - -// PackageInstalled tests if the given package name is installed -func (z *Zypper) PackageInstalled(pkg *Package) (bool, error) { - if !pkg.SystemPackage { - if pkg.InstallCheck != nil { - return pkg.InstallCheck(), nil - } - return false, nil - } - stdout, err := execCmd("zypper", "info", pkg.Name) - if err != nil { - _, ok := err.(*exec.ExitError) - if ok { - return false, nil - } - return false, err - } - reg := regexp.MustCompile(`.*Installed\s*:\s*(Yes)\s*`) - matches := reg.FindStringSubmatch(stdout) - pkg.Version = "" - noOfMatches := len(matches) - if noOfMatches > 1 { - z.getPackageVersion(pkg, stdout) - } - return noOfMatches > 1, err -} - -// PackageAvailable tests if the given package is available for installation -func (z *Zypper) PackageAvailable(pkg *Package) (bool, error) { - if pkg.SystemPackage == false { - return false, nil - } - stdout, err := execCmd("zypper", "info", pkg.Name) - // We add a space to ensure we get a full match, not partial match - if err != nil { - _, ok := err.(*exec.ExitError) - if ok { - return false, nil - } - return false, err - } - - available := strings.Contains(stdout, "Information for package") - if available { - z.getPackageVersion(pkg, stdout) - } - - return available, nil -} - -// InstallCommand returns the package manager specific command to install a package -func (z *Zypper) InstallCommand(pkg *Package) string { - if pkg.SystemPackage == false { - return pkg.InstallCommand - } - return "sudo zypper in " + pkg.Name -} - -func (z *Zypper) getPackageVersion(pkg *Package, output string) { - - reg := regexp.MustCompile(`.*Version.*:(.*)`) - matches := reg.FindStringSubmatch(output) - pkg.Version = "" - noOfMatches := len(matches) - if noOfMatches > 1 { - pkg.Version = strings.TrimSpace(matches[1]) - } -} diff --git a/v3/internal/fileexplorer/desktopfile.go b/v3/internal/fileexplorer/desktopfile.go deleted file mode 100644 index 4cdd0af04..000000000 --- a/v3/internal/fileexplorer/desktopfile.go +++ /dev/null @@ -1,96 +0,0 @@ -package fileexplorer - -import ( - "bufio" - "io" - "os" - "strings" -) - -// DesktopEntry represents a parsed .desktop file's [Desktop Entry] section. -// This is a minimal parser that only extracts the fields we need, -// replacing the full gopkg.in/ini.v1 dependency (~34KB + 68 transitive deps). -type DesktopEntry struct { - Exec string -} - -// ParseDesktopFile parses a .desktop file and returns the Desktop Entry section. -// It follows the Desktop Entry Specification: -// ParseDesktopFile parses the `[Desktop Entry]` section of the desktop file at path and returns a DesktopEntry. -// It returns an error if the file cannot be opened or if parsing the file fails. -func ParseDesktopFile(path string) (*DesktopEntry, error) { - f, err := os.Open(path) - if err != nil { - return nil, err - } - defer f.Close() - return ParseDesktopReader(f) -} - -// ParseDesktopReader parses the [Desktop Entry] section of a .desktop file from r and extracts the Exec value. -// It ignores empty lines and lines starting with '#', treats section names as case-sensitive, and stops parsing after leaving the [Desktop Entry] section. -// The returned *DesktopEntry has Exec set to the exact value of the Exec key if present (whitespace preserved). -// An error is returned if reading from r fails. -func ParseDesktopReader(r io.Reader) (*DesktopEntry, error) { - scanner := bufio.NewScanner(r) - entry := &DesktopEntry{} - - inDesktopEntry := false - - for scanner.Scan() { - line := scanner.Text() - - // Skip empty lines - if len(line) == 0 { - continue - } - - // Skip comments (# at start of line) - if line[0] == '#' { - continue - } - - // Handle section headers - if line[0] == '[' { - // Check if this is the [Desktop Entry] section - // The spec says section names are case-sensitive - trimmed := strings.TrimSpace(line) - if trimmed == "[Desktop Entry]" { - inDesktopEntry = true - } else if inDesktopEntry { - // We've left the [Desktop Entry] section - // (e.g., entering [Desktop Action new-window]) - // We already have what we need, so we can stop - break - } - continue - } - - // Only process key=value pairs in [Desktop Entry] section - if !inDesktopEntry { - continue - } - - // Parse key=value (spec says no spaces around =, but be lenient) - eqIdx := strings.Index(line, "=") - if eqIdx == -1 { - continue - } - - key := strings.TrimSpace(line[:eqIdx]) - value := line[eqIdx+1:] // Don't trim value - preserve intentional whitespace - - // We only need the Exec key - // Per spec, keys are case-sensitive and Exec is always "Exec" - if key == "Exec" { - entry.Exec = value - // Continue parsing in case there are multiple Exec lines (shouldn't happen but be safe) - } - } - - if err := scanner.Err(); err != nil { - return nil, err - } - - return entry, nil -} \ No newline at end of file diff --git a/v3/internal/fileexplorer/desktopfile_test.go b/v3/internal/fileexplorer/desktopfile_test.go deleted file mode 100644 index feac60fcb..000000000 --- a/v3/internal/fileexplorer/desktopfile_test.go +++ /dev/null @@ -1,532 +0,0 @@ -package fileexplorer - -import ( - "strings" - "testing" -) - -func TestParseDesktopReader(t *testing.T) { - tests := []struct { - name string - input string - wantExec string - wantErr bool - }{ - { - name: "simple desktop file", - input: `[Desktop Entry] -Name=Files -Exec=nautilus %U -Icon=org.gnome.Nautilus -`, - wantExec: "nautilus %U", - }, - { - name: "exec with full path", - input: `[Desktop Entry] -Name=1Password -Exec=/opt/1Password/1password %U -`, - wantExec: "/opt/1Password/1password %U", - }, - { - name: "exec without arguments", - input: `[Desktop Entry] -Name=Btop -Exec=btop -Terminal=true -`, - wantExec: "btop", - }, - { - name: "exec with spaces in path", - input: `[Desktop Entry] -Name=My App -Exec="/path/with spaces/myapp" %f -`, - wantExec: `"/path/with spaces/myapp" %f`, - }, - { - name: "comments are ignored", - input: `# This is a comment -[Desktop Entry] -# Another comment -Name=Files -Exec=nautilus -# Comment after -`, - wantExec: "nautilus", - }, - { - name: "empty lines are ignored", - input: ` - -[Desktop Entry] - -Name=Files - -Exec=nautilus - -`, - wantExec: "nautilus", - }, - { - name: "key before section is ignored", - input: `Exec=ignored -[Desktop Entry] -Exec=nautilus -`, - wantExec: "nautilus", - }, - { - name: "other sections after Desktop Entry are ignored", - input: `[Desktop Entry] -Exec=nautilus --new-window %U -Icon=nautilus - -[Desktop Action new-window] -Name=New Window -Exec=nautilus --new-window -`, - wantExec: "nautilus --new-window %U", - }, - { - name: "section before Desktop Entry is ignored", - input: `[Some Other Section] -Exec=ignored - -[Desktop Entry] -Exec=nautilus -`, - wantExec: "nautilus", - }, - { - name: "case sensitive section name", - input: `[desktop entry] -Exec=ignored - -[Desktop Entry] -Exec=correct -`, - wantExec: "correct", - }, - { - name: "case sensitive key name", - input: `[Desktop Entry] -exec=ignored -EXEC=also ignored -Exec=correct -`, - wantExec: "correct", - }, - { - name: "value with equals sign", - input: `[Desktop Entry] -Exec=env VAR=value myapp -`, - wantExec: "env VAR=value myapp", - }, - { - name: "value with multiple equals signs", - input: `[Desktop Entry] -Exec=env A=1 B=2 C=3 myapp -`, - wantExec: "env A=1 B=2 C=3 myapp", - }, - { - name: "localized keys are separate", - input: `[Desktop Entry] -Name[en]=Files -Name=Default Files -Exec[en]=ignored -Exec=nautilus -`, - wantExec: "nautilus", - }, - { - name: "whitespace in section header", - input: `[Desktop Entry] -Exec=nautilus -`, - wantExec: "nautilus", - }, - { - name: "no exec key", - input: `[Desktop Entry] -Name=Files -Icon=nautilus -`, - wantExec: "", - }, - { - name: "empty file", - input: ``, - wantExec: "", - }, - { - name: "only comments", - input: `# Comment 1 -# Comment 2 -`, - wantExec: "", - }, - { - name: "no Desktop Entry section", - input: `[Other Section] -Exec=ignored -`, - wantExec: "", - }, - { - name: "real nautilus desktop file structure", - input: `[Desktop Entry] -Name[en_CA]=Files -Name[en_GB]=Files -Name=Files -Comment=Access and organize files -Keywords=folder;manager;explore;disk;filesystem;nautilus; -Exec=nautilus --new-window %U -Icon=org.gnome.Nautilus -Terminal=false -Type=Application -DBusActivatable=true -StartupNotify=true -Categories=GNOME;GTK;Utility;Core;FileManager; -MimeType=inode/directory;application/x-7z-compressed; -X-GNOME-UsesNotifications=true -Actions=new-window; - -[Desktop Action new-window] -Name=New Window -Exec=nautilus --new-window -`, - wantExec: "nautilus --new-window %U", - }, - { - name: "thunar style", - input: `[Desktop Entry] -Version=1.0 -Name=Thunar File Manager -Exec=thunar %F -Icon=Thunar -Type=Application -Categories=System;FileTools;FileManager; -`, - wantExec: "thunar %F", - }, - { - name: "dolphin style", - input: `[Desktop Entry] -Type=Application -Exec=dolphin %u -Icon=system-file-manager -Name=Dolphin -GenericName=File Manager -`, - wantExec: "dolphin %u", - }, - { - name: "pcmanfm style", - input: `[Desktop Entry] -Type=Application -Name=PCManFM -GenericName=File Manager -Exec=pcmanfm %U -Icon=system-file-manager -`, - wantExec: "pcmanfm %U", - }, - { - name: "exec with environment variable", - input: `[Desktop Entry] -Exec=env GDK_BACKEND=x11 nautilus %U -`, - wantExec: "env GDK_BACKEND=x11 nautilus %U", - }, - { - name: "trailing whitespace in value preserved", - input: `[Desktop Entry] -Exec=nautilus -`, - wantExec: "nautilus ", - }, - { - name: "leading whitespace in key", - input: `[Desktop Entry] - Exec=nautilus -`, - wantExec: "nautilus", - }, - { - name: "space around equals", - input: `[Desktop Entry] -Exec = nautilus -`, - wantExec: " nautilus", // We trim the key, value starts after = - }, - { - name: "line without equals is ignored", - input: `[Desktop Entry] -InvalidLine -Exec=nautilus -AnotherInvalidLine -`, - wantExec: "nautilus", - }, - { - name: "UTF-8 in exec path", - input: `[Desktop Entry] -Exec=/usr/bin/文件管理器 %U -`, - wantExec: "/usr/bin/文件管理器 %U", - }, - { - name: "special characters in exec", - input: `[Desktop Entry] -Exec=sh -c "echo 'hello world' && nautilus %U" -`, - wantExec: `sh -c "echo 'hello world' && nautilus %U"`, - }, - { - name: "multiple Desktop Entry sections (invalid file, last value wins)", - input: `[Desktop Entry] -Exec=first - -[Desktop Entry] -Exec=second -`, - wantExec: "second", // Invalid file, but we handle it gracefully - }, - { - name: "very long exec line", - input: `[Desktop Entry] -Exec=` + strings.Repeat("a", 1000) + ` -`, - wantExec: strings.Repeat("a", 1000), - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - entry, err := ParseDesktopReader(strings.NewReader(tt.input)) - if (err != nil) != tt.wantErr { - t.Errorf("ParseDesktopReader() error = %v, wantErr %v", err, tt.wantErr) - return - } - if err != nil { - return - } - if entry.Exec != tt.wantExec { - t.Errorf("ParseDesktopReader() Exec = %q, want %q", entry.Exec, tt.wantExec) - } - }) - } -} - -func TestParseDesktopReader_LineScanning(t *testing.T) { - // Test that we handle lines at the scanner's limit (64KB default) - // bufio.Scanner returns an error for lines > 64KB, which is acceptable - // since real .desktop files never have lines that long - - t.Run("line at buffer limit returns error", func(t *testing.T) { - // Create a line that exceeds the buffer size (64KB) - longValue := strings.Repeat("x", 65536) - input := "[Desktop Entry]\nExec=" + longValue + "\n" - - _, err := ParseDesktopReader(strings.NewReader(input)) - if err == nil { - t.Error("Expected error for line exceeding buffer size, got nil") - } - }) - - t.Run("line under buffer limit works", func(t *testing.T) { - // Create a line that's under the limit (should work fine) - longValue := strings.Repeat("x", 60000) - input := "[Desktop Entry]\nExec=" + longValue + "\n" - - entry, err := ParseDesktopReader(strings.NewReader(input)) - if err != nil { - t.Errorf("Unexpected error for long but valid line: %v", err) - return - } - if entry.Exec != longValue { - t.Errorf("Long line not parsed correctly, got length %d, want %d", len(entry.Exec), len(longValue)) - } - }) -} - -func TestParseDesktopReader_RealWorldFiles(t *testing.T) { - // These are actual .desktop file contents from real systems - realWorldTests := []struct { - name string - content string - wantExec string - }{ - { - name: "GNOME Nautilus 43.x", - content: `[Desktop Entry] -Name=Files -Comment=Access and organize files -Keywords=folder;manager;explore;disk;filesystem;nautilus; -Exec=nautilus --new-window %U -Icon=org.gnome.Nautilus -Terminal=false -Type=Application -DBusActivatable=true -StartupNotify=true -Categories=GNOME;GTK;Utility;Core;FileManager; -MimeType=inode/directory;application/x-7z-compressed; -Actions=new-window; - -[Desktop Action new-window] -Name=New Window -Exec=nautilus --new-window`, - wantExec: "nautilus --new-window %U", - }, - { - name: "KDE Dolphin", - content: `[Desktop Entry] -Type=Application -Exec=dolphin %u -Icon=system-file-manager -Terminal=false -InitialPreference=9 -Name=Dolphin -GenericName=File Manager -MimeType=inode/directory; -Categories=Qt;KDE;System;FileTools;FileManager; -Actions=new-window; - -[Desktop Action new-window] -Name=Open a New Window -Exec=dolphin %u`, - wantExec: "dolphin %u", - }, - { - name: "Thunar", - content: `[Desktop Entry] -Version=1.0 -Name=Thunar File Manager -GenericName=File Manager -Comment=Browse the filesystem with the file manager -Exec=thunar %F -Icon=Thunar -Terminal=false -StartupNotify=true -Type=Application -Categories=System;FileTools;FileManager; -`, - wantExec: "thunar %F", - }, - { - name: "PCManFM", - content: `[Desktop Entry] -Type=Application -Name=PCManFM -GenericName=File Manager -Comment=Browse the file system -Exec=pcmanfm %U -Icon=system-file-manager -Terminal=false -StartupNotify=true -Categories=Utility;FileManager;`, - wantExec: "pcmanfm %U", - }, - { - name: "Caja (MATE)", - content: `[Desktop Entry] -Name=Files -Comment=Access and organize files -Exec=caja %U -Icon=system-file-manager -Terminal=false -Type=Application -Categories=MATE;System;FileManager; -StartupNotify=true`, - wantExec: "caja %U", - }, - { - name: "Nemo (Cinnamon)", - content: `[Desktop Entry] -Name=Files -Comment=Access and organize files -Exec=nemo %U -Icon=folder -Terminal=false -Type=Application -StartupNotify=true -Categories=GNOME;GTK;Utility;Core; -MimeType=inode/directory;`, - wantExec: "nemo %U", - }, - } - - for _, tt := range realWorldTests { - t.Run(tt.name, func(t *testing.T) { - entry, err := ParseDesktopReader(strings.NewReader(tt.content)) - if err != nil { - t.Fatalf("ParseDesktopReader() error = %v", err) - } - if entry.Exec != tt.wantExec { - t.Errorf("ParseDesktopReader() Exec = %q, want %q", entry.Exec, tt.wantExec) - } - }) - } -} - -// BenchmarkParseDesktopReader measures parsing performance -func BenchmarkParseDesktopReader(b *testing.B) { - // Real Nautilus .desktop file content - content := `[Desktop Entry] -Name=Files -Comment=Access and organize files -Keywords=folder;manager;explore;disk;filesystem;nautilus; -Exec=nautilus --new-window %U -Icon=org.gnome.Nautilus -Terminal=false -Type=Application -DBusActivatable=true -StartupNotify=true -Categories=GNOME;GTK;Utility;Core;FileManager; -MimeType=inode/directory;application/x-7z-compressed; -Actions=new-window; - -[Desktop Action new-window] -Name=New Window -Exec=nautilus --new-window -` - - b.ResetTimer() - for i := 0; i < b.N; i++ { - _, err := ParseDesktopReader(strings.NewReader(content)) - if err != nil { - b.Fatal(err) - } - } -} - -// BenchmarkParseDesktopReader_Large tests parsing a file with many localized entries -func BenchmarkParseDesktopReader_Large(b *testing.B) { - // Simulate a desktop file with many localized Name entries (like Nautilus) - var sb strings.Builder - sb.WriteString("[Desktop Entry]\n") - for i := 0; i < 100; i++ { - sb.WriteString("Name[lang") - sb.WriteString(strings.Repeat("x", 5)) - sb.WriteString("]=Localized Name\n") - } - sb.WriteString("Exec=nautilus %U\n") - sb.WriteString("[Desktop Action new-window]\n") - sb.WriteString("Name=New Window\n") - sb.WriteString("Exec=nautilus\n") - - content := sb.String() - - b.ResetTimer() - for i := 0; i < b.N; i++ { - _, err := ParseDesktopReader(strings.NewReader(content)) - if err != nil { - b.Fatal(err) - } - } -} diff --git a/v3/internal/fileexplorer/fileexplorer.go b/v3/internal/fileexplorer/fileexplorer.go deleted file mode 100644 index bc0048f94..000000000 --- a/v3/internal/fileexplorer/fileexplorer.go +++ /dev/null @@ -1,61 +0,0 @@ -package fileexplorer - -import ( - "context" - "errors" - "fmt" - "os" - "os/exec" - "path/filepath" - "runtime" - "time" -) - -func OpenFileManager(path string, selectFile bool) error { - ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) - defer cancel() - - path = os.ExpandEnv(path) - path = filepath.Clean(path) - absPath, err := filepath.Abs(path) - if err != nil { - return fmt.Errorf("failed to resolve the absolute path: %w", err) - } - path = absPath - if pathInfo, err := os.Stat(path); err != nil { - return fmt.Errorf("failed to access the specified path: %w", err) - } else { - selectFile = selectFile && !pathInfo.IsDir() - } - - var ( - ignoreExitCode bool = false - ) - - switch runtime.GOOS { - case "windows": - // NOTE: Disabling the exit code check on Windows system. Workaround for explorer.exe - // exit code handling (https://github.com/microsoft/WSL/issues/6565) - ignoreExitCode = true - case "darwin", "linux": - default: - return errors.New("unsupported platform: " + runtime.GOOS) - } - - explorerBin, explorerArgs, err := explorerBinArgs(path, selectFile) - if err != nil { - return fmt.Errorf("failed to determine the file explorer binary: %w", err) - } - - cmd := exec.CommandContext(ctx, explorerBin, explorerArgs...) - cmd.SysProcAttr = sysProcAttr(path, selectFile) - cmd.Stdout = nil - cmd.Stderr = nil - - if err := cmd.Run(); err != nil { - if !ignoreExitCode { - return fmt.Errorf("failed to open the file explorer: %w", err) - } - } - return nil -} diff --git a/v3/internal/fileexplorer/fileexplorer_darwin.go b/v3/internal/fileexplorer/fileexplorer_darwin.go deleted file mode 100644 index ce16d1206..000000000 --- a/v3/internal/fileexplorer/fileexplorer_darwin.go +++ /dev/null @@ -1,19 +0,0 @@ -//go:build darwin - -package fileexplorer - -import "syscall" - -func explorerBinArgs(path string, selectFile bool) (string, []string, error) { - args := []string{} - if selectFile { - args = append(args, "-R") - } - - args = append(args, path) - return "open", args, nil -} - -func sysProcAttr(path string, selectFile bool) *syscall.SysProcAttr { - return &syscall.SysProcAttr{} -} diff --git a/v3/internal/fileexplorer/fileexplorer_linux.go b/v3/internal/fileexplorer/fileexplorer_linux.go deleted file mode 100644 index bf7e070a7..000000000 --- a/v3/internal/fileexplorer/fileexplorer_linux.go +++ /dev/null @@ -1,113 +0,0 @@ -//go:build linux - -package fileexplorer - -import ( - "bytes" - "fmt" - "net/url" - "os" - "os/exec" - "path/filepath" - "strings" - "syscall" -) - -// when possible; the fallback method does not support selecting a file. -func explorerBinArgs(path string, selectFile bool) (string, []string, error) { - // Map of field codes to their replacements - var fieldCodes = map[string]string{ - "%d": "", - "%D": "", - "%n": "", - "%N": "", - "%v": "", - "%m": "", - "%f": path, - "%F": path, - "%u": pathToURI(path), - "%U": pathToURI(path), - } - fileManagerQuery := exec.Command("xdg-mime", "query", "default", "inode/directory") - buf := new(bytes.Buffer) - fileManagerQuery.Stdout = buf - fileManagerQuery.Stderr = nil - - if err := fileManagerQuery.Run(); err != nil { - return fallbackExplorerBinArgs(path, selectFile) - } - - desktopFilePath, err := findDesktopFile(strings.TrimSpace((buf.String()))) - if err != nil { - return fallbackExplorerBinArgs(path, selectFile) - } - - entry, err := ParseDesktopFile(desktopFilePath) - if err != nil { - // Opting to fallback rather than fail - return fallbackExplorerBinArgs(path, selectFile) - } - - execCmd := entry.Exec - for fieldCode, replacement := range fieldCodes { - execCmd = strings.ReplaceAll(execCmd, fieldCode, replacement) - } - args := strings.Fields(execCmd) - if !strings.Contains(strings.Join(args, " "), path) { - args = append(args, path) - } - - return args[0], args[1:], nil -} - -func sysProcAttr(path string, selectFile bool) *syscall.SysProcAttr { - return &syscall.SysProcAttr{} -} - -func fallbackExplorerBinArgs(path string, selectFile bool) (string, []string, error) { - // NOTE: The linux fallback explorer opening does not support file selection - - stat, err := os.Stat(path) - if err != nil { - return "", []string{}, fmt.Errorf("stat path: %w", err) - } - - // If the path is a file, we want to open the directory containing the file - if !stat.IsDir() { - path = filepath.Dir(path) - } - - return "xdg-open", []string{path}, nil -} - -func pathToURI(path string) string { - absPath, err := filepath.Abs(path) - if err != nil { - return path - } - // Use url.URL to properly construct file URIs. - // url.PathEscape incorrectly escapes forward slashes (/ -> %2F), - // which breaks file manager path parsing. - u := &url.URL{ - Scheme: "file", - Path: absPath, - } - return u.String() -} - -func findDesktopFile(xdgFileName string) (string, error) { - paths := []string{ - filepath.Join(os.Getenv("XDG_DATA_HOME"), "applications"), - filepath.Join(os.Getenv("HOME"), ".local", "share", "applications"), - "/usr/share/applications", - } - - for _, path := range paths { - desktopFile := filepath.Join(path, xdgFileName) - if _, err := os.Stat(desktopFile); err == nil { - return desktopFile, nil - } - } - err := fmt.Errorf("desktop file not found: %s", xdgFileName) - return "", err -} \ No newline at end of file diff --git a/v3/internal/fileexplorer/fileexplorer_test.go b/v3/internal/fileexplorer/fileexplorer_test.go deleted file mode 100644 index 8f7a9b39f..000000000 --- a/v3/internal/fileexplorer/fileexplorer_test.go +++ /dev/null @@ -1,83 +0,0 @@ -package fileexplorer_test - -import ( - "fmt" - "os" - "path/filepath" - "runtime" - "strings" - "testing" - - "github.com/wailsapp/wails/v3/internal/fileexplorer" -) - -// Credit: https://stackoverflow.com/a/50631395 -func skipCI(t *testing.T) { - if os.Getenv("CI") != "" { - t.Skip("Skipping testing in CI environment") - } -} - -func TestFileExplorer(t *testing.T) { - skipCI(t) - // TestFileExplorer verifies that the OpenFileManager function correctly handles: - // - Opening files in the native file manager across different platforms - // - Selecting files when the selectFile parameter is true - // - Various error conditions like non-existent paths - tempDir := t.TempDir() // Create a temporary directory for tests - - tests := []struct { - name string - path string - selectFile bool - expectedErr error - }{ - {"Open Existing File", tempDir, false, nil}, - {"Select Existing File", tempDir, true, nil}, - {"Non-Existent Path", "/path/does/not/exist", false, fmt.Errorf("failed to access the specified path: /path/does/not/exist")}, - {"Path with Special Characters", filepath.Join(tempDir, "test space.txt"), true, nil}, - {"No Permission Path", "/root/test.txt", false, fmt.Errorf("failed to open the file explorer: /root/test.txt")}, - } - - for _, test := range tests { - t.Run(test.name, func(t *testing.T) { - t.Run("Windows", func(t *testing.T) { - runPlatformTest(t, "windows") - }) - t.Run("Linux", func(t *testing.T) { - runPlatformTest(t, "linux") - }) - t.Run("Darwin", func(t *testing.T) { - runPlatformTest(t, "darwin") - }) - }) - } -} - -func runPlatformTest(t *testing.T, platform string) { - if runtime.GOOS != platform { - t.Skipf("Skipping test on non-%s platform", strings.ToTitle(platform)) - } - - testFile := filepath.Join(t.TempDir(), "test.txt") - if err := os.WriteFile(testFile, []byte("Test file contents"), 0644); err != nil { - t.Fatal(err) - } - - tests := []struct { - name string - selectFile bool - }{ - {"OpenFile", false}, - {"SelectFile", true}, - } - - for _, test := range tests { - t.Run(test.name, func(t *testing.T) { - err := fileexplorer.OpenFileManager(testFile, test.selectFile) - if err != nil { - t.Errorf("OpenFileManager(%s, %v) error = %v", testFile, test.selectFile, err) - } - }) - } -} diff --git a/v3/internal/fileexplorer/fileexplorer_windows.go b/v3/internal/fileexplorer/fileexplorer_windows.go deleted file mode 100644 index 6498c5f26..000000000 --- a/v3/internal/fileexplorer/fileexplorer_windows.go +++ /dev/null @@ -1,24 +0,0 @@ -//go:build windows - -package fileexplorer - -import ( - "fmt" - "syscall" -) - -func explorerBinArgs(path string, selectFile bool) (string, []string, error) { - return "explorer.exe", []string{}, nil -} - -func sysProcAttr(path string, selectFile bool) *syscall.SysProcAttr { - if selectFile { - return &syscall.SysProcAttr{ - CmdLine: fmt.Sprintf("explorer.exe /select,\"%s\"", path), - } - } else { - return &syscall.SysProcAttr{ - CmdLine: fmt.Sprintf("explorer.exe \"%s\"", path), - } - } -} diff --git a/v3/internal/flags/bindings.go b/v3/internal/flags/bindings.go deleted file mode 100644 index a95566af6..000000000 --- a/v3/internal/flags/bindings.go +++ /dev/null @@ -1,97 +0,0 @@ -package flags - -import ( - "errors" - "slices" - "strings" - "unicode/utf8" -) - -type GenerateBindingsOptions struct { - BuildFlagsString string `name:"f" description:"A list of additional space-separated Go build flags. Flags (or parts of them) can be wrapped in single or double quotes to include spaces"` - OutputDirectory string `name:"d" description:"The output directory" default:"frontend/bindings"` - ModelsFilename string `name:"models" description:"File name for exported JS/TS models (excluding the extension)" default:"models"` - IndexFilename string `name:"index" description:"File name for JS/TS package indexes (excluding the extension)" default:"index"` - TS bool `name:"ts" description:"Generate Typescript bindings"` - UseInterfaces bool `name:"i" description:"Generate Typescript interfaces instead of classes"` - UseBundledRuntime bool `name:"b" description:"Use the bundled runtime instead of importing the npm package"` - UseNames bool `name:"names" description:"Use names instead of IDs for the binding calls"` - NoEvents bool `name:"noevents" description:"Do not generate types for registered custom events"` - NoIndex bool `name:"noindex" description:"Do not generate JS/TS index files"` - DryRun bool `name:"dry" description:"Do not write output files"` - Silent bool `name:"silent" description:"Silent mode"` - Verbose bool `name:"v" description:"Enable debug output"` - Clean bool `name:"clean" description:"Clean output directory before generation" default:"true"` -} - -var ErrUnmatchedQuote = errors.New("build flags contain an unmatched quote") - -func isWhitespace(r rune) bool { - // We use Go's definition of whitespace instead of the Unicode ones - return r == ' ' || r == '\t' || r == '\r' || r == '\n' -} - -func isNonWhitespace(r rune) bool { - return !isWhitespace(r) -} - -func isQuote(r rune) bool { - return r == '\'' || r == '"' -} - -func isQuoteOrWhitespace(r rune) bool { - return isQuote(r) || isWhitespace(r) -} - -func (options *GenerateBindingsOptions) BuildFlags() (flags []string, err error) { - str := options.BuildFlagsString - - // temporary buffer for flag assembly - flag := make([]byte, 0, 32) - - for start := strings.IndexFunc(str, isNonWhitespace); start >= 0; start = strings.IndexFunc(str, isNonWhitespace) { - // each iteration starts at the beginning of a flag - // skip initial whitespace - str = str[start:] - - // iterate over all quoted and unquoted parts of the flag and join them - for { - breakpoint := strings.IndexFunc(str, isQuoteOrWhitespace) - if breakpoint < 0 { - breakpoint = len(str) - } - - // append everything up to the breakpoint - flag = append(flag, str[:breakpoint]...) - str = str[breakpoint:] - - quote, quoteSize := utf8.DecodeRuneInString(str) - if !isQuote(quote) { - // if the breakpoint is not a quote, we reached the end of the flag - break - } - - // otherwise, look for the closing quote - str = str[quoteSize:] - closingQuote := strings.IndexRune(str, quote) - - // closing quote not found, append everything to the last flag and raise an error - if closingQuote < 0 { - flag = append(flag, str...) - str = "" - err = ErrUnmatchedQuote - break - } - - // closing quote found, append quoted content to the flag and restart after the quote - flag = append(flag, str[:closingQuote]...) - str = str[closingQuote+quoteSize:] - } - - // append a clone of the flag to the result, then reuse buffer space - flags = append(flags, string(slices.Clone(flag))) - flag = flag[:0] - } - - return -} diff --git a/v3/internal/flags/bindings_test.go b/v3/internal/flags/bindings_test.go deleted file mode 100644 index 506ca1b00..000000000 --- a/v3/internal/flags/bindings_test.go +++ /dev/null @@ -1,125 +0,0 @@ -package flags - -import ( - "testing" - - "github.com/google/go-cmp/cmp" - "github.com/google/go-cmp/cmp/cmpopts" -) - -func TestBuildFlags(t *testing.T) { - tests := []struct { - name string - input string - wantFlags []string - wantErr bool - }{ - { - name: "empty string", - input: "", - wantFlags: nil, - }, - { - name: "single flag, multiple spaces", - input: " -v ", - wantFlags: []string{"-v"}, - }, - { - name: "multiple flags, complex spaces", - input: " \t-v\r\n-x", - wantFlags: []string{"-v", "-x"}, - }, - { - name: "empty flag (single quotes)", - input: `''`, - wantFlags: []string{""}, - }, - { - name: "empty flag (double quotes)", - input: `""`, - wantFlags: []string{""}, - }, - { - name: "flag with spaces (single quotes)", - input: `'a b'`, - wantFlags: []string{"a \tb"}, - }, - { - name: "flag with spaces (double quotes)", - input: `'a b'`, - wantFlags: []string{"a \tb"}, - }, - { - name: "mixed quoted and non-quoted flags (single quotes)", - input: `-v 'a b ' -x`, - wantFlags: []string{"-v", "a b ", "-x"}, - }, - { - name: "mixed quoted and non-quoted flags (double quotes)", - input: `-v "a b " -x`, - wantFlags: []string{"-v", "a b ", "-x"}, - }, - { - name: "mixed quoted and non-quoted flags (mixed quotes)", - input: `-v "a b " '-x'`, - wantFlags: []string{"-v", "a b ", "-x"}, - }, - { - name: "double quote within single quotes", - input: `' " '`, - wantFlags: []string{" \" "}, - }, - { - name: "single quote within double quotes", - input: `" ' "`, - wantFlags: []string{" ' "}, - }, - { - name: "unmatched single quote", - input: `-v "a b " '-x -y`, - wantFlags: []string{"-v", "a b ", "-x -y"}, - wantErr: true, - }, - { - name: "unmatched double quote", - input: `-v "a b " "-x -y`, - wantFlags: []string{"-v", "a b ", "-x -y"}, - wantErr: true, - }, - { - name: "mismatched single quote", - input: `-v "a b " '-x" -y`, - wantFlags: []string{"-v", "a b ", "-x\" -y"}, - wantErr: true, - }, - { - name: "mismatched double quote", - input: `-v "a b " "-x' -y`, - wantFlags: []string{"-v", "a b ", "-x' -y"}, - wantErr: true, - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - options := GenerateBindingsOptions{ - BuildFlagsString: tt.input, - } - - var wantErr error = nil - if tt.wantErr { - wantErr = ErrUnmatchedQuote - } - - gotFlags, gotErr := options.BuildFlags() - - if diff := cmp.Diff(tt.wantFlags, gotFlags); diff != "" { - t.Errorf("BuildFlags() unexpected result: %s\n", diff) - } - - if diff := cmp.Diff(wantErr, gotErr, cmpopts.EquateErrors()); diff != "" { - t.Errorf("BuildFlags() unexpected error: %s\n", diff) - } - }) - } -} diff --git a/v3/internal/flags/common.go b/v3/internal/flags/common.go deleted file mode 100644 index e58eff411..000000000 --- a/v3/internal/flags/common.go +++ /dev/null @@ -1,5 +0,0 @@ -package flags - -type Common struct { - NoColour bool `description:"Disable colour in output"` -} diff --git a/v3/internal/flags/init.go b/v3/internal/flags/init.go deleted file mode 100644 index ec108b91d..000000000 --- a/v3/internal/flags/init.go +++ /dev/null @@ -1,23 +0,0 @@ -package flags - -type Init struct { - Common - - PackageName string `name:"p" description:"Package name" default:"main"` - TemplateName string `name:"t" description:"Name of built-in template to use, path to template or template url" default:"vanilla"` - ProjectName string `name:"n" description:"Name of project" default:""` - ProjectDir string `name:"d" description:"Project directory" default:"."` - Quiet bool `name:"q" description:"Suppress output to console"` - List bool `name:"l" description:"List templates"` - SkipGoModTidy bool `name:"skipgomodtidy" description:"Skip running go mod tidy"` - Git string `name:"git" description:"Git repository URL to initialize (e.g. github.com/username/project)"` - ModulePath string `name:"mod" description:"The Go module path for the project. Will be computed from the Git URL if unspecified."` - ProductName string `description:"The name of the product" default:"My Product"` - ProductDescription string `description:"The description of the product" default:"My Product Description"` - ProductVersion string `description:"The version of the product" default:"0.1.0"` - ProductCompany string `description:"The company of the product" default:"My Company"` - ProductCopyright string `description:"The copyright notice" default:"\u00a9 now, My Company"` - ProductComments string `description:"Comments to add to the generated files" default:"This is a comment"` - ProductIdentifier string `description:"The product identifier, e.g com.mycompany.myproduct"` - SkipWarning bool `name:"s" description:"Skips the warning message when using remote templates"` -} diff --git a/v3/internal/flags/lipo.go b/v3/internal/flags/lipo.go deleted file mode 100644 index 90f2893fd..000000000 --- a/v3/internal/flags/lipo.go +++ /dev/null @@ -1,12 +0,0 @@ -package flags - -// Lipo represents the options for creating macOS universal binaries -type Lipo struct { - Common - - // Output is the path for the universal binary - Output string `name:"output" short:"o" description:"Output path for the universal binary" default:""` - - // Inputs are the architecture-specific binaries to combine - Inputs []string `name:"input" short:"i" description:"Input binaries to combine (specify multiple times)" default:""` -} diff --git a/v3/internal/flags/msix.go b/v3/internal/flags/msix.go deleted file mode 100644 index 17bbbd446..000000000 --- a/v3/internal/flags/msix.go +++ /dev/null @@ -1,26 +0,0 @@ -package flags - -// ToolMSIX represents the options for the MSIX packaging command -type ToolMSIX struct { - Common - - // Project configuration - ConfigPath string `name:"config" description:"Path to the project configuration file" default:"wails.json"` - - // MSIX package information - Publisher string `name:"publisher" description:"Publisher name for the MSIX package (e.g., CN=CompanyName)" default:""` - - // Certificate for signing - CertificatePath string `name:"cert" description:"Path to the certificate file for signing the MSIX package" default:""` - CertificatePassword string `name:"cert-password" description:"Password for the certificate file" default:""` - - // Build options - Arch string `name:"arch" description:"Architecture of the package (x64, x86, arm64)" default:"x64"` - ExecutableName string `name:"name" description:"Name of the executable in the package" default:""` - ExecutablePath string `name:"executable" description:"Path to the executable file to package" default:""` - OutputPath string `name:"out" description:"Path where the MSIX package will be saved" default:""` - - // Tool selection - UseMsixPackagingTool bool `name:"use-msix-tool" description:"Use the Microsoft MSIX Packaging Tool for packaging" default:"false"` - UseMakeAppx bool `name:"use-makeappx" description:"Use MakeAppx.exe for packaging" default:"true"` -} diff --git a/v3/internal/flags/package.go b/v3/internal/flags/package.go deleted file mode 100644 index bd56107c5..000000000 --- a/v3/internal/flags/package.go +++ /dev/null @@ -1,13 +0,0 @@ -package flags - -// ToolPackage represents the options for the package command -type ToolPackage struct { - Common - - Format string `name:"format" description:"Package format to generate (deb, rpm, archlinux, dmg)" default:"deb"` - ExecutableName string `name:"name" description:"Name of the executable to package" default:"myapp"` - ConfigPath string `name:"config" description:"Path to the package configuration file" default:""` - Out string `name:"out" description:"Path to the output dir" default:"."` - BackgroundImage string `name:"background" description:"Path to an optional background image for the DMG" default:""` - CreateDMG bool `name:"create-dmg" description:"Create a DMG file (macOS only)" default:"false"` -} diff --git a/v3/internal/flags/service.go b/v3/internal/flags/service.go deleted file mode 100644 index f7fd8ec2e..000000000 --- a/v3/internal/flags/service.go +++ /dev/null @@ -1,14 +0,0 @@ -package flags - -type ServiceInit struct { - Name string `name:"n" description:"Name of service" default:"example_service"` - Description string `name:"d" description:"Description of service" default:"Example service"` - PackageName string `name:"p" description:"Package name for service" default:""` - OutputDir string `name:"o" description:"Output directory" default:"."` - Quiet bool `name:"q" description:"Suppress output to console"` - Author string `name:"a" description:"Author of service" default:""` - Version string `name:"v" description:"Version of service" default:""` - Website string `name:"w" description:"Website of service" default:""` - Repository string `name:"r" description:"Repository of service" default:""` - License string `name:"l" description:"License of service" default:""` -} diff --git a/v3/internal/flags/sign.go b/v3/internal/flags/sign.go deleted file mode 100644 index 9e8442405..000000000 --- a/v3/internal/flags/sign.go +++ /dev/null @@ -1,26 +0,0 @@ -package flags - -// Sign contains flags for the sign command -type Sign struct { - Input string `name:"input" description:"Path to the file to sign"` - Output string `name:"output" description:"Output path (optional, defaults to in-place signing)"` - Verbose bool `name:"verbose" description:"Enable verbose output"` - - // Windows/macOS certificate signing - Certificate string `name:"certificate" description:"Path to PKCS#12 (.pfx/.p12) certificate file"` - Password string `name:"password" description:"Certificate password (reads from keychain if not provided)"` - Thumbprint string `name:"thumbprint" description:"Certificate thumbprint in Windows certificate store"` - Timestamp string `name:"timestamp" description:"Timestamp server URL"` - - // macOS specific - Identity string `name:"identity" description:"Signing identity (e.g., 'Developer ID Application: ...')"` - Entitlements string `name:"entitlements" description:"Path to entitlements plist file"` - HardenedRuntime bool `name:"hardened-runtime" description:"Enable hardened runtime (default: true for notarization)"` - Notarize bool `name:"notarize" description:"Submit for Apple notarization after signing"` - KeychainProfile string `name:"keychain-profile" description:"Keychain profile for notarization credentials"` - - // Linux PGP signing - PGPKey string `name:"pgp-key" description:"Path to PGP private key file"` - PGPPassword string `name:"pgp-password" description:"PGP key password (reads from keychain if not provided)"` - Role string `name:"role" description:"DEB signing role (origin, maint, archive, builder)"` -} diff --git a/v3/internal/flags/signing.go b/v3/internal/flags/signing.go deleted file mode 100644 index 72dd71f3c..000000000 --- a/v3/internal/flags/signing.go +++ /dev/null @@ -1,9 +0,0 @@ -package flags - -type SigningSetup struct { - Platforms []string `name:"platform" description:"Platform(s) to configure (darwin, windows, linux). If not specified, auto-detects from build directory."` -} - -type EntitlementsSetup struct { - Output string `name:"output" description:"Output path for entitlements.plist (default: build/darwin/entitlements.plist)"` -} diff --git a/v3/internal/flags/task_wrapper.go b/v3/internal/flags/task_wrapper.go deleted file mode 100644 index d77535f6c..000000000 --- a/v3/internal/flags/task_wrapper.go +++ /dev/null @@ -1,17 +0,0 @@ -package flags - -type Build struct { - Common -} - -type Dev struct { - Common -} - -type Package struct { - Common -} - -type SignWrapper struct { - Common -} diff --git a/v3/internal/generator/.gitignore b/v3/internal/generator/.gitignore deleted file mode 100644 index 3ed83544e..000000000 --- a/v3/internal/generator/.gitignore +++ /dev/null @@ -1,4 +0,0 @@ -.task -node_modules -testdata/output/**/*.got.[jt]s -testdata/output/**/*.got.log diff --git a/v3/internal/generator/README.md b/v3/internal/generator/README.md deleted file mode 100644 index 20b879245..000000000 --- a/v3/internal/generator/README.md +++ /dev/null @@ -1,6 +0,0 @@ -# Generator - -This package contains the static analyser used for parsing Wails projects so that we may: - -- Generate the bindings for the frontend -- Generate Typescript definitions for the structs used by the bindings diff --git a/v3/internal/generator/Taskfile.yaml b/v3/internal/generator/Taskfile.yaml deleted file mode 100644 index 491e426b9..000000000 --- a/v3/internal/generator/Taskfile.yaml +++ /dev/null @@ -1,56 +0,0 @@ -# https://taskfile.dev - -version: "3" - -shopt: [globstar] - -tasks: - clean: - cmds: - - rm -rf ./testdata/output/**/*.got.[jt]s ./testdata/output/**/*.got.log - - test: - cmds: - - go test -count=1 -v . - - task: test:check - - test:analyse: - cmds: - - go test -count=1 -v -run ^TestAnalyser . - - test:constants: - cmds: - - go test -v -count=1 -run ^TestGenerateConstants . - - test:generate: - cmds: - - go test -v -count=1 -run ^TestGenerator . - - task: test:check - - test:regenerate: - cmds: - - cmd: rm -rf ./testdata/output/* - - cmd: go test -v -count=1 -run ^TestGenerator . - ignore_error: true - - task: test:generate - - test:check: - dir: ./testdata - deps: - - install-deps - cmds: - - npx tsc - - npx madge --circular output/ - - install-deps: - internal: true - dir: ./testdata - sources: - - package.json - cmds: - - npm install - - update: - dir: ./testdata - cmds: - - npx npm-check-updates -u diff --git a/v3/internal/generator/analyse.go b/v3/internal/generator/analyse.go deleted file mode 100644 index e3f664496..000000000 --- a/v3/internal/generator/analyse.go +++ /dev/null @@ -1,220 +0,0 @@ -package generator - -import ( - "fmt" - "go/token" - "go/types" - "iter" - - "github.com/wailsapp/wails/v3/internal/generator/config" - "golang.org/x/tools/go/packages" -) - -// FindServices scans the given packages for invocations -// of the NewService function from the Wails application package. -// -// Whenever one is found and the type of its unique argument -// is a valid service type, the corresponding named type object -// is fed into the returned iterator. -// -// Results are deduplicated, i.e. the iterator yields any given object at most once. -func FindServices(pkgs []*packages.Package, systemPaths *config.SystemPaths, logger config.Logger) (iter.Seq[*types.TypeName], types.Object, error) { - type instanceInfo struct { - args *types.TypeList - pos token.Position - } - - type target struct { - obj types.Object - param int - } - - type targetInfo struct { - target - cause token.Position - } - - // instances maps objects (TypeName or Func) to their instance list. - instances := make(map[types.Object][]instanceInfo) - - // owner maps type parameter objects to their parent object (TypeName or Func) - owner := make(map[*types.TypeName]types.Object) - - // scheduled holds the set of type parameters - // that have been already scheduled for analysis, - // for deduplication. - scheduled := make(map[target]bool) - - // registerEvent holds the `application.RegisterEvent` function if found. - var registerEvent types.Object - - // next lists type parameter objects that have yet to be analysed. - var next []targetInfo - - // Initialise instance/owner maps and detect application.NewService. - for _, pkg := range pkgs { - for ident, instance := range pkg.TypesInfo.Instances { - obj := pkg.TypesInfo.Uses[ident] - - // Add to instance map. - objInstances, seen := instances[obj] - instances[obj] = append(objInstances, instanceInfo{ - instance.TypeArgs, - pkg.Fset.Position(ident.Pos()), - }) - - if seen { - continue - } - - // Object seen for the first time: - // add type params to owner map. - var tp *types.TypeParamList - - if t, ok := obj.Type().(interface{ TypeParams() *types.TypeParamList }); ok { - tp = t.TypeParams() - } else { - // Instantiated object has unexpected kind: - // the spec might have changed. - logger.Warningf( - "unexpected instantiation for %s: please report this to Wails maintainers", - types.ObjectString(obj, nil), - ) - continue - } - - // Add type params to owner map. - for i := range tp.Len() { - if param := tp.At(i).Obj(); param != nil { - owner[param] = obj - } - } - - // If this is a named type, process methods. - if recv, ok := obj.Type().(*types.Named); ok && recv.NumMethods() > 0 { - // Register receiver type params. - for i := range recv.NumMethods() { - tp := recv.Method(i).Type().(*types.Signature).RecvTypeParams() - for j := range tp.Len() { - if param := tp.At(j).Obj(); param != nil { - owner[param] = obj - } - } - } - } - - // Detect application.RegisterEvent - if registerEvent == nil && obj.Name() == "RegisterEvent" && obj.Pkg().Path() == systemPaths.ApplicationPackage { - fn, ok := obj.(*types.Func) - if !ok { - return nil, nil, ErrBadApplicationPackage - } - - signature := fn.Type().(*types.Signature) - if signature.Params().Len() != 1 || signature.Results().Len() != 0 || signature.TypeParams().Len() != 1 { - logger.Warningf("application.RegisterService params: %d, results: %d, typeparams: %d", signature.Params().Len(), signature.Results().Len(), signature.TypeParams().Len()) - return nil, nil, ErrBadApplicationPackage - } - - if !types.Identical(signature.Params().At(0).Type(), types.Universe.Lookup("string").Type()) { - logger.Warningf("application.RegisterService parameter type: %v", signature.Params().At(0).Type()) - return nil, nil, ErrBadApplicationPackage - } - - registerEvent = obj - continue - } - - // Detect application.NewService - if len(next) == 0 && obj.Name() == "NewService" && obj.Pkg().Path() == systemPaths.ApplicationPackage { - fn, ok := obj.(*types.Func) - if !ok { - return nil, nil, ErrBadApplicationPackage - } - - signature := fn.Type().(*types.Signature) - if signature.Params().Len() != 1 || signature.Results().Len() != 1 || tp.Len() != 1 { - logger.Warningf("application.NewService params: %d, results: %d, typeparams: %d", signature.Params().Len(), signature.Results().Len(), tp.Len()) - return nil, nil, ErrBadApplicationPackage - } - - // Schedule unique type param for analysis. - tgt := target{obj, 0} - scheduled[tgt] = true - next = append(next, targetInfo{target: tgt}) - continue - } - } - } - - // found tracks service types that have been found so far, for deduplication. - found := make(map[*types.TypeName]bool) - - return func(yield func(*types.TypeName) bool) { - // Process targets. - for len(next) > 0 { - // Pop one target off the next list. - tgt := next[len(next)-1] - next = next[:len(next)-1] - - // Prepare indirect binding message. - indirectMsg := "" - if tgt.cause.IsValid() { - indirectMsg = fmt.Sprintf(" (indirectly bound at %s)", tgt.cause) - } - - for _, instance := range instances[tgt.obj] { - // Retrieve type argument. - serviceType := types.Unalias(instance.args.At(tgt.param)) - - var named *types.Named - - switch t := serviceType.(type) { - case *types.Named: - // Process named type. - named = t.Origin() - - case *types.TypeParam: - // Schedule type parameter for analysis. - newtgt := target{owner[t.Obj()], t.Index()} - if !scheduled[newtgt] { - scheduled[newtgt] = true - - // Retrieve position of call to application.NewService - // that caused this target to be scheduled. - cause := tgt.cause - if !tgt.cause.IsValid() { - // This _is_ a call to application.NewService. - cause = instance.pos - } - - // Push on next list. - next = append(next, targetInfo{newtgt, cause}) - } - continue - - default: - logger.Warningf("%s: ignoring anonymous service type %s%s", instance.pos, serviceType, indirectMsg) - continue - } - - // Reject interfaces and generic types. - if types.IsInterface(named.Underlying()) { - logger.Warningf("%s: ignoring interface service type %s%s", instance.pos, named, indirectMsg) - continue - } else if named.TypeParams() != nil { - logger.Warningf("%s: ignoring generic service type %s%s", instance.pos, named, indirectMsg) - continue - } - - // Record and yield type object. - if !found[named.Obj()] { - found[named.Obj()] = true - if !yield(named.Obj()) { - return - } - } - } - } - }, registerEvent, nil -} diff --git a/v3/internal/generator/analyse_test.go b/v3/internal/generator/analyse_test.go deleted file mode 100644 index 06c593901..000000000 --- a/v3/internal/generator/analyse_test.go +++ /dev/null @@ -1,135 +0,0 @@ -package generator - -import ( - "encoding/json" - "errors" - "go/types" - "os" - "path" - "path/filepath" - "slices" - "testing" - - "github.com/google/go-cmp/cmp" - "github.com/pterm/pterm" - "github.com/wailsapp/wails/v3/internal/generator/config" -) - -func TestAnalyser(t *testing.T) { - type testParams struct { - name string - want []string - events bool - } - - // Gather tests from cases directory. - entries, err := os.ReadDir("testcases") - if err != nil { - t.Fatal(err) - } - - tests := make([]testParams, 0, len(entries)+1) - - for _, entry := range entries { - if !entry.IsDir() { - continue - } - - test := testParams{ - name: entry.Name(), - want: make([]string, 0), - } - - want, err := os.Open(filepath.Join("testcases", entry.Name(), "bound_types.json")) - if err != nil { - if !errors.Is(err, os.ErrNotExist) { - t.Fatal(err) - } - } else { - err = json.NewDecoder(want).Decode(&test.want) - want.Close() - if err != nil { - t.Fatal(err) - } - } - - for i := range test.want { - test.want[i] = path.Clean("github.com/wailsapp/wails/v3/internal/generator/testcases/" + test.name + test.want[i]) - } - slices.Sort(test.want) - - events, err := os.Open(filepath.Join("testcases", entry.Name(), "events.json")) - if err != nil { - if !errors.Is(err, os.ErrNotExist) { - t.Fatal(err) - } - } else { - err = json.NewDecoder(events).Decode(&test.events) - events.Close() - if err != nil { - t.Fatal(err) - } - } - - tests = append(tests, test) - } - - // Add global test. - { - all := testParams{ - name: "...", - } - - for _, test := range tests { - all.want = append(all.want, test.want...) - all.events = all.events || test.events - } - slices.Sort(all.want) - - tests = append(tests, all) - } - - // Resolve system package paths. - systemPaths, err := ResolveSystemPaths(nil) - if err != nil { - t.Fatal(err) - } - - for _, test := range tests { - pkgPattern := "github.com/wailsapp/wails/v3/internal/generator/testcases/" + test.name - - t.Run("pkg="+test.name, func(t *testing.T) { - pkgs, err := LoadPackages(nil, pkgPattern) - if err != nil { - t.Fatal(err) - } - - for _, pkg := range pkgs { - for _, err := range pkg.Errors { - pterm.Warning.Println(err) - } - } - - got := make([]string, 0) - - services, registerService, err := FindServices(pkgs, systemPaths, config.DefaultPtermLogger(nil)) - if err != nil { - t.Error(err) - } - - for obj := range services { - got = append(got, types.TypeString(obj.Type(), nil)) - } - - slices.Sort(got) - - if diff := cmp.Diff(test.want, got); diff != "" { - t.Errorf("Found services mismatch (-want +got):\n%s", diff) - } - - if test.events != (registerService != nil) { - t.Errorf("Found events mismatch: wanted=%t, got=%t", test.events, registerService != nil) - } - }) - } -} diff --git a/v3/internal/generator/collect/_reference/json_marshaler_behaviour.go b/v3/internal/generator/collect/_reference/json_marshaler_behaviour.go deleted file mode 100644 index bc2c99524..000000000 --- a/v3/internal/generator/collect/_reference/json_marshaler_behaviour.go +++ /dev/null @@ -1,166 +0,0 @@ -// This example explores exhaustively the behaviour of encoding/json -// when handling types that implement marshaler interfaces. -// -// When encoding values, encoding/json makes no distinction -// between pointer and base types: -// if the base type implements a marshaler interface, -// be it with plain receiver or pointer receiver, -// json.Marshal picks it up. -// -// json.Marshaler is always preferred to encoding.TextMarshaler, -// without any consideration for the receiver type. -// -// When encoding map keys, on the other hand, -// the map key type must implement encoding.TextMarshaler strictly, -// i.e. if the interface is implemented only for plain receivers, -// pointer keys will not be accepted. -// -// json.Marshaler is ignored in this case, i.e. it makes no difference -// whether the key type implements it or not. -// -// Decoding behaviour w.r.t. unmarshaler types mirrors encoding behaviour. -package main - -import ( - "encoding/json" - "fmt" -) - -type A struct{} -type B struct{} -type C struct{} -type D struct{} -type E struct{} -type F struct{} -type G struct{} -type H struct{} - -type T struct { - A A - Ap *A - B B - Bp *B - C C - Cp *C - D D - Dp *D - E E - Ep *E - F F - Fp *F - G G - Gp *G - H H - Hp *H -} - -type MT struct { - //A map[A]bool // error - //Ap map[*A]bool // error - //B map[B]bool // error - //Bp map[*B]bool // error - C map[C]bool - Cp map[*C]bool - //D map[D]bool // error - Dp map[*D]bool - E map[E]bool - Ep map[*E]bool - //F map[F]bool // error - Fp map[*F]bool - G map[G]bool - Gp map[*G]bool - //H map[H]bool // error - Hp map[*H]bool -} - -func (A) MarshalJSON() ([]byte, error) { - return []byte(`"This is j A"`), nil -} - -func (*B) MarshalJSON() ([]byte, error) { - return []byte(`"This is j *B"`), nil -} - -func (C) MarshalText() ([]byte, error) { - return []byte(`This is t C`), nil -} - -func (*D) MarshalText() ([]byte, error) { - return []byte(`This is t *D`), nil -} - -func (E) MarshalJSON() ([]byte, error) { - return []byte(`"This is j E"`), nil -} - -func (E) MarshalText() ([]byte, error) { - return []byte(`This is t E`), nil -} - -func (F) MarshalJSON() ([]byte, error) { - return []byte(`"This is j F"`), nil -} - -func (*F) MarshalText() ([]byte, error) { - return []byte(`This is t *F`), nil -} - -func (*G) MarshalJSON() ([]byte, error) { - return []byte(`"This is j *G"`), nil -} - -func (G) MarshalText() ([]byte, error) { - return []byte(`This is t G`), nil -} - -func (*H) MarshalJSON() ([]byte, error) { - return []byte(`"This is j *H"`), nil -} - -func (*H) MarshalText() ([]byte, error) { - return []byte(`This is t *H`), nil -} - -func main() { - t := &T{ - A{}, - &A{}, - B{}, - &B{}, - C{}, - &C{}, - D{}, - &D{}, - E{}, - &E{}, - F{}, - &F{}, - G{}, - &G{}, - H{}, - &H{}, - } - enc, err := json.Marshal(t) - fmt.Println(string(enc), err) - - mt := &MT{ - //map[A]bool{A{}: true}, // error - //map[*A]bool{&A{}: true}, // error - //map[B]bool{B{}: true}, // error - //map[*B]bool{&B{}: true}, // error - map[C]bool{C{}: true}, - map[*C]bool{&C{}: true}, - //map[D]bool{D{}: true}, // error - map[*D]bool{&D{}: true}, - map[E]bool{E{}: true}, - map[*E]bool{&E{}: true}, - //map[F]bool{F{}: true}, // error - map[*F]bool{&F{}: true}, - map[G]bool{G{}: true}, - map[*G]bool{&G{}: true}, - //map[H]bool{H{}: true}, // error - map[*H]bool{&H{}: true}, - } - enc, err = json.Marshal(mt) - fmt.Println(string(enc), err) -} diff --git a/v3/internal/generator/collect/collector.go b/v3/internal/generator/collect/collector.go deleted file mode 100644 index 2485c1162..000000000 --- a/v3/internal/generator/collect/collector.go +++ /dev/null @@ -1,119 +0,0 @@ -package collect - -import ( - "go/ast" - "go/types" - "sync" - "sync/atomic" - - "github.com/wailsapp/wails/v3/internal/flags" - "github.com/wailsapp/wails/v3/internal/generator/config" - "golang.org/x/tools/go/packages" -) - -// Scheduler instances provide task scheduling -// for collection activities. -type Scheduler interface { - // Schedule should run the given function according - // to the implementation's preferred strategy. - // - // Scheduled tasks may call Schedule again; - // therefore, if tasks run concurrently, - // the implementation must support concurrent calls. - Schedule(task func()) -} - -// Info instances provide information about either -// a type-checker object, a struct type or a group of declarations. -type Info interface { - Object() types.Object - Type() types.Type - Node() ast.Node -} - -// Collector wraps all bookkeeping data structures that are needed -// to collect data about a set of packages, bindings and models. -type Collector struct { - // pkgs caches packages that have been registered for collection. - pkgs map[*types.Package]*PackageInfo - - // cache caches collected information about type-checker objects - // and declaration groups. Elements are [Info] instances. - cache sync.Map - - // events holds collected information about registered custom events. - events *EventMap - // appVoidType caches the application.Void named type that stands in for the void TS type. - appVoidType atomic.Value - - systemPaths *config.SystemPaths - options *flags.GenerateBindingsOptions - scheduler Scheduler - logger config.Logger -} - -// NewCollector initialises a new Collector instance for the given package set. -func NewCollector(pkgs []*packages.Package, registerEvent types.Object, systemPaths *config.SystemPaths, options *flags.GenerateBindingsOptions, scheduler Scheduler, logger config.Logger) *Collector { - collector := &Collector{ - pkgs: make(map[*types.Package]*PackageInfo, len(pkgs)), - - systemPaths: systemPaths, - options: options, - scheduler: scheduler, - logger: logger, - } - - // Register packages. - for _, pkg := range pkgs { - collector.pkgs[pkg.Types] = newPackageInfo(pkg, collector) - } - - // Initialise event map. - if !options.NoEvents { - collector.events = newEventMap(collector, registerEvent) - } - - return collector -} - -// fromCache returns the cached Info instance associated -// to the given type-checker object or declaration group. -// If none exists, a new one is created. -func (collector *Collector) fromCache(objectOrGroup any) Info { - entry, ok := collector.cache.Load(objectOrGroup) - info, _ := entry.(Info) - - if !ok { - switch x := objectOrGroup.(type) { - case *ast.GenDecl, *ast.ValueSpec, *ast.Field: - info = newGroupInfo(x.(ast.Node)) - - case *types.Const: - info = newConstInfo(collector, x) - - case *types.Func: - info = newMethodInfo(collector, x.Origin()) - - case *types.TypeName: - info = newTypeInfo(collector, x) - - case *types.Var: - if !x.IsField() { - panic("cache lookup for invalid object kind") - } - - info = newFieldInfo(collector, x.Origin()) - - case *types.Struct: - info = newStructInfo(collector, x) - - default: - panic("cache lookup for invalid object kind") - } - - entry, _ = collector.cache.LoadOrStore(objectOrGroup, info) - info, _ = entry.(Info) - } - - return info -} diff --git a/v3/internal/generator/collect/const.go b/v3/internal/generator/collect/const.go deleted file mode 100644 index ad624bdad..000000000 --- a/v3/internal/generator/collect/const.go +++ /dev/null @@ -1,104 +0,0 @@ -package collect - -import ( - "go/ast" - "go/constant" - "go/token" - "go/types" - "sync" -) - -// ConstInfo records information about a constant declaration. -// -// Read accesses to any public field are only safe -// if a call to [ConstInfo.Collect] has completed before the access, -// for example by calling it in the accessing goroutine -// or before spawning the accessing goroutine. -type ConstInfo struct { - Name string - Value any - - Pos token.Pos - Spec *GroupInfo - Decl *GroupInfo - - obj *types.Const - node ast.Node - - collector *Collector - once sync.Once -} - -func newConstInfo(collector *Collector, obj *types.Const) *ConstInfo { - return &ConstInfo{ - obj: obj, - collector: collector, - } -} - -// Const returns the unique ConstInfo instance -// associated to the given object within a collector. -// -// Const is safe for concurrent use. -func (collector *Collector) Const(obj *types.Const) *ConstInfo { - return collector.fromCache(obj).(*ConstInfo) -} - -func (info *ConstInfo) Object() types.Object { - return info.obj -} - -func (info *ConstInfo) Type() types.Type { - return info.obj.Type() -} - -func (info *ConstInfo) Node() ast.Node { - return info.Collect().node -} - -// Collect gathers information about the constant described by its receiver. -// It can be called concurrently by multiple goroutines; -// the computation will be performed just once. -// -// Collect returns the receiver for chaining. -// It is safe to call Collect with nil receiver. -// -// After Collect returns, the calling goroutine and all goroutines -// it might spawn afterwards are free to access -// the receiver's fields indefinitely. -func (info *ConstInfo) Collect() *ConstInfo { - if info == nil { - return nil - } - - info.once.Do(func() { - collector := info.collector - - info.Name = info.obj.Name() - info.Value = constant.Val(info.obj.Val()) - - info.Pos = info.obj.Pos() - - path := collector.findDeclaration(info.obj) - if path == nil { - collector.logger.Warningf( - "package %s: const %s: could not find declaration for constant object", - info.obj.Pkg().Path(), - info.Name, - ) - - // Provide dummy groups. - dummyGroup := newGroupInfo(nil).Collect() - info.Spec = dummyGroup - info.Decl = dummyGroup - return - } - - // path shape: *ast.ValueSpec, *ast.GenDecl, *ast.File - info.Spec = collector.fromCache(path[0]).(*GroupInfo).Collect() - info.Decl = collector.fromCache(path[1]).(*GroupInfo).Collect() - info.node = path[0] - }) - - return info -} diff --git a/v3/internal/generator/collect/declaration.go b/v3/internal/generator/collect/declaration.go deleted file mode 100644 index 7f2ccc989..000000000 --- a/v3/internal/generator/collect/declaration.go +++ /dev/null @@ -1,246 +0,0 @@ -package collect - -import ( - "cmp" - "go/ast" - "go/token" - "go/types" - "slices" -) - -// findDeclaration returns the AST spec or declaration -// that defines the given _global_ type-checker object. -// -// Specifically, the first element in the returned slice -// is the relevant spec or declaration, followed by its chain -// of parent nodes up to the declaring [ast.File]. -// -// If no corresponding declaration can be found within -// the set of registered packages, the returned slice is nil. -// -// Resulting node types are as follows: -// - global functions and concrete methods (*types.Func) -// map to *ast.FuncDecl nodes; -// - interface methods from global interfaces (*types.Func) -// map to *ast.Field nodes within their interface expression; -// - struct fields from global structs (*types.Var) -// map to *ast.Field nodes within their struct expression; -// - global constants and variables map to *ast.ValueSpec nodes; -// - global named types map to *ast.TypeSpec nodes; -// - for type parameters, the result is always nil; -// - for local objects defined within functions, -// field types, variable types or field values, -// the result is always nil; -// -// findDeclaration supports unsynchronised concurrent calls. -func (collector *Collector) findDeclaration(obj types.Object) (path []ast.Node) { - pkg := collector.Package(obj.Pkg()).Collect() - if pkg == nil { - return nil - } - - file := findEnclosingFile(pkg.Files, obj.Pos()) - if file == nil { - return nil - } - - // Find enclosing declaration. - decl := findEnclosingNode(file.Decls, obj.Pos()) - if decl == nil { - // Invalid position. - return nil - } - - var gen *ast.GenDecl - - switch d := decl.(type) { - case *ast.FuncDecl: - if obj.Pos() == d.Name.Pos() { - // Object is function. - return []ast.Node{decl, file} - } - - // Ignore local objects defined within function bodies. - return nil - - case *ast.BadDecl: - // What's up?? - return nil - - case *ast.GenDecl: - gen = d - } - - // Handle *ast.GenDecl - - // Find enclosing ast.Spec - spec := findEnclosingNode(gen.Specs, obj.Pos()) - if spec == nil { - // Invalid position. - return nil - } - - var def ast.Expr - - switch s := spec.(type) { - case *ast.ValueSpec: - if s.Names[0].Pos() <= obj.Pos() && obj.Pos() < s.Names[len(s.Names)-1].End() { - // Object is variable or constant. - return []ast.Node{spec, decl, file} - } - - // Ignore local objects defined within variable types/values. - return nil - - case *ast.TypeSpec: - if obj.Pos() == s.Name.Pos() { - // Object is named type. - return []ast.Node{spec, decl, file} - } - - if obj.Pos() < s.Type.Pos() || s.Type.End() <= obj.Pos() { - // Type param or invalid position. - return nil - } - - // Struct or interface field? - def = s.Type - } - - // Handle struct or interface field. - - var iface *ast.InterfaceType - - switch d := def.(type) { - case *ast.StructType: - // Find enclosing field - field := findEnclosingNode(d.Fields.List, obj.Pos()) - if field == nil { - // Invalid position. - return nil - } - - if len(field.Names) == 0 { - // Handle embedded field. - ftype := ast.Unparen(field.Type) - - // Unwrap pointer. - if ptr, ok := ftype.(*ast.StarExpr); ok { - ftype = ast.Unparen(ptr.X) - } - - // Unwrap generic instantiation. - switch t := field.Type.(type) { - case *ast.IndexExpr: - ftype = ast.Unparen(t.X) - case *ast.IndexListExpr: - ftype = ast.Unparen(t.X) - } - - // Unwrap selector. - if sel, ok := ftype.(*ast.SelectorExpr); ok { - ftype = sel.Sel - } - - // ftype must now be an identifier. - if obj.Pos() == ftype.Pos() { - // Object is this embedded field. - return []ast.Node{field, d.Fields, def, spec, decl, file} - } - } else if field.Names[0].Pos() <= obj.Pos() && obj.Pos() < field.Names[len(field.Names)-1].End() { - // Object is one of these fields. - return []ast.Node{field, d.Fields, def, spec, decl, file} - } - - // Ignore local objects defined within field types. - return nil - - case *ast.InterfaceType: - iface = d - - default: - // Other local object or invalid position. - return nil - } - - path = []ast.Node{file, decl, spec, def, iface.Methods} - - // Handle interface method. - for { - field := findEnclosingNode(iface.Methods.List, obj.Pos()) - if field == nil { - // Invalid position. - return nil - } - - path = append(path, field) - - if len(field.Names) == 0 { - // Handle embedded interface. - var ok bool - iface, ok = ast.Unparen(field.Type).(*ast.InterfaceType) - if !ok { - // Not embedded interface, ignore. - return nil - } - - path = append(path, iface, iface.Methods) - // Explore embedded interface. - - } else if field.Names[0].Pos() <= obj.Pos() && obj.Pos() < field.Names[len(field.Names)-1].End() { - // Object is one of these fields. - slices.Reverse(path) - return path - } else { - // Ignore local objects defined within interface method signatures. - return nil - } - } -} - -// findEnclosingFile finds the unique file in files, if any, that encloses the given position. -func findEnclosingFile(files []*ast.File, pos token.Pos) *ast.File { - // Perform a binary search to find the file enclosing the node. - // We can't use findEnclosingNode here because it is less accurate and less efficient with files. - fileIndex, exact := slices.BinarySearchFunc(files, pos, func(f *ast.File, p token.Pos) int { - return cmp.Compare(f.FileStart, p) - }) - - // If exact is true, pkg.Files[fileIndex] is the file we are looking for; - // otherwise, it is the first file whose start position is _after_ obj.Pos(). - if !exact { - fileIndex-- - } - - // When exact is false, the position might lie within an empty segment in between two files. - if fileIndex < 0 || files[fileIndex].FileEnd <= pos { - return nil - } - - return files[fileIndex] -} - -// findEnclosingNode finds the unique node in nodes, if any, -// that encloses the given position. -// -// It uses binary search and therefore expects -// the nodes slice to be sorted in source order. -func findEnclosingNode[S ~[]E, E ast.Node](nodes S, pos token.Pos) (node E) { - // Perform a binary search to find the nearest node. - index, exact := slices.BinarySearchFunc(nodes, pos, func(n E, p token.Pos) int { - return cmp.Compare(n.Pos(), p) - }) - - // If exact is true, nodes[index] is the node we are looking for; - // otherwise, it is the first node whose start position is _after_ pos. - if !exact { - index-- - } - - // When exact is false, the position might lie within an empty segment in between two nodes. - if index < 0 || nodes[index].End() <= pos { - return // zero value, nil in practice. - } - - return nodes[index] -} diff --git a/v3/internal/generator/collect/directive.go b/v3/internal/generator/collect/directive.go deleted file mode 100644 index 05293a640..000000000 --- a/v3/internal/generator/collect/directive.go +++ /dev/null @@ -1,101 +0,0 @@ -package collect - -import ( - "fmt" - "strings" - "unicode" - "unicode/utf8" - - "github.com/wailsapp/wails/v3/internal/flags" -) - -// IsDirective returns true if the given comment -// is a directive of the form //wails: + directive. -func IsDirective(comment string, directive string) bool { - if strings.HasPrefix(comment, "//wails:"+directive) { - length := len("//wails:") + len(directive) - if len(comment) == length { - return true - } - - next, _ := utf8.DecodeRuneInString(comment[length:]) - return unicode.IsSpace(next) - } - - return false -} - -// ParseDirective extracts the argument portion of a //wails: + directive comment. -func ParseDirective(comment string, directive string) string { - rawArg := comment[len("//wails:")+len(directive):] - - if directive != "inject" { - return strings.TrimSpace(rawArg) - } - - // wails:inject requires special parsing: - // do not trim all surrounding space, just the one space - // immediately after the directive name. - _, wsize := utf8.DecodeRuneInString(rawArg) - return rawArg[wsize:] -} - -// ParseCondition parses an optional two-character condition prefix -// for include or inject directives. -// It returns the argument stripped of the prefix and the resulting condition. -// If the condition is malformed, ParseCondition returns a non-nil error. -func ParseCondition(argument string) (string, Condition, error) { - cond, arg, present := strings.Cut(argument, ":") - if !present { - return cond, Condition{true, true, true, true}, nil - } - - if len(cond) != 2 || !strings.ContainsRune("*jt", rune(cond[0])) || !strings.ContainsRune("*ci", rune(cond[1])) { - return argument, - Condition{true, true, true, true}, - fmt.Errorf("invalid condition code '%s': expected format is '(*|j|t)(*|c|i)'", cond) - } - - condition := Condition{true, true, true, true} - - switch cond[0] { - case 'j': - condition.TS = false - case 't': - condition.JS = false - } - - switch cond[1] { - case 'c': - condition.Interfaces = false - case 'i': - condition.Classes = false - } - - return arg, condition, nil -} - -type Condition struct { - JS bool - TS bool - Classes bool - Interfaces bool -} - -// Satisfied returns true when the condition described by the receiver -// is satisfied by the given configuration. -func (cond Condition) Satisfied(options *flags.GenerateBindingsOptions) bool { - if options.TS { - if options.UseInterfaces { - return cond.TS && cond.Interfaces - } else { - return cond.TS && cond.Classes - } - } else { - if options.UseInterfaces { - return cond.JS && cond.Interfaces - } else { - return cond.JS && cond.Classes - } - } -} diff --git a/v3/internal/generator/collect/events.go b/v3/internal/generator/collect/events.go deleted file mode 100644 index 21e7cd7a9..000000000 --- a/v3/internal/generator/collect/events.go +++ /dev/null @@ -1,283 +0,0 @@ -package collect - -import ( - _ "embed" - "go/ast" - "go/constant" - "go/token" - "go/types" - "slices" - "strings" - "sync" - - "golang.org/x/tools/go/ast/astutil" -) - -type ( - // EventMap holds information about a set of custom events - // and their associated data types. - // - // Read accesses to any public field are only safe - // if a call to [EventMap.Collect] has completed before the access, - // for example by calling it in the accessing goroutine - // or before spawning the accessing goroutine. - EventMap struct { - Imports *ImportMap - Defs []*EventInfo - - registerEvent types.Object - collector *Collector - once sync.Once - } - - // EventInfo holds information about a single event definition. - EventInfo struct { - // Name is the name of the event. - Name string - - // Data is the data type the event has been registered with. - // It may be nil in case of conflicting definitions. - Data types.Type - - // Pos records the position - // of the first discovered definition for this event. - Pos token.Position - } -) - -func newEventMap(collector *Collector, registerEvent types.Object) *EventMap { - return &EventMap{ - registerEvent: registerEvent, - collector: collector, - } -} - -// EventMap returns the unique event map associated with the given collector, -// or nil if event collection is disabled. -func (collector *Collector) EventMap() *EventMap { - return collector.events -} - -// Stats returns statistics for this event map. -// It is an error to call stats before a call to [EventMap.Collect] has completed. -func (em *EventMap) Stats() *Stats { - return &Stats{ - NumEvents: len(em.Defs), - } -} - -// Collect gathers information for the event map described by its receiver. -// It can be called concurrently by multiple goroutines; -// the computation will be performed just once. -// -// Collect returns the receiver for chaining. -// It is safe to call Collect with nil receiver. -// -// After Collect returns, the calling goroutine and all goroutines -// it might spawn afterwards are free to access -// the receiver's fields indefinitely. -func (em *EventMap) Collect() *EventMap { - if em == nil { - return nil - } - - em.once.Do(func() { - // XXX: initialise the import map with a fake package. - // At present this works fine; let's hope it doesn't come back and haunt us later. - em.Imports = NewImportMap(&PackageInfo{ - Path: em.collector.systemPaths.InternalPackage, - collector: em.collector, - }) - - if em.registerEvent == nil { - return - } - - var ( - wg sync.WaitGroup - defs sync.Map - ) - - for pkg := range em.collector.Iterate { - if !pkg.IsOrImportsApp { - // Packages that are not, and do not import, the Wails application package - // cannot define any events. - continue - } - - wg.Add(1) - - // Process packages in parallel. - em.collector.scheduler.Schedule(func() { - em.collectEventsInPackage(pkg, &defs) - wg.Done() - }) - } - - wg.Wait() - - // Collect valid events. - em.Defs = slices.Collect(func(yield func(*EventInfo) bool) { - for _, v := range defs.Range { - event := v.(*EventInfo) - if event.Data != nil && !IsParametric(event.Data) { - if !yield(event) { - break - } - } - } - }) - - // Sort by name, ascending. - slices.SortFunc(em.Defs, func(a, b *EventInfo) int { - return strings.Compare(a.Name, b.Name) - }) - - // Record required types. - // This must be done at the end because: - // - [ImportMap.AddType] does not support concurrent calls, and - // - we only know the set of valid events after inspecting all definitions. - for _, def := range em.Defs { - em.Imports.AddType(def.Data) - } - }) - - return em -} - -func (em *EventMap) collectEventsInPackage(pkg *PackageInfo, defs *sync.Map) { - for ident, inst := range pkg.TypesInfo.Instances { - if pkg.TypesInfo.Uses[ident] != em.registerEvent { - continue - } - - file := findEnclosingFile(pkg.Collect().Files, ident.Pos()) - if file == nil { - em.collector.logger.Warningf( - "package %s: found event declaration with no associated source file", - pkg.Path, - ) - continue - } - - path, _ := astutil.PathEnclosingInterval(file, ident.Pos(), ident.End()) - if path[0] != ident { - em.collector.logger.Warningf( - "%v: event declaration not found in source file", - pkg.Fset.Position(ident.Pos()), - ) - continue - } - - // Walk up the path: *ast.Ident -> *ast.SelectorExpr? -> (*ast.IndexExpr | *ast.IndexListExpr)? -> *ast.CallExpr? - path = path[1:] - - if _, ok := path[0].(*ast.SelectorExpr); ok { - path = path[1:] - } - - if _, ok := path[0].(*ast.IndexExpr); ok { - path = path[1:] - } else if _, ok := path[0].(*ast.IndexListExpr); ok { - path = path[1:] - } - - call, ok := path[0].(*ast.CallExpr) - if !ok { - em.collector.logger.Warningf( - "%v: `application.RegisterEvent` is instantiated here but not called", - pkg.Fset.Position(path[0].Pos()), - ) - em.collector.logger.Warningf("events registered through indirect calls are not discoverable by the binding generator: it is recommended to invoke `application.RegisterEvent` directly") - continue - } - - if len(call.Args) == 0 { - // Invalid calls result in compile-time failures and can be ignored safely. - continue - } - - eventName, ok := pkg.TypesInfo.Types[call.Args[0]] - if !ok || !types.AssignableTo(eventName.Type, types.Universe.Lookup("string").Type()) { - // Mistyped calls result in compile-time failures and can be ignored safely. - continue - } - - if eventName.Value == nil { - em.collector.logger.Warningf( - "%v: `application.RegisterEvent` called here with non-constant event name", - pkg.Fset.Position(call.Pos()), - ) - em.collector.logger.Warningf("dynamically registered event names are not discoverable by the binding generator: it is recommended to invoke `application.RegisterEvent` with constant arguments only") - continue - } - - event := &EventInfo{ - Data: inst.TypeArgs.At(0), - Pos: pkg.Fset.Position(call.Pos()), - } - if eventName.Value.Kind() == constant.String { - event.Name = constant.StringVal(eventName.Value) - } else { - event.Name = eventName.Value.ExactString() - } - - if IsKnownEvent(event.Name) { - em.collector.logger.Warningf( - "%v: event '%s' is a known system event and cannot be overridden; this call to `application.RegisterEvent` will panic", - event.Pos, - event.Name, - ) - continue - } - - if v, ok := defs.LoadOrStore(event.Name, event); ok { - prev := v.(*EventInfo) - if prev.Data != nil && !types.Identical(event.Data, prev.Data) { - next := &EventInfo{ - Name: prev.Name, - Pos: prev.Pos, - } - - if defs.CompareAndSwap(prev.Name, prev, next) { - em.collector.logger.Warningf("event '%s' has multiple conflicting definitions and will be ignored", event.Name) - em.collector.logger.Warningf( - "%v: event '%s' has one of multiple definitions here with data type %s", - prev.Pos, - prev.Name, - prev.Data, - ) - } - - prev = next - } - if prev.Data == nil { - em.collector.logger.Warningf( - "%v: event '%s' has one of multiple definitions here with data type %s", - event.Pos, - event.Name, - event.Data, - ) - } - continue - } - - // Emit unsupported type warnings only for first definition - if IsParametric(event.Data) { - em.collector.logger.Warningf( - "%v: data type %s for event '%s' contains unresolved type parameters and will be ignored`", - event.Pos, - event.Data, - event.Name, - ) - em.collector.logger.Warningf("generic wrappers for calls to `application.RegisterEvent` are not analysable by the binding generator: it is recommended to call `application.RegisterEvent` with concrete types only") - } else if types.IsInterface(event.Data) && !types.Identical(event.Data.Underlying(), typeAny) && !em.collector.IsVoidAlias(event.Data) { - em.collector.logger.Warningf( - "%v: data type %s for event '%s' is a non-empty interface: emitting events from the frontend with data other than `null` is not supported by encoding/json and will likely result in runtime errors", - event.Pos, - event.Data, - event.Name, - ) - } - } -} diff --git a/v3/internal/generator/collect/field.go b/v3/internal/generator/collect/field.go deleted file mode 100644 index eed808114..000000000 --- a/v3/internal/generator/collect/field.go +++ /dev/null @@ -1,102 +0,0 @@ -package collect - -import ( - "go/ast" - "go/token" - "go/types" - "sync" -) - -// FieldInfo records information about a struct field declaration. -// -// Read accesses to any public field are only safe -// if a call to [FieldInfo.Collect] has completed before the access, -// for example by calling it in the accessing goroutine -// or before spawning the accessing goroutine. -type FieldInfo struct { - Name string - Blank bool - Embedded bool - - Pos token.Pos - Decl *GroupInfo - - obj *types.Var - node ast.Node - - collector *Collector - once sync.Once -} - -// newFieldInfo initialises a descriptor for the given field object. -func newFieldInfo(collector *Collector, obj *types.Var) *FieldInfo { - return &FieldInfo{ - obj: obj, - collector: collector, - } -} - -// Field returns the unique FieldInfo instance -// associated to the given object within a collector. -// -// Field is safe for concurrent use. -func (collector *Collector) Field(obj *types.Var) *FieldInfo { - if !obj.IsField() { - return nil - } - - return collector.fromCache(obj).(*FieldInfo) -} - -func (info *FieldInfo) Object() types.Object { - return info.obj -} - -func (info *FieldInfo) Type() types.Type { - return info.obj.Type() -} - -func (info *FieldInfo) Node() ast.Node { - return info.Collect().node -} - -// Collect gathers information about the struct field -// described by its receiver. -// It can be called concurrently by multiple goroutines; -// the computation will be performed just once. -// -// Collect returns the receiver for chaining. -// It is safe to call Collect with nil receiver. -// -// After Collect returns, the calling goroutine and all goroutines -// it might spawn afterwards are free to access -// the receiver's fields indefinitely. -func (info *FieldInfo) Collect() *FieldInfo { - if info == nil { - return nil - } - - info.once.Do(func() { - collector := info.collector - - info.Name = info.obj.Name() - info.Blank = (info.Name == "" || info.Name == "_") - info.Embedded = info.obj.Embedded() - - info.Pos = info.obj.Pos() - - path := collector.findDeclaration(info.obj) - if path == nil { - // Do not report failure: it is expected for anonymous struct fields. - // Provide dummy group. - info.Decl = newGroupInfo(nil).Collect() - return - } - - // path shape: *ast.Field, *ast.FieldList, ... - info.Decl = collector.fromCache(path[0]).(*GroupInfo).Collect() - info.node = path[0] - }) - - return info -} diff --git a/v3/internal/generator/collect/group.go b/v3/internal/generator/collect/group.go deleted file mode 100644 index 62d83304c..000000000 --- a/v3/internal/generator/collect/group.go +++ /dev/null @@ -1,95 +0,0 @@ -package collect - -import ( - "go/ast" - "go/token" - "go/types" - "slices" - "sync" -) - -// GroupInfo records information about a group -// of type, field or constant declarations. -// This may be either a list of distinct specifications -// wrapped in parentheses, or a single specification -// declaring multiple fields or constants. -// -// Read accesses to any public field are only safe -// if a call to [GroupInfo.Collect] has completed before the access, -// for example by calling it in the accessing goroutine -// or before spawning the accessing goroutine. -type GroupInfo struct { - Pos token.Pos - Doc *ast.CommentGroup - - node ast.Node - - once sync.Once -} - -func newGroupInfo(node ast.Node) *GroupInfo { - return &GroupInfo{ - node: node, - } -} - -func (*GroupInfo) Object() types.Object { - return nil -} - -func (*GroupInfo) Type() types.Type { - return nil -} - -func (info *GroupInfo) Node() ast.Node { - return info.node -} - -// Collect gathers information about the declaration group -// described by its receiver. -// It can be called concurrently by multiple goroutines; -// the computation will be performed just once. -// -// Collect returns the receiver for chaining. -// It is safe to call Collect with nil receiver. -// -// After Collect returns, the calling goroutine and all goroutines -// it might spawn afterwards are free to access -// the receiver's fields indefinitely. -func (info *GroupInfo) Collect() *GroupInfo { - if info == nil { - return nil - } - - info.once.Do(func() { - switch n := info.node.(type) { - case *ast.GenDecl: - info.Pos = n.Pos() - info.Doc = n.Doc - - case *ast.ValueSpec: - info.Pos = n.Pos() - info.Doc = n.Doc - if info.Doc == nil { - info.Doc = n.Comment - } else if n.Comment != nil { - info.Doc = &ast.CommentGroup{ - List: slices.Concat(n.Doc.List, n.Comment.List), - } - } - - case *ast.Field: - info.Pos = n.Pos() - info.Doc = n.Doc - if info.Doc == nil { - info.Doc = n.Comment - } else if n.Comment != nil { - info.Doc = &ast.CommentGroup{ - List: slices.Concat(n.Doc.List, n.Comment.List), - } - } - } - }) - - return info -} diff --git a/v3/internal/generator/collect/imports.go b/v3/internal/generator/collect/imports.go deleted file mode 100644 index e7777ab23..000000000 --- a/v3/internal/generator/collect/imports.go +++ /dev/null @@ -1,287 +0,0 @@ -package collect - -import ( - "go/types" - "path/filepath" -) - -type ( - // ImportMap records deduplicated imports by a binding or models module. - // It computes relative import paths and assigns import names, - // taking care to avoid collisions. - ImportMap struct { - // Self records the path of the importing package. - Self string - - // ImportModels records whether models from the current package may be needed. - ImportModels bool - - // External records information about each imported package, - // keyed by package path. - External map[string]ImportInfo - - // counters holds the occurence count for each package name in External. - counters map[string]int - collector *Collector - } - - // ImportInfo records information about a single import. - ImportInfo struct { - Name string - Index int // Progressive number for identically named imports, starting from 0 for each distinct name. - RelPath string - } -) - -// NewImportMap initialises an import map for the given importer package. -// The argument may be nil, in which case import paths will be relative -// to the root output directory. -func NewImportMap(importer *PackageInfo) *ImportMap { - var ( - self string - collector *Collector - ) - if importer != nil { - self = importer.Path - collector = importer.collector - } - - return &ImportMap{ - Self: self, - - External: make(map[string]ImportInfo), - - counters: make(map[string]int), - collector: collector, - } -} - -// Merge merges the given import map into the receiver. -// The importing package must be the same. -func (imports *ImportMap) Merge(other *ImportMap) { - if other.Self != imports.Self { - panic("cannot merge import maps with different importing package") - } - - if other.ImportModels { - imports.ImportModels = true - } - - for path, info := range other.External { - if _, ok := imports.External[path]; ok { - continue - } - - counter := imports.counters[info.Name] - imports.counters[info.Name] = counter + 1 - - imports.External[path] = ImportInfo{ - Name: info.Name, - Index: counter, - RelPath: info.RelPath, - } - } -} - -// Add adds the given package to the import map if not already present, -// choosing import names so as to avoid collisions. -// -// Add does not support unsynchronised concurrent calls -// on the same receiver. -func (imports *ImportMap) Add(pkg *PackageInfo) { - if pkg.Path == imports.Self { - // Do not import self. - return - } - - if imports.External[pkg.Path].Name != "" { - // Package already imported. - return - } - - // Fetch and update counter for name. - counter := imports.counters[pkg.Name] - imports.counters[pkg.Name] = counter + 1 - - // Always add counters to - imports.External[pkg.Path] = ImportInfo{ - Name: pkg.Name, - Index: counter, - RelPath: computeImportPath(imports.Self, pkg.Path), - } -} - -// AddType adds all dependencies of the given type to the import map -// and marks all referenced named types as models. -// -// It is a runtime error to call AddType on an ImportMap -// created with nil importing package. -// -// AddType does not support unsynchronised concurrent calls -// on the same receiver. -func (imports *ImportMap) AddType(typ types.Type) { - imports.addTypeImpl(typ, make(map[*types.TypeName]bool)) -} - -// addTypeImpl provides the actual implementation of AddType. -// The visited parameter is used to break cycles. -func (imports *ImportMap) addTypeImpl(typ types.Type, visited map[*types.TypeName]bool) { - collector := imports.collector - if collector == nil { - panic("AddType called on ImportMap with nil collector") - } - - for { // Avoid recursion where possible. - switch t := typ.(type) { - case *types.Alias, *types.Named: - obj := typ.(interface{ Obj() *types.TypeName }).Obj() - if obj.Pkg() == nil { - // Ignore universe type. - return - } - - if visited[obj] { - // Break type cycles. - return - } - visited[obj] = true - - // Special case: application.Void will render as TS void hence no dependencies and no model - if collector.IsVoidAlias(obj) { - return - } - - if obj.Pkg().Path() == imports.Self { - imports.ImportModels = true - } - - // Record model. - imports.collector.Model(obj) - - // Import parent package. - imports.Add(collector.Package(obj.Pkg())) - - instance, _ := typ.(interface{ TypeArgs() *types.TypeList }) - if instance != nil { - // Record type argument dependencies. - if targs := instance.TypeArgs(); targs != nil { - for i := range targs.Len() { - imports.addTypeImpl(targs.At(i), visited) - } - } - } - - if collector.options.UseInterfaces { - // No creation/initialisation code required. - return - } - - if _, isAlias := typ.(*types.Alias); isAlias { - // Aliased type might be needed during - // JS value creation and initialisation. - typ = types.Unalias(typ) - break - } - - if IsClass(typ) || IsAny(typ) || IsStringAlias(typ) { - return - } - - // If named type does not map to a class, unknown type or string, - // its underlying type may be needed during JS value creation. - typ = typ.Underlying() - - case *types.Basic: - switch { - case t.Info()&(types.IsBoolean|types.IsInteger|types.IsUnsigned|types.IsFloat|types.IsString) != 0: - break - case t.Info()&types.IsComplex != 0: - collector.logger.Warningf("package %s: complex types are not supported by encoding/json", imports.Self) - default: - collector.logger.Warningf("package %s: unknown basic type %s: please report this to Wails maintainers", imports.Self, typ) - } - return - - case *types.Array, *types.Pointer, *types.Slice: - typ = typ.(interface{ Elem() types.Type }).Elem() - - case *types.Chan: - collector.logger.Warningf("package %s: channel types are not supported by encoding/json", imports.Self) - return - - case *types.Map: - if IsMapKey(t.Key()) { - if IsStringAlias(t.Key()) || IsNumberAlias(t.Key()) { - // This model type is always rendered as a string alias, - // hence we can generate it and use it as a type for JS object keys. - imports.addTypeImpl(t.Key(), visited) - } - } else if IsTypeParam(t.Key()) { - // In some cases, type params or pointers to type params - // may be valid as map keys, but not for all instantiations. - // When that happens, emit a softer warning. - collector.logger.Warningf( - "package %s: type %s is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors", - imports.Self, types.TypeString(t.Key(), nil), - ) - } else { - collector.logger.Warningf( - "package %s: type %s is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors", - imports.Self, types.TypeString(t.Key(), nil), - ) - } - - typ = t.Elem() - - case *types.Signature: - collector.logger.Warningf("package %s: function types are not supported by encoding/json", imports.Self) - return - - case *types.Struct: - if t.NumFields() == 0 || MaybeJSONMarshaler(typ) != NonMarshaler || MaybeTextMarshaler(typ) != NonMarshaler { - // Struct is empty, or marshals to custom JSON (any) or string. - return - } - - // Retrieve struct info and ensure it is complete. - info := collector.Struct(t).Collect() - - if len(info.Fields) == 0 { - // No visible fields. - return - } - - // Add field dependencies. - for i := range len(info.Fields) - 1 { - imports.addTypeImpl(info.Fields[i].Type, visited) - } - - // Process last field without recursion. - typ = info.Fields[len(info.Fields)-1].Type - - case *types.Interface, *types.TypeParam: - // No dependencies. - return - - default: - collector.logger.Warningf("package %s: unknown or unexpected type %s: please report this to Wails maintainers", imports.Self, typ) - return - } - } -} - -// computeImportPath returns the shortest relative import path -// through which the importer package can reference the imported one. -func computeImportPath(importer string, imported string) string { - rel, err := filepath.Rel(importer, imported) - if err != nil { - panic(err) - } - - rel = filepath.ToSlash(rel) - if rel[0] == '.' { - return rel - } else { - return "./" + rel - } -} diff --git a/v3/internal/generator/collect/index.go b/v3/internal/generator/collect/index.go deleted file mode 100644 index ae4d31240..000000000 --- a/v3/internal/generator/collect/index.go +++ /dev/null @@ -1,121 +0,0 @@ -package collect - -import ( - "slices" - "strings" -) - -// PackageIndex lists all services, models and unexported models -// to be generated from a single package. -// -// When obtained through a call to [PackageInfo.Index], -// each service and model appears at most once; -// services and models are sorted -// by internal property (all exported first), then by name. -type PackageIndex struct { - Package *PackageInfo - - Services []*ServiceInfo - HasExportedServices bool // If true, there is at least one exported service. - - Models []*ModelInfo - HasExportedModels bool // If true, there is at least one exported model. -} - -// Index computes a [PackageIndex] for the selected language from the list -// of generated services and models and regenerates cached stats. -// -// Services and models appear at most once in the returned slices; -// services are sorted by name; -// exported models precede all unexported ones -// and both ranges are sorted by name. -// -// Index calls info.Collect, and therefore provides the same guarantees. -// It is safe for concurrent use. -func (info *PackageInfo) Index(TS bool) (index *PackageIndex) { - // Init index. - index = &PackageIndex{ - Package: info.Collect(), - } - - // Init stats - stats := &Stats{ - NumPackages: 1, - } - - // Gather services. - for _, value := range info.services.Range { - service := value.(*ServiceInfo) - if !service.IsEmpty() { - index.Services = append(index.Services, service) - // Mark presence of exported services - if !service.Internal { - index.HasExportedServices = true - } - // Update service stats. - stats.NumServices++ - stats.NumMethods += len(service.Methods) - } - } - - // Sort services by internal property (exported first), then by name. - slices.SortFunc(index.Services, func(s1 *ServiceInfo, s2 *ServiceInfo) int { - if s1 == s2 { - return 0 - } - - if s1.Internal != s2.Internal { - if s1.Internal { - return 1 - } else { - return -1 - } - } - - return strings.Compare(s1.Name, s2.Name) - }) - - // Gather models. - for _, value := range info.models.Range { - model := value.(*ModelInfo) - index.Models = append(index.Models, model) - // Mark presence of exported models - if !model.Internal { - index.HasExportedModels = true - } - // Update model stats. - if len(model.Values) > 0 { - stats.NumEnums++ - } else { - stats.NumModels++ - } - } - - // Sort models by internal property (exported first), then by name. - slices.SortFunc(index.Models, func(m1 *ModelInfo, m2 *ModelInfo) int { - if m1 == m2 { - return 0 - } - - if m1.Internal != m2.Internal { - if m1.Internal { - return 1 - } else { - return -1 - } - } - - return strings.Compare(m1.Name, m2.Name) - }) - - // Cache stats - info.stats.Store(stats) - - return -} - -// IsEmpty returns true if the given index -// contains no data for the selected language. -func (index *PackageIndex) IsEmpty() bool { - return !index.HasExportedServices && !index.HasExportedModels && len(index.Package.Injections) == 0 -} diff --git a/v3/internal/generator/collect/known_events.go b/v3/internal/generator/collect/known_events.go deleted file mode 100644 index 857071585..000000000 --- a/v3/internal/generator/collect/known_events.go +++ /dev/null @@ -1,222 +0,0 @@ -package collect - -func IsKnownEvent(name string) bool { - _, ok := knownEvents[name] - return ok -} - -var knownEvents = map[string]struct{}{ - "common:ApplicationOpenedWithFile": {}, - "common:ApplicationStarted": {}, - "common:ApplicationLaunchedWithUrl": {}, - "common:ThemeChanged": {}, - "common:WindowClosing": {}, - "common:WindowDidMove": {}, - "common:WindowDidResize": {}, - "common:WindowDPIChanged": {}, - "common:WindowFilesDropped": {}, - "common:WindowFocus": {}, - "common:WindowFullscreen": {}, - "common:WindowHide": {}, - "common:WindowLostFocus": {}, - "common:WindowMaximise": {}, - "common:WindowMinimise": {}, - "common:WindowToggleFrameless": {}, - "common:WindowRestore": {}, - "common:WindowRuntimeReady": {}, - "common:WindowShow": {}, - "common:WindowUnFullscreen": {}, - "common:WindowUnMaximise": {}, - "common:WindowUnMinimise": {}, - "common:WindowZoom": {}, - "common:WindowZoomIn": {}, - "common:WindowZoomOut": {}, - "common:WindowZoomReset": {}, - "linux:ApplicationStartup": {}, - "linux:SystemThemeChanged": {}, - "linux:WindowDeleteEvent": {}, - "linux:WindowDidMove": {}, - "linux:WindowDidResize": {}, - "linux:WindowFocusIn": {}, - "linux:WindowFocusOut": {}, - "linux:WindowLoadStarted": {}, - "linux:WindowLoadRedirected": {}, - "linux:WindowLoadCommitted": {}, - "linux:WindowLoadFinished": {}, - "mac:ApplicationDidBecomeActive": {}, - "mac:ApplicationDidChangeBackingProperties": {}, - "mac:ApplicationDidChangeEffectiveAppearance": {}, - "mac:ApplicationDidChangeIcon": {}, - "mac:ApplicationDidChangeOcclusionState": {}, - "mac:ApplicationDidChangeScreenParameters": {}, - "mac:ApplicationDidChangeStatusBarFrame": {}, - "mac:ApplicationDidChangeStatusBarOrientation": {}, - "mac:ApplicationDidChangeTheme": {}, - "mac:ApplicationDidFinishLaunching": {}, - "mac:ApplicationDidHide": {}, - "mac:ApplicationDidResignActive": {}, - "mac:ApplicationDidUnhide": {}, - "mac:ApplicationDidUpdate": {}, - "mac:ApplicationShouldHandleReopen": {}, - "mac:ApplicationWillBecomeActive": {}, - "mac:ApplicationWillFinishLaunching": {}, - "mac:ApplicationWillHide": {}, - "mac:ApplicationWillResignActive": {}, - "mac:ApplicationWillTerminate": {}, - "mac:ApplicationWillUnhide": {}, - "mac:ApplicationWillUpdate": {}, - "mac:MenuDidAddItem": {}, - "mac:MenuDidBeginTracking": {}, - "mac:MenuDidClose": {}, - "mac:MenuDidDisplayItem": {}, - "mac:MenuDidEndTracking": {}, - "mac:MenuDidHighlightItem": {}, - "mac:MenuDidOpen": {}, - "mac:MenuDidPopUp": {}, - "mac:MenuDidRemoveItem": {}, - "mac:MenuDidSendAction": {}, - "mac:MenuDidSendActionToItem": {}, - "mac:MenuDidUpdate": {}, - "mac:MenuWillAddItem": {}, - "mac:MenuWillBeginTracking": {}, - "mac:MenuWillDisplayItem": {}, - "mac:MenuWillEndTracking": {}, - "mac:MenuWillHighlightItem": {}, - "mac:MenuWillOpen": {}, - "mac:MenuWillPopUp": {}, - "mac:MenuWillRemoveItem": {}, - "mac:MenuWillSendAction": {}, - "mac:MenuWillSendActionToItem": {}, - "mac:MenuWillUpdate": {}, - "mac:WebViewDidCommitNavigation": {}, - "mac:WebViewDidFinishNavigation": {}, - "mac:WebViewDidReceiveServerRedirectForProvisionalNavigation": {}, - "mac:WebViewDidStartProvisionalNavigation": {}, - "mac:WindowDidBecomeKey": {}, - "mac:WindowDidBecomeMain": {}, - "mac:WindowDidBeginSheet": {}, - "mac:WindowDidChangeAlpha": {}, - "mac:WindowDidChangeBackingLocation": {}, - "mac:WindowDidChangeBackingProperties": {}, - "mac:WindowDidChangeCollectionBehavior": {}, - "mac:WindowDidChangeEffectiveAppearance": {}, - "mac:WindowDidChangeOcclusionState": {}, - "mac:WindowDidChangeOrderingMode": {}, - "mac:WindowDidChangeScreen": {}, - "mac:WindowDidChangeScreenParameters": {}, - "mac:WindowDidChangeScreenProfile": {}, - "mac:WindowDidChangeScreenSpace": {}, - "mac:WindowDidChangeScreenSpaceProperties": {}, - "mac:WindowDidChangeSharingType": {}, - "mac:WindowDidChangeSpace": {}, - "mac:WindowDidChangeSpaceOrderingMode": {}, - "mac:WindowDidChangeTitle": {}, - "mac:WindowDidChangeToolbar": {}, - "mac:WindowDidDeminiaturize": {}, - "mac:WindowDidEndSheet": {}, - "mac:WindowDidEnterFullScreen": {}, - "mac:WindowDidEnterVersionBrowser": {}, - "mac:WindowDidExitFullScreen": {}, - "mac:WindowDidExitVersionBrowser": {}, - "mac:WindowDidExpose": {}, - "mac:WindowDidFocus": {}, - "mac:WindowDidMiniaturize": {}, - "mac:WindowDidMove": {}, - "mac:WindowDidOrderOffScreen": {}, - "mac:WindowDidOrderOnScreen": {}, - "mac:WindowDidResignKey": {}, - "mac:WindowDidResignMain": {}, - "mac:WindowDidResize": {}, - "mac:WindowDidUpdate": {}, - "mac:WindowDidUpdateAlpha": {}, - "mac:WindowDidUpdateCollectionBehavior": {}, - "mac:WindowDidUpdateCollectionProperties": {}, - "mac:WindowDidUpdateShadow": {}, - "mac:WindowDidUpdateTitle": {}, - "mac:WindowDidUpdateToolbar": {}, - "mac:WindowDidZoom": {}, - "mac:WindowFileDraggingEntered": {}, - "mac:WindowFileDraggingExited": {}, - "mac:WindowFileDraggingPerformed": {}, - "mac:WindowHide": {}, - "mac:WindowMaximise": {}, - "mac:WindowUnMaximise": {}, - "mac:WindowMinimise": {}, - "mac:WindowUnMinimise": {}, - "mac:WindowShouldClose": {}, - "mac:WindowShow": {}, - "mac:WindowWillBecomeKey": {}, - "mac:WindowWillBecomeMain": {}, - "mac:WindowWillBeginSheet": {}, - "mac:WindowWillChangeOrderingMode": {}, - "mac:WindowWillClose": {}, - "mac:WindowWillDeminiaturize": {}, - "mac:WindowWillEnterFullScreen": {}, - "mac:WindowWillEnterVersionBrowser": {}, - "mac:WindowWillExitFullScreen": {}, - "mac:WindowWillExitVersionBrowser": {}, - "mac:WindowWillFocus": {}, - "mac:WindowWillMiniaturize": {}, - "mac:WindowWillMove": {}, - "mac:WindowWillOrderOffScreen": {}, - "mac:WindowWillOrderOnScreen": {}, - "mac:WindowWillResignMain": {}, - "mac:WindowWillResize": {}, - "mac:WindowWillUnfocus": {}, - "mac:WindowWillUpdate": {}, - "mac:WindowWillUpdateAlpha": {}, - "mac:WindowWillUpdateCollectionBehavior": {}, - "mac:WindowWillUpdateCollectionProperties": {}, - "mac:WindowWillUpdateShadow": {}, - "mac:WindowWillUpdateTitle": {}, - "mac:WindowWillUpdateToolbar": {}, - "mac:WindowWillUpdateVisibility": {}, - "mac:WindowWillUseStandardFrame": {}, - "mac:WindowZoomIn": {}, - "mac:WindowZoomOut": {}, - "mac:WindowZoomReset": {}, - "windows:APMPowerSettingChange": {}, - "windows:APMPowerStatusChange": {}, - "windows:APMResumeAutomatic": {}, - "windows:APMResumeSuspend": {}, - "windows:APMSuspend": {}, - "windows:ApplicationStarted": {}, - "windows:SystemThemeChanged": {}, - "windows:WebViewNavigationCompleted": {}, - "windows:WindowActive": {}, - "windows:WindowBackgroundErase": {}, - "windows:WindowClickActive": {}, - "windows:WindowClosing": {}, - "windows:WindowDidMove": {}, - "windows:WindowDidResize": {}, - "windows:WindowDPIChanged": {}, - "windows:WindowDragDrop": {}, - "windows:WindowDragEnter": {}, - "windows:WindowDragLeave": {}, - "windows:WindowDragOver": {}, - "windows:WindowEndMove": {}, - "windows:WindowEndResize": {}, - "windows:WindowFullscreen": {}, - "windows:WindowHide": {}, - "windows:WindowInactive": {}, - "windows:WindowKeyDown": {}, - "windows:WindowKeyUp": {}, - "windows:WindowKillFocus": {}, - "windows:WindowNonClientHit": {}, - "windows:WindowNonClientMouseDown": {}, - "windows:WindowNonClientMouseLeave": {}, - "windows:WindowNonClientMouseMove": {}, - "windows:WindowNonClientMouseUp": {}, - "windows:WindowPaint": {}, - "windows:WindowRestore": {}, - "windows:WindowSetFocus": {}, - "windows:WindowShow": {}, - "windows:WindowStartMove": {}, - "windows:WindowStartResize": {}, - "windows:WindowUnFullscreen": {}, - "windows:WindowZOrderChanged": {}, - "windows:WindowMinimise": {}, - "windows:WindowUnMinimise": {}, - "windows:WindowMaximise": {}, - "windows:WindowUnMaximise": {}, -} diff --git a/v3/internal/generator/collect/method.go b/v3/internal/generator/collect/method.go deleted file mode 100644 index adff7aaaa..000000000 --- a/v3/internal/generator/collect/method.go +++ /dev/null @@ -1,115 +0,0 @@ -package collect - -import ( - "go/ast" - "go/types" - "sync" -) - -// MethodInfo records information about a method declaration. -// -// Read accesses to any public field are only safe -// if a call to [MethodInfo.Collect] has completed before the access, -// for example by calling it in the accessing goroutine -// or before spawning the accessing goroutine. -type MethodInfo struct { - Name string - - // Abstract is true when the described method belongs to an interface. - Abstract bool - - Doc *ast.CommentGroup - Decl *GroupInfo - - obj *types.Func - node ast.Node - - collector *Collector - once sync.Once -} - -func newMethodInfo(collector *Collector, obj *types.Func) *MethodInfo { - return &MethodInfo{ - obj: obj, - collector: collector, - } -} - -// Method returns the unique MethodInfo instance -// associated to the given object within a collector. -// -// Method is safe for concurrent use. -func (collector *Collector) Method(obj *types.Func) *MethodInfo { - return collector.fromCache(obj).(*MethodInfo) -} - -func (info *MethodInfo) Object() types.Object { - return info.obj -} - -func (info *MethodInfo) Type() types.Type { - return info.obj.Type() -} - -func (info *MethodInfo) Node() ast.Node { - return info.Collect().node -} - -// Collect gathers information about the method described by its receiver. -// It can be called concurrently by multiple goroutines; -// the computation will be performed just once. -// -// Collect returns the receiver for chaining. -// It is safe to call Collect with nil receiver. -// -// After Collect returns, the calling goroutine and all goroutines -// it might spawn afterwards are free to access -// the receiver's fields indefinitely. -func (info *MethodInfo) Collect() *MethodInfo { - if info == nil { - return nil - } - - info.once.Do(func() { - collector := info.collector - - info.Name = info.obj.Name() - - path := collector.findDeclaration(info.obj) - if path == nil { - recv := "" - if info.obj.Type() != nil { - recv = info.obj.Type().(*types.Signature).Recv().Type().String() + "." - } - - collector.logger.Warningf( - "package %s: method %s%s: could not find declaration for method object", - info.obj.Pkg().Path(), - recv, - info.obj.Name(), - ) - - // Provide dummy group. - info.Decl = newGroupInfo(nil).Collect() - return - } - - // path shape: *ast.FuncDecl/*ast.Field, ... - info.node = path[0] - - // Retrieve doc comments. - switch n := info.node.(type) { - case *ast.FuncDecl: - // Concrete method. - info.Doc = n.Doc - info.Decl = newGroupInfo(nil).Collect() // Provide dummy group. - - case *ast.Field: - // Abstract method. - info.Abstract = true - info.Decl = newGroupInfo(path[0]).Collect() - } - }) - - return info -} diff --git a/v3/internal/generator/collect/model.go b/v3/internal/generator/collect/model.go deleted file mode 100644 index 5acabf17b..000000000 --- a/v3/internal/generator/collect/model.go +++ /dev/null @@ -1,383 +0,0 @@ -package collect - -import ( - "cmp" - "go/ast" - "go/constant" - "go/types" - "slices" - "strings" - "sync" -) - -type ( - // ModelInfo records all information that is required - // to render JS/TS code for a model type. - // - // Read accesses to exported fields are only safe - // if a call to [ModelInfo.Collect] has completed before the access, - // for example by calling it in the accessing goroutine - // or before spawning the accessing goroutine. - ModelInfo struct { - *TypeInfo - - // Internal records whether the model - // should be exported by the index file. - Internal bool - - // Imports records dependencies for this model. - Imports *ImportMap - - // Type records the target type for an alias or derived model, - // the underlying type for an enum. - Type types.Type - - // Fields records the property list for a class or struct alias model, - // in order of declaration and grouped by their declaring [ast.Field]. - Fields [][]*ModelFieldInfo - - // Values records the value list for an enum model, - // in order of declaration and grouped - // by their declaring [ast.GenDecl] and [ast.ValueSpec]. - Values [][][]*ConstInfo - - // TypeParams records type parameter names for generic models. - TypeParams []string - - // Predicates caches the value of all type predicates for this model. - // - // WARN: whenever working with a generic uninstantiated model type, - // use these instead of invoking predicate functions, - // which may incur a large performance penalty. - Predicates Predicates - - collector *Collector - once sync.Once - } - - // ModelFieldInfo holds extended information - // about a struct field in a model type. - ModelFieldInfo struct { - *StructField - *FieldInfo - } - - // Predicates caches the value of all type predicates. - Predicates struct { - IsJSONMarshaler MarshalerKind - MaybeJSONMarshaler MarshalerKind - IsTextMarshaler MarshalerKind - MaybeTextMarshaler MarshalerKind - IsMapKey bool - IsTypeParam bool - IsStringAlias bool - IsNumberAlias bool - IsClass bool - IsAny bool - } -) - -func newModelInfo(collector *Collector, obj *types.TypeName) *ModelInfo { - return &ModelInfo{ - TypeInfo: collector.Type(obj), - collector: collector, - } -} - -// Model retrieves the the unique [ModelInfo] instance -// associated to the given type object within a Collector. -// If none is present, Model initialises a new one -// registers it for code generation -// and schedules background collection activity. -// -// Model is safe for concurrent use. -func (collector *Collector) Model(obj *types.TypeName) *ModelInfo { - pkg := collector.Package(obj.Pkg()) - if pkg == nil { - return nil - } - - model, present := pkg.recordModel(obj) - if !present { - collector.scheduler.Schedule(func() { model.Collect() }) - } - - return model -} - -// Collect gathers information for the model described by its receiver. -// It can be called concurrently by multiple goroutines; -// the computation will be performed just once. -// -// Collect returns the receiver for chaining. -// It is safe to call Collect with nil receiver. -// -// After Collect returns, the calling goroutine and all goroutines -// it might spawn afterwards are free to access -// the receiver's fields indefinitely. -func (info *ModelInfo) Collect() *ModelInfo { - if info == nil { - return nil - } - - // Changes in the following logic must be reflected adequately - // by the predicates in properties.go, by ImportMap.AddType - // and by all render.Module methods. - - info.once.Do(func() { - collector := info.collector - obj := info.Object().(*types.TypeName) - - typ := obj.Type() - - // Collect type information. - info.TypeInfo.Collect() - - // Initialise import map. - info.Imports = NewImportMap(collector.Package(obj.Pkg())) - - // Setup fallback type. - info.Type = types.Universe.Lookup("any").Type() - - // Record whether the model should be exported. - info.Internal = !obj.Exported() - - // Parse directives. - for _, doc := range []*ast.CommentGroup{info.Doc, info.Decl.Doc} { - if doc == nil { - continue - } - for _, comment := range doc.List { - if IsDirective(comment.Text, "internal") { - info.Internal = true - } - } - } - - // Record type parameter names. - var isGeneric bool - if generic, ok := typ.(interface{ TypeParams() *types.TypeParamList }); ok { - tparams := generic.TypeParams() - isGeneric = tparams != nil - - if isGeneric && tparams.Len() > 0 { - info.TypeParams = make([]string, tparams.Len()) - for i := range tparams.Len() { - info.TypeParams[i] = tparams.At(i).Obj().Name() - } - } - } - - // Precompute predicates. - // Preinstantiate typ to avoid repeated instantiations in predicate code. - ityp := instantiate(typ) - info.Predicates = Predicates{ - IsJSONMarshaler: IsJSONMarshaler(ityp), - MaybeJSONMarshaler: MaybeJSONMarshaler(ityp), - IsTextMarshaler: IsTextMarshaler(ityp), - MaybeTextMarshaler: MaybeTextMarshaler(ityp), - IsMapKey: IsMapKey(ityp), - IsTypeParam: IsTypeParam(ityp), - IsStringAlias: IsStringAlias(ityp), - IsNumberAlias: IsNumberAlias(ityp), - IsClass: IsClass(ityp), - IsAny: IsAny(ityp), - } - - var def types.Type - var constants []*types.Const - - switch t := typ.(type) { - case *types.Alias: - // Model is an alias: take rhs as definition. - // It is important not to skip alias chains with [types.Unalias] - // because in doing so we could end up with a private type from another package. - def = t.Rhs() - - // Test for constants with alias type, - // but only when non-generic alias resolves to a basic type - // (hence not to e.g. a named type). - if basic, ok := types.Unalias(def).(*types.Basic); ok { - if !isGeneric && basic.Info()&types.IsConstType != 0 && basic.Info()&types.IsComplex == 0 { - // Non-generic alias resolves to a representable constant type: - // look for defined constants whose type is exactly the alias typ. - for _, name := range obj.Pkg().Scope().Names() { - if cnst, ok := obj.Pkg().Scope().Lookup(name).(*types.Const); ok { - alias, isAlias := cnst.Type().(*types.Alias) - if isAlias && cnst.Val().Kind() != constant.Unknown && alias.Obj() == t.Obj() { - constants = append(constants, cnst) - } - } - } - } - } - - case *types.Named: - // Model is a named type: - // jump directly to underlying type to match go semantics, - // i.e. do not render named types as aliases for other named types. - def = typ.Underlying() - - // Check whether it implements marshaler interfaces or has defined constants. - if info.Predicates.MaybeJSONMarshaler != NonMarshaler { - // Type marshals to a custom value of unknown shape. - // If it has explicit custom marshaling logic, render it as any; - // otherwise, delegate to the underlying type that must be the actual [json.Marshaler]. - if info.Predicates.MaybeJSONMarshaler == ExplicitMarshaler { - return - } - } else if info.Predicates.MaybeTextMarshaler != NonMarshaler { - // Type marshals to a custom string of unknown shape. - // If it has explicit custom marshaling logic, render it as string; - // otherwise, delegate to the underlying type that must be the actual [encoding.TextMarshaler]. - // - // One exception must be made for situations - // where the underlying type is a [json.Marshaler] but the model is not: - // in that case, we cannot delegate to the underlying type either. - // Note that in such a case the underlying type is never a pointer or interface, - // because those cannot have explicitly defined methods, - // hence it would not possible for the model not to be a [json.Marshaler] - // while the underlying type is. - if info.Predicates.MaybeTextMarshaler == ExplicitMarshaler || MaybeJSONMarshaler(def) != NonMarshaler { - info.Type = types.Typ[types.String] - return - } - } else if basic, ok := def.Underlying().(*types.Basic); ok { - // Test for enums (excluding marshalers and generic types). - if !isGeneric && basic.Info()&types.IsConstType != 0 && basic.Info()&types.IsComplex == 0 { - // Named type is defined as a representable constant type: - // look for defined constants of that named type. - for _, name := range obj.Pkg().Scope().Names() { - if cnst, ok := obj.Pkg().Scope().Lookup(name).(*types.Const); ok { - if cnst.Val().Kind() != constant.Unknown && types.Identical(cnst.Type(), typ) { - constants = append(constants, cnst) - } - } - } - } - } - - default: - panic("model has unknown object kind (neither alias nor named type)") - } - - // Handle struct types. - strct, isStruct := def.(*types.Struct) - if isStruct && info.Predicates.MaybeJSONMarshaler == NonMarshaler && info.Predicates.MaybeTextMarshaler == NonMarshaler { - // Def is struct and model is not a marshaler: - // collect information about struct fields. - info.collectStruct(strct) - info.Type = nil - return - } - - // Record required imports. - info.Imports.AddType(def) - - // Handle enum types. - // constants slice is always empty for structs, marshalers. - if len(constants) > 0 { - // Collect information about enum values. - info.collectEnum(constants) - } - - // That's all, folks. Render as a TS alias. - info.Type = def - }) - - return info -} - -// collectEnum collects information about enum values and their declarations. -func (info *ModelInfo) collectEnum(constants []*types.Const) { - // Collect information about each constant object. - values := make([]*ConstInfo, len(constants)) - for i, cnst := range constants { - values[i] = info.collector.Const(cnst).Collect() - } - - // Sort values by grouping and source order. - slices.SortFunc(values, func(v1 *ConstInfo, v2 *ConstInfo) int { - // Skip comparisons for identical pointers. - if v1 == v2 { - return 0 - } - - // Sort first by source order of declaration group. - if v1.Decl != v2.Decl { - return cmp.Compare(v1.Decl.Pos, v2.Decl.Pos) - } - - // Then by source order of spec. - if v1.Spec != v2.Spec { - return cmp.Compare(v1.Spec.Pos, v2.Spec.Pos) - } - - // Then by source order of identifiers. - if v1.Pos != v2.Pos { - return cmp.Compare(v1.Pos, v2.Pos) - } - - // Finally by name (for constants whose source position is unknown). - return strings.Compare(v1.Name, v2.Name) - }) - - // Split value list into groups and subgroups. - var decl, spec *GroupInfo - decli, speci := -1, -1 - - for _, value := range values { - if value.Spec != spec { - spec = value.Spec - - if value.Decl == decl { - speci++ - } else { - decl = value.Decl - decli++ - speci = 0 - info.Values = append(info.Values, nil) - } - - info.Values[decli] = append(info.Values[decli], nil) - } - - info.Values[decli][speci] = append(info.Values[decli][speci], value) - } -} - -// collectStruct collects information about struct fields and their declarations. -func (info *ModelInfo) collectStruct(strct *types.Struct) { - collector := info.collector - - // Retrieve struct info. - structInfo := collector.Struct(strct).Collect() - - // Allocate result slice. - fields := make([]*ModelFieldInfo, len(structInfo.Fields)) - - // Collect fields. - for i, field := range structInfo.Fields { - // Record required imports. - info.Imports.AddType(field.Type) - - fields[i] = &ModelFieldInfo{ - StructField: field, - FieldInfo: collector.Field(field.Object).Collect(), - } - } - - // Split field list into groups, preserving the original order. - var decl *GroupInfo - decli := -1 - - for _, field := range fields { - if field.Decl != decl { - decl = field.Decl - decli++ - info.Fields = append(info.Fields, nil) - } - - info.Fields[decli] = append(info.Fields[decli], field) - } -} diff --git a/v3/internal/generator/collect/package.go b/v3/internal/generator/collect/package.go deleted file mode 100644 index 1d4a9414b..000000000 --- a/v3/internal/generator/collect/package.go +++ /dev/null @@ -1,300 +0,0 @@ -package collect - -import ( - "cmp" - "go/ast" - "go/token" - "go/types" - "path/filepath" - "slices" - "strings" - "sync" - "sync/atomic" - - "golang.org/x/tools/go/packages" -) - -// PackageInfo records information about a package. -// -// Read accesses to fields Path, Name, IsOrImportsApp, Types, TypesInfo, Fset, -// are safe at any time without any synchronisation. -// -// Read accesses to all other fields are only safe -// if a call to [PackageInfo.Collect] has completed before the access, -// for example by calling it in the accessing goroutine -// or before spawning the accessing goroutine. -// -// Concurrent write accesses are only allowed through the provided methods. -type PackageInfo struct { - // Path holds the canonical path of the described package. - Path string - - // Name holds the import name of the described package. - Name string - - // IsOrImportsApp is true if this package is, or depends upon, the Wails application package. - IsOrImportsApp bool - - // Types and TypesInfo hold type information for this package. - Types *types.Package - TypesInfo *types.Info - - // Fset holds the FileSet that was used to parse this package. - Fset *token.FileSet - - // Files holds parsed files for this package, - // ordered by start position to support binary search. - Files []*ast.File - - // Docs holds package doc comments. - Docs []*ast.CommentGroup - - // Includes holds a list of additional files to include - // with the generated bindings. - // It maps file names to their paths on disk. - Includes map[string]string - - // Injections holds a list of code lines to be injected - // into the package index file. - Injections []string - - // services records service types that have to be generated for this package. - // We rely upon [sync.Map] for atomic swapping support. - // Keys are *types.TypeName, values are *ServiceInfo. - services sync.Map - - // models records model types that have to be generated for this package. - // We rely upon [sync.Map] for atomic swapping support. - // Keys are *types.TypeName, values are *ModelInfo. - models sync.Map - - // stats caches statistics about this package. - stats atomic.Pointer[Stats] - - collector *Collector - once sync.Once -} - -func newPackageInfo(pkg *packages.Package, collector *Collector) *PackageInfo { - _, importsApp := pkg.Imports[collector.systemPaths.ApplicationPackage] - - return &PackageInfo{ - Path: pkg.PkgPath, - Name: pkg.Name, - - IsOrImportsApp: importsApp || pkg.PkgPath == collector.systemPaths.ApplicationPackage, - - Types: pkg.Types, - TypesInfo: pkg.TypesInfo, - - Fset: pkg.Fset, - Files: pkg.Syntax, - - collector: collector, - } -} - -// Package retrieves the unique [PackageInfo] instance, if any, -// associated to the given package object within a Collector. -// -// Package is safe for concurrent use. -func (collector *Collector) Package(pkg *types.Package) *PackageInfo { - return collector.pkgs[pkg] -} - -// Iterate calls yield sequentially for each [PackageInfo] instance -// registered with the collector. If yield returns false, -// Iterate stops the iteration. -// -// Iterate is safe for concurrent use. -func (collector *Collector) Iterate(yield func(pkg *PackageInfo) bool) { - for _, pkg := range collector.pkgs { - if !yield(pkg) { - return - } - } -} - -// Stats returns cached statistics for this package. -// If [PackageInfo.Index] has not been called yet, it returns nil. -// -// Stats is safe for unsynchronised concurrent calls. -func (info *PackageInfo) Stats() *Stats { - return info.stats.Load() -} - -// Collect gathers information about the package described by its receiver. -// It can be called concurrently by multiple goroutines; -// the computation will be performed just once. -// -// Collect returns the receiver for chaining. -// It is safe to call Collect with nil receiver. -// -// After Collect returns, the calling goroutine and all goroutines -// it might spawn afterwards are free to access -// the receiver's fields indefinitely. -func (info *PackageInfo) Collect() *PackageInfo { - if info == nil { - return nil - } - - info.once.Do(func() { - collector := info.collector - - // Sort files by source position. - if !slices.IsSortedFunc(info.Files, compareAstFiles) { - info.Files = slices.Clone(info.Files) - slices.SortFunc(info.Files, compareAstFiles) - } - - // Collect docs and parse directives. - for _, file := range info.Files { - if file.Doc == nil { - continue - } - - info.Docs = append(info.Docs, file.Doc) - - // Retrieve file directory. - pos := info.Fset.Position(file.Pos()) - if !pos.IsValid() { - collector.logger.Errorf( - "package %s: found AST file with unknown path: `wails:include` directives from that file will be ignored", - info.Path, - ) - } - dir := filepath.Dir(pos.Filename) - - // Parse directives. - if info.Includes == nil { - info.Includes = make(map[string]string) - } - for _, comment := range file.Doc.List { - switch { - case IsDirective(comment.Text, "inject"): - // Check condition. - line, cond, err := ParseCondition(ParseDirective(comment.Text, "inject")) - if err != nil { - collector.logger.Errorf( - "%s: in `wails:inject` directive: %v", - info.Fset.Position(comment.Pos()), - err, - ) - continue - } - - if !cond.Satisfied(collector.options) { - continue - } - - // Record injected line. - info.Injections = append(info.Injections, line) - - case pos.IsValid() && IsDirective(comment.Text, "include"): - // Check condition. - pattern, cond, err := ParseCondition(ParseDirective(comment.Text, "include")) - if err != nil { - collector.logger.Errorf( - "%s: in `wails:include` directive: %v", - info.Fset.Position(comment.Pos()), - err, - ) - continue - } - - if !cond.Satisfied(collector.options) { - continue - } - - // Collect matching files. - paths, err := filepath.Glob(filepath.Join(dir, pattern)) - if err != nil { - collector.logger.Errorf( - "%s: invalid pattern '%s' in `wails:include` directive: %v", - info.Fset.Position(comment.Pos()), - pattern, - err, - ) - continue - } else if len(paths) == 0 { - collector.logger.Warningf( - "%s: pattern '%s' in `wails:include` directive matched no files", - info.Fset.Position(comment.Pos()), - pattern, - ) - continue - } - - // Announce and record matching files. - for _, path := range paths { - name := strings.ToLower(filepath.Base(path)) - if old, ok := info.Includes[name]; ok { - collector.logger.Errorf( - "%s: duplicate included file name '%s' in package %s; old path: '%s'; new path: '%s'", - info.Fset.Position(comment.Pos()), - name, - info.Path, - old, - path, - ) - continue - } - - collector.logger.Debugf( - "including file '%s' as '%s' in package %s", - path, - name, - info.Path, - ) - - info.Includes[name] = path - } - } - } - } - }) - - return info -} - -// recordService adds the given service type object -// to the set of bindings generated for this package. -// It returns the unique [ServiceInfo] instance associated -// with the given type object. -// -// It is an error to pass in here a type whose parent package -// is not the one described by the receiver. -// -// recordService is safe for unsynchronised concurrent calls. -func (info *PackageInfo) recordService(obj *types.TypeName) *ServiceInfo { - // Fetch current value, then add if not already present. - service, _ := info.services.Load(obj) - if service == nil { - service, _ = info.services.LoadOrStore(obj, newServiceInfo(info.collector, obj)) - } - return service.(*ServiceInfo) -} - -// recordModel adds the given model type object -// to the set of models generated for this package. -// It returns the unique [ModelInfo] instance associated -// with the given type object. The present result is true -// if the model was already registered. -// -// It is an error to pass in here a type whose parent package -// is not the one described by the receiver. -// -// recordModel is safe for unsynchronised concurrent calls. -func (info *PackageInfo) recordModel(obj *types.TypeName) (model *ModelInfo, present bool) { - // Fetch current value, then add if not already present. - imodel, present := info.models.Load(obj) - if imodel == nil { - imodel, present = info.models.LoadOrStore(obj, newModelInfo(info.collector, obj)) - } - return imodel.(*ModelInfo), present -} - -// compareAstFiles compares two AST files by starting position. -func compareAstFiles(f1 *ast.File, f2 *ast.File) int { - return cmp.Compare(f1.FileStart, f2.FileStart) -} diff --git a/v3/internal/generator/collect/predicates.go b/v3/internal/generator/collect/predicates.go deleted file mode 100644 index 6a22646fd..000000000 --- a/v3/internal/generator/collect/predicates.go +++ /dev/null @@ -1,660 +0,0 @@ -package collect - -// This file gathers functions that test useful properties of model types. -// The rationale for the way things are handled here -// is given in the example file found at ./_reference/json_marshaler_behaviour.go - -import ( - "go/token" - "go/types" - "iter" - - "golang.org/x/exp/typeparams" -) - -// Cached interface types. -var ( - ifaceTextMarshaler = types.NewInterfaceType([]*types.Func{ - types.NewFunc(token.NoPos, nil, "MarshalText", - types.NewSignatureType(nil, nil, nil, types.NewTuple(), types.NewTuple( - types.NewParam(token.NoPos, nil, "", types.NewSlice(types.Universe.Lookup("byte").Type())), - types.NewParam(token.NoPos, nil, "", types.Universe.Lookup("error").Type()), - ), false)), - }, nil).Complete() - - ifaceJSONMarshaler = types.NewInterfaceType([]*types.Func{ - types.NewFunc(token.NoPos, nil, "MarshalJSON", - types.NewSignatureType(nil, nil, nil, types.NewTuple(), types.NewTuple( - types.NewParam(token.NoPos, nil, "", types.NewSlice(types.Universe.Lookup("byte").Type())), - types.NewParam(token.NoPos, nil, "", types.Universe.Lookup("error").Type()), - ), false)), - }, nil).Complete() -) - -// MarshalerKind values describe -// whether and how a type implements a marshaler interface. -// For any one of the two marshaler interfaces, a type is -// - a NonMarshaler if it does not implement it; -// - an ImplicitMarshaler if it inherits the implementation from its underlying type; -// - an ExplicitMarshaler if it defines the relevant method explicitly. -type MarshalerKind byte - -const ( - NonMarshaler MarshalerKind = iota - ImplicitMarshaler - ExplicitMarshaler -) - -// termlist returns an iterator over the normalised term list of the given type. -// If typ is invalid or has an empty type set, termlist returns the empty sequence. -// If typ has an empty term list -// then termlist returns a sequence with just one element: the type itself. -// -// TODO: replace with new term set API once Go 1.25 is out. -// See go.dev/issue/61013 -func termlist(typ types.Type) iter.Seq[*typeparams.Term] { - terms, err := typeparams.NormalTerms(types.Unalias(typ)) - return func(yield func(*typeparams.Term) bool) { - if err == nil && len(terms) == 0 { - yield(typeparams.NewTerm(false, typ)) - } else { - for _, term := range terms { - if !yield(term) { - break - } - } - } - } -} - -// instantiate instantiates typ if it is an uninstantiated generic type -// using its own type parameters as arguments in order to preserve genericity. -// -// If typ is not generic or already instantiated, it is returned as is. -// If typ is not an alias, then the returned type is not an alias either. -func instantiate(typ types.Type) types.Type { - if t, ok := typ.(interface { - TypeParams() *types.TypeParamList - TypeArgs() *types.TypeList - }); ok && t.TypeParams() != nil && t.TypeArgs() == nil { - args := make([]types.Type, t.TypeParams().Len()) - for i := range args { - args[i] = t.TypeParams().At(i) - } - - typ, _ = types.Instantiate(nil, typ, args, false) - } - - return typ -} - -// isMarshaler checks whether the given type -// implements one of the two marshaler interfaces, -// and whether it implements it explicitly, -// i.e. by defining the relevant method directly -// instead of inheriting it from the underlying type. -// -// If addressable is true, it checks both pointer and non-pointer receivers. -// -// The behaviour of isMarshaler is unspecified -// if marshaler is not one of [json.Marshaler] or [encoding.TextMarshaler]. -func isMarshaler(typ types.Type, marshaler *types.Interface, addressable bool, visited map[*types.TypeName]MarshalerKind) MarshalerKind { - // Follow alias chain and instantiate if necessary. - // - // types.Implements does not handle generics, - // hence when typ is generic it must be instantiated. - // - // Instantiation operations may incur a large performance penalty and are usually cached, - // but doing so here would entail some complex global state and a potential memory leak. - // Because typ should be generic only during model collection, - // it should be enough to cache the result of marshaler queries for models. - typ = instantiate(types.Unalias(typ)) - - // Invariant: at this point, typ is not an alias. - - if typ == types.Typ[types.Invalid] { - // Do not pass invalid types to [types.Implements]. - return NonMarshaler - } - - result := types.Implements(typ, marshaler) - - ptr, isPtr := typ.Underlying().(*types.Pointer) - - if !result && addressable && !isPtr { - result = types.Implements(types.NewPointer(typ), marshaler) - } - - named, isNamed := typ.(*types.Named) - - if result { - // Check whether marshaler method is implemented explicitly on a named type. - if isNamed { - method := marshaler.Method(0).Name() - for i := range named.NumMethods() { - if named.Method(i).Name() == method { - return ExplicitMarshaler - } - } - } - - return ImplicitMarshaler - } - - // Fast path: named types that fail the [types.Implements] test cannot be marshalers. - // - // WARN: currently typeparams cannot be used on the rhs of a named type declaration. - // If that changes in the future, - // this guard will become essential for correctness, - // not just a shortcut. - if isNamed { - return NonMarshaler - } - - // Unwrap at most one pointer and follow alias chain. - if isPtr { - typ = types.Unalias(ptr.Elem()) - } - - // Invariant: at this point, typ is not an alias. - - // Type parameters require special handling: - // iterate over their term list and treat them as marshalers - // if so are all their potential instantiations. - - tp, ok := typ.(*types.TypeParam) - if !ok { - return NonMarshaler - } - - // Init cycle detection/deduplication map. - if visited == nil { - visited = make(map[*types.TypeName]MarshalerKind) - } - - // Type params cannot be embedded in constraints directly, - // but they can be embedded as pointer terms. - // - // When we hit that kind of cycle, - // we can err towards it being a marshaler: - // such a constraint is meaningless anyways, - // as no type can be simultaneously a pointer to itself. - // - // Therefore, we iterate the type set - // only for unvisited pointers-to-typeparams, - // and return the current best guess - // for those we have already visited. - // - // WARN: there has been some talk - // of allowing type parameters as embedded fields/terms. - // That might make our lives miserable here. - // The spec must be monitored for changes in that regard. - if isPtr { - if kind, ok := visited[tp.Obj()]; ok { - return kind - } - } - - // Initialise kind to explicit marshaler, then decrease as needed. - kind := ExplicitMarshaler - - if isPtr { - // Pointers are never explicit marshalers. - kind = ImplicitMarshaler - // Mark pointer-to-typeparam as visited and init current best guess. - visited[tp.Obj()] = kind - } - - // Iterate term list. - for term := range termlist(tp) { - ttyp := types.Unalias(term.Type()) - - // Reject if tp has a tilde or invalid element in its term list - // or has a method-only constraint. - // - // Valid tilde terms - // can always be satisfied by named types that hide their methods - // hence fail in general to implement the required interface. - if term.Tilde() || ttyp == types.Typ[types.Invalid] || ttyp == tp { - kind = NonMarshaler - break - } - - // Propagate the presence of a wrapping pointer. - if isPtr { - ttyp = types.NewPointer(ttyp) - } - - kind = min(kind, isMarshaler(ttyp, marshaler, addressable && !isPtr, visited)) - if kind == NonMarshaler { - // We can stop here as we've reached the minimum [MarshalerKind]. - break - } - } - - // Store final response for pointer-to-typeparam. - if isPtr { - visited[tp.Obj()] = kind - } - - return kind -} - -// IsTextMarshaler queries whether and how the given type -// implements the [encoding.TextMarshaler] interface. -func IsTextMarshaler(typ types.Type) MarshalerKind { - return isMarshaler(typ, ifaceTextMarshaler, false, nil) -} - -// MaybeTextMarshaler queries whether and how the given type -// implements the [encoding.TextMarshaler] interface for at least one receiver form. -func MaybeTextMarshaler(typ types.Type) MarshalerKind { - return isMarshaler(typ, ifaceTextMarshaler, true, nil) -} - -// IsJSONMarshaler queries whether and how the given type -// implements the [json.Marshaler] interface. -func IsJSONMarshaler(typ types.Type) MarshalerKind { - return isMarshaler(typ, ifaceJSONMarshaler, false, nil) -} - -// MaybeJSONMarshaler queries whether and how the given type -// implements the [json.Marshaler] interface for at least one receiver form. -func MaybeJSONMarshaler(typ types.Type) MarshalerKind { - return isMarshaler(typ, ifaceJSONMarshaler, true, nil) -} - -// IsMapKey returns true if the given type -// is accepted as a map key by encoding/json. -func IsMapKey(typ types.Type) bool { - // Iterate over type set and return true if all elements are valid. - // - // We cannot simply delegate to [IsTextMarshaler] here - // because a union of some basic terms and some TextMarshalers - // might still be acceptable. - // - // NOTE: If typ is not a typeparam or constraint, termlist returns just typ itself. - // If typ has an empty type set, it's safe to return true - // because the map cannot be instantiated anyways. - for term := range termlist(typ) { - ttyp := types.Unalias(term.Type()) - - // Types whose underlying type is a signed/unsigned integer or a string - // are always acceptable, whether they are marshalers or not. - if basic, ok := ttyp.Underlying().(*types.Basic); ok { - if basic.Info()&(types.IsInteger|types.IsUnsigned|types.IsString) != 0 { - continue - } - } - - // Valid tilde terms - // can always be satisfied by named types that hide their methods - // hence fail in general to implement the required interface. - // For example one could have: - // - // type NotAKey struct{ encoding.TextMarshaler } - // func (NotAKey) MarshalText() int { ... } - // - // which satisfies ~struct{ encoding.TextMarshaler } - // but is not itself a TextMarshaler. - // - // It might still be the case that the constraint - // requires explicitly a marshaling method, - // hence we perform one last check on typ. - // - // For example, we reject interface{ ~struct{ ... } } - // but still accept interface{ ~struct{ ... }; MarshalText() ([]byte, error) } - // - // All other cases are only acceptable - // if the type implements [encoding.TextMarshaler] in non-addressable mode. - if term.Tilde() || IsTextMarshaler(ttyp) == NonMarshaler { - // When some term fails, test the input typ itself, - // but only if it has not been tested already. - // - // Note that when term.Tilde() is true - // then it is always the case that typ != term.Type(), - // because cyclic constraints are not allowed - // and naked type parameters cannot occur in type unions. - return typ != term.Type() && IsTextMarshaler(typ) != NonMarshaler - } - } - - return true -} - -// IsTypeParam returns true when the given type -// is either a TypeParam or a pointer to a TypeParam. -func IsTypeParam(typ types.Type) bool { - switch t := types.Unalias(typ).(type) { - case *types.TypeParam: - return true - case *types.Pointer: - _, ok := types.Unalias(t.Elem()).(*types.TypeParam) - return ok - default: - return false - } -} - -// IsStringAlias returns true when -// either typ will be rendered to JS/TS as an alias for the TS type `string`, -// or typ itself (not its underlying type) is a pointer -// whose element type satisfies the property described above. -// -// This predicate is only safe to use either with map keys, -// where pointers are treated in an ad-hoc way by [json.Marshal], -// or when typ IS ALREADY KNOWN to be either [types.Alias] or [types.Named]. -// -// Otherwise, the result might be incorrect: -// IsStringAlias MUST NOT be used to check -// whether an arbitrary instance of [types.Type] -// renders as a JS/TS string type. -// -// Notice that IsStringAlias returns false for all type parameters: -// detecting those that must be always instantiated as string aliases -// is technically possible, but very difficult. -func IsStringAlias(typ types.Type) bool { - // Unwrap at most one pointer. - // NOTE: do not unalias typ before testing: - // aliases whose underlying type is a pointer - // are never rendered as strings. - if ptr, ok := typ.(*types.Pointer); ok { - typ = ptr.Elem() - } - - switch typ.(type) { - case *types.Alias, *types.Named: - // Aliases and named types might be rendered as string aliases. - default: - // Not a model type, hence not an alias. - return false - } - - // Skip pointer and interface types: they are always nullable - // and cannot have any explicitly defined methods. - // This takes care of rejecting type params as well, - // since their underlying type is guaranteed to be an interface. - switch typ.Underlying().(type) { - case *types.Pointer, *types.Interface: - return false - } - - // Follow alias chain. - typ = types.Unalias(typ) - - // Aliases of the basic string type are rendered as strings. - if basic, ok := typ.(*types.Basic); ok { - return basic.Info()&types.IsString != 0 - } - - // json.Marshalers can only be rendered as any. - // TextMarshalers that aren't json.Marshalers render as strings. - if MaybeJSONMarshaler(typ) != NonMarshaler { - return false - } else if MaybeTextMarshaler(typ) != NonMarshaler { - return true - } - - // Named types whose underlying type is a string are rendered as strings. - basic, ok := typ.Underlying().(*types.Basic) - return ok && basic.Info()&types.IsString != 0 -} - -// IsNumberAlias returns true when -// either typ will be rendered to JS/TS as an alias for the TS type `number`, -// or typ itself (not its underlying type) is a pointer -// whose element type satisfies the property described above. -// -// This predicate is only safe to use either with map keys, -// where pointers are treated in an ad-hoc way by [json.Marshal], -// or when typ IS ALREADY KNOWN to be either [types.Alias] or [types.Named]. -// -// Otherwise, the result might be incorrect: -// IsNumberAlias MUST NOT be used to check -// whether an arbitrary instance of [types.Type] -// renders as a JS/TS number type. -// -// Notice that IsNumberAlias returns false for all type parameters: -// detecting those that must be always instantiated as number aliases -// is technically possible, but very difficult. -func IsNumberAlias(typ types.Type) bool { - // Unwrap at most one pointer. - // NOTE: do not unalias typ before testing: - // aliases whose underlying type is a pointer - // are never rendered as numbers. - if ptr, ok := typ.(*types.Pointer); ok { - typ = ptr.Elem() - } - - switch typ.(type) { - case *types.Alias, *types.Named: - // Aliases and named types might be rendered as number aliases. - default: - // Not a model type, hence not an alias. - return false - } - - // Skip pointer and interface types: they are always nullable - // and cannot have any explicitly defined methods. - // This takes care of rejecting type params as well, - // since their underlying type is guaranteed to be an interface. - switch typ.Underlying().(type) { - case *types.Pointer, *types.Interface: - return false - } - - // Follow alias chain. - typ = types.Unalias(typ) - - // Aliases of the basic numeric types are rendered as numbers. - if basic, ok := typ.(*types.Basic); ok { - return basic.Info()&(types.IsInteger|types.IsUnsigned|types.IsFloat) != 0 - } - - // json.Marshalers can only be rendered as any. - // TextMarshalers that aren't json.Marshalers render as strings not numbers. - if MaybeJSONMarshaler(typ) != NonMarshaler || MaybeTextMarshaler(typ) != NonMarshaler { - return false - } - - // Named types whose underlying type is numeric are rendered as numbers. - basic, ok := typ.Underlying().(*types.Basic) - return ok && basic.Info()&(types.IsInteger|types.IsUnsigned|types.IsFloat) != 0 -} - -// IsClass returns true if the given type will be rendered -// as a JS/TS model class (or interface). -func IsClass(typ types.Type) bool { - // Follow alias chain. - typ = types.Unalias(typ) - - if _, isNamed := typ.(*types.Named); !isNamed { - // Unnamed types are never rendered as classes. - return false - } - - // Struct named types without custom marshaling are rendered as classes. - _, isStruct := typ.Underlying().(*types.Struct) - return isStruct && MaybeJSONMarshaler(typ) == NonMarshaler && MaybeTextMarshaler(typ) == NonMarshaler -} - -// IsAny returns true if the given type -// is guaranteed to render as the TS any type or equivalent. -// -// It might return false negatives for generic aliases, -// hence should only be used with instantiated types -// or in contexts where false negatives are acceptable. -func IsAny(typ types.Type) bool { - // Follow alias chain. - typ = types.Unalias(typ) - - if MaybeJSONMarshaler(typ) != NonMarshaler { - // If typ is either a named type, an interface, a pointer or a struct, - // it will be rendered as (possibly an alias for) the TS any type. - // - // If it is a type parameter that implements json.Marshal, - // every possible concrete instantiation will implement json.Marshal, - // hence will be rendered as the TS any type. - return true - } - - if MaybeTextMarshaler(typ) != NonMarshaler { - // If type is either a named type, an interface, a pointer or a struct, - // it will be rendered as (possibly an alias for) - // the (possibly nullable) TS string type. - // - // If typ is a type parameter, we know at this point - // that it does not necessarily implement json.Marshaler, - // hence it will be possible to instantiate it in a way - // that renders as the (possibly nullable) TS string type. - return false - } - - if ptr, ok := typ.Underlying().(*types.Pointer); ok { - // Pointers render as the union of their element type with null. - // This is equivalent to the TS any type - // if and only if so is the element type. - return IsAny(ptr.Elem()) - } - - // All types listed below have rich TS equivalents, - // hence won't be equivalent to the TS any type. - // - // WARN: it is important to keep these lists explicit and up to date - // instead of listing the unsupported types (which would be much easier). - // - // By doing so, IsAny will keep working correctly - // in case future updates to the Go spec introduce new type families, - // thus buying the maintainers some time to patch the binding generator. - - // Retrieve underlying type. - switch t := typ.Underlying().(type) { - case *types.Basic: - // Complex types are not supported. - return t.Info()&(types.IsBoolean|types.IsInteger|types.IsUnsigned|types.IsFloat|types.IsString) == 0 - case *types.Array, *types.Slice, *types.Map, *types.Struct, *types.TypeParam: - return false - } - - return true -} - -// IsParametric returns true if the given type -// contains unresolved type parameters. -func IsParametric(typ types.Type) bool { - for { // Avoid recursion where possible - switch t := typ.(type) { - case *types.Alias, *types.Named: - tp := t.(interface{ TypeParams() *types.TypeParamList }).TypeParams() - ta := t.(interface{ TypeArgs() *types.TypeList }).TypeArgs() - - if tp.Len() == 0 { - // Not a generic alias/named type. - return false - } - - if ta.Len() == 0 { - // Uninstantiated generic. - return true - } - - for i := range ta.Len() - 1 { - if IsParametric(ta.At(i)) { - return true - } - } - - typ = ta.At(ta.Len() - 1) - - case *types.Basic: - return false - - case *types.Array, *types.Pointer, *types.Slice, *types.Chan: - typ = typ.(interface{ Elem() types.Type }).Elem() - - case *types.Map: - if IsParametric(t.Key()) { - return true - } - - typ = t.Elem() - - case *types.Signature: - if IsParametric(t.Params()) { - return true - } - - typ = t.Results() - - case *types.Struct: - if t.NumFields() == 0 { - // No more subtypes to check. - return false - } - - for i := range t.NumFields() - 1 { - if IsParametric(t.Field(i).Type()) { - return true - } - } - - typ = t.Field(t.NumFields() - 1).Type() - - case *types.Interface: - for m := range t.ExplicitMethods() { - if IsParametric(m.Type()) { - return true - } - } - - if t.NumEmbeddeds() == 0 { - // No more subtypes to check. - return false - } - - for i := range t.NumEmbeddeds() - 1 { - if IsParametric(t.EmbeddedType(i)) { - return true - } - } - - typ = t.EmbeddedType(t.NumEmbeddeds() - 1) - - case *types.Tuple: - if t.Len() == 0 { - // No more subtypes to check. - return false - } - - for i := range t.Len() - 1 { - if IsParametric(t.At(i).Type()) { - return true - } - } - - typ = t.At(t.Len() - 1).Type() - - case *types.TypeParam: - return true - - case *types.Union: - if t.Len() == 0 { - // No more subtypes to check. - return false - } - - for i := range t.Len() - 1 { - if IsParametric(t.Term(i).Type()) { - return true - } - } - - typ = t.Term(t.Len() - 1).Type() - - default: - // Unknown new type. - // This is wrong but [ImportMap.AddType] will take care of reporting it eventually. - return false - } - } -} diff --git a/v3/internal/generator/collect/service.go b/v3/internal/generator/collect/service.go deleted file mode 100644 index 56f500f79..000000000 --- a/v3/internal/generator/collect/service.go +++ /dev/null @@ -1,332 +0,0 @@ -package collect - -import ( - "fmt" - "go/ast" - "go/types" - "strconv" - "sync" - - "github.com/wailsapp/wails/v3/internal/hash" - "golang.org/x/tools/go/types/typeutil" -) - -type ( - // ServiceInfo records all information that is required - // to render JS/TS code for a service type. - // - // Read accesses to any public field are only safe - // if a call to [ServiceInfo.Collect] has completed before the access, - // for example by calling it in the accessing goroutine - // or before spawning the accessing goroutine. - ServiceInfo struct { - *TypeInfo - - // Internal records whether the service - // should be exported by the index file. - Internal bool - - Imports *ImportMap - Methods []*ServiceMethodInfo - - // HasInternalMethods records whether the service - // defines lifecycle or http server methods. - HasInternalMethods bool - - // Injections stores a list of JS code lines - // that should be injected into the generated file. - Injections []string - - collector *Collector - once sync.Once - } - - // ServiceMethodInfo records all information that is required - // to render JS/TS code for a service method. - ServiceMethodInfo struct { - *MethodInfo - FQN string - ID string - Internal bool - Params []*ParamInfo - Results []types.Type - } - - // ParamInfo records all information that is required - // to render JS/TS code for a service method parameter. - ParamInfo struct { - Name string - Type types.Type - Blank bool - Variadic bool - } -) - -func newServiceInfo(collector *Collector, obj *types.TypeName) *ServiceInfo { - return &ServiceInfo{ - TypeInfo: collector.Type(obj), - collector: collector, - } -} - -// Service returns the unique ServiceInfo instance -// associated to the given object within a collector -// and registers it for code generation. -// -// Service is safe for concurrent use. -func (collector *Collector) Service(obj *types.TypeName) *ServiceInfo { - pkg := collector.Package(obj.Pkg()) - if pkg == nil { - return nil - } - - return pkg.recordService(obj) -} - -// IsEmpty returns true if no methods or code injections -// are present for this service, for the selected language. -func (info *ServiceInfo) IsEmpty() bool { - // Ensure information has been collected. - info.Collect() - return len(info.Methods) == 0 && len(info.Injections) == 0 -} - -// Collect gathers information about the service described by its receiver. -// It can be called concurrently by multiple goroutines; -// the computation will be performed just once. -// -// Collect returns the receiver for chaining. -// It is safe to call Collect with nil receiver. -// -// After Collect returns, the calling goroutine and all goroutines -// it might spawn afterwards are free to access -// the receiver's fields indefinitely. -func (info *ServiceInfo) Collect() *ServiceInfo { - if info == nil { - return nil - } - - info.once.Do(func() { - collector := info.collector - obj := info.Object().(*types.TypeName) - - // Collect type information. - info.TypeInfo.Collect() - - // Initialise import map. - info.Imports = NewImportMap(collector.Package(obj.Pkg())) - - // Compute intuitive method set (i.e. both pointer and non-pointer receiver). - // Do not use a method set cache because - // - it would hurt concurrency (requires mutual exclusion), - // - it is only useful when the same type is queried many times; - // this may only happen here if some embedded types appear frequently, - // which should be far from average. - mset := typeutil.IntuitiveMethodSet(obj.Type(), nil) - - // Collect method information. - info.Methods = make([]*ServiceMethodInfo, 0, len(mset)) - for _, sel := range mset { - switch { - case internalServiceMethods[sel.Obj().Name()]: - info.HasInternalMethods = true - continue - case !sel.Obj().Exported(): - // Ignore unexported and internal methods. - continue - } - - methodInfo := info.collectMethod(sel.Obj().(*types.Func)) - if methodInfo != nil { - info.Methods = append(info.Methods, methodInfo) - } - } - - // Record whether the service should be exported. - info.Internal = !obj.Exported() - - // Parse directives. - for _, doc := range []*ast.CommentGroup{info.Doc, info.Decl.Doc} { - if doc == nil { - continue - } - for _, comment := range doc.List { - switch { - case IsDirective(comment.Text, "internal"): - info.Internal = true - - case IsDirective(comment.Text, "inject"): - // Check condition. - line, cond, err := ParseCondition(ParseDirective(comment.Text, "inject")) - if err != nil { - collector.logger.Errorf( - "%s: in `wails:inject` directive: %v", - collector.Package(obj.Pkg()).Fset.Position(comment.Pos()), - err, - ) - continue - } - - if !cond.Satisfied(collector.options) { - continue - } - - // Record injected line. - info.Injections = append(info.Injections, line) - } - } - } - }) - - return info -} - -// internalServiceMethod is a set of methods -// that are handled specially by the binding engine -// and must not be exposed to the frontend. -var internalServiceMethods = map[string]bool{ - "ServiceName": true, - "ServiceStartup": true, - "ServiceShutdown": true, - "ServeHTTP": true, -} - -// typeError caches the type-checker type for the Go error interface. -var typeError = types.Universe.Lookup("error").Type() - -// typeAny caches the empty interface type. -var typeAny = types.Universe.Lookup("any").Type().Underlying() - -// collectMethod collects and returns information about a service method. -// It is intended to be called only by ServiceInfo.Collect. -func (info *ServiceInfo) collectMethod(method *types.Func) *ServiceMethodInfo { - collector := info.collector - obj := info.Object().(*types.TypeName) - - signature, _ := method.Type().(*types.Signature) - if signature == nil { - // Skip invalid interface method. - // TODO: is this actually necessary? - return nil - } - - // Compute fully qualified name. - path := obj.Pkg().Path() - if obj.Pkg().Name() == "main" { - // reflect.Method.PkgPath is always "main" for the main package. - // This should not cause collisions because - // other main packages are not importable. - path = "main" - } - - fqn := path + "." + obj.Name() + "." + method.Name() - id := hash.Fnv(fqn) - - methodInfo := &ServiceMethodInfo{ - MethodInfo: collector.Method(method).Collect(), - FQN: fqn, - ID: strconv.FormatUint(uint64(id), 10), - Params: make([]*ParamInfo, 0, signature.Params().Len()), - Results: make([]types.Type, 0, signature.Results().Len()), - } - - // Parse directives. - if methodInfo.Doc != nil { - var methodIdFound bool - - for _, comment := range methodInfo.Doc.List { - switch { - case IsDirective(comment.Text, "ignore"): - return nil - - case IsDirective(comment.Text, "internal"): - methodInfo.Internal = true - - case !methodIdFound && IsDirective(comment.Text, "id"): - idString := ParseDirective(comment.Text, "id") - idValue, err := strconv.ParseUint(idString, 10, 32) - - if err != nil { - collector.logger.Errorf( - "%s: invalid value '%s' in `wails:id` directive: expected a valid uint32 value", - collector.Package(method.Pkg()).Fset.Position(comment.Pos()), - idString, - ) - continue - } - - // Announce and record alias. - collector.logger.Infof( - "package %s: method %s.%s: default ID %s replaced by %d", - path, - obj.Name(), - method.Name(), - methodInfo.ID, - idValue, - ) - methodInfo.ID = strconv.FormatUint(idValue, 10) - methodIdFound = true - } - } - } - - // Collect parameters. - for i := range signature.Params().Len() { - param := signature.Params().At(i) - - if i == 0 { - // Skip first parameter if it has context type. - named, ok := types.Unalias(param.Type()).(*types.Named) - if ok && named.Obj().Pkg().Path() == collector.systemPaths.ContextPackage && named.Obj().Name() == "Context" { - continue - } - } - - if types.IsInterface(param.Type()) && !types.Identical(param.Type().Underlying(), typeAny) { - paramName := param.Name() - if paramName == "" || paramName == "_" { - paramName = fmt.Sprintf("#%d", i+1) - } - - collector.logger.Warningf( - "%s: parameter %s has non-empty interface type %s: passing values other than `null` is not supported by encoding/json and will likely result in runtime errors", - collector.Package(method.Pkg()).Fset.Position(param.Pos()), - paramName, - param.Type(), - ) - } - - // Record type dependencies. - info.Imports.AddType(param.Type()) - - // Record parameter. - methodInfo.Params = append(methodInfo.Params, &ParamInfo{ - Name: param.Name(), - Type: param.Type(), - Blank: param.Name() == "" || param.Name() == "_", - }) - } - - if signature.Variadic() { - methodInfo.Params[len(methodInfo.Params)-1].Type = methodInfo.Params[len(methodInfo.Params)-1].Type.(*types.Slice).Elem() - methodInfo.Params[len(methodInfo.Params)-1].Variadic = true - } - - // Collect results. - for i := range signature.Results().Len() { - result := signature.Results().At(i) - - if types.Identical(result.Type(), typeError) { - // Skip error results, they are thrown as exceptions - continue - } - - // Record type dependencies. - info.Imports.AddType(result.Type()) - - // Record result. - methodInfo.Results = append(methodInfo.Results, result.Type()) - } - - return methodInfo -} diff --git a/v3/internal/generator/collect/stats.go b/v3/internal/generator/collect/stats.go deleted file mode 100644 index 9b5045565..000000000 --- a/v3/internal/generator/collect/stats.go +++ /dev/null @@ -1,36 +0,0 @@ -package collect - -import "time" - -type Stats struct { - NumPackages int - NumServices int - NumMethods int - NumEnums int - NumModels int - NumEvents int - StartTime time.Time - EndTime time.Time -} - -func (stats *Stats) Start() { - stats.StartTime = time.Now() - stats.EndTime = stats.StartTime -} - -func (stats *Stats) Stop() { - stats.EndTime = time.Now() -} - -func (stats *Stats) Elapsed() time.Duration { - return stats.EndTime.Sub(stats.StartTime) -} - -func (stats *Stats) Add(other *Stats) { - stats.NumPackages += other.NumPackages - stats.NumServices += other.NumServices - stats.NumMethods += other.NumMethods - stats.NumEnums += other.NumEnums - stats.NumModels += other.NumModels - stats.NumEvents += other.NumEvents -} diff --git a/v3/internal/generator/collect/struct.go b/v3/internal/generator/collect/struct.go deleted file mode 100644 index b9a1b99ca..000000000 --- a/v3/internal/generator/collect/struct.go +++ /dev/null @@ -1,352 +0,0 @@ -package collect - -import ( - "cmp" - "go/ast" - "go/types" - "reflect" - "slices" - "strings" - "sync" - "unicode" -) - -type ( - // StructInfo records the flattened field list for a struct type, - // taking into account JSON tags. - // - // The field list is initially empty. It will be populated - // upon calling [StructInfo.Collect] for the first time. - // - // Read accesses to the field list are only safe - // if a call to [StructInfo.Collect] has been completed before the access, - // for example by calling it in the accessing goroutine - // or before spawning the accessing goroutine. - StructInfo struct { - Fields []*StructField - - typ *types.Struct - - collector *Collector - once sync.Once - } - - // FieldInfo represents a single field in a struct. - StructField struct { - JsonName string // Avoid collisions with [FieldInfo.Name]. - Type types.Type - Optional bool - Quoted bool - - // Object holds the described type-checker object. - Object *types.Var - } -) - -func newStructInfo(collector *Collector, typ *types.Struct) *StructInfo { - return &StructInfo{ - typ: typ, - collector: collector, - } -} - -// Struct retrieves the unique [StructInfo] instance -// associated to the given type within a Collector. -// If none is present, a new one is initialised. -// -// Struct is safe for concurrent use. -func (collector *Collector) Struct(typ *types.Struct) *StructInfo { - // Cache by type pointer, do not use a typeutil.Map: - // - for models, it may result in incorrect comments; - // - for anonymous structs, it would probably bring little benefit - // because the probability of repetitions is much lower. - - return collector.fromCache(typ).(*StructInfo) -} - -func (*StructInfo) Object() types.Object { - return nil -} - -func (info *StructInfo) Type() types.Type { - return info.typ -} - -func (*StructInfo) Node() ast.Node { - return nil -} - -// Collect gathers information for the structure described by its receiver. -// It can be called concurrently by multiple goroutines; -// the computation will be performed just once. -// -// The field list of the receiver is populated -// by the same flattening algorithm employed by encoding/json. -// JSON struct tags are accounted for. -// -// Collect returns the receiver for chaining. -// It is safe to call Collect with nil receiver. -// -// After Collect returns, the calling goroutine and all goroutines -// it might spawn afterwards are free to access -// the receiver's fields indefinitely. -func (info *StructInfo) Collect() *StructInfo { - if info == nil { - return nil - } - - type fieldData struct { - *StructField - - // Data for the encoding/json flattening algorithm. - nameFromTag bool - index []int - } - - info.once.Do(func() { - // Flattened list of fields with additional information. - fields := make([]fieldData, 0, info.typ.NumFields()) - - // Queued embedded types for current and next level. - current := make([]fieldData, 0, info.typ.NumFields()) - next := make([]fieldData, 1, max(1, info.typ.NumFields())) - - // Count of queued embedded types for current and next level. - count := make(map[*types.Struct]int) - nextCount := make(map[*types.Struct]int) - - // Set of visited types to avoid duplicating work. - visited := make(map[*types.Struct]bool) - - next[0] = fieldData{ - StructField: &StructField{ - Type: info.typ, - }, - } - - for len(next) > 0 { - current, next = next, current[:0] - count, nextCount = nextCount, count - clear(nextCount) - - for _, embedded := range current { - // Scan embedded type for fields to include. - estruct := embedded.Type.Underlying().(*types.Struct) - - // Skip previously visited structs - if visited[estruct] { - continue - } - visited[estruct] = true - - // WARNING: do not reuse cached info for embedded structs. - // It may lead to incorrect results for subtle reasons. - - for i := range estruct.NumFields() { - field := estruct.Field(i) - - // Retrieve type of field, following aliases conservatively - // and unwrapping exactly one pointer. - ftype := field.Type() - if ptr, ok := types.Unalias(ftype).(*types.Pointer); ok { - ftype = ptr.Elem() - } - - // Detect struct alias and keep it. - fstruct, _ := types.Unalias(ftype).(*types.Struct) - if fstruct == nil { - // Not a struct alias, follow alias chain. - ftype = types.Unalias(ftype) - fstruct, _ = ftype.Underlying().(*types.Struct) - } - - if field.Embedded() { - if !field.Exported() && fstruct == nil { - // Ignore embedded fields of unexported non-struct types. - continue - } - } else if !field.Exported() { - // Ignore unexported non-embedded fields. - continue - } - - // Retrieve and parse json tag. - tag := reflect.StructTag(estruct.Tag(i)).Get("json") - name, optional, quoted, visible := parseTag(tag) - if !visible { - // Ignored by encoding/json. - continue - } - - if !isValidFieldName(name) { - // Ignore alternative name if invalid. - name = "" - } - - index := make([]int, len(embedded.index)+1) - copy(index, embedded.index) - index[len(embedded.index)] = i - - if name != "" || !field.Embedded() || fstruct == nil { - // Tag name is non-empty, - // or field is not embedded, - // or field is not structure: - // add to field list. - - if !info.collector.options.UseInterfaces { - // In class mode, mark parametric fields as optional - // because there is no way to know their default JS value in advance. - if _, isTypeParam := types.Unalias(field.Type()).(*types.TypeParam); isTypeParam { - optional = true - } - } - - finfo := fieldData{ - StructField: &StructField{ - JsonName: name, - Type: field.Type(), - Optional: optional, - Quoted: quoted, - - Object: field, - }, - nameFromTag: name != "", - index: index, - } - - if name == "" { - finfo.JsonName = field.Name() - } - - fields = append(fields, finfo) - if count[estruct] > 1 { - // The struct we are scanning - // appears multiple times at the current level. - // This means that all its fields are ambiguous - // and must disappear. - // Duplicate them so that the field selection phase - // below will erase them. - fields = append(fields, finfo) - } - - continue - } - - // Queue embedded field for next level. - // If it has been queued already, do not duplicate it. - nextCount[fstruct]++ - if nextCount[fstruct] == 1 { - next = append(next, fieldData{ - StructField: &StructField{ - Type: ftype, - }, - index: index, - }) - } - } - } - } - - // Prepare for field selection phase. - slices.SortFunc(fields, func(f1 fieldData, f2 fieldData) int { - // Sort by name first. - if diff := strings.Compare(f1.JsonName, f2.JsonName); diff != 0 { - return diff - } - - // Break ties by depth of occurrence. - if diff := cmp.Compare(len(f1.index), len(f2.index)); diff != 0 { - return diff - } - - // Break ties by presence of json tag (prioritize presence). - if f1.nameFromTag != f2.nameFromTag { - if f1.nameFromTag { - return -1 - } else { - return 1 - } - } - - // Break ties by order of occurrence. - return slices.Compare(f1.index, f2.index) - }) - - fieldCount := 0 - - // Keep for each name the dominant field, drop those for which ties - // still exist (ignoring order of occurrence). - for i, j := 0, 1; j <= len(fields); j++ { - if j < len(fields) && fields[i].JsonName == fields[j].JsonName { - continue - } - - // If there is only one field with the current name, - // or there is a dominant one, keep it. - if i+1 == j || len(fields[i].index) != len(fields[i+1].index) || fields[i].nameFromTag != fields[i+1].nameFromTag { - fields[fieldCount] = fields[i] - fieldCount++ - } - - i = j - } - - fields = fields[:fieldCount] - - // Sort by order of occurrence. - slices.SortFunc(fields, func(f1 fieldData, f2 fieldData) int { - return slices.Compare(f1.index, f2.index) - }) - - // Copy selected fields to receiver. - info.Fields = make([]*StructField, len(fields)) - for i, field := range fields { - info.Fields[i] = field.StructField - } - - info.typ = nil - }) - - return info -} - -// parseTag parses a json field tag and extracts -// all options recognised by encoding/json. -func parseTag(tag string) (name string, optional bool, quoted bool, visible bool) { - if tag == "-" { - return "", false, false, false - } else { - visible = true - } - - parts := strings.Split(tag, ",") - - name = parts[0] - - for _, option := range parts[1:] { - switch option { - case "omitempty", "omitzero": - optional = true - case "string": - quoted = true - } - } - - return -} - -// isValidFieldName determines whether a field name is valid -// according to encoding/json. -func isValidFieldName(name string) bool { - if name == "" { - return false - } - - for _, c := range name { - if !strings.ContainsRune("!#$%&()*+-./:;<=>?@[]^_{|}~ ", c) && !unicode.IsLetter(c) && !unicode.IsDigit(c) { - return false - } - } - - return true -} diff --git a/v3/internal/generator/collect/type.go b/v3/internal/generator/collect/type.go deleted file mode 100644 index 24e5adefc..000000000 --- a/v3/internal/generator/collect/type.go +++ /dev/null @@ -1,113 +0,0 @@ -package collect - -import ( - "go/ast" - "go/types" - "slices" - "sync" -) - -// TypeInfo records information about a type declaration. -// -// Read accesses to any public field are only safe -// if a call to [TypeInfo.Collect] has completed before the access, -// for example by calling it in the accessing goroutine -// or before spawning the accessing goroutine. -type TypeInfo struct { - Name string - - // Alias is true for type aliases. - Alias bool - - Doc *ast.CommentGroup - Decl *GroupInfo - - obj *types.TypeName - node ast.Node - - collector *Collector - once sync.Once -} - -// newTypeInfo initialises a descriptor for the given named type object. -func newTypeInfo(collector *Collector, obj *types.TypeName) *TypeInfo { - return &TypeInfo{ - obj: obj, - collector: collector, - } -} - -// Type returns the unique TypeInfo instance -// associated to the given object within a collector. -// -// Type is safe for concurrent use. -func (collector *Collector) Type(obj *types.TypeName) *TypeInfo { - return collector.fromCache(obj).(*TypeInfo) -} - -func (info *TypeInfo) Object() types.Object { - return info.obj -} - -func (info *TypeInfo) Type() types.Type { - return info.obj.Type() -} - -func (info *TypeInfo) Node() ast.Node { - return info.Collect().node -} - -// Collect gathers information about the type described by its receiver. -// It can be called concurrently by multiple goroutines; -// the computation will be performed just once. -// -// Collect returns the receiver for chaining. -// It is safe to call Collect with nil receiver. -// -// After Collect returns, the calling goroutine and all goroutines -// it might spawn afterwards are free to access -// the receiver's fields indefinitely. -func (info *TypeInfo) Collect() *TypeInfo { - if info == nil { - return nil - } - - info.once.Do(func() { - collector := info.collector - - info.Name = info.obj.Name() - info.Alias = info.obj.IsAlias() - - path := collector.findDeclaration(info.obj) - if path == nil { - collector.logger.Warningf( - "package %s: type %s: could not find declaration for type object", - info.obj.Pkg().Path(), - info.Name, - ) - - // Provide dummy group. - info.Decl = newGroupInfo(nil).Collect() - return - } - - // path shape: *ast.TypeSpec, *ast.GenDecl, *ast.File - tspec := path[0].(*ast.TypeSpec) - - // Retrieve doc comments. - info.Doc = tspec.Doc - if info.Doc == nil { - info.Doc = tspec.Comment - } else if tspec.Comment != nil { - info.Doc = &ast.CommentGroup{ - List: slices.Concat(tspec.Doc.List, tspec.Comment.List), - } - } - - info.Decl = collector.fromCache(path[1]).(*GroupInfo).Collect() - - info.node = path[0] - }) - - return info -} diff --git a/v3/internal/generator/collect/void.go b/v3/internal/generator/collect/void.go deleted file mode 100644 index b2a377ec8..000000000 --- a/v3/internal/generator/collect/void.go +++ /dev/null @@ -1,28 +0,0 @@ -package collect - -import ( - "go/types" -) - -// IsVoidAlias returns true when the given type or object is the application.Void named type that stands in for the void TS type. -func (collector *Collector) IsVoidAlias(typOrObj any) bool { - var obj types.Object - switch to := typOrObj.(type) { - case types.Object: - obj = to - case interface{ Obj() *types.TypeName }: - obj = to.Obj() - default: - return false - } - - if vt := collector.appVoidType.Load(); vt != nil && obj == vt { - return true - } else if vt == nil && obj.Name() == "Void" && obj.Pkg() != nil && obj.Pkg().Path() == collector.systemPaths.ApplicationPackage { // Check name before package to fail fast - // Cache void alias for faster checking - collector.appVoidType.Store(obj) - return true - } - - return false -} diff --git a/v3/internal/generator/config/file.go b/v3/internal/generator/config/file.go deleted file mode 100644 index 1e3bc7477..000000000 --- a/v3/internal/generator/config/file.go +++ /dev/null @@ -1,64 +0,0 @@ -package config - -import ( - "io" - "os" - "path/filepath" -) - -// FileCreator abstracts away file and directory creation. -// We use this to implement tests cleanly. -// -// Paths are always relative to the output directory. -// -// A FileCreator must allow concurrent calls to Create transparently. -// Each [io.WriteCloser] instance returned by a call to Create -// will be used by one goroutine at a time; but distinct instances -// must support concurrent use by distinct goroutines. -type FileCreator interface { - Create(path string) (io.WriteCloser, error) -} - -// FileCreatorFunc is an adapter to allow -// the use of ordinary functions as file creators. -type FileCreatorFunc func(path string) (io.WriteCloser, error) - -// Create calls f(path). -func (f FileCreatorFunc) Create(path string) (io.WriteCloser, error) { - return f(path) -} - -// NullCreator is a dummy file creator implementation. -// Calls to Create never fail and return -// a writer that discards all incoming data. -var NullCreator FileCreator = FileCreatorFunc(func(path string) (io.WriteCloser, error) { - return nullWriteCloser{}, nil -}) - -// DirCreator returns a file creator that creates files -// relative to the given output directory. -// -// It joins the output directory and the file path, -// calls [os.MkdirAll] on the directory part of the result, -// then [os.Create] on the full file path. -func DirCreator(outputDir string) FileCreator { - return FileCreatorFunc(func(path string) (io.WriteCloser, error) { - path = filepath.Join(outputDir, path) - - if err := os.MkdirAll(filepath.Dir(path), 0o777); err != nil { - return nil, err - } - - return os.Create(path) - }) -} - -type nullWriteCloser struct{} - -func (nullWriteCloser) Write(data []byte) (int, error) { - return len(data), nil -} - -func (nullWriteCloser) Close() error { - return nil -} diff --git a/v3/internal/generator/config/log.go b/v3/internal/generator/config/log.go deleted file mode 100644 index cdfceb3db..000000000 --- a/v3/internal/generator/config/log.go +++ /dev/null @@ -1,102 +0,0 @@ -package config - -import ( - "fmt" - - "github.com/pterm/pterm" -) - -// A Logger instance provides methods to format and report messages -// intended for the end user. -// -// All Logger methods may be called concurrently by its consumers. -type Logger interface { - // Errorf should process its arguments as if they were passed to fmt.Sprintf - // and report the resulting string to the user as an error message. - Errorf(format string, a ...any) - - // Warningf should process its arguments as if they were passed to fmt.Sprintf - // and report the resulting string to the user as a warning message. - Warningf(format string, a ...any) - - // Infof should process its arguments as if they were passed to fmt.Sprintf - // and report the resulting string to the user as an informational message. - Infof(format string, a ...any) - - // Debugf should process its arguments as if they were passed to fmt.Sprintf - // and report the resulting string to the user as a debug message. - Debugf(format string, a ...any) - - // Statusf should process its arguments as if they were passed to fmt.Sprintf - // and report the resulting string to the user as a status message. - Statusf(format string, a ...any) -} - -// NullLogger is a dummy Logger implementation -// that discards all incoming messages. -var NullLogger Logger = nullLogger{} - -type nullLogger struct{} - -func (nullLogger) Errorf(format string, a ...any) {} -func (nullLogger) Warningf(format string, a ...any) {} -func (nullLogger) Infof(format string, a ...any) {} -func (nullLogger) Debugf(format string, a ...any) {} -func (nullLogger) Statusf(format string, a ...any) {} - -// DefaultPtermLogger returns a Logger implementation that writes -// to the default pterm printers for each logging level. -// -// If spinner is not nil, it is used to log status updates. -// The spinner must have been started already. -func DefaultPtermLogger(spinner *pterm.SpinnerPrinter) Logger { - return &PtermLogger{ - &pterm.Error, - &pterm.Warning, - &pterm.Info, - &pterm.Debug, - spinner, - } -} - -// PtermLogger is a Logger implementation that writes to pterm printers. -// If any field is nil, PtermLogger discards all messages of that level. -type PtermLogger struct { - Error pterm.TextPrinter - Warning pterm.TextPrinter - Info pterm.TextPrinter - Debug pterm.TextPrinter - Spinner *pterm.SpinnerPrinter -} - -func (logger *PtermLogger) Errorf(format string, a ...any) { - if logger.Error != nil { - logger.Error.Printfln(format, a...) - } -} - -func (logger *PtermLogger) Warningf(format string, a ...any) { - if logger.Warning != nil { - // Prefix with [warn] to prevent GitHub Actions Go problem matcher - // from treating warnings as errors (it matches file.go:line:col: patterns) - logger.Warning.Printfln("[warn] "+format, a...) - } -} - -func (logger *PtermLogger) Infof(format string, a ...any) { - if logger.Info != nil { - logger.Info.Printfln(format, a...) - } -} - -func (logger *PtermLogger) Debugf(format string, a ...any) { - if logger.Debug != nil { - logger.Debug.Printfln(format, a...) - } -} - -func (logger *PtermLogger) Statusf(format string, a ...any) { - if logger.Spinner != nil { - logger.Spinner.UpdateText(fmt.Sprintf(format, a...)) - } -} diff --git a/v3/internal/generator/config/paths.go b/v3/internal/generator/config/paths.go deleted file mode 100644 index 26e1acb51..000000000 --- a/v3/internal/generator/config/paths.go +++ /dev/null @@ -1,14 +0,0 @@ -package config - -// WailsAppPkgPath is the official import path of Wails v3's application package. -const WailsAppPkgPath = "github.com/wailsapp/wails/v3/pkg/application" - -// WailsInternalPkgPath is the official import path of Wails v3's internal package. -const WailsInternalPkgPath = "github.com/wailsapp/wails/v3/internal" - -// SystemPaths holds resolved paths of required system packages. -type SystemPaths struct { - ContextPackage string - ApplicationPackage string - InternalPackage string -} diff --git a/v3/internal/generator/constants.go b/v3/internal/generator/constants.go deleted file mode 100644 index 3c0c85873..000000000 --- a/v3/internal/generator/constants.go +++ /dev/null @@ -1,54 +0,0 @@ -package generator - -import ( - "fmt" - "go/ast" - "go/parser" - "go/token" - "strings" -) - -func GenerateConstants(goData []byte) (string, error) { - - // Create a new token file set and parser - fs := token.NewFileSet() - f, err := parser.ParseFile(fs, "", goData, parser.AllErrors) - if err != nil { - return "", err - } - - // Extract constant declarations and generate JavaScript constants - var jsConstants []string - for _, decl := range f.Decls { - if gd, ok := decl.(*ast.GenDecl); ok && gd.Tok == token.CONST { - for _, spec := range gd.Specs { - if vs, ok := spec.(*ast.ValueSpec); ok { - for i, name := range vs.Names { - value := vs.Values[i] - if value != nil { - jsConstants = append(jsConstants, fmt.Sprintf("export const %s = %s;", name.Name, jsValue(value))) - } - } - } - } - } - } - - // Join the JavaScript constants into a single string - jsCode := strings.Join(jsConstants, "\n") - - return jsCode, nil -} - -func jsValue(expr ast.Expr) string { - // Implement conversion from Go constant value to JavaScript value here. - // You can add more cases for different types if needed. - switch e := expr.(type) { - case *ast.BasicLit: - return e.Value - case *ast.Ident: - return e.Name - default: - return "" - } -} diff --git a/v3/internal/generator/constants_test.go b/v3/internal/generator/constants_test.go deleted file mode 100644 index 9e056dcac..000000000 --- a/v3/internal/generator/constants_test.go +++ /dev/null @@ -1,55 +0,0 @@ -package generator - -import "testing" - -func TestGenerateConstants(t *testing.T) { - tests := []struct { - name string - goData []byte - want string - wantErr bool - }{ - { - name: "int", - goData: []byte(`package test -const one = 1`), - want: "export const one = 1;", - wantErr: false, - }, - { - name: "float", - goData: []byte(`package test -const one_point_five = 1.5`), - want: "export const one_point_five = 1.5;", - wantErr: false, - }, - { - name: "string", - goData: []byte(`package test -const one_as_a_string = "1"`), - want: `export const one_as_a_string = "1";`, - wantErr: false, - }, - { - name: "nested", - goData: []byte(`package test -const ( - one_as_a_string = "1" -)`), - want: `export const one_as_a_string = "1";`, - wantErr: false, - }, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - got, err := GenerateConstants(tt.goData) - if (err != nil) != tt.wantErr { - t.Errorf("GenerateConstants() error = %v, wantErr %v", err, tt.wantErr) - return - } - if got != tt.want { - t.Errorf("GenerateConstants() got = %v, want %v", got, tt.want) - } - }) - } -} diff --git a/v3/internal/generator/errors.go b/v3/internal/generator/errors.go deleted file mode 100644 index 1536ea9be..000000000 --- a/v3/internal/generator/errors.go +++ /dev/null @@ -1,196 +0,0 @@ -package generator - -import ( - "errors" - "fmt" - "maps" - "slices" - "sync" - - "github.com/wailsapp/wails/v3/internal/generator/config" -) - -// ErrNoContextPackage indicates that -// the canonical path for the standard context package -// did not match any actual package. -var ErrNoContextPackage = errors.New("standard context package not found at canonical import path ('context'): is the Wails v3 module properly installed? ") - -// ErrNoApplicationPackage indicates that -// the canonical path for the Wails application package -// did not match any actual package. -var ErrNoApplicationPackage = errors.New("Wails application package not found at canonical import path ('" + config.WailsAppPkgPath + "'): is the Wails v3 module properly installed? ") - -// ErrNoInternalPackage indicates that -// the canonical path for the Wails internal package -// did not match any actual package. -var ErrNoInternalPackage = errors.New("Wails internal package not found at canonical import path ('" + config.WailsInternalPkgPath + "'): is the Wails v3 module properly installed? ") - -// ErrBadApplicationPackage indicates that -// the Wails application package has invalid content. -var ErrBadApplicationPackage = errors.New("package " + config.WailsAppPkgPath + ": function NewService has wrong signature: is the Wails v3 module properly installed? ") - -// ErrNoPackages is returned by [Generator.Generate] -// when [LoadPackages] returns no error and no packages. -var ErrNoPackages = errors.New("the given patterns matched no packages") - -// ErrorReport accumulates and logs error -// and warning messages, with deduplication. -// -// It implements the error interface; the Error method -// returns a report counting messages emitted so far. -// -// It also implements the interface [config.Logger] for convenience. -type ErrorReport struct { - logger config.Logger - - mu sync.Mutex - warnings map[string]bool - errors map[string]bool -} - -// NewErrorReport report initialises an ErrorReport instance -// with the provided Logger implementation. -// -// If logger is nil, messages will be accumulated but not logged. -func NewErrorReport(logger config.Logger) *ErrorReport { - if logger == nil { - logger = config.NullLogger - } - - return &ErrorReport{ - logger: logger, - warnings: make(map[string]bool), - errors: make(map[string]bool), - } -} - -// Error returns a string reporting the number -// of errors and warnings emitted so far. -func (report *ErrorReport) Error() string { - report.mu.Lock() - defer report.mu.Unlock() - - if len(report.errors) > 0 && len(report.warnings) == 0 { - var plural string - if len(report.errors) > 1 { - plural = "s" - } - return fmt.Sprintf("%d error%s emitted", len(report.errors), plural) - - } else if len(report.errors) == 0 && len(report.warnings) > 0 { - var plural string - if len(report.warnings) > 1 { - plural = "s" - } - - return fmt.Sprintf("%d warning%s emitted", len(report.warnings), plural) - - } else if len(report.errors) > 0 && len(report.warnings) > 0 { - var eplural, wplural string - if len(report.errors) > 1 { - eplural = "s" - } - if len(report.warnings) > 1 { - wplural = "s" - } - - return fmt.Sprintf("%d error%s and %d warning%s emitted", len(report.errors), eplural, len(report.warnings), wplural) - - } else { - return "no errors or warnings emitted" - } -} - -// HasErrors returns true if at least one error has been added to the report. -func (report *ErrorReport) HasErrors() bool { - report.mu.Lock() - result := len(report.errors) > 0 - report.mu.Unlock() - return result -} - -// HasWarnings returns true if at least one warning has been added to the report. -func (report *ErrorReport) HasWarnings() bool { - report.mu.Lock() - result := len(report.warnings) > 0 - report.mu.Unlock() - return result -} - -// Errors returns the list of error messages -// that have been added to the report. -// The order is randomised. -func (report *ErrorReport) Errors() []string { - report.mu.Lock() - defer report.mu.Unlock() - - return slices.Collect(maps.Keys(report.errors)) -} - -// Warnings returns the list of warning messages -// that have been added to the report. -// The order is randomised. -func (report *ErrorReport) Warnings() []string { - report.mu.Lock() - defer report.mu.Unlock() - - return slices.Collect(maps.Keys(report.warnings)) -} - -// Errorf formats an error message and adds it to the report. -// If not already present, the message is forwarded -// to the logger instance provided during initialisation. -func (report *ErrorReport) Errorf(format string, a ...any) { - msg := fmt.Sprintf(format, a...) - - report.mu.Lock() - defer report.mu.Unlock() - - present := report.errors[msg] - report.errors[msg] = true - - if !present { - report.logger.Errorf(format, a...) - } -} - -// Warningf formats an error message and adds it to the report. -// If not already present, the message is forwarded -// to the logger instance provided during initialisation. -func (report *ErrorReport) Warningf(format string, a ...any) { - msg := fmt.Sprintf(format, a...) - - report.mu.Lock() - defer report.mu.Unlock() - - present := report.warnings[msg] - report.warnings[msg] = true - - if !present { - report.logger.Warningf(format, a...) - } -} - -// Infof forwards the given informational message -// to the logger instance provided during initialisation. -// -// This method is here just for convenience and performs no deduplication. -func (report *ErrorReport) Infof(format string, a ...any) { - report.logger.Infof(format, a...) -} - -// Debugf forwards the given informational message -// to the logger instance provided during initialisation. -// -// This method is here just for convenience and performs no deduplication. -func (report *ErrorReport) Debugf(format string, a ...any) { - report.logger.Debugf(format, a...) -} - -// Statusf forwards the given status message -// to the logger instance provided during initialisation. -// -// This method is here just for convenience and performs no deduplication. -func (report *ErrorReport) Statusf(format string, a ...any) { - report.logger.Statusf(format, a...) -} diff --git a/v3/internal/generator/events.go b/v3/internal/generator/events.go deleted file mode 100644 index ef1ebd380..000000000 --- a/v3/internal/generator/events.go +++ /dev/null @@ -1,53 +0,0 @@ -package generator - -import ( - "path/filepath" - - "github.com/wailsapp/wails/v3/internal/generator/collect" -) - -func (generator *Generator) generateEvents(events *collect.EventMap) { - // Generate event data table. - generator.scheduler.Schedule(func() { - file, err := generator.creator.Create(filepath.Join(events.Imports.Self, generator.renderer.EventDataFile())) - if err != nil { - generator.logger.Errorf("%v", err) - generator.logger.Errorf("event data table generation failed") - return - } - defer func() { - if err := file.Close(); err != nil { - generator.logger.Errorf("%v", err) - generator.logger.Errorf("event data table generation failed") - } - }() - - err = generator.renderer.EventData(file, events) - if err != nil { - generator.logger.Errorf("%v", err) - generator.logger.Errorf("event data table generation failed") - } - }) - - // Generate event creation code. - generator.scheduler.Schedule(func() { - file, err := generator.creator.Create(filepath.Join(events.Imports.Self, generator.renderer.EventCreateFile())) - if err != nil { - generator.logger.Errorf("%v", err) - generator.logger.Errorf("event creation code generation failed") - return - } - defer func() { - if err := file.Close(); err != nil { - generator.logger.Errorf("%v", err) - generator.logger.Errorf("event creation code generation failed") - } - }() - - err = generator.renderer.EventCreate(file, events) - if err != nil { - generator.logger.Errorf("%v", err) - generator.logger.Errorf("event creation code generation failed") - } - }) -} diff --git a/v3/internal/generator/generate.go b/v3/internal/generator/generate.go deleted file mode 100644 index 2885cdd3c..000000000 --- a/v3/internal/generator/generate.go +++ /dev/null @@ -1,280 +0,0 @@ -package generator - -import ( - "fmt" - "io" - "strings" - "sync" - "time" - - "github.com/wailsapp/wails/v3/internal/flags" - "github.com/wailsapp/wails/v3/internal/generator/collect" - "github.com/wailsapp/wails/v3/internal/generator/config" - "github.com/wailsapp/wails/v3/internal/generator/render" -) - -// Generator wraps all bookkeeping data structures that are needed -// to generate bindings for a set of packages. -type Generator struct { - options *flags.GenerateBindingsOptions - creator config.FileCreator - - // serviceFiles maps service file paths to their type object. - // It is used for lower/upper-case collision detection. - // Keys are strings, values are *types.TypeName. - serviceFiles sync.Map - - collector *collect.Collector - renderer *render.Renderer - - logger *ErrorReport - scheduler scheduler -} - -// NewGenerator configures a new generator instance. -// The options argument must not be nil. -// If creator is nil, no output file will be created. -// If logger is not nil, it is used to report messages interactively. -func NewGenerator(options *flags.GenerateBindingsOptions, creator config.FileCreator, logger config.Logger) *Generator { - if creator == nil { - creator = config.NullCreator - } - - report := NewErrorReport(logger) - - return &Generator{ - options: options, - creator: config.FileCreatorFunc(func(path string) (io.WriteCloser, error) { - report.Debugf("writing output file %s", path) - return creator.Create(path) - }), - - logger: report, - } -} - -// Generate runs the binding generation process -// for the packages specified by the given patterns. -// -// Concurrent or repeated calls to Generate with the same receiver -// are not allowed. -// -// The stats result field is never nil. -// -// The error result field is nil in case of complete success (no warning). -// Otherwise, it may either report errors that occured while loading -// the initial set of packages, or errors returned by the static analyser, -// or be an [ErrorReport] instance. -// -// If error is an ErrorReport, it may have accumulated no errors, just warnings. -// When this is the case, all bindings have been generated successfully. -// -// Parsing/type-checking errors or errors encountered while writing -// individual files will be printed directly to the [config.Logger] instance -// provided during initialisation. -func (generator *Generator) Generate(patterns ...string) (stats *collect.Stats, err error) { - stats = &collect.Stats{} - stats.Start() - defer stats.Stop() - - // Validate file names. - err = generator.validateFileNames() - if err != nil { - return - } - - // Parse build flags. - buildFlags, err := generator.options.BuildFlags() - if err != nil { - return - } - - // Start package loading feedback. - var lpkgMutex sync.Mutex - generator.logger.Statusf("Loading packages...") - go func() { - time.Sleep(5 * time.Second) - if lpkgMutex.TryLock() { - generator.logger.Statusf("Loading packages... (this may take a long time)") - lpkgMutex.Unlock() - } - }() - - systemPaths, err := ResolveSystemPaths(buildFlags) - if err != nil { - return - } - - // Load initial packages. - pkgs, err := LoadPackages(buildFlags, patterns...) - - // Suppress package loading feedback. - lpkgMutex.Lock() - - // Check for loading errors. - if err != nil { - return - } - if len(patterns) > 0 && len(pkgs) == 0 { - err = ErrNoPackages - return - } - - // Report parsing/type-checking errors. - for _, pkg := range pkgs { - for _, err := range pkg.Errors { - generator.logger.Warningf("%v", err) - } - } - - // Panic on repeated calls. - if generator.collector != nil { - panic("Generate() must not be called more than once on the same receiver") - } - - // Update status. - if generator.options.NoEvents { - generator.logger.Statusf("Looking for services...") - } else { - generator.logger.Statusf("Looking for services and events...") - } - serviceOrEventFound := sync.OnceFunc(func() { generator.logger.Statusf("Generating bindings...") }) - - // Run static analysis. - services, registerEvent, err := FindServices(pkgs, systemPaths, generator.logger) - - // Initialise subcomponents. - generator.collector = collect.NewCollector(pkgs, registerEvent, systemPaths, generator.options, &generator.scheduler, generator.logger) - generator.renderer = render.NewRenderer(generator.collector, generator.options) - - // Check for analyser errors. - if err != nil { - return - } - - // Discard unneeded data. - pkgs = nil - - // Schedule collection and code generation for event data types. - if !generator.options.NoEvents { - generator.scheduler.Schedule(func() { - events := generator.collector.EventMap().Collect() - if len(events.Defs) > 0 { - serviceOrEventFound() - // Not a data race because we wait for this scheduled task - // to complete before accessing stats again. - stats.Add(events.Stats()) - } - generator.generateEvents(events) - }) - } - - // Schedule code generation for each found service. - for obj := range services { - serviceOrEventFound() - generator.scheduler.Schedule(func() { - generator.generateService(obj) - }) - } - - // Wait until all services have been generated and all models collected. - generator.scheduler.Wait() - - // Invariants: - // - Service files have been generated for all discovered services; - // - ModelInfo.Collect has been called on all discovered models, and therefore - // - all required models have been discovered. - - // Update status. - if generator.options.NoIndex { - generator.logger.Statusf("Generating models...") - } else { - generator.logger.Statusf("Generating models and index files...") - } - - // Schedule models, index and included files generation for each package. - for pkg := range generator.collector.Iterate { - generator.scheduler.Schedule(func() { - generator.generateModelsIndexIncludes(pkg) - }) - } - - // Wait until all models and indices have been generated. - generator.scheduler.Wait() - - // Populate stats. - generator.logger.Statusf("Collecting stats...") - for info := range generator.collector.Iterate { - stats.Add(info.Stats()) - } - - // Return non-empty error report. - if generator.logger.HasErrors() || generator.logger.HasWarnings() { - err = generator.logger - } - - return -} - -// generateModelsIndexIncludes schedules generation of public/private model files, -// included files and, if allowed by the options, -// of an index file for the given package. -func (generator *Generator) generateModelsIndexIncludes(pkg *collect.PackageInfo) { - index := pkg.Index(generator.options.TS) - - // info.Index implies info.Collect: goroutines spawned below - // can access package information freely. - - if len(index.Models) > 0 { - generator.scheduler.Schedule(func() { - generator.generateModels(pkg, index.Models) - }) - } - - if len(index.Package.Includes) > 0 { - generator.scheduler.Schedule(func() { - generator.generateIncludes(index) - }) - } - - if !generator.options.NoIndex && !index.IsEmpty() { - generator.generateIndex(index) - } -} - -// validateFileNames validates user-provided filenames. -func (generator *Generator) validateFileNames() error { - switch { - case generator.options.ModelsFilename == "": - return fmt.Errorf("models filename must not be empty") - - case !generator.options.NoIndex && generator.options.IndexFilename == "": - return fmt.Errorf("package index filename must not be empty") - - case generator.options.ModelsFilename != strings.ToLower(generator.options.ModelsFilename): - return fmt.Errorf("models filename must not contain uppercase characters") - - case generator.options.IndexFilename != strings.ToLower(generator.options.IndexFilename): - return fmt.Errorf("package index filename must not contain uppercase characters") - - case !generator.options.NoIndex && generator.options.ModelsFilename == generator.options.IndexFilename: - return fmt.Errorf("models and package indexes cannot share the same filename") - } - - return nil -} - -// scheduler provides an implementation of the [collect.Scheduler] interface. -type scheduler struct { - sync.WaitGroup -} - -// Schedule runs the given function concurrently, -// registering it on the scheduler's wait group. -func (sched *scheduler) Schedule(task func()) { - sched.Add(1) - go func() { - defer sched.Done() - task() - }() -} diff --git a/v3/internal/generator/generate_test.go b/v3/internal/generator/generate_test.go deleted file mode 100644 index 04c01bef6..000000000 --- a/v3/internal/generator/generate_test.go +++ /dev/null @@ -1,273 +0,0 @@ -package generator - -import ( - "errors" - "fmt" - "io" - "io/fs" - "os" - "path/filepath" - "slices" - "strings" - "sync" - "testing" - - "github.com/google/go-cmp/cmp" - "github.com/wailsapp/wails/v3/internal/flags" - "github.com/wailsapp/wails/v3/internal/generator/config" - "github.com/wailsapp/wails/v3/internal/generator/render" -) - -const testcases = "github.com/wailsapp/wails/v3/internal/generator/testcases/..." - -type testParams struct { - name string - options *flags.GenerateBindingsOptions - outputDir string - want map[string]bool -} - -func TestGenerator(t *testing.T) { - const ( - useNamesBit = 1 << iota - useInterfacesBit - tsBit - ) - - // Generate configuration matrix. - tests := make([]*testParams, 1<<3) - for i := range tests { - options := &flags.GenerateBindingsOptions{ - ModelsFilename: "models", - IndexFilename: "index", - - UseBundledRuntime: true, - - TS: i&tsBit != 0, - UseInterfaces: i&useInterfacesBit != 0, - UseNames: i&useNamesBit != 0, - } - - name := configString(options) - - tests[i] = &testParams{ - name: name, - options: options, - outputDir: filepath.Join("testdata/output", name), - want: make(map[string]bool), - } - } - - for _, test := range tests { - // Create output dir. - if err := os.MkdirAll(test.outputDir, 0777); err != nil { - t.Fatal(err) - } - - // Walk output dir. - err := filepath.WalkDir(test.outputDir, func(path string, d fs.DirEntry, err error) error { - // Skip directories. - if d.IsDir() { - return nil - } - - // Skip got files. - if strings.HasSuffix(d.Name(), ".got.js") || strings.HasSuffix(d.Name(), ".got.ts") || strings.HasSuffix(d.Name(), ".got.log") { - return nil - } - - // Record file. - test.want[filepath.Clean("."+path[len(test.outputDir):])] = false - return nil - }) - - if err != nil { - t.Fatal(err) - } - } - - // Run tests. - for _, test := range tests { - t.Run(test.name, func(t *testing.T) { - creator := outputCreator(t, test) - - generator := NewGenerator( - test.options, - creator, - // Use NullLogger to suppress console output during tests. - // Warnings are written to warnings.log for comparison instead. - // This prevents GitHub Actions Go problem matcher from treating - // warning output as errors. - config.NullLogger, - ) - - _, err := generator.Generate(testcases) - if report := (*ErrorReport)(nil); errors.As(err, &report) { - if report.HasErrors() { - t.Error(report) - } - - // Log warnings and compare with reference output. - if log, err := creator.Create("warnings.log"); err != nil { - t.Error(err) - } else { - func() { - defer log.Close() - - warnings := report.Warnings() - slices.Sort(warnings) - - // Normalize paths in warnings to be relative to the testcases directory - // This ensures consistent output across different development environments and CI - for i, msg := range warnings { - // Handle both Unix and Windows path separators - msg = strings.ReplaceAll(msg, "\\", "/") - - // Check if this is a file path (contains line:column position) - // File paths look like: /path/to/file.go:123:45: message - // Package paths look like: package github.com/...: message - if strings.HasPrefix(msg, "package ") { - // Keep package warnings as-is - warnings[i] = msg - } else if idx := strings.Index(msg, "testcases/"); idx >= 0 { - // Check if it's a file path by looking for :line:column pattern after testcases/ - testcasesEnd := idx + len("testcases/") - colonIdx := strings.Index(msg[testcasesEnd:], ":") - if colonIdx > 0 { - // This looks like a file path, normalize it - warnings[i] = "/testcases/" + msg[testcasesEnd:] - } else { - // Not a file path, keep as-is - warnings[i] = msg - } - } else { - // Keep other warnings as-is - warnings[i] = msg - } - } - - for _, msg := range warnings { - // Prefix with [warn] to prevent GitHub Actions Go problem matcher - // from treating these as errors when diff output is shown - fmt.Fprint(log, "[warn] "+msg, render.Newline) - } - }() - } - } else if err != nil { - t.Error(err) - } - - for path, present := range test.want { - if !present { - t.Errorf("Missing output file '%s'", path) - } - } - }) - } -} - -// configString computes a subtest name from the given configuration. -func configString(options *flags.GenerateBindingsOptions) string { - lang := "JS" - if options.TS { - lang = "TS" - } - return fmt.Sprintf("lang=%s/UseInterfaces=%v/UseNames=%v", lang, options.UseInterfaces, options.UseNames) -} - -// outputCreator returns a FileCreator that detects want/got pairs -// and schedules them for comparison. -// -// If no corresponding want file exists, it is created and reported. -func outputCreator(t *testing.T, params *testParams) config.FileCreator { - var mu sync.Mutex - return config.FileCreatorFunc(func(path string) (io.WriteCloser, error) { - path = filepath.Clean(path) - prefixedPath := filepath.Join(params.outputDir, path) - - // Protect want map accesses. - mu.Lock() - defer mu.Unlock() - - if seen, ok := params.want[path]; ok { - // File exists: mark as seen and compare. - if seen { - t.Errorf("Duplicate output file '%s'", path) - } - params.want[path] = true - - // Open want file. - wf, err := os.Open(prefixedPath) - if err != nil { - return nil, err - } - - // Create or truncate got file. - ext := filepath.Ext(prefixedPath) - gf, err := os.Create(fmt.Sprintf("%s.got%s", prefixedPath[:len(prefixedPath)-len(ext)], ext)) - if err != nil { - return nil, err - } - - // Initialise comparer. - return &outputComparer{t, path, wf, gf}, nil - } else { - // File does not exist: create it. - t.Errorf("Unexpected output file '%s'", path) - params.want[path] = true - - if err := os.MkdirAll(filepath.Dir(prefixedPath), 0777); err != nil { - return nil, err - } - - return os.Create(prefixedPath) - } - }) -} - -// outputComparer is a io.WriteCloser that writes to got. -// -// When Close is called, it compares want to got; if they are identical, -// it deletes got; otherwise it reports a testing error. -type outputComparer struct { - t *testing.T - path string - want *os.File - got *os.File -} - -func (comparer *outputComparer) Write(data []byte) (int, error) { - return comparer.got.Write(data) -} - -func (comparer *outputComparer) Close() error { - defer comparer.want.Close() - defer comparer.got.Close() - - comparer.got.Seek(0, io.SeekStart) - - // Read want data. - want, err := io.ReadAll(comparer.want) - if err != nil { - comparer.t.Error(err) - return nil - } - - got, err := io.ReadAll(comparer.got) - if err != nil { - comparer.t.Error(err) - return nil - } - - if diff := cmp.Diff(want, got); diff != "" { - comparer.t.Errorf("Output file '%s' mismatch (-want +got):\n%s", comparer.path, diff) - } else { - // On success, delete got file. - comparer.got.Close() - if err := os.Remove(comparer.got.Name()); err != nil { - comparer.t.Error(err) - } - } - - return nil -} diff --git a/v3/internal/generator/includes.go b/v3/internal/generator/includes.go deleted file mode 100644 index b8bed2392..000000000 --- a/v3/internal/generator/includes.go +++ /dev/null @@ -1,100 +0,0 @@ -package generator - -import ( - "io" - "os" - "path/filepath" - "slices" - "strings" - - "github.com/wailsapp/wails/v3/internal/generator/collect" -) - -// generateIncludes copies included files to the package directory -// for the package summarised by the given index. -func (generator *Generator) generateIncludes(index *collect.PackageIndex) { - for name, path := range index.Package.Includes { - // Validate filename. - switch name { - case generator.renderer.ModelsFile(): - if index.HasExportedModels { - generator.logger.Errorf( - "package %s: included file '%s' collides with models filename; please rename the file or choose a different filename for models", - index.Package.Path, - path, - ) - return - } - - case generator.renderer.IndexFile(): - if !generator.options.NoIndex && !index.IsEmpty() { - generator.logger.Errorf( - "package %s: included file '%s' collides with JS/TS index filename; please rename the file or choose a different filename for JS/TS indexes", - index.Package.Path, - path, - ) - return - } - } - - // Validate against services. - service, ok := slices.BinarySearchFunc(index.Services, name, func(service *collect.ServiceInfo, name string) int { - return strings.Compare(generator.renderer.ServiceFile(service.Name), name) - }) - if ok { - generator.logger.Errorf( - "package %s: included file '%s' collides with filename for service %s; please rename either the file or the service", - index.Package.Path, - path, - index.Services[service].Name, - ) - return - } - - // Copy file to destination in separate goroutine. - generator.scheduler.Schedule(func() { - src, err := os.Open(path) - if err != nil { - generator.logger.Errorf("%v", err) - generator.logger.Errorf("package %s: could not read included file '%s'", index.Package.Path, path) - return - } - defer src.Close() - - stat, err := src.Stat() - if err != nil { - generator.logger.Errorf("%v", err) - generator.logger.Errorf("package %s: could not read included file '%s'", index.Package.Path, path) - return - } - - if stat.IsDir() { - generator.logger.Errorf( - "package %s: included file '%s' is a directory; please glob or list all descendants explicitly", - index.Package.Path, - path, - ) - return - } - - dst, err := generator.creator.Create(filepath.Join(index.Package.Path, name)) - if err != nil { - generator.logger.Errorf("%v", err) - generator.logger.Errorf("package %s: could not write included file '%s'", index.Package.Path, name) - return - } - defer func() { - if err := dst.Close(); err != nil { - generator.logger.Errorf("%v", err) - generator.logger.Errorf("package %s: could not write included file '%s'", index.Package.Path, name) - } - }() - - _, err = io.Copy(dst, src) - if err != nil { - generator.logger.Errorf("%v", err) - generator.logger.Errorf("package %s: could not copy included file '%s'", index.Package.Path, name) - } - }) - } -} diff --git a/v3/internal/generator/index.go b/v3/internal/generator/index.go deleted file mode 100644 index e7a73c71f..000000000 --- a/v3/internal/generator/index.go +++ /dev/null @@ -1,53 +0,0 @@ -package generator - -import ( - "path/filepath" - - "github.com/wailsapp/wails/v3/internal/generator/collect" -) - -// generateIndex generates an index file from the given index information. -func (generator *Generator) generateIndex(index *collect.PackageIndex) { - defer generator.reportDualRoles(index) - - file, err := generator.creator.Create(filepath.Join(index.Package.Path, generator.renderer.IndexFile())) - if err != nil { - generator.logger.Errorf("%v", err) - generator.logger.Errorf("package %s: index generation failed", index.Package.Path) - return - } - defer func() { - if err := file.Close(); err != nil { - generator.logger.Errorf("%v", err) - generator.logger.Errorf("package %s: index generation failed", index.Package.Path) - } - }() - - err = generator.renderer.Index(file, index) - if err != nil { - generator.logger.Errorf("%v", err) - generator.logger.Errorf("package %s: index generation failed", index.Package.Path) - } -} - -// reportDualRoles checks for models types that are also service types -// and emits a warning. -func (generator *Generator) reportDualRoles(index *collect.PackageIndex) { - services, models := index.Services, index.Models - for len(services) > 0 && len(models) > 0 { - if services[0].Name < models[0].Name { - services = services[1:] - } else if services[0].Name > models[0].Name { - models = models[1:] - } else { - generator.logger.Warningf( - "package %s: type %s has been marked both as a service and as a model; shadowing between the two may take place when importing generated JS indexes", - index.Package.Path, - services[0].Name, - ) - - services = services[1:] - models = models[1:] - } - } -} diff --git a/v3/internal/generator/load.go b/v3/internal/generator/load.go deleted file mode 100644 index da09ff76f..000000000 --- a/v3/internal/generator/load.go +++ /dev/null @@ -1,123 +0,0 @@ -package generator - -import ( - "go/ast" - "go/parser" - "go/token" - - "github.com/wailsapp/wails/v3/internal/generator/config" - "golang.org/x/tools/go/packages" -) - -// ResolveSystemPaths resolves paths for stdlib and Wails packages. -func ResolveSystemPaths(buildFlags []string) (paths *config.SystemPaths, err error) { - // Resolve context pkg path. - contextPkgPaths, err := ResolvePatterns(buildFlags, "context") - if err != nil { - return - } else if len(contextPkgPaths) < 1 { - err = ErrNoContextPackage - return - } else if len(contextPkgPaths) > 1 { - // This should never happen... - panic("context package path matched multiple packages") - } - - // Resolve wails app pkg path. - wailsAppPkgPaths, err := ResolvePatterns(buildFlags, config.WailsAppPkgPath) - if err != nil { - return - } else if len(wailsAppPkgPaths) < 1 { - err = ErrNoApplicationPackage - return - } else if len(wailsAppPkgPaths) > 1 { - // This should never happen... - panic("wails application package path matched multiple packages") - } - - // Resolve wails internal pkg path. - wailsInternalPkgPaths, err := ResolvePatterns(buildFlags, config.WailsInternalPkgPath) - if err != nil { - return - } else if len(wailsInternalPkgPaths) < 1 { - err = ErrNoInternalPackage - return - } else if len(wailsInternalPkgPaths) > 1 { - // This should never happen... - panic("wails internal package path matched multiple packages") - } - - paths = &config.SystemPaths{ - ContextPackage: contextPkgPaths[0], - ApplicationPackage: wailsAppPkgPaths[0], - InternalPackage: wailsInternalPkgPaths[0], - } - return -} - -// ResolvePatterns returns a slice containing all package paths -// that match the given patterns, according to the underlying build tool -// and within the context of the current working directory. -func ResolvePatterns(buildFlags []string, patterns ...string) (paths []string, err error) { - rewrittenPatterns := make([]string, len(patterns)) - for i, pattern := range patterns { - rewrittenPatterns[i] = "pattern=" + pattern - } - - pkgs, err := packages.Load(&packages.Config{ - Mode: packages.NeedName, - BuildFlags: buildFlags, - }, rewrittenPatterns...) - - for _, pkg := range pkgs { - paths = append(paths, pkg.PkgPath) - } - - return -} - -// LoadPackages loads the packages specified by the given patterns -// and their whole dependency tree. It returns a slice containing -// all packages that match the given patterns and all of their direct -// and indirect dependencies. -// -// The returned slice is in post-order w.r.t. the dependency relation, -// i.e. if package A depends on package B, then package B precedes package A. -// -// All returned package instances include syntax trees and full type information. -// -// Syntax is loaded in the context of a global [token.FileSet], -// which is available through the field [packages.Package.Fset] -// on each returned package. Therefore, source positions -// are canonical across all loaded packages. -func LoadPackages(buildFlags []string, patterns ...string) (pkgs []*packages.Package, err error) { - rewrittenPatterns := make([]string, len(patterns)) - for i, pattern := range patterns { - rewrittenPatterns[i] = "pattern=" + pattern - } - - // Global file set. - fset := token.NewFileSet() - - roots, err := packages.Load(&packages.Config{ - // NOTE: some Go maintainers now believe deprecation was an error and recommend using Load* modes - // (see e.g. https://github.com/golang/go/issues/48226#issuecomment-1948792315). - Mode: packages.LoadAllSyntax, - BuildFlags: buildFlags, - Fset: fset, - ParseFile: func(fset *token.FileSet, filename string, src []byte) (file *ast.File, err error) { - file, err = parser.ParseFile(fset, filename, src, parser.ParseComments|parser.SkipObjectResolution) - return - }, - }, rewrittenPatterns...) - - // Flatten dependency tree. - packages.Visit(roots, nil, func(pkg *packages.Package) { - if pkg.Fset != fset { - panic("fileset missing or not the global one") - } - pkgs = append(pkgs, pkg) - }) - - return -} diff --git a/v3/internal/generator/models.go b/v3/internal/generator/models.go deleted file mode 100644 index 2fe4f407f..000000000 --- a/v3/internal/generator/models.go +++ /dev/null @@ -1,39 +0,0 @@ -package generator - -import ( - "path/filepath" - - "github.com/wailsapp/wails/v3/internal/generator/collect" -) - -// generateModels generates a JS/TS models file for the given list of models. -// A call to info.Collect must complete before entering generateModels. -func (generator *Generator) generateModels(info *collect.PackageInfo, models []*collect.ModelInfo) { - // Merge all import maps. - imports := collect.NewImportMap(info) - for _, model := range models { - imports.Merge(model.Imports) - } - - // Clear irrelevant imports. - imports.ImportModels = false - - file, err := generator.creator.Create(filepath.Join(info.Path, generator.renderer.ModelsFile())) - if err != nil { - generator.logger.Errorf("%v", err) - generator.logger.Errorf("package %s: models generation failed", info.Path) - return - } - defer func() { - if err := file.Close(); err != nil { - generator.logger.Errorf("%v", err) - generator.logger.Errorf("package %s: models generation failed", info.Path) - } - }() - - err = generator.renderer.Models(file, imports, models) - if err != nil { - generator.logger.Errorf("%v", err) - generator.logger.Errorf("package %s: models generation failed", info.Path) - } -} diff --git a/v3/internal/generator/render/create.go b/v3/internal/generator/render/create.go deleted file mode 100644 index 85d38a536..000000000 --- a/v3/internal/generator/render/create.go +++ /dev/null @@ -1,360 +0,0 @@ -package render - -import ( - "fmt" - "go/types" - "strings" - "text/template" - - "github.com/wailsapp/wails/v3/internal/generator/collect" -) - -// SkipCreate returns true if the given array of types needs no creation code. -func (m *module) SkipCreate(ts []types.Type) bool { - for _, typ := range ts { - if m.NeedsCreate(typ) { - return false - } - } - return true -} - -// NeedsCreate returns true if the given type needs some creation code. -func (m *module) NeedsCreate(typ types.Type) bool { - return m.needsCreateImpl(typ, make(map[*types.TypeName]bool)) -} - -// needsCreateImpl provides the actual implementation of NeedsCreate. -// The visited parameter is used to break cycles. -func (m *module) needsCreateImpl(typ types.Type, visited map[*types.TypeName]bool) bool { - switch t := typ.(type) { - case *types.Alias: - if m.collector.IsVoidAlias(t.Obj()) { - return false - } - - return m.needsCreateImpl(types.Unalias(typ), visited) - - case *types.Named: - obj := t.Obj() - if visited[obj] { - // The only way to hit a cycle here - // is through a chain of structs, nested pointers and arrays (not slices). - // We can safely return false at this point - // since the cycle will not contribute to the final answer. - return false - } - visited[obj] = true - - if obj.Pkg() == nil { - // Builtin named type: render underlying type. - return m.needsCreateImpl(t.Underlying(), visited) - } - - if m.collector.IsVoidAlias(obj) { - return false - } - - if collect.IsAny(typ) || collect.IsStringAlias(typ) { - break - } else if collect.IsClass(typ) { - return true - } else { - return m.needsCreateImpl(t.Underlying(), visited) - } - - case *types.Array, *types.Pointer: - return m.needsCreateImpl(typ.(interface{ Elem() types.Type }).Elem(), visited) - - case *types.Map, *types.Slice: - return true - - case *types.Struct: - if t.NumFields() == 0 || collect.MaybeJSONMarshaler(typ) != collect.NonMarshaler || collect.MaybeTextMarshaler(typ) != collect.NonMarshaler { - return false - } - - info := m.collector.Struct(t) - info.Collect() - - for _, field := range info.Fields { - if m.needsCreateImpl(field.Type, visited) { - return true - } - } - - case *types.TypeParam: - return true - } - - return false -} - -// JSCreate renders JS/TS code that creates an instance -// of the given type from JSON data. -// -// JSCreate's output may be incorrect -// if m.Imports.AddType has not been called for the given type. -func (m *module) JSCreate(typ types.Type) string { - return m.JSCreateWithParams(typ, "") -} - -// JSCreateWithParams renders JS/TS code that creates an instance -// of the given type from JSON data. For generic types, -// it renders parameterised code. -// -// JSCreateWithParams's output may be incorrect -// if m.Imports.AddType has not been called for the given type. -func (m *module) JSCreateWithParams(typ types.Type, params string) string { - if len(params) > 0 && !collect.IsParametric(typ) { - // Forget params for non-generic types. - params = "" - } - - switch t := typ.(type) { - case *types.Alias: - if m.collector.IsVoidAlias(t.Obj()) { - return "$Create.Any" - } - - return m.JSCreateWithParams(types.Unalias(typ), params) - - case *types.Array, *types.Pointer: - pp, ok := m.postponedCreates.At(typ).(*postponed) - if ok { - return fmt.Sprintf("$$createType%d%s", pp.index, params) - } - - createElement := m.JSCreateWithParams(typ.(interface{ Elem() types.Type }).Elem(), params) - if createElement != "$Create.Any" { - pp = &postponed{m.postponedCreates.Len(), params} - m.postponedCreates.Set(typ, pp) - return fmt.Sprintf("$$createType%d%s", pp.index, params) - } - - case *types.Map: - pp, ok := m.postponedCreates.At(typ).(*postponed) - if !ok { - m.JSCreateWithParams(t.Elem(), params) - pp = &postponed{m.postponedCreates.Len(), params} - m.postponedCreates.Set(typ, pp) - } - - return fmt.Sprintf("$$createType%d%s", pp.index, params) - - case *types.Named: - if t.Obj().Pkg() == nil { - // Builtin named type: render underlying type. - return m.JSCreateWithParams(t.Underlying(), params) - } - - if m.collector.IsVoidAlias(t.Obj()) { - return "$Create.Any" - } - - if !m.NeedsCreate(typ) { - break - } - - pp, ok := m.postponedCreates.At(typ).(*postponed) - if !ok { - if t.TypeArgs() != nil && t.TypeArgs().Len() > 0 { - // Postpone type args. - for i := range t.TypeArgs().Len() { - m.JSCreateWithParams(t.TypeArgs().At(i), params) - } - } - - pp = &postponed{m.postponedCreates.Len(), params} - m.postponedCreates.Set(typ, pp) - - if !collect.IsClass(typ) { - m.JSCreateWithParams(t.Underlying(), params) - } - } - - return fmt.Sprintf("$$createType%d%s", pp.index, params) - - case *types.Slice: - if types.Identical(typ, typeByteSlice) { - return "$Create.ByteSlice" - } - - pp, ok := m.postponedCreates.At(typ).(*postponed) - if !ok { - m.JSCreateWithParams(t.Elem(), params) - pp = &postponed{m.postponedCreates.Len(), params} - m.postponedCreates.Set(typ, pp) - } - - return fmt.Sprintf("$$createType%d%s", pp.index, params) - - case *types.Struct: - if t.NumFields() == 0 || collect.MaybeJSONMarshaler(typ) != collect.NonMarshaler || collect.MaybeTextMarshaler(typ) != collect.NonMarshaler { - break - } - - pp, ok := m.postponedCreates.At(typ).(*postponed) - if ok { - return fmt.Sprintf("$$createType%d%s", pp.index, params) - } - - info := m.collector.Struct(t) - info.Collect() - - postpone := false - for _, field := range info.Fields { - if m.JSCreateWithParams(field.Type, params) != "$Create.Any" { - postpone = true - } - } - - if postpone { - pp = &postponed{m.postponedCreates.Len(), params} - m.postponedCreates.Set(typ, pp) - return fmt.Sprintf("$$createType%d%s", pp.index, params) - } - - case *types.TypeParam: - return fmt.Sprintf("$$createParam%s", typeparam(t.Index(), t.Obj().Name())) - } - - return "$Create.Any" -} - -// PostponedCreates returns the list of postponed create functions -// for the given module. -func (m *module) PostponedCreates() []string { - result := make([]string, m.postponedCreates.Len()) - - m.postponedCreates.Iterate(func(key types.Type, value any) { - pp := value.(*postponed) - - pre, post := "", "" - if pp.params != "" { - if m.TS { - pre = createParamRegex.ReplaceAllString(pp.params, "${0}: any") + " => " - } else { - pre = "/** @type {(...args: any[]) => any} */(" + pp.params + " => " - post = ")" - } - } - - switch t := key.(type) { - case *types.Array, *types.Slice: - result[pp.index] = fmt.Sprintf("%s$Create.Array(%s)%s", pre, m.JSCreateWithParams(t.(interface{ Elem() types.Type }).Elem(), pp.params), post) - - case *types.Map: - result[pp.index] = fmt.Sprintf("%s$Create.Map($Create.Any, %s)%s", pre, m.JSCreateWithParams(t.Elem(), pp.params), post) - - case *types.Named: - if !collect.IsClass(key) { - // Creation functions for non-struct named types - // require an indirect assignment to break cycles. - - // Typescript cannot infer the return type on its own: add hints. - cast, argType, returnType := "", "", "" - if m.TS { - argType = ": any[]" - returnType = ": any" - } else { - cast = "/** @type {(...args: any[]) => any} */" - } - - result[pp.index] = fmt.Sprintf(` -%s(function $$initCreateType%d(...args%s)%s { - if ($$createType%d === $$initCreateType%d) { - $$createType%d = %s%s%s; - } - return $$createType%d(...args); -})`, - cast, pp.index, argType, returnType, - pp.index, pp.index, - pp.index, pre, m.JSCreateWithParams(t.Underlying(), pp.params), post, - pp.index, - )[1:] // Remove initial newline. - - // We're done. - break - } - - var builder strings.Builder - - builder.WriteString(pre) - - if t.Obj().Pkg().Path() == m.Imports.Self { - if m.Imports.ImportModels { - builder.WriteString("$models.") - } - } else { - builder.WriteString(jsimport(m.Imports.External[t.Obj().Pkg().Path()])) - builder.WriteRune('.') - } - builder.WriteString(jsid(t.Obj().Name())) - builder.WriteString(".createFrom") - - if t.TypeArgs() != nil && t.TypeArgs().Len() > 0 { - builder.WriteString("(") - for i := range t.TypeArgs().Len() { - if i > 0 { - builder.WriteString(", ") - } - builder.WriteString(m.JSCreateWithParams(t.TypeArgs().At(i), pp.params)) - } - builder.WriteString(")") - } - builder.WriteString(post) - - result[pp.index] = builder.String() - - case *types.Pointer: - result[pp.index] = fmt.Sprintf("%s$Create.Nullable(%s)%s", pre, m.JSCreateWithParams(t.Elem(), pp.params), post) - - case *types.Struct: - info := m.collector.Struct(t) - info.Collect() - - var builder strings.Builder - builder.WriteString(pre) - builder.WriteString("$Create.Struct({") - - for _, field := range info.Fields { - createField := m.JSCreateWithParams(field.Type, pp.params) - if createField == "$Create.Any" { - continue - } - - builder.WriteString("\n \"") - template.JSEscape(&builder, []byte(field.JsonName)) - builder.WriteString("\": ") - builder.WriteString(createField) - builder.WriteRune(',') - } - - if len(info.Fields) > 0 { - builder.WriteRune('\n') - } - builder.WriteString("})") - builder.WriteString(post) - - result[pp.index] = builder.String() - - default: - result[pp.index] = pre + "$Create.Any" + post - } - }) - - if Newline != "\n" { - // Replace newlines according to local git config. - for i := range result { - result[i] = strings.ReplaceAll(result[i], "\n", Newline) - } - } - - return result -} - -type postponed struct { - index int - params string -} diff --git a/v3/internal/generator/render/default.go b/v3/internal/generator/render/default.go deleted file mode 100644 index 793c704ba..000000000 --- a/v3/internal/generator/render/default.go +++ /dev/null @@ -1,179 +0,0 @@ -package render - -import ( - "fmt" - "go/types" - "strings" - "text/template" - - "github.com/wailsapp/wails/v3/internal/generator/collect" -) - -// JSDefault renders the Javascript representation -// of the zero value of the given type, -// using the receiver's import map to resolve dependencies. -// -// JSDefault's output may be incorrect -// if imports.AddType has not been called for the given type. -func (m *module) JSDefault(typ types.Type, quoted bool) (result string) { - switch t := typ.(type) { - case *types.Alias, *types.Named: - result, ok := m.renderNamedDefault(t.(aliasOrNamed), quoted) - if ok { - return result - } - - case *types.Array: - if t.Len() == 0 { - return "[]" - } else { - // Initialise array with expected number of elements - return fmt.Sprintf("Array.from({ length: %d }, () => %s)", t.Len(), m.JSDefault(t.Elem(), false)) - } - - case *types.Slice: - if types.Identical(typ, typeByteSlice) { - return `""` - } else { - return "[]" - } - - case *types.Basic: - return m.renderBasicDefault(t, quoted) - - case *types.Map: - return "{}" - - case *types.Struct: - return m.renderStructDefault(t) - - case *types.TypeParam: - // Should be unreachable - panic("type parameters have no default value") - } - - // Fall back to null. - // encoding/json ignores null values so this is safe. - return "null" -} - -// renderBasicDefault outputs the Javascript representation -// of the zero value for the given basic type. -func (*module) renderBasicDefault(typ *types.Basic, quoted bool) string { - switch { - case typ.Info()&types.IsBoolean != 0: - if quoted { - return `"false"` - } else { - return "false" - } - - case typ.Info()&types.IsNumeric != 0 && typ.Info()&types.IsComplex == 0: - if quoted { - return `"0"` - } else { - return "0" - } - - case typ.Info()&types.IsString != 0: - if quoted { - return `'""'` - } else { - return `""` - } - } - - // Fall back to untyped mode. - if quoted { - return `""` - } else { - // encoding/json ignores null values so this is safe. - return "null" - } -} - -// renderNamedDefault outputs the Javascript representation -// of the zero value for the given alias or named type. -// The result field named 'ok' is true when the resulting code is valid. -// If false, it must be discarded. -func (m *module) renderNamedDefault(typ aliasOrNamed, quoted bool) (result string, ok bool) { - if typ.Obj().Pkg() == nil { - // Builtin alias or named type: render underlying type. - return m.JSDefault(typ.Underlying(), quoted), true - } - - if quoted { - // WARN: Do not test with IsAny/IsStringAlias here!! We only want to catch marshalers. - if collect.MaybeJSONMarshaler(typ) == collect.NonMarshaler && collect.MaybeTextMarshaler(typ) == collect.NonMarshaler { - if basic, ok := typ.Underlying().(*types.Basic); ok { - // Quoted mode for basic alias/named type that is not a marshaler: delegate. - return m.renderBasicDefault(basic, quoted), true - } - // No need to handle typeparams: they are initialised to null anyways. - } - } - - prefix := "" - if m.Imports.ImportModels { - prefix = "$models." - } - - if collect.IsAny(typ) { - return "", false - } else if collect.MaybeTextMarshaler(typ) != collect.NonMarshaler { - return `""`, true - } else if collect.IsClass(typ) && !istpalias(typ) { - if typ.Obj().Pkg().Path() == m.Imports.Self { - return fmt.Sprintf("(new %s%s())", prefix, jsid(typ.Obj().Name())), true - } else { - return fmt.Sprintf("(new %s.%s())", jsimport(m.Imports.External[typ.Obj().Pkg().Path()]), jsid(typ.Obj().Name())), true - } - } else if _, isAlias := typ.(*types.Alias); isAlias { - return m.JSDefault(types.Unalias(typ), quoted), true - } else if len(m.collector.Model(typ.Obj()).Collect().Values) > 0 { - if typ.Obj().Pkg().Path() == m.Imports.Self { - return fmt.Sprintf("%s%s.$zero", prefix, jsid(typ.Obj().Name())), true - } else { - return fmt.Sprintf("%s.%s.$zero", jsimport(m.Imports.External[typ.Obj().Pkg().Path()]), jsid(typ.Obj().Name())), true - } - } else { - return m.JSDefault(typ.Underlying(), quoted), true - } -} - -// renderStructDefault outputs the Javascript representation -// of the zero value for the given struct type. -func (m *module) renderStructDefault(typ *types.Struct) string { - if collect.MaybeJSONMarshaler(typ) != collect.NonMarshaler { - return "null" - } else if collect.MaybeTextMarshaler(typ) != collect.NonMarshaler { - return `""` - } - - info := m.collector.Struct(typ) - info.Collect() - - var builder strings.Builder - - builder.WriteRune('{') - for i, field := range info.Fields { - if field.Optional { - continue - } - - if i > 0 { - builder.WriteString(", ") - } - - builder.WriteRune('"') - template.JSEscape(&builder, []byte(field.JsonName)) - builder.WriteRune('"') - - builder.WriteString(": ") - - builder.WriteString(m.JSDefault(field.Type, field.Quoted)) - } - builder.WriteRune('}') - - return builder.String() -} diff --git a/v3/internal/generator/render/doc.go b/v3/internal/generator/render/doc.go deleted file mode 100644 index 8ed46d9c5..000000000 --- a/v3/internal/generator/render/doc.go +++ /dev/null @@ -1,136 +0,0 @@ -package render - -import ( - "bufio" - "bytes" - "go/ast" - "strings" - "unicode" - - "github.com/wailsapp/wails/v3/internal/generator/collect" -) - -// hasdoc checks whether the given comment group contains actual doc comments. -func hasdoc(group *ast.CommentGroup) bool { - if group == nil { - return false - } - - // TODO: this is horrible, make it more efficient? - return strings.ContainsFunc(group.Text(), func(r rune) bool { return !unicode.IsSpace(r) }) -} - -var commentTerminator = []byte("*/") - -// jsdoc splits the given comment into lines and rewrites it as follows: -// - first, line terminators are stripped; -// - then a line terminator, the indent string and ' * ' -// are prepended to each line; -// - occurrences of the comment terminator '*/' are replaced with '* /' -// to avoid accidentally terminating the surrounding comment. -// -// All lines thus modified are joined back together. -// -// The returned string can be inserted in a multiline JSDoc comment -// with the given indentation. -func jsdoc(comment string, indent string) string { - var builder strings.Builder - prefix := []byte(Newline + indent + " * ") - - scanner := bufio.NewScanner(bytes.NewReader([]byte(comment))) - for scanner.Scan() { - line := scanner.Bytes() - - // Prepend prefix. - builder.Write(prefix) - - // Escape comment terminators. - for t := bytes.Index(line, commentTerminator); t >= 0; t = bytes.Index(line, commentTerminator) { - builder.Write(line[:t+1]) - builder.WriteRune(' ') - line = line[t+1:] - } - - builder.Write(line) - } - - return builder.String() -} - -// jsdocline removes all newlines in the given comment -// and escapes comment terminators using the same strategy as jsdoc. -func jsdocline(comment string) string { - var builder strings.Builder - - scanner := bufio.NewScanner(bytes.NewReader([]byte(comment))) - for scanner.Scan() { - line := bytes.TrimSpace(scanner.Bytes()) - if len(line) == 0 { - // Skip empty lines. - continue - } - - // Prepend space to separate lines. - builder.WriteRune(' ') - - // Escape comment terminators. - for t := bytes.Index(line, commentTerminator); t >= 0; t = bytes.Index(line, commentTerminator) { - builder.Write(line[:t+1]) - builder.WriteRune(' ') - line = line[t+1:] - } - - builder.Write(line) - } - - // Return resulting string, but skip initial space. - return builder.String()[1:] -} - -// isjsdocid returns true if the given string is a valid ECMAScript identifier, -// excluding unicode escape sequences. This is the property name format supported by JSDoc. -func isjsdocid(name string) bool { - for i, r := range name { - if i == 0 && !id_start(r) && r != '$' && r != '_' { - return false - } else if i > 0 && !id_continue(r) && r != '$' { - return false - } - } - return true -} - -// isjsdocobj returns true if all field names in the given model -// are valid jsdoc property names. -func isjsdocobj(model *collect.ModelInfo) bool { - if len(model.Fields) == 0 { - return false - } - for _, decl := range model.Fields { - for _, field := range decl { - if !isjsdocid(field.JsonName) { - return false - } - } - } - return true -} - -// id_start returns true if the given rune is in the ID_Start category -// according to UAX#31 (https://unicode.org/reports/tr31/). -func id_start(r rune) bool { - return (unicode.IsLetter(r) || - unicode.Is(unicode.Nl, r) || - unicode.Is(unicode.Other_ID_Start, r)) && !unicode.Is(unicode.Pattern_Syntax, r) && !unicode.Is(unicode.Pattern_White_Space, r) -} - -// id_continue returns true if the given rune is in the ID_Continue category -// according to UAX#31 (https://unicode.org/reports/tr31/). -func id_continue(r rune) bool { - return (id_start(r) || - unicode.Is(unicode.Mn, r) || - unicode.Is(unicode.Mc, r) || - unicode.Is(unicode.Nd, r) || - unicode.Is(unicode.Pc, r) || - unicode.Is(unicode.Other_ID_Continue, r)) && !unicode.Is(unicode.Pattern_Syntax, r) && !unicode.Is(unicode.Pattern_White_Space, r) -} diff --git a/v3/internal/generator/render/functions.go b/v3/internal/generator/render/functions.go deleted file mode 100644 index 6123095e8..000000000 --- a/v3/internal/generator/render/functions.go +++ /dev/null @@ -1,107 +0,0 @@ -package render - -import ( - "fmt" - "go/types" - "math/big" - "strconv" - "strings" - "text/template" - - "github.com/wailsapp/wails/v3/internal/generator/collect" -) - -// tmplFunctions holds a map of utility functions -// that should be available in every template. -var tmplFunctions = template.FuncMap{ - "fixext": fixext, - "hasdoc": hasdoc, - "isjsdocid": isjsdocid, - "isjsdocobj": isjsdocobj, - "istpalias": istpalias, - "jsdoc": jsdoc, - "jsdocline": jsdocline, - "jsid": jsid, - "jsimport": jsimport, - "jsparam": jsparam, - "jsvalue": jsvalue, - "modelinfo": modelinfo, - "typeparam": typeparam, - "unalias": types.Unalias, -} - -// fixext replaces a *.ts extension with *.js in the given string. -// This is necessary to allow emitting javascript with the Typescript compiler. -func fixext(path string) string { - if strings.HasSuffix(path, ".ts") { - return path[:len(path)-3] + ".js" - } else { - return path - } -} - -// jsimport formats an external import name -// by joining the name with its occurrence index. -// Names are modified even when the index is 0 -// to avoid collisions with Go identifiers. -func jsimport(info collect.ImportInfo) string { - return fmt.Sprintf("%s$%d", info.Name, info.Index) -} - -// jsparam renders the JS name of a parameter. -// Blank parameters are replaced with a dollar sign followed by the given index. -// Non-blank parameters are escaped by [jsid]. -func jsparam(index int, param *collect.ParamInfo) string { - if param.Blank { - return "$" + strconv.Itoa(index) - } else { - return jsid(param.Name) - } -} - -// typeparam renders the TS name of a type parameter. -// Blank parameters are replaced with a double dollar sign -// followed by the given index. -// Non-blank parameters are escaped with jsid. -func typeparam(index int, param string) string { - if param == "" || param == "_" { - return "$$" + strconv.Itoa(index) - } else { - return jsid(param) - } -} - -// jsvalue renders a Go constant value to its Javascript representation. -func jsvalue(value any) string { - switch v := value.(type) { - case bool: - if v { - return "true" - } else { - return "false" - } - case string: - return fmt.Sprintf(`"%s"`, template.JSEscapeString(v)) - case int64: - return strconv.FormatInt(v, 10) - case *big.Int: - return v.String() - case *big.Float: - return v.Text('e', -1) - case *big.Rat: - return v.RatString() - } - - // Fall back to undefined. - return "(void(0))" -} - -// istpalias determines whether typ is an alias -// that when uninstantiated resolves to a typeparam. -func istpalias(typ types.Type) bool { - if alias, ok := typ.(*types.Alias); ok { - return collect.IsTypeParam(alias.Origin()) - } - - return false -} diff --git a/v3/internal/generator/render/identifier.go b/v3/internal/generator/render/identifier.go deleted file mode 100644 index 7a7b89f9d..000000000 --- a/v3/internal/generator/render/identifier.go +++ /dev/null @@ -1,92 +0,0 @@ -package render - -import ( - "slices" -) - -// jsid escapes identifiers that match JS/TS reserved words -// by prepending a dollar sign. -func jsid(ident string) string { - if _, reserved := slices.BinarySearch(protectedWords, ident); reserved { - return "$" + ident - } - return ident -} - -func init() { - // Ensure reserved words are sorted in ascending lexicographical order. - slices.Sort(protectedWords) -} - -// protectedWords is a list of JS + TS words that are either reserved -// or have special meaning. Keep in ascending lexicographical order -// for best startup performance. -var protectedWords = []string{ - "JSON", - "Object", - "any", - "arguments", - "as", - "async", - "await", - "boolean", - "break", - "case", - "catch", - "class", - "const", - "constructor", - "continue", - "debugger", - "declare", - "default", - "delete", - "do", - "else", - "enum", - "export", - "extends", - "false", - "finally", - "for", - "from", - "function", - "get", - "if", - "implements", - "import", - "in", - "instanceof", - "interface", - "let", - "module", - "namespace", - "new", - "null", - "number", - "of", - "package", - "private", - "protected", - "public", - "require", - "return", - "set", - "static", - "string", - "super", - "switch", - "symbol", - "this", - "throw", - "true", - "try", - "type", - "typeof", - "undefined", - "var", - "void", - "while", - "with", - "yield", -} diff --git a/v3/internal/generator/render/info.go b/v3/internal/generator/render/info.go deleted file mode 100644 index 3947f117a..000000000 --- a/v3/internal/generator/render/info.go +++ /dev/null @@ -1,77 +0,0 @@ -package render - -import ( - "regexp" - "strings" - - "github.com/wailsapp/wails/v3/internal/generator/collect" -) - -// modelInfo gathers useful information about a model. -type modelInfo struct { - HasValues bool - IsEnum bool - - IsAlias bool - IsClassAlias bool - IsTypeAlias bool - - IsClassOrInterface bool - IsInterface bool - IsClass bool - - Template struct { - Params string - ParamList string - CreateList string - } -} - -// createParamRegex must match type parameter creation strings as generated by [modelinfo]. -var createParamRegex = regexp.MustCompile(`\$\$createParam[^\s,)]*`) - -// modelinfo gathers and returns useful information about the given model. -func modelinfo(model *collect.ModelInfo, useInterfaces bool) (info modelInfo) { - info.HasValues = len(model.Values) > 0 - info.IsEnum = info.HasValues && !model.Alias - - info.IsAlias = !info.IsEnum && model.Type != nil - info.IsClassAlias = info.IsAlias && model.Predicates.IsClass && !useInterfaces - info.IsTypeAlias = info.IsAlias && !info.IsClassAlias - - info.IsClassOrInterface = !info.IsEnum && !info.IsAlias - info.IsInterface = info.IsClassOrInterface && (model.Alias || useInterfaces) - info.IsClass = info.IsClassOrInterface && !info.IsInterface - - if len(model.TypeParams) > 0 { - var params, paramList, createList strings.Builder - - paramList.WriteRune('<') - createList.WriteRune('(') - - for i, param := range model.TypeParams { - param = typeparam(i, param) - - if i > 0 { - params.WriteRune(',') - paramList.WriteString(", ") - createList.WriteString(", ") - } - - params.WriteString(param) - paramList.WriteString(param) - - createList.WriteString("$$createParam") - createList.WriteString(param) - } - - paramList.WriteRune('>') - createList.WriteRune(')') - - info.Template.Params = params.String() - info.Template.ParamList = paramList.String() - info.Template.CreateList = createList.String() - } - - return -} diff --git a/v3/internal/generator/render/module.go b/v3/internal/generator/render/module.go deleted file mode 100644 index 3611c939a..000000000 --- a/v3/internal/generator/render/module.go +++ /dev/null @@ -1,26 +0,0 @@ -package render - -import ( - "github.com/wailsapp/wails/v3/internal/flags" - "github.com/wailsapp/wails/v3/internal/generator/collect" - "golang.org/x/tools/go/types/typeutil" -) - -// module gathers data that is used when rendering a single JS/TS module. -type module struct { - *Renderer - *flags.GenerateBindingsOptions - - Imports *collect.ImportMap - - postponedCreates typeutil.Map -} - -// Runtime returns the import path for the Wails JS runtime module. -func (m *module) Runtime() string { - if m.UseBundledRuntime { - return "/wails/runtime.js" - } else { - return "@wailsio/runtime" - } -} diff --git a/v3/internal/generator/render/renderer.go b/v3/internal/generator/render/renderer.go deleted file mode 100644 index 81a6f5871..000000000 --- a/v3/internal/generator/render/renderer.go +++ /dev/null @@ -1,183 +0,0 @@ -package render - -import ( - "go/types" - "io" - "slices" - "strings" - "text/template" - - "github.com/wailsapp/wails/v3/internal/flags" - "github.com/wailsapp/wails/v3/internal/generator/collect" -) - -// Renderer holds the template set for a given configuration. -// It provides methods for rendering various output modules. -type Renderer struct { - collector *collect.Collector - options *flags.GenerateBindingsOptions - - ext string - - service *template.Template - models *template.Template -} - -// NewRenderer initialises a code renderer -// for the given configuration and data collector. -func NewRenderer(collector *collect.Collector, options *flags.GenerateBindingsOptions) *Renderer { - ext := ".js" - if options.TS { - ext = ".ts" - } - - return &Renderer{ - collector: collector, - options: options, - - ext: ext, - - service: tmplService[tmplLanguage(options.TS)], - models: tmplModels[tmplLanguage(options.TS)], - } -} - -// ServiceFile returns the standard name of a service file -// for the given struct name, with the appropriate extension. -func (renderer *Renderer) ServiceFile(name string) string { - return strings.ToLower(name) + renderer.ext -} - -// ModelsFile returns the standard name of a models file -// with the appropriate extension. -func (renderer *Renderer) ModelsFile() string { - return renderer.options.ModelsFilename + renderer.ext -} - -// EventDataFile returns the standard name of the event data definitions file -// with the appropriate extension. -func (renderer *Renderer) EventDataFile() string { - return "eventdata.d.ts" -} - -// EventCreateFile returns the standard name of the event data creation file -// with the appropriate extension. -func (renderer *Renderer) EventCreateFile() string { - return "eventcreate" + renderer.ext -} - -// IndexFile returns the standard name of a package index file -// with the appropriate extension. -func (renderer *Renderer) IndexFile() string { - return renderer.options.IndexFilename + renderer.ext -} - -// Service renders binding code for the given service type to w. -func (renderer *Renderer) Service(w io.Writer, info *collect.ServiceInfo) error { - return renderer.service.Execute(w, &struct { - module - Service *collect.ServiceInfo - }{ - module{ - Renderer: renderer, - GenerateBindingsOptions: renderer.options, - Imports: info.Imports, - }, - info, - }) -} - -// Models renders type definitions for the given list of models. -func (renderer *Renderer) Models(w io.Writer, imports *collect.ImportMap, models []*collect.ModelInfo) error { - if !renderer.options.UseInterfaces { - // Sort class aliases after the class they alias. - // Works in amortized linear time thanks to an auxiliary map. - - // Track postponed class aliases and their dependencies. - aliases := make(map[types.Object][]*collect.ModelInfo, len(models)) - - models = slices.Clone(models) - for i, j := 0, 0; i < len(models); i++ { - if models[i].Type != nil && models[i].Predicates.IsClass { - // models[i] is a class alias: - // models[i].Type is guaranteed to be - // either an alias or a named type - obj := models[i].Type.(interface{ Obj() *types.TypeName }).Obj() - if obj.Pkg().Path() == imports.Self { - // models[i] aliases a type from the current module. - if a, ok := aliases[obj]; !ok || len(a) > 0 { - // The aliased type has not been visited already, postpone. - aliases[obj] = append(a, models[i]) - continue - } - } - } - - // Append models[i]. - models[j] = models[i] - j++ - - // Keep appending aliases whose aliased type has been just appended. - for k := j - 1; k < j; k++ { - a := aliases[models[k].Object()] - aliases[models[k].Object()] = nil // Mark aliased model as visited - j += copy(models[j:], a) - } - } - } - - return renderer.models.Execute(w, &struct { - module - Models []*collect.ModelInfo - }{ - module{ - Renderer: renderer, - GenerateBindingsOptions: renderer.options, - Imports: imports, - }, - models, - }) -} - -// EventData renders the given event map to w as an event data table. -func (renderer *Renderer) EventData(w io.Writer, events *collect.EventMap) error { - return tmplEventData.Execute(w, &struct { - module - Events *collect.EventMap - }{ - module{ - Renderer: renderer, - GenerateBindingsOptions: renderer.options, - Imports: events.Imports, - }, - events, - }) -} - -// EventCreate renders the given event map to w as event data creation code. -func (renderer *Renderer) EventCreate(w io.Writer, events *collect.EventMap) error { - return tmplEventCreate.Execute(w, &struct { - module - Events *collect.EventMap - }{ - module{ - Renderer: renderer, - GenerateBindingsOptions: renderer.options, - Imports: events.Imports, - }, - events, - }) -} - -// Index renders the given package index to w. -func (renderer *Renderer) Index(w io.Writer, index *collect.PackageIndex) error { - return tmplIndex.Execute(w, &struct { - *collect.PackageIndex - *Renderer - *flags.GenerateBindingsOptions - }{ - index, - renderer, - renderer.options, - }) -} diff --git a/v3/internal/generator/render/templates.go b/v3/internal/generator/render/templates.go deleted file mode 100644 index 5b137d665..000000000 --- a/v3/internal/generator/render/templates.go +++ /dev/null @@ -1,42 +0,0 @@ -package render - -import ( - "embed" - "strings" - "text/template" -) - -//go:embed templates/*.tmpl -var templates embed.FS - -type tmplLanguage bool - -const tmplJS, tmplTS tmplLanguage = false, true - -var tmplService = map[tmplLanguage]*template.Template{ - tmplJS: template.Must(template.New("service.js.tmpl").Funcs(tmplFunctions).ParseFS(templates, "templates/service.js.tmpl")), - tmplTS: template.Must(template.New("service.ts.tmpl").Funcs(tmplFunctions).ParseFS(templates, "templates/service.ts.tmpl")), -} - -var tmplModels = map[tmplLanguage]*template.Template{ - tmplJS: template.Must(template.New("models.js.tmpl").Funcs(tmplFunctions).ParseFS(templates, "templates/models.js.tmpl")), - tmplTS: template.Must(template.New("models.ts.tmpl").Funcs(tmplFunctions).ParseFS(templates, "templates/models.ts.tmpl")), -} - -var tmplEventData = template.Must(template.New("eventdata.d.ts.tmpl").Funcs(tmplFunctions).ParseFS(templates, "templates/eventdata.d.ts.tmpl")) -var tmplEventCreate = template.Must(template.New("eventcreate.js.tmpl").Funcs(tmplFunctions).ParseFS(templates, "templates/eventcreate.js.tmpl")) - -var tmplIndex = template.Must(template.New("index.tmpl").Funcs(tmplFunctions).ParseFS(templates, "templates/index.tmpl")) - -var Newline string - -func init() { - var builder strings.Builder - - err := template.Must(template.New("newline.tmpl").ParseFS(templates, "templates/newline.tmpl")).Execute(&builder, nil) - if err != nil { - panic(err) - } - - Newline = builder.String() -} diff --git a/v3/internal/generator/render/templates/eventcreate.js.tmpl b/v3/internal/generator/render/templates/eventcreate.js.tmpl deleted file mode 100644 index 2aa8eb254..000000000 --- a/v3/internal/generator/render/templates/eventcreate.js.tmpl +++ /dev/null @@ -1,47 +0,0 @@ -{{$module := .}} -{{- $runtime := $module.Runtime}} -{{- $models := (fixext $module.ModelsFile)}} -{{- $useInterfaces := $module.UseInterfaces}} -{{- $imports := $module.Imports}} -{{- with .Events -}} -//@ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Create as $Create } from "{{js $runtime}}"; -{{if (and (not $useInterfaces) .Defs)}} -{{- range $imports.External}} -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as {{jsimport .}} from "{{js .RelPath}}/{{js $models}}"; -{{- end}}{{if $imports.External}} -{{end}} -{{- if $imports.ImportModels}} -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./{{js $models}}"; -{{end}} -function configure() { - Object.freeze(Object.assign($Create.Events, { - {{- range .Defs}} - {{- $create := ($module.JSCreate .Data)}} - {{- if ne $create "$Create.Any"}} - "{{js .Name}}": {{$create}}, - {{- end}} - {{- end}} - })); -} -{{$postponed := $module.PostponedCreates}} -{{- if $postponed}} -// Private type creation functions -{{- range $i, $create := $postponed}} -{{if and (ge (len $create) 54) (eq (slice $create 39 54) "function $$init")}}var {{else}}const {{end -}} -$$createType{{$i}} = {{$create}}; -{{- end}} -{{end}} -configure(); -{{else}} -Object.freeze($Create.Events); -{{end}}{{end -}} diff --git a/v3/internal/generator/render/templates/eventdata.d.ts.tmpl b/v3/internal/generator/render/templates/eventdata.d.ts.tmpl deleted file mode 100644 index 9278a6a7c..000000000 --- a/v3/internal/generator/render/templates/eventdata.d.ts.tmpl +++ /dev/null @@ -1,32 +0,0 @@ -{{$module := .}} -{{- $runtime := $module.Runtime}} -{{- $models := (fixext $module.ModelsFile)}} -{{- $imports := $module.Imports}} -{{- with .Events -}} -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT -{{if .Defs}} -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import type { Events } from "{{js $runtime}}"; -{{range $imports.External}} -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import type * as {{jsimport .}} from "{{js .RelPath}}/{{js $models}}"; -{{- end}}{{if $imports.External}} -{{end}} -{{- if $imports.ImportModels}} -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import type * as $models from "./{{js $models}}"; -{{end}} -declare module "{{js $runtime}}" { - namespace Events { - interface CustomEvents { - {{- range .Defs}} - "{{js .Name}}": {{$module.JSType .Data}}; - {{- end}} - } - } -} -{{end}}{{end -}} diff --git a/v3/internal/generator/render/templates/index.tmpl b/v3/internal/generator/render/templates/index.tmpl deleted file mode 100644 index fd067bf50..000000000 --- a/v3/internal/generator/render/templates/index.tmpl +++ /dev/null @@ -1,102 +0,0 @@ -{{$renderer := .}} -{{- $useInterfaces := .UseInterfaces}} -{{- $models := (fixext .ModelsFile)}} -{{- if not .TS -}} -// @ts-check -{{end -}} -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT -{{$hasDocs := false}} -{{- range .Package.Docs}} -{{- if hasdoc .}}{{$hasDocs := true}}{{break}}{{end}} -{{- end}} -{{- if $hasDocs}} -/** -{{- range .Package.Docs}} -{{- jsdoc .Text ""}} -{{- end}} - * @module - */ -{{end}} -{{- if .Services}} -{{- range .Services}}{{if .Internal}}{{break}}{{end}} -import * as {{jsid .Name}} from "./{{js (fixext ($renderer.ServiceFile .Name))}}"; -{{- end}} -export { -{{- range $i, $service := .Services}} - {{- if .Internal}}{{break}}{{end}} - {{- if gt $i 0}},{{end}} - {{jsid .Name}} -{{- end}} -}; -{{end}} - -{{- $hasObjects := false}} -{{- $hasTypes := false}} - -{{- range $model := .Models}} -{{- if $model.Internal}}{{break}}{{end}} - -{{- $info := modelinfo $model $useInterfaces }} - -{{- if or $info.HasValues $info.IsClassAlias $info.IsClass}} -{{- if not $hasObjects}} - {{- $hasObjects = true}} -export { -{{- else}},{{end}} - {{jsid $model.Name}} -{{- else}} - {{- $hasTypes = true}} -{{- end}} -{{- end}} -{{- if $hasObjects}} -} from "./{{js $models}}"; -{{end}} - -{{- if $hasTypes}} -{{- $hasTypes = false}} - -{{- if .TS}} -export type { -{{- else}} -import * as $models from "./{{js $models}}"; -{{end}} -{{- range $model := .Models}} -{{- if $model.Internal}}{{break}}{{end}} - -{{- $info := modelinfo $model $useInterfaces }} -{{- $template := $info.Template }} - -{{- if or $info.HasValues $info.IsClassAlias $info.IsClass}}{{continue}}{{end}} - -{{- if $renderer.TS}} - {{- if $hasTypes}},{{end}} - {{jsid $model.Name}} -{{- else}} -/** -{{- if hasdoc $model.Decl.Doc}} -{{- jsdoc $model.Decl.Doc.Text ""}}{{if hasdoc $model.Doc}} - *{{end}} -{{- end}} -{{- if hasdoc $model.Doc}} -{{- jsdoc $model.Doc.Text ""}} -{{- end}} -{{- if $template.ParamList}} - * @template {{$template.Params}} -{{- end}} - * @typedef {$models.{{jsid $model.Name}}{{$template.ParamList -}} } {{jsid $model.Name}} - */ -{{end}} - -{{- $hasTypes = true}} -{{- end}} - -{{- if .TS}} -} from "./{{js $models}}"; -{{end}} - -{{- end}} -{{- range .Package.Injections}} -{{.}} -{{- end}}{{if .Package.Injections}} -{{end -}} diff --git a/v3/internal/generator/render/templates/models.js.tmpl b/v3/internal/generator/render/templates/models.js.tmpl deleted file mode 100644 index 6c0e98b8b..000000000 --- a/v3/internal/generator/render/templates/models.js.tmpl +++ /dev/null @@ -1,207 +0,0 @@ -{{$module := .}} -{{- $runtime := $module.Runtime}} -{{- $models := (fixext $module.ModelsFile)}} -{{- $useInterfaces := .UseInterfaces}} -{{- $imports := $module.Imports -}} -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT -{{if not $useInterfaces}} -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Create as $Create } from "{{js $runtime}}"; -{{end -}} -{{range $imports.External}} -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as {{jsimport .}} from "{{js .RelPath}}/{{js $models}}"; -{{- end}}{{if $imports.External}} -{{end}} -{{- range $model := .Models}} - -{{- $info := modelinfo $model $useInterfaces }} -{{- $template := $info.Template }} - -{{- if or $template.ParamList (hasdoc $model.Decl.Doc) (hasdoc $model.Doc) $info.IsEnum $info.IsTypeAlias $info.IsInterface}} -/** -{{- if hasdoc $model.Decl.Doc}} -{{- jsdoc $model.Decl.Doc.Text ""}}{{if hasdoc $model.Doc}} - *{{end}} -{{- end}} -{{- if hasdoc $model.Doc}} -{{- jsdoc $model.Doc.Text ""}} -{{- end}} -{{- if and $template.ParamList (not $info.IsClassAlias)}} - * @template {{$template.Params}} -{{- end}} -{{- if $info.IsEnum}} - * @readonly - * @enum { {{- $module.JSType $model.Type -}} } -{{- else if $info.IsTypeAlias}} - * @typedef { {{- $module.JSType $model.Type -}} } {{jsid $model.Name}} -{{- else if $info.IsInterface}} -{{- if isjsdocobj $model}} - * @typedef {Object} {{jsid $model.Name}} -{{- range $i, $decl := $model.Fields}}{{range $j, $field := $decl}} - * @property { {{- $module.JSFieldType $field.StructField -}} } - {{- if $field.Optional}} [{{else}} {{end}}{{$field.JsonName}}{{if $field.Optional}}]{{end}} - {{- if hasdoc $field.Decl.Doc}} - {{jsdocline $field.Decl.Doc.Text}}{{end}} -{{- end}}{{end}} -{{- else}} - * @typedef { { -{{- range $i, $decl := $model.Fields}}{{range $j, $field := $decl}} - * "{{js $field.JsonName}}"{{if $field.Optional}}?{{end}}: {{$module.JSFieldType $field.StructField}}, -{{- end}}{{end}} - * } } {{jsid $model.Name}} -{{- end}} -{{- end}} - */ -{{- end}} -{{- if $info.HasValues}} -{{- if not $info.IsEnum}} - -/** - * Predefined constants for type {{jsid $model.Name}}. - * @namespace - */ -{{- end}} -export const {{jsid $model.Name}} = { -{{- if $info.IsEnum}} - /** - * The Go zero value for the underlying type of the enum. - */ - $zero: {{$module.JSDefault $model.Type false}}, -{{end}} -{{- range $i, $decl := $model.Values}}{{range $j, $spec := $decl}}{{range $k, $value := $spec}} - {{- if and (ne $i 0) (eq $j 0) (eq $k 0)}} -{{end}} - {{- if or (and (eq $j 0) (eq $k 0) (hasdoc $value.Decl.Doc)) (and (eq $k 0) (hasdoc $value.Spec.Doc))}} - {{- if gt $j 0}} -{{end}} - /** - {{- if and (eq $j 0) (eq $k 0) (hasdoc $value.Decl.Doc)}} - {{- jsdoc $value.Decl.Doc.Text " "}}{{if and (eq $k 0) (hasdoc $value.Spec.Doc)}} - *{{end}} - {{- end}} - {{- if and (eq $k 0) (hasdoc $value.Spec.Doc)}} - {{- jsdoc $value.Spec.Doc.Text " "}} - {{- end}} - */ - {{- end}} - {{jsid $value.Name}}: {{jsvalue $value.Value}}, -{{- end}}{{end}}{{end}} -}; -{{else if $info.IsClassAlias}} -export const {{jsid $model.Name}} = {{if istpalias $model.Type -}} - {{$module.JSType (unalias $model.Type).Origin}}; -{{- else -}} - {{$module.JSType $model.Type.Origin}}; -{{- end}} - -/** -{{- if hasdoc $model.Decl.Doc}} -{{- jsdoc $model.Decl.Doc.Text ""}}{{if hasdoc $model.Doc}} - *{{end}} -{{- end}} -{{- if hasdoc $model.Doc}} -{{- jsdoc $model.Doc.Text ""}} -{{- end}} -{{- if $template.ParamList}} - * @template {{$template.Params}} -{{- end}} - * @typedef { {{- $module.JSType $model.Type -}} } {{jsid $model.Name}} - */ -{{else if and $info.IsClass}} -export class {{jsid $model.Name}} { - /** - * Creates a new {{jsid $model.Name}} instance. - * @param {Partial<{{jsid $model.Name}}{{$template.ParamList}}>} [$$source = {}] - The source object to create the {{jsid $model.Name}}. - */ - constructor($$source = {}) { - {{- range $decl := $model.Fields}}{{range $j, $field := $decl}} - {{- /* - In JS we need to set all properties explicitly - because JSDoc has no support for arbitrary property names yet. - See https://github.com/jsdoc/jsdoc/issues/1468 - - For optional fields we make the initialization code unreachable - and cast the false condition to any to prevent any complaint from Typescript. - */}} - if ({{if $field.Optional}}/** @type {any} */(false){{else}}!("{{js $field.JsonName}}" in $$source){{end}}) { - /** - {{- if and (eq $j 0) (hasdoc $field.Decl.Doc)}} - {{- jsdoc $field.Decl.Doc.Text " "}} - {{- end}} - * @member - * @type { {{- $module.JSFieldType $field.StructField}}{{if $field.Optional}} | undefined{{end -}} } - */ - this["{{js $field.JsonName}}"] = {{if $field.Optional}}undefined{{else}}{{$module.JSDefault $field.Type $field.Quoted}}{{end}}; - } - {{- end}}{{end}} - - Object.assign(this, $$source); - } - - /** - {{- if $template.ParamList}} - * Given creation functions for each type parameter, - * returns a creation function for a concrete instance - * of the generic class {{jsid $model.Name}}. - {{- range $i, $param := $model.TypeParams}} - {{- $param = (typeparam $i $param)}} - * @template [{{$param}}=any] - {{- end}} - {{- range $i, $param := $model.TypeParams}} - {{- $param = (typeparam $i $param)}} - * @param {(source: any) => {{$param -}} } $$createParam{{$param}} - {{- end}} - * @returns {($$source?: any) => {{jsid $model.Name}}{{$template.ParamList -}} } - {{- else}} - * Creates a new {{jsid $model.Name}} instance from a string or object. - * @param {any} [$$source = {}] - * @returns { {{- jsid $model.Name -}} } - {{- end}} - */ - static createFrom{{if $template.ParamList}}{{$template.CreateList}}{{else}}($$source = {}){{end}} { - {{- range $i, $spec := $model.Fields}}{{range $j, $field := $spec}} - {{- $create := ($module.JSCreateWithParams $field.Type $template.CreateList)}} - {{- if ne $create "$Create.Any"}} - const $$createField{{$i}}_{{$j}} = {{$create}}; - {{- end}} - {{- end}}{{end}} - {{- $indent := ""}} - {{- if $template.ParamList}} - {{- $indent = " "}} - return ($$source = {}) => { - {{- end}} - {{$indent}}let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - {{- range $i, $spec := $model.Fields}}{{range $j, $field := $spec}} - {{- if $module.NeedsCreate $field.Type}} - {{$indent}}if ("{{js $field.JsonName}}" in $$parsedSource) { - {{$indent}} $$parsedSource["{{js $field.JsonName}}"] = $$createField{{$i}}_{{$j}}($$parsedSource["{{js $field.JsonName}}"]); - {{$indent -}} } - {{- end}} - {{- end}}{{end}} - {{$indent}}return new {{jsid $model.Name}}(/** @type {Partial<{{jsid $model.Name}}{{$template.ParamList}}>} */($$parsedSource)); - {{- if $template.ParamList}} - }; - {{- end}} - } -} -{{else}} -{{- /* Rendered as a @typedef */}} -{{end}} -{{- end}} -{{- $postponed := $module.PostponedCreates}} -{{- if $postponed}} -// Private type creation functions -{{- range $i, $create := $postponed}} -{{if and (ge (len $create) 54) (eq (slice $create 39 54) "function $$init")}}var {{else}}const {{end -}} -$$createType{{$i}} = {{$create}}; -{{- end}} -{{end}} -{{- if $useInterfaces}} -// In interface mode, this file is likely to contain just comments. -// We add a dummy export statement to ensure it is recognised as an ES module. -export {}; -{{end -}} diff --git a/v3/internal/generator/render/templates/models.ts.tmpl b/v3/internal/generator/render/templates/models.ts.tmpl deleted file mode 100644 index a6073af08..000000000 --- a/v3/internal/generator/render/templates/models.ts.tmpl +++ /dev/null @@ -1,189 +0,0 @@ -{{$module := .}} -{{- $runtime := $module.Runtime}} -{{- $models := (fixext $module.ModelsFile)}} -{{- $useInterfaces := .UseInterfaces}} -{{- $imports := $module.Imports -}} -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT -{{if not $useInterfaces}} -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Create as $Create } from "{{js $runtime}}"; -{{end -}} -{{range $imports.External}} -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as {{jsimport .}} from "{{js .RelPath}}/{{js $models}}"; -{{- end}}{{if $imports.External}} -{{end}} -{{- range $model := .Models}} - -{{- $info := modelinfo $model $useInterfaces }} -{{- $template := $info.Template }} - -{{- if or (hasdoc $model.Decl.Doc) (hasdoc $model.Doc)}} -/** -{{- if hasdoc $model.Decl.Doc}} -{{- jsdoc $model.Decl.Doc.Text ""}}{{if hasdoc $model.Doc}} - *{{end}} -{{- end}} -{{- if hasdoc $model.Doc}} -{{- jsdoc $model.Doc.Text ""}} -{{- end}} - */ -{{- end}} -{{- if $info.IsEnum}} -export enum {{jsid $model.Name}} { - /** - * The Go zero value for the underlying type of the enum. - */ - $zero = {{$module.JSDefault $model.Type false}}, -{{range $i, $decl := $model.Values}}{{range $j, $spec := $decl}}{{range $k, $value := $spec}} - {{- if and (ne $i 0) (eq $j 0) (eq $k 0)}} -{{end}} - {{- if or (and (eq $j 0) (eq $k 0) (hasdoc $value.Decl.Doc)) (and (eq $k 0) (hasdoc $value.Spec.Doc))}} - {{- if gt $j 0}} -{{end}} - /** - {{- if and (eq $j 0) (eq $k 0) (hasdoc $value.Decl.Doc)}} - {{- jsdoc $value.Decl.Doc.Text " "}}{{if and (eq $k 0) (hasdoc $value.Spec.Doc)}} - *{{end}} - {{- end}} - {{- if and (eq $k 0) (hasdoc $value.Spec.Doc)}} - {{- jsdoc $value.Spec.Doc.Text " "}} - {{- end}} - */ - {{- end}} - {{jsid $value.Name}} = {{jsvalue $value.Value}}, - {{- end}}{{end}}{{end}} -}; -{{else if $info.IsClassAlias}} -export const {{jsid $model.Name}} = {{if istpalias $model.Type -}} - {{$module.JSType (unalias $model.Type).Origin}}; -{{- else -}} - {{$module.JSType $model.Type.Origin}}; -{{- end}} -{{- if or (hasdoc $model.Decl.Doc) (hasdoc $model.Doc)}} - -/** -{{- if hasdoc $model.Decl.Doc}} -{{- jsdoc $model.Decl.Doc.Text ""}}{{if hasdoc $model.Doc}} - *{{end}} -{{- end}} -{{- if hasdoc $model.Doc}} -{{- jsdoc $model.Doc.Text ""}} -{{- end}} - */ -{{- end}} -export type {{jsid $model.Name}}{{$template.ParamList}} = {{$module.JSType $model.Type}}; -{{else if $info.IsTypeAlias}} -export type {{jsid $model.Name}}{{$template.ParamList}} = {{$module.JSType $model.Type}}; -{{- if $info.HasValues}} - -/** - * Predefined constants for type {{jsid $model.Name}}. - * @namespace - */ -export const {{jsid $model.Name}} = { -{{- range $i, $decl := $model.Values}}{{range $j, $spec := $decl}}{{range $k, $value := $spec}} - {{- if and (ne $i 0) (eq $j 0) (eq $k 0)}} -{{end}} - {{- if or (and (eq $j 0) (eq $k 0) (hasdoc $value.Decl.Doc)) (and (eq $k 0) (hasdoc $value.Spec.Doc))}} - {{- if gt $j 0}} -{{end}} - /** - {{- if and (eq $j 0) (eq $k 0) (hasdoc $value.Decl.Doc)}} - {{- jsdoc $value.Decl.Doc.Text " "}}{{if and (eq $k 0) (hasdoc $value.Spec.Doc)}} - *{{end}} - {{- end}} - {{- if and (eq $k 0) (hasdoc $value.Spec.Doc)}} - {{- jsdoc $value.Spec.Doc.Text " "}} - {{- end}} - */ - {{- end}} - {{jsid $value.Name}}: {{jsvalue $value.Value}}, -{{- end}}{{end}}{{end}} -}; -{{- end}} -{{else if $info.IsClassOrInterface}} -export {{if $info.IsInterface}}interface{{else}}class{{end}} {{jsid $model.Name}}{{$template.ParamList}} { - {{- range $i, $decl := $model.Fields}}{{range $j, $field := $decl}} - {{- if and (eq $j 0) (hasdoc $field.Decl.Doc)}} - {{- if gt $i 0}} -{{end}} - /** - {{- jsdoc $field.Decl.Doc.Text " "}} - */ - {{- end}} - "{{js $field.JsonName}}"{{if $field.Optional}}?{{end}}: {{$module.JSFieldType $field.StructField}}; - {{- end}}{{end}} -{{- if $info.IsClass}} - - /** Creates a new {{jsid $model.Name}} instance. */ - constructor($$source: Partial<{{jsid $model.Name}}{{$template.ParamList}}> = {}) { - {{- range $spec := $model.Fields}}{{range $i, $field := $spec}}{{if not $field.Optional}} - if (!("{{js $field.JsonName}}" in $$source)) { - this["{{js $field.JsonName}}"] = {{$module.JSDefault $field.Type $field.Quoted}}; - } - {{- end}}{{end}}{{end}} - - Object.assign(this, $$source); - } - - /** - {{- if $template.ParamList}} - * Given creation functions for each type parameter, - * returns a creation function for a concrete instance - * of the generic class {{jsid $model.Name}}. - {{- else}} - * Creates a new {{jsid $model.Name}} instance from a string or object. - {{- end}} - */ - static createFrom{{if $template.ParamList}}< - {{- range $i, $param := $model.TypeParams}} - {{- $param = (typeparam $i $param)}} - {{- if gt $i 0}}, {{end -}} - {{$param}} = any - {{- end}}>{{end}}({{if $template.ParamList}} - {{- range $i, $param := $model.TypeParams}} - {{- $param = (typeparam $i $param)}} - {{- if gt $i 0}}, {{end -}} - $$createParam{{$param}}: (source: any) => {{$param}}{{end -}} - {{else}}$$source: any = {}{{end}}): - {{- if $template.ParamList}} ($$source?: any) =>{{end}} {{jsid $model.Name}}{{$template.ParamList}} { - {{- range $i, $spec := $model.Fields}}{{range $j, $field := $spec}} - {{- $create := ($module.JSCreateWithParams $field.Type $template.CreateList)}} - {{- if ne $create "$Create.Any"}} - const $$createField{{$i}}_{{$j}} = {{$create}}; - {{- end}} - {{- end}}{{end}} - {{- $indent := ""}} - {{- if $template.ParamList}} - {{- $indent = " "}} - return ($$source: any = {}) => { - {{- end}} - {{$indent}}let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - {{- range $i, $spec := $model.Fields}}{{range $j, $field := $spec}} - {{- if $module.NeedsCreate $field.Type}} - {{$indent}}if ("{{js $field.JsonName}}" in $$parsedSource) { - {{$indent}} $$parsedSource["{{js $field.JsonName}}"] = $$createField{{$i}}_{{$j}}($$parsedSource["{{js $field.JsonName}}"]); - {{$indent -}} } - {{- end}} - {{- end}}{{end}} - {{$indent}}return new {{jsid $model.Name}}{{$template.ParamList}}($$parsedSource as Partial<{{jsid $model.Name}}{{$template.ParamList}}>); - {{- if $template.ParamList}} - }; - {{- end}} - } -{{- end}} -} -{{end}} -{{- end}} -{{- $postponed := $module.PostponedCreates}} -{{- if $postponed}} -// Private type creation functions -{{- range $i, $create := $postponed}} -{{if and (ge (len $create) 16) (eq (slice $create 1 16) "function $$init")}}var {{else}}const {{end -}} -$$createType{{$i}} = {{$create}}; -{{- end}} -{{end -}} diff --git a/v3/internal/generator/render/templates/newline.tmpl b/v3/internal/generator/render/templates/newline.tmpl deleted file mode 100644 index d28790668..000000000 --- a/v3/internal/generator/render/templates/newline.tmpl +++ /dev/null @@ -1,6 +0,0 @@ -{{/* This template should render to a single newline (either LF or CRLF). */}} -{{/* - Git might be configured to rewrite LF newlines to CRLF - in templates, test cases and data, especially on Windows. - Having a newline template enables detection of the current newline mode. -*/ -}} diff --git a/v3/internal/generator/render/templates/service.js.tmpl b/v3/internal/generator/render/templates/service.js.tmpl deleted file mode 100644 index f71e055bf..000000000 --- a/v3/internal/generator/render/templates/service.js.tmpl +++ /dev/null @@ -1,100 +0,0 @@ -{{$module := .}} -{{- $runtime := $module.Runtime}} -{{- $models := (fixext $module.ModelsFile)}} -{{- $useNames := $module.UseNames}} -{{- $useInterfaces := $module.UseInterfaces}} -{{- $imports := $module.Imports}} -{{- with .Service -}} -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT -{{if or (hasdoc .Decl.Doc) (hasdoc .Doc)}} -/** -{{- if hasdoc .Decl.Doc}} -{{- jsdoc .Decl.Doc.Text ""}}{{if hasdoc .Doc}} - *{{end}} -{{- end}} -{{- if hasdoc .Doc}} -{{- jsdoc .Doc.Text ""}} -{{- end}} - * @module - */ -{{end}} -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise{{if not $useInterfaces}}, Create as $Create{{end}} } from "{{js $runtime}}"; -{{range $imports.External}} -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as {{jsimport .}} from "{{js .RelPath}}/{{js $models}}"; -{{- end}}{{if $imports.External}} -{{end}} -{{- if $imports.ImportModels}} -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./{{js $models}}"; -{{end}} -{{- range .Methods}} -/** -{{- if hasdoc .Decl.Doc}} -{{- jsdoc .Decl.Doc.Text ""}}{{if hasdoc .Doc}} - *{{end}} -{{- end}} -{{- if hasdoc .Doc}} -{{- jsdoc .Doc.Text ""}} -{{- end}} -{{- range $i, $param := .Params}} - * @param { {{- $module.JSType .Type}}{{if .Variadic}}[]{{end -}} } {{jsparam $i .}} -{{- end}} - * @returns {$CancellablePromise< - {{- if eq 0 (len .Results) -}} - void - {{- else if eq 1 (len .Results)}} - {{- $module.JSType (index .Results 0)}} - {{- else -}} - [{{range $i, $result := .Results}} - {{- if gt $i 0}}, {{end}} - {{- $module.JSType $result}} - {{- end}}] - {{- end}}>} - */ -{{if not .Internal}}export {{end}}function {{.Name}}({{range $i, $param := .Params -}} - {{- if gt $i 0}}, {{end}} - {{- if .Variadic}}...{{end}} - {{- jsparam $i .}} -{{- end}}) { - {{- if $useNames}} - return $Call.ByName("{{js .FQN}}" - {{- else}} - return $Call.ByID({{.ID}} - {{- end}}{{range $i, $param := .Params}}, {{jsparam $i .}}{{end}}) - {{- if or $useInterfaces (not .Results) ($module.SkipCreate .Results) -}} - ; - {{- else -}} - .then(/** @type {($result: any) => any} */(($result) => { - {{- if eq 1 (len .Results)}} - return {{$module.JSCreate (index .Results 0)}}($result); - {{- else}} - {{- range $i, $type := .Results}} - {{- $create := ($module.JSCreate $type)}} - {{- if ne $create "$Create.Any"}} - $result[{{$i}}] = {{$create}}($result[{{$i}}]); - {{- end}}{{end}} - return $result; - {{- end}} - })); - {{- end}} -} -{{end}} -{{- $postponed := $module.PostponedCreates}} -{{- if $postponed}} -// Private type creation functions -{{- range $i, $create := $postponed}} -{{if and (ge (len $create) 54) (eq (slice $create 39 54) "function $$init")}}var {{else}}const {{end -}} -$$createType{{$i}} = {{$create}}; -{{- end}} -{{end}} -{{- range .Injections}} -{{.}} -{{- end}}{{if .Injections}} -{{end}}{{end -}} diff --git a/v3/internal/generator/render/templates/service.ts.tmpl b/v3/internal/generator/render/templates/service.ts.tmpl deleted file mode 100644 index 4db90fe60..000000000 --- a/v3/internal/generator/render/templates/service.ts.tmpl +++ /dev/null @@ -1,97 +0,0 @@ -{{$module := .}} -{{- $runtime := $module.Runtime}} -{{- $models := (fixext $module.ModelsFile)}} -{{- $useNames := $module.UseNames}} -{{- $useInterfaces := $module.UseInterfaces}} -{{- $imports := $module.Imports}} -{{- with .Service -}} -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT -{{if or (hasdoc .Decl.Doc) (hasdoc .Doc)}} -/** -{{- if hasdoc .Decl.Doc}} -{{- jsdoc .Decl.Doc.Text ""}}{{if hasdoc .Doc}} - *{{end}} -{{- end}} -{{- if hasdoc .Doc}} -{{- jsdoc .Doc.Text ""}} -{{- end}} - * @module - */ -{{end}} -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise{{if not $useInterfaces}}, Create as $Create{{end}} } from "{{js $runtime}}"; -{{range $imports.External}} -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as {{jsimport .}} from "{{js .RelPath}}/{{js $models}}"; -{{- end}}{{if $imports.External}} -{{end}} -{{- if $imports.ImportModels}} -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./{{js $models}}"; -{{end}} -{{- range .Methods}} -{{- if or (hasdoc .Decl.Doc) (hasdoc .Doc)}} -/** -{{- if hasdoc .Decl.Doc}} -{{- jsdoc .Decl.Doc.Text ""}}{{if hasdoc .Doc}} - *{{end}} -{{- end}} -{{- if .Doc}} -{{- jsdoc .Doc.Text ""}} -{{- end}} - */ -{{- end}} -{{if not .Internal}}export {{end}}function {{.Name}}({{range $i, $param := .Params -}} - {{- if gt $i 0}}, {{end}} - {{- if .Variadic}}...{{end}} - {{- jsparam $i .}}: {{$module.JSType .Type}}{{if .Variadic}}[]{{end}} -{{- end}}): $CancellablePromise< - {{- if eq 0 (len .Results) -}} - void - {{- else if eq 1 (len .Results)}} - {{- $module.JSType (index .Results 0)}} - {{- else -}} - [{{range $i, $result := .Results}} - {{- if gt $i 0}}, {{end}} - {{- $module.JSType $result}} - {{- end}}] - {{- end}}> { - {{- if $useNames}} - return $Call.ByName("{{js .FQN}}" - {{- else}} - return $Call.ByID({{.ID}} - {{- end}}{{range $i, $param := .Params}}, {{jsparam $i .}}{{end}}) - {{- if or $useInterfaces (not .Results) ($module.SkipCreate .Results) -}} - ; - {{- else -}} - .then(($result: any) => { - {{- if eq 1 (len .Results)}} - return {{$module.JSCreate (index .Results 0)}}($result); - {{- else}} - {{- range $i, $type := .Results}} - {{- $create := ($module.JSCreate $type)}} - {{- if ne $create "$Create.Any"}} - $result[{{$i}}] = {{$create}}($result[{{$i}}]); - {{- end}}{{end}} - return $result; - {{- end}} - }); - {{- end}} -} -{{end}} -{{- $postponed := $module.PostponedCreates}} -{{- if $postponed}} -// Private type creation functions -{{- range $i, $create := $postponed}} -{{if and (ge (len $create) 16) (eq (slice $create 1 16) "function $$init")}}var {{else}}const {{end -}} -$$createType{{$i}} = {{$create}}; -{{- end}} -{{end}} -{{- range .Injections}} -{{.}} -{{- end}}{{if .Injections}} -{{end}}{{end -}} diff --git a/v3/internal/generator/render/type.go b/v3/internal/generator/render/type.go deleted file mode 100644 index 24a1e7af9..000000000 --- a/v3/internal/generator/render/type.go +++ /dev/null @@ -1,270 +0,0 @@ -package render - -import ( - "fmt" - "go/types" - "strings" - "text/template" - - "github.com/wailsapp/wails/v3/internal/generator/collect" -) - -// aliasOrNamed is a common interface for *types.Alias and *types.Named. -type aliasOrNamed interface { - types.Type - Obj() *types.TypeName -} - -// typeByteSlice caches the type-checker type for a slice of bytes. -var typeByteSlice = types.NewSlice(types.Universe.Lookup("byte").Type()) - -// JSType renders a Go type to its TypeScript representation, -// using the receiver's import map to resolve dependencies. -// -// JSType's output may be incorrect if m.Imports.AddType -// has not been called for the given type. -func (m *module) JSType(typ types.Type) string { - result, _ := m.renderType(typ, false) - return result -} - -// JSFieldType renders a struct field type to its TypeScript representation, -// using the receiver's import map to resolve dependencies. -// -// JSFieldType's output may be incorrect if m.Imports.AddType -// has not been called for the given type. -func (m *module) JSFieldType(field *collect.StructField) string { - result, _ := m.renderType(field.Type, field.Quoted) - return result -} - -// renderType provides the actual implementation of [module.Type]. -// It returns the rendered type and a boolean indicating whether -// the resulting expression describes a nullable type. -func (m *module) renderType(typ types.Type, quoted bool) (result string, nullable bool) { - switch t := typ.(type) { - case *types.Alias, *types.Named: - return m.renderNamedType(typ.(aliasOrNamed), quoted) - - case *types.Array, *types.Slice: - null := "" - if _, isSlice := typ.(*types.Slice); isSlice && m.UseInterfaces { - // In interface mode, record the fact that encoding/json marshals nil slices as null. - null = " | null" - } - - if types.Identical(typ, typeByteSlice) { - // encoding/json marshals byte slices as base64 strings - return "string" + null, null != "" - } - - elem, ptr := m.renderType(typ.(interface{ Elem() types.Type }).Elem(), false) - if ptr { - return fmt.Sprintf("(%s)[]%s", elem, null), null != "" - } else { - return fmt.Sprintf("%s[]%s", elem, null), null != "" - } - - case *types.Basic: - return m.renderBasicType(t, quoted), false - - case *types.Map: - return m.renderMapType(t) - - case *types.Pointer: - elem, nullable := m.renderType(t.Elem(), false) - if nullable { - return elem, nullable - } else { - return fmt.Sprintf("%s | null", elem), true - } - - case *types.Struct: - return m.renderStructType(t), false - - case *types.TypeParam: - pre, post := "", "" - if quoted { - pre, post = "(", " | string)" - } - return fmt.Sprintf("%s%s%s", pre, typeparam(t.Index(), t.Obj().Name()), post), false - } - - // Fall back to untyped mode. - return "any", false -} - -// renderBasicType outputs the TypeScript representation -// of the given basic type. -func (*module) renderBasicType(typ *types.Basic, quoted bool) string { - switch { - case typ.Info()&types.IsBoolean != 0: - if quoted { - return "`${boolean}`" - } else { - return "boolean" - } - - case typ.Info()&types.IsNumeric != 0 && typ.Info()&types.IsComplex == 0: - if quoted { - return "`${number}`" - } else { - return "number" - } - - case typ.Info()&types.IsString != 0: - if quoted { - return "`\"${string}\"`" - } else { - return "string" - } - } - - // Fall back to untyped mode. - if quoted { - return "string" - } else { - return "any" - } -} - -// renderMapType outputs the TypeScript representation of the given map type. -func (m *module) renderMapType(typ *types.Map) (result string, nullable bool) { - null := "" - if m.UseInterfaces { - // In interface mode, record the fact that encoding/json marshals nil slices as null. - null = " | null" - } - - key := "string" - elem, _ := m.renderType(typ.Elem(), false) - - // Test whether we can upgrade key rendering. - switch k := typ.Key().(type) { - case *types.Basic: - if k.Info()&types.IsString == 0 && collect.IsMapKey(k) { - // Render non-string basic type in quoted mode. - key = m.renderBasicType(k, true) - } - - case *types.Alias, *types.Named, *types.Pointer: - if collect.IsMapKey(k) { - if collect.IsStringAlias(k) || collect.IsNumberAlias(k) { - // Alias or named type is a string and therefore - // safe to use as a JS object key. - if ptr, ok := k.(*types.Pointer); ok { - // Unwrap pointers to string aliases. - key, _ = m.renderType(ptr.Elem(), false) - } else { - key, _ = m.renderType(k, false) - } - } else if basic, ok := k.Underlying().(*types.Basic); ok && basic.Info()&types.IsString == 0 { - // Render non-string basic type in quoted mode. - key = m.renderBasicType(basic, true) - } - } - } - - return fmt.Sprintf("{ [_ in %s]?: %s }%s", key, elem, null), m.UseInterfaces -} - -// renderNamedType outputs the TS representation -// of the given named or alias type. -func (m *module) renderNamedType(typ aliasOrNamed, quoted bool) (result string, nullable bool) { - if typ.Obj().Pkg() == nil { - // Builtin alias or named type: render underlying type. - return m.renderType(typ.Underlying(), quoted) - } - - // Special case: application.Void renders as TS void - if m.collector.IsVoidAlias(typ.Obj()) { - return "void", false - } - - if quoted { - switch a := types.Unalias(typ).(type) { - case *types.Basic: - // Quoted mode for (alias of?) basic type: delegate. - return m.renderBasicType(a, quoted), false - case *types.TypeParam: - // Quoted mode for (alias of?) typeparam: delegate. - return m.renderType(a, quoted) - case *types.Named: - // Quoted mode for (alias of?) named type. - // WARN: Do not test with IsAny/IsStringAlias here!! We only want to catch marshalers. - if collect.MaybeJSONMarshaler(typ) == collect.NonMarshaler && collect.MaybeTextMarshaler(typ) == collect.NonMarshaler { - // No custom marshaling for this type. - if u, ok := a.Underlying().(*types.Basic); ok { - // Quoted mode for basic named type that is not a marshaler: delegate. - return m.renderBasicType(u, quoted), false - } - } - } - } - - var builder strings.Builder - - if typ.Obj().Pkg().Path() == m.Imports.Self { - if m.Imports.ImportModels { - builder.WriteString("$models.") - } - } else { - builder.WriteString(jsimport(m.Imports.External[typ.Obj().Pkg().Path()])) - builder.WriteRune('.') - } - builder.WriteString(jsid(typ.Obj().Name())) - - instance, _ := typ.(interface{ TypeArgs() *types.TypeList }) - if instance != nil { - // Render type arguments. - if targs := instance.TypeArgs(); targs != nil && targs.Len() > 0 { - builder.WriteRune('<') - for i := range targs.Len() { - if i > 0 { - builder.WriteString(", ") - } - arg, _ := m.renderType(targs.At(i), false) - builder.WriteString(arg) - } - builder.WriteRune('>') - } - } - - return builder.String(), false -} - -// renderStructType outputs the TS representation -// of the given anonymous struct type. -func (m *module) renderStructType(typ *types.Struct) string { - if collect.MaybeJSONMarshaler(typ) != collect.NonMarshaler { - return "any" - } else if collect.MaybeTextMarshaler(typ) != collect.NonMarshaler { - return "string" - } - - info := m.collector.Struct(typ) - info.Collect() - - var builder strings.Builder - - builder.WriteRune('{') - for i, field := range info.Fields { - if i > 0 { - builder.WriteString(", ") - } - - builder.WriteRune('"') - template.JSEscape(&builder, []byte(field.JsonName)) - builder.WriteRune('"') - - if field.Optional { - builder.WriteRune('?') - } - - builder.WriteString(": ") - builder.WriteString(m.JSFieldType(field)) - } - builder.WriteRune('}') - - return builder.String() -} diff --git a/v3/internal/generator/service.go b/v3/internal/generator/service.go deleted file mode 100644 index fcbfa9447..000000000 --- a/v3/internal/generator/service.go +++ /dev/null @@ -1,102 +0,0 @@ -package generator - -import ( - "go/types" - "path/filepath" -) - -// generateService collects information -// and generates JS/TS binding code -// for the given service type object. -func (generator *Generator) generateService(obj *types.TypeName) { - generator.logger.Debugf( - "discovered service type %s from package %s", - obj.Name(), - obj.Pkg().Path(), - ) - - success := false - defer func() { - if !success { - generator.logger.Errorf( - "package %s: type %s: service code generation failed", - obj.Pkg().Path(), - obj.Name(), - ) - } - }() - - // Collect service information. - info := generator.collector.Service(obj).Collect() - if info == nil { - return - } - - if info.IsEmpty() { - if !info.HasInternalMethods { - generator.logger.Infof( - "package %s: type %s: service has no valid exported methods, skipping", - obj.Pkg().Path(), - obj.Name(), - ) - } - success = true - return - } - - // Check for standard filename collisions. - filename := generator.renderer.ServiceFile(info.Name) - switch filename { - case generator.renderer.ModelsFile(): - generator.logger.Errorf( - "package %s: type %s: service filename collides with models filename; please rename the type or choose a different filename for models", - obj.Pkg().Path(), - obj.Name(), - ) - return - - case generator.renderer.IndexFile(): - if !generator.options.NoIndex { - generator.logger.Errorf( - "package %s: type %s: service filename collides with JS/TS index filename; please rename the type or choose a different filename for JS/TS indexes", - obj.Pkg().Path(), - obj.Name(), - ) - return - } - } - - // Check for upper/lower-case filename collisions. - path := filepath.Join(info.Imports.Self, filename) - if other, present := generator.serviceFiles.LoadOrStore(path, obj); present { - generator.logger.Errorf( - "package %s: type %s: service filename collides with filename for service %s; please avoid multiple services whose names differ only in case", - obj.Pkg().Path(), - obj.Name(), - other.(*types.TypeName).Name(), - ) - return - } - - // Create service file. - file, err := generator.creator.Create(path) - if err != nil { - generator.logger.Errorf("%v", err) - return - } - defer func() { - if err := file.Close(); err != nil { - generator.logger.Errorf("%v", err) - success = false - } - }() - - // Render service code. - err = generator.renderer.Service(file, info) - if err != nil { - generator.logger.Errorf("%v", err) - return - } - - success = true -} diff --git a/v3/internal/generator/testcases/aliases/bound_types.json b/v3/internal/generator/testcases/aliases/bound_types.json deleted file mode 100644 index a8b95e321..000000000 --- a/v3/internal/generator/testcases/aliases/bound_types.json +++ /dev/null @@ -1,3 +0,0 @@ -[ - ".GreetService" -] diff --git a/v3/internal/generator/testcases/aliases/main.go b/v3/internal/generator/testcases/aliases/main.go deleted file mode 100644 index 3fd5941af..000000000 --- a/v3/internal/generator/testcases/aliases/main.go +++ /dev/null @@ -1,146 +0,0 @@ -package main - -import ( - _ "embed" - "encoding" - "log" - - "github.com/wailsapp/wails/v3/internal/generator/testcases/aliases/subpkg" - nobindingshere "github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here" - "github.com/wailsapp/wails/v3/pkg/application" -) - -// GreetService is great -type GreetService int - -// A nice type Alias. -type Alias = int - -// A class alias. -type AliasedPerson = Person - -// An empty struct alias. -type EmptyAliasStruct = struct{} - -// A struct alias. -// This should be rendered as a typedef or interface in every mode. -type AliasStruct = struct { - // A field with a comment. - Foo []int - Bar, Baz string `json:",omitempty"` // Definitely not Foo. - - Other OtherAliasStruct // A nested alias struct. -} - -// Another struct alias. -type OtherAliasStruct = struct { - NoMoreIdeas []rune -} - -// An empty struct. -type EmptyStruct struct{} - -// A non-generic struct containing an alias. -type Person struct { - Name string // The Person's name. - AliasedField Alias // A random alias field. -} - -// A generic struct containing an alias. -type GenericPerson[T any] struct { - Name T - AliasedField Alias -} - -// Another class alias, but ordered after its aliased class. -type StrangelyAliasedPerson = Person - -// A generic alias that forwards to a type parameter. -type GenericAlias[T any] = T - -// A generic alias that wraps a pointer type. -type GenericPtrAlias[T any] = *GenericAlias[T] - -// A generic alias that wraps a map. -type GenericMapAlias[T interface { - comparable - encoding.TextMarshaler -}, U any] = map[T]U - -// A generic alias that wraps a generic struct. -type GenericPersonAlias[T any] = GenericPerson[[]GenericPtrAlias[T]] - -// An alias that wraps a class through a non-typeparam alias. -type IndirectPersonAlias = GenericPersonAlias[bool] - -// An alias that wraps a class through a typeparam alias. -type TPIndirectPersonAlias = GenericAlias[GenericPerson[bool]] - -// An alias referencing another package that is not used elsewhere. -type SubPackageAlias = subpkg.SubStruct - -// A class whose fields have various aliased types. -type AliasGroup struct { - GAi GenericAlias[int] - GAP GenericAlias[GenericPerson[bool]] - GPAs GenericPtrAlias[[]string] - GPAP GenericPtrAlias[GenericPerson[[]int]] - GMA GenericMapAlias[struct{ encoding.TextMarshaler }, float32] - GPA GenericPersonAlias[bool] - IPA IndirectPersonAlias - TPIPA TPIndirectPersonAlias - SPA SubPackageAlias -} - -// Get someone. -func (GreetService) Get(aliasValue Alias) Person { - return Person{"hello", aliasValue} -} - -// Get someone quite different. -func (GreetService) GetButDifferent() GenericPerson[bool] { - return GenericPerson[bool]{true, 13} -} - -// Apparently, aliases are all the rage right now. -func (GreetService) GetButAliased(p AliasedPerson) StrangelyAliasedPerson { - return p -} - -func (GreetService) GetButForeignPrivateAlias() (_ nobindingshere.PrivatePerson) { - return -} - -func (GreetService) GetButSubPackageAlias() (_ SubPackageAlias) { - return -} - -func (GreetService) GetButGenericAliases() (_ AliasGroup) { - return -} - -// Greet a lot of unusual things. -func (GreetService) Greet(EmptyAliasStruct, EmptyStruct) AliasStruct { - return AliasStruct{} -} - -func NewGreetService() application.Service { - return application.NewService(new(GreetService)) -} - -func main() { - app := application.New(application.Options{ - Services: []application.Service{ - NewGreetService(), - }, - }) - - app.Window.New() - - err := app.Run() - - if err != nil { - log.Fatal(err) - } - -} diff --git a/v3/internal/generator/testcases/aliases/subpkg/subpkg.go b/v3/internal/generator/testcases/aliases/subpkg/subpkg.go deleted file mode 100644 index 379e8b84c..000000000 --- a/v3/internal/generator/testcases/aliases/subpkg/subpkg.go +++ /dev/null @@ -1,6 +0,0 @@ -package subpkg - -// SubStruct is a type in a subpackage that is only referenced through an alias. -type SubStruct struct { - SomeField []string -} diff --git a/v3/internal/generator/testcases/complex_expressions/bound_types.json b/v3/internal/generator/testcases/complex_expressions/bound_types.json deleted file mode 100644 index b00766ba0..000000000 --- a/v3/internal/generator/testcases/complex_expressions/bound_types.json +++ /dev/null @@ -1,14 +0,0 @@ -[ - ".Service1", - ".Service2", - ".Service3", - ".Service4", - ".Service5", - ".Service6", - "/config.Service7", - "/config.Service8", - "/config.Service9", - "/config.Service10", - "/config.Service11", - "/config.Service12" -] diff --git a/v3/internal/generator/testcases/complex_expressions/config/config.go b/v3/internal/generator/testcases/complex_expressions/config/config.go deleted file mode 100644 index f5f40dd86..000000000 --- a/v3/internal/generator/testcases/complex_expressions/config/config.go +++ /dev/null @@ -1,82 +0,0 @@ -package config - -import "github.com/wailsapp/wails/v3/pkg/application" - -type Service7 struct{} -type Service8 struct{} -type Service9 struct{} -type Service10 struct{} -type Service11 struct{} -type Service12 struct{} - -func (*Service7) TestMethod() {} - -func (*Service9) TestMethod2() {} - -func NewService7() application.Service { - return application.NewService(new(Service7)) -} - -func NewService8() (result application.Service) { - result = application.NewService(&Service8{}) - return -} - -type ServiceProvider struct { - AService application.Service - *ProviderWithMethod - HeresAnotherOne application.Service -} - -type ProviderWithMethod struct { - OtherService any -} - -func (pm *ProviderWithMethod) Init() { - pm.OtherService = application.NewService(&Service10{}) -} - -var Services []application.Service - -func init() { - var ourServices = []application.Service{ - NewService7(), - NewService8(), - } - - Services = make([]application.Service, len(ourServices)) - - for i, el := range ourServices { - Services[len(ourServices)-i] = el - } -} - -func MoreServices() ServiceProvider { - var provider ServiceProvider - - provider.AService = application.NewService(&Service9{}) - provider.ProviderWithMethod = new(ProviderWithMethod) - - return provider -} - -type ProviderInitialiser interface { - InitProvider(provider any) -} - -type internalProviderInitialiser struct{} - -func NewProviderInitialiser() ProviderInitialiser { - return internalProviderInitialiser{} -} - -func (internalProviderInitialiser) InitProvider(provider any) { - switch p := provider.(type) { - case *ServiceProvider: - p.HeresAnotherOne = application.NewService(&Service11{}) - default: - if anyp, ok := p.(*any); ok { - *anyp = application.NewService(&Service12{}) - } - } -} diff --git a/v3/internal/generator/testcases/complex_expressions/main.go b/v3/internal/generator/testcases/complex_expressions/main.go deleted file mode 100644 index eca22794e..000000000 --- a/v3/internal/generator/testcases/complex_expressions/main.go +++ /dev/null @@ -1,66 +0,0 @@ -package main - -import ( - _ "embed" - "log" - "slices" - - "github.com/wailsapp/wails/v3/internal/generator/testcases/complex_expressions/config" - "github.com/wailsapp/wails/v3/pkg/application" -) - -type Service1 struct{} -type Service2 struct{} -type Service3 struct{} -type Service4 struct{} -type Service5 struct{} -type Service6 struct{} - -var GlobalServices []application.Service - -func main() { - services := []application.Service{ - application.NewService(&Service1{}), - } - - services = append(services, application.NewService(&Service2{}), application.Service{}, application.Service{}) - services[2] = application.NewService(&Service3{}) - - var options = application.Options{ - Services: config.Services, - } - - provider := config.MoreServices() - provider.Init() - - pinit := config.NewProviderInitialiser() - pinit.InitProvider(&provider) - // Method resolution should work here just like above. - config.NewProviderInitialiser().InitProvider(&services[3]) - - copy(options.Services, []application.Service{application.NewService(&Service4{}), provider.HeresAnotherOne, provider.OtherService.(application.Service)}) - (options.Services) = append(options.Services, slices.Insert(services, 1, GlobalServices[2:]...)...) - - app := application.New(options) - - app.Window.New() - - err := app.Run() - - if err != nil { - log.Fatal(err) - } - -} - -func init() { - var global = make([]application.Service, 4) - - global[0] = application.NewService(&Service5{}) - global = slices.Replace(global, 1, 4, - application.NewService(&Service6{}), - config.MoreServices().AService, - ) - - GlobalServices = slices.Clip(global) -} diff --git a/v3/internal/generator/testcases/complex_instantiations/bound_types.json b/v3/internal/generator/testcases/complex_instantiations/bound_types.json deleted file mode 100644 index 663519c0c..000000000 --- a/v3/internal/generator/testcases/complex_instantiations/bound_types.json +++ /dev/null @@ -1,18 +0,0 @@ -[ - ".Service1", - ".Service2", - ".Service3", - ".Service4", - ".Service5", - ".Service6", - ".Service7", - ".Service8", - ".Service9", - ".Service10", - ".Service11", - ".Service12", - ".Service13", - ".Service14", - ".Service15", - "/other.Service16" -] diff --git a/v3/internal/generator/testcases/complex_instantiations/factory.go b/v3/internal/generator/testcases/complex_instantiations/factory.go deleted file mode 100644 index 854af6967..000000000 --- a/v3/internal/generator/testcases/complex_instantiations/factory.go +++ /dev/null @@ -1,21 +0,0 @@ -package main - -import "github.com/wailsapp/wails/v3/pkg/application" - -type Factory[T any, U any] struct { - simpleFactory[T] -} - -func NewFactory[T any, U any]() *Factory[T, U] { - return &Factory[T, U]{} -} - -func (*Factory[T, U]) GetU() application.Service { - return application.NewService(new(U)) -} - -type simpleFactory[T any] struct{} - -func (simpleFactory[U]) Get() application.Service { - return application.NewService(new(U)) -} diff --git a/v3/internal/generator/testcases/complex_instantiations/funcs.go b/v3/internal/generator/testcases/complex_instantiations/funcs.go deleted file mode 100644 index 7aea0e7e0..000000000 --- a/v3/internal/generator/testcases/complex_instantiations/funcs.go +++ /dev/null @@ -1,14 +0,0 @@ -package main - -import "github.com/wailsapp/wails/v3/pkg/application" - -func ServiceInitialiser[T any]() func(*T) application.Service { - return application.NewService[T] -} - -func CustomNewServices[T any, U any]() []application.Service { - return []application.Service{ - application.NewService(new(T)), - application.NewService(new(U)), - } -} diff --git a/v3/internal/generator/testcases/complex_instantiations/main.go b/v3/internal/generator/testcases/complex_instantiations/main.go deleted file mode 100644 index 3b6a0fb6c..000000000 --- a/v3/internal/generator/testcases/complex_instantiations/main.go +++ /dev/null @@ -1,59 +0,0 @@ -package main - -import ( - _ "embed" - "log" - - "github.com/wailsapp/wails/v3/internal/generator/testcases/complex_instantiations/other" - "github.com/wailsapp/wails/v3/pkg/application" -) - -type Service1 struct{} -type Service2 struct{} -type Service3 struct{} -type Service4 struct{} -type Service5 struct{} -type Service6 struct{} -type Service7 struct{} -type Service8 struct{} -type Service9 struct{} -type Service10 struct{} -type Service11 struct{} -type Service12 struct{} -type Service13 struct{} -type Service14 struct{} -type Service15 struct{} - -type SimplifiedFactory[T any] = Factory[T, Service15] - -func main() { - factory := NewFactory[Service1, Service2]() - otherFactory := other.NewFactory[Service3, Service4]() - - app := application.New(application.Options{ - Services: append(append( - []application.Service{ - factory.Get(), - factory.GetU(), - otherFactory.Get(), - otherFactory.GetU(), - application.NewService(&Service5{}), - ServiceInitialiser[Service6]()(&Service6{}), - other.CustomNewService(Service7{}), - other.ServiceInitialiser[Service8]()(&Service8{}), - application.NewServiceWithOptions(&Service13{}, application.ServiceOptions{Name: "custom name"}), - SimplifiedFactory[Service14]{}.Get(), - other.LocalService, - }, - CustomNewServices[Service9, Service10]()...), - other.CustomNewServices[Service11, Service12]()...), - }) - - app.Window.New() - - err := app.Run() - - if err != nil { - log.Fatal(err) - } -} diff --git a/v3/internal/generator/testcases/complex_instantiations/other/factory.go b/v3/internal/generator/testcases/complex_instantiations/other/factory.go deleted file mode 100644 index d8e3aadb7..000000000 --- a/v3/internal/generator/testcases/complex_instantiations/other/factory.go +++ /dev/null @@ -1,21 +0,0 @@ -package other - -import "github.com/wailsapp/wails/v3/pkg/application" - -type Factory[T any, U any] struct { - simpleFactory[T] -} - -func NewFactory[T any, U any]() *Factory[T, U] { - return &Factory[T, U]{} -} - -func (*Factory[T, U]) GetU() application.Service { - return application.NewService(new(U)) -} - -type simpleFactory[T any] struct{} - -func (simpleFactory[U]) Get() application.Service { - return application.NewService(new(U)) -} diff --git a/v3/internal/generator/testcases/complex_instantiations/other/funcs.go b/v3/internal/generator/testcases/complex_instantiations/other/funcs.go deleted file mode 100644 index daf1ad066..000000000 --- a/v3/internal/generator/testcases/complex_instantiations/other/funcs.go +++ /dev/null @@ -1,18 +0,0 @@ -package other - -import "github.com/wailsapp/wails/v3/pkg/application" - -func CustomNewService[T any](srv T) application.Service { - return application.NewService(&srv) -} - -func ServiceInitialiser[T any]() func(*T) application.Service { - return application.NewService[T] -} - -func CustomNewServices[T any, U any]() []application.Service { - return []application.Service{ - application.NewService(new(T)), - application.NewService(new(U)), - } -} diff --git a/v3/internal/generator/testcases/complex_instantiations/other/local.go b/v3/internal/generator/testcases/complex_instantiations/other/local.go deleted file mode 100644 index f08abb26a..000000000 --- a/v3/internal/generator/testcases/complex_instantiations/other/local.go +++ /dev/null @@ -1,7 +0,0 @@ -package other - -import "github.com/wailsapp/wails/v3/pkg/application" - -type Service16 int - -var LocalService = application.NewService(new(Service16)) diff --git a/v3/internal/generator/testcases/complex_json/bound_types.json b/v3/internal/generator/testcases/complex_json/bound_types.json deleted file mode 100644 index a8b95e321..000000000 --- a/v3/internal/generator/testcases/complex_json/bound_types.json +++ /dev/null @@ -1,3 +0,0 @@ -[ - ".GreetService" -] diff --git a/v3/internal/generator/testcases/complex_json/events.json b/v3/internal/generator/testcases/complex_json/events.json deleted file mode 100644 index f32a5804e..000000000 --- a/v3/internal/generator/testcases/complex_json/events.json +++ /dev/null @@ -1 +0,0 @@ -true \ No newline at end of file diff --git a/v3/internal/generator/testcases/complex_json/main.go b/v3/internal/generator/testcases/complex_json/main.go deleted file mode 100644 index 2ed78d55b..000000000 --- a/v3/internal/generator/testcases/complex_json/main.go +++ /dev/null @@ -1,129 +0,0 @@ -package main - -import ( - _ "embed" - "log" - - "github.com/wailsapp/wails/v3/pkg/application" -) - -// Title is a title -type Title string - -const ( - // Mister is a title - Mister Title = "Mr" - Miss Title = "Miss" - Ms Title = "Ms" - Mrs Title = "Mrs" - Dr Title = "Dr" -) - -// GreetService is great -type GreetService struct{} - -type Embedded1 struct { - // Friends should be shadowed in Person by a field of lesser depth - Friends int - - // Vanish should be omitted from Person because there is another field with same depth and no tag - Vanish float32 - - // StillThere should be shadowed in Person by other field with same depth and a json tag - StillThere string - - // embedded4 should effectively appear as an embedded field - embedded4 - - // unexported should be invisible - unexported bool -} - -type Embedded2 struct { - // Vanish should be omitted from Person because there is another field with same depth and no tag - Vanish bool - - // StillThereButRenamed should shadow in Person the other field with same depth and no json tag - StillThereButRenamed *Embedded3 `json:"StillThere"` -} - -type Embedded3 string - -// Person represents a person -type Person struct { - // Titles is optional in JSON - Titles []Title `json:",omitzero"` - - // Names has a - // multiline comment - Names []string - - // Partner has a custom and complex JSON key - Partner *Person `json:"the person's partner ❤️"` - Friends []*Person - - Embedded1 - Embedded2 - - // UselessMap is invisible to JSON - UselessMap map[int]bool `json:"-"` - - // StrangeNumber maps to "-" - StrangeNumber float32 `json:"-,"` - - // Embedded3 should appear with key "Embedded3" - Embedded3 - - // StrangerNumber is serialized as a string - StrangerNumber int `json:",string"` - // StrangestString is optional and serialized as a JSON string - StrangestString string `json:",omitempty,string"` - // StringStrangest is serialized as a JSON string and optional - StringStrangest string `json:",string,omitempty"` - - // unexportedToo should be invisible even with a json tag - unexportedToo bool `json:"Unexported"` - - // embedded4 should be optional and appear with key "emb4" - embedded4 `json:"emb4,omitempty"` -} - -type embedded4 struct { - // NamingThingsIsHard is a law of programming - NamingThingsIsHard bool `json:",string"` - - // Friends should not be shadowed in Person as embedded4 is not embedded - // from encoding/json's point of view; - // however, it should be shadowed in Embedded1 - Friends bool - - // Embedded string should be invisible because it's unexported - string -} - -// Greet does XYZ -func (*GreetService) Greet(person Person, emb Embedded1) string { - return "" -} - -func main() { - app := application.New(application.Options{ - Services: []application.Service{ - application.NewService(&GreetService{}), - }, - }) - - app.Window.New() - - err := app.Run() - - if err != nil { - log.Fatal(err) - } - -} - -func init() { - application.RegisterEvent[map[string]int]("collision") - application.RegisterEvent[*struct{ Field []bool }]("overlap") -} diff --git a/v3/internal/generator/testcases/complex_method/bound_types.json b/v3/internal/generator/testcases/complex_method/bound_types.json deleted file mode 100644 index a8b95e321..000000000 --- a/v3/internal/generator/testcases/complex_method/bound_types.json +++ /dev/null @@ -1,3 +0,0 @@ -[ - ".GreetService" -] diff --git a/v3/internal/generator/testcases/complex_method/main.go b/v3/internal/generator/testcases/complex_method/main.go deleted file mode 100644 index 23ea29dee..000000000 --- a/v3/internal/generator/testcases/complex_method/main.go +++ /dev/null @@ -1,43 +0,0 @@ -package main - -import ( - _ "embed" - "log" - - "github.com/wailsapp/wails/v3/pkg/application" -) - -// GreetService is great -type GreetService struct{} - -// Person represents a person -type Person struct { - Name string -} - -// Greet does XYZ -// It has a multiline doc comment -// The comment has even some */ traps!! -func (*GreetService) Greet(str string, people []Person, _ struct { - AnotherCount int - AnotherOne *Person -}, assoc map[int]*bool, _ []*float32, other ...string) (person Person, _ any, err1 error, _ []int, err error) { - return -} - -func main() { - app := application.New(application.Options{ - Services: []application.Service{ - application.NewService(&GreetService{}), - }, - }) - - app.Window.New() - - err := app.Run() - - if err != nil { - log.Fatal(err) - } - -} diff --git a/v3/internal/generator/testcases/cyclic_imports/bound_types.json b/v3/internal/generator/testcases/cyclic_imports/bound_types.json deleted file mode 100644 index a8b95e321..000000000 --- a/v3/internal/generator/testcases/cyclic_imports/bound_types.json +++ /dev/null @@ -1,3 +0,0 @@ -[ - ".GreetService" -] diff --git a/v3/internal/generator/testcases/cyclic_imports/main.go b/v3/internal/generator/testcases/cyclic_imports/main.go deleted file mode 100644 index 58feb98a1..000000000 --- a/v3/internal/generator/testcases/cyclic_imports/main.go +++ /dev/null @@ -1,55 +0,0 @@ -package main - -import ( - _ "embed" - "log" - - "github.com/wailsapp/wails/v3/pkg/application" -) - -// GreetService is great -type GreetService int - -type StructA struct { - B *structB -} - -type structB struct { - A *StructA -} - -type StructC struct { - D structD -} - -type structD struct { - E StructE -} - -type StructE struct{} - -// Make a cycle. -func (GreetService) MakeCycles() (_ StructA, _ StructC) { - return -} - -func NewGreetService() application.Service { - return application.NewService(new(GreetService)) -} - -func main() { - app := application.New(application.Options{ - Services: []application.Service{ - NewGreetService(), - }, - }) - - app.Window.New() - - err := app.Run() - - if err != nil { - log.Fatal(err) - } - -} diff --git a/v3/internal/generator/testcases/cyclic_types/bound_types.json b/v3/internal/generator/testcases/cyclic_types/bound_types.json deleted file mode 100644 index a8b95e321..000000000 --- a/v3/internal/generator/testcases/cyclic_types/bound_types.json +++ /dev/null @@ -1,3 +0,0 @@ -[ - ".GreetService" -] diff --git a/v3/internal/generator/testcases/cyclic_types/main.go b/v3/internal/generator/testcases/cyclic_types/main.go deleted file mode 100644 index a5a9f5b46..000000000 --- a/v3/internal/generator/testcases/cyclic_types/main.go +++ /dev/null @@ -1,46 +0,0 @@ -package main - -import ( - _ "embed" - "log" - - "github.com/wailsapp/wails/v3/pkg/application" -) - -// GreetService is great -type GreetService int - -type Cyclic []map[string]Alias - -type Alias = *Cyclic - -type GenericCyclic[T any] []struct { - X *GenericCyclic[T] - Y []T -} - -// Make a cycle. -func (GreetService) MakeCycles() (_ Cyclic, _ GenericCyclic[GenericCyclic[int]]) { - return -} - -func NewGreetService() application.Service { - return application.NewService(new(GreetService)) -} - -func main() { - app := application.New(application.Options{ - Services: []application.Service{ - NewGreetService(), - }, - }) - - app.Window.New() - - err := app.Run() - - if err != nil { - log.Fatal(err) - } - -} diff --git a/v3/internal/generator/testcases/directives/bound_types.json b/v3/internal/generator/testcases/directives/bound_types.json deleted file mode 100644 index 62c02c0ca..000000000 --- a/v3/internal/generator/testcases/directives/bound_types.json +++ /dev/null @@ -1,5 +0,0 @@ -[ - ".InternalService", - ".Service", - ".unexportedService" -] diff --git a/v3/internal/generator/testcases/directives/includes.go b/v3/internal/generator/testcases/directives/includes.go deleted file mode 100644 index 669d5305c..000000000 --- a/v3/internal/generator/testcases/directives/includes.go +++ /dev/null @@ -1,11 +0,0 @@ -//wails:include js/test.js -//wails:include **:js/test_all.js -//wails:include *c:js/test_c.js -//wails:include *i:js/test_i.js -//wails:include j*:js/test_j.js -//wails:include jc:js/test_jc.js -//wails:include ji:js/test_ji.js -//wails:include t*:js/test_t.ts -//wails:include tc:js/test_tc.ts -//wails:include ti:js/test_ti.ts -package main diff --git a/v3/internal/generator/testcases/directives/internal.go b/v3/internal/generator/testcases/directives/internal.go deleted file mode 100644 index 86f06e02d..000000000 --- a/v3/internal/generator/testcases/directives/internal.go +++ /dev/null @@ -1,15 +0,0 @@ -package main - -// An exported but internal model. -// -//wails:internal -type InternalModel struct { - Field string -} - -// An exported but internal service. -// -//wails:internal -type InternalService struct{} - -func (InternalService) Method(InternalModel) {} diff --git a/v3/internal/generator/testcases/directives/js/test.js b/v3/internal/generator/testcases/directives/js/test.js deleted file mode 100644 index 138385f53..000000000 --- a/v3/internal/generator/testcases/directives/js/test.js +++ /dev/null @@ -1,3 +0,0 @@ -import { CustomMethod } from "./service.js"; - -CustomMethod("everywhere"); diff --git a/v3/internal/generator/testcases/directives/js/test_all.js b/v3/internal/generator/testcases/directives/js/test_all.js deleted file mode 100644 index 19d5c2f42..000000000 --- a/v3/internal/generator/testcases/directives/js/test_all.js +++ /dev/null @@ -1,3 +0,0 @@ -import { CustomMethod } from "./service.js"; - -CustomMethod("everywhere again"); diff --git a/v3/internal/generator/testcases/directives/js/test_c.js b/v3/internal/generator/testcases/directives/js/test_c.js deleted file mode 100644 index 724e79e12..000000000 --- a/v3/internal/generator/testcases/directives/js/test_c.js +++ /dev/null @@ -1,3 +0,0 @@ -import { CustomMethod } from "./service.js"; - -CustomMethod("Classes"); diff --git a/v3/internal/generator/testcases/directives/js/test_i.js b/v3/internal/generator/testcases/directives/js/test_i.js deleted file mode 100644 index 442f20472..000000000 --- a/v3/internal/generator/testcases/directives/js/test_i.js +++ /dev/null @@ -1,3 +0,0 @@ -import { CustomMethod } from "./service.js"; - -CustomMethod("Interfaces"); diff --git a/v3/internal/generator/testcases/directives/js/test_j.js b/v3/internal/generator/testcases/directives/js/test_j.js deleted file mode 100644 index b2f9c5edb..000000000 --- a/v3/internal/generator/testcases/directives/js/test_j.js +++ /dev/null @@ -1,3 +0,0 @@ -import { CustomMethod } from "./service.js"; - -CustomMethod("JS"); diff --git a/v3/internal/generator/testcases/directives/js/test_jc.js b/v3/internal/generator/testcases/directives/js/test_jc.js deleted file mode 100644 index ddf4920e5..000000000 --- a/v3/internal/generator/testcases/directives/js/test_jc.js +++ /dev/null @@ -1,3 +0,0 @@ -import { CustomMethod } from "./service.js"; - -CustomMethod("JS Classes"); diff --git a/v3/internal/generator/testcases/directives/js/test_ji.js b/v3/internal/generator/testcases/directives/js/test_ji.js deleted file mode 100644 index 36e28f09b..000000000 --- a/v3/internal/generator/testcases/directives/js/test_ji.js +++ /dev/null @@ -1,3 +0,0 @@ -import { CustomMethod } from "./service.js"; - -CustomMethod("JS Interfaces"); diff --git a/v3/internal/generator/testcases/directives/js/test_t.ts b/v3/internal/generator/testcases/directives/js/test_t.ts deleted file mode 100644 index 253d3f2f6..000000000 --- a/v3/internal/generator/testcases/directives/js/test_t.ts +++ /dev/null @@ -1,3 +0,0 @@ -import { CustomMethod } from "./service.js"; - -CustomMethod("TS"); diff --git a/v3/internal/generator/testcases/directives/js/test_tc.ts b/v3/internal/generator/testcases/directives/js/test_tc.ts deleted file mode 100644 index 66b739d3a..000000000 --- a/v3/internal/generator/testcases/directives/js/test_tc.ts +++ /dev/null @@ -1,3 +0,0 @@ -import { CustomMethod } from "./service.js"; - -CustomMethod("TS Classes"); diff --git a/v3/internal/generator/testcases/directives/js/test_ti.ts b/v3/internal/generator/testcases/directives/js/test_ti.ts deleted file mode 100644 index 7400e97aa..000000000 --- a/v3/internal/generator/testcases/directives/js/test_ti.ts +++ /dev/null @@ -1,3 +0,0 @@ -import { CustomMethod } from "./service.js"; - -CustomMethod("TS Interfaces"); diff --git a/v3/internal/generator/testcases/directives/main.go b/v3/internal/generator/testcases/directives/main.go deleted file mode 100644 index ee204027a..000000000 --- a/v3/internal/generator/testcases/directives/main.go +++ /dev/null @@ -1,60 +0,0 @@ -//wails:inject console.log("Hello everywhere!"); -//wails:inject **:console.log("Hello everywhere again!"); -//wails:inject *c:console.log("Hello Classes!"); -//wails:inject *i:console.log("Hello Interfaces!"); -//wails:inject j*:console.log("Hello JS!"); -//wails:inject jc:console.log("Hello JS Classes!"); -//wails:inject ji:console.log("Hello JS Interfaces!"); -//wails:inject t*:console.log("Hello TS!"); -//wails:inject tc:console.log("Hello TS Classes!"); -//wails:inject ti:console.log("Hello TS Interfaces!"); -package main - -import ( - _ "embed" - "log" - - "github.com/wailsapp/wails/v3/internal/generator/testcases/directives/otherpackage" - "github.com/wailsapp/wails/v3/pkg/application" -) - -type IgnoredType struct { - Field int -} - -//wails:inject j*:/** -//wails:inject j*: * @param {string} arg -//wails:inject j*: * @returns {Promise} -//wails:inject j*: */ -//wails:inject j*:export async function CustomMethod(arg) { -//wails:inject t*:export async function CustomMethod(arg: string): Promise { -//wails:inject await InternalMethod("Hello " + arg + "!"); -//wails:inject } -type Service struct{} - -func (*Service) VisibleMethod(otherpackage.Dummy) {} - -//wails:ignore -func (*Service) IgnoredMethod(IgnoredType) {} - -//wails:internal -func (*Service) InternalMethod(string) {} - -func main() { - app := application.New(application.Options{ - Services: []application.Service{ - application.NewService(&Service{}), - application.NewService(&unexportedService{}), - application.NewService(&InternalService{}), - }, - }) - - app.Window.New() - - err := app.Run() - - if err != nil { - log.Fatal(err) - } - -} diff --git a/v3/internal/generator/testcases/directives/otherpackage/dummy.go b/v3/internal/generator/testcases/directives/otherpackage/dummy.go deleted file mode 100644 index e8f688f05..000000000 --- a/v3/internal/generator/testcases/directives/otherpackage/dummy.go +++ /dev/null @@ -1,5 +0,0 @@ -//wails:include jc:js/*_j*.js -//wails:include tc:js/*_t*.ts -package otherpackage - -type Dummy struct{} diff --git a/v3/internal/generator/testcases/directives/otherpackage/js/test_j.js b/v3/internal/generator/testcases/directives/otherpackage/js/test_j.js deleted file mode 100644 index 2166d33b6..000000000 --- a/v3/internal/generator/testcases/directives/otherpackage/js/test_j.js +++ /dev/null @@ -1,3 +0,0 @@ -import { CustomMethod } from "../service.js"; - -CustomMethod("JS"); diff --git a/v3/internal/generator/testcases/directives/otherpackage/js/test_jc.js b/v3/internal/generator/testcases/directives/otherpackage/js/test_jc.js deleted file mode 100644 index 338898726..000000000 --- a/v3/internal/generator/testcases/directives/otherpackage/js/test_jc.js +++ /dev/null @@ -1,3 +0,0 @@ -import { CustomMethod } from "../service.js"; - -CustomMethod("JS Classes"); diff --git a/v3/internal/generator/testcases/directives/otherpackage/js/test_t.ts b/v3/internal/generator/testcases/directives/otherpackage/js/test_t.ts deleted file mode 100644 index 6703820f1..000000000 --- a/v3/internal/generator/testcases/directives/otherpackage/js/test_t.ts +++ /dev/null @@ -1,3 +0,0 @@ -import { CustomMethod } from "../service.js"; - -CustomMethod("TS"); diff --git a/v3/internal/generator/testcases/directives/otherpackage/js/test_tc.ts b/v3/internal/generator/testcases/directives/otherpackage/js/test_tc.ts deleted file mode 100644 index 15d2994e9..000000000 --- a/v3/internal/generator/testcases/directives/otherpackage/js/test_tc.ts +++ /dev/null @@ -1,3 +0,0 @@ -import { CustomMethod } from "../service.js"; - -CustomMethod("TS Classes"); diff --git a/v3/internal/generator/testcases/directives/unexported.go b/v3/internal/generator/testcases/directives/unexported.go deleted file mode 100644 index 56708c5ae..000000000 --- a/v3/internal/generator/testcases/directives/unexported.go +++ /dev/null @@ -1,11 +0,0 @@ -package main - -// An unexported model. -type unexportedModel struct { - Field string -} - -// An unexported service. -type unexportedService struct{} - -func (unexportedService) Method(unexportedModel) {} diff --git a/v3/internal/generator/testcases/embedded_interface/bound_types.json b/v3/internal/generator/testcases/embedded_interface/bound_types.json deleted file mode 100644 index a8b95e321..000000000 --- a/v3/internal/generator/testcases/embedded_interface/bound_types.json +++ /dev/null @@ -1,3 +0,0 @@ -[ - ".GreetService" -] diff --git a/v3/internal/generator/testcases/embedded_interface/main.go b/v3/internal/generator/testcases/embedded_interface/main.go deleted file mode 100644 index 2f65d6519..000000000 --- a/v3/internal/generator/testcases/embedded_interface/main.go +++ /dev/null @@ -1,51 +0,0 @@ -package main - -import ( - "log" - - "github.com/wailsapp/wails/v3/pkg/application" -) - -// GreetService is great -type GreetService struct { - AnInterface -} - -type AnInterface interface { - // Comment 1. - Method1() - - Method2() // Comment 2. - - // Comment 3a. - Method3() // Comment 3b. - - interface { - // Comment 4. - Method4() - } - - InterfaceAlias -} - -type InterfaceAlias = interface { - // Comment 5. - Method5() -} - -func main() { - app := application.New(application.Options{ - Services: []application.Service{ - application.NewService(&GreetService{}), - }, - }) - - app.Window.New() - - err := app.Run() - - if err != nil { - log.Fatal(err) - } - -} diff --git a/v3/internal/generator/testcases/enum/bound_types.json b/v3/internal/generator/testcases/enum/bound_types.json deleted file mode 100644 index a8b95e321..000000000 --- a/v3/internal/generator/testcases/enum/bound_types.json +++ /dev/null @@ -1,3 +0,0 @@ -[ - ".GreetService" -] diff --git a/v3/internal/generator/testcases/enum/main.go b/v3/internal/generator/testcases/enum/main.go deleted file mode 100644 index 22603ce37..000000000 --- a/v3/internal/generator/testcases/enum/main.go +++ /dev/null @@ -1,74 +0,0 @@ -package main - -import ( - _ "embed" - "log" - - "github.com/wailsapp/wails/v3/pkg/application" -) - -// Title is a title -type Title string - -const ( - // Mister is a title - Mister Title = "Mr" - Miss Title = "Miss" - Ms Title = "Ms" - Mrs Title = "Mrs" - Dr Title = "Dr" -) - -// Age is an integer with some predefined values -type Age = int - -const ( - NewBorn Age = 0 - Teenager Age = 12 - YoungAdult Age = 18 - - // Oh no, some grey hair! - MiddleAged Age = 50 - Mathusalem Age = 1000 // Unbelievable! -) - -// GreetService is great -type GreetService struct { - SomeVariable int - lowerCase string - target *Person -} - -// Person represents a person -type Person struct { - Title Title - Name string - Age Age -} - -// Greet does XYZ -func (*GreetService) Greet(name string, title Title) string { - return "Hello " + string(title) + " " + name -} - -// NewPerson creates a new person -func (*GreetService) NewPerson(name string) *Person { - return &Person{Name: name} -} - -func main() { - app := application.New(application.Options{ - Services: []application.Service{ - application.NewService(&GreetService{}), - }, - }) - - app.Window.New() - - err := app.Run() - - if err != nil { - log.Fatal(err) - } - -} diff --git a/v3/internal/generator/testcases/enum_from_imported_package/bound_types.json b/v3/internal/generator/testcases/enum_from_imported_package/bound_types.json deleted file mode 100644 index a8b95e321..000000000 --- a/v3/internal/generator/testcases/enum_from_imported_package/bound_types.json +++ /dev/null @@ -1,3 +0,0 @@ -[ - ".GreetService" -] diff --git a/v3/internal/generator/testcases/enum_from_imported_package/main.go b/v3/internal/generator/testcases/enum_from_imported_package/main.go deleted file mode 100644 index f0348eb5c..000000000 --- a/v3/internal/generator/testcases/enum_from_imported_package/main.go +++ /dev/null @@ -1,38 +0,0 @@ -package main - -import ( - _ "embed" - "log" - - "github.com/wailsapp/wails/v3/internal/generator/testcases/enum_from_imported_package/services" - - "github.com/wailsapp/wails/v3/pkg/application" -) - -// GreetService is great -type GreetService struct { - SomeVariable int - lowerCase string -} - -// Greet does XYZ -func (*GreetService) Greet(name string, title services.Title) string { - return "Hello " + title.String() + " " + name -} - -func main() { - app := application.New(application.Options{ - Services: []application.Service{ - application.NewService(&GreetService{}), - }, - }) - - app.Window.New() - - err := app.Run() - - if err != nil { - log.Fatal(err) - } - -} diff --git a/v3/internal/generator/testcases/enum_from_imported_package/services/other.go b/v3/internal/generator/testcases/enum_from_imported_package/services/other.go deleted file mode 100644 index 5d15f239c..000000000 --- a/v3/internal/generator/testcases/enum_from_imported_package/services/other.go +++ /dev/null @@ -1,16 +0,0 @@ -package services - -type Title string - -func (t Title) String() string { - return string(t) -} - -const ( - // Mister is a title - Mister Title = "Mr" - Miss Title = "Miss" - Ms Title = "Ms" - Mrs Title = "Mrs" - Dr Title = "Dr" -) diff --git a/v3/internal/generator/testcases/enum_map_keys/bound_types.json b/v3/internal/generator/testcases/enum_map_keys/bound_types.json deleted file mode 100644 index 429c3a59c..000000000 --- a/v3/internal/generator/testcases/enum_map_keys/bound_types.json +++ /dev/null @@ -1,3 +0,0 @@ -[ - ".EnumMapService" -] diff --git a/v3/internal/generator/testcases/enum_map_keys/main.go b/v3/internal/generator/testcases/enum_map_keys/main.go deleted file mode 100644 index 6667dc892..000000000 --- a/v3/internal/generator/testcases/enum_map_keys/main.go +++ /dev/null @@ -1,133 +0,0 @@ -package main - -import ( - _ "embed" - "log" - - "github.com/wailsapp/wails/v3/pkg/application" -) - -// Status represents different status values -type Status string - -const ( - StatusPending Status = "pending" - StatusRunning Status = "running" - StatusCompleted Status = "completed" - StatusFailed Status = "failed" -) - -// Priority represents priority levels -type Priority int - -const ( - PriorityLow Priority = 1 - PriorityMedium Priority = 2 - PriorityHigh Priority = 3 -) - -// Color represents color values -type Color uint8 - -const ( - Red Color = 1 - Green Color = 2 - Blue Color = 3 -) - -// EnumMapService tests various enum map key scenarios -type EnumMapService struct{} - -// GetStatusMessages returns a map with string enum keys -func (*EnumMapService) GetStatusMessages() map[Status]string { - return map[Status]string{ - StatusPending: "Task is pending", - StatusRunning: "Task is running", - StatusCompleted: "Task completed successfully", - StatusFailed: "Task failed", - } -} - -// GetPriorityWeights returns a map with integer enum keys -func (*EnumMapService) GetPriorityWeights() map[Priority]float64 { - return map[Priority]float64{ - PriorityLow: 1.0, - PriorityMedium: 2.5, - PriorityHigh: 5.0, - } -} - -// GetColorCodes returns a map with uint8 enum keys -func (*EnumMapService) GetColorCodes() map[Color]string { - return map[Color]string{ - Red: "#FF0000", - Green: "#00FF00", - Blue: "#0000FF", - } -} - -// GetNestedEnumMap returns a map with enum keys and complex values -func (*EnumMapService) GetNestedEnumMap() map[Status]map[Priority]string { - return map[Status]map[Priority]string{ - StatusPending: { - PriorityLow: "Waiting in queue", - PriorityMedium: "Scheduled soon", - PriorityHigh: "Next in line", - }, - StatusRunning: { - PriorityLow: "Processing slowly", - PriorityMedium: "Processing normally", - PriorityHigh: "Processing urgently", - }, - } -} - -// GetOptionalEnumMap returns a map with enum keys to optional values -func (*EnumMapService) GetOptionalEnumMap() map[Status]*string { - running := "Currently running" - return map[Status]*string{ - StatusPending: nil, - StatusRunning: &running, - StatusCompleted: nil, - StatusFailed: nil, - } -} - -// Person represents a person with status -type Person struct { - Name string - Status Status -} - -// GetPersonsByStatus returns a map with enum keys to struct values -func (*EnumMapService) GetPersonsByStatus() map[Status][]Person { - return map[Status][]Person{ - StatusPending: { - {Name: "Alice", Status: StatusPending}, - {Name: "Bob", Status: StatusPending}, - }, - StatusRunning: { - {Name: "Charlie", Status: StatusRunning}, - }, - StatusCompleted: { - {Name: "Dave", Status: StatusCompleted}, - {Name: "Eve", Status: StatusCompleted}, - }, - } -} - -func main() { - app := application.New(application.Options{ - Services: []application.Service{ - application.NewService(&EnumMapService{}), - }, - }) - - app.Window.New() - - err := app.Run() - - if err != nil { - log.Fatal(err) - } -} diff --git a/v3/internal/generator/testcases/events_only/events.go b/v3/internal/generator/testcases/events_only/events.go deleted file mode 100644 index dcd4c642c..000000000 --- a/v3/internal/generator/testcases/events_only/events.go +++ /dev/null @@ -1,26 +0,0 @@ -package events_only - -import ( - "fmt" - - nobindingshere "github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here" - "github.com/wailsapp/wails/v3/pkg/application" -) - -// SomeClass renders as a TS class. -type SomeClass struct { - Field string - Meadow nobindingshere.HowDifferent[rune] -} - -func init() { - application.RegisterEvent[string]("events_only:string") - application.RegisterEvent[map[string][]int]("events_only:map") - application.RegisterEvent[SomeClass]("events_only:class") - application.RegisterEvent[int]("collision") - application.RegisterEvent[bool](fmt.Sprintf("events_only:%s%d", "dynamic", 3)) -} - -func init() { - application.RegisterEvent[application.Void]("events_only:nodata") -} diff --git a/v3/internal/generator/testcases/events_only/events.json b/v3/internal/generator/testcases/events_only/events.json deleted file mode 100644 index f32a5804e..000000000 --- a/v3/internal/generator/testcases/events_only/events.json +++ /dev/null @@ -1 +0,0 @@ -true \ No newline at end of file diff --git a/v3/internal/generator/testcases/events_only/other.go b/v3/internal/generator/testcases/events_only/other.go deleted file mode 100644 index 1f76b4280..000000000 --- a/v3/internal/generator/testcases/events_only/other.go +++ /dev/null @@ -1,26 +0,0 @@ -package events_only - -import ( - "github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/more" - "github.com/wailsapp/wails/v3/pkg/application" -) - -const eventPrefix = "events_only" + `:` - -var registerStringEvent = application.RegisterEvent[string] - -func registerIntEvent(name string) { - application.RegisterEvent[int](name) -} - -func registerSliceEvent[T any]() { - application.RegisterEvent[[]T]("parametric") -} - -func init() { - application.RegisterEvent[[]more.StringPtr](eventPrefix + "other") - application.RegisterEvent[string]("common:ApplicationStarted") - registerStringEvent("indirect_var") - registerIntEvent("indirect_fn") - registerSliceEvent[uintptr]() -} diff --git a/v3/internal/generator/testcases/function_from_imported_package/bound_types.json b/v3/internal/generator/testcases/function_from_imported_package/bound_types.json deleted file mode 100644 index 86a0a8812..000000000 --- a/v3/internal/generator/testcases/function_from_imported_package/bound_types.json +++ /dev/null @@ -1,4 +0,0 @@ -[ - ".GreetService", - "/services.OtherService" -] diff --git a/v3/internal/generator/testcases/function_from_imported_package/main.go b/v3/internal/generator/testcases/function_from_imported_package/main.go deleted file mode 100644 index 03e5b209f..000000000 --- a/v3/internal/generator/testcases/function_from_imported_package/main.go +++ /dev/null @@ -1,51 +0,0 @@ -package main - -import ( - _ "embed" - "log" - - "github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_imported_package/services" - - "github.com/wailsapp/wails/v3/pkg/application" -) - -// GreetService is great -type GreetService struct { - SomeVariable int - lowerCase string - target *Person -} - -// Person is a person -type Person struct { - Name string - Address *services.Address -} - -// Greet does XYZ -func (*GreetService) Greet(name string) string { - return "Hello " + name -} - -// NewPerson creates a new person -func (*GreetService) NewPerson(name string) *Person { - return &Person{Name: name} -} - -func main() { - app := application.New(application.Options{ - Services: []application.Service{ - application.NewService(&GreetService{}), - services.NewOtherService(), - }, - }) - - app.Window.New() - - err := app.Run() - - if err != nil { - log.Fatal(err) - } - -} diff --git a/v3/internal/generator/testcases/function_from_imported_package/services/other.go b/v3/internal/generator/testcases/function_from_imported_package/services/other.go deleted file mode 100644 index 4ac6e6efd..000000000 --- a/v3/internal/generator/testcases/function_from_imported_package/services/other.go +++ /dev/null @@ -1,28 +0,0 @@ -package services - -import "github.com/wailsapp/wails/v3/pkg/application" - -// OtherService is a struct -// that does things -type OtherService struct { - t int -} - -type Address struct { - Street string - State string - Country string -} - -// Yay does this and that -func (o *OtherService) Yay() *Address { - return &Address{ - Street: "123 Pitt Street", - State: "New South Wales", - Country: "Australia", - } -} - -func NewOtherService() application.Service { - return application.NewService(&OtherService{}) -} diff --git a/v3/internal/generator/testcases/function_from_nested_imported_package/bound_types.json b/v3/internal/generator/testcases/function_from_nested_imported_package/bound_types.json deleted file mode 100644 index 7f9f0ea61..000000000 --- a/v3/internal/generator/testcases/function_from_nested_imported_package/bound_types.json +++ /dev/null @@ -1,4 +0,0 @@ -[ - ".GreetService", - "/services/other.OtherService" -] diff --git a/v3/internal/generator/testcases/function_from_nested_imported_package/main.go b/v3/internal/generator/testcases/function_from_nested_imported_package/main.go deleted file mode 100644 index 820fc4f83..000000000 --- a/v3/internal/generator/testcases/function_from_nested_imported_package/main.go +++ /dev/null @@ -1,50 +0,0 @@ -package main - -import ( - _ "embed" - "log" - - "github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_nested_imported_package/services/other" - - "github.com/wailsapp/wails/v3/pkg/application" -) - -// GreetService is great -type GreetService struct { - SomeVariable int - lowerCase string - target *Person -} - -type Person struct { - Name string - Address *other.Address -} - -// Greet does XYZ -func (*GreetService) Greet(name string) string { - return "Hello " + name -} - -// NewPerson creates a new person -func (*GreetService) NewPerson(name string) *Person { - return &Person{Name: name} -} - -func main() { - app := application.New(application.Options{ - Services: []application.Service{ - application.NewService(&GreetService{}), - other.NewOtherService(), - }, - }) - - app.Window.New() - - err := app.Run() - - if err != nil { - log.Fatal(err) - } - -} diff --git a/v3/internal/generator/testcases/function_from_nested_imported_package/services/other/other.go b/v3/internal/generator/testcases/function_from_nested_imported_package/services/other/other.go deleted file mode 100644 index fa12f63ce..000000000 --- a/v3/internal/generator/testcases/function_from_nested_imported_package/services/other/other.go +++ /dev/null @@ -1,28 +0,0 @@ -package other - -import "github.com/wailsapp/wails/v3/pkg/application" - -// OtherService is a struct -// that does things -type OtherService struct { - t int -} - -type Address struct { - Street string - State string - Country string -} - -// Yay does this and that -func (o *OtherService) Yay() *Address { - return &Address{ - Street: "123 Pitt Street", - State: "New South Wales", - Country: "Australia", - } -} - -func NewOtherService() application.Service { - return application.NewService(&OtherService{}) -} diff --git a/v3/internal/generator/testcases/function_multiple_files/bound_types.json b/v3/internal/generator/testcases/function_multiple_files/bound_types.json deleted file mode 100644 index a8b95e321..000000000 --- a/v3/internal/generator/testcases/function_multiple_files/bound_types.json +++ /dev/null @@ -1,3 +0,0 @@ -[ - ".GreetService" -] diff --git a/v3/internal/generator/testcases/function_multiple_files/greet.go b/v3/internal/generator/testcases/function_multiple_files/greet.go deleted file mode 100644 index b0153f22f..000000000 --- a/v3/internal/generator/testcases/function_multiple_files/greet.go +++ /dev/null @@ -1,20 +0,0 @@ -package main - -import ( - _ "embed" - - "github.com/wailsapp/wails/v3/pkg/application" -) - -type GreetService struct { - SomeVariable int - lowerCase string -} - -func (*GreetService) Greet(name string) string { - return "Hello " + name -} - -func NewGreetService() application.Service { - return application.NewService(&GreetService{}) -} diff --git a/v3/internal/generator/testcases/function_multiple_files/main.go b/v3/internal/generator/testcases/function_multiple_files/main.go deleted file mode 100644 index 240168530..000000000 --- a/v3/internal/generator/testcases/function_multiple_files/main.go +++ /dev/null @@ -1,25 +0,0 @@ -package main - -import ( - _ "embed" - "log" - - "github.com/wailsapp/wails/v3/pkg/application" -) - -func main() { - app := application.New(application.Options{ - Services: []application.Service{ - NewGreetService(), - }, - }) - - app.Window.New() - - err := app.Run() - - if err != nil { - log.Fatal(err) - } - -} diff --git a/v3/internal/generator/testcases/function_single/bound_types.json b/v3/internal/generator/testcases/function_single/bound_types.json deleted file mode 100644 index a8b95e321..000000000 --- a/v3/internal/generator/testcases/function_single/bound_types.json +++ /dev/null @@ -1,3 +0,0 @@ -[ - ".GreetService" -] diff --git a/v3/internal/generator/testcases/function_single/main.go b/v3/internal/generator/testcases/function_single/main.go deleted file mode 100644 index 738505455..000000000 --- a/v3/internal/generator/testcases/function_single/main.go +++ /dev/null @@ -1,40 +0,0 @@ -package main - -import ( - _ "embed" - "log" - - "github.com/wailsapp/wails/v3/pkg/application" -) - -// GreetService is great -type GreetService struct { - SomeVariable int - lowerCase string -} - -// Greet someone -func (*GreetService) Greet(name string) string { - return "Hello " + name -} - -func NewGreetService() application.Service { - return application.NewService(&GreetService{}) -} - -func main() { - app := application.New(application.Options{ - Services: []application.Service{ - NewGreetService(), - }, - }) - - app.Window.New() - - err := app.Run() - - if err != nil { - log.Fatal(err) - } - -} diff --git a/v3/internal/generator/testcases/function_single_context/bound_types.json b/v3/internal/generator/testcases/function_single_context/bound_types.json deleted file mode 100644 index a8b95e321..000000000 --- a/v3/internal/generator/testcases/function_single_context/bound_types.json +++ /dev/null @@ -1,3 +0,0 @@ -[ - ".GreetService" -] diff --git a/v3/internal/generator/testcases/function_single_context/main.go b/v3/internal/generator/testcases/function_single_context/main.go deleted file mode 100644 index 1a785ddba..000000000 --- a/v3/internal/generator/testcases/function_single_context/main.go +++ /dev/null @@ -1,46 +0,0 @@ -package main - -import ( - "context" - _ "embed" - "log" - - "github.com/wailsapp/wails/v3/pkg/application" -) - -// GreetService is great -type GreetService struct { - SomeVariable int - lowerCase string -} - -// Greet someone -func (*GreetService) Greet(name string) string { - return "Hello " + name -} - -// Greet someone -func (*GreetService) GreetWithContext(ctx context.Context, name string) string { - return "Hello " + name -} - -func NewGreetService() application.Service { - return application.NewService(&GreetService{}) -} - -func main() { - app := application.New(application.Options{ - Services: []application.Service{ - NewGreetService(), - }, - }) - - app.Window.New() - - err := app.Run() - - if err != nil { - log.Fatal(err) - } - -} diff --git a/v3/internal/generator/testcases/function_single_internal/bound_types.json b/v3/internal/generator/testcases/function_single_internal/bound_types.json deleted file mode 100644 index a8b95e321..000000000 --- a/v3/internal/generator/testcases/function_single_internal/bound_types.json +++ /dev/null @@ -1,3 +0,0 @@ -[ - ".GreetService" -] diff --git a/v3/internal/generator/testcases/function_single_internal/main.go b/v3/internal/generator/testcases/function_single_internal/main.go deleted file mode 100644 index f66dd3649..000000000 --- a/v3/internal/generator/testcases/function_single_internal/main.go +++ /dev/null @@ -1,61 +0,0 @@ -package main - -import ( - "context" - _ "embed" - "log" - "net/http" - - "github.com/wailsapp/wails/v3/pkg/application" -) - -// GreetService is great -type GreetService struct { - SomeVariable int - lowerCase string -} - -// Greet someone -func (*GreetService) Greet(name string) string { - return "Hello " + name -} - -// Debugging name -func (*GreetService) ServiceName() string { - return "GreetService" -} - -// Lifecycle -func (*GreetService) ServiceStartup(context.Context, application.ServiceOptions) error { - return nil -} - -// Lifecycle -func (*GreetService) ServiceShutdown() error { - return nil -} - -// Serve some routes -func (*GreetService) ServeHTTP(http.ResponseWriter, *http.Request) { -} - -func NewGreetService() application.Service { - return application.NewService(&GreetService{}) -} - -func main() { - app := application.New(application.Options{ - Services: []application.Service{ - NewGreetService(), - }, - }) - - app.Window.New() - - err := app.Run() - - if err != nil { - log.Fatal(err) - } - -} diff --git a/v3/internal/generator/testcases/map_keys/bound_types.json b/v3/internal/generator/testcases/map_keys/bound_types.json deleted file mode 100644 index 1a27d889e..000000000 --- a/v3/internal/generator/testcases/map_keys/bound_types.json +++ /dev/null @@ -1,3 +0,0 @@ -[ - ".Service" -] diff --git a/v3/internal/generator/testcases/map_keys/main.go b/v3/internal/generator/testcases/map_keys/main.go deleted file mode 100644 index 31c353bfc..000000000 --- a/v3/internal/generator/testcases/map_keys/main.go +++ /dev/null @@ -1,307 +0,0 @@ -package main - -import ( - _ "embed" - "encoding" - "encoding/json" - "log" - - "github.com/wailsapp/wails/v3/pkg/application" -) - -type Service struct{} - -type NonTextMarshaler struct{} - -type ValueTextMarshaler struct{} - -func (ValueTextMarshaler) MarshalText() ([]byte, error) { return nil, nil } - -type PointerTextMarshaler struct{} - -func (*PointerTextMarshaler) MarshalText() ([]byte, error) { return nil, nil } - -type JsonTextMarshaler struct{} - -func (JsonTextMarshaler) MarshalJSON() ([]byte, error) { return nil, nil } -func (JsonTextMarshaler) MarshalText() ([]byte, error) { return nil, nil } - -type CustomInterface interface { - MarshalText() ([]byte, error) -} - -type EmbeddedInterface interface { - encoding.TextMarshaler -} - -type EmbeddedInterfaces interface { - json.Marshaler - encoding.TextMarshaler -} - -type BasicConstraint interface { - ~int | ~int8 | ~int16 | ~int32 | ~int64 | - ~uint | ~uint8 | ~uint16 | ~uint32 | ~uint64 | - ~string -} - -type BadTildeConstraint interface { - int | ~struct{} | string -} - -type GoodTildeConstraint interface { - int | ~struct{} | string - MarshalText() ([]byte, error) -} - -type NonBasicConstraint interface { - ValueTextMarshaler | *PointerTextMarshaler -} - -type PointableConstraint interface { - ValueTextMarshaler | PointerTextMarshaler -} - -type MixedConstraint interface { - uint | ~string | ValueTextMarshaler | *PointerTextMarshaler -} - -type InterfaceConstraint interface { - comparable - encoding.TextMarshaler -} - -type PointerConstraint[T comparable] interface { - *T - encoding.TextMarshaler -} - -type EmbeddedValue struct{ ValueTextMarshaler } -type EmbeddedValuePtr struct{ *ValueTextMarshaler } -type EmbeddedPointer struct{ PointerTextMarshaler } -type EmbeddedPointerPtr struct{ *PointerTextMarshaler } - -type EmbeddedCustomInterface struct{ CustomInterface } -type EmbeddedOriginalInterface struct{ encoding.TextMarshaler } - -type WrongType bool -type WrongAlias = bool -type StringType string -type StringAlias = string -type IntType int -type IntAlias = int - -type ValueType ValueTextMarshaler -type ValuePtrType *ValueTextMarshaler -type ValueAlias = ValueTextMarshaler -type ValuePtrAlias = *ValueTextMarshaler - -type PointerType PointerTextMarshaler -type PointerPtrType *PointerTextMarshaler -type PointerAlias = PointerTextMarshaler -type PointerPtrAlias = *PointerTextMarshaler - -type InterfaceType encoding.TextMarshaler -type InterfacePtrType *encoding.TextMarshaler -type InterfaceAlias = encoding.TextMarshaler -type InterfacePtrAlias = *encoding.TextMarshaler - -type ComparableCstrAlias[R comparable] = R -type ComparableCstrPtrAlias[R comparable] = *R -type BasicCstrAlias[S BasicConstraint] = S -type BasicCstrPtrAlias[S BasicConstraint] = *S -type BadTildeCstrAlias[T BadTildeConstraint] = T -type BadTildeCstrPtrAlias[T BadTildeConstraint] = *T -type GoodTildeCstrAlias[U GoodTildeConstraint] = U -type GoodTildeCstrPtrAlias[U GoodTildeConstraint] = *U -type NonBasicCstrAlias[V NonBasicConstraint] = V -type NonBasicCstrPtrAlias[V NonBasicConstraint] = *V -type PointableCstrAlias[W PointableConstraint] = W -type PointableCstrPtrAlias[W PointableConstraint] = *W -type MixedCstrAlias[X MixedConstraint] = X -type MixedCstrPtrAlias[X MixedConstraint] = *X -type InterfaceCstrAlias[Y InterfaceConstraint] = Y -type InterfaceCstrPtrAlias[Y InterfaceConstraint] = *Y -type PointerCstrAlias[R comparable, Z PointerConstraint[R]] = Z -type PointerCstrPtrAlias[R comparable, Z PointerConstraint[R]] = *Z - -type Maps[R comparable, S BasicConstraint, T BadTildeConstraint, U GoodTildeConstraint, V NonBasicConstraint, W PointableConstraint, X MixedConstraint, Y InterfaceConstraint, Z PointerConstraint[R]] struct { - Bool map[bool]int // Reject - Int map[int]int // Accept - Uint map[uint]int // Accept - Float map[float32]int // Reject - Complex map[complex64]int // Reject - Byte map[byte]int // Accept - Rune map[rune]int // Accept - String map[string]int // Accept - - IntPtr map[*int]int // Reject - UintPtr map[*uint]int // Reject - FloatPtr map[*float32]int // Reject - ComplexPtr map[*complex64]int // Reject - StringPtr map[*string]int // Reject - - NTM map[NonTextMarshaler]int // Reject - NTMPtr map[*NonTextMarshaler]int // Reject - VTM map[ValueTextMarshaler]int // Accept - VTMPtr map[*ValueTextMarshaler]int // Accept - PTM map[PointerTextMarshaler]int // Reject - PTMPtr map[*PointerTextMarshaler]int // Accept - JTM map[JsonTextMarshaler]int // Accept, hide - JTMPtr map[*JsonTextMarshaler]int // Accept, hide - - A map[any]int // Reject - APtr map[*any]int // Reject - TM map[encoding.TextMarshaler]int // Accept, hide - TMPtr map[*encoding.TextMarshaler]int // Reject - CI map[CustomInterface]int // Accept, hide - CIPtr map[*CustomInterface]int // Reject - EI map[EmbeddedInterface]int // Accept, hide - EIPtr map[*EmbeddedInterface]int // Reject - - EV map[EmbeddedValue]int // Accept - EVPtr map[*EmbeddedValue]int // Accept - EVP map[EmbeddedValuePtr]int // Accept - EVPPtr map[*EmbeddedValuePtr]int // Accept - EP map[EmbeddedPointer]int // Reject - EPPtr map[*EmbeddedPointer]int // Accept - EPP map[EmbeddedPointerPtr]int // Accept - EPPPtr map[*EmbeddedPointerPtr]int // Accept - - ECI map[EmbeddedCustomInterface]int // Accept - ECIPtr map[*EmbeddedCustomInterface]int // Accept - EOI map[EmbeddedOriginalInterface]int // Accept - EOIPtr map[*EmbeddedOriginalInterface]int // Accept - - WT map[WrongType]int // Reject - WA map[WrongAlias]int // Reject - ST map[StringType]int // Accept - SA map[StringAlias]int // Accept - IntT map[IntType]int // Accept - IntA map[IntAlias]int // Accept - - VT map[ValueType]int // Reject - VTPtr map[*ValueType]int // Reject - VPT map[ValuePtrType]int // Reject - VPTPtr map[*ValuePtrType]int // Reject - VA map[ValueAlias]int // Accept - VAPtr map[*ValueAlias]int // Accept - VPA map[ValuePtrAlias]int // Accept, hide - VPAPtr map[*ValuePtrAlias]int // Reject - - PT map[PointerType]int // Reject - PTPtr map[*PointerType]int // Reject - PPT map[PointerPtrType]int // Reject - PPTPtr map[*PointerPtrType]int // Reject - PA map[PointerAlias]int // Reject - PAPtr map[*PointerAlias]int // Accept - PPA map[PointerPtrAlias]int // Accept, hide - PPAPtr map[*PointerPtrAlias]int // Reject - - IT map[InterfaceType]int // Accept, hide - ITPtr map[*InterfaceType]int // Reject - IPT map[InterfacePtrType]int // Reject - IPTPtr map[*InterfacePtrType]int // Reject - IA map[InterfaceAlias]int // Accept, hide - IAPtr map[*InterfaceAlias]int // Reject - IPA map[InterfacePtrAlias]int // Reject - IPAPtr map[*InterfacePtrAlias]int // Reject - - TPR map[R]int // Soft reject - TPRPtr map[*R]int // Soft reject - TPS map[S]int // Accept, hide - TPSPtr map[*S]int // Soft reject - TPT map[T]int // Soft reject - TPTPtr map[*T]int // Soft reject - TPU map[U]int // Accept, hide - TPUPtr map[*U]int // Soft reject - TPV map[V]int // Accept, hide - TPVPtr map[*V]int // Soft reject - TPW map[W]int // Soft reject - TPWPtr map[*W]int // Accept, hide - TPX map[X]int // Accept, hide - TPXPtr map[*X]int // Soft reject - TPY map[Y]int // Accept, hide - TPYPtr map[*Y]int // Soft reject - TPZ map[Z]int // Accept, hide - TPZPtr map[*Z]int // Soft reject - - GAR map[ComparableCstrAlias[R]]int // Soft reject - GARPtr map[ComparableCstrPtrAlias[R]]int // Soft reject - GAS map[BasicCstrAlias[S]]int // Accept, hide - GASPtr map[BasicCstrPtrAlias[S]]int // Soft reject - GAT map[BadTildeCstrAlias[T]]int // Soft reject - GATPtr map[BadTildeCstrPtrAlias[T]]int // Soft reject - GAU map[GoodTildeCstrAlias[U]]int // Accept, hide - GAUPtr map[GoodTildeCstrPtrAlias[U]]int // Soft reject - GAV map[NonBasicCstrAlias[V]]int // Accept, hide - GAVPtr map[NonBasicCstrPtrAlias[V]]int // Soft reject - GAW map[PointableCstrAlias[W]]int // Soft reject - GAWPtr map[PointableCstrPtrAlias[W]]int // Accept, hide - GAX map[MixedCstrAlias[X]]int // Accept, hide - GAXPtr map[MixedCstrPtrAlias[X]]int // Soft reject - GAY map[InterfaceCstrAlias[Y]]int // Accept, hide - GAYPtr map[InterfaceCstrPtrAlias[Y]]int // Soft reject - GAZ map[PointerCstrAlias[R, Z]]int // Accept, hide - GAZPtr map[PointerCstrPtrAlias[R, Z]]int // Soft reject - - GACi map[ComparableCstrAlias[int]]int // Accept - GACV map[ComparableCstrAlias[ValueTextMarshaler]]int // Accept - GACP map[ComparableCstrAlias[PointerTextMarshaler]]int // Reject - GACiPtr map[ComparableCstrPtrAlias[int]]int // Reject - GACVPtr map[ComparableCstrPtrAlias[ValueTextMarshaler]]int // Accept, hide - GACPPtr map[ComparableCstrPtrAlias[PointerTextMarshaler]]int // Accept, hide - GABi map[BasicCstrAlias[int]]int // Accept - GABs map[BasicCstrAlias[string]]int // Accept - GABiPtr map[BasicCstrPtrAlias[int]]int // Reject - GABT map[BadTildeCstrAlias[struct{}]]int // Reject - GABTPtr map[BadTildeCstrPtrAlias[struct{}]]int // Reject - GAGT map[GoodTildeCstrAlias[ValueTextMarshaler]]int // Accept - GAGTPtr map[GoodTildeCstrPtrAlias[ValueTextMarshaler]]int // Accept, hide - GANBV map[NonBasicCstrAlias[ValueTextMarshaler]]int // Accept - GANBP map[NonBasicCstrAlias[*PointerTextMarshaler]]int // Accept, hide - GANBVPtr map[NonBasicCstrPtrAlias[ValueTextMarshaler]]int // Accept, hide - GANBPPtr map[NonBasicCstrPtrAlias[*PointerTextMarshaler]]int // Reject - GAPlV1 map[PointableCstrAlias[ValueTextMarshaler]]int // Accept - GAPlV2 map[*PointableCstrAlias[ValueTextMarshaler]]int // Accept - GAPlP1 map[PointableCstrAlias[PointerTextMarshaler]]int // Reject - GAPlP2 map[*PointableCstrAlias[PointerTextMarshaler]]int // Accept - GAPlVPtr map[PointableCstrPtrAlias[ValueTextMarshaler]]int // Accept, hide - GAPlPPtr map[PointableCstrPtrAlias[PointerTextMarshaler]]int // Accept, hide - GAMi map[MixedCstrAlias[uint]]int // Accept - GAMS map[MixedCstrAlias[StringType]]int // Accept - GAMV map[MixedCstrAlias[ValueTextMarshaler]]int // Accept - GAMSPtr map[MixedCstrPtrAlias[StringType]]int // Reject - GAMVPtr map[MixedCstrPtrAlias[ValueTextMarshaler]]int // Accept, hide - GAII map[InterfaceCstrAlias[encoding.TextMarshaler]]int // Accept, hide - GAIV map[InterfaceCstrAlias[ValueTextMarshaler]]int // Accept - GAIP map[InterfaceCstrAlias[*PointerTextMarshaler]]int // Accept, hide - GAIIPtr map[InterfaceCstrPtrAlias[encoding.TextMarshaler]]int // Reject - GAIVPtr map[InterfaceCstrPtrAlias[ValueTextMarshaler]]int // Accept, hide - GAIPPtr map[InterfaceCstrPtrAlias[*PointerTextMarshaler]]int // Reject - GAPrV map[PointerCstrAlias[ValueTextMarshaler, *ValueTextMarshaler]]int // Accept, hide - GAPrP map[PointerCstrAlias[PointerTextMarshaler, *PointerTextMarshaler]]int // Accept, hide - GAPrVPtr map[PointerCstrPtrAlias[ValueTextMarshaler, *ValueTextMarshaler]]int // Reject - GAPrPPtr map[PointerCstrPtrAlias[PointerTextMarshaler, *PointerTextMarshaler]]int // Reject -} - -func (*Service) Method() (_ Maps[PointerTextMarshaler, int, int, ValueTextMarshaler, *PointerTextMarshaler, ValueTextMarshaler, StringType, ValueTextMarshaler, *PointerTextMarshaler]) { - return -} - -func main() { - app := application.New(application.Options{ - Services: []application.Service{ - application.NewService(&Service{}), - }, - }) - - app.Window.New() - - err := app.Run() - - if err != nil { - log.Fatal(err) - } - -} diff --git a/v3/internal/generator/testcases/marshalers/bound_types.json b/v3/internal/generator/testcases/marshalers/bound_types.json deleted file mode 100644 index 1a27d889e..000000000 --- a/v3/internal/generator/testcases/marshalers/bound_types.json +++ /dev/null @@ -1,3 +0,0 @@ -[ - ".Service" -] diff --git a/v3/internal/generator/testcases/marshalers/events.json b/v3/internal/generator/testcases/marshalers/events.json deleted file mode 100644 index f32a5804e..000000000 --- a/v3/internal/generator/testcases/marshalers/events.json +++ /dev/null @@ -1 +0,0 @@ -true \ No newline at end of file diff --git a/v3/internal/generator/testcases/marshalers/main.go b/v3/internal/generator/testcases/marshalers/main.go deleted file mode 100644 index 95300480c..000000000 --- a/v3/internal/generator/testcases/marshalers/main.go +++ /dev/null @@ -1,215 +0,0 @@ -package main - -import ( - _ "embed" - "encoding" - "encoding/json" - "log" - - "github.com/wailsapp/wails/v3/pkg/application" -) - -type Service struct{} - -// class {} -type NonMarshaler struct{} - -// any -type ValueJsonMarshaler struct{} - -func (ValueJsonMarshaler) MarshalJSON() ([]byte, error) { return nil, nil } - -// any -type PointerJsonMarshaler struct{} - -func (*PointerJsonMarshaler) MarshalJSON() ([]byte, error) { return nil, nil } - -// string -type ValueTextMarshaler struct{} - -func (ValueTextMarshaler) MarshalText() ([]byte, error) { return nil, nil } - -// string -type PointerTextMarshaler struct{} - -func (*PointerTextMarshaler) MarshalText() ([]byte, error) { return nil, nil } - -// any -type ValueMarshaler struct{} - -func (ValueMarshaler) MarshalJSON() ([]byte, error) { return nil, nil } -func (ValueMarshaler) MarshalText() ([]byte, error) { return nil, nil } - -// any -type PointerMarshaler struct{} - -func (*PointerMarshaler) MarshalJSON() ([]byte, error) { return nil, nil } -func (*PointerMarshaler) MarshalText() ([]byte, error) { return nil, nil } - -// any -type UnderlyingJsonMarshaler struct{ json.Marshaler } - -// string -type UnderlyingTextMarshaler struct{ encoding.TextMarshaler } - -// any -type UnderlyingMarshaler struct { - json.Marshaler - encoding.TextMarshaler -} - -type customJsonMarshaler interface { - MarshalJSON() ([]byte, error) -} - -type customTextMarshaler interface { - MarshalText() ([]byte, error) -} - -type customMarshaler interface { - MarshalJSON() ([]byte, error) - MarshalText() ([]byte, error) -} - -// struct{} -type AliasNonMarshaler = struct{} - -// any -type AliasJsonMarshaler = struct{ json.Marshaler } - -// string -type AliasTextMarshaler = struct{ encoding.TextMarshaler } - -// any -type AliasMarshaler = struct { - json.Marshaler - encoding.TextMarshaler -} - -// any -type ImplicitJsonMarshaler UnderlyingJsonMarshaler - -// string -type ImplicitTextMarshaler UnderlyingTextMarshaler - -// any -type ImplicitMarshaler UnderlyingMarshaler - -// string -type ImplicitNonJson UnderlyingMarshaler - -func (ImplicitNonJson) MarshalJSON() {} - -// any -type ImplicitNonText UnderlyingMarshaler - -func (ImplicitNonText) MarshalText() {} - -// class{ Marshaler, TextMarshaler } -type ImplicitNonMarshaler UnderlyingMarshaler - -func (ImplicitNonMarshaler) MarshalJSON() {} -func (ImplicitNonMarshaler) MarshalText() {} - -// any -type ImplicitJsonButText UnderlyingJsonMarshaler - -func (ImplicitJsonButText) MarshalText() ([]byte, error) { return nil, nil } - -// any -type ImplicitTextButJson UnderlyingTextMarshaler - -func (ImplicitTextButJson) MarshalJSON() ([]byte, error) { return nil, nil } - -type Data struct { - NM NonMarshaler - NMPtr *NonMarshaler // NonMarshaler | null - - VJM ValueJsonMarshaler - VJMPtr *ValueJsonMarshaler // ValueJsonMarshaler | null - PJM PointerJsonMarshaler - PJMPtr *PointerJsonMarshaler // PointerJsonMarshaler | null - - VTM ValueTextMarshaler - VTMPtr *ValueTextMarshaler // ValueTextMarshaler | null - PTM PointerTextMarshaler - PTMPtr *PointerTextMarshaler // PointerTextMarshaler | null - - VM ValueMarshaler - VMPtr *ValueMarshaler // ValueMarshaler | null - PM PointerMarshaler - PMPtr *PointerMarshaler // PointerMarshaler | null - - UJM UnderlyingJsonMarshaler - UJMPtr *UnderlyingJsonMarshaler // UnderlyingJsonMarshaler | null - UTM UnderlyingTextMarshaler - UTMPtr *UnderlyingTextMarshaler // UnderlyingTextMarshaler | null - UM UnderlyingMarshaler - UMPtr *UnderlyingMarshaler // UnderlyingMarshaler | null - - JM struct{ json.Marshaler } // any - JMPtr *struct{ json.Marshaler } // any | null - TM struct{ encoding.TextMarshaler } // string - TMPtr *struct{ encoding.TextMarshaler } // string | null - CJM struct{ customJsonMarshaler } // any - CJMPtr *struct{ customJsonMarshaler } // any | null - CTM struct{ customTextMarshaler } // string - CTMPtr *struct{ customTextMarshaler } // string | null - CM struct{ customMarshaler } // any - CMPtr *struct{ customMarshaler } // any | null - - ANM AliasNonMarshaler - ANMPtr *AliasNonMarshaler // AliasNonMarshaler | null - AJM AliasJsonMarshaler - AJMPtr *AliasJsonMarshaler // AliasJsonMarshaler | null - ATM AliasTextMarshaler - ATMPtr *AliasTextMarshaler // AliasTextMarshaler | null - AM AliasMarshaler - AMPtr *AliasMarshaler // AliasMarshaler | null - - ImJM ImplicitJsonMarshaler - ImJMPtr *ImplicitJsonMarshaler // ImplicitJsonMarshaler | null - ImTM ImplicitTextMarshaler - ImTMPtr *ImplicitTextMarshaler // ImplicitTextMarshaler | null - ImM ImplicitMarshaler - ImMPtr *ImplicitMarshaler // ImplicitMarshaler | null - - ImNJ ImplicitNonJson - ImNJPtr *ImplicitNonJson // ImplicitNonJson | null - ImNT ImplicitNonText - ImNTPtr *ImplicitNonText // ImplicitNonText | null - ImNM ImplicitNonMarshaler - ImNMPtr *ImplicitNonMarshaler // ImplicitNonMarshaler | null - - ImJbT ImplicitJsonButText - ImJbTPtr *ImplicitJsonButText // ImplicitJsonButText | null - ImTbJ ImplicitTextButJson - ImTbJPtr *ImplicitTextButJson // ImplicitTextButJson | null -} - -func (*Service) Method() (_ Data) { - return -} - -func main() { - app := application.New(application.Options{ - Services: []application.Service{ - application.NewService(&Service{}), - }, - }) - - app.Window.New() - - err := app.Run() - - if err != nil { - log.Fatal(err) - } - -} - -func init() { - application.RegisterEvent[*struct{ Field []bool }]("collision") - application.RegisterEvent[*struct{ Field []bool }]("overlap") - application.RegisterEvent[json.Marshaler]("interface") -} diff --git a/v3/internal/generator/testcases/no_bindings_here/more/more.go b/v3/internal/generator/testcases/no_bindings_here/more/more.go deleted file mode 100644 index d17eff09c..000000000 --- a/v3/internal/generator/testcases/no_bindings_here/more/more.go +++ /dev/null @@ -1,4 +0,0 @@ -package more - -// StringPtr is a nullable string. -type StringPtr *string diff --git a/v3/internal/generator/testcases/no_bindings_here/other/othermethods.go b/v3/internal/generator/testcases/no_bindings_here/other/othermethods.go deleted file mode 100644 index 8d4ec6ba8..000000000 --- a/v3/internal/generator/testcases/no_bindings_here/other/othermethods.go +++ /dev/null @@ -1,11 +0,0 @@ -package other - -// OtherMethods has another method, but through a private embedded type. -type OtherMethods struct { - otherMethodsImpl -} - -type otherMethodsImpl int - -// LikeThisOtherOne does nothing as well, but is different. -func (*otherMethodsImpl) LikeThisOtherOne() {} diff --git a/v3/internal/generator/testcases/no_bindings_here/other/otherperson.go b/v3/internal/generator/testcases/no_bindings_here/other/otherperson.go deleted file mode 100644 index 516c965b5..000000000 --- a/v3/internal/generator/testcases/no_bindings_here/other/otherperson.go +++ /dev/null @@ -1,10 +0,0 @@ -package other - -// OtherPerson is like a person, but different. -type OtherPerson[T any] struct { - // They have a name as well. - Name string - - // But they may have many differences. - Differences []T -} diff --git a/v3/internal/generator/testcases/no_bindings_here/person.go b/v3/internal/generator/testcases/no_bindings_here/person.go deleted file mode 100644 index b0b6f941d..000000000 --- a/v3/internal/generator/testcases/no_bindings_here/person.go +++ /dev/null @@ -1,26 +0,0 @@ -package nobindingshere - -import "github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/other" - -// Person is not a number. -type Person struct { - // They have a name. - Name string - Friends [4]Impersonator // Exactly 4 sketchy friends. -} - -// Impersonator gets their fields from other people. -type Impersonator = other.OtherPerson[int] - -// HowDifferent is a curious kind of person -// that lets other people decide how they are different. -type HowDifferent[How any] other.OtherPerson[map[string]How] - -// PrivatePerson gets their fields from hidden sources. -type PrivatePerson = personImpl - -type personImpl struct { - // Nickname conceals a person's identity. - Nickname string - Person -} diff --git a/v3/internal/generator/testcases/no_bindings_here/somemethods.go b/v3/internal/generator/testcases/no_bindings_here/somemethods.go deleted file mode 100644 index 4b0602a64..000000000 --- a/v3/internal/generator/testcases/no_bindings_here/somemethods.go +++ /dev/null @@ -1,13 +0,0 @@ -package nobindingshere - -import "github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/other" - -// SomeMethods exports some methods. -type SomeMethods struct { - other.OtherMethods -} - -// LikeThisOne is an example method that does nothing. -func (SomeMethods) LikeThisOne() (_ Person, _ HowDifferent[bool], _ PrivatePerson) { - return -} diff --git a/v3/internal/generator/testcases/out_of_tree/bound_types.json b/v3/internal/generator/testcases/out_of_tree/bound_types.json deleted file mode 100644 index c0714f177..000000000 --- a/v3/internal/generator/testcases/out_of_tree/bound_types.json +++ /dev/null @@ -1,7 +0,0 @@ -[ - ".GreetService", - ".EmbedService", - ".EmbedOther", - "/../no_bindings_here.SomeMethods", - "/../no_bindings_here/other.OtherMethods" -] diff --git a/v3/internal/generator/testcases/out_of_tree/main.go b/v3/internal/generator/testcases/out_of_tree/main.go deleted file mode 100644 index c3dfbc9ee..000000000 --- a/v3/internal/generator/testcases/out_of_tree/main.go +++ /dev/null @@ -1,47 +0,0 @@ -package main - -import ( - _ "embed" - "log" - - nobindingshere "github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here" - "github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/other" - "github.com/wailsapp/wails/v3/pkg/application" -) - -// GreetService is great -type GreetService int - -// EmbedService is tricky. -type EmbedService struct { - nobindingshere.SomeMethods -} - -// EmbedOther is even trickier. -type EmbedOther struct { - other.OtherMethods -} - -// Greet someone -func (*GreetService) Greet(string) {} - -func main() { - app := application.New(application.Options{ - Services: []application.Service{ - application.NewService(new(GreetService)), - application.NewService(&EmbedService{}), - application.NewService(&EmbedOther{}), - application.NewService(&nobindingshere.SomeMethods{}), - application.NewService(&other.OtherMethods{}), - }, - }) - - app.Window.New() - - err := app.Run() - - if err != nil { - log.Fatal(err) - } - -} diff --git a/v3/internal/generator/testcases/struct_literal_multiple/bound_types.json b/v3/internal/generator/testcases/struct_literal_multiple/bound_types.json deleted file mode 100644 index be815a97e..000000000 --- a/v3/internal/generator/testcases/struct_literal_multiple/bound_types.json +++ /dev/null @@ -1,4 +0,0 @@ -[ - ".GreetService", - ".OtherService" -] diff --git a/v3/internal/generator/testcases/struct_literal_multiple/main.go b/v3/internal/generator/testcases/struct_literal_multiple/main.go deleted file mode 100644 index 5e1081504..000000000 --- a/v3/internal/generator/testcases/struct_literal_multiple/main.go +++ /dev/null @@ -1,41 +0,0 @@ -package main - -import ( - _ "embed" - "log" - - "github.com/wailsapp/wails/v3/pkg/application" -) - -type GreetService struct { - SomeVariable int - lowerCase string -} - -func (*GreetService) Greet(name string) string { - return "Hello " + name -} - -type OtherService struct { - t int -} - -func (o *OtherService) Hello() {} - -func main() { - app := application.New(application.Options{ - Services: []application.Service{ - application.NewService(&GreetService{}), - application.NewService(&OtherService{}), - }, - }) - - app.Window.New() - - err := app.Run() - - if err != nil { - log.Fatal(err) - } - -} diff --git a/v3/internal/generator/testcases/struct_literal_multiple_files/bound_types.json b/v3/internal/generator/testcases/struct_literal_multiple_files/bound_types.json deleted file mode 100644 index be815a97e..000000000 --- a/v3/internal/generator/testcases/struct_literal_multiple_files/bound_types.json +++ /dev/null @@ -1,4 +0,0 @@ -[ - ".GreetService", - ".OtherService" -] diff --git a/v3/internal/generator/testcases/struct_literal_multiple_files/greet.go b/v3/internal/generator/testcases/struct_literal_multiple_files/greet.go deleted file mode 100644 index 2a45396a7..000000000 --- a/v3/internal/generator/testcases/struct_literal_multiple_files/greet.go +++ /dev/null @@ -1,14 +0,0 @@ -package main - -import ( - _ "embed" -) - -type GreetService struct { - SomeVariable int - lowerCase string -} - -func (*GreetService) Greet(name string) string { - return "Hello " + name -} diff --git a/v3/internal/generator/testcases/struct_literal_multiple_files/main.go b/v3/internal/generator/testcases/struct_literal_multiple_files/main.go deleted file mode 100644 index ae80a4cba..000000000 --- a/v3/internal/generator/testcases/struct_literal_multiple_files/main.go +++ /dev/null @@ -1,26 +0,0 @@ -package main - -import ( - _ "embed" - "log" - - "github.com/wailsapp/wails/v3/pkg/application" -) - -func main() { - app := application.New(application.Options{ - Services: []application.Service{ - application.NewService(&GreetService{}), - application.NewService(&OtherService{}), - }, - }) - - app.Window.New() - - err := app.Run() - - if err != nil { - log.Fatal(err) - } - -} diff --git a/v3/internal/generator/testcases/struct_literal_multiple_files/other.go b/v3/internal/generator/testcases/struct_literal_multiple_files/other.go deleted file mode 100644 index ad5e661ef..000000000 --- a/v3/internal/generator/testcases/struct_literal_multiple_files/other.go +++ /dev/null @@ -1,7 +0,0 @@ -package main - -type OtherService struct { - t int -} - -func (o *OtherService) Hello() {} diff --git a/v3/internal/generator/testcases/struct_literal_multiple_other/bound_types.json b/v3/internal/generator/testcases/struct_literal_multiple_other/bound_types.json deleted file mode 100644 index 86a0a8812..000000000 --- a/v3/internal/generator/testcases/struct_literal_multiple_other/bound_types.json +++ /dev/null @@ -1,4 +0,0 @@ -[ - ".GreetService", - "/services.OtherService" -] diff --git a/v3/internal/generator/testcases/struct_literal_multiple_other/main.go b/v3/internal/generator/testcases/struct_literal_multiple_other/main.go deleted file mode 100644 index 7b7a3a2ab..000000000 --- a/v3/internal/generator/testcases/struct_literal_multiple_other/main.go +++ /dev/null @@ -1,49 +0,0 @@ -package main - -import ( - _ "embed" - "log" - - "github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_other/services" - "github.com/wailsapp/wails/v3/pkg/application" -) - -// GreetService is great -type GreetService struct { - SomeVariable int - lowerCase string - target *Person -} - -type Person struct { - Name string - Address *services.Address -} - -// Greet does XYZ -func (*GreetService) Greet(name string) string { - return "Hello " + name -} - -// NewPerson creates a new person -func (*GreetService) NewPerson(name string) *Person { - return &Person{Name: name} -} - -func main() { - app := application.New(application.Options{ - Services: []application.Service{ - application.NewService(&GreetService{}), - application.NewService(&services.OtherService{}), - }, - }) - - app.Window.New() - - err := app.Run() - - if err != nil { - log.Fatal(err) - } - -} diff --git a/v3/internal/generator/testcases/struct_literal_multiple_other/services/other.go b/v3/internal/generator/testcases/struct_literal_multiple_other/services/other.go deleted file mode 100644 index 55472595b..000000000 --- a/v3/internal/generator/testcases/struct_literal_multiple_other/services/other.go +++ /dev/null @@ -1,22 +0,0 @@ -package services - -// OtherService is a struct -// that does things -type OtherService struct { - t int -} - -type Address struct { - Street string - State string - Country string -} - -// Yay does this and that -func (o *OtherService) Yay() *Address { - return &Address{ - Street: "123 Pitt Street", - State: "New South Wales", - Country: "Australia", - } -} diff --git a/v3/internal/generator/testcases/struct_literal_non_pointer_single/bound_types.json b/v3/internal/generator/testcases/struct_literal_non_pointer_single/bound_types.json deleted file mode 100644 index a8b95e321..000000000 --- a/v3/internal/generator/testcases/struct_literal_non_pointer_single/bound_types.json +++ /dev/null @@ -1,3 +0,0 @@ -[ - ".GreetService" -] diff --git a/v3/internal/generator/testcases/struct_literal_non_pointer_single/main.go b/v3/internal/generator/testcases/struct_literal_non_pointer_single/main.go deleted file mode 100644 index e0fd8247d..000000000 --- a/v3/internal/generator/testcases/struct_literal_non_pointer_single/main.go +++ /dev/null @@ -1,205 +0,0 @@ -package main - -import ( - _ "embed" - "log" - "strings" - - "github.com/wailsapp/wails/v3/pkg/application" -) - -type Person struct { - Name string - Parent *Person - Details struct { - Age int - Address struct { - Street string - } - } -} - -// GreetService is great -type GreetService struct { - SomeVariable int - lowerCase string -} - -// Greet someone -func (GreetService) Greet(name string) string { - return "Hello " + name -} - -func (GreetService) NoInputsStringOut() string { - return "Hello" -} - -func (GreetService) StringArrayInputStringOut(in []string) string { - return strings.Join(in, ",") -} - -func (GreetService) StringArrayInputStringArrayOut(in []string) []string { - return in -} - -func (GreetService) StringArrayInputNamedOutput(in []string) (output []string) { - return in -} - -func (GreetService) StringArrayInputNamedOutputs(in []string) (output []string, err error) { - return in, nil -} - -func (GreetService) IntPointerInputNamedOutputs(in *int) (output *int, err error) { - return in, nil -} - -func (GreetService) UIntPointerInAndOutput(in *uint) *uint { - return in -} - -func (GreetService) UInt8PointerInAndOutput(in *uint8) *uint8 { - return in -} - -func (GreetService) UInt16PointerInAndOutput(in *uint16) *uint16 { - return in -} - -func (GreetService) UInt32PointerInAndOutput(in *uint32) *uint32 { - return in -} - -func (GreetService) UInt64PointerInAndOutput(in *uint64) *uint64 { - return in -} - -func (GreetService) IntPointerInAndOutput(in *int) *int { - return in -} - -func (GreetService) Int8PointerInAndOutput(in *int8) *int8 { - return in -} - -func (GreetService) Int16PointerInAndOutput(in *int16) *int16 { - return in -} - -func (GreetService) Int32PointerInAndOutput(in *int32) *int32 { - return in -} - -func (GreetService) Int64PointerInAndOutput(in *int64) *int64 { - return in -} - -func (GreetService) IntInIntOut(in int) int { - return in -} - -func (GreetService) Int8InIntOut(in int8) int8 { - return in -} -func (GreetService) Int16InIntOut(in int16) int16 { - return in -} -func (GreetService) Int32InIntOut(in int32) int32 { - return in -} -func (GreetService) Int64InIntOut(in int64) int64 { - return in -} - -func (GreetService) UIntInUIntOut(in uint) uint { - return in -} - -func (GreetService) UInt8InUIntOut(in uint8) uint8 { - return in -} -func (GreetService) UInt16InUIntOut(in uint16) uint16 { - return in -} -func (GreetService) UInt32InUIntOut(in uint32) uint32 { - return in -} -func (GreetService) UInt64InUIntOut(in uint64) uint64 { - return in -} - -func (GreetService) Float32InFloat32Out(in float32) float32 { - return in -} - -func (GreetService) Float64InFloat64Out(in float64) float64 { - return in -} - -func (GreetService) PointerFloat32InFloat32Out(in *float32) *float32 { - return in -} - -func (GreetService) PointerFloat64InFloat64Out(in *float64) *float64 { - return in -} - -func (GreetService) BoolInBoolOut(in bool) bool { - return in -} - -func (GreetService) PointerBoolInBoolOut(in *bool) *bool { - return in -} - -func (GreetService) PointerStringInStringOut(in *string) *string { - return in -} - -func (GreetService) StructPointerInputErrorOutput(in *Person) error { - return nil -} - -func (GreetService) StructInputStructOutput(in Person) Person { - return in -} - -func (GreetService) StructPointerInputStructPointerOutput(in *Person) *Person { - return in -} - -func (GreetService) MapIntInt(in map[int]int) { -} - -func (GreetService) PointerMapIntInt(in *map[int]int) { -} - -func (GreetService) MapIntIntPointer(in map[int]*int) { -} - -func (GreetService) MapIntSliceInt(in map[int][]int) { -} - -func (GreetService) MapIntSliceIntInMapIntSliceIntOut(in map[int][]int) (out map[int][]int) { - return nil -} - -func (GreetService) ArrayInt(in [4]int) { -} - -func main() { - app := application.New(application.Options{ - Services: []application.Service{ - application.NewService(&GreetService{}), - }, - }) - - app.Window.New() - - err := app.Run() - - if err != nil { - log.Fatal(err) - } - -} diff --git a/v3/internal/generator/testcases/struct_literal_single/bound_types.json b/v3/internal/generator/testcases/struct_literal_single/bound_types.json deleted file mode 100644 index a8b95e321..000000000 --- a/v3/internal/generator/testcases/struct_literal_single/bound_types.json +++ /dev/null @@ -1,3 +0,0 @@ -[ - ".GreetService" -] diff --git a/v3/internal/generator/testcases/struct_literal_single/main.go b/v3/internal/generator/testcases/struct_literal_single/main.go deleted file mode 100644 index 945874a0b..000000000 --- a/v3/internal/generator/testcases/struct_literal_single/main.go +++ /dev/null @@ -1,205 +0,0 @@ -package main - -import ( - _ "embed" - "log" - "strings" - - "github.com/wailsapp/wails/v3/pkg/application" -) - -type Person struct { - Name string - Parent *Person - Details struct { - Age int - Address struct { - Street string - } - } -} - -// GreetService is great -type GreetService struct { - SomeVariable int - lowerCase string -} - -// Greet someone -func (*GreetService) Greet(name string) string { - return "Hello " + name -} - -func (*GreetService) NoInputsStringOut() string { - return "Hello" -} - -func (*GreetService) StringArrayInputStringOut(in []string) string { - return strings.Join(in, ",") -} - -func (*GreetService) StringArrayInputStringArrayOut(in []string) []string { - return in -} - -func (*GreetService) StringArrayInputNamedOutput(in []string) (output []string) { - return in -} - -func (*GreetService) StringArrayInputNamedOutputs(in []string) (output []string, err error) { - return in, nil -} - -func (*GreetService) IntPointerInputNamedOutputs(in *int) (output *int, err error) { - return in, nil -} - -func (*GreetService) UIntPointerInAndOutput(in *uint) *uint { - return in -} - -func (*GreetService) UInt8PointerInAndOutput(in *uint8) *uint8 { - return in -} - -func (*GreetService) UInt16PointerInAndOutput(in *uint16) *uint16 { - return in -} - -func (*GreetService) UInt32PointerInAndOutput(in *uint32) *uint32 { - return in -} - -func (*GreetService) UInt64PointerInAndOutput(in *uint64) *uint64 { - return in -} - -func (*GreetService) IntPointerInAndOutput(in *int) *int { - return in -} - -func (*GreetService) Int8PointerInAndOutput(in *int8) *int8 { - return in -} - -func (*GreetService) Int16PointerInAndOutput(in *int16) *int16 { - return in -} - -func (*GreetService) Int32PointerInAndOutput(in *int32) *int32 { - return in -} - -func (*GreetService) Int64PointerInAndOutput(in *int64) *int64 { - return in -} - -func (*GreetService) IntInIntOut(in int) int { - return in -} - -func (*GreetService) Int8InIntOut(in int8) int8 { - return in -} -func (*GreetService) Int16InIntOut(in int16) int16 { - return in -} -func (*GreetService) Int32InIntOut(in int32) int32 { - return in -} -func (*GreetService) Int64InIntOut(in int64) int64 { - return in -} - -func (*GreetService) UIntInUIntOut(in uint) uint { - return in -} - -func (*GreetService) UInt8InUIntOut(in uint8) uint8 { - return in -} -func (*GreetService) UInt16InUIntOut(in uint16) uint16 { - return in -} -func (*GreetService) UInt32InUIntOut(in uint32) uint32 { - return in -} -func (*GreetService) UInt64InUIntOut(in uint64) uint64 { - return in -} - -func (*GreetService) Float32InFloat32Out(in float32) float32 { - return in -} - -func (*GreetService) Float64InFloat64Out(in float64) float64 { - return in -} - -func (*GreetService) PointerFloat32InFloat32Out(in *float32) *float32 { - return in -} - -func (*GreetService) PointerFloat64InFloat64Out(in *float64) *float64 { - return in -} - -func (*GreetService) BoolInBoolOut(in bool) bool { - return in -} - -func (*GreetService) PointerBoolInBoolOut(in *bool) *bool { - return in -} - -func (*GreetService) PointerStringInStringOut(in *string) *string { - return in -} - -func (*GreetService) StructPointerInputErrorOutput(in *Person) error { - return nil -} - -func (*GreetService) StructInputStructOutput(in Person) Person { - return in -} - -func (*GreetService) StructPointerInputStructPointerOutput(in *Person) *Person { - return in -} - -func (*GreetService) MapIntInt(in map[int]int) { -} - -func (*GreetService) PointerMapIntInt(in *map[int]int) { -} - -func (*GreetService) MapIntIntPointer(in map[int]*int) { -} - -func (*GreetService) MapIntSliceInt(in map[int][]int) { -} - -func (*GreetService) MapIntSliceIntInMapIntSliceIntOut(in map[int][]int) (out map[int][]int) { - return nil -} - -func (*GreetService) ArrayInt(in [4]int) { -} - -func main() { - app := application.New(application.Options{ - Services: []application.Service{ - application.NewService(&GreetService{}), - }, - }) - - app.Window.New() - - err := app.Run() - - if err != nil { - log.Fatal(err) - } - -} diff --git a/v3/internal/generator/testcases/variable_single/bound_types.json b/v3/internal/generator/testcases/variable_single/bound_types.json deleted file mode 100644 index a8b95e321..000000000 --- a/v3/internal/generator/testcases/variable_single/bound_types.json +++ /dev/null @@ -1,3 +0,0 @@ -[ - ".GreetService" -] diff --git a/v3/internal/generator/testcases/variable_single/main.go b/v3/internal/generator/testcases/variable_single/main.go deleted file mode 100644 index 5baf1a04f..000000000 --- a/v3/internal/generator/testcases/variable_single/main.go +++ /dev/null @@ -1,37 +0,0 @@ -package main - -import ( - _ "embed" - "log" - - "github.com/wailsapp/wails/v3/pkg/application" -) - -// GreetService is great -type GreetService struct { - SomeVariable int - lowerCase string -} - -// Greet someone -func (*GreetService) Greet(name string) string { - return "Hello " + name -} - -func main() { - greetService := application.NewService(&GreetService{}) - app := application.New(application.Options{ - Services: []application.Service{ - greetService, - }, - }) - - app.Window.New() - - err := app.Run() - - if err != nil { - log.Fatal(err) - } - -} diff --git a/v3/internal/generator/testcases/variable_single_from_function/bound_types.json b/v3/internal/generator/testcases/variable_single_from_function/bound_types.json deleted file mode 100644 index a8b95e321..000000000 --- a/v3/internal/generator/testcases/variable_single_from_function/bound_types.json +++ /dev/null @@ -1,3 +0,0 @@ -[ - ".GreetService" -] diff --git a/v3/internal/generator/testcases/variable_single_from_function/main.go b/v3/internal/generator/testcases/variable_single_from_function/main.go deleted file mode 100644 index 247702051..000000000 --- a/v3/internal/generator/testcases/variable_single_from_function/main.go +++ /dev/null @@ -1,42 +0,0 @@ -package main - -import ( - _ "embed" - "log" - - "github.com/wailsapp/wails/v3/pkg/application" -) - -// GreetService is great -type GreetService struct { - SomeVariable int - lowerCase string -} - -// Greet someone -func (*GreetService) Greet(name string) string { - return "Hello " + name -} - -func NewGreetService() application.Service { - return application.NewService(&GreetService{}) -} - -func main() { - greetService := NewGreetService() - app := application.New(application.Options{ - Services: []application.Service{ - greetService, - }, - }) - - _ = app.Window.New() // discard - // or: win := app.Window.New() // keep for later - - err := app.Run() - - if err != nil { - log.Fatal(err) - } - -} diff --git a/v3/internal/generator/testcases/variable_single_from_other_function/bound_types.json b/v3/internal/generator/testcases/variable_single_from_other_function/bound_types.json deleted file mode 100644 index 86a0a8812..000000000 --- a/v3/internal/generator/testcases/variable_single_from_other_function/bound_types.json +++ /dev/null @@ -1,4 +0,0 @@ -[ - ".GreetService", - "/services.OtherService" -] diff --git a/v3/internal/generator/testcases/variable_single_from_other_function/main.go b/v3/internal/generator/testcases/variable_single_from_other_function/main.go deleted file mode 100644 index 6bbb73f46..000000000 --- a/v3/internal/generator/testcases/variable_single_from_other_function/main.go +++ /dev/null @@ -1,53 +0,0 @@ -package main - -import ( - _ "embed" - "log" - - "github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_other_function/services" - - "github.com/wailsapp/wails/v3/pkg/application" -) - -// GreetService is great -type GreetService struct { - SomeVariable int - lowerCase string - target *Person -} - -// Person is a person! -// They have a name and an address -type Person struct { - Name string - Address *services.Address -} - -// Greet does XYZ -func (*GreetService) Greet(name string) string { - return "Hello " + name -} - -// NewPerson creates a new person -func (*GreetService) NewPerson(name string) *Person { - return &Person{Name: name} -} - -func main() { - otherService := services.NewOtherService() - app := application.New(application.Options{ - Services: []application.Service{ - application.NewService(&GreetService{}), - otherService, - }, - }) - - app.Window.New() - - err := app.Run() - - if err != nil { - log.Fatal(err) - } - -} diff --git a/v3/internal/generator/testcases/variable_single_from_other_function/services/other.go b/v3/internal/generator/testcases/variable_single_from_other_function/services/other.go deleted file mode 100644 index 4ac6e6efd..000000000 --- a/v3/internal/generator/testcases/variable_single_from_other_function/services/other.go +++ /dev/null @@ -1,28 +0,0 @@ -package services - -import "github.com/wailsapp/wails/v3/pkg/application" - -// OtherService is a struct -// that does things -type OtherService struct { - t int -} - -type Address struct { - Street string - State string - Country string -} - -// Yay does this and that -func (o *OtherService) Yay() *Address { - return &Address{ - Street: "123 Pitt Street", - State: "New South Wales", - Country: "Australia", - } -} - -func NewOtherService() application.Service { - return application.NewService(&OtherService{}) -} diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/encoding/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/encoding/index.js deleted file mode 100644 index cf48d86db..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/encoding/index.js +++ /dev/null @@ -1,13 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as $models from "./models.js"; - -/** - * TextMarshaler is the interface implemented by an object that can - * marshal itself into a textual form. - * - * MarshalText encodes the receiver into UTF-8-encoded text and returns the result. - * @typedef {$models.TextMarshaler} TextMarshaler - */ diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/encoding/json/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/encoding/json/index.js deleted file mode 100644 index 22f1fd904..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/encoding/json/index.js +++ /dev/null @@ -1,11 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as $models from "./models.js"; - -/** - * Marshaler is the interface implemented by types that - * can marshal themselves into valid JSON. - * @typedef {$models.Marshaler} Marshaler - */ diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/encoding/json/models.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/encoding/json/models.js deleted file mode 100644 index 96abf0ef1..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/encoding/json/models.js +++ /dev/null @@ -1,13 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Create as $Create } from "/wails/runtime.js"; - -/** - * Marshaler is the interface implemented by types that - * can marshal themselves into valid JSON. - * @typedef {any} Marshaler - */ diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/encoding/models.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/encoding/models.js deleted file mode 100644 index 59cfef5bd..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/encoding/models.js +++ /dev/null @@ -1,15 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Create as $Create } from "/wails/runtime.js"; - -/** - * TextMarshaler is the interface implemented by an object that can - * marshal itself into a textual form. - * - * MarshalText encodes the receiver into UTF-8-encoded text and returns the result. - * @typedef {any} TextMarshaler - */ diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/eventcreate.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/eventcreate.js deleted file mode 100644 index 9cc7781aa..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/eventcreate.js +++ /dev/null @@ -1,39 +0,0 @@ -//@ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Create as $Create } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as json$0 from "../../../../../encoding/json/models.js"; -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as events_only$0 from "./generator/testcases/events_only/models.js"; -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as more$0 from "./generator/testcases/no_bindings_here/more/models.js"; - -function configure() { - Object.freeze(Object.assign($Create.Events, { - "events_only:class": $$createType0, - "events_only:map": $$createType2, - "events_only:other": $$createType3, - "overlap": $$createType6, - })); -} - -// Private type creation functions -const $$createType0 = events_only$0.SomeClass.createFrom; -const $$createType1 = $Create.Array($Create.Any); -const $$createType2 = $Create.Map($Create.Any, $$createType1); -const $$createType3 = $Create.Array($Create.Any); -const $$createType4 = $Create.Array($Create.Any); -const $$createType5 = $Create.Struct({ - "Field": $$createType4, -}); -const $$createType6 = $Create.Nullable($$createType5); - -configure(); diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/eventdata.d.ts b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/eventdata.d.ts deleted file mode 100644 index 3e53d9287..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/eventdata.d.ts +++ /dev/null @@ -1,30 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import type { Events } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import type * as json$0 from "../../../../../encoding/json/models.js"; -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import type * as events_only$0 from "./generator/testcases/events_only/models.js"; -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import type * as more$0 from "./generator/testcases/no_bindings_here/more/models.js"; - -declare module "/wails/runtime.js" { - namespace Events { - interface CustomEvents { - "events_only:class": events_only$0.SomeClass; - "events_only:map": { [_ in string]?: number[] }; - "events_only:nodata": void; - "events_only:other": more$0.StringPtr[]; - "events_only:string": string; - "interface": json$0.Marshaler; - "overlap": {"Field": boolean[]} | null; - } - } -} diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/aliases/greetservice.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/aliases/greetservice.js deleted file mode 100644 index 212ef1b21..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/aliases/greetservice.js +++ /dev/null @@ -1,110 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as subpkg$0 from "./subpkg/models.js"; -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as nobindingshere$0 from "../no_bindings_here/models.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * Get someone. - * @param {$models.Alias} aliasValue - * @returns {$CancellablePromise<$models.Person>} - */ -export function Get(aliasValue) { - return $Call.ByID(1928502664, aliasValue).then(/** @type {($result: any) => any} */(($result) => { - return $$createType0($result); - })); -} - -/** - * Apparently, aliases are all the rage right now. - * @param {$models.AliasedPerson} p - * @returns {$CancellablePromise<$models.StrangelyAliasedPerson>} - */ -export function GetButAliased(p) { - return $Call.ByID(1896499664, p).then(/** @type {($result: any) => any} */(($result) => { - return $$createType0($result); - })); -} - -/** - * Get someone quite different. - * @returns {$CancellablePromise<$models.GenericPerson>} - */ -export function GetButDifferent() { - return $Call.ByID(2240931744).then(/** @type {($result: any) => any} */(($result) => { - return $$createType1($result); - })); -} - -/** - * @returns {$CancellablePromise} - */ -export function GetButForeignPrivateAlias() { - return $Call.ByID(643456960).then(/** @type {($result: any) => any} */(($result) => { - return $$createType2($result); - })); -} - -/** - * @returns {$CancellablePromise<$models.AliasGroup>} - */ -export function GetButGenericAliases() { - return $Call.ByID(914093800).then(/** @type {($result: any) => any} */(($result) => { - return $$createType3($result); - })); -} - -/** - * @returns {$CancellablePromise<$models.SubPackageAlias>} - */ -export function GetButSubPackageAlias() { - return $Call.ByID(1443276371).then(/** @type {($result: any) => any} */(($result) => { - return $$createType4($result); - })); -} - -/** - * Greet a lot of unusual things. - * @param {$models.EmptyAliasStruct} $0 - * @param {$models.EmptyStruct} $1 - * @returns {$CancellablePromise<$models.AliasStruct>} - */ -export function Greet($0, $1) { - return $Call.ByID(1411160069, $0, $1).then(/** @type {($result: any) => any} */(($result) => { - return $$createType8($result); - })); -} - -// Private type creation functions -const $$createType0 = $models.Person.createFrom; -const $$createType1 = $models.GenericPerson.createFrom($Create.Any); -const $$createType2 = nobindingshere$0.personImpl.createFrom; -const $$createType3 = $models.AliasGroup.createFrom; -const $$createType4 = subpkg$0.SubStruct.createFrom; -const $$createType5 = $Create.Array($Create.Any); -const $$createType6 = $Create.Array($Create.Any); -const $$createType7 = $Create.Struct({ - "NoMoreIdeas": $$createType6, -}); -const $$createType8 = $Create.Struct({ - "Foo": $$createType5, - "Other": $$createType7, -}); diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/aliases/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/aliases/index.js deleted file mode 100644 index acfbc8a9b..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/aliases/index.js +++ /dev/null @@ -1,62 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; - -export { - AliasGroup, - AliasedPerson, - EmptyStruct, - GenericPerson, - GenericPersonAlias, - IndirectPersonAlias, - Person, - StrangelyAliasedPerson, - SubPackageAlias, - TPIndirectPersonAlias -} from "./models.js"; - -import * as $models from "./models.js"; - -/** - * A nice type Alias. - * @typedef {$models.Alias} Alias - */ - -/** - * A struct alias. - * This should be rendered as a typedef or interface in every mode. - * @typedef {$models.AliasStruct} AliasStruct - */ - -/** - * An empty struct alias. - * @typedef {$models.EmptyAliasStruct} EmptyAliasStruct - */ - -/** - * A generic alias that forwards to a type parameter. - * @template T - * @typedef {$models.GenericAlias} GenericAlias - */ - -/** - * A generic alias that wraps a map. - * @template T,U - * @typedef {$models.GenericMapAlias} GenericMapAlias - */ - -/** - * A generic alias that wraps a pointer type. - * @template T - * @typedef {$models.GenericPtrAlias} GenericPtrAlias - */ - -/** - * Another struct alias. - * @typedef {$models.OtherAliasStruct} OtherAliasStruct - */ diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/aliases/models.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/aliases/models.js deleted file mode 100644 index 31bb61c83..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/aliases/models.js +++ /dev/null @@ -1,360 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Create as $Create } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as subpkg$0 from "./subpkg/models.js"; - -/** - * A nice type Alias. - * @typedef {number} Alias - */ - -/** - * A class whose fields have various aliased types. - */ -export class AliasGroup { - /** - * Creates a new AliasGroup instance. - * @param {Partial} [$$source = {}] - The source object to create the AliasGroup. - */ - constructor($$source = {}) { - if (!("GAi" in $$source)) { - /** - * @member - * @type {GenericAlias} - */ - this["GAi"] = 0; - } - if (!("GAP" in $$source)) { - /** - * @member - * @type {GenericAlias>} - */ - this["GAP"] = (new GenericPerson()); - } - if (!("GPAs" in $$source)) { - /** - * @member - * @type {GenericPtrAlias} - */ - this["GPAs"] = null; - } - if (!("GPAP" in $$source)) { - /** - * @member - * @type {GenericPtrAlias>} - */ - this["GPAP"] = null; - } - if (!("GMA" in $$source)) { - /** - * @member - * @type {GenericMapAlias} - */ - this["GMA"] = {}; - } - if (!("GPA" in $$source)) { - /** - * @member - * @type {GenericPersonAlias} - */ - this["GPA"] = (new GenericPersonAlias()); - } - if (!("IPA" in $$source)) { - /** - * @member - * @type {IndirectPersonAlias} - */ - this["IPA"] = (new IndirectPersonAlias()); - } - if (!("TPIPA" in $$source)) { - /** - * @member - * @type {TPIndirectPersonAlias} - */ - this["TPIPA"] = (new TPIndirectPersonAlias()); - } - if (!("SPA" in $$source)) { - /** - * @member - * @type {SubPackageAlias} - */ - this["SPA"] = (new SubPackageAlias()); - } - - Object.assign(this, $$source); - } - - /** - * Creates a new AliasGroup instance from a string or object. - * @param {any} [$$source = {}] - * @returns {AliasGroup} - */ - static createFrom($$source = {}) { - const $$createField1_0 = $$createType0; - const $$createField2_0 = $$createType2; - const $$createField3_0 = $$createType5; - const $$createField4_0 = $$createType6; - const $$createField5_0 = $$createType8; - const $$createField6_0 = $$createType8; - const $$createField7_0 = $$createType0; - const $$createField8_0 = $$createType9; - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - if ("GAP" in $$parsedSource) { - $$parsedSource["GAP"] = $$createField1_0($$parsedSource["GAP"]); - } - if ("GPAs" in $$parsedSource) { - $$parsedSource["GPAs"] = $$createField2_0($$parsedSource["GPAs"]); - } - if ("GPAP" in $$parsedSource) { - $$parsedSource["GPAP"] = $$createField3_0($$parsedSource["GPAP"]); - } - if ("GMA" in $$parsedSource) { - $$parsedSource["GMA"] = $$createField4_0($$parsedSource["GMA"]); - } - if ("GPA" in $$parsedSource) { - $$parsedSource["GPA"] = $$createField5_0($$parsedSource["GPA"]); - } - if ("IPA" in $$parsedSource) { - $$parsedSource["IPA"] = $$createField6_0($$parsedSource["IPA"]); - } - if ("TPIPA" in $$parsedSource) { - $$parsedSource["TPIPA"] = $$createField7_0($$parsedSource["TPIPA"]); - } - if ("SPA" in $$parsedSource) { - $$parsedSource["SPA"] = $$createField8_0($$parsedSource["SPA"]); - } - return new AliasGroup(/** @type {Partial} */($$parsedSource)); - } -} - -/** - * A struct alias. - * This should be rendered as a typedef or interface in every mode. - * @typedef {Object} AliasStruct - * @property {number[]} Foo - A field with a comment. - * @property {string} [Bar] - Definitely not Foo. - * @property {string} [Baz] - Definitely not Foo. - * @property {OtherAliasStruct} Other - A nested alias struct. - */ - -/** - * An empty struct alias. - * @typedef { { - * } } EmptyAliasStruct - */ - -/** - * An empty struct. - */ -export class EmptyStruct { - /** - * Creates a new EmptyStruct instance. - * @param {Partial} [$$source = {}] - The source object to create the EmptyStruct. - */ - constructor($$source = {}) { - - Object.assign(this, $$source); - } - - /** - * Creates a new EmptyStruct instance from a string or object. - * @param {any} [$$source = {}] - * @returns {EmptyStruct} - */ - static createFrom($$source = {}) { - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - return new EmptyStruct(/** @type {Partial} */($$parsedSource)); - } -} - -/** - * A generic alias that forwards to a type parameter. - * @template T - * @typedef {T} GenericAlias - */ - -/** - * A generic alias that wraps a map. - * @template T,U - * @typedef {{ [_ in string]?: U }} GenericMapAlias - */ - -/** - * A generic struct containing an alias. - * @template T - */ -export class GenericPerson { - /** - * Creates a new GenericPerson instance. - * @param {Partial>} [$$source = {}] - The source object to create the GenericPerson. - */ - constructor($$source = {}) { - if (/** @type {any} */(false)) { - /** - * @member - * @type {T | undefined} - */ - this["Name"] = undefined; - } - if (!("AliasedField" in $$source)) { - /** - * @member - * @type {Alias} - */ - this["AliasedField"] = 0; - } - - Object.assign(this, $$source); - } - - /** - * Given creation functions for each type parameter, - * returns a creation function for a concrete instance - * of the generic class GenericPerson. - * @template [T=any] - * @param {(source: any) => T} $$createParamT - * @returns {($$source?: any) => GenericPerson} - */ - static createFrom($$createParamT) { - const $$createField0_0 = $$createParamT; - return ($$source = {}) => { - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - if ("Name" in $$parsedSource) { - $$parsedSource["Name"] = $$createField0_0($$parsedSource["Name"]); - } - return new GenericPerson(/** @type {Partial>} */($$parsedSource)); - }; - } -} - -/** - * A generic alias that wraps a generic struct. - */ -export const GenericPersonAlias = GenericPerson; - -/** - * A generic alias that wraps a generic struct. - * @template T - * @typedef {GenericPerson[]>} GenericPersonAlias - */ - -/** - * A generic alias that wraps a pointer type. - * @template T - * @typedef {GenericAlias | null} GenericPtrAlias - */ - -/** - * An alias that wraps a class through a non-typeparam alias. - */ -export const IndirectPersonAlias = GenericPersonAlias; - -/** - * An alias that wraps a class through a non-typeparam alias. - * @typedef {GenericPersonAlias} IndirectPersonAlias - */ - -/** - * Another struct alias. - * @typedef {Object} OtherAliasStruct - * @property {number[]} NoMoreIdeas - */ - -/** - * A non-generic struct containing an alias. - */ -export class Person { - /** - * Creates a new Person instance. - * @param {Partial} [$$source = {}] - The source object to create the Person. - */ - constructor($$source = {}) { - if (!("Name" in $$source)) { - /** - * The Person's name. - * @member - * @type {string} - */ - this["Name"] = ""; - } - if (!("AliasedField" in $$source)) { - /** - * A random alias field. - * @member - * @type {Alias} - */ - this["AliasedField"] = 0; - } - - Object.assign(this, $$source); - } - - /** - * Creates a new Person instance from a string or object. - * @param {any} [$$source = {}] - * @returns {Person} - */ - static createFrom($$source = {}) { - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - return new Person(/** @type {Partial} */($$parsedSource)); - } -} - -/** - * A class alias. - */ -export const AliasedPerson = Person; - -/** - * A class alias. - * @typedef {Person} AliasedPerson - */ - -/** - * Another class alias, but ordered after its aliased class. - */ -export const StrangelyAliasedPerson = Person; - -/** - * Another class alias, but ordered after its aliased class. - * @typedef {Person} StrangelyAliasedPerson - */ - -/** - * An alias referencing another package that is not used elsewhere. - */ -export const SubPackageAlias = subpkg$0.SubStruct; - -/** - * An alias referencing another package that is not used elsewhere. - * @typedef {subpkg$0.SubStruct} SubPackageAlias - */ - -/** - * An alias that wraps a class through a typeparam alias. - */ -export const TPIndirectPersonAlias = GenericPerson; - -/** - * An alias that wraps a class through a typeparam alias. - * @typedef {GenericAlias>} TPIndirectPersonAlias - */ - -// Private type creation functions -const $$createType0 = GenericPerson.createFrom($Create.Any); -const $$createType1 = $Create.Array($Create.Any); -const $$createType2 = $Create.Nullable($$createType1); -const $$createType3 = $Create.Array($Create.Any); -const $$createType4 = GenericPerson.createFrom($$createType3); -const $$createType5 = $Create.Nullable($$createType4); -const $$createType6 = $Create.Map($Create.Any, $Create.Any); -const $$createType7 = $Create.Array($Create.Any); -const $$createType8 = GenericPerson.createFrom($$createType7); -const $$createType9 = subpkg$0.SubStruct.createFrom; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/aliases/subpkg/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/aliases/subpkg/index.js deleted file mode 100644 index a3d65abcf..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/aliases/subpkg/index.js +++ /dev/null @@ -1,7 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -export { - SubStruct -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/aliases/subpkg/models.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/aliases/subpkg/models.js deleted file mode 100644 index c582d6149..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/aliases/subpkg/models.js +++ /dev/null @@ -1,45 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Create as $Create } from "/wails/runtime.js"; - -/** - * SubStruct is a type in a subpackage that is only referenced through an alias. - */ -export class SubStruct { - /** - * Creates a new SubStruct instance. - * @param {Partial} [$$source = {}] - The source object to create the SubStruct. - */ - constructor($$source = {}) { - if (!("SomeField" in $$source)) { - /** - * @member - * @type {string[]} - */ - this["SomeField"] = []; - } - - Object.assign(this, $$source); - } - - /** - * Creates a new SubStruct instance from a string or object. - * @param {any} [$$source = {}] - * @returns {SubStruct} - */ - static createFrom($$source = {}) { - const $$createField0_0 = $$createType0; - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - if ("SomeField" in $$parsedSource) { - $$parsedSource["SomeField"] = $$createField0_0($$parsedSource["SomeField"]); - } - return new SubStruct(/** @type {Partial} */($$parsedSource)); - } -} - -// Private type creation functions -const $$createType0 = $Create.Array($Create.Any); diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_expressions/config/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_expressions/config/index.js deleted file mode 100644 index f6c839720..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_expressions/config/index.js +++ /dev/null @@ -1,10 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as Service7 from "./service7.js"; -import * as Service9 from "./service9.js"; -export { - Service7, - Service9 -}; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_expressions/config/service7.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_expressions/config/service7.js deleted file mode 100644 index 42219054f..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_expressions/config/service7.js +++ /dev/null @@ -1,14 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -/** - * @returns {$CancellablePromise} - */ -export function TestMethod() { - return $Call.ByID(2241101727); -} diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_expressions/config/service9.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_expressions/config/service9.js deleted file mode 100644 index 5e27fbc9e..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_expressions/config/service9.js +++ /dev/null @@ -1,14 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -/** - * @returns {$CancellablePromise} - */ -export function TestMethod2() { - return $Call.ByID(1556848345); -} diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_json/greetservice.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_json/greetservice.js deleted file mode 100644 index fa634943d..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_json/greetservice.js +++ /dev/null @@ -1,26 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * Greet does XYZ - * @param {$models.Person} person - * @param {$models.Embedded1} emb - * @returns {$CancellablePromise} - */ -export function Greet(person, emb) { - return $Call.ByID(1411160069, person, emb); -} diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_json/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_json/index.js deleted file mode 100644 index ab78e5ea3..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_json/index.js +++ /dev/null @@ -1,20 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; - -export { - Embedded1, - Person, - Title -} from "./models.js"; - -import * as $models from "./models.js"; - -/** - * @typedef {$models.Embedded3} Embedded3 - */ diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_json/models.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_json/models.js deleted file mode 100644 index 7a0edf1c7..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_json/models.js +++ /dev/null @@ -1,272 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Create as $Create } from "/wails/runtime.js"; - -export class Embedded1 { - /** - * Creates a new Embedded1 instance. - * @param {Partial} [$$source = {}] - The source object to create the Embedded1. - */ - constructor($$source = {}) { - if (!("Friends" in $$source)) { - /** - * Friends should be shadowed in Person by a field of lesser depth - * @member - * @type {number} - */ - this["Friends"] = 0; - } - if (!("Vanish" in $$source)) { - /** - * Vanish should be omitted from Person because there is another field with same depth and no tag - * @member - * @type {number} - */ - this["Vanish"] = 0; - } - if (!("StillThere" in $$source)) { - /** - * StillThere should be shadowed in Person by other field with same depth and a json tag - * @member - * @type {string} - */ - this["StillThere"] = ""; - } - if (!("NamingThingsIsHard" in $$source)) { - /** - * NamingThingsIsHard is a law of programming - * @member - * @type {`${boolean}`} - */ - this["NamingThingsIsHard"] = "false"; - } - - Object.assign(this, $$source); - } - - /** - * Creates a new Embedded1 instance from a string or object. - * @param {any} [$$source = {}] - * @returns {Embedded1} - */ - static createFrom($$source = {}) { - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - return new Embedded1(/** @type {Partial} */($$parsedSource)); - } -} - -/** - * @typedef {string} Embedded3 - */ - -/** - * Person represents a person - */ -export class Person { - /** - * Creates a new Person instance. - * @param {Partial} [$$source = {}] - The source object to create the Person. - */ - constructor($$source = {}) { - if (/** @type {any} */(false)) { - /** - * Titles is optional in JSON - * @member - * @type {Title[] | undefined} - */ - this["Titles"] = undefined; - } - if (!("Names" in $$source)) { - /** - * Names has a - * multiline comment - * @member - * @type {string[]} - */ - this["Names"] = []; - } - if (!("Partner" in $$source)) { - /** - * Partner has a custom and complex JSON key - * @member - * @type {Person | null} - */ - this["Partner"] = null; - } - if (!("Friends" in $$source)) { - /** - * @member - * @type {(Person | null)[]} - */ - this["Friends"] = []; - } - if (!("NamingThingsIsHard" in $$source)) { - /** - * NamingThingsIsHard is a law of programming - * @member - * @type {`${boolean}`} - */ - this["NamingThingsIsHard"] = "false"; - } - if (!("StillThere" in $$source)) { - /** - * StillThereButRenamed should shadow in Person the other field with same depth and no json tag - * @member - * @type {Embedded3 | null} - */ - this["StillThere"] = null; - } - if (!("-" in $$source)) { - /** - * StrangeNumber maps to "-" - * @member - * @type {number} - */ - this["-"] = 0; - } - if (!("Embedded3" in $$source)) { - /** - * Embedded3 should appear with key "Embedded3" - * @member - * @type {Embedded3} - */ - this["Embedded3"] = ""; - } - if (!("StrangerNumber" in $$source)) { - /** - * StrangerNumber is serialized as a string - * @member - * @type {`${number}`} - */ - this["StrangerNumber"] = "0"; - } - if (/** @type {any} */(false)) { - /** - * StrangestString is optional and serialized as a JSON string - * @member - * @type {`"${string}"` | undefined} - */ - this["StrangestString"] = undefined; - } - if (/** @type {any} */(false)) { - /** - * StringStrangest is serialized as a JSON string and optional - * @member - * @type {`"${string}"` | undefined} - */ - this["StringStrangest"] = undefined; - } - if (/** @type {any} */(false)) { - /** - * embedded4 should be optional and appear with key "emb4" - * @member - * @type {embedded4 | undefined} - */ - this["emb4"] = undefined; - } - - Object.assign(this, $$source); - } - - /** - * Creates a new Person instance from a string or object. - * @param {any} [$$source = {}] - * @returns {Person} - */ - static createFrom($$source = {}) { - const $$createField0_0 = $$createType0; - const $$createField1_0 = $$createType1; - const $$createField2_0 = $$createType3; - const $$createField3_0 = $$createType4; - const $$createField11_0 = $$createType5; - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - if ("Titles" in $$parsedSource) { - $$parsedSource["Titles"] = $$createField0_0($$parsedSource["Titles"]); - } - if ("Names" in $$parsedSource) { - $$parsedSource["Names"] = $$createField1_0($$parsedSource["Names"]); - } - if ("Partner" in $$parsedSource) { - $$parsedSource["Partner"] = $$createField2_0($$parsedSource["Partner"]); - } - if ("Friends" in $$parsedSource) { - $$parsedSource["Friends"] = $$createField3_0($$parsedSource["Friends"]); - } - if ("emb4" in $$parsedSource) { - $$parsedSource["emb4"] = $$createField11_0($$parsedSource["emb4"]); - } - return new Person(/** @type {Partial} */($$parsedSource)); - } -} - -/** - * Title is a title - * @readonly - * @enum {string} - */ -export const Title = { - /** - * The Go zero value for the underlying type of the enum. - */ - $zero: "", - - /** - * Mister is a title - */ - Mister: "Mr", - Miss: "Miss", - Ms: "Ms", - Mrs: "Mrs", - Dr: "Dr", -}; - -export class embedded4 { - /** - * Creates a new embedded4 instance. - * @param {Partial} [$$source = {}] - The source object to create the embedded4. - */ - constructor($$source = {}) { - if (!("NamingThingsIsHard" in $$source)) { - /** - * NamingThingsIsHard is a law of programming - * @member - * @type {`${boolean}`} - */ - this["NamingThingsIsHard"] = "false"; - } - if (!("Friends" in $$source)) { - /** - * Friends should not be shadowed in Person as embedded4 is not embedded - * from encoding/json's point of view; - * however, it should be shadowed in Embedded1 - * @member - * @type {boolean} - */ - this["Friends"] = false; - } - - Object.assign(this, $$source); - } - - /** - * Creates a new embedded4 instance from a string or object. - * @param {any} [$$source = {}] - * @returns {embedded4} - */ - static createFrom($$source = {}) { - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - return new embedded4(/** @type {Partial} */($$parsedSource)); - } -} - -// Private type creation functions -const $$createType0 = $Create.Array($Create.Any); -const $$createType1 = $Create.Array($Create.Any); -const $$createType2 = Person.createFrom; -const $$createType3 = $Create.Nullable($$createType2); -const $$createType4 = $Create.Array($$createType3); -const $$createType5 = embedded4.createFrom; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_method/greetservice.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_method/greetservice.js deleted file mode 100644 index b15a5517a..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_method/greetservice.js +++ /dev/null @@ -1,40 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * Greet does XYZ - * It has a multiline doc comment - * The comment has even some * / traps!! - * @param {string} str - * @param {$models.Person[]} people - * @param {{"AnotherCount": number, "AnotherOne": $models.Person | null}} $2 - * @param {{ [_ in `${number}`]?: boolean | null }} assoc - * @param {(number | null)[]} $4 - * @param {string[]} other - * @returns {$CancellablePromise<[$models.Person, any, number[]]>} - */ -export function Greet(str, people, $2, assoc, $4, ...other) { - return $Call.ByID(1411160069, str, people, $2, assoc, $4, other).then(/** @type {($result: any) => any} */(($result) => { - $result[0] = $$createType0($result[0]); - $result[2] = $$createType1($result[2]); - return $result; - })); -} - -// Private type creation functions -const $$createType0 = $models.Person.createFrom; -const $$createType1 = $Create.Array($Create.Any); diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_method/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_method/index.js deleted file mode 100644 index fefe6b6ba..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_method/index.js +++ /dev/null @@ -1,12 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; - -export { - Person -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_method/models.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_method/models.js deleted file mode 100644 index 82af81baf..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_method/models.js +++ /dev/null @@ -1,38 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Create as $Create } from "/wails/runtime.js"; - -/** - * Person represents a person - */ -export class Person { - /** - * Creates a new Person instance. - * @param {Partial} [$$source = {}] - The source object to create the Person. - */ - constructor($$source = {}) { - if (!("Name" in $$source)) { - /** - * @member - * @type {string} - */ - this["Name"] = ""; - } - - Object.assign(this, $$source); - } - - /** - * Creates a new Person instance from a string or object. - * @param {any} [$$source = {}] - * @returns {Person} - */ - static createFrom($$source = {}) { - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - return new Person(/** @type {Partial} */($$parsedSource)); - } -} diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/cyclic_imports/greetservice.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/cyclic_imports/greetservice.js deleted file mode 100644 index 29255dd9c..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/cyclic_imports/greetservice.js +++ /dev/null @@ -1,32 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * Make a cycle. - * @returns {$CancellablePromise<[$models.StructA, $models.StructC]>} - */ -export function MakeCycles() { - return $Call.ByID(440020721).then(/** @type {($result: any) => any} */(($result) => { - $result[0] = $$createType0($result[0]); - $result[1] = $$createType1($result[1]); - return $result; - })); -} - -// Private type creation functions -const $$createType0 = $models.StructA.createFrom; -const $$createType1 = $models.StructC.createFrom; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/cyclic_imports/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/cyclic_imports/index.js deleted file mode 100644 index 0ad0efb4e..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/cyclic_imports/index.js +++ /dev/null @@ -1,14 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; - -export { - StructA, - StructC, - StructE -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/cyclic_imports/models.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/cyclic_imports/models.js deleted file mode 100644 index f24f5a2c9..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/cyclic_imports/models.js +++ /dev/null @@ -1,164 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Create as $Create } from "/wails/runtime.js"; - -export class StructA { - /** - * Creates a new StructA instance. - * @param {Partial} [$$source = {}] - The source object to create the StructA. - */ - constructor($$source = {}) { - if (!("B" in $$source)) { - /** - * @member - * @type {structB | null} - */ - this["B"] = null; - } - - Object.assign(this, $$source); - } - - /** - * Creates a new StructA instance from a string or object. - * @param {any} [$$source = {}] - * @returns {StructA} - */ - static createFrom($$source = {}) { - const $$createField0_0 = $$createType1; - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - if ("B" in $$parsedSource) { - $$parsedSource["B"] = $$createField0_0($$parsedSource["B"]); - } - return new StructA(/** @type {Partial} */($$parsedSource)); - } -} - -export class StructC { - /** - * Creates a new StructC instance. - * @param {Partial} [$$source = {}] - The source object to create the StructC. - */ - constructor($$source = {}) { - if (!("D" in $$source)) { - /** - * @member - * @type {structD} - */ - this["D"] = (new structD()); - } - - Object.assign(this, $$source); - } - - /** - * Creates a new StructC instance from a string or object. - * @param {any} [$$source = {}] - * @returns {StructC} - */ - static createFrom($$source = {}) { - const $$createField0_0 = $$createType2; - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - if ("D" in $$parsedSource) { - $$parsedSource["D"] = $$createField0_0($$parsedSource["D"]); - } - return new StructC(/** @type {Partial} */($$parsedSource)); - } -} - -export class StructE { - /** - * Creates a new StructE instance. - * @param {Partial} [$$source = {}] - The source object to create the StructE. - */ - constructor($$source = {}) { - - Object.assign(this, $$source); - } - - /** - * Creates a new StructE instance from a string or object. - * @param {any} [$$source = {}] - * @returns {StructE} - */ - static createFrom($$source = {}) { - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - return new StructE(/** @type {Partial} */($$parsedSource)); - } -} - -export class structB { - /** - * Creates a new structB instance. - * @param {Partial} [$$source = {}] - The source object to create the structB. - */ - constructor($$source = {}) { - if (!("A" in $$source)) { - /** - * @member - * @type {StructA | null} - */ - this["A"] = null; - } - - Object.assign(this, $$source); - } - - /** - * Creates a new structB instance from a string or object. - * @param {any} [$$source = {}] - * @returns {structB} - */ - static createFrom($$source = {}) { - const $$createField0_0 = $$createType4; - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - if ("A" in $$parsedSource) { - $$parsedSource["A"] = $$createField0_0($$parsedSource["A"]); - } - return new structB(/** @type {Partial} */($$parsedSource)); - } -} - -export class structD { - /** - * Creates a new structD instance. - * @param {Partial} [$$source = {}] - The source object to create the structD. - */ - constructor($$source = {}) { - if (!("E" in $$source)) { - /** - * @member - * @type {StructE} - */ - this["E"] = (new StructE()); - } - - Object.assign(this, $$source); - } - - /** - * Creates a new structD instance from a string or object. - * @param {any} [$$source = {}] - * @returns {structD} - */ - static createFrom($$source = {}) { - const $$createField0_0 = $$createType5; - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - if ("E" in $$parsedSource) { - $$parsedSource["E"] = $$createField0_0($$parsedSource["E"]); - } - return new structD(/** @type {Partial} */($$parsedSource)); - } -} - -// Private type creation functions -const $$createType0 = structB.createFrom; -const $$createType1 = $Create.Nullable($$createType0); -const $$createType2 = structD.createFrom; -const $$createType3 = StructA.createFrom; -const $$createType4 = $Create.Nullable($$createType3); -const $$createType5 = StructE.createFrom; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/cyclic_types/greetservice.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/cyclic_types/greetservice.js deleted file mode 100644 index faf090884..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/cyclic_types/greetservice.js +++ /dev/null @@ -1,65 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * Make a cycle. - * @returns {$CancellablePromise<[$models.Cyclic, $models.GenericCyclic<$models.GenericCyclic>]>} - */ -export function MakeCycles() { - return $Call.ByID(440020721).then(/** @type {($result: any) => any} */(($result) => { - $result[0] = $$createType0($result[0]); - $result[1] = $$createType9($result[1]); - return $result; - })); -} - -// Private type creation functions -var $$createType0 = /** @type {(...args: any[]) => any} */(function $$initCreateType0(...args) { - if ($$createType0 === $$initCreateType0) { - $$createType0 = $$createType3; - } - return $$createType0(...args); -}); -const $$createType1 = $Create.Nullable($$createType0); -const $$createType2 = $Create.Map($Create.Any, $$createType1); -const $$createType3 = $Create.Array($$createType2); -var $$createType4 = /** @type {(...args: any[]) => any} */(function $$initCreateType4(...args) { - if ($$createType4 === $$initCreateType4) { - $$createType4 = $$createType8; - } - return $$createType4(...args); -}); -const $$createType5 = $Create.Nullable($$createType4); -const $$createType6 = $Create.Array($Create.Any); -const $$createType7 = $Create.Struct({ - "X": $$createType5, - "Y": $$createType6, -}); -const $$createType8 = $Create.Array($$createType7); -var $$createType9 = /** @type {(...args: any[]) => any} */(function $$initCreateType9(...args) { - if ($$createType9 === $$initCreateType9) { - $$createType9 = $$createType13; - } - return $$createType9(...args); -}); -const $$createType10 = $Create.Nullable($$createType9); -const $$createType11 = $Create.Array($$createType4); -const $$createType12 = $Create.Struct({ - "X": $$createType10, - "Y": $$createType11, -}); -const $$createType13 = $Create.Array($$createType12); diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/cyclic_types/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/cyclic_types/index.js deleted file mode 100644 index 9fc31bf7c..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/cyclic_types/index.js +++ /dev/null @@ -1,23 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; - -import * as $models from "./models.js"; - -/** - * @typedef {$models.Alias} Alias - */ - -/** - * @typedef {$models.Cyclic} Cyclic - */ - -/** - * @template T - * @typedef {$models.GenericCyclic} GenericCyclic - */ diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/cyclic_types/models.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/cyclic_types/models.js deleted file mode 100644 index 824b9e78c..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/cyclic_types/models.js +++ /dev/null @@ -1,20 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Create as $Create } from "/wails/runtime.js"; - -/** - * @typedef {Cyclic | null} Alias - */ - -/** - * @typedef {{ [_ in string]?: Alias }[]} Cyclic - */ - -/** - * @template T - * @typedef {{"X": GenericCyclic | null, "Y": T[]}[]} GenericCyclic - */ diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/index.js deleted file mode 100644 index 972196ce3..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/index.js +++ /dev/null @@ -1,14 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as Service from "./service.js"; -export { - Service -}; - -console.log("Hello everywhere!"); -console.log("Hello everywhere again!"); -console.log("Hello Classes!"); -console.log("Hello JS!"); -console.log("Hello JS Classes!"); diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/internalservice.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/internalservice.js deleted file mode 100644 index fce17fb1d..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/internalservice.js +++ /dev/null @@ -1,24 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * An exported but internal service. - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * @param {$models.InternalModel} $0 - * @returns {$CancellablePromise} - */ -export function Method($0) { - return $Call.ByID(538079117, $0); -} diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/models.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/models.js deleted file mode 100644 index 291a3cecf..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/models.js +++ /dev/null @@ -1,69 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Create as $Create } from "/wails/runtime.js"; - -/** - * An exported but internal model. - */ -export class InternalModel { - /** - * Creates a new InternalModel instance. - * @param {Partial} [$$source = {}] - The source object to create the InternalModel. - */ - constructor($$source = {}) { - if (!("Field" in $$source)) { - /** - * @member - * @type {string} - */ - this["Field"] = ""; - } - - Object.assign(this, $$source); - } - - /** - * Creates a new InternalModel instance from a string or object. - * @param {any} [$$source = {}] - * @returns {InternalModel} - */ - static createFrom($$source = {}) { - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - return new InternalModel(/** @type {Partial} */($$parsedSource)); - } -} - -/** - * An unexported model. - */ -export class unexportedModel { - /** - * Creates a new unexportedModel instance. - * @param {Partial} [$$source = {}] - The source object to create the unexportedModel. - */ - constructor($$source = {}) { - if (!("Field" in $$source)) { - /** - * @member - * @type {string} - */ - this["Field"] = ""; - } - - Object.assign(this, $$source); - } - - /** - * Creates a new unexportedModel instance from a string or object. - * @param {any} [$$source = {}] - * @returns {unexportedModel} - */ - static createFrom($$source = {}) { - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - return new unexportedModel(/** @type {Partial} */($$parsedSource)); - } -} diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/otherpackage/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/otherpackage/index.js deleted file mode 100644 index b7e83cfd4..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/otherpackage/index.js +++ /dev/null @@ -1,7 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -export { - Dummy -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/otherpackage/models.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/otherpackage/models.js deleted file mode 100644 index 274f4eed4..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/otherpackage/models.js +++ /dev/null @@ -1,28 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Create as $Create } from "/wails/runtime.js"; - -export class Dummy { - /** - * Creates a new Dummy instance. - * @param {Partial} [$$source = {}] - The source object to create the Dummy. - */ - constructor($$source = {}) { - - Object.assign(this, $$source); - } - - /** - * Creates a new Dummy instance from a string or object. - * @param {any} [$$source = {}] - * @returns {Dummy} - */ - static createFrom($$source = {}) { - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - return new Dummy(/** @type {Partial} */($$parsedSource)); - } -} diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/otherpackage/test_j.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/otherpackage/test_j.js deleted file mode 100644 index 2166d33b6..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/otherpackage/test_j.js +++ /dev/null @@ -1,3 +0,0 @@ -import { CustomMethod } from "../service.js"; - -CustomMethod("JS"); diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/otherpackage/test_jc.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/otherpackage/test_jc.js deleted file mode 100644 index 338898726..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/otherpackage/test_jc.js +++ /dev/null @@ -1,3 +0,0 @@ -import { CustomMethod } from "../service.js"; - -CustomMethod("JS Classes"); diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/service.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/service.js deleted file mode 100644 index cc7ed89d3..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/service.js +++ /dev/null @@ -1,35 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as otherpackage$0 from "./otherpackage/models.js"; - -/** - * @param {string} $0 - * @returns {$CancellablePromise} - */ -function InternalMethod($0) { - return $Call.ByID(3518775569, $0); -} - -/** - * @param {otherpackage$0.Dummy} $0 - * @returns {$CancellablePromise} - */ -export function VisibleMethod($0) { - return $Call.ByID(474018228, $0); -} - -/** - * @param {string} arg - * @returns {Promise} - */ -export async function CustomMethod(arg) { - await InternalMethod("Hello " + arg + "!"); -} diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/test.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/test.js deleted file mode 100644 index 138385f53..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/test.js +++ /dev/null @@ -1,3 +0,0 @@ -import { CustomMethod } from "./service.js"; - -CustomMethod("everywhere"); diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/test_all.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/test_all.js deleted file mode 100644 index 19d5c2f42..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/test_all.js +++ /dev/null @@ -1,3 +0,0 @@ -import { CustomMethod } from "./service.js"; - -CustomMethod("everywhere again"); diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/test_c.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/test_c.js deleted file mode 100644 index 724e79e12..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/test_c.js +++ /dev/null @@ -1,3 +0,0 @@ -import { CustomMethod } from "./service.js"; - -CustomMethod("Classes"); diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/test_j.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/test_j.js deleted file mode 100644 index b2f9c5edb..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/test_j.js +++ /dev/null @@ -1,3 +0,0 @@ -import { CustomMethod } from "./service.js"; - -CustomMethod("JS"); diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/test_jc.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/test_jc.js deleted file mode 100644 index ddf4920e5..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/test_jc.js +++ /dev/null @@ -1,3 +0,0 @@ -import { CustomMethod } from "./service.js"; - -CustomMethod("JS Classes"); diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/unexportedservice.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/unexportedservice.js deleted file mode 100644 index d3f53be87..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/unexportedservice.js +++ /dev/null @@ -1,24 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * An unexported service. - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * @param {$models.unexportedModel} $0 - * @returns {$CancellablePromise} - */ -export function Method($0) { - return $Call.ByID(37626172, $0); -} diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/embedded_interface/greetservice.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/embedded_interface/greetservice.js deleted file mode 100644 index a178744b9..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/embedded_interface/greetservice.js +++ /dev/null @@ -1,53 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -/** - * Comment 1. - * @returns {$CancellablePromise} - */ -export function Method1() { - return $Call.ByID(841558284); -} - -/** - * Comment 2. - * @returns {$CancellablePromise} - */ -export function Method2() { - return $Call.ByID(891891141); -} - -/** - * Comment 3a. - * Comment 3b. - * @returns {$CancellablePromise} - */ -export function Method3() { - return $Call.ByID(875113522); -} - -/** - * Comment 4. - * @returns {$CancellablePromise} - */ -export function Method4() { - return $Call.ByID(791225427); -} - -/** - * Comment 5. - * @returns {$CancellablePromise} - */ -export function Method5() { - return $Call.ByID(774447808); -} diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/embedded_interface/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/embedded_interface/index.js deleted file mode 100644 index fdf1ff435..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/embedded_interface/index.js +++ /dev/null @@ -1,8 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/enum/greetservice.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/enum/greetservice.js deleted file mode 100644 index ed402a8b2..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/enum/greetservice.js +++ /dev/null @@ -1,41 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * Greet does XYZ - * @param {string} name - * @param {$models.Title} title - * @returns {$CancellablePromise} - */ -export function Greet(name, title) { - return $Call.ByID(1411160069, name, title); -} - -/** - * NewPerson creates a new person - * @param {string} name - * @returns {$CancellablePromise<$models.Person | null>} - */ -export function NewPerson(name) { - return $Call.ByID(1661412647, name).then(/** @type {($result: any) => any} */(($result) => { - return $$createType1($result); - })); -} - -// Private type creation functions -const $$createType0 = $models.Person.createFrom; -const $$createType1 = $Create.Nullable($$createType0); diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/enum/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/enum/index.js deleted file mode 100644 index d5d66d4cb..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/enum/index.js +++ /dev/null @@ -1,14 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; - -export { - Age, - Person, - Title -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/enum/models.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/enum/models.js deleted file mode 100644 index 2c5df9ee7..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/enum/models.js +++ /dev/null @@ -1,98 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Create as $Create } from "/wails/runtime.js"; - -/** - * Age is an integer with some predefined values - * @typedef {number} Age - */ - -/** - * Predefined constants for type Age. - * @namespace - */ -export const Age = { - NewBorn: 0, - Teenager: 12, - YoungAdult: 18, - - /** - * Oh no, some grey hair! - */ - MiddleAged: 50, - - /** - * Unbelievable! - */ - Mathusalem: 1000, -}; - -/** - * Person represents a person - */ -export class Person { - /** - * Creates a new Person instance. - * @param {Partial} [$$source = {}] - The source object to create the Person. - */ - constructor($$source = {}) { - if (!("Title" in $$source)) { - /** - * @member - * @type {Title} - */ - this["Title"] = Title.$zero; - } - if (!("Name" in $$source)) { - /** - * @member - * @type {string} - */ - this["Name"] = ""; - } - if (!("Age" in $$source)) { - /** - * @member - * @type {Age} - */ - this["Age"] = 0; - } - - Object.assign(this, $$source); - } - - /** - * Creates a new Person instance from a string or object. - * @param {any} [$$source = {}] - * @returns {Person} - */ - static createFrom($$source = {}) { - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - return new Person(/** @type {Partial} */($$parsedSource)); - } -} - -/** - * Title is a title - * @readonly - * @enum {string} - */ -export const Title = { - /** - * The Go zero value for the underlying type of the enum. - */ - $zero: "", - - /** - * Mister is a title - */ - Mister: "Mr", - Miss: "Miss", - Ms: "Ms", - Mrs: "Mrs", - Dr: "Dr", -}; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_from_imported_package/greetservice.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_from_imported_package/greetservice.js deleted file mode 100644 index fbc2294e9..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_from_imported_package/greetservice.js +++ /dev/null @@ -1,26 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as services$0 from "./services/models.js"; - -/** - * Greet does XYZ - * @param {string} name - * @param {services$0.Title} title - * @returns {$CancellablePromise} - */ -export function Greet(name, title) { - return $Call.ByID(1411160069, name, title); -} diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_from_imported_package/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_from_imported_package/index.js deleted file mode 100644 index fdf1ff435..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_from_imported_package/index.js +++ /dev/null @@ -1,8 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_from_imported_package/services/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_from_imported_package/services/index.js deleted file mode 100644 index 089a8b685..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_from_imported_package/services/index.js +++ /dev/null @@ -1,7 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -export { - Title -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_from_imported_package/services/models.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_from_imported_package/services/models.js deleted file mode 100644 index 65ebfa2f7..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_from_imported_package/services/models.js +++ /dev/null @@ -1,27 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Create as $Create } from "/wails/runtime.js"; - -/** - * @readonly - * @enum {string} - */ -export const Title = { - /** - * The Go zero value for the underlying type of the enum. - */ - $zero: "", - - /** - * Mister is a title - */ - Mister: "Mr", - Miss: "Miss", - Ms: "Ms", - Mrs: "Mrs", - Dr: "Dr", -}; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_map_keys/enummapservice.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_map_keys/enummapservice.js deleted file mode 100644 index 9afec2c30..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_map_keys/enummapservice.js +++ /dev/null @@ -1,87 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * EnumMapService tests various enum map key scenarios - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * GetColorCodes returns a map with uint8 enum keys - * @returns {$CancellablePromise<{ [_ in $models.Color]?: string }>} - */ -export function GetColorCodes() { - return $Call.ByID(2794981443).then(/** @type {($result: any) => any} */(($result) => { - return $$createType0($result); - })); -} - -/** - * GetNestedEnumMap returns a map with enum keys and complex values - * @returns {$CancellablePromise<{ [_ in $models.Status]?: { [_ in $models.Priority]?: string } }>} - */ -export function GetNestedEnumMap() { - return $Call.ByID(3603489560).then(/** @type {($result: any) => any} */(($result) => { - return $$createType2($result); - })); -} - -/** - * GetOptionalEnumMap returns a map with enum keys to optional values - * @returns {$CancellablePromise<{ [_ in $models.Status]?: string | null }>} - */ -export function GetOptionalEnumMap() { - return $Call.ByID(1871606385).then(/** @type {($result: any) => any} */(($result) => { - return $$createType3($result); - })); -} - -/** - * GetPersonsByStatus returns a map with enum keys to struct values - * @returns {$CancellablePromise<{ [_ in $models.Status]?: $models.Person[] }>} - */ -export function GetPersonsByStatus() { - return $Call.ByID(2189502217).then(/** @type {($result: any) => any} */(($result) => { - return $$createType6($result); - })); -} - -/** - * GetPriorityWeights returns a map with integer enum keys - * @returns {$CancellablePromise<{ [_ in $models.Priority]?: number }>} - */ -export function GetPriorityWeights() { - return $Call.ByID(1542216941).then(/** @type {($result: any) => any} */(($result) => { - return $$createType7($result); - })); -} - -/** - * GetStatusMessages returns a map with string enum keys - * @returns {$CancellablePromise<{ [_ in $models.Status]?: string }>} - */ -export function GetStatusMessages() { - return $Call.ByID(1788640810).then(/** @type {($result: any) => any} */(($result) => { - return $$createType8($result); - })); -} - -// Private type creation functions -const $$createType0 = $Create.Map($Create.Any, $Create.Any); -const $$createType1 = $Create.Map($Create.Any, $Create.Any); -const $$createType2 = $Create.Map($Create.Any, $$createType1); -const $$createType3 = $Create.Map($Create.Any, $Create.Any); -const $$createType4 = $models.Person.createFrom; -const $$createType5 = $Create.Array($$createType4); -const $$createType6 = $Create.Map($Create.Any, $$createType5); -const $$createType7 = $Create.Map($Create.Any, $Create.Any); -const $$createType8 = $Create.Map($Create.Any, $Create.Any); diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_map_keys/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_map_keys/index.js deleted file mode 100644 index 21da516bd..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_map_keys/index.js +++ /dev/null @@ -1,15 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as EnumMapService from "./enummapservice.js"; -export { - EnumMapService -}; - -export { - Color, - Person, - Priority, - Status -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_map_keys/models.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_map_keys/models.js deleted file mode 100644 index f2c58312c..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_map_keys/models.js +++ /dev/null @@ -1,94 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Create as $Create } from "/wails/runtime.js"; - -/** - * Color represents color values - * @readonly - * @enum {number} - */ -export const Color = { - /** - * The Go zero value for the underlying type of the enum. - */ - $zero: 0, - - Red: 1, - Green: 2, - Blue: 3, -}; - -/** - * Person represents a person with status - */ -export class Person { - /** - * Creates a new Person instance. - * @param {Partial} [$$source = {}] - The source object to create the Person. - */ - constructor($$source = {}) { - if (!("Name" in $$source)) { - /** - * @member - * @type {string} - */ - this["Name"] = ""; - } - if (!("Status" in $$source)) { - /** - * @member - * @type {Status} - */ - this["Status"] = Status.$zero; - } - - Object.assign(this, $$source); - } - - /** - * Creates a new Person instance from a string or object. - * @param {any} [$$source = {}] - * @returns {Person} - */ - static createFrom($$source = {}) { - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - return new Person(/** @type {Partial} */($$parsedSource)); - } -} - -/** - * Priority represents priority levels - * @readonly - * @enum {number} - */ -export const Priority = { - /** - * The Go zero value for the underlying type of the enum. - */ - $zero: 0, - - PriorityLow: 1, - PriorityMedium: 2, - PriorityHigh: 3, -}; - -/** - * Status represents different status values - * @readonly - * @enum {string} - */ -export const Status = { - /** - * The Go zero value for the underlying type of the enum. - */ - $zero: "", - - StatusPending: "pending", - StatusRunning: "running", - StatusCompleted: "completed", - StatusFailed: "failed", -}; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/events_only/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/events_only/index.js deleted file mode 100644 index ebcbd137f..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/events_only/index.js +++ /dev/null @@ -1,7 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -export { - SomeClass -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/events_only/models.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/events_only/models.js deleted file mode 100644 index 498ff20b5..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/events_only/models.js +++ /dev/null @@ -1,56 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Create as $Create } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as nobindingshere$0 from "../no_bindings_here/models.js"; - -/** - * SomeClass renders as a TS class. - */ -export class SomeClass { - /** - * Creates a new SomeClass instance. - * @param {Partial} [$$source = {}] - The source object to create the SomeClass. - */ - constructor($$source = {}) { - if (!("Field" in $$source)) { - /** - * @member - * @type {string} - */ - this["Field"] = ""; - } - if (!("Meadow" in $$source)) { - /** - * @member - * @type {nobindingshere$0.HowDifferent} - */ - this["Meadow"] = (new nobindingshere$0.HowDifferent()); - } - - Object.assign(this, $$source); - } - - /** - * Creates a new SomeClass instance from a string or object. - * @param {any} [$$source = {}] - * @returns {SomeClass} - */ - static createFrom($$source = {}) { - const $$createField1_0 = $$createType0; - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - if ("Meadow" in $$parsedSource) { - $$parsedSource["Meadow"] = $$createField1_0($$parsedSource["Meadow"]); - } - return new SomeClass(/** @type {Partial} */($$parsedSource)); - } -} - -// Private type creation functions -const $$createType0 = nobindingshere$0.HowDifferent.createFrom($Create.Any); diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_imported_package/greetservice.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_imported_package/greetservice.js deleted file mode 100644 index 50737a34b..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_imported_package/greetservice.js +++ /dev/null @@ -1,40 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * Greet does XYZ - * @param {string} name - * @returns {$CancellablePromise} - */ -export function Greet(name) { - return $Call.ByID(1411160069, name); -} - -/** - * NewPerson creates a new person - * @param {string} name - * @returns {$CancellablePromise<$models.Person | null>} - */ -export function NewPerson(name) { - return $Call.ByID(1661412647, name).then(/** @type {($result: any) => any} */(($result) => { - return $$createType1($result); - })); -} - -// Private type creation functions -const $$createType0 = $models.Person.createFrom; -const $$createType1 = $Create.Nullable($$createType0); diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_imported_package/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_imported_package/index.js deleted file mode 100644 index fefe6b6ba..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_imported_package/index.js +++ /dev/null @@ -1,12 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; - -export { - Person -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_imported_package/models.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_imported_package/models.js deleted file mode 100644 index 0ab295133..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_imported_package/models.js +++ /dev/null @@ -1,57 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Create as $Create } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as services$0 from "./services/models.js"; - -/** - * Person is a person - */ -export class Person { - /** - * Creates a new Person instance. - * @param {Partial} [$$source = {}] - The source object to create the Person. - */ - constructor($$source = {}) { - if (!("Name" in $$source)) { - /** - * @member - * @type {string} - */ - this["Name"] = ""; - } - if (!("Address" in $$source)) { - /** - * @member - * @type {services$0.Address | null} - */ - this["Address"] = null; - } - - Object.assign(this, $$source); - } - - /** - * Creates a new Person instance from a string or object. - * @param {any} [$$source = {}] - * @returns {Person} - */ - static createFrom($$source = {}) { - const $$createField1_0 = $$createType1; - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - if ("Address" in $$parsedSource) { - $$parsedSource["Address"] = $$createField1_0($$parsedSource["Address"]); - } - return new Person(/** @type {Partial} */($$parsedSource)); - } -} - -// Private type creation functions -const $$createType0 = services$0.Address.createFrom; -const $$createType1 = $Create.Nullable($$createType0); diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_imported_package/services/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_imported_package/services/index.js deleted file mode 100644 index ed65b6d15..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_imported_package/services/index.js +++ /dev/null @@ -1,12 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as OtherService from "./otherservice.js"; -export { - OtherService -}; - -export { - Address -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_imported_package/services/models.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_imported_package/services/models.js deleted file mode 100644 index 24a5de807..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_imported_package/services/models.js +++ /dev/null @@ -1,49 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Create as $Create } from "/wails/runtime.js"; - -export class Address { - /** - * Creates a new Address instance. - * @param {Partial
                    } [$$source = {}] - The source object to create the Address. - */ - constructor($$source = {}) { - if (!("Street" in $$source)) { - /** - * @member - * @type {string} - */ - this["Street"] = ""; - } - if (!("State" in $$source)) { - /** - * @member - * @type {string} - */ - this["State"] = ""; - } - if (!("Country" in $$source)) { - /** - * @member - * @type {string} - */ - this["Country"] = ""; - } - - Object.assign(this, $$source); - } - - /** - * Creates a new Address instance from a string or object. - * @param {any} [$$source = {}] - * @returns {Address} - */ - static createFrom($$source = {}) { - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - return new Address(/** @type {Partial
                    } */($$parsedSource)); - } -} diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_imported_package/services/otherservice.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_imported_package/services/otherservice.js deleted file mode 100644 index 1866aca09..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_imported_package/services/otherservice.js +++ /dev/null @@ -1,31 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * OtherService is a struct - * that does things - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * Yay does this and that - * @returns {$CancellablePromise<$models.Address | null>} - */ -export function Yay() { - return $Call.ByID(2007737399).then(/** @type {($result: any) => any} */(($result) => { - return $$createType1($result); - })); -} - -// Private type creation functions -const $$createType0 = $models.Address.createFrom; -const $$createType1 = $Create.Nullable($$createType0); diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_nested_imported_package/greetservice.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_nested_imported_package/greetservice.js deleted file mode 100644 index 50737a34b..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_nested_imported_package/greetservice.js +++ /dev/null @@ -1,40 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * Greet does XYZ - * @param {string} name - * @returns {$CancellablePromise} - */ -export function Greet(name) { - return $Call.ByID(1411160069, name); -} - -/** - * NewPerson creates a new person - * @param {string} name - * @returns {$CancellablePromise<$models.Person | null>} - */ -export function NewPerson(name) { - return $Call.ByID(1661412647, name).then(/** @type {($result: any) => any} */(($result) => { - return $$createType1($result); - })); -} - -// Private type creation functions -const $$createType0 = $models.Person.createFrom; -const $$createType1 = $Create.Nullable($$createType0); diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_nested_imported_package/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_nested_imported_package/index.js deleted file mode 100644 index fefe6b6ba..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_nested_imported_package/index.js +++ /dev/null @@ -1,12 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; - -export { - Person -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_nested_imported_package/models.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_nested_imported_package/models.js deleted file mode 100644 index 29a95e11e..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_nested_imported_package/models.js +++ /dev/null @@ -1,54 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Create as $Create } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as other$0 from "./services/other/models.js"; - -export class Person { - /** - * Creates a new Person instance. - * @param {Partial} [$$source = {}] - The source object to create the Person. - */ - constructor($$source = {}) { - if (!("Name" in $$source)) { - /** - * @member - * @type {string} - */ - this["Name"] = ""; - } - if (!("Address" in $$source)) { - /** - * @member - * @type {other$0.Address | null} - */ - this["Address"] = null; - } - - Object.assign(this, $$source); - } - - /** - * Creates a new Person instance from a string or object. - * @param {any} [$$source = {}] - * @returns {Person} - */ - static createFrom($$source = {}) { - const $$createField1_0 = $$createType1; - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - if ("Address" in $$parsedSource) { - $$parsedSource["Address"] = $$createField1_0($$parsedSource["Address"]); - } - return new Person(/** @type {Partial} */($$parsedSource)); - } -} - -// Private type creation functions -const $$createType0 = other$0.Address.createFrom; -const $$createType1 = $Create.Nullable($$createType0); diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_nested_imported_package/services/other/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_nested_imported_package/services/other/index.js deleted file mode 100644 index ed65b6d15..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_nested_imported_package/services/other/index.js +++ /dev/null @@ -1,12 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as OtherService from "./otherservice.js"; -export { - OtherService -}; - -export { - Address -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_nested_imported_package/services/other/models.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_nested_imported_package/services/other/models.js deleted file mode 100644 index 24a5de807..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_nested_imported_package/services/other/models.js +++ /dev/null @@ -1,49 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Create as $Create } from "/wails/runtime.js"; - -export class Address { - /** - * Creates a new Address instance. - * @param {Partial
                    } [$$source = {}] - The source object to create the Address. - */ - constructor($$source = {}) { - if (!("Street" in $$source)) { - /** - * @member - * @type {string} - */ - this["Street"] = ""; - } - if (!("State" in $$source)) { - /** - * @member - * @type {string} - */ - this["State"] = ""; - } - if (!("Country" in $$source)) { - /** - * @member - * @type {string} - */ - this["Country"] = ""; - } - - Object.assign(this, $$source); - } - - /** - * Creates a new Address instance from a string or object. - * @param {any} [$$source = {}] - * @returns {Address} - */ - static createFrom($$source = {}) { - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - return new Address(/** @type {Partial
                    } */($$parsedSource)); - } -} diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_nested_imported_package/services/other/otherservice.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_nested_imported_package/services/other/otherservice.js deleted file mode 100644 index 293a2f0bb..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_nested_imported_package/services/other/otherservice.js +++ /dev/null @@ -1,31 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * OtherService is a struct - * that does things - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * Yay does this and that - * @returns {$CancellablePromise<$models.Address | null>} - */ -export function Yay() { - return $Call.ByID(2447353446).then(/** @type {($result: any) => any} */(($result) => { - return $$createType1($result); - })); -} - -// Private type creation functions -const $$createType0 = $models.Address.createFrom; -const $$createType1 = $Create.Nullable($$createType0); diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_multiple_files/greetservice.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_multiple_files/greetservice.js deleted file mode 100644 index e50a4a6ab..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_multiple_files/greetservice.js +++ /dev/null @@ -1,15 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -/** - * @param {string} name - * @returns {$CancellablePromise} - */ -export function Greet(name) { - return $Call.ByID(1411160069, name); -} diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_multiple_files/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_multiple_files/index.js deleted file mode 100644 index fdf1ff435..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_multiple_files/index.js +++ /dev/null @@ -1,8 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single/greetservice.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single/greetservice.js deleted file mode 100644 index 9dfe48511..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single/greetservice.js +++ /dev/null @@ -1,21 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -/** - * Greet someone - * @param {string} name - * @returns {$CancellablePromise} - */ -export function Greet(name) { - return $Call.ByID(1411160069, name); -} diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single/index.js deleted file mode 100644 index fdf1ff435..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single/index.js +++ /dev/null @@ -1,8 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single_context/greetservice.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single_context/greetservice.js deleted file mode 100644 index 1bc7cb45b..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single_context/greetservice.js +++ /dev/null @@ -1,30 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -/** - * Greet someone - * @param {string} name - * @returns {$CancellablePromise} - */ -export function Greet(name) { - return $Call.ByID(1411160069, name); -} - -/** - * Greet someone - * @param {string} name - * @returns {$CancellablePromise} - */ -export function GreetWithContext(name) { - return $Call.ByID(1310150960, name); -} diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single_context/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single_context/index.js deleted file mode 100644 index fdf1ff435..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single_context/index.js +++ /dev/null @@ -1,8 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single_internal/greetservice.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single_internal/greetservice.js deleted file mode 100644 index 9dfe48511..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single_internal/greetservice.js +++ /dev/null @@ -1,21 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -/** - * Greet someone - * @param {string} name - * @returns {$CancellablePromise} - */ -export function Greet(name) { - return $Call.ByID(1411160069, name); -} diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single_internal/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single_internal/index.js deleted file mode 100644 index fdf1ff435..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single_internal/index.js +++ /dev/null @@ -1,8 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys/index.js deleted file mode 100644 index 3e1e0ecdb..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys/index.js +++ /dev/null @@ -1,105 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as Service from "./service.js"; -export { - Service -}; - -export { - Maps -} from "./models.js"; - -import * as $models from "./models.js"; - -/** - * @template S - * @typedef {$models.BasicCstrAlias} BasicCstrAlias - */ - -/** - * @template R - * @typedef {$models.ComparableCstrAlias} ComparableCstrAlias - */ - -/** - * @typedef {$models.EmbeddedCustomInterface} EmbeddedCustomInterface - */ - -/** - * @typedef {$models.EmbeddedOriginalInterface} EmbeddedOriginalInterface - */ - -/** - * @typedef {$models.EmbeddedPointer} EmbeddedPointer - */ - -/** - * @typedef {$models.EmbeddedPointerPtr} EmbeddedPointerPtr - */ - -/** - * @typedef {$models.EmbeddedValue} EmbeddedValue - */ - -/** - * @typedef {$models.EmbeddedValuePtr} EmbeddedValuePtr - */ - -/** - * @template U - * @typedef {$models.GoodTildeCstrAlias} GoodTildeCstrAlias - */ - -/** - * @typedef {$models.IntAlias} IntAlias - */ - -/** - * @typedef {$models.IntType} IntType - */ - -/** - * @template Y - * @typedef {$models.InterfaceCstrAlias} InterfaceCstrAlias - */ - -/** - * @template X - * @typedef {$models.MixedCstrAlias} MixedCstrAlias - */ - -/** - * @template V - * @typedef {$models.NonBasicCstrAlias} NonBasicCstrAlias - */ - -/** - * @template W - * @typedef {$models.PointableCstrAlias} PointableCstrAlias - */ - -/** - * @typedef {$models.PointerAlias} PointerAlias - */ - -/** - * @typedef {$models.PointerTextMarshaler} PointerTextMarshaler - */ - -/** - * @typedef {$models.StringAlias} StringAlias - */ - -/** - * @typedef {$models.StringType} StringType - */ - -/** - * @typedef {$models.ValueAlias} ValueAlias - */ - -/** - * @typedef {$models.ValueTextMarshaler} ValueTextMarshaler - */ diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys/models.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys/models.js deleted file mode 100644 index 61bc3d532..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys/models.js +++ /dev/null @@ -1,1965 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Create as $Create } from "/wails/runtime.js"; - -/** - * @template S - * @typedef {S} BasicCstrAlias - */ - -/** - * @template R - * @typedef {R} ComparableCstrAlias - */ - -/** - * @typedef {string} EmbeddedCustomInterface - */ - -/** - * @typedef {string} EmbeddedOriginalInterface - */ - -/** - * @typedef {string} EmbeddedPointer - */ - -/** - * @typedef {string} EmbeddedPointerPtr - */ - -/** - * @typedef {string} EmbeddedValue - */ - -/** - * @typedef {string} EmbeddedValuePtr - */ - -/** - * @template U - * @typedef {U} GoodTildeCstrAlias - */ - -/** - * @typedef {number} IntAlias - */ - -/** - * @typedef {number} IntType - */ - -/** - * @template Y - * @typedef {Y} InterfaceCstrAlias - */ - -/** - * @template R,S,T,U,V,W,X,Y,Z - */ -export class Maps { - /** - * Creates a new Maps instance. - * @param {Partial>} [$$source = {}] - The source object to create the Maps. - */ - constructor($$source = {}) { - if (!("Bool" in $$source)) { - /** - * Reject - * @member - * @type {{ [_ in string]?: number }} - */ - this["Bool"] = {}; - } - if (!("Int" in $$source)) { - /** - * Accept - * @member - * @type {{ [_ in `${number}`]?: number }} - */ - this["Int"] = {}; - } - if (!("Uint" in $$source)) { - /** - * Accept - * @member - * @type {{ [_ in `${number}`]?: number }} - */ - this["Uint"] = {}; - } - if (!("Float" in $$source)) { - /** - * Reject - * @member - * @type {{ [_ in string]?: number }} - */ - this["Float"] = {}; - } - if (!("Complex" in $$source)) { - /** - * Reject - * @member - * @type {{ [_ in string]?: number }} - */ - this["Complex"] = {}; - } - if (!("Byte" in $$source)) { - /** - * Accept - * @member - * @type {{ [_ in `${number}`]?: number }} - */ - this["Byte"] = {}; - } - if (!("Rune" in $$source)) { - /** - * Accept - * @member - * @type {{ [_ in `${number}`]?: number }} - */ - this["Rune"] = {}; - } - if (!("String" in $$source)) { - /** - * Accept - * @member - * @type {{ [_ in string]?: number }} - */ - this["String"] = {}; - } - if (!("IntPtr" in $$source)) { - /** - * Reject - * @member - * @type {{ [_ in string]?: number }} - */ - this["IntPtr"] = {}; - } - if (!("UintPtr" in $$source)) { - /** - * Reject - * @member - * @type {{ [_ in string]?: number }} - */ - this["UintPtr"] = {}; - } - if (!("FloatPtr" in $$source)) { - /** - * Reject - * @member - * @type {{ [_ in string]?: number }} - */ - this["FloatPtr"] = {}; - } - if (!("ComplexPtr" in $$source)) { - /** - * Reject - * @member - * @type {{ [_ in string]?: number }} - */ - this["ComplexPtr"] = {}; - } - if (!("StringPtr" in $$source)) { - /** - * Reject - * @member - * @type {{ [_ in string]?: number }} - */ - this["StringPtr"] = {}; - } - if (!("NTM" in $$source)) { - /** - * Reject - * @member - * @type {{ [_ in string]?: number }} - */ - this["NTM"] = {}; - } - if (!("NTMPtr" in $$source)) { - /** - * Reject - * @member - * @type {{ [_ in string]?: number }} - */ - this["NTMPtr"] = {}; - } - if (!("VTM" in $$source)) { - /** - * Accept - * @member - * @type {{ [_ in ValueTextMarshaler]?: number }} - */ - this["VTM"] = {}; - } - if (!("VTMPtr" in $$source)) { - /** - * Accept - * @member - * @type {{ [_ in ValueTextMarshaler]?: number }} - */ - this["VTMPtr"] = {}; - } - if (!("PTM" in $$source)) { - /** - * Reject - * @member - * @type {{ [_ in string]?: number }} - */ - this["PTM"] = {}; - } - if (!("PTMPtr" in $$source)) { - /** - * Accept - * @member - * @type {{ [_ in PointerTextMarshaler]?: number }} - */ - this["PTMPtr"] = {}; - } - if (!("JTM" in $$source)) { - /** - * Accept, hide - * @member - * @type {{ [_ in string]?: number }} - */ - this["JTM"] = {}; - } - if (!("JTMPtr" in $$source)) { - /** - * Accept, hide - * @member - * @type {{ [_ in string]?: number }} - */ - this["JTMPtr"] = {}; - } - if (!("A" in $$source)) { - /** - * Reject - * @member - * @type {{ [_ in string]?: number }} - */ - this["A"] = {}; - } - if (!("APtr" in $$source)) { - /** - * Reject - * @member - * @type {{ [_ in string]?: number }} - */ - this["APtr"] = {}; - } - if (!("TM" in $$source)) { - /** - * Accept, hide - * @member - * @type {{ [_ in string]?: number }} - */ - this["TM"] = {}; - } - if (!("TMPtr" in $$source)) { - /** - * Reject - * @member - * @type {{ [_ in string]?: number }} - */ - this["TMPtr"] = {}; - } - if (!("CI" in $$source)) { - /** - * Accept, hide - * @member - * @type {{ [_ in string]?: number }} - */ - this["CI"] = {}; - } - if (!("CIPtr" in $$source)) { - /** - * Reject - * @member - * @type {{ [_ in string]?: number }} - */ - this["CIPtr"] = {}; - } - if (!("EI" in $$source)) { - /** - * Accept, hide - * @member - * @type {{ [_ in string]?: number }} - */ - this["EI"] = {}; - } - if (!("EIPtr" in $$source)) { - /** - * Reject - * @member - * @type {{ [_ in string]?: number }} - */ - this["EIPtr"] = {}; - } - if (!("EV" in $$source)) { - /** - * Accept - * @member - * @type {{ [_ in EmbeddedValue]?: number }} - */ - this["EV"] = {}; - } - if (!("EVPtr" in $$source)) { - /** - * Accept - * @member - * @type {{ [_ in EmbeddedValue]?: number }} - */ - this["EVPtr"] = {}; - } - if (!("EVP" in $$source)) { - /** - * Accept - * @member - * @type {{ [_ in EmbeddedValuePtr]?: number }} - */ - this["EVP"] = {}; - } - if (!("EVPPtr" in $$source)) { - /** - * Accept - * @member - * @type {{ [_ in EmbeddedValuePtr]?: number }} - */ - this["EVPPtr"] = {}; - } - if (!("EP" in $$source)) { - /** - * Reject - * @member - * @type {{ [_ in string]?: number }} - */ - this["EP"] = {}; - } - if (!("EPPtr" in $$source)) { - /** - * Accept - * @member - * @type {{ [_ in EmbeddedPointer]?: number }} - */ - this["EPPtr"] = {}; - } - if (!("EPP" in $$source)) { - /** - * Accept - * @member - * @type {{ [_ in EmbeddedPointerPtr]?: number }} - */ - this["EPP"] = {}; - } - if (!("EPPPtr" in $$source)) { - /** - * Accept - * @member - * @type {{ [_ in EmbeddedPointerPtr]?: number }} - */ - this["EPPPtr"] = {}; - } - if (!("ECI" in $$source)) { - /** - * Accept - * @member - * @type {{ [_ in EmbeddedCustomInterface]?: number }} - */ - this["ECI"] = {}; - } - if (!("ECIPtr" in $$source)) { - /** - * Accept - * @member - * @type {{ [_ in EmbeddedCustomInterface]?: number }} - */ - this["ECIPtr"] = {}; - } - if (!("EOI" in $$source)) { - /** - * Accept - * @member - * @type {{ [_ in EmbeddedOriginalInterface]?: number }} - */ - this["EOI"] = {}; - } - if (!("EOIPtr" in $$source)) { - /** - * Accept - * @member - * @type {{ [_ in EmbeddedOriginalInterface]?: number }} - */ - this["EOIPtr"] = {}; - } - if (!("WT" in $$source)) { - /** - * Reject - * @member - * @type {{ [_ in string]?: number }} - */ - this["WT"] = {}; - } - if (!("WA" in $$source)) { - /** - * Reject - * @member - * @type {{ [_ in string]?: number }} - */ - this["WA"] = {}; - } - if (!("ST" in $$source)) { - /** - * Accept - * @member - * @type {{ [_ in StringType]?: number }} - */ - this["ST"] = {}; - } - if (!("SA" in $$source)) { - /** - * Accept - * @member - * @type {{ [_ in StringAlias]?: number }} - */ - this["SA"] = {}; - } - if (!("IntT" in $$source)) { - /** - * Accept - * @member - * @type {{ [_ in IntType]?: number }} - */ - this["IntT"] = {}; - } - if (!("IntA" in $$source)) { - /** - * Accept - * @member - * @type {{ [_ in IntAlias]?: number }} - */ - this["IntA"] = {}; - } - if (!("VT" in $$source)) { - /** - * Reject - * @member - * @type {{ [_ in string]?: number }} - */ - this["VT"] = {}; - } - if (!("VTPtr" in $$source)) { - /** - * Reject - * @member - * @type {{ [_ in string]?: number }} - */ - this["VTPtr"] = {}; - } - if (!("VPT" in $$source)) { - /** - * Reject - * @member - * @type {{ [_ in string]?: number }} - */ - this["VPT"] = {}; - } - if (!("VPTPtr" in $$source)) { - /** - * Reject - * @member - * @type {{ [_ in string]?: number }} - */ - this["VPTPtr"] = {}; - } - if (!("VA" in $$source)) { - /** - * Accept - * @member - * @type {{ [_ in ValueAlias]?: number }} - */ - this["VA"] = {}; - } - if (!("VAPtr" in $$source)) { - /** - * Accept - * @member - * @type {{ [_ in ValueAlias]?: number }} - */ - this["VAPtr"] = {}; - } - if (!("VPA" in $$source)) { - /** - * Accept, hide - * @member - * @type {{ [_ in string]?: number }} - */ - this["VPA"] = {}; - } - if (!("VPAPtr" in $$source)) { - /** - * Reject - * @member - * @type {{ [_ in string]?: number }} - */ - this["VPAPtr"] = {}; - } - if (!("PT" in $$source)) { - /** - * Reject - * @member - * @type {{ [_ in string]?: number }} - */ - this["PT"] = {}; - } - if (!("PTPtr" in $$source)) { - /** - * Reject - * @member - * @type {{ [_ in string]?: number }} - */ - this["PTPtr"] = {}; - } - if (!("PPT" in $$source)) { - /** - * Reject - * @member - * @type {{ [_ in string]?: number }} - */ - this["PPT"] = {}; - } - if (!("PPTPtr" in $$source)) { - /** - * Reject - * @member - * @type {{ [_ in string]?: number }} - */ - this["PPTPtr"] = {}; - } - if (!("PA" in $$source)) { - /** - * Reject - * @member - * @type {{ [_ in string]?: number }} - */ - this["PA"] = {}; - } - if (!("PAPtr" in $$source)) { - /** - * Accept - * @member - * @type {{ [_ in PointerAlias]?: number }} - */ - this["PAPtr"] = {}; - } - if (!("PPA" in $$source)) { - /** - * Accept, hide - * @member - * @type {{ [_ in string]?: number }} - */ - this["PPA"] = {}; - } - if (!("PPAPtr" in $$source)) { - /** - * Reject - * @member - * @type {{ [_ in string]?: number }} - */ - this["PPAPtr"] = {}; - } - if (!("IT" in $$source)) { - /** - * Accept, hide - * @member - * @type {{ [_ in string]?: number }} - */ - this["IT"] = {}; - } - if (!("ITPtr" in $$source)) { - /** - * Reject - * @member - * @type {{ [_ in string]?: number }} - */ - this["ITPtr"] = {}; - } - if (!("IPT" in $$source)) { - /** - * Reject - * @member - * @type {{ [_ in string]?: number }} - */ - this["IPT"] = {}; - } - if (!("IPTPtr" in $$source)) { - /** - * Reject - * @member - * @type {{ [_ in string]?: number }} - */ - this["IPTPtr"] = {}; - } - if (!("IA" in $$source)) { - /** - * Accept, hide - * @member - * @type {{ [_ in string]?: number }} - */ - this["IA"] = {}; - } - if (!("IAPtr" in $$source)) { - /** - * Reject - * @member - * @type {{ [_ in string]?: number }} - */ - this["IAPtr"] = {}; - } - if (!("IPA" in $$source)) { - /** - * Reject - * @member - * @type {{ [_ in string]?: number }} - */ - this["IPA"] = {}; - } - if (!("IPAPtr" in $$source)) { - /** - * Reject - * @member - * @type {{ [_ in string]?: number }} - */ - this["IPAPtr"] = {}; - } - if (!("TPR" in $$source)) { - /** - * Soft reject - * @member - * @type {{ [_ in string]?: number }} - */ - this["TPR"] = {}; - } - if (!("TPRPtr" in $$source)) { - /** - * Soft reject - * @member - * @type {{ [_ in string]?: number }} - */ - this["TPRPtr"] = {}; - } - if (!("TPS" in $$source)) { - /** - * Accept, hide - * @member - * @type {{ [_ in string]?: number }} - */ - this["TPS"] = {}; - } - if (!("TPSPtr" in $$source)) { - /** - * Soft reject - * @member - * @type {{ [_ in string]?: number }} - */ - this["TPSPtr"] = {}; - } - if (!("TPT" in $$source)) { - /** - * Soft reject - * @member - * @type {{ [_ in string]?: number }} - */ - this["TPT"] = {}; - } - if (!("TPTPtr" in $$source)) { - /** - * Soft reject - * @member - * @type {{ [_ in string]?: number }} - */ - this["TPTPtr"] = {}; - } - if (!("TPU" in $$source)) { - /** - * Accept, hide - * @member - * @type {{ [_ in string]?: number }} - */ - this["TPU"] = {}; - } - if (!("TPUPtr" in $$source)) { - /** - * Soft reject - * @member - * @type {{ [_ in string]?: number }} - */ - this["TPUPtr"] = {}; - } - if (!("TPV" in $$source)) { - /** - * Accept, hide - * @member - * @type {{ [_ in string]?: number }} - */ - this["TPV"] = {}; - } - if (!("TPVPtr" in $$source)) { - /** - * Soft reject - * @member - * @type {{ [_ in string]?: number }} - */ - this["TPVPtr"] = {}; - } - if (!("TPW" in $$source)) { - /** - * Soft reject - * @member - * @type {{ [_ in string]?: number }} - */ - this["TPW"] = {}; - } - if (!("TPWPtr" in $$source)) { - /** - * Accept, hide - * @member - * @type {{ [_ in string]?: number }} - */ - this["TPWPtr"] = {}; - } - if (!("TPX" in $$source)) { - /** - * Accept, hide - * @member - * @type {{ [_ in string]?: number }} - */ - this["TPX"] = {}; - } - if (!("TPXPtr" in $$source)) { - /** - * Soft reject - * @member - * @type {{ [_ in string]?: number }} - */ - this["TPXPtr"] = {}; - } - if (!("TPY" in $$source)) { - /** - * Accept, hide - * @member - * @type {{ [_ in string]?: number }} - */ - this["TPY"] = {}; - } - if (!("TPYPtr" in $$source)) { - /** - * Soft reject - * @member - * @type {{ [_ in string]?: number }} - */ - this["TPYPtr"] = {}; - } - if (!("TPZ" in $$source)) { - /** - * Accept, hide - * @member - * @type {{ [_ in string]?: number }} - */ - this["TPZ"] = {}; - } - if (!("TPZPtr" in $$source)) { - /** - * Soft reject - * @member - * @type {{ [_ in string]?: number }} - */ - this["TPZPtr"] = {}; - } - if (!("GAR" in $$source)) { - /** - * Soft reject - * @member - * @type {{ [_ in string]?: number }} - */ - this["GAR"] = {}; - } - if (!("GARPtr" in $$source)) { - /** - * Soft reject - * @member - * @type {{ [_ in string]?: number }} - */ - this["GARPtr"] = {}; - } - if (!("GAS" in $$source)) { - /** - * Accept, hide - * @member - * @type {{ [_ in string]?: number }} - */ - this["GAS"] = {}; - } - if (!("GASPtr" in $$source)) { - /** - * Soft reject - * @member - * @type {{ [_ in string]?: number }} - */ - this["GASPtr"] = {}; - } - if (!("GAT" in $$source)) { - /** - * Soft reject - * @member - * @type {{ [_ in string]?: number }} - */ - this["GAT"] = {}; - } - if (!("GATPtr" in $$source)) { - /** - * Soft reject - * @member - * @type {{ [_ in string]?: number }} - */ - this["GATPtr"] = {}; - } - if (!("GAU" in $$source)) { - /** - * Accept, hide - * @member - * @type {{ [_ in string]?: number }} - */ - this["GAU"] = {}; - } - if (!("GAUPtr" in $$source)) { - /** - * Soft reject - * @member - * @type {{ [_ in string]?: number }} - */ - this["GAUPtr"] = {}; - } - if (!("GAV" in $$source)) { - /** - * Accept, hide - * @member - * @type {{ [_ in string]?: number }} - */ - this["GAV"] = {}; - } - if (!("GAVPtr" in $$source)) { - /** - * Soft reject - * @member - * @type {{ [_ in string]?: number }} - */ - this["GAVPtr"] = {}; - } - if (!("GAW" in $$source)) { - /** - * Soft reject - * @member - * @type {{ [_ in string]?: number }} - */ - this["GAW"] = {}; - } - if (!("GAWPtr" in $$source)) { - /** - * Accept, hide - * @member - * @type {{ [_ in string]?: number }} - */ - this["GAWPtr"] = {}; - } - if (!("GAX" in $$source)) { - /** - * Accept, hide - * @member - * @type {{ [_ in string]?: number }} - */ - this["GAX"] = {}; - } - if (!("GAXPtr" in $$source)) { - /** - * Soft reject - * @member - * @type {{ [_ in string]?: number }} - */ - this["GAXPtr"] = {}; - } - if (!("GAY" in $$source)) { - /** - * Accept, hide - * @member - * @type {{ [_ in string]?: number }} - */ - this["GAY"] = {}; - } - if (!("GAYPtr" in $$source)) { - /** - * Soft reject - * @member - * @type {{ [_ in string]?: number }} - */ - this["GAYPtr"] = {}; - } - if (!("GAZ" in $$source)) { - /** - * Accept, hide - * @member - * @type {{ [_ in string]?: number }} - */ - this["GAZ"] = {}; - } - if (!("GAZPtr" in $$source)) { - /** - * Soft reject - * @member - * @type {{ [_ in string]?: number }} - */ - this["GAZPtr"] = {}; - } - if (!("GACi" in $$source)) { - /** - * Accept - * @member - * @type {{ [_ in ComparableCstrAlias]?: number }} - */ - this["GACi"] = {}; - } - if (!("GACV" in $$source)) { - /** - * Accept - * @member - * @type {{ [_ in ComparableCstrAlias]?: number }} - */ - this["GACV"] = {}; - } - if (!("GACP" in $$source)) { - /** - * Reject - * @member - * @type {{ [_ in string]?: number }} - */ - this["GACP"] = {}; - } - if (!("GACiPtr" in $$source)) { - /** - * Reject - * @member - * @type {{ [_ in string]?: number }} - */ - this["GACiPtr"] = {}; - } - if (!("GACVPtr" in $$source)) { - /** - * Accept, hide - * @member - * @type {{ [_ in string]?: number }} - */ - this["GACVPtr"] = {}; - } - if (!("GACPPtr" in $$source)) { - /** - * Accept, hide - * @member - * @type {{ [_ in string]?: number }} - */ - this["GACPPtr"] = {}; - } - if (!("GABi" in $$source)) { - /** - * Accept - * @member - * @type {{ [_ in BasicCstrAlias]?: number }} - */ - this["GABi"] = {}; - } - if (!("GABs" in $$source)) { - /** - * Accept - * @member - * @type {{ [_ in BasicCstrAlias]?: number }} - */ - this["GABs"] = {}; - } - if (!("GABiPtr" in $$source)) { - /** - * Reject - * @member - * @type {{ [_ in string]?: number }} - */ - this["GABiPtr"] = {}; - } - if (!("GABT" in $$source)) { - /** - * Reject - * @member - * @type {{ [_ in string]?: number }} - */ - this["GABT"] = {}; - } - if (!("GABTPtr" in $$source)) { - /** - * Reject - * @member - * @type {{ [_ in string]?: number }} - */ - this["GABTPtr"] = {}; - } - if (!("GAGT" in $$source)) { - /** - * Accept - * @member - * @type {{ [_ in GoodTildeCstrAlias]?: number }} - */ - this["GAGT"] = {}; - } - if (!("GAGTPtr" in $$source)) { - /** - * Accept, hide - * @member - * @type {{ [_ in string]?: number }} - */ - this["GAGTPtr"] = {}; - } - if (!("GANBV" in $$source)) { - /** - * Accept - * @member - * @type {{ [_ in NonBasicCstrAlias]?: number }} - */ - this["GANBV"] = {}; - } - if (!("GANBP" in $$source)) { - /** - * Accept, hide - * @member - * @type {{ [_ in string]?: number }} - */ - this["GANBP"] = {}; - } - if (!("GANBVPtr" in $$source)) { - /** - * Accept, hide - * @member - * @type {{ [_ in string]?: number }} - */ - this["GANBVPtr"] = {}; - } - if (!("GANBPPtr" in $$source)) { - /** - * Reject - * @member - * @type {{ [_ in string]?: number }} - */ - this["GANBPPtr"] = {}; - } - if (!("GAPlV1" in $$source)) { - /** - * Accept - * @member - * @type {{ [_ in PointableCstrAlias]?: number }} - */ - this["GAPlV1"] = {}; - } - if (!("GAPlV2" in $$source)) { - /** - * Accept - * @member - * @type {{ [_ in PointableCstrAlias]?: number }} - */ - this["GAPlV2"] = {}; - } - if (!("GAPlP1" in $$source)) { - /** - * Reject - * @member - * @type {{ [_ in string]?: number }} - */ - this["GAPlP1"] = {}; - } - if (!("GAPlP2" in $$source)) { - /** - * Accept - * @member - * @type {{ [_ in PointableCstrAlias]?: number }} - */ - this["GAPlP2"] = {}; - } - if (!("GAPlVPtr" in $$source)) { - /** - * Accept, hide - * @member - * @type {{ [_ in string]?: number }} - */ - this["GAPlVPtr"] = {}; - } - if (!("GAPlPPtr" in $$source)) { - /** - * Accept, hide - * @member - * @type {{ [_ in string]?: number }} - */ - this["GAPlPPtr"] = {}; - } - if (!("GAMi" in $$source)) { - /** - * Accept - * @member - * @type {{ [_ in MixedCstrAlias]?: number }} - */ - this["GAMi"] = {}; - } - if (!("GAMS" in $$source)) { - /** - * Accept - * @member - * @type {{ [_ in MixedCstrAlias]?: number }} - */ - this["GAMS"] = {}; - } - if (!("GAMV" in $$source)) { - /** - * Accept - * @member - * @type {{ [_ in MixedCstrAlias]?: number }} - */ - this["GAMV"] = {}; - } - if (!("GAMSPtr" in $$source)) { - /** - * Reject - * @member - * @type {{ [_ in string]?: number }} - */ - this["GAMSPtr"] = {}; - } - if (!("GAMVPtr" in $$source)) { - /** - * Accept, hide - * @member - * @type {{ [_ in string]?: number }} - */ - this["GAMVPtr"] = {}; - } - if (!("GAII" in $$source)) { - /** - * Accept, hide - * @member - * @type {{ [_ in string]?: number }} - */ - this["GAII"] = {}; - } - if (!("GAIV" in $$source)) { - /** - * Accept - * @member - * @type {{ [_ in InterfaceCstrAlias]?: number }} - */ - this["GAIV"] = {}; - } - if (!("GAIP" in $$source)) { - /** - * Accept, hide - * @member - * @type {{ [_ in string]?: number }} - */ - this["GAIP"] = {}; - } - if (!("GAIIPtr" in $$source)) { - /** - * Reject - * @member - * @type {{ [_ in string]?: number }} - */ - this["GAIIPtr"] = {}; - } - if (!("GAIVPtr" in $$source)) { - /** - * Accept, hide - * @member - * @type {{ [_ in string]?: number }} - */ - this["GAIVPtr"] = {}; - } - if (!("GAIPPtr" in $$source)) { - /** - * Reject - * @member - * @type {{ [_ in string]?: number }} - */ - this["GAIPPtr"] = {}; - } - if (!("GAPrV" in $$source)) { - /** - * Accept, hide - * @member - * @type {{ [_ in string]?: number }} - */ - this["GAPrV"] = {}; - } - if (!("GAPrP" in $$source)) { - /** - * Accept, hide - * @member - * @type {{ [_ in string]?: number }} - */ - this["GAPrP"] = {}; - } - if (!("GAPrVPtr" in $$source)) { - /** - * Reject - * @member - * @type {{ [_ in string]?: number }} - */ - this["GAPrVPtr"] = {}; - } - if (!("GAPrPPtr" in $$source)) { - /** - * Reject - * @member - * @type {{ [_ in string]?: number }} - */ - this["GAPrPPtr"] = {}; - } - - Object.assign(this, $$source); - } - - /** - * Given creation functions for each type parameter, - * returns a creation function for a concrete instance - * of the generic class Maps. - * @template [R=any] - * @template [S=any] - * @template [T=any] - * @template [U=any] - * @template [V=any] - * @template [W=any] - * @template [X=any] - * @template [Y=any] - * @template [Z=any] - * @param {(source: any) => R} $$createParamR - * @param {(source: any) => S} $$createParamS - * @param {(source: any) => T} $$createParamT - * @param {(source: any) => U} $$createParamU - * @param {(source: any) => V} $$createParamV - * @param {(source: any) => W} $$createParamW - * @param {(source: any) => X} $$createParamX - * @param {(source: any) => Y} $$createParamY - * @param {(source: any) => Z} $$createParamZ - * @returns {($$source?: any) => Maps} - */ - static createFrom($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ) { - const $$createField0_0 = $$createType0; - const $$createField1_0 = $$createType1; - const $$createField2_0 = $$createType2; - const $$createField3_0 = $$createType3; - const $$createField4_0 = $$createType4; - const $$createField5_0 = $$createType5; - const $$createField6_0 = $$createType6; - const $$createField7_0 = $$createType7; - const $$createField8_0 = $$createType8; - const $$createField9_0 = $$createType9; - const $$createField10_0 = $$createType10; - const $$createField11_0 = $$createType11; - const $$createField12_0 = $$createType12; - const $$createField13_0 = $$createType13; - const $$createField14_0 = $$createType14; - const $$createField15_0 = $$createType15; - const $$createField16_0 = $$createType16; - const $$createField17_0 = $$createType17; - const $$createField18_0 = $$createType18; - const $$createField19_0 = $$createType19; - const $$createField20_0 = $$createType20; - const $$createField21_0 = $$createType21; - const $$createField22_0 = $$createType22; - const $$createField23_0 = $$createType23; - const $$createField24_0 = $$createType24; - const $$createField25_0 = $$createType25; - const $$createField26_0 = $$createType26; - const $$createField27_0 = $$createType27; - const $$createField28_0 = $$createType28; - const $$createField29_0 = $$createType29; - const $$createField30_0 = $$createType30; - const $$createField31_0 = $$createType31; - const $$createField32_0 = $$createType32; - const $$createField33_0 = $$createType33; - const $$createField34_0 = $$createType34; - const $$createField35_0 = $$createType35; - const $$createField36_0 = $$createType36; - const $$createField37_0 = $$createType37; - const $$createField38_0 = $$createType38; - const $$createField39_0 = $$createType39; - const $$createField40_0 = $$createType40; - const $$createField41_0 = $$createType41; - const $$createField42_0 = $$createType0; - const $$createField43_0 = $$createType42; - const $$createField44_0 = $$createType7; - const $$createField45_0 = $$createType43; - const $$createField46_0 = $$createType1; - const $$createField47_0 = $$createType44; - const $$createField48_0 = $$createType45; - const $$createField49_0 = $$createType46; - const $$createField50_0 = $$createType47; - const $$createField51_0 = $$createType15; - const $$createField52_0 = $$createType16; - const $$createField53_0 = $$createType16; - const $$createField54_0 = $$createType48; - const $$createField55_0 = $$createType49; - const $$createField56_0 = $$createType50; - const $$createField57_0 = $$createType51; - const $$createField58_0 = $$createType52; - const $$createField59_0 = $$createType17; - const $$createField60_0 = $$createType18; - const $$createField61_0 = $$createType18; - const $$createField62_0 = $$createType53; - const $$createField63_0 = $$createType54; - const $$createField64_0 = $$createType55; - const $$createField65_0 = $$createType56; - const $$createField66_0 = $$createType57; - const $$createField67_0 = $$createType23; - const $$createField68_0 = $$createType24; - const $$createField69_0 = $$createType24; - const $$createField70_0 = $$createType58; - const $$createField71_0 = $$createType59($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ); - const $$createField72_0 = $$createType60($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ); - const $$createField73_0 = $$createType61($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ); - const $$createField74_0 = $$createType62($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ); - const $$createField75_0 = $$createType63($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ); - const $$createField76_0 = $$createType64($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ); - const $$createField77_0 = $$createType65($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ); - const $$createField78_0 = $$createType66($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ); - const $$createField79_0 = $$createType67($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ); - const $$createField80_0 = $$createType68($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ); - const $$createField81_0 = $$createType69($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ); - const $$createField82_0 = $$createType70($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ); - const $$createField83_0 = $$createType71($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ); - const $$createField84_0 = $$createType72($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ); - const $$createField85_0 = $$createType73($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ); - const $$createField86_0 = $$createType74($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ); - const $$createField87_0 = $$createType75($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ); - const $$createField88_0 = $$createType76($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ); - const $$createField89_0 = $$createType59($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ); - const $$createField90_0 = $$createType60($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ); - const $$createField91_0 = $$createType61($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ); - const $$createField92_0 = $$createType62($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ); - const $$createField93_0 = $$createType63($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ); - const $$createField94_0 = $$createType64($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ); - const $$createField95_0 = $$createType65($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ); - const $$createField96_0 = $$createType66($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ); - const $$createField97_0 = $$createType67($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ); - const $$createField98_0 = $$createType68($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ); - const $$createField99_0 = $$createType69($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ); - const $$createField100_0 = $$createType70($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ); - const $$createField101_0 = $$createType71($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ); - const $$createField102_0 = $$createType72($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ); - const $$createField103_0 = $$createType73($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ); - const $$createField104_0 = $$createType74($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ); - const $$createField105_0 = $$createType75($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ); - const $$createField106_0 = $$createType76($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ); - const $$createField107_0 = $$createType1; - const $$createField108_0 = $$createType15; - const $$createField109_0 = $$createType17; - const $$createField110_0 = $$createType8; - const $$createField111_0 = $$createType16; - const $$createField112_0 = $$createType18; - const $$createField113_0 = $$createType1; - const $$createField114_0 = $$createType7; - const $$createField115_0 = $$createType8; - const $$createField116_0 = $$createType77; - const $$createField117_0 = $$createType78; - const $$createField118_0 = $$createType15; - const $$createField119_0 = $$createType16; - const $$createField120_0 = $$createType15; - const $$createField121_0 = $$createType18; - const $$createField122_0 = $$createType16; - const $$createField123_0 = $$createType53; - const $$createField124_0 = $$createType15; - const $$createField125_0 = $$createType16; - const $$createField126_0 = $$createType17; - const $$createField127_0 = $$createType18; - const $$createField128_0 = $$createType16; - const $$createField129_0 = $$createType18; - const $$createField130_0 = $$createType2; - const $$createField131_0 = $$createType42; - const $$createField132_0 = $$createType15; - const $$createField133_0 = $$createType79; - const $$createField134_0 = $$createType16; - const $$createField135_0 = $$createType23; - const $$createField136_0 = $$createType15; - const $$createField137_0 = $$createType18; - const $$createField138_0 = $$createType24; - const $$createField139_0 = $$createType16; - const $$createField140_0 = $$createType53; - const $$createField141_0 = $$createType16; - const $$createField142_0 = $$createType18; - const $$createField143_0 = $$createType48; - const $$createField144_0 = $$createType53; - return ($$source = {}) => { - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - if ("Bool" in $$parsedSource) { - $$parsedSource["Bool"] = $$createField0_0($$parsedSource["Bool"]); - } - if ("Int" in $$parsedSource) { - $$parsedSource["Int"] = $$createField1_0($$parsedSource["Int"]); - } - if ("Uint" in $$parsedSource) { - $$parsedSource["Uint"] = $$createField2_0($$parsedSource["Uint"]); - } - if ("Float" in $$parsedSource) { - $$parsedSource["Float"] = $$createField3_0($$parsedSource["Float"]); - } - if ("Complex" in $$parsedSource) { - $$parsedSource["Complex"] = $$createField4_0($$parsedSource["Complex"]); - } - if ("Byte" in $$parsedSource) { - $$parsedSource["Byte"] = $$createField5_0($$parsedSource["Byte"]); - } - if ("Rune" in $$parsedSource) { - $$parsedSource["Rune"] = $$createField6_0($$parsedSource["Rune"]); - } - if ("String" in $$parsedSource) { - $$parsedSource["String"] = $$createField7_0($$parsedSource["String"]); - } - if ("IntPtr" in $$parsedSource) { - $$parsedSource["IntPtr"] = $$createField8_0($$parsedSource["IntPtr"]); - } - if ("UintPtr" in $$parsedSource) { - $$parsedSource["UintPtr"] = $$createField9_0($$parsedSource["UintPtr"]); - } - if ("FloatPtr" in $$parsedSource) { - $$parsedSource["FloatPtr"] = $$createField10_0($$parsedSource["FloatPtr"]); - } - if ("ComplexPtr" in $$parsedSource) { - $$parsedSource["ComplexPtr"] = $$createField11_0($$parsedSource["ComplexPtr"]); - } - if ("StringPtr" in $$parsedSource) { - $$parsedSource["StringPtr"] = $$createField12_0($$parsedSource["StringPtr"]); - } - if ("NTM" in $$parsedSource) { - $$parsedSource["NTM"] = $$createField13_0($$parsedSource["NTM"]); - } - if ("NTMPtr" in $$parsedSource) { - $$parsedSource["NTMPtr"] = $$createField14_0($$parsedSource["NTMPtr"]); - } - if ("VTM" in $$parsedSource) { - $$parsedSource["VTM"] = $$createField15_0($$parsedSource["VTM"]); - } - if ("VTMPtr" in $$parsedSource) { - $$parsedSource["VTMPtr"] = $$createField16_0($$parsedSource["VTMPtr"]); - } - if ("PTM" in $$parsedSource) { - $$parsedSource["PTM"] = $$createField17_0($$parsedSource["PTM"]); - } - if ("PTMPtr" in $$parsedSource) { - $$parsedSource["PTMPtr"] = $$createField18_0($$parsedSource["PTMPtr"]); - } - if ("JTM" in $$parsedSource) { - $$parsedSource["JTM"] = $$createField19_0($$parsedSource["JTM"]); - } - if ("JTMPtr" in $$parsedSource) { - $$parsedSource["JTMPtr"] = $$createField20_0($$parsedSource["JTMPtr"]); - } - if ("A" in $$parsedSource) { - $$parsedSource["A"] = $$createField21_0($$parsedSource["A"]); - } - if ("APtr" in $$parsedSource) { - $$parsedSource["APtr"] = $$createField22_0($$parsedSource["APtr"]); - } - if ("TM" in $$parsedSource) { - $$parsedSource["TM"] = $$createField23_0($$parsedSource["TM"]); - } - if ("TMPtr" in $$parsedSource) { - $$parsedSource["TMPtr"] = $$createField24_0($$parsedSource["TMPtr"]); - } - if ("CI" in $$parsedSource) { - $$parsedSource["CI"] = $$createField25_0($$parsedSource["CI"]); - } - if ("CIPtr" in $$parsedSource) { - $$parsedSource["CIPtr"] = $$createField26_0($$parsedSource["CIPtr"]); - } - if ("EI" in $$parsedSource) { - $$parsedSource["EI"] = $$createField27_0($$parsedSource["EI"]); - } - if ("EIPtr" in $$parsedSource) { - $$parsedSource["EIPtr"] = $$createField28_0($$parsedSource["EIPtr"]); - } - if ("EV" in $$parsedSource) { - $$parsedSource["EV"] = $$createField29_0($$parsedSource["EV"]); - } - if ("EVPtr" in $$parsedSource) { - $$parsedSource["EVPtr"] = $$createField30_0($$parsedSource["EVPtr"]); - } - if ("EVP" in $$parsedSource) { - $$parsedSource["EVP"] = $$createField31_0($$parsedSource["EVP"]); - } - if ("EVPPtr" in $$parsedSource) { - $$parsedSource["EVPPtr"] = $$createField32_0($$parsedSource["EVPPtr"]); - } - if ("EP" in $$parsedSource) { - $$parsedSource["EP"] = $$createField33_0($$parsedSource["EP"]); - } - if ("EPPtr" in $$parsedSource) { - $$parsedSource["EPPtr"] = $$createField34_0($$parsedSource["EPPtr"]); - } - if ("EPP" in $$parsedSource) { - $$parsedSource["EPP"] = $$createField35_0($$parsedSource["EPP"]); - } - if ("EPPPtr" in $$parsedSource) { - $$parsedSource["EPPPtr"] = $$createField36_0($$parsedSource["EPPPtr"]); - } - if ("ECI" in $$parsedSource) { - $$parsedSource["ECI"] = $$createField37_0($$parsedSource["ECI"]); - } - if ("ECIPtr" in $$parsedSource) { - $$parsedSource["ECIPtr"] = $$createField38_0($$parsedSource["ECIPtr"]); - } - if ("EOI" in $$parsedSource) { - $$parsedSource["EOI"] = $$createField39_0($$parsedSource["EOI"]); - } - if ("EOIPtr" in $$parsedSource) { - $$parsedSource["EOIPtr"] = $$createField40_0($$parsedSource["EOIPtr"]); - } - if ("WT" in $$parsedSource) { - $$parsedSource["WT"] = $$createField41_0($$parsedSource["WT"]); - } - if ("WA" in $$parsedSource) { - $$parsedSource["WA"] = $$createField42_0($$parsedSource["WA"]); - } - if ("ST" in $$parsedSource) { - $$parsedSource["ST"] = $$createField43_0($$parsedSource["ST"]); - } - if ("SA" in $$parsedSource) { - $$parsedSource["SA"] = $$createField44_0($$parsedSource["SA"]); - } - if ("IntT" in $$parsedSource) { - $$parsedSource["IntT"] = $$createField45_0($$parsedSource["IntT"]); - } - if ("IntA" in $$parsedSource) { - $$parsedSource["IntA"] = $$createField46_0($$parsedSource["IntA"]); - } - if ("VT" in $$parsedSource) { - $$parsedSource["VT"] = $$createField47_0($$parsedSource["VT"]); - } - if ("VTPtr" in $$parsedSource) { - $$parsedSource["VTPtr"] = $$createField48_0($$parsedSource["VTPtr"]); - } - if ("VPT" in $$parsedSource) { - $$parsedSource["VPT"] = $$createField49_0($$parsedSource["VPT"]); - } - if ("VPTPtr" in $$parsedSource) { - $$parsedSource["VPTPtr"] = $$createField50_0($$parsedSource["VPTPtr"]); - } - if ("VA" in $$parsedSource) { - $$parsedSource["VA"] = $$createField51_0($$parsedSource["VA"]); - } - if ("VAPtr" in $$parsedSource) { - $$parsedSource["VAPtr"] = $$createField52_0($$parsedSource["VAPtr"]); - } - if ("VPA" in $$parsedSource) { - $$parsedSource["VPA"] = $$createField53_0($$parsedSource["VPA"]); - } - if ("VPAPtr" in $$parsedSource) { - $$parsedSource["VPAPtr"] = $$createField54_0($$parsedSource["VPAPtr"]); - } - if ("PT" in $$parsedSource) { - $$parsedSource["PT"] = $$createField55_0($$parsedSource["PT"]); - } - if ("PTPtr" in $$parsedSource) { - $$parsedSource["PTPtr"] = $$createField56_0($$parsedSource["PTPtr"]); - } - if ("PPT" in $$parsedSource) { - $$parsedSource["PPT"] = $$createField57_0($$parsedSource["PPT"]); - } - if ("PPTPtr" in $$parsedSource) { - $$parsedSource["PPTPtr"] = $$createField58_0($$parsedSource["PPTPtr"]); - } - if ("PA" in $$parsedSource) { - $$parsedSource["PA"] = $$createField59_0($$parsedSource["PA"]); - } - if ("PAPtr" in $$parsedSource) { - $$parsedSource["PAPtr"] = $$createField60_0($$parsedSource["PAPtr"]); - } - if ("PPA" in $$parsedSource) { - $$parsedSource["PPA"] = $$createField61_0($$parsedSource["PPA"]); - } - if ("PPAPtr" in $$parsedSource) { - $$parsedSource["PPAPtr"] = $$createField62_0($$parsedSource["PPAPtr"]); - } - if ("IT" in $$parsedSource) { - $$parsedSource["IT"] = $$createField63_0($$parsedSource["IT"]); - } - if ("ITPtr" in $$parsedSource) { - $$parsedSource["ITPtr"] = $$createField64_0($$parsedSource["ITPtr"]); - } - if ("IPT" in $$parsedSource) { - $$parsedSource["IPT"] = $$createField65_0($$parsedSource["IPT"]); - } - if ("IPTPtr" in $$parsedSource) { - $$parsedSource["IPTPtr"] = $$createField66_0($$parsedSource["IPTPtr"]); - } - if ("IA" in $$parsedSource) { - $$parsedSource["IA"] = $$createField67_0($$parsedSource["IA"]); - } - if ("IAPtr" in $$parsedSource) { - $$parsedSource["IAPtr"] = $$createField68_0($$parsedSource["IAPtr"]); - } - if ("IPA" in $$parsedSource) { - $$parsedSource["IPA"] = $$createField69_0($$parsedSource["IPA"]); - } - if ("IPAPtr" in $$parsedSource) { - $$parsedSource["IPAPtr"] = $$createField70_0($$parsedSource["IPAPtr"]); - } - if ("TPR" in $$parsedSource) { - $$parsedSource["TPR"] = $$createField71_0($$parsedSource["TPR"]); - } - if ("TPRPtr" in $$parsedSource) { - $$parsedSource["TPRPtr"] = $$createField72_0($$parsedSource["TPRPtr"]); - } - if ("TPS" in $$parsedSource) { - $$parsedSource["TPS"] = $$createField73_0($$parsedSource["TPS"]); - } - if ("TPSPtr" in $$parsedSource) { - $$parsedSource["TPSPtr"] = $$createField74_0($$parsedSource["TPSPtr"]); - } - if ("TPT" in $$parsedSource) { - $$parsedSource["TPT"] = $$createField75_0($$parsedSource["TPT"]); - } - if ("TPTPtr" in $$parsedSource) { - $$parsedSource["TPTPtr"] = $$createField76_0($$parsedSource["TPTPtr"]); - } - if ("TPU" in $$parsedSource) { - $$parsedSource["TPU"] = $$createField77_0($$parsedSource["TPU"]); - } - if ("TPUPtr" in $$parsedSource) { - $$parsedSource["TPUPtr"] = $$createField78_0($$parsedSource["TPUPtr"]); - } - if ("TPV" in $$parsedSource) { - $$parsedSource["TPV"] = $$createField79_0($$parsedSource["TPV"]); - } - if ("TPVPtr" in $$parsedSource) { - $$parsedSource["TPVPtr"] = $$createField80_0($$parsedSource["TPVPtr"]); - } - if ("TPW" in $$parsedSource) { - $$parsedSource["TPW"] = $$createField81_0($$parsedSource["TPW"]); - } - if ("TPWPtr" in $$parsedSource) { - $$parsedSource["TPWPtr"] = $$createField82_0($$parsedSource["TPWPtr"]); - } - if ("TPX" in $$parsedSource) { - $$parsedSource["TPX"] = $$createField83_0($$parsedSource["TPX"]); - } - if ("TPXPtr" in $$parsedSource) { - $$parsedSource["TPXPtr"] = $$createField84_0($$parsedSource["TPXPtr"]); - } - if ("TPY" in $$parsedSource) { - $$parsedSource["TPY"] = $$createField85_0($$parsedSource["TPY"]); - } - if ("TPYPtr" in $$parsedSource) { - $$parsedSource["TPYPtr"] = $$createField86_0($$parsedSource["TPYPtr"]); - } - if ("TPZ" in $$parsedSource) { - $$parsedSource["TPZ"] = $$createField87_0($$parsedSource["TPZ"]); - } - if ("TPZPtr" in $$parsedSource) { - $$parsedSource["TPZPtr"] = $$createField88_0($$parsedSource["TPZPtr"]); - } - if ("GAR" in $$parsedSource) { - $$parsedSource["GAR"] = $$createField89_0($$parsedSource["GAR"]); - } - if ("GARPtr" in $$parsedSource) { - $$parsedSource["GARPtr"] = $$createField90_0($$parsedSource["GARPtr"]); - } - if ("GAS" in $$parsedSource) { - $$parsedSource["GAS"] = $$createField91_0($$parsedSource["GAS"]); - } - if ("GASPtr" in $$parsedSource) { - $$parsedSource["GASPtr"] = $$createField92_0($$parsedSource["GASPtr"]); - } - if ("GAT" in $$parsedSource) { - $$parsedSource["GAT"] = $$createField93_0($$parsedSource["GAT"]); - } - if ("GATPtr" in $$parsedSource) { - $$parsedSource["GATPtr"] = $$createField94_0($$parsedSource["GATPtr"]); - } - if ("GAU" in $$parsedSource) { - $$parsedSource["GAU"] = $$createField95_0($$parsedSource["GAU"]); - } - if ("GAUPtr" in $$parsedSource) { - $$parsedSource["GAUPtr"] = $$createField96_0($$parsedSource["GAUPtr"]); - } - if ("GAV" in $$parsedSource) { - $$parsedSource["GAV"] = $$createField97_0($$parsedSource["GAV"]); - } - if ("GAVPtr" in $$parsedSource) { - $$parsedSource["GAVPtr"] = $$createField98_0($$parsedSource["GAVPtr"]); - } - if ("GAW" in $$parsedSource) { - $$parsedSource["GAW"] = $$createField99_0($$parsedSource["GAW"]); - } - if ("GAWPtr" in $$parsedSource) { - $$parsedSource["GAWPtr"] = $$createField100_0($$parsedSource["GAWPtr"]); - } - if ("GAX" in $$parsedSource) { - $$parsedSource["GAX"] = $$createField101_0($$parsedSource["GAX"]); - } - if ("GAXPtr" in $$parsedSource) { - $$parsedSource["GAXPtr"] = $$createField102_0($$parsedSource["GAXPtr"]); - } - if ("GAY" in $$parsedSource) { - $$parsedSource["GAY"] = $$createField103_0($$parsedSource["GAY"]); - } - if ("GAYPtr" in $$parsedSource) { - $$parsedSource["GAYPtr"] = $$createField104_0($$parsedSource["GAYPtr"]); - } - if ("GAZ" in $$parsedSource) { - $$parsedSource["GAZ"] = $$createField105_0($$parsedSource["GAZ"]); - } - if ("GAZPtr" in $$parsedSource) { - $$parsedSource["GAZPtr"] = $$createField106_0($$parsedSource["GAZPtr"]); - } - if ("GACi" in $$parsedSource) { - $$parsedSource["GACi"] = $$createField107_0($$parsedSource["GACi"]); - } - if ("GACV" in $$parsedSource) { - $$parsedSource["GACV"] = $$createField108_0($$parsedSource["GACV"]); - } - if ("GACP" in $$parsedSource) { - $$parsedSource["GACP"] = $$createField109_0($$parsedSource["GACP"]); - } - if ("GACiPtr" in $$parsedSource) { - $$parsedSource["GACiPtr"] = $$createField110_0($$parsedSource["GACiPtr"]); - } - if ("GACVPtr" in $$parsedSource) { - $$parsedSource["GACVPtr"] = $$createField111_0($$parsedSource["GACVPtr"]); - } - if ("GACPPtr" in $$parsedSource) { - $$parsedSource["GACPPtr"] = $$createField112_0($$parsedSource["GACPPtr"]); - } - if ("GABi" in $$parsedSource) { - $$parsedSource["GABi"] = $$createField113_0($$parsedSource["GABi"]); - } - if ("GABs" in $$parsedSource) { - $$parsedSource["GABs"] = $$createField114_0($$parsedSource["GABs"]); - } - if ("GABiPtr" in $$parsedSource) { - $$parsedSource["GABiPtr"] = $$createField115_0($$parsedSource["GABiPtr"]); - } - if ("GABT" in $$parsedSource) { - $$parsedSource["GABT"] = $$createField116_0($$parsedSource["GABT"]); - } - if ("GABTPtr" in $$parsedSource) { - $$parsedSource["GABTPtr"] = $$createField117_0($$parsedSource["GABTPtr"]); - } - if ("GAGT" in $$parsedSource) { - $$parsedSource["GAGT"] = $$createField118_0($$parsedSource["GAGT"]); - } - if ("GAGTPtr" in $$parsedSource) { - $$parsedSource["GAGTPtr"] = $$createField119_0($$parsedSource["GAGTPtr"]); - } - if ("GANBV" in $$parsedSource) { - $$parsedSource["GANBV"] = $$createField120_0($$parsedSource["GANBV"]); - } - if ("GANBP" in $$parsedSource) { - $$parsedSource["GANBP"] = $$createField121_0($$parsedSource["GANBP"]); - } - if ("GANBVPtr" in $$parsedSource) { - $$parsedSource["GANBVPtr"] = $$createField122_0($$parsedSource["GANBVPtr"]); - } - if ("GANBPPtr" in $$parsedSource) { - $$parsedSource["GANBPPtr"] = $$createField123_0($$parsedSource["GANBPPtr"]); - } - if ("GAPlV1" in $$parsedSource) { - $$parsedSource["GAPlV1"] = $$createField124_0($$parsedSource["GAPlV1"]); - } - if ("GAPlV2" in $$parsedSource) { - $$parsedSource["GAPlV2"] = $$createField125_0($$parsedSource["GAPlV2"]); - } - if ("GAPlP1" in $$parsedSource) { - $$parsedSource["GAPlP1"] = $$createField126_0($$parsedSource["GAPlP1"]); - } - if ("GAPlP2" in $$parsedSource) { - $$parsedSource["GAPlP2"] = $$createField127_0($$parsedSource["GAPlP2"]); - } - if ("GAPlVPtr" in $$parsedSource) { - $$parsedSource["GAPlVPtr"] = $$createField128_0($$parsedSource["GAPlVPtr"]); - } - if ("GAPlPPtr" in $$parsedSource) { - $$parsedSource["GAPlPPtr"] = $$createField129_0($$parsedSource["GAPlPPtr"]); - } - if ("GAMi" in $$parsedSource) { - $$parsedSource["GAMi"] = $$createField130_0($$parsedSource["GAMi"]); - } - if ("GAMS" in $$parsedSource) { - $$parsedSource["GAMS"] = $$createField131_0($$parsedSource["GAMS"]); - } - if ("GAMV" in $$parsedSource) { - $$parsedSource["GAMV"] = $$createField132_0($$parsedSource["GAMV"]); - } - if ("GAMSPtr" in $$parsedSource) { - $$parsedSource["GAMSPtr"] = $$createField133_0($$parsedSource["GAMSPtr"]); - } - if ("GAMVPtr" in $$parsedSource) { - $$parsedSource["GAMVPtr"] = $$createField134_0($$parsedSource["GAMVPtr"]); - } - if ("GAII" in $$parsedSource) { - $$parsedSource["GAII"] = $$createField135_0($$parsedSource["GAII"]); - } - if ("GAIV" in $$parsedSource) { - $$parsedSource["GAIV"] = $$createField136_0($$parsedSource["GAIV"]); - } - if ("GAIP" in $$parsedSource) { - $$parsedSource["GAIP"] = $$createField137_0($$parsedSource["GAIP"]); - } - if ("GAIIPtr" in $$parsedSource) { - $$parsedSource["GAIIPtr"] = $$createField138_0($$parsedSource["GAIIPtr"]); - } - if ("GAIVPtr" in $$parsedSource) { - $$parsedSource["GAIVPtr"] = $$createField139_0($$parsedSource["GAIVPtr"]); - } - if ("GAIPPtr" in $$parsedSource) { - $$parsedSource["GAIPPtr"] = $$createField140_0($$parsedSource["GAIPPtr"]); - } - if ("GAPrV" in $$parsedSource) { - $$parsedSource["GAPrV"] = $$createField141_0($$parsedSource["GAPrV"]); - } - if ("GAPrP" in $$parsedSource) { - $$parsedSource["GAPrP"] = $$createField142_0($$parsedSource["GAPrP"]); - } - if ("GAPrVPtr" in $$parsedSource) { - $$parsedSource["GAPrVPtr"] = $$createField143_0($$parsedSource["GAPrVPtr"]); - } - if ("GAPrPPtr" in $$parsedSource) { - $$parsedSource["GAPrPPtr"] = $$createField144_0($$parsedSource["GAPrPPtr"]); - } - return new Maps(/** @type {Partial>} */($$parsedSource)); - }; - } -} - -/** - * @template X - * @typedef {X} MixedCstrAlias - */ - -/** - * @template V - * @typedef {V} NonBasicCstrAlias - */ - -/** - * @template W - * @typedef {W} PointableCstrAlias - */ - -/** - * @typedef {PointerTextMarshaler} PointerAlias - */ - -/** - * @typedef {string} PointerTextMarshaler - */ - -/** - * @typedef {string} StringAlias - */ - -/** - * @typedef {string} StringType - */ - -/** - * @typedef {ValueTextMarshaler} ValueAlias - */ - -/** - * @typedef {string} ValueTextMarshaler - */ - -// Private type creation functions -const $$createType0 = $Create.Map($Create.Any, $Create.Any); -const $$createType1 = $Create.Map($Create.Any, $Create.Any); -const $$createType2 = $Create.Map($Create.Any, $Create.Any); -const $$createType3 = $Create.Map($Create.Any, $Create.Any); -const $$createType4 = $Create.Map($Create.Any, $Create.Any); -const $$createType5 = $Create.Map($Create.Any, $Create.Any); -const $$createType6 = $Create.Map($Create.Any, $Create.Any); -const $$createType7 = $Create.Map($Create.Any, $Create.Any); -const $$createType8 = $Create.Map($Create.Any, $Create.Any); -const $$createType9 = $Create.Map($Create.Any, $Create.Any); -const $$createType10 = $Create.Map($Create.Any, $Create.Any); -const $$createType11 = $Create.Map($Create.Any, $Create.Any); -const $$createType12 = $Create.Map($Create.Any, $Create.Any); -const $$createType13 = $Create.Map($Create.Any, $Create.Any); -const $$createType14 = $Create.Map($Create.Any, $Create.Any); -const $$createType15 = $Create.Map($Create.Any, $Create.Any); -const $$createType16 = $Create.Map($Create.Any, $Create.Any); -const $$createType17 = $Create.Map($Create.Any, $Create.Any); -const $$createType18 = $Create.Map($Create.Any, $Create.Any); -const $$createType19 = $Create.Map($Create.Any, $Create.Any); -const $$createType20 = $Create.Map($Create.Any, $Create.Any); -const $$createType21 = $Create.Map($Create.Any, $Create.Any); -const $$createType22 = $Create.Map($Create.Any, $Create.Any); -const $$createType23 = $Create.Map($Create.Any, $Create.Any); -const $$createType24 = $Create.Map($Create.Any, $Create.Any); -const $$createType25 = $Create.Map($Create.Any, $Create.Any); -const $$createType26 = $Create.Map($Create.Any, $Create.Any); -const $$createType27 = $Create.Map($Create.Any, $Create.Any); -const $$createType28 = $Create.Map($Create.Any, $Create.Any); -const $$createType29 = $Create.Map($Create.Any, $Create.Any); -const $$createType30 = $Create.Map($Create.Any, $Create.Any); -const $$createType31 = $Create.Map($Create.Any, $Create.Any); -const $$createType32 = $Create.Map($Create.Any, $Create.Any); -const $$createType33 = $Create.Map($Create.Any, $Create.Any); -const $$createType34 = $Create.Map($Create.Any, $Create.Any); -const $$createType35 = $Create.Map($Create.Any, $Create.Any); -const $$createType36 = $Create.Map($Create.Any, $Create.Any); -const $$createType37 = $Create.Map($Create.Any, $Create.Any); -const $$createType38 = $Create.Map($Create.Any, $Create.Any); -const $$createType39 = $Create.Map($Create.Any, $Create.Any); -const $$createType40 = $Create.Map($Create.Any, $Create.Any); -const $$createType41 = $Create.Map($Create.Any, $Create.Any); -const $$createType42 = $Create.Map($Create.Any, $Create.Any); -const $$createType43 = $Create.Map($Create.Any, $Create.Any); -const $$createType44 = $Create.Map($Create.Any, $Create.Any); -const $$createType45 = $Create.Map($Create.Any, $Create.Any); -const $$createType46 = $Create.Map($Create.Any, $Create.Any); -const $$createType47 = $Create.Map($Create.Any, $Create.Any); -const $$createType48 = $Create.Map($Create.Any, $Create.Any); -const $$createType49 = $Create.Map($Create.Any, $Create.Any); -const $$createType50 = $Create.Map($Create.Any, $Create.Any); -const $$createType51 = $Create.Map($Create.Any, $Create.Any); -const $$createType52 = $Create.Map($Create.Any, $Create.Any); -const $$createType53 = $Create.Map($Create.Any, $Create.Any); -const $$createType54 = $Create.Map($Create.Any, $Create.Any); -const $$createType55 = $Create.Map($Create.Any, $Create.Any); -const $$createType56 = $Create.Map($Create.Any, $Create.Any); -const $$createType57 = $Create.Map($Create.Any, $Create.Any); -const $$createType58 = $Create.Map($Create.Any, $Create.Any); -const $$createType59 = /** @type {(...args: any[]) => any} */(($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ) => $Create.Map($Create.Any, $Create.Any)); -const $$createType60 = /** @type {(...args: any[]) => any} */(($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ) => $Create.Map($Create.Any, $Create.Any)); -const $$createType61 = /** @type {(...args: any[]) => any} */(($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ) => $Create.Map($Create.Any, $Create.Any)); -const $$createType62 = /** @type {(...args: any[]) => any} */(($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ) => $Create.Map($Create.Any, $Create.Any)); -const $$createType63 = /** @type {(...args: any[]) => any} */(($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ) => $Create.Map($Create.Any, $Create.Any)); -const $$createType64 = /** @type {(...args: any[]) => any} */(($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ) => $Create.Map($Create.Any, $Create.Any)); -const $$createType65 = /** @type {(...args: any[]) => any} */(($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ) => $Create.Map($Create.Any, $Create.Any)); -const $$createType66 = /** @type {(...args: any[]) => any} */(($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ) => $Create.Map($Create.Any, $Create.Any)); -const $$createType67 = /** @type {(...args: any[]) => any} */(($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ) => $Create.Map($Create.Any, $Create.Any)); -const $$createType68 = /** @type {(...args: any[]) => any} */(($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ) => $Create.Map($Create.Any, $Create.Any)); -const $$createType69 = /** @type {(...args: any[]) => any} */(($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ) => $Create.Map($Create.Any, $Create.Any)); -const $$createType70 = /** @type {(...args: any[]) => any} */(($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ) => $Create.Map($Create.Any, $Create.Any)); -const $$createType71 = /** @type {(...args: any[]) => any} */(($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ) => $Create.Map($Create.Any, $Create.Any)); -const $$createType72 = /** @type {(...args: any[]) => any} */(($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ) => $Create.Map($Create.Any, $Create.Any)); -const $$createType73 = /** @type {(...args: any[]) => any} */(($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ) => $Create.Map($Create.Any, $Create.Any)); -const $$createType74 = /** @type {(...args: any[]) => any} */(($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ) => $Create.Map($Create.Any, $Create.Any)); -const $$createType75 = /** @type {(...args: any[]) => any} */(($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ) => $Create.Map($Create.Any, $Create.Any)); -const $$createType76 = /** @type {(...args: any[]) => any} */(($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ) => $Create.Map($Create.Any, $Create.Any)); -const $$createType77 = $Create.Map($Create.Any, $Create.Any); -const $$createType78 = $Create.Map($Create.Any, $Create.Any); -const $$createType79 = $Create.Map($Create.Any, $Create.Any); diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys/service.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys/service.js deleted file mode 100644 index 870b2804b..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys/service.js +++ /dev/null @@ -1,23 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * @returns {$CancellablePromise<$models.Maps<$models.PointerTextMarshaler, number, number, $models.ValueTextMarshaler, $models.PointerTextMarshaler | null, $models.ValueTextMarshaler, $models.StringType, $models.ValueTextMarshaler, $models.PointerTextMarshaler | null>>} - */ -export function Method() { - return $Call.ByID(4021345184).then(/** @type {($result: any) => any} */(($result) => { - return $$createType0($result); - })); -} - -// Private type creation functions -const $$createType0 = $models.Maps.createFrom($Create.Any, $Create.Any, $Create.Any, $Create.Any, $Create.Any, $Create.Any, $Create.Any, $Create.Any, $Create.Any); diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/marshalers/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/marshalers/index.js deleted file mode 100644 index 8f525252e..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/marshalers/index.js +++ /dev/null @@ -1,116 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as Service from "./service.js"; -export { - Service -}; - -export { - Data, - ImplicitNonMarshaler, - NonMarshaler -} from "./models.js"; - -import * as $models from "./models.js"; - -/** - * any - * @typedef {$models.AliasJsonMarshaler} AliasJsonMarshaler - */ - -/** - * any - * @typedef {$models.AliasMarshaler} AliasMarshaler - */ - -/** - * struct{} - * @typedef {$models.AliasNonMarshaler} AliasNonMarshaler - */ - -/** - * string - * @typedef {$models.AliasTextMarshaler} AliasTextMarshaler - */ - -/** - * any - * @typedef {$models.ImplicitJsonButText} ImplicitJsonButText - */ - -/** - * any - * @typedef {$models.ImplicitJsonMarshaler} ImplicitJsonMarshaler - */ - -/** - * any - * @typedef {$models.ImplicitMarshaler} ImplicitMarshaler - */ - -/** - * string - * @typedef {$models.ImplicitNonJson} ImplicitNonJson - */ - -/** - * any - * @typedef {$models.ImplicitNonText} ImplicitNonText - */ - -/** - * any - * @typedef {$models.ImplicitTextButJson} ImplicitTextButJson - */ - -/** - * string - * @typedef {$models.ImplicitTextMarshaler} ImplicitTextMarshaler - */ - -/** - * any - * @typedef {$models.PointerJsonMarshaler} PointerJsonMarshaler - */ - -/** - * any - * @typedef {$models.PointerMarshaler} PointerMarshaler - */ - -/** - * string - * @typedef {$models.PointerTextMarshaler} PointerTextMarshaler - */ - -/** - * any - * @typedef {$models.UnderlyingJsonMarshaler} UnderlyingJsonMarshaler - */ - -/** - * any - * @typedef {$models.UnderlyingMarshaler} UnderlyingMarshaler - */ - -/** - * string - * @typedef {$models.UnderlyingTextMarshaler} UnderlyingTextMarshaler - */ - -/** - * any - * @typedef {$models.ValueJsonMarshaler} ValueJsonMarshaler - */ - -/** - * any - * @typedef {$models.ValueMarshaler} ValueMarshaler - */ - -/** - * string - * @typedef {$models.ValueTextMarshaler} ValueTextMarshaler - */ diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/marshalers/models.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/marshalers/models.js deleted file mode 100644 index 77fe552ea..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/marshalers/models.js +++ /dev/null @@ -1,630 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Create as $Create } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as encoding$0 from "../../../../../../../../encoding/models.js"; -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as json$0 from "../../../../../../../../encoding/json/models.js"; - -/** - * any - * @typedef {any} AliasJsonMarshaler - */ - -/** - * any - * @typedef {any} AliasMarshaler - */ - -/** - * struct{} - * @typedef { { - * } } AliasNonMarshaler - */ - -/** - * string - * @typedef {string} AliasTextMarshaler - */ - -export class Data { - /** - * Creates a new Data instance. - * @param {Partial} [$$source = {}] - The source object to create the Data. - */ - constructor($$source = {}) { - if (!("NM" in $$source)) { - /** - * @member - * @type {NonMarshaler} - */ - this["NM"] = (new NonMarshaler()); - } - if (!("NMPtr" in $$source)) { - /** - * NonMarshaler | null - * @member - * @type {NonMarshaler | null} - */ - this["NMPtr"] = null; - } - if (!("VJM" in $$source)) { - /** - * @member - * @type {ValueJsonMarshaler} - */ - this["VJM"] = null; - } - if (!("VJMPtr" in $$source)) { - /** - * ValueJsonMarshaler | null - * @member - * @type {ValueJsonMarshaler | null} - */ - this["VJMPtr"] = null; - } - if (!("PJM" in $$source)) { - /** - * @member - * @type {PointerJsonMarshaler} - */ - this["PJM"] = null; - } - if (!("PJMPtr" in $$source)) { - /** - * PointerJsonMarshaler | null - * @member - * @type {PointerJsonMarshaler | null} - */ - this["PJMPtr"] = null; - } - if (!("VTM" in $$source)) { - /** - * @member - * @type {ValueTextMarshaler} - */ - this["VTM"] = ""; - } - if (!("VTMPtr" in $$source)) { - /** - * ValueTextMarshaler | null - * @member - * @type {ValueTextMarshaler | null} - */ - this["VTMPtr"] = null; - } - if (!("PTM" in $$source)) { - /** - * @member - * @type {PointerTextMarshaler} - */ - this["PTM"] = ""; - } - if (!("PTMPtr" in $$source)) { - /** - * PointerTextMarshaler | null - * @member - * @type {PointerTextMarshaler | null} - */ - this["PTMPtr"] = null; - } - if (!("VM" in $$source)) { - /** - * @member - * @type {ValueMarshaler} - */ - this["VM"] = null; - } - if (!("VMPtr" in $$source)) { - /** - * ValueMarshaler | null - * @member - * @type {ValueMarshaler | null} - */ - this["VMPtr"] = null; - } - if (!("PM" in $$source)) { - /** - * @member - * @type {PointerMarshaler} - */ - this["PM"] = null; - } - if (!("PMPtr" in $$source)) { - /** - * PointerMarshaler | null - * @member - * @type {PointerMarshaler | null} - */ - this["PMPtr"] = null; - } - if (!("UJM" in $$source)) { - /** - * @member - * @type {UnderlyingJsonMarshaler} - */ - this["UJM"] = null; - } - if (!("UJMPtr" in $$source)) { - /** - * UnderlyingJsonMarshaler | null - * @member - * @type {UnderlyingJsonMarshaler | null} - */ - this["UJMPtr"] = null; - } - if (!("UTM" in $$source)) { - /** - * @member - * @type {UnderlyingTextMarshaler} - */ - this["UTM"] = ""; - } - if (!("UTMPtr" in $$source)) { - /** - * UnderlyingTextMarshaler | null - * @member - * @type {UnderlyingTextMarshaler | null} - */ - this["UTMPtr"] = null; - } - if (!("UM" in $$source)) { - /** - * @member - * @type {UnderlyingMarshaler} - */ - this["UM"] = null; - } - if (!("UMPtr" in $$source)) { - /** - * UnderlyingMarshaler | null - * @member - * @type {UnderlyingMarshaler | null} - */ - this["UMPtr"] = null; - } - if (!("JM" in $$source)) { - /** - * any - * @member - * @type {any} - */ - this["JM"] = null; - } - if (!("JMPtr" in $$source)) { - /** - * any | null - * @member - * @type {any | null} - */ - this["JMPtr"] = null; - } - if (!("TM" in $$source)) { - /** - * string - * @member - * @type {string} - */ - this["TM"] = ""; - } - if (!("TMPtr" in $$source)) { - /** - * string | null - * @member - * @type {string | null} - */ - this["TMPtr"] = null; - } - if (!("CJM" in $$source)) { - /** - * any - * @member - * @type {any} - */ - this["CJM"] = null; - } - if (!("CJMPtr" in $$source)) { - /** - * any | null - * @member - * @type {any | null} - */ - this["CJMPtr"] = null; - } - if (!("CTM" in $$source)) { - /** - * string - * @member - * @type {string} - */ - this["CTM"] = ""; - } - if (!("CTMPtr" in $$source)) { - /** - * string | null - * @member - * @type {string | null} - */ - this["CTMPtr"] = null; - } - if (!("CM" in $$source)) { - /** - * any - * @member - * @type {any} - */ - this["CM"] = null; - } - if (!("CMPtr" in $$source)) { - /** - * any | null - * @member - * @type {any | null} - */ - this["CMPtr"] = null; - } - if (!("ANM" in $$source)) { - /** - * @member - * @type {AliasNonMarshaler} - */ - this["ANM"] = {}; - } - if (!("ANMPtr" in $$source)) { - /** - * AliasNonMarshaler | null - * @member - * @type {AliasNonMarshaler | null} - */ - this["ANMPtr"] = null; - } - if (!("AJM" in $$source)) { - /** - * @member - * @type {AliasJsonMarshaler} - */ - this["AJM"] = null; - } - if (!("AJMPtr" in $$source)) { - /** - * AliasJsonMarshaler | null - * @member - * @type {AliasJsonMarshaler | null} - */ - this["AJMPtr"] = null; - } - if (!("ATM" in $$source)) { - /** - * @member - * @type {AliasTextMarshaler} - */ - this["ATM"] = ""; - } - if (!("ATMPtr" in $$source)) { - /** - * AliasTextMarshaler | null - * @member - * @type {AliasTextMarshaler | null} - */ - this["ATMPtr"] = null; - } - if (!("AM" in $$source)) { - /** - * @member - * @type {AliasMarshaler} - */ - this["AM"] = null; - } - if (!("AMPtr" in $$source)) { - /** - * AliasMarshaler | null - * @member - * @type {AliasMarshaler | null} - */ - this["AMPtr"] = null; - } - if (!("ImJM" in $$source)) { - /** - * @member - * @type {ImplicitJsonMarshaler} - */ - this["ImJM"] = null; - } - if (!("ImJMPtr" in $$source)) { - /** - * ImplicitJsonMarshaler | null - * @member - * @type {ImplicitJsonMarshaler | null} - */ - this["ImJMPtr"] = null; - } - if (!("ImTM" in $$source)) { - /** - * @member - * @type {ImplicitTextMarshaler} - */ - this["ImTM"] = ""; - } - if (!("ImTMPtr" in $$source)) { - /** - * ImplicitTextMarshaler | null - * @member - * @type {ImplicitTextMarshaler | null} - */ - this["ImTMPtr"] = null; - } - if (!("ImM" in $$source)) { - /** - * @member - * @type {ImplicitMarshaler} - */ - this["ImM"] = null; - } - if (!("ImMPtr" in $$source)) { - /** - * ImplicitMarshaler | null - * @member - * @type {ImplicitMarshaler | null} - */ - this["ImMPtr"] = null; - } - if (!("ImNJ" in $$source)) { - /** - * @member - * @type {ImplicitNonJson} - */ - this["ImNJ"] = ""; - } - if (!("ImNJPtr" in $$source)) { - /** - * ImplicitNonJson | null - * @member - * @type {ImplicitNonJson | null} - */ - this["ImNJPtr"] = null; - } - if (!("ImNT" in $$source)) { - /** - * @member - * @type {ImplicitNonText} - */ - this["ImNT"] = null; - } - if (!("ImNTPtr" in $$source)) { - /** - * ImplicitNonText | null - * @member - * @type {ImplicitNonText | null} - */ - this["ImNTPtr"] = null; - } - if (!("ImNM" in $$source)) { - /** - * @member - * @type {ImplicitNonMarshaler} - */ - this["ImNM"] = (new ImplicitNonMarshaler()); - } - if (!("ImNMPtr" in $$source)) { - /** - * ImplicitNonMarshaler | null - * @member - * @type {ImplicitNonMarshaler | null} - */ - this["ImNMPtr"] = null; - } - if (!("ImJbT" in $$source)) { - /** - * @member - * @type {ImplicitJsonButText} - */ - this["ImJbT"] = null; - } - if (!("ImJbTPtr" in $$source)) { - /** - * ImplicitJsonButText | null - * @member - * @type {ImplicitJsonButText | null} - */ - this["ImJbTPtr"] = null; - } - if (!("ImTbJ" in $$source)) { - /** - * @member - * @type {ImplicitTextButJson} - */ - this["ImTbJ"] = null; - } - if (!("ImTbJPtr" in $$source)) { - /** - * ImplicitTextButJson | null - * @member - * @type {ImplicitTextButJson | null} - */ - this["ImTbJPtr"] = null; - } - - Object.assign(this, $$source); - } - - /** - * Creates a new Data instance from a string or object. - * @param {any} [$$source = {}] - * @returns {Data} - */ - static createFrom($$source = {}) { - const $$createField0_0 = $$createType0; - const $$createField1_0 = $$createType1; - const $$createField48_0 = $$createType2; - const $$createField49_0 = $$createType3; - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - if ("NM" in $$parsedSource) { - $$parsedSource["NM"] = $$createField0_0($$parsedSource["NM"]); - } - if ("NMPtr" in $$parsedSource) { - $$parsedSource["NMPtr"] = $$createField1_0($$parsedSource["NMPtr"]); - } - if ("ImNM" in $$parsedSource) { - $$parsedSource["ImNM"] = $$createField48_0($$parsedSource["ImNM"]); - } - if ("ImNMPtr" in $$parsedSource) { - $$parsedSource["ImNMPtr"] = $$createField49_0($$parsedSource["ImNMPtr"]); - } - return new Data(/** @type {Partial} */($$parsedSource)); - } -} - -/** - * any - * @typedef {any} ImplicitJsonButText - */ - -/** - * any - * @typedef {any} ImplicitJsonMarshaler - */ - -/** - * any - * @typedef {any} ImplicitMarshaler - */ - -/** - * string - * @typedef {string} ImplicitNonJson - */ - -/** - * class{ Marshaler, TextMarshaler } - */ -export class ImplicitNonMarshaler { - /** - * Creates a new ImplicitNonMarshaler instance. - * @param {Partial} [$$source = {}] - The source object to create the ImplicitNonMarshaler. - */ - constructor($$source = {}) { - if (!("Marshaler" in $$source)) { - /** - * @member - * @type {json$0.Marshaler} - */ - this["Marshaler"] = null; - } - if (!("TextMarshaler" in $$source)) { - /** - * @member - * @type {encoding$0.TextMarshaler} - */ - this["TextMarshaler"] = ""; - } - - Object.assign(this, $$source); - } - - /** - * Creates a new ImplicitNonMarshaler instance from a string or object. - * @param {any} [$$source = {}] - * @returns {ImplicitNonMarshaler} - */ - static createFrom($$source = {}) { - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - return new ImplicitNonMarshaler(/** @type {Partial} */($$parsedSource)); - } -} - -/** - * any - * @typedef {any} ImplicitNonText - */ - -/** - * any - * @typedef {any} ImplicitTextButJson - */ - -/** - * string - * @typedef {string} ImplicitTextMarshaler - */ - -/** - * class {} - */ -export class NonMarshaler { - /** - * Creates a new NonMarshaler instance. - * @param {Partial} [$$source = {}] - The source object to create the NonMarshaler. - */ - constructor($$source = {}) { - - Object.assign(this, $$source); - } - - /** - * Creates a new NonMarshaler instance from a string or object. - * @param {any} [$$source = {}] - * @returns {NonMarshaler} - */ - static createFrom($$source = {}) { - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - return new NonMarshaler(/** @type {Partial} */($$parsedSource)); - } -} - -/** - * any - * @typedef {any} PointerJsonMarshaler - */ - -/** - * any - * @typedef {any} PointerMarshaler - */ - -/** - * string - * @typedef {string} PointerTextMarshaler - */ - -/** - * any - * @typedef {any} UnderlyingJsonMarshaler - */ - -/** - * any - * @typedef {any} UnderlyingMarshaler - */ - -/** - * string - * @typedef {string} UnderlyingTextMarshaler - */ - -/** - * any - * @typedef {any} ValueJsonMarshaler - */ - -/** - * any - * @typedef {any} ValueMarshaler - */ - -/** - * string - * @typedef {string} ValueTextMarshaler - */ - -// Private type creation functions -const $$createType0 = NonMarshaler.createFrom; -const $$createType1 = $Create.Nullable($$createType0); -const $$createType2 = ImplicitNonMarshaler.createFrom; -const $$createType3 = $Create.Nullable($$createType2); diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/marshalers/service.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/marshalers/service.js deleted file mode 100644 index 5b415f83e..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/marshalers/service.js +++ /dev/null @@ -1,23 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * @returns {$CancellablePromise<$models.Data>} - */ -export function Method() { - return $Call.ByID(4021345184).then(/** @type {($result: any) => any} */(($result) => { - return $$createType0($result); - })); -} - -// Private type creation functions -const $$createType0 = $models.Data.createFrom; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/index.js deleted file mode 100644 index 9be766c03..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/index.js +++ /dev/null @@ -1,15 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as SomeMethods from "./somemethods.js"; -export { - SomeMethods -}; - -export { - HowDifferent, - Impersonator, - Person, - PrivatePerson -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/models.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/models.js deleted file mode 100644 index c443e292a..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/models.js +++ /dev/null @@ -1,181 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Create as $Create } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as other$0 from "./other/models.js"; - -/** - * HowDifferent is a curious kind of person - * that lets other people decide how they are different. - * @template How - */ -export class HowDifferent { - /** - * Creates a new HowDifferent instance. - * @param {Partial>} [$$source = {}] - The source object to create the HowDifferent. - */ - constructor($$source = {}) { - if (!("Name" in $$source)) { - /** - * They have a name as well. - * @member - * @type {string} - */ - this["Name"] = ""; - } - if (!("Differences" in $$source)) { - /** - * But they may have many differences. - * @member - * @type {{ [_ in string]?: How }[]} - */ - this["Differences"] = []; - } - - Object.assign(this, $$source); - } - - /** - * Given creation functions for each type parameter, - * returns a creation function for a concrete instance - * of the generic class HowDifferent. - * @template [How=any] - * @param {(source: any) => How} $$createParamHow - * @returns {($$source?: any) => HowDifferent} - */ - static createFrom($$createParamHow) { - const $$createField1_0 = $$createType1($$createParamHow); - return ($$source = {}) => { - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - if ("Differences" in $$parsedSource) { - $$parsedSource["Differences"] = $$createField1_0($$parsedSource["Differences"]); - } - return new HowDifferent(/** @type {Partial>} */($$parsedSource)); - }; - } -} - -/** - * Impersonator gets their fields from other people. - */ -export const Impersonator = other$0.OtherPerson; - -/** - * Impersonator gets their fields from other people. - * @typedef {other$0.OtherPerson} Impersonator - */ - -/** - * Person is not a number. - */ -export class Person { - /** - * Creates a new Person instance. - * @param {Partial} [$$source = {}] - The source object to create the Person. - */ - constructor($$source = {}) { - if (!("Name" in $$source)) { - /** - * They have a name. - * @member - * @type {string} - */ - this["Name"] = ""; - } - if (!("Friends" in $$source)) { - /** - * Exactly 4 sketchy friends. - * @member - * @type {Impersonator[]} - */ - this["Friends"] = Array.from({ length: 4 }, () => (new Impersonator())); - } - - Object.assign(this, $$source); - } - - /** - * Creates a new Person instance from a string or object. - * @param {any} [$$source = {}] - * @returns {Person} - */ - static createFrom($$source = {}) { - const $$createField1_0 = $$createType3; - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - if ("Friends" in $$parsedSource) { - $$parsedSource["Friends"] = $$createField1_0($$parsedSource["Friends"]); - } - return new Person(/** @type {Partial} */($$parsedSource)); - } -} - -export class personImpl { - /** - * Creates a new personImpl instance. - * @param {Partial} [$$source = {}] - The source object to create the personImpl. - */ - constructor($$source = {}) { - if (!("Nickname" in $$source)) { - /** - * Nickname conceals a person's identity. - * @member - * @type {string} - */ - this["Nickname"] = ""; - } - if (!("Name" in $$source)) { - /** - * They have a name. - * @member - * @type {string} - */ - this["Name"] = ""; - } - if (!("Friends" in $$source)) { - /** - * Exactly 4 sketchy friends. - * @member - * @type {Impersonator[]} - */ - this["Friends"] = Array.from({ length: 4 }, () => (new Impersonator())); - } - - Object.assign(this, $$source); - } - - /** - * Creates a new personImpl instance from a string or object. - * @param {any} [$$source = {}] - * @returns {personImpl} - */ - static createFrom($$source = {}) { - const $$createField2_0 = $$createType3; - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - if ("Friends" in $$parsedSource) { - $$parsedSource["Friends"] = $$createField2_0($$parsedSource["Friends"]); - } - return new personImpl(/** @type {Partial} */($$parsedSource)); - } -} - -/** - * PrivatePerson gets their fields from hidden sources. - */ -export const PrivatePerson = personImpl; - -/** - * PrivatePerson gets their fields from hidden sources. - * @typedef {personImpl} PrivatePerson - */ - -// Private type creation functions -const $$createType0 = /** @type {(...args: any[]) => any} */(($$createParamHow) => $Create.Map($Create.Any, $$createParamHow)); -const $$createType1 = /** @type {(...args: any[]) => any} */(($$createParamHow) => $Create.Array($$createType0($$createParamHow))); -const $$createType2 = other$0.OtherPerson.createFrom($Create.Any); -const $$createType3 = $Create.Array($$createType2); diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/more/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/more/index.js deleted file mode 100644 index c3eabd022..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/more/index.js +++ /dev/null @@ -1,10 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as $models from "./models.js"; - -/** - * StringPtr is a nullable string. - * @typedef {$models.StringPtr} StringPtr - */ diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/more/models.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/more/models.js deleted file mode 100644 index b4fdacf8e..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/more/models.js +++ /dev/null @@ -1,12 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Create as $Create } from "/wails/runtime.js"; - -/** - * StringPtr is a nullable string. - * @typedef {string | null} StringPtr - */ diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/other/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/other/index.js deleted file mode 100644 index db4e64147..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/other/index.js +++ /dev/null @@ -1,12 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as OtherMethods from "./othermethods.js"; -export { - OtherMethods -}; - -export { - OtherPerson -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/other/models.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/other/models.js deleted file mode 100644 index 89992cacf..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/other/models.js +++ /dev/null @@ -1,60 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Create as $Create } from "/wails/runtime.js"; - -/** - * OtherPerson is like a person, but different. - * @template T - */ -export class OtherPerson { - /** - * Creates a new OtherPerson instance. - * @param {Partial>} [$$source = {}] - The source object to create the OtherPerson. - */ - constructor($$source = {}) { - if (!("Name" in $$source)) { - /** - * They have a name as well. - * @member - * @type {string} - */ - this["Name"] = ""; - } - if (!("Differences" in $$source)) { - /** - * But they may have many differences. - * @member - * @type {T[]} - */ - this["Differences"] = []; - } - - Object.assign(this, $$source); - } - - /** - * Given creation functions for each type parameter, - * returns a creation function for a concrete instance - * of the generic class OtherPerson. - * @template [T=any] - * @param {(source: any) => T} $$createParamT - * @returns {($$source?: any) => OtherPerson} - */ - static createFrom($$createParamT) { - const $$createField1_0 = $$createType0($$createParamT); - return ($$source = {}) => { - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - if ("Differences" in $$parsedSource) { - $$parsedSource["Differences"] = $$createField1_0($$parsedSource["Differences"]); - } - return new OtherPerson(/** @type {Partial>} */($$parsedSource)); - }; - } -} - -// Private type creation functions -const $$createType0 = /** @type {(...args: any[]) => any} */(($$createParamT) => $Create.Array($$createParamT)); diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/other/othermethods.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/other/othermethods.js deleted file mode 100644 index 36b25c183..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/other/othermethods.js +++ /dev/null @@ -1,20 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * OtherMethods has another method, but through a private embedded type. - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -/** - * LikeThisOtherOne does nothing as well, but is different. - * @returns {$CancellablePromise} - */ -export function LikeThisOtherOne() { - return $Call.ByID(3606939272); -} diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/somemethods.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/somemethods.js deleted file mode 100644 index a87ccf6c4..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/somemethods.js +++ /dev/null @@ -1,42 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * SomeMethods exports some methods. - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * LikeThisOne is an example method that does nothing. - * @returns {$CancellablePromise<[$models.Person, $models.HowDifferent, $models.PrivatePerson]>} - */ -export function LikeThisOne() { - return $Call.ByID(2124352079).then(/** @type {($result: any) => any} */(($result) => { - $result[0] = $$createType0($result[0]); - $result[1] = $$createType1($result[1]); - $result[2] = $$createType2($result[2]); - return $result; - })); -} - -/** - * LikeThisOtherOne does nothing as well, but is different. - * @returns {$CancellablePromise} - */ -export function LikeThisOtherOne() { - return $Call.ByID(4281222271); -} - -// Private type creation functions -const $$createType0 = $models.Person.createFrom; -const $$createType1 = $models.HowDifferent.createFrom($Create.Any); -const $$createType2 = $models.personImpl.createFrom; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/out_of_tree/embedother.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/out_of_tree/embedother.js deleted file mode 100644 index 5fb44fbc6..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/out_of_tree/embedother.js +++ /dev/null @@ -1,20 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * EmbedOther is even trickier. - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -/** - * LikeThisOtherOne does nothing as well, but is different. - * @returns {$CancellablePromise} - */ -export function LikeThisOtherOne() { - return $Call.ByID(3566862802); -} diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/out_of_tree/embedservice.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/out_of_tree/embedservice.js deleted file mode 100644 index 5ec6c820e..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/out_of_tree/embedservice.js +++ /dev/null @@ -1,42 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * EmbedService is tricky. - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as nobindingshere$0 from "../no_bindings_here/models.js"; - -/** - * LikeThisOne is an example method that does nothing. - * @returns {$CancellablePromise<[nobindingshere$0.Person, nobindingshere$0.HowDifferent, nobindingshere$0.PrivatePerson]>} - */ -export function LikeThisOne() { - return $Call.ByID(2590614085).then(/** @type {($result: any) => any} */(($result) => { - $result[0] = $$createType0($result[0]); - $result[1] = $$createType1($result[1]); - $result[2] = $$createType2($result[2]); - return $result; - })); -} - -/** - * LikeThisOtherOne does nothing as well, but is different. - * @returns {$CancellablePromise} - */ -export function LikeThisOtherOne() { - return $Call.ByID(773650321); -} - -// Private type creation functions -const $$createType0 = nobindingshere$0.Person.createFrom; -const $$createType1 = nobindingshere$0.HowDifferent.createFrom($Create.Any); -const $$createType2 = nobindingshere$0.personImpl.createFrom; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/out_of_tree/greetservice.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/out_of_tree/greetservice.js deleted file mode 100644 index 8afbd8b3a..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/out_of_tree/greetservice.js +++ /dev/null @@ -1,21 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -/** - * Greet someone - * @param {string} $0 - * @returns {$CancellablePromise} - */ -export function Greet($0) { - return $Call.ByID(1411160069, $0); -} diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/out_of_tree/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/out_of_tree/index.js deleted file mode 100644 index 734fb02e7..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/out_of_tree/index.js +++ /dev/null @@ -1,12 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as EmbedOther from "./embedother.js"; -import * as EmbedService from "./embedservice.js"; -import * as GreetService from "./greetservice.js"; -export { - EmbedOther, - EmbedService, - GreetService -}; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple/greetservice.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple/greetservice.js deleted file mode 100644 index e50a4a6ab..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple/greetservice.js +++ /dev/null @@ -1,15 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -/** - * @param {string} name - * @returns {$CancellablePromise} - */ -export function Greet(name) { - return $Call.ByID(1411160069, name); -} diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple/index.js deleted file mode 100644 index 62ddbc166..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple/index.js +++ /dev/null @@ -1,10 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -import * as OtherService from "./otherservice.js"; -export { - GreetService, - OtherService -}; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple/otherservice.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple/otherservice.js deleted file mode 100644 index f017774d8..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple/otherservice.js +++ /dev/null @@ -1,14 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -/** - * @returns {$CancellablePromise} - */ -export function Hello() { - return $Call.ByID(4249972365); -} diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_files/greetservice.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_files/greetservice.js deleted file mode 100644 index e50a4a6ab..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_files/greetservice.js +++ /dev/null @@ -1,15 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -/** - * @param {string} name - * @returns {$CancellablePromise} - */ -export function Greet(name) { - return $Call.ByID(1411160069, name); -} diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_files/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_files/index.js deleted file mode 100644 index 62ddbc166..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_files/index.js +++ /dev/null @@ -1,10 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -import * as OtherService from "./otherservice.js"; -export { - GreetService, - OtherService -}; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_files/otherservice.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_files/otherservice.js deleted file mode 100644 index f017774d8..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_files/otherservice.js +++ /dev/null @@ -1,14 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -/** - * @returns {$CancellablePromise} - */ -export function Hello() { - return $Call.ByID(4249972365); -} diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_other/greetservice.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_other/greetservice.js deleted file mode 100644 index 50737a34b..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_other/greetservice.js +++ /dev/null @@ -1,40 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * Greet does XYZ - * @param {string} name - * @returns {$CancellablePromise} - */ -export function Greet(name) { - return $Call.ByID(1411160069, name); -} - -/** - * NewPerson creates a new person - * @param {string} name - * @returns {$CancellablePromise<$models.Person | null>} - */ -export function NewPerson(name) { - return $Call.ByID(1661412647, name).then(/** @type {($result: any) => any} */(($result) => { - return $$createType1($result); - })); -} - -// Private type creation functions -const $$createType0 = $models.Person.createFrom; -const $$createType1 = $Create.Nullable($$createType0); diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_other/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_other/index.js deleted file mode 100644 index fefe6b6ba..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_other/index.js +++ /dev/null @@ -1,12 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; - -export { - Person -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_other/models.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_other/models.js deleted file mode 100644 index 04771d2ca..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_other/models.js +++ /dev/null @@ -1,54 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Create as $Create } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as services$0 from "./services/models.js"; - -export class Person { - /** - * Creates a new Person instance. - * @param {Partial} [$$source = {}] - The source object to create the Person. - */ - constructor($$source = {}) { - if (!("Name" in $$source)) { - /** - * @member - * @type {string} - */ - this["Name"] = ""; - } - if (!("Address" in $$source)) { - /** - * @member - * @type {services$0.Address | null} - */ - this["Address"] = null; - } - - Object.assign(this, $$source); - } - - /** - * Creates a new Person instance from a string or object. - * @param {any} [$$source = {}] - * @returns {Person} - */ - static createFrom($$source = {}) { - const $$createField1_0 = $$createType1; - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - if ("Address" in $$parsedSource) { - $$parsedSource["Address"] = $$createField1_0($$parsedSource["Address"]); - } - return new Person(/** @type {Partial} */($$parsedSource)); - } -} - -// Private type creation functions -const $$createType0 = services$0.Address.createFrom; -const $$createType1 = $Create.Nullable($$createType0); diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_other/services/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_other/services/index.js deleted file mode 100644 index ed65b6d15..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_other/services/index.js +++ /dev/null @@ -1,12 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as OtherService from "./otherservice.js"; -export { - OtherService -}; - -export { - Address -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_other/services/models.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_other/services/models.js deleted file mode 100644 index 24a5de807..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_other/services/models.js +++ /dev/null @@ -1,49 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Create as $Create } from "/wails/runtime.js"; - -export class Address { - /** - * Creates a new Address instance. - * @param {Partial
                    } [$$source = {}] - The source object to create the Address. - */ - constructor($$source = {}) { - if (!("Street" in $$source)) { - /** - * @member - * @type {string} - */ - this["Street"] = ""; - } - if (!("State" in $$source)) { - /** - * @member - * @type {string} - */ - this["State"] = ""; - } - if (!("Country" in $$source)) { - /** - * @member - * @type {string} - */ - this["Country"] = ""; - } - - Object.assign(this, $$source); - } - - /** - * Creates a new Address instance from a string or object. - * @param {any} [$$source = {}] - * @returns {Address} - */ - static createFrom($$source = {}) { - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - return new Address(/** @type {Partial
                    } */($$parsedSource)); - } -} diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_other/services/otherservice.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_other/services/otherservice.js deleted file mode 100644 index 24dc0334e..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_other/services/otherservice.js +++ /dev/null @@ -1,31 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * OtherService is a struct - * that does things - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * Yay does this and that - * @returns {$CancellablePromise<$models.Address | null>} - */ -export function Yay() { - return $Call.ByID(3568225479).then(/** @type {($result: any) => any} */(($result) => { - return $$createType1($result); - })); -} - -// Private type creation functions -const $$createType0 = $models.Address.createFrom; -const $$createType1 = $Create.Nullable($$createType0); diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_non_pointer_single/greetservice.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_non_pointer_single/greetservice.js deleted file mode 100644 index d4501598a..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_non_pointer_single/greetservice.js +++ /dev/null @@ -1,379 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * @param {number[]} $in - * @returns {$CancellablePromise} - */ -export function ArrayInt($in) { - return $Call.ByID(3862002418, $in); -} - -/** - * @param {boolean} $in - * @returns {$CancellablePromise} - */ -export function BoolInBoolOut($in) { - return $Call.ByID(2424639793, $in); -} - -/** - * @param {number} $in - * @returns {$CancellablePromise} - */ -export function Float32InFloat32Out($in) { - return $Call.ByID(3132595881, $in); -} - -/** - * @param {number} $in - * @returns {$CancellablePromise} - */ -export function Float64InFloat64Out($in) { - return $Call.ByID(2182412247, $in); -} - -/** - * Greet someone - * @param {string} name - * @returns {$CancellablePromise} - */ -export function Greet(name) { - return $Call.ByID(1411160069, name); -} - -/** - * @param {number} $in - * @returns {$CancellablePromise} - */ -export function Int16InIntOut($in) { - return $Call.ByID(3306292566, $in); -} - -/** - * @param {number | null} $in - * @returns {$CancellablePromise} - */ -export function Int16PointerInAndOutput($in) { - return $Call.ByID(1754277916, $in); -} - -/** - * @param {number} $in - * @returns {$CancellablePromise} - */ -export function Int32InIntOut($in) { - return $Call.ByID(1909469092, $in); -} - -/** - * @param {number | null} $in - * @returns {$CancellablePromise} - */ -export function Int32PointerInAndOutput($in) { - return $Call.ByID(4251088558, $in); -} - -/** - * @param {number} $in - * @returns {$CancellablePromise} - */ -export function Int64InIntOut($in) { - return $Call.ByID(1343888303, $in); -} - -/** - * @param {number | null} $in - * @returns {$CancellablePromise} - */ -export function Int64PointerInAndOutput($in) { - return $Call.ByID(2205561041, $in); -} - -/** - * @param {number} $in - * @returns {$CancellablePromise} - */ -export function Int8InIntOut($in) { - return $Call.ByID(572240879, $in); -} - -/** - * @param {number | null} $in - * @returns {$CancellablePromise} - */ -export function Int8PointerInAndOutput($in) { - return $Call.ByID(2189402897, $in); -} - -/** - * @param {number} $in - * @returns {$CancellablePromise} - */ -export function IntInIntOut($in) { - return $Call.ByID(642881729, $in); -} - -/** - * @param {number | null} $in - * @returns {$CancellablePromise} - */ -export function IntPointerInAndOutput($in) { - return $Call.ByID(1066151743, $in); -} - -/** - * @param {number | null} $in - * @returns {$CancellablePromise} - */ -export function IntPointerInputNamedOutputs($in) { - return $Call.ByID(2718999663, $in); -} - -/** - * @param {{ [_ in `${number}`]?: number }} $in - * @returns {$CancellablePromise} - */ -export function MapIntInt($in) { - return $Call.ByID(2386486356, $in); -} - -/** - * @param {{ [_ in `${number}`]?: number | null }} $in - * @returns {$CancellablePromise} - */ -export function MapIntIntPointer($in) { - return $Call.ByID(2163571325, $in); -} - -/** - * @param {{ [_ in `${number}`]?: number[] }} $in - * @returns {$CancellablePromise} - */ -export function MapIntSliceInt($in) { - return $Call.ByID(2900172572, $in); -} - -/** - * @param {{ [_ in `${number}`]?: number[] }} $in - * @returns {$CancellablePromise<{ [_ in `${number}`]?: number[] }>} - */ -export function MapIntSliceIntInMapIntSliceIntOut($in) { - return $Call.ByID(881980169, $in).then(/** @type {($result: any) => any} */(($result) => { - return $$createType1($result); - })); -} - -/** - * @returns {$CancellablePromise} - */ -export function NoInputsStringOut() { - return $Call.ByID(1075577233); -} - -/** - * @param {boolean | null} $in - * @returns {$CancellablePromise} - */ -export function PointerBoolInBoolOut($in) { - return $Call.ByID(3589606958, $in); -} - -/** - * @param {number | null} $in - * @returns {$CancellablePromise} - */ -export function PointerFloat32InFloat32Out($in) { - return $Call.ByID(224675106, $in); -} - -/** - * @param {number | null} $in - * @returns {$CancellablePromise} - */ -export function PointerFloat64InFloat64Out($in) { - return $Call.ByID(2124953624, $in); -} - -/** - * @param {{ [_ in `${number}`]?: number } | null} $in - * @returns {$CancellablePromise} - */ -export function PointerMapIntInt($in) { - return $Call.ByID(3516977899, $in); -} - -/** - * @param {string | null} $in - * @returns {$CancellablePromise} - */ -export function PointerStringInStringOut($in) { - return $Call.ByID(229603958, $in); -} - -/** - * @param {string[]} $in - * @returns {$CancellablePromise} - */ -export function StringArrayInputNamedOutput($in) { - return $Call.ByID(3678582682, $in).then(/** @type {($result: any) => any} */(($result) => { - return $$createType2($result); - })); -} - -/** - * @param {string[]} $in - * @returns {$CancellablePromise} - */ -export function StringArrayInputNamedOutputs($in) { - return $Call.ByID(319259595, $in).then(/** @type {($result: any) => any} */(($result) => { - return $$createType2($result); - })); -} - -/** - * @param {string[]} $in - * @returns {$CancellablePromise} - */ -export function StringArrayInputStringArrayOut($in) { - return $Call.ByID(383995060, $in).then(/** @type {($result: any) => any} */(($result) => { - return $$createType2($result); - })); -} - -/** - * @param {string[]} $in - * @returns {$CancellablePromise} - */ -export function StringArrayInputStringOut($in) { - return $Call.ByID(1091960237, $in); -} - -/** - * @param {$models.Person} $in - * @returns {$CancellablePromise<$models.Person>} - */ -export function StructInputStructOutput($in) { - return $Call.ByID(3835643147, $in).then(/** @type {($result: any) => any} */(($result) => { - return $$createType3($result); - })); -} - -/** - * @param {$models.Person | null} $in - * @returns {$CancellablePromise} - */ -export function StructPointerInputErrorOutput($in) { - return $Call.ByID(2447692557, $in); -} - -/** - * @param {$models.Person | null} $in - * @returns {$CancellablePromise<$models.Person | null>} - */ -export function StructPointerInputStructPointerOutput($in) { - return $Call.ByID(2943477349, $in).then(/** @type {($result: any) => any} */(($result) => { - return $$createType4($result); - })); -} - -/** - * @param {number} $in - * @returns {$CancellablePromise} - */ -export function UInt16InUIntOut($in) { - return $Call.ByID(3401034892, $in); -} - -/** - * @param {number | null} $in - * @returns {$CancellablePromise} - */ -export function UInt16PointerInAndOutput($in) { - return $Call.ByID(1236957573, $in); -} - -/** - * @param {number} $in - * @returns {$CancellablePromise} - */ -export function UInt32InUIntOut($in) { - return $Call.ByID(1160383782, $in); -} - -/** - * @param {number | null} $in - * @returns {$CancellablePromise} - */ -export function UInt32PointerInAndOutput($in) { - return $Call.ByID(1739300671, $in); -} - -/** - * @param {number} $in - * @returns {$CancellablePromise} - */ -export function UInt64InUIntOut($in) { - return $Call.ByID(793803239, $in); -} - -/** - * @param {number | null} $in - * @returns {$CancellablePromise} - */ -export function UInt64PointerInAndOutput($in) { - return $Call.ByID(1403757716, $in); -} - -/** - * @param {number} $in - * @returns {$CancellablePromise} - */ -export function UInt8InUIntOut($in) { - return $Call.ByID(2988345717, $in); -} - -/** - * @param {number | null} $in - * @returns {$CancellablePromise} - */ -export function UInt8PointerInAndOutput($in) { - return $Call.ByID(518250834, $in); -} - -/** - * @param {number} $in - * @returns {$CancellablePromise} - */ -export function UIntInUIntOut($in) { - return $Call.ByID(2836661285, $in); -} - -/** - * @param {number | null} $in - * @returns {$CancellablePromise} - */ -export function UIntPointerInAndOutput($in) { - return $Call.ByID(1367187362, $in); -} - -// Private type creation functions -const $$createType0 = $Create.Array($Create.Any); -const $$createType1 = $Create.Map($Create.Any, $$createType0); -const $$createType2 = $Create.Array($Create.Any); -const $$createType3 = $models.Person.createFrom; -const $$createType4 = $Create.Nullable($$createType3); diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_non_pointer_single/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_non_pointer_single/index.js deleted file mode 100644 index fefe6b6ba..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_non_pointer_single/index.js +++ /dev/null @@ -1,12 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; - -export { - Person -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_non_pointer_single/models.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_non_pointer_single/models.js deleted file mode 100644 index 69c96370a..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_non_pointer_single/models.js +++ /dev/null @@ -1,57 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Create as $Create } from "/wails/runtime.js"; - -export class Person { - /** - * Creates a new Person instance. - * @param {Partial} [$$source = {}] - The source object to create the Person. - */ - constructor($$source = {}) { - if (!("Name" in $$source)) { - /** - * @member - * @type {string} - */ - this["Name"] = ""; - } - if (!("Parent" in $$source)) { - /** - * @member - * @type {Person | null} - */ - this["Parent"] = null; - } - if (!("Details" in $$source)) { - /** - * @member - * @type {{"Age": number, "Address": {"Street": string}}} - */ - this["Details"] = {"Age": 0, "Address": {"Street": ""}}; - } - - Object.assign(this, $$source); - } - - /** - * Creates a new Person instance from a string or object. - * @param {any} [$$source = {}] - * @returns {Person} - */ - static createFrom($$source = {}) { - const $$createField1_0 = $$createType1; - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - if ("Parent" in $$parsedSource) { - $$parsedSource["Parent"] = $$createField1_0($$parsedSource["Parent"]); - } - return new Person(/** @type {Partial} */($$parsedSource)); - } -} - -// Private type creation functions -const $$createType0 = Person.createFrom; -const $$createType1 = $Create.Nullable($$createType0); diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_single/greetservice.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_single/greetservice.js deleted file mode 100644 index d4501598a..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_single/greetservice.js +++ /dev/null @@ -1,379 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * @param {number[]} $in - * @returns {$CancellablePromise} - */ -export function ArrayInt($in) { - return $Call.ByID(3862002418, $in); -} - -/** - * @param {boolean} $in - * @returns {$CancellablePromise} - */ -export function BoolInBoolOut($in) { - return $Call.ByID(2424639793, $in); -} - -/** - * @param {number} $in - * @returns {$CancellablePromise} - */ -export function Float32InFloat32Out($in) { - return $Call.ByID(3132595881, $in); -} - -/** - * @param {number} $in - * @returns {$CancellablePromise} - */ -export function Float64InFloat64Out($in) { - return $Call.ByID(2182412247, $in); -} - -/** - * Greet someone - * @param {string} name - * @returns {$CancellablePromise} - */ -export function Greet(name) { - return $Call.ByID(1411160069, name); -} - -/** - * @param {number} $in - * @returns {$CancellablePromise} - */ -export function Int16InIntOut($in) { - return $Call.ByID(3306292566, $in); -} - -/** - * @param {number | null} $in - * @returns {$CancellablePromise} - */ -export function Int16PointerInAndOutput($in) { - return $Call.ByID(1754277916, $in); -} - -/** - * @param {number} $in - * @returns {$CancellablePromise} - */ -export function Int32InIntOut($in) { - return $Call.ByID(1909469092, $in); -} - -/** - * @param {number | null} $in - * @returns {$CancellablePromise} - */ -export function Int32PointerInAndOutput($in) { - return $Call.ByID(4251088558, $in); -} - -/** - * @param {number} $in - * @returns {$CancellablePromise} - */ -export function Int64InIntOut($in) { - return $Call.ByID(1343888303, $in); -} - -/** - * @param {number | null} $in - * @returns {$CancellablePromise} - */ -export function Int64PointerInAndOutput($in) { - return $Call.ByID(2205561041, $in); -} - -/** - * @param {number} $in - * @returns {$CancellablePromise} - */ -export function Int8InIntOut($in) { - return $Call.ByID(572240879, $in); -} - -/** - * @param {number | null} $in - * @returns {$CancellablePromise} - */ -export function Int8PointerInAndOutput($in) { - return $Call.ByID(2189402897, $in); -} - -/** - * @param {number} $in - * @returns {$CancellablePromise} - */ -export function IntInIntOut($in) { - return $Call.ByID(642881729, $in); -} - -/** - * @param {number | null} $in - * @returns {$CancellablePromise} - */ -export function IntPointerInAndOutput($in) { - return $Call.ByID(1066151743, $in); -} - -/** - * @param {number | null} $in - * @returns {$CancellablePromise} - */ -export function IntPointerInputNamedOutputs($in) { - return $Call.ByID(2718999663, $in); -} - -/** - * @param {{ [_ in `${number}`]?: number }} $in - * @returns {$CancellablePromise} - */ -export function MapIntInt($in) { - return $Call.ByID(2386486356, $in); -} - -/** - * @param {{ [_ in `${number}`]?: number | null }} $in - * @returns {$CancellablePromise} - */ -export function MapIntIntPointer($in) { - return $Call.ByID(2163571325, $in); -} - -/** - * @param {{ [_ in `${number}`]?: number[] }} $in - * @returns {$CancellablePromise} - */ -export function MapIntSliceInt($in) { - return $Call.ByID(2900172572, $in); -} - -/** - * @param {{ [_ in `${number}`]?: number[] }} $in - * @returns {$CancellablePromise<{ [_ in `${number}`]?: number[] }>} - */ -export function MapIntSliceIntInMapIntSliceIntOut($in) { - return $Call.ByID(881980169, $in).then(/** @type {($result: any) => any} */(($result) => { - return $$createType1($result); - })); -} - -/** - * @returns {$CancellablePromise} - */ -export function NoInputsStringOut() { - return $Call.ByID(1075577233); -} - -/** - * @param {boolean | null} $in - * @returns {$CancellablePromise} - */ -export function PointerBoolInBoolOut($in) { - return $Call.ByID(3589606958, $in); -} - -/** - * @param {number | null} $in - * @returns {$CancellablePromise} - */ -export function PointerFloat32InFloat32Out($in) { - return $Call.ByID(224675106, $in); -} - -/** - * @param {number | null} $in - * @returns {$CancellablePromise} - */ -export function PointerFloat64InFloat64Out($in) { - return $Call.ByID(2124953624, $in); -} - -/** - * @param {{ [_ in `${number}`]?: number } | null} $in - * @returns {$CancellablePromise} - */ -export function PointerMapIntInt($in) { - return $Call.ByID(3516977899, $in); -} - -/** - * @param {string | null} $in - * @returns {$CancellablePromise} - */ -export function PointerStringInStringOut($in) { - return $Call.ByID(229603958, $in); -} - -/** - * @param {string[]} $in - * @returns {$CancellablePromise} - */ -export function StringArrayInputNamedOutput($in) { - return $Call.ByID(3678582682, $in).then(/** @type {($result: any) => any} */(($result) => { - return $$createType2($result); - })); -} - -/** - * @param {string[]} $in - * @returns {$CancellablePromise} - */ -export function StringArrayInputNamedOutputs($in) { - return $Call.ByID(319259595, $in).then(/** @type {($result: any) => any} */(($result) => { - return $$createType2($result); - })); -} - -/** - * @param {string[]} $in - * @returns {$CancellablePromise} - */ -export function StringArrayInputStringArrayOut($in) { - return $Call.ByID(383995060, $in).then(/** @type {($result: any) => any} */(($result) => { - return $$createType2($result); - })); -} - -/** - * @param {string[]} $in - * @returns {$CancellablePromise} - */ -export function StringArrayInputStringOut($in) { - return $Call.ByID(1091960237, $in); -} - -/** - * @param {$models.Person} $in - * @returns {$CancellablePromise<$models.Person>} - */ -export function StructInputStructOutput($in) { - return $Call.ByID(3835643147, $in).then(/** @type {($result: any) => any} */(($result) => { - return $$createType3($result); - })); -} - -/** - * @param {$models.Person | null} $in - * @returns {$CancellablePromise} - */ -export function StructPointerInputErrorOutput($in) { - return $Call.ByID(2447692557, $in); -} - -/** - * @param {$models.Person | null} $in - * @returns {$CancellablePromise<$models.Person | null>} - */ -export function StructPointerInputStructPointerOutput($in) { - return $Call.ByID(2943477349, $in).then(/** @type {($result: any) => any} */(($result) => { - return $$createType4($result); - })); -} - -/** - * @param {number} $in - * @returns {$CancellablePromise} - */ -export function UInt16InUIntOut($in) { - return $Call.ByID(3401034892, $in); -} - -/** - * @param {number | null} $in - * @returns {$CancellablePromise} - */ -export function UInt16PointerInAndOutput($in) { - return $Call.ByID(1236957573, $in); -} - -/** - * @param {number} $in - * @returns {$CancellablePromise} - */ -export function UInt32InUIntOut($in) { - return $Call.ByID(1160383782, $in); -} - -/** - * @param {number | null} $in - * @returns {$CancellablePromise} - */ -export function UInt32PointerInAndOutput($in) { - return $Call.ByID(1739300671, $in); -} - -/** - * @param {number} $in - * @returns {$CancellablePromise} - */ -export function UInt64InUIntOut($in) { - return $Call.ByID(793803239, $in); -} - -/** - * @param {number | null} $in - * @returns {$CancellablePromise} - */ -export function UInt64PointerInAndOutput($in) { - return $Call.ByID(1403757716, $in); -} - -/** - * @param {number} $in - * @returns {$CancellablePromise} - */ -export function UInt8InUIntOut($in) { - return $Call.ByID(2988345717, $in); -} - -/** - * @param {number | null} $in - * @returns {$CancellablePromise} - */ -export function UInt8PointerInAndOutput($in) { - return $Call.ByID(518250834, $in); -} - -/** - * @param {number} $in - * @returns {$CancellablePromise} - */ -export function UIntInUIntOut($in) { - return $Call.ByID(2836661285, $in); -} - -/** - * @param {number | null} $in - * @returns {$CancellablePromise} - */ -export function UIntPointerInAndOutput($in) { - return $Call.ByID(1367187362, $in); -} - -// Private type creation functions -const $$createType0 = $Create.Array($Create.Any); -const $$createType1 = $Create.Map($Create.Any, $$createType0); -const $$createType2 = $Create.Array($Create.Any); -const $$createType3 = $models.Person.createFrom; -const $$createType4 = $Create.Nullable($$createType3); diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_single/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_single/index.js deleted file mode 100644 index fefe6b6ba..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_single/index.js +++ /dev/null @@ -1,12 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; - -export { - Person -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_single/models.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_single/models.js deleted file mode 100644 index 69c96370a..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_single/models.js +++ /dev/null @@ -1,57 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Create as $Create } from "/wails/runtime.js"; - -export class Person { - /** - * Creates a new Person instance. - * @param {Partial} [$$source = {}] - The source object to create the Person. - */ - constructor($$source = {}) { - if (!("Name" in $$source)) { - /** - * @member - * @type {string} - */ - this["Name"] = ""; - } - if (!("Parent" in $$source)) { - /** - * @member - * @type {Person | null} - */ - this["Parent"] = null; - } - if (!("Details" in $$source)) { - /** - * @member - * @type {{"Age": number, "Address": {"Street": string}}} - */ - this["Details"] = {"Age": 0, "Address": {"Street": ""}}; - } - - Object.assign(this, $$source); - } - - /** - * Creates a new Person instance from a string or object. - * @param {any} [$$source = {}] - * @returns {Person} - */ - static createFrom($$source = {}) { - const $$createField1_0 = $$createType1; - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - if ("Parent" in $$parsedSource) { - $$parsedSource["Parent"] = $$createField1_0($$parsedSource["Parent"]); - } - return new Person(/** @type {Partial} */($$parsedSource)); - } -} - -// Private type creation functions -const $$createType0 = Person.createFrom; -const $$createType1 = $Create.Nullable($$createType0); diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single/greetservice.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single/greetservice.js deleted file mode 100644 index 9dfe48511..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single/greetservice.js +++ /dev/null @@ -1,21 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -/** - * Greet someone - * @param {string} name - * @returns {$CancellablePromise} - */ -export function Greet(name) { - return $Call.ByID(1411160069, name); -} diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single/index.js deleted file mode 100644 index fdf1ff435..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single/index.js +++ /dev/null @@ -1,8 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_function/greetservice.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_function/greetservice.js deleted file mode 100644 index 9dfe48511..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_function/greetservice.js +++ /dev/null @@ -1,21 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -/** - * Greet someone - * @param {string} name - * @returns {$CancellablePromise} - */ -export function Greet(name) { - return $Call.ByID(1411160069, name); -} diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_function/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_function/index.js deleted file mode 100644 index fdf1ff435..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_function/index.js +++ /dev/null @@ -1,8 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_other_function/greetservice.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_other_function/greetservice.js deleted file mode 100644 index 50737a34b..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_other_function/greetservice.js +++ /dev/null @@ -1,40 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * Greet does XYZ - * @param {string} name - * @returns {$CancellablePromise} - */ -export function Greet(name) { - return $Call.ByID(1411160069, name); -} - -/** - * NewPerson creates a new person - * @param {string} name - * @returns {$CancellablePromise<$models.Person | null>} - */ -export function NewPerson(name) { - return $Call.ByID(1661412647, name).then(/** @type {($result: any) => any} */(($result) => { - return $$createType1($result); - })); -} - -// Private type creation functions -const $$createType0 = $models.Person.createFrom; -const $$createType1 = $Create.Nullable($$createType0); diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_other_function/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_other_function/index.js deleted file mode 100644 index fefe6b6ba..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_other_function/index.js +++ /dev/null @@ -1,12 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; - -export { - Person -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_other_function/models.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_other_function/models.js deleted file mode 100644 index d7bfe75cf..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_other_function/models.js +++ /dev/null @@ -1,58 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Create as $Create } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as services$0 from "./services/models.js"; - -/** - * Person is a person! - * They have a name and an address - */ -export class Person { - /** - * Creates a new Person instance. - * @param {Partial} [$$source = {}] - The source object to create the Person. - */ - constructor($$source = {}) { - if (!("Name" in $$source)) { - /** - * @member - * @type {string} - */ - this["Name"] = ""; - } - if (!("Address" in $$source)) { - /** - * @member - * @type {services$0.Address | null} - */ - this["Address"] = null; - } - - Object.assign(this, $$source); - } - - /** - * Creates a new Person instance from a string or object. - * @param {any} [$$source = {}] - * @returns {Person} - */ - static createFrom($$source = {}) { - const $$createField1_0 = $$createType1; - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - if ("Address" in $$parsedSource) { - $$parsedSource["Address"] = $$createField1_0($$parsedSource["Address"]); - } - return new Person(/** @type {Partial} */($$parsedSource)); - } -} - -// Private type creation functions -const $$createType0 = services$0.Address.createFrom; -const $$createType1 = $Create.Nullable($$createType0); diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_other_function/services/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_other_function/services/index.js deleted file mode 100644 index ed65b6d15..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_other_function/services/index.js +++ /dev/null @@ -1,12 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as OtherService from "./otherservice.js"; -export { - OtherService -}; - -export { - Address -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_other_function/services/models.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_other_function/services/models.js deleted file mode 100644 index 24a5de807..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_other_function/services/models.js +++ /dev/null @@ -1,49 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Create as $Create } from "/wails/runtime.js"; - -export class Address { - /** - * Creates a new Address instance. - * @param {Partial
                    } [$$source = {}] - The source object to create the Address. - */ - constructor($$source = {}) { - if (!("Street" in $$source)) { - /** - * @member - * @type {string} - */ - this["Street"] = ""; - } - if (!("State" in $$source)) { - /** - * @member - * @type {string} - */ - this["State"] = ""; - } - if (!("Country" in $$source)) { - /** - * @member - * @type {string} - */ - this["Country"] = ""; - } - - Object.assign(this, $$source); - } - - /** - * Creates a new Address instance from a string or object. - * @param {any} [$$source = {}] - * @returns {Address} - */ - static createFrom($$source = {}) { - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - return new Address(/** @type {Partial
                    } */($$parsedSource)); - } -} diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_other_function/services/otherservice.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_other_function/services/otherservice.js deleted file mode 100644 index de3c9d51d..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_other_function/services/otherservice.js +++ /dev/null @@ -1,31 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * OtherService is a struct - * that does things - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * Yay does this and that - * @returns {$CancellablePromise<$models.Address | null>} - */ -export function Yay() { - return $Call.ByID(1491748400).then(/** @type {($result: any) => any} */(($result) => { - return $$createType1($result); - })); -} - -// Private type creation functions -const $$createType0 = $models.Address.createFrom; -const $$createType1 = $Create.Nullable($$createType0); diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/warnings.log b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/warnings.log deleted file mode 100644 index ce8369307..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=false/warnings.log +++ /dev/null @@ -1,83 +0,0 @@ -[warn] /testcases/complex_json/main.go:127:2: event 'collision' has one of multiple definitions here with data type map[string]int -[warn] /testcases/events_only/events.go:20:2: event 'collision' has one of multiple definitions here with data type int -[warn] /testcases/events_only/events.go:21:2: `application.RegisterEvent` called here with non-constant event name -[warn] /testcases/events_only/other.go:10:5: `application.RegisterEvent` is instantiated here but not called -[warn] /testcases/events_only/other.go:13:2: `application.RegisterEvent` called here with non-constant event name -[warn] /testcases/events_only/other.go:17:2: data type []T for event 'parametric' contains unresolved type parameters and will be ignored` -[warn] /testcases/events_only/other.go:22:2: event 'common:ApplicationStarted' is a known system event and cannot be overridden; this call to `application.RegisterEvent` will panic -[warn] /testcases/marshalers/main.go:212:2: event 'collision' has one of multiple definitions here with data type *struct{Field []bool} -[warn] /testcases/marshalers/main.go:214:2: data type encoding/json.Marshaler for event 'interface' is a non-empty interface: emitting events from the frontend with data other than `null` is not supported by encoding/json and will likely result in runtime errors -[warn] dynamically registered event names are not discoverable by the binding generator: it is recommended to invoke `application.RegisterEvent` with constant arguments only -[warn] event 'collision' has multiple conflicting definitions and will be ignored -[warn] events registered through indirect calls are not discoverable by the binding generator: it is recommended to invoke `application.RegisterEvent` directly -[warn] generic wrappers for calls to `application.RegisterEvent` are not analysable by the binding generator: it is recommended to call `application.RegisterEvent` with concrete types only -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *R is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *S is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *T is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *U is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *V is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *X is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *Y is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *Z is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *any is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *complex64 is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *encoding.TextMarshaler is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *float32 is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.CustomInterface is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.EmbeddedInterface is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.InterfaceAlias is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.InterfacePtrAlias is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.InterfacePtrType is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.InterfaceType is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.NonTextMarshaler is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.PointerPtrAlias is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.PointerPtrType is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.PointerType is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.ValuePtrAlias is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.ValuePtrType is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.ValueType is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *int is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *string is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *uint is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type R is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type T is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type W is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type any is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type bool is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type complex64 is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type float32 is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.BadTildeCstrAlias[T] is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.BadTildeCstrAlias[struct{}] is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.BadTildeCstrPtrAlias[T] is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.BadTildeCstrPtrAlias[struct{}] is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.BasicCstrPtrAlias[S] is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.BasicCstrPtrAlias[int] is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.ComparableCstrAlias[R] is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.ComparableCstrAlias[github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.PointerTextMarshaler] is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.ComparableCstrPtrAlias[R] is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.ComparableCstrPtrAlias[int] is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.EmbeddedPointer is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.GoodTildeCstrPtrAlias[U] is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.InterfaceCstrPtrAlias[*github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.PointerTextMarshaler] is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.InterfaceCstrPtrAlias[Y] is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.InterfaceCstrPtrAlias[encoding.TextMarshaler] is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.InterfacePtrAlias is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.InterfacePtrType is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.MixedCstrPtrAlias[X] is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.MixedCstrPtrAlias[github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.StringType] is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.NonBasicCstrPtrAlias[*github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.PointerTextMarshaler] is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.NonBasicCstrPtrAlias[V] is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.NonTextMarshaler is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.PointableCstrAlias[W] is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.PointableCstrAlias[github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.PointerTextMarshaler] is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.PointerAlias is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.PointerCstrPtrAlias[R, Z] is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.PointerCstrPtrAlias[github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.PointerTextMarshaler, *github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.PointerTextMarshaler] is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.PointerCstrPtrAlias[github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.ValueTextMarshaler, *github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.ValueTextMarshaler] is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.PointerPtrType is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.PointerTextMarshaler is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.PointerType is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.ValuePtrType is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.ValueType is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.WrongAlias is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.WrongType is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/encoding/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/encoding/index.js deleted file mode 100644 index cf48d86db..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/encoding/index.js +++ /dev/null @@ -1,13 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as $models from "./models.js"; - -/** - * TextMarshaler is the interface implemented by an object that can - * marshal itself into a textual form. - * - * MarshalText encodes the receiver into UTF-8-encoded text and returns the result. - * @typedef {$models.TextMarshaler} TextMarshaler - */ diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/encoding/json/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/encoding/json/index.js deleted file mode 100644 index 22f1fd904..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/encoding/json/index.js +++ /dev/null @@ -1,11 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as $models from "./models.js"; - -/** - * Marshaler is the interface implemented by types that - * can marshal themselves into valid JSON. - * @typedef {$models.Marshaler} Marshaler - */ diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/encoding/json/models.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/encoding/json/models.js deleted file mode 100644 index 96abf0ef1..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/encoding/json/models.js +++ /dev/null @@ -1,13 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Create as $Create } from "/wails/runtime.js"; - -/** - * Marshaler is the interface implemented by types that - * can marshal themselves into valid JSON. - * @typedef {any} Marshaler - */ diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/encoding/models.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/encoding/models.js deleted file mode 100644 index 59cfef5bd..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/encoding/models.js +++ /dev/null @@ -1,15 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Create as $Create } from "/wails/runtime.js"; - -/** - * TextMarshaler is the interface implemented by an object that can - * marshal itself into a textual form. - * - * MarshalText encodes the receiver into UTF-8-encoded text and returns the result. - * @typedef {any} TextMarshaler - */ diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/eventcreate.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/eventcreate.js deleted file mode 100644 index 9cc7781aa..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/eventcreate.js +++ /dev/null @@ -1,39 +0,0 @@ -//@ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Create as $Create } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as json$0 from "../../../../../encoding/json/models.js"; -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as events_only$0 from "./generator/testcases/events_only/models.js"; -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as more$0 from "./generator/testcases/no_bindings_here/more/models.js"; - -function configure() { - Object.freeze(Object.assign($Create.Events, { - "events_only:class": $$createType0, - "events_only:map": $$createType2, - "events_only:other": $$createType3, - "overlap": $$createType6, - })); -} - -// Private type creation functions -const $$createType0 = events_only$0.SomeClass.createFrom; -const $$createType1 = $Create.Array($Create.Any); -const $$createType2 = $Create.Map($Create.Any, $$createType1); -const $$createType3 = $Create.Array($Create.Any); -const $$createType4 = $Create.Array($Create.Any); -const $$createType5 = $Create.Struct({ - "Field": $$createType4, -}); -const $$createType6 = $Create.Nullable($$createType5); - -configure(); diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/eventdata.d.ts b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/eventdata.d.ts deleted file mode 100644 index 3e53d9287..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/eventdata.d.ts +++ /dev/null @@ -1,30 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import type { Events } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import type * as json$0 from "../../../../../encoding/json/models.js"; -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import type * as events_only$0 from "./generator/testcases/events_only/models.js"; -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import type * as more$0 from "./generator/testcases/no_bindings_here/more/models.js"; - -declare module "/wails/runtime.js" { - namespace Events { - interface CustomEvents { - "events_only:class": events_only$0.SomeClass; - "events_only:map": { [_ in string]?: number[] }; - "events_only:nodata": void; - "events_only:other": more$0.StringPtr[]; - "events_only:string": string; - "interface": json$0.Marshaler; - "overlap": {"Field": boolean[]} | null; - } - } -} diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/aliases/greetservice.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/aliases/greetservice.js deleted file mode 100644 index 72760c645..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/aliases/greetservice.js +++ /dev/null @@ -1,110 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as subpkg$0 from "./subpkg/models.js"; -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as nobindingshere$0 from "../no_bindings_here/models.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * Get someone. - * @param {$models.Alias} aliasValue - * @returns {$CancellablePromise<$models.Person>} - */ -export function Get(aliasValue) { - return $Call.ByName("main.GreetService.Get", aliasValue).then(/** @type {($result: any) => any} */(($result) => { - return $$createType0($result); - })); -} - -/** - * Apparently, aliases are all the rage right now. - * @param {$models.AliasedPerson} p - * @returns {$CancellablePromise<$models.StrangelyAliasedPerson>} - */ -export function GetButAliased(p) { - return $Call.ByName("main.GreetService.GetButAliased", p).then(/** @type {($result: any) => any} */(($result) => { - return $$createType0($result); - })); -} - -/** - * Get someone quite different. - * @returns {$CancellablePromise<$models.GenericPerson>} - */ -export function GetButDifferent() { - return $Call.ByName("main.GreetService.GetButDifferent").then(/** @type {($result: any) => any} */(($result) => { - return $$createType1($result); - })); -} - -/** - * @returns {$CancellablePromise} - */ -export function GetButForeignPrivateAlias() { - return $Call.ByName("main.GreetService.GetButForeignPrivateAlias").then(/** @type {($result: any) => any} */(($result) => { - return $$createType2($result); - })); -} - -/** - * @returns {$CancellablePromise<$models.AliasGroup>} - */ -export function GetButGenericAliases() { - return $Call.ByName("main.GreetService.GetButGenericAliases").then(/** @type {($result: any) => any} */(($result) => { - return $$createType3($result); - })); -} - -/** - * @returns {$CancellablePromise<$models.SubPackageAlias>} - */ -export function GetButSubPackageAlias() { - return $Call.ByName("main.GreetService.GetButSubPackageAlias").then(/** @type {($result: any) => any} */(($result) => { - return $$createType4($result); - })); -} - -/** - * Greet a lot of unusual things. - * @param {$models.EmptyAliasStruct} $0 - * @param {$models.EmptyStruct} $1 - * @returns {$CancellablePromise<$models.AliasStruct>} - */ -export function Greet($0, $1) { - return $Call.ByName("main.GreetService.Greet", $0, $1).then(/** @type {($result: any) => any} */(($result) => { - return $$createType8($result); - })); -} - -// Private type creation functions -const $$createType0 = $models.Person.createFrom; -const $$createType1 = $models.GenericPerson.createFrom($Create.Any); -const $$createType2 = nobindingshere$0.personImpl.createFrom; -const $$createType3 = $models.AliasGroup.createFrom; -const $$createType4 = subpkg$0.SubStruct.createFrom; -const $$createType5 = $Create.Array($Create.Any); -const $$createType6 = $Create.Array($Create.Any); -const $$createType7 = $Create.Struct({ - "NoMoreIdeas": $$createType6, -}); -const $$createType8 = $Create.Struct({ - "Foo": $$createType5, - "Other": $$createType7, -}); diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/aliases/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/aliases/index.js deleted file mode 100644 index acfbc8a9b..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/aliases/index.js +++ /dev/null @@ -1,62 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; - -export { - AliasGroup, - AliasedPerson, - EmptyStruct, - GenericPerson, - GenericPersonAlias, - IndirectPersonAlias, - Person, - StrangelyAliasedPerson, - SubPackageAlias, - TPIndirectPersonAlias -} from "./models.js"; - -import * as $models from "./models.js"; - -/** - * A nice type Alias. - * @typedef {$models.Alias} Alias - */ - -/** - * A struct alias. - * This should be rendered as a typedef or interface in every mode. - * @typedef {$models.AliasStruct} AliasStruct - */ - -/** - * An empty struct alias. - * @typedef {$models.EmptyAliasStruct} EmptyAliasStruct - */ - -/** - * A generic alias that forwards to a type parameter. - * @template T - * @typedef {$models.GenericAlias} GenericAlias - */ - -/** - * A generic alias that wraps a map. - * @template T,U - * @typedef {$models.GenericMapAlias} GenericMapAlias - */ - -/** - * A generic alias that wraps a pointer type. - * @template T - * @typedef {$models.GenericPtrAlias} GenericPtrAlias - */ - -/** - * Another struct alias. - * @typedef {$models.OtherAliasStruct} OtherAliasStruct - */ diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/aliases/models.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/aliases/models.js deleted file mode 100644 index 31bb61c83..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/aliases/models.js +++ /dev/null @@ -1,360 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Create as $Create } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as subpkg$0 from "./subpkg/models.js"; - -/** - * A nice type Alias. - * @typedef {number} Alias - */ - -/** - * A class whose fields have various aliased types. - */ -export class AliasGroup { - /** - * Creates a new AliasGroup instance. - * @param {Partial} [$$source = {}] - The source object to create the AliasGroup. - */ - constructor($$source = {}) { - if (!("GAi" in $$source)) { - /** - * @member - * @type {GenericAlias} - */ - this["GAi"] = 0; - } - if (!("GAP" in $$source)) { - /** - * @member - * @type {GenericAlias>} - */ - this["GAP"] = (new GenericPerson()); - } - if (!("GPAs" in $$source)) { - /** - * @member - * @type {GenericPtrAlias} - */ - this["GPAs"] = null; - } - if (!("GPAP" in $$source)) { - /** - * @member - * @type {GenericPtrAlias>} - */ - this["GPAP"] = null; - } - if (!("GMA" in $$source)) { - /** - * @member - * @type {GenericMapAlias} - */ - this["GMA"] = {}; - } - if (!("GPA" in $$source)) { - /** - * @member - * @type {GenericPersonAlias} - */ - this["GPA"] = (new GenericPersonAlias()); - } - if (!("IPA" in $$source)) { - /** - * @member - * @type {IndirectPersonAlias} - */ - this["IPA"] = (new IndirectPersonAlias()); - } - if (!("TPIPA" in $$source)) { - /** - * @member - * @type {TPIndirectPersonAlias} - */ - this["TPIPA"] = (new TPIndirectPersonAlias()); - } - if (!("SPA" in $$source)) { - /** - * @member - * @type {SubPackageAlias} - */ - this["SPA"] = (new SubPackageAlias()); - } - - Object.assign(this, $$source); - } - - /** - * Creates a new AliasGroup instance from a string or object. - * @param {any} [$$source = {}] - * @returns {AliasGroup} - */ - static createFrom($$source = {}) { - const $$createField1_0 = $$createType0; - const $$createField2_0 = $$createType2; - const $$createField3_0 = $$createType5; - const $$createField4_0 = $$createType6; - const $$createField5_0 = $$createType8; - const $$createField6_0 = $$createType8; - const $$createField7_0 = $$createType0; - const $$createField8_0 = $$createType9; - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - if ("GAP" in $$parsedSource) { - $$parsedSource["GAP"] = $$createField1_0($$parsedSource["GAP"]); - } - if ("GPAs" in $$parsedSource) { - $$parsedSource["GPAs"] = $$createField2_0($$parsedSource["GPAs"]); - } - if ("GPAP" in $$parsedSource) { - $$parsedSource["GPAP"] = $$createField3_0($$parsedSource["GPAP"]); - } - if ("GMA" in $$parsedSource) { - $$parsedSource["GMA"] = $$createField4_0($$parsedSource["GMA"]); - } - if ("GPA" in $$parsedSource) { - $$parsedSource["GPA"] = $$createField5_0($$parsedSource["GPA"]); - } - if ("IPA" in $$parsedSource) { - $$parsedSource["IPA"] = $$createField6_0($$parsedSource["IPA"]); - } - if ("TPIPA" in $$parsedSource) { - $$parsedSource["TPIPA"] = $$createField7_0($$parsedSource["TPIPA"]); - } - if ("SPA" in $$parsedSource) { - $$parsedSource["SPA"] = $$createField8_0($$parsedSource["SPA"]); - } - return new AliasGroup(/** @type {Partial} */($$parsedSource)); - } -} - -/** - * A struct alias. - * This should be rendered as a typedef or interface in every mode. - * @typedef {Object} AliasStruct - * @property {number[]} Foo - A field with a comment. - * @property {string} [Bar] - Definitely not Foo. - * @property {string} [Baz] - Definitely not Foo. - * @property {OtherAliasStruct} Other - A nested alias struct. - */ - -/** - * An empty struct alias. - * @typedef { { - * } } EmptyAliasStruct - */ - -/** - * An empty struct. - */ -export class EmptyStruct { - /** - * Creates a new EmptyStruct instance. - * @param {Partial} [$$source = {}] - The source object to create the EmptyStruct. - */ - constructor($$source = {}) { - - Object.assign(this, $$source); - } - - /** - * Creates a new EmptyStruct instance from a string or object. - * @param {any} [$$source = {}] - * @returns {EmptyStruct} - */ - static createFrom($$source = {}) { - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - return new EmptyStruct(/** @type {Partial} */($$parsedSource)); - } -} - -/** - * A generic alias that forwards to a type parameter. - * @template T - * @typedef {T} GenericAlias - */ - -/** - * A generic alias that wraps a map. - * @template T,U - * @typedef {{ [_ in string]?: U }} GenericMapAlias - */ - -/** - * A generic struct containing an alias. - * @template T - */ -export class GenericPerson { - /** - * Creates a new GenericPerson instance. - * @param {Partial>} [$$source = {}] - The source object to create the GenericPerson. - */ - constructor($$source = {}) { - if (/** @type {any} */(false)) { - /** - * @member - * @type {T | undefined} - */ - this["Name"] = undefined; - } - if (!("AliasedField" in $$source)) { - /** - * @member - * @type {Alias} - */ - this["AliasedField"] = 0; - } - - Object.assign(this, $$source); - } - - /** - * Given creation functions for each type parameter, - * returns a creation function for a concrete instance - * of the generic class GenericPerson. - * @template [T=any] - * @param {(source: any) => T} $$createParamT - * @returns {($$source?: any) => GenericPerson} - */ - static createFrom($$createParamT) { - const $$createField0_0 = $$createParamT; - return ($$source = {}) => { - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - if ("Name" in $$parsedSource) { - $$parsedSource["Name"] = $$createField0_0($$parsedSource["Name"]); - } - return new GenericPerson(/** @type {Partial>} */($$parsedSource)); - }; - } -} - -/** - * A generic alias that wraps a generic struct. - */ -export const GenericPersonAlias = GenericPerson; - -/** - * A generic alias that wraps a generic struct. - * @template T - * @typedef {GenericPerson[]>} GenericPersonAlias - */ - -/** - * A generic alias that wraps a pointer type. - * @template T - * @typedef {GenericAlias | null} GenericPtrAlias - */ - -/** - * An alias that wraps a class through a non-typeparam alias. - */ -export const IndirectPersonAlias = GenericPersonAlias; - -/** - * An alias that wraps a class through a non-typeparam alias. - * @typedef {GenericPersonAlias} IndirectPersonAlias - */ - -/** - * Another struct alias. - * @typedef {Object} OtherAliasStruct - * @property {number[]} NoMoreIdeas - */ - -/** - * A non-generic struct containing an alias. - */ -export class Person { - /** - * Creates a new Person instance. - * @param {Partial} [$$source = {}] - The source object to create the Person. - */ - constructor($$source = {}) { - if (!("Name" in $$source)) { - /** - * The Person's name. - * @member - * @type {string} - */ - this["Name"] = ""; - } - if (!("AliasedField" in $$source)) { - /** - * A random alias field. - * @member - * @type {Alias} - */ - this["AliasedField"] = 0; - } - - Object.assign(this, $$source); - } - - /** - * Creates a new Person instance from a string or object. - * @param {any} [$$source = {}] - * @returns {Person} - */ - static createFrom($$source = {}) { - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - return new Person(/** @type {Partial} */($$parsedSource)); - } -} - -/** - * A class alias. - */ -export const AliasedPerson = Person; - -/** - * A class alias. - * @typedef {Person} AliasedPerson - */ - -/** - * Another class alias, but ordered after its aliased class. - */ -export const StrangelyAliasedPerson = Person; - -/** - * Another class alias, but ordered after its aliased class. - * @typedef {Person} StrangelyAliasedPerson - */ - -/** - * An alias referencing another package that is not used elsewhere. - */ -export const SubPackageAlias = subpkg$0.SubStruct; - -/** - * An alias referencing another package that is not used elsewhere. - * @typedef {subpkg$0.SubStruct} SubPackageAlias - */ - -/** - * An alias that wraps a class through a typeparam alias. - */ -export const TPIndirectPersonAlias = GenericPerson; - -/** - * An alias that wraps a class through a typeparam alias. - * @typedef {GenericAlias>} TPIndirectPersonAlias - */ - -// Private type creation functions -const $$createType0 = GenericPerson.createFrom($Create.Any); -const $$createType1 = $Create.Array($Create.Any); -const $$createType2 = $Create.Nullable($$createType1); -const $$createType3 = $Create.Array($Create.Any); -const $$createType4 = GenericPerson.createFrom($$createType3); -const $$createType5 = $Create.Nullable($$createType4); -const $$createType6 = $Create.Map($Create.Any, $Create.Any); -const $$createType7 = $Create.Array($Create.Any); -const $$createType8 = GenericPerson.createFrom($$createType7); -const $$createType9 = subpkg$0.SubStruct.createFrom; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/aliases/subpkg/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/aliases/subpkg/index.js deleted file mode 100644 index a3d65abcf..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/aliases/subpkg/index.js +++ /dev/null @@ -1,7 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -export { - SubStruct -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/aliases/subpkg/models.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/aliases/subpkg/models.js deleted file mode 100644 index c582d6149..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/aliases/subpkg/models.js +++ /dev/null @@ -1,45 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Create as $Create } from "/wails/runtime.js"; - -/** - * SubStruct is a type in a subpackage that is only referenced through an alias. - */ -export class SubStruct { - /** - * Creates a new SubStruct instance. - * @param {Partial} [$$source = {}] - The source object to create the SubStruct. - */ - constructor($$source = {}) { - if (!("SomeField" in $$source)) { - /** - * @member - * @type {string[]} - */ - this["SomeField"] = []; - } - - Object.assign(this, $$source); - } - - /** - * Creates a new SubStruct instance from a string or object. - * @param {any} [$$source = {}] - * @returns {SubStruct} - */ - static createFrom($$source = {}) { - const $$createField0_0 = $$createType0; - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - if ("SomeField" in $$parsedSource) { - $$parsedSource["SomeField"] = $$createField0_0($$parsedSource["SomeField"]); - } - return new SubStruct(/** @type {Partial} */($$parsedSource)); - } -} - -// Private type creation functions -const $$createType0 = $Create.Array($Create.Any); diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_expressions/config/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_expressions/config/index.js deleted file mode 100644 index f6c839720..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_expressions/config/index.js +++ /dev/null @@ -1,10 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as Service7 from "./service7.js"; -import * as Service9 from "./service9.js"; -export { - Service7, - Service9 -}; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_expressions/config/service7.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_expressions/config/service7.js deleted file mode 100644 index 54e794649..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_expressions/config/service7.js +++ /dev/null @@ -1,14 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -/** - * @returns {$CancellablePromise} - */ -export function TestMethod() { - return $Call.ByName("github.com/wailsapp/wails/v3/internal/generator/testcases/complex_expressions/config.Service7.TestMethod"); -} diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_expressions/config/service9.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_expressions/config/service9.js deleted file mode 100644 index f6e8901a9..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_expressions/config/service9.js +++ /dev/null @@ -1,14 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -/** - * @returns {$CancellablePromise} - */ -export function TestMethod2() { - return $Call.ByName("github.com/wailsapp/wails/v3/internal/generator/testcases/complex_expressions/config.Service9.TestMethod2"); -} diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_json/greetservice.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_json/greetservice.js deleted file mode 100644 index b5c320f3d..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_json/greetservice.js +++ /dev/null @@ -1,26 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * Greet does XYZ - * @param {$models.Person} person - * @param {$models.Embedded1} emb - * @returns {$CancellablePromise} - */ -export function Greet(person, emb) { - return $Call.ByName("main.GreetService.Greet", person, emb); -} diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_json/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_json/index.js deleted file mode 100644 index ab78e5ea3..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_json/index.js +++ /dev/null @@ -1,20 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; - -export { - Embedded1, - Person, - Title -} from "./models.js"; - -import * as $models from "./models.js"; - -/** - * @typedef {$models.Embedded3} Embedded3 - */ diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_json/models.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_json/models.js deleted file mode 100644 index 7a0edf1c7..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_json/models.js +++ /dev/null @@ -1,272 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Create as $Create } from "/wails/runtime.js"; - -export class Embedded1 { - /** - * Creates a new Embedded1 instance. - * @param {Partial} [$$source = {}] - The source object to create the Embedded1. - */ - constructor($$source = {}) { - if (!("Friends" in $$source)) { - /** - * Friends should be shadowed in Person by a field of lesser depth - * @member - * @type {number} - */ - this["Friends"] = 0; - } - if (!("Vanish" in $$source)) { - /** - * Vanish should be omitted from Person because there is another field with same depth and no tag - * @member - * @type {number} - */ - this["Vanish"] = 0; - } - if (!("StillThere" in $$source)) { - /** - * StillThere should be shadowed in Person by other field with same depth and a json tag - * @member - * @type {string} - */ - this["StillThere"] = ""; - } - if (!("NamingThingsIsHard" in $$source)) { - /** - * NamingThingsIsHard is a law of programming - * @member - * @type {`${boolean}`} - */ - this["NamingThingsIsHard"] = "false"; - } - - Object.assign(this, $$source); - } - - /** - * Creates a new Embedded1 instance from a string or object. - * @param {any} [$$source = {}] - * @returns {Embedded1} - */ - static createFrom($$source = {}) { - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - return new Embedded1(/** @type {Partial} */($$parsedSource)); - } -} - -/** - * @typedef {string} Embedded3 - */ - -/** - * Person represents a person - */ -export class Person { - /** - * Creates a new Person instance. - * @param {Partial} [$$source = {}] - The source object to create the Person. - */ - constructor($$source = {}) { - if (/** @type {any} */(false)) { - /** - * Titles is optional in JSON - * @member - * @type {Title[] | undefined} - */ - this["Titles"] = undefined; - } - if (!("Names" in $$source)) { - /** - * Names has a - * multiline comment - * @member - * @type {string[]} - */ - this["Names"] = []; - } - if (!("Partner" in $$source)) { - /** - * Partner has a custom and complex JSON key - * @member - * @type {Person | null} - */ - this["Partner"] = null; - } - if (!("Friends" in $$source)) { - /** - * @member - * @type {(Person | null)[]} - */ - this["Friends"] = []; - } - if (!("NamingThingsIsHard" in $$source)) { - /** - * NamingThingsIsHard is a law of programming - * @member - * @type {`${boolean}`} - */ - this["NamingThingsIsHard"] = "false"; - } - if (!("StillThere" in $$source)) { - /** - * StillThereButRenamed should shadow in Person the other field with same depth and no json tag - * @member - * @type {Embedded3 | null} - */ - this["StillThere"] = null; - } - if (!("-" in $$source)) { - /** - * StrangeNumber maps to "-" - * @member - * @type {number} - */ - this["-"] = 0; - } - if (!("Embedded3" in $$source)) { - /** - * Embedded3 should appear with key "Embedded3" - * @member - * @type {Embedded3} - */ - this["Embedded3"] = ""; - } - if (!("StrangerNumber" in $$source)) { - /** - * StrangerNumber is serialized as a string - * @member - * @type {`${number}`} - */ - this["StrangerNumber"] = "0"; - } - if (/** @type {any} */(false)) { - /** - * StrangestString is optional and serialized as a JSON string - * @member - * @type {`"${string}"` | undefined} - */ - this["StrangestString"] = undefined; - } - if (/** @type {any} */(false)) { - /** - * StringStrangest is serialized as a JSON string and optional - * @member - * @type {`"${string}"` | undefined} - */ - this["StringStrangest"] = undefined; - } - if (/** @type {any} */(false)) { - /** - * embedded4 should be optional and appear with key "emb4" - * @member - * @type {embedded4 | undefined} - */ - this["emb4"] = undefined; - } - - Object.assign(this, $$source); - } - - /** - * Creates a new Person instance from a string or object. - * @param {any} [$$source = {}] - * @returns {Person} - */ - static createFrom($$source = {}) { - const $$createField0_0 = $$createType0; - const $$createField1_0 = $$createType1; - const $$createField2_0 = $$createType3; - const $$createField3_0 = $$createType4; - const $$createField11_0 = $$createType5; - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - if ("Titles" in $$parsedSource) { - $$parsedSource["Titles"] = $$createField0_0($$parsedSource["Titles"]); - } - if ("Names" in $$parsedSource) { - $$parsedSource["Names"] = $$createField1_0($$parsedSource["Names"]); - } - if ("Partner" in $$parsedSource) { - $$parsedSource["Partner"] = $$createField2_0($$parsedSource["Partner"]); - } - if ("Friends" in $$parsedSource) { - $$parsedSource["Friends"] = $$createField3_0($$parsedSource["Friends"]); - } - if ("emb4" in $$parsedSource) { - $$parsedSource["emb4"] = $$createField11_0($$parsedSource["emb4"]); - } - return new Person(/** @type {Partial} */($$parsedSource)); - } -} - -/** - * Title is a title - * @readonly - * @enum {string} - */ -export const Title = { - /** - * The Go zero value for the underlying type of the enum. - */ - $zero: "", - - /** - * Mister is a title - */ - Mister: "Mr", - Miss: "Miss", - Ms: "Ms", - Mrs: "Mrs", - Dr: "Dr", -}; - -export class embedded4 { - /** - * Creates a new embedded4 instance. - * @param {Partial} [$$source = {}] - The source object to create the embedded4. - */ - constructor($$source = {}) { - if (!("NamingThingsIsHard" in $$source)) { - /** - * NamingThingsIsHard is a law of programming - * @member - * @type {`${boolean}`} - */ - this["NamingThingsIsHard"] = "false"; - } - if (!("Friends" in $$source)) { - /** - * Friends should not be shadowed in Person as embedded4 is not embedded - * from encoding/json's point of view; - * however, it should be shadowed in Embedded1 - * @member - * @type {boolean} - */ - this["Friends"] = false; - } - - Object.assign(this, $$source); - } - - /** - * Creates a new embedded4 instance from a string or object. - * @param {any} [$$source = {}] - * @returns {embedded4} - */ - static createFrom($$source = {}) { - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - return new embedded4(/** @type {Partial} */($$parsedSource)); - } -} - -// Private type creation functions -const $$createType0 = $Create.Array($Create.Any); -const $$createType1 = $Create.Array($Create.Any); -const $$createType2 = Person.createFrom; -const $$createType3 = $Create.Nullable($$createType2); -const $$createType4 = $Create.Array($$createType3); -const $$createType5 = embedded4.createFrom; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_method/greetservice.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_method/greetservice.js deleted file mode 100644 index 979c8281d..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_method/greetservice.js +++ /dev/null @@ -1,40 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * Greet does XYZ - * It has a multiline doc comment - * The comment has even some * / traps!! - * @param {string} str - * @param {$models.Person[]} people - * @param {{"AnotherCount": number, "AnotherOne": $models.Person | null}} $2 - * @param {{ [_ in `${number}`]?: boolean | null }} assoc - * @param {(number | null)[]} $4 - * @param {string[]} other - * @returns {$CancellablePromise<[$models.Person, any, number[]]>} - */ -export function Greet(str, people, $2, assoc, $4, ...other) { - return $Call.ByName("main.GreetService.Greet", str, people, $2, assoc, $4, other).then(/** @type {($result: any) => any} */(($result) => { - $result[0] = $$createType0($result[0]); - $result[2] = $$createType1($result[2]); - return $result; - })); -} - -// Private type creation functions -const $$createType0 = $models.Person.createFrom; -const $$createType1 = $Create.Array($Create.Any); diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_method/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_method/index.js deleted file mode 100644 index fefe6b6ba..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_method/index.js +++ /dev/null @@ -1,12 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; - -export { - Person -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_method/models.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_method/models.js deleted file mode 100644 index 82af81baf..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_method/models.js +++ /dev/null @@ -1,38 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Create as $Create } from "/wails/runtime.js"; - -/** - * Person represents a person - */ -export class Person { - /** - * Creates a new Person instance. - * @param {Partial} [$$source = {}] - The source object to create the Person. - */ - constructor($$source = {}) { - if (!("Name" in $$source)) { - /** - * @member - * @type {string} - */ - this["Name"] = ""; - } - - Object.assign(this, $$source); - } - - /** - * Creates a new Person instance from a string or object. - * @param {any} [$$source = {}] - * @returns {Person} - */ - static createFrom($$source = {}) { - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - return new Person(/** @type {Partial} */($$parsedSource)); - } -} diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/cyclic_imports/greetservice.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/cyclic_imports/greetservice.js deleted file mode 100644 index 651fd2d97..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/cyclic_imports/greetservice.js +++ /dev/null @@ -1,32 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * Make a cycle. - * @returns {$CancellablePromise<[$models.StructA, $models.StructC]>} - */ -export function MakeCycles() { - return $Call.ByName("main.GreetService.MakeCycles").then(/** @type {($result: any) => any} */(($result) => { - $result[0] = $$createType0($result[0]); - $result[1] = $$createType1($result[1]); - return $result; - })); -} - -// Private type creation functions -const $$createType0 = $models.StructA.createFrom; -const $$createType1 = $models.StructC.createFrom; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/cyclic_imports/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/cyclic_imports/index.js deleted file mode 100644 index 0ad0efb4e..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/cyclic_imports/index.js +++ /dev/null @@ -1,14 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; - -export { - StructA, - StructC, - StructE -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/cyclic_imports/models.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/cyclic_imports/models.js deleted file mode 100644 index f24f5a2c9..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/cyclic_imports/models.js +++ /dev/null @@ -1,164 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Create as $Create } from "/wails/runtime.js"; - -export class StructA { - /** - * Creates a new StructA instance. - * @param {Partial} [$$source = {}] - The source object to create the StructA. - */ - constructor($$source = {}) { - if (!("B" in $$source)) { - /** - * @member - * @type {structB | null} - */ - this["B"] = null; - } - - Object.assign(this, $$source); - } - - /** - * Creates a new StructA instance from a string or object. - * @param {any} [$$source = {}] - * @returns {StructA} - */ - static createFrom($$source = {}) { - const $$createField0_0 = $$createType1; - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - if ("B" in $$parsedSource) { - $$parsedSource["B"] = $$createField0_0($$parsedSource["B"]); - } - return new StructA(/** @type {Partial} */($$parsedSource)); - } -} - -export class StructC { - /** - * Creates a new StructC instance. - * @param {Partial} [$$source = {}] - The source object to create the StructC. - */ - constructor($$source = {}) { - if (!("D" in $$source)) { - /** - * @member - * @type {structD} - */ - this["D"] = (new structD()); - } - - Object.assign(this, $$source); - } - - /** - * Creates a new StructC instance from a string or object. - * @param {any} [$$source = {}] - * @returns {StructC} - */ - static createFrom($$source = {}) { - const $$createField0_0 = $$createType2; - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - if ("D" in $$parsedSource) { - $$parsedSource["D"] = $$createField0_0($$parsedSource["D"]); - } - return new StructC(/** @type {Partial} */($$parsedSource)); - } -} - -export class StructE { - /** - * Creates a new StructE instance. - * @param {Partial} [$$source = {}] - The source object to create the StructE. - */ - constructor($$source = {}) { - - Object.assign(this, $$source); - } - - /** - * Creates a new StructE instance from a string or object. - * @param {any} [$$source = {}] - * @returns {StructE} - */ - static createFrom($$source = {}) { - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - return new StructE(/** @type {Partial} */($$parsedSource)); - } -} - -export class structB { - /** - * Creates a new structB instance. - * @param {Partial} [$$source = {}] - The source object to create the structB. - */ - constructor($$source = {}) { - if (!("A" in $$source)) { - /** - * @member - * @type {StructA | null} - */ - this["A"] = null; - } - - Object.assign(this, $$source); - } - - /** - * Creates a new structB instance from a string or object. - * @param {any} [$$source = {}] - * @returns {structB} - */ - static createFrom($$source = {}) { - const $$createField0_0 = $$createType4; - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - if ("A" in $$parsedSource) { - $$parsedSource["A"] = $$createField0_0($$parsedSource["A"]); - } - return new structB(/** @type {Partial} */($$parsedSource)); - } -} - -export class structD { - /** - * Creates a new structD instance. - * @param {Partial} [$$source = {}] - The source object to create the structD. - */ - constructor($$source = {}) { - if (!("E" in $$source)) { - /** - * @member - * @type {StructE} - */ - this["E"] = (new StructE()); - } - - Object.assign(this, $$source); - } - - /** - * Creates a new structD instance from a string or object. - * @param {any} [$$source = {}] - * @returns {structD} - */ - static createFrom($$source = {}) { - const $$createField0_0 = $$createType5; - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - if ("E" in $$parsedSource) { - $$parsedSource["E"] = $$createField0_0($$parsedSource["E"]); - } - return new structD(/** @type {Partial} */($$parsedSource)); - } -} - -// Private type creation functions -const $$createType0 = structB.createFrom; -const $$createType1 = $Create.Nullable($$createType0); -const $$createType2 = structD.createFrom; -const $$createType3 = StructA.createFrom; -const $$createType4 = $Create.Nullable($$createType3); -const $$createType5 = StructE.createFrom; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/cyclic_types/greetservice.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/cyclic_types/greetservice.js deleted file mode 100644 index b4cbaa216..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/cyclic_types/greetservice.js +++ /dev/null @@ -1,65 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * Make a cycle. - * @returns {$CancellablePromise<[$models.Cyclic, $models.GenericCyclic<$models.GenericCyclic>]>} - */ -export function MakeCycles() { - return $Call.ByName("main.GreetService.MakeCycles").then(/** @type {($result: any) => any} */(($result) => { - $result[0] = $$createType0($result[0]); - $result[1] = $$createType9($result[1]); - return $result; - })); -} - -// Private type creation functions -var $$createType0 = /** @type {(...args: any[]) => any} */(function $$initCreateType0(...args) { - if ($$createType0 === $$initCreateType0) { - $$createType0 = $$createType3; - } - return $$createType0(...args); -}); -const $$createType1 = $Create.Nullable($$createType0); -const $$createType2 = $Create.Map($Create.Any, $$createType1); -const $$createType3 = $Create.Array($$createType2); -var $$createType4 = /** @type {(...args: any[]) => any} */(function $$initCreateType4(...args) { - if ($$createType4 === $$initCreateType4) { - $$createType4 = $$createType8; - } - return $$createType4(...args); -}); -const $$createType5 = $Create.Nullable($$createType4); -const $$createType6 = $Create.Array($Create.Any); -const $$createType7 = $Create.Struct({ - "X": $$createType5, - "Y": $$createType6, -}); -const $$createType8 = $Create.Array($$createType7); -var $$createType9 = /** @type {(...args: any[]) => any} */(function $$initCreateType9(...args) { - if ($$createType9 === $$initCreateType9) { - $$createType9 = $$createType13; - } - return $$createType9(...args); -}); -const $$createType10 = $Create.Nullable($$createType9); -const $$createType11 = $Create.Array($$createType4); -const $$createType12 = $Create.Struct({ - "X": $$createType10, - "Y": $$createType11, -}); -const $$createType13 = $Create.Array($$createType12); diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/cyclic_types/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/cyclic_types/index.js deleted file mode 100644 index 9fc31bf7c..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/cyclic_types/index.js +++ /dev/null @@ -1,23 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; - -import * as $models from "./models.js"; - -/** - * @typedef {$models.Alias} Alias - */ - -/** - * @typedef {$models.Cyclic} Cyclic - */ - -/** - * @template T - * @typedef {$models.GenericCyclic} GenericCyclic - */ diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/cyclic_types/models.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/cyclic_types/models.js deleted file mode 100644 index 824b9e78c..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/cyclic_types/models.js +++ /dev/null @@ -1,20 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Create as $Create } from "/wails/runtime.js"; - -/** - * @typedef {Cyclic | null} Alias - */ - -/** - * @typedef {{ [_ in string]?: Alias }[]} Cyclic - */ - -/** - * @template T - * @typedef {{"X": GenericCyclic | null, "Y": T[]}[]} GenericCyclic - */ diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/index.js deleted file mode 100644 index 972196ce3..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/index.js +++ /dev/null @@ -1,14 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as Service from "./service.js"; -export { - Service -}; - -console.log("Hello everywhere!"); -console.log("Hello everywhere again!"); -console.log("Hello Classes!"); -console.log("Hello JS!"); -console.log("Hello JS Classes!"); diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/internalservice.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/internalservice.js deleted file mode 100644 index 51a9c6be9..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/internalservice.js +++ /dev/null @@ -1,24 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * An exported but internal service. - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * @param {$models.InternalModel} $0 - * @returns {$CancellablePromise} - */ -export function Method($0) { - return $Call.ByName("main.InternalService.Method", $0); -} diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/models.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/models.js deleted file mode 100644 index 291a3cecf..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/models.js +++ /dev/null @@ -1,69 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Create as $Create } from "/wails/runtime.js"; - -/** - * An exported but internal model. - */ -export class InternalModel { - /** - * Creates a new InternalModel instance. - * @param {Partial} [$$source = {}] - The source object to create the InternalModel. - */ - constructor($$source = {}) { - if (!("Field" in $$source)) { - /** - * @member - * @type {string} - */ - this["Field"] = ""; - } - - Object.assign(this, $$source); - } - - /** - * Creates a new InternalModel instance from a string or object. - * @param {any} [$$source = {}] - * @returns {InternalModel} - */ - static createFrom($$source = {}) { - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - return new InternalModel(/** @type {Partial} */($$parsedSource)); - } -} - -/** - * An unexported model. - */ -export class unexportedModel { - /** - * Creates a new unexportedModel instance. - * @param {Partial} [$$source = {}] - The source object to create the unexportedModel. - */ - constructor($$source = {}) { - if (!("Field" in $$source)) { - /** - * @member - * @type {string} - */ - this["Field"] = ""; - } - - Object.assign(this, $$source); - } - - /** - * Creates a new unexportedModel instance from a string or object. - * @param {any} [$$source = {}] - * @returns {unexportedModel} - */ - static createFrom($$source = {}) { - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - return new unexportedModel(/** @type {Partial} */($$parsedSource)); - } -} diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/otherpackage/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/otherpackage/index.js deleted file mode 100644 index b7e83cfd4..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/otherpackage/index.js +++ /dev/null @@ -1,7 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -export { - Dummy -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/otherpackage/models.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/otherpackage/models.js deleted file mode 100644 index 274f4eed4..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/otherpackage/models.js +++ /dev/null @@ -1,28 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Create as $Create } from "/wails/runtime.js"; - -export class Dummy { - /** - * Creates a new Dummy instance. - * @param {Partial} [$$source = {}] - The source object to create the Dummy. - */ - constructor($$source = {}) { - - Object.assign(this, $$source); - } - - /** - * Creates a new Dummy instance from a string or object. - * @param {any} [$$source = {}] - * @returns {Dummy} - */ - static createFrom($$source = {}) { - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - return new Dummy(/** @type {Partial} */($$parsedSource)); - } -} diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/otherpackage/test_j.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/otherpackage/test_j.js deleted file mode 100644 index 2166d33b6..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/otherpackage/test_j.js +++ /dev/null @@ -1,3 +0,0 @@ -import { CustomMethod } from "../service.js"; - -CustomMethod("JS"); diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/otherpackage/test_jc.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/otherpackage/test_jc.js deleted file mode 100644 index 338898726..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/otherpackage/test_jc.js +++ /dev/null @@ -1,3 +0,0 @@ -import { CustomMethod } from "../service.js"; - -CustomMethod("JS Classes"); diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/service.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/service.js deleted file mode 100644 index c59f8e184..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/service.js +++ /dev/null @@ -1,35 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as otherpackage$0 from "./otherpackage/models.js"; - -/** - * @param {string} $0 - * @returns {$CancellablePromise} - */ -function InternalMethod($0) { - return $Call.ByName("main.Service.InternalMethod", $0); -} - -/** - * @param {otherpackage$0.Dummy} $0 - * @returns {$CancellablePromise} - */ -export function VisibleMethod($0) { - return $Call.ByName("main.Service.VisibleMethod", $0); -} - -/** - * @param {string} arg - * @returns {Promise} - */ -export async function CustomMethod(arg) { - await InternalMethod("Hello " + arg + "!"); -} diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/test.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/test.js deleted file mode 100644 index 138385f53..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/test.js +++ /dev/null @@ -1,3 +0,0 @@ -import { CustomMethod } from "./service.js"; - -CustomMethod("everywhere"); diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/test_all.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/test_all.js deleted file mode 100644 index 19d5c2f42..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/test_all.js +++ /dev/null @@ -1,3 +0,0 @@ -import { CustomMethod } from "./service.js"; - -CustomMethod("everywhere again"); diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/test_c.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/test_c.js deleted file mode 100644 index 724e79e12..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/test_c.js +++ /dev/null @@ -1,3 +0,0 @@ -import { CustomMethod } from "./service.js"; - -CustomMethod("Classes"); diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/test_j.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/test_j.js deleted file mode 100644 index b2f9c5edb..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/test_j.js +++ /dev/null @@ -1,3 +0,0 @@ -import { CustomMethod } from "./service.js"; - -CustomMethod("JS"); diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/test_jc.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/test_jc.js deleted file mode 100644 index ddf4920e5..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/test_jc.js +++ /dev/null @@ -1,3 +0,0 @@ -import { CustomMethod } from "./service.js"; - -CustomMethod("JS Classes"); diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/unexportedservice.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/unexportedservice.js deleted file mode 100644 index 8a93f316f..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/unexportedservice.js +++ /dev/null @@ -1,24 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * An unexported service. - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * @param {$models.unexportedModel} $0 - * @returns {$CancellablePromise} - */ -export function Method($0) { - return $Call.ByName("main.unexportedService.Method", $0); -} diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/embedded_interface/greetservice.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/embedded_interface/greetservice.js deleted file mode 100644 index 494240982..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/embedded_interface/greetservice.js +++ /dev/null @@ -1,53 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -/** - * Comment 1. - * @returns {$CancellablePromise} - */ -export function Method1() { - return $Call.ByName("main.GreetService.Method1"); -} - -/** - * Comment 2. - * @returns {$CancellablePromise} - */ -export function Method2() { - return $Call.ByName("main.GreetService.Method2"); -} - -/** - * Comment 3a. - * Comment 3b. - * @returns {$CancellablePromise} - */ -export function Method3() { - return $Call.ByName("main.GreetService.Method3"); -} - -/** - * Comment 4. - * @returns {$CancellablePromise} - */ -export function Method4() { - return $Call.ByName("main.GreetService.Method4"); -} - -/** - * Comment 5. - * @returns {$CancellablePromise} - */ -export function Method5() { - return $Call.ByName("main.GreetService.Method5"); -} diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/embedded_interface/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/embedded_interface/index.js deleted file mode 100644 index fdf1ff435..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/embedded_interface/index.js +++ /dev/null @@ -1,8 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/enum/greetservice.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/enum/greetservice.js deleted file mode 100644 index fd18bf8a3..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/enum/greetservice.js +++ /dev/null @@ -1,41 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * Greet does XYZ - * @param {string} name - * @param {$models.Title} title - * @returns {$CancellablePromise} - */ -export function Greet(name, title) { - return $Call.ByName("main.GreetService.Greet", name, title); -} - -/** - * NewPerson creates a new person - * @param {string} name - * @returns {$CancellablePromise<$models.Person | null>} - */ -export function NewPerson(name) { - return $Call.ByName("main.GreetService.NewPerson", name).then(/** @type {($result: any) => any} */(($result) => { - return $$createType1($result); - })); -} - -// Private type creation functions -const $$createType0 = $models.Person.createFrom; -const $$createType1 = $Create.Nullable($$createType0); diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/enum/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/enum/index.js deleted file mode 100644 index d5d66d4cb..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/enum/index.js +++ /dev/null @@ -1,14 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; - -export { - Age, - Person, - Title -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/enum/models.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/enum/models.js deleted file mode 100644 index 2c5df9ee7..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/enum/models.js +++ /dev/null @@ -1,98 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Create as $Create } from "/wails/runtime.js"; - -/** - * Age is an integer with some predefined values - * @typedef {number} Age - */ - -/** - * Predefined constants for type Age. - * @namespace - */ -export const Age = { - NewBorn: 0, - Teenager: 12, - YoungAdult: 18, - - /** - * Oh no, some grey hair! - */ - MiddleAged: 50, - - /** - * Unbelievable! - */ - Mathusalem: 1000, -}; - -/** - * Person represents a person - */ -export class Person { - /** - * Creates a new Person instance. - * @param {Partial} [$$source = {}] - The source object to create the Person. - */ - constructor($$source = {}) { - if (!("Title" in $$source)) { - /** - * @member - * @type {Title} - */ - this["Title"] = Title.$zero; - } - if (!("Name" in $$source)) { - /** - * @member - * @type {string} - */ - this["Name"] = ""; - } - if (!("Age" in $$source)) { - /** - * @member - * @type {Age} - */ - this["Age"] = 0; - } - - Object.assign(this, $$source); - } - - /** - * Creates a new Person instance from a string or object. - * @param {any} [$$source = {}] - * @returns {Person} - */ - static createFrom($$source = {}) { - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - return new Person(/** @type {Partial} */($$parsedSource)); - } -} - -/** - * Title is a title - * @readonly - * @enum {string} - */ -export const Title = { - /** - * The Go zero value for the underlying type of the enum. - */ - $zero: "", - - /** - * Mister is a title - */ - Mister: "Mr", - Miss: "Miss", - Ms: "Ms", - Mrs: "Mrs", - Dr: "Dr", -}; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_from_imported_package/greetservice.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_from_imported_package/greetservice.js deleted file mode 100644 index 125c76d13..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_from_imported_package/greetservice.js +++ /dev/null @@ -1,26 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as services$0 from "./services/models.js"; - -/** - * Greet does XYZ - * @param {string} name - * @param {services$0.Title} title - * @returns {$CancellablePromise} - */ -export function Greet(name, title) { - return $Call.ByName("main.GreetService.Greet", name, title); -} diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_from_imported_package/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_from_imported_package/index.js deleted file mode 100644 index fdf1ff435..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_from_imported_package/index.js +++ /dev/null @@ -1,8 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_from_imported_package/services/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_from_imported_package/services/index.js deleted file mode 100644 index 089a8b685..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_from_imported_package/services/index.js +++ /dev/null @@ -1,7 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -export { - Title -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_from_imported_package/services/models.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_from_imported_package/services/models.js deleted file mode 100644 index 65ebfa2f7..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_from_imported_package/services/models.js +++ /dev/null @@ -1,27 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Create as $Create } from "/wails/runtime.js"; - -/** - * @readonly - * @enum {string} - */ -export const Title = { - /** - * The Go zero value for the underlying type of the enum. - */ - $zero: "", - - /** - * Mister is a title - */ - Mister: "Mr", - Miss: "Miss", - Ms: "Ms", - Mrs: "Mrs", - Dr: "Dr", -}; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_map_keys/enummapservice.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_map_keys/enummapservice.js deleted file mode 100644 index 91f1b3eec..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_map_keys/enummapservice.js +++ /dev/null @@ -1,87 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * EnumMapService tests various enum map key scenarios - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * GetColorCodes returns a map with uint8 enum keys - * @returns {$CancellablePromise<{ [_ in $models.Color]?: string }>} - */ -export function GetColorCodes() { - return $Call.ByName("main.EnumMapService.GetColorCodes").then(/** @type {($result: any) => any} */(($result) => { - return $$createType0($result); - })); -} - -/** - * GetNestedEnumMap returns a map with enum keys and complex values - * @returns {$CancellablePromise<{ [_ in $models.Status]?: { [_ in $models.Priority]?: string } }>} - */ -export function GetNestedEnumMap() { - return $Call.ByName("main.EnumMapService.GetNestedEnumMap").then(/** @type {($result: any) => any} */(($result) => { - return $$createType2($result); - })); -} - -/** - * GetOptionalEnumMap returns a map with enum keys to optional values - * @returns {$CancellablePromise<{ [_ in $models.Status]?: string | null }>} - */ -export function GetOptionalEnumMap() { - return $Call.ByName("main.EnumMapService.GetOptionalEnumMap").then(/** @type {($result: any) => any} */(($result) => { - return $$createType3($result); - })); -} - -/** - * GetPersonsByStatus returns a map with enum keys to struct values - * @returns {$CancellablePromise<{ [_ in $models.Status]?: $models.Person[] }>} - */ -export function GetPersonsByStatus() { - return $Call.ByName("main.EnumMapService.GetPersonsByStatus").then(/** @type {($result: any) => any} */(($result) => { - return $$createType6($result); - })); -} - -/** - * GetPriorityWeights returns a map with integer enum keys - * @returns {$CancellablePromise<{ [_ in $models.Priority]?: number }>} - */ -export function GetPriorityWeights() { - return $Call.ByName("main.EnumMapService.GetPriorityWeights").then(/** @type {($result: any) => any} */(($result) => { - return $$createType7($result); - })); -} - -/** - * GetStatusMessages returns a map with string enum keys - * @returns {$CancellablePromise<{ [_ in $models.Status]?: string }>} - */ -export function GetStatusMessages() { - return $Call.ByName("main.EnumMapService.GetStatusMessages").then(/** @type {($result: any) => any} */(($result) => { - return $$createType8($result); - })); -} - -// Private type creation functions -const $$createType0 = $Create.Map($Create.Any, $Create.Any); -const $$createType1 = $Create.Map($Create.Any, $Create.Any); -const $$createType2 = $Create.Map($Create.Any, $$createType1); -const $$createType3 = $Create.Map($Create.Any, $Create.Any); -const $$createType4 = $models.Person.createFrom; -const $$createType5 = $Create.Array($$createType4); -const $$createType6 = $Create.Map($Create.Any, $$createType5); -const $$createType7 = $Create.Map($Create.Any, $Create.Any); -const $$createType8 = $Create.Map($Create.Any, $Create.Any); diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_map_keys/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_map_keys/index.js deleted file mode 100644 index 21da516bd..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_map_keys/index.js +++ /dev/null @@ -1,15 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as EnumMapService from "./enummapservice.js"; -export { - EnumMapService -}; - -export { - Color, - Person, - Priority, - Status -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_map_keys/models.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_map_keys/models.js deleted file mode 100644 index f2c58312c..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_map_keys/models.js +++ /dev/null @@ -1,94 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Create as $Create } from "/wails/runtime.js"; - -/** - * Color represents color values - * @readonly - * @enum {number} - */ -export const Color = { - /** - * The Go zero value for the underlying type of the enum. - */ - $zero: 0, - - Red: 1, - Green: 2, - Blue: 3, -}; - -/** - * Person represents a person with status - */ -export class Person { - /** - * Creates a new Person instance. - * @param {Partial} [$$source = {}] - The source object to create the Person. - */ - constructor($$source = {}) { - if (!("Name" in $$source)) { - /** - * @member - * @type {string} - */ - this["Name"] = ""; - } - if (!("Status" in $$source)) { - /** - * @member - * @type {Status} - */ - this["Status"] = Status.$zero; - } - - Object.assign(this, $$source); - } - - /** - * Creates a new Person instance from a string or object. - * @param {any} [$$source = {}] - * @returns {Person} - */ - static createFrom($$source = {}) { - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - return new Person(/** @type {Partial} */($$parsedSource)); - } -} - -/** - * Priority represents priority levels - * @readonly - * @enum {number} - */ -export const Priority = { - /** - * The Go zero value for the underlying type of the enum. - */ - $zero: 0, - - PriorityLow: 1, - PriorityMedium: 2, - PriorityHigh: 3, -}; - -/** - * Status represents different status values - * @readonly - * @enum {string} - */ -export const Status = { - /** - * The Go zero value for the underlying type of the enum. - */ - $zero: "", - - StatusPending: "pending", - StatusRunning: "running", - StatusCompleted: "completed", - StatusFailed: "failed", -}; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/events_only/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/events_only/index.js deleted file mode 100644 index ebcbd137f..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/events_only/index.js +++ /dev/null @@ -1,7 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -export { - SomeClass -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/events_only/models.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/events_only/models.js deleted file mode 100644 index 498ff20b5..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/events_only/models.js +++ /dev/null @@ -1,56 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Create as $Create } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as nobindingshere$0 from "../no_bindings_here/models.js"; - -/** - * SomeClass renders as a TS class. - */ -export class SomeClass { - /** - * Creates a new SomeClass instance. - * @param {Partial} [$$source = {}] - The source object to create the SomeClass. - */ - constructor($$source = {}) { - if (!("Field" in $$source)) { - /** - * @member - * @type {string} - */ - this["Field"] = ""; - } - if (!("Meadow" in $$source)) { - /** - * @member - * @type {nobindingshere$0.HowDifferent} - */ - this["Meadow"] = (new nobindingshere$0.HowDifferent()); - } - - Object.assign(this, $$source); - } - - /** - * Creates a new SomeClass instance from a string or object. - * @param {any} [$$source = {}] - * @returns {SomeClass} - */ - static createFrom($$source = {}) { - const $$createField1_0 = $$createType0; - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - if ("Meadow" in $$parsedSource) { - $$parsedSource["Meadow"] = $$createField1_0($$parsedSource["Meadow"]); - } - return new SomeClass(/** @type {Partial} */($$parsedSource)); - } -} - -// Private type creation functions -const $$createType0 = nobindingshere$0.HowDifferent.createFrom($Create.Any); diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_imported_package/greetservice.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_imported_package/greetservice.js deleted file mode 100644 index 16a94df37..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_imported_package/greetservice.js +++ /dev/null @@ -1,40 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * Greet does XYZ - * @param {string} name - * @returns {$CancellablePromise} - */ -export function Greet(name) { - return $Call.ByName("main.GreetService.Greet", name); -} - -/** - * NewPerson creates a new person - * @param {string} name - * @returns {$CancellablePromise<$models.Person | null>} - */ -export function NewPerson(name) { - return $Call.ByName("main.GreetService.NewPerson", name).then(/** @type {($result: any) => any} */(($result) => { - return $$createType1($result); - })); -} - -// Private type creation functions -const $$createType0 = $models.Person.createFrom; -const $$createType1 = $Create.Nullable($$createType0); diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_imported_package/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_imported_package/index.js deleted file mode 100644 index fefe6b6ba..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_imported_package/index.js +++ /dev/null @@ -1,12 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; - -export { - Person -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_imported_package/models.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_imported_package/models.js deleted file mode 100644 index 0ab295133..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_imported_package/models.js +++ /dev/null @@ -1,57 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Create as $Create } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as services$0 from "./services/models.js"; - -/** - * Person is a person - */ -export class Person { - /** - * Creates a new Person instance. - * @param {Partial} [$$source = {}] - The source object to create the Person. - */ - constructor($$source = {}) { - if (!("Name" in $$source)) { - /** - * @member - * @type {string} - */ - this["Name"] = ""; - } - if (!("Address" in $$source)) { - /** - * @member - * @type {services$0.Address | null} - */ - this["Address"] = null; - } - - Object.assign(this, $$source); - } - - /** - * Creates a new Person instance from a string or object. - * @param {any} [$$source = {}] - * @returns {Person} - */ - static createFrom($$source = {}) { - const $$createField1_0 = $$createType1; - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - if ("Address" in $$parsedSource) { - $$parsedSource["Address"] = $$createField1_0($$parsedSource["Address"]); - } - return new Person(/** @type {Partial} */($$parsedSource)); - } -} - -// Private type creation functions -const $$createType0 = services$0.Address.createFrom; -const $$createType1 = $Create.Nullable($$createType0); diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_imported_package/services/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_imported_package/services/index.js deleted file mode 100644 index ed65b6d15..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_imported_package/services/index.js +++ /dev/null @@ -1,12 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as OtherService from "./otherservice.js"; -export { - OtherService -}; - -export { - Address -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_imported_package/services/models.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_imported_package/services/models.js deleted file mode 100644 index 24a5de807..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_imported_package/services/models.js +++ /dev/null @@ -1,49 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Create as $Create } from "/wails/runtime.js"; - -export class Address { - /** - * Creates a new Address instance. - * @param {Partial
                    } [$$source = {}] - The source object to create the Address. - */ - constructor($$source = {}) { - if (!("Street" in $$source)) { - /** - * @member - * @type {string} - */ - this["Street"] = ""; - } - if (!("State" in $$source)) { - /** - * @member - * @type {string} - */ - this["State"] = ""; - } - if (!("Country" in $$source)) { - /** - * @member - * @type {string} - */ - this["Country"] = ""; - } - - Object.assign(this, $$source); - } - - /** - * Creates a new Address instance from a string or object. - * @param {any} [$$source = {}] - * @returns {Address} - */ - static createFrom($$source = {}) { - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - return new Address(/** @type {Partial
                    } */($$parsedSource)); - } -} diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_imported_package/services/otherservice.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_imported_package/services/otherservice.js deleted file mode 100644 index ba2c614cd..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_imported_package/services/otherservice.js +++ /dev/null @@ -1,31 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * OtherService is a struct - * that does things - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * Yay does this and that - * @returns {$CancellablePromise<$models.Address | null>} - */ -export function Yay() { - return $Call.ByName("github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_imported_package/services.OtherService.Yay").then(/** @type {($result: any) => any} */(($result) => { - return $$createType1($result); - })); -} - -// Private type creation functions -const $$createType0 = $models.Address.createFrom; -const $$createType1 = $Create.Nullable($$createType0); diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_nested_imported_package/greetservice.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_nested_imported_package/greetservice.js deleted file mode 100644 index 16a94df37..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_nested_imported_package/greetservice.js +++ /dev/null @@ -1,40 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * Greet does XYZ - * @param {string} name - * @returns {$CancellablePromise} - */ -export function Greet(name) { - return $Call.ByName("main.GreetService.Greet", name); -} - -/** - * NewPerson creates a new person - * @param {string} name - * @returns {$CancellablePromise<$models.Person | null>} - */ -export function NewPerson(name) { - return $Call.ByName("main.GreetService.NewPerson", name).then(/** @type {($result: any) => any} */(($result) => { - return $$createType1($result); - })); -} - -// Private type creation functions -const $$createType0 = $models.Person.createFrom; -const $$createType1 = $Create.Nullable($$createType0); diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_nested_imported_package/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_nested_imported_package/index.js deleted file mode 100644 index fefe6b6ba..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_nested_imported_package/index.js +++ /dev/null @@ -1,12 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; - -export { - Person -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_nested_imported_package/models.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_nested_imported_package/models.js deleted file mode 100644 index 29a95e11e..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_nested_imported_package/models.js +++ /dev/null @@ -1,54 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Create as $Create } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as other$0 from "./services/other/models.js"; - -export class Person { - /** - * Creates a new Person instance. - * @param {Partial} [$$source = {}] - The source object to create the Person. - */ - constructor($$source = {}) { - if (!("Name" in $$source)) { - /** - * @member - * @type {string} - */ - this["Name"] = ""; - } - if (!("Address" in $$source)) { - /** - * @member - * @type {other$0.Address | null} - */ - this["Address"] = null; - } - - Object.assign(this, $$source); - } - - /** - * Creates a new Person instance from a string or object. - * @param {any} [$$source = {}] - * @returns {Person} - */ - static createFrom($$source = {}) { - const $$createField1_0 = $$createType1; - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - if ("Address" in $$parsedSource) { - $$parsedSource["Address"] = $$createField1_0($$parsedSource["Address"]); - } - return new Person(/** @type {Partial} */($$parsedSource)); - } -} - -// Private type creation functions -const $$createType0 = other$0.Address.createFrom; -const $$createType1 = $Create.Nullable($$createType0); diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_nested_imported_package/services/other/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_nested_imported_package/services/other/index.js deleted file mode 100644 index ed65b6d15..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_nested_imported_package/services/other/index.js +++ /dev/null @@ -1,12 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as OtherService from "./otherservice.js"; -export { - OtherService -}; - -export { - Address -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_nested_imported_package/services/other/models.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_nested_imported_package/services/other/models.js deleted file mode 100644 index 24a5de807..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_nested_imported_package/services/other/models.js +++ /dev/null @@ -1,49 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Create as $Create } from "/wails/runtime.js"; - -export class Address { - /** - * Creates a new Address instance. - * @param {Partial
                    } [$$source = {}] - The source object to create the Address. - */ - constructor($$source = {}) { - if (!("Street" in $$source)) { - /** - * @member - * @type {string} - */ - this["Street"] = ""; - } - if (!("State" in $$source)) { - /** - * @member - * @type {string} - */ - this["State"] = ""; - } - if (!("Country" in $$source)) { - /** - * @member - * @type {string} - */ - this["Country"] = ""; - } - - Object.assign(this, $$source); - } - - /** - * Creates a new Address instance from a string or object. - * @param {any} [$$source = {}] - * @returns {Address} - */ - static createFrom($$source = {}) { - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - return new Address(/** @type {Partial
                    } */($$parsedSource)); - } -} diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_nested_imported_package/services/other/otherservice.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_nested_imported_package/services/other/otherservice.js deleted file mode 100644 index f6269f0b5..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_nested_imported_package/services/other/otherservice.js +++ /dev/null @@ -1,31 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * OtherService is a struct - * that does things - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * Yay does this and that - * @returns {$CancellablePromise<$models.Address | null>} - */ -export function Yay() { - return $Call.ByName("github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_nested_imported_package/services/other.OtherService.Yay").then(/** @type {($result: any) => any} */(($result) => { - return $$createType1($result); - })); -} - -// Private type creation functions -const $$createType0 = $models.Address.createFrom; -const $$createType1 = $Create.Nullable($$createType0); diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_multiple_files/greetservice.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_multiple_files/greetservice.js deleted file mode 100644 index e6a0e3a74..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_multiple_files/greetservice.js +++ /dev/null @@ -1,15 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -/** - * @param {string} name - * @returns {$CancellablePromise} - */ -export function Greet(name) { - return $Call.ByName("main.GreetService.Greet", name); -} diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_multiple_files/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_multiple_files/index.js deleted file mode 100644 index fdf1ff435..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_multiple_files/index.js +++ /dev/null @@ -1,8 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single/greetservice.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single/greetservice.js deleted file mode 100644 index 6364fa8f6..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single/greetservice.js +++ /dev/null @@ -1,21 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -/** - * Greet someone - * @param {string} name - * @returns {$CancellablePromise} - */ -export function Greet(name) { - return $Call.ByName("main.GreetService.Greet", name); -} diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single/index.js deleted file mode 100644 index fdf1ff435..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single/index.js +++ /dev/null @@ -1,8 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single_context/greetservice.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single_context/greetservice.js deleted file mode 100644 index e91d18592..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single_context/greetservice.js +++ /dev/null @@ -1,30 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -/** - * Greet someone - * @param {string} name - * @returns {$CancellablePromise} - */ -export function Greet(name) { - return $Call.ByName("main.GreetService.Greet", name); -} - -/** - * Greet someone - * @param {string} name - * @returns {$CancellablePromise} - */ -export function GreetWithContext(name) { - return $Call.ByName("main.GreetService.GreetWithContext", name); -} diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single_context/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single_context/index.js deleted file mode 100644 index fdf1ff435..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single_context/index.js +++ /dev/null @@ -1,8 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single_internal/greetservice.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single_internal/greetservice.js deleted file mode 100644 index 6364fa8f6..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single_internal/greetservice.js +++ /dev/null @@ -1,21 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -/** - * Greet someone - * @param {string} name - * @returns {$CancellablePromise} - */ -export function Greet(name) { - return $Call.ByName("main.GreetService.Greet", name); -} diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single_internal/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single_internal/index.js deleted file mode 100644 index fdf1ff435..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single_internal/index.js +++ /dev/null @@ -1,8 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys/index.js deleted file mode 100644 index 3e1e0ecdb..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys/index.js +++ /dev/null @@ -1,105 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as Service from "./service.js"; -export { - Service -}; - -export { - Maps -} from "./models.js"; - -import * as $models from "./models.js"; - -/** - * @template S - * @typedef {$models.BasicCstrAlias} BasicCstrAlias - */ - -/** - * @template R - * @typedef {$models.ComparableCstrAlias} ComparableCstrAlias - */ - -/** - * @typedef {$models.EmbeddedCustomInterface} EmbeddedCustomInterface - */ - -/** - * @typedef {$models.EmbeddedOriginalInterface} EmbeddedOriginalInterface - */ - -/** - * @typedef {$models.EmbeddedPointer} EmbeddedPointer - */ - -/** - * @typedef {$models.EmbeddedPointerPtr} EmbeddedPointerPtr - */ - -/** - * @typedef {$models.EmbeddedValue} EmbeddedValue - */ - -/** - * @typedef {$models.EmbeddedValuePtr} EmbeddedValuePtr - */ - -/** - * @template U - * @typedef {$models.GoodTildeCstrAlias} GoodTildeCstrAlias - */ - -/** - * @typedef {$models.IntAlias} IntAlias - */ - -/** - * @typedef {$models.IntType} IntType - */ - -/** - * @template Y - * @typedef {$models.InterfaceCstrAlias} InterfaceCstrAlias - */ - -/** - * @template X - * @typedef {$models.MixedCstrAlias} MixedCstrAlias - */ - -/** - * @template V - * @typedef {$models.NonBasicCstrAlias} NonBasicCstrAlias - */ - -/** - * @template W - * @typedef {$models.PointableCstrAlias} PointableCstrAlias - */ - -/** - * @typedef {$models.PointerAlias} PointerAlias - */ - -/** - * @typedef {$models.PointerTextMarshaler} PointerTextMarshaler - */ - -/** - * @typedef {$models.StringAlias} StringAlias - */ - -/** - * @typedef {$models.StringType} StringType - */ - -/** - * @typedef {$models.ValueAlias} ValueAlias - */ - -/** - * @typedef {$models.ValueTextMarshaler} ValueTextMarshaler - */ diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys/models.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys/models.js deleted file mode 100644 index 61bc3d532..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys/models.js +++ /dev/null @@ -1,1965 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Create as $Create } from "/wails/runtime.js"; - -/** - * @template S - * @typedef {S} BasicCstrAlias - */ - -/** - * @template R - * @typedef {R} ComparableCstrAlias - */ - -/** - * @typedef {string} EmbeddedCustomInterface - */ - -/** - * @typedef {string} EmbeddedOriginalInterface - */ - -/** - * @typedef {string} EmbeddedPointer - */ - -/** - * @typedef {string} EmbeddedPointerPtr - */ - -/** - * @typedef {string} EmbeddedValue - */ - -/** - * @typedef {string} EmbeddedValuePtr - */ - -/** - * @template U - * @typedef {U} GoodTildeCstrAlias - */ - -/** - * @typedef {number} IntAlias - */ - -/** - * @typedef {number} IntType - */ - -/** - * @template Y - * @typedef {Y} InterfaceCstrAlias - */ - -/** - * @template R,S,T,U,V,W,X,Y,Z - */ -export class Maps { - /** - * Creates a new Maps instance. - * @param {Partial>} [$$source = {}] - The source object to create the Maps. - */ - constructor($$source = {}) { - if (!("Bool" in $$source)) { - /** - * Reject - * @member - * @type {{ [_ in string]?: number }} - */ - this["Bool"] = {}; - } - if (!("Int" in $$source)) { - /** - * Accept - * @member - * @type {{ [_ in `${number}`]?: number }} - */ - this["Int"] = {}; - } - if (!("Uint" in $$source)) { - /** - * Accept - * @member - * @type {{ [_ in `${number}`]?: number }} - */ - this["Uint"] = {}; - } - if (!("Float" in $$source)) { - /** - * Reject - * @member - * @type {{ [_ in string]?: number }} - */ - this["Float"] = {}; - } - if (!("Complex" in $$source)) { - /** - * Reject - * @member - * @type {{ [_ in string]?: number }} - */ - this["Complex"] = {}; - } - if (!("Byte" in $$source)) { - /** - * Accept - * @member - * @type {{ [_ in `${number}`]?: number }} - */ - this["Byte"] = {}; - } - if (!("Rune" in $$source)) { - /** - * Accept - * @member - * @type {{ [_ in `${number}`]?: number }} - */ - this["Rune"] = {}; - } - if (!("String" in $$source)) { - /** - * Accept - * @member - * @type {{ [_ in string]?: number }} - */ - this["String"] = {}; - } - if (!("IntPtr" in $$source)) { - /** - * Reject - * @member - * @type {{ [_ in string]?: number }} - */ - this["IntPtr"] = {}; - } - if (!("UintPtr" in $$source)) { - /** - * Reject - * @member - * @type {{ [_ in string]?: number }} - */ - this["UintPtr"] = {}; - } - if (!("FloatPtr" in $$source)) { - /** - * Reject - * @member - * @type {{ [_ in string]?: number }} - */ - this["FloatPtr"] = {}; - } - if (!("ComplexPtr" in $$source)) { - /** - * Reject - * @member - * @type {{ [_ in string]?: number }} - */ - this["ComplexPtr"] = {}; - } - if (!("StringPtr" in $$source)) { - /** - * Reject - * @member - * @type {{ [_ in string]?: number }} - */ - this["StringPtr"] = {}; - } - if (!("NTM" in $$source)) { - /** - * Reject - * @member - * @type {{ [_ in string]?: number }} - */ - this["NTM"] = {}; - } - if (!("NTMPtr" in $$source)) { - /** - * Reject - * @member - * @type {{ [_ in string]?: number }} - */ - this["NTMPtr"] = {}; - } - if (!("VTM" in $$source)) { - /** - * Accept - * @member - * @type {{ [_ in ValueTextMarshaler]?: number }} - */ - this["VTM"] = {}; - } - if (!("VTMPtr" in $$source)) { - /** - * Accept - * @member - * @type {{ [_ in ValueTextMarshaler]?: number }} - */ - this["VTMPtr"] = {}; - } - if (!("PTM" in $$source)) { - /** - * Reject - * @member - * @type {{ [_ in string]?: number }} - */ - this["PTM"] = {}; - } - if (!("PTMPtr" in $$source)) { - /** - * Accept - * @member - * @type {{ [_ in PointerTextMarshaler]?: number }} - */ - this["PTMPtr"] = {}; - } - if (!("JTM" in $$source)) { - /** - * Accept, hide - * @member - * @type {{ [_ in string]?: number }} - */ - this["JTM"] = {}; - } - if (!("JTMPtr" in $$source)) { - /** - * Accept, hide - * @member - * @type {{ [_ in string]?: number }} - */ - this["JTMPtr"] = {}; - } - if (!("A" in $$source)) { - /** - * Reject - * @member - * @type {{ [_ in string]?: number }} - */ - this["A"] = {}; - } - if (!("APtr" in $$source)) { - /** - * Reject - * @member - * @type {{ [_ in string]?: number }} - */ - this["APtr"] = {}; - } - if (!("TM" in $$source)) { - /** - * Accept, hide - * @member - * @type {{ [_ in string]?: number }} - */ - this["TM"] = {}; - } - if (!("TMPtr" in $$source)) { - /** - * Reject - * @member - * @type {{ [_ in string]?: number }} - */ - this["TMPtr"] = {}; - } - if (!("CI" in $$source)) { - /** - * Accept, hide - * @member - * @type {{ [_ in string]?: number }} - */ - this["CI"] = {}; - } - if (!("CIPtr" in $$source)) { - /** - * Reject - * @member - * @type {{ [_ in string]?: number }} - */ - this["CIPtr"] = {}; - } - if (!("EI" in $$source)) { - /** - * Accept, hide - * @member - * @type {{ [_ in string]?: number }} - */ - this["EI"] = {}; - } - if (!("EIPtr" in $$source)) { - /** - * Reject - * @member - * @type {{ [_ in string]?: number }} - */ - this["EIPtr"] = {}; - } - if (!("EV" in $$source)) { - /** - * Accept - * @member - * @type {{ [_ in EmbeddedValue]?: number }} - */ - this["EV"] = {}; - } - if (!("EVPtr" in $$source)) { - /** - * Accept - * @member - * @type {{ [_ in EmbeddedValue]?: number }} - */ - this["EVPtr"] = {}; - } - if (!("EVP" in $$source)) { - /** - * Accept - * @member - * @type {{ [_ in EmbeddedValuePtr]?: number }} - */ - this["EVP"] = {}; - } - if (!("EVPPtr" in $$source)) { - /** - * Accept - * @member - * @type {{ [_ in EmbeddedValuePtr]?: number }} - */ - this["EVPPtr"] = {}; - } - if (!("EP" in $$source)) { - /** - * Reject - * @member - * @type {{ [_ in string]?: number }} - */ - this["EP"] = {}; - } - if (!("EPPtr" in $$source)) { - /** - * Accept - * @member - * @type {{ [_ in EmbeddedPointer]?: number }} - */ - this["EPPtr"] = {}; - } - if (!("EPP" in $$source)) { - /** - * Accept - * @member - * @type {{ [_ in EmbeddedPointerPtr]?: number }} - */ - this["EPP"] = {}; - } - if (!("EPPPtr" in $$source)) { - /** - * Accept - * @member - * @type {{ [_ in EmbeddedPointerPtr]?: number }} - */ - this["EPPPtr"] = {}; - } - if (!("ECI" in $$source)) { - /** - * Accept - * @member - * @type {{ [_ in EmbeddedCustomInterface]?: number }} - */ - this["ECI"] = {}; - } - if (!("ECIPtr" in $$source)) { - /** - * Accept - * @member - * @type {{ [_ in EmbeddedCustomInterface]?: number }} - */ - this["ECIPtr"] = {}; - } - if (!("EOI" in $$source)) { - /** - * Accept - * @member - * @type {{ [_ in EmbeddedOriginalInterface]?: number }} - */ - this["EOI"] = {}; - } - if (!("EOIPtr" in $$source)) { - /** - * Accept - * @member - * @type {{ [_ in EmbeddedOriginalInterface]?: number }} - */ - this["EOIPtr"] = {}; - } - if (!("WT" in $$source)) { - /** - * Reject - * @member - * @type {{ [_ in string]?: number }} - */ - this["WT"] = {}; - } - if (!("WA" in $$source)) { - /** - * Reject - * @member - * @type {{ [_ in string]?: number }} - */ - this["WA"] = {}; - } - if (!("ST" in $$source)) { - /** - * Accept - * @member - * @type {{ [_ in StringType]?: number }} - */ - this["ST"] = {}; - } - if (!("SA" in $$source)) { - /** - * Accept - * @member - * @type {{ [_ in StringAlias]?: number }} - */ - this["SA"] = {}; - } - if (!("IntT" in $$source)) { - /** - * Accept - * @member - * @type {{ [_ in IntType]?: number }} - */ - this["IntT"] = {}; - } - if (!("IntA" in $$source)) { - /** - * Accept - * @member - * @type {{ [_ in IntAlias]?: number }} - */ - this["IntA"] = {}; - } - if (!("VT" in $$source)) { - /** - * Reject - * @member - * @type {{ [_ in string]?: number }} - */ - this["VT"] = {}; - } - if (!("VTPtr" in $$source)) { - /** - * Reject - * @member - * @type {{ [_ in string]?: number }} - */ - this["VTPtr"] = {}; - } - if (!("VPT" in $$source)) { - /** - * Reject - * @member - * @type {{ [_ in string]?: number }} - */ - this["VPT"] = {}; - } - if (!("VPTPtr" in $$source)) { - /** - * Reject - * @member - * @type {{ [_ in string]?: number }} - */ - this["VPTPtr"] = {}; - } - if (!("VA" in $$source)) { - /** - * Accept - * @member - * @type {{ [_ in ValueAlias]?: number }} - */ - this["VA"] = {}; - } - if (!("VAPtr" in $$source)) { - /** - * Accept - * @member - * @type {{ [_ in ValueAlias]?: number }} - */ - this["VAPtr"] = {}; - } - if (!("VPA" in $$source)) { - /** - * Accept, hide - * @member - * @type {{ [_ in string]?: number }} - */ - this["VPA"] = {}; - } - if (!("VPAPtr" in $$source)) { - /** - * Reject - * @member - * @type {{ [_ in string]?: number }} - */ - this["VPAPtr"] = {}; - } - if (!("PT" in $$source)) { - /** - * Reject - * @member - * @type {{ [_ in string]?: number }} - */ - this["PT"] = {}; - } - if (!("PTPtr" in $$source)) { - /** - * Reject - * @member - * @type {{ [_ in string]?: number }} - */ - this["PTPtr"] = {}; - } - if (!("PPT" in $$source)) { - /** - * Reject - * @member - * @type {{ [_ in string]?: number }} - */ - this["PPT"] = {}; - } - if (!("PPTPtr" in $$source)) { - /** - * Reject - * @member - * @type {{ [_ in string]?: number }} - */ - this["PPTPtr"] = {}; - } - if (!("PA" in $$source)) { - /** - * Reject - * @member - * @type {{ [_ in string]?: number }} - */ - this["PA"] = {}; - } - if (!("PAPtr" in $$source)) { - /** - * Accept - * @member - * @type {{ [_ in PointerAlias]?: number }} - */ - this["PAPtr"] = {}; - } - if (!("PPA" in $$source)) { - /** - * Accept, hide - * @member - * @type {{ [_ in string]?: number }} - */ - this["PPA"] = {}; - } - if (!("PPAPtr" in $$source)) { - /** - * Reject - * @member - * @type {{ [_ in string]?: number }} - */ - this["PPAPtr"] = {}; - } - if (!("IT" in $$source)) { - /** - * Accept, hide - * @member - * @type {{ [_ in string]?: number }} - */ - this["IT"] = {}; - } - if (!("ITPtr" in $$source)) { - /** - * Reject - * @member - * @type {{ [_ in string]?: number }} - */ - this["ITPtr"] = {}; - } - if (!("IPT" in $$source)) { - /** - * Reject - * @member - * @type {{ [_ in string]?: number }} - */ - this["IPT"] = {}; - } - if (!("IPTPtr" in $$source)) { - /** - * Reject - * @member - * @type {{ [_ in string]?: number }} - */ - this["IPTPtr"] = {}; - } - if (!("IA" in $$source)) { - /** - * Accept, hide - * @member - * @type {{ [_ in string]?: number }} - */ - this["IA"] = {}; - } - if (!("IAPtr" in $$source)) { - /** - * Reject - * @member - * @type {{ [_ in string]?: number }} - */ - this["IAPtr"] = {}; - } - if (!("IPA" in $$source)) { - /** - * Reject - * @member - * @type {{ [_ in string]?: number }} - */ - this["IPA"] = {}; - } - if (!("IPAPtr" in $$source)) { - /** - * Reject - * @member - * @type {{ [_ in string]?: number }} - */ - this["IPAPtr"] = {}; - } - if (!("TPR" in $$source)) { - /** - * Soft reject - * @member - * @type {{ [_ in string]?: number }} - */ - this["TPR"] = {}; - } - if (!("TPRPtr" in $$source)) { - /** - * Soft reject - * @member - * @type {{ [_ in string]?: number }} - */ - this["TPRPtr"] = {}; - } - if (!("TPS" in $$source)) { - /** - * Accept, hide - * @member - * @type {{ [_ in string]?: number }} - */ - this["TPS"] = {}; - } - if (!("TPSPtr" in $$source)) { - /** - * Soft reject - * @member - * @type {{ [_ in string]?: number }} - */ - this["TPSPtr"] = {}; - } - if (!("TPT" in $$source)) { - /** - * Soft reject - * @member - * @type {{ [_ in string]?: number }} - */ - this["TPT"] = {}; - } - if (!("TPTPtr" in $$source)) { - /** - * Soft reject - * @member - * @type {{ [_ in string]?: number }} - */ - this["TPTPtr"] = {}; - } - if (!("TPU" in $$source)) { - /** - * Accept, hide - * @member - * @type {{ [_ in string]?: number }} - */ - this["TPU"] = {}; - } - if (!("TPUPtr" in $$source)) { - /** - * Soft reject - * @member - * @type {{ [_ in string]?: number }} - */ - this["TPUPtr"] = {}; - } - if (!("TPV" in $$source)) { - /** - * Accept, hide - * @member - * @type {{ [_ in string]?: number }} - */ - this["TPV"] = {}; - } - if (!("TPVPtr" in $$source)) { - /** - * Soft reject - * @member - * @type {{ [_ in string]?: number }} - */ - this["TPVPtr"] = {}; - } - if (!("TPW" in $$source)) { - /** - * Soft reject - * @member - * @type {{ [_ in string]?: number }} - */ - this["TPW"] = {}; - } - if (!("TPWPtr" in $$source)) { - /** - * Accept, hide - * @member - * @type {{ [_ in string]?: number }} - */ - this["TPWPtr"] = {}; - } - if (!("TPX" in $$source)) { - /** - * Accept, hide - * @member - * @type {{ [_ in string]?: number }} - */ - this["TPX"] = {}; - } - if (!("TPXPtr" in $$source)) { - /** - * Soft reject - * @member - * @type {{ [_ in string]?: number }} - */ - this["TPXPtr"] = {}; - } - if (!("TPY" in $$source)) { - /** - * Accept, hide - * @member - * @type {{ [_ in string]?: number }} - */ - this["TPY"] = {}; - } - if (!("TPYPtr" in $$source)) { - /** - * Soft reject - * @member - * @type {{ [_ in string]?: number }} - */ - this["TPYPtr"] = {}; - } - if (!("TPZ" in $$source)) { - /** - * Accept, hide - * @member - * @type {{ [_ in string]?: number }} - */ - this["TPZ"] = {}; - } - if (!("TPZPtr" in $$source)) { - /** - * Soft reject - * @member - * @type {{ [_ in string]?: number }} - */ - this["TPZPtr"] = {}; - } - if (!("GAR" in $$source)) { - /** - * Soft reject - * @member - * @type {{ [_ in string]?: number }} - */ - this["GAR"] = {}; - } - if (!("GARPtr" in $$source)) { - /** - * Soft reject - * @member - * @type {{ [_ in string]?: number }} - */ - this["GARPtr"] = {}; - } - if (!("GAS" in $$source)) { - /** - * Accept, hide - * @member - * @type {{ [_ in string]?: number }} - */ - this["GAS"] = {}; - } - if (!("GASPtr" in $$source)) { - /** - * Soft reject - * @member - * @type {{ [_ in string]?: number }} - */ - this["GASPtr"] = {}; - } - if (!("GAT" in $$source)) { - /** - * Soft reject - * @member - * @type {{ [_ in string]?: number }} - */ - this["GAT"] = {}; - } - if (!("GATPtr" in $$source)) { - /** - * Soft reject - * @member - * @type {{ [_ in string]?: number }} - */ - this["GATPtr"] = {}; - } - if (!("GAU" in $$source)) { - /** - * Accept, hide - * @member - * @type {{ [_ in string]?: number }} - */ - this["GAU"] = {}; - } - if (!("GAUPtr" in $$source)) { - /** - * Soft reject - * @member - * @type {{ [_ in string]?: number }} - */ - this["GAUPtr"] = {}; - } - if (!("GAV" in $$source)) { - /** - * Accept, hide - * @member - * @type {{ [_ in string]?: number }} - */ - this["GAV"] = {}; - } - if (!("GAVPtr" in $$source)) { - /** - * Soft reject - * @member - * @type {{ [_ in string]?: number }} - */ - this["GAVPtr"] = {}; - } - if (!("GAW" in $$source)) { - /** - * Soft reject - * @member - * @type {{ [_ in string]?: number }} - */ - this["GAW"] = {}; - } - if (!("GAWPtr" in $$source)) { - /** - * Accept, hide - * @member - * @type {{ [_ in string]?: number }} - */ - this["GAWPtr"] = {}; - } - if (!("GAX" in $$source)) { - /** - * Accept, hide - * @member - * @type {{ [_ in string]?: number }} - */ - this["GAX"] = {}; - } - if (!("GAXPtr" in $$source)) { - /** - * Soft reject - * @member - * @type {{ [_ in string]?: number }} - */ - this["GAXPtr"] = {}; - } - if (!("GAY" in $$source)) { - /** - * Accept, hide - * @member - * @type {{ [_ in string]?: number }} - */ - this["GAY"] = {}; - } - if (!("GAYPtr" in $$source)) { - /** - * Soft reject - * @member - * @type {{ [_ in string]?: number }} - */ - this["GAYPtr"] = {}; - } - if (!("GAZ" in $$source)) { - /** - * Accept, hide - * @member - * @type {{ [_ in string]?: number }} - */ - this["GAZ"] = {}; - } - if (!("GAZPtr" in $$source)) { - /** - * Soft reject - * @member - * @type {{ [_ in string]?: number }} - */ - this["GAZPtr"] = {}; - } - if (!("GACi" in $$source)) { - /** - * Accept - * @member - * @type {{ [_ in ComparableCstrAlias]?: number }} - */ - this["GACi"] = {}; - } - if (!("GACV" in $$source)) { - /** - * Accept - * @member - * @type {{ [_ in ComparableCstrAlias]?: number }} - */ - this["GACV"] = {}; - } - if (!("GACP" in $$source)) { - /** - * Reject - * @member - * @type {{ [_ in string]?: number }} - */ - this["GACP"] = {}; - } - if (!("GACiPtr" in $$source)) { - /** - * Reject - * @member - * @type {{ [_ in string]?: number }} - */ - this["GACiPtr"] = {}; - } - if (!("GACVPtr" in $$source)) { - /** - * Accept, hide - * @member - * @type {{ [_ in string]?: number }} - */ - this["GACVPtr"] = {}; - } - if (!("GACPPtr" in $$source)) { - /** - * Accept, hide - * @member - * @type {{ [_ in string]?: number }} - */ - this["GACPPtr"] = {}; - } - if (!("GABi" in $$source)) { - /** - * Accept - * @member - * @type {{ [_ in BasicCstrAlias]?: number }} - */ - this["GABi"] = {}; - } - if (!("GABs" in $$source)) { - /** - * Accept - * @member - * @type {{ [_ in BasicCstrAlias]?: number }} - */ - this["GABs"] = {}; - } - if (!("GABiPtr" in $$source)) { - /** - * Reject - * @member - * @type {{ [_ in string]?: number }} - */ - this["GABiPtr"] = {}; - } - if (!("GABT" in $$source)) { - /** - * Reject - * @member - * @type {{ [_ in string]?: number }} - */ - this["GABT"] = {}; - } - if (!("GABTPtr" in $$source)) { - /** - * Reject - * @member - * @type {{ [_ in string]?: number }} - */ - this["GABTPtr"] = {}; - } - if (!("GAGT" in $$source)) { - /** - * Accept - * @member - * @type {{ [_ in GoodTildeCstrAlias]?: number }} - */ - this["GAGT"] = {}; - } - if (!("GAGTPtr" in $$source)) { - /** - * Accept, hide - * @member - * @type {{ [_ in string]?: number }} - */ - this["GAGTPtr"] = {}; - } - if (!("GANBV" in $$source)) { - /** - * Accept - * @member - * @type {{ [_ in NonBasicCstrAlias]?: number }} - */ - this["GANBV"] = {}; - } - if (!("GANBP" in $$source)) { - /** - * Accept, hide - * @member - * @type {{ [_ in string]?: number }} - */ - this["GANBP"] = {}; - } - if (!("GANBVPtr" in $$source)) { - /** - * Accept, hide - * @member - * @type {{ [_ in string]?: number }} - */ - this["GANBVPtr"] = {}; - } - if (!("GANBPPtr" in $$source)) { - /** - * Reject - * @member - * @type {{ [_ in string]?: number }} - */ - this["GANBPPtr"] = {}; - } - if (!("GAPlV1" in $$source)) { - /** - * Accept - * @member - * @type {{ [_ in PointableCstrAlias]?: number }} - */ - this["GAPlV1"] = {}; - } - if (!("GAPlV2" in $$source)) { - /** - * Accept - * @member - * @type {{ [_ in PointableCstrAlias]?: number }} - */ - this["GAPlV2"] = {}; - } - if (!("GAPlP1" in $$source)) { - /** - * Reject - * @member - * @type {{ [_ in string]?: number }} - */ - this["GAPlP1"] = {}; - } - if (!("GAPlP2" in $$source)) { - /** - * Accept - * @member - * @type {{ [_ in PointableCstrAlias]?: number }} - */ - this["GAPlP2"] = {}; - } - if (!("GAPlVPtr" in $$source)) { - /** - * Accept, hide - * @member - * @type {{ [_ in string]?: number }} - */ - this["GAPlVPtr"] = {}; - } - if (!("GAPlPPtr" in $$source)) { - /** - * Accept, hide - * @member - * @type {{ [_ in string]?: number }} - */ - this["GAPlPPtr"] = {}; - } - if (!("GAMi" in $$source)) { - /** - * Accept - * @member - * @type {{ [_ in MixedCstrAlias]?: number }} - */ - this["GAMi"] = {}; - } - if (!("GAMS" in $$source)) { - /** - * Accept - * @member - * @type {{ [_ in MixedCstrAlias]?: number }} - */ - this["GAMS"] = {}; - } - if (!("GAMV" in $$source)) { - /** - * Accept - * @member - * @type {{ [_ in MixedCstrAlias]?: number }} - */ - this["GAMV"] = {}; - } - if (!("GAMSPtr" in $$source)) { - /** - * Reject - * @member - * @type {{ [_ in string]?: number }} - */ - this["GAMSPtr"] = {}; - } - if (!("GAMVPtr" in $$source)) { - /** - * Accept, hide - * @member - * @type {{ [_ in string]?: number }} - */ - this["GAMVPtr"] = {}; - } - if (!("GAII" in $$source)) { - /** - * Accept, hide - * @member - * @type {{ [_ in string]?: number }} - */ - this["GAII"] = {}; - } - if (!("GAIV" in $$source)) { - /** - * Accept - * @member - * @type {{ [_ in InterfaceCstrAlias]?: number }} - */ - this["GAIV"] = {}; - } - if (!("GAIP" in $$source)) { - /** - * Accept, hide - * @member - * @type {{ [_ in string]?: number }} - */ - this["GAIP"] = {}; - } - if (!("GAIIPtr" in $$source)) { - /** - * Reject - * @member - * @type {{ [_ in string]?: number }} - */ - this["GAIIPtr"] = {}; - } - if (!("GAIVPtr" in $$source)) { - /** - * Accept, hide - * @member - * @type {{ [_ in string]?: number }} - */ - this["GAIVPtr"] = {}; - } - if (!("GAIPPtr" in $$source)) { - /** - * Reject - * @member - * @type {{ [_ in string]?: number }} - */ - this["GAIPPtr"] = {}; - } - if (!("GAPrV" in $$source)) { - /** - * Accept, hide - * @member - * @type {{ [_ in string]?: number }} - */ - this["GAPrV"] = {}; - } - if (!("GAPrP" in $$source)) { - /** - * Accept, hide - * @member - * @type {{ [_ in string]?: number }} - */ - this["GAPrP"] = {}; - } - if (!("GAPrVPtr" in $$source)) { - /** - * Reject - * @member - * @type {{ [_ in string]?: number }} - */ - this["GAPrVPtr"] = {}; - } - if (!("GAPrPPtr" in $$source)) { - /** - * Reject - * @member - * @type {{ [_ in string]?: number }} - */ - this["GAPrPPtr"] = {}; - } - - Object.assign(this, $$source); - } - - /** - * Given creation functions for each type parameter, - * returns a creation function for a concrete instance - * of the generic class Maps. - * @template [R=any] - * @template [S=any] - * @template [T=any] - * @template [U=any] - * @template [V=any] - * @template [W=any] - * @template [X=any] - * @template [Y=any] - * @template [Z=any] - * @param {(source: any) => R} $$createParamR - * @param {(source: any) => S} $$createParamS - * @param {(source: any) => T} $$createParamT - * @param {(source: any) => U} $$createParamU - * @param {(source: any) => V} $$createParamV - * @param {(source: any) => W} $$createParamW - * @param {(source: any) => X} $$createParamX - * @param {(source: any) => Y} $$createParamY - * @param {(source: any) => Z} $$createParamZ - * @returns {($$source?: any) => Maps} - */ - static createFrom($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ) { - const $$createField0_0 = $$createType0; - const $$createField1_0 = $$createType1; - const $$createField2_0 = $$createType2; - const $$createField3_0 = $$createType3; - const $$createField4_0 = $$createType4; - const $$createField5_0 = $$createType5; - const $$createField6_0 = $$createType6; - const $$createField7_0 = $$createType7; - const $$createField8_0 = $$createType8; - const $$createField9_0 = $$createType9; - const $$createField10_0 = $$createType10; - const $$createField11_0 = $$createType11; - const $$createField12_0 = $$createType12; - const $$createField13_0 = $$createType13; - const $$createField14_0 = $$createType14; - const $$createField15_0 = $$createType15; - const $$createField16_0 = $$createType16; - const $$createField17_0 = $$createType17; - const $$createField18_0 = $$createType18; - const $$createField19_0 = $$createType19; - const $$createField20_0 = $$createType20; - const $$createField21_0 = $$createType21; - const $$createField22_0 = $$createType22; - const $$createField23_0 = $$createType23; - const $$createField24_0 = $$createType24; - const $$createField25_0 = $$createType25; - const $$createField26_0 = $$createType26; - const $$createField27_0 = $$createType27; - const $$createField28_0 = $$createType28; - const $$createField29_0 = $$createType29; - const $$createField30_0 = $$createType30; - const $$createField31_0 = $$createType31; - const $$createField32_0 = $$createType32; - const $$createField33_0 = $$createType33; - const $$createField34_0 = $$createType34; - const $$createField35_0 = $$createType35; - const $$createField36_0 = $$createType36; - const $$createField37_0 = $$createType37; - const $$createField38_0 = $$createType38; - const $$createField39_0 = $$createType39; - const $$createField40_0 = $$createType40; - const $$createField41_0 = $$createType41; - const $$createField42_0 = $$createType0; - const $$createField43_0 = $$createType42; - const $$createField44_0 = $$createType7; - const $$createField45_0 = $$createType43; - const $$createField46_0 = $$createType1; - const $$createField47_0 = $$createType44; - const $$createField48_0 = $$createType45; - const $$createField49_0 = $$createType46; - const $$createField50_0 = $$createType47; - const $$createField51_0 = $$createType15; - const $$createField52_0 = $$createType16; - const $$createField53_0 = $$createType16; - const $$createField54_0 = $$createType48; - const $$createField55_0 = $$createType49; - const $$createField56_0 = $$createType50; - const $$createField57_0 = $$createType51; - const $$createField58_0 = $$createType52; - const $$createField59_0 = $$createType17; - const $$createField60_0 = $$createType18; - const $$createField61_0 = $$createType18; - const $$createField62_0 = $$createType53; - const $$createField63_0 = $$createType54; - const $$createField64_0 = $$createType55; - const $$createField65_0 = $$createType56; - const $$createField66_0 = $$createType57; - const $$createField67_0 = $$createType23; - const $$createField68_0 = $$createType24; - const $$createField69_0 = $$createType24; - const $$createField70_0 = $$createType58; - const $$createField71_0 = $$createType59($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ); - const $$createField72_0 = $$createType60($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ); - const $$createField73_0 = $$createType61($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ); - const $$createField74_0 = $$createType62($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ); - const $$createField75_0 = $$createType63($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ); - const $$createField76_0 = $$createType64($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ); - const $$createField77_0 = $$createType65($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ); - const $$createField78_0 = $$createType66($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ); - const $$createField79_0 = $$createType67($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ); - const $$createField80_0 = $$createType68($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ); - const $$createField81_0 = $$createType69($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ); - const $$createField82_0 = $$createType70($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ); - const $$createField83_0 = $$createType71($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ); - const $$createField84_0 = $$createType72($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ); - const $$createField85_0 = $$createType73($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ); - const $$createField86_0 = $$createType74($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ); - const $$createField87_0 = $$createType75($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ); - const $$createField88_0 = $$createType76($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ); - const $$createField89_0 = $$createType59($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ); - const $$createField90_0 = $$createType60($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ); - const $$createField91_0 = $$createType61($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ); - const $$createField92_0 = $$createType62($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ); - const $$createField93_0 = $$createType63($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ); - const $$createField94_0 = $$createType64($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ); - const $$createField95_0 = $$createType65($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ); - const $$createField96_0 = $$createType66($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ); - const $$createField97_0 = $$createType67($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ); - const $$createField98_0 = $$createType68($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ); - const $$createField99_0 = $$createType69($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ); - const $$createField100_0 = $$createType70($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ); - const $$createField101_0 = $$createType71($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ); - const $$createField102_0 = $$createType72($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ); - const $$createField103_0 = $$createType73($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ); - const $$createField104_0 = $$createType74($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ); - const $$createField105_0 = $$createType75($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ); - const $$createField106_0 = $$createType76($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ); - const $$createField107_0 = $$createType1; - const $$createField108_0 = $$createType15; - const $$createField109_0 = $$createType17; - const $$createField110_0 = $$createType8; - const $$createField111_0 = $$createType16; - const $$createField112_0 = $$createType18; - const $$createField113_0 = $$createType1; - const $$createField114_0 = $$createType7; - const $$createField115_0 = $$createType8; - const $$createField116_0 = $$createType77; - const $$createField117_0 = $$createType78; - const $$createField118_0 = $$createType15; - const $$createField119_0 = $$createType16; - const $$createField120_0 = $$createType15; - const $$createField121_0 = $$createType18; - const $$createField122_0 = $$createType16; - const $$createField123_0 = $$createType53; - const $$createField124_0 = $$createType15; - const $$createField125_0 = $$createType16; - const $$createField126_0 = $$createType17; - const $$createField127_0 = $$createType18; - const $$createField128_0 = $$createType16; - const $$createField129_0 = $$createType18; - const $$createField130_0 = $$createType2; - const $$createField131_0 = $$createType42; - const $$createField132_0 = $$createType15; - const $$createField133_0 = $$createType79; - const $$createField134_0 = $$createType16; - const $$createField135_0 = $$createType23; - const $$createField136_0 = $$createType15; - const $$createField137_0 = $$createType18; - const $$createField138_0 = $$createType24; - const $$createField139_0 = $$createType16; - const $$createField140_0 = $$createType53; - const $$createField141_0 = $$createType16; - const $$createField142_0 = $$createType18; - const $$createField143_0 = $$createType48; - const $$createField144_0 = $$createType53; - return ($$source = {}) => { - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - if ("Bool" in $$parsedSource) { - $$parsedSource["Bool"] = $$createField0_0($$parsedSource["Bool"]); - } - if ("Int" in $$parsedSource) { - $$parsedSource["Int"] = $$createField1_0($$parsedSource["Int"]); - } - if ("Uint" in $$parsedSource) { - $$parsedSource["Uint"] = $$createField2_0($$parsedSource["Uint"]); - } - if ("Float" in $$parsedSource) { - $$parsedSource["Float"] = $$createField3_0($$parsedSource["Float"]); - } - if ("Complex" in $$parsedSource) { - $$parsedSource["Complex"] = $$createField4_0($$parsedSource["Complex"]); - } - if ("Byte" in $$parsedSource) { - $$parsedSource["Byte"] = $$createField5_0($$parsedSource["Byte"]); - } - if ("Rune" in $$parsedSource) { - $$parsedSource["Rune"] = $$createField6_0($$parsedSource["Rune"]); - } - if ("String" in $$parsedSource) { - $$parsedSource["String"] = $$createField7_0($$parsedSource["String"]); - } - if ("IntPtr" in $$parsedSource) { - $$parsedSource["IntPtr"] = $$createField8_0($$parsedSource["IntPtr"]); - } - if ("UintPtr" in $$parsedSource) { - $$parsedSource["UintPtr"] = $$createField9_0($$parsedSource["UintPtr"]); - } - if ("FloatPtr" in $$parsedSource) { - $$parsedSource["FloatPtr"] = $$createField10_0($$parsedSource["FloatPtr"]); - } - if ("ComplexPtr" in $$parsedSource) { - $$parsedSource["ComplexPtr"] = $$createField11_0($$parsedSource["ComplexPtr"]); - } - if ("StringPtr" in $$parsedSource) { - $$parsedSource["StringPtr"] = $$createField12_0($$parsedSource["StringPtr"]); - } - if ("NTM" in $$parsedSource) { - $$parsedSource["NTM"] = $$createField13_0($$parsedSource["NTM"]); - } - if ("NTMPtr" in $$parsedSource) { - $$parsedSource["NTMPtr"] = $$createField14_0($$parsedSource["NTMPtr"]); - } - if ("VTM" in $$parsedSource) { - $$parsedSource["VTM"] = $$createField15_0($$parsedSource["VTM"]); - } - if ("VTMPtr" in $$parsedSource) { - $$parsedSource["VTMPtr"] = $$createField16_0($$parsedSource["VTMPtr"]); - } - if ("PTM" in $$parsedSource) { - $$parsedSource["PTM"] = $$createField17_0($$parsedSource["PTM"]); - } - if ("PTMPtr" in $$parsedSource) { - $$parsedSource["PTMPtr"] = $$createField18_0($$parsedSource["PTMPtr"]); - } - if ("JTM" in $$parsedSource) { - $$parsedSource["JTM"] = $$createField19_0($$parsedSource["JTM"]); - } - if ("JTMPtr" in $$parsedSource) { - $$parsedSource["JTMPtr"] = $$createField20_0($$parsedSource["JTMPtr"]); - } - if ("A" in $$parsedSource) { - $$parsedSource["A"] = $$createField21_0($$parsedSource["A"]); - } - if ("APtr" in $$parsedSource) { - $$parsedSource["APtr"] = $$createField22_0($$parsedSource["APtr"]); - } - if ("TM" in $$parsedSource) { - $$parsedSource["TM"] = $$createField23_0($$parsedSource["TM"]); - } - if ("TMPtr" in $$parsedSource) { - $$parsedSource["TMPtr"] = $$createField24_0($$parsedSource["TMPtr"]); - } - if ("CI" in $$parsedSource) { - $$parsedSource["CI"] = $$createField25_0($$parsedSource["CI"]); - } - if ("CIPtr" in $$parsedSource) { - $$parsedSource["CIPtr"] = $$createField26_0($$parsedSource["CIPtr"]); - } - if ("EI" in $$parsedSource) { - $$parsedSource["EI"] = $$createField27_0($$parsedSource["EI"]); - } - if ("EIPtr" in $$parsedSource) { - $$parsedSource["EIPtr"] = $$createField28_0($$parsedSource["EIPtr"]); - } - if ("EV" in $$parsedSource) { - $$parsedSource["EV"] = $$createField29_0($$parsedSource["EV"]); - } - if ("EVPtr" in $$parsedSource) { - $$parsedSource["EVPtr"] = $$createField30_0($$parsedSource["EVPtr"]); - } - if ("EVP" in $$parsedSource) { - $$parsedSource["EVP"] = $$createField31_0($$parsedSource["EVP"]); - } - if ("EVPPtr" in $$parsedSource) { - $$parsedSource["EVPPtr"] = $$createField32_0($$parsedSource["EVPPtr"]); - } - if ("EP" in $$parsedSource) { - $$parsedSource["EP"] = $$createField33_0($$parsedSource["EP"]); - } - if ("EPPtr" in $$parsedSource) { - $$parsedSource["EPPtr"] = $$createField34_0($$parsedSource["EPPtr"]); - } - if ("EPP" in $$parsedSource) { - $$parsedSource["EPP"] = $$createField35_0($$parsedSource["EPP"]); - } - if ("EPPPtr" in $$parsedSource) { - $$parsedSource["EPPPtr"] = $$createField36_0($$parsedSource["EPPPtr"]); - } - if ("ECI" in $$parsedSource) { - $$parsedSource["ECI"] = $$createField37_0($$parsedSource["ECI"]); - } - if ("ECIPtr" in $$parsedSource) { - $$parsedSource["ECIPtr"] = $$createField38_0($$parsedSource["ECIPtr"]); - } - if ("EOI" in $$parsedSource) { - $$parsedSource["EOI"] = $$createField39_0($$parsedSource["EOI"]); - } - if ("EOIPtr" in $$parsedSource) { - $$parsedSource["EOIPtr"] = $$createField40_0($$parsedSource["EOIPtr"]); - } - if ("WT" in $$parsedSource) { - $$parsedSource["WT"] = $$createField41_0($$parsedSource["WT"]); - } - if ("WA" in $$parsedSource) { - $$parsedSource["WA"] = $$createField42_0($$parsedSource["WA"]); - } - if ("ST" in $$parsedSource) { - $$parsedSource["ST"] = $$createField43_0($$parsedSource["ST"]); - } - if ("SA" in $$parsedSource) { - $$parsedSource["SA"] = $$createField44_0($$parsedSource["SA"]); - } - if ("IntT" in $$parsedSource) { - $$parsedSource["IntT"] = $$createField45_0($$parsedSource["IntT"]); - } - if ("IntA" in $$parsedSource) { - $$parsedSource["IntA"] = $$createField46_0($$parsedSource["IntA"]); - } - if ("VT" in $$parsedSource) { - $$parsedSource["VT"] = $$createField47_0($$parsedSource["VT"]); - } - if ("VTPtr" in $$parsedSource) { - $$parsedSource["VTPtr"] = $$createField48_0($$parsedSource["VTPtr"]); - } - if ("VPT" in $$parsedSource) { - $$parsedSource["VPT"] = $$createField49_0($$parsedSource["VPT"]); - } - if ("VPTPtr" in $$parsedSource) { - $$parsedSource["VPTPtr"] = $$createField50_0($$parsedSource["VPTPtr"]); - } - if ("VA" in $$parsedSource) { - $$parsedSource["VA"] = $$createField51_0($$parsedSource["VA"]); - } - if ("VAPtr" in $$parsedSource) { - $$parsedSource["VAPtr"] = $$createField52_0($$parsedSource["VAPtr"]); - } - if ("VPA" in $$parsedSource) { - $$parsedSource["VPA"] = $$createField53_0($$parsedSource["VPA"]); - } - if ("VPAPtr" in $$parsedSource) { - $$parsedSource["VPAPtr"] = $$createField54_0($$parsedSource["VPAPtr"]); - } - if ("PT" in $$parsedSource) { - $$parsedSource["PT"] = $$createField55_0($$parsedSource["PT"]); - } - if ("PTPtr" in $$parsedSource) { - $$parsedSource["PTPtr"] = $$createField56_0($$parsedSource["PTPtr"]); - } - if ("PPT" in $$parsedSource) { - $$parsedSource["PPT"] = $$createField57_0($$parsedSource["PPT"]); - } - if ("PPTPtr" in $$parsedSource) { - $$parsedSource["PPTPtr"] = $$createField58_0($$parsedSource["PPTPtr"]); - } - if ("PA" in $$parsedSource) { - $$parsedSource["PA"] = $$createField59_0($$parsedSource["PA"]); - } - if ("PAPtr" in $$parsedSource) { - $$parsedSource["PAPtr"] = $$createField60_0($$parsedSource["PAPtr"]); - } - if ("PPA" in $$parsedSource) { - $$parsedSource["PPA"] = $$createField61_0($$parsedSource["PPA"]); - } - if ("PPAPtr" in $$parsedSource) { - $$parsedSource["PPAPtr"] = $$createField62_0($$parsedSource["PPAPtr"]); - } - if ("IT" in $$parsedSource) { - $$parsedSource["IT"] = $$createField63_0($$parsedSource["IT"]); - } - if ("ITPtr" in $$parsedSource) { - $$parsedSource["ITPtr"] = $$createField64_0($$parsedSource["ITPtr"]); - } - if ("IPT" in $$parsedSource) { - $$parsedSource["IPT"] = $$createField65_0($$parsedSource["IPT"]); - } - if ("IPTPtr" in $$parsedSource) { - $$parsedSource["IPTPtr"] = $$createField66_0($$parsedSource["IPTPtr"]); - } - if ("IA" in $$parsedSource) { - $$parsedSource["IA"] = $$createField67_0($$parsedSource["IA"]); - } - if ("IAPtr" in $$parsedSource) { - $$parsedSource["IAPtr"] = $$createField68_0($$parsedSource["IAPtr"]); - } - if ("IPA" in $$parsedSource) { - $$parsedSource["IPA"] = $$createField69_0($$parsedSource["IPA"]); - } - if ("IPAPtr" in $$parsedSource) { - $$parsedSource["IPAPtr"] = $$createField70_0($$parsedSource["IPAPtr"]); - } - if ("TPR" in $$parsedSource) { - $$parsedSource["TPR"] = $$createField71_0($$parsedSource["TPR"]); - } - if ("TPRPtr" in $$parsedSource) { - $$parsedSource["TPRPtr"] = $$createField72_0($$parsedSource["TPRPtr"]); - } - if ("TPS" in $$parsedSource) { - $$parsedSource["TPS"] = $$createField73_0($$parsedSource["TPS"]); - } - if ("TPSPtr" in $$parsedSource) { - $$parsedSource["TPSPtr"] = $$createField74_0($$parsedSource["TPSPtr"]); - } - if ("TPT" in $$parsedSource) { - $$parsedSource["TPT"] = $$createField75_0($$parsedSource["TPT"]); - } - if ("TPTPtr" in $$parsedSource) { - $$parsedSource["TPTPtr"] = $$createField76_0($$parsedSource["TPTPtr"]); - } - if ("TPU" in $$parsedSource) { - $$parsedSource["TPU"] = $$createField77_0($$parsedSource["TPU"]); - } - if ("TPUPtr" in $$parsedSource) { - $$parsedSource["TPUPtr"] = $$createField78_0($$parsedSource["TPUPtr"]); - } - if ("TPV" in $$parsedSource) { - $$parsedSource["TPV"] = $$createField79_0($$parsedSource["TPV"]); - } - if ("TPVPtr" in $$parsedSource) { - $$parsedSource["TPVPtr"] = $$createField80_0($$parsedSource["TPVPtr"]); - } - if ("TPW" in $$parsedSource) { - $$parsedSource["TPW"] = $$createField81_0($$parsedSource["TPW"]); - } - if ("TPWPtr" in $$parsedSource) { - $$parsedSource["TPWPtr"] = $$createField82_0($$parsedSource["TPWPtr"]); - } - if ("TPX" in $$parsedSource) { - $$parsedSource["TPX"] = $$createField83_0($$parsedSource["TPX"]); - } - if ("TPXPtr" in $$parsedSource) { - $$parsedSource["TPXPtr"] = $$createField84_0($$parsedSource["TPXPtr"]); - } - if ("TPY" in $$parsedSource) { - $$parsedSource["TPY"] = $$createField85_0($$parsedSource["TPY"]); - } - if ("TPYPtr" in $$parsedSource) { - $$parsedSource["TPYPtr"] = $$createField86_0($$parsedSource["TPYPtr"]); - } - if ("TPZ" in $$parsedSource) { - $$parsedSource["TPZ"] = $$createField87_0($$parsedSource["TPZ"]); - } - if ("TPZPtr" in $$parsedSource) { - $$parsedSource["TPZPtr"] = $$createField88_0($$parsedSource["TPZPtr"]); - } - if ("GAR" in $$parsedSource) { - $$parsedSource["GAR"] = $$createField89_0($$parsedSource["GAR"]); - } - if ("GARPtr" in $$parsedSource) { - $$parsedSource["GARPtr"] = $$createField90_0($$parsedSource["GARPtr"]); - } - if ("GAS" in $$parsedSource) { - $$parsedSource["GAS"] = $$createField91_0($$parsedSource["GAS"]); - } - if ("GASPtr" in $$parsedSource) { - $$parsedSource["GASPtr"] = $$createField92_0($$parsedSource["GASPtr"]); - } - if ("GAT" in $$parsedSource) { - $$parsedSource["GAT"] = $$createField93_0($$parsedSource["GAT"]); - } - if ("GATPtr" in $$parsedSource) { - $$parsedSource["GATPtr"] = $$createField94_0($$parsedSource["GATPtr"]); - } - if ("GAU" in $$parsedSource) { - $$parsedSource["GAU"] = $$createField95_0($$parsedSource["GAU"]); - } - if ("GAUPtr" in $$parsedSource) { - $$parsedSource["GAUPtr"] = $$createField96_0($$parsedSource["GAUPtr"]); - } - if ("GAV" in $$parsedSource) { - $$parsedSource["GAV"] = $$createField97_0($$parsedSource["GAV"]); - } - if ("GAVPtr" in $$parsedSource) { - $$parsedSource["GAVPtr"] = $$createField98_0($$parsedSource["GAVPtr"]); - } - if ("GAW" in $$parsedSource) { - $$parsedSource["GAW"] = $$createField99_0($$parsedSource["GAW"]); - } - if ("GAWPtr" in $$parsedSource) { - $$parsedSource["GAWPtr"] = $$createField100_0($$parsedSource["GAWPtr"]); - } - if ("GAX" in $$parsedSource) { - $$parsedSource["GAX"] = $$createField101_0($$parsedSource["GAX"]); - } - if ("GAXPtr" in $$parsedSource) { - $$parsedSource["GAXPtr"] = $$createField102_0($$parsedSource["GAXPtr"]); - } - if ("GAY" in $$parsedSource) { - $$parsedSource["GAY"] = $$createField103_0($$parsedSource["GAY"]); - } - if ("GAYPtr" in $$parsedSource) { - $$parsedSource["GAYPtr"] = $$createField104_0($$parsedSource["GAYPtr"]); - } - if ("GAZ" in $$parsedSource) { - $$parsedSource["GAZ"] = $$createField105_0($$parsedSource["GAZ"]); - } - if ("GAZPtr" in $$parsedSource) { - $$parsedSource["GAZPtr"] = $$createField106_0($$parsedSource["GAZPtr"]); - } - if ("GACi" in $$parsedSource) { - $$parsedSource["GACi"] = $$createField107_0($$parsedSource["GACi"]); - } - if ("GACV" in $$parsedSource) { - $$parsedSource["GACV"] = $$createField108_0($$parsedSource["GACV"]); - } - if ("GACP" in $$parsedSource) { - $$parsedSource["GACP"] = $$createField109_0($$parsedSource["GACP"]); - } - if ("GACiPtr" in $$parsedSource) { - $$parsedSource["GACiPtr"] = $$createField110_0($$parsedSource["GACiPtr"]); - } - if ("GACVPtr" in $$parsedSource) { - $$parsedSource["GACVPtr"] = $$createField111_0($$parsedSource["GACVPtr"]); - } - if ("GACPPtr" in $$parsedSource) { - $$parsedSource["GACPPtr"] = $$createField112_0($$parsedSource["GACPPtr"]); - } - if ("GABi" in $$parsedSource) { - $$parsedSource["GABi"] = $$createField113_0($$parsedSource["GABi"]); - } - if ("GABs" in $$parsedSource) { - $$parsedSource["GABs"] = $$createField114_0($$parsedSource["GABs"]); - } - if ("GABiPtr" in $$parsedSource) { - $$parsedSource["GABiPtr"] = $$createField115_0($$parsedSource["GABiPtr"]); - } - if ("GABT" in $$parsedSource) { - $$parsedSource["GABT"] = $$createField116_0($$parsedSource["GABT"]); - } - if ("GABTPtr" in $$parsedSource) { - $$parsedSource["GABTPtr"] = $$createField117_0($$parsedSource["GABTPtr"]); - } - if ("GAGT" in $$parsedSource) { - $$parsedSource["GAGT"] = $$createField118_0($$parsedSource["GAGT"]); - } - if ("GAGTPtr" in $$parsedSource) { - $$parsedSource["GAGTPtr"] = $$createField119_0($$parsedSource["GAGTPtr"]); - } - if ("GANBV" in $$parsedSource) { - $$parsedSource["GANBV"] = $$createField120_0($$parsedSource["GANBV"]); - } - if ("GANBP" in $$parsedSource) { - $$parsedSource["GANBP"] = $$createField121_0($$parsedSource["GANBP"]); - } - if ("GANBVPtr" in $$parsedSource) { - $$parsedSource["GANBVPtr"] = $$createField122_0($$parsedSource["GANBVPtr"]); - } - if ("GANBPPtr" in $$parsedSource) { - $$parsedSource["GANBPPtr"] = $$createField123_0($$parsedSource["GANBPPtr"]); - } - if ("GAPlV1" in $$parsedSource) { - $$parsedSource["GAPlV1"] = $$createField124_0($$parsedSource["GAPlV1"]); - } - if ("GAPlV2" in $$parsedSource) { - $$parsedSource["GAPlV2"] = $$createField125_0($$parsedSource["GAPlV2"]); - } - if ("GAPlP1" in $$parsedSource) { - $$parsedSource["GAPlP1"] = $$createField126_0($$parsedSource["GAPlP1"]); - } - if ("GAPlP2" in $$parsedSource) { - $$parsedSource["GAPlP2"] = $$createField127_0($$parsedSource["GAPlP2"]); - } - if ("GAPlVPtr" in $$parsedSource) { - $$parsedSource["GAPlVPtr"] = $$createField128_0($$parsedSource["GAPlVPtr"]); - } - if ("GAPlPPtr" in $$parsedSource) { - $$parsedSource["GAPlPPtr"] = $$createField129_0($$parsedSource["GAPlPPtr"]); - } - if ("GAMi" in $$parsedSource) { - $$parsedSource["GAMi"] = $$createField130_0($$parsedSource["GAMi"]); - } - if ("GAMS" in $$parsedSource) { - $$parsedSource["GAMS"] = $$createField131_0($$parsedSource["GAMS"]); - } - if ("GAMV" in $$parsedSource) { - $$parsedSource["GAMV"] = $$createField132_0($$parsedSource["GAMV"]); - } - if ("GAMSPtr" in $$parsedSource) { - $$parsedSource["GAMSPtr"] = $$createField133_0($$parsedSource["GAMSPtr"]); - } - if ("GAMVPtr" in $$parsedSource) { - $$parsedSource["GAMVPtr"] = $$createField134_0($$parsedSource["GAMVPtr"]); - } - if ("GAII" in $$parsedSource) { - $$parsedSource["GAII"] = $$createField135_0($$parsedSource["GAII"]); - } - if ("GAIV" in $$parsedSource) { - $$parsedSource["GAIV"] = $$createField136_0($$parsedSource["GAIV"]); - } - if ("GAIP" in $$parsedSource) { - $$parsedSource["GAIP"] = $$createField137_0($$parsedSource["GAIP"]); - } - if ("GAIIPtr" in $$parsedSource) { - $$parsedSource["GAIIPtr"] = $$createField138_0($$parsedSource["GAIIPtr"]); - } - if ("GAIVPtr" in $$parsedSource) { - $$parsedSource["GAIVPtr"] = $$createField139_0($$parsedSource["GAIVPtr"]); - } - if ("GAIPPtr" in $$parsedSource) { - $$parsedSource["GAIPPtr"] = $$createField140_0($$parsedSource["GAIPPtr"]); - } - if ("GAPrV" in $$parsedSource) { - $$parsedSource["GAPrV"] = $$createField141_0($$parsedSource["GAPrV"]); - } - if ("GAPrP" in $$parsedSource) { - $$parsedSource["GAPrP"] = $$createField142_0($$parsedSource["GAPrP"]); - } - if ("GAPrVPtr" in $$parsedSource) { - $$parsedSource["GAPrVPtr"] = $$createField143_0($$parsedSource["GAPrVPtr"]); - } - if ("GAPrPPtr" in $$parsedSource) { - $$parsedSource["GAPrPPtr"] = $$createField144_0($$parsedSource["GAPrPPtr"]); - } - return new Maps(/** @type {Partial>} */($$parsedSource)); - }; - } -} - -/** - * @template X - * @typedef {X} MixedCstrAlias - */ - -/** - * @template V - * @typedef {V} NonBasicCstrAlias - */ - -/** - * @template W - * @typedef {W} PointableCstrAlias - */ - -/** - * @typedef {PointerTextMarshaler} PointerAlias - */ - -/** - * @typedef {string} PointerTextMarshaler - */ - -/** - * @typedef {string} StringAlias - */ - -/** - * @typedef {string} StringType - */ - -/** - * @typedef {ValueTextMarshaler} ValueAlias - */ - -/** - * @typedef {string} ValueTextMarshaler - */ - -// Private type creation functions -const $$createType0 = $Create.Map($Create.Any, $Create.Any); -const $$createType1 = $Create.Map($Create.Any, $Create.Any); -const $$createType2 = $Create.Map($Create.Any, $Create.Any); -const $$createType3 = $Create.Map($Create.Any, $Create.Any); -const $$createType4 = $Create.Map($Create.Any, $Create.Any); -const $$createType5 = $Create.Map($Create.Any, $Create.Any); -const $$createType6 = $Create.Map($Create.Any, $Create.Any); -const $$createType7 = $Create.Map($Create.Any, $Create.Any); -const $$createType8 = $Create.Map($Create.Any, $Create.Any); -const $$createType9 = $Create.Map($Create.Any, $Create.Any); -const $$createType10 = $Create.Map($Create.Any, $Create.Any); -const $$createType11 = $Create.Map($Create.Any, $Create.Any); -const $$createType12 = $Create.Map($Create.Any, $Create.Any); -const $$createType13 = $Create.Map($Create.Any, $Create.Any); -const $$createType14 = $Create.Map($Create.Any, $Create.Any); -const $$createType15 = $Create.Map($Create.Any, $Create.Any); -const $$createType16 = $Create.Map($Create.Any, $Create.Any); -const $$createType17 = $Create.Map($Create.Any, $Create.Any); -const $$createType18 = $Create.Map($Create.Any, $Create.Any); -const $$createType19 = $Create.Map($Create.Any, $Create.Any); -const $$createType20 = $Create.Map($Create.Any, $Create.Any); -const $$createType21 = $Create.Map($Create.Any, $Create.Any); -const $$createType22 = $Create.Map($Create.Any, $Create.Any); -const $$createType23 = $Create.Map($Create.Any, $Create.Any); -const $$createType24 = $Create.Map($Create.Any, $Create.Any); -const $$createType25 = $Create.Map($Create.Any, $Create.Any); -const $$createType26 = $Create.Map($Create.Any, $Create.Any); -const $$createType27 = $Create.Map($Create.Any, $Create.Any); -const $$createType28 = $Create.Map($Create.Any, $Create.Any); -const $$createType29 = $Create.Map($Create.Any, $Create.Any); -const $$createType30 = $Create.Map($Create.Any, $Create.Any); -const $$createType31 = $Create.Map($Create.Any, $Create.Any); -const $$createType32 = $Create.Map($Create.Any, $Create.Any); -const $$createType33 = $Create.Map($Create.Any, $Create.Any); -const $$createType34 = $Create.Map($Create.Any, $Create.Any); -const $$createType35 = $Create.Map($Create.Any, $Create.Any); -const $$createType36 = $Create.Map($Create.Any, $Create.Any); -const $$createType37 = $Create.Map($Create.Any, $Create.Any); -const $$createType38 = $Create.Map($Create.Any, $Create.Any); -const $$createType39 = $Create.Map($Create.Any, $Create.Any); -const $$createType40 = $Create.Map($Create.Any, $Create.Any); -const $$createType41 = $Create.Map($Create.Any, $Create.Any); -const $$createType42 = $Create.Map($Create.Any, $Create.Any); -const $$createType43 = $Create.Map($Create.Any, $Create.Any); -const $$createType44 = $Create.Map($Create.Any, $Create.Any); -const $$createType45 = $Create.Map($Create.Any, $Create.Any); -const $$createType46 = $Create.Map($Create.Any, $Create.Any); -const $$createType47 = $Create.Map($Create.Any, $Create.Any); -const $$createType48 = $Create.Map($Create.Any, $Create.Any); -const $$createType49 = $Create.Map($Create.Any, $Create.Any); -const $$createType50 = $Create.Map($Create.Any, $Create.Any); -const $$createType51 = $Create.Map($Create.Any, $Create.Any); -const $$createType52 = $Create.Map($Create.Any, $Create.Any); -const $$createType53 = $Create.Map($Create.Any, $Create.Any); -const $$createType54 = $Create.Map($Create.Any, $Create.Any); -const $$createType55 = $Create.Map($Create.Any, $Create.Any); -const $$createType56 = $Create.Map($Create.Any, $Create.Any); -const $$createType57 = $Create.Map($Create.Any, $Create.Any); -const $$createType58 = $Create.Map($Create.Any, $Create.Any); -const $$createType59 = /** @type {(...args: any[]) => any} */(($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ) => $Create.Map($Create.Any, $Create.Any)); -const $$createType60 = /** @type {(...args: any[]) => any} */(($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ) => $Create.Map($Create.Any, $Create.Any)); -const $$createType61 = /** @type {(...args: any[]) => any} */(($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ) => $Create.Map($Create.Any, $Create.Any)); -const $$createType62 = /** @type {(...args: any[]) => any} */(($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ) => $Create.Map($Create.Any, $Create.Any)); -const $$createType63 = /** @type {(...args: any[]) => any} */(($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ) => $Create.Map($Create.Any, $Create.Any)); -const $$createType64 = /** @type {(...args: any[]) => any} */(($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ) => $Create.Map($Create.Any, $Create.Any)); -const $$createType65 = /** @type {(...args: any[]) => any} */(($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ) => $Create.Map($Create.Any, $Create.Any)); -const $$createType66 = /** @type {(...args: any[]) => any} */(($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ) => $Create.Map($Create.Any, $Create.Any)); -const $$createType67 = /** @type {(...args: any[]) => any} */(($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ) => $Create.Map($Create.Any, $Create.Any)); -const $$createType68 = /** @type {(...args: any[]) => any} */(($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ) => $Create.Map($Create.Any, $Create.Any)); -const $$createType69 = /** @type {(...args: any[]) => any} */(($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ) => $Create.Map($Create.Any, $Create.Any)); -const $$createType70 = /** @type {(...args: any[]) => any} */(($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ) => $Create.Map($Create.Any, $Create.Any)); -const $$createType71 = /** @type {(...args: any[]) => any} */(($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ) => $Create.Map($Create.Any, $Create.Any)); -const $$createType72 = /** @type {(...args: any[]) => any} */(($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ) => $Create.Map($Create.Any, $Create.Any)); -const $$createType73 = /** @type {(...args: any[]) => any} */(($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ) => $Create.Map($Create.Any, $Create.Any)); -const $$createType74 = /** @type {(...args: any[]) => any} */(($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ) => $Create.Map($Create.Any, $Create.Any)); -const $$createType75 = /** @type {(...args: any[]) => any} */(($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ) => $Create.Map($Create.Any, $Create.Any)); -const $$createType76 = /** @type {(...args: any[]) => any} */(($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ) => $Create.Map($Create.Any, $Create.Any)); -const $$createType77 = $Create.Map($Create.Any, $Create.Any); -const $$createType78 = $Create.Map($Create.Any, $Create.Any); -const $$createType79 = $Create.Map($Create.Any, $Create.Any); diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys/service.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys/service.js deleted file mode 100644 index cc98f3a89..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys/service.js +++ /dev/null @@ -1,23 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * @returns {$CancellablePromise<$models.Maps<$models.PointerTextMarshaler, number, number, $models.ValueTextMarshaler, $models.PointerTextMarshaler | null, $models.ValueTextMarshaler, $models.StringType, $models.ValueTextMarshaler, $models.PointerTextMarshaler | null>>} - */ -export function Method() { - return $Call.ByName("main.Service.Method").then(/** @type {($result: any) => any} */(($result) => { - return $$createType0($result); - })); -} - -// Private type creation functions -const $$createType0 = $models.Maps.createFrom($Create.Any, $Create.Any, $Create.Any, $Create.Any, $Create.Any, $Create.Any, $Create.Any, $Create.Any, $Create.Any); diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/marshalers/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/marshalers/index.js deleted file mode 100644 index 8f525252e..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/marshalers/index.js +++ /dev/null @@ -1,116 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as Service from "./service.js"; -export { - Service -}; - -export { - Data, - ImplicitNonMarshaler, - NonMarshaler -} from "./models.js"; - -import * as $models from "./models.js"; - -/** - * any - * @typedef {$models.AliasJsonMarshaler} AliasJsonMarshaler - */ - -/** - * any - * @typedef {$models.AliasMarshaler} AliasMarshaler - */ - -/** - * struct{} - * @typedef {$models.AliasNonMarshaler} AliasNonMarshaler - */ - -/** - * string - * @typedef {$models.AliasTextMarshaler} AliasTextMarshaler - */ - -/** - * any - * @typedef {$models.ImplicitJsonButText} ImplicitJsonButText - */ - -/** - * any - * @typedef {$models.ImplicitJsonMarshaler} ImplicitJsonMarshaler - */ - -/** - * any - * @typedef {$models.ImplicitMarshaler} ImplicitMarshaler - */ - -/** - * string - * @typedef {$models.ImplicitNonJson} ImplicitNonJson - */ - -/** - * any - * @typedef {$models.ImplicitNonText} ImplicitNonText - */ - -/** - * any - * @typedef {$models.ImplicitTextButJson} ImplicitTextButJson - */ - -/** - * string - * @typedef {$models.ImplicitTextMarshaler} ImplicitTextMarshaler - */ - -/** - * any - * @typedef {$models.PointerJsonMarshaler} PointerJsonMarshaler - */ - -/** - * any - * @typedef {$models.PointerMarshaler} PointerMarshaler - */ - -/** - * string - * @typedef {$models.PointerTextMarshaler} PointerTextMarshaler - */ - -/** - * any - * @typedef {$models.UnderlyingJsonMarshaler} UnderlyingJsonMarshaler - */ - -/** - * any - * @typedef {$models.UnderlyingMarshaler} UnderlyingMarshaler - */ - -/** - * string - * @typedef {$models.UnderlyingTextMarshaler} UnderlyingTextMarshaler - */ - -/** - * any - * @typedef {$models.ValueJsonMarshaler} ValueJsonMarshaler - */ - -/** - * any - * @typedef {$models.ValueMarshaler} ValueMarshaler - */ - -/** - * string - * @typedef {$models.ValueTextMarshaler} ValueTextMarshaler - */ diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/marshalers/models.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/marshalers/models.js deleted file mode 100644 index 77fe552ea..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/marshalers/models.js +++ /dev/null @@ -1,630 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Create as $Create } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as encoding$0 from "../../../../../../../../encoding/models.js"; -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as json$0 from "../../../../../../../../encoding/json/models.js"; - -/** - * any - * @typedef {any} AliasJsonMarshaler - */ - -/** - * any - * @typedef {any} AliasMarshaler - */ - -/** - * struct{} - * @typedef { { - * } } AliasNonMarshaler - */ - -/** - * string - * @typedef {string} AliasTextMarshaler - */ - -export class Data { - /** - * Creates a new Data instance. - * @param {Partial} [$$source = {}] - The source object to create the Data. - */ - constructor($$source = {}) { - if (!("NM" in $$source)) { - /** - * @member - * @type {NonMarshaler} - */ - this["NM"] = (new NonMarshaler()); - } - if (!("NMPtr" in $$source)) { - /** - * NonMarshaler | null - * @member - * @type {NonMarshaler | null} - */ - this["NMPtr"] = null; - } - if (!("VJM" in $$source)) { - /** - * @member - * @type {ValueJsonMarshaler} - */ - this["VJM"] = null; - } - if (!("VJMPtr" in $$source)) { - /** - * ValueJsonMarshaler | null - * @member - * @type {ValueJsonMarshaler | null} - */ - this["VJMPtr"] = null; - } - if (!("PJM" in $$source)) { - /** - * @member - * @type {PointerJsonMarshaler} - */ - this["PJM"] = null; - } - if (!("PJMPtr" in $$source)) { - /** - * PointerJsonMarshaler | null - * @member - * @type {PointerJsonMarshaler | null} - */ - this["PJMPtr"] = null; - } - if (!("VTM" in $$source)) { - /** - * @member - * @type {ValueTextMarshaler} - */ - this["VTM"] = ""; - } - if (!("VTMPtr" in $$source)) { - /** - * ValueTextMarshaler | null - * @member - * @type {ValueTextMarshaler | null} - */ - this["VTMPtr"] = null; - } - if (!("PTM" in $$source)) { - /** - * @member - * @type {PointerTextMarshaler} - */ - this["PTM"] = ""; - } - if (!("PTMPtr" in $$source)) { - /** - * PointerTextMarshaler | null - * @member - * @type {PointerTextMarshaler | null} - */ - this["PTMPtr"] = null; - } - if (!("VM" in $$source)) { - /** - * @member - * @type {ValueMarshaler} - */ - this["VM"] = null; - } - if (!("VMPtr" in $$source)) { - /** - * ValueMarshaler | null - * @member - * @type {ValueMarshaler | null} - */ - this["VMPtr"] = null; - } - if (!("PM" in $$source)) { - /** - * @member - * @type {PointerMarshaler} - */ - this["PM"] = null; - } - if (!("PMPtr" in $$source)) { - /** - * PointerMarshaler | null - * @member - * @type {PointerMarshaler | null} - */ - this["PMPtr"] = null; - } - if (!("UJM" in $$source)) { - /** - * @member - * @type {UnderlyingJsonMarshaler} - */ - this["UJM"] = null; - } - if (!("UJMPtr" in $$source)) { - /** - * UnderlyingJsonMarshaler | null - * @member - * @type {UnderlyingJsonMarshaler | null} - */ - this["UJMPtr"] = null; - } - if (!("UTM" in $$source)) { - /** - * @member - * @type {UnderlyingTextMarshaler} - */ - this["UTM"] = ""; - } - if (!("UTMPtr" in $$source)) { - /** - * UnderlyingTextMarshaler | null - * @member - * @type {UnderlyingTextMarshaler | null} - */ - this["UTMPtr"] = null; - } - if (!("UM" in $$source)) { - /** - * @member - * @type {UnderlyingMarshaler} - */ - this["UM"] = null; - } - if (!("UMPtr" in $$source)) { - /** - * UnderlyingMarshaler | null - * @member - * @type {UnderlyingMarshaler | null} - */ - this["UMPtr"] = null; - } - if (!("JM" in $$source)) { - /** - * any - * @member - * @type {any} - */ - this["JM"] = null; - } - if (!("JMPtr" in $$source)) { - /** - * any | null - * @member - * @type {any | null} - */ - this["JMPtr"] = null; - } - if (!("TM" in $$source)) { - /** - * string - * @member - * @type {string} - */ - this["TM"] = ""; - } - if (!("TMPtr" in $$source)) { - /** - * string | null - * @member - * @type {string | null} - */ - this["TMPtr"] = null; - } - if (!("CJM" in $$source)) { - /** - * any - * @member - * @type {any} - */ - this["CJM"] = null; - } - if (!("CJMPtr" in $$source)) { - /** - * any | null - * @member - * @type {any | null} - */ - this["CJMPtr"] = null; - } - if (!("CTM" in $$source)) { - /** - * string - * @member - * @type {string} - */ - this["CTM"] = ""; - } - if (!("CTMPtr" in $$source)) { - /** - * string | null - * @member - * @type {string | null} - */ - this["CTMPtr"] = null; - } - if (!("CM" in $$source)) { - /** - * any - * @member - * @type {any} - */ - this["CM"] = null; - } - if (!("CMPtr" in $$source)) { - /** - * any | null - * @member - * @type {any | null} - */ - this["CMPtr"] = null; - } - if (!("ANM" in $$source)) { - /** - * @member - * @type {AliasNonMarshaler} - */ - this["ANM"] = {}; - } - if (!("ANMPtr" in $$source)) { - /** - * AliasNonMarshaler | null - * @member - * @type {AliasNonMarshaler | null} - */ - this["ANMPtr"] = null; - } - if (!("AJM" in $$source)) { - /** - * @member - * @type {AliasJsonMarshaler} - */ - this["AJM"] = null; - } - if (!("AJMPtr" in $$source)) { - /** - * AliasJsonMarshaler | null - * @member - * @type {AliasJsonMarshaler | null} - */ - this["AJMPtr"] = null; - } - if (!("ATM" in $$source)) { - /** - * @member - * @type {AliasTextMarshaler} - */ - this["ATM"] = ""; - } - if (!("ATMPtr" in $$source)) { - /** - * AliasTextMarshaler | null - * @member - * @type {AliasTextMarshaler | null} - */ - this["ATMPtr"] = null; - } - if (!("AM" in $$source)) { - /** - * @member - * @type {AliasMarshaler} - */ - this["AM"] = null; - } - if (!("AMPtr" in $$source)) { - /** - * AliasMarshaler | null - * @member - * @type {AliasMarshaler | null} - */ - this["AMPtr"] = null; - } - if (!("ImJM" in $$source)) { - /** - * @member - * @type {ImplicitJsonMarshaler} - */ - this["ImJM"] = null; - } - if (!("ImJMPtr" in $$source)) { - /** - * ImplicitJsonMarshaler | null - * @member - * @type {ImplicitJsonMarshaler | null} - */ - this["ImJMPtr"] = null; - } - if (!("ImTM" in $$source)) { - /** - * @member - * @type {ImplicitTextMarshaler} - */ - this["ImTM"] = ""; - } - if (!("ImTMPtr" in $$source)) { - /** - * ImplicitTextMarshaler | null - * @member - * @type {ImplicitTextMarshaler | null} - */ - this["ImTMPtr"] = null; - } - if (!("ImM" in $$source)) { - /** - * @member - * @type {ImplicitMarshaler} - */ - this["ImM"] = null; - } - if (!("ImMPtr" in $$source)) { - /** - * ImplicitMarshaler | null - * @member - * @type {ImplicitMarshaler | null} - */ - this["ImMPtr"] = null; - } - if (!("ImNJ" in $$source)) { - /** - * @member - * @type {ImplicitNonJson} - */ - this["ImNJ"] = ""; - } - if (!("ImNJPtr" in $$source)) { - /** - * ImplicitNonJson | null - * @member - * @type {ImplicitNonJson | null} - */ - this["ImNJPtr"] = null; - } - if (!("ImNT" in $$source)) { - /** - * @member - * @type {ImplicitNonText} - */ - this["ImNT"] = null; - } - if (!("ImNTPtr" in $$source)) { - /** - * ImplicitNonText | null - * @member - * @type {ImplicitNonText | null} - */ - this["ImNTPtr"] = null; - } - if (!("ImNM" in $$source)) { - /** - * @member - * @type {ImplicitNonMarshaler} - */ - this["ImNM"] = (new ImplicitNonMarshaler()); - } - if (!("ImNMPtr" in $$source)) { - /** - * ImplicitNonMarshaler | null - * @member - * @type {ImplicitNonMarshaler | null} - */ - this["ImNMPtr"] = null; - } - if (!("ImJbT" in $$source)) { - /** - * @member - * @type {ImplicitJsonButText} - */ - this["ImJbT"] = null; - } - if (!("ImJbTPtr" in $$source)) { - /** - * ImplicitJsonButText | null - * @member - * @type {ImplicitJsonButText | null} - */ - this["ImJbTPtr"] = null; - } - if (!("ImTbJ" in $$source)) { - /** - * @member - * @type {ImplicitTextButJson} - */ - this["ImTbJ"] = null; - } - if (!("ImTbJPtr" in $$source)) { - /** - * ImplicitTextButJson | null - * @member - * @type {ImplicitTextButJson | null} - */ - this["ImTbJPtr"] = null; - } - - Object.assign(this, $$source); - } - - /** - * Creates a new Data instance from a string or object. - * @param {any} [$$source = {}] - * @returns {Data} - */ - static createFrom($$source = {}) { - const $$createField0_0 = $$createType0; - const $$createField1_0 = $$createType1; - const $$createField48_0 = $$createType2; - const $$createField49_0 = $$createType3; - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - if ("NM" in $$parsedSource) { - $$parsedSource["NM"] = $$createField0_0($$parsedSource["NM"]); - } - if ("NMPtr" in $$parsedSource) { - $$parsedSource["NMPtr"] = $$createField1_0($$parsedSource["NMPtr"]); - } - if ("ImNM" in $$parsedSource) { - $$parsedSource["ImNM"] = $$createField48_0($$parsedSource["ImNM"]); - } - if ("ImNMPtr" in $$parsedSource) { - $$parsedSource["ImNMPtr"] = $$createField49_0($$parsedSource["ImNMPtr"]); - } - return new Data(/** @type {Partial} */($$parsedSource)); - } -} - -/** - * any - * @typedef {any} ImplicitJsonButText - */ - -/** - * any - * @typedef {any} ImplicitJsonMarshaler - */ - -/** - * any - * @typedef {any} ImplicitMarshaler - */ - -/** - * string - * @typedef {string} ImplicitNonJson - */ - -/** - * class{ Marshaler, TextMarshaler } - */ -export class ImplicitNonMarshaler { - /** - * Creates a new ImplicitNonMarshaler instance. - * @param {Partial} [$$source = {}] - The source object to create the ImplicitNonMarshaler. - */ - constructor($$source = {}) { - if (!("Marshaler" in $$source)) { - /** - * @member - * @type {json$0.Marshaler} - */ - this["Marshaler"] = null; - } - if (!("TextMarshaler" in $$source)) { - /** - * @member - * @type {encoding$0.TextMarshaler} - */ - this["TextMarshaler"] = ""; - } - - Object.assign(this, $$source); - } - - /** - * Creates a new ImplicitNonMarshaler instance from a string or object. - * @param {any} [$$source = {}] - * @returns {ImplicitNonMarshaler} - */ - static createFrom($$source = {}) { - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - return new ImplicitNonMarshaler(/** @type {Partial} */($$parsedSource)); - } -} - -/** - * any - * @typedef {any} ImplicitNonText - */ - -/** - * any - * @typedef {any} ImplicitTextButJson - */ - -/** - * string - * @typedef {string} ImplicitTextMarshaler - */ - -/** - * class {} - */ -export class NonMarshaler { - /** - * Creates a new NonMarshaler instance. - * @param {Partial} [$$source = {}] - The source object to create the NonMarshaler. - */ - constructor($$source = {}) { - - Object.assign(this, $$source); - } - - /** - * Creates a new NonMarshaler instance from a string or object. - * @param {any} [$$source = {}] - * @returns {NonMarshaler} - */ - static createFrom($$source = {}) { - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - return new NonMarshaler(/** @type {Partial} */($$parsedSource)); - } -} - -/** - * any - * @typedef {any} PointerJsonMarshaler - */ - -/** - * any - * @typedef {any} PointerMarshaler - */ - -/** - * string - * @typedef {string} PointerTextMarshaler - */ - -/** - * any - * @typedef {any} UnderlyingJsonMarshaler - */ - -/** - * any - * @typedef {any} UnderlyingMarshaler - */ - -/** - * string - * @typedef {string} UnderlyingTextMarshaler - */ - -/** - * any - * @typedef {any} ValueJsonMarshaler - */ - -/** - * any - * @typedef {any} ValueMarshaler - */ - -/** - * string - * @typedef {string} ValueTextMarshaler - */ - -// Private type creation functions -const $$createType0 = NonMarshaler.createFrom; -const $$createType1 = $Create.Nullable($$createType0); -const $$createType2 = ImplicitNonMarshaler.createFrom; -const $$createType3 = $Create.Nullable($$createType2); diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/marshalers/service.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/marshalers/service.js deleted file mode 100644 index e6c23e4f0..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/marshalers/service.js +++ /dev/null @@ -1,23 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * @returns {$CancellablePromise<$models.Data>} - */ -export function Method() { - return $Call.ByName("main.Service.Method").then(/** @type {($result: any) => any} */(($result) => { - return $$createType0($result); - })); -} - -// Private type creation functions -const $$createType0 = $models.Data.createFrom; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/index.js deleted file mode 100644 index 9be766c03..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/index.js +++ /dev/null @@ -1,15 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as SomeMethods from "./somemethods.js"; -export { - SomeMethods -}; - -export { - HowDifferent, - Impersonator, - Person, - PrivatePerson -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/models.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/models.js deleted file mode 100644 index c443e292a..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/models.js +++ /dev/null @@ -1,181 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Create as $Create } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as other$0 from "./other/models.js"; - -/** - * HowDifferent is a curious kind of person - * that lets other people decide how they are different. - * @template How - */ -export class HowDifferent { - /** - * Creates a new HowDifferent instance. - * @param {Partial>} [$$source = {}] - The source object to create the HowDifferent. - */ - constructor($$source = {}) { - if (!("Name" in $$source)) { - /** - * They have a name as well. - * @member - * @type {string} - */ - this["Name"] = ""; - } - if (!("Differences" in $$source)) { - /** - * But they may have many differences. - * @member - * @type {{ [_ in string]?: How }[]} - */ - this["Differences"] = []; - } - - Object.assign(this, $$source); - } - - /** - * Given creation functions for each type parameter, - * returns a creation function for a concrete instance - * of the generic class HowDifferent. - * @template [How=any] - * @param {(source: any) => How} $$createParamHow - * @returns {($$source?: any) => HowDifferent} - */ - static createFrom($$createParamHow) { - const $$createField1_0 = $$createType1($$createParamHow); - return ($$source = {}) => { - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - if ("Differences" in $$parsedSource) { - $$parsedSource["Differences"] = $$createField1_0($$parsedSource["Differences"]); - } - return new HowDifferent(/** @type {Partial>} */($$parsedSource)); - }; - } -} - -/** - * Impersonator gets their fields from other people. - */ -export const Impersonator = other$0.OtherPerson; - -/** - * Impersonator gets their fields from other people. - * @typedef {other$0.OtherPerson} Impersonator - */ - -/** - * Person is not a number. - */ -export class Person { - /** - * Creates a new Person instance. - * @param {Partial} [$$source = {}] - The source object to create the Person. - */ - constructor($$source = {}) { - if (!("Name" in $$source)) { - /** - * They have a name. - * @member - * @type {string} - */ - this["Name"] = ""; - } - if (!("Friends" in $$source)) { - /** - * Exactly 4 sketchy friends. - * @member - * @type {Impersonator[]} - */ - this["Friends"] = Array.from({ length: 4 }, () => (new Impersonator())); - } - - Object.assign(this, $$source); - } - - /** - * Creates a new Person instance from a string or object. - * @param {any} [$$source = {}] - * @returns {Person} - */ - static createFrom($$source = {}) { - const $$createField1_0 = $$createType3; - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - if ("Friends" in $$parsedSource) { - $$parsedSource["Friends"] = $$createField1_0($$parsedSource["Friends"]); - } - return new Person(/** @type {Partial} */($$parsedSource)); - } -} - -export class personImpl { - /** - * Creates a new personImpl instance. - * @param {Partial} [$$source = {}] - The source object to create the personImpl. - */ - constructor($$source = {}) { - if (!("Nickname" in $$source)) { - /** - * Nickname conceals a person's identity. - * @member - * @type {string} - */ - this["Nickname"] = ""; - } - if (!("Name" in $$source)) { - /** - * They have a name. - * @member - * @type {string} - */ - this["Name"] = ""; - } - if (!("Friends" in $$source)) { - /** - * Exactly 4 sketchy friends. - * @member - * @type {Impersonator[]} - */ - this["Friends"] = Array.from({ length: 4 }, () => (new Impersonator())); - } - - Object.assign(this, $$source); - } - - /** - * Creates a new personImpl instance from a string or object. - * @param {any} [$$source = {}] - * @returns {personImpl} - */ - static createFrom($$source = {}) { - const $$createField2_0 = $$createType3; - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - if ("Friends" in $$parsedSource) { - $$parsedSource["Friends"] = $$createField2_0($$parsedSource["Friends"]); - } - return new personImpl(/** @type {Partial} */($$parsedSource)); - } -} - -/** - * PrivatePerson gets their fields from hidden sources. - */ -export const PrivatePerson = personImpl; - -/** - * PrivatePerson gets their fields from hidden sources. - * @typedef {personImpl} PrivatePerson - */ - -// Private type creation functions -const $$createType0 = /** @type {(...args: any[]) => any} */(($$createParamHow) => $Create.Map($Create.Any, $$createParamHow)); -const $$createType1 = /** @type {(...args: any[]) => any} */(($$createParamHow) => $Create.Array($$createType0($$createParamHow))); -const $$createType2 = other$0.OtherPerson.createFrom($Create.Any); -const $$createType3 = $Create.Array($$createType2); diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/more/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/more/index.js deleted file mode 100644 index c3eabd022..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/more/index.js +++ /dev/null @@ -1,10 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as $models from "./models.js"; - -/** - * StringPtr is a nullable string. - * @typedef {$models.StringPtr} StringPtr - */ diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/more/models.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/more/models.js deleted file mode 100644 index b4fdacf8e..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/more/models.js +++ /dev/null @@ -1,12 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Create as $Create } from "/wails/runtime.js"; - -/** - * StringPtr is a nullable string. - * @typedef {string | null} StringPtr - */ diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/other/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/other/index.js deleted file mode 100644 index db4e64147..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/other/index.js +++ /dev/null @@ -1,12 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as OtherMethods from "./othermethods.js"; -export { - OtherMethods -}; - -export { - OtherPerson -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/other/models.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/other/models.js deleted file mode 100644 index 89992cacf..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/other/models.js +++ /dev/null @@ -1,60 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Create as $Create } from "/wails/runtime.js"; - -/** - * OtherPerson is like a person, but different. - * @template T - */ -export class OtherPerson { - /** - * Creates a new OtherPerson instance. - * @param {Partial>} [$$source = {}] - The source object to create the OtherPerson. - */ - constructor($$source = {}) { - if (!("Name" in $$source)) { - /** - * They have a name as well. - * @member - * @type {string} - */ - this["Name"] = ""; - } - if (!("Differences" in $$source)) { - /** - * But they may have many differences. - * @member - * @type {T[]} - */ - this["Differences"] = []; - } - - Object.assign(this, $$source); - } - - /** - * Given creation functions for each type parameter, - * returns a creation function for a concrete instance - * of the generic class OtherPerson. - * @template [T=any] - * @param {(source: any) => T} $$createParamT - * @returns {($$source?: any) => OtherPerson} - */ - static createFrom($$createParamT) { - const $$createField1_0 = $$createType0($$createParamT); - return ($$source = {}) => { - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - if ("Differences" in $$parsedSource) { - $$parsedSource["Differences"] = $$createField1_0($$parsedSource["Differences"]); - } - return new OtherPerson(/** @type {Partial>} */($$parsedSource)); - }; - } -} - -// Private type creation functions -const $$createType0 = /** @type {(...args: any[]) => any} */(($$createParamT) => $Create.Array($$createParamT)); diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/other/othermethods.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/other/othermethods.js deleted file mode 100644 index d2819bc4b..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/other/othermethods.js +++ /dev/null @@ -1,20 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * OtherMethods has another method, but through a private embedded type. - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -/** - * LikeThisOtherOne does nothing as well, but is different. - * @returns {$CancellablePromise} - */ -export function LikeThisOtherOne() { - return $Call.ByName("github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/other.OtherMethods.LikeThisOtherOne"); -} diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/somemethods.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/somemethods.js deleted file mode 100644 index 35bc3579d..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/somemethods.js +++ /dev/null @@ -1,42 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * SomeMethods exports some methods. - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * LikeThisOne is an example method that does nothing. - * @returns {$CancellablePromise<[$models.Person, $models.HowDifferent, $models.PrivatePerson]>} - */ -export function LikeThisOne() { - return $Call.ByName("github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here.SomeMethods.LikeThisOne").then(/** @type {($result: any) => any} */(($result) => { - $result[0] = $$createType0($result[0]); - $result[1] = $$createType1($result[1]); - $result[2] = $$createType2($result[2]); - return $result; - })); -} - -/** - * LikeThisOtherOne does nothing as well, but is different. - * @returns {$CancellablePromise} - */ -export function LikeThisOtherOne() { - return $Call.ByName("github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here.SomeMethods.LikeThisOtherOne"); -} - -// Private type creation functions -const $$createType0 = $models.Person.createFrom; -const $$createType1 = $models.HowDifferent.createFrom($Create.Any); -const $$createType2 = $models.personImpl.createFrom; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/out_of_tree/embedother.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/out_of_tree/embedother.js deleted file mode 100644 index 0497b16bc..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/out_of_tree/embedother.js +++ /dev/null @@ -1,20 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * EmbedOther is even trickier. - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -/** - * LikeThisOtherOne does nothing as well, but is different. - * @returns {$CancellablePromise} - */ -export function LikeThisOtherOne() { - return $Call.ByName("main.EmbedOther.LikeThisOtherOne"); -} diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/out_of_tree/embedservice.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/out_of_tree/embedservice.js deleted file mode 100644 index 903e4153f..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/out_of_tree/embedservice.js +++ /dev/null @@ -1,42 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * EmbedService is tricky. - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as nobindingshere$0 from "../no_bindings_here/models.js"; - -/** - * LikeThisOne is an example method that does nothing. - * @returns {$CancellablePromise<[nobindingshere$0.Person, nobindingshere$0.HowDifferent, nobindingshere$0.PrivatePerson]>} - */ -export function LikeThisOne() { - return $Call.ByName("main.EmbedService.LikeThisOne").then(/** @type {($result: any) => any} */(($result) => { - $result[0] = $$createType0($result[0]); - $result[1] = $$createType1($result[1]); - $result[2] = $$createType2($result[2]); - return $result; - })); -} - -/** - * LikeThisOtherOne does nothing as well, but is different. - * @returns {$CancellablePromise} - */ -export function LikeThisOtherOne() { - return $Call.ByName("main.EmbedService.LikeThisOtherOne"); -} - -// Private type creation functions -const $$createType0 = nobindingshere$0.Person.createFrom; -const $$createType1 = nobindingshere$0.HowDifferent.createFrom($Create.Any); -const $$createType2 = nobindingshere$0.personImpl.createFrom; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/out_of_tree/greetservice.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/out_of_tree/greetservice.js deleted file mode 100644 index fe683f548..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/out_of_tree/greetservice.js +++ /dev/null @@ -1,21 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -/** - * Greet someone - * @param {string} $0 - * @returns {$CancellablePromise} - */ -export function Greet($0) { - return $Call.ByName("main.GreetService.Greet", $0); -} diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/out_of_tree/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/out_of_tree/index.js deleted file mode 100644 index 734fb02e7..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/out_of_tree/index.js +++ /dev/null @@ -1,12 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as EmbedOther from "./embedother.js"; -import * as EmbedService from "./embedservice.js"; -import * as GreetService from "./greetservice.js"; -export { - EmbedOther, - EmbedService, - GreetService -}; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple/greetservice.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple/greetservice.js deleted file mode 100644 index e6a0e3a74..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple/greetservice.js +++ /dev/null @@ -1,15 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -/** - * @param {string} name - * @returns {$CancellablePromise} - */ -export function Greet(name) { - return $Call.ByName("main.GreetService.Greet", name); -} diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple/index.js deleted file mode 100644 index 62ddbc166..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple/index.js +++ /dev/null @@ -1,10 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -import * as OtherService from "./otherservice.js"; -export { - GreetService, - OtherService -}; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple/otherservice.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple/otherservice.js deleted file mode 100644 index 69652f626..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple/otherservice.js +++ /dev/null @@ -1,14 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -/** - * @returns {$CancellablePromise} - */ -export function Hello() { - return $Call.ByName("main.OtherService.Hello"); -} diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_files/greetservice.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_files/greetservice.js deleted file mode 100644 index e6a0e3a74..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_files/greetservice.js +++ /dev/null @@ -1,15 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -/** - * @param {string} name - * @returns {$CancellablePromise} - */ -export function Greet(name) { - return $Call.ByName("main.GreetService.Greet", name); -} diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_files/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_files/index.js deleted file mode 100644 index 62ddbc166..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_files/index.js +++ /dev/null @@ -1,10 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -import * as OtherService from "./otherservice.js"; -export { - GreetService, - OtherService -}; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_files/otherservice.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_files/otherservice.js deleted file mode 100644 index 69652f626..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_files/otherservice.js +++ /dev/null @@ -1,14 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -/** - * @returns {$CancellablePromise} - */ -export function Hello() { - return $Call.ByName("main.OtherService.Hello"); -} diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_other/greetservice.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_other/greetservice.js deleted file mode 100644 index 16a94df37..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_other/greetservice.js +++ /dev/null @@ -1,40 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * Greet does XYZ - * @param {string} name - * @returns {$CancellablePromise} - */ -export function Greet(name) { - return $Call.ByName("main.GreetService.Greet", name); -} - -/** - * NewPerson creates a new person - * @param {string} name - * @returns {$CancellablePromise<$models.Person | null>} - */ -export function NewPerson(name) { - return $Call.ByName("main.GreetService.NewPerson", name).then(/** @type {($result: any) => any} */(($result) => { - return $$createType1($result); - })); -} - -// Private type creation functions -const $$createType0 = $models.Person.createFrom; -const $$createType1 = $Create.Nullable($$createType0); diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_other/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_other/index.js deleted file mode 100644 index fefe6b6ba..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_other/index.js +++ /dev/null @@ -1,12 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; - -export { - Person -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_other/models.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_other/models.js deleted file mode 100644 index 04771d2ca..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_other/models.js +++ /dev/null @@ -1,54 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Create as $Create } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as services$0 from "./services/models.js"; - -export class Person { - /** - * Creates a new Person instance. - * @param {Partial} [$$source = {}] - The source object to create the Person. - */ - constructor($$source = {}) { - if (!("Name" in $$source)) { - /** - * @member - * @type {string} - */ - this["Name"] = ""; - } - if (!("Address" in $$source)) { - /** - * @member - * @type {services$0.Address | null} - */ - this["Address"] = null; - } - - Object.assign(this, $$source); - } - - /** - * Creates a new Person instance from a string or object. - * @param {any} [$$source = {}] - * @returns {Person} - */ - static createFrom($$source = {}) { - const $$createField1_0 = $$createType1; - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - if ("Address" in $$parsedSource) { - $$parsedSource["Address"] = $$createField1_0($$parsedSource["Address"]); - } - return new Person(/** @type {Partial} */($$parsedSource)); - } -} - -// Private type creation functions -const $$createType0 = services$0.Address.createFrom; -const $$createType1 = $Create.Nullable($$createType0); diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_other/services/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_other/services/index.js deleted file mode 100644 index ed65b6d15..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_other/services/index.js +++ /dev/null @@ -1,12 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as OtherService from "./otherservice.js"; -export { - OtherService -}; - -export { - Address -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_other/services/models.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_other/services/models.js deleted file mode 100644 index 24a5de807..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_other/services/models.js +++ /dev/null @@ -1,49 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Create as $Create } from "/wails/runtime.js"; - -export class Address { - /** - * Creates a new Address instance. - * @param {Partial
                    } [$$source = {}] - The source object to create the Address. - */ - constructor($$source = {}) { - if (!("Street" in $$source)) { - /** - * @member - * @type {string} - */ - this["Street"] = ""; - } - if (!("State" in $$source)) { - /** - * @member - * @type {string} - */ - this["State"] = ""; - } - if (!("Country" in $$source)) { - /** - * @member - * @type {string} - */ - this["Country"] = ""; - } - - Object.assign(this, $$source); - } - - /** - * Creates a new Address instance from a string or object. - * @param {any} [$$source = {}] - * @returns {Address} - */ - static createFrom($$source = {}) { - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - return new Address(/** @type {Partial
                    } */($$parsedSource)); - } -} diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_other/services/otherservice.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_other/services/otherservice.js deleted file mode 100644 index 327b15c9c..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_other/services/otherservice.js +++ /dev/null @@ -1,31 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * OtherService is a struct - * that does things - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * Yay does this and that - * @returns {$CancellablePromise<$models.Address | null>} - */ -export function Yay() { - return $Call.ByName("github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_other/services.OtherService.Yay").then(/** @type {($result: any) => any} */(($result) => { - return $$createType1($result); - })); -} - -// Private type creation functions -const $$createType0 = $models.Address.createFrom; -const $$createType1 = $Create.Nullable($$createType0); diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_non_pointer_single/greetservice.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_non_pointer_single/greetservice.js deleted file mode 100644 index f6d1adf22..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_non_pointer_single/greetservice.js +++ /dev/null @@ -1,379 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * @param {number[]} $in - * @returns {$CancellablePromise} - */ -export function ArrayInt($in) { - return $Call.ByName("main.GreetService.ArrayInt", $in); -} - -/** - * @param {boolean} $in - * @returns {$CancellablePromise} - */ -export function BoolInBoolOut($in) { - return $Call.ByName("main.GreetService.BoolInBoolOut", $in); -} - -/** - * @param {number} $in - * @returns {$CancellablePromise} - */ -export function Float32InFloat32Out($in) { - return $Call.ByName("main.GreetService.Float32InFloat32Out", $in); -} - -/** - * @param {number} $in - * @returns {$CancellablePromise} - */ -export function Float64InFloat64Out($in) { - return $Call.ByName("main.GreetService.Float64InFloat64Out", $in); -} - -/** - * Greet someone - * @param {string} name - * @returns {$CancellablePromise} - */ -export function Greet(name) { - return $Call.ByName("main.GreetService.Greet", name); -} - -/** - * @param {number} $in - * @returns {$CancellablePromise} - */ -export function Int16InIntOut($in) { - return $Call.ByName("main.GreetService.Int16InIntOut", $in); -} - -/** - * @param {number | null} $in - * @returns {$CancellablePromise} - */ -export function Int16PointerInAndOutput($in) { - return $Call.ByName("main.GreetService.Int16PointerInAndOutput", $in); -} - -/** - * @param {number} $in - * @returns {$CancellablePromise} - */ -export function Int32InIntOut($in) { - return $Call.ByName("main.GreetService.Int32InIntOut", $in); -} - -/** - * @param {number | null} $in - * @returns {$CancellablePromise} - */ -export function Int32PointerInAndOutput($in) { - return $Call.ByName("main.GreetService.Int32PointerInAndOutput", $in); -} - -/** - * @param {number} $in - * @returns {$CancellablePromise} - */ -export function Int64InIntOut($in) { - return $Call.ByName("main.GreetService.Int64InIntOut", $in); -} - -/** - * @param {number | null} $in - * @returns {$CancellablePromise} - */ -export function Int64PointerInAndOutput($in) { - return $Call.ByName("main.GreetService.Int64PointerInAndOutput", $in); -} - -/** - * @param {number} $in - * @returns {$CancellablePromise} - */ -export function Int8InIntOut($in) { - return $Call.ByName("main.GreetService.Int8InIntOut", $in); -} - -/** - * @param {number | null} $in - * @returns {$CancellablePromise} - */ -export function Int8PointerInAndOutput($in) { - return $Call.ByName("main.GreetService.Int8PointerInAndOutput", $in); -} - -/** - * @param {number} $in - * @returns {$CancellablePromise} - */ -export function IntInIntOut($in) { - return $Call.ByName("main.GreetService.IntInIntOut", $in); -} - -/** - * @param {number | null} $in - * @returns {$CancellablePromise} - */ -export function IntPointerInAndOutput($in) { - return $Call.ByName("main.GreetService.IntPointerInAndOutput", $in); -} - -/** - * @param {number | null} $in - * @returns {$CancellablePromise} - */ -export function IntPointerInputNamedOutputs($in) { - return $Call.ByName("main.GreetService.IntPointerInputNamedOutputs", $in); -} - -/** - * @param {{ [_ in `${number}`]?: number }} $in - * @returns {$CancellablePromise} - */ -export function MapIntInt($in) { - return $Call.ByName("main.GreetService.MapIntInt", $in); -} - -/** - * @param {{ [_ in `${number}`]?: number | null }} $in - * @returns {$CancellablePromise} - */ -export function MapIntIntPointer($in) { - return $Call.ByName("main.GreetService.MapIntIntPointer", $in); -} - -/** - * @param {{ [_ in `${number}`]?: number[] }} $in - * @returns {$CancellablePromise} - */ -export function MapIntSliceInt($in) { - return $Call.ByName("main.GreetService.MapIntSliceInt", $in); -} - -/** - * @param {{ [_ in `${number}`]?: number[] }} $in - * @returns {$CancellablePromise<{ [_ in `${number}`]?: number[] }>} - */ -export function MapIntSliceIntInMapIntSliceIntOut($in) { - return $Call.ByName("main.GreetService.MapIntSliceIntInMapIntSliceIntOut", $in).then(/** @type {($result: any) => any} */(($result) => { - return $$createType1($result); - })); -} - -/** - * @returns {$CancellablePromise} - */ -export function NoInputsStringOut() { - return $Call.ByName("main.GreetService.NoInputsStringOut"); -} - -/** - * @param {boolean | null} $in - * @returns {$CancellablePromise} - */ -export function PointerBoolInBoolOut($in) { - return $Call.ByName("main.GreetService.PointerBoolInBoolOut", $in); -} - -/** - * @param {number | null} $in - * @returns {$CancellablePromise} - */ -export function PointerFloat32InFloat32Out($in) { - return $Call.ByName("main.GreetService.PointerFloat32InFloat32Out", $in); -} - -/** - * @param {number | null} $in - * @returns {$CancellablePromise} - */ -export function PointerFloat64InFloat64Out($in) { - return $Call.ByName("main.GreetService.PointerFloat64InFloat64Out", $in); -} - -/** - * @param {{ [_ in `${number}`]?: number } | null} $in - * @returns {$CancellablePromise} - */ -export function PointerMapIntInt($in) { - return $Call.ByName("main.GreetService.PointerMapIntInt", $in); -} - -/** - * @param {string | null} $in - * @returns {$CancellablePromise} - */ -export function PointerStringInStringOut($in) { - return $Call.ByName("main.GreetService.PointerStringInStringOut", $in); -} - -/** - * @param {string[]} $in - * @returns {$CancellablePromise} - */ -export function StringArrayInputNamedOutput($in) { - return $Call.ByName("main.GreetService.StringArrayInputNamedOutput", $in).then(/** @type {($result: any) => any} */(($result) => { - return $$createType2($result); - })); -} - -/** - * @param {string[]} $in - * @returns {$CancellablePromise} - */ -export function StringArrayInputNamedOutputs($in) { - return $Call.ByName("main.GreetService.StringArrayInputNamedOutputs", $in).then(/** @type {($result: any) => any} */(($result) => { - return $$createType2($result); - })); -} - -/** - * @param {string[]} $in - * @returns {$CancellablePromise} - */ -export function StringArrayInputStringArrayOut($in) { - return $Call.ByName("main.GreetService.StringArrayInputStringArrayOut", $in).then(/** @type {($result: any) => any} */(($result) => { - return $$createType2($result); - })); -} - -/** - * @param {string[]} $in - * @returns {$CancellablePromise} - */ -export function StringArrayInputStringOut($in) { - return $Call.ByName("main.GreetService.StringArrayInputStringOut", $in); -} - -/** - * @param {$models.Person} $in - * @returns {$CancellablePromise<$models.Person>} - */ -export function StructInputStructOutput($in) { - return $Call.ByName("main.GreetService.StructInputStructOutput", $in).then(/** @type {($result: any) => any} */(($result) => { - return $$createType3($result); - })); -} - -/** - * @param {$models.Person | null} $in - * @returns {$CancellablePromise} - */ -export function StructPointerInputErrorOutput($in) { - return $Call.ByName("main.GreetService.StructPointerInputErrorOutput", $in); -} - -/** - * @param {$models.Person | null} $in - * @returns {$CancellablePromise<$models.Person | null>} - */ -export function StructPointerInputStructPointerOutput($in) { - return $Call.ByName("main.GreetService.StructPointerInputStructPointerOutput", $in).then(/** @type {($result: any) => any} */(($result) => { - return $$createType4($result); - })); -} - -/** - * @param {number} $in - * @returns {$CancellablePromise} - */ -export function UInt16InUIntOut($in) { - return $Call.ByName("main.GreetService.UInt16InUIntOut", $in); -} - -/** - * @param {number | null} $in - * @returns {$CancellablePromise} - */ -export function UInt16PointerInAndOutput($in) { - return $Call.ByName("main.GreetService.UInt16PointerInAndOutput", $in); -} - -/** - * @param {number} $in - * @returns {$CancellablePromise} - */ -export function UInt32InUIntOut($in) { - return $Call.ByName("main.GreetService.UInt32InUIntOut", $in); -} - -/** - * @param {number | null} $in - * @returns {$CancellablePromise} - */ -export function UInt32PointerInAndOutput($in) { - return $Call.ByName("main.GreetService.UInt32PointerInAndOutput", $in); -} - -/** - * @param {number} $in - * @returns {$CancellablePromise} - */ -export function UInt64InUIntOut($in) { - return $Call.ByName("main.GreetService.UInt64InUIntOut", $in); -} - -/** - * @param {number | null} $in - * @returns {$CancellablePromise} - */ -export function UInt64PointerInAndOutput($in) { - return $Call.ByName("main.GreetService.UInt64PointerInAndOutput", $in); -} - -/** - * @param {number} $in - * @returns {$CancellablePromise} - */ -export function UInt8InUIntOut($in) { - return $Call.ByName("main.GreetService.UInt8InUIntOut", $in); -} - -/** - * @param {number | null} $in - * @returns {$CancellablePromise} - */ -export function UInt8PointerInAndOutput($in) { - return $Call.ByName("main.GreetService.UInt8PointerInAndOutput", $in); -} - -/** - * @param {number} $in - * @returns {$CancellablePromise} - */ -export function UIntInUIntOut($in) { - return $Call.ByName("main.GreetService.UIntInUIntOut", $in); -} - -/** - * @param {number | null} $in - * @returns {$CancellablePromise} - */ -export function UIntPointerInAndOutput($in) { - return $Call.ByName("main.GreetService.UIntPointerInAndOutput", $in); -} - -// Private type creation functions -const $$createType0 = $Create.Array($Create.Any); -const $$createType1 = $Create.Map($Create.Any, $$createType0); -const $$createType2 = $Create.Array($Create.Any); -const $$createType3 = $models.Person.createFrom; -const $$createType4 = $Create.Nullable($$createType3); diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_non_pointer_single/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_non_pointer_single/index.js deleted file mode 100644 index fefe6b6ba..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_non_pointer_single/index.js +++ /dev/null @@ -1,12 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; - -export { - Person -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_non_pointer_single/models.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_non_pointer_single/models.js deleted file mode 100644 index 69c96370a..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_non_pointer_single/models.js +++ /dev/null @@ -1,57 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Create as $Create } from "/wails/runtime.js"; - -export class Person { - /** - * Creates a new Person instance. - * @param {Partial} [$$source = {}] - The source object to create the Person. - */ - constructor($$source = {}) { - if (!("Name" in $$source)) { - /** - * @member - * @type {string} - */ - this["Name"] = ""; - } - if (!("Parent" in $$source)) { - /** - * @member - * @type {Person | null} - */ - this["Parent"] = null; - } - if (!("Details" in $$source)) { - /** - * @member - * @type {{"Age": number, "Address": {"Street": string}}} - */ - this["Details"] = {"Age": 0, "Address": {"Street": ""}}; - } - - Object.assign(this, $$source); - } - - /** - * Creates a new Person instance from a string or object. - * @param {any} [$$source = {}] - * @returns {Person} - */ - static createFrom($$source = {}) { - const $$createField1_0 = $$createType1; - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - if ("Parent" in $$parsedSource) { - $$parsedSource["Parent"] = $$createField1_0($$parsedSource["Parent"]); - } - return new Person(/** @type {Partial} */($$parsedSource)); - } -} - -// Private type creation functions -const $$createType0 = Person.createFrom; -const $$createType1 = $Create.Nullable($$createType0); diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_single/greetservice.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_single/greetservice.js deleted file mode 100644 index f6d1adf22..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_single/greetservice.js +++ /dev/null @@ -1,379 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * @param {number[]} $in - * @returns {$CancellablePromise} - */ -export function ArrayInt($in) { - return $Call.ByName("main.GreetService.ArrayInt", $in); -} - -/** - * @param {boolean} $in - * @returns {$CancellablePromise} - */ -export function BoolInBoolOut($in) { - return $Call.ByName("main.GreetService.BoolInBoolOut", $in); -} - -/** - * @param {number} $in - * @returns {$CancellablePromise} - */ -export function Float32InFloat32Out($in) { - return $Call.ByName("main.GreetService.Float32InFloat32Out", $in); -} - -/** - * @param {number} $in - * @returns {$CancellablePromise} - */ -export function Float64InFloat64Out($in) { - return $Call.ByName("main.GreetService.Float64InFloat64Out", $in); -} - -/** - * Greet someone - * @param {string} name - * @returns {$CancellablePromise} - */ -export function Greet(name) { - return $Call.ByName("main.GreetService.Greet", name); -} - -/** - * @param {number} $in - * @returns {$CancellablePromise} - */ -export function Int16InIntOut($in) { - return $Call.ByName("main.GreetService.Int16InIntOut", $in); -} - -/** - * @param {number | null} $in - * @returns {$CancellablePromise} - */ -export function Int16PointerInAndOutput($in) { - return $Call.ByName("main.GreetService.Int16PointerInAndOutput", $in); -} - -/** - * @param {number} $in - * @returns {$CancellablePromise} - */ -export function Int32InIntOut($in) { - return $Call.ByName("main.GreetService.Int32InIntOut", $in); -} - -/** - * @param {number | null} $in - * @returns {$CancellablePromise} - */ -export function Int32PointerInAndOutput($in) { - return $Call.ByName("main.GreetService.Int32PointerInAndOutput", $in); -} - -/** - * @param {number} $in - * @returns {$CancellablePromise} - */ -export function Int64InIntOut($in) { - return $Call.ByName("main.GreetService.Int64InIntOut", $in); -} - -/** - * @param {number | null} $in - * @returns {$CancellablePromise} - */ -export function Int64PointerInAndOutput($in) { - return $Call.ByName("main.GreetService.Int64PointerInAndOutput", $in); -} - -/** - * @param {number} $in - * @returns {$CancellablePromise} - */ -export function Int8InIntOut($in) { - return $Call.ByName("main.GreetService.Int8InIntOut", $in); -} - -/** - * @param {number | null} $in - * @returns {$CancellablePromise} - */ -export function Int8PointerInAndOutput($in) { - return $Call.ByName("main.GreetService.Int8PointerInAndOutput", $in); -} - -/** - * @param {number} $in - * @returns {$CancellablePromise} - */ -export function IntInIntOut($in) { - return $Call.ByName("main.GreetService.IntInIntOut", $in); -} - -/** - * @param {number | null} $in - * @returns {$CancellablePromise} - */ -export function IntPointerInAndOutput($in) { - return $Call.ByName("main.GreetService.IntPointerInAndOutput", $in); -} - -/** - * @param {number | null} $in - * @returns {$CancellablePromise} - */ -export function IntPointerInputNamedOutputs($in) { - return $Call.ByName("main.GreetService.IntPointerInputNamedOutputs", $in); -} - -/** - * @param {{ [_ in `${number}`]?: number }} $in - * @returns {$CancellablePromise} - */ -export function MapIntInt($in) { - return $Call.ByName("main.GreetService.MapIntInt", $in); -} - -/** - * @param {{ [_ in `${number}`]?: number | null }} $in - * @returns {$CancellablePromise} - */ -export function MapIntIntPointer($in) { - return $Call.ByName("main.GreetService.MapIntIntPointer", $in); -} - -/** - * @param {{ [_ in `${number}`]?: number[] }} $in - * @returns {$CancellablePromise} - */ -export function MapIntSliceInt($in) { - return $Call.ByName("main.GreetService.MapIntSliceInt", $in); -} - -/** - * @param {{ [_ in `${number}`]?: number[] }} $in - * @returns {$CancellablePromise<{ [_ in `${number}`]?: number[] }>} - */ -export function MapIntSliceIntInMapIntSliceIntOut($in) { - return $Call.ByName("main.GreetService.MapIntSliceIntInMapIntSliceIntOut", $in).then(/** @type {($result: any) => any} */(($result) => { - return $$createType1($result); - })); -} - -/** - * @returns {$CancellablePromise} - */ -export function NoInputsStringOut() { - return $Call.ByName("main.GreetService.NoInputsStringOut"); -} - -/** - * @param {boolean | null} $in - * @returns {$CancellablePromise} - */ -export function PointerBoolInBoolOut($in) { - return $Call.ByName("main.GreetService.PointerBoolInBoolOut", $in); -} - -/** - * @param {number | null} $in - * @returns {$CancellablePromise} - */ -export function PointerFloat32InFloat32Out($in) { - return $Call.ByName("main.GreetService.PointerFloat32InFloat32Out", $in); -} - -/** - * @param {number | null} $in - * @returns {$CancellablePromise} - */ -export function PointerFloat64InFloat64Out($in) { - return $Call.ByName("main.GreetService.PointerFloat64InFloat64Out", $in); -} - -/** - * @param {{ [_ in `${number}`]?: number } | null} $in - * @returns {$CancellablePromise} - */ -export function PointerMapIntInt($in) { - return $Call.ByName("main.GreetService.PointerMapIntInt", $in); -} - -/** - * @param {string | null} $in - * @returns {$CancellablePromise} - */ -export function PointerStringInStringOut($in) { - return $Call.ByName("main.GreetService.PointerStringInStringOut", $in); -} - -/** - * @param {string[]} $in - * @returns {$CancellablePromise} - */ -export function StringArrayInputNamedOutput($in) { - return $Call.ByName("main.GreetService.StringArrayInputNamedOutput", $in).then(/** @type {($result: any) => any} */(($result) => { - return $$createType2($result); - })); -} - -/** - * @param {string[]} $in - * @returns {$CancellablePromise} - */ -export function StringArrayInputNamedOutputs($in) { - return $Call.ByName("main.GreetService.StringArrayInputNamedOutputs", $in).then(/** @type {($result: any) => any} */(($result) => { - return $$createType2($result); - })); -} - -/** - * @param {string[]} $in - * @returns {$CancellablePromise} - */ -export function StringArrayInputStringArrayOut($in) { - return $Call.ByName("main.GreetService.StringArrayInputStringArrayOut", $in).then(/** @type {($result: any) => any} */(($result) => { - return $$createType2($result); - })); -} - -/** - * @param {string[]} $in - * @returns {$CancellablePromise} - */ -export function StringArrayInputStringOut($in) { - return $Call.ByName("main.GreetService.StringArrayInputStringOut", $in); -} - -/** - * @param {$models.Person} $in - * @returns {$CancellablePromise<$models.Person>} - */ -export function StructInputStructOutput($in) { - return $Call.ByName("main.GreetService.StructInputStructOutput", $in).then(/** @type {($result: any) => any} */(($result) => { - return $$createType3($result); - })); -} - -/** - * @param {$models.Person | null} $in - * @returns {$CancellablePromise} - */ -export function StructPointerInputErrorOutput($in) { - return $Call.ByName("main.GreetService.StructPointerInputErrorOutput", $in); -} - -/** - * @param {$models.Person | null} $in - * @returns {$CancellablePromise<$models.Person | null>} - */ -export function StructPointerInputStructPointerOutput($in) { - return $Call.ByName("main.GreetService.StructPointerInputStructPointerOutput", $in).then(/** @type {($result: any) => any} */(($result) => { - return $$createType4($result); - })); -} - -/** - * @param {number} $in - * @returns {$CancellablePromise} - */ -export function UInt16InUIntOut($in) { - return $Call.ByName("main.GreetService.UInt16InUIntOut", $in); -} - -/** - * @param {number | null} $in - * @returns {$CancellablePromise} - */ -export function UInt16PointerInAndOutput($in) { - return $Call.ByName("main.GreetService.UInt16PointerInAndOutput", $in); -} - -/** - * @param {number} $in - * @returns {$CancellablePromise} - */ -export function UInt32InUIntOut($in) { - return $Call.ByName("main.GreetService.UInt32InUIntOut", $in); -} - -/** - * @param {number | null} $in - * @returns {$CancellablePromise} - */ -export function UInt32PointerInAndOutput($in) { - return $Call.ByName("main.GreetService.UInt32PointerInAndOutput", $in); -} - -/** - * @param {number} $in - * @returns {$CancellablePromise} - */ -export function UInt64InUIntOut($in) { - return $Call.ByName("main.GreetService.UInt64InUIntOut", $in); -} - -/** - * @param {number | null} $in - * @returns {$CancellablePromise} - */ -export function UInt64PointerInAndOutput($in) { - return $Call.ByName("main.GreetService.UInt64PointerInAndOutput", $in); -} - -/** - * @param {number} $in - * @returns {$CancellablePromise} - */ -export function UInt8InUIntOut($in) { - return $Call.ByName("main.GreetService.UInt8InUIntOut", $in); -} - -/** - * @param {number | null} $in - * @returns {$CancellablePromise} - */ -export function UInt8PointerInAndOutput($in) { - return $Call.ByName("main.GreetService.UInt8PointerInAndOutput", $in); -} - -/** - * @param {number} $in - * @returns {$CancellablePromise} - */ -export function UIntInUIntOut($in) { - return $Call.ByName("main.GreetService.UIntInUIntOut", $in); -} - -/** - * @param {number | null} $in - * @returns {$CancellablePromise} - */ -export function UIntPointerInAndOutput($in) { - return $Call.ByName("main.GreetService.UIntPointerInAndOutput", $in); -} - -// Private type creation functions -const $$createType0 = $Create.Array($Create.Any); -const $$createType1 = $Create.Map($Create.Any, $$createType0); -const $$createType2 = $Create.Array($Create.Any); -const $$createType3 = $models.Person.createFrom; -const $$createType4 = $Create.Nullable($$createType3); diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_single/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_single/index.js deleted file mode 100644 index fefe6b6ba..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_single/index.js +++ /dev/null @@ -1,12 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; - -export { - Person -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_single/models.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_single/models.js deleted file mode 100644 index 69c96370a..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_single/models.js +++ /dev/null @@ -1,57 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Create as $Create } from "/wails/runtime.js"; - -export class Person { - /** - * Creates a new Person instance. - * @param {Partial} [$$source = {}] - The source object to create the Person. - */ - constructor($$source = {}) { - if (!("Name" in $$source)) { - /** - * @member - * @type {string} - */ - this["Name"] = ""; - } - if (!("Parent" in $$source)) { - /** - * @member - * @type {Person | null} - */ - this["Parent"] = null; - } - if (!("Details" in $$source)) { - /** - * @member - * @type {{"Age": number, "Address": {"Street": string}}} - */ - this["Details"] = {"Age": 0, "Address": {"Street": ""}}; - } - - Object.assign(this, $$source); - } - - /** - * Creates a new Person instance from a string or object. - * @param {any} [$$source = {}] - * @returns {Person} - */ - static createFrom($$source = {}) { - const $$createField1_0 = $$createType1; - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - if ("Parent" in $$parsedSource) { - $$parsedSource["Parent"] = $$createField1_0($$parsedSource["Parent"]); - } - return new Person(/** @type {Partial} */($$parsedSource)); - } -} - -// Private type creation functions -const $$createType0 = Person.createFrom; -const $$createType1 = $Create.Nullable($$createType0); diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single/greetservice.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single/greetservice.js deleted file mode 100644 index 6364fa8f6..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single/greetservice.js +++ /dev/null @@ -1,21 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -/** - * Greet someone - * @param {string} name - * @returns {$CancellablePromise} - */ -export function Greet(name) { - return $Call.ByName("main.GreetService.Greet", name); -} diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single/index.js deleted file mode 100644 index fdf1ff435..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single/index.js +++ /dev/null @@ -1,8 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_function/greetservice.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_function/greetservice.js deleted file mode 100644 index 6364fa8f6..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_function/greetservice.js +++ /dev/null @@ -1,21 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -/** - * Greet someone - * @param {string} name - * @returns {$CancellablePromise} - */ -export function Greet(name) { - return $Call.ByName("main.GreetService.Greet", name); -} diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_function/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_function/index.js deleted file mode 100644 index fdf1ff435..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_function/index.js +++ /dev/null @@ -1,8 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_other_function/greetservice.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_other_function/greetservice.js deleted file mode 100644 index 16a94df37..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_other_function/greetservice.js +++ /dev/null @@ -1,40 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * Greet does XYZ - * @param {string} name - * @returns {$CancellablePromise} - */ -export function Greet(name) { - return $Call.ByName("main.GreetService.Greet", name); -} - -/** - * NewPerson creates a new person - * @param {string} name - * @returns {$CancellablePromise<$models.Person | null>} - */ -export function NewPerson(name) { - return $Call.ByName("main.GreetService.NewPerson", name).then(/** @type {($result: any) => any} */(($result) => { - return $$createType1($result); - })); -} - -// Private type creation functions -const $$createType0 = $models.Person.createFrom; -const $$createType1 = $Create.Nullable($$createType0); diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_other_function/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_other_function/index.js deleted file mode 100644 index fefe6b6ba..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_other_function/index.js +++ /dev/null @@ -1,12 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; - -export { - Person -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_other_function/models.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_other_function/models.js deleted file mode 100644 index d7bfe75cf..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_other_function/models.js +++ /dev/null @@ -1,58 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Create as $Create } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as services$0 from "./services/models.js"; - -/** - * Person is a person! - * They have a name and an address - */ -export class Person { - /** - * Creates a new Person instance. - * @param {Partial} [$$source = {}] - The source object to create the Person. - */ - constructor($$source = {}) { - if (!("Name" in $$source)) { - /** - * @member - * @type {string} - */ - this["Name"] = ""; - } - if (!("Address" in $$source)) { - /** - * @member - * @type {services$0.Address | null} - */ - this["Address"] = null; - } - - Object.assign(this, $$source); - } - - /** - * Creates a new Person instance from a string or object. - * @param {any} [$$source = {}] - * @returns {Person} - */ - static createFrom($$source = {}) { - const $$createField1_0 = $$createType1; - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - if ("Address" in $$parsedSource) { - $$parsedSource["Address"] = $$createField1_0($$parsedSource["Address"]); - } - return new Person(/** @type {Partial} */($$parsedSource)); - } -} - -// Private type creation functions -const $$createType0 = services$0.Address.createFrom; -const $$createType1 = $Create.Nullable($$createType0); diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_other_function/services/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_other_function/services/index.js deleted file mode 100644 index ed65b6d15..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_other_function/services/index.js +++ /dev/null @@ -1,12 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as OtherService from "./otherservice.js"; -export { - OtherService -}; - -export { - Address -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_other_function/services/models.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_other_function/services/models.js deleted file mode 100644 index 24a5de807..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_other_function/services/models.js +++ /dev/null @@ -1,49 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Create as $Create } from "/wails/runtime.js"; - -export class Address { - /** - * Creates a new Address instance. - * @param {Partial
                    } [$$source = {}] - The source object to create the Address. - */ - constructor($$source = {}) { - if (!("Street" in $$source)) { - /** - * @member - * @type {string} - */ - this["Street"] = ""; - } - if (!("State" in $$source)) { - /** - * @member - * @type {string} - */ - this["State"] = ""; - } - if (!("Country" in $$source)) { - /** - * @member - * @type {string} - */ - this["Country"] = ""; - } - - Object.assign(this, $$source); - } - - /** - * Creates a new Address instance from a string or object. - * @param {any} [$$source = {}] - * @returns {Address} - */ - static createFrom($$source = {}) { - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - return new Address(/** @type {Partial
                    } */($$parsedSource)); - } -} diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_other_function/services/otherservice.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_other_function/services/otherservice.js deleted file mode 100644 index d413366d6..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_other_function/services/otherservice.js +++ /dev/null @@ -1,31 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * OtherService is a struct - * that does things - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * Yay does this and that - * @returns {$CancellablePromise<$models.Address | null>} - */ -export function Yay() { - return $Call.ByName("github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_other_function/services.OtherService.Yay").then(/** @type {($result: any) => any} */(($result) => { - return $$createType1($result); - })); -} - -// Private type creation functions -const $$createType0 = $models.Address.createFrom; -const $$createType1 = $Create.Nullable($$createType0); diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/warnings.log b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/warnings.log deleted file mode 100644 index ce8369307..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=false/UseNames=true/warnings.log +++ /dev/null @@ -1,83 +0,0 @@ -[warn] /testcases/complex_json/main.go:127:2: event 'collision' has one of multiple definitions here with data type map[string]int -[warn] /testcases/events_only/events.go:20:2: event 'collision' has one of multiple definitions here with data type int -[warn] /testcases/events_only/events.go:21:2: `application.RegisterEvent` called here with non-constant event name -[warn] /testcases/events_only/other.go:10:5: `application.RegisterEvent` is instantiated here but not called -[warn] /testcases/events_only/other.go:13:2: `application.RegisterEvent` called here with non-constant event name -[warn] /testcases/events_only/other.go:17:2: data type []T for event 'parametric' contains unresolved type parameters and will be ignored` -[warn] /testcases/events_only/other.go:22:2: event 'common:ApplicationStarted' is a known system event and cannot be overridden; this call to `application.RegisterEvent` will panic -[warn] /testcases/marshalers/main.go:212:2: event 'collision' has one of multiple definitions here with data type *struct{Field []bool} -[warn] /testcases/marshalers/main.go:214:2: data type encoding/json.Marshaler for event 'interface' is a non-empty interface: emitting events from the frontend with data other than `null` is not supported by encoding/json and will likely result in runtime errors -[warn] dynamically registered event names are not discoverable by the binding generator: it is recommended to invoke `application.RegisterEvent` with constant arguments only -[warn] event 'collision' has multiple conflicting definitions and will be ignored -[warn] events registered through indirect calls are not discoverable by the binding generator: it is recommended to invoke `application.RegisterEvent` directly -[warn] generic wrappers for calls to `application.RegisterEvent` are not analysable by the binding generator: it is recommended to call `application.RegisterEvent` with concrete types only -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *R is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *S is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *T is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *U is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *V is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *X is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *Y is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *Z is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *any is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *complex64 is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *encoding.TextMarshaler is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *float32 is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.CustomInterface is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.EmbeddedInterface is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.InterfaceAlias is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.InterfacePtrAlias is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.InterfacePtrType is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.InterfaceType is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.NonTextMarshaler is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.PointerPtrAlias is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.PointerPtrType is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.PointerType is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.ValuePtrAlias is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.ValuePtrType is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.ValueType is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *int is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *string is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *uint is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type R is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type T is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type W is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type any is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type bool is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type complex64 is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type float32 is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.BadTildeCstrAlias[T] is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.BadTildeCstrAlias[struct{}] is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.BadTildeCstrPtrAlias[T] is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.BadTildeCstrPtrAlias[struct{}] is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.BasicCstrPtrAlias[S] is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.BasicCstrPtrAlias[int] is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.ComparableCstrAlias[R] is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.ComparableCstrAlias[github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.PointerTextMarshaler] is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.ComparableCstrPtrAlias[R] is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.ComparableCstrPtrAlias[int] is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.EmbeddedPointer is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.GoodTildeCstrPtrAlias[U] is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.InterfaceCstrPtrAlias[*github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.PointerTextMarshaler] is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.InterfaceCstrPtrAlias[Y] is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.InterfaceCstrPtrAlias[encoding.TextMarshaler] is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.InterfacePtrAlias is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.InterfacePtrType is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.MixedCstrPtrAlias[X] is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.MixedCstrPtrAlias[github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.StringType] is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.NonBasicCstrPtrAlias[*github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.PointerTextMarshaler] is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.NonBasicCstrPtrAlias[V] is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.NonTextMarshaler is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.PointableCstrAlias[W] is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.PointableCstrAlias[github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.PointerTextMarshaler] is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.PointerAlias is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.PointerCstrPtrAlias[R, Z] is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.PointerCstrPtrAlias[github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.PointerTextMarshaler, *github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.PointerTextMarshaler] is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.PointerCstrPtrAlias[github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.ValueTextMarshaler, *github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.ValueTextMarshaler] is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.PointerPtrType is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.PointerTextMarshaler is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.PointerType is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.ValuePtrType is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.ValueType is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.WrongAlias is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.WrongType is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/encoding/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/encoding/index.js deleted file mode 100644 index cf48d86db..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/encoding/index.js +++ /dev/null @@ -1,13 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as $models from "./models.js"; - -/** - * TextMarshaler is the interface implemented by an object that can - * marshal itself into a textual form. - * - * MarshalText encodes the receiver into UTF-8-encoded text and returns the result. - * @typedef {$models.TextMarshaler} TextMarshaler - */ diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/encoding/json/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/encoding/json/index.js deleted file mode 100644 index 22f1fd904..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/encoding/json/index.js +++ /dev/null @@ -1,11 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as $models from "./models.js"; - -/** - * Marshaler is the interface implemented by types that - * can marshal themselves into valid JSON. - * @typedef {$models.Marshaler} Marshaler - */ diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/encoding/json/models.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/encoding/json/models.js deleted file mode 100644 index 5dce4eea6..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/encoding/json/models.js +++ /dev/null @@ -1,13 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * Marshaler is the interface implemented by types that - * can marshal themselves into valid JSON. - * @typedef {any} Marshaler - */ - -// In interface mode, this file is likely to contain just comments. -// We add a dummy export statement to ensure it is recognised as an ES module. -export {}; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/encoding/models.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/encoding/models.js deleted file mode 100644 index db89bafbc..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/encoding/models.js +++ /dev/null @@ -1,15 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * TextMarshaler is the interface implemented by an object that can - * marshal itself into a textual form. - * - * MarshalText encodes the receiver into UTF-8-encoded text and returns the result. - * @typedef {any} TextMarshaler - */ - -// In interface mode, this file is likely to contain just comments. -// We add a dummy export statement to ensure it is recognised as an ES module. -export {}; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/eventcreate.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/eventcreate.js deleted file mode 100644 index 71a208a3d..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/eventcreate.js +++ /dev/null @@ -1,9 +0,0 @@ -//@ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Create as $Create } from "/wails/runtime.js"; - -Object.freeze($Create.Events); diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/eventdata.d.ts b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/eventdata.d.ts deleted file mode 100644 index be1730836..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/eventdata.d.ts +++ /dev/null @@ -1,30 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import type { Events } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import type * as json$0 from "../../../../../encoding/json/models.js"; -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import type * as events_only$0 from "./generator/testcases/events_only/models.js"; -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import type * as more$0 from "./generator/testcases/no_bindings_here/more/models.js"; - -declare module "/wails/runtime.js" { - namespace Events { - interface CustomEvents { - "events_only:class": events_only$0.SomeClass; - "events_only:map": { [_ in string]?: number[] | null } | null; - "events_only:nodata": void; - "events_only:other": more$0.StringPtr[] | null; - "events_only:string": string; - "interface": json$0.Marshaler; - "overlap": {"Field": boolean[] | null} | null; - } - } -} diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/aliases/greetservice.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/aliases/greetservice.js deleted file mode 100644 index cafc6aa33..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/aliases/greetservice.js +++ /dev/null @@ -1,77 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as nobindingshere$0 from "../no_bindings_here/models.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * Get someone. - * @param {$models.Alias} aliasValue - * @returns {$CancellablePromise<$models.Person>} - */ -export function Get(aliasValue) { - return $Call.ByID(1928502664, aliasValue); -} - -/** - * Apparently, aliases are all the rage right now. - * @param {$models.AliasedPerson} p - * @returns {$CancellablePromise<$models.StrangelyAliasedPerson>} - */ -export function GetButAliased(p) { - return $Call.ByID(1896499664, p); -} - -/** - * Get someone quite different. - * @returns {$CancellablePromise<$models.GenericPerson>} - */ -export function GetButDifferent() { - return $Call.ByID(2240931744); -} - -/** - * @returns {$CancellablePromise} - */ -export function GetButForeignPrivateAlias() { - return $Call.ByID(643456960); -} - -/** - * @returns {$CancellablePromise<$models.AliasGroup>} - */ -export function GetButGenericAliases() { - return $Call.ByID(914093800); -} - -/** - * @returns {$CancellablePromise<$models.SubPackageAlias>} - */ -export function GetButSubPackageAlias() { - return $Call.ByID(1443276371); -} - -/** - * Greet a lot of unusual things. - * @param {$models.EmptyAliasStruct} $0 - * @param {$models.EmptyStruct} $1 - * @returns {$CancellablePromise<$models.AliasStruct>} - */ -export function Greet($0, $1) { - return $Call.ByID(1411160069, $0, $1); -} diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/aliases/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/aliases/index.js deleted file mode 100644 index 32457ecf3..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/aliases/index.js +++ /dev/null @@ -1,101 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; - -import * as $models from "./models.js"; - -/** - * A nice type Alias. - * @typedef {$models.Alias} Alias - */ - -/** - * A class whose fields have various aliased types. - * @typedef {$models.AliasGroup} AliasGroup - */ - -/** - * A struct alias. - * This should be rendered as a typedef or interface in every mode. - * @typedef {$models.AliasStruct} AliasStruct - */ - -/** - * A class alias. - * @typedef {$models.AliasedPerson} AliasedPerson - */ - -/** - * An empty struct alias. - * @typedef {$models.EmptyAliasStruct} EmptyAliasStruct - */ - -/** - * An empty struct. - * @typedef {$models.EmptyStruct} EmptyStruct - */ - -/** - * A generic alias that forwards to a type parameter. - * @template T - * @typedef {$models.GenericAlias} GenericAlias - */ - -/** - * A generic alias that wraps a map. - * @template T,U - * @typedef {$models.GenericMapAlias} GenericMapAlias - */ - -/** - * A generic struct containing an alias. - * @template T - * @typedef {$models.GenericPerson} GenericPerson - */ - -/** - * A generic alias that wraps a generic struct. - * @template T - * @typedef {$models.GenericPersonAlias} GenericPersonAlias - */ - -/** - * A generic alias that wraps a pointer type. - * @template T - * @typedef {$models.GenericPtrAlias} GenericPtrAlias - */ - -/** - * An alias that wraps a class through a non-typeparam alias. - * @typedef {$models.IndirectPersonAlias} IndirectPersonAlias - */ - -/** - * Another struct alias. - * @typedef {$models.OtherAliasStruct} OtherAliasStruct - */ - -/** - * A non-generic struct containing an alias. - * @typedef {$models.Person} Person - */ - -/** - * Another class alias, but ordered after its aliased class. - * @typedef {$models.StrangelyAliasedPerson} StrangelyAliasedPerson - */ - -/** - * An alias referencing another package that is not used elsewhere. - * @typedef {$models.SubPackageAlias} SubPackageAlias - */ - -/** - * An alias that wraps a class through a typeparam alias. - * @typedef {$models.TPIndirectPersonAlias} TPIndirectPersonAlias - */ diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/aliases/models.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/aliases/models.js deleted file mode 100644 index 52116e035..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/aliases/models.js +++ /dev/null @@ -1,122 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as subpkg$0 from "./subpkg/models.js"; - -/** - * A nice type Alias. - * @typedef {number} Alias - */ - -/** - * A class whose fields have various aliased types. - * @typedef {Object} AliasGroup - * @property {GenericAlias} GAi - * @property {GenericAlias>} GAP - * @property {GenericPtrAlias} GPAs - * @property {GenericPtrAlias>} GPAP - * @property {GenericMapAlias} GMA - * @property {GenericPersonAlias} GPA - * @property {IndirectPersonAlias} IPA - * @property {TPIndirectPersonAlias} TPIPA - * @property {SubPackageAlias} SPA - */ - -/** - * A struct alias. - * This should be rendered as a typedef or interface in every mode. - * @typedef {Object} AliasStruct - * @property {number[] | null} Foo - A field with a comment. - * @property {string} [Bar] - Definitely not Foo. - * @property {string} [Baz] - Definitely not Foo. - * @property {OtherAliasStruct} Other - A nested alias struct. - */ - -/** - * A class alias. - * @typedef {Person} AliasedPerson - */ - -/** - * An empty struct alias. - * @typedef { { - * } } EmptyAliasStruct - */ - -/** - * An empty struct. - * @typedef { { - * } } EmptyStruct - */ - -/** - * A generic alias that forwards to a type parameter. - * @template T - * @typedef {T} GenericAlias - */ - -/** - * A generic alias that wraps a map. - * @template T,U - * @typedef {{ [_ in string]?: U } | null} GenericMapAlias - */ - -/** - * A generic struct containing an alias. - * @template T - * @typedef {Object} GenericPerson - * @property {T} Name - * @property {Alias} AliasedField - */ - -/** - * A generic alias that wraps a generic struct. - * @template T - * @typedef {GenericPerson[] | null>} GenericPersonAlias - */ - -/** - * A generic alias that wraps a pointer type. - * @template T - * @typedef {GenericAlias | null} GenericPtrAlias - */ - -/** - * An alias that wraps a class through a non-typeparam alias. - * @typedef {GenericPersonAlias} IndirectPersonAlias - */ - -/** - * Another struct alias. - * @typedef {Object} OtherAliasStruct - * @property {number[] | null} NoMoreIdeas - */ - -/** - * A non-generic struct containing an alias. - * @typedef {Object} Person - * @property {string} Name - The Person's name. - * @property {Alias} AliasedField - A random alias field. - */ - -/** - * Another class alias, but ordered after its aliased class. - * @typedef {Person} StrangelyAliasedPerson - */ - -/** - * An alias referencing another package that is not used elsewhere. - * @typedef {subpkg$0.SubStruct} SubPackageAlias - */ - -/** - * An alias that wraps a class through a typeparam alias. - * @typedef {GenericAlias>} TPIndirectPersonAlias - */ - -// In interface mode, this file is likely to contain just comments. -// We add a dummy export statement to ensure it is recognised as an ES module. -export {}; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/aliases/subpkg/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/aliases/subpkg/index.js deleted file mode 100644 index e6b65eedd..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/aliases/subpkg/index.js +++ /dev/null @@ -1,10 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as $models from "./models.js"; - -/** - * SubStruct is a type in a subpackage that is only referenced through an alias. - * @typedef {$models.SubStruct} SubStruct - */ diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/aliases/subpkg/models.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/aliases/subpkg/models.js deleted file mode 100644 index d711593fc..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/aliases/subpkg/models.js +++ /dev/null @@ -1,13 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * SubStruct is a type in a subpackage that is only referenced through an alias. - * @typedef {Object} SubStruct - * @property {string[] | null} SomeField - */ - -// In interface mode, this file is likely to contain just comments. -// We add a dummy export statement to ensure it is recognised as an ES module. -export {}; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_expressions/config/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_expressions/config/index.js deleted file mode 100644 index f6c839720..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_expressions/config/index.js +++ /dev/null @@ -1,10 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as Service7 from "./service7.js"; -import * as Service9 from "./service9.js"; -export { - Service7, - Service9 -}; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_expressions/config/service7.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_expressions/config/service7.js deleted file mode 100644 index 2a4188bce..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_expressions/config/service7.js +++ /dev/null @@ -1,14 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -/** - * @returns {$CancellablePromise} - */ -export function TestMethod() { - return $Call.ByID(2241101727); -} diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_expressions/config/service9.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_expressions/config/service9.js deleted file mode 100644 index ead6f5da4..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_expressions/config/service9.js +++ /dev/null @@ -1,14 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -/** - * @returns {$CancellablePromise} - */ -export function TestMethod2() { - return $Call.ByID(1556848345); -} diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_json/greetservice.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_json/greetservice.js deleted file mode 100644 index 995d46c13..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_json/greetservice.js +++ /dev/null @@ -1,26 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * Greet does XYZ - * @param {$models.Person} person - * @param {$models.Embedded1} emb - * @returns {$CancellablePromise} - */ -export function Greet(person, emb) { - return $Call.ByID(1411160069, person, emb); -} diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_json/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_json/index.js deleted file mode 100644 index f21130b86..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_json/index.js +++ /dev/null @@ -1,27 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; - -export { - Title -} from "./models.js"; - -import * as $models from "./models.js"; - -/** - * @typedef {$models.Embedded1} Embedded1 - */ - -/** - * @typedef {$models.Embedded3} Embedded3 - */ - -/** - * Person represents a person - * @typedef {$models.Person} Person - */ diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_json/models.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_json/models.js deleted file mode 100644 index b30630777..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_json/models.js +++ /dev/null @@ -1,64 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * @typedef {Object} Embedded1 - * @property {number} Friends - Friends should be shadowed in Person by a field of lesser depth - * @property {number} Vanish - Vanish should be omitted from Person because there is another field with same depth and no tag - * @property {string} StillThere - StillThere should be shadowed in Person by other field with same depth and a json tag - * @property {`${boolean}`} NamingThingsIsHard - NamingThingsIsHard is a law of programming - */ - -/** - * @typedef {string} Embedded3 - */ - -/** - * Person represents a person - * @typedef { { - * "Titles"?: Title[] | null, - * "Names": string[] | null, - * "Partner": Person | null, - * "Friends": (Person | null)[] | null, - * "NamingThingsIsHard": `${boolean}`, - * "StillThere": Embedded3 | null, - * "-": number, - * "Embedded3": Embedded3, - * "StrangerNumber": `${number}`, - * "StrangestString"?: `"${string}"`, - * "StringStrangest"?: `"${string}"`, - * "emb4"?: embedded4, - * } } Person - */ - -/** - * Title is a title - * @readonly - * @enum {string} - */ -export const Title = { - /** - * The Go zero value for the underlying type of the enum. - */ - $zero: "", - - /** - * Mister is a title - */ - Mister: "Mr", - Miss: "Miss", - Ms: "Ms", - Mrs: "Mrs", - Dr: "Dr", -}; - -/** - * @typedef {Object} embedded4 - * @property {`${boolean}`} NamingThingsIsHard - NamingThingsIsHard is a law of programming - * @property {boolean} Friends - Friends should not be shadowed in Person as embedded4 is not embedded from encoding/json's point of view; however, it should be shadowed in Embedded1 - */ - -// In interface mode, this file is likely to contain just comments. -// We add a dummy export statement to ensure it is recognised as an ES module. -export {}; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_method/greetservice.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_method/greetservice.js deleted file mode 100644 index 2a5131f82..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_method/greetservice.js +++ /dev/null @@ -1,32 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * Greet does XYZ - * It has a multiline doc comment - * The comment has even some * / traps!! - * @param {string} str - * @param {$models.Person[] | null} people - * @param {{"AnotherCount": number, "AnotherOne": $models.Person | null}} $2 - * @param {{ [_ in `${number}`]?: boolean | null } | null} assoc - * @param {(number | null)[] | null} $4 - * @param {string[]} other - * @returns {$CancellablePromise<[$models.Person, any, number[] | null]>} - */ -export function Greet(str, people, $2, assoc, $4, ...other) { - return $Call.ByID(1411160069, str, people, $2, assoc, $4, other); -} diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_method/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_method/index.js deleted file mode 100644 index 88af1203b..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_method/index.js +++ /dev/null @@ -1,15 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; - -import * as $models from "./models.js"; - -/** - * Person represents a person - * @typedef {$models.Person} Person - */ diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_method/models.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_method/models.js deleted file mode 100644 index 035bc0792..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_method/models.js +++ /dev/null @@ -1,13 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * Person represents a person - * @typedef {Object} Person - * @property {string} Name - */ - -// In interface mode, this file is likely to contain just comments. -// We add a dummy export statement to ensure it is recognised as an ES module. -export {}; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/cyclic_imports/greetservice.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/cyclic_imports/greetservice.js deleted file mode 100644 index 53027124b..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/cyclic_imports/greetservice.js +++ /dev/null @@ -1,24 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * Make a cycle. - * @returns {$CancellablePromise<[$models.StructA, $models.StructC]>} - */ -export function MakeCycles() { - return $Call.ByID(440020721); -} diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/cyclic_imports/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/cyclic_imports/index.js deleted file mode 100644 index 9b49a9172..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/cyclic_imports/index.js +++ /dev/null @@ -1,22 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; - -import * as $models from "./models.js"; - -/** - * @typedef {$models.StructA} StructA - */ - -/** - * @typedef {$models.StructC} StructC - */ - -/** - * @typedef {$models.StructE} StructE - */ diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/cyclic_imports/models.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/cyclic_imports/models.js deleted file mode 100644 index 50e0d0fc0..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/cyclic_imports/models.js +++ /dev/null @@ -1,32 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * @typedef {Object} StructA - * @property {structB | null} B - */ - -/** - * @typedef {Object} StructC - * @property {structD} D - */ - -/** - * @typedef { { - * } } StructE - */ - -/** - * @typedef {Object} structB - * @property {StructA | null} A - */ - -/** - * @typedef {Object} structD - * @property {StructE} E - */ - -// In interface mode, this file is likely to contain just comments. -// We add a dummy export statement to ensure it is recognised as an ES module. -export {}; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/cyclic_types/greetservice.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/cyclic_types/greetservice.js deleted file mode 100644 index 382e6bac3..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/cyclic_types/greetservice.js +++ /dev/null @@ -1,24 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * Make a cycle. - * @returns {$CancellablePromise<[$models.Cyclic, $models.GenericCyclic<$models.GenericCyclic>]>} - */ -export function MakeCycles() { - return $Call.ByID(440020721); -} diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/cyclic_types/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/cyclic_types/index.js deleted file mode 100644 index 9fc31bf7c..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/cyclic_types/index.js +++ /dev/null @@ -1,23 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; - -import * as $models from "./models.js"; - -/** - * @typedef {$models.Alias} Alias - */ - -/** - * @typedef {$models.Cyclic} Cyclic - */ - -/** - * @template T - * @typedef {$models.GenericCyclic} GenericCyclic - */ diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/cyclic_types/models.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/cyclic_types/models.js deleted file mode 100644 index 45780d15c..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/cyclic_types/models.js +++ /dev/null @@ -1,20 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * @typedef {Cyclic | null} Alias - */ - -/** - * @typedef {({ [_ in string]?: Alias } | null)[] | null} Cyclic - */ - -/** - * @template T - * @typedef {{"X": GenericCyclic | null, "Y": T[] | null}[] | null} GenericCyclic - */ - -// In interface mode, this file is likely to contain just comments. -// We add a dummy export statement to ensure it is recognised as an ES module. -export {}; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/index.js deleted file mode 100644 index 40d68bf85..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/index.js +++ /dev/null @@ -1,14 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as Service from "./service.js"; -export { - Service -}; - -console.log("Hello everywhere!"); -console.log("Hello everywhere again!"); -console.log("Hello Interfaces!"); -console.log("Hello JS!"); -console.log("Hello JS Interfaces!"); diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/internalservice.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/internalservice.js deleted file mode 100644 index f96a46e77..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/internalservice.js +++ /dev/null @@ -1,24 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * An exported but internal service. - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * @param {$models.InternalModel} $0 - * @returns {$CancellablePromise} - */ -export function Method($0) { - return $Call.ByID(538079117, $0); -} diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/models.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/models.js deleted file mode 100644 index a4c233c8c..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/models.js +++ /dev/null @@ -1,19 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * An exported but internal model. - * @typedef {Object} InternalModel - * @property {string} Field - */ - -/** - * An unexported model. - * @typedef {Object} unexportedModel - * @property {string} Field - */ - -// In interface mode, this file is likely to contain just comments. -// We add a dummy export statement to ensure it is recognised as an ES module. -export {}; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/otherpackage/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/otherpackage/index.js deleted file mode 100644 index c93da8f05..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/otherpackage/index.js +++ /dev/null @@ -1,9 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as $models from "./models.js"; - -/** - * @typedef {$models.Dummy} Dummy - */ diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/otherpackage/models.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/otherpackage/models.js deleted file mode 100644 index 6b6f5401f..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/otherpackage/models.js +++ /dev/null @@ -1,12 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * @typedef { { - * } } Dummy - */ - -// In interface mode, this file is likely to contain just comments. -// We add a dummy export statement to ensure it is recognised as an ES module. -export {}; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/service.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/service.js deleted file mode 100644 index 0d869be84..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/service.js +++ /dev/null @@ -1,35 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as otherpackage$0 from "./otherpackage/models.js"; - -/** - * @param {string} $0 - * @returns {$CancellablePromise} - */ -function InternalMethod($0) { - return $Call.ByID(3518775569, $0); -} - -/** - * @param {otherpackage$0.Dummy} $0 - * @returns {$CancellablePromise} - */ -export function VisibleMethod($0) { - return $Call.ByID(474018228, $0); -} - -/** - * @param {string} arg - * @returns {Promise} - */ -export async function CustomMethod(arg) { - await InternalMethod("Hello " + arg + "!"); -} diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/test.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/test.js deleted file mode 100644 index 138385f53..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/test.js +++ /dev/null @@ -1,3 +0,0 @@ -import { CustomMethod } from "./service.js"; - -CustomMethod("everywhere"); diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/test_all.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/test_all.js deleted file mode 100644 index 19d5c2f42..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/test_all.js +++ /dev/null @@ -1,3 +0,0 @@ -import { CustomMethod } from "./service.js"; - -CustomMethod("everywhere again"); diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/test_i.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/test_i.js deleted file mode 100644 index 442f20472..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/test_i.js +++ /dev/null @@ -1,3 +0,0 @@ -import { CustomMethod } from "./service.js"; - -CustomMethod("Interfaces"); diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/test_j.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/test_j.js deleted file mode 100644 index b2f9c5edb..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/test_j.js +++ /dev/null @@ -1,3 +0,0 @@ -import { CustomMethod } from "./service.js"; - -CustomMethod("JS"); diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/test_ji.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/test_ji.js deleted file mode 100644 index 36e28f09b..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/test_ji.js +++ /dev/null @@ -1,3 +0,0 @@ -import { CustomMethod } from "./service.js"; - -CustomMethod("JS Interfaces"); diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/unexportedservice.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/unexportedservice.js deleted file mode 100644 index 573852d5a..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/unexportedservice.js +++ /dev/null @@ -1,24 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * An unexported service. - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * @param {$models.unexportedModel} $0 - * @returns {$CancellablePromise} - */ -export function Method($0) { - return $Call.ByID(37626172, $0); -} diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/embedded_interface/greetservice.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/embedded_interface/greetservice.js deleted file mode 100644 index d364009d6..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/embedded_interface/greetservice.js +++ /dev/null @@ -1,53 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -/** - * Comment 1. - * @returns {$CancellablePromise} - */ -export function Method1() { - return $Call.ByID(841558284); -} - -/** - * Comment 2. - * @returns {$CancellablePromise} - */ -export function Method2() { - return $Call.ByID(891891141); -} - -/** - * Comment 3a. - * Comment 3b. - * @returns {$CancellablePromise} - */ -export function Method3() { - return $Call.ByID(875113522); -} - -/** - * Comment 4. - * @returns {$CancellablePromise} - */ -export function Method4() { - return $Call.ByID(791225427); -} - -/** - * Comment 5. - * @returns {$CancellablePromise} - */ -export function Method5() { - return $Call.ByID(774447808); -} diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/embedded_interface/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/embedded_interface/index.js deleted file mode 100644 index fdf1ff435..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/embedded_interface/index.js +++ /dev/null @@ -1,8 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/enum/greetservice.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/enum/greetservice.js deleted file mode 100644 index f14b3b6b2..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/enum/greetservice.js +++ /dev/null @@ -1,35 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * Greet does XYZ - * @param {string} name - * @param {$models.Title} title - * @returns {$CancellablePromise} - */ -export function Greet(name, title) { - return $Call.ByID(1411160069, name, title); -} - -/** - * NewPerson creates a new person - * @param {string} name - * @returns {$CancellablePromise<$models.Person | null>} - */ -export function NewPerson(name) { - return $Call.ByID(1661412647, name); -} diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/enum/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/enum/index.js deleted file mode 100644 index 649d8d016..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/enum/index.js +++ /dev/null @@ -1,20 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; - -export { - Age, - Title -} from "./models.js"; - -import * as $models from "./models.js"; - -/** - * Person represents a person - * @typedef {$models.Person} Person - */ diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/enum/models.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/enum/models.js deleted file mode 100644 index e7c70729c..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/enum/models.js +++ /dev/null @@ -1,61 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * Age is an integer with some predefined values - * @typedef {number} Age - */ - -/** - * Predefined constants for type Age. - * @namespace - */ -export const Age = { - NewBorn: 0, - Teenager: 12, - YoungAdult: 18, - - /** - * Oh no, some grey hair! - */ - MiddleAged: 50, - - /** - * Unbelievable! - */ - Mathusalem: 1000, -}; - -/** - * Person represents a person - * @typedef {Object} Person - * @property {Title} Title - * @property {string} Name - * @property {Age} Age - */ - -/** - * Title is a title - * @readonly - * @enum {string} - */ -export const Title = { - /** - * The Go zero value for the underlying type of the enum. - */ - $zero: "", - - /** - * Mister is a title - */ - Mister: "Mr", - Miss: "Miss", - Ms: "Ms", - Mrs: "Mrs", - Dr: "Dr", -}; - -// In interface mode, this file is likely to contain just comments. -// We add a dummy export statement to ensure it is recognised as an ES module. -export {}; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_from_imported_package/greetservice.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_from_imported_package/greetservice.js deleted file mode 100644 index 508c12b72..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_from_imported_package/greetservice.js +++ /dev/null @@ -1,26 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as services$0 from "./services/models.js"; - -/** - * Greet does XYZ - * @param {string} name - * @param {services$0.Title} title - * @returns {$CancellablePromise} - */ -export function Greet(name, title) { - return $Call.ByID(1411160069, name, title); -} diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_from_imported_package/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_from_imported_package/index.js deleted file mode 100644 index fdf1ff435..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_from_imported_package/index.js +++ /dev/null @@ -1,8 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_from_imported_package/services/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_from_imported_package/services/index.js deleted file mode 100644 index 089a8b685..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_from_imported_package/services/index.js +++ /dev/null @@ -1,7 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -export { - Title -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_from_imported_package/services/models.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_from_imported_package/services/models.js deleted file mode 100644 index e0e2d3014..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_from_imported_package/services/models.js +++ /dev/null @@ -1,27 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * @readonly - * @enum {string} - */ -export const Title = { - /** - * The Go zero value for the underlying type of the enum. - */ - $zero: "", - - /** - * Mister is a title - */ - Mister: "Mr", - Miss: "Miss", - Ms: "Ms", - Mrs: "Mrs", - Dr: "Dr", -}; - -// In interface mode, this file is likely to contain just comments. -// We add a dummy export statement to ensure it is recognised as an ES module. -export {}; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_map_keys/enummapservice.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_map_keys/enummapservice.js deleted file mode 100644 index 4ff0746a3..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_map_keys/enummapservice.js +++ /dev/null @@ -1,64 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * EnumMapService tests various enum map key scenarios - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * GetColorCodes returns a map with uint8 enum keys - * @returns {$CancellablePromise<{ [_ in $models.Color]?: string } | null>} - */ -export function GetColorCodes() { - return $Call.ByID(2794981443); -} - -/** - * GetNestedEnumMap returns a map with enum keys and complex values - * @returns {$CancellablePromise<{ [_ in $models.Status]?: { [_ in $models.Priority]?: string } | null } | null>} - */ -export function GetNestedEnumMap() { - return $Call.ByID(3603489560); -} - -/** - * GetOptionalEnumMap returns a map with enum keys to optional values - * @returns {$CancellablePromise<{ [_ in $models.Status]?: string | null } | null>} - */ -export function GetOptionalEnumMap() { - return $Call.ByID(1871606385); -} - -/** - * GetPersonsByStatus returns a map with enum keys to struct values - * @returns {$CancellablePromise<{ [_ in $models.Status]?: $models.Person[] | null } | null>} - */ -export function GetPersonsByStatus() { - return $Call.ByID(2189502217); -} - -/** - * GetPriorityWeights returns a map with integer enum keys - * @returns {$CancellablePromise<{ [_ in $models.Priority]?: number } | null>} - */ -export function GetPriorityWeights() { - return $Call.ByID(1542216941); -} - -/** - * GetStatusMessages returns a map with string enum keys - * @returns {$CancellablePromise<{ [_ in $models.Status]?: string } | null>} - */ -export function GetStatusMessages() { - return $Call.ByID(1788640810); -} diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_map_keys/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_map_keys/index.js deleted file mode 100644 index 4d0ba0f49..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_map_keys/index.js +++ /dev/null @@ -1,21 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as EnumMapService from "./enummapservice.js"; -export { - EnumMapService -}; - -export { - Color, - Priority, - Status -} from "./models.js"; - -import * as $models from "./models.js"; - -/** - * Person represents a person with status - * @typedef {$models.Person} Person - */ diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_map_keys/models.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_map_keys/models.js deleted file mode 100644 index 9658a39a8..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_map_keys/models.js +++ /dev/null @@ -1,63 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * Color represents color values - * @readonly - * @enum {number} - */ -export const Color = { - /** - * The Go zero value for the underlying type of the enum. - */ - $zero: 0, - - Red: 1, - Green: 2, - Blue: 3, -}; - -/** - * Person represents a person with status - * @typedef {Object} Person - * @property {string} Name - * @property {Status} Status - */ - -/** - * Priority represents priority levels - * @readonly - * @enum {number} - */ -export const Priority = { - /** - * The Go zero value for the underlying type of the enum. - */ - $zero: 0, - - PriorityLow: 1, - PriorityMedium: 2, - PriorityHigh: 3, -}; - -/** - * Status represents different status values - * @readonly - * @enum {string} - */ -export const Status = { - /** - * The Go zero value for the underlying type of the enum. - */ - $zero: "", - - StatusPending: "pending", - StatusRunning: "running", - StatusCompleted: "completed", - StatusFailed: "failed", -}; - -// In interface mode, this file is likely to contain just comments. -// We add a dummy export statement to ensure it is recognised as an ES module. -export {}; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/events_only/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/events_only/index.js deleted file mode 100644 index 14b4d5da8..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/events_only/index.js +++ /dev/null @@ -1,10 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as $models from "./models.js"; - -/** - * SomeClass renders as a TS class. - * @typedef {$models.SomeClass} SomeClass - */ diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/events_only/models.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/events_only/models.js deleted file mode 100644 index b99dbf18d..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/events_only/models.js +++ /dev/null @@ -1,18 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as nobindingshere$0 from "../no_bindings_here/models.js"; - -/** - * SomeClass renders as a TS class. - * @typedef {Object} SomeClass - * @property {string} Field - * @property {nobindingshere$0.HowDifferent} Meadow - */ - -// In interface mode, this file is likely to contain just comments. -// We add a dummy export statement to ensure it is recognised as an ES module. -export {}; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_imported_package/greetservice.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_imported_package/greetservice.js deleted file mode 100644 index 40d2245b9..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_imported_package/greetservice.js +++ /dev/null @@ -1,34 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * Greet does XYZ - * @param {string} name - * @returns {$CancellablePromise} - */ -export function Greet(name) { - return $Call.ByID(1411160069, name); -} - -/** - * NewPerson creates a new person - * @param {string} name - * @returns {$CancellablePromise<$models.Person | null>} - */ -export function NewPerson(name) { - return $Call.ByID(1661412647, name); -} diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_imported_package/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_imported_package/index.js deleted file mode 100644 index 26922b7eb..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_imported_package/index.js +++ /dev/null @@ -1,15 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; - -import * as $models from "./models.js"; - -/** - * Person is a person - * @typedef {$models.Person} Person - */ diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_imported_package/models.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_imported_package/models.js deleted file mode 100644 index 5743a9055..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_imported_package/models.js +++ /dev/null @@ -1,18 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as services$0 from "./services/models.js"; - -/** - * Person is a person - * @typedef {Object} Person - * @property {string} Name - * @property {services$0.Address | null} Address - */ - -// In interface mode, this file is likely to contain just comments. -// We add a dummy export statement to ensure it is recognised as an ES module. -export {}; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_imported_package/services/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_imported_package/services/index.js deleted file mode 100644 index 588ef7ca7..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_imported_package/services/index.js +++ /dev/null @@ -1,14 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as OtherService from "./otherservice.js"; -export { - OtherService -}; - -import * as $models from "./models.js"; - -/** - * @typedef {$models.Address} Address - */ diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_imported_package/services/models.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_imported_package/services/models.js deleted file mode 100644 index c04e3b10b..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_imported_package/services/models.js +++ /dev/null @@ -1,14 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * @typedef {Object} Address - * @property {string} Street - * @property {string} State - * @property {string} Country - */ - -// In interface mode, this file is likely to contain just comments. -// We add a dummy export statement to ensure it is recognised as an ES module. -export {}; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_imported_package/services/otherservice.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_imported_package/services/otherservice.js deleted file mode 100644 index dff4e0d5f..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_imported_package/services/otherservice.js +++ /dev/null @@ -1,25 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * OtherService is a struct - * that does things - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * Yay does this and that - * @returns {$CancellablePromise<$models.Address | null>} - */ -export function Yay() { - return $Call.ByID(2007737399); -} diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_nested_imported_package/greetservice.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_nested_imported_package/greetservice.js deleted file mode 100644 index 40d2245b9..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_nested_imported_package/greetservice.js +++ /dev/null @@ -1,34 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * Greet does XYZ - * @param {string} name - * @returns {$CancellablePromise} - */ -export function Greet(name) { - return $Call.ByID(1411160069, name); -} - -/** - * NewPerson creates a new person - * @param {string} name - * @returns {$CancellablePromise<$models.Person | null>} - */ -export function NewPerson(name) { - return $Call.ByID(1661412647, name); -} diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_nested_imported_package/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_nested_imported_package/index.js deleted file mode 100644 index cb2979a7a..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_nested_imported_package/index.js +++ /dev/null @@ -1,14 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; - -import * as $models from "./models.js"; - -/** - * @typedef {$models.Person} Person - */ diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_nested_imported_package/models.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_nested_imported_package/models.js deleted file mode 100644 index 8a9890617..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_nested_imported_package/models.js +++ /dev/null @@ -1,17 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as other$0 from "./services/other/models.js"; - -/** - * @typedef {Object} Person - * @property {string} Name - * @property {other$0.Address | null} Address - */ - -// In interface mode, this file is likely to contain just comments. -// We add a dummy export statement to ensure it is recognised as an ES module. -export {}; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_nested_imported_package/services/other/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_nested_imported_package/services/other/index.js deleted file mode 100644 index 588ef7ca7..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_nested_imported_package/services/other/index.js +++ /dev/null @@ -1,14 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as OtherService from "./otherservice.js"; -export { - OtherService -}; - -import * as $models from "./models.js"; - -/** - * @typedef {$models.Address} Address - */ diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_nested_imported_package/services/other/models.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_nested_imported_package/services/other/models.js deleted file mode 100644 index c04e3b10b..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_nested_imported_package/services/other/models.js +++ /dev/null @@ -1,14 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * @typedef {Object} Address - * @property {string} Street - * @property {string} State - * @property {string} Country - */ - -// In interface mode, this file is likely to contain just comments. -// We add a dummy export statement to ensure it is recognised as an ES module. -export {}; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_nested_imported_package/services/other/otherservice.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_nested_imported_package/services/other/otherservice.js deleted file mode 100644 index 182a9e091..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_nested_imported_package/services/other/otherservice.js +++ /dev/null @@ -1,25 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * OtherService is a struct - * that does things - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * Yay does this and that - * @returns {$CancellablePromise<$models.Address | null>} - */ -export function Yay() { - return $Call.ByID(2447353446); -} diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_multiple_files/greetservice.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_multiple_files/greetservice.js deleted file mode 100644 index 9343d5531..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_multiple_files/greetservice.js +++ /dev/null @@ -1,15 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -/** - * @param {string} name - * @returns {$CancellablePromise} - */ -export function Greet(name) { - return $Call.ByID(1411160069, name); -} diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_multiple_files/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_multiple_files/index.js deleted file mode 100644 index fdf1ff435..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_multiple_files/index.js +++ /dev/null @@ -1,8 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single/greetservice.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single/greetservice.js deleted file mode 100644 index 6c1448d81..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single/greetservice.js +++ /dev/null @@ -1,21 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -/** - * Greet someone - * @param {string} name - * @returns {$CancellablePromise} - */ -export function Greet(name) { - return $Call.ByID(1411160069, name); -} diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single/index.js deleted file mode 100644 index fdf1ff435..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single/index.js +++ /dev/null @@ -1,8 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single_context/greetservice.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single_context/greetservice.js deleted file mode 100644 index be0cf5ce8..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single_context/greetservice.js +++ /dev/null @@ -1,30 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -/** - * Greet someone - * @param {string} name - * @returns {$CancellablePromise} - */ -export function Greet(name) { - return $Call.ByID(1411160069, name); -} - -/** - * Greet someone - * @param {string} name - * @returns {$CancellablePromise} - */ -export function GreetWithContext(name) { - return $Call.ByID(1310150960, name); -} diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single_context/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single_context/index.js deleted file mode 100644 index fdf1ff435..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single_context/index.js +++ /dev/null @@ -1,8 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single_internal/greetservice.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single_internal/greetservice.js deleted file mode 100644 index 6c1448d81..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single_internal/greetservice.js +++ /dev/null @@ -1,21 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -/** - * Greet someone - * @param {string} name - * @returns {$CancellablePromise} - */ -export function Greet(name) { - return $Call.ByID(1411160069, name); -} diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single_internal/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single_internal/index.js deleted file mode 100644 index fdf1ff435..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single_internal/index.js +++ /dev/null @@ -1,8 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys/index.js deleted file mode 100644 index a92a0cb10..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys/index.js +++ /dev/null @@ -1,106 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as Service from "./service.js"; -export { - Service -}; - -import * as $models from "./models.js"; - -/** - * @template S - * @typedef {$models.BasicCstrAlias} BasicCstrAlias - */ - -/** - * @template R - * @typedef {$models.ComparableCstrAlias} ComparableCstrAlias - */ - -/** - * @typedef {$models.EmbeddedCustomInterface} EmbeddedCustomInterface - */ - -/** - * @typedef {$models.EmbeddedOriginalInterface} EmbeddedOriginalInterface - */ - -/** - * @typedef {$models.EmbeddedPointer} EmbeddedPointer - */ - -/** - * @typedef {$models.EmbeddedPointerPtr} EmbeddedPointerPtr - */ - -/** - * @typedef {$models.EmbeddedValue} EmbeddedValue - */ - -/** - * @typedef {$models.EmbeddedValuePtr} EmbeddedValuePtr - */ - -/** - * @template U - * @typedef {$models.GoodTildeCstrAlias} GoodTildeCstrAlias - */ - -/** - * @typedef {$models.IntAlias} IntAlias - */ - -/** - * @typedef {$models.IntType} IntType - */ - -/** - * @template Y - * @typedef {$models.InterfaceCstrAlias} InterfaceCstrAlias - */ - -/** - * @template R,S,T,U,V,W,X,Y,Z - * @typedef {$models.Maps} Maps - */ - -/** - * @template X - * @typedef {$models.MixedCstrAlias} MixedCstrAlias - */ - -/** - * @template V - * @typedef {$models.NonBasicCstrAlias} NonBasicCstrAlias - */ - -/** - * @template W - * @typedef {$models.PointableCstrAlias} PointableCstrAlias - */ - -/** - * @typedef {$models.PointerAlias} PointerAlias - */ - -/** - * @typedef {$models.PointerTextMarshaler} PointerTextMarshaler - */ - -/** - * @typedef {$models.StringAlias} StringAlias - */ - -/** - * @typedef {$models.StringType} StringType - */ - -/** - * @typedef {$models.ValueAlias} ValueAlias - */ - -/** - * @typedef {$models.ValueTextMarshaler} ValueTextMarshaler - */ diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys/models.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys/models.js deleted file mode 100644 index 371763800..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys/models.js +++ /dev/null @@ -1,248 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * @template S - * @typedef {S} BasicCstrAlias - */ - -/** - * @template R - * @typedef {R} ComparableCstrAlias - */ - -/** - * @typedef {string} EmbeddedCustomInterface - */ - -/** - * @typedef {string} EmbeddedOriginalInterface - */ - -/** - * @typedef {string} EmbeddedPointer - */ - -/** - * @typedef {string} EmbeddedPointerPtr - */ - -/** - * @typedef {string} EmbeddedValue - */ - -/** - * @typedef {string} EmbeddedValuePtr - */ - -/** - * @template U - * @typedef {U} GoodTildeCstrAlias - */ - -/** - * @typedef {number} IntAlias - */ - -/** - * @typedef {number} IntType - */ - -/** - * @template Y - * @typedef {Y} InterfaceCstrAlias - */ - -/** - * @template R,S,T,U,V,W,X,Y,Z - * @typedef {Object} Maps - * @property {{ [_ in string]?: number } | null} Bool - Reject - * @property {{ [_ in `${number}`]?: number } | null} Int - Accept - * @property {{ [_ in `${number}`]?: number } | null} Uint - Accept - * @property {{ [_ in string]?: number } | null} Float - Reject - * @property {{ [_ in string]?: number } | null} Complex - Reject - * @property {{ [_ in `${number}`]?: number } | null} Byte - Accept - * @property {{ [_ in `${number}`]?: number } | null} Rune - Accept - * @property {{ [_ in string]?: number } | null} String - Accept - * @property {{ [_ in string]?: number } | null} IntPtr - Reject - * @property {{ [_ in string]?: number } | null} UintPtr - Reject - * @property {{ [_ in string]?: number } | null} FloatPtr - Reject - * @property {{ [_ in string]?: number } | null} ComplexPtr - Reject - * @property {{ [_ in string]?: number } | null} StringPtr - Reject - * @property {{ [_ in string]?: number } | null} NTM - Reject - * @property {{ [_ in string]?: number } | null} NTMPtr - Reject - * @property {{ [_ in ValueTextMarshaler]?: number } | null} VTM - Accept - * @property {{ [_ in ValueTextMarshaler]?: number } | null} VTMPtr - Accept - * @property {{ [_ in string]?: number } | null} PTM - Reject - * @property {{ [_ in PointerTextMarshaler]?: number } | null} PTMPtr - Accept - * @property {{ [_ in string]?: number } | null} JTM - Accept, hide - * @property {{ [_ in string]?: number } | null} JTMPtr - Accept, hide - * @property {{ [_ in string]?: number } | null} A - Reject - * @property {{ [_ in string]?: number } | null} APtr - Reject - * @property {{ [_ in string]?: number } | null} TM - Accept, hide - * @property {{ [_ in string]?: number } | null} TMPtr - Reject - * @property {{ [_ in string]?: number } | null} CI - Accept, hide - * @property {{ [_ in string]?: number } | null} CIPtr - Reject - * @property {{ [_ in string]?: number } | null} EI - Accept, hide - * @property {{ [_ in string]?: number } | null} EIPtr - Reject - * @property {{ [_ in EmbeddedValue]?: number } | null} EV - Accept - * @property {{ [_ in EmbeddedValue]?: number } | null} EVPtr - Accept - * @property {{ [_ in EmbeddedValuePtr]?: number } | null} EVP - Accept - * @property {{ [_ in EmbeddedValuePtr]?: number } | null} EVPPtr - Accept - * @property {{ [_ in string]?: number } | null} EP - Reject - * @property {{ [_ in EmbeddedPointer]?: number } | null} EPPtr - Accept - * @property {{ [_ in EmbeddedPointerPtr]?: number } | null} EPP - Accept - * @property {{ [_ in EmbeddedPointerPtr]?: number } | null} EPPPtr - Accept - * @property {{ [_ in EmbeddedCustomInterface]?: number } | null} ECI - Accept - * @property {{ [_ in EmbeddedCustomInterface]?: number } | null} ECIPtr - Accept - * @property {{ [_ in EmbeddedOriginalInterface]?: number } | null} EOI - Accept - * @property {{ [_ in EmbeddedOriginalInterface]?: number } | null} EOIPtr - Accept - * @property {{ [_ in string]?: number } | null} WT - Reject - * @property {{ [_ in string]?: number } | null} WA - Reject - * @property {{ [_ in StringType]?: number } | null} ST - Accept - * @property {{ [_ in StringAlias]?: number } | null} SA - Accept - * @property {{ [_ in IntType]?: number } | null} IntT - Accept - * @property {{ [_ in IntAlias]?: number } | null} IntA - Accept - * @property {{ [_ in string]?: number } | null} VT - Reject - * @property {{ [_ in string]?: number } | null} VTPtr - Reject - * @property {{ [_ in string]?: number } | null} VPT - Reject - * @property {{ [_ in string]?: number } | null} VPTPtr - Reject - * @property {{ [_ in ValueAlias]?: number } | null} VA - Accept - * @property {{ [_ in ValueAlias]?: number } | null} VAPtr - Accept - * @property {{ [_ in string]?: number } | null} VPA - Accept, hide - * @property {{ [_ in string]?: number } | null} VPAPtr - Reject - * @property {{ [_ in string]?: number } | null} PT - Reject - * @property {{ [_ in string]?: number } | null} PTPtr - Reject - * @property {{ [_ in string]?: number } | null} PPT - Reject - * @property {{ [_ in string]?: number } | null} PPTPtr - Reject - * @property {{ [_ in string]?: number } | null} PA - Reject - * @property {{ [_ in PointerAlias]?: number } | null} PAPtr - Accept - * @property {{ [_ in string]?: number } | null} PPA - Accept, hide - * @property {{ [_ in string]?: number } | null} PPAPtr - Reject - * @property {{ [_ in string]?: number } | null} IT - Accept, hide - * @property {{ [_ in string]?: number } | null} ITPtr - Reject - * @property {{ [_ in string]?: number } | null} IPT - Reject - * @property {{ [_ in string]?: number } | null} IPTPtr - Reject - * @property {{ [_ in string]?: number } | null} IA - Accept, hide - * @property {{ [_ in string]?: number } | null} IAPtr - Reject - * @property {{ [_ in string]?: number } | null} IPA - Reject - * @property {{ [_ in string]?: number } | null} IPAPtr - Reject - * @property {{ [_ in string]?: number } | null} TPR - Soft reject - * @property {{ [_ in string]?: number } | null} TPRPtr - Soft reject - * @property {{ [_ in string]?: number } | null} TPS - Accept, hide - * @property {{ [_ in string]?: number } | null} TPSPtr - Soft reject - * @property {{ [_ in string]?: number } | null} TPT - Soft reject - * @property {{ [_ in string]?: number } | null} TPTPtr - Soft reject - * @property {{ [_ in string]?: number } | null} TPU - Accept, hide - * @property {{ [_ in string]?: number } | null} TPUPtr - Soft reject - * @property {{ [_ in string]?: number } | null} TPV - Accept, hide - * @property {{ [_ in string]?: number } | null} TPVPtr - Soft reject - * @property {{ [_ in string]?: number } | null} TPW - Soft reject - * @property {{ [_ in string]?: number } | null} TPWPtr - Accept, hide - * @property {{ [_ in string]?: number } | null} TPX - Accept, hide - * @property {{ [_ in string]?: number } | null} TPXPtr - Soft reject - * @property {{ [_ in string]?: number } | null} TPY - Accept, hide - * @property {{ [_ in string]?: number } | null} TPYPtr - Soft reject - * @property {{ [_ in string]?: number } | null} TPZ - Accept, hide - * @property {{ [_ in string]?: number } | null} TPZPtr - Soft reject - * @property {{ [_ in string]?: number } | null} GAR - Soft reject - * @property {{ [_ in string]?: number } | null} GARPtr - Soft reject - * @property {{ [_ in string]?: number } | null} GAS - Accept, hide - * @property {{ [_ in string]?: number } | null} GASPtr - Soft reject - * @property {{ [_ in string]?: number } | null} GAT - Soft reject - * @property {{ [_ in string]?: number } | null} GATPtr - Soft reject - * @property {{ [_ in string]?: number } | null} GAU - Accept, hide - * @property {{ [_ in string]?: number } | null} GAUPtr - Soft reject - * @property {{ [_ in string]?: number } | null} GAV - Accept, hide - * @property {{ [_ in string]?: number } | null} GAVPtr - Soft reject - * @property {{ [_ in string]?: number } | null} GAW - Soft reject - * @property {{ [_ in string]?: number } | null} GAWPtr - Accept, hide - * @property {{ [_ in string]?: number } | null} GAX - Accept, hide - * @property {{ [_ in string]?: number } | null} GAXPtr - Soft reject - * @property {{ [_ in string]?: number } | null} GAY - Accept, hide - * @property {{ [_ in string]?: number } | null} GAYPtr - Soft reject - * @property {{ [_ in string]?: number } | null} GAZ - Accept, hide - * @property {{ [_ in string]?: number } | null} GAZPtr - Soft reject - * @property {{ [_ in ComparableCstrAlias]?: number } | null} GACi - Accept - * @property {{ [_ in ComparableCstrAlias]?: number } | null} GACV - Accept - * @property {{ [_ in string]?: number } | null} GACP - Reject - * @property {{ [_ in string]?: number } | null} GACiPtr - Reject - * @property {{ [_ in string]?: number } | null} GACVPtr - Accept, hide - * @property {{ [_ in string]?: number } | null} GACPPtr - Accept, hide - * @property {{ [_ in BasicCstrAlias]?: number } | null} GABi - Accept - * @property {{ [_ in BasicCstrAlias]?: number } | null} GABs - Accept - * @property {{ [_ in string]?: number } | null} GABiPtr - Reject - * @property {{ [_ in string]?: number } | null} GABT - Reject - * @property {{ [_ in string]?: number } | null} GABTPtr - Reject - * @property {{ [_ in GoodTildeCstrAlias]?: number } | null} GAGT - Accept - * @property {{ [_ in string]?: number } | null} GAGTPtr - Accept, hide - * @property {{ [_ in NonBasicCstrAlias]?: number } | null} GANBV - Accept - * @property {{ [_ in string]?: number } | null} GANBP - Accept, hide - * @property {{ [_ in string]?: number } | null} GANBVPtr - Accept, hide - * @property {{ [_ in string]?: number } | null} GANBPPtr - Reject - * @property {{ [_ in PointableCstrAlias]?: number } | null} GAPlV1 - Accept - * @property {{ [_ in PointableCstrAlias]?: number } | null} GAPlV2 - Accept - * @property {{ [_ in string]?: number } | null} GAPlP1 - Reject - * @property {{ [_ in PointableCstrAlias]?: number } | null} GAPlP2 - Accept - * @property {{ [_ in string]?: number } | null} GAPlVPtr - Accept, hide - * @property {{ [_ in string]?: number } | null} GAPlPPtr - Accept, hide - * @property {{ [_ in MixedCstrAlias]?: number } | null} GAMi - Accept - * @property {{ [_ in MixedCstrAlias]?: number } | null} GAMS - Accept - * @property {{ [_ in MixedCstrAlias]?: number } | null} GAMV - Accept - * @property {{ [_ in string]?: number } | null} GAMSPtr - Reject - * @property {{ [_ in string]?: number } | null} GAMVPtr - Accept, hide - * @property {{ [_ in string]?: number } | null} GAII - Accept, hide - * @property {{ [_ in InterfaceCstrAlias]?: number } | null} GAIV - Accept - * @property {{ [_ in string]?: number } | null} GAIP - Accept, hide - * @property {{ [_ in string]?: number } | null} GAIIPtr - Reject - * @property {{ [_ in string]?: number } | null} GAIVPtr - Accept, hide - * @property {{ [_ in string]?: number } | null} GAIPPtr - Reject - * @property {{ [_ in string]?: number } | null} GAPrV - Accept, hide - * @property {{ [_ in string]?: number } | null} GAPrP - Accept, hide - * @property {{ [_ in string]?: number } | null} GAPrVPtr - Reject - * @property {{ [_ in string]?: number } | null} GAPrPPtr - Reject - */ - -/** - * @template X - * @typedef {X} MixedCstrAlias - */ - -/** - * @template V - * @typedef {V} NonBasicCstrAlias - */ - -/** - * @template W - * @typedef {W} PointableCstrAlias - */ - -/** - * @typedef {PointerTextMarshaler} PointerAlias - */ - -/** - * @typedef {string} PointerTextMarshaler - */ - -/** - * @typedef {string} StringAlias - */ - -/** - * @typedef {string} StringType - */ - -/** - * @typedef {ValueTextMarshaler} ValueAlias - */ - -/** - * @typedef {string} ValueTextMarshaler - */ - -// In interface mode, this file is likely to contain just comments. -// We add a dummy export statement to ensure it is recognised as an ES module. -export {}; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys/service.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys/service.js deleted file mode 100644 index 810db1875..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys/service.js +++ /dev/null @@ -1,18 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * @returns {$CancellablePromise<$models.Maps<$models.PointerTextMarshaler, number, number, $models.ValueTextMarshaler, $models.PointerTextMarshaler | null, $models.ValueTextMarshaler, $models.StringType, $models.ValueTextMarshaler, $models.PointerTextMarshaler | null>>} - */ -export function Method() { - return $Call.ByID(4021345184); -} diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/marshalers/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/marshalers/index.js deleted file mode 100644 index 0f2edd9c7..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/marshalers/index.js +++ /dev/null @@ -1,124 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as Service from "./service.js"; -export { - Service -}; - -import * as $models from "./models.js"; - -/** - * any - * @typedef {$models.AliasJsonMarshaler} AliasJsonMarshaler - */ - -/** - * any - * @typedef {$models.AliasMarshaler} AliasMarshaler - */ - -/** - * struct{} - * @typedef {$models.AliasNonMarshaler} AliasNonMarshaler - */ - -/** - * string - * @typedef {$models.AliasTextMarshaler} AliasTextMarshaler - */ - -/** - * @typedef {$models.Data} Data - */ - -/** - * any - * @typedef {$models.ImplicitJsonButText} ImplicitJsonButText - */ - -/** - * any - * @typedef {$models.ImplicitJsonMarshaler} ImplicitJsonMarshaler - */ - -/** - * any - * @typedef {$models.ImplicitMarshaler} ImplicitMarshaler - */ - -/** - * string - * @typedef {$models.ImplicitNonJson} ImplicitNonJson - */ - -/** - * class{ Marshaler, TextMarshaler } - * @typedef {$models.ImplicitNonMarshaler} ImplicitNonMarshaler - */ - -/** - * any - * @typedef {$models.ImplicitNonText} ImplicitNonText - */ - -/** - * any - * @typedef {$models.ImplicitTextButJson} ImplicitTextButJson - */ - -/** - * string - * @typedef {$models.ImplicitTextMarshaler} ImplicitTextMarshaler - */ - -/** - * class {} - * @typedef {$models.NonMarshaler} NonMarshaler - */ - -/** - * any - * @typedef {$models.PointerJsonMarshaler} PointerJsonMarshaler - */ - -/** - * any - * @typedef {$models.PointerMarshaler} PointerMarshaler - */ - -/** - * string - * @typedef {$models.PointerTextMarshaler} PointerTextMarshaler - */ - -/** - * any - * @typedef {$models.UnderlyingJsonMarshaler} UnderlyingJsonMarshaler - */ - -/** - * any - * @typedef {$models.UnderlyingMarshaler} UnderlyingMarshaler - */ - -/** - * string - * @typedef {$models.UnderlyingTextMarshaler} UnderlyingTextMarshaler - */ - -/** - * any - * @typedef {$models.ValueJsonMarshaler} ValueJsonMarshaler - */ - -/** - * any - * @typedef {$models.ValueMarshaler} ValueMarshaler - */ - -/** - * string - * @typedef {$models.ValueTextMarshaler} ValueTextMarshaler - */ diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/marshalers/models.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/marshalers/models.js deleted file mode 100644 index a956da60f..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/marshalers/models.js +++ /dev/null @@ -1,186 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as encoding$0 from "../../../../../../../../encoding/models.js"; -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as json$0 from "../../../../../../../../encoding/json/models.js"; - -/** - * any - * @typedef {any} AliasJsonMarshaler - */ - -/** - * any - * @typedef {any} AliasMarshaler - */ - -/** - * struct{} - * @typedef { { - * } } AliasNonMarshaler - */ - -/** - * string - * @typedef {string} AliasTextMarshaler - */ - -/** - * @typedef {Object} Data - * @property {NonMarshaler} NM - * @property {NonMarshaler | null} NMPtr - NonMarshaler | null - * @property {ValueJsonMarshaler} VJM - * @property {ValueJsonMarshaler | null} VJMPtr - ValueJsonMarshaler | null - * @property {PointerJsonMarshaler} PJM - * @property {PointerJsonMarshaler | null} PJMPtr - PointerJsonMarshaler | null - * @property {ValueTextMarshaler} VTM - * @property {ValueTextMarshaler | null} VTMPtr - ValueTextMarshaler | null - * @property {PointerTextMarshaler} PTM - * @property {PointerTextMarshaler | null} PTMPtr - PointerTextMarshaler | null - * @property {ValueMarshaler} VM - * @property {ValueMarshaler | null} VMPtr - ValueMarshaler | null - * @property {PointerMarshaler} PM - * @property {PointerMarshaler | null} PMPtr - PointerMarshaler | null - * @property {UnderlyingJsonMarshaler} UJM - * @property {UnderlyingJsonMarshaler | null} UJMPtr - UnderlyingJsonMarshaler | null - * @property {UnderlyingTextMarshaler} UTM - * @property {UnderlyingTextMarshaler | null} UTMPtr - UnderlyingTextMarshaler | null - * @property {UnderlyingMarshaler} UM - * @property {UnderlyingMarshaler | null} UMPtr - UnderlyingMarshaler | null - * @property {any} JM - any - * @property {any | null} JMPtr - any | null - * @property {string} TM - string - * @property {string | null} TMPtr - string | null - * @property {any} CJM - any - * @property {any | null} CJMPtr - any | null - * @property {string} CTM - string - * @property {string | null} CTMPtr - string | null - * @property {any} CM - any - * @property {any | null} CMPtr - any | null - * @property {AliasNonMarshaler} ANM - * @property {AliasNonMarshaler | null} ANMPtr - AliasNonMarshaler | null - * @property {AliasJsonMarshaler} AJM - * @property {AliasJsonMarshaler | null} AJMPtr - AliasJsonMarshaler | null - * @property {AliasTextMarshaler} ATM - * @property {AliasTextMarshaler | null} ATMPtr - AliasTextMarshaler | null - * @property {AliasMarshaler} AM - * @property {AliasMarshaler | null} AMPtr - AliasMarshaler | null - * @property {ImplicitJsonMarshaler} ImJM - * @property {ImplicitJsonMarshaler | null} ImJMPtr - ImplicitJsonMarshaler | null - * @property {ImplicitTextMarshaler} ImTM - * @property {ImplicitTextMarshaler | null} ImTMPtr - ImplicitTextMarshaler | null - * @property {ImplicitMarshaler} ImM - * @property {ImplicitMarshaler | null} ImMPtr - ImplicitMarshaler | null - * @property {ImplicitNonJson} ImNJ - * @property {ImplicitNonJson | null} ImNJPtr - ImplicitNonJson | null - * @property {ImplicitNonText} ImNT - * @property {ImplicitNonText | null} ImNTPtr - ImplicitNonText | null - * @property {ImplicitNonMarshaler} ImNM - * @property {ImplicitNonMarshaler | null} ImNMPtr - ImplicitNonMarshaler | null - * @property {ImplicitJsonButText} ImJbT - * @property {ImplicitJsonButText | null} ImJbTPtr - ImplicitJsonButText | null - * @property {ImplicitTextButJson} ImTbJ - * @property {ImplicitTextButJson | null} ImTbJPtr - ImplicitTextButJson | null - */ - -/** - * any - * @typedef {any} ImplicitJsonButText - */ - -/** - * any - * @typedef {any} ImplicitJsonMarshaler - */ - -/** - * any - * @typedef {any} ImplicitMarshaler - */ - -/** - * string - * @typedef {string} ImplicitNonJson - */ - -/** - * class{ Marshaler, TextMarshaler } - * @typedef {Object} ImplicitNonMarshaler - * @property {json$0.Marshaler} Marshaler - * @property {encoding$0.TextMarshaler} TextMarshaler - */ - -/** - * any - * @typedef {any} ImplicitNonText - */ - -/** - * any - * @typedef {any} ImplicitTextButJson - */ - -/** - * string - * @typedef {string} ImplicitTextMarshaler - */ - -/** - * class {} - * @typedef { { - * } } NonMarshaler - */ - -/** - * any - * @typedef {any} PointerJsonMarshaler - */ - -/** - * any - * @typedef {any} PointerMarshaler - */ - -/** - * string - * @typedef {string} PointerTextMarshaler - */ - -/** - * any - * @typedef {any} UnderlyingJsonMarshaler - */ - -/** - * any - * @typedef {any} UnderlyingMarshaler - */ - -/** - * string - * @typedef {string} UnderlyingTextMarshaler - */ - -/** - * any - * @typedef {any} ValueJsonMarshaler - */ - -/** - * any - * @typedef {any} ValueMarshaler - */ - -/** - * string - * @typedef {string} ValueTextMarshaler - */ - -// In interface mode, this file is likely to contain just comments. -// We add a dummy export statement to ensure it is recognised as an ES module. -export {}; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/marshalers/service.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/marshalers/service.js deleted file mode 100644 index 5ba9fe470..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/marshalers/service.js +++ /dev/null @@ -1,18 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * @returns {$CancellablePromise<$models.Data>} - */ -export function Method() { - return $Call.ByID(4021345184); -} diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/index.js deleted file mode 100644 index 0b7f42650..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/index.js +++ /dev/null @@ -1,32 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as SomeMethods from "./somemethods.js"; -export { - SomeMethods -}; - -import * as $models from "./models.js"; - -/** - * HowDifferent is a curious kind of person - * that lets other people decide how they are different. - * @template How - * @typedef {$models.HowDifferent} HowDifferent - */ - -/** - * Impersonator gets their fields from other people. - * @typedef {$models.Impersonator} Impersonator - */ - -/** - * Person is not a number. - * @typedef {$models.Person} Person - */ - -/** - * PrivatePerson gets their fields from hidden sources. - * @typedef {$models.PrivatePerson} PrivatePerson - */ diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/models.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/models.js deleted file mode 100644 index 93a37dc23..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/models.js +++ /dev/null @@ -1,44 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as other$0 from "./other/models.js"; - -/** - * HowDifferent is a curious kind of person - * that lets other people decide how they are different. - * @template How - * @typedef {Object} HowDifferent - * @property {string} Name - They have a name as well. - * @property {({ [_ in string]?: How } | null)[] | null} Differences - But they may have many differences. - */ - -/** - * Impersonator gets their fields from other people. - * @typedef {other$0.OtherPerson} Impersonator - */ - -/** - * Person is not a number. - * @typedef {Object} Person - * @property {string} Name - They have a name. - * @property {Impersonator[]} Friends - Exactly 4 sketchy friends. - */ - -/** - * PrivatePerson gets their fields from hidden sources. - * @typedef {personImpl} PrivatePerson - */ - -/** - * @typedef {Object} personImpl - * @property {string} Nickname - Nickname conceals a person's identity. - * @property {string} Name - They have a name. - * @property {Impersonator[]} Friends - Exactly 4 sketchy friends. - */ - -// In interface mode, this file is likely to contain just comments. -// We add a dummy export statement to ensure it is recognised as an ES module. -export {}; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/more/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/more/index.js deleted file mode 100644 index c3eabd022..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/more/index.js +++ /dev/null @@ -1,10 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as $models from "./models.js"; - -/** - * StringPtr is a nullable string. - * @typedef {$models.StringPtr} StringPtr - */ diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/more/models.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/more/models.js deleted file mode 100644 index 04f4d47dd..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/more/models.js +++ /dev/null @@ -1,12 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * StringPtr is a nullable string. - * @typedef {string | null} StringPtr - */ - -// In interface mode, this file is likely to contain just comments. -// We add a dummy export statement to ensure it is recognised as an ES module. -export {}; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/other/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/other/index.js deleted file mode 100644 index 33246d35e..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/other/index.js +++ /dev/null @@ -1,16 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as OtherMethods from "./othermethods.js"; -export { - OtherMethods -}; - -import * as $models from "./models.js"; - -/** - * OtherPerson is like a person, but different. - * @template T - * @typedef {$models.OtherPerson} OtherPerson - */ diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/other/models.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/other/models.js deleted file mode 100644 index 63a2ee722..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/other/models.js +++ /dev/null @@ -1,15 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * OtherPerson is like a person, but different. - * @template T - * @typedef {Object} OtherPerson - * @property {string} Name - They have a name as well. - * @property {T[] | null} Differences - But they may have many differences. - */ - -// In interface mode, this file is likely to contain just comments. -// We add a dummy export statement to ensure it is recognised as an ES module. -export {}; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/other/othermethods.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/other/othermethods.js deleted file mode 100644 index d647deeb4..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/other/othermethods.js +++ /dev/null @@ -1,20 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * OtherMethods has another method, but through a private embedded type. - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -/** - * LikeThisOtherOne does nothing as well, but is different. - * @returns {$CancellablePromise} - */ -export function LikeThisOtherOne() { - return $Call.ByID(3606939272); -} diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/somemethods.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/somemethods.js deleted file mode 100644 index dca6f4e6c..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/somemethods.js +++ /dev/null @@ -1,32 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * SomeMethods exports some methods. - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * LikeThisOne is an example method that does nothing. - * @returns {$CancellablePromise<[$models.Person, $models.HowDifferent, $models.PrivatePerson]>} - */ -export function LikeThisOne() { - return $Call.ByID(2124352079); -} - -/** - * LikeThisOtherOne does nothing as well, but is different. - * @returns {$CancellablePromise} - */ -export function LikeThisOtherOne() { - return $Call.ByID(4281222271); -} diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/out_of_tree/embedother.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/out_of_tree/embedother.js deleted file mode 100644 index 19bdcac29..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/out_of_tree/embedother.js +++ /dev/null @@ -1,20 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * EmbedOther is even trickier. - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -/** - * LikeThisOtherOne does nothing as well, but is different. - * @returns {$CancellablePromise} - */ -export function LikeThisOtherOne() { - return $Call.ByID(3566862802); -} diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/out_of_tree/embedservice.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/out_of_tree/embedservice.js deleted file mode 100644 index f50558b8c..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/out_of_tree/embedservice.js +++ /dev/null @@ -1,32 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * EmbedService is tricky. - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as nobindingshere$0 from "../no_bindings_here/models.js"; - -/** - * LikeThisOne is an example method that does nothing. - * @returns {$CancellablePromise<[nobindingshere$0.Person, nobindingshere$0.HowDifferent, nobindingshere$0.PrivatePerson]>} - */ -export function LikeThisOne() { - return $Call.ByID(2590614085); -} - -/** - * LikeThisOtherOne does nothing as well, but is different. - * @returns {$CancellablePromise} - */ -export function LikeThisOtherOne() { - return $Call.ByID(773650321); -} diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/out_of_tree/greetservice.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/out_of_tree/greetservice.js deleted file mode 100644 index 3597b6460..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/out_of_tree/greetservice.js +++ /dev/null @@ -1,21 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -/** - * Greet someone - * @param {string} $0 - * @returns {$CancellablePromise} - */ -export function Greet($0) { - return $Call.ByID(1411160069, $0); -} diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/out_of_tree/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/out_of_tree/index.js deleted file mode 100644 index 734fb02e7..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/out_of_tree/index.js +++ /dev/null @@ -1,12 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as EmbedOther from "./embedother.js"; -import * as EmbedService from "./embedservice.js"; -import * as GreetService from "./greetservice.js"; -export { - EmbedOther, - EmbedService, - GreetService -}; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple/greetservice.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple/greetservice.js deleted file mode 100644 index 9343d5531..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple/greetservice.js +++ /dev/null @@ -1,15 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -/** - * @param {string} name - * @returns {$CancellablePromise} - */ -export function Greet(name) { - return $Call.ByID(1411160069, name); -} diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple/index.js deleted file mode 100644 index 62ddbc166..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple/index.js +++ /dev/null @@ -1,10 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -import * as OtherService from "./otherservice.js"; -export { - GreetService, - OtherService -}; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple/otherservice.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple/otherservice.js deleted file mode 100644 index b4f3f039c..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple/otherservice.js +++ /dev/null @@ -1,14 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -/** - * @returns {$CancellablePromise} - */ -export function Hello() { - return $Call.ByID(4249972365); -} diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_files/greetservice.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_files/greetservice.js deleted file mode 100644 index 9343d5531..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_files/greetservice.js +++ /dev/null @@ -1,15 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -/** - * @param {string} name - * @returns {$CancellablePromise} - */ -export function Greet(name) { - return $Call.ByID(1411160069, name); -} diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_files/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_files/index.js deleted file mode 100644 index 62ddbc166..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_files/index.js +++ /dev/null @@ -1,10 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -import * as OtherService from "./otherservice.js"; -export { - GreetService, - OtherService -}; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_files/otherservice.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_files/otherservice.js deleted file mode 100644 index b4f3f039c..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_files/otherservice.js +++ /dev/null @@ -1,14 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -/** - * @returns {$CancellablePromise} - */ -export function Hello() { - return $Call.ByID(4249972365); -} diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_other/greetservice.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_other/greetservice.js deleted file mode 100644 index 40d2245b9..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_other/greetservice.js +++ /dev/null @@ -1,34 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * Greet does XYZ - * @param {string} name - * @returns {$CancellablePromise} - */ -export function Greet(name) { - return $Call.ByID(1411160069, name); -} - -/** - * NewPerson creates a new person - * @param {string} name - * @returns {$CancellablePromise<$models.Person | null>} - */ -export function NewPerson(name) { - return $Call.ByID(1661412647, name); -} diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_other/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_other/index.js deleted file mode 100644 index cb2979a7a..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_other/index.js +++ /dev/null @@ -1,14 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; - -import * as $models from "./models.js"; - -/** - * @typedef {$models.Person} Person - */ diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_other/models.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_other/models.js deleted file mode 100644 index 41b452f57..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_other/models.js +++ /dev/null @@ -1,17 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as services$0 from "./services/models.js"; - -/** - * @typedef {Object} Person - * @property {string} Name - * @property {services$0.Address | null} Address - */ - -// In interface mode, this file is likely to contain just comments. -// We add a dummy export statement to ensure it is recognised as an ES module. -export {}; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_other/services/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_other/services/index.js deleted file mode 100644 index 588ef7ca7..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_other/services/index.js +++ /dev/null @@ -1,14 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as OtherService from "./otherservice.js"; -export { - OtherService -}; - -import * as $models from "./models.js"; - -/** - * @typedef {$models.Address} Address - */ diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_other/services/models.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_other/services/models.js deleted file mode 100644 index c04e3b10b..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_other/services/models.js +++ /dev/null @@ -1,14 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * @typedef {Object} Address - * @property {string} Street - * @property {string} State - * @property {string} Country - */ - -// In interface mode, this file is likely to contain just comments. -// We add a dummy export statement to ensure it is recognised as an ES module. -export {}; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_other/services/otherservice.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_other/services/otherservice.js deleted file mode 100644 index 7a4789f75..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_other/services/otherservice.js +++ /dev/null @@ -1,25 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * OtherService is a struct - * that does things - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * Yay does this and that - * @returns {$CancellablePromise<$models.Address | null>} - */ -export function Yay() { - return $Call.ByID(3568225479); -} diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_non_pointer_single/greetservice.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_non_pointer_single/greetservice.js deleted file mode 100644 index e55c2595c..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_non_pointer_single/greetservice.js +++ /dev/null @@ -1,360 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * @param {number[]} $in - * @returns {$CancellablePromise} - */ -export function ArrayInt($in) { - return $Call.ByID(3862002418, $in); -} - -/** - * @param {boolean} $in - * @returns {$CancellablePromise} - */ -export function BoolInBoolOut($in) { - return $Call.ByID(2424639793, $in); -} - -/** - * @param {number} $in - * @returns {$CancellablePromise} - */ -export function Float32InFloat32Out($in) { - return $Call.ByID(3132595881, $in); -} - -/** - * @param {number} $in - * @returns {$CancellablePromise} - */ -export function Float64InFloat64Out($in) { - return $Call.ByID(2182412247, $in); -} - -/** - * Greet someone - * @param {string} name - * @returns {$CancellablePromise} - */ -export function Greet(name) { - return $Call.ByID(1411160069, name); -} - -/** - * @param {number} $in - * @returns {$CancellablePromise} - */ -export function Int16InIntOut($in) { - return $Call.ByID(3306292566, $in); -} - -/** - * @param {number | null} $in - * @returns {$CancellablePromise} - */ -export function Int16PointerInAndOutput($in) { - return $Call.ByID(1754277916, $in); -} - -/** - * @param {number} $in - * @returns {$CancellablePromise} - */ -export function Int32InIntOut($in) { - return $Call.ByID(1909469092, $in); -} - -/** - * @param {number | null} $in - * @returns {$CancellablePromise} - */ -export function Int32PointerInAndOutput($in) { - return $Call.ByID(4251088558, $in); -} - -/** - * @param {number} $in - * @returns {$CancellablePromise} - */ -export function Int64InIntOut($in) { - return $Call.ByID(1343888303, $in); -} - -/** - * @param {number | null} $in - * @returns {$CancellablePromise} - */ -export function Int64PointerInAndOutput($in) { - return $Call.ByID(2205561041, $in); -} - -/** - * @param {number} $in - * @returns {$CancellablePromise} - */ -export function Int8InIntOut($in) { - return $Call.ByID(572240879, $in); -} - -/** - * @param {number | null} $in - * @returns {$CancellablePromise} - */ -export function Int8PointerInAndOutput($in) { - return $Call.ByID(2189402897, $in); -} - -/** - * @param {number} $in - * @returns {$CancellablePromise} - */ -export function IntInIntOut($in) { - return $Call.ByID(642881729, $in); -} - -/** - * @param {number | null} $in - * @returns {$CancellablePromise} - */ -export function IntPointerInAndOutput($in) { - return $Call.ByID(1066151743, $in); -} - -/** - * @param {number | null} $in - * @returns {$CancellablePromise} - */ -export function IntPointerInputNamedOutputs($in) { - return $Call.ByID(2718999663, $in); -} - -/** - * @param {{ [_ in `${number}`]?: number } | null} $in - * @returns {$CancellablePromise} - */ -export function MapIntInt($in) { - return $Call.ByID(2386486356, $in); -} - -/** - * @param {{ [_ in `${number}`]?: number | null } | null} $in - * @returns {$CancellablePromise} - */ -export function MapIntIntPointer($in) { - return $Call.ByID(2163571325, $in); -} - -/** - * @param {{ [_ in `${number}`]?: number[] | null } | null} $in - * @returns {$CancellablePromise} - */ -export function MapIntSliceInt($in) { - return $Call.ByID(2900172572, $in); -} - -/** - * @param {{ [_ in `${number}`]?: number[] | null } | null} $in - * @returns {$CancellablePromise<{ [_ in `${number}`]?: number[] | null } | null>} - */ -export function MapIntSliceIntInMapIntSliceIntOut($in) { - return $Call.ByID(881980169, $in); -} - -/** - * @returns {$CancellablePromise} - */ -export function NoInputsStringOut() { - return $Call.ByID(1075577233); -} - -/** - * @param {boolean | null} $in - * @returns {$CancellablePromise} - */ -export function PointerBoolInBoolOut($in) { - return $Call.ByID(3589606958, $in); -} - -/** - * @param {number | null} $in - * @returns {$CancellablePromise} - */ -export function PointerFloat32InFloat32Out($in) { - return $Call.ByID(224675106, $in); -} - -/** - * @param {number | null} $in - * @returns {$CancellablePromise} - */ -export function PointerFloat64InFloat64Out($in) { - return $Call.ByID(2124953624, $in); -} - -/** - * @param {{ [_ in `${number}`]?: number } | null} $in - * @returns {$CancellablePromise} - */ -export function PointerMapIntInt($in) { - return $Call.ByID(3516977899, $in); -} - -/** - * @param {string | null} $in - * @returns {$CancellablePromise} - */ -export function PointerStringInStringOut($in) { - return $Call.ByID(229603958, $in); -} - -/** - * @param {string[] | null} $in - * @returns {$CancellablePromise} - */ -export function StringArrayInputNamedOutput($in) { - return $Call.ByID(3678582682, $in); -} - -/** - * @param {string[] | null} $in - * @returns {$CancellablePromise} - */ -export function StringArrayInputNamedOutputs($in) { - return $Call.ByID(319259595, $in); -} - -/** - * @param {string[] | null} $in - * @returns {$CancellablePromise} - */ -export function StringArrayInputStringArrayOut($in) { - return $Call.ByID(383995060, $in); -} - -/** - * @param {string[] | null} $in - * @returns {$CancellablePromise} - */ -export function StringArrayInputStringOut($in) { - return $Call.ByID(1091960237, $in); -} - -/** - * @param {$models.Person} $in - * @returns {$CancellablePromise<$models.Person>} - */ -export function StructInputStructOutput($in) { - return $Call.ByID(3835643147, $in); -} - -/** - * @param {$models.Person | null} $in - * @returns {$CancellablePromise} - */ -export function StructPointerInputErrorOutput($in) { - return $Call.ByID(2447692557, $in); -} - -/** - * @param {$models.Person | null} $in - * @returns {$CancellablePromise<$models.Person | null>} - */ -export function StructPointerInputStructPointerOutput($in) { - return $Call.ByID(2943477349, $in); -} - -/** - * @param {number} $in - * @returns {$CancellablePromise} - */ -export function UInt16InUIntOut($in) { - return $Call.ByID(3401034892, $in); -} - -/** - * @param {number | null} $in - * @returns {$CancellablePromise} - */ -export function UInt16PointerInAndOutput($in) { - return $Call.ByID(1236957573, $in); -} - -/** - * @param {number} $in - * @returns {$CancellablePromise} - */ -export function UInt32InUIntOut($in) { - return $Call.ByID(1160383782, $in); -} - -/** - * @param {number | null} $in - * @returns {$CancellablePromise} - */ -export function UInt32PointerInAndOutput($in) { - return $Call.ByID(1739300671, $in); -} - -/** - * @param {number} $in - * @returns {$CancellablePromise} - */ -export function UInt64InUIntOut($in) { - return $Call.ByID(793803239, $in); -} - -/** - * @param {number | null} $in - * @returns {$CancellablePromise} - */ -export function UInt64PointerInAndOutput($in) { - return $Call.ByID(1403757716, $in); -} - -/** - * @param {number} $in - * @returns {$CancellablePromise} - */ -export function UInt8InUIntOut($in) { - return $Call.ByID(2988345717, $in); -} - -/** - * @param {number | null} $in - * @returns {$CancellablePromise} - */ -export function UInt8PointerInAndOutput($in) { - return $Call.ByID(518250834, $in); -} - -/** - * @param {number} $in - * @returns {$CancellablePromise} - */ -export function UIntInUIntOut($in) { - return $Call.ByID(2836661285, $in); -} - -/** - * @param {number | null} $in - * @returns {$CancellablePromise} - */ -export function UIntPointerInAndOutput($in) { - return $Call.ByID(1367187362, $in); -} diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_non_pointer_single/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_non_pointer_single/index.js deleted file mode 100644 index cb2979a7a..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_non_pointer_single/index.js +++ /dev/null @@ -1,14 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; - -import * as $models from "./models.js"; - -/** - * @typedef {$models.Person} Person - */ diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_non_pointer_single/models.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_non_pointer_single/models.js deleted file mode 100644 index ec6136e27..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_non_pointer_single/models.js +++ /dev/null @@ -1,14 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * @typedef {Object} Person - * @property {string} Name - * @property {Person | null} Parent - * @property {{"Age": number, "Address": {"Street": string}}} Details - */ - -// In interface mode, this file is likely to contain just comments. -// We add a dummy export statement to ensure it is recognised as an ES module. -export {}; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_single/greetservice.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_single/greetservice.js deleted file mode 100644 index e55c2595c..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_single/greetservice.js +++ /dev/null @@ -1,360 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * @param {number[]} $in - * @returns {$CancellablePromise} - */ -export function ArrayInt($in) { - return $Call.ByID(3862002418, $in); -} - -/** - * @param {boolean} $in - * @returns {$CancellablePromise} - */ -export function BoolInBoolOut($in) { - return $Call.ByID(2424639793, $in); -} - -/** - * @param {number} $in - * @returns {$CancellablePromise} - */ -export function Float32InFloat32Out($in) { - return $Call.ByID(3132595881, $in); -} - -/** - * @param {number} $in - * @returns {$CancellablePromise} - */ -export function Float64InFloat64Out($in) { - return $Call.ByID(2182412247, $in); -} - -/** - * Greet someone - * @param {string} name - * @returns {$CancellablePromise} - */ -export function Greet(name) { - return $Call.ByID(1411160069, name); -} - -/** - * @param {number} $in - * @returns {$CancellablePromise} - */ -export function Int16InIntOut($in) { - return $Call.ByID(3306292566, $in); -} - -/** - * @param {number | null} $in - * @returns {$CancellablePromise} - */ -export function Int16PointerInAndOutput($in) { - return $Call.ByID(1754277916, $in); -} - -/** - * @param {number} $in - * @returns {$CancellablePromise} - */ -export function Int32InIntOut($in) { - return $Call.ByID(1909469092, $in); -} - -/** - * @param {number | null} $in - * @returns {$CancellablePromise} - */ -export function Int32PointerInAndOutput($in) { - return $Call.ByID(4251088558, $in); -} - -/** - * @param {number} $in - * @returns {$CancellablePromise} - */ -export function Int64InIntOut($in) { - return $Call.ByID(1343888303, $in); -} - -/** - * @param {number | null} $in - * @returns {$CancellablePromise} - */ -export function Int64PointerInAndOutput($in) { - return $Call.ByID(2205561041, $in); -} - -/** - * @param {number} $in - * @returns {$CancellablePromise} - */ -export function Int8InIntOut($in) { - return $Call.ByID(572240879, $in); -} - -/** - * @param {number | null} $in - * @returns {$CancellablePromise} - */ -export function Int8PointerInAndOutput($in) { - return $Call.ByID(2189402897, $in); -} - -/** - * @param {number} $in - * @returns {$CancellablePromise} - */ -export function IntInIntOut($in) { - return $Call.ByID(642881729, $in); -} - -/** - * @param {number | null} $in - * @returns {$CancellablePromise} - */ -export function IntPointerInAndOutput($in) { - return $Call.ByID(1066151743, $in); -} - -/** - * @param {number | null} $in - * @returns {$CancellablePromise} - */ -export function IntPointerInputNamedOutputs($in) { - return $Call.ByID(2718999663, $in); -} - -/** - * @param {{ [_ in `${number}`]?: number } | null} $in - * @returns {$CancellablePromise} - */ -export function MapIntInt($in) { - return $Call.ByID(2386486356, $in); -} - -/** - * @param {{ [_ in `${number}`]?: number | null } | null} $in - * @returns {$CancellablePromise} - */ -export function MapIntIntPointer($in) { - return $Call.ByID(2163571325, $in); -} - -/** - * @param {{ [_ in `${number}`]?: number[] | null } | null} $in - * @returns {$CancellablePromise} - */ -export function MapIntSliceInt($in) { - return $Call.ByID(2900172572, $in); -} - -/** - * @param {{ [_ in `${number}`]?: number[] | null } | null} $in - * @returns {$CancellablePromise<{ [_ in `${number}`]?: number[] | null } | null>} - */ -export function MapIntSliceIntInMapIntSliceIntOut($in) { - return $Call.ByID(881980169, $in); -} - -/** - * @returns {$CancellablePromise} - */ -export function NoInputsStringOut() { - return $Call.ByID(1075577233); -} - -/** - * @param {boolean | null} $in - * @returns {$CancellablePromise} - */ -export function PointerBoolInBoolOut($in) { - return $Call.ByID(3589606958, $in); -} - -/** - * @param {number | null} $in - * @returns {$CancellablePromise} - */ -export function PointerFloat32InFloat32Out($in) { - return $Call.ByID(224675106, $in); -} - -/** - * @param {number | null} $in - * @returns {$CancellablePromise} - */ -export function PointerFloat64InFloat64Out($in) { - return $Call.ByID(2124953624, $in); -} - -/** - * @param {{ [_ in `${number}`]?: number } | null} $in - * @returns {$CancellablePromise} - */ -export function PointerMapIntInt($in) { - return $Call.ByID(3516977899, $in); -} - -/** - * @param {string | null} $in - * @returns {$CancellablePromise} - */ -export function PointerStringInStringOut($in) { - return $Call.ByID(229603958, $in); -} - -/** - * @param {string[] | null} $in - * @returns {$CancellablePromise} - */ -export function StringArrayInputNamedOutput($in) { - return $Call.ByID(3678582682, $in); -} - -/** - * @param {string[] | null} $in - * @returns {$CancellablePromise} - */ -export function StringArrayInputNamedOutputs($in) { - return $Call.ByID(319259595, $in); -} - -/** - * @param {string[] | null} $in - * @returns {$CancellablePromise} - */ -export function StringArrayInputStringArrayOut($in) { - return $Call.ByID(383995060, $in); -} - -/** - * @param {string[] | null} $in - * @returns {$CancellablePromise} - */ -export function StringArrayInputStringOut($in) { - return $Call.ByID(1091960237, $in); -} - -/** - * @param {$models.Person} $in - * @returns {$CancellablePromise<$models.Person>} - */ -export function StructInputStructOutput($in) { - return $Call.ByID(3835643147, $in); -} - -/** - * @param {$models.Person | null} $in - * @returns {$CancellablePromise} - */ -export function StructPointerInputErrorOutput($in) { - return $Call.ByID(2447692557, $in); -} - -/** - * @param {$models.Person | null} $in - * @returns {$CancellablePromise<$models.Person | null>} - */ -export function StructPointerInputStructPointerOutput($in) { - return $Call.ByID(2943477349, $in); -} - -/** - * @param {number} $in - * @returns {$CancellablePromise} - */ -export function UInt16InUIntOut($in) { - return $Call.ByID(3401034892, $in); -} - -/** - * @param {number | null} $in - * @returns {$CancellablePromise} - */ -export function UInt16PointerInAndOutput($in) { - return $Call.ByID(1236957573, $in); -} - -/** - * @param {number} $in - * @returns {$CancellablePromise} - */ -export function UInt32InUIntOut($in) { - return $Call.ByID(1160383782, $in); -} - -/** - * @param {number | null} $in - * @returns {$CancellablePromise} - */ -export function UInt32PointerInAndOutput($in) { - return $Call.ByID(1739300671, $in); -} - -/** - * @param {number} $in - * @returns {$CancellablePromise} - */ -export function UInt64InUIntOut($in) { - return $Call.ByID(793803239, $in); -} - -/** - * @param {number | null} $in - * @returns {$CancellablePromise} - */ -export function UInt64PointerInAndOutput($in) { - return $Call.ByID(1403757716, $in); -} - -/** - * @param {number} $in - * @returns {$CancellablePromise} - */ -export function UInt8InUIntOut($in) { - return $Call.ByID(2988345717, $in); -} - -/** - * @param {number | null} $in - * @returns {$CancellablePromise} - */ -export function UInt8PointerInAndOutput($in) { - return $Call.ByID(518250834, $in); -} - -/** - * @param {number} $in - * @returns {$CancellablePromise} - */ -export function UIntInUIntOut($in) { - return $Call.ByID(2836661285, $in); -} - -/** - * @param {number | null} $in - * @returns {$CancellablePromise} - */ -export function UIntPointerInAndOutput($in) { - return $Call.ByID(1367187362, $in); -} diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_single/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_single/index.js deleted file mode 100644 index cb2979a7a..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_single/index.js +++ /dev/null @@ -1,14 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; - -import * as $models from "./models.js"; - -/** - * @typedef {$models.Person} Person - */ diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_single/models.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_single/models.js deleted file mode 100644 index ec6136e27..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_single/models.js +++ /dev/null @@ -1,14 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * @typedef {Object} Person - * @property {string} Name - * @property {Person | null} Parent - * @property {{"Age": number, "Address": {"Street": string}}} Details - */ - -// In interface mode, this file is likely to contain just comments. -// We add a dummy export statement to ensure it is recognised as an ES module. -export {}; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single/greetservice.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single/greetservice.js deleted file mode 100644 index 6c1448d81..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single/greetservice.js +++ /dev/null @@ -1,21 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -/** - * Greet someone - * @param {string} name - * @returns {$CancellablePromise} - */ -export function Greet(name) { - return $Call.ByID(1411160069, name); -} diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single/index.js deleted file mode 100644 index fdf1ff435..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single/index.js +++ /dev/null @@ -1,8 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_function/greetservice.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_function/greetservice.js deleted file mode 100644 index 6c1448d81..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_function/greetservice.js +++ /dev/null @@ -1,21 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -/** - * Greet someone - * @param {string} name - * @returns {$CancellablePromise} - */ -export function Greet(name) { - return $Call.ByID(1411160069, name); -} diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_function/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_function/index.js deleted file mode 100644 index fdf1ff435..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_function/index.js +++ /dev/null @@ -1,8 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_other_function/greetservice.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_other_function/greetservice.js deleted file mode 100644 index 40d2245b9..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_other_function/greetservice.js +++ /dev/null @@ -1,34 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * Greet does XYZ - * @param {string} name - * @returns {$CancellablePromise} - */ -export function Greet(name) { - return $Call.ByID(1411160069, name); -} - -/** - * NewPerson creates a new person - * @param {string} name - * @returns {$CancellablePromise<$models.Person | null>} - */ -export function NewPerson(name) { - return $Call.ByID(1661412647, name); -} diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_other_function/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_other_function/index.js deleted file mode 100644 index 977600693..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_other_function/index.js +++ /dev/null @@ -1,16 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; - -import * as $models from "./models.js"; - -/** - * Person is a person! - * They have a name and an address - * @typedef {$models.Person} Person - */ diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_other_function/models.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_other_function/models.js deleted file mode 100644 index ab5cea255..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_other_function/models.js +++ /dev/null @@ -1,19 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as services$0 from "./services/models.js"; - -/** - * Person is a person! - * They have a name and an address - * @typedef {Object} Person - * @property {string} Name - * @property {services$0.Address | null} Address - */ - -// In interface mode, this file is likely to contain just comments. -// We add a dummy export statement to ensure it is recognised as an ES module. -export {}; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_other_function/services/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_other_function/services/index.js deleted file mode 100644 index 588ef7ca7..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_other_function/services/index.js +++ /dev/null @@ -1,14 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as OtherService from "./otherservice.js"; -export { - OtherService -}; - -import * as $models from "./models.js"; - -/** - * @typedef {$models.Address} Address - */ diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_other_function/services/models.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_other_function/services/models.js deleted file mode 100644 index c04e3b10b..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_other_function/services/models.js +++ /dev/null @@ -1,14 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * @typedef {Object} Address - * @property {string} Street - * @property {string} State - * @property {string} Country - */ - -// In interface mode, this file is likely to contain just comments. -// We add a dummy export statement to ensure it is recognised as an ES module. -export {}; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_other_function/services/otherservice.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_other_function/services/otherservice.js deleted file mode 100644 index 3c9c56546..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_other_function/services/otherservice.js +++ /dev/null @@ -1,25 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * OtherService is a struct - * that does things - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * Yay does this and that - * @returns {$CancellablePromise<$models.Address | null>} - */ -export function Yay() { - return $Call.ByID(1491748400); -} diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/warnings.log b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/warnings.log deleted file mode 100644 index ce8369307..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=false/warnings.log +++ /dev/null @@ -1,83 +0,0 @@ -[warn] /testcases/complex_json/main.go:127:2: event 'collision' has one of multiple definitions here with data type map[string]int -[warn] /testcases/events_only/events.go:20:2: event 'collision' has one of multiple definitions here with data type int -[warn] /testcases/events_only/events.go:21:2: `application.RegisterEvent` called here with non-constant event name -[warn] /testcases/events_only/other.go:10:5: `application.RegisterEvent` is instantiated here but not called -[warn] /testcases/events_only/other.go:13:2: `application.RegisterEvent` called here with non-constant event name -[warn] /testcases/events_only/other.go:17:2: data type []T for event 'parametric' contains unresolved type parameters and will be ignored` -[warn] /testcases/events_only/other.go:22:2: event 'common:ApplicationStarted' is a known system event and cannot be overridden; this call to `application.RegisterEvent` will panic -[warn] /testcases/marshalers/main.go:212:2: event 'collision' has one of multiple definitions here with data type *struct{Field []bool} -[warn] /testcases/marshalers/main.go:214:2: data type encoding/json.Marshaler for event 'interface' is a non-empty interface: emitting events from the frontend with data other than `null` is not supported by encoding/json and will likely result in runtime errors -[warn] dynamically registered event names are not discoverable by the binding generator: it is recommended to invoke `application.RegisterEvent` with constant arguments only -[warn] event 'collision' has multiple conflicting definitions and will be ignored -[warn] events registered through indirect calls are not discoverable by the binding generator: it is recommended to invoke `application.RegisterEvent` directly -[warn] generic wrappers for calls to `application.RegisterEvent` are not analysable by the binding generator: it is recommended to call `application.RegisterEvent` with concrete types only -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *R is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *S is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *T is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *U is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *V is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *X is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *Y is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *Z is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *any is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *complex64 is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *encoding.TextMarshaler is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *float32 is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.CustomInterface is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.EmbeddedInterface is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.InterfaceAlias is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.InterfacePtrAlias is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.InterfacePtrType is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.InterfaceType is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.NonTextMarshaler is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.PointerPtrAlias is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.PointerPtrType is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.PointerType is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.ValuePtrAlias is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.ValuePtrType is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.ValueType is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *int is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *string is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *uint is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type R is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type T is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type W is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type any is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type bool is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type complex64 is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type float32 is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.BadTildeCstrAlias[T] is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.BadTildeCstrAlias[struct{}] is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.BadTildeCstrPtrAlias[T] is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.BadTildeCstrPtrAlias[struct{}] is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.BasicCstrPtrAlias[S] is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.BasicCstrPtrAlias[int] is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.ComparableCstrAlias[R] is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.ComparableCstrAlias[github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.PointerTextMarshaler] is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.ComparableCstrPtrAlias[R] is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.ComparableCstrPtrAlias[int] is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.EmbeddedPointer is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.GoodTildeCstrPtrAlias[U] is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.InterfaceCstrPtrAlias[*github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.PointerTextMarshaler] is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.InterfaceCstrPtrAlias[Y] is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.InterfaceCstrPtrAlias[encoding.TextMarshaler] is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.InterfacePtrAlias is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.InterfacePtrType is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.MixedCstrPtrAlias[X] is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.MixedCstrPtrAlias[github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.StringType] is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.NonBasicCstrPtrAlias[*github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.PointerTextMarshaler] is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.NonBasicCstrPtrAlias[V] is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.NonTextMarshaler is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.PointableCstrAlias[W] is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.PointableCstrAlias[github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.PointerTextMarshaler] is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.PointerAlias is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.PointerCstrPtrAlias[R, Z] is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.PointerCstrPtrAlias[github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.PointerTextMarshaler, *github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.PointerTextMarshaler] is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.PointerCstrPtrAlias[github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.ValueTextMarshaler, *github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.ValueTextMarshaler] is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.PointerPtrType is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.PointerTextMarshaler is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.PointerType is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.ValuePtrType is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.ValueType is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.WrongAlias is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.WrongType is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/encoding/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/encoding/index.js deleted file mode 100644 index cf48d86db..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/encoding/index.js +++ /dev/null @@ -1,13 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as $models from "./models.js"; - -/** - * TextMarshaler is the interface implemented by an object that can - * marshal itself into a textual form. - * - * MarshalText encodes the receiver into UTF-8-encoded text and returns the result. - * @typedef {$models.TextMarshaler} TextMarshaler - */ diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/encoding/json/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/encoding/json/index.js deleted file mode 100644 index 22f1fd904..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/encoding/json/index.js +++ /dev/null @@ -1,11 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as $models from "./models.js"; - -/** - * Marshaler is the interface implemented by types that - * can marshal themselves into valid JSON. - * @typedef {$models.Marshaler} Marshaler - */ diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/encoding/json/models.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/encoding/json/models.js deleted file mode 100644 index 5dce4eea6..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/encoding/json/models.js +++ /dev/null @@ -1,13 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * Marshaler is the interface implemented by types that - * can marshal themselves into valid JSON. - * @typedef {any} Marshaler - */ - -// In interface mode, this file is likely to contain just comments. -// We add a dummy export statement to ensure it is recognised as an ES module. -export {}; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/encoding/models.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/encoding/models.js deleted file mode 100644 index db89bafbc..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/encoding/models.js +++ /dev/null @@ -1,15 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * TextMarshaler is the interface implemented by an object that can - * marshal itself into a textual form. - * - * MarshalText encodes the receiver into UTF-8-encoded text and returns the result. - * @typedef {any} TextMarshaler - */ - -// In interface mode, this file is likely to contain just comments. -// We add a dummy export statement to ensure it is recognised as an ES module. -export {}; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/eventcreate.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/eventcreate.js deleted file mode 100644 index 71a208a3d..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/eventcreate.js +++ /dev/null @@ -1,9 +0,0 @@ -//@ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Create as $Create } from "/wails/runtime.js"; - -Object.freeze($Create.Events); diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/eventdata.d.ts b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/eventdata.d.ts deleted file mode 100644 index be1730836..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/eventdata.d.ts +++ /dev/null @@ -1,30 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import type { Events } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import type * as json$0 from "../../../../../encoding/json/models.js"; -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import type * as events_only$0 from "./generator/testcases/events_only/models.js"; -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import type * as more$0 from "./generator/testcases/no_bindings_here/more/models.js"; - -declare module "/wails/runtime.js" { - namespace Events { - interface CustomEvents { - "events_only:class": events_only$0.SomeClass; - "events_only:map": { [_ in string]?: number[] | null } | null; - "events_only:nodata": void; - "events_only:other": more$0.StringPtr[] | null; - "events_only:string": string; - "interface": json$0.Marshaler; - "overlap": {"Field": boolean[] | null} | null; - } - } -} diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/aliases/greetservice.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/aliases/greetservice.js deleted file mode 100644 index c4ae72eae..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/aliases/greetservice.js +++ /dev/null @@ -1,77 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as nobindingshere$0 from "../no_bindings_here/models.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * Get someone. - * @param {$models.Alias} aliasValue - * @returns {$CancellablePromise<$models.Person>} - */ -export function Get(aliasValue) { - return $Call.ByName("main.GreetService.Get", aliasValue); -} - -/** - * Apparently, aliases are all the rage right now. - * @param {$models.AliasedPerson} p - * @returns {$CancellablePromise<$models.StrangelyAliasedPerson>} - */ -export function GetButAliased(p) { - return $Call.ByName("main.GreetService.GetButAliased", p); -} - -/** - * Get someone quite different. - * @returns {$CancellablePromise<$models.GenericPerson>} - */ -export function GetButDifferent() { - return $Call.ByName("main.GreetService.GetButDifferent"); -} - -/** - * @returns {$CancellablePromise} - */ -export function GetButForeignPrivateAlias() { - return $Call.ByName("main.GreetService.GetButForeignPrivateAlias"); -} - -/** - * @returns {$CancellablePromise<$models.AliasGroup>} - */ -export function GetButGenericAliases() { - return $Call.ByName("main.GreetService.GetButGenericAliases"); -} - -/** - * @returns {$CancellablePromise<$models.SubPackageAlias>} - */ -export function GetButSubPackageAlias() { - return $Call.ByName("main.GreetService.GetButSubPackageAlias"); -} - -/** - * Greet a lot of unusual things. - * @param {$models.EmptyAliasStruct} $0 - * @param {$models.EmptyStruct} $1 - * @returns {$CancellablePromise<$models.AliasStruct>} - */ -export function Greet($0, $1) { - return $Call.ByName("main.GreetService.Greet", $0, $1); -} diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/aliases/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/aliases/index.js deleted file mode 100644 index 32457ecf3..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/aliases/index.js +++ /dev/null @@ -1,101 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; - -import * as $models from "./models.js"; - -/** - * A nice type Alias. - * @typedef {$models.Alias} Alias - */ - -/** - * A class whose fields have various aliased types. - * @typedef {$models.AliasGroup} AliasGroup - */ - -/** - * A struct alias. - * This should be rendered as a typedef or interface in every mode. - * @typedef {$models.AliasStruct} AliasStruct - */ - -/** - * A class alias. - * @typedef {$models.AliasedPerson} AliasedPerson - */ - -/** - * An empty struct alias. - * @typedef {$models.EmptyAliasStruct} EmptyAliasStruct - */ - -/** - * An empty struct. - * @typedef {$models.EmptyStruct} EmptyStruct - */ - -/** - * A generic alias that forwards to a type parameter. - * @template T - * @typedef {$models.GenericAlias} GenericAlias - */ - -/** - * A generic alias that wraps a map. - * @template T,U - * @typedef {$models.GenericMapAlias} GenericMapAlias - */ - -/** - * A generic struct containing an alias. - * @template T - * @typedef {$models.GenericPerson} GenericPerson - */ - -/** - * A generic alias that wraps a generic struct. - * @template T - * @typedef {$models.GenericPersonAlias} GenericPersonAlias - */ - -/** - * A generic alias that wraps a pointer type. - * @template T - * @typedef {$models.GenericPtrAlias} GenericPtrAlias - */ - -/** - * An alias that wraps a class through a non-typeparam alias. - * @typedef {$models.IndirectPersonAlias} IndirectPersonAlias - */ - -/** - * Another struct alias. - * @typedef {$models.OtherAliasStruct} OtherAliasStruct - */ - -/** - * A non-generic struct containing an alias. - * @typedef {$models.Person} Person - */ - -/** - * Another class alias, but ordered after its aliased class. - * @typedef {$models.StrangelyAliasedPerson} StrangelyAliasedPerson - */ - -/** - * An alias referencing another package that is not used elsewhere. - * @typedef {$models.SubPackageAlias} SubPackageAlias - */ - -/** - * An alias that wraps a class through a typeparam alias. - * @typedef {$models.TPIndirectPersonAlias} TPIndirectPersonAlias - */ diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/aliases/models.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/aliases/models.js deleted file mode 100644 index 52116e035..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/aliases/models.js +++ /dev/null @@ -1,122 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as subpkg$0 from "./subpkg/models.js"; - -/** - * A nice type Alias. - * @typedef {number} Alias - */ - -/** - * A class whose fields have various aliased types. - * @typedef {Object} AliasGroup - * @property {GenericAlias} GAi - * @property {GenericAlias>} GAP - * @property {GenericPtrAlias} GPAs - * @property {GenericPtrAlias>} GPAP - * @property {GenericMapAlias} GMA - * @property {GenericPersonAlias} GPA - * @property {IndirectPersonAlias} IPA - * @property {TPIndirectPersonAlias} TPIPA - * @property {SubPackageAlias} SPA - */ - -/** - * A struct alias. - * This should be rendered as a typedef or interface in every mode. - * @typedef {Object} AliasStruct - * @property {number[] | null} Foo - A field with a comment. - * @property {string} [Bar] - Definitely not Foo. - * @property {string} [Baz] - Definitely not Foo. - * @property {OtherAliasStruct} Other - A nested alias struct. - */ - -/** - * A class alias. - * @typedef {Person} AliasedPerson - */ - -/** - * An empty struct alias. - * @typedef { { - * } } EmptyAliasStruct - */ - -/** - * An empty struct. - * @typedef { { - * } } EmptyStruct - */ - -/** - * A generic alias that forwards to a type parameter. - * @template T - * @typedef {T} GenericAlias - */ - -/** - * A generic alias that wraps a map. - * @template T,U - * @typedef {{ [_ in string]?: U } | null} GenericMapAlias - */ - -/** - * A generic struct containing an alias. - * @template T - * @typedef {Object} GenericPerson - * @property {T} Name - * @property {Alias} AliasedField - */ - -/** - * A generic alias that wraps a generic struct. - * @template T - * @typedef {GenericPerson[] | null>} GenericPersonAlias - */ - -/** - * A generic alias that wraps a pointer type. - * @template T - * @typedef {GenericAlias | null} GenericPtrAlias - */ - -/** - * An alias that wraps a class through a non-typeparam alias. - * @typedef {GenericPersonAlias} IndirectPersonAlias - */ - -/** - * Another struct alias. - * @typedef {Object} OtherAliasStruct - * @property {number[] | null} NoMoreIdeas - */ - -/** - * A non-generic struct containing an alias. - * @typedef {Object} Person - * @property {string} Name - The Person's name. - * @property {Alias} AliasedField - A random alias field. - */ - -/** - * Another class alias, but ordered after its aliased class. - * @typedef {Person} StrangelyAliasedPerson - */ - -/** - * An alias referencing another package that is not used elsewhere. - * @typedef {subpkg$0.SubStruct} SubPackageAlias - */ - -/** - * An alias that wraps a class through a typeparam alias. - * @typedef {GenericAlias>} TPIndirectPersonAlias - */ - -// In interface mode, this file is likely to contain just comments. -// We add a dummy export statement to ensure it is recognised as an ES module. -export {}; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/aliases/subpkg/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/aliases/subpkg/index.js deleted file mode 100644 index e6b65eedd..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/aliases/subpkg/index.js +++ /dev/null @@ -1,10 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as $models from "./models.js"; - -/** - * SubStruct is a type in a subpackage that is only referenced through an alias. - * @typedef {$models.SubStruct} SubStruct - */ diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/aliases/subpkg/models.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/aliases/subpkg/models.js deleted file mode 100644 index d711593fc..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/aliases/subpkg/models.js +++ /dev/null @@ -1,13 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * SubStruct is a type in a subpackage that is only referenced through an alias. - * @typedef {Object} SubStruct - * @property {string[] | null} SomeField - */ - -// In interface mode, this file is likely to contain just comments. -// We add a dummy export statement to ensure it is recognised as an ES module. -export {}; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_expressions/config/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_expressions/config/index.js deleted file mode 100644 index f6c839720..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_expressions/config/index.js +++ /dev/null @@ -1,10 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as Service7 from "./service7.js"; -import * as Service9 from "./service9.js"; -export { - Service7, - Service9 -}; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_expressions/config/service7.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_expressions/config/service7.js deleted file mode 100644 index f62552e8a..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_expressions/config/service7.js +++ /dev/null @@ -1,14 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -/** - * @returns {$CancellablePromise} - */ -export function TestMethod() { - return $Call.ByName("github.com/wailsapp/wails/v3/internal/generator/testcases/complex_expressions/config.Service7.TestMethod"); -} diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_expressions/config/service9.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_expressions/config/service9.js deleted file mode 100644 index 244e74afe..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_expressions/config/service9.js +++ /dev/null @@ -1,14 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -/** - * @returns {$CancellablePromise} - */ -export function TestMethod2() { - return $Call.ByName("github.com/wailsapp/wails/v3/internal/generator/testcases/complex_expressions/config.Service9.TestMethod2"); -} diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_json/greetservice.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_json/greetservice.js deleted file mode 100644 index e146c3669..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_json/greetservice.js +++ /dev/null @@ -1,26 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * Greet does XYZ - * @param {$models.Person} person - * @param {$models.Embedded1} emb - * @returns {$CancellablePromise} - */ -export function Greet(person, emb) { - return $Call.ByName("main.GreetService.Greet", person, emb); -} diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_json/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_json/index.js deleted file mode 100644 index f21130b86..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_json/index.js +++ /dev/null @@ -1,27 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; - -export { - Title -} from "./models.js"; - -import * as $models from "./models.js"; - -/** - * @typedef {$models.Embedded1} Embedded1 - */ - -/** - * @typedef {$models.Embedded3} Embedded3 - */ - -/** - * Person represents a person - * @typedef {$models.Person} Person - */ diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_json/models.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_json/models.js deleted file mode 100644 index b30630777..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_json/models.js +++ /dev/null @@ -1,64 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * @typedef {Object} Embedded1 - * @property {number} Friends - Friends should be shadowed in Person by a field of lesser depth - * @property {number} Vanish - Vanish should be omitted from Person because there is another field with same depth and no tag - * @property {string} StillThere - StillThere should be shadowed in Person by other field with same depth and a json tag - * @property {`${boolean}`} NamingThingsIsHard - NamingThingsIsHard is a law of programming - */ - -/** - * @typedef {string} Embedded3 - */ - -/** - * Person represents a person - * @typedef { { - * "Titles"?: Title[] | null, - * "Names": string[] | null, - * "Partner": Person | null, - * "Friends": (Person | null)[] | null, - * "NamingThingsIsHard": `${boolean}`, - * "StillThere": Embedded3 | null, - * "-": number, - * "Embedded3": Embedded3, - * "StrangerNumber": `${number}`, - * "StrangestString"?: `"${string}"`, - * "StringStrangest"?: `"${string}"`, - * "emb4"?: embedded4, - * } } Person - */ - -/** - * Title is a title - * @readonly - * @enum {string} - */ -export const Title = { - /** - * The Go zero value for the underlying type of the enum. - */ - $zero: "", - - /** - * Mister is a title - */ - Mister: "Mr", - Miss: "Miss", - Ms: "Ms", - Mrs: "Mrs", - Dr: "Dr", -}; - -/** - * @typedef {Object} embedded4 - * @property {`${boolean}`} NamingThingsIsHard - NamingThingsIsHard is a law of programming - * @property {boolean} Friends - Friends should not be shadowed in Person as embedded4 is not embedded from encoding/json's point of view; however, it should be shadowed in Embedded1 - */ - -// In interface mode, this file is likely to contain just comments. -// We add a dummy export statement to ensure it is recognised as an ES module. -export {}; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_method/greetservice.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_method/greetservice.js deleted file mode 100644 index 567dc8884..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_method/greetservice.js +++ /dev/null @@ -1,32 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * Greet does XYZ - * It has a multiline doc comment - * The comment has even some * / traps!! - * @param {string} str - * @param {$models.Person[] | null} people - * @param {{"AnotherCount": number, "AnotherOne": $models.Person | null}} $2 - * @param {{ [_ in `${number}`]?: boolean | null } | null} assoc - * @param {(number | null)[] | null} $4 - * @param {string[]} other - * @returns {$CancellablePromise<[$models.Person, any, number[] | null]>} - */ -export function Greet(str, people, $2, assoc, $4, ...other) { - return $Call.ByName("main.GreetService.Greet", str, people, $2, assoc, $4, other); -} diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_method/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_method/index.js deleted file mode 100644 index 88af1203b..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_method/index.js +++ /dev/null @@ -1,15 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; - -import * as $models from "./models.js"; - -/** - * Person represents a person - * @typedef {$models.Person} Person - */ diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_method/models.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_method/models.js deleted file mode 100644 index 035bc0792..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_method/models.js +++ /dev/null @@ -1,13 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * Person represents a person - * @typedef {Object} Person - * @property {string} Name - */ - -// In interface mode, this file is likely to contain just comments. -// We add a dummy export statement to ensure it is recognised as an ES module. -export {}; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/cyclic_imports/greetservice.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/cyclic_imports/greetservice.js deleted file mode 100644 index 8203e4168..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/cyclic_imports/greetservice.js +++ /dev/null @@ -1,24 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * Make a cycle. - * @returns {$CancellablePromise<[$models.StructA, $models.StructC]>} - */ -export function MakeCycles() { - return $Call.ByName("main.GreetService.MakeCycles"); -} diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/cyclic_imports/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/cyclic_imports/index.js deleted file mode 100644 index 9b49a9172..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/cyclic_imports/index.js +++ /dev/null @@ -1,22 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; - -import * as $models from "./models.js"; - -/** - * @typedef {$models.StructA} StructA - */ - -/** - * @typedef {$models.StructC} StructC - */ - -/** - * @typedef {$models.StructE} StructE - */ diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/cyclic_imports/models.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/cyclic_imports/models.js deleted file mode 100644 index 50e0d0fc0..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/cyclic_imports/models.js +++ /dev/null @@ -1,32 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * @typedef {Object} StructA - * @property {structB | null} B - */ - -/** - * @typedef {Object} StructC - * @property {structD} D - */ - -/** - * @typedef { { - * } } StructE - */ - -/** - * @typedef {Object} structB - * @property {StructA | null} A - */ - -/** - * @typedef {Object} structD - * @property {StructE} E - */ - -// In interface mode, this file is likely to contain just comments. -// We add a dummy export statement to ensure it is recognised as an ES module. -export {}; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/cyclic_types/greetservice.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/cyclic_types/greetservice.js deleted file mode 100644 index 623e88035..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/cyclic_types/greetservice.js +++ /dev/null @@ -1,24 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * Make a cycle. - * @returns {$CancellablePromise<[$models.Cyclic, $models.GenericCyclic<$models.GenericCyclic>]>} - */ -export function MakeCycles() { - return $Call.ByName("main.GreetService.MakeCycles"); -} diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/cyclic_types/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/cyclic_types/index.js deleted file mode 100644 index 9fc31bf7c..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/cyclic_types/index.js +++ /dev/null @@ -1,23 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; - -import * as $models from "./models.js"; - -/** - * @typedef {$models.Alias} Alias - */ - -/** - * @typedef {$models.Cyclic} Cyclic - */ - -/** - * @template T - * @typedef {$models.GenericCyclic} GenericCyclic - */ diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/cyclic_types/models.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/cyclic_types/models.js deleted file mode 100644 index 45780d15c..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/cyclic_types/models.js +++ /dev/null @@ -1,20 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * @typedef {Cyclic | null} Alias - */ - -/** - * @typedef {({ [_ in string]?: Alias } | null)[] | null} Cyclic - */ - -/** - * @template T - * @typedef {{"X": GenericCyclic | null, "Y": T[] | null}[] | null} GenericCyclic - */ - -// In interface mode, this file is likely to contain just comments. -// We add a dummy export statement to ensure it is recognised as an ES module. -export {}; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/index.js deleted file mode 100644 index 40d68bf85..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/index.js +++ /dev/null @@ -1,14 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as Service from "./service.js"; -export { - Service -}; - -console.log("Hello everywhere!"); -console.log("Hello everywhere again!"); -console.log("Hello Interfaces!"); -console.log("Hello JS!"); -console.log("Hello JS Interfaces!"); diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/internalservice.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/internalservice.js deleted file mode 100644 index 374d13203..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/internalservice.js +++ /dev/null @@ -1,24 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * An exported but internal service. - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * @param {$models.InternalModel} $0 - * @returns {$CancellablePromise} - */ -export function Method($0) { - return $Call.ByName("main.InternalService.Method", $0); -} diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/models.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/models.js deleted file mode 100644 index a4c233c8c..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/models.js +++ /dev/null @@ -1,19 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * An exported but internal model. - * @typedef {Object} InternalModel - * @property {string} Field - */ - -/** - * An unexported model. - * @typedef {Object} unexportedModel - * @property {string} Field - */ - -// In interface mode, this file is likely to contain just comments. -// We add a dummy export statement to ensure it is recognised as an ES module. -export {}; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/otherpackage/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/otherpackage/index.js deleted file mode 100644 index c93da8f05..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/otherpackage/index.js +++ /dev/null @@ -1,9 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as $models from "./models.js"; - -/** - * @typedef {$models.Dummy} Dummy - */ diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/otherpackage/models.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/otherpackage/models.js deleted file mode 100644 index 6b6f5401f..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/otherpackage/models.js +++ /dev/null @@ -1,12 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * @typedef { { - * } } Dummy - */ - -// In interface mode, this file is likely to contain just comments. -// We add a dummy export statement to ensure it is recognised as an ES module. -export {}; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/service.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/service.js deleted file mode 100644 index 8332051eb..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/service.js +++ /dev/null @@ -1,35 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as otherpackage$0 from "./otherpackage/models.js"; - -/** - * @param {string} $0 - * @returns {$CancellablePromise} - */ -function InternalMethod($0) { - return $Call.ByName("main.Service.InternalMethod", $0); -} - -/** - * @param {otherpackage$0.Dummy} $0 - * @returns {$CancellablePromise} - */ -export function VisibleMethod($0) { - return $Call.ByName("main.Service.VisibleMethod", $0); -} - -/** - * @param {string} arg - * @returns {Promise} - */ -export async function CustomMethod(arg) { - await InternalMethod("Hello " + arg + "!"); -} diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/test.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/test.js deleted file mode 100644 index 138385f53..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/test.js +++ /dev/null @@ -1,3 +0,0 @@ -import { CustomMethod } from "./service.js"; - -CustomMethod("everywhere"); diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/test_all.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/test_all.js deleted file mode 100644 index 19d5c2f42..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/test_all.js +++ /dev/null @@ -1,3 +0,0 @@ -import { CustomMethod } from "./service.js"; - -CustomMethod("everywhere again"); diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/test_i.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/test_i.js deleted file mode 100644 index 442f20472..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/test_i.js +++ /dev/null @@ -1,3 +0,0 @@ -import { CustomMethod } from "./service.js"; - -CustomMethod("Interfaces"); diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/test_j.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/test_j.js deleted file mode 100644 index b2f9c5edb..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/test_j.js +++ /dev/null @@ -1,3 +0,0 @@ -import { CustomMethod } from "./service.js"; - -CustomMethod("JS"); diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/test_ji.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/test_ji.js deleted file mode 100644 index 36e28f09b..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/test_ji.js +++ /dev/null @@ -1,3 +0,0 @@ -import { CustomMethod } from "./service.js"; - -CustomMethod("JS Interfaces"); diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/unexportedservice.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/unexportedservice.js deleted file mode 100644 index 1fe8a0f69..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/unexportedservice.js +++ /dev/null @@ -1,24 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * An unexported service. - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * @param {$models.unexportedModel} $0 - * @returns {$CancellablePromise} - */ -export function Method($0) { - return $Call.ByName("main.unexportedService.Method", $0); -} diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/embedded_interface/greetservice.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/embedded_interface/greetservice.js deleted file mode 100644 index 3d245f10c..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/embedded_interface/greetservice.js +++ /dev/null @@ -1,53 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -/** - * Comment 1. - * @returns {$CancellablePromise} - */ -export function Method1() { - return $Call.ByName("main.GreetService.Method1"); -} - -/** - * Comment 2. - * @returns {$CancellablePromise} - */ -export function Method2() { - return $Call.ByName("main.GreetService.Method2"); -} - -/** - * Comment 3a. - * Comment 3b. - * @returns {$CancellablePromise} - */ -export function Method3() { - return $Call.ByName("main.GreetService.Method3"); -} - -/** - * Comment 4. - * @returns {$CancellablePromise} - */ -export function Method4() { - return $Call.ByName("main.GreetService.Method4"); -} - -/** - * Comment 5. - * @returns {$CancellablePromise} - */ -export function Method5() { - return $Call.ByName("main.GreetService.Method5"); -} diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/embedded_interface/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/embedded_interface/index.js deleted file mode 100644 index fdf1ff435..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/embedded_interface/index.js +++ /dev/null @@ -1,8 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/enum/greetservice.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/enum/greetservice.js deleted file mode 100644 index fa5b9a262..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/enum/greetservice.js +++ /dev/null @@ -1,35 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * Greet does XYZ - * @param {string} name - * @param {$models.Title} title - * @returns {$CancellablePromise} - */ -export function Greet(name, title) { - return $Call.ByName("main.GreetService.Greet", name, title); -} - -/** - * NewPerson creates a new person - * @param {string} name - * @returns {$CancellablePromise<$models.Person | null>} - */ -export function NewPerson(name) { - return $Call.ByName("main.GreetService.NewPerson", name); -} diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/enum/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/enum/index.js deleted file mode 100644 index 649d8d016..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/enum/index.js +++ /dev/null @@ -1,20 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; - -export { - Age, - Title -} from "./models.js"; - -import * as $models from "./models.js"; - -/** - * Person represents a person - * @typedef {$models.Person} Person - */ diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/enum/models.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/enum/models.js deleted file mode 100644 index e7c70729c..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/enum/models.js +++ /dev/null @@ -1,61 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * Age is an integer with some predefined values - * @typedef {number} Age - */ - -/** - * Predefined constants for type Age. - * @namespace - */ -export const Age = { - NewBorn: 0, - Teenager: 12, - YoungAdult: 18, - - /** - * Oh no, some grey hair! - */ - MiddleAged: 50, - - /** - * Unbelievable! - */ - Mathusalem: 1000, -}; - -/** - * Person represents a person - * @typedef {Object} Person - * @property {Title} Title - * @property {string} Name - * @property {Age} Age - */ - -/** - * Title is a title - * @readonly - * @enum {string} - */ -export const Title = { - /** - * The Go zero value for the underlying type of the enum. - */ - $zero: "", - - /** - * Mister is a title - */ - Mister: "Mr", - Miss: "Miss", - Ms: "Ms", - Mrs: "Mrs", - Dr: "Dr", -}; - -// In interface mode, this file is likely to contain just comments. -// We add a dummy export statement to ensure it is recognised as an ES module. -export {}; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_from_imported_package/greetservice.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_from_imported_package/greetservice.js deleted file mode 100644 index 2f953de7c..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_from_imported_package/greetservice.js +++ /dev/null @@ -1,26 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as services$0 from "./services/models.js"; - -/** - * Greet does XYZ - * @param {string} name - * @param {services$0.Title} title - * @returns {$CancellablePromise} - */ -export function Greet(name, title) { - return $Call.ByName("main.GreetService.Greet", name, title); -} diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_from_imported_package/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_from_imported_package/index.js deleted file mode 100644 index fdf1ff435..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_from_imported_package/index.js +++ /dev/null @@ -1,8 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_from_imported_package/services/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_from_imported_package/services/index.js deleted file mode 100644 index 089a8b685..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_from_imported_package/services/index.js +++ /dev/null @@ -1,7 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -export { - Title -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_from_imported_package/services/models.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_from_imported_package/services/models.js deleted file mode 100644 index e0e2d3014..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_from_imported_package/services/models.js +++ /dev/null @@ -1,27 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * @readonly - * @enum {string} - */ -export const Title = { - /** - * The Go zero value for the underlying type of the enum. - */ - $zero: "", - - /** - * Mister is a title - */ - Mister: "Mr", - Miss: "Miss", - Ms: "Ms", - Mrs: "Mrs", - Dr: "Dr", -}; - -// In interface mode, this file is likely to contain just comments. -// We add a dummy export statement to ensure it is recognised as an ES module. -export {}; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_map_keys/enummapservice.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_map_keys/enummapservice.js deleted file mode 100644 index a2f4e9651..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_map_keys/enummapservice.js +++ /dev/null @@ -1,64 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * EnumMapService tests various enum map key scenarios - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * GetColorCodes returns a map with uint8 enum keys - * @returns {$CancellablePromise<{ [_ in $models.Color]?: string } | null>} - */ -export function GetColorCodes() { - return $Call.ByName("main.EnumMapService.GetColorCodes"); -} - -/** - * GetNestedEnumMap returns a map with enum keys and complex values - * @returns {$CancellablePromise<{ [_ in $models.Status]?: { [_ in $models.Priority]?: string } | null } | null>} - */ -export function GetNestedEnumMap() { - return $Call.ByName("main.EnumMapService.GetNestedEnumMap"); -} - -/** - * GetOptionalEnumMap returns a map with enum keys to optional values - * @returns {$CancellablePromise<{ [_ in $models.Status]?: string | null } | null>} - */ -export function GetOptionalEnumMap() { - return $Call.ByName("main.EnumMapService.GetOptionalEnumMap"); -} - -/** - * GetPersonsByStatus returns a map with enum keys to struct values - * @returns {$CancellablePromise<{ [_ in $models.Status]?: $models.Person[] | null } | null>} - */ -export function GetPersonsByStatus() { - return $Call.ByName("main.EnumMapService.GetPersonsByStatus"); -} - -/** - * GetPriorityWeights returns a map with integer enum keys - * @returns {$CancellablePromise<{ [_ in $models.Priority]?: number } | null>} - */ -export function GetPriorityWeights() { - return $Call.ByName("main.EnumMapService.GetPriorityWeights"); -} - -/** - * GetStatusMessages returns a map with string enum keys - * @returns {$CancellablePromise<{ [_ in $models.Status]?: string } | null>} - */ -export function GetStatusMessages() { - return $Call.ByName("main.EnumMapService.GetStatusMessages"); -} diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_map_keys/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_map_keys/index.js deleted file mode 100644 index 4d0ba0f49..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_map_keys/index.js +++ /dev/null @@ -1,21 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as EnumMapService from "./enummapservice.js"; -export { - EnumMapService -}; - -export { - Color, - Priority, - Status -} from "./models.js"; - -import * as $models from "./models.js"; - -/** - * Person represents a person with status - * @typedef {$models.Person} Person - */ diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_map_keys/models.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_map_keys/models.js deleted file mode 100644 index 9658a39a8..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_map_keys/models.js +++ /dev/null @@ -1,63 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * Color represents color values - * @readonly - * @enum {number} - */ -export const Color = { - /** - * The Go zero value for the underlying type of the enum. - */ - $zero: 0, - - Red: 1, - Green: 2, - Blue: 3, -}; - -/** - * Person represents a person with status - * @typedef {Object} Person - * @property {string} Name - * @property {Status} Status - */ - -/** - * Priority represents priority levels - * @readonly - * @enum {number} - */ -export const Priority = { - /** - * The Go zero value for the underlying type of the enum. - */ - $zero: 0, - - PriorityLow: 1, - PriorityMedium: 2, - PriorityHigh: 3, -}; - -/** - * Status represents different status values - * @readonly - * @enum {string} - */ -export const Status = { - /** - * The Go zero value for the underlying type of the enum. - */ - $zero: "", - - StatusPending: "pending", - StatusRunning: "running", - StatusCompleted: "completed", - StatusFailed: "failed", -}; - -// In interface mode, this file is likely to contain just comments. -// We add a dummy export statement to ensure it is recognised as an ES module. -export {}; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/events_only/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/events_only/index.js deleted file mode 100644 index 14b4d5da8..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/events_only/index.js +++ /dev/null @@ -1,10 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as $models from "./models.js"; - -/** - * SomeClass renders as a TS class. - * @typedef {$models.SomeClass} SomeClass - */ diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/events_only/models.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/events_only/models.js deleted file mode 100644 index b99dbf18d..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/events_only/models.js +++ /dev/null @@ -1,18 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as nobindingshere$0 from "../no_bindings_here/models.js"; - -/** - * SomeClass renders as a TS class. - * @typedef {Object} SomeClass - * @property {string} Field - * @property {nobindingshere$0.HowDifferent} Meadow - */ - -// In interface mode, this file is likely to contain just comments. -// We add a dummy export statement to ensure it is recognised as an ES module. -export {}; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_imported_package/greetservice.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_imported_package/greetservice.js deleted file mode 100644 index 8ab5f3462..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_imported_package/greetservice.js +++ /dev/null @@ -1,34 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * Greet does XYZ - * @param {string} name - * @returns {$CancellablePromise} - */ -export function Greet(name) { - return $Call.ByName("main.GreetService.Greet", name); -} - -/** - * NewPerson creates a new person - * @param {string} name - * @returns {$CancellablePromise<$models.Person | null>} - */ -export function NewPerson(name) { - return $Call.ByName("main.GreetService.NewPerson", name); -} diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_imported_package/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_imported_package/index.js deleted file mode 100644 index 26922b7eb..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_imported_package/index.js +++ /dev/null @@ -1,15 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; - -import * as $models from "./models.js"; - -/** - * Person is a person - * @typedef {$models.Person} Person - */ diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_imported_package/models.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_imported_package/models.js deleted file mode 100644 index 5743a9055..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_imported_package/models.js +++ /dev/null @@ -1,18 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as services$0 from "./services/models.js"; - -/** - * Person is a person - * @typedef {Object} Person - * @property {string} Name - * @property {services$0.Address | null} Address - */ - -// In interface mode, this file is likely to contain just comments. -// We add a dummy export statement to ensure it is recognised as an ES module. -export {}; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_imported_package/services/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_imported_package/services/index.js deleted file mode 100644 index 588ef7ca7..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_imported_package/services/index.js +++ /dev/null @@ -1,14 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as OtherService from "./otherservice.js"; -export { - OtherService -}; - -import * as $models from "./models.js"; - -/** - * @typedef {$models.Address} Address - */ diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_imported_package/services/models.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_imported_package/services/models.js deleted file mode 100644 index c04e3b10b..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_imported_package/services/models.js +++ /dev/null @@ -1,14 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * @typedef {Object} Address - * @property {string} Street - * @property {string} State - * @property {string} Country - */ - -// In interface mode, this file is likely to contain just comments. -// We add a dummy export statement to ensure it is recognised as an ES module. -export {}; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_imported_package/services/otherservice.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_imported_package/services/otherservice.js deleted file mode 100644 index a27b0fea8..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_imported_package/services/otherservice.js +++ /dev/null @@ -1,25 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * OtherService is a struct - * that does things - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * Yay does this and that - * @returns {$CancellablePromise<$models.Address | null>} - */ -export function Yay() { - return $Call.ByName("github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_imported_package/services.OtherService.Yay"); -} diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_nested_imported_package/greetservice.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_nested_imported_package/greetservice.js deleted file mode 100644 index 8ab5f3462..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_nested_imported_package/greetservice.js +++ /dev/null @@ -1,34 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * Greet does XYZ - * @param {string} name - * @returns {$CancellablePromise} - */ -export function Greet(name) { - return $Call.ByName("main.GreetService.Greet", name); -} - -/** - * NewPerson creates a new person - * @param {string} name - * @returns {$CancellablePromise<$models.Person | null>} - */ -export function NewPerson(name) { - return $Call.ByName("main.GreetService.NewPerson", name); -} diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_nested_imported_package/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_nested_imported_package/index.js deleted file mode 100644 index cb2979a7a..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_nested_imported_package/index.js +++ /dev/null @@ -1,14 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; - -import * as $models from "./models.js"; - -/** - * @typedef {$models.Person} Person - */ diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_nested_imported_package/models.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_nested_imported_package/models.js deleted file mode 100644 index 8a9890617..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_nested_imported_package/models.js +++ /dev/null @@ -1,17 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as other$0 from "./services/other/models.js"; - -/** - * @typedef {Object} Person - * @property {string} Name - * @property {other$0.Address | null} Address - */ - -// In interface mode, this file is likely to contain just comments. -// We add a dummy export statement to ensure it is recognised as an ES module. -export {}; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_nested_imported_package/services/other/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_nested_imported_package/services/other/index.js deleted file mode 100644 index 588ef7ca7..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_nested_imported_package/services/other/index.js +++ /dev/null @@ -1,14 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as OtherService from "./otherservice.js"; -export { - OtherService -}; - -import * as $models from "./models.js"; - -/** - * @typedef {$models.Address} Address - */ diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_nested_imported_package/services/other/models.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_nested_imported_package/services/other/models.js deleted file mode 100644 index c04e3b10b..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_nested_imported_package/services/other/models.js +++ /dev/null @@ -1,14 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * @typedef {Object} Address - * @property {string} Street - * @property {string} State - * @property {string} Country - */ - -// In interface mode, this file is likely to contain just comments. -// We add a dummy export statement to ensure it is recognised as an ES module. -export {}; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_nested_imported_package/services/other/otherservice.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_nested_imported_package/services/other/otherservice.js deleted file mode 100644 index 98097e64f..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_nested_imported_package/services/other/otherservice.js +++ /dev/null @@ -1,25 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * OtherService is a struct - * that does things - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * Yay does this and that - * @returns {$CancellablePromise<$models.Address | null>} - */ -export function Yay() { - return $Call.ByName("github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_nested_imported_package/services/other.OtherService.Yay"); -} diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_multiple_files/greetservice.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_multiple_files/greetservice.js deleted file mode 100644 index e2ba84581..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_multiple_files/greetservice.js +++ /dev/null @@ -1,15 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -/** - * @param {string} name - * @returns {$CancellablePromise} - */ -export function Greet(name) { - return $Call.ByName("main.GreetService.Greet", name); -} diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_multiple_files/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_multiple_files/index.js deleted file mode 100644 index fdf1ff435..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_multiple_files/index.js +++ /dev/null @@ -1,8 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single/greetservice.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single/greetservice.js deleted file mode 100644 index bba7ea7ea..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single/greetservice.js +++ /dev/null @@ -1,21 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -/** - * Greet someone - * @param {string} name - * @returns {$CancellablePromise} - */ -export function Greet(name) { - return $Call.ByName("main.GreetService.Greet", name); -} diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single/index.js deleted file mode 100644 index fdf1ff435..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single/index.js +++ /dev/null @@ -1,8 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single_context/greetservice.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single_context/greetservice.js deleted file mode 100644 index f89bfc417..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single_context/greetservice.js +++ /dev/null @@ -1,30 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -/** - * Greet someone - * @param {string} name - * @returns {$CancellablePromise} - */ -export function Greet(name) { - return $Call.ByName("main.GreetService.Greet", name); -} - -/** - * Greet someone - * @param {string} name - * @returns {$CancellablePromise} - */ -export function GreetWithContext(name) { - return $Call.ByName("main.GreetService.GreetWithContext", name); -} diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single_context/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single_context/index.js deleted file mode 100644 index fdf1ff435..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single_context/index.js +++ /dev/null @@ -1,8 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single_internal/greetservice.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single_internal/greetservice.js deleted file mode 100644 index bba7ea7ea..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single_internal/greetservice.js +++ /dev/null @@ -1,21 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -/** - * Greet someone - * @param {string} name - * @returns {$CancellablePromise} - */ -export function Greet(name) { - return $Call.ByName("main.GreetService.Greet", name); -} diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single_internal/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single_internal/index.js deleted file mode 100644 index fdf1ff435..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single_internal/index.js +++ /dev/null @@ -1,8 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys/index.js deleted file mode 100644 index a92a0cb10..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys/index.js +++ /dev/null @@ -1,106 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as Service from "./service.js"; -export { - Service -}; - -import * as $models from "./models.js"; - -/** - * @template S - * @typedef {$models.BasicCstrAlias} BasicCstrAlias - */ - -/** - * @template R - * @typedef {$models.ComparableCstrAlias} ComparableCstrAlias - */ - -/** - * @typedef {$models.EmbeddedCustomInterface} EmbeddedCustomInterface - */ - -/** - * @typedef {$models.EmbeddedOriginalInterface} EmbeddedOriginalInterface - */ - -/** - * @typedef {$models.EmbeddedPointer} EmbeddedPointer - */ - -/** - * @typedef {$models.EmbeddedPointerPtr} EmbeddedPointerPtr - */ - -/** - * @typedef {$models.EmbeddedValue} EmbeddedValue - */ - -/** - * @typedef {$models.EmbeddedValuePtr} EmbeddedValuePtr - */ - -/** - * @template U - * @typedef {$models.GoodTildeCstrAlias} GoodTildeCstrAlias - */ - -/** - * @typedef {$models.IntAlias} IntAlias - */ - -/** - * @typedef {$models.IntType} IntType - */ - -/** - * @template Y - * @typedef {$models.InterfaceCstrAlias} InterfaceCstrAlias - */ - -/** - * @template R,S,T,U,V,W,X,Y,Z - * @typedef {$models.Maps} Maps - */ - -/** - * @template X - * @typedef {$models.MixedCstrAlias} MixedCstrAlias - */ - -/** - * @template V - * @typedef {$models.NonBasicCstrAlias} NonBasicCstrAlias - */ - -/** - * @template W - * @typedef {$models.PointableCstrAlias} PointableCstrAlias - */ - -/** - * @typedef {$models.PointerAlias} PointerAlias - */ - -/** - * @typedef {$models.PointerTextMarshaler} PointerTextMarshaler - */ - -/** - * @typedef {$models.StringAlias} StringAlias - */ - -/** - * @typedef {$models.StringType} StringType - */ - -/** - * @typedef {$models.ValueAlias} ValueAlias - */ - -/** - * @typedef {$models.ValueTextMarshaler} ValueTextMarshaler - */ diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys/models.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys/models.js deleted file mode 100644 index 371763800..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys/models.js +++ /dev/null @@ -1,248 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * @template S - * @typedef {S} BasicCstrAlias - */ - -/** - * @template R - * @typedef {R} ComparableCstrAlias - */ - -/** - * @typedef {string} EmbeddedCustomInterface - */ - -/** - * @typedef {string} EmbeddedOriginalInterface - */ - -/** - * @typedef {string} EmbeddedPointer - */ - -/** - * @typedef {string} EmbeddedPointerPtr - */ - -/** - * @typedef {string} EmbeddedValue - */ - -/** - * @typedef {string} EmbeddedValuePtr - */ - -/** - * @template U - * @typedef {U} GoodTildeCstrAlias - */ - -/** - * @typedef {number} IntAlias - */ - -/** - * @typedef {number} IntType - */ - -/** - * @template Y - * @typedef {Y} InterfaceCstrAlias - */ - -/** - * @template R,S,T,U,V,W,X,Y,Z - * @typedef {Object} Maps - * @property {{ [_ in string]?: number } | null} Bool - Reject - * @property {{ [_ in `${number}`]?: number } | null} Int - Accept - * @property {{ [_ in `${number}`]?: number } | null} Uint - Accept - * @property {{ [_ in string]?: number } | null} Float - Reject - * @property {{ [_ in string]?: number } | null} Complex - Reject - * @property {{ [_ in `${number}`]?: number } | null} Byte - Accept - * @property {{ [_ in `${number}`]?: number } | null} Rune - Accept - * @property {{ [_ in string]?: number } | null} String - Accept - * @property {{ [_ in string]?: number } | null} IntPtr - Reject - * @property {{ [_ in string]?: number } | null} UintPtr - Reject - * @property {{ [_ in string]?: number } | null} FloatPtr - Reject - * @property {{ [_ in string]?: number } | null} ComplexPtr - Reject - * @property {{ [_ in string]?: number } | null} StringPtr - Reject - * @property {{ [_ in string]?: number } | null} NTM - Reject - * @property {{ [_ in string]?: number } | null} NTMPtr - Reject - * @property {{ [_ in ValueTextMarshaler]?: number } | null} VTM - Accept - * @property {{ [_ in ValueTextMarshaler]?: number } | null} VTMPtr - Accept - * @property {{ [_ in string]?: number } | null} PTM - Reject - * @property {{ [_ in PointerTextMarshaler]?: number } | null} PTMPtr - Accept - * @property {{ [_ in string]?: number } | null} JTM - Accept, hide - * @property {{ [_ in string]?: number } | null} JTMPtr - Accept, hide - * @property {{ [_ in string]?: number } | null} A - Reject - * @property {{ [_ in string]?: number } | null} APtr - Reject - * @property {{ [_ in string]?: number } | null} TM - Accept, hide - * @property {{ [_ in string]?: number } | null} TMPtr - Reject - * @property {{ [_ in string]?: number } | null} CI - Accept, hide - * @property {{ [_ in string]?: number } | null} CIPtr - Reject - * @property {{ [_ in string]?: number } | null} EI - Accept, hide - * @property {{ [_ in string]?: number } | null} EIPtr - Reject - * @property {{ [_ in EmbeddedValue]?: number } | null} EV - Accept - * @property {{ [_ in EmbeddedValue]?: number } | null} EVPtr - Accept - * @property {{ [_ in EmbeddedValuePtr]?: number } | null} EVP - Accept - * @property {{ [_ in EmbeddedValuePtr]?: number } | null} EVPPtr - Accept - * @property {{ [_ in string]?: number } | null} EP - Reject - * @property {{ [_ in EmbeddedPointer]?: number } | null} EPPtr - Accept - * @property {{ [_ in EmbeddedPointerPtr]?: number } | null} EPP - Accept - * @property {{ [_ in EmbeddedPointerPtr]?: number } | null} EPPPtr - Accept - * @property {{ [_ in EmbeddedCustomInterface]?: number } | null} ECI - Accept - * @property {{ [_ in EmbeddedCustomInterface]?: number } | null} ECIPtr - Accept - * @property {{ [_ in EmbeddedOriginalInterface]?: number } | null} EOI - Accept - * @property {{ [_ in EmbeddedOriginalInterface]?: number } | null} EOIPtr - Accept - * @property {{ [_ in string]?: number } | null} WT - Reject - * @property {{ [_ in string]?: number } | null} WA - Reject - * @property {{ [_ in StringType]?: number } | null} ST - Accept - * @property {{ [_ in StringAlias]?: number } | null} SA - Accept - * @property {{ [_ in IntType]?: number } | null} IntT - Accept - * @property {{ [_ in IntAlias]?: number } | null} IntA - Accept - * @property {{ [_ in string]?: number } | null} VT - Reject - * @property {{ [_ in string]?: number } | null} VTPtr - Reject - * @property {{ [_ in string]?: number } | null} VPT - Reject - * @property {{ [_ in string]?: number } | null} VPTPtr - Reject - * @property {{ [_ in ValueAlias]?: number } | null} VA - Accept - * @property {{ [_ in ValueAlias]?: number } | null} VAPtr - Accept - * @property {{ [_ in string]?: number } | null} VPA - Accept, hide - * @property {{ [_ in string]?: number } | null} VPAPtr - Reject - * @property {{ [_ in string]?: number } | null} PT - Reject - * @property {{ [_ in string]?: number } | null} PTPtr - Reject - * @property {{ [_ in string]?: number } | null} PPT - Reject - * @property {{ [_ in string]?: number } | null} PPTPtr - Reject - * @property {{ [_ in string]?: number } | null} PA - Reject - * @property {{ [_ in PointerAlias]?: number } | null} PAPtr - Accept - * @property {{ [_ in string]?: number } | null} PPA - Accept, hide - * @property {{ [_ in string]?: number } | null} PPAPtr - Reject - * @property {{ [_ in string]?: number } | null} IT - Accept, hide - * @property {{ [_ in string]?: number } | null} ITPtr - Reject - * @property {{ [_ in string]?: number } | null} IPT - Reject - * @property {{ [_ in string]?: number } | null} IPTPtr - Reject - * @property {{ [_ in string]?: number } | null} IA - Accept, hide - * @property {{ [_ in string]?: number } | null} IAPtr - Reject - * @property {{ [_ in string]?: number } | null} IPA - Reject - * @property {{ [_ in string]?: number } | null} IPAPtr - Reject - * @property {{ [_ in string]?: number } | null} TPR - Soft reject - * @property {{ [_ in string]?: number } | null} TPRPtr - Soft reject - * @property {{ [_ in string]?: number } | null} TPS - Accept, hide - * @property {{ [_ in string]?: number } | null} TPSPtr - Soft reject - * @property {{ [_ in string]?: number } | null} TPT - Soft reject - * @property {{ [_ in string]?: number } | null} TPTPtr - Soft reject - * @property {{ [_ in string]?: number } | null} TPU - Accept, hide - * @property {{ [_ in string]?: number } | null} TPUPtr - Soft reject - * @property {{ [_ in string]?: number } | null} TPV - Accept, hide - * @property {{ [_ in string]?: number } | null} TPVPtr - Soft reject - * @property {{ [_ in string]?: number } | null} TPW - Soft reject - * @property {{ [_ in string]?: number } | null} TPWPtr - Accept, hide - * @property {{ [_ in string]?: number } | null} TPX - Accept, hide - * @property {{ [_ in string]?: number } | null} TPXPtr - Soft reject - * @property {{ [_ in string]?: number } | null} TPY - Accept, hide - * @property {{ [_ in string]?: number } | null} TPYPtr - Soft reject - * @property {{ [_ in string]?: number } | null} TPZ - Accept, hide - * @property {{ [_ in string]?: number } | null} TPZPtr - Soft reject - * @property {{ [_ in string]?: number } | null} GAR - Soft reject - * @property {{ [_ in string]?: number } | null} GARPtr - Soft reject - * @property {{ [_ in string]?: number } | null} GAS - Accept, hide - * @property {{ [_ in string]?: number } | null} GASPtr - Soft reject - * @property {{ [_ in string]?: number } | null} GAT - Soft reject - * @property {{ [_ in string]?: number } | null} GATPtr - Soft reject - * @property {{ [_ in string]?: number } | null} GAU - Accept, hide - * @property {{ [_ in string]?: number } | null} GAUPtr - Soft reject - * @property {{ [_ in string]?: number } | null} GAV - Accept, hide - * @property {{ [_ in string]?: number } | null} GAVPtr - Soft reject - * @property {{ [_ in string]?: number } | null} GAW - Soft reject - * @property {{ [_ in string]?: number } | null} GAWPtr - Accept, hide - * @property {{ [_ in string]?: number } | null} GAX - Accept, hide - * @property {{ [_ in string]?: number } | null} GAXPtr - Soft reject - * @property {{ [_ in string]?: number } | null} GAY - Accept, hide - * @property {{ [_ in string]?: number } | null} GAYPtr - Soft reject - * @property {{ [_ in string]?: number } | null} GAZ - Accept, hide - * @property {{ [_ in string]?: number } | null} GAZPtr - Soft reject - * @property {{ [_ in ComparableCstrAlias]?: number } | null} GACi - Accept - * @property {{ [_ in ComparableCstrAlias]?: number } | null} GACV - Accept - * @property {{ [_ in string]?: number } | null} GACP - Reject - * @property {{ [_ in string]?: number } | null} GACiPtr - Reject - * @property {{ [_ in string]?: number } | null} GACVPtr - Accept, hide - * @property {{ [_ in string]?: number } | null} GACPPtr - Accept, hide - * @property {{ [_ in BasicCstrAlias]?: number } | null} GABi - Accept - * @property {{ [_ in BasicCstrAlias]?: number } | null} GABs - Accept - * @property {{ [_ in string]?: number } | null} GABiPtr - Reject - * @property {{ [_ in string]?: number } | null} GABT - Reject - * @property {{ [_ in string]?: number } | null} GABTPtr - Reject - * @property {{ [_ in GoodTildeCstrAlias]?: number } | null} GAGT - Accept - * @property {{ [_ in string]?: number } | null} GAGTPtr - Accept, hide - * @property {{ [_ in NonBasicCstrAlias]?: number } | null} GANBV - Accept - * @property {{ [_ in string]?: number } | null} GANBP - Accept, hide - * @property {{ [_ in string]?: number } | null} GANBVPtr - Accept, hide - * @property {{ [_ in string]?: number } | null} GANBPPtr - Reject - * @property {{ [_ in PointableCstrAlias]?: number } | null} GAPlV1 - Accept - * @property {{ [_ in PointableCstrAlias]?: number } | null} GAPlV2 - Accept - * @property {{ [_ in string]?: number } | null} GAPlP1 - Reject - * @property {{ [_ in PointableCstrAlias]?: number } | null} GAPlP2 - Accept - * @property {{ [_ in string]?: number } | null} GAPlVPtr - Accept, hide - * @property {{ [_ in string]?: number } | null} GAPlPPtr - Accept, hide - * @property {{ [_ in MixedCstrAlias]?: number } | null} GAMi - Accept - * @property {{ [_ in MixedCstrAlias]?: number } | null} GAMS - Accept - * @property {{ [_ in MixedCstrAlias]?: number } | null} GAMV - Accept - * @property {{ [_ in string]?: number } | null} GAMSPtr - Reject - * @property {{ [_ in string]?: number } | null} GAMVPtr - Accept, hide - * @property {{ [_ in string]?: number } | null} GAII - Accept, hide - * @property {{ [_ in InterfaceCstrAlias]?: number } | null} GAIV - Accept - * @property {{ [_ in string]?: number } | null} GAIP - Accept, hide - * @property {{ [_ in string]?: number } | null} GAIIPtr - Reject - * @property {{ [_ in string]?: number } | null} GAIVPtr - Accept, hide - * @property {{ [_ in string]?: number } | null} GAIPPtr - Reject - * @property {{ [_ in string]?: number } | null} GAPrV - Accept, hide - * @property {{ [_ in string]?: number } | null} GAPrP - Accept, hide - * @property {{ [_ in string]?: number } | null} GAPrVPtr - Reject - * @property {{ [_ in string]?: number } | null} GAPrPPtr - Reject - */ - -/** - * @template X - * @typedef {X} MixedCstrAlias - */ - -/** - * @template V - * @typedef {V} NonBasicCstrAlias - */ - -/** - * @template W - * @typedef {W} PointableCstrAlias - */ - -/** - * @typedef {PointerTextMarshaler} PointerAlias - */ - -/** - * @typedef {string} PointerTextMarshaler - */ - -/** - * @typedef {string} StringAlias - */ - -/** - * @typedef {string} StringType - */ - -/** - * @typedef {ValueTextMarshaler} ValueAlias - */ - -/** - * @typedef {string} ValueTextMarshaler - */ - -// In interface mode, this file is likely to contain just comments. -// We add a dummy export statement to ensure it is recognised as an ES module. -export {}; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys/service.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys/service.js deleted file mode 100644 index e207d968c..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys/service.js +++ /dev/null @@ -1,18 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * @returns {$CancellablePromise<$models.Maps<$models.PointerTextMarshaler, number, number, $models.ValueTextMarshaler, $models.PointerTextMarshaler | null, $models.ValueTextMarshaler, $models.StringType, $models.ValueTextMarshaler, $models.PointerTextMarshaler | null>>} - */ -export function Method() { - return $Call.ByName("main.Service.Method"); -} diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/marshalers/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/marshalers/index.js deleted file mode 100644 index 0f2edd9c7..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/marshalers/index.js +++ /dev/null @@ -1,124 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as Service from "./service.js"; -export { - Service -}; - -import * as $models from "./models.js"; - -/** - * any - * @typedef {$models.AliasJsonMarshaler} AliasJsonMarshaler - */ - -/** - * any - * @typedef {$models.AliasMarshaler} AliasMarshaler - */ - -/** - * struct{} - * @typedef {$models.AliasNonMarshaler} AliasNonMarshaler - */ - -/** - * string - * @typedef {$models.AliasTextMarshaler} AliasTextMarshaler - */ - -/** - * @typedef {$models.Data} Data - */ - -/** - * any - * @typedef {$models.ImplicitJsonButText} ImplicitJsonButText - */ - -/** - * any - * @typedef {$models.ImplicitJsonMarshaler} ImplicitJsonMarshaler - */ - -/** - * any - * @typedef {$models.ImplicitMarshaler} ImplicitMarshaler - */ - -/** - * string - * @typedef {$models.ImplicitNonJson} ImplicitNonJson - */ - -/** - * class{ Marshaler, TextMarshaler } - * @typedef {$models.ImplicitNonMarshaler} ImplicitNonMarshaler - */ - -/** - * any - * @typedef {$models.ImplicitNonText} ImplicitNonText - */ - -/** - * any - * @typedef {$models.ImplicitTextButJson} ImplicitTextButJson - */ - -/** - * string - * @typedef {$models.ImplicitTextMarshaler} ImplicitTextMarshaler - */ - -/** - * class {} - * @typedef {$models.NonMarshaler} NonMarshaler - */ - -/** - * any - * @typedef {$models.PointerJsonMarshaler} PointerJsonMarshaler - */ - -/** - * any - * @typedef {$models.PointerMarshaler} PointerMarshaler - */ - -/** - * string - * @typedef {$models.PointerTextMarshaler} PointerTextMarshaler - */ - -/** - * any - * @typedef {$models.UnderlyingJsonMarshaler} UnderlyingJsonMarshaler - */ - -/** - * any - * @typedef {$models.UnderlyingMarshaler} UnderlyingMarshaler - */ - -/** - * string - * @typedef {$models.UnderlyingTextMarshaler} UnderlyingTextMarshaler - */ - -/** - * any - * @typedef {$models.ValueJsonMarshaler} ValueJsonMarshaler - */ - -/** - * any - * @typedef {$models.ValueMarshaler} ValueMarshaler - */ - -/** - * string - * @typedef {$models.ValueTextMarshaler} ValueTextMarshaler - */ diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/marshalers/models.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/marshalers/models.js deleted file mode 100644 index a956da60f..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/marshalers/models.js +++ /dev/null @@ -1,186 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as encoding$0 from "../../../../../../../../encoding/models.js"; -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as json$0 from "../../../../../../../../encoding/json/models.js"; - -/** - * any - * @typedef {any} AliasJsonMarshaler - */ - -/** - * any - * @typedef {any} AliasMarshaler - */ - -/** - * struct{} - * @typedef { { - * } } AliasNonMarshaler - */ - -/** - * string - * @typedef {string} AliasTextMarshaler - */ - -/** - * @typedef {Object} Data - * @property {NonMarshaler} NM - * @property {NonMarshaler | null} NMPtr - NonMarshaler | null - * @property {ValueJsonMarshaler} VJM - * @property {ValueJsonMarshaler | null} VJMPtr - ValueJsonMarshaler | null - * @property {PointerJsonMarshaler} PJM - * @property {PointerJsonMarshaler | null} PJMPtr - PointerJsonMarshaler | null - * @property {ValueTextMarshaler} VTM - * @property {ValueTextMarshaler | null} VTMPtr - ValueTextMarshaler | null - * @property {PointerTextMarshaler} PTM - * @property {PointerTextMarshaler | null} PTMPtr - PointerTextMarshaler | null - * @property {ValueMarshaler} VM - * @property {ValueMarshaler | null} VMPtr - ValueMarshaler | null - * @property {PointerMarshaler} PM - * @property {PointerMarshaler | null} PMPtr - PointerMarshaler | null - * @property {UnderlyingJsonMarshaler} UJM - * @property {UnderlyingJsonMarshaler | null} UJMPtr - UnderlyingJsonMarshaler | null - * @property {UnderlyingTextMarshaler} UTM - * @property {UnderlyingTextMarshaler | null} UTMPtr - UnderlyingTextMarshaler | null - * @property {UnderlyingMarshaler} UM - * @property {UnderlyingMarshaler | null} UMPtr - UnderlyingMarshaler | null - * @property {any} JM - any - * @property {any | null} JMPtr - any | null - * @property {string} TM - string - * @property {string | null} TMPtr - string | null - * @property {any} CJM - any - * @property {any | null} CJMPtr - any | null - * @property {string} CTM - string - * @property {string | null} CTMPtr - string | null - * @property {any} CM - any - * @property {any | null} CMPtr - any | null - * @property {AliasNonMarshaler} ANM - * @property {AliasNonMarshaler | null} ANMPtr - AliasNonMarshaler | null - * @property {AliasJsonMarshaler} AJM - * @property {AliasJsonMarshaler | null} AJMPtr - AliasJsonMarshaler | null - * @property {AliasTextMarshaler} ATM - * @property {AliasTextMarshaler | null} ATMPtr - AliasTextMarshaler | null - * @property {AliasMarshaler} AM - * @property {AliasMarshaler | null} AMPtr - AliasMarshaler | null - * @property {ImplicitJsonMarshaler} ImJM - * @property {ImplicitJsonMarshaler | null} ImJMPtr - ImplicitJsonMarshaler | null - * @property {ImplicitTextMarshaler} ImTM - * @property {ImplicitTextMarshaler | null} ImTMPtr - ImplicitTextMarshaler | null - * @property {ImplicitMarshaler} ImM - * @property {ImplicitMarshaler | null} ImMPtr - ImplicitMarshaler | null - * @property {ImplicitNonJson} ImNJ - * @property {ImplicitNonJson | null} ImNJPtr - ImplicitNonJson | null - * @property {ImplicitNonText} ImNT - * @property {ImplicitNonText | null} ImNTPtr - ImplicitNonText | null - * @property {ImplicitNonMarshaler} ImNM - * @property {ImplicitNonMarshaler | null} ImNMPtr - ImplicitNonMarshaler | null - * @property {ImplicitJsonButText} ImJbT - * @property {ImplicitJsonButText | null} ImJbTPtr - ImplicitJsonButText | null - * @property {ImplicitTextButJson} ImTbJ - * @property {ImplicitTextButJson | null} ImTbJPtr - ImplicitTextButJson | null - */ - -/** - * any - * @typedef {any} ImplicitJsonButText - */ - -/** - * any - * @typedef {any} ImplicitJsonMarshaler - */ - -/** - * any - * @typedef {any} ImplicitMarshaler - */ - -/** - * string - * @typedef {string} ImplicitNonJson - */ - -/** - * class{ Marshaler, TextMarshaler } - * @typedef {Object} ImplicitNonMarshaler - * @property {json$0.Marshaler} Marshaler - * @property {encoding$0.TextMarshaler} TextMarshaler - */ - -/** - * any - * @typedef {any} ImplicitNonText - */ - -/** - * any - * @typedef {any} ImplicitTextButJson - */ - -/** - * string - * @typedef {string} ImplicitTextMarshaler - */ - -/** - * class {} - * @typedef { { - * } } NonMarshaler - */ - -/** - * any - * @typedef {any} PointerJsonMarshaler - */ - -/** - * any - * @typedef {any} PointerMarshaler - */ - -/** - * string - * @typedef {string} PointerTextMarshaler - */ - -/** - * any - * @typedef {any} UnderlyingJsonMarshaler - */ - -/** - * any - * @typedef {any} UnderlyingMarshaler - */ - -/** - * string - * @typedef {string} UnderlyingTextMarshaler - */ - -/** - * any - * @typedef {any} ValueJsonMarshaler - */ - -/** - * any - * @typedef {any} ValueMarshaler - */ - -/** - * string - * @typedef {string} ValueTextMarshaler - */ - -// In interface mode, this file is likely to contain just comments. -// We add a dummy export statement to ensure it is recognised as an ES module. -export {}; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/marshalers/service.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/marshalers/service.js deleted file mode 100644 index 9ad0c6d96..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/marshalers/service.js +++ /dev/null @@ -1,18 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * @returns {$CancellablePromise<$models.Data>} - */ -export function Method() { - return $Call.ByName("main.Service.Method"); -} diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/index.js deleted file mode 100644 index 0b7f42650..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/index.js +++ /dev/null @@ -1,32 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as SomeMethods from "./somemethods.js"; -export { - SomeMethods -}; - -import * as $models from "./models.js"; - -/** - * HowDifferent is a curious kind of person - * that lets other people decide how they are different. - * @template How - * @typedef {$models.HowDifferent} HowDifferent - */ - -/** - * Impersonator gets their fields from other people. - * @typedef {$models.Impersonator} Impersonator - */ - -/** - * Person is not a number. - * @typedef {$models.Person} Person - */ - -/** - * PrivatePerson gets their fields from hidden sources. - * @typedef {$models.PrivatePerson} PrivatePerson - */ diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/models.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/models.js deleted file mode 100644 index 93a37dc23..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/models.js +++ /dev/null @@ -1,44 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as other$0 from "./other/models.js"; - -/** - * HowDifferent is a curious kind of person - * that lets other people decide how they are different. - * @template How - * @typedef {Object} HowDifferent - * @property {string} Name - They have a name as well. - * @property {({ [_ in string]?: How } | null)[] | null} Differences - But they may have many differences. - */ - -/** - * Impersonator gets their fields from other people. - * @typedef {other$0.OtherPerson} Impersonator - */ - -/** - * Person is not a number. - * @typedef {Object} Person - * @property {string} Name - They have a name. - * @property {Impersonator[]} Friends - Exactly 4 sketchy friends. - */ - -/** - * PrivatePerson gets their fields from hidden sources. - * @typedef {personImpl} PrivatePerson - */ - -/** - * @typedef {Object} personImpl - * @property {string} Nickname - Nickname conceals a person's identity. - * @property {string} Name - They have a name. - * @property {Impersonator[]} Friends - Exactly 4 sketchy friends. - */ - -// In interface mode, this file is likely to contain just comments. -// We add a dummy export statement to ensure it is recognised as an ES module. -export {}; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/more/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/more/index.js deleted file mode 100644 index c3eabd022..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/more/index.js +++ /dev/null @@ -1,10 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as $models from "./models.js"; - -/** - * StringPtr is a nullable string. - * @typedef {$models.StringPtr} StringPtr - */ diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/more/models.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/more/models.js deleted file mode 100644 index 04f4d47dd..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/more/models.js +++ /dev/null @@ -1,12 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * StringPtr is a nullable string. - * @typedef {string | null} StringPtr - */ - -// In interface mode, this file is likely to contain just comments. -// We add a dummy export statement to ensure it is recognised as an ES module. -export {}; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/other/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/other/index.js deleted file mode 100644 index 33246d35e..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/other/index.js +++ /dev/null @@ -1,16 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as OtherMethods from "./othermethods.js"; -export { - OtherMethods -}; - -import * as $models from "./models.js"; - -/** - * OtherPerson is like a person, but different. - * @template T - * @typedef {$models.OtherPerson} OtherPerson - */ diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/other/models.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/other/models.js deleted file mode 100644 index 63a2ee722..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/other/models.js +++ /dev/null @@ -1,15 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * OtherPerson is like a person, but different. - * @template T - * @typedef {Object} OtherPerson - * @property {string} Name - They have a name as well. - * @property {T[] | null} Differences - But they may have many differences. - */ - -// In interface mode, this file is likely to contain just comments. -// We add a dummy export statement to ensure it is recognised as an ES module. -export {}; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/other/othermethods.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/other/othermethods.js deleted file mode 100644 index c3f8ff04b..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/other/othermethods.js +++ /dev/null @@ -1,20 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * OtherMethods has another method, but through a private embedded type. - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -/** - * LikeThisOtherOne does nothing as well, but is different. - * @returns {$CancellablePromise} - */ -export function LikeThisOtherOne() { - return $Call.ByName("github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/other.OtherMethods.LikeThisOtherOne"); -} diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/somemethods.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/somemethods.js deleted file mode 100644 index 92435f679..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/somemethods.js +++ /dev/null @@ -1,32 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * SomeMethods exports some methods. - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * LikeThisOne is an example method that does nothing. - * @returns {$CancellablePromise<[$models.Person, $models.HowDifferent, $models.PrivatePerson]>} - */ -export function LikeThisOne() { - return $Call.ByName("github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here.SomeMethods.LikeThisOne"); -} - -/** - * LikeThisOtherOne does nothing as well, but is different. - * @returns {$CancellablePromise} - */ -export function LikeThisOtherOne() { - return $Call.ByName("github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here.SomeMethods.LikeThisOtherOne"); -} diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/out_of_tree/embedother.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/out_of_tree/embedother.js deleted file mode 100644 index 490c12c08..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/out_of_tree/embedother.js +++ /dev/null @@ -1,20 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * EmbedOther is even trickier. - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -/** - * LikeThisOtherOne does nothing as well, but is different. - * @returns {$CancellablePromise} - */ -export function LikeThisOtherOne() { - return $Call.ByName("main.EmbedOther.LikeThisOtherOne"); -} diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/out_of_tree/embedservice.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/out_of_tree/embedservice.js deleted file mode 100644 index 5f940b2c7..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/out_of_tree/embedservice.js +++ /dev/null @@ -1,32 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * EmbedService is tricky. - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as nobindingshere$0 from "../no_bindings_here/models.js"; - -/** - * LikeThisOne is an example method that does nothing. - * @returns {$CancellablePromise<[nobindingshere$0.Person, nobindingshere$0.HowDifferent, nobindingshere$0.PrivatePerson]>} - */ -export function LikeThisOne() { - return $Call.ByName("main.EmbedService.LikeThisOne"); -} - -/** - * LikeThisOtherOne does nothing as well, but is different. - * @returns {$CancellablePromise} - */ -export function LikeThisOtherOne() { - return $Call.ByName("main.EmbedService.LikeThisOtherOne"); -} diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/out_of_tree/greetservice.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/out_of_tree/greetservice.js deleted file mode 100644 index f8c6b19b2..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/out_of_tree/greetservice.js +++ /dev/null @@ -1,21 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -/** - * Greet someone - * @param {string} $0 - * @returns {$CancellablePromise} - */ -export function Greet($0) { - return $Call.ByName("main.GreetService.Greet", $0); -} diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/out_of_tree/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/out_of_tree/index.js deleted file mode 100644 index 734fb02e7..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/out_of_tree/index.js +++ /dev/null @@ -1,12 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as EmbedOther from "./embedother.js"; -import * as EmbedService from "./embedservice.js"; -import * as GreetService from "./greetservice.js"; -export { - EmbedOther, - EmbedService, - GreetService -}; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple/greetservice.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple/greetservice.js deleted file mode 100644 index e2ba84581..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple/greetservice.js +++ /dev/null @@ -1,15 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -/** - * @param {string} name - * @returns {$CancellablePromise} - */ -export function Greet(name) { - return $Call.ByName("main.GreetService.Greet", name); -} diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple/index.js deleted file mode 100644 index 62ddbc166..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple/index.js +++ /dev/null @@ -1,10 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -import * as OtherService from "./otherservice.js"; -export { - GreetService, - OtherService -}; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple/otherservice.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple/otherservice.js deleted file mode 100644 index 2fdca31cc..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple/otherservice.js +++ /dev/null @@ -1,14 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -/** - * @returns {$CancellablePromise} - */ -export function Hello() { - return $Call.ByName("main.OtherService.Hello"); -} diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_files/greetservice.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_files/greetservice.js deleted file mode 100644 index e2ba84581..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_files/greetservice.js +++ /dev/null @@ -1,15 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -/** - * @param {string} name - * @returns {$CancellablePromise} - */ -export function Greet(name) { - return $Call.ByName("main.GreetService.Greet", name); -} diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_files/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_files/index.js deleted file mode 100644 index 62ddbc166..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_files/index.js +++ /dev/null @@ -1,10 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -import * as OtherService from "./otherservice.js"; -export { - GreetService, - OtherService -}; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_files/otherservice.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_files/otherservice.js deleted file mode 100644 index 2fdca31cc..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_files/otherservice.js +++ /dev/null @@ -1,14 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -/** - * @returns {$CancellablePromise} - */ -export function Hello() { - return $Call.ByName("main.OtherService.Hello"); -} diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_other/greetservice.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_other/greetservice.js deleted file mode 100644 index 8ab5f3462..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_other/greetservice.js +++ /dev/null @@ -1,34 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * Greet does XYZ - * @param {string} name - * @returns {$CancellablePromise} - */ -export function Greet(name) { - return $Call.ByName("main.GreetService.Greet", name); -} - -/** - * NewPerson creates a new person - * @param {string} name - * @returns {$CancellablePromise<$models.Person | null>} - */ -export function NewPerson(name) { - return $Call.ByName("main.GreetService.NewPerson", name); -} diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_other/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_other/index.js deleted file mode 100644 index cb2979a7a..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_other/index.js +++ /dev/null @@ -1,14 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; - -import * as $models from "./models.js"; - -/** - * @typedef {$models.Person} Person - */ diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_other/models.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_other/models.js deleted file mode 100644 index 41b452f57..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_other/models.js +++ /dev/null @@ -1,17 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as services$0 from "./services/models.js"; - -/** - * @typedef {Object} Person - * @property {string} Name - * @property {services$0.Address | null} Address - */ - -// In interface mode, this file is likely to contain just comments. -// We add a dummy export statement to ensure it is recognised as an ES module. -export {}; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_other/services/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_other/services/index.js deleted file mode 100644 index 588ef7ca7..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_other/services/index.js +++ /dev/null @@ -1,14 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as OtherService from "./otherservice.js"; -export { - OtherService -}; - -import * as $models from "./models.js"; - -/** - * @typedef {$models.Address} Address - */ diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_other/services/models.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_other/services/models.js deleted file mode 100644 index c04e3b10b..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_other/services/models.js +++ /dev/null @@ -1,14 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * @typedef {Object} Address - * @property {string} Street - * @property {string} State - * @property {string} Country - */ - -// In interface mode, this file is likely to contain just comments. -// We add a dummy export statement to ensure it is recognised as an ES module. -export {}; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_other/services/otherservice.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_other/services/otherservice.js deleted file mode 100644 index 911d42560..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_other/services/otherservice.js +++ /dev/null @@ -1,25 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * OtherService is a struct - * that does things - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * Yay does this and that - * @returns {$CancellablePromise<$models.Address | null>} - */ -export function Yay() { - return $Call.ByName("github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_other/services.OtherService.Yay"); -} diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_non_pointer_single/greetservice.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_non_pointer_single/greetservice.js deleted file mode 100644 index 83a363e8a..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_non_pointer_single/greetservice.js +++ /dev/null @@ -1,360 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * @param {number[]} $in - * @returns {$CancellablePromise} - */ -export function ArrayInt($in) { - return $Call.ByName("main.GreetService.ArrayInt", $in); -} - -/** - * @param {boolean} $in - * @returns {$CancellablePromise} - */ -export function BoolInBoolOut($in) { - return $Call.ByName("main.GreetService.BoolInBoolOut", $in); -} - -/** - * @param {number} $in - * @returns {$CancellablePromise} - */ -export function Float32InFloat32Out($in) { - return $Call.ByName("main.GreetService.Float32InFloat32Out", $in); -} - -/** - * @param {number} $in - * @returns {$CancellablePromise} - */ -export function Float64InFloat64Out($in) { - return $Call.ByName("main.GreetService.Float64InFloat64Out", $in); -} - -/** - * Greet someone - * @param {string} name - * @returns {$CancellablePromise} - */ -export function Greet(name) { - return $Call.ByName("main.GreetService.Greet", name); -} - -/** - * @param {number} $in - * @returns {$CancellablePromise} - */ -export function Int16InIntOut($in) { - return $Call.ByName("main.GreetService.Int16InIntOut", $in); -} - -/** - * @param {number | null} $in - * @returns {$CancellablePromise} - */ -export function Int16PointerInAndOutput($in) { - return $Call.ByName("main.GreetService.Int16PointerInAndOutput", $in); -} - -/** - * @param {number} $in - * @returns {$CancellablePromise} - */ -export function Int32InIntOut($in) { - return $Call.ByName("main.GreetService.Int32InIntOut", $in); -} - -/** - * @param {number | null} $in - * @returns {$CancellablePromise} - */ -export function Int32PointerInAndOutput($in) { - return $Call.ByName("main.GreetService.Int32PointerInAndOutput", $in); -} - -/** - * @param {number} $in - * @returns {$CancellablePromise} - */ -export function Int64InIntOut($in) { - return $Call.ByName("main.GreetService.Int64InIntOut", $in); -} - -/** - * @param {number | null} $in - * @returns {$CancellablePromise} - */ -export function Int64PointerInAndOutput($in) { - return $Call.ByName("main.GreetService.Int64PointerInAndOutput", $in); -} - -/** - * @param {number} $in - * @returns {$CancellablePromise} - */ -export function Int8InIntOut($in) { - return $Call.ByName("main.GreetService.Int8InIntOut", $in); -} - -/** - * @param {number | null} $in - * @returns {$CancellablePromise} - */ -export function Int8PointerInAndOutput($in) { - return $Call.ByName("main.GreetService.Int8PointerInAndOutput", $in); -} - -/** - * @param {number} $in - * @returns {$CancellablePromise} - */ -export function IntInIntOut($in) { - return $Call.ByName("main.GreetService.IntInIntOut", $in); -} - -/** - * @param {number | null} $in - * @returns {$CancellablePromise} - */ -export function IntPointerInAndOutput($in) { - return $Call.ByName("main.GreetService.IntPointerInAndOutput", $in); -} - -/** - * @param {number | null} $in - * @returns {$CancellablePromise} - */ -export function IntPointerInputNamedOutputs($in) { - return $Call.ByName("main.GreetService.IntPointerInputNamedOutputs", $in); -} - -/** - * @param {{ [_ in `${number}`]?: number } | null} $in - * @returns {$CancellablePromise} - */ -export function MapIntInt($in) { - return $Call.ByName("main.GreetService.MapIntInt", $in); -} - -/** - * @param {{ [_ in `${number}`]?: number | null } | null} $in - * @returns {$CancellablePromise} - */ -export function MapIntIntPointer($in) { - return $Call.ByName("main.GreetService.MapIntIntPointer", $in); -} - -/** - * @param {{ [_ in `${number}`]?: number[] | null } | null} $in - * @returns {$CancellablePromise} - */ -export function MapIntSliceInt($in) { - return $Call.ByName("main.GreetService.MapIntSliceInt", $in); -} - -/** - * @param {{ [_ in `${number}`]?: number[] | null } | null} $in - * @returns {$CancellablePromise<{ [_ in `${number}`]?: number[] | null } | null>} - */ -export function MapIntSliceIntInMapIntSliceIntOut($in) { - return $Call.ByName("main.GreetService.MapIntSliceIntInMapIntSliceIntOut", $in); -} - -/** - * @returns {$CancellablePromise} - */ -export function NoInputsStringOut() { - return $Call.ByName("main.GreetService.NoInputsStringOut"); -} - -/** - * @param {boolean | null} $in - * @returns {$CancellablePromise} - */ -export function PointerBoolInBoolOut($in) { - return $Call.ByName("main.GreetService.PointerBoolInBoolOut", $in); -} - -/** - * @param {number | null} $in - * @returns {$CancellablePromise} - */ -export function PointerFloat32InFloat32Out($in) { - return $Call.ByName("main.GreetService.PointerFloat32InFloat32Out", $in); -} - -/** - * @param {number | null} $in - * @returns {$CancellablePromise} - */ -export function PointerFloat64InFloat64Out($in) { - return $Call.ByName("main.GreetService.PointerFloat64InFloat64Out", $in); -} - -/** - * @param {{ [_ in `${number}`]?: number } | null} $in - * @returns {$CancellablePromise} - */ -export function PointerMapIntInt($in) { - return $Call.ByName("main.GreetService.PointerMapIntInt", $in); -} - -/** - * @param {string | null} $in - * @returns {$CancellablePromise} - */ -export function PointerStringInStringOut($in) { - return $Call.ByName("main.GreetService.PointerStringInStringOut", $in); -} - -/** - * @param {string[] | null} $in - * @returns {$CancellablePromise} - */ -export function StringArrayInputNamedOutput($in) { - return $Call.ByName("main.GreetService.StringArrayInputNamedOutput", $in); -} - -/** - * @param {string[] | null} $in - * @returns {$CancellablePromise} - */ -export function StringArrayInputNamedOutputs($in) { - return $Call.ByName("main.GreetService.StringArrayInputNamedOutputs", $in); -} - -/** - * @param {string[] | null} $in - * @returns {$CancellablePromise} - */ -export function StringArrayInputStringArrayOut($in) { - return $Call.ByName("main.GreetService.StringArrayInputStringArrayOut", $in); -} - -/** - * @param {string[] | null} $in - * @returns {$CancellablePromise} - */ -export function StringArrayInputStringOut($in) { - return $Call.ByName("main.GreetService.StringArrayInputStringOut", $in); -} - -/** - * @param {$models.Person} $in - * @returns {$CancellablePromise<$models.Person>} - */ -export function StructInputStructOutput($in) { - return $Call.ByName("main.GreetService.StructInputStructOutput", $in); -} - -/** - * @param {$models.Person | null} $in - * @returns {$CancellablePromise} - */ -export function StructPointerInputErrorOutput($in) { - return $Call.ByName("main.GreetService.StructPointerInputErrorOutput", $in); -} - -/** - * @param {$models.Person | null} $in - * @returns {$CancellablePromise<$models.Person | null>} - */ -export function StructPointerInputStructPointerOutput($in) { - return $Call.ByName("main.GreetService.StructPointerInputStructPointerOutput", $in); -} - -/** - * @param {number} $in - * @returns {$CancellablePromise} - */ -export function UInt16InUIntOut($in) { - return $Call.ByName("main.GreetService.UInt16InUIntOut", $in); -} - -/** - * @param {number | null} $in - * @returns {$CancellablePromise} - */ -export function UInt16PointerInAndOutput($in) { - return $Call.ByName("main.GreetService.UInt16PointerInAndOutput", $in); -} - -/** - * @param {number} $in - * @returns {$CancellablePromise} - */ -export function UInt32InUIntOut($in) { - return $Call.ByName("main.GreetService.UInt32InUIntOut", $in); -} - -/** - * @param {number | null} $in - * @returns {$CancellablePromise} - */ -export function UInt32PointerInAndOutput($in) { - return $Call.ByName("main.GreetService.UInt32PointerInAndOutput", $in); -} - -/** - * @param {number} $in - * @returns {$CancellablePromise} - */ -export function UInt64InUIntOut($in) { - return $Call.ByName("main.GreetService.UInt64InUIntOut", $in); -} - -/** - * @param {number | null} $in - * @returns {$CancellablePromise} - */ -export function UInt64PointerInAndOutput($in) { - return $Call.ByName("main.GreetService.UInt64PointerInAndOutput", $in); -} - -/** - * @param {number} $in - * @returns {$CancellablePromise} - */ -export function UInt8InUIntOut($in) { - return $Call.ByName("main.GreetService.UInt8InUIntOut", $in); -} - -/** - * @param {number | null} $in - * @returns {$CancellablePromise} - */ -export function UInt8PointerInAndOutput($in) { - return $Call.ByName("main.GreetService.UInt8PointerInAndOutput", $in); -} - -/** - * @param {number} $in - * @returns {$CancellablePromise} - */ -export function UIntInUIntOut($in) { - return $Call.ByName("main.GreetService.UIntInUIntOut", $in); -} - -/** - * @param {number | null} $in - * @returns {$CancellablePromise} - */ -export function UIntPointerInAndOutput($in) { - return $Call.ByName("main.GreetService.UIntPointerInAndOutput", $in); -} diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_non_pointer_single/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_non_pointer_single/index.js deleted file mode 100644 index cb2979a7a..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_non_pointer_single/index.js +++ /dev/null @@ -1,14 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; - -import * as $models from "./models.js"; - -/** - * @typedef {$models.Person} Person - */ diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_non_pointer_single/models.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_non_pointer_single/models.js deleted file mode 100644 index ec6136e27..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_non_pointer_single/models.js +++ /dev/null @@ -1,14 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * @typedef {Object} Person - * @property {string} Name - * @property {Person | null} Parent - * @property {{"Age": number, "Address": {"Street": string}}} Details - */ - -// In interface mode, this file is likely to contain just comments. -// We add a dummy export statement to ensure it is recognised as an ES module. -export {}; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_single/greetservice.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_single/greetservice.js deleted file mode 100644 index 83a363e8a..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_single/greetservice.js +++ /dev/null @@ -1,360 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * @param {number[]} $in - * @returns {$CancellablePromise} - */ -export function ArrayInt($in) { - return $Call.ByName("main.GreetService.ArrayInt", $in); -} - -/** - * @param {boolean} $in - * @returns {$CancellablePromise} - */ -export function BoolInBoolOut($in) { - return $Call.ByName("main.GreetService.BoolInBoolOut", $in); -} - -/** - * @param {number} $in - * @returns {$CancellablePromise} - */ -export function Float32InFloat32Out($in) { - return $Call.ByName("main.GreetService.Float32InFloat32Out", $in); -} - -/** - * @param {number} $in - * @returns {$CancellablePromise} - */ -export function Float64InFloat64Out($in) { - return $Call.ByName("main.GreetService.Float64InFloat64Out", $in); -} - -/** - * Greet someone - * @param {string} name - * @returns {$CancellablePromise} - */ -export function Greet(name) { - return $Call.ByName("main.GreetService.Greet", name); -} - -/** - * @param {number} $in - * @returns {$CancellablePromise} - */ -export function Int16InIntOut($in) { - return $Call.ByName("main.GreetService.Int16InIntOut", $in); -} - -/** - * @param {number | null} $in - * @returns {$CancellablePromise} - */ -export function Int16PointerInAndOutput($in) { - return $Call.ByName("main.GreetService.Int16PointerInAndOutput", $in); -} - -/** - * @param {number} $in - * @returns {$CancellablePromise} - */ -export function Int32InIntOut($in) { - return $Call.ByName("main.GreetService.Int32InIntOut", $in); -} - -/** - * @param {number | null} $in - * @returns {$CancellablePromise} - */ -export function Int32PointerInAndOutput($in) { - return $Call.ByName("main.GreetService.Int32PointerInAndOutput", $in); -} - -/** - * @param {number} $in - * @returns {$CancellablePromise} - */ -export function Int64InIntOut($in) { - return $Call.ByName("main.GreetService.Int64InIntOut", $in); -} - -/** - * @param {number | null} $in - * @returns {$CancellablePromise} - */ -export function Int64PointerInAndOutput($in) { - return $Call.ByName("main.GreetService.Int64PointerInAndOutput", $in); -} - -/** - * @param {number} $in - * @returns {$CancellablePromise} - */ -export function Int8InIntOut($in) { - return $Call.ByName("main.GreetService.Int8InIntOut", $in); -} - -/** - * @param {number | null} $in - * @returns {$CancellablePromise} - */ -export function Int8PointerInAndOutput($in) { - return $Call.ByName("main.GreetService.Int8PointerInAndOutput", $in); -} - -/** - * @param {number} $in - * @returns {$CancellablePromise} - */ -export function IntInIntOut($in) { - return $Call.ByName("main.GreetService.IntInIntOut", $in); -} - -/** - * @param {number | null} $in - * @returns {$CancellablePromise} - */ -export function IntPointerInAndOutput($in) { - return $Call.ByName("main.GreetService.IntPointerInAndOutput", $in); -} - -/** - * @param {number | null} $in - * @returns {$CancellablePromise} - */ -export function IntPointerInputNamedOutputs($in) { - return $Call.ByName("main.GreetService.IntPointerInputNamedOutputs", $in); -} - -/** - * @param {{ [_ in `${number}`]?: number } | null} $in - * @returns {$CancellablePromise} - */ -export function MapIntInt($in) { - return $Call.ByName("main.GreetService.MapIntInt", $in); -} - -/** - * @param {{ [_ in `${number}`]?: number | null } | null} $in - * @returns {$CancellablePromise} - */ -export function MapIntIntPointer($in) { - return $Call.ByName("main.GreetService.MapIntIntPointer", $in); -} - -/** - * @param {{ [_ in `${number}`]?: number[] | null } | null} $in - * @returns {$CancellablePromise} - */ -export function MapIntSliceInt($in) { - return $Call.ByName("main.GreetService.MapIntSliceInt", $in); -} - -/** - * @param {{ [_ in `${number}`]?: number[] | null } | null} $in - * @returns {$CancellablePromise<{ [_ in `${number}`]?: number[] | null } | null>} - */ -export function MapIntSliceIntInMapIntSliceIntOut($in) { - return $Call.ByName("main.GreetService.MapIntSliceIntInMapIntSliceIntOut", $in); -} - -/** - * @returns {$CancellablePromise} - */ -export function NoInputsStringOut() { - return $Call.ByName("main.GreetService.NoInputsStringOut"); -} - -/** - * @param {boolean | null} $in - * @returns {$CancellablePromise} - */ -export function PointerBoolInBoolOut($in) { - return $Call.ByName("main.GreetService.PointerBoolInBoolOut", $in); -} - -/** - * @param {number | null} $in - * @returns {$CancellablePromise} - */ -export function PointerFloat32InFloat32Out($in) { - return $Call.ByName("main.GreetService.PointerFloat32InFloat32Out", $in); -} - -/** - * @param {number | null} $in - * @returns {$CancellablePromise} - */ -export function PointerFloat64InFloat64Out($in) { - return $Call.ByName("main.GreetService.PointerFloat64InFloat64Out", $in); -} - -/** - * @param {{ [_ in `${number}`]?: number } | null} $in - * @returns {$CancellablePromise} - */ -export function PointerMapIntInt($in) { - return $Call.ByName("main.GreetService.PointerMapIntInt", $in); -} - -/** - * @param {string | null} $in - * @returns {$CancellablePromise} - */ -export function PointerStringInStringOut($in) { - return $Call.ByName("main.GreetService.PointerStringInStringOut", $in); -} - -/** - * @param {string[] | null} $in - * @returns {$CancellablePromise} - */ -export function StringArrayInputNamedOutput($in) { - return $Call.ByName("main.GreetService.StringArrayInputNamedOutput", $in); -} - -/** - * @param {string[] | null} $in - * @returns {$CancellablePromise} - */ -export function StringArrayInputNamedOutputs($in) { - return $Call.ByName("main.GreetService.StringArrayInputNamedOutputs", $in); -} - -/** - * @param {string[] | null} $in - * @returns {$CancellablePromise} - */ -export function StringArrayInputStringArrayOut($in) { - return $Call.ByName("main.GreetService.StringArrayInputStringArrayOut", $in); -} - -/** - * @param {string[] | null} $in - * @returns {$CancellablePromise} - */ -export function StringArrayInputStringOut($in) { - return $Call.ByName("main.GreetService.StringArrayInputStringOut", $in); -} - -/** - * @param {$models.Person} $in - * @returns {$CancellablePromise<$models.Person>} - */ -export function StructInputStructOutput($in) { - return $Call.ByName("main.GreetService.StructInputStructOutput", $in); -} - -/** - * @param {$models.Person | null} $in - * @returns {$CancellablePromise} - */ -export function StructPointerInputErrorOutput($in) { - return $Call.ByName("main.GreetService.StructPointerInputErrorOutput", $in); -} - -/** - * @param {$models.Person | null} $in - * @returns {$CancellablePromise<$models.Person | null>} - */ -export function StructPointerInputStructPointerOutput($in) { - return $Call.ByName("main.GreetService.StructPointerInputStructPointerOutput", $in); -} - -/** - * @param {number} $in - * @returns {$CancellablePromise} - */ -export function UInt16InUIntOut($in) { - return $Call.ByName("main.GreetService.UInt16InUIntOut", $in); -} - -/** - * @param {number | null} $in - * @returns {$CancellablePromise} - */ -export function UInt16PointerInAndOutput($in) { - return $Call.ByName("main.GreetService.UInt16PointerInAndOutput", $in); -} - -/** - * @param {number} $in - * @returns {$CancellablePromise} - */ -export function UInt32InUIntOut($in) { - return $Call.ByName("main.GreetService.UInt32InUIntOut", $in); -} - -/** - * @param {number | null} $in - * @returns {$CancellablePromise} - */ -export function UInt32PointerInAndOutput($in) { - return $Call.ByName("main.GreetService.UInt32PointerInAndOutput", $in); -} - -/** - * @param {number} $in - * @returns {$CancellablePromise} - */ -export function UInt64InUIntOut($in) { - return $Call.ByName("main.GreetService.UInt64InUIntOut", $in); -} - -/** - * @param {number | null} $in - * @returns {$CancellablePromise} - */ -export function UInt64PointerInAndOutput($in) { - return $Call.ByName("main.GreetService.UInt64PointerInAndOutput", $in); -} - -/** - * @param {number} $in - * @returns {$CancellablePromise} - */ -export function UInt8InUIntOut($in) { - return $Call.ByName("main.GreetService.UInt8InUIntOut", $in); -} - -/** - * @param {number | null} $in - * @returns {$CancellablePromise} - */ -export function UInt8PointerInAndOutput($in) { - return $Call.ByName("main.GreetService.UInt8PointerInAndOutput", $in); -} - -/** - * @param {number} $in - * @returns {$CancellablePromise} - */ -export function UIntInUIntOut($in) { - return $Call.ByName("main.GreetService.UIntInUIntOut", $in); -} - -/** - * @param {number | null} $in - * @returns {$CancellablePromise} - */ -export function UIntPointerInAndOutput($in) { - return $Call.ByName("main.GreetService.UIntPointerInAndOutput", $in); -} diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_single/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_single/index.js deleted file mode 100644 index cb2979a7a..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_single/index.js +++ /dev/null @@ -1,14 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; - -import * as $models from "./models.js"; - -/** - * @typedef {$models.Person} Person - */ diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_single/models.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_single/models.js deleted file mode 100644 index ec6136e27..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_single/models.js +++ /dev/null @@ -1,14 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * @typedef {Object} Person - * @property {string} Name - * @property {Person | null} Parent - * @property {{"Age": number, "Address": {"Street": string}}} Details - */ - -// In interface mode, this file is likely to contain just comments. -// We add a dummy export statement to ensure it is recognised as an ES module. -export {}; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single/greetservice.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single/greetservice.js deleted file mode 100644 index bba7ea7ea..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single/greetservice.js +++ /dev/null @@ -1,21 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -/** - * Greet someone - * @param {string} name - * @returns {$CancellablePromise} - */ -export function Greet(name) { - return $Call.ByName("main.GreetService.Greet", name); -} diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single/index.js deleted file mode 100644 index fdf1ff435..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single/index.js +++ /dev/null @@ -1,8 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_function/greetservice.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_function/greetservice.js deleted file mode 100644 index bba7ea7ea..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_function/greetservice.js +++ /dev/null @@ -1,21 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -/** - * Greet someone - * @param {string} name - * @returns {$CancellablePromise} - */ -export function Greet(name) { - return $Call.ByName("main.GreetService.Greet", name); -} diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_function/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_function/index.js deleted file mode 100644 index fdf1ff435..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_function/index.js +++ /dev/null @@ -1,8 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_other_function/greetservice.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_other_function/greetservice.js deleted file mode 100644 index 8ab5f3462..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_other_function/greetservice.js +++ /dev/null @@ -1,34 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * Greet does XYZ - * @param {string} name - * @returns {$CancellablePromise} - */ -export function Greet(name) { - return $Call.ByName("main.GreetService.Greet", name); -} - -/** - * NewPerson creates a new person - * @param {string} name - * @returns {$CancellablePromise<$models.Person | null>} - */ -export function NewPerson(name) { - return $Call.ByName("main.GreetService.NewPerson", name); -} diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_other_function/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_other_function/index.js deleted file mode 100644 index 977600693..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_other_function/index.js +++ /dev/null @@ -1,16 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; - -import * as $models from "./models.js"; - -/** - * Person is a person! - * They have a name and an address - * @typedef {$models.Person} Person - */ diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_other_function/models.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_other_function/models.js deleted file mode 100644 index ab5cea255..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_other_function/models.js +++ /dev/null @@ -1,19 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as services$0 from "./services/models.js"; - -/** - * Person is a person! - * They have a name and an address - * @typedef {Object} Person - * @property {string} Name - * @property {services$0.Address | null} Address - */ - -// In interface mode, this file is likely to contain just comments. -// We add a dummy export statement to ensure it is recognised as an ES module. -export {}; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_other_function/services/index.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_other_function/services/index.js deleted file mode 100644 index 588ef7ca7..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_other_function/services/index.js +++ /dev/null @@ -1,14 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as OtherService from "./otherservice.js"; -export { - OtherService -}; - -import * as $models from "./models.js"; - -/** - * @typedef {$models.Address} Address - */ diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_other_function/services/models.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_other_function/services/models.js deleted file mode 100644 index c04e3b10b..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_other_function/services/models.js +++ /dev/null @@ -1,14 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * @typedef {Object} Address - * @property {string} Street - * @property {string} State - * @property {string} Country - */ - -// In interface mode, this file is likely to contain just comments. -// We add a dummy export statement to ensure it is recognised as an ES module. -export {}; diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_other_function/services/otherservice.js b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_other_function/services/otherservice.js deleted file mode 100644 index 6594edc5b..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_other_function/services/otherservice.js +++ /dev/null @@ -1,25 +0,0 @@ -// @ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * OtherService is a struct - * that does things - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * Yay does this and that - * @returns {$CancellablePromise<$models.Address | null>} - */ -export function Yay() { - return $Call.ByName("github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_other_function/services.OtherService.Yay"); -} diff --git a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/warnings.log b/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/warnings.log deleted file mode 100644 index ce8369307..000000000 --- a/v3/internal/generator/testdata/output/lang=JS/UseInterfaces=true/UseNames=true/warnings.log +++ /dev/null @@ -1,83 +0,0 @@ -[warn] /testcases/complex_json/main.go:127:2: event 'collision' has one of multiple definitions here with data type map[string]int -[warn] /testcases/events_only/events.go:20:2: event 'collision' has one of multiple definitions here with data type int -[warn] /testcases/events_only/events.go:21:2: `application.RegisterEvent` called here with non-constant event name -[warn] /testcases/events_only/other.go:10:5: `application.RegisterEvent` is instantiated here but not called -[warn] /testcases/events_only/other.go:13:2: `application.RegisterEvent` called here with non-constant event name -[warn] /testcases/events_only/other.go:17:2: data type []T for event 'parametric' contains unresolved type parameters and will be ignored` -[warn] /testcases/events_only/other.go:22:2: event 'common:ApplicationStarted' is a known system event and cannot be overridden; this call to `application.RegisterEvent` will panic -[warn] /testcases/marshalers/main.go:212:2: event 'collision' has one of multiple definitions here with data type *struct{Field []bool} -[warn] /testcases/marshalers/main.go:214:2: data type encoding/json.Marshaler for event 'interface' is a non-empty interface: emitting events from the frontend with data other than `null` is not supported by encoding/json and will likely result in runtime errors -[warn] dynamically registered event names are not discoverable by the binding generator: it is recommended to invoke `application.RegisterEvent` with constant arguments only -[warn] event 'collision' has multiple conflicting definitions and will be ignored -[warn] events registered through indirect calls are not discoverable by the binding generator: it is recommended to invoke `application.RegisterEvent` directly -[warn] generic wrappers for calls to `application.RegisterEvent` are not analysable by the binding generator: it is recommended to call `application.RegisterEvent` with concrete types only -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *R is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *S is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *T is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *U is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *V is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *X is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *Y is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *Z is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *any is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *complex64 is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *encoding.TextMarshaler is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *float32 is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.CustomInterface is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.EmbeddedInterface is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.InterfaceAlias is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.InterfacePtrAlias is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.InterfacePtrType is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.InterfaceType is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.NonTextMarshaler is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.PointerPtrAlias is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.PointerPtrType is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.PointerType is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.ValuePtrAlias is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.ValuePtrType is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.ValueType is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *int is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *string is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *uint is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type R is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type T is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type W is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type any is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type bool is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type complex64 is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type float32 is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.BadTildeCstrAlias[T] is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.BadTildeCstrAlias[struct{}] is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.BadTildeCstrPtrAlias[T] is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.BadTildeCstrPtrAlias[struct{}] is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.BasicCstrPtrAlias[S] is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.BasicCstrPtrAlias[int] is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.ComparableCstrAlias[R] is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.ComparableCstrAlias[github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.PointerTextMarshaler] is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.ComparableCstrPtrAlias[R] is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.ComparableCstrPtrAlias[int] is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.EmbeddedPointer is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.GoodTildeCstrPtrAlias[U] is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.InterfaceCstrPtrAlias[*github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.PointerTextMarshaler] is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.InterfaceCstrPtrAlias[Y] is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.InterfaceCstrPtrAlias[encoding.TextMarshaler] is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.InterfacePtrAlias is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.InterfacePtrType is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.MixedCstrPtrAlias[X] is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.MixedCstrPtrAlias[github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.StringType] is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.NonBasicCstrPtrAlias[*github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.PointerTextMarshaler] is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.NonBasicCstrPtrAlias[V] is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.NonTextMarshaler is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.PointableCstrAlias[W] is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.PointableCstrAlias[github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.PointerTextMarshaler] is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.PointerAlias is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.PointerCstrPtrAlias[R, Z] is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.PointerCstrPtrAlias[github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.PointerTextMarshaler, *github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.PointerTextMarshaler] is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.PointerCstrPtrAlias[github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.ValueTextMarshaler, *github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.ValueTextMarshaler] is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.PointerPtrType is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.PointerTextMarshaler is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.PointerType is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.ValuePtrType is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.ValueType is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.WrongAlias is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.WrongType is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/encoding/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/encoding/index.ts deleted file mode 100644 index ba2885969..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/encoding/index.ts +++ /dev/null @@ -1,6 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -export type { - TextMarshaler -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/encoding/json/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/encoding/json/index.ts deleted file mode 100644 index 00ec01151..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/encoding/json/index.ts +++ /dev/null @@ -1,6 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -export type { - Marshaler -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/encoding/json/models.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/encoding/json/models.ts deleted file mode 100644 index 8cd1a164f..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/encoding/json/models.ts +++ /dev/null @@ -1,12 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Create as $Create } from "/wails/runtime.js"; - -/** - * Marshaler is the interface implemented by types that - * can marshal themselves into valid JSON. - */ -export type Marshaler = any; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/encoding/models.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/encoding/models.ts deleted file mode 100644 index 235dfce3e..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/encoding/models.ts +++ /dev/null @@ -1,14 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Create as $Create } from "/wails/runtime.js"; - -/** - * TextMarshaler is the interface implemented by an object that can - * marshal itself into a textual form. - * - * MarshalText encodes the receiver into UTF-8-encoded text and returns the result. - */ -export type TextMarshaler = any; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/eventcreate.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/eventcreate.ts deleted file mode 100644 index 9cc7781aa..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/eventcreate.ts +++ /dev/null @@ -1,39 +0,0 @@ -//@ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Create as $Create } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as json$0 from "../../../../../encoding/json/models.js"; -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as events_only$0 from "./generator/testcases/events_only/models.js"; -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as more$0 from "./generator/testcases/no_bindings_here/more/models.js"; - -function configure() { - Object.freeze(Object.assign($Create.Events, { - "events_only:class": $$createType0, - "events_only:map": $$createType2, - "events_only:other": $$createType3, - "overlap": $$createType6, - })); -} - -// Private type creation functions -const $$createType0 = events_only$0.SomeClass.createFrom; -const $$createType1 = $Create.Array($Create.Any); -const $$createType2 = $Create.Map($Create.Any, $$createType1); -const $$createType3 = $Create.Array($Create.Any); -const $$createType4 = $Create.Array($Create.Any); -const $$createType5 = $Create.Struct({ - "Field": $$createType4, -}); -const $$createType6 = $Create.Nullable($$createType5); - -configure(); diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/eventdata.d.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/eventdata.d.ts deleted file mode 100644 index 3e53d9287..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/eventdata.d.ts +++ /dev/null @@ -1,30 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import type { Events } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import type * as json$0 from "../../../../../encoding/json/models.js"; -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import type * as events_only$0 from "./generator/testcases/events_only/models.js"; -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import type * as more$0 from "./generator/testcases/no_bindings_here/more/models.js"; - -declare module "/wails/runtime.js" { - namespace Events { - interface CustomEvents { - "events_only:class": events_only$0.SomeClass; - "events_only:map": { [_ in string]?: number[] }; - "events_only:nodata": void; - "events_only:other": more$0.StringPtr[]; - "events_only:string": string; - "interface": json$0.Marshaler; - "overlap": {"Field": boolean[]} | null; - } - } -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/aliases/greetservice.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/aliases/greetservice.ts deleted file mode 100644 index ccc8ac9fe..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/aliases/greetservice.ts +++ /dev/null @@ -1,92 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as subpkg$0 from "./subpkg/models.js"; -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as nobindingshere$0 from "../no_bindings_here/models.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * Get someone. - */ -export function Get(aliasValue: $models.Alias): $CancellablePromise<$models.Person> { - return $Call.ByID(1928502664, aliasValue).then(($result: any) => { - return $$createType0($result); - }); -} - -/** - * Apparently, aliases are all the rage right now. - */ -export function GetButAliased(p: $models.AliasedPerson): $CancellablePromise<$models.StrangelyAliasedPerson> { - return $Call.ByID(1896499664, p).then(($result: any) => { - return $$createType0($result); - }); -} - -/** - * Get someone quite different. - */ -export function GetButDifferent(): $CancellablePromise<$models.GenericPerson> { - return $Call.ByID(2240931744).then(($result: any) => { - return $$createType1($result); - }); -} - -export function GetButForeignPrivateAlias(): $CancellablePromise { - return $Call.ByID(643456960).then(($result: any) => { - return $$createType2($result); - }); -} - -export function GetButGenericAliases(): $CancellablePromise<$models.AliasGroup> { - return $Call.ByID(914093800).then(($result: any) => { - return $$createType3($result); - }); -} - -export function GetButSubPackageAlias(): $CancellablePromise<$models.SubPackageAlias> { - return $Call.ByID(1443276371).then(($result: any) => { - return $$createType4($result); - }); -} - -/** - * Greet a lot of unusual things. - */ -export function Greet($0: $models.EmptyAliasStruct, $1: $models.EmptyStruct): $CancellablePromise<$models.AliasStruct> { - return $Call.ByID(1411160069, $0, $1).then(($result: any) => { - return $$createType8($result); - }); -} - -// Private type creation functions -const $$createType0 = $models.Person.createFrom; -const $$createType1 = $models.GenericPerson.createFrom($Create.Any); -const $$createType2 = nobindingshere$0.personImpl.createFrom; -const $$createType3 = $models.AliasGroup.createFrom; -const $$createType4 = subpkg$0.SubStruct.createFrom; -const $$createType5 = $Create.Array($Create.Any); -const $$createType6 = $Create.Array($Create.Any); -const $$createType7 = $Create.Struct({ - "NoMoreIdeas": $$createType6, -}); -const $$createType8 = $Create.Struct({ - "Foo": $$createType5, - "Other": $$createType7, -}); diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/aliases/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/aliases/index.ts deleted file mode 100644 index f01ba91e8..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/aliases/index.ts +++ /dev/null @@ -1,30 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; - -export { - AliasGroup, - AliasedPerson, - EmptyStruct, - GenericPerson, - GenericPersonAlias, - IndirectPersonAlias, - Person, - StrangelyAliasedPerson, - SubPackageAlias, - TPIndirectPersonAlias -} from "./models.js"; - -export type { - Alias, - AliasStruct, - EmptyAliasStruct, - GenericAlias, - GenericMapAlias, - GenericPtrAlias, - OtherAliasStruct -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/aliases/models.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/aliases/models.ts deleted file mode 100644 index 56840a1c3..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/aliases/models.ts +++ /dev/null @@ -1,313 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Create as $Create } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as subpkg$0 from "./subpkg/models.js"; - -/** - * A nice type Alias. - */ -export type Alias = number; - -/** - * A class whose fields have various aliased types. - */ -export class AliasGroup { - "GAi": GenericAlias; - "GAP": GenericAlias>; - "GPAs": GenericPtrAlias; - "GPAP": GenericPtrAlias>; - "GMA": GenericMapAlias; - "GPA": GenericPersonAlias; - "IPA": IndirectPersonAlias; - "TPIPA": TPIndirectPersonAlias; - "SPA": SubPackageAlias; - - /** Creates a new AliasGroup instance. */ - constructor($$source: Partial = {}) { - if (!("GAi" in $$source)) { - this["GAi"] = 0; - } - if (!("GAP" in $$source)) { - this["GAP"] = (new GenericPerson()); - } - if (!("GPAs" in $$source)) { - this["GPAs"] = null; - } - if (!("GPAP" in $$source)) { - this["GPAP"] = null; - } - if (!("GMA" in $$source)) { - this["GMA"] = {}; - } - if (!("GPA" in $$source)) { - this["GPA"] = (new GenericPersonAlias()); - } - if (!("IPA" in $$source)) { - this["IPA"] = (new IndirectPersonAlias()); - } - if (!("TPIPA" in $$source)) { - this["TPIPA"] = (new TPIndirectPersonAlias()); - } - if (!("SPA" in $$source)) { - this["SPA"] = (new SubPackageAlias()); - } - - Object.assign(this, $$source); - } - - /** - * Creates a new AliasGroup instance from a string or object. - */ - static createFrom($$source: any = {}): AliasGroup { - const $$createField1_0 = $$createType0; - const $$createField2_0 = $$createType2; - const $$createField3_0 = $$createType5; - const $$createField4_0 = $$createType6; - const $$createField5_0 = $$createType8; - const $$createField6_0 = $$createType8; - const $$createField7_0 = $$createType0; - const $$createField8_0 = $$createType9; - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - if ("GAP" in $$parsedSource) { - $$parsedSource["GAP"] = $$createField1_0($$parsedSource["GAP"]); - } - if ("GPAs" in $$parsedSource) { - $$parsedSource["GPAs"] = $$createField2_0($$parsedSource["GPAs"]); - } - if ("GPAP" in $$parsedSource) { - $$parsedSource["GPAP"] = $$createField3_0($$parsedSource["GPAP"]); - } - if ("GMA" in $$parsedSource) { - $$parsedSource["GMA"] = $$createField4_0($$parsedSource["GMA"]); - } - if ("GPA" in $$parsedSource) { - $$parsedSource["GPA"] = $$createField5_0($$parsedSource["GPA"]); - } - if ("IPA" in $$parsedSource) { - $$parsedSource["IPA"] = $$createField6_0($$parsedSource["IPA"]); - } - if ("TPIPA" in $$parsedSource) { - $$parsedSource["TPIPA"] = $$createField7_0($$parsedSource["TPIPA"]); - } - if ("SPA" in $$parsedSource) { - $$parsedSource["SPA"] = $$createField8_0($$parsedSource["SPA"]); - } - return new AliasGroup($$parsedSource as Partial); - } -} - -/** - * A struct alias. - * This should be rendered as a typedef or interface in every mode. - */ -export interface AliasStruct { - /** - * A field with a comment. - */ - "Foo": number[]; - - /** - * Definitely not Foo. - */ - "Bar"?: string; - "Baz"?: string; - - /** - * A nested alias struct. - */ - "Other": OtherAliasStruct; -} - -/** - * An empty struct alias. - */ -export interface EmptyAliasStruct { -} - -/** - * An empty struct. - */ -export class EmptyStruct { - - /** Creates a new EmptyStruct instance. */ - constructor($$source: Partial = {}) { - - Object.assign(this, $$source); - } - - /** - * Creates a new EmptyStruct instance from a string or object. - */ - static createFrom($$source: any = {}): EmptyStruct { - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - return new EmptyStruct($$parsedSource as Partial); - } -} - -/** - * A generic alias that forwards to a type parameter. - */ -export type GenericAlias = T; - -/** - * A generic alias that wraps a map. - */ -export type GenericMapAlias = { [_ in string]?: U }; - -/** - * A generic struct containing an alias. - */ -export class GenericPerson { - "Name"?: T; - "AliasedField": Alias; - - /** Creates a new GenericPerson instance. */ - constructor($$source: Partial> = {}) { - if (!("AliasedField" in $$source)) { - this["AliasedField"] = 0; - } - - Object.assign(this, $$source); - } - - /** - * Given creation functions for each type parameter, - * returns a creation function for a concrete instance - * of the generic class GenericPerson. - */ - static createFrom($$createParamT: (source: any) => T): ($$source?: any) => GenericPerson { - const $$createField0_0 = $$createParamT; - return ($$source: any = {}) => { - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - if ("Name" in $$parsedSource) { - $$parsedSource["Name"] = $$createField0_0($$parsedSource["Name"]); - } - return new GenericPerson($$parsedSource as Partial>); - }; - } -} - -/** - * A generic alias that wraps a generic struct. - */ -export const GenericPersonAlias = GenericPerson; - -/** - * A generic alias that wraps a generic struct. - */ -export type GenericPersonAlias = GenericPerson[]>; - -/** - * A generic alias that wraps a pointer type. - */ -export type GenericPtrAlias = GenericAlias | null; - -/** - * An alias that wraps a class through a non-typeparam alias. - */ -export const IndirectPersonAlias = GenericPersonAlias; - -/** - * An alias that wraps a class through a non-typeparam alias. - */ -export type IndirectPersonAlias = GenericPersonAlias; - -/** - * Another struct alias. - */ -export interface OtherAliasStruct { - "NoMoreIdeas": number[]; -} - -/** - * A non-generic struct containing an alias. - */ -export class Person { - /** - * The Person's name. - */ - "Name": string; - - /** - * A random alias field. - */ - "AliasedField": Alias; - - /** Creates a new Person instance. */ - constructor($$source: Partial = {}) { - if (!("Name" in $$source)) { - this["Name"] = ""; - } - if (!("AliasedField" in $$source)) { - this["AliasedField"] = 0; - } - - Object.assign(this, $$source); - } - - /** - * Creates a new Person instance from a string or object. - */ - static createFrom($$source: any = {}): Person { - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - return new Person($$parsedSource as Partial); - } -} - -/** - * A class alias. - */ -export const AliasedPerson = Person; - -/** - * A class alias. - */ -export type AliasedPerson = Person; - -/** - * Another class alias, but ordered after its aliased class. - */ -export const StrangelyAliasedPerson = Person; - -/** - * Another class alias, but ordered after its aliased class. - */ -export type StrangelyAliasedPerson = Person; - -/** - * An alias referencing another package that is not used elsewhere. - */ -export const SubPackageAlias = subpkg$0.SubStruct; - -/** - * An alias referencing another package that is not used elsewhere. - */ -export type SubPackageAlias = subpkg$0.SubStruct; - -/** - * An alias that wraps a class through a typeparam alias. - */ -export const TPIndirectPersonAlias = GenericPerson; - -/** - * An alias that wraps a class through a typeparam alias. - */ -export type TPIndirectPersonAlias = GenericAlias>; - -// Private type creation functions -const $$createType0 = GenericPerson.createFrom($Create.Any); -const $$createType1 = $Create.Array($Create.Any); -const $$createType2 = $Create.Nullable($$createType1); -const $$createType3 = $Create.Array($Create.Any); -const $$createType4 = GenericPerson.createFrom($$createType3); -const $$createType5 = $Create.Nullable($$createType4); -const $$createType6 = $Create.Map($Create.Any, $Create.Any); -const $$createType7 = $Create.Array($Create.Any); -const $$createType8 = GenericPerson.createFrom($$createType7); -const $$createType9 = subpkg$0.SubStruct.createFrom; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/aliases/subpkg/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/aliases/subpkg/index.ts deleted file mode 100644 index 19a8a0184..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/aliases/subpkg/index.ts +++ /dev/null @@ -1,6 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -export { - SubStruct -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/aliases/subpkg/models.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/aliases/subpkg/models.ts deleted file mode 100644 index 03ba700d1..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/aliases/subpkg/models.ts +++ /dev/null @@ -1,37 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Create as $Create } from "/wails/runtime.js"; - -/** - * SubStruct is a type in a subpackage that is only referenced through an alias. - */ -export class SubStruct { - "SomeField": string[]; - - /** Creates a new SubStruct instance. */ - constructor($$source: Partial = {}) { - if (!("SomeField" in $$source)) { - this["SomeField"] = []; - } - - Object.assign(this, $$source); - } - - /** - * Creates a new SubStruct instance from a string or object. - */ - static createFrom($$source: any = {}): SubStruct { - const $$createField0_0 = $$createType0; - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - if ("SomeField" in $$parsedSource) { - $$parsedSource["SomeField"] = $$createField0_0($$parsedSource["SomeField"]); - } - return new SubStruct($$parsedSource as Partial); - } -} - -// Private type creation functions -const $$createType0 = $Create.Array($Create.Any); diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_expressions/config/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_expressions/config/index.ts deleted file mode 100644 index bdcf43c67..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_expressions/config/index.ts +++ /dev/null @@ -1,9 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as Service7 from "./service7.js"; -import * as Service9 from "./service9.js"; -export { - Service7, - Service9 -}; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_expressions/config/service7.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_expressions/config/service7.ts deleted file mode 100644 index 8fe0035ed..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_expressions/config/service7.ts +++ /dev/null @@ -1,10 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -export function TestMethod(): $CancellablePromise { - return $Call.ByID(2241101727); -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_expressions/config/service9.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_expressions/config/service9.ts deleted file mode 100644 index 8260ce500..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_expressions/config/service9.ts +++ /dev/null @@ -1,10 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -export function TestMethod2(): $CancellablePromise { - return $Call.ByID(1556848345); -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_json/greetservice.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_json/greetservice.ts deleted file mode 100644 index 69c89433a..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_json/greetservice.ts +++ /dev/null @@ -1,22 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * Greet does XYZ - */ -export function Greet(person: $models.Person, emb: $models.Embedded1): $CancellablePromise { - return $Call.ByID(1411160069, person, emb); -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_json/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_json/index.ts deleted file mode 100644 index 6cdc52c66..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_json/index.ts +++ /dev/null @@ -1,17 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; - -export { - Embedded1, - Person, - Title -} from "./models.js"; - -export type { - Embedded3 -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_json/models.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_json/models.ts deleted file mode 100644 index 50f23b52d..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_json/models.ts +++ /dev/null @@ -1,237 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Create as $Create } from "/wails/runtime.js"; - -export class Embedded1 { - /** - * Friends should be shadowed in Person by a field of lesser depth - */ - "Friends": number; - - /** - * Vanish should be omitted from Person because there is another field with same depth and no tag - */ - "Vanish": number; - - /** - * StillThere should be shadowed in Person by other field with same depth and a json tag - */ - "StillThere": string; - - /** - * NamingThingsIsHard is a law of programming - */ - "NamingThingsIsHard": `${boolean}`; - - /** Creates a new Embedded1 instance. */ - constructor($$source: Partial = {}) { - if (!("Friends" in $$source)) { - this["Friends"] = 0; - } - if (!("Vanish" in $$source)) { - this["Vanish"] = 0; - } - if (!("StillThere" in $$source)) { - this["StillThere"] = ""; - } - if (!("NamingThingsIsHard" in $$source)) { - this["NamingThingsIsHard"] = "false"; - } - - Object.assign(this, $$source); - } - - /** - * Creates a new Embedded1 instance from a string or object. - */ - static createFrom($$source: any = {}): Embedded1 { - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - return new Embedded1($$parsedSource as Partial); - } -} - -export type Embedded3 = string; - -/** - * Person represents a person - */ -export class Person { - /** - * Titles is optional in JSON - */ - "Titles"?: Title[]; - - /** - * Names has a - * multiline comment - */ - "Names": string[]; - - /** - * Partner has a custom and complex JSON key - */ - "Partner": Person | null; - "Friends": (Person | null)[]; - - /** - * NamingThingsIsHard is a law of programming - */ - "NamingThingsIsHard": `${boolean}`; - - /** - * StillThereButRenamed should shadow in Person the other field with same depth and no json tag - */ - "StillThere": Embedded3 | null; - - /** - * StrangeNumber maps to "-" - */ - "-": number; - - /** - * Embedded3 should appear with key "Embedded3" - */ - "Embedded3": Embedded3; - - /** - * StrangerNumber is serialized as a string - */ - "StrangerNumber": `${number}`; - - /** - * StrangestString is optional and serialized as a JSON string - */ - "StrangestString"?: `"${string}"`; - - /** - * StringStrangest is serialized as a JSON string and optional - */ - "StringStrangest"?: `"${string}"`; - - /** - * embedded4 should be optional and appear with key "emb4" - */ - "emb4"?: embedded4; - - /** Creates a new Person instance. */ - constructor($$source: Partial = {}) { - if (!("Names" in $$source)) { - this["Names"] = []; - } - if (!("Partner" in $$source)) { - this["Partner"] = null; - } - if (!("Friends" in $$source)) { - this["Friends"] = []; - } - if (!("NamingThingsIsHard" in $$source)) { - this["NamingThingsIsHard"] = "false"; - } - if (!("StillThere" in $$source)) { - this["StillThere"] = null; - } - if (!("-" in $$source)) { - this["-"] = 0; - } - if (!("Embedded3" in $$source)) { - this["Embedded3"] = ""; - } - if (!("StrangerNumber" in $$source)) { - this["StrangerNumber"] = "0"; - } - - Object.assign(this, $$source); - } - - /** - * Creates a new Person instance from a string or object. - */ - static createFrom($$source: any = {}): Person { - const $$createField0_0 = $$createType0; - const $$createField1_0 = $$createType1; - const $$createField2_0 = $$createType3; - const $$createField3_0 = $$createType4; - const $$createField11_0 = $$createType5; - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - if ("Titles" in $$parsedSource) { - $$parsedSource["Titles"] = $$createField0_0($$parsedSource["Titles"]); - } - if ("Names" in $$parsedSource) { - $$parsedSource["Names"] = $$createField1_0($$parsedSource["Names"]); - } - if ("Partner" in $$parsedSource) { - $$parsedSource["Partner"] = $$createField2_0($$parsedSource["Partner"]); - } - if ("Friends" in $$parsedSource) { - $$parsedSource["Friends"] = $$createField3_0($$parsedSource["Friends"]); - } - if ("emb4" in $$parsedSource) { - $$parsedSource["emb4"] = $$createField11_0($$parsedSource["emb4"]); - } - return new Person($$parsedSource as Partial); - } -} - -/** - * Title is a title - */ -export enum Title { - /** - * The Go zero value for the underlying type of the enum. - */ - $zero = "", - - /** - * Mister is a title - */ - Mister = "Mr", - Miss = "Miss", - Ms = "Ms", - Mrs = "Mrs", - Dr = "Dr", -}; - -export class embedded4 { - /** - * NamingThingsIsHard is a law of programming - */ - "NamingThingsIsHard": `${boolean}`; - - /** - * Friends should not be shadowed in Person as embedded4 is not embedded - * from encoding/json's point of view; - * however, it should be shadowed in Embedded1 - */ - "Friends": boolean; - - /** Creates a new embedded4 instance. */ - constructor($$source: Partial = {}) { - if (!("NamingThingsIsHard" in $$source)) { - this["NamingThingsIsHard"] = "false"; - } - if (!("Friends" in $$source)) { - this["Friends"] = false; - } - - Object.assign(this, $$source); - } - - /** - * Creates a new embedded4 instance from a string or object. - */ - static createFrom($$source: any = {}): embedded4 { - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - return new embedded4($$parsedSource as Partial); - } -} - -// Private type creation functions -const $$createType0 = $Create.Array($Create.Any); -const $$createType1 = $Create.Array($Create.Any); -const $$createType2 = Person.createFrom; -const $$createType3 = $Create.Nullable($$createType2); -const $$createType4 = $Create.Array($$createType3); -const $$createType5 = embedded4.createFrom; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_method/greetservice.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_method/greetservice.ts deleted file mode 100644 index 2c9200a0c..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_method/greetservice.ts +++ /dev/null @@ -1,32 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * Greet does XYZ - * It has a multiline doc comment - * The comment has even some * / traps!! - */ -export function Greet(str: string, people: $models.Person[], $2: {"AnotherCount": number, "AnotherOne": $models.Person | null}, assoc: { [_ in `${number}`]?: boolean | null }, $4: (number | null)[], ...other: string[]): $CancellablePromise<[$models.Person, any, number[]]> { - return $Call.ByID(1411160069, str, people, $2, assoc, $4, other).then(($result: any) => { - $result[0] = $$createType0($result[0]); - $result[2] = $$createType1($result[2]); - return $result; - }); -} - -// Private type creation functions -const $$createType0 = $models.Person.createFrom; -const $$createType1 = $Create.Array($Create.Any); diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_method/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_method/index.ts deleted file mode 100644 index f95c1b558..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_method/index.ts +++ /dev/null @@ -1,11 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; - -export { - Person -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_method/models.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_method/models.ts deleted file mode 100644 index 2417aff4c..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_method/models.ts +++ /dev/null @@ -1,30 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Create as $Create } from "/wails/runtime.js"; - -/** - * Person represents a person - */ -export class Person { - "Name": string; - - /** Creates a new Person instance. */ - constructor($$source: Partial = {}) { - if (!("Name" in $$source)) { - this["Name"] = ""; - } - - Object.assign(this, $$source); - } - - /** - * Creates a new Person instance from a string or object. - */ - static createFrom($$source: any = {}): Person { - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - return new Person($$parsedSource as Partial); - } -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/cyclic_imports/greetservice.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/cyclic_imports/greetservice.ts deleted file mode 100644 index c1c70be69..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/cyclic_imports/greetservice.ts +++ /dev/null @@ -1,30 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * Make a cycle. - */ -export function MakeCycles(): $CancellablePromise<[$models.StructA, $models.StructC]> { - return $Call.ByID(440020721).then(($result: any) => { - $result[0] = $$createType0($result[0]); - $result[1] = $$createType1($result[1]); - return $result; - }); -} - -// Private type creation functions -const $$createType0 = $models.StructA.createFrom; -const $$createType1 = $models.StructC.createFrom; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/cyclic_imports/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/cyclic_imports/index.ts deleted file mode 100644 index 4b190b8da..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/cyclic_imports/index.ts +++ /dev/null @@ -1,13 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; - -export { - StructA, - StructC, - StructE -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/cyclic_imports/models.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/cyclic_imports/models.ts deleted file mode 100644 index 9e86cd674..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/cyclic_imports/models.ts +++ /dev/null @@ -1,131 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Create as $Create } from "/wails/runtime.js"; - -export class StructA { - "B": structB | null; - - /** Creates a new StructA instance. */ - constructor($$source: Partial = {}) { - if (!("B" in $$source)) { - this["B"] = null; - } - - Object.assign(this, $$source); - } - - /** - * Creates a new StructA instance from a string or object. - */ - static createFrom($$source: any = {}): StructA { - const $$createField0_0 = $$createType1; - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - if ("B" in $$parsedSource) { - $$parsedSource["B"] = $$createField0_0($$parsedSource["B"]); - } - return new StructA($$parsedSource as Partial); - } -} - -export class StructC { - "D": structD; - - /** Creates a new StructC instance. */ - constructor($$source: Partial = {}) { - if (!("D" in $$source)) { - this["D"] = (new structD()); - } - - Object.assign(this, $$source); - } - - /** - * Creates a new StructC instance from a string or object. - */ - static createFrom($$source: any = {}): StructC { - const $$createField0_0 = $$createType2; - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - if ("D" in $$parsedSource) { - $$parsedSource["D"] = $$createField0_0($$parsedSource["D"]); - } - return new StructC($$parsedSource as Partial); - } -} - -export class StructE { - - /** Creates a new StructE instance. */ - constructor($$source: Partial = {}) { - - Object.assign(this, $$source); - } - - /** - * Creates a new StructE instance from a string or object. - */ - static createFrom($$source: any = {}): StructE { - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - return new StructE($$parsedSource as Partial); - } -} - -export class structB { - "A": StructA | null; - - /** Creates a new structB instance. */ - constructor($$source: Partial = {}) { - if (!("A" in $$source)) { - this["A"] = null; - } - - Object.assign(this, $$source); - } - - /** - * Creates a new structB instance from a string or object. - */ - static createFrom($$source: any = {}): structB { - const $$createField0_0 = $$createType4; - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - if ("A" in $$parsedSource) { - $$parsedSource["A"] = $$createField0_0($$parsedSource["A"]); - } - return new structB($$parsedSource as Partial); - } -} - -export class structD { - "E": StructE; - - /** Creates a new structD instance. */ - constructor($$source: Partial = {}) { - if (!("E" in $$source)) { - this["E"] = (new StructE()); - } - - Object.assign(this, $$source); - } - - /** - * Creates a new structD instance from a string or object. - */ - static createFrom($$source: any = {}): structD { - const $$createField0_0 = $$createType5; - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - if ("E" in $$parsedSource) { - $$parsedSource["E"] = $$createField0_0($$parsedSource["E"]); - } - return new structD($$parsedSource as Partial); - } -} - -// Private type creation functions -const $$createType0 = structB.createFrom; -const $$createType1 = $Create.Nullable($$createType0); -const $$createType2 = structD.createFrom; -const $$createType3 = StructA.createFrom; -const $$createType4 = $Create.Nullable($$createType3); -const $$createType5 = StructE.createFrom; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/cyclic_types/greetservice.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/cyclic_types/greetservice.ts deleted file mode 100644 index cbddfb346..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/cyclic_types/greetservice.ts +++ /dev/null @@ -1,63 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * Make a cycle. - */ -export function MakeCycles(): $CancellablePromise<[$models.Cyclic, $models.GenericCyclic<$models.GenericCyclic>]> { - return $Call.ByID(440020721).then(($result: any) => { - $result[0] = $$createType0($result[0]); - $result[1] = $$createType9($result[1]); - return $result; - }); -} - -// Private type creation functions -var $$createType0 = (function $$initCreateType0(...args: any[]): any { - if ($$createType0 === $$initCreateType0) { - $$createType0 = $$createType3; - } - return $$createType0(...args); -}); -const $$createType1 = $Create.Nullable($$createType0); -const $$createType2 = $Create.Map($Create.Any, $$createType1); -const $$createType3 = $Create.Array($$createType2); -var $$createType4 = (function $$initCreateType4(...args: any[]): any { - if ($$createType4 === $$initCreateType4) { - $$createType4 = $$createType8; - } - return $$createType4(...args); -}); -const $$createType5 = $Create.Nullable($$createType4); -const $$createType6 = $Create.Array($Create.Any); -const $$createType7 = $Create.Struct({ - "X": $$createType5, - "Y": $$createType6, -}); -const $$createType8 = $Create.Array($$createType7); -var $$createType9 = (function $$initCreateType9(...args: any[]): any { - if ($$createType9 === $$initCreateType9) { - $$createType9 = $$createType13; - } - return $$createType9(...args); -}); -const $$createType10 = $Create.Nullable($$createType9); -const $$createType11 = $Create.Array($$createType4); -const $$createType12 = $Create.Struct({ - "X": $$createType10, - "Y": $$createType11, -}); -const $$createType13 = $Create.Array($$createType12); diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/cyclic_types/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/cyclic_types/index.ts deleted file mode 100644 index 16cef660c..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/cyclic_types/index.ts +++ /dev/null @@ -1,13 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; - -export type { - Alias, - Cyclic, - GenericCyclic -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/cyclic_types/models.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/cyclic_types/models.ts deleted file mode 100644 index 05c08cc6b..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/cyclic_types/models.ts +++ /dev/null @@ -1,12 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Create as $Create } from "/wails/runtime.js"; - -export type Alias = Cyclic | null; - -export type Cyclic = { [_ in string]?: Alias }[]; - -export type GenericCyclic = {"X": GenericCyclic | null, "Y": T[]}[]; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/index.ts deleted file mode 100644 index b9fbdba96..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/index.ts +++ /dev/null @@ -1,13 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as Service from "./service.js"; -export { - Service -}; - -console.log("Hello everywhere!"); -console.log("Hello everywhere again!"); -console.log("Hello Classes!"); -console.log("Hello TS!"); -console.log("Hello TS Classes!"); diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/internalservice.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/internalservice.ts deleted file mode 100644 index b968330db..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/internalservice.ts +++ /dev/null @@ -1,19 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * An exported but internal service. - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -export function Method($0: $models.InternalModel): $CancellablePromise { - return $Call.ByID(538079117, $0); -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/models.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/models.ts deleted file mode 100644 index 4d242fc2c..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/models.ts +++ /dev/null @@ -1,54 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Create as $Create } from "/wails/runtime.js"; - -/** - * An exported but internal model. - */ -export class InternalModel { - "Field": string; - - /** Creates a new InternalModel instance. */ - constructor($$source: Partial = {}) { - if (!("Field" in $$source)) { - this["Field"] = ""; - } - - Object.assign(this, $$source); - } - - /** - * Creates a new InternalModel instance from a string or object. - */ - static createFrom($$source: any = {}): InternalModel { - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - return new InternalModel($$parsedSource as Partial); - } -} - -/** - * An unexported model. - */ -export class unexportedModel { - "Field": string; - - /** Creates a new unexportedModel instance. */ - constructor($$source: Partial = {}) { - if (!("Field" in $$source)) { - this["Field"] = ""; - } - - Object.assign(this, $$source); - } - - /** - * Creates a new unexportedModel instance from a string or object. - */ - static createFrom($$source: any = {}): unexportedModel { - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - return new unexportedModel($$parsedSource as Partial); - } -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/otherpackage/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/otherpackage/index.ts deleted file mode 100644 index e52a0ccb8..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/otherpackage/index.ts +++ /dev/null @@ -1,6 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -export { - Dummy -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/otherpackage/models.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/otherpackage/models.ts deleted file mode 100644 index b927155d5..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/otherpackage/models.ts +++ /dev/null @@ -1,23 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Create as $Create } from "/wails/runtime.js"; - -export class Dummy { - - /** Creates a new Dummy instance. */ - constructor($$source: Partial = {}) { - - Object.assign(this, $$source); - } - - /** - * Creates a new Dummy instance from a string or object. - */ - static createFrom($$source: any = {}): Dummy { - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - return new Dummy($$parsedSource as Partial); - } -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/otherpackage/test_t.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/otherpackage/test_t.ts deleted file mode 100644 index 6703820f1..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/otherpackage/test_t.ts +++ /dev/null @@ -1,3 +0,0 @@ -import { CustomMethod } from "../service.js"; - -CustomMethod("TS"); diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/otherpackage/test_tc.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/otherpackage/test_tc.ts deleted file mode 100644 index 15d2994e9..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/otherpackage/test_tc.ts +++ /dev/null @@ -1,3 +0,0 @@ -import { CustomMethod } from "../service.js"; - -CustomMethod("TS Classes"); diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/service.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/service.ts deleted file mode 100644 index 338c7fbd1..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/service.ts +++ /dev/null @@ -1,22 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as otherpackage$0 from "./otherpackage/models.js"; - -function InternalMethod($0: string): $CancellablePromise { - return $Call.ByID(3518775569, $0); -} - -export function VisibleMethod($0: otherpackage$0.Dummy): $CancellablePromise { - return $Call.ByID(474018228, $0); -} - -export async function CustomMethod(arg: string): Promise { - await InternalMethod("Hello " + arg + "!"); -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/test.js b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/test.js deleted file mode 100644 index 138385f53..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/test.js +++ /dev/null @@ -1,3 +0,0 @@ -import { CustomMethod } from "./service.js"; - -CustomMethod("everywhere"); diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/test_all.js b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/test_all.js deleted file mode 100644 index 19d5c2f42..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/test_all.js +++ /dev/null @@ -1,3 +0,0 @@ -import { CustomMethod } from "./service.js"; - -CustomMethod("everywhere again"); diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/test_c.js b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/test_c.js deleted file mode 100644 index 724e79e12..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/test_c.js +++ /dev/null @@ -1,3 +0,0 @@ -import { CustomMethod } from "./service.js"; - -CustomMethod("Classes"); diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/test_t.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/test_t.ts deleted file mode 100644 index 253d3f2f6..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/test_t.ts +++ /dev/null @@ -1,3 +0,0 @@ -import { CustomMethod } from "./service.js"; - -CustomMethod("TS"); diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/test_tc.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/test_tc.ts deleted file mode 100644 index 66b739d3a..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/test_tc.ts +++ /dev/null @@ -1,3 +0,0 @@ -import { CustomMethod } from "./service.js"; - -CustomMethod("TS Classes"); diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/unexportedservice.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/unexportedservice.ts deleted file mode 100644 index a819daffd..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/unexportedservice.ts +++ /dev/null @@ -1,19 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * An unexported service. - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -export function Method($0: $models.unexportedModel): $CancellablePromise { - return $Call.ByID(37626172, $0); -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/embedded_interface/greetservice.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/embedded_interface/greetservice.ts deleted file mode 100644 index b5d189f76..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/embedded_interface/greetservice.ts +++ /dev/null @@ -1,47 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -/** - * Comment 1. - */ -export function Method1(): $CancellablePromise { - return $Call.ByID(841558284); -} - -/** - * Comment 2. - */ -export function Method2(): $CancellablePromise { - return $Call.ByID(891891141); -} - -/** - * Comment 3a. - * Comment 3b. - */ -export function Method3(): $CancellablePromise { - return $Call.ByID(875113522); -} - -/** - * Comment 4. - */ -export function Method4(): $CancellablePromise { - return $Call.ByID(791225427); -} - -/** - * Comment 5. - */ -export function Method5(): $CancellablePromise { - return $Call.ByID(774447808); -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/embedded_interface/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/embedded_interface/index.ts deleted file mode 100644 index 50e3f0435..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/embedded_interface/index.ts +++ /dev/null @@ -1,7 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/enum/greetservice.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/enum/greetservice.ts deleted file mode 100644 index 10de8838c..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/enum/greetservice.ts +++ /dev/null @@ -1,35 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * Greet does XYZ - */ -export function Greet(name: string, title: $models.Title): $CancellablePromise { - return $Call.ByID(1411160069, name, title); -} - -/** - * NewPerson creates a new person - */ -export function NewPerson(name: string): $CancellablePromise<$models.Person | null> { - return $Call.ByID(1661412647, name).then(($result: any) => { - return $$createType1($result); - }); -} - -// Private type creation functions -const $$createType0 = $models.Person.createFrom; -const $$createType1 = $Create.Nullable($$createType0); diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/enum/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/enum/index.ts deleted file mode 100644 index 3b4d2f5c6..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/enum/index.ts +++ /dev/null @@ -1,13 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; - -export { - Age, - Person, - Title -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/enum/models.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/enum/models.ts deleted file mode 100644 index a50282a38..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/enum/models.ts +++ /dev/null @@ -1,82 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Create as $Create } from "/wails/runtime.js"; - -/** - * Age is an integer with some predefined values - */ -export type Age = number; - -/** - * Predefined constants for type Age. - * @namespace - */ -export const Age = { - NewBorn: 0, - Teenager: 12, - YoungAdult: 18, - - /** - * Oh no, some grey hair! - */ - MiddleAged: 50, - - /** - * Unbelievable! - */ - Mathusalem: 1000, -}; - -/** - * Person represents a person - */ -export class Person { - "Title": Title; - "Name": string; - "Age": Age; - - /** Creates a new Person instance. */ - constructor($$source: Partial = {}) { - if (!("Title" in $$source)) { - this["Title"] = Title.$zero; - } - if (!("Name" in $$source)) { - this["Name"] = ""; - } - if (!("Age" in $$source)) { - this["Age"] = 0; - } - - Object.assign(this, $$source); - } - - /** - * Creates a new Person instance from a string or object. - */ - static createFrom($$source: any = {}): Person { - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - return new Person($$parsedSource as Partial); - } -} - -/** - * Title is a title - */ -export enum Title { - /** - * The Go zero value for the underlying type of the enum. - */ - $zero = "", - - /** - * Mister is a title - */ - Mister = "Mr", - Miss = "Miss", - Ms = "Ms", - Mrs = "Mrs", - Dr = "Dr", -}; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_from_imported_package/greetservice.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_from_imported_package/greetservice.ts deleted file mode 100644 index 3bce7b000..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_from_imported_package/greetservice.ts +++ /dev/null @@ -1,22 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as services$0 from "./services/models.js"; - -/** - * Greet does XYZ - */ -export function Greet(name: string, title: services$0.Title): $CancellablePromise { - return $Call.ByID(1411160069, name, title); -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_from_imported_package/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_from_imported_package/index.ts deleted file mode 100644 index 50e3f0435..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_from_imported_package/index.ts +++ /dev/null @@ -1,7 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_from_imported_package/services/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_from_imported_package/services/index.ts deleted file mode 100644 index 01c612edc..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_from_imported_package/services/index.ts +++ /dev/null @@ -1,6 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -export { - Title -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_from_imported_package/services/models.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_from_imported_package/services/models.ts deleted file mode 100644 index 661222bdf..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_from_imported_package/services/models.ts +++ /dev/null @@ -1,22 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Create as $Create } from "/wails/runtime.js"; - -export enum Title { - /** - * The Go zero value for the underlying type of the enum. - */ - $zero = "", - - /** - * Mister is a title - */ - Mister = "Mr", - Miss = "Miss", - Ms = "Ms", - Mrs = "Mrs", - Dr = "Dr", -}; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_map_keys/enummapservice.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_map_keys/enummapservice.ts deleted file mode 100644 index dcaa34b3e..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_map_keys/enummapservice.ts +++ /dev/null @@ -1,80 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * EnumMapService tests various enum map key scenarios - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * GetColorCodes returns a map with uint8 enum keys - */ -export function GetColorCodes(): $CancellablePromise<{ [_ in $models.Color]?: string }> { - return $Call.ByID(2794981443).then(($result: any) => { - return $$createType0($result); - }); -} - -/** - * GetNestedEnumMap returns a map with enum keys and complex values - */ -export function GetNestedEnumMap(): $CancellablePromise<{ [_ in $models.Status]?: { [_ in $models.Priority]?: string } }> { - return $Call.ByID(3603489560).then(($result: any) => { - return $$createType2($result); - }); -} - -/** - * GetOptionalEnumMap returns a map with enum keys to optional values - */ -export function GetOptionalEnumMap(): $CancellablePromise<{ [_ in $models.Status]?: string | null }> { - return $Call.ByID(1871606385).then(($result: any) => { - return $$createType3($result); - }); -} - -/** - * GetPersonsByStatus returns a map with enum keys to struct values - */ -export function GetPersonsByStatus(): $CancellablePromise<{ [_ in $models.Status]?: $models.Person[] }> { - return $Call.ByID(2189502217).then(($result: any) => { - return $$createType6($result); - }); -} - -/** - * GetPriorityWeights returns a map with integer enum keys - */ -export function GetPriorityWeights(): $CancellablePromise<{ [_ in $models.Priority]?: number }> { - return $Call.ByID(1542216941).then(($result: any) => { - return $$createType7($result); - }); -} - -/** - * GetStatusMessages returns a map with string enum keys - */ -export function GetStatusMessages(): $CancellablePromise<{ [_ in $models.Status]?: string }> { - return $Call.ByID(1788640810).then(($result: any) => { - return $$createType8($result); - }); -} - -// Private type creation functions -const $$createType0 = $Create.Map($Create.Any, $Create.Any); -const $$createType1 = $Create.Map($Create.Any, $Create.Any); -const $$createType2 = $Create.Map($Create.Any, $$createType1); -const $$createType3 = $Create.Map($Create.Any, $Create.Any); -const $$createType4 = $models.Person.createFrom; -const $$createType5 = $Create.Array($$createType4); -const $$createType6 = $Create.Map($Create.Any, $$createType5); -const $$createType7 = $Create.Map($Create.Any, $Create.Any); -const $$createType8 = $Create.Map($Create.Any, $Create.Any); diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_map_keys/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_map_keys/index.ts deleted file mode 100644 index d209a0f7d..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_map_keys/index.ts +++ /dev/null @@ -1,14 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as EnumMapService from "./enummapservice.js"; -export { - EnumMapService -}; - -export { - Color, - Person, - Priority, - Status -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_map_keys/models.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_map_keys/models.ts deleted file mode 100644 index ba3d2baeb..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_map_keys/models.ts +++ /dev/null @@ -1,77 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Create as $Create } from "/wails/runtime.js"; - -/** - * Color represents color values - */ -export enum Color { - /** - * The Go zero value for the underlying type of the enum. - */ - $zero = 0, - - Red = 1, - Green = 2, - Blue = 3, -}; - -/** - * Person represents a person with status - */ -export class Person { - "Name": string; - "Status": Status; - - /** Creates a new Person instance. */ - constructor($$source: Partial = {}) { - if (!("Name" in $$source)) { - this["Name"] = ""; - } - if (!("Status" in $$source)) { - this["Status"] = Status.$zero; - } - - Object.assign(this, $$source); - } - - /** - * Creates a new Person instance from a string or object. - */ - static createFrom($$source: any = {}): Person { - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - return new Person($$parsedSource as Partial); - } -} - -/** - * Priority represents priority levels - */ -export enum Priority { - /** - * The Go zero value for the underlying type of the enum. - */ - $zero = 0, - - PriorityLow = 1, - PriorityMedium = 2, - PriorityHigh = 3, -}; - -/** - * Status represents different status values - */ -export enum Status { - /** - * The Go zero value for the underlying type of the enum. - */ - $zero = "", - - StatusPending = "pending", - StatusRunning = "running", - StatusCompleted = "completed", - StatusFailed = "failed", -}; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/events_only/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/events_only/index.ts deleted file mode 100644 index bb6e0a17f..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/events_only/index.ts +++ /dev/null @@ -1,6 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -export { - SomeClass -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/events_only/models.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/events_only/models.ts deleted file mode 100644 index 4719f61cf..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/events_only/models.ts +++ /dev/null @@ -1,45 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Create as $Create } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as nobindingshere$0 from "../no_bindings_here/models.js"; - -/** - * SomeClass renders as a TS class. - */ -export class SomeClass { - "Field": string; - "Meadow": nobindingshere$0.HowDifferent; - - /** Creates a new SomeClass instance. */ - constructor($$source: Partial = {}) { - if (!("Field" in $$source)) { - this["Field"] = ""; - } - if (!("Meadow" in $$source)) { - this["Meadow"] = (new nobindingshere$0.HowDifferent()); - } - - Object.assign(this, $$source); - } - - /** - * Creates a new SomeClass instance from a string or object. - */ - static createFrom($$source: any = {}): SomeClass { - const $$createField1_0 = $$createType0; - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - if ("Meadow" in $$parsedSource) { - $$parsedSource["Meadow"] = $$createField1_0($$parsedSource["Meadow"]); - } - return new SomeClass($$parsedSource as Partial); - } -} - -// Private type creation functions -const $$createType0 = nobindingshere$0.HowDifferent.createFrom($Create.Any); diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_imported_package/greetservice.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_imported_package/greetservice.ts deleted file mode 100644 index 88cafa9d1..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_imported_package/greetservice.ts +++ /dev/null @@ -1,35 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * Greet does XYZ - */ -export function Greet(name: string): $CancellablePromise { - return $Call.ByID(1411160069, name); -} - -/** - * NewPerson creates a new person - */ -export function NewPerson(name: string): $CancellablePromise<$models.Person | null> { - return $Call.ByID(1661412647, name).then(($result: any) => { - return $$createType1($result); - }); -} - -// Private type creation functions -const $$createType0 = $models.Person.createFrom; -const $$createType1 = $Create.Nullable($$createType0); diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_imported_package/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_imported_package/index.ts deleted file mode 100644 index f95c1b558..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_imported_package/index.ts +++ /dev/null @@ -1,11 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; - -export { - Person -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_imported_package/models.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_imported_package/models.ts deleted file mode 100644 index f1ff262a1..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_imported_package/models.ts +++ /dev/null @@ -1,46 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Create as $Create } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as services$0 from "./services/models.js"; - -/** - * Person is a person - */ -export class Person { - "Name": string; - "Address": services$0.Address | null; - - /** Creates a new Person instance. */ - constructor($$source: Partial = {}) { - if (!("Name" in $$source)) { - this["Name"] = ""; - } - if (!("Address" in $$source)) { - this["Address"] = null; - } - - Object.assign(this, $$source); - } - - /** - * Creates a new Person instance from a string or object. - */ - static createFrom($$source: any = {}): Person { - const $$createField1_0 = $$createType1; - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - if ("Address" in $$parsedSource) { - $$parsedSource["Address"] = $$createField1_0($$parsedSource["Address"]); - } - return new Person($$parsedSource as Partial); - } -} - -// Private type creation functions -const $$createType0 = services$0.Address.createFrom; -const $$createType1 = $Create.Nullable($$createType0); diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_imported_package/services/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_imported_package/services/index.ts deleted file mode 100644 index e4d86b717..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_imported_package/services/index.ts +++ /dev/null @@ -1,11 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as OtherService from "./otherservice.js"; -export { - OtherService -}; - -export { - Address -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_imported_package/services/models.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_imported_package/services/models.ts deleted file mode 100644 index a4be6e904..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_imported_package/services/models.ts +++ /dev/null @@ -1,35 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Create as $Create } from "/wails/runtime.js"; - -export class Address { - "Street": string; - "State": string; - "Country": string; - - /** Creates a new Address instance. */ - constructor($$source: Partial
                    = {}) { - if (!("Street" in $$source)) { - this["Street"] = ""; - } - if (!("State" in $$source)) { - this["State"] = ""; - } - if (!("Country" in $$source)) { - this["Country"] = ""; - } - - Object.assign(this, $$source); - } - - /** - * Creates a new Address instance from a string or object. - */ - static createFrom($$source: any = {}): Address { - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - return new Address($$parsedSource as Partial
                    ); - } -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_imported_package/services/otherservice.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_imported_package/services/otherservice.ts deleted file mode 100644 index 8dc381545..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_imported_package/services/otherservice.ts +++ /dev/null @@ -1,29 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * OtherService is a struct - * that does things - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * Yay does this and that - */ -export function Yay(): $CancellablePromise<$models.Address | null> { - return $Call.ByID(2007737399).then(($result: any) => { - return $$createType1($result); - }); -} - -// Private type creation functions -const $$createType0 = $models.Address.createFrom; -const $$createType1 = $Create.Nullable($$createType0); diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_nested_imported_package/greetservice.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_nested_imported_package/greetservice.ts deleted file mode 100644 index 88cafa9d1..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_nested_imported_package/greetservice.ts +++ /dev/null @@ -1,35 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * Greet does XYZ - */ -export function Greet(name: string): $CancellablePromise { - return $Call.ByID(1411160069, name); -} - -/** - * NewPerson creates a new person - */ -export function NewPerson(name: string): $CancellablePromise<$models.Person | null> { - return $Call.ByID(1661412647, name).then(($result: any) => { - return $$createType1($result); - }); -} - -// Private type creation functions -const $$createType0 = $models.Person.createFrom; -const $$createType1 = $Create.Nullable($$createType0); diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_nested_imported_package/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_nested_imported_package/index.ts deleted file mode 100644 index f95c1b558..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_nested_imported_package/index.ts +++ /dev/null @@ -1,11 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; - -export { - Person -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_nested_imported_package/models.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_nested_imported_package/models.ts deleted file mode 100644 index 88b2c78db..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_nested_imported_package/models.ts +++ /dev/null @@ -1,43 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Create as $Create } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as other$0 from "./services/other/models.js"; - -export class Person { - "Name": string; - "Address": other$0.Address | null; - - /** Creates a new Person instance. */ - constructor($$source: Partial = {}) { - if (!("Name" in $$source)) { - this["Name"] = ""; - } - if (!("Address" in $$source)) { - this["Address"] = null; - } - - Object.assign(this, $$source); - } - - /** - * Creates a new Person instance from a string or object. - */ - static createFrom($$source: any = {}): Person { - const $$createField1_0 = $$createType1; - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - if ("Address" in $$parsedSource) { - $$parsedSource["Address"] = $$createField1_0($$parsedSource["Address"]); - } - return new Person($$parsedSource as Partial); - } -} - -// Private type creation functions -const $$createType0 = other$0.Address.createFrom; -const $$createType1 = $Create.Nullable($$createType0); diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_nested_imported_package/services/other/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_nested_imported_package/services/other/index.ts deleted file mode 100644 index e4d86b717..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_nested_imported_package/services/other/index.ts +++ /dev/null @@ -1,11 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as OtherService from "./otherservice.js"; -export { - OtherService -}; - -export { - Address -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_nested_imported_package/services/other/models.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_nested_imported_package/services/other/models.ts deleted file mode 100644 index a4be6e904..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_nested_imported_package/services/other/models.ts +++ /dev/null @@ -1,35 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Create as $Create } from "/wails/runtime.js"; - -export class Address { - "Street": string; - "State": string; - "Country": string; - - /** Creates a new Address instance. */ - constructor($$source: Partial
                    = {}) { - if (!("Street" in $$source)) { - this["Street"] = ""; - } - if (!("State" in $$source)) { - this["State"] = ""; - } - if (!("Country" in $$source)) { - this["Country"] = ""; - } - - Object.assign(this, $$source); - } - - /** - * Creates a new Address instance from a string or object. - */ - static createFrom($$source: any = {}): Address { - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - return new Address($$parsedSource as Partial
                    ); - } -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_nested_imported_package/services/other/otherservice.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_nested_imported_package/services/other/otherservice.ts deleted file mode 100644 index fe69a1da0..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_nested_imported_package/services/other/otherservice.ts +++ /dev/null @@ -1,29 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * OtherService is a struct - * that does things - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * Yay does this and that - */ -export function Yay(): $CancellablePromise<$models.Address | null> { - return $Call.ByID(2447353446).then(($result: any) => { - return $$createType1($result); - }); -} - -// Private type creation functions -const $$createType0 = $models.Address.createFrom; -const $$createType1 = $Create.Nullable($$createType0); diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_multiple_files/greetservice.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_multiple_files/greetservice.ts deleted file mode 100644 index 62283209b..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_multiple_files/greetservice.ts +++ /dev/null @@ -1,10 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -export function Greet(name: string): $CancellablePromise { - return $Call.ByID(1411160069, name); -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_multiple_files/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_multiple_files/index.ts deleted file mode 100644 index 50e3f0435..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_multiple_files/index.ts +++ /dev/null @@ -1,7 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single/greetservice.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single/greetservice.ts deleted file mode 100644 index 6e6ac2007..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single/greetservice.ts +++ /dev/null @@ -1,18 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -/** - * Greet someone - */ -export function Greet(name: string): $CancellablePromise { - return $Call.ByID(1411160069, name); -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single/index.ts deleted file mode 100644 index 50e3f0435..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single/index.ts +++ /dev/null @@ -1,7 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single_context/greetservice.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single_context/greetservice.ts deleted file mode 100644 index 386913d65..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single_context/greetservice.ts +++ /dev/null @@ -1,25 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -/** - * Greet someone - */ -export function Greet(name: string): $CancellablePromise { - return $Call.ByID(1411160069, name); -} - -/** - * Greet someone - */ -export function GreetWithContext(name: string): $CancellablePromise { - return $Call.ByID(1310150960, name); -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single_context/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single_context/index.ts deleted file mode 100644 index 50e3f0435..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single_context/index.ts +++ /dev/null @@ -1,7 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single_internal/greetservice.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single_internal/greetservice.ts deleted file mode 100644 index 6e6ac2007..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single_internal/greetservice.ts +++ /dev/null @@ -1,18 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -/** - * Greet someone - */ -export function Greet(name: string): $CancellablePromise { - return $Call.ByID(1411160069, name); -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single_internal/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single_internal/index.ts deleted file mode 100644 index 50e3f0435..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single_internal/index.ts +++ /dev/null @@ -1,7 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys/index.ts deleted file mode 100644 index 8d52924fe..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys/index.ts +++ /dev/null @@ -1,35 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as Service from "./service.js"; -export { - Service -}; - -export { - Maps -} from "./models.js"; - -export type { - BasicCstrAlias, - ComparableCstrAlias, - EmbeddedCustomInterface, - EmbeddedOriginalInterface, - EmbeddedPointer, - EmbeddedPointerPtr, - EmbeddedValue, - EmbeddedValuePtr, - GoodTildeCstrAlias, - IntAlias, - IntType, - InterfaceCstrAlias, - MixedCstrAlias, - NonBasicCstrAlias, - PointableCstrAlias, - PointerAlias, - PointerTextMarshaler, - StringAlias, - StringType, - ValueAlias, - ValueTextMarshaler -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys/models.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys/models.ts deleted file mode 100644 index b0f112227..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys/models.ts +++ /dev/null @@ -1,1890 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Create as $Create } from "/wails/runtime.js"; - -export type BasicCstrAlias = S; - -export type ComparableCstrAlias = R; - -export type EmbeddedCustomInterface = string; - -export type EmbeddedOriginalInterface = string; - -export type EmbeddedPointer = string; - -export type EmbeddedPointerPtr = string; - -export type EmbeddedValue = string; - -export type EmbeddedValuePtr = string; - -export type GoodTildeCstrAlias = U; - -export type IntAlias = number; - -export type IntType = number; - -export type InterfaceCstrAlias = Y; - -export class Maps { - /** - * Reject - */ - "Bool": { [_ in string]?: number }; - - /** - * Accept - */ - "Int": { [_ in `${number}`]?: number }; - - /** - * Accept - */ - "Uint": { [_ in `${number}`]?: number }; - - /** - * Reject - */ - "Float": { [_ in string]?: number }; - - /** - * Reject - */ - "Complex": { [_ in string]?: number }; - - /** - * Accept - */ - "Byte": { [_ in `${number}`]?: number }; - - /** - * Accept - */ - "Rune": { [_ in `${number}`]?: number }; - - /** - * Accept - */ - "String": { [_ in string]?: number }; - - /** - * Reject - */ - "IntPtr": { [_ in string]?: number }; - - /** - * Reject - */ - "UintPtr": { [_ in string]?: number }; - - /** - * Reject - */ - "FloatPtr": { [_ in string]?: number }; - - /** - * Reject - */ - "ComplexPtr": { [_ in string]?: number }; - - /** - * Reject - */ - "StringPtr": { [_ in string]?: number }; - - /** - * Reject - */ - "NTM": { [_ in string]?: number }; - - /** - * Reject - */ - "NTMPtr": { [_ in string]?: number }; - - /** - * Accept - */ - "VTM": { [_ in ValueTextMarshaler]?: number }; - - /** - * Accept - */ - "VTMPtr": { [_ in ValueTextMarshaler]?: number }; - - /** - * Reject - */ - "PTM": { [_ in string]?: number }; - - /** - * Accept - */ - "PTMPtr": { [_ in PointerTextMarshaler]?: number }; - - /** - * Accept, hide - */ - "JTM": { [_ in string]?: number }; - - /** - * Accept, hide - */ - "JTMPtr": { [_ in string]?: number }; - - /** - * Reject - */ - "A": { [_ in string]?: number }; - - /** - * Reject - */ - "APtr": { [_ in string]?: number }; - - /** - * Accept, hide - */ - "TM": { [_ in string]?: number }; - - /** - * Reject - */ - "TMPtr": { [_ in string]?: number }; - - /** - * Accept, hide - */ - "CI": { [_ in string]?: number }; - - /** - * Reject - */ - "CIPtr": { [_ in string]?: number }; - - /** - * Accept, hide - */ - "EI": { [_ in string]?: number }; - - /** - * Reject - */ - "EIPtr": { [_ in string]?: number }; - - /** - * Accept - */ - "EV": { [_ in EmbeddedValue]?: number }; - - /** - * Accept - */ - "EVPtr": { [_ in EmbeddedValue]?: number }; - - /** - * Accept - */ - "EVP": { [_ in EmbeddedValuePtr]?: number }; - - /** - * Accept - */ - "EVPPtr": { [_ in EmbeddedValuePtr]?: number }; - - /** - * Reject - */ - "EP": { [_ in string]?: number }; - - /** - * Accept - */ - "EPPtr": { [_ in EmbeddedPointer]?: number }; - - /** - * Accept - */ - "EPP": { [_ in EmbeddedPointerPtr]?: number }; - - /** - * Accept - */ - "EPPPtr": { [_ in EmbeddedPointerPtr]?: number }; - - /** - * Accept - */ - "ECI": { [_ in EmbeddedCustomInterface]?: number }; - - /** - * Accept - */ - "ECIPtr": { [_ in EmbeddedCustomInterface]?: number }; - - /** - * Accept - */ - "EOI": { [_ in EmbeddedOriginalInterface]?: number }; - - /** - * Accept - */ - "EOIPtr": { [_ in EmbeddedOriginalInterface]?: number }; - - /** - * Reject - */ - "WT": { [_ in string]?: number }; - - /** - * Reject - */ - "WA": { [_ in string]?: number }; - - /** - * Accept - */ - "ST": { [_ in StringType]?: number }; - - /** - * Accept - */ - "SA": { [_ in StringAlias]?: number }; - - /** - * Accept - */ - "IntT": { [_ in IntType]?: number }; - - /** - * Accept - */ - "IntA": { [_ in IntAlias]?: number }; - - /** - * Reject - */ - "VT": { [_ in string]?: number }; - - /** - * Reject - */ - "VTPtr": { [_ in string]?: number }; - - /** - * Reject - */ - "VPT": { [_ in string]?: number }; - - /** - * Reject - */ - "VPTPtr": { [_ in string]?: number }; - - /** - * Accept - */ - "VA": { [_ in ValueAlias]?: number }; - - /** - * Accept - */ - "VAPtr": { [_ in ValueAlias]?: number }; - - /** - * Accept, hide - */ - "VPA": { [_ in string]?: number }; - - /** - * Reject - */ - "VPAPtr": { [_ in string]?: number }; - - /** - * Reject - */ - "PT": { [_ in string]?: number }; - - /** - * Reject - */ - "PTPtr": { [_ in string]?: number }; - - /** - * Reject - */ - "PPT": { [_ in string]?: number }; - - /** - * Reject - */ - "PPTPtr": { [_ in string]?: number }; - - /** - * Reject - */ - "PA": { [_ in string]?: number }; - - /** - * Accept - */ - "PAPtr": { [_ in PointerAlias]?: number }; - - /** - * Accept, hide - */ - "PPA": { [_ in string]?: number }; - - /** - * Reject - */ - "PPAPtr": { [_ in string]?: number }; - - /** - * Accept, hide - */ - "IT": { [_ in string]?: number }; - - /** - * Reject - */ - "ITPtr": { [_ in string]?: number }; - - /** - * Reject - */ - "IPT": { [_ in string]?: number }; - - /** - * Reject - */ - "IPTPtr": { [_ in string]?: number }; - - /** - * Accept, hide - */ - "IA": { [_ in string]?: number }; - - /** - * Reject - */ - "IAPtr": { [_ in string]?: number }; - - /** - * Reject - */ - "IPA": { [_ in string]?: number }; - - /** - * Reject - */ - "IPAPtr": { [_ in string]?: number }; - - /** - * Soft reject - */ - "TPR": { [_ in string]?: number }; - - /** - * Soft reject - */ - "TPRPtr": { [_ in string]?: number }; - - /** - * Accept, hide - */ - "TPS": { [_ in string]?: number }; - - /** - * Soft reject - */ - "TPSPtr": { [_ in string]?: number }; - - /** - * Soft reject - */ - "TPT": { [_ in string]?: number }; - - /** - * Soft reject - */ - "TPTPtr": { [_ in string]?: number }; - - /** - * Accept, hide - */ - "TPU": { [_ in string]?: number }; - - /** - * Soft reject - */ - "TPUPtr": { [_ in string]?: number }; - - /** - * Accept, hide - */ - "TPV": { [_ in string]?: number }; - - /** - * Soft reject - */ - "TPVPtr": { [_ in string]?: number }; - - /** - * Soft reject - */ - "TPW": { [_ in string]?: number }; - - /** - * Accept, hide - */ - "TPWPtr": { [_ in string]?: number }; - - /** - * Accept, hide - */ - "TPX": { [_ in string]?: number }; - - /** - * Soft reject - */ - "TPXPtr": { [_ in string]?: number }; - - /** - * Accept, hide - */ - "TPY": { [_ in string]?: number }; - - /** - * Soft reject - */ - "TPYPtr": { [_ in string]?: number }; - - /** - * Accept, hide - */ - "TPZ": { [_ in string]?: number }; - - /** - * Soft reject - */ - "TPZPtr": { [_ in string]?: number }; - - /** - * Soft reject - */ - "GAR": { [_ in string]?: number }; - - /** - * Soft reject - */ - "GARPtr": { [_ in string]?: number }; - - /** - * Accept, hide - */ - "GAS": { [_ in string]?: number }; - - /** - * Soft reject - */ - "GASPtr": { [_ in string]?: number }; - - /** - * Soft reject - */ - "GAT": { [_ in string]?: number }; - - /** - * Soft reject - */ - "GATPtr": { [_ in string]?: number }; - - /** - * Accept, hide - */ - "GAU": { [_ in string]?: number }; - - /** - * Soft reject - */ - "GAUPtr": { [_ in string]?: number }; - - /** - * Accept, hide - */ - "GAV": { [_ in string]?: number }; - - /** - * Soft reject - */ - "GAVPtr": { [_ in string]?: number }; - - /** - * Soft reject - */ - "GAW": { [_ in string]?: number }; - - /** - * Accept, hide - */ - "GAWPtr": { [_ in string]?: number }; - - /** - * Accept, hide - */ - "GAX": { [_ in string]?: number }; - - /** - * Soft reject - */ - "GAXPtr": { [_ in string]?: number }; - - /** - * Accept, hide - */ - "GAY": { [_ in string]?: number }; - - /** - * Soft reject - */ - "GAYPtr": { [_ in string]?: number }; - - /** - * Accept, hide - */ - "GAZ": { [_ in string]?: number }; - - /** - * Soft reject - */ - "GAZPtr": { [_ in string]?: number }; - - /** - * Accept - */ - "GACi": { [_ in ComparableCstrAlias]?: number }; - - /** - * Accept - */ - "GACV": { [_ in ComparableCstrAlias]?: number }; - - /** - * Reject - */ - "GACP": { [_ in string]?: number }; - - /** - * Reject - */ - "GACiPtr": { [_ in string]?: number }; - - /** - * Accept, hide - */ - "GACVPtr": { [_ in string]?: number }; - - /** - * Accept, hide - */ - "GACPPtr": { [_ in string]?: number }; - - /** - * Accept - */ - "GABi": { [_ in BasicCstrAlias]?: number }; - - /** - * Accept - */ - "GABs": { [_ in BasicCstrAlias]?: number }; - - /** - * Reject - */ - "GABiPtr": { [_ in string]?: number }; - - /** - * Reject - */ - "GABT": { [_ in string]?: number }; - - /** - * Reject - */ - "GABTPtr": { [_ in string]?: number }; - - /** - * Accept - */ - "GAGT": { [_ in GoodTildeCstrAlias]?: number }; - - /** - * Accept, hide - */ - "GAGTPtr": { [_ in string]?: number }; - - /** - * Accept - */ - "GANBV": { [_ in NonBasicCstrAlias]?: number }; - - /** - * Accept, hide - */ - "GANBP": { [_ in string]?: number }; - - /** - * Accept, hide - */ - "GANBVPtr": { [_ in string]?: number }; - - /** - * Reject - */ - "GANBPPtr": { [_ in string]?: number }; - - /** - * Accept - */ - "GAPlV1": { [_ in PointableCstrAlias]?: number }; - - /** - * Accept - */ - "GAPlV2": { [_ in PointableCstrAlias]?: number }; - - /** - * Reject - */ - "GAPlP1": { [_ in string]?: number }; - - /** - * Accept - */ - "GAPlP2": { [_ in PointableCstrAlias]?: number }; - - /** - * Accept, hide - */ - "GAPlVPtr": { [_ in string]?: number }; - - /** - * Accept, hide - */ - "GAPlPPtr": { [_ in string]?: number }; - - /** - * Accept - */ - "GAMi": { [_ in MixedCstrAlias]?: number }; - - /** - * Accept - */ - "GAMS": { [_ in MixedCstrAlias]?: number }; - - /** - * Accept - */ - "GAMV": { [_ in MixedCstrAlias]?: number }; - - /** - * Reject - */ - "GAMSPtr": { [_ in string]?: number }; - - /** - * Accept, hide - */ - "GAMVPtr": { [_ in string]?: number }; - - /** - * Accept, hide - */ - "GAII": { [_ in string]?: number }; - - /** - * Accept - */ - "GAIV": { [_ in InterfaceCstrAlias]?: number }; - - /** - * Accept, hide - */ - "GAIP": { [_ in string]?: number }; - - /** - * Reject - */ - "GAIIPtr": { [_ in string]?: number }; - - /** - * Accept, hide - */ - "GAIVPtr": { [_ in string]?: number }; - - /** - * Reject - */ - "GAIPPtr": { [_ in string]?: number }; - - /** - * Accept, hide - */ - "GAPrV": { [_ in string]?: number }; - - /** - * Accept, hide - */ - "GAPrP": { [_ in string]?: number }; - - /** - * Reject - */ - "GAPrVPtr": { [_ in string]?: number }; - - /** - * Reject - */ - "GAPrPPtr": { [_ in string]?: number }; - - /** Creates a new Maps instance. */ - constructor($$source: Partial> = {}) { - if (!("Bool" in $$source)) { - this["Bool"] = {}; - } - if (!("Int" in $$source)) { - this["Int"] = {}; - } - if (!("Uint" in $$source)) { - this["Uint"] = {}; - } - if (!("Float" in $$source)) { - this["Float"] = {}; - } - if (!("Complex" in $$source)) { - this["Complex"] = {}; - } - if (!("Byte" in $$source)) { - this["Byte"] = {}; - } - if (!("Rune" in $$source)) { - this["Rune"] = {}; - } - if (!("String" in $$source)) { - this["String"] = {}; - } - if (!("IntPtr" in $$source)) { - this["IntPtr"] = {}; - } - if (!("UintPtr" in $$source)) { - this["UintPtr"] = {}; - } - if (!("FloatPtr" in $$source)) { - this["FloatPtr"] = {}; - } - if (!("ComplexPtr" in $$source)) { - this["ComplexPtr"] = {}; - } - if (!("StringPtr" in $$source)) { - this["StringPtr"] = {}; - } - if (!("NTM" in $$source)) { - this["NTM"] = {}; - } - if (!("NTMPtr" in $$source)) { - this["NTMPtr"] = {}; - } - if (!("VTM" in $$source)) { - this["VTM"] = {}; - } - if (!("VTMPtr" in $$source)) { - this["VTMPtr"] = {}; - } - if (!("PTM" in $$source)) { - this["PTM"] = {}; - } - if (!("PTMPtr" in $$source)) { - this["PTMPtr"] = {}; - } - if (!("JTM" in $$source)) { - this["JTM"] = {}; - } - if (!("JTMPtr" in $$source)) { - this["JTMPtr"] = {}; - } - if (!("A" in $$source)) { - this["A"] = {}; - } - if (!("APtr" in $$source)) { - this["APtr"] = {}; - } - if (!("TM" in $$source)) { - this["TM"] = {}; - } - if (!("TMPtr" in $$source)) { - this["TMPtr"] = {}; - } - if (!("CI" in $$source)) { - this["CI"] = {}; - } - if (!("CIPtr" in $$source)) { - this["CIPtr"] = {}; - } - if (!("EI" in $$source)) { - this["EI"] = {}; - } - if (!("EIPtr" in $$source)) { - this["EIPtr"] = {}; - } - if (!("EV" in $$source)) { - this["EV"] = {}; - } - if (!("EVPtr" in $$source)) { - this["EVPtr"] = {}; - } - if (!("EVP" in $$source)) { - this["EVP"] = {}; - } - if (!("EVPPtr" in $$source)) { - this["EVPPtr"] = {}; - } - if (!("EP" in $$source)) { - this["EP"] = {}; - } - if (!("EPPtr" in $$source)) { - this["EPPtr"] = {}; - } - if (!("EPP" in $$source)) { - this["EPP"] = {}; - } - if (!("EPPPtr" in $$source)) { - this["EPPPtr"] = {}; - } - if (!("ECI" in $$source)) { - this["ECI"] = {}; - } - if (!("ECIPtr" in $$source)) { - this["ECIPtr"] = {}; - } - if (!("EOI" in $$source)) { - this["EOI"] = {}; - } - if (!("EOIPtr" in $$source)) { - this["EOIPtr"] = {}; - } - if (!("WT" in $$source)) { - this["WT"] = {}; - } - if (!("WA" in $$source)) { - this["WA"] = {}; - } - if (!("ST" in $$source)) { - this["ST"] = {}; - } - if (!("SA" in $$source)) { - this["SA"] = {}; - } - if (!("IntT" in $$source)) { - this["IntT"] = {}; - } - if (!("IntA" in $$source)) { - this["IntA"] = {}; - } - if (!("VT" in $$source)) { - this["VT"] = {}; - } - if (!("VTPtr" in $$source)) { - this["VTPtr"] = {}; - } - if (!("VPT" in $$source)) { - this["VPT"] = {}; - } - if (!("VPTPtr" in $$source)) { - this["VPTPtr"] = {}; - } - if (!("VA" in $$source)) { - this["VA"] = {}; - } - if (!("VAPtr" in $$source)) { - this["VAPtr"] = {}; - } - if (!("VPA" in $$source)) { - this["VPA"] = {}; - } - if (!("VPAPtr" in $$source)) { - this["VPAPtr"] = {}; - } - if (!("PT" in $$source)) { - this["PT"] = {}; - } - if (!("PTPtr" in $$source)) { - this["PTPtr"] = {}; - } - if (!("PPT" in $$source)) { - this["PPT"] = {}; - } - if (!("PPTPtr" in $$source)) { - this["PPTPtr"] = {}; - } - if (!("PA" in $$source)) { - this["PA"] = {}; - } - if (!("PAPtr" in $$source)) { - this["PAPtr"] = {}; - } - if (!("PPA" in $$source)) { - this["PPA"] = {}; - } - if (!("PPAPtr" in $$source)) { - this["PPAPtr"] = {}; - } - if (!("IT" in $$source)) { - this["IT"] = {}; - } - if (!("ITPtr" in $$source)) { - this["ITPtr"] = {}; - } - if (!("IPT" in $$source)) { - this["IPT"] = {}; - } - if (!("IPTPtr" in $$source)) { - this["IPTPtr"] = {}; - } - if (!("IA" in $$source)) { - this["IA"] = {}; - } - if (!("IAPtr" in $$source)) { - this["IAPtr"] = {}; - } - if (!("IPA" in $$source)) { - this["IPA"] = {}; - } - if (!("IPAPtr" in $$source)) { - this["IPAPtr"] = {}; - } - if (!("TPR" in $$source)) { - this["TPR"] = {}; - } - if (!("TPRPtr" in $$source)) { - this["TPRPtr"] = {}; - } - if (!("TPS" in $$source)) { - this["TPS"] = {}; - } - if (!("TPSPtr" in $$source)) { - this["TPSPtr"] = {}; - } - if (!("TPT" in $$source)) { - this["TPT"] = {}; - } - if (!("TPTPtr" in $$source)) { - this["TPTPtr"] = {}; - } - if (!("TPU" in $$source)) { - this["TPU"] = {}; - } - if (!("TPUPtr" in $$source)) { - this["TPUPtr"] = {}; - } - if (!("TPV" in $$source)) { - this["TPV"] = {}; - } - if (!("TPVPtr" in $$source)) { - this["TPVPtr"] = {}; - } - if (!("TPW" in $$source)) { - this["TPW"] = {}; - } - if (!("TPWPtr" in $$source)) { - this["TPWPtr"] = {}; - } - if (!("TPX" in $$source)) { - this["TPX"] = {}; - } - if (!("TPXPtr" in $$source)) { - this["TPXPtr"] = {}; - } - if (!("TPY" in $$source)) { - this["TPY"] = {}; - } - if (!("TPYPtr" in $$source)) { - this["TPYPtr"] = {}; - } - if (!("TPZ" in $$source)) { - this["TPZ"] = {}; - } - if (!("TPZPtr" in $$source)) { - this["TPZPtr"] = {}; - } - if (!("GAR" in $$source)) { - this["GAR"] = {}; - } - if (!("GARPtr" in $$source)) { - this["GARPtr"] = {}; - } - if (!("GAS" in $$source)) { - this["GAS"] = {}; - } - if (!("GASPtr" in $$source)) { - this["GASPtr"] = {}; - } - if (!("GAT" in $$source)) { - this["GAT"] = {}; - } - if (!("GATPtr" in $$source)) { - this["GATPtr"] = {}; - } - if (!("GAU" in $$source)) { - this["GAU"] = {}; - } - if (!("GAUPtr" in $$source)) { - this["GAUPtr"] = {}; - } - if (!("GAV" in $$source)) { - this["GAV"] = {}; - } - if (!("GAVPtr" in $$source)) { - this["GAVPtr"] = {}; - } - if (!("GAW" in $$source)) { - this["GAW"] = {}; - } - if (!("GAWPtr" in $$source)) { - this["GAWPtr"] = {}; - } - if (!("GAX" in $$source)) { - this["GAX"] = {}; - } - if (!("GAXPtr" in $$source)) { - this["GAXPtr"] = {}; - } - if (!("GAY" in $$source)) { - this["GAY"] = {}; - } - if (!("GAYPtr" in $$source)) { - this["GAYPtr"] = {}; - } - if (!("GAZ" in $$source)) { - this["GAZ"] = {}; - } - if (!("GAZPtr" in $$source)) { - this["GAZPtr"] = {}; - } - if (!("GACi" in $$source)) { - this["GACi"] = {}; - } - if (!("GACV" in $$source)) { - this["GACV"] = {}; - } - if (!("GACP" in $$source)) { - this["GACP"] = {}; - } - if (!("GACiPtr" in $$source)) { - this["GACiPtr"] = {}; - } - if (!("GACVPtr" in $$source)) { - this["GACVPtr"] = {}; - } - if (!("GACPPtr" in $$source)) { - this["GACPPtr"] = {}; - } - if (!("GABi" in $$source)) { - this["GABi"] = {}; - } - if (!("GABs" in $$source)) { - this["GABs"] = {}; - } - if (!("GABiPtr" in $$source)) { - this["GABiPtr"] = {}; - } - if (!("GABT" in $$source)) { - this["GABT"] = {}; - } - if (!("GABTPtr" in $$source)) { - this["GABTPtr"] = {}; - } - if (!("GAGT" in $$source)) { - this["GAGT"] = {}; - } - if (!("GAGTPtr" in $$source)) { - this["GAGTPtr"] = {}; - } - if (!("GANBV" in $$source)) { - this["GANBV"] = {}; - } - if (!("GANBP" in $$source)) { - this["GANBP"] = {}; - } - if (!("GANBVPtr" in $$source)) { - this["GANBVPtr"] = {}; - } - if (!("GANBPPtr" in $$source)) { - this["GANBPPtr"] = {}; - } - if (!("GAPlV1" in $$source)) { - this["GAPlV1"] = {}; - } - if (!("GAPlV2" in $$source)) { - this["GAPlV2"] = {}; - } - if (!("GAPlP1" in $$source)) { - this["GAPlP1"] = {}; - } - if (!("GAPlP2" in $$source)) { - this["GAPlP2"] = {}; - } - if (!("GAPlVPtr" in $$source)) { - this["GAPlVPtr"] = {}; - } - if (!("GAPlPPtr" in $$source)) { - this["GAPlPPtr"] = {}; - } - if (!("GAMi" in $$source)) { - this["GAMi"] = {}; - } - if (!("GAMS" in $$source)) { - this["GAMS"] = {}; - } - if (!("GAMV" in $$source)) { - this["GAMV"] = {}; - } - if (!("GAMSPtr" in $$source)) { - this["GAMSPtr"] = {}; - } - if (!("GAMVPtr" in $$source)) { - this["GAMVPtr"] = {}; - } - if (!("GAII" in $$source)) { - this["GAII"] = {}; - } - if (!("GAIV" in $$source)) { - this["GAIV"] = {}; - } - if (!("GAIP" in $$source)) { - this["GAIP"] = {}; - } - if (!("GAIIPtr" in $$source)) { - this["GAIIPtr"] = {}; - } - if (!("GAIVPtr" in $$source)) { - this["GAIVPtr"] = {}; - } - if (!("GAIPPtr" in $$source)) { - this["GAIPPtr"] = {}; - } - if (!("GAPrV" in $$source)) { - this["GAPrV"] = {}; - } - if (!("GAPrP" in $$source)) { - this["GAPrP"] = {}; - } - if (!("GAPrVPtr" in $$source)) { - this["GAPrVPtr"] = {}; - } - if (!("GAPrPPtr" in $$source)) { - this["GAPrPPtr"] = {}; - } - - Object.assign(this, $$source); - } - - /** - * Given creation functions for each type parameter, - * returns a creation function for a concrete instance - * of the generic class Maps. - */ - static createFrom($$createParamR: (source: any) => R, $$createParamS: (source: any) => S, $$createParamT: (source: any) => T, $$createParamU: (source: any) => U, $$createParamV: (source: any) => V, $$createParamW: (source: any) => W, $$createParamX: (source: any) => X, $$createParamY: (source: any) => Y, $$createParamZ: (source: any) => Z): ($$source?: any) => Maps { - const $$createField0_0 = $$createType0; - const $$createField1_0 = $$createType1; - const $$createField2_0 = $$createType2; - const $$createField3_0 = $$createType3; - const $$createField4_0 = $$createType4; - const $$createField5_0 = $$createType5; - const $$createField6_0 = $$createType6; - const $$createField7_0 = $$createType7; - const $$createField8_0 = $$createType8; - const $$createField9_0 = $$createType9; - const $$createField10_0 = $$createType10; - const $$createField11_0 = $$createType11; - const $$createField12_0 = $$createType12; - const $$createField13_0 = $$createType13; - const $$createField14_0 = $$createType14; - const $$createField15_0 = $$createType15; - const $$createField16_0 = $$createType16; - const $$createField17_0 = $$createType17; - const $$createField18_0 = $$createType18; - const $$createField19_0 = $$createType19; - const $$createField20_0 = $$createType20; - const $$createField21_0 = $$createType21; - const $$createField22_0 = $$createType22; - const $$createField23_0 = $$createType23; - const $$createField24_0 = $$createType24; - const $$createField25_0 = $$createType25; - const $$createField26_0 = $$createType26; - const $$createField27_0 = $$createType27; - const $$createField28_0 = $$createType28; - const $$createField29_0 = $$createType29; - const $$createField30_0 = $$createType30; - const $$createField31_0 = $$createType31; - const $$createField32_0 = $$createType32; - const $$createField33_0 = $$createType33; - const $$createField34_0 = $$createType34; - const $$createField35_0 = $$createType35; - const $$createField36_0 = $$createType36; - const $$createField37_0 = $$createType37; - const $$createField38_0 = $$createType38; - const $$createField39_0 = $$createType39; - const $$createField40_0 = $$createType40; - const $$createField41_0 = $$createType41; - const $$createField42_0 = $$createType0; - const $$createField43_0 = $$createType42; - const $$createField44_0 = $$createType7; - const $$createField45_0 = $$createType43; - const $$createField46_0 = $$createType1; - const $$createField47_0 = $$createType44; - const $$createField48_0 = $$createType45; - const $$createField49_0 = $$createType46; - const $$createField50_0 = $$createType47; - const $$createField51_0 = $$createType15; - const $$createField52_0 = $$createType16; - const $$createField53_0 = $$createType16; - const $$createField54_0 = $$createType48; - const $$createField55_0 = $$createType49; - const $$createField56_0 = $$createType50; - const $$createField57_0 = $$createType51; - const $$createField58_0 = $$createType52; - const $$createField59_0 = $$createType17; - const $$createField60_0 = $$createType18; - const $$createField61_0 = $$createType18; - const $$createField62_0 = $$createType53; - const $$createField63_0 = $$createType54; - const $$createField64_0 = $$createType55; - const $$createField65_0 = $$createType56; - const $$createField66_0 = $$createType57; - const $$createField67_0 = $$createType23; - const $$createField68_0 = $$createType24; - const $$createField69_0 = $$createType24; - const $$createField70_0 = $$createType58; - const $$createField71_0 = $$createType59($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ); - const $$createField72_0 = $$createType60($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ); - const $$createField73_0 = $$createType61($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ); - const $$createField74_0 = $$createType62($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ); - const $$createField75_0 = $$createType63($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ); - const $$createField76_0 = $$createType64($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ); - const $$createField77_0 = $$createType65($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ); - const $$createField78_0 = $$createType66($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ); - const $$createField79_0 = $$createType67($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ); - const $$createField80_0 = $$createType68($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ); - const $$createField81_0 = $$createType69($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ); - const $$createField82_0 = $$createType70($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ); - const $$createField83_0 = $$createType71($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ); - const $$createField84_0 = $$createType72($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ); - const $$createField85_0 = $$createType73($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ); - const $$createField86_0 = $$createType74($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ); - const $$createField87_0 = $$createType75($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ); - const $$createField88_0 = $$createType76($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ); - const $$createField89_0 = $$createType59($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ); - const $$createField90_0 = $$createType60($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ); - const $$createField91_0 = $$createType61($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ); - const $$createField92_0 = $$createType62($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ); - const $$createField93_0 = $$createType63($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ); - const $$createField94_0 = $$createType64($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ); - const $$createField95_0 = $$createType65($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ); - const $$createField96_0 = $$createType66($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ); - const $$createField97_0 = $$createType67($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ); - const $$createField98_0 = $$createType68($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ); - const $$createField99_0 = $$createType69($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ); - const $$createField100_0 = $$createType70($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ); - const $$createField101_0 = $$createType71($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ); - const $$createField102_0 = $$createType72($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ); - const $$createField103_0 = $$createType73($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ); - const $$createField104_0 = $$createType74($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ); - const $$createField105_0 = $$createType75($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ); - const $$createField106_0 = $$createType76($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ); - const $$createField107_0 = $$createType1; - const $$createField108_0 = $$createType15; - const $$createField109_0 = $$createType17; - const $$createField110_0 = $$createType8; - const $$createField111_0 = $$createType16; - const $$createField112_0 = $$createType18; - const $$createField113_0 = $$createType1; - const $$createField114_0 = $$createType7; - const $$createField115_0 = $$createType8; - const $$createField116_0 = $$createType77; - const $$createField117_0 = $$createType78; - const $$createField118_0 = $$createType15; - const $$createField119_0 = $$createType16; - const $$createField120_0 = $$createType15; - const $$createField121_0 = $$createType18; - const $$createField122_0 = $$createType16; - const $$createField123_0 = $$createType53; - const $$createField124_0 = $$createType15; - const $$createField125_0 = $$createType16; - const $$createField126_0 = $$createType17; - const $$createField127_0 = $$createType18; - const $$createField128_0 = $$createType16; - const $$createField129_0 = $$createType18; - const $$createField130_0 = $$createType2; - const $$createField131_0 = $$createType42; - const $$createField132_0 = $$createType15; - const $$createField133_0 = $$createType79; - const $$createField134_0 = $$createType16; - const $$createField135_0 = $$createType23; - const $$createField136_0 = $$createType15; - const $$createField137_0 = $$createType18; - const $$createField138_0 = $$createType24; - const $$createField139_0 = $$createType16; - const $$createField140_0 = $$createType53; - const $$createField141_0 = $$createType16; - const $$createField142_0 = $$createType18; - const $$createField143_0 = $$createType48; - const $$createField144_0 = $$createType53; - return ($$source: any = {}) => { - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - if ("Bool" in $$parsedSource) { - $$parsedSource["Bool"] = $$createField0_0($$parsedSource["Bool"]); - } - if ("Int" in $$parsedSource) { - $$parsedSource["Int"] = $$createField1_0($$parsedSource["Int"]); - } - if ("Uint" in $$parsedSource) { - $$parsedSource["Uint"] = $$createField2_0($$parsedSource["Uint"]); - } - if ("Float" in $$parsedSource) { - $$parsedSource["Float"] = $$createField3_0($$parsedSource["Float"]); - } - if ("Complex" in $$parsedSource) { - $$parsedSource["Complex"] = $$createField4_0($$parsedSource["Complex"]); - } - if ("Byte" in $$parsedSource) { - $$parsedSource["Byte"] = $$createField5_0($$parsedSource["Byte"]); - } - if ("Rune" in $$parsedSource) { - $$parsedSource["Rune"] = $$createField6_0($$parsedSource["Rune"]); - } - if ("String" in $$parsedSource) { - $$parsedSource["String"] = $$createField7_0($$parsedSource["String"]); - } - if ("IntPtr" in $$parsedSource) { - $$parsedSource["IntPtr"] = $$createField8_0($$parsedSource["IntPtr"]); - } - if ("UintPtr" in $$parsedSource) { - $$parsedSource["UintPtr"] = $$createField9_0($$parsedSource["UintPtr"]); - } - if ("FloatPtr" in $$parsedSource) { - $$parsedSource["FloatPtr"] = $$createField10_0($$parsedSource["FloatPtr"]); - } - if ("ComplexPtr" in $$parsedSource) { - $$parsedSource["ComplexPtr"] = $$createField11_0($$parsedSource["ComplexPtr"]); - } - if ("StringPtr" in $$parsedSource) { - $$parsedSource["StringPtr"] = $$createField12_0($$parsedSource["StringPtr"]); - } - if ("NTM" in $$parsedSource) { - $$parsedSource["NTM"] = $$createField13_0($$parsedSource["NTM"]); - } - if ("NTMPtr" in $$parsedSource) { - $$parsedSource["NTMPtr"] = $$createField14_0($$parsedSource["NTMPtr"]); - } - if ("VTM" in $$parsedSource) { - $$parsedSource["VTM"] = $$createField15_0($$parsedSource["VTM"]); - } - if ("VTMPtr" in $$parsedSource) { - $$parsedSource["VTMPtr"] = $$createField16_0($$parsedSource["VTMPtr"]); - } - if ("PTM" in $$parsedSource) { - $$parsedSource["PTM"] = $$createField17_0($$parsedSource["PTM"]); - } - if ("PTMPtr" in $$parsedSource) { - $$parsedSource["PTMPtr"] = $$createField18_0($$parsedSource["PTMPtr"]); - } - if ("JTM" in $$parsedSource) { - $$parsedSource["JTM"] = $$createField19_0($$parsedSource["JTM"]); - } - if ("JTMPtr" in $$parsedSource) { - $$parsedSource["JTMPtr"] = $$createField20_0($$parsedSource["JTMPtr"]); - } - if ("A" in $$parsedSource) { - $$parsedSource["A"] = $$createField21_0($$parsedSource["A"]); - } - if ("APtr" in $$parsedSource) { - $$parsedSource["APtr"] = $$createField22_0($$parsedSource["APtr"]); - } - if ("TM" in $$parsedSource) { - $$parsedSource["TM"] = $$createField23_0($$parsedSource["TM"]); - } - if ("TMPtr" in $$parsedSource) { - $$parsedSource["TMPtr"] = $$createField24_0($$parsedSource["TMPtr"]); - } - if ("CI" in $$parsedSource) { - $$parsedSource["CI"] = $$createField25_0($$parsedSource["CI"]); - } - if ("CIPtr" in $$parsedSource) { - $$parsedSource["CIPtr"] = $$createField26_0($$parsedSource["CIPtr"]); - } - if ("EI" in $$parsedSource) { - $$parsedSource["EI"] = $$createField27_0($$parsedSource["EI"]); - } - if ("EIPtr" in $$parsedSource) { - $$parsedSource["EIPtr"] = $$createField28_0($$parsedSource["EIPtr"]); - } - if ("EV" in $$parsedSource) { - $$parsedSource["EV"] = $$createField29_0($$parsedSource["EV"]); - } - if ("EVPtr" in $$parsedSource) { - $$parsedSource["EVPtr"] = $$createField30_0($$parsedSource["EVPtr"]); - } - if ("EVP" in $$parsedSource) { - $$parsedSource["EVP"] = $$createField31_0($$parsedSource["EVP"]); - } - if ("EVPPtr" in $$parsedSource) { - $$parsedSource["EVPPtr"] = $$createField32_0($$parsedSource["EVPPtr"]); - } - if ("EP" in $$parsedSource) { - $$parsedSource["EP"] = $$createField33_0($$parsedSource["EP"]); - } - if ("EPPtr" in $$parsedSource) { - $$parsedSource["EPPtr"] = $$createField34_0($$parsedSource["EPPtr"]); - } - if ("EPP" in $$parsedSource) { - $$parsedSource["EPP"] = $$createField35_0($$parsedSource["EPP"]); - } - if ("EPPPtr" in $$parsedSource) { - $$parsedSource["EPPPtr"] = $$createField36_0($$parsedSource["EPPPtr"]); - } - if ("ECI" in $$parsedSource) { - $$parsedSource["ECI"] = $$createField37_0($$parsedSource["ECI"]); - } - if ("ECIPtr" in $$parsedSource) { - $$parsedSource["ECIPtr"] = $$createField38_0($$parsedSource["ECIPtr"]); - } - if ("EOI" in $$parsedSource) { - $$parsedSource["EOI"] = $$createField39_0($$parsedSource["EOI"]); - } - if ("EOIPtr" in $$parsedSource) { - $$parsedSource["EOIPtr"] = $$createField40_0($$parsedSource["EOIPtr"]); - } - if ("WT" in $$parsedSource) { - $$parsedSource["WT"] = $$createField41_0($$parsedSource["WT"]); - } - if ("WA" in $$parsedSource) { - $$parsedSource["WA"] = $$createField42_0($$parsedSource["WA"]); - } - if ("ST" in $$parsedSource) { - $$parsedSource["ST"] = $$createField43_0($$parsedSource["ST"]); - } - if ("SA" in $$parsedSource) { - $$parsedSource["SA"] = $$createField44_0($$parsedSource["SA"]); - } - if ("IntT" in $$parsedSource) { - $$parsedSource["IntT"] = $$createField45_0($$parsedSource["IntT"]); - } - if ("IntA" in $$parsedSource) { - $$parsedSource["IntA"] = $$createField46_0($$parsedSource["IntA"]); - } - if ("VT" in $$parsedSource) { - $$parsedSource["VT"] = $$createField47_0($$parsedSource["VT"]); - } - if ("VTPtr" in $$parsedSource) { - $$parsedSource["VTPtr"] = $$createField48_0($$parsedSource["VTPtr"]); - } - if ("VPT" in $$parsedSource) { - $$parsedSource["VPT"] = $$createField49_0($$parsedSource["VPT"]); - } - if ("VPTPtr" in $$parsedSource) { - $$parsedSource["VPTPtr"] = $$createField50_0($$parsedSource["VPTPtr"]); - } - if ("VA" in $$parsedSource) { - $$parsedSource["VA"] = $$createField51_0($$parsedSource["VA"]); - } - if ("VAPtr" in $$parsedSource) { - $$parsedSource["VAPtr"] = $$createField52_0($$parsedSource["VAPtr"]); - } - if ("VPA" in $$parsedSource) { - $$parsedSource["VPA"] = $$createField53_0($$parsedSource["VPA"]); - } - if ("VPAPtr" in $$parsedSource) { - $$parsedSource["VPAPtr"] = $$createField54_0($$parsedSource["VPAPtr"]); - } - if ("PT" in $$parsedSource) { - $$parsedSource["PT"] = $$createField55_0($$parsedSource["PT"]); - } - if ("PTPtr" in $$parsedSource) { - $$parsedSource["PTPtr"] = $$createField56_0($$parsedSource["PTPtr"]); - } - if ("PPT" in $$parsedSource) { - $$parsedSource["PPT"] = $$createField57_0($$parsedSource["PPT"]); - } - if ("PPTPtr" in $$parsedSource) { - $$parsedSource["PPTPtr"] = $$createField58_0($$parsedSource["PPTPtr"]); - } - if ("PA" in $$parsedSource) { - $$parsedSource["PA"] = $$createField59_0($$parsedSource["PA"]); - } - if ("PAPtr" in $$parsedSource) { - $$parsedSource["PAPtr"] = $$createField60_0($$parsedSource["PAPtr"]); - } - if ("PPA" in $$parsedSource) { - $$parsedSource["PPA"] = $$createField61_0($$parsedSource["PPA"]); - } - if ("PPAPtr" in $$parsedSource) { - $$parsedSource["PPAPtr"] = $$createField62_0($$parsedSource["PPAPtr"]); - } - if ("IT" in $$parsedSource) { - $$parsedSource["IT"] = $$createField63_0($$parsedSource["IT"]); - } - if ("ITPtr" in $$parsedSource) { - $$parsedSource["ITPtr"] = $$createField64_0($$parsedSource["ITPtr"]); - } - if ("IPT" in $$parsedSource) { - $$parsedSource["IPT"] = $$createField65_0($$parsedSource["IPT"]); - } - if ("IPTPtr" in $$parsedSource) { - $$parsedSource["IPTPtr"] = $$createField66_0($$parsedSource["IPTPtr"]); - } - if ("IA" in $$parsedSource) { - $$parsedSource["IA"] = $$createField67_0($$parsedSource["IA"]); - } - if ("IAPtr" in $$parsedSource) { - $$parsedSource["IAPtr"] = $$createField68_0($$parsedSource["IAPtr"]); - } - if ("IPA" in $$parsedSource) { - $$parsedSource["IPA"] = $$createField69_0($$parsedSource["IPA"]); - } - if ("IPAPtr" in $$parsedSource) { - $$parsedSource["IPAPtr"] = $$createField70_0($$parsedSource["IPAPtr"]); - } - if ("TPR" in $$parsedSource) { - $$parsedSource["TPR"] = $$createField71_0($$parsedSource["TPR"]); - } - if ("TPRPtr" in $$parsedSource) { - $$parsedSource["TPRPtr"] = $$createField72_0($$parsedSource["TPRPtr"]); - } - if ("TPS" in $$parsedSource) { - $$parsedSource["TPS"] = $$createField73_0($$parsedSource["TPS"]); - } - if ("TPSPtr" in $$parsedSource) { - $$parsedSource["TPSPtr"] = $$createField74_0($$parsedSource["TPSPtr"]); - } - if ("TPT" in $$parsedSource) { - $$parsedSource["TPT"] = $$createField75_0($$parsedSource["TPT"]); - } - if ("TPTPtr" in $$parsedSource) { - $$parsedSource["TPTPtr"] = $$createField76_0($$parsedSource["TPTPtr"]); - } - if ("TPU" in $$parsedSource) { - $$parsedSource["TPU"] = $$createField77_0($$parsedSource["TPU"]); - } - if ("TPUPtr" in $$parsedSource) { - $$parsedSource["TPUPtr"] = $$createField78_0($$parsedSource["TPUPtr"]); - } - if ("TPV" in $$parsedSource) { - $$parsedSource["TPV"] = $$createField79_0($$parsedSource["TPV"]); - } - if ("TPVPtr" in $$parsedSource) { - $$parsedSource["TPVPtr"] = $$createField80_0($$parsedSource["TPVPtr"]); - } - if ("TPW" in $$parsedSource) { - $$parsedSource["TPW"] = $$createField81_0($$parsedSource["TPW"]); - } - if ("TPWPtr" in $$parsedSource) { - $$parsedSource["TPWPtr"] = $$createField82_0($$parsedSource["TPWPtr"]); - } - if ("TPX" in $$parsedSource) { - $$parsedSource["TPX"] = $$createField83_0($$parsedSource["TPX"]); - } - if ("TPXPtr" in $$parsedSource) { - $$parsedSource["TPXPtr"] = $$createField84_0($$parsedSource["TPXPtr"]); - } - if ("TPY" in $$parsedSource) { - $$parsedSource["TPY"] = $$createField85_0($$parsedSource["TPY"]); - } - if ("TPYPtr" in $$parsedSource) { - $$parsedSource["TPYPtr"] = $$createField86_0($$parsedSource["TPYPtr"]); - } - if ("TPZ" in $$parsedSource) { - $$parsedSource["TPZ"] = $$createField87_0($$parsedSource["TPZ"]); - } - if ("TPZPtr" in $$parsedSource) { - $$parsedSource["TPZPtr"] = $$createField88_0($$parsedSource["TPZPtr"]); - } - if ("GAR" in $$parsedSource) { - $$parsedSource["GAR"] = $$createField89_0($$parsedSource["GAR"]); - } - if ("GARPtr" in $$parsedSource) { - $$parsedSource["GARPtr"] = $$createField90_0($$parsedSource["GARPtr"]); - } - if ("GAS" in $$parsedSource) { - $$parsedSource["GAS"] = $$createField91_0($$parsedSource["GAS"]); - } - if ("GASPtr" in $$parsedSource) { - $$parsedSource["GASPtr"] = $$createField92_0($$parsedSource["GASPtr"]); - } - if ("GAT" in $$parsedSource) { - $$parsedSource["GAT"] = $$createField93_0($$parsedSource["GAT"]); - } - if ("GATPtr" in $$parsedSource) { - $$parsedSource["GATPtr"] = $$createField94_0($$parsedSource["GATPtr"]); - } - if ("GAU" in $$parsedSource) { - $$parsedSource["GAU"] = $$createField95_0($$parsedSource["GAU"]); - } - if ("GAUPtr" in $$parsedSource) { - $$parsedSource["GAUPtr"] = $$createField96_0($$parsedSource["GAUPtr"]); - } - if ("GAV" in $$parsedSource) { - $$parsedSource["GAV"] = $$createField97_0($$parsedSource["GAV"]); - } - if ("GAVPtr" in $$parsedSource) { - $$parsedSource["GAVPtr"] = $$createField98_0($$parsedSource["GAVPtr"]); - } - if ("GAW" in $$parsedSource) { - $$parsedSource["GAW"] = $$createField99_0($$parsedSource["GAW"]); - } - if ("GAWPtr" in $$parsedSource) { - $$parsedSource["GAWPtr"] = $$createField100_0($$parsedSource["GAWPtr"]); - } - if ("GAX" in $$parsedSource) { - $$parsedSource["GAX"] = $$createField101_0($$parsedSource["GAX"]); - } - if ("GAXPtr" in $$parsedSource) { - $$parsedSource["GAXPtr"] = $$createField102_0($$parsedSource["GAXPtr"]); - } - if ("GAY" in $$parsedSource) { - $$parsedSource["GAY"] = $$createField103_0($$parsedSource["GAY"]); - } - if ("GAYPtr" in $$parsedSource) { - $$parsedSource["GAYPtr"] = $$createField104_0($$parsedSource["GAYPtr"]); - } - if ("GAZ" in $$parsedSource) { - $$parsedSource["GAZ"] = $$createField105_0($$parsedSource["GAZ"]); - } - if ("GAZPtr" in $$parsedSource) { - $$parsedSource["GAZPtr"] = $$createField106_0($$parsedSource["GAZPtr"]); - } - if ("GACi" in $$parsedSource) { - $$parsedSource["GACi"] = $$createField107_0($$parsedSource["GACi"]); - } - if ("GACV" in $$parsedSource) { - $$parsedSource["GACV"] = $$createField108_0($$parsedSource["GACV"]); - } - if ("GACP" in $$parsedSource) { - $$parsedSource["GACP"] = $$createField109_0($$parsedSource["GACP"]); - } - if ("GACiPtr" in $$parsedSource) { - $$parsedSource["GACiPtr"] = $$createField110_0($$parsedSource["GACiPtr"]); - } - if ("GACVPtr" in $$parsedSource) { - $$parsedSource["GACVPtr"] = $$createField111_0($$parsedSource["GACVPtr"]); - } - if ("GACPPtr" in $$parsedSource) { - $$parsedSource["GACPPtr"] = $$createField112_0($$parsedSource["GACPPtr"]); - } - if ("GABi" in $$parsedSource) { - $$parsedSource["GABi"] = $$createField113_0($$parsedSource["GABi"]); - } - if ("GABs" in $$parsedSource) { - $$parsedSource["GABs"] = $$createField114_0($$parsedSource["GABs"]); - } - if ("GABiPtr" in $$parsedSource) { - $$parsedSource["GABiPtr"] = $$createField115_0($$parsedSource["GABiPtr"]); - } - if ("GABT" in $$parsedSource) { - $$parsedSource["GABT"] = $$createField116_0($$parsedSource["GABT"]); - } - if ("GABTPtr" in $$parsedSource) { - $$parsedSource["GABTPtr"] = $$createField117_0($$parsedSource["GABTPtr"]); - } - if ("GAGT" in $$parsedSource) { - $$parsedSource["GAGT"] = $$createField118_0($$parsedSource["GAGT"]); - } - if ("GAGTPtr" in $$parsedSource) { - $$parsedSource["GAGTPtr"] = $$createField119_0($$parsedSource["GAGTPtr"]); - } - if ("GANBV" in $$parsedSource) { - $$parsedSource["GANBV"] = $$createField120_0($$parsedSource["GANBV"]); - } - if ("GANBP" in $$parsedSource) { - $$parsedSource["GANBP"] = $$createField121_0($$parsedSource["GANBP"]); - } - if ("GANBVPtr" in $$parsedSource) { - $$parsedSource["GANBVPtr"] = $$createField122_0($$parsedSource["GANBVPtr"]); - } - if ("GANBPPtr" in $$parsedSource) { - $$parsedSource["GANBPPtr"] = $$createField123_0($$parsedSource["GANBPPtr"]); - } - if ("GAPlV1" in $$parsedSource) { - $$parsedSource["GAPlV1"] = $$createField124_0($$parsedSource["GAPlV1"]); - } - if ("GAPlV2" in $$parsedSource) { - $$parsedSource["GAPlV2"] = $$createField125_0($$parsedSource["GAPlV2"]); - } - if ("GAPlP1" in $$parsedSource) { - $$parsedSource["GAPlP1"] = $$createField126_0($$parsedSource["GAPlP1"]); - } - if ("GAPlP2" in $$parsedSource) { - $$parsedSource["GAPlP2"] = $$createField127_0($$parsedSource["GAPlP2"]); - } - if ("GAPlVPtr" in $$parsedSource) { - $$parsedSource["GAPlVPtr"] = $$createField128_0($$parsedSource["GAPlVPtr"]); - } - if ("GAPlPPtr" in $$parsedSource) { - $$parsedSource["GAPlPPtr"] = $$createField129_0($$parsedSource["GAPlPPtr"]); - } - if ("GAMi" in $$parsedSource) { - $$parsedSource["GAMi"] = $$createField130_0($$parsedSource["GAMi"]); - } - if ("GAMS" in $$parsedSource) { - $$parsedSource["GAMS"] = $$createField131_0($$parsedSource["GAMS"]); - } - if ("GAMV" in $$parsedSource) { - $$parsedSource["GAMV"] = $$createField132_0($$parsedSource["GAMV"]); - } - if ("GAMSPtr" in $$parsedSource) { - $$parsedSource["GAMSPtr"] = $$createField133_0($$parsedSource["GAMSPtr"]); - } - if ("GAMVPtr" in $$parsedSource) { - $$parsedSource["GAMVPtr"] = $$createField134_0($$parsedSource["GAMVPtr"]); - } - if ("GAII" in $$parsedSource) { - $$parsedSource["GAII"] = $$createField135_0($$parsedSource["GAII"]); - } - if ("GAIV" in $$parsedSource) { - $$parsedSource["GAIV"] = $$createField136_0($$parsedSource["GAIV"]); - } - if ("GAIP" in $$parsedSource) { - $$parsedSource["GAIP"] = $$createField137_0($$parsedSource["GAIP"]); - } - if ("GAIIPtr" in $$parsedSource) { - $$parsedSource["GAIIPtr"] = $$createField138_0($$parsedSource["GAIIPtr"]); - } - if ("GAIVPtr" in $$parsedSource) { - $$parsedSource["GAIVPtr"] = $$createField139_0($$parsedSource["GAIVPtr"]); - } - if ("GAIPPtr" in $$parsedSource) { - $$parsedSource["GAIPPtr"] = $$createField140_0($$parsedSource["GAIPPtr"]); - } - if ("GAPrV" in $$parsedSource) { - $$parsedSource["GAPrV"] = $$createField141_0($$parsedSource["GAPrV"]); - } - if ("GAPrP" in $$parsedSource) { - $$parsedSource["GAPrP"] = $$createField142_0($$parsedSource["GAPrP"]); - } - if ("GAPrVPtr" in $$parsedSource) { - $$parsedSource["GAPrVPtr"] = $$createField143_0($$parsedSource["GAPrVPtr"]); - } - if ("GAPrPPtr" in $$parsedSource) { - $$parsedSource["GAPrPPtr"] = $$createField144_0($$parsedSource["GAPrPPtr"]); - } - return new Maps($$parsedSource as Partial>); - }; - } -} - -export type MixedCstrAlias = X; - -export type NonBasicCstrAlias = V; - -export type PointableCstrAlias = W; - -export type PointerAlias = PointerTextMarshaler; - -export type PointerTextMarshaler = string; - -export type StringAlias = string; - -export type StringType = string; - -export type ValueAlias = ValueTextMarshaler; - -export type ValueTextMarshaler = string; - -// Private type creation functions -const $$createType0 = $Create.Map($Create.Any, $Create.Any); -const $$createType1 = $Create.Map($Create.Any, $Create.Any); -const $$createType2 = $Create.Map($Create.Any, $Create.Any); -const $$createType3 = $Create.Map($Create.Any, $Create.Any); -const $$createType4 = $Create.Map($Create.Any, $Create.Any); -const $$createType5 = $Create.Map($Create.Any, $Create.Any); -const $$createType6 = $Create.Map($Create.Any, $Create.Any); -const $$createType7 = $Create.Map($Create.Any, $Create.Any); -const $$createType8 = $Create.Map($Create.Any, $Create.Any); -const $$createType9 = $Create.Map($Create.Any, $Create.Any); -const $$createType10 = $Create.Map($Create.Any, $Create.Any); -const $$createType11 = $Create.Map($Create.Any, $Create.Any); -const $$createType12 = $Create.Map($Create.Any, $Create.Any); -const $$createType13 = $Create.Map($Create.Any, $Create.Any); -const $$createType14 = $Create.Map($Create.Any, $Create.Any); -const $$createType15 = $Create.Map($Create.Any, $Create.Any); -const $$createType16 = $Create.Map($Create.Any, $Create.Any); -const $$createType17 = $Create.Map($Create.Any, $Create.Any); -const $$createType18 = $Create.Map($Create.Any, $Create.Any); -const $$createType19 = $Create.Map($Create.Any, $Create.Any); -const $$createType20 = $Create.Map($Create.Any, $Create.Any); -const $$createType21 = $Create.Map($Create.Any, $Create.Any); -const $$createType22 = $Create.Map($Create.Any, $Create.Any); -const $$createType23 = $Create.Map($Create.Any, $Create.Any); -const $$createType24 = $Create.Map($Create.Any, $Create.Any); -const $$createType25 = $Create.Map($Create.Any, $Create.Any); -const $$createType26 = $Create.Map($Create.Any, $Create.Any); -const $$createType27 = $Create.Map($Create.Any, $Create.Any); -const $$createType28 = $Create.Map($Create.Any, $Create.Any); -const $$createType29 = $Create.Map($Create.Any, $Create.Any); -const $$createType30 = $Create.Map($Create.Any, $Create.Any); -const $$createType31 = $Create.Map($Create.Any, $Create.Any); -const $$createType32 = $Create.Map($Create.Any, $Create.Any); -const $$createType33 = $Create.Map($Create.Any, $Create.Any); -const $$createType34 = $Create.Map($Create.Any, $Create.Any); -const $$createType35 = $Create.Map($Create.Any, $Create.Any); -const $$createType36 = $Create.Map($Create.Any, $Create.Any); -const $$createType37 = $Create.Map($Create.Any, $Create.Any); -const $$createType38 = $Create.Map($Create.Any, $Create.Any); -const $$createType39 = $Create.Map($Create.Any, $Create.Any); -const $$createType40 = $Create.Map($Create.Any, $Create.Any); -const $$createType41 = $Create.Map($Create.Any, $Create.Any); -const $$createType42 = $Create.Map($Create.Any, $Create.Any); -const $$createType43 = $Create.Map($Create.Any, $Create.Any); -const $$createType44 = $Create.Map($Create.Any, $Create.Any); -const $$createType45 = $Create.Map($Create.Any, $Create.Any); -const $$createType46 = $Create.Map($Create.Any, $Create.Any); -const $$createType47 = $Create.Map($Create.Any, $Create.Any); -const $$createType48 = $Create.Map($Create.Any, $Create.Any); -const $$createType49 = $Create.Map($Create.Any, $Create.Any); -const $$createType50 = $Create.Map($Create.Any, $Create.Any); -const $$createType51 = $Create.Map($Create.Any, $Create.Any); -const $$createType52 = $Create.Map($Create.Any, $Create.Any); -const $$createType53 = $Create.Map($Create.Any, $Create.Any); -const $$createType54 = $Create.Map($Create.Any, $Create.Any); -const $$createType55 = $Create.Map($Create.Any, $Create.Any); -const $$createType56 = $Create.Map($Create.Any, $Create.Any); -const $$createType57 = $Create.Map($Create.Any, $Create.Any); -const $$createType58 = $Create.Map($Create.Any, $Create.Any); -const $$createType59 = ($$createParamR: any, $$createParamS: any, $$createParamT: any, $$createParamU: any, $$createParamV: any, $$createParamW: any, $$createParamX: any, $$createParamY: any, $$createParamZ: any) => $Create.Map($Create.Any, $Create.Any); -const $$createType60 = ($$createParamR: any, $$createParamS: any, $$createParamT: any, $$createParamU: any, $$createParamV: any, $$createParamW: any, $$createParamX: any, $$createParamY: any, $$createParamZ: any) => $Create.Map($Create.Any, $Create.Any); -const $$createType61 = ($$createParamR: any, $$createParamS: any, $$createParamT: any, $$createParamU: any, $$createParamV: any, $$createParamW: any, $$createParamX: any, $$createParamY: any, $$createParamZ: any) => $Create.Map($Create.Any, $Create.Any); -const $$createType62 = ($$createParamR: any, $$createParamS: any, $$createParamT: any, $$createParamU: any, $$createParamV: any, $$createParamW: any, $$createParamX: any, $$createParamY: any, $$createParamZ: any) => $Create.Map($Create.Any, $Create.Any); -const $$createType63 = ($$createParamR: any, $$createParamS: any, $$createParamT: any, $$createParamU: any, $$createParamV: any, $$createParamW: any, $$createParamX: any, $$createParamY: any, $$createParamZ: any) => $Create.Map($Create.Any, $Create.Any); -const $$createType64 = ($$createParamR: any, $$createParamS: any, $$createParamT: any, $$createParamU: any, $$createParamV: any, $$createParamW: any, $$createParamX: any, $$createParamY: any, $$createParamZ: any) => $Create.Map($Create.Any, $Create.Any); -const $$createType65 = ($$createParamR: any, $$createParamS: any, $$createParamT: any, $$createParamU: any, $$createParamV: any, $$createParamW: any, $$createParamX: any, $$createParamY: any, $$createParamZ: any) => $Create.Map($Create.Any, $Create.Any); -const $$createType66 = ($$createParamR: any, $$createParamS: any, $$createParamT: any, $$createParamU: any, $$createParamV: any, $$createParamW: any, $$createParamX: any, $$createParamY: any, $$createParamZ: any) => $Create.Map($Create.Any, $Create.Any); -const $$createType67 = ($$createParamR: any, $$createParamS: any, $$createParamT: any, $$createParamU: any, $$createParamV: any, $$createParamW: any, $$createParamX: any, $$createParamY: any, $$createParamZ: any) => $Create.Map($Create.Any, $Create.Any); -const $$createType68 = ($$createParamR: any, $$createParamS: any, $$createParamT: any, $$createParamU: any, $$createParamV: any, $$createParamW: any, $$createParamX: any, $$createParamY: any, $$createParamZ: any) => $Create.Map($Create.Any, $Create.Any); -const $$createType69 = ($$createParamR: any, $$createParamS: any, $$createParamT: any, $$createParamU: any, $$createParamV: any, $$createParamW: any, $$createParamX: any, $$createParamY: any, $$createParamZ: any) => $Create.Map($Create.Any, $Create.Any); -const $$createType70 = ($$createParamR: any, $$createParamS: any, $$createParamT: any, $$createParamU: any, $$createParamV: any, $$createParamW: any, $$createParamX: any, $$createParamY: any, $$createParamZ: any) => $Create.Map($Create.Any, $Create.Any); -const $$createType71 = ($$createParamR: any, $$createParamS: any, $$createParamT: any, $$createParamU: any, $$createParamV: any, $$createParamW: any, $$createParamX: any, $$createParamY: any, $$createParamZ: any) => $Create.Map($Create.Any, $Create.Any); -const $$createType72 = ($$createParamR: any, $$createParamS: any, $$createParamT: any, $$createParamU: any, $$createParamV: any, $$createParamW: any, $$createParamX: any, $$createParamY: any, $$createParamZ: any) => $Create.Map($Create.Any, $Create.Any); -const $$createType73 = ($$createParamR: any, $$createParamS: any, $$createParamT: any, $$createParamU: any, $$createParamV: any, $$createParamW: any, $$createParamX: any, $$createParamY: any, $$createParamZ: any) => $Create.Map($Create.Any, $Create.Any); -const $$createType74 = ($$createParamR: any, $$createParamS: any, $$createParamT: any, $$createParamU: any, $$createParamV: any, $$createParamW: any, $$createParamX: any, $$createParamY: any, $$createParamZ: any) => $Create.Map($Create.Any, $Create.Any); -const $$createType75 = ($$createParamR: any, $$createParamS: any, $$createParamT: any, $$createParamU: any, $$createParamV: any, $$createParamW: any, $$createParamX: any, $$createParamY: any, $$createParamZ: any) => $Create.Map($Create.Any, $Create.Any); -const $$createType76 = ($$createParamR: any, $$createParamS: any, $$createParamT: any, $$createParamU: any, $$createParamV: any, $$createParamW: any, $$createParamX: any, $$createParamY: any, $$createParamZ: any) => $Create.Map($Create.Any, $Create.Any); -const $$createType77 = $Create.Map($Create.Any, $Create.Any); -const $$createType78 = $Create.Map($Create.Any, $Create.Any); -const $$createType79 = $Create.Map($Create.Any, $Create.Any); diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys/service.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys/service.ts deleted file mode 100644 index bd5e88c7b..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys/service.ts +++ /dev/null @@ -1,19 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -export function Method(): $CancellablePromise<$models.Maps<$models.PointerTextMarshaler, number, number, $models.ValueTextMarshaler, $models.PointerTextMarshaler | null, $models.ValueTextMarshaler, $models.StringType, $models.ValueTextMarshaler, $models.PointerTextMarshaler | null>> { - return $Call.ByID(4021345184).then(($result: any) => { - return $$createType0($result); - }); -} - -// Private type creation functions -const $$createType0 = $models.Maps.createFrom($Create.Any, $Create.Any, $Create.Any, $Create.Any, $Create.Any, $Create.Any, $Create.Any, $Create.Any, $Create.Any); diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/marshalers/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/marshalers/index.ts deleted file mode 100644 index bbe49e32f..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/marshalers/index.ts +++ /dev/null @@ -1,36 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as Service from "./service.js"; -export { - Service -}; - -export { - Data, - ImplicitNonMarshaler, - NonMarshaler -} from "./models.js"; - -export type { - AliasJsonMarshaler, - AliasMarshaler, - AliasNonMarshaler, - AliasTextMarshaler, - ImplicitJsonButText, - ImplicitJsonMarshaler, - ImplicitMarshaler, - ImplicitNonJson, - ImplicitNonText, - ImplicitTextButJson, - ImplicitTextMarshaler, - PointerJsonMarshaler, - PointerMarshaler, - PointerTextMarshaler, - UnderlyingJsonMarshaler, - UnderlyingMarshaler, - UnderlyingTextMarshaler, - ValueJsonMarshaler, - ValueMarshaler, - ValueTextMarshaler -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/marshalers/models.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/marshalers/models.ts deleted file mode 100644 index d8db23862..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/marshalers/models.ts +++ /dev/null @@ -1,545 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Create as $Create } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as encoding$0 from "../../../../../../../../encoding/models.js"; -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as json$0 from "../../../../../../../../encoding/json/models.js"; - -/** - * any - */ -export type AliasJsonMarshaler = any; - -/** - * any - */ -export type AliasMarshaler = any; - -/** - * struct{} - */ -export interface AliasNonMarshaler { -} - -/** - * string - */ -export type AliasTextMarshaler = string; - -export class Data { - "NM": NonMarshaler; - - /** - * NonMarshaler | null - */ - "NMPtr": NonMarshaler | null; - "VJM": ValueJsonMarshaler; - - /** - * ValueJsonMarshaler | null - */ - "VJMPtr": ValueJsonMarshaler | null; - "PJM": PointerJsonMarshaler; - - /** - * PointerJsonMarshaler | null - */ - "PJMPtr": PointerJsonMarshaler | null; - "VTM": ValueTextMarshaler; - - /** - * ValueTextMarshaler | null - */ - "VTMPtr": ValueTextMarshaler | null; - "PTM": PointerTextMarshaler; - - /** - * PointerTextMarshaler | null - */ - "PTMPtr": PointerTextMarshaler | null; - "VM": ValueMarshaler; - - /** - * ValueMarshaler | null - */ - "VMPtr": ValueMarshaler | null; - "PM": PointerMarshaler; - - /** - * PointerMarshaler | null - */ - "PMPtr": PointerMarshaler | null; - "UJM": UnderlyingJsonMarshaler; - - /** - * UnderlyingJsonMarshaler | null - */ - "UJMPtr": UnderlyingJsonMarshaler | null; - "UTM": UnderlyingTextMarshaler; - - /** - * UnderlyingTextMarshaler | null - */ - "UTMPtr": UnderlyingTextMarshaler | null; - "UM": UnderlyingMarshaler; - - /** - * UnderlyingMarshaler | null - */ - "UMPtr": UnderlyingMarshaler | null; - - /** - * any - */ - "JM": any; - - /** - * any | null - */ - "JMPtr": any | null; - - /** - * string - */ - "TM": string; - - /** - * string | null - */ - "TMPtr": string | null; - - /** - * any - */ - "CJM": any; - - /** - * any | null - */ - "CJMPtr": any | null; - - /** - * string - */ - "CTM": string; - - /** - * string | null - */ - "CTMPtr": string | null; - - /** - * any - */ - "CM": any; - - /** - * any | null - */ - "CMPtr": any | null; - "ANM": AliasNonMarshaler; - - /** - * AliasNonMarshaler | null - */ - "ANMPtr": AliasNonMarshaler | null; - "AJM": AliasJsonMarshaler; - - /** - * AliasJsonMarshaler | null - */ - "AJMPtr": AliasJsonMarshaler | null; - "ATM": AliasTextMarshaler; - - /** - * AliasTextMarshaler | null - */ - "ATMPtr": AliasTextMarshaler | null; - "AM": AliasMarshaler; - - /** - * AliasMarshaler | null - */ - "AMPtr": AliasMarshaler | null; - "ImJM": ImplicitJsonMarshaler; - - /** - * ImplicitJsonMarshaler | null - */ - "ImJMPtr": ImplicitJsonMarshaler | null; - "ImTM": ImplicitTextMarshaler; - - /** - * ImplicitTextMarshaler | null - */ - "ImTMPtr": ImplicitTextMarshaler | null; - "ImM": ImplicitMarshaler; - - /** - * ImplicitMarshaler | null - */ - "ImMPtr": ImplicitMarshaler | null; - "ImNJ": ImplicitNonJson; - - /** - * ImplicitNonJson | null - */ - "ImNJPtr": ImplicitNonJson | null; - "ImNT": ImplicitNonText; - - /** - * ImplicitNonText | null - */ - "ImNTPtr": ImplicitNonText | null; - "ImNM": ImplicitNonMarshaler; - - /** - * ImplicitNonMarshaler | null - */ - "ImNMPtr": ImplicitNonMarshaler | null; - "ImJbT": ImplicitJsonButText; - - /** - * ImplicitJsonButText | null - */ - "ImJbTPtr": ImplicitJsonButText | null; - "ImTbJ": ImplicitTextButJson; - - /** - * ImplicitTextButJson | null - */ - "ImTbJPtr": ImplicitTextButJson | null; - - /** Creates a new Data instance. */ - constructor($$source: Partial = {}) { - if (!("NM" in $$source)) { - this["NM"] = (new NonMarshaler()); - } - if (!("NMPtr" in $$source)) { - this["NMPtr"] = null; - } - if (!("VJM" in $$source)) { - this["VJM"] = null; - } - if (!("VJMPtr" in $$source)) { - this["VJMPtr"] = null; - } - if (!("PJM" in $$source)) { - this["PJM"] = null; - } - if (!("PJMPtr" in $$source)) { - this["PJMPtr"] = null; - } - if (!("VTM" in $$source)) { - this["VTM"] = ""; - } - if (!("VTMPtr" in $$source)) { - this["VTMPtr"] = null; - } - if (!("PTM" in $$source)) { - this["PTM"] = ""; - } - if (!("PTMPtr" in $$source)) { - this["PTMPtr"] = null; - } - if (!("VM" in $$source)) { - this["VM"] = null; - } - if (!("VMPtr" in $$source)) { - this["VMPtr"] = null; - } - if (!("PM" in $$source)) { - this["PM"] = null; - } - if (!("PMPtr" in $$source)) { - this["PMPtr"] = null; - } - if (!("UJM" in $$source)) { - this["UJM"] = null; - } - if (!("UJMPtr" in $$source)) { - this["UJMPtr"] = null; - } - if (!("UTM" in $$source)) { - this["UTM"] = ""; - } - if (!("UTMPtr" in $$source)) { - this["UTMPtr"] = null; - } - if (!("UM" in $$source)) { - this["UM"] = null; - } - if (!("UMPtr" in $$source)) { - this["UMPtr"] = null; - } - if (!("JM" in $$source)) { - this["JM"] = null; - } - if (!("JMPtr" in $$source)) { - this["JMPtr"] = null; - } - if (!("TM" in $$source)) { - this["TM"] = ""; - } - if (!("TMPtr" in $$source)) { - this["TMPtr"] = null; - } - if (!("CJM" in $$source)) { - this["CJM"] = null; - } - if (!("CJMPtr" in $$source)) { - this["CJMPtr"] = null; - } - if (!("CTM" in $$source)) { - this["CTM"] = ""; - } - if (!("CTMPtr" in $$source)) { - this["CTMPtr"] = null; - } - if (!("CM" in $$source)) { - this["CM"] = null; - } - if (!("CMPtr" in $$source)) { - this["CMPtr"] = null; - } - if (!("ANM" in $$source)) { - this["ANM"] = {}; - } - if (!("ANMPtr" in $$source)) { - this["ANMPtr"] = null; - } - if (!("AJM" in $$source)) { - this["AJM"] = null; - } - if (!("AJMPtr" in $$source)) { - this["AJMPtr"] = null; - } - if (!("ATM" in $$source)) { - this["ATM"] = ""; - } - if (!("ATMPtr" in $$source)) { - this["ATMPtr"] = null; - } - if (!("AM" in $$source)) { - this["AM"] = null; - } - if (!("AMPtr" in $$source)) { - this["AMPtr"] = null; - } - if (!("ImJM" in $$source)) { - this["ImJM"] = null; - } - if (!("ImJMPtr" in $$source)) { - this["ImJMPtr"] = null; - } - if (!("ImTM" in $$source)) { - this["ImTM"] = ""; - } - if (!("ImTMPtr" in $$source)) { - this["ImTMPtr"] = null; - } - if (!("ImM" in $$source)) { - this["ImM"] = null; - } - if (!("ImMPtr" in $$source)) { - this["ImMPtr"] = null; - } - if (!("ImNJ" in $$source)) { - this["ImNJ"] = ""; - } - if (!("ImNJPtr" in $$source)) { - this["ImNJPtr"] = null; - } - if (!("ImNT" in $$source)) { - this["ImNT"] = null; - } - if (!("ImNTPtr" in $$source)) { - this["ImNTPtr"] = null; - } - if (!("ImNM" in $$source)) { - this["ImNM"] = (new ImplicitNonMarshaler()); - } - if (!("ImNMPtr" in $$source)) { - this["ImNMPtr"] = null; - } - if (!("ImJbT" in $$source)) { - this["ImJbT"] = null; - } - if (!("ImJbTPtr" in $$source)) { - this["ImJbTPtr"] = null; - } - if (!("ImTbJ" in $$source)) { - this["ImTbJ"] = null; - } - if (!("ImTbJPtr" in $$source)) { - this["ImTbJPtr"] = null; - } - - Object.assign(this, $$source); - } - - /** - * Creates a new Data instance from a string or object. - */ - static createFrom($$source: any = {}): Data { - const $$createField0_0 = $$createType0; - const $$createField1_0 = $$createType1; - const $$createField48_0 = $$createType2; - const $$createField49_0 = $$createType3; - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - if ("NM" in $$parsedSource) { - $$parsedSource["NM"] = $$createField0_0($$parsedSource["NM"]); - } - if ("NMPtr" in $$parsedSource) { - $$parsedSource["NMPtr"] = $$createField1_0($$parsedSource["NMPtr"]); - } - if ("ImNM" in $$parsedSource) { - $$parsedSource["ImNM"] = $$createField48_0($$parsedSource["ImNM"]); - } - if ("ImNMPtr" in $$parsedSource) { - $$parsedSource["ImNMPtr"] = $$createField49_0($$parsedSource["ImNMPtr"]); - } - return new Data($$parsedSource as Partial); - } -} - -/** - * any - */ -export type ImplicitJsonButText = any; - -/** - * any - */ -export type ImplicitJsonMarshaler = any; - -/** - * any - */ -export type ImplicitMarshaler = any; - -/** - * string - */ -export type ImplicitNonJson = string; - -/** - * class{ Marshaler, TextMarshaler } - */ -export class ImplicitNonMarshaler { - "Marshaler": json$0.Marshaler; - "TextMarshaler": encoding$0.TextMarshaler; - - /** Creates a new ImplicitNonMarshaler instance. */ - constructor($$source: Partial = {}) { - if (!("Marshaler" in $$source)) { - this["Marshaler"] = null; - } - if (!("TextMarshaler" in $$source)) { - this["TextMarshaler"] = ""; - } - - Object.assign(this, $$source); - } - - /** - * Creates a new ImplicitNonMarshaler instance from a string or object. - */ - static createFrom($$source: any = {}): ImplicitNonMarshaler { - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - return new ImplicitNonMarshaler($$parsedSource as Partial); - } -} - -/** - * any - */ -export type ImplicitNonText = any; - -/** - * any - */ -export type ImplicitTextButJson = any; - -/** - * string - */ -export type ImplicitTextMarshaler = string; - -/** - * class {} - */ -export class NonMarshaler { - - /** Creates a new NonMarshaler instance. */ - constructor($$source: Partial = {}) { - - Object.assign(this, $$source); - } - - /** - * Creates a new NonMarshaler instance from a string or object. - */ - static createFrom($$source: any = {}): NonMarshaler { - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - return new NonMarshaler($$parsedSource as Partial); - } -} - -/** - * any - */ -export type PointerJsonMarshaler = any; - -/** - * any - */ -export type PointerMarshaler = any; - -/** - * string - */ -export type PointerTextMarshaler = string; - -/** - * any - */ -export type UnderlyingJsonMarshaler = any; - -/** - * any - */ -export type UnderlyingMarshaler = any; - -/** - * string - */ -export type UnderlyingTextMarshaler = string; - -/** - * any - */ -export type ValueJsonMarshaler = any; - -/** - * any - */ -export type ValueMarshaler = any; - -/** - * string - */ -export type ValueTextMarshaler = string; - -// Private type creation functions -const $$createType0 = NonMarshaler.createFrom; -const $$createType1 = $Create.Nullable($$createType0); -const $$createType2 = ImplicitNonMarshaler.createFrom; -const $$createType3 = $Create.Nullable($$createType2); diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/marshalers/service.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/marshalers/service.ts deleted file mode 100644 index 342fcf3c4..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/marshalers/service.ts +++ /dev/null @@ -1,19 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -export function Method(): $CancellablePromise<$models.Data> { - return $Call.ByID(4021345184).then(($result: any) => { - return $$createType0($result); - }); -} - -// Private type creation functions -const $$createType0 = $models.Data.createFrom; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/index.ts deleted file mode 100644 index 19d990dbf..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/index.ts +++ /dev/null @@ -1,14 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as SomeMethods from "./somemethods.js"; -export { - SomeMethods -}; - -export { - HowDifferent, - Impersonator, - Person, - PrivatePerson -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/models.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/models.ts deleted file mode 100644 index 967f8dbfd..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/models.ts +++ /dev/null @@ -1,163 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Create as $Create } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as other$0 from "./other/models.js"; - -/** - * HowDifferent is a curious kind of person - * that lets other people decide how they are different. - */ -export class HowDifferent { - /** - * They have a name as well. - */ - "Name": string; - - /** - * But they may have many differences. - */ - "Differences": { [_ in string]?: How }[]; - - /** Creates a new HowDifferent instance. */ - constructor($$source: Partial> = {}) { - if (!("Name" in $$source)) { - this["Name"] = ""; - } - if (!("Differences" in $$source)) { - this["Differences"] = []; - } - - Object.assign(this, $$source); - } - - /** - * Given creation functions for each type parameter, - * returns a creation function for a concrete instance - * of the generic class HowDifferent. - */ - static createFrom($$createParamHow: (source: any) => How): ($$source?: any) => HowDifferent { - const $$createField1_0 = $$createType1($$createParamHow); - return ($$source: any = {}) => { - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - if ("Differences" in $$parsedSource) { - $$parsedSource["Differences"] = $$createField1_0($$parsedSource["Differences"]); - } - return new HowDifferent($$parsedSource as Partial>); - }; - } -} - -/** - * Impersonator gets their fields from other people. - */ -export const Impersonator = other$0.OtherPerson; - -/** - * Impersonator gets their fields from other people. - */ -export type Impersonator = other$0.OtherPerson; - -/** - * Person is not a number. - */ -export class Person { - /** - * They have a name. - */ - "Name": string; - - /** - * Exactly 4 sketchy friends. - */ - "Friends": Impersonator[]; - - /** Creates a new Person instance. */ - constructor($$source: Partial = {}) { - if (!("Name" in $$source)) { - this["Name"] = ""; - } - if (!("Friends" in $$source)) { - this["Friends"] = Array.from({ length: 4 }, () => (new Impersonator())); - } - - Object.assign(this, $$source); - } - - /** - * Creates a new Person instance from a string or object. - */ - static createFrom($$source: any = {}): Person { - const $$createField1_0 = $$createType3; - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - if ("Friends" in $$parsedSource) { - $$parsedSource["Friends"] = $$createField1_0($$parsedSource["Friends"]); - } - return new Person($$parsedSource as Partial); - } -} - -export class personImpl { - /** - * Nickname conceals a person's identity. - */ - "Nickname": string; - - /** - * They have a name. - */ - "Name": string; - - /** - * Exactly 4 sketchy friends. - */ - "Friends": Impersonator[]; - - /** Creates a new personImpl instance. */ - constructor($$source: Partial = {}) { - if (!("Nickname" in $$source)) { - this["Nickname"] = ""; - } - if (!("Name" in $$source)) { - this["Name"] = ""; - } - if (!("Friends" in $$source)) { - this["Friends"] = Array.from({ length: 4 }, () => (new Impersonator())); - } - - Object.assign(this, $$source); - } - - /** - * Creates a new personImpl instance from a string or object. - */ - static createFrom($$source: any = {}): personImpl { - const $$createField2_0 = $$createType3; - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - if ("Friends" in $$parsedSource) { - $$parsedSource["Friends"] = $$createField2_0($$parsedSource["Friends"]); - } - return new personImpl($$parsedSource as Partial); - } -} - -/** - * PrivatePerson gets their fields from hidden sources. - */ -export const PrivatePerson = personImpl; - -/** - * PrivatePerson gets their fields from hidden sources. - */ -export type PrivatePerson = personImpl; - -// Private type creation functions -const $$createType0 = ($$createParamHow: any) => $Create.Map($Create.Any, $$createParamHow); -const $$createType1 = ($$createParamHow: any) => $Create.Array($$createType0($$createParamHow)); -const $$createType2 = other$0.OtherPerson.createFrom($Create.Any); -const $$createType3 = $Create.Array($$createType2); diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/more/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/more/index.ts deleted file mode 100644 index ac743f356..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/more/index.ts +++ /dev/null @@ -1,6 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -export type { - StringPtr -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/more/models.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/more/models.ts deleted file mode 100644 index 168c7fdba..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/more/models.ts +++ /dev/null @@ -1,11 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Create as $Create } from "/wails/runtime.js"; - -/** - * StringPtr is a nullable string. - */ -export type StringPtr = string | null; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/other/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/other/index.ts deleted file mode 100644 index d2d973b28..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/other/index.ts +++ /dev/null @@ -1,11 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as OtherMethods from "./othermethods.js"; -export { - OtherMethods -}; - -export { - OtherPerson -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/other/models.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/other/models.ts deleted file mode 100644 index 711735a2b..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/other/models.ts +++ /dev/null @@ -1,52 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Create as $Create } from "/wails/runtime.js"; - -/** - * OtherPerson is like a person, but different. - */ -export class OtherPerson { - /** - * They have a name as well. - */ - "Name": string; - - /** - * But they may have many differences. - */ - "Differences": T[]; - - /** Creates a new OtherPerson instance. */ - constructor($$source: Partial> = {}) { - if (!("Name" in $$source)) { - this["Name"] = ""; - } - if (!("Differences" in $$source)) { - this["Differences"] = []; - } - - Object.assign(this, $$source); - } - - /** - * Given creation functions for each type parameter, - * returns a creation function for a concrete instance - * of the generic class OtherPerson. - */ - static createFrom($$createParamT: (source: any) => T): ($$source?: any) => OtherPerson { - const $$createField1_0 = $$createType0($$createParamT); - return ($$source: any = {}) => { - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - if ("Differences" in $$parsedSource) { - $$parsedSource["Differences"] = $$createField1_0($$parsedSource["Differences"]); - } - return new OtherPerson($$parsedSource as Partial>); - }; - } -} - -// Private type creation functions -const $$createType0 = ($$createParamT: any) => $Create.Array($$createParamT); diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/other/othermethods.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/other/othermethods.ts deleted file mode 100644 index da11f7f2f..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/other/othermethods.ts +++ /dev/null @@ -1,18 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * OtherMethods has another method, but through a private embedded type. - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -/** - * LikeThisOtherOne does nothing as well, but is different. - */ -export function LikeThisOtherOne(): $CancellablePromise { - return $Call.ByID(3606939272); -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/somemethods.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/somemethods.ts deleted file mode 100644 index 9ef257343..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/somemethods.ts +++ /dev/null @@ -1,39 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * SomeMethods exports some methods. - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * LikeThisOne is an example method that does nothing. - */ -export function LikeThisOne(): $CancellablePromise<[$models.Person, $models.HowDifferent, $models.PrivatePerson]> { - return $Call.ByID(2124352079).then(($result: any) => { - $result[0] = $$createType0($result[0]); - $result[1] = $$createType1($result[1]); - $result[2] = $$createType2($result[2]); - return $result; - }); -} - -/** - * LikeThisOtherOne does nothing as well, but is different. - */ -export function LikeThisOtherOne(): $CancellablePromise { - return $Call.ByID(4281222271); -} - -// Private type creation functions -const $$createType0 = $models.Person.createFrom; -const $$createType1 = $models.HowDifferent.createFrom($Create.Any); -const $$createType2 = $models.personImpl.createFrom; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/out_of_tree/embedother.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/out_of_tree/embedother.ts deleted file mode 100644 index a5fe5368f..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/out_of_tree/embedother.ts +++ /dev/null @@ -1,18 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * EmbedOther is even trickier. - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -/** - * LikeThisOtherOne does nothing as well, but is different. - */ -export function LikeThisOtherOne(): $CancellablePromise { - return $Call.ByID(3566862802); -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/out_of_tree/embedservice.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/out_of_tree/embedservice.ts deleted file mode 100644 index 615eae691..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/out_of_tree/embedservice.ts +++ /dev/null @@ -1,39 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * EmbedService is tricky. - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as nobindingshere$0 from "../no_bindings_here/models.js"; - -/** - * LikeThisOne is an example method that does nothing. - */ -export function LikeThisOne(): $CancellablePromise<[nobindingshere$0.Person, nobindingshere$0.HowDifferent, nobindingshere$0.PrivatePerson]> { - return $Call.ByID(2590614085).then(($result: any) => { - $result[0] = $$createType0($result[0]); - $result[1] = $$createType1($result[1]); - $result[2] = $$createType2($result[2]); - return $result; - }); -} - -/** - * LikeThisOtherOne does nothing as well, but is different. - */ -export function LikeThisOtherOne(): $CancellablePromise { - return $Call.ByID(773650321); -} - -// Private type creation functions -const $$createType0 = nobindingshere$0.Person.createFrom; -const $$createType1 = nobindingshere$0.HowDifferent.createFrom($Create.Any); -const $$createType2 = nobindingshere$0.personImpl.createFrom; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/out_of_tree/greetservice.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/out_of_tree/greetservice.ts deleted file mode 100644 index 83ca81acc..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/out_of_tree/greetservice.ts +++ /dev/null @@ -1,18 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -/** - * Greet someone - */ -export function Greet($0: string): $CancellablePromise { - return $Call.ByID(1411160069, $0); -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/out_of_tree/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/out_of_tree/index.ts deleted file mode 100644 index e69bebf3b..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/out_of_tree/index.ts +++ /dev/null @@ -1,11 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as EmbedOther from "./embedother.js"; -import * as EmbedService from "./embedservice.js"; -import * as GreetService from "./greetservice.js"; -export { - EmbedOther, - EmbedService, - GreetService -}; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple/greetservice.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple/greetservice.ts deleted file mode 100644 index 62283209b..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple/greetservice.ts +++ /dev/null @@ -1,10 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -export function Greet(name: string): $CancellablePromise { - return $Call.ByID(1411160069, name); -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple/index.ts deleted file mode 100644 index 5c4ebea4f..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple/index.ts +++ /dev/null @@ -1,9 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -import * as OtherService from "./otherservice.js"; -export { - GreetService, - OtherService -}; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple/otherservice.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple/otherservice.ts deleted file mode 100644 index 6c902629c..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple/otherservice.ts +++ /dev/null @@ -1,10 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -export function Hello(): $CancellablePromise { - return $Call.ByID(4249972365); -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_files/greetservice.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_files/greetservice.ts deleted file mode 100644 index 62283209b..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_files/greetservice.ts +++ /dev/null @@ -1,10 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -export function Greet(name: string): $CancellablePromise { - return $Call.ByID(1411160069, name); -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_files/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_files/index.ts deleted file mode 100644 index 5c4ebea4f..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_files/index.ts +++ /dev/null @@ -1,9 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -import * as OtherService from "./otherservice.js"; -export { - GreetService, - OtherService -}; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_files/otherservice.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_files/otherservice.ts deleted file mode 100644 index 6c902629c..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_files/otherservice.ts +++ /dev/null @@ -1,10 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -export function Hello(): $CancellablePromise { - return $Call.ByID(4249972365); -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_other/greetservice.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_other/greetservice.ts deleted file mode 100644 index 88cafa9d1..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_other/greetservice.ts +++ /dev/null @@ -1,35 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * Greet does XYZ - */ -export function Greet(name: string): $CancellablePromise { - return $Call.ByID(1411160069, name); -} - -/** - * NewPerson creates a new person - */ -export function NewPerson(name: string): $CancellablePromise<$models.Person | null> { - return $Call.ByID(1661412647, name).then(($result: any) => { - return $$createType1($result); - }); -} - -// Private type creation functions -const $$createType0 = $models.Person.createFrom; -const $$createType1 = $Create.Nullable($$createType0); diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_other/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_other/index.ts deleted file mode 100644 index f95c1b558..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_other/index.ts +++ /dev/null @@ -1,11 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; - -export { - Person -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_other/models.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_other/models.ts deleted file mode 100644 index d76f68d9d..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_other/models.ts +++ /dev/null @@ -1,43 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Create as $Create } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as services$0 from "./services/models.js"; - -export class Person { - "Name": string; - "Address": services$0.Address | null; - - /** Creates a new Person instance. */ - constructor($$source: Partial = {}) { - if (!("Name" in $$source)) { - this["Name"] = ""; - } - if (!("Address" in $$source)) { - this["Address"] = null; - } - - Object.assign(this, $$source); - } - - /** - * Creates a new Person instance from a string or object. - */ - static createFrom($$source: any = {}): Person { - const $$createField1_0 = $$createType1; - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - if ("Address" in $$parsedSource) { - $$parsedSource["Address"] = $$createField1_0($$parsedSource["Address"]); - } - return new Person($$parsedSource as Partial); - } -} - -// Private type creation functions -const $$createType0 = services$0.Address.createFrom; -const $$createType1 = $Create.Nullable($$createType0); diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_other/services/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_other/services/index.ts deleted file mode 100644 index e4d86b717..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_other/services/index.ts +++ /dev/null @@ -1,11 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as OtherService from "./otherservice.js"; -export { - OtherService -}; - -export { - Address -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_other/services/models.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_other/services/models.ts deleted file mode 100644 index a4be6e904..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_other/services/models.ts +++ /dev/null @@ -1,35 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Create as $Create } from "/wails/runtime.js"; - -export class Address { - "Street": string; - "State": string; - "Country": string; - - /** Creates a new Address instance. */ - constructor($$source: Partial
                    = {}) { - if (!("Street" in $$source)) { - this["Street"] = ""; - } - if (!("State" in $$source)) { - this["State"] = ""; - } - if (!("Country" in $$source)) { - this["Country"] = ""; - } - - Object.assign(this, $$source); - } - - /** - * Creates a new Address instance from a string or object. - */ - static createFrom($$source: any = {}): Address { - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - return new Address($$parsedSource as Partial
                    ); - } -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_other/services/otherservice.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_other/services/otherservice.ts deleted file mode 100644 index b8c293ad7..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_other/services/otherservice.ts +++ /dev/null @@ -1,29 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * OtherService is a struct - * that does things - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * Yay does this and that - */ -export function Yay(): $CancellablePromise<$models.Address | null> { - return $Call.ByID(3568225479).then(($result: any) => { - return $$createType1($result); - }); -} - -// Private type creation functions -const $$createType0 = $models.Address.createFrom; -const $$createType1 = $Create.Nullable($$createType0); diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_non_pointer_single/greetservice.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_non_pointer_single/greetservice.ts deleted file mode 100644 index 9f8faede9..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_non_pointer_single/greetservice.ts +++ /dev/null @@ -1,209 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -export function ArrayInt($in: number[]): $CancellablePromise { - return $Call.ByID(3862002418, $in); -} - -export function BoolInBoolOut($in: boolean): $CancellablePromise { - return $Call.ByID(2424639793, $in); -} - -export function Float32InFloat32Out($in: number): $CancellablePromise { - return $Call.ByID(3132595881, $in); -} - -export function Float64InFloat64Out($in: number): $CancellablePromise { - return $Call.ByID(2182412247, $in); -} - -/** - * Greet someone - */ -export function Greet(name: string): $CancellablePromise { - return $Call.ByID(1411160069, name); -} - -export function Int16InIntOut($in: number): $CancellablePromise { - return $Call.ByID(3306292566, $in); -} - -export function Int16PointerInAndOutput($in: number | null): $CancellablePromise { - return $Call.ByID(1754277916, $in); -} - -export function Int32InIntOut($in: number): $CancellablePromise { - return $Call.ByID(1909469092, $in); -} - -export function Int32PointerInAndOutput($in: number | null): $CancellablePromise { - return $Call.ByID(4251088558, $in); -} - -export function Int64InIntOut($in: number): $CancellablePromise { - return $Call.ByID(1343888303, $in); -} - -export function Int64PointerInAndOutput($in: number | null): $CancellablePromise { - return $Call.ByID(2205561041, $in); -} - -export function Int8InIntOut($in: number): $CancellablePromise { - return $Call.ByID(572240879, $in); -} - -export function Int8PointerInAndOutput($in: number | null): $CancellablePromise { - return $Call.ByID(2189402897, $in); -} - -export function IntInIntOut($in: number): $CancellablePromise { - return $Call.ByID(642881729, $in); -} - -export function IntPointerInAndOutput($in: number | null): $CancellablePromise { - return $Call.ByID(1066151743, $in); -} - -export function IntPointerInputNamedOutputs($in: number | null): $CancellablePromise { - return $Call.ByID(2718999663, $in); -} - -export function MapIntInt($in: { [_ in `${number}`]?: number }): $CancellablePromise { - return $Call.ByID(2386486356, $in); -} - -export function MapIntIntPointer($in: { [_ in `${number}`]?: number | null }): $CancellablePromise { - return $Call.ByID(2163571325, $in); -} - -export function MapIntSliceInt($in: { [_ in `${number}`]?: number[] }): $CancellablePromise { - return $Call.ByID(2900172572, $in); -} - -export function MapIntSliceIntInMapIntSliceIntOut($in: { [_ in `${number}`]?: number[] }): $CancellablePromise<{ [_ in `${number}`]?: number[] }> { - return $Call.ByID(881980169, $in).then(($result: any) => { - return $$createType1($result); - }); -} - -export function NoInputsStringOut(): $CancellablePromise { - return $Call.ByID(1075577233); -} - -export function PointerBoolInBoolOut($in: boolean | null): $CancellablePromise { - return $Call.ByID(3589606958, $in); -} - -export function PointerFloat32InFloat32Out($in: number | null): $CancellablePromise { - return $Call.ByID(224675106, $in); -} - -export function PointerFloat64InFloat64Out($in: number | null): $CancellablePromise { - return $Call.ByID(2124953624, $in); -} - -export function PointerMapIntInt($in: { [_ in `${number}`]?: number } | null): $CancellablePromise { - return $Call.ByID(3516977899, $in); -} - -export function PointerStringInStringOut($in: string | null): $CancellablePromise { - return $Call.ByID(229603958, $in); -} - -export function StringArrayInputNamedOutput($in: string[]): $CancellablePromise { - return $Call.ByID(3678582682, $in).then(($result: any) => { - return $$createType2($result); - }); -} - -export function StringArrayInputNamedOutputs($in: string[]): $CancellablePromise { - return $Call.ByID(319259595, $in).then(($result: any) => { - return $$createType2($result); - }); -} - -export function StringArrayInputStringArrayOut($in: string[]): $CancellablePromise { - return $Call.ByID(383995060, $in).then(($result: any) => { - return $$createType2($result); - }); -} - -export function StringArrayInputStringOut($in: string[]): $CancellablePromise { - return $Call.ByID(1091960237, $in); -} - -export function StructInputStructOutput($in: $models.Person): $CancellablePromise<$models.Person> { - return $Call.ByID(3835643147, $in).then(($result: any) => { - return $$createType3($result); - }); -} - -export function StructPointerInputErrorOutput($in: $models.Person | null): $CancellablePromise { - return $Call.ByID(2447692557, $in); -} - -export function StructPointerInputStructPointerOutput($in: $models.Person | null): $CancellablePromise<$models.Person | null> { - return $Call.ByID(2943477349, $in).then(($result: any) => { - return $$createType4($result); - }); -} - -export function UInt16InUIntOut($in: number): $CancellablePromise { - return $Call.ByID(3401034892, $in); -} - -export function UInt16PointerInAndOutput($in: number | null): $CancellablePromise { - return $Call.ByID(1236957573, $in); -} - -export function UInt32InUIntOut($in: number): $CancellablePromise { - return $Call.ByID(1160383782, $in); -} - -export function UInt32PointerInAndOutput($in: number | null): $CancellablePromise { - return $Call.ByID(1739300671, $in); -} - -export function UInt64InUIntOut($in: number): $CancellablePromise { - return $Call.ByID(793803239, $in); -} - -export function UInt64PointerInAndOutput($in: number | null): $CancellablePromise { - return $Call.ByID(1403757716, $in); -} - -export function UInt8InUIntOut($in: number): $CancellablePromise { - return $Call.ByID(2988345717, $in); -} - -export function UInt8PointerInAndOutput($in: number | null): $CancellablePromise { - return $Call.ByID(518250834, $in); -} - -export function UIntInUIntOut($in: number): $CancellablePromise { - return $Call.ByID(2836661285, $in); -} - -export function UIntPointerInAndOutput($in: number | null): $CancellablePromise { - return $Call.ByID(1367187362, $in); -} - -// Private type creation functions -const $$createType0 = $Create.Array($Create.Any); -const $$createType1 = $Create.Map($Create.Any, $$createType0); -const $$createType2 = $Create.Array($Create.Any); -const $$createType3 = $models.Person.createFrom; -const $$createType4 = $Create.Nullable($$createType3); diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_non_pointer_single/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_non_pointer_single/index.ts deleted file mode 100644 index f95c1b558..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_non_pointer_single/index.ts +++ /dev/null @@ -1,11 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; - -export { - Person -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_non_pointer_single/models.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_non_pointer_single/models.ts deleted file mode 100644 index cd282c90c..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_non_pointer_single/models.ts +++ /dev/null @@ -1,43 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Create as $Create } from "/wails/runtime.js"; - -export class Person { - "Name": string; - "Parent": Person | null; - "Details": {"Age": number, "Address": {"Street": string}}; - - /** Creates a new Person instance. */ - constructor($$source: Partial = {}) { - if (!("Name" in $$source)) { - this["Name"] = ""; - } - if (!("Parent" in $$source)) { - this["Parent"] = null; - } - if (!("Details" in $$source)) { - this["Details"] = {"Age": 0, "Address": {"Street": ""}}; - } - - Object.assign(this, $$source); - } - - /** - * Creates a new Person instance from a string or object. - */ - static createFrom($$source: any = {}): Person { - const $$createField1_0 = $$createType1; - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - if ("Parent" in $$parsedSource) { - $$parsedSource["Parent"] = $$createField1_0($$parsedSource["Parent"]); - } - return new Person($$parsedSource as Partial); - } -} - -// Private type creation functions -const $$createType0 = Person.createFrom; -const $$createType1 = $Create.Nullable($$createType0); diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_single/greetservice.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_single/greetservice.ts deleted file mode 100644 index 9f8faede9..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_single/greetservice.ts +++ /dev/null @@ -1,209 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -export function ArrayInt($in: number[]): $CancellablePromise { - return $Call.ByID(3862002418, $in); -} - -export function BoolInBoolOut($in: boolean): $CancellablePromise { - return $Call.ByID(2424639793, $in); -} - -export function Float32InFloat32Out($in: number): $CancellablePromise { - return $Call.ByID(3132595881, $in); -} - -export function Float64InFloat64Out($in: number): $CancellablePromise { - return $Call.ByID(2182412247, $in); -} - -/** - * Greet someone - */ -export function Greet(name: string): $CancellablePromise { - return $Call.ByID(1411160069, name); -} - -export function Int16InIntOut($in: number): $CancellablePromise { - return $Call.ByID(3306292566, $in); -} - -export function Int16PointerInAndOutput($in: number | null): $CancellablePromise { - return $Call.ByID(1754277916, $in); -} - -export function Int32InIntOut($in: number): $CancellablePromise { - return $Call.ByID(1909469092, $in); -} - -export function Int32PointerInAndOutput($in: number | null): $CancellablePromise { - return $Call.ByID(4251088558, $in); -} - -export function Int64InIntOut($in: number): $CancellablePromise { - return $Call.ByID(1343888303, $in); -} - -export function Int64PointerInAndOutput($in: number | null): $CancellablePromise { - return $Call.ByID(2205561041, $in); -} - -export function Int8InIntOut($in: number): $CancellablePromise { - return $Call.ByID(572240879, $in); -} - -export function Int8PointerInAndOutput($in: number | null): $CancellablePromise { - return $Call.ByID(2189402897, $in); -} - -export function IntInIntOut($in: number): $CancellablePromise { - return $Call.ByID(642881729, $in); -} - -export function IntPointerInAndOutput($in: number | null): $CancellablePromise { - return $Call.ByID(1066151743, $in); -} - -export function IntPointerInputNamedOutputs($in: number | null): $CancellablePromise { - return $Call.ByID(2718999663, $in); -} - -export function MapIntInt($in: { [_ in `${number}`]?: number }): $CancellablePromise { - return $Call.ByID(2386486356, $in); -} - -export function MapIntIntPointer($in: { [_ in `${number}`]?: number | null }): $CancellablePromise { - return $Call.ByID(2163571325, $in); -} - -export function MapIntSliceInt($in: { [_ in `${number}`]?: number[] }): $CancellablePromise { - return $Call.ByID(2900172572, $in); -} - -export function MapIntSliceIntInMapIntSliceIntOut($in: { [_ in `${number}`]?: number[] }): $CancellablePromise<{ [_ in `${number}`]?: number[] }> { - return $Call.ByID(881980169, $in).then(($result: any) => { - return $$createType1($result); - }); -} - -export function NoInputsStringOut(): $CancellablePromise { - return $Call.ByID(1075577233); -} - -export function PointerBoolInBoolOut($in: boolean | null): $CancellablePromise { - return $Call.ByID(3589606958, $in); -} - -export function PointerFloat32InFloat32Out($in: number | null): $CancellablePromise { - return $Call.ByID(224675106, $in); -} - -export function PointerFloat64InFloat64Out($in: number | null): $CancellablePromise { - return $Call.ByID(2124953624, $in); -} - -export function PointerMapIntInt($in: { [_ in `${number}`]?: number } | null): $CancellablePromise { - return $Call.ByID(3516977899, $in); -} - -export function PointerStringInStringOut($in: string | null): $CancellablePromise { - return $Call.ByID(229603958, $in); -} - -export function StringArrayInputNamedOutput($in: string[]): $CancellablePromise { - return $Call.ByID(3678582682, $in).then(($result: any) => { - return $$createType2($result); - }); -} - -export function StringArrayInputNamedOutputs($in: string[]): $CancellablePromise { - return $Call.ByID(319259595, $in).then(($result: any) => { - return $$createType2($result); - }); -} - -export function StringArrayInputStringArrayOut($in: string[]): $CancellablePromise { - return $Call.ByID(383995060, $in).then(($result: any) => { - return $$createType2($result); - }); -} - -export function StringArrayInputStringOut($in: string[]): $CancellablePromise { - return $Call.ByID(1091960237, $in); -} - -export function StructInputStructOutput($in: $models.Person): $CancellablePromise<$models.Person> { - return $Call.ByID(3835643147, $in).then(($result: any) => { - return $$createType3($result); - }); -} - -export function StructPointerInputErrorOutput($in: $models.Person | null): $CancellablePromise { - return $Call.ByID(2447692557, $in); -} - -export function StructPointerInputStructPointerOutput($in: $models.Person | null): $CancellablePromise<$models.Person | null> { - return $Call.ByID(2943477349, $in).then(($result: any) => { - return $$createType4($result); - }); -} - -export function UInt16InUIntOut($in: number): $CancellablePromise { - return $Call.ByID(3401034892, $in); -} - -export function UInt16PointerInAndOutput($in: number | null): $CancellablePromise { - return $Call.ByID(1236957573, $in); -} - -export function UInt32InUIntOut($in: number): $CancellablePromise { - return $Call.ByID(1160383782, $in); -} - -export function UInt32PointerInAndOutput($in: number | null): $CancellablePromise { - return $Call.ByID(1739300671, $in); -} - -export function UInt64InUIntOut($in: number): $CancellablePromise { - return $Call.ByID(793803239, $in); -} - -export function UInt64PointerInAndOutput($in: number | null): $CancellablePromise { - return $Call.ByID(1403757716, $in); -} - -export function UInt8InUIntOut($in: number): $CancellablePromise { - return $Call.ByID(2988345717, $in); -} - -export function UInt8PointerInAndOutput($in: number | null): $CancellablePromise { - return $Call.ByID(518250834, $in); -} - -export function UIntInUIntOut($in: number): $CancellablePromise { - return $Call.ByID(2836661285, $in); -} - -export function UIntPointerInAndOutput($in: number | null): $CancellablePromise { - return $Call.ByID(1367187362, $in); -} - -// Private type creation functions -const $$createType0 = $Create.Array($Create.Any); -const $$createType1 = $Create.Map($Create.Any, $$createType0); -const $$createType2 = $Create.Array($Create.Any); -const $$createType3 = $models.Person.createFrom; -const $$createType4 = $Create.Nullable($$createType3); diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_single/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_single/index.ts deleted file mode 100644 index f95c1b558..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_single/index.ts +++ /dev/null @@ -1,11 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; - -export { - Person -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_single/models.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_single/models.ts deleted file mode 100644 index cd282c90c..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_single/models.ts +++ /dev/null @@ -1,43 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Create as $Create } from "/wails/runtime.js"; - -export class Person { - "Name": string; - "Parent": Person | null; - "Details": {"Age": number, "Address": {"Street": string}}; - - /** Creates a new Person instance. */ - constructor($$source: Partial = {}) { - if (!("Name" in $$source)) { - this["Name"] = ""; - } - if (!("Parent" in $$source)) { - this["Parent"] = null; - } - if (!("Details" in $$source)) { - this["Details"] = {"Age": 0, "Address": {"Street": ""}}; - } - - Object.assign(this, $$source); - } - - /** - * Creates a new Person instance from a string or object. - */ - static createFrom($$source: any = {}): Person { - const $$createField1_0 = $$createType1; - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - if ("Parent" in $$parsedSource) { - $$parsedSource["Parent"] = $$createField1_0($$parsedSource["Parent"]); - } - return new Person($$parsedSource as Partial); - } -} - -// Private type creation functions -const $$createType0 = Person.createFrom; -const $$createType1 = $Create.Nullable($$createType0); diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single/greetservice.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single/greetservice.ts deleted file mode 100644 index 6e6ac2007..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single/greetservice.ts +++ /dev/null @@ -1,18 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -/** - * Greet someone - */ -export function Greet(name: string): $CancellablePromise { - return $Call.ByID(1411160069, name); -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single/index.ts deleted file mode 100644 index 50e3f0435..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single/index.ts +++ /dev/null @@ -1,7 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_function/greetservice.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_function/greetservice.ts deleted file mode 100644 index 6e6ac2007..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_function/greetservice.ts +++ /dev/null @@ -1,18 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -/** - * Greet someone - */ -export function Greet(name: string): $CancellablePromise { - return $Call.ByID(1411160069, name); -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_function/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_function/index.ts deleted file mode 100644 index 50e3f0435..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_function/index.ts +++ /dev/null @@ -1,7 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_other_function/greetservice.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_other_function/greetservice.ts deleted file mode 100644 index 88cafa9d1..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_other_function/greetservice.ts +++ /dev/null @@ -1,35 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * Greet does XYZ - */ -export function Greet(name: string): $CancellablePromise { - return $Call.ByID(1411160069, name); -} - -/** - * NewPerson creates a new person - */ -export function NewPerson(name: string): $CancellablePromise<$models.Person | null> { - return $Call.ByID(1661412647, name).then(($result: any) => { - return $$createType1($result); - }); -} - -// Private type creation functions -const $$createType0 = $models.Person.createFrom; -const $$createType1 = $Create.Nullable($$createType0); diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_other_function/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_other_function/index.ts deleted file mode 100644 index f95c1b558..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_other_function/index.ts +++ /dev/null @@ -1,11 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; - -export { - Person -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_other_function/models.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_other_function/models.ts deleted file mode 100644 index f6eee9de8..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_other_function/models.ts +++ /dev/null @@ -1,47 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Create as $Create } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as services$0 from "./services/models.js"; - -/** - * Person is a person! - * They have a name and an address - */ -export class Person { - "Name": string; - "Address": services$0.Address | null; - - /** Creates a new Person instance. */ - constructor($$source: Partial = {}) { - if (!("Name" in $$source)) { - this["Name"] = ""; - } - if (!("Address" in $$source)) { - this["Address"] = null; - } - - Object.assign(this, $$source); - } - - /** - * Creates a new Person instance from a string or object. - */ - static createFrom($$source: any = {}): Person { - const $$createField1_0 = $$createType1; - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - if ("Address" in $$parsedSource) { - $$parsedSource["Address"] = $$createField1_0($$parsedSource["Address"]); - } - return new Person($$parsedSource as Partial); - } -} - -// Private type creation functions -const $$createType0 = services$0.Address.createFrom; -const $$createType1 = $Create.Nullable($$createType0); diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_other_function/services/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_other_function/services/index.ts deleted file mode 100644 index e4d86b717..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_other_function/services/index.ts +++ /dev/null @@ -1,11 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as OtherService from "./otherservice.js"; -export { - OtherService -}; - -export { - Address -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_other_function/services/models.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_other_function/services/models.ts deleted file mode 100644 index a4be6e904..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_other_function/services/models.ts +++ /dev/null @@ -1,35 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Create as $Create } from "/wails/runtime.js"; - -export class Address { - "Street": string; - "State": string; - "Country": string; - - /** Creates a new Address instance. */ - constructor($$source: Partial
                    = {}) { - if (!("Street" in $$source)) { - this["Street"] = ""; - } - if (!("State" in $$source)) { - this["State"] = ""; - } - if (!("Country" in $$source)) { - this["Country"] = ""; - } - - Object.assign(this, $$source); - } - - /** - * Creates a new Address instance from a string or object. - */ - static createFrom($$source: any = {}): Address { - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - return new Address($$parsedSource as Partial
                    ); - } -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_other_function/services/otherservice.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_other_function/services/otherservice.ts deleted file mode 100644 index ec098d45a..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_other_function/services/otherservice.ts +++ /dev/null @@ -1,29 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * OtherService is a struct - * that does things - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * Yay does this and that - */ -export function Yay(): $CancellablePromise<$models.Address | null> { - return $Call.ByID(1491748400).then(($result: any) => { - return $$createType1($result); - }); -} - -// Private type creation functions -const $$createType0 = $models.Address.createFrom; -const $$createType1 = $Create.Nullable($$createType0); diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/warnings.log b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/warnings.log deleted file mode 100644 index ce8369307..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=false/warnings.log +++ /dev/null @@ -1,83 +0,0 @@ -[warn] /testcases/complex_json/main.go:127:2: event 'collision' has one of multiple definitions here with data type map[string]int -[warn] /testcases/events_only/events.go:20:2: event 'collision' has one of multiple definitions here with data type int -[warn] /testcases/events_only/events.go:21:2: `application.RegisterEvent` called here with non-constant event name -[warn] /testcases/events_only/other.go:10:5: `application.RegisterEvent` is instantiated here but not called -[warn] /testcases/events_only/other.go:13:2: `application.RegisterEvent` called here with non-constant event name -[warn] /testcases/events_only/other.go:17:2: data type []T for event 'parametric' contains unresolved type parameters and will be ignored` -[warn] /testcases/events_only/other.go:22:2: event 'common:ApplicationStarted' is a known system event and cannot be overridden; this call to `application.RegisterEvent` will panic -[warn] /testcases/marshalers/main.go:212:2: event 'collision' has one of multiple definitions here with data type *struct{Field []bool} -[warn] /testcases/marshalers/main.go:214:2: data type encoding/json.Marshaler for event 'interface' is a non-empty interface: emitting events from the frontend with data other than `null` is not supported by encoding/json and will likely result in runtime errors -[warn] dynamically registered event names are not discoverable by the binding generator: it is recommended to invoke `application.RegisterEvent` with constant arguments only -[warn] event 'collision' has multiple conflicting definitions and will be ignored -[warn] events registered through indirect calls are not discoverable by the binding generator: it is recommended to invoke `application.RegisterEvent` directly -[warn] generic wrappers for calls to `application.RegisterEvent` are not analysable by the binding generator: it is recommended to call `application.RegisterEvent` with concrete types only -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *R is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *S is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *T is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *U is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *V is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *X is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *Y is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *Z is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *any is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *complex64 is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *encoding.TextMarshaler is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *float32 is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.CustomInterface is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.EmbeddedInterface is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.InterfaceAlias is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.InterfacePtrAlias is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.InterfacePtrType is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.InterfaceType is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.NonTextMarshaler is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.PointerPtrAlias is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.PointerPtrType is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.PointerType is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.ValuePtrAlias is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.ValuePtrType is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.ValueType is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *int is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *string is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *uint is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type R is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type T is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type W is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type any is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type bool is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type complex64 is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type float32 is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.BadTildeCstrAlias[T] is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.BadTildeCstrAlias[struct{}] is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.BadTildeCstrPtrAlias[T] is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.BadTildeCstrPtrAlias[struct{}] is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.BasicCstrPtrAlias[S] is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.BasicCstrPtrAlias[int] is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.ComparableCstrAlias[R] is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.ComparableCstrAlias[github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.PointerTextMarshaler] is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.ComparableCstrPtrAlias[R] is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.ComparableCstrPtrAlias[int] is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.EmbeddedPointer is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.GoodTildeCstrPtrAlias[U] is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.InterfaceCstrPtrAlias[*github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.PointerTextMarshaler] is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.InterfaceCstrPtrAlias[Y] is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.InterfaceCstrPtrAlias[encoding.TextMarshaler] is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.InterfacePtrAlias is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.InterfacePtrType is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.MixedCstrPtrAlias[X] is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.MixedCstrPtrAlias[github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.StringType] is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.NonBasicCstrPtrAlias[*github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.PointerTextMarshaler] is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.NonBasicCstrPtrAlias[V] is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.NonTextMarshaler is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.PointableCstrAlias[W] is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.PointableCstrAlias[github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.PointerTextMarshaler] is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.PointerAlias is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.PointerCstrPtrAlias[R, Z] is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.PointerCstrPtrAlias[github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.PointerTextMarshaler, *github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.PointerTextMarshaler] is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.PointerCstrPtrAlias[github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.ValueTextMarshaler, *github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.ValueTextMarshaler] is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.PointerPtrType is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.PointerTextMarshaler is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.PointerType is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.ValuePtrType is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.ValueType is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.WrongAlias is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.WrongType is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/encoding/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/encoding/index.ts deleted file mode 100644 index ba2885969..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/encoding/index.ts +++ /dev/null @@ -1,6 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -export type { - TextMarshaler -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/encoding/json/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/encoding/json/index.ts deleted file mode 100644 index 00ec01151..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/encoding/json/index.ts +++ /dev/null @@ -1,6 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -export type { - Marshaler -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/encoding/json/models.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/encoding/json/models.ts deleted file mode 100644 index 8cd1a164f..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/encoding/json/models.ts +++ /dev/null @@ -1,12 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Create as $Create } from "/wails/runtime.js"; - -/** - * Marshaler is the interface implemented by types that - * can marshal themselves into valid JSON. - */ -export type Marshaler = any; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/encoding/models.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/encoding/models.ts deleted file mode 100644 index 235dfce3e..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/encoding/models.ts +++ /dev/null @@ -1,14 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Create as $Create } from "/wails/runtime.js"; - -/** - * TextMarshaler is the interface implemented by an object that can - * marshal itself into a textual form. - * - * MarshalText encodes the receiver into UTF-8-encoded text and returns the result. - */ -export type TextMarshaler = any; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/eventcreate.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/eventcreate.ts deleted file mode 100644 index 9cc7781aa..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/eventcreate.ts +++ /dev/null @@ -1,39 +0,0 @@ -//@ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Create as $Create } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as json$0 from "../../../../../encoding/json/models.js"; -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as events_only$0 from "./generator/testcases/events_only/models.js"; -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as more$0 from "./generator/testcases/no_bindings_here/more/models.js"; - -function configure() { - Object.freeze(Object.assign($Create.Events, { - "events_only:class": $$createType0, - "events_only:map": $$createType2, - "events_only:other": $$createType3, - "overlap": $$createType6, - })); -} - -// Private type creation functions -const $$createType0 = events_only$0.SomeClass.createFrom; -const $$createType1 = $Create.Array($Create.Any); -const $$createType2 = $Create.Map($Create.Any, $$createType1); -const $$createType3 = $Create.Array($Create.Any); -const $$createType4 = $Create.Array($Create.Any); -const $$createType5 = $Create.Struct({ - "Field": $$createType4, -}); -const $$createType6 = $Create.Nullable($$createType5); - -configure(); diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/eventdata.d.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/eventdata.d.ts deleted file mode 100644 index 3e53d9287..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/eventdata.d.ts +++ /dev/null @@ -1,30 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import type { Events } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import type * as json$0 from "../../../../../encoding/json/models.js"; -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import type * as events_only$0 from "./generator/testcases/events_only/models.js"; -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import type * as more$0 from "./generator/testcases/no_bindings_here/more/models.js"; - -declare module "/wails/runtime.js" { - namespace Events { - interface CustomEvents { - "events_only:class": events_only$0.SomeClass; - "events_only:map": { [_ in string]?: number[] }; - "events_only:nodata": void; - "events_only:other": more$0.StringPtr[]; - "events_only:string": string; - "interface": json$0.Marshaler; - "overlap": {"Field": boolean[]} | null; - } - } -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/aliases/greetservice.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/aliases/greetservice.ts deleted file mode 100644 index ac113f0da..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/aliases/greetservice.ts +++ /dev/null @@ -1,92 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as subpkg$0 from "./subpkg/models.js"; -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as nobindingshere$0 from "../no_bindings_here/models.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * Get someone. - */ -export function Get(aliasValue: $models.Alias): $CancellablePromise<$models.Person> { - return $Call.ByName("main.GreetService.Get", aliasValue).then(($result: any) => { - return $$createType0($result); - }); -} - -/** - * Apparently, aliases are all the rage right now. - */ -export function GetButAliased(p: $models.AliasedPerson): $CancellablePromise<$models.StrangelyAliasedPerson> { - return $Call.ByName("main.GreetService.GetButAliased", p).then(($result: any) => { - return $$createType0($result); - }); -} - -/** - * Get someone quite different. - */ -export function GetButDifferent(): $CancellablePromise<$models.GenericPerson> { - return $Call.ByName("main.GreetService.GetButDifferent").then(($result: any) => { - return $$createType1($result); - }); -} - -export function GetButForeignPrivateAlias(): $CancellablePromise { - return $Call.ByName("main.GreetService.GetButForeignPrivateAlias").then(($result: any) => { - return $$createType2($result); - }); -} - -export function GetButGenericAliases(): $CancellablePromise<$models.AliasGroup> { - return $Call.ByName("main.GreetService.GetButGenericAliases").then(($result: any) => { - return $$createType3($result); - }); -} - -export function GetButSubPackageAlias(): $CancellablePromise<$models.SubPackageAlias> { - return $Call.ByName("main.GreetService.GetButSubPackageAlias").then(($result: any) => { - return $$createType4($result); - }); -} - -/** - * Greet a lot of unusual things. - */ -export function Greet($0: $models.EmptyAliasStruct, $1: $models.EmptyStruct): $CancellablePromise<$models.AliasStruct> { - return $Call.ByName("main.GreetService.Greet", $0, $1).then(($result: any) => { - return $$createType8($result); - }); -} - -// Private type creation functions -const $$createType0 = $models.Person.createFrom; -const $$createType1 = $models.GenericPerson.createFrom($Create.Any); -const $$createType2 = nobindingshere$0.personImpl.createFrom; -const $$createType3 = $models.AliasGroup.createFrom; -const $$createType4 = subpkg$0.SubStruct.createFrom; -const $$createType5 = $Create.Array($Create.Any); -const $$createType6 = $Create.Array($Create.Any); -const $$createType7 = $Create.Struct({ - "NoMoreIdeas": $$createType6, -}); -const $$createType8 = $Create.Struct({ - "Foo": $$createType5, - "Other": $$createType7, -}); diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/aliases/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/aliases/index.ts deleted file mode 100644 index f01ba91e8..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/aliases/index.ts +++ /dev/null @@ -1,30 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; - -export { - AliasGroup, - AliasedPerson, - EmptyStruct, - GenericPerson, - GenericPersonAlias, - IndirectPersonAlias, - Person, - StrangelyAliasedPerson, - SubPackageAlias, - TPIndirectPersonAlias -} from "./models.js"; - -export type { - Alias, - AliasStruct, - EmptyAliasStruct, - GenericAlias, - GenericMapAlias, - GenericPtrAlias, - OtherAliasStruct -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/aliases/models.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/aliases/models.ts deleted file mode 100644 index 56840a1c3..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/aliases/models.ts +++ /dev/null @@ -1,313 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Create as $Create } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as subpkg$0 from "./subpkg/models.js"; - -/** - * A nice type Alias. - */ -export type Alias = number; - -/** - * A class whose fields have various aliased types. - */ -export class AliasGroup { - "GAi": GenericAlias; - "GAP": GenericAlias>; - "GPAs": GenericPtrAlias; - "GPAP": GenericPtrAlias>; - "GMA": GenericMapAlias; - "GPA": GenericPersonAlias; - "IPA": IndirectPersonAlias; - "TPIPA": TPIndirectPersonAlias; - "SPA": SubPackageAlias; - - /** Creates a new AliasGroup instance. */ - constructor($$source: Partial = {}) { - if (!("GAi" in $$source)) { - this["GAi"] = 0; - } - if (!("GAP" in $$source)) { - this["GAP"] = (new GenericPerson()); - } - if (!("GPAs" in $$source)) { - this["GPAs"] = null; - } - if (!("GPAP" in $$source)) { - this["GPAP"] = null; - } - if (!("GMA" in $$source)) { - this["GMA"] = {}; - } - if (!("GPA" in $$source)) { - this["GPA"] = (new GenericPersonAlias()); - } - if (!("IPA" in $$source)) { - this["IPA"] = (new IndirectPersonAlias()); - } - if (!("TPIPA" in $$source)) { - this["TPIPA"] = (new TPIndirectPersonAlias()); - } - if (!("SPA" in $$source)) { - this["SPA"] = (new SubPackageAlias()); - } - - Object.assign(this, $$source); - } - - /** - * Creates a new AliasGroup instance from a string or object. - */ - static createFrom($$source: any = {}): AliasGroup { - const $$createField1_0 = $$createType0; - const $$createField2_0 = $$createType2; - const $$createField3_0 = $$createType5; - const $$createField4_0 = $$createType6; - const $$createField5_0 = $$createType8; - const $$createField6_0 = $$createType8; - const $$createField7_0 = $$createType0; - const $$createField8_0 = $$createType9; - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - if ("GAP" in $$parsedSource) { - $$parsedSource["GAP"] = $$createField1_0($$parsedSource["GAP"]); - } - if ("GPAs" in $$parsedSource) { - $$parsedSource["GPAs"] = $$createField2_0($$parsedSource["GPAs"]); - } - if ("GPAP" in $$parsedSource) { - $$parsedSource["GPAP"] = $$createField3_0($$parsedSource["GPAP"]); - } - if ("GMA" in $$parsedSource) { - $$parsedSource["GMA"] = $$createField4_0($$parsedSource["GMA"]); - } - if ("GPA" in $$parsedSource) { - $$parsedSource["GPA"] = $$createField5_0($$parsedSource["GPA"]); - } - if ("IPA" in $$parsedSource) { - $$parsedSource["IPA"] = $$createField6_0($$parsedSource["IPA"]); - } - if ("TPIPA" in $$parsedSource) { - $$parsedSource["TPIPA"] = $$createField7_0($$parsedSource["TPIPA"]); - } - if ("SPA" in $$parsedSource) { - $$parsedSource["SPA"] = $$createField8_0($$parsedSource["SPA"]); - } - return new AliasGroup($$parsedSource as Partial); - } -} - -/** - * A struct alias. - * This should be rendered as a typedef or interface in every mode. - */ -export interface AliasStruct { - /** - * A field with a comment. - */ - "Foo": number[]; - - /** - * Definitely not Foo. - */ - "Bar"?: string; - "Baz"?: string; - - /** - * A nested alias struct. - */ - "Other": OtherAliasStruct; -} - -/** - * An empty struct alias. - */ -export interface EmptyAliasStruct { -} - -/** - * An empty struct. - */ -export class EmptyStruct { - - /** Creates a new EmptyStruct instance. */ - constructor($$source: Partial = {}) { - - Object.assign(this, $$source); - } - - /** - * Creates a new EmptyStruct instance from a string or object. - */ - static createFrom($$source: any = {}): EmptyStruct { - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - return new EmptyStruct($$parsedSource as Partial); - } -} - -/** - * A generic alias that forwards to a type parameter. - */ -export type GenericAlias = T; - -/** - * A generic alias that wraps a map. - */ -export type GenericMapAlias = { [_ in string]?: U }; - -/** - * A generic struct containing an alias. - */ -export class GenericPerson { - "Name"?: T; - "AliasedField": Alias; - - /** Creates a new GenericPerson instance. */ - constructor($$source: Partial> = {}) { - if (!("AliasedField" in $$source)) { - this["AliasedField"] = 0; - } - - Object.assign(this, $$source); - } - - /** - * Given creation functions for each type parameter, - * returns a creation function for a concrete instance - * of the generic class GenericPerson. - */ - static createFrom($$createParamT: (source: any) => T): ($$source?: any) => GenericPerson { - const $$createField0_0 = $$createParamT; - return ($$source: any = {}) => { - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - if ("Name" in $$parsedSource) { - $$parsedSource["Name"] = $$createField0_0($$parsedSource["Name"]); - } - return new GenericPerson($$parsedSource as Partial>); - }; - } -} - -/** - * A generic alias that wraps a generic struct. - */ -export const GenericPersonAlias = GenericPerson; - -/** - * A generic alias that wraps a generic struct. - */ -export type GenericPersonAlias = GenericPerson[]>; - -/** - * A generic alias that wraps a pointer type. - */ -export type GenericPtrAlias = GenericAlias | null; - -/** - * An alias that wraps a class through a non-typeparam alias. - */ -export const IndirectPersonAlias = GenericPersonAlias; - -/** - * An alias that wraps a class through a non-typeparam alias. - */ -export type IndirectPersonAlias = GenericPersonAlias; - -/** - * Another struct alias. - */ -export interface OtherAliasStruct { - "NoMoreIdeas": number[]; -} - -/** - * A non-generic struct containing an alias. - */ -export class Person { - /** - * The Person's name. - */ - "Name": string; - - /** - * A random alias field. - */ - "AliasedField": Alias; - - /** Creates a new Person instance. */ - constructor($$source: Partial = {}) { - if (!("Name" in $$source)) { - this["Name"] = ""; - } - if (!("AliasedField" in $$source)) { - this["AliasedField"] = 0; - } - - Object.assign(this, $$source); - } - - /** - * Creates a new Person instance from a string or object. - */ - static createFrom($$source: any = {}): Person { - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - return new Person($$parsedSource as Partial); - } -} - -/** - * A class alias. - */ -export const AliasedPerson = Person; - -/** - * A class alias. - */ -export type AliasedPerson = Person; - -/** - * Another class alias, but ordered after its aliased class. - */ -export const StrangelyAliasedPerson = Person; - -/** - * Another class alias, but ordered after its aliased class. - */ -export type StrangelyAliasedPerson = Person; - -/** - * An alias referencing another package that is not used elsewhere. - */ -export const SubPackageAlias = subpkg$0.SubStruct; - -/** - * An alias referencing another package that is not used elsewhere. - */ -export type SubPackageAlias = subpkg$0.SubStruct; - -/** - * An alias that wraps a class through a typeparam alias. - */ -export const TPIndirectPersonAlias = GenericPerson; - -/** - * An alias that wraps a class through a typeparam alias. - */ -export type TPIndirectPersonAlias = GenericAlias>; - -// Private type creation functions -const $$createType0 = GenericPerson.createFrom($Create.Any); -const $$createType1 = $Create.Array($Create.Any); -const $$createType2 = $Create.Nullable($$createType1); -const $$createType3 = $Create.Array($Create.Any); -const $$createType4 = GenericPerson.createFrom($$createType3); -const $$createType5 = $Create.Nullable($$createType4); -const $$createType6 = $Create.Map($Create.Any, $Create.Any); -const $$createType7 = $Create.Array($Create.Any); -const $$createType8 = GenericPerson.createFrom($$createType7); -const $$createType9 = subpkg$0.SubStruct.createFrom; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/aliases/subpkg/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/aliases/subpkg/index.ts deleted file mode 100644 index 19a8a0184..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/aliases/subpkg/index.ts +++ /dev/null @@ -1,6 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -export { - SubStruct -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/aliases/subpkg/models.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/aliases/subpkg/models.ts deleted file mode 100644 index 03ba700d1..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/aliases/subpkg/models.ts +++ /dev/null @@ -1,37 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Create as $Create } from "/wails/runtime.js"; - -/** - * SubStruct is a type in a subpackage that is only referenced through an alias. - */ -export class SubStruct { - "SomeField": string[]; - - /** Creates a new SubStruct instance. */ - constructor($$source: Partial = {}) { - if (!("SomeField" in $$source)) { - this["SomeField"] = []; - } - - Object.assign(this, $$source); - } - - /** - * Creates a new SubStruct instance from a string or object. - */ - static createFrom($$source: any = {}): SubStruct { - const $$createField0_0 = $$createType0; - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - if ("SomeField" in $$parsedSource) { - $$parsedSource["SomeField"] = $$createField0_0($$parsedSource["SomeField"]); - } - return new SubStruct($$parsedSource as Partial); - } -} - -// Private type creation functions -const $$createType0 = $Create.Array($Create.Any); diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_expressions/config/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_expressions/config/index.ts deleted file mode 100644 index bdcf43c67..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_expressions/config/index.ts +++ /dev/null @@ -1,9 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as Service7 from "./service7.js"; -import * as Service9 from "./service9.js"; -export { - Service7, - Service9 -}; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_expressions/config/service7.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_expressions/config/service7.ts deleted file mode 100644 index 0780a0de3..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_expressions/config/service7.ts +++ /dev/null @@ -1,10 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -export function TestMethod(): $CancellablePromise { - return $Call.ByName("github.com/wailsapp/wails/v3/internal/generator/testcases/complex_expressions/config.Service7.TestMethod"); -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_expressions/config/service9.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_expressions/config/service9.ts deleted file mode 100644 index a2222265f..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_expressions/config/service9.ts +++ /dev/null @@ -1,10 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -export function TestMethod2(): $CancellablePromise { - return $Call.ByName("github.com/wailsapp/wails/v3/internal/generator/testcases/complex_expressions/config.Service9.TestMethod2"); -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_json/greetservice.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_json/greetservice.ts deleted file mode 100644 index f2106e7f4..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_json/greetservice.ts +++ /dev/null @@ -1,22 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * Greet does XYZ - */ -export function Greet(person: $models.Person, emb: $models.Embedded1): $CancellablePromise { - return $Call.ByName("main.GreetService.Greet", person, emb); -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_json/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_json/index.ts deleted file mode 100644 index 6cdc52c66..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_json/index.ts +++ /dev/null @@ -1,17 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; - -export { - Embedded1, - Person, - Title -} from "./models.js"; - -export type { - Embedded3 -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_json/models.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_json/models.ts deleted file mode 100644 index 50f23b52d..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_json/models.ts +++ /dev/null @@ -1,237 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Create as $Create } from "/wails/runtime.js"; - -export class Embedded1 { - /** - * Friends should be shadowed in Person by a field of lesser depth - */ - "Friends": number; - - /** - * Vanish should be omitted from Person because there is another field with same depth and no tag - */ - "Vanish": number; - - /** - * StillThere should be shadowed in Person by other field with same depth and a json tag - */ - "StillThere": string; - - /** - * NamingThingsIsHard is a law of programming - */ - "NamingThingsIsHard": `${boolean}`; - - /** Creates a new Embedded1 instance. */ - constructor($$source: Partial = {}) { - if (!("Friends" in $$source)) { - this["Friends"] = 0; - } - if (!("Vanish" in $$source)) { - this["Vanish"] = 0; - } - if (!("StillThere" in $$source)) { - this["StillThere"] = ""; - } - if (!("NamingThingsIsHard" in $$source)) { - this["NamingThingsIsHard"] = "false"; - } - - Object.assign(this, $$source); - } - - /** - * Creates a new Embedded1 instance from a string or object. - */ - static createFrom($$source: any = {}): Embedded1 { - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - return new Embedded1($$parsedSource as Partial); - } -} - -export type Embedded3 = string; - -/** - * Person represents a person - */ -export class Person { - /** - * Titles is optional in JSON - */ - "Titles"?: Title[]; - - /** - * Names has a - * multiline comment - */ - "Names": string[]; - - /** - * Partner has a custom and complex JSON key - */ - "Partner": Person | null; - "Friends": (Person | null)[]; - - /** - * NamingThingsIsHard is a law of programming - */ - "NamingThingsIsHard": `${boolean}`; - - /** - * StillThereButRenamed should shadow in Person the other field with same depth and no json tag - */ - "StillThere": Embedded3 | null; - - /** - * StrangeNumber maps to "-" - */ - "-": number; - - /** - * Embedded3 should appear with key "Embedded3" - */ - "Embedded3": Embedded3; - - /** - * StrangerNumber is serialized as a string - */ - "StrangerNumber": `${number}`; - - /** - * StrangestString is optional and serialized as a JSON string - */ - "StrangestString"?: `"${string}"`; - - /** - * StringStrangest is serialized as a JSON string and optional - */ - "StringStrangest"?: `"${string}"`; - - /** - * embedded4 should be optional and appear with key "emb4" - */ - "emb4"?: embedded4; - - /** Creates a new Person instance. */ - constructor($$source: Partial = {}) { - if (!("Names" in $$source)) { - this["Names"] = []; - } - if (!("Partner" in $$source)) { - this["Partner"] = null; - } - if (!("Friends" in $$source)) { - this["Friends"] = []; - } - if (!("NamingThingsIsHard" in $$source)) { - this["NamingThingsIsHard"] = "false"; - } - if (!("StillThere" in $$source)) { - this["StillThere"] = null; - } - if (!("-" in $$source)) { - this["-"] = 0; - } - if (!("Embedded3" in $$source)) { - this["Embedded3"] = ""; - } - if (!("StrangerNumber" in $$source)) { - this["StrangerNumber"] = "0"; - } - - Object.assign(this, $$source); - } - - /** - * Creates a new Person instance from a string or object. - */ - static createFrom($$source: any = {}): Person { - const $$createField0_0 = $$createType0; - const $$createField1_0 = $$createType1; - const $$createField2_0 = $$createType3; - const $$createField3_0 = $$createType4; - const $$createField11_0 = $$createType5; - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - if ("Titles" in $$parsedSource) { - $$parsedSource["Titles"] = $$createField0_0($$parsedSource["Titles"]); - } - if ("Names" in $$parsedSource) { - $$parsedSource["Names"] = $$createField1_0($$parsedSource["Names"]); - } - if ("Partner" in $$parsedSource) { - $$parsedSource["Partner"] = $$createField2_0($$parsedSource["Partner"]); - } - if ("Friends" in $$parsedSource) { - $$parsedSource["Friends"] = $$createField3_0($$parsedSource["Friends"]); - } - if ("emb4" in $$parsedSource) { - $$parsedSource["emb4"] = $$createField11_0($$parsedSource["emb4"]); - } - return new Person($$parsedSource as Partial); - } -} - -/** - * Title is a title - */ -export enum Title { - /** - * The Go zero value for the underlying type of the enum. - */ - $zero = "", - - /** - * Mister is a title - */ - Mister = "Mr", - Miss = "Miss", - Ms = "Ms", - Mrs = "Mrs", - Dr = "Dr", -}; - -export class embedded4 { - /** - * NamingThingsIsHard is a law of programming - */ - "NamingThingsIsHard": `${boolean}`; - - /** - * Friends should not be shadowed in Person as embedded4 is not embedded - * from encoding/json's point of view; - * however, it should be shadowed in Embedded1 - */ - "Friends": boolean; - - /** Creates a new embedded4 instance. */ - constructor($$source: Partial = {}) { - if (!("NamingThingsIsHard" in $$source)) { - this["NamingThingsIsHard"] = "false"; - } - if (!("Friends" in $$source)) { - this["Friends"] = false; - } - - Object.assign(this, $$source); - } - - /** - * Creates a new embedded4 instance from a string or object. - */ - static createFrom($$source: any = {}): embedded4 { - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - return new embedded4($$parsedSource as Partial); - } -} - -// Private type creation functions -const $$createType0 = $Create.Array($Create.Any); -const $$createType1 = $Create.Array($Create.Any); -const $$createType2 = Person.createFrom; -const $$createType3 = $Create.Nullable($$createType2); -const $$createType4 = $Create.Array($$createType3); -const $$createType5 = embedded4.createFrom; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_method/greetservice.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_method/greetservice.ts deleted file mode 100644 index 32514cc98..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_method/greetservice.ts +++ /dev/null @@ -1,32 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * Greet does XYZ - * It has a multiline doc comment - * The comment has even some * / traps!! - */ -export function Greet(str: string, people: $models.Person[], $2: {"AnotherCount": number, "AnotherOne": $models.Person | null}, assoc: { [_ in `${number}`]?: boolean | null }, $4: (number | null)[], ...other: string[]): $CancellablePromise<[$models.Person, any, number[]]> { - return $Call.ByName("main.GreetService.Greet", str, people, $2, assoc, $4, other).then(($result: any) => { - $result[0] = $$createType0($result[0]); - $result[2] = $$createType1($result[2]); - return $result; - }); -} - -// Private type creation functions -const $$createType0 = $models.Person.createFrom; -const $$createType1 = $Create.Array($Create.Any); diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_method/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_method/index.ts deleted file mode 100644 index f95c1b558..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_method/index.ts +++ /dev/null @@ -1,11 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; - -export { - Person -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_method/models.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_method/models.ts deleted file mode 100644 index 2417aff4c..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_method/models.ts +++ /dev/null @@ -1,30 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Create as $Create } from "/wails/runtime.js"; - -/** - * Person represents a person - */ -export class Person { - "Name": string; - - /** Creates a new Person instance. */ - constructor($$source: Partial = {}) { - if (!("Name" in $$source)) { - this["Name"] = ""; - } - - Object.assign(this, $$source); - } - - /** - * Creates a new Person instance from a string or object. - */ - static createFrom($$source: any = {}): Person { - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - return new Person($$parsedSource as Partial); - } -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/cyclic_imports/greetservice.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/cyclic_imports/greetservice.ts deleted file mode 100644 index 2f0e45aff..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/cyclic_imports/greetservice.ts +++ /dev/null @@ -1,30 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * Make a cycle. - */ -export function MakeCycles(): $CancellablePromise<[$models.StructA, $models.StructC]> { - return $Call.ByName("main.GreetService.MakeCycles").then(($result: any) => { - $result[0] = $$createType0($result[0]); - $result[1] = $$createType1($result[1]); - return $result; - }); -} - -// Private type creation functions -const $$createType0 = $models.StructA.createFrom; -const $$createType1 = $models.StructC.createFrom; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/cyclic_imports/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/cyclic_imports/index.ts deleted file mode 100644 index 4b190b8da..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/cyclic_imports/index.ts +++ /dev/null @@ -1,13 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; - -export { - StructA, - StructC, - StructE -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/cyclic_imports/models.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/cyclic_imports/models.ts deleted file mode 100644 index 9e86cd674..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/cyclic_imports/models.ts +++ /dev/null @@ -1,131 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Create as $Create } from "/wails/runtime.js"; - -export class StructA { - "B": structB | null; - - /** Creates a new StructA instance. */ - constructor($$source: Partial = {}) { - if (!("B" in $$source)) { - this["B"] = null; - } - - Object.assign(this, $$source); - } - - /** - * Creates a new StructA instance from a string or object. - */ - static createFrom($$source: any = {}): StructA { - const $$createField0_0 = $$createType1; - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - if ("B" in $$parsedSource) { - $$parsedSource["B"] = $$createField0_0($$parsedSource["B"]); - } - return new StructA($$parsedSource as Partial); - } -} - -export class StructC { - "D": structD; - - /** Creates a new StructC instance. */ - constructor($$source: Partial = {}) { - if (!("D" in $$source)) { - this["D"] = (new structD()); - } - - Object.assign(this, $$source); - } - - /** - * Creates a new StructC instance from a string or object. - */ - static createFrom($$source: any = {}): StructC { - const $$createField0_0 = $$createType2; - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - if ("D" in $$parsedSource) { - $$parsedSource["D"] = $$createField0_0($$parsedSource["D"]); - } - return new StructC($$parsedSource as Partial); - } -} - -export class StructE { - - /** Creates a new StructE instance. */ - constructor($$source: Partial = {}) { - - Object.assign(this, $$source); - } - - /** - * Creates a new StructE instance from a string or object. - */ - static createFrom($$source: any = {}): StructE { - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - return new StructE($$parsedSource as Partial); - } -} - -export class structB { - "A": StructA | null; - - /** Creates a new structB instance. */ - constructor($$source: Partial = {}) { - if (!("A" in $$source)) { - this["A"] = null; - } - - Object.assign(this, $$source); - } - - /** - * Creates a new structB instance from a string or object. - */ - static createFrom($$source: any = {}): structB { - const $$createField0_0 = $$createType4; - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - if ("A" in $$parsedSource) { - $$parsedSource["A"] = $$createField0_0($$parsedSource["A"]); - } - return new structB($$parsedSource as Partial); - } -} - -export class structD { - "E": StructE; - - /** Creates a new structD instance. */ - constructor($$source: Partial = {}) { - if (!("E" in $$source)) { - this["E"] = (new StructE()); - } - - Object.assign(this, $$source); - } - - /** - * Creates a new structD instance from a string or object. - */ - static createFrom($$source: any = {}): structD { - const $$createField0_0 = $$createType5; - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - if ("E" in $$parsedSource) { - $$parsedSource["E"] = $$createField0_0($$parsedSource["E"]); - } - return new structD($$parsedSource as Partial); - } -} - -// Private type creation functions -const $$createType0 = structB.createFrom; -const $$createType1 = $Create.Nullable($$createType0); -const $$createType2 = structD.createFrom; -const $$createType3 = StructA.createFrom; -const $$createType4 = $Create.Nullable($$createType3); -const $$createType5 = StructE.createFrom; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/cyclic_types/greetservice.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/cyclic_types/greetservice.ts deleted file mode 100644 index dba844168..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/cyclic_types/greetservice.ts +++ /dev/null @@ -1,63 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * Make a cycle. - */ -export function MakeCycles(): $CancellablePromise<[$models.Cyclic, $models.GenericCyclic<$models.GenericCyclic>]> { - return $Call.ByName("main.GreetService.MakeCycles").then(($result: any) => { - $result[0] = $$createType0($result[0]); - $result[1] = $$createType9($result[1]); - return $result; - }); -} - -// Private type creation functions -var $$createType0 = (function $$initCreateType0(...args: any[]): any { - if ($$createType0 === $$initCreateType0) { - $$createType0 = $$createType3; - } - return $$createType0(...args); -}); -const $$createType1 = $Create.Nullable($$createType0); -const $$createType2 = $Create.Map($Create.Any, $$createType1); -const $$createType3 = $Create.Array($$createType2); -var $$createType4 = (function $$initCreateType4(...args: any[]): any { - if ($$createType4 === $$initCreateType4) { - $$createType4 = $$createType8; - } - return $$createType4(...args); -}); -const $$createType5 = $Create.Nullable($$createType4); -const $$createType6 = $Create.Array($Create.Any); -const $$createType7 = $Create.Struct({ - "X": $$createType5, - "Y": $$createType6, -}); -const $$createType8 = $Create.Array($$createType7); -var $$createType9 = (function $$initCreateType9(...args: any[]): any { - if ($$createType9 === $$initCreateType9) { - $$createType9 = $$createType13; - } - return $$createType9(...args); -}); -const $$createType10 = $Create.Nullable($$createType9); -const $$createType11 = $Create.Array($$createType4); -const $$createType12 = $Create.Struct({ - "X": $$createType10, - "Y": $$createType11, -}); -const $$createType13 = $Create.Array($$createType12); diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/cyclic_types/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/cyclic_types/index.ts deleted file mode 100644 index 16cef660c..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/cyclic_types/index.ts +++ /dev/null @@ -1,13 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; - -export type { - Alias, - Cyclic, - GenericCyclic -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/cyclic_types/models.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/cyclic_types/models.ts deleted file mode 100644 index 05c08cc6b..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/cyclic_types/models.ts +++ /dev/null @@ -1,12 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Create as $Create } from "/wails/runtime.js"; - -export type Alias = Cyclic | null; - -export type Cyclic = { [_ in string]?: Alias }[]; - -export type GenericCyclic = {"X": GenericCyclic | null, "Y": T[]}[]; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/index.ts deleted file mode 100644 index b9fbdba96..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/index.ts +++ /dev/null @@ -1,13 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as Service from "./service.js"; -export { - Service -}; - -console.log("Hello everywhere!"); -console.log("Hello everywhere again!"); -console.log("Hello Classes!"); -console.log("Hello TS!"); -console.log("Hello TS Classes!"); diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/internalservice.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/internalservice.ts deleted file mode 100644 index 9271273bc..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/internalservice.ts +++ /dev/null @@ -1,19 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * An exported but internal service. - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -export function Method($0: $models.InternalModel): $CancellablePromise { - return $Call.ByName("main.InternalService.Method", $0); -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/models.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/models.ts deleted file mode 100644 index 4d242fc2c..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/models.ts +++ /dev/null @@ -1,54 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Create as $Create } from "/wails/runtime.js"; - -/** - * An exported but internal model. - */ -export class InternalModel { - "Field": string; - - /** Creates a new InternalModel instance. */ - constructor($$source: Partial = {}) { - if (!("Field" in $$source)) { - this["Field"] = ""; - } - - Object.assign(this, $$source); - } - - /** - * Creates a new InternalModel instance from a string or object. - */ - static createFrom($$source: any = {}): InternalModel { - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - return new InternalModel($$parsedSource as Partial); - } -} - -/** - * An unexported model. - */ -export class unexportedModel { - "Field": string; - - /** Creates a new unexportedModel instance. */ - constructor($$source: Partial = {}) { - if (!("Field" in $$source)) { - this["Field"] = ""; - } - - Object.assign(this, $$source); - } - - /** - * Creates a new unexportedModel instance from a string or object. - */ - static createFrom($$source: any = {}): unexportedModel { - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - return new unexportedModel($$parsedSource as Partial); - } -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/otherpackage/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/otherpackage/index.ts deleted file mode 100644 index e52a0ccb8..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/otherpackage/index.ts +++ /dev/null @@ -1,6 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -export { - Dummy -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/otherpackage/models.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/otherpackage/models.ts deleted file mode 100644 index b927155d5..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/otherpackage/models.ts +++ /dev/null @@ -1,23 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Create as $Create } from "/wails/runtime.js"; - -export class Dummy { - - /** Creates a new Dummy instance. */ - constructor($$source: Partial = {}) { - - Object.assign(this, $$source); - } - - /** - * Creates a new Dummy instance from a string or object. - */ - static createFrom($$source: any = {}): Dummy { - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - return new Dummy($$parsedSource as Partial); - } -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/otherpackage/test_t.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/otherpackage/test_t.ts deleted file mode 100644 index 6703820f1..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/otherpackage/test_t.ts +++ /dev/null @@ -1,3 +0,0 @@ -import { CustomMethod } from "../service.js"; - -CustomMethod("TS"); diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/otherpackage/test_tc.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/otherpackage/test_tc.ts deleted file mode 100644 index 15d2994e9..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/otherpackage/test_tc.ts +++ /dev/null @@ -1,3 +0,0 @@ -import { CustomMethod } from "../service.js"; - -CustomMethod("TS Classes"); diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/service.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/service.ts deleted file mode 100644 index 0687bd8ac..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/service.ts +++ /dev/null @@ -1,22 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as otherpackage$0 from "./otherpackage/models.js"; - -function InternalMethod($0: string): $CancellablePromise { - return $Call.ByName("main.Service.InternalMethod", $0); -} - -export function VisibleMethod($0: otherpackage$0.Dummy): $CancellablePromise { - return $Call.ByName("main.Service.VisibleMethod", $0); -} - -export async function CustomMethod(arg: string): Promise { - await InternalMethod("Hello " + arg + "!"); -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/test.js b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/test.js deleted file mode 100644 index 138385f53..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/test.js +++ /dev/null @@ -1,3 +0,0 @@ -import { CustomMethod } from "./service.js"; - -CustomMethod("everywhere"); diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/test_all.js b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/test_all.js deleted file mode 100644 index 19d5c2f42..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/test_all.js +++ /dev/null @@ -1,3 +0,0 @@ -import { CustomMethod } from "./service.js"; - -CustomMethod("everywhere again"); diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/test_c.js b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/test_c.js deleted file mode 100644 index 724e79e12..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/test_c.js +++ /dev/null @@ -1,3 +0,0 @@ -import { CustomMethod } from "./service.js"; - -CustomMethod("Classes"); diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/test_t.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/test_t.ts deleted file mode 100644 index 253d3f2f6..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/test_t.ts +++ /dev/null @@ -1,3 +0,0 @@ -import { CustomMethod } from "./service.js"; - -CustomMethod("TS"); diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/test_tc.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/test_tc.ts deleted file mode 100644 index 66b739d3a..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/test_tc.ts +++ /dev/null @@ -1,3 +0,0 @@ -import { CustomMethod } from "./service.js"; - -CustomMethod("TS Classes"); diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/unexportedservice.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/unexportedservice.ts deleted file mode 100644 index 34b23e24d..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/unexportedservice.ts +++ /dev/null @@ -1,19 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * An unexported service. - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -export function Method($0: $models.unexportedModel): $CancellablePromise { - return $Call.ByName("main.unexportedService.Method", $0); -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/embedded_interface/greetservice.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/embedded_interface/greetservice.ts deleted file mode 100644 index c5b06be75..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/embedded_interface/greetservice.ts +++ /dev/null @@ -1,47 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -/** - * Comment 1. - */ -export function Method1(): $CancellablePromise { - return $Call.ByName("main.GreetService.Method1"); -} - -/** - * Comment 2. - */ -export function Method2(): $CancellablePromise { - return $Call.ByName("main.GreetService.Method2"); -} - -/** - * Comment 3a. - * Comment 3b. - */ -export function Method3(): $CancellablePromise { - return $Call.ByName("main.GreetService.Method3"); -} - -/** - * Comment 4. - */ -export function Method4(): $CancellablePromise { - return $Call.ByName("main.GreetService.Method4"); -} - -/** - * Comment 5. - */ -export function Method5(): $CancellablePromise { - return $Call.ByName("main.GreetService.Method5"); -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/embedded_interface/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/embedded_interface/index.ts deleted file mode 100644 index 50e3f0435..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/embedded_interface/index.ts +++ /dev/null @@ -1,7 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/enum/greetservice.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/enum/greetservice.ts deleted file mode 100644 index 45abc153e..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/enum/greetservice.ts +++ /dev/null @@ -1,35 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * Greet does XYZ - */ -export function Greet(name: string, title: $models.Title): $CancellablePromise { - return $Call.ByName("main.GreetService.Greet", name, title); -} - -/** - * NewPerson creates a new person - */ -export function NewPerson(name: string): $CancellablePromise<$models.Person | null> { - return $Call.ByName("main.GreetService.NewPerson", name).then(($result: any) => { - return $$createType1($result); - }); -} - -// Private type creation functions -const $$createType0 = $models.Person.createFrom; -const $$createType1 = $Create.Nullable($$createType0); diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/enum/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/enum/index.ts deleted file mode 100644 index 3b4d2f5c6..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/enum/index.ts +++ /dev/null @@ -1,13 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; - -export { - Age, - Person, - Title -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/enum/models.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/enum/models.ts deleted file mode 100644 index a50282a38..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/enum/models.ts +++ /dev/null @@ -1,82 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Create as $Create } from "/wails/runtime.js"; - -/** - * Age is an integer with some predefined values - */ -export type Age = number; - -/** - * Predefined constants for type Age. - * @namespace - */ -export const Age = { - NewBorn: 0, - Teenager: 12, - YoungAdult: 18, - - /** - * Oh no, some grey hair! - */ - MiddleAged: 50, - - /** - * Unbelievable! - */ - Mathusalem: 1000, -}; - -/** - * Person represents a person - */ -export class Person { - "Title": Title; - "Name": string; - "Age": Age; - - /** Creates a new Person instance. */ - constructor($$source: Partial = {}) { - if (!("Title" in $$source)) { - this["Title"] = Title.$zero; - } - if (!("Name" in $$source)) { - this["Name"] = ""; - } - if (!("Age" in $$source)) { - this["Age"] = 0; - } - - Object.assign(this, $$source); - } - - /** - * Creates a new Person instance from a string or object. - */ - static createFrom($$source: any = {}): Person { - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - return new Person($$parsedSource as Partial); - } -} - -/** - * Title is a title - */ -export enum Title { - /** - * The Go zero value for the underlying type of the enum. - */ - $zero = "", - - /** - * Mister is a title - */ - Mister = "Mr", - Miss = "Miss", - Ms = "Ms", - Mrs = "Mrs", - Dr = "Dr", -}; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_from_imported_package/greetservice.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_from_imported_package/greetservice.ts deleted file mode 100644 index c4afd85da..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_from_imported_package/greetservice.ts +++ /dev/null @@ -1,22 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as services$0 from "./services/models.js"; - -/** - * Greet does XYZ - */ -export function Greet(name: string, title: services$0.Title): $CancellablePromise { - return $Call.ByName("main.GreetService.Greet", name, title); -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_from_imported_package/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_from_imported_package/index.ts deleted file mode 100644 index 50e3f0435..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_from_imported_package/index.ts +++ /dev/null @@ -1,7 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_from_imported_package/services/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_from_imported_package/services/index.ts deleted file mode 100644 index 01c612edc..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_from_imported_package/services/index.ts +++ /dev/null @@ -1,6 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -export { - Title -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_from_imported_package/services/models.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_from_imported_package/services/models.ts deleted file mode 100644 index 661222bdf..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_from_imported_package/services/models.ts +++ /dev/null @@ -1,22 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Create as $Create } from "/wails/runtime.js"; - -export enum Title { - /** - * The Go zero value for the underlying type of the enum. - */ - $zero = "", - - /** - * Mister is a title - */ - Mister = "Mr", - Miss = "Miss", - Ms = "Ms", - Mrs = "Mrs", - Dr = "Dr", -}; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_map_keys/enummapservice.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_map_keys/enummapservice.ts deleted file mode 100644 index 3fc57b4ce..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_map_keys/enummapservice.ts +++ /dev/null @@ -1,80 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * EnumMapService tests various enum map key scenarios - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * GetColorCodes returns a map with uint8 enum keys - */ -export function GetColorCodes(): $CancellablePromise<{ [_ in $models.Color]?: string }> { - return $Call.ByName("main.EnumMapService.GetColorCodes").then(($result: any) => { - return $$createType0($result); - }); -} - -/** - * GetNestedEnumMap returns a map with enum keys and complex values - */ -export function GetNestedEnumMap(): $CancellablePromise<{ [_ in $models.Status]?: { [_ in $models.Priority]?: string } }> { - return $Call.ByName("main.EnumMapService.GetNestedEnumMap").then(($result: any) => { - return $$createType2($result); - }); -} - -/** - * GetOptionalEnumMap returns a map with enum keys to optional values - */ -export function GetOptionalEnumMap(): $CancellablePromise<{ [_ in $models.Status]?: string | null }> { - return $Call.ByName("main.EnumMapService.GetOptionalEnumMap").then(($result: any) => { - return $$createType3($result); - }); -} - -/** - * GetPersonsByStatus returns a map with enum keys to struct values - */ -export function GetPersonsByStatus(): $CancellablePromise<{ [_ in $models.Status]?: $models.Person[] }> { - return $Call.ByName("main.EnumMapService.GetPersonsByStatus").then(($result: any) => { - return $$createType6($result); - }); -} - -/** - * GetPriorityWeights returns a map with integer enum keys - */ -export function GetPriorityWeights(): $CancellablePromise<{ [_ in $models.Priority]?: number }> { - return $Call.ByName("main.EnumMapService.GetPriorityWeights").then(($result: any) => { - return $$createType7($result); - }); -} - -/** - * GetStatusMessages returns a map with string enum keys - */ -export function GetStatusMessages(): $CancellablePromise<{ [_ in $models.Status]?: string }> { - return $Call.ByName("main.EnumMapService.GetStatusMessages").then(($result: any) => { - return $$createType8($result); - }); -} - -// Private type creation functions -const $$createType0 = $Create.Map($Create.Any, $Create.Any); -const $$createType1 = $Create.Map($Create.Any, $Create.Any); -const $$createType2 = $Create.Map($Create.Any, $$createType1); -const $$createType3 = $Create.Map($Create.Any, $Create.Any); -const $$createType4 = $models.Person.createFrom; -const $$createType5 = $Create.Array($$createType4); -const $$createType6 = $Create.Map($Create.Any, $$createType5); -const $$createType7 = $Create.Map($Create.Any, $Create.Any); -const $$createType8 = $Create.Map($Create.Any, $Create.Any); diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_map_keys/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_map_keys/index.ts deleted file mode 100644 index d209a0f7d..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_map_keys/index.ts +++ /dev/null @@ -1,14 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as EnumMapService from "./enummapservice.js"; -export { - EnumMapService -}; - -export { - Color, - Person, - Priority, - Status -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_map_keys/models.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_map_keys/models.ts deleted file mode 100644 index ba3d2baeb..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_map_keys/models.ts +++ /dev/null @@ -1,77 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Create as $Create } from "/wails/runtime.js"; - -/** - * Color represents color values - */ -export enum Color { - /** - * The Go zero value for the underlying type of the enum. - */ - $zero = 0, - - Red = 1, - Green = 2, - Blue = 3, -}; - -/** - * Person represents a person with status - */ -export class Person { - "Name": string; - "Status": Status; - - /** Creates a new Person instance. */ - constructor($$source: Partial = {}) { - if (!("Name" in $$source)) { - this["Name"] = ""; - } - if (!("Status" in $$source)) { - this["Status"] = Status.$zero; - } - - Object.assign(this, $$source); - } - - /** - * Creates a new Person instance from a string or object. - */ - static createFrom($$source: any = {}): Person { - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - return new Person($$parsedSource as Partial); - } -} - -/** - * Priority represents priority levels - */ -export enum Priority { - /** - * The Go zero value for the underlying type of the enum. - */ - $zero = 0, - - PriorityLow = 1, - PriorityMedium = 2, - PriorityHigh = 3, -}; - -/** - * Status represents different status values - */ -export enum Status { - /** - * The Go zero value for the underlying type of the enum. - */ - $zero = "", - - StatusPending = "pending", - StatusRunning = "running", - StatusCompleted = "completed", - StatusFailed = "failed", -}; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/events_only/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/events_only/index.ts deleted file mode 100644 index bb6e0a17f..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/events_only/index.ts +++ /dev/null @@ -1,6 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -export { - SomeClass -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/events_only/models.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/events_only/models.ts deleted file mode 100644 index 4719f61cf..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/events_only/models.ts +++ /dev/null @@ -1,45 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Create as $Create } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as nobindingshere$0 from "../no_bindings_here/models.js"; - -/** - * SomeClass renders as a TS class. - */ -export class SomeClass { - "Field": string; - "Meadow": nobindingshere$0.HowDifferent; - - /** Creates a new SomeClass instance. */ - constructor($$source: Partial = {}) { - if (!("Field" in $$source)) { - this["Field"] = ""; - } - if (!("Meadow" in $$source)) { - this["Meadow"] = (new nobindingshere$0.HowDifferent()); - } - - Object.assign(this, $$source); - } - - /** - * Creates a new SomeClass instance from a string or object. - */ - static createFrom($$source: any = {}): SomeClass { - const $$createField1_0 = $$createType0; - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - if ("Meadow" in $$parsedSource) { - $$parsedSource["Meadow"] = $$createField1_0($$parsedSource["Meadow"]); - } - return new SomeClass($$parsedSource as Partial); - } -} - -// Private type creation functions -const $$createType0 = nobindingshere$0.HowDifferent.createFrom($Create.Any); diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_imported_package/greetservice.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_imported_package/greetservice.ts deleted file mode 100644 index 1a2ffb266..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_imported_package/greetservice.ts +++ /dev/null @@ -1,35 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * Greet does XYZ - */ -export function Greet(name: string): $CancellablePromise { - return $Call.ByName("main.GreetService.Greet", name); -} - -/** - * NewPerson creates a new person - */ -export function NewPerson(name: string): $CancellablePromise<$models.Person | null> { - return $Call.ByName("main.GreetService.NewPerson", name).then(($result: any) => { - return $$createType1($result); - }); -} - -// Private type creation functions -const $$createType0 = $models.Person.createFrom; -const $$createType1 = $Create.Nullable($$createType0); diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_imported_package/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_imported_package/index.ts deleted file mode 100644 index f95c1b558..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_imported_package/index.ts +++ /dev/null @@ -1,11 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; - -export { - Person -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_imported_package/models.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_imported_package/models.ts deleted file mode 100644 index f1ff262a1..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_imported_package/models.ts +++ /dev/null @@ -1,46 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Create as $Create } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as services$0 from "./services/models.js"; - -/** - * Person is a person - */ -export class Person { - "Name": string; - "Address": services$0.Address | null; - - /** Creates a new Person instance. */ - constructor($$source: Partial = {}) { - if (!("Name" in $$source)) { - this["Name"] = ""; - } - if (!("Address" in $$source)) { - this["Address"] = null; - } - - Object.assign(this, $$source); - } - - /** - * Creates a new Person instance from a string or object. - */ - static createFrom($$source: any = {}): Person { - const $$createField1_0 = $$createType1; - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - if ("Address" in $$parsedSource) { - $$parsedSource["Address"] = $$createField1_0($$parsedSource["Address"]); - } - return new Person($$parsedSource as Partial); - } -} - -// Private type creation functions -const $$createType0 = services$0.Address.createFrom; -const $$createType1 = $Create.Nullable($$createType0); diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_imported_package/services/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_imported_package/services/index.ts deleted file mode 100644 index e4d86b717..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_imported_package/services/index.ts +++ /dev/null @@ -1,11 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as OtherService from "./otherservice.js"; -export { - OtherService -}; - -export { - Address -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_imported_package/services/models.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_imported_package/services/models.ts deleted file mode 100644 index a4be6e904..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_imported_package/services/models.ts +++ /dev/null @@ -1,35 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Create as $Create } from "/wails/runtime.js"; - -export class Address { - "Street": string; - "State": string; - "Country": string; - - /** Creates a new Address instance. */ - constructor($$source: Partial
                    = {}) { - if (!("Street" in $$source)) { - this["Street"] = ""; - } - if (!("State" in $$source)) { - this["State"] = ""; - } - if (!("Country" in $$source)) { - this["Country"] = ""; - } - - Object.assign(this, $$source); - } - - /** - * Creates a new Address instance from a string or object. - */ - static createFrom($$source: any = {}): Address { - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - return new Address($$parsedSource as Partial
                    ); - } -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_imported_package/services/otherservice.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_imported_package/services/otherservice.ts deleted file mode 100644 index f44f172e7..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_imported_package/services/otherservice.ts +++ /dev/null @@ -1,29 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * OtherService is a struct - * that does things - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * Yay does this and that - */ -export function Yay(): $CancellablePromise<$models.Address | null> { - return $Call.ByName("github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_imported_package/services.OtherService.Yay").then(($result: any) => { - return $$createType1($result); - }); -} - -// Private type creation functions -const $$createType0 = $models.Address.createFrom; -const $$createType1 = $Create.Nullable($$createType0); diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_nested_imported_package/greetservice.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_nested_imported_package/greetservice.ts deleted file mode 100644 index 1a2ffb266..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_nested_imported_package/greetservice.ts +++ /dev/null @@ -1,35 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * Greet does XYZ - */ -export function Greet(name: string): $CancellablePromise { - return $Call.ByName("main.GreetService.Greet", name); -} - -/** - * NewPerson creates a new person - */ -export function NewPerson(name: string): $CancellablePromise<$models.Person | null> { - return $Call.ByName("main.GreetService.NewPerson", name).then(($result: any) => { - return $$createType1($result); - }); -} - -// Private type creation functions -const $$createType0 = $models.Person.createFrom; -const $$createType1 = $Create.Nullable($$createType0); diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_nested_imported_package/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_nested_imported_package/index.ts deleted file mode 100644 index f95c1b558..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_nested_imported_package/index.ts +++ /dev/null @@ -1,11 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; - -export { - Person -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_nested_imported_package/models.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_nested_imported_package/models.ts deleted file mode 100644 index 88b2c78db..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_nested_imported_package/models.ts +++ /dev/null @@ -1,43 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Create as $Create } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as other$0 from "./services/other/models.js"; - -export class Person { - "Name": string; - "Address": other$0.Address | null; - - /** Creates a new Person instance. */ - constructor($$source: Partial = {}) { - if (!("Name" in $$source)) { - this["Name"] = ""; - } - if (!("Address" in $$source)) { - this["Address"] = null; - } - - Object.assign(this, $$source); - } - - /** - * Creates a new Person instance from a string or object. - */ - static createFrom($$source: any = {}): Person { - const $$createField1_0 = $$createType1; - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - if ("Address" in $$parsedSource) { - $$parsedSource["Address"] = $$createField1_0($$parsedSource["Address"]); - } - return new Person($$parsedSource as Partial); - } -} - -// Private type creation functions -const $$createType0 = other$0.Address.createFrom; -const $$createType1 = $Create.Nullable($$createType0); diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_nested_imported_package/services/other/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_nested_imported_package/services/other/index.ts deleted file mode 100644 index e4d86b717..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_nested_imported_package/services/other/index.ts +++ /dev/null @@ -1,11 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as OtherService from "./otherservice.js"; -export { - OtherService -}; - -export { - Address -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_nested_imported_package/services/other/models.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_nested_imported_package/services/other/models.ts deleted file mode 100644 index a4be6e904..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_nested_imported_package/services/other/models.ts +++ /dev/null @@ -1,35 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Create as $Create } from "/wails/runtime.js"; - -export class Address { - "Street": string; - "State": string; - "Country": string; - - /** Creates a new Address instance. */ - constructor($$source: Partial
                    = {}) { - if (!("Street" in $$source)) { - this["Street"] = ""; - } - if (!("State" in $$source)) { - this["State"] = ""; - } - if (!("Country" in $$source)) { - this["Country"] = ""; - } - - Object.assign(this, $$source); - } - - /** - * Creates a new Address instance from a string or object. - */ - static createFrom($$source: any = {}): Address { - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - return new Address($$parsedSource as Partial
                    ); - } -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_nested_imported_package/services/other/otherservice.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_nested_imported_package/services/other/otherservice.ts deleted file mode 100644 index fa9a93fc8..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_nested_imported_package/services/other/otherservice.ts +++ /dev/null @@ -1,29 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * OtherService is a struct - * that does things - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * Yay does this and that - */ -export function Yay(): $CancellablePromise<$models.Address | null> { - return $Call.ByName("github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_nested_imported_package/services/other.OtherService.Yay").then(($result: any) => { - return $$createType1($result); - }); -} - -// Private type creation functions -const $$createType0 = $models.Address.createFrom; -const $$createType1 = $Create.Nullable($$createType0); diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_multiple_files/greetservice.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_multiple_files/greetservice.ts deleted file mode 100644 index 460b2b374..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_multiple_files/greetservice.ts +++ /dev/null @@ -1,10 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -export function Greet(name: string): $CancellablePromise { - return $Call.ByName("main.GreetService.Greet", name); -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_multiple_files/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_multiple_files/index.ts deleted file mode 100644 index 50e3f0435..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_multiple_files/index.ts +++ /dev/null @@ -1,7 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single/greetservice.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single/greetservice.ts deleted file mode 100644 index 6a6a881dc..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single/greetservice.ts +++ /dev/null @@ -1,18 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -/** - * Greet someone - */ -export function Greet(name: string): $CancellablePromise { - return $Call.ByName("main.GreetService.Greet", name); -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single/index.ts deleted file mode 100644 index 50e3f0435..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single/index.ts +++ /dev/null @@ -1,7 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single_context/greetservice.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single_context/greetservice.ts deleted file mode 100644 index aec011527..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single_context/greetservice.ts +++ /dev/null @@ -1,25 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -/** - * Greet someone - */ -export function Greet(name: string): $CancellablePromise { - return $Call.ByName("main.GreetService.Greet", name); -} - -/** - * Greet someone - */ -export function GreetWithContext(name: string): $CancellablePromise { - return $Call.ByName("main.GreetService.GreetWithContext", name); -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single_context/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single_context/index.ts deleted file mode 100644 index 50e3f0435..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single_context/index.ts +++ /dev/null @@ -1,7 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single_internal/greetservice.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single_internal/greetservice.ts deleted file mode 100644 index 6a6a881dc..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single_internal/greetservice.ts +++ /dev/null @@ -1,18 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -/** - * Greet someone - */ -export function Greet(name: string): $CancellablePromise { - return $Call.ByName("main.GreetService.Greet", name); -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single_internal/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single_internal/index.ts deleted file mode 100644 index 50e3f0435..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single_internal/index.ts +++ /dev/null @@ -1,7 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys/index.ts deleted file mode 100644 index 8d52924fe..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys/index.ts +++ /dev/null @@ -1,35 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as Service from "./service.js"; -export { - Service -}; - -export { - Maps -} from "./models.js"; - -export type { - BasicCstrAlias, - ComparableCstrAlias, - EmbeddedCustomInterface, - EmbeddedOriginalInterface, - EmbeddedPointer, - EmbeddedPointerPtr, - EmbeddedValue, - EmbeddedValuePtr, - GoodTildeCstrAlias, - IntAlias, - IntType, - InterfaceCstrAlias, - MixedCstrAlias, - NonBasicCstrAlias, - PointableCstrAlias, - PointerAlias, - PointerTextMarshaler, - StringAlias, - StringType, - ValueAlias, - ValueTextMarshaler -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys/models.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys/models.ts deleted file mode 100644 index b0f112227..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys/models.ts +++ /dev/null @@ -1,1890 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Create as $Create } from "/wails/runtime.js"; - -export type BasicCstrAlias = S; - -export type ComparableCstrAlias = R; - -export type EmbeddedCustomInterface = string; - -export type EmbeddedOriginalInterface = string; - -export type EmbeddedPointer = string; - -export type EmbeddedPointerPtr = string; - -export type EmbeddedValue = string; - -export type EmbeddedValuePtr = string; - -export type GoodTildeCstrAlias = U; - -export type IntAlias = number; - -export type IntType = number; - -export type InterfaceCstrAlias = Y; - -export class Maps { - /** - * Reject - */ - "Bool": { [_ in string]?: number }; - - /** - * Accept - */ - "Int": { [_ in `${number}`]?: number }; - - /** - * Accept - */ - "Uint": { [_ in `${number}`]?: number }; - - /** - * Reject - */ - "Float": { [_ in string]?: number }; - - /** - * Reject - */ - "Complex": { [_ in string]?: number }; - - /** - * Accept - */ - "Byte": { [_ in `${number}`]?: number }; - - /** - * Accept - */ - "Rune": { [_ in `${number}`]?: number }; - - /** - * Accept - */ - "String": { [_ in string]?: number }; - - /** - * Reject - */ - "IntPtr": { [_ in string]?: number }; - - /** - * Reject - */ - "UintPtr": { [_ in string]?: number }; - - /** - * Reject - */ - "FloatPtr": { [_ in string]?: number }; - - /** - * Reject - */ - "ComplexPtr": { [_ in string]?: number }; - - /** - * Reject - */ - "StringPtr": { [_ in string]?: number }; - - /** - * Reject - */ - "NTM": { [_ in string]?: number }; - - /** - * Reject - */ - "NTMPtr": { [_ in string]?: number }; - - /** - * Accept - */ - "VTM": { [_ in ValueTextMarshaler]?: number }; - - /** - * Accept - */ - "VTMPtr": { [_ in ValueTextMarshaler]?: number }; - - /** - * Reject - */ - "PTM": { [_ in string]?: number }; - - /** - * Accept - */ - "PTMPtr": { [_ in PointerTextMarshaler]?: number }; - - /** - * Accept, hide - */ - "JTM": { [_ in string]?: number }; - - /** - * Accept, hide - */ - "JTMPtr": { [_ in string]?: number }; - - /** - * Reject - */ - "A": { [_ in string]?: number }; - - /** - * Reject - */ - "APtr": { [_ in string]?: number }; - - /** - * Accept, hide - */ - "TM": { [_ in string]?: number }; - - /** - * Reject - */ - "TMPtr": { [_ in string]?: number }; - - /** - * Accept, hide - */ - "CI": { [_ in string]?: number }; - - /** - * Reject - */ - "CIPtr": { [_ in string]?: number }; - - /** - * Accept, hide - */ - "EI": { [_ in string]?: number }; - - /** - * Reject - */ - "EIPtr": { [_ in string]?: number }; - - /** - * Accept - */ - "EV": { [_ in EmbeddedValue]?: number }; - - /** - * Accept - */ - "EVPtr": { [_ in EmbeddedValue]?: number }; - - /** - * Accept - */ - "EVP": { [_ in EmbeddedValuePtr]?: number }; - - /** - * Accept - */ - "EVPPtr": { [_ in EmbeddedValuePtr]?: number }; - - /** - * Reject - */ - "EP": { [_ in string]?: number }; - - /** - * Accept - */ - "EPPtr": { [_ in EmbeddedPointer]?: number }; - - /** - * Accept - */ - "EPP": { [_ in EmbeddedPointerPtr]?: number }; - - /** - * Accept - */ - "EPPPtr": { [_ in EmbeddedPointerPtr]?: number }; - - /** - * Accept - */ - "ECI": { [_ in EmbeddedCustomInterface]?: number }; - - /** - * Accept - */ - "ECIPtr": { [_ in EmbeddedCustomInterface]?: number }; - - /** - * Accept - */ - "EOI": { [_ in EmbeddedOriginalInterface]?: number }; - - /** - * Accept - */ - "EOIPtr": { [_ in EmbeddedOriginalInterface]?: number }; - - /** - * Reject - */ - "WT": { [_ in string]?: number }; - - /** - * Reject - */ - "WA": { [_ in string]?: number }; - - /** - * Accept - */ - "ST": { [_ in StringType]?: number }; - - /** - * Accept - */ - "SA": { [_ in StringAlias]?: number }; - - /** - * Accept - */ - "IntT": { [_ in IntType]?: number }; - - /** - * Accept - */ - "IntA": { [_ in IntAlias]?: number }; - - /** - * Reject - */ - "VT": { [_ in string]?: number }; - - /** - * Reject - */ - "VTPtr": { [_ in string]?: number }; - - /** - * Reject - */ - "VPT": { [_ in string]?: number }; - - /** - * Reject - */ - "VPTPtr": { [_ in string]?: number }; - - /** - * Accept - */ - "VA": { [_ in ValueAlias]?: number }; - - /** - * Accept - */ - "VAPtr": { [_ in ValueAlias]?: number }; - - /** - * Accept, hide - */ - "VPA": { [_ in string]?: number }; - - /** - * Reject - */ - "VPAPtr": { [_ in string]?: number }; - - /** - * Reject - */ - "PT": { [_ in string]?: number }; - - /** - * Reject - */ - "PTPtr": { [_ in string]?: number }; - - /** - * Reject - */ - "PPT": { [_ in string]?: number }; - - /** - * Reject - */ - "PPTPtr": { [_ in string]?: number }; - - /** - * Reject - */ - "PA": { [_ in string]?: number }; - - /** - * Accept - */ - "PAPtr": { [_ in PointerAlias]?: number }; - - /** - * Accept, hide - */ - "PPA": { [_ in string]?: number }; - - /** - * Reject - */ - "PPAPtr": { [_ in string]?: number }; - - /** - * Accept, hide - */ - "IT": { [_ in string]?: number }; - - /** - * Reject - */ - "ITPtr": { [_ in string]?: number }; - - /** - * Reject - */ - "IPT": { [_ in string]?: number }; - - /** - * Reject - */ - "IPTPtr": { [_ in string]?: number }; - - /** - * Accept, hide - */ - "IA": { [_ in string]?: number }; - - /** - * Reject - */ - "IAPtr": { [_ in string]?: number }; - - /** - * Reject - */ - "IPA": { [_ in string]?: number }; - - /** - * Reject - */ - "IPAPtr": { [_ in string]?: number }; - - /** - * Soft reject - */ - "TPR": { [_ in string]?: number }; - - /** - * Soft reject - */ - "TPRPtr": { [_ in string]?: number }; - - /** - * Accept, hide - */ - "TPS": { [_ in string]?: number }; - - /** - * Soft reject - */ - "TPSPtr": { [_ in string]?: number }; - - /** - * Soft reject - */ - "TPT": { [_ in string]?: number }; - - /** - * Soft reject - */ - "TPTPtr": { [_ in string]?: number }; - - /** - * Accept, hide - */ - "TPU": { [_ in string]?: number }; - - /** - * Soft reject - */ - "TPUPtr": { [_ in string]?: number }; - - /** - * Accept, hide - */ - "TPV": { [_ in string]?: number }; - - /** - * Soft reject - */ - "TPVPtr": { [_ in string]?: number }; - - /** - * Soft reject - */ - "TPW": { [_ in string]?: number }; - - /** - * Accept, hide - */ - "TPWPtr": { [_ in string]?: number }; - - /** - * Accept, hide - */ - "TPX": { [_ in string]?: number }; - - /** - * Soft reject - */ - "TPXPtr": { [_ in string]?: number }; - - /** - * Accept, hide - */ - "TPY": { [_ in string]?: number }; - - /** - * Soft reject - */ - "TPYPtr": { [_ in string]?: number }; - - /** - * Accept, hide - */ - "TPZ": { [_ in string]?: number }; - - /** - * Soft reject - */ - "TPZPtr": { [_ in string]?: number }; - - /** - * Soft reject - */ - "GAR": { [_ in string]?: number }; - - /** - * Soft reject - */ - "GARPtr": { [_ in string]?: number }; - - /** - * Accept, hide - */ - "GAS": { [_ in string]?: number }; - - /** - * Soft reject - */ - "GASPtr": { [_ in string]?: number }; - - /** - * Soft reject - */ - "GAT": { [_ in string]?: number }; - - /** - * Soft reject - */ - "GATPtr": { [_ in string]?: number }; - - /** - * Accept, hide - */ - "GAU": { [_ in string]?: number }; - - /** - * Soft reject - */ - "GAUPtr": { [_ in string]?: number }; - - /** - * Accept, hide - */ - "GAV": { [_ in string]?: number }; - - /** - * Soft reject - */ - "GAVPtr": { [_ in string]?: number }; - - /** - * Soft reject - */ - "GAW": { [_ in string]?: number }; - - /** - * Accept, hide - */ - "GAWPtr": { [_ in string]?: number }; - - /** - * Accept, hide - */ - "GAX": { [_ in string]?: number }; - - /** - * Soft reject - */ - "GAXPtr": { [_ in string]?: number }; - - /** - * Accept, hide - */ - "GAY": { [_ in string]?: number }; - - /** - * Soft reject - */ - "GAYPtr": { [_ in string]?: number }; - - /** - * Accept, hide - */ - "GAZ": { [_ in string]?: number }; - - /** - * Soft reject - */ - "GAZPtr": { [_ in string]?: number }; - - /** - * Accept - */ - "GACi": { [_ in ComparableCstrAlias]?: number }; - - /** - * Accept - */ - "GACV": { [_ in ComparableCstrAlias]?: number }; - - /** - * Reject - */ - "GACP": { [_ in string]?: number }; - - /** - * Reject - */ - "GACiPtr": { [_ in string]?: number }; - - /** - * Accept, hide - */ - "GACVPtr": { [_ in string]?: number }; - - /** - * Accept, hide - */ - "GACPPtr": { [_ in string]?: number }; - - /** - * Accept - */ - "GABi": { [_ in BasicCstrAlias]?: number }; - - /** - * Accept - */ - "GABs": { [_ in BasicCstrAlias]?: number }; - - /** - * Reject - */ - "GABiPtr": { [_ in string]?: number }; - - /** - * Reject - */ - "GABT": { [_ in string]?: number }; - - /** - * Reject - */ - "GABTPtr": { [_ in string]?: number }; - - /** - * Accept - */ - "GAGT": { [_ in GoodTildeCstrAlias]?: number }; - - /** - * Accept, hide - */ - "GAGTPtr": { [_ in string]?: number }; - - /** - * Accept - */ - "GANBV": { [_ in NonBasicCstrAlias]?: number }; - - /** - * Accept, hide - */ - "GANBP": { [_ in string]?: number }; - - /** - * Accept, hide - */ - "GANBVPtr": { [_ in string]?: number }; - - /** - * Reject - */ - "GANBPPtr": { [_ in string]?: number }; - - /** - * Accept - */ - "GAPlV1": { [_ in PointableCstrAlias]?: number }; - - /** - * Accept - */ - "GAPlV2": { [_ in PointableCstrAlias]?: number }; - - /** - * Reject - */ - "GAPlP1": { [_ in string]?: number }; - - /** - * Accept - */ - "GAPlP2": { [_ in PointableCstrAlias]?: number }; - - /** - * Accept, hide - */ - "GAPlVPtr": { [_ in string]?: number }; - - /** - * Accept, hide - */ - "GAPlPPtr": { [_ in string]?: number }; - - /** - * Accept - */ - "GAMi": { [_ in MixedCstrAlias]?: number }; - - /** - * Accept - */ - "GAMS": { [_ in MixedCstrAlias]?: number }; - - /** - * Accept - */ - "GAMV": { [_ in MixedCstrAlias]?: number }; - - /** - * Reject - */ - "GAMSPtr": { [_ in string]?: number }; - - /** - * Accept, hide - */ - "GAMVPtr": { [_ in string]?: number }; - - /** - * Accept, hide - */ - "GAII": { [_ in string]?: number }; - - /** - * Accept - */ - "GAIV": { [_ in InterfaceCstrAlias]?: number }; - - /** - * Accept, hide - */ - "GAIP": { [_ in string]?: number }; - - /** - * Reject - */ - "GAIIPtr": { [_ in string]?: number }; - - /** - * Accept, hide - */ - "GAIVPtr": { [_ in string]?: number }; - - /** - * Reject - */ - "GAIPPtr": { [_ in string]?: number }; - - /** - * Accept, hide - */ - "GAPrV": { [_ in string]?: number }; - - /** - * Accept, hide - */ - "GAPrP": { [_ in string]?: number }; - - /** - * Reject - */ - "GAPrVPtr": { [_ in string]?: number }; - - /** - * Reject - */ - "GAPrPPtr": { [_ in string]?: number }; - - /** Creates a new Maps instance. */ - constructor($$source: Partial> = {}) { - if (!("Bool" in $$source)) { - this["Bool"] = {}; - } - if (!("Int" in $$source)) { - this["Int"] = {}; - } - if (!("Uint" in $$source)) { - this["Uint"] = {}; - } - if (!("Float" in $$source)) { - this["Float"] = {}; - } - if (!("Complex" in $$source)) { - this["Complex"] = {}; - } - if (!("Byte" in $$source)) { - this["Byte"] = {}; - } - if (!("Rune" in $$source)) { - this["Rune"] = {}; - } - if (!("String" in $$source)) { - this["String"] = {}; - } - if (!("IntPtr" in $$source)) { - this["IntPtr"] = {}; - } - if (!("UintPtr" in $$source)) { - this["UintPtr"] = {}; - } - if (!("FloatPtr" in $$source)) { - this["FloatPtr"] = {}; - } - if (!("ComplexPtr" in $$source)) { - this["ComplexPtr"] = {}; - } - if (!("StringPtr" in $$source)) { - this["StringPtr"] = {}; - } - if (!("NTM" in $$source)) { - this["NTM"] = {}; - } - if (!("NTMPtr" in $$source)) { - this["NTMPtr"] = {}; - } - if (!("VTM" in $$source)) { - this["VTM"] = {}; - } - if (!("VTMPtr" in $$source)) { - this["VTMPtr"] = {}; - } - if (!("PTM" in $$source)) { - this["PTM"] = {}; - } - if (!("PTMPtr" in $$source)) { - this["PTMPtr"] = {}; - } - if (!("JTM" in $$source)) { - this["JTM"] = {}; - } - if (!("JTMPtr" in $$source)) { - this["JTMPtr"] = {}; - } - if (!("A" in $$source)) { - this["A"] = {}; - } - if (!("APtr" in $$source)) { - this["APtr"] = {}; - } - if (!("TM" in $$source)) { - this["TM"] = {}; - } - if (!("TMPtr" in $$source)) { - this["TMPtr"] = {}; - } - if (!("CI" in $$source)) { - this["CI"] = {}; - } - if (!("CIPtr" in $$source)) { - this["CIPtr"] = {}; - } - if (!("EI" in $$source)) { - this["EI"] = {}; - } - if (!("EIPtr" in $$source)) { - this["EIPtr"] = {}; - } - if (!("EV" in $$source)) { - this["EV"] = {}; - } - if (!("EVPtr" in $$source)) { - this["EVPtr"] = {}; - } - if (!("EVP" in $$source)) { - this["EVP"] = {}; - } - if (!("EVPPtr" in $$source)) { - this["EVPPtr"] = {}; - } - if (!("EP" in $$source)) { - this["EP"] = {}; - } - if (!("EPPtr" in $$source)) { - this["EPPtr"] = {}; - } - if (!("EPP" in $$source)) { - this["EPP"] = {}; - } - if (!("EPPPtr" in $$source)) { - this["EPPPtr"] = {}; - } - if (!("ECI" in $$source)) { - this["ECI"] = {}; - } - if (!("ECIPtr" in $$source)) { - this["ECIPtr"] = {}; - } - if (!("EOI" in $$source)) { - this["EOI"] = {}; - } - if (!("EOIPtr" in $$source)) { - this["EOIPtr"] = {}; - } - if (!("WT" in $$source)) { - this["WT"] = {}; - } - if (!("WA" in $$source)) { - this["WA"] = {}; - } - if (!("ST" in $$source)) { - this["ST"] = {}; - } - if (!("SA" in $$source)) { - this["SA"] = {}; - } - if (!("IntT" in $$source)) { - this["IntT"] = {}; - } - if (!("IntA" in $$source)) { - this["IntA"] = {}; - } - if (!("VT" in $$source)) { - this["VT"] = {}; - } - if (!("VTPtr" in $$source)) { - this["VTPtr"] = {}; - } - if (!("VPT" in $$source)) { - this["VPT"] = {}; - } - if (!("VPTPtr" in $$source)) { - this["VPTPtr"] = {}; - } - if (!("VA" in $$source)) { - this["VA"] = {}; - } - if (!("VAPtr" in $$source)) { - this["VAPtr"] = {}; - } - if (!("VPA" in $$source)) { - this["VPA"] = {}; - } - if (!("VPAPtr" in $$source)) { - this["VPAPtr"] = {}; - } - if (!("PT" in $$source)) { - this["PT"] = {}; - } - if (!("PTPtr" in $$source)) { - this["PTPtr"] = {}; - } - if (!("PPT" in $$source)) { - this["PPT"] = {}; - } - if (!("PPTPtr" in $$source)) { - this["PPTPtr"] = {}; - } - if (!("PA" in $$source)) { - this["PA"] = {}; - } - if (!("PAPtr" in $$source)) { - this["PAPtr"] = {}; - } - if (!("PPA" in $$source)) { - this["PPA"] = {}; - } - if (!("PPAPtr" in $$source)) { - this["PPAPtr"] = {}; - } - if (!("IT" in $$source)) { - this["IT"] = {}; - } - if (!("ITPtr" in $$source)) { - this["ITPtr"] = {}; - } - if (!("IPT" in $$source)) { - this["IPT"] = {}; - } - if (!("IPTPtr" in $$source)) { - this["IPTPtr"] = {}; - } - if (!("IA" in $$source)) { - this["IA"] = {}; - } - if (!("IAPtr" in $$source)) { - this["IAPtr"] = {}; - } - if (!("IPA" in $$source)) { - this["IPA"] = {}; - } - if (!("IPAPtr" in $$source)) { - this["IPAPtr"] = {}; - } - if (!("TPR" in $$source)) { - this["TPR"] = {}; - } - if (!("TPRPtr" in $$source)) { - this["TPRPtr"] = {}; - } - if (!("TPS" in $$source)) { - this["TPS"] = {}; - } - if (!("TPSPtr" in $$source)) { - this["TPSPtr"] = {}; - } - if (!("TPT" in $$source)) { - this["TPT"] = {}; - } - if (!("TPTPtr" in $$source)) { - this["TPTPtr"] = {}; - } - if (!("TPU" in $$source)) { - this["TPU"] = {}; - } - if (!("TPUPtr" in $$source)) { - this["TPUPtr"] = {}; - } - if (!("TPV" in $$source)) { - this["TPV"] = {}; - } - if (!("TPVPtr" in $$source)) { - this["TPVPtr"] = {}; - } - if (!("TPW" in $$source)) { - this["TPW"] = {}; - } - if (!("TPWPtr" in $$source)) { - this["TPWPtr"] = {}; - } - if (!("TPX" in $$source)) { - this["TPX"] = {}; - } - if (!("TPXPtr" in $$source)) { - this["TPXPtr"] = {}; - } - if (!("TPY" in $$source)) { - this["TPY"] = {}; - } - if (!("TPYPtr" in $$source)) { - this["TPYPtr"] = {}; - } - if (!("TPZ" in $$source)) { - this["TPZ"] = {}; - } - if (!("TPZPtr" in $$source)) { - this["TPZPtr"] = {}; - } - if (!("GAR" in $$source)) { - this["GAR"] = {}; - } - if (!("GARPtr" in $$source)) { - this["GARPtr"] = {}; - } - if (!("GAS" in $$source)) { - this["GAS"] = {}; - } - if (!("GASPtr" in $$source)) { - this["GASPtr"] = {}; - } - if (!("GAT" in $$source)) { - this["GAT"] = {}; - } - if (!("GATPtr" in $$source)) { - this["GATPtr"] = {}; - } - if (!("GAU" in $$source)) { - this["GAU"] = {}; - } - if (!("GAUPtr" in $$source)) { - this["GAUPtr"] = {}; - } - if (!("GAV" in $$source)) { - this["GAV"] = {}; - } - if (!("GAVPtr" in $$source)) { - this["GAVPtr"] = {}; - } - if (!("GAW" in $$source)) { - this["GAW"] = {}; - } - if (!("GAWPtr" in $$source)) { - this["GAWPtr"] = {}; - } - if (!("GAX" in $$source)) { - this["GAX"] = {}; - } - if (!("GAXPtr" in $$source)) { - this["GAXPtr"] = {}; - } - if (!("GAY" in $$source)) { - this["GAY"] = {}; - } - if (!("GAYPtr" in $$source)) { - this["GAYPtr"] = {}; - } - if (!("GAZ" in $$source)) { - this["GAZ"] = {}; - } - if (!("GAZPtr" in $$source)) { - this["GAZPtr"] = {}; - } - if (!("GACi" in $$source)) { - this["GACi"] = {}; - } - if (!("GACV" in $$source)) { - this["GACV"] = {}; - } - if (!("GACP" in $$source)) { - this["GACP"] = {}; - } - if (!("GACiPtr" in $$source)) { - this["GACiPtr"] = {}; - } - if (!("GACVPtr" in $$source)) { - this["GACVPtr"] = {}; - } - if (!("GACPPtr" in $$source)) { - this["GACPPtr"] = {}; - } - if (!("GABi" in $$source)) { - this["GABi"] = {}; - } - if (!("GABs" in $$source)) { - this["GABs"] = {}; - } - if (!("GABiPtr" in $$source)) { - this["GABiPtr"] = {}; - } - if (!("GABT" in $$source)) { - this["GABT"] = {}; - } - if (!("GABTPtr" in $$source)) { - this["GABTPtr"] = {}; - } - if (!("GAGT" in $$source)) { - this["GAGT"] = {}; - } - if (!("GAGTPtr" in $$source)) { - this["GAGTPtr"] = {}; - } - if (!("GANBV" in $$source)) { - this["GANBV"] = {}; - } - if (!("GANBP" in $$source)) { - this["GANBP"] = {}; - } - if (!("GANBVPtr" in $$source)) { - this["GANBVPtr"] = {}; - } - if (!("GANBPPtr" in $$source)) { - this["GANBPPtr"] = {}; - } - if (!("GAPlV1" in $$source)) { - this["GAPlV1"] = {}; - } - if (!("GAPlV2" in $$source)) { - this["GAPlV2"] = {}; - } - if (!("GAPlP1" in $$source)) { - this["GAPlP1"] = {}; - } - if (!("GAPlP2" in $$source)) { - this["GAPlP2"] = {}; - } - if (!("GAPlVPtr" in $$source)) { - this["GAPlVPtr"] = {}; - } - if (!("GAPlPPtr" in $$source)) { - this["GAPlPPtr"] = {}; - } - if (!("GAMi" in $$source)) { - this["GAMi"] = {}; - } - if (!("GAMS" in $$source)) { - this["GAMS"] = {}; - } - if (!("GAMV" in $$source)) { - this["GAMV"] = {}; - } - if (!("GAMSPtr" in $$source)) { - this["GAMSPtr"] = {}; - } - if (!("GAMVPtr" in $$source)) { - this["GAMVPtr"] = {}; - } - if (!("GAII" in $$source)) { - this["GAII"] = {}; - } - if (!("GAIV" in $$source)) { - this["GAIV"] = {}; - } - if (!("GAIP" in $$source)) { - this["GAIP"] = {}; - } - if (!("GAIIPtr" in $$source)) { - this["GAIIPtr"] = {}; - } - if (!("GAIVPtr" in $$source)) { - this["GAIVPtr"] = {}; - } - if (!("GAIPPtr" in $$source)) { - this["GAIPPtr"] = {}; - } - if (!("GAPrV" in $$source)) { - this["GAPrV"] = {}; - } - if (!("GAPrP" in $$source)) { - this["GAPrP"] = {}; - } - if (!("GAPrVPtr" in $$source)) { - this["GAPrVPtr"] = {}; - } - if (!("GAPrPPtr" in $$source)) { - this["GAPrPPtr"] = {}; - } - - Object.assign(this, $$source); - } - - /** - * Given creation functions for each type parameter, - * returns a creation function for a concrete instance - * of the generic class Maps. - */ - static createFrom($$createParamR: (source: any) => R, $$createParamS: (source: any) => S, $$createParamT: (source: any) => T, $$createParamU: (source: any) => U, $$createParamV: (source: any) => V, $$createParamW: (source: any) => W, $$createParamX: (source: any) => X, $$createParamY: (source: any) => Y, $$createParamZ: (source: any) => Z): ($$source?: any) => Maps { - const $$createField0_0 = $$createType0; - const $$createField1_0 = $$createType1; - const $$createField2_0 = $$createType2; - const $$createField3_0 = $$createType3; - const $$createField4_0 = $$createType4; - const $$createField5_0 = $$createType5; - const $$createField6_0 = $$createType6; - const $$createField7_0 = $$createType7; - const $$createField8_0 = $$createType8; - const $$createField9_0 = $$createType9; - const $$createField10_0 = $$createType10; - const $$createField11_0 = $$createType11; - const $$createField12_0 = $$createType12; - const $$createField13_0 = $$createType13; - const $$createField14_0 = $$createType14; - const $$createField15_0 = $$createType15; - const $$createField16_0 = $$createType16; - const $$createField17_0 = $$createType17; - const $$createField18_0 = $$createType18; - const $$createField19_0 = $$createType19; - const $$createField20_0 = $$createType20; - const $$createField21_0 = $$createType21; - const $$createField22_0 = $$createType22; - const $$createField23_0 = $$createType23; - const $$createField24_0 = $$createType24; - const $$createField25_0 = $$createType25; - const $$createField26_0 = $$createType26; - const $$createField27_0 = $$createType27; - const $$createField28_0 = $$createType28; - const $$createField29_0 = $$createType29; - const $$createField30_0 = $$createType30; - const $$createField31_0 = $$createType31; - const $$createField32_0 = $$createType32; - const $$createField33_0 = $$createType33; - const $$createField34_0 = $$createType34; - const $$createField35_0 = $$createType35; - const $$createField36_0 = $$createType36; - const $$createField37_0 = $$createType37; - const $$createField38_0 = $$createType38; - const $$createField39_0 = $$createType39; - const $$createField40_0 = $$createType40; - const $$createField41_0 = $$createType41; - const $$createField42_0 = $$createType0; - const $$createField43_0 = $$createType42; - const $$createField44_0 = $$createType7; - const $$createField45_0 = $$createType43; - const $$createField46_0 = $$createType1; - const $$createField47_0 = $$createType44; - const $$createField48_0 = $$createType45; - const $$createField49_0 = $$createType46; - const $$createField50_0 = $$createType47; - const $$createField51_0 = $$createType15; - const $$createField52_0 = $$createType16; - const $$createField53_0 = $$createType16; - const $$createField54_0 = $$createType48; - const $$createField55_0 = $$createType49; - const $$createField56_0 = $$createType50; - const $$createField57_0 = $$createType51; - const $$createField58_0 = $$createType52; - const $$createField59_0 = $$createType17; - const $$createField60_0 = $$createType18; - const $$createField61_0 = $$createType18; - const $$createField62_0 = $$createType53; - const $$createField63_0 = $$createType54; - const $$createField64_0 = $$createType55; - const $$createField65_0 = $$createType56; - const $$createField66_0 = $$createType57; - const $$createField67_0 = $$createType23; - const $$createField68_0 = $$createType24; - const $$createField69_0 = $$createType24; - const $$createField70_0 = $$createType58; - const $$createField71_0 = $$createType59($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ); - const $$createField72_0 = $$createType60($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ); - const $$createField73_0 = $$createType61($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ); - const $$createField74_0 = $$createType62($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ); - const $$createField75_0 = $$createType63($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ); - const $$createField76_0 = $$createType64($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ); - const $$createField77_0 = $$createType65($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ); - const $$createField78_0 = $$createType66($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ); - const $$createField79_0 = $$createType67($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ); - const $$createField80_0 = $$createType68($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ); - const $$createField81_0 = $$createType69($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ); - const $$createField82_0 = $$createType70($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ); - const $$createField83_0 = $$createType71($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ); - const $$createField84_0 = $$createType72($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ); - const $$createField85_0 = $$createType73($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ); - const $$createField86_0 = $$createType74($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ); - const $$createField87_0 = $$createType75($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ); - const $$createField88_0 = $$createType76($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ); - const $$createField89_0 = $$createType59($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ); - const $$createField90_0 = $$createType60($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ); - const $$createField91_0 = $$createType61($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ); - const $$createField92_0 = $$createType62($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ); - const $$createField93_0 = $$createType63($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ); - const $$createField94_0 = $$createType64($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ); - const $$createField95_0 = $$createType65($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ); - const $$createField96_0 = $$createType66($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ); - const $$createField97_0 = $$createType67($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ); - const $$createField98_0 = $$createType68($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ); - const $$createField99_0 = $$createType69($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ); - const $$createField100_0 = $$createType70($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ); - const $$createField101_0 = $$createType71($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ); - const $$createField102_0 = $$createType72($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ); - const $$createField103_0 = $$createType73($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ); - const $$createField104_0 = $$createType74($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ); - const $$createField105_0 = $$createType75($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ); - const $$createField106_0 = $$createType76($$createParamR, $$createParamS, $$createParamT, $$createParamU, $$createParamV, $$createParamW, $$createParamX, $$createParamY, $$createParamZ); - const $$createField107_0 = $$createType1; - const $$createField108_0 = $$createType15; - const $$createField109_0 = $$createType17; - const $$createField110_0 = $$createType8; - const $$createField111_0 = $$createType16; - const $$createField112_0 = $$createType18; - const $$createField113_0 = $$createType1; - const $$createField114_0 = $$createType7; - const $$createField115_0 = $$createType8; - const $$createField116_0 = $$createType77; - const $$createField117_0 = $$createType78; - const $$createField118_0 = $$createType15; - const $$createField119_0 = $$createType16; - const $$createField120_0 = $$createType15; - const $$createField121_0 = $$createType18; - const $$createField122_0 = $$createType16; - const $$createField123_0 = $$createType53; - const $$createField124_0 = $$createType15; - const $$createField125_0 = $$createType16; - const $$createField126_0 = $$createType17; - const $$createField127_0 = $$createType18; - const $$createField128_0 = $$createType16; - const $$createField129_0 = $$createType18; - const $$createField130_0 = $$createType2; - const $$createField131_0 = $$createType42; - const $$createField132_0 = $$createType15; - const $$createField133_0 = $$createType79; - const $$createField134_0 = $$createType16; - const $$createField135_0 = $$createType23; - const $$createField136_0 = $$createType15; - const $$createField137_0 = $$createType18; - const $$createField138_0 = $$createType24; - const $$createField139_0 = $$createType16; - const $$createField140_0 = $$createType53; - const $$createField141_0 = $$createType16; - const $$createField142_0 = $$createType18; - const $$createField143_0 = $$createType48; - const $$createField144_0 = $$createType53; - return ($$source: any = {}) => { - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - if ("Bool" in $$parsedSource) { - $$parsedSource["Bool"] = $$createField0_0($$parsedSource["Bool"]); - } - if ("Int" in $$parsedSource) { - $$parsedSource["Int"] = $$createField1_0($$parsedSource["Int"]); - } - if ("Uint" in $$parsedSource) { - $$parsedSource["Uint"] = $$createField2_0($$parsedSource["Uint"]); - } - if ("Float" in $$parsedSource) { - $$parsedSource["Float"] = $$createField3_0($$parsedSource["Float"]); - } - if ("Complex" in $$parsedSource) { - $$parsedSource["Complex"] = $$createField4_0($$parsedSource["Complex"]); - } - if ("Byte" in $$parsedSource) { - $$parsedSource["Byte"] = $$createField5_0($$parsedSource["Byte"]); - } - if ("Rune" in $$parsedSource) { - $$parsedSource["Rune"] = $$createField6_0($$parsedSource["Rune"]); - } - if ("String" in $$parsedSource) { - $$parsedSource["String"] = $$createField7_0($$parsedSource["String"]); - } - if ("IntPtr" in $$parsedSource) { - $$parsedSource["IntPtr"] = $$createField8_0($$parsedSource["IntPtr"]); - } - if ("UintPtr" in $$parsedSource) { - $$parsedSource["UintPtr"] = $$createField9_0($$parsedSource["UintPtr"]); - } - if ("FloatPtr" in $$parsedSource) { - $$parsedSource["FloatPtr"] = $$createField10_0($$parsedSource["FloatPtr"]); - } - if ("ComplexPtr" in $$parsedSource) { - $$parsedSource["ComplexPtr"] = $$createField11_0($$parsedSource["ComplexPtr"]); - } - if ("StringPtr" in $$parsedSource) { - $$parsedSource["StringPtr"] = $$createField12_0($$parsedSource["StringPtr"]); - } - if ("NTM" in $$parsedSource) { - $$parsedSource["NTM"] = $$createField13_0($$parsedSource["NTM"]); - } - if ("NTMPtr" in $$parsedSource) { - $$parsedSource["NTMPtr"] = $$createField14_0($$parsedSource["NTMPtr"]); - } - if ("VTM" in $$parsedSource) { - $$parsedSource["VTM"] = $$createField15_0($$parsedSource["VTM"]); - } - if ("VTMPtr" in $$parsedSource) { - $$parsedSource["VTMPtr"] = $$createField16_0($$parsedSource["VTMPtr"]); - } - if ("PTM" in $$parsedSource) { - $$parsedSource["PTM"] = $$createField17_0($$parsedSource["PTM"]); - } - if ("PTMPtr" in $$parsedSource) { - $$parsedSource["PTMPtr"] = $$createField18_0($$parsedSource["PTMPtr"]); - } - if ("JTM" in $$parsedSource) { - $$parsedSource["JTM"] = $$createField19_0($$parsedSource["JTM"]); - } - if ("JTMPtr" in $$parsedSource) { - $$parsedSource["JTMPtr"] = $$createField20_0($$parsedSource["JTMPtr"]); - } - if ("A" in $$parsedSource) { - $$parsedSource["A"] = $$createField21_0($$parsedSource["A"]); - } - if ("APtr" in $$parsedSource) { - $$parsedSource["APtr"] = $$createField22_0($$parsedSource["APtr"]); - } - if ("TM" in $$parsedSource) { - $$parsedSource["TM"] = $$createField23_0($$parsedSource["TM"]); - } - if ("TMPtr" in $$parsedSource) { - $$parsedSource["TMPtr"] = $$createField24_0($$parsedSource["TMPtr"]); - } - if ("CI" in $$parsedSource) { - $$parsedSource["CI"] = $$createField25_0($$parsedSource["CI"]); - } - if ("CIPtr" in $$parsedSource) { - $$parsedSource["CIPtr"] = $$createField26_0($$parsedSource["CIPtr"]); - } - if ("EI" in $$parsedSource) { - $$parsedSource["EI"] = $$createField27_0($$parsedSource["EI"]); - } - if ("EIPtr" in $$parsedSource) { - $$parsedSource["EIPtr"] = $$createField28_0($$parsedSource["EIPtr"]); - } - if ("EV" in $$parsedSource) { - $$parsedSource["EV"] = $$createField29_0($$parsedSource["EV"]); - } - if ("EVPtr" in $$parsedSource) { - $$parsedSource["EVPtr"] = $$createField30_0($$parsedSource["EVPtr"]); - } - if ("EVP" in $$parsedSource) { - $$parsedSource["EVP"] = $$createField31_0($$parsedSource["EVP"]); - } - if ("EVPPtr" in $$parsedSource) { - $$parsedSource["EVPPtr"] = $$createField32_0($$parsedSource["EVPPtr"]); - } - if ("EP" in $$parsedSource) { - $$parsedSource["EP"] = $$createField33_0($$parsedSource["EP"]); - } - if ("EPPtr" in $$parsedSource) { - $$parsedSource["EPPtr"] = $$createField34_0($$parsedSource["EPPtr"]); - } - if ("EPP" in $$parsedSource) { - $$parsedSource["EPP"] = $$createField35_0($$parsedSource["EPP"]); - } - if ("EPPPtr" in $$parsedSource) { - $$parsedSource["EPPPtr"] = $$createField36_0($$parsedSource["EPPPtr"]); - } - if ("ECI" in $$parsedSource) { - $$parsedSource["ECI"] = $$createField37_0($$parsedSource["ECI"]); - } - if ("ECIPtr" in $$parsedSource) { - $$parsedSource["ECIPtr"] = $$createField38_0($$parsedSource["ECIPtr"]); - } - if ("EOI" in $$parsedSource) { - $$parsedSource["EOI"] = $$createField39_0($$parsedSource["EOI"]); - } - if ("EOIPtr" in $$parsedSource) { - $$parsedSource["EOIPtr"] = $$createField40_0($$parsedSource["EOIPtr"]); - } - if ("WT" in $$parsedSource) { - $$parsedSource["WT"] = $$createField41_0($$parsedSource["WT"]); - } - if ("WA" in $$parsedSource) { - $$parsedSource["WA"] = $$createField42_0($$parsedSource["WA"]); - } - if ("ST" in $$parsedSource) { - $$parsedSource["ST"] = $$createField43_0($$parsedSource["ST"]); - } - if ("SA" in $$parsedSource) { - $$parsedSource["SA"] = $$createField44_0($$parsedSource["SA"]); - } - if ("IntT" in $$parsedSource) { - $$parsedSource["IntT"] = $$createField45_0($$parsedSource["IntT"]); - } - if ("IntA" in $$parsedSource) { - $$parsedSource["IntA"] = $$createField46_0($$parsedSource["IntA"]); - } - if ("VT" in $$parsedSource) { - $$parsedSource["VT"] = $$createField47_0($$parsedSource["VT"]); - } - if ("VTPtr" in $$parsedSource) { - $$parsedSource["VTPtr"] = $$createField48_0($$parsedSource["VTPtr"]); - } - if ("VPT" in $$parsedSource) { - $$parsedSource["VPT"] = $$createField49_0($$parsedSource["VPT"]); - } - if ("VPTPtr" in $$parsedSource) { - $$parsedSource["VPTPtr"] = $$createField50_0($$parsedSource["VPTPtr"]); - } - if ("VA" in $$parsedSource) { - $$parsedSource["VA"] = $$createField51_0($$parsedSource["VA"]); - } - if ("VAPtr" in $$parsedSource) { - $$parsedSource["VAPtr"] = $$createField52_0($$parsedSource["VAPtr"]); - } - if ("VPA" in $$parsedSource) { - $$parsedSource["VPA"] = $$createField53_0($$parsedSource["VPA"]); - } - if ("VPAPtr" in $$parsedSource) { - $$parsedSource["VPAPtr"] = $$createField54_0($$parsedSource["VPAPtr"]); - } - if ("PT" in $$parsedSource) { - $$parsedSource["PT"] = $$createField55_0($$parsedSource["PT"]); - } - if ("PTPtr" in $$parsedSource) { - $$parsedSource["PTPtr"] = $$createField56_0($$parsedSource["PTPtr"]); - } - if ("PPT" in $$parsedSource) { - $$parsedSource["PPT"] = $$createField57_0($$parsedSource["PPT"]); - } - if ("PPTPtr" in $$parsedSource) { - $$parsedSource["PPTPtr"] = $$createField58_0($$parsedSource["PPTPtr"]); - } - if ("PA" in $$parsedSource) { - $$parsedSource["PA"] = $$createField59_0($$parsedSource["PA"]); - } - if ("PAPtr" in $$parsedSource) { - $$parsedSource["PAPtr"] = $$createField60_0($$parsedSource["PAPtr"]); - } - if ("PPA" in $$parsedSource) { - $$parsedSource["PPA"] = $$createField61_0($$parsedSource["PPA"]); - } - if ("PPAPtr" in $$parsedSource) { - $$parsedSource["PPAPtr"] = $$createField62_0($$parsedSource["PPAPtr"]); - } - if ("IT" in $$parsedSource) { - $$parsedSource["IT"] = $$createField63_0($$parsedSource["IT"]); - } - if ("ITPtr" in $$parsedSource) { - $$parsedSource["ITPtr"] = $$createField64_0($$parsedSource["ITPtr"]); - } - if ("IPT" in $$parsedSource) { - $$parsedSource["IPT"] = $$createField65_0($$parsedSource["IPT"]); - } - if ("IPTPtr" in $$parsedSource) { - $$parsedSource["IPTPtr"] = $$createField66_0($$parsedSource["IPTPtr"]); - } - if ("IA" in $$parsedSource) { - $$parsedSource["IA"] = $$createField67_0($$parsedSource["IA"]); - } - if ("IAPtr" in $$parsedSource) { - $$parsedSource["IAPtr"] = $$createField68_0($$parsedSource["IAPtr"]); - } - if ("IPA" in $$parsedSource) { - $$parsedSource["IPA"] = $$createField69_0($$parsedSource["IPA"]); - } - if ("IPAPtr" in $$parsedSource) { - $$parsedSource["IPAPtr"] = $$createField70_0($$parsedSource["IPAPtr"]); - } - if ("TPR" in $$parsedSource) { - $$parsedSource["TPR"] = $$createField71_0($$parsedSource["TPR"]); - } - if ("TPRPtr" in $$parsedSource) { - $$parsedSource["TPRPtr"] = $$createField72_0($$parsedSource["TPRPtr"]); - } - if ("TPS" in $$parsedSource) { - $$parsedSource["TPS"] = $$createField73_0($$parsedSource["TPS"]); - } - if ("TPSPtr" in $$parsedSource) { - $$parsedSource["TPSPtr"] = $$createField74_0($$parsedSource["TPSPtr"]); - } - if ("TPT" in $$parsedSource) { - $$parsedSource["TPT"] = $$createField75_0($$parsedSource["TPT"]); - } - if ("TPTPtr" in $$parsedSource) { - $$parsedSource["TPTPtr"] = $$createField76_0($$parsedSource["TPTPtr"]); - } - if ("TPU" in $$parsedSource) { - $$parsedSource["TPU"] = $$createField77_0($$parsedSource["TPU"]); - } - if ("TPUPtr" in $$parsedSource) { - $$parsedSource["TPUPtr"] = $$createField78_0($$parsedSource["TPUPtr"]); - } - if ("TPV" in $$parsedSource) { - $$parsedSource["TPV"] = $$createField79_0($$parsedSource["TPV"]); - } - if ("TPVPtr" in $$parsedSource) { - $$parsedSource["TPVPtr"] = $$createField80_0($$parsedSource["TPVPtr"]); - } - if ("TPW" in $$parsedSource) { - $$parsedSource["TPW"] = $$createField81_0($$parsedSource["TPW"]); - } - if ("TPWPtr" in $$parsedSource) { - $$parsedSource["TPWPtr"] = $$createField82_0($$parsedSource["TPWPtr"]); - } - if ("TPX" in $$parsedSource) { - $$parsedSource["TPX"] = $$createField83_0($$parsedSource["TPX"]); - } - if ("TPXPtr" in $$parsedSource) { - $$parsedSource["TPXPtr"] = $$createField84_0($$parsedSource["TPXPtr"]); - } - if ("TPY" in $$parsedSource) { - $$parsedSource["TPY"] = $$createField85_0($$parsedSource["TPY"]); - } - if ("TPYPtr" in $$parsedSource) { - $$parsedSource["TPYPtr"] = $$createField86_0($$parsedSource["TPYPtr"]); - } - if ("TPZ" in $$parsedSource) { - $$parsedSource["TPZ"] = $$createField87_0($$parsedSource["TPZ"]); - } - if ("TPZPtr" in $$parsedSource) { - $$parsedSource["TPZPtr"] = $$createField88_0($$parsedSource["TPZPtr"]); - } - if ("GAR" in $$parsedSource) { - $$parsedSource["GAR"] = $$createField89_0($$parsedSource["GAR"]); - } - if ("GARPtr" in $$parsedSource) { - $$parsedSource["GARPtr"] = $$createField90_0($$parsedSource["GARPtr"]); - } - if ("GAS" in $$parsedSource) { - $$parsedSource["GAS"] = $$createField91_0($$parsedSource["GAS"]); - } - if ("GASPtr" in $$parsedSource) { - $$parsedSource["GASPtr"] = $$createField92_0($$parsedSource["GASPtr"]); - } - if ("GAT" in $$parsedSource) { - $$parsedSource["GAT"] = $$createField93_0($$parsedSource["GAT"]); - } - if ("GATPtr" in $$parsedSource) { - $$parsedSource["GATPtr"] = $$createField94_0($$parsedSource["GATPtr"]); - } - if ("GAU" in $$parsedSource) { - $$parsedSource["GAU"] = $$createField95_0($$parsedSource["GAU"]); - } - if ("GAUPtr" in $$parsedSource) { - $$parsedSource["GAUPtr"] = $$createField96_0($$parsedSource["GAUPtr"]); - } - if ("GAV" in $$parsedSource) { - $$parsedSource["GAV"] = $$createField97_0($$parsedSource["GAV"]); - } - if ("GAVPtr" in $$parsedSource) { - $$parsedSource["GAVPtr"] = $$createField98_0($$parsedSource["GAVPtr"]); - } - if ("GAW" in $$parsedSource) { - $$parsedSource["GAW"] = $$createField99_0($$parsedSource["GAW"]); - } - if ("GAWPtr" in $$parsedSource) { - $$parsedSource["GAWPtr"] = $$createField100_0($$parsedSource["GAWPtr"]); - } - if ("GAX" in $$parsedSource) { - $$parsedSource["GAX"] = $$createField101_0($$parsedSource["GAX"]); - } - if ("GAXPtr" in $$parsedSource) { - $$parsedSource["GAXPtr"] = $$createField102_0($$parsedSource["GAXPtr"]); - } - if ("GAY" in $$parsedSource) { - $$parsedSource["GAY"] = $$createField103_0($$parsedSource["GAY"]); - } - if ("GAYPtr" in $$parsedSource) { - $$parsedSource["GAYPtr"] = $$createField104_0($$parsedSource["GAYPtr"]); - } - if ("GAZ" in $$parsedSource) { - $$parsedSource["GAZ"] = $$createField105_0($$parsedSource["GAZ"]); - } - if ("GAZPtr" in $$parsedSource) { - $$parsedSource["GAZPtr"] = $$createField106_0($$parsedSource["GAZPtr"]); - } - if ("GACi" in $$parsedSource) { - $$parsedSource["GACi"] = $$createField107_0($$parsedSource["GACi"]); - } - if ("GACV" in $$parsedSource) { - $$parsedSource["GACV"] = $$createField108_0($$parsedSource["GACV"]); - } - if ("GACP" in $$parsedSource) { - $$parsedSource["GACP"] = $$createField109_0($$parsedSource["GACP"]); - } - if ("GACiPtr" in $$parsedSource) { - $$parsedSource["GACiPtr"] = $$createField110_0($$parsedSource["GACiPtr"]); - } - if ("GACVPtr" in $$parsedSource) { - $$parsedSource["GACVPtr"] = $$createField111_0($$parsedSource["GACVPtr"]); - } - if ("GACPPtr" in $$parsedSource) { - $$parsedSource["GACPPtr"] = $$createField112_0($$parsedSource["GACPPtr"]); - } - if ("GABi" in $$parsedSource) { - $$parsedSource["GABi"] = $$createField113_0($$parsedSource["GABi"]); - } - if ("GABs" in $$parsedSource) { - $$parsedSource["GABs"] = $$createField114_0($$parsedSource["GABs"]); - } - if ("GABiPtr" in $$parsedSource) { - $$parsedSource["GABiPtr"] = $$createField115_0($$parsedSource["GABiPtr"]); - } - if ("GABT" in $$parsedSource) { - $$parsedSource["GABT"] = $$createField116_0($$parsedSource["GABT"]); - } - if ("GABTPtr" in $$parsedSource) { - $$parsedSource["GABTPtr"] = $$createField117_0($$parsedSource["GABTPtr"]); - } - if ("GAGT" in $$parsedSource) { - $$parsedSource["GAGT"] = $$createField118_0($$parsedSource["GAGT"]); - } - if ("GAGTPtr" in $$parsedSource) { - $$parsedSource["GAGTPtr"] = $$createField119_0($$parsedSource["GAGTPtr"]); - } - if ("GANBV" in $$parsedSource) { - $$parsedSource["GANBV"] = $$createField120_0($$parsedSource["GANBV"]); - } - if ("GANBP" in $$parsedSource) { - $$parsedSource["GANBP"] = $$createField121_0($$parsedSource["GANBP"]); - } - if ("GANBVPtr" in $$parsedSource) { - $$parsedSource["GANBVPtr"] = $$createField122_0($$parsedSource["GANBVPtr"]); - } - if ("GANBPPtr" in $$parsedSource) { - $$parsedSource["GANBPPtr"] = $$createField123_0($$parsedSource["GANBPPtr"]); - } - if ("GAPlV1" in $$parsedSource) { - $$parsedSource["GAPlV1"] = $$createField124_0($$parsedSource["GAPlV1"]); - } - if ("GAPlV2" in $$parsedSource) { - $$parsedSource["GAPlV2"] = $$createField125_0($$parsedSource["GAPlV2"]); - } - if ("GAPlP1" in $$parsedSource) { - $$parsedSource["GAPlP1"] = $$createField126_0($$parsedSource["GAPlP1"]); - } - if ("GAPlP2" in $$parsedSource) { - $$parsedSource["GAPlP2"] = $$createField127_0($$parsedSource["GAPlP2"]); - } - if ("GAPlVPtr" in $$parsedSource) { - $$parsedSource["GAPlVPtr"] = $$createField128_0($$parsedSource["GAPlVPtr"]); - } - if ("GAPlPPtr" in $$parsedSource) { - $$parsedSource["GAPlPPtr"] = $$createField129_0($$parsedSource["GAPlPPtr"]); - } - if ("GAMi" in $$parsedSource) { - $$parsedSource["GAMi"] = $$createField130_0($$parsedSource["GAMi"]); - } - if ("GAMS" in $$parsedSource) { - $$parsedSource["GAMS"] = $$createField131_0($$parsedSource["GAMS"]); - } - if ("GAMV" in $$parsedSource) { - $$parsedSource["GAMV"] = $$createField132_0($$parsedSource["GAMV"]); - } - if ("GAMSPtr" in $$parsedSource) { - $$parsedSource["GAMSPtr"] = $$createField133_0($$parsedSource["GAMSPtr"]); - } - if ("GAMVPtr" in $$parsedSource) { - $$parsedSource["GAMVPtr"] = $$createField134_0($$parsedSource["GAMVPtr"]); - } - if ("GAII" in $$parsedSource) { - $$parsedSource["GAII"] = $$createField135_0($$parsedSource["GAII"]); - } - if ("GAIV" in $$parsedSource) { - $$parsedSource["GAIV"] = $$createField136_0($$parsedSource["GAIV"]); - } - if ("GAIP" in $$parsedSource) { - $$parsedSource["GAIP"] = $$createField137_0($$parsedSource["GAIP"]); - } - if ("GAIIPtr" in $$parsedSource) { - $$parsedSource["GAIIPtr"] = $$createField138_0($$parsedSource["GAIIPtr"]); - } - if ("GAIVPtr" in $$parsedSource) { - $$parsedSource["GAIVPtr"] = $$createField139_0($$parsedSource["GAIVPtr"]); - } - if ("GAIPPtr" in $$parsedSource) { - $$parsedSource["GAIPPtr"] = $$createField140_0($$parsedSource["GAIPPtr"]); - } - if ("GAPrV" in $$parsedSource) { - $$parsedSource["GAPrV"] = $$createField141_0($$parsedSource["GAPrV"]); - } - if ("GAPrP" in $$parsedSource) { - $$parsedSource["GAPrP"] = $$createField142_0($$parsedSource["GAPrP"]); - } - if ("GAPrVPtr" in $$parsedSource) { - $$parsedSource["GAPrVPtr"] = $$createField143_0($$parsedSource["GAPrVPtr"]); - } - if ("GAPrPPtr" in $$parsedSource) { - $$parsedSource["GAPrPPtr"] = $$createField144_0($$parsedSource["GAPrPPtr"]); - } - return new Maps($$parsedSource as Partial>); - }; - } -} - -export type MixedCstrAlias = X; - -export type NonBasicCstrAlias = V; - -export type PointableCstrAlias = W; - -export type PointerAlias = PointerTextMarshaler; - -export type PointerTextMarshaler = string; - -export type StringAlias = string; - -export type StringType = string; - -export type ValueAlias = ValueTextMarshaler; - -export type ValueTextMarshaler = string; - -// Private type creation functions -const $$createType0 = $Create.Map($Create.Any, $Create.Any); -const $$createType1 = $Create.Map($Create.Any, $Create.Any); -const $$createType2 = $Create.Map($Create.Any, $Create.Any); -const $$createType3 = $Create.Map($Create.Any, $Create.Any); -const $$createType4 = $Create.Map($Create.Any, $Create.Any); -const $$createType5 = $Create.Map($Create.Any, $Create.Any); -const $$createType6 = $Create.Map($Create.Any, $Create.Any); -const $$createType7 = $Create.Map($Create.Any, $Create.Any); -const $$createType8 = $Create.Map($Create.Any, $Create.Any); -const $$createType9 = $Create.Map($Create.Any, $Create.Any); -const $$createType10 = $Create.Map($Create.Any, $Create.Any); -const $$createType11 = $Create.Map($Create.Any, $Create.Any); -const $$createType12 = $Create.Map($Create.Any, $Create.Any); -const $$createType13 = $Create.Map($Create.Any, $Create.Any); -const $$createType14 = $Create.Map($Create.Any, $Create.Any); -const $$createType15 = $Create.Map($Create.Any, $Create.Any); -const $$createType16 = $Create.Map($Create.Any, $Create.Any); -const $$createType17 = $Create.Map($Create.Any, $Create.Any); -const $$createType18 = $Create.Map($Create.Any, $Create.Any); -const $$createType19 = $Create.Map($Create.Any, $Create.Any); -const $$createType20 = $Create.Map($Create.Any, $Create.Any); -const $$createType21 = $Create.Map($Create.Any, $Create.Any); -const $$createType22 = $Create.Map($Create.Any, $Create.Any); -const $$createType23 = $Create.Map($Create.Any, $Create.Any); -const $$createType24 = $Create.Map($Create.Any, $Create.Any); -const $$createType25 = $Create.Map($Create.Any, $Create.Any); -const $$createType26 = $Create.Map($Create.Any, $Create.Any); -const $$createType27 = $Create.Map($Create.Any, $Create.Any); -const $$createType28 = $Create.Map($Create.Any, $Create.Any); -const $$createType29 = $Create.Map($Create.Any, $Create.Any); -const $$createType30 = $Create.Map($Create.Any, $Create.Any); -const $$createType31 = $Create.Map($Create.Any, $Create.Any); -const $$createType32 = $Create.Map($Create.Any, $Create.Any); -const $$createType33 = $Create.Map($Create.Any, $Create.Any); -const $$createType34 = $Create.Map($Create.Any, $Create.Any); -const $$createType35 = $Create.Map($Create.Any, $Create.Any); -const $$createType36 = $Create.Map($Create.Any, $Create.Any); -const $$createType37 = $Create.Map($Create.Any, $Create.Any); -const $$createType38 = $Create.Map($Create.Any, $Create.Any); -const $$createType39 = $Create.Map($Create.Any, $Create.Any); -const $$createType40 = $Create.Map($Create.Any, $Create.Any); -const $$createType41 = $Create.Map($Create.Any, $Create.Any); -const $$createType42 = $Create.Map($Create.Any, $Create.Any); -const $$createType43 = $Create.Map($Create.Any, $Create.Any); -const $$createType44 = $Create.Map($Create.Any, $Create.Any); -const $$createType45 = $Create.Map($Create.Any, $Create.Any); -const $$createType46 = $Create.Map($Create.Any, $Create.Any); -const $$createType47 = $Create.Map($Create.Any, $Create.Any); -const $$createType48 = $Create.Map($Create.Any, $Create.Any); -const $$createType49 = $Create.Map($Create.Any, $Create.Any); -const $$createType50 = $Create.Map($Create.Any, $Create.Any); -const $$createType51 = $Create.Map($Create.Any, $Create.Any); -const $$createType52 = $Create.Map($Create.Any, $Create.Any); -const $$createType53 = $Create.Map($Create.Any, $Create.Any); -const $$createType54 = $Create.Map($Create.Any, $Create.Any); -const $$createType55 = $Create.Map($Create.Any, $Create.Any); -const $$createType56 = $Create.Map($Create.Any, $Create.Any); -const $$createType57 = $Create.Map($Create.Any, $Create.Any); -const $$createType58 = $Create.Map($Create.Any, $Create.Any); -const $$createType59 = ($$createParamR: any, $$createParamS: any, $$createParamT: any, $$createParamU: any, $$createParamV: any, $$createParamW: any, $$createParamX: any, $$createParamY: any, $$createParamZ: any) => $Create.Map($Create.Any, $Create.Any); -const $$createType60 = ($$createParamR: any, $$createParamS: any, $$createParamT: any, $$createParamU: any, $$createParamV: any, $$createParamW: any, $$createParamX: any, $$createParamY: any, $$createParamZ: any) => $Create.Map($Create.Any, $Create.Any); -const $$createType61 = ($$createParamR: any, $$createParamS: any, $$createParamT: any, $$createParamU: any, $$createParamV: any, $$createParamW: any, $$createParamX: any, $$createParamY: any, $$createParamZ: any) => $Create.Map($Create.Any, $Create.Any); -const $$createType62 = ($$createParamR: any, $$createParamS: any, $$createParamT: any, $$createParamU: any, $$createParamV: any, $$createParamW: any, $$createParamX: any, $$createParamY: any, $$createParamZ: any) => $Create.Map($Create.Any, $Create.Any); -const $$createType63 = ($$createParamR: any, $$createParamS: any, $$createParamT: any, $$createParamU: any, $$createParamV: any, $$createParamW: any, $$createParamX: any, $$createParamY: any, $$createParamZ: any) => $Create.Map($Create.Any, $Create.Any); -const $$createType64 = ($$createParamR: any, $$createParamS: any, $$createParamT: any, $$createParamU: any, $$createParamV: any, $$createParamW: any, $$createParamX: any, $$createParamY: any, $$createParamZ: any) => $Create.Map($Create.Any, $Create.Any); -const $$createType65 = ($$createParamR: any, $$createParamS: any, $$createParamT: any, $$createParamU: any, $$createParamV: any, $$createParamW: any, $$createParamX: any, $$createParamY: any, $$createParamZ: any) => $Create.Map($Create.Any, $Create.Any); -const $$createType66 = ($$createParamR: any, $$createParamS: any, $$createParamT: any, $$createParamU: any, $$createParamV: any, $$createParamW: any, $$createParamX: any, $$createParamY: any, $$createParamZ: any) => $Create.Map($Create.Any, $Create.Any); -const $$createType67 = ($$createParamR: any, $$createParamS: any, $$createParamT: any, $$createParamU: any, $$createParamV: any, $$createParamW: any, $$createParamX: any, $$createParamY: any, $$createParamZ: any) => $Create.Map($Create.Any, $Create.Any); -const $$createType68 = ($$createParamR: any, $$createParamS: any, $$createParamT: any, $$createParamU: any, $$createParamV: any, $$createParamW: any, $$createParamX: any, $$createParamY: any, $$createParamZ: any) => $Create.Map($Create.Any, $Create.Any); -const $$createType69 = ($$createParamR: any, $$createParamS: any, $$createParamT: any, $$createParamU: any, $$createParamV: any, $$createParamW: any, $$createParamX: any, $$createParamY: any, $$createParamZ: any) => $Create.Map($Create.Any, $Create.Any); -const $$createType70 = ($$createParamR: any, $$createParamS: any, $$createParamT: any, $$createParamU: any, $$createParamV: any, $$createParamW: any, $$createParamX: any, $$createParamY: any, $$createParamZ: any) => $Create.Map($Create.Any, $Create.Any); -const $$createType71 = ($$createParamR: any, $$createParamS: any, $$createParamT: any, $$createParamU: any, $$createParamV: any, $$createParamW: any, $$createParamX: any, $$createParamY: any, $$createParamZ: any) => $Create.Map($Create.Any, $Create.Any); -const $$createType72 = ($$createParamR: any, $$createParamS: any, $$createParamT: any, $$createParamU: any, $$createParamV: any, $$createParamW: any, $$createParamX: any, $$createParamY: any, $$createParamZ: any) => $Create.Map($Create.Any, $Create.Any); -const $$createType73 = ($$createParamR: any, $$createParamS: any, $$createParamT: any, $$createParamU: any, $$createParamV: any, $$createParamW: any, $$createParamX: any, $$createParamY: any, $$createParamZ: any) => $Create.Map($Create.Any, $Create.Any); -const $$createType74 = ($$createParamR: any, $$createParamS: any, $$createParamT: any, $$createParamU: any, $$createParamV: any, $$createParamW: any, $$createParamX: any, $$createParamY: any, $$createParamZ: any) => $Create.Map($Create.Any, $Create.Any); -const $$createType75 = ($$createParamR: any, $$createParamS: any, $$createParamT: any, $$createParamU: any, $$createParamV: any, $$createParamW: any, $$createParamX: any, $$createParamY: any, $$createParamZ: any) => $Create.Map($Create.Any, $Create.Any); -const $$createType76 = ($$createParamR: any, $$createParamS: any, $$createParamT: any, $$createParamU: any, $$createParamV: any, $$createParamW: any, $$createParamX: any, $$createParamY: any, $$createParamZ: any) => $Create.Map($Create.Any, $Create.Any); -const $$createType77 = $Create.Map($Create.Any, $Create.Any); -const $$createType78 = $Create.Map($Create.Any, $Create.Any); -const $$createType79 = $Create.Map($Create.Any, $Create.Any); diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys/service.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys/service.ts deleted file mode 100644 index d62acda96..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys/service.ts +++ /dev/null @@ -1,19 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -export function Method(): $CancellablePromise<$models.Maps<$models.PointerTextMarshaler, number, number, $models.ValueTextMarshaler, $models.PointerTextMarshaler | null, $models.ValueTextMarshaler, $models.StringType, $models.ValueTextMarshaler, $models.PointerTextMarshaler | null>> { - return $Call.ByName("main.Service.Method").then(($result: any) => { - return $$createType0($result); - }); -} - -// Private type creation functions -const $$createType0 = $models.Maps.createFrom($Create.Any, $Create.Any, $Create.Any, $Create.Any, $Create.Any, $Create.Any, $Create.Any, $Create.Any, $Create.Any); diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/marshalers/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/marshalers/index.ts deleted file mode 100644 index bbe49e32f..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/marshalers/index.ts +++ /dev/null @@ -1,36 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as Service from "./service.js"; -export { - Service -}; - -export { - Data, - ImplicitNonMarshaler, - NonMarshaler -} from "./models.js"; - -export type { - AliasJsonMarshaler, - AliasMarshaler, - AliasNonMarshaler, - AliasTextMarshaler, - ImplicitJsonButText, - ImplicitJsonMarshaler, - ImplicitMarshaler, - ImplicitNonJson, - ImplicitNonText, - ImplicitTextButJson, - ImplicitTextMarshaler, - PointerJsonMarshaler, - PointerMarshaler, - PointerTextMarshaler, - UnderlyingJsonMarshaler, - UnderlyingMarshaler, - UnderlyingTextMarshaler, - ValueJsonMarshaler, - ValueMarshaler, - ValueTextMarshaler -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/marshalers/models.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/marshalers/models.ts deleted file mode 100644 index d8db23862..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/marshalers/models.ts +++ /dev/null @@ -1,545 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Create as $Create } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as encoding$0 from "../../../../../../../../encoding/models.js"; -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as json$0 from "../../../../../../../../encoding/json/models.js"; - -/** - * any - */ -export type AliasJsonMarshaler = any; - -/** - * any - */ -export type AliasMarshaler = any; - -/** - * struct{} - */ -export interface AliasNonMarshaler { -} - -/** - * string - */ -export type AliasTextMarshaler = string; - -export class Data { - "NM": NonMarshaler; - - /** - * NonMarshaler | null - */ - "NMPtr": NonMarshaler | null; - "VJM": ValueJsonMarshaler; - - /** - * ValueJsonMarshaler | null - */ - "VJMPtr": ValueJsonMarshaler | null; - "PJM": PointerJsonMarshaler; - - /** - * PointerJsonMarshaler | null - */ - "PJMPtr": PointerJsonMarshaler | null; - "VTM": ValueTextMarshaler; - - /** - * ValueTextMarshaler | null - */ - "VTMPtr": ValueTextMarshaler | null; - "PTM": PointerTextMarshaler; - - /** - * PointerTextMarshaler | null - */ - "PTMPtr": PointerTextMarshaler | null; - "VM": ValueMarshaler; - - /** - * ValueMarshaler | null - */ - "VMPtr": ValueMarshaler | null; - "PM": PointerMarshaler; - - /** - * PointerMarshaler | null - */ - "PMPtr": PointerMarshaler | null; - "UJM": UnderlyingJsonMarshaler; - - /** - * UnderlyingJsonMarshaler | null - */ - "UJMPtr": UnderlyingJsonMarshaler | null; - "UTM": UnderlyingTextMarshaler; - - /** - * UnderlyingTextMarshaler | null - */ - "UTMPtr": UnderlyingTextMarshaler | null; - "UM": UnderlyingMarshaler; - - /** - * UnderlyingMarshaler | null - */ - "UMPtr": UnderlyingMarshaler | null; - - /** - * any - */ - "JM": any; - - /** - * any | null - */ - "JMPtr": any | null; - - /** - * string - */ - "TM": string; - - /** - * string | null - */ - "TMPtr": string | null; - - /** - * any - */ - "CJM": any; - - /** - * any | null - */ - "CJMPtr": any | null; - - /** - * string - */ - "CTM": string; - - /** - * string | null - */ - "CTMPtr": string | null; - - /** - * any - */ - "CM": any; - - /** - * any | null - */ - "CMPtr": any | null; - "ANM": AliasNonMarshaler; - - /** - * AliasNonMarshaler | null - */ - "ANMPtr": AliasNonMarshaler | null; - "AJM": AliasJsonMarshaler; - - /** - * AliasJsonMarshaler | null - */ - "AJMPtr": AliasJsonMarshaler | null; - "ATM": AliasTextMarshaler; - - /** - * AliasTextMarshaler | null - */ - "ATMPtr": AliasTextMarshaler | null; - "AM": AliasMarshaler; - - /** - * AliasMarshaler | null - */ - "AMPtr": AliasMarshaler | null; - "ImJM": ImplicitJsonMarshaler; - - /** - * ImplicitJsonMarshaler | null - */ - "ImJMPtr": ImplicitJsonMarshaler | null; - "ImTM": ImplicitTextMarshaler; - - /** - * ImplicitTextMarshaler | null - */ - "ImTMPtr": ImplicitTextMarshaler | null; - "ImM": ImplicitMarshaler; - - /** - * ImplicitMarshaler | null - */ - "ImMPtr": ImplicitMarshaler | null; - "ImNJ": ImplicitNonJson; - - /** - * ImplicitNonJson | null - */ - "ImNJPtr": ImplicitNonJson | null; - "ImNT": ImplicitNonText; - - /** - * ImplicitNonText | null - */ - "ImNTPtr": ImplicitNonText | null; - "ImNM": ImplicitNonMarshaler; - - /** - * ImplicitNonMarshaler | null - */ - "ImNMPtr": ImplicitNonMarshaler | null; - "ImJbT": ImplicitJsonButText; - - /** - * ImplicitJsonButText | null - */ - "ImJbTPtr": ImplicitJsonButText | null; - "ImTbJ": ImplicitTextButJson; - - /** - * ImplicitTextButJson | null - */ - "ImTbJPtr": ImplicitTextButJson | null; - - /** Creates a new Data instance. */ - constructor($$source: Partial = {}) { - if (!("NM" in $$source)) { - this["NM"] = (new NonMarshaler()); - } - if (!("NMPtr" in $$source)) { - this["NMPtr"] = null; - } - if (!("VJM" in $$source)) { - this["VJM"] = null; - } - if (!("VJMPtr" in $$source)) { - this["VJMPtr"] = null; - } - if (!("PJM" in $$source)) { - this["PJM"] = null; - } - if (!("PJMPtr" in $$source)) { - this["PJMPtr"] = null; - } - if (!("VTM" in $$source)) { - this["VTM"] = ""; - } - if (!("VTMPtr" in $$source)) { - this["VTMPtr"] = null; - } - if (!("PTM" in $$source)) { - this["PTM"] = ""; - } - if (!("PTMPtr" in $$source)) { - this["PTMPtr"] = null; - } - if (!("VM" in $$source)) { - this["VM"] = null; - } - if (!("VMPtr" in $$source)) { - this["VMPtr"] = null; - } - if (!("PM" in $$source)) { - this["PM"] = null; - } - if (!("PMPtr" in $$source)) { - this["PMPtr"] = null; - } - if (!("UJM" in $$source)) { - this["UJM"] = null; - } - if (!("UJMPtr" in $$source)) { - this["UJMPtr"] = null; - } - if (!("UTM" in $$source)) { - this["UTM"] = ""; - } - if (!("UTMPtr" in $$source)) { - this["UTMPtr"] = null; - } - if (!("UM" in $$source)) { - this["UM"] = null; - } - if (!("UMPtr" in $$source)) { - this["UMPtr"] = null; - } - if (!("JM" in $$source)) { - this["JM"] = null; - } - if (!("JMPtr" in $$source)) { - this["JMPtr"] = null; - } - if (!("TM" in $$source)) { - this["TM"] = ""; - } - if (!("TMPtr" in $$source)) { - this["TMPtr"] = null; - } - if (!("CJM" in $$source)) { - this["CJM"] = null; - } - if (!("CJMPtr" in $$source)) { - this["CJMPtr"] = null; - } - if (!("CTM" in $$source)) { - this["CTM"] = ""; - } - if (!("CTMPtr" in $$source)) { - this["CTMPtr"] = null; - } - if (!("CM" in $$source)) { - this["CM"] = null; - } - if (!("CMPtr" in $$source)) { - this["CMPtr"] = null; - } - if (!("ANM" in $$source)) { - this["ANM"] = {}; - } - if (!("ANMPtr" in $$source)) { - this["ANMPtr"] = null; - } - if (!("AJM" in $$source)) { - this["AJM"] = null; - } - if (!("AJMPtr" in $$source)) { - this["AJMPtr"] = null; - } - if (!("ATM" in $$source)) { - this["ATM"] = ""; - } - if (!("ATMPtr" in $$source)) { - this["ATMPtr"] = null; - } - if (!("AM" in $$source)) { - this["AM"] = null; - } - if (!("AMPtr" in $$source)) { - this["AMPtr"] = null; - } - if (!("ImJM" in $$source)) { - this["ImJM"] = null; - } - if (!("ImJMPtr" in $$source)) { - this["ImJMPtr"] = null; - } - if (!("ImTM" in $$source)) { - this["ImTM"] = ""; - } - if (!("ImTMPtr" in $$source)) { - this["ImTMPtr"] = null; - } - if (!("ImM" in $$source)) { - this["ImM"] = null; - } - if (!("ImMPtr" in $$source)) { - this["ImMPtr"] = null; - } - if (!("ImNJ" in $$source)) { - this["ImNJ"] = ""; - } - if (!("ImNJPtr" in $$source)) { - this["ImNJPtr"] = null; - } - if (!("ImNT" in $$source)) { - this["ImNT"] = null; - } - if (!("ImNTPtr" in $$source)) { - this["ImNTPtr"] = null; - } - if (!("ImNM" in $$source)) { - this["ImNM"] = (new ImplicitNonMarshaler()); - } - if (!("ImNMPtr" in $$source)) { - this["ImNMPtr"] = null; - } - if (!("ImJbT" in $$source)) { - this["ImJbT"] = null; - } - if (!("ImJbTPtr" in $$source)) { - this["ImJbTPtr"] = null; - } - if (!("ImTbJ" in $$source)) { - this["ImTbJ"] = null; - } - if (!("ImTbJPtr" in $$source)) { - this["ImTbJPtr"] = null; - } - - Object.assign(this, $$source); - } - - /** - * Creates a new Data instance from a string or object. - */ - static createFrom($$source: any = {}): Data { - const $$createField0_0 = $$createType0; - const $$createField1_0 = $$createType1; - const $$createField48_0 = $$createType2; - const $$createField49_0 = $$createType3; - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - if ("NM" in $$parsedSource) { - $$parsedSource["NM"] = $$createField0_0($$parsedSource["NM"]); - } - if ("NMPtr" in $$parsedSource) { - $$parsedSource["NMPtr"] = $$createField1_0($$parsedSource["NMPtr"]); - } - if ("ImNM" in $$parsedSource) { - $$parsedSource["ImNM"] = $$createField48_0($$parsedSource["ImNM"]); - } - if ("ImNMPtr" in $$parsedSource) { - $$parsedSource["ImNMPtr"] = $$createField49_0($$parsedSource["ImNMPtr"]); - } - return new Data($$parsedSource as Partial); - } -} - -/** - * any - */ -export type ImplicitJsonButText = any; - -/** - * any - */ -export type ImplicitJsonMarshaler = any; - -/** - * any - */ -export type ImplicitMarshaler = any; - -/** - * string - */ -export type ImplicitNonJson = string; - -/** - * class{ Marshaler, TextMarshaler } - */ -export class ImplicitNonMarshaler { - "Marshaler": json$0.Marshaler; - "TextMarshaler": encoding$0.TextMarshaler; - - /** Creates a new ImplicitNonMarshaler instance. */ - constructor($$source: Partial = {}) { - if (!("Marshaler" in $$source)) { - this["Marshaler"] = null; - } - if (!("TextMarshaler" in $$source)) { - this["TextMarshaler"] = ""; - } - - Object.assign(this, $$source); - } - - /** - * Creates a new ImplicitNonMarshaler instance from a string or object. - */ - static createFrom($$source: any = {}): ImplicitNonMarshaler { - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - return new ImplicitNonMarshaler($$parsedSource as Partial); - } -} - -/** - * any - */ -export type ImplicitNonText = any; - -/** - * any - */ -export type ImplicitTextButJson = any; - -/** - * string - */ -export type ImplicitTextMarshaler = string; - -/** - * class {} - */ -export class NonMarshaler { - - /** Creates a new NonMarshaler instance. */ - constructor($$source: Partial = {}) { - - Object.assign(this, $$source); - } - - /** - * Creates a new NonMarshaler instance from a string or object. - */ - static createFrom($$source: any = {}): NonMarshaler { - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - return new NonMarshaler($$parsedSource as Partial); - } -} - -/** - * any - */ -export type PointerJsonMarshaler = any; - -/** - * any - */ -export type PointerMarshaler = any; - -/** - * string - */ -export type PointerTextMarshaler = string; - -/** - * any - */ -export type UnderlyingJsonMarshaler = any; - -/** - * any - */ -export type UnderlyingMarshaler = any; - -/** - * string - */ -export type UnderlyingTextMarshaler = string; - -/** - * any - */ -export type ValueJsonMarshaler = any; - -/** - * any - */ -export type ValueMarshaler = any; - -/** - * string - */ -export type ValueTextMarshaler = string; - -// Private type creation functions -const $$createType0 = NonMarshaler.createFrom; -const $$createType1 = $Create.Nullable($$createType0); -const $$createType2 = ImplicitNonMarshaler.createFrom; -const $$createType3 = $Create.Nullable($$createType2); diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/marshalers/service.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/marshalers/service.ts deleted file mode 100644 index 8e2af391b..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/marshalers/service.ts +++ /dev/null @@ -1,19 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -export function Method(): $CancellablePromise<$models.Data> { - return $Call.ByName("main.Service.Method").then(($result: any) => { - return $$createType0($result); - }); -} - -// Private type creation functions -const $$createType0 = $models.Data.createFrom; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/index.ts deleted file mode 100644 index 19d990dbf..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/index.ts +++ /dev/null @@ -1,14 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as SomeMethods from "./somemethods.js"; -export { - SomeMethods -}; - -export { - HowDifferent, - Impersonator, - Person, - PrivatePerson -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/models.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/models.ts deleted file mode 100644 index 967f8dbfd..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/models.ts +++ /dev/null @@ -1,163 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Create as $Create } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as other$0 from "./other/models.js"; - -/** - * HowDifferent is a curious kind of person - * that lets other people decide how they are different. - */ -export class HowDifferent { - /** - * They have a name as well. - */ - "Name": string; - - /** - * But they may have many differences. - */ - "Differences": { [_ in string]?: How }[]; - - /** Creates a new HowDifferent instance. */ - constructor($$source: Partial> = {}) { - if (!("Name" in $$source)) { - this["Name"] = ""; - } - if (!("Differences" in $$source)) { - this["Differences"] = []; - } - - Object.assign(this, $$source); - } - - /** - * Given creation functions for each type parameter, - * returns a creation function for a concrete instance - * of the generic class HowDifferent. - */ - static createFrom($$createParamHow: (source: any) => How): ($$source?: any) => HowDifferent { - const $$createField1_0 = $$createType1($$createParamHow); - return ($$source: any = {}) => { - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - if ("Differences" in $$parsedSource) { - $$parsedSource["Differences"] = $$createField1_0($$parsedSource["Differences"]); - } - return new HowDifferent($$parsedSource as Partial>); - }; - } -} - -/** - * Impersonator gets their fields from other people. - */ -export const Impersonator = other$0.OtherPerson; - -/** - * Impersonator gets their fields from other people. - */ -export type Impersonator = other$0.OtherPerson; - -/** - * Person is not a number. - */ -export class Person { - /** - * They have a name. - */ - "Name": string; - - /** - * Exactly 4 sketchy friends. - */ - "Friends": Impersonator[]; - - /** Creates a new Person instance. */ - constructor($$source: Partial = {}) { - if (!("Name" in $$source)) { - this["Name"] = ""; - } - if (!("Friends" in $$source)) { - this["Friends"] = Array.from({ length: 4 }, () => (new Impersonator())); - } - - Object.assign(this, $$source); - } - - /** - * Creates a new Person instance from a string or object. - */ - static createFrom($$source: any = {}): Person { - const $$createField1_0 = $$createType3; - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - if ("Friends" in $$parsedSource) { - $$parsedSource["Friends"] = $$createField1_0($$parsedSource["Friends"]); - } - return new Person($$parsedSource as Partial); - } -} - -export class personImpl { - /** - * Nickname conceals a person's identity. - */ - "Nickname": string; - - /** - * They have a name. - */ - "Name": string; - - /** - * Exactly 4 sketchy friends. - */ - "Friends": Impersonator[]; - - /** Creates a new personImpl instance. */ - constructor($$source: Partial = {}) { - if (!("Nickname" in $$source)) { - this["Nickname"] = ""; - } - if (!("Name" in $$source)) { - this["Name"] = ""; - } - if (!("Friends" in $$source)) { - this["Friends"] = Array.from({ length: 4 }, () => (new Impersonator())); - } - - Object.assign(this, $$source); - } - - /** - * Creates a new personImpl instance from a string or object. - */ - static createFrom($$source: any = {}): personImpl { - const $$createField2_0 = $$createType3; - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - if ("Friends" in $$parsedSource) { - $$parsedSource["Friends"] = $$createField2_0($$parsedSource["Friends"]); - } - return new personImpl($$parsedSource as Partial); - } -} - -/** - * PrivatePerson gets their fields from hidden sources. - */ -export const PrivatePerson = personImpl; - -/** - * PrivatePerson gets their fields from hidden sources. - */ -export type PrivatePerson = personImpl; - -// Private type creation functions -const $$createType0 = ($$createParamHow: any) => $Create.Map($Create.Any, $$createParamHow); -const $$createType1 = ($$createParamHow: any) => $Create.Array($$createType0($$createParamHow)); -const $$createType2 = other$0.OtherPerson.createFrom($Create.Any); -const $$createType3 = $Create.Array($$createType2); diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/more/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/more/index.ts deleted file mode 100644 index ac743f356..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/more/index.ts +++ /dev/null @@ -1,6 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -export type { - StringPtr -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/more/models.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/more/models.ts deleted file mode 100644 index 168c7fdba..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/more/models.ts +++ /dev/null @@ -1,11 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Create as $Create } from "/wails/runtime.js"; - -/** - * StringPtr is a nullable string. - */ -export type StringPtr = string | null; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/other/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/other/index.ts deleted file mode 100644 index d2d973b28..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/other/index.ts +++ /dev/null @@ -1,11 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as OtherMethods from "./othermethods.js"; -export { - OtherMethods -}; - -export { - OtherPerson -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/other/models.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/other/models.ts deleted file mode 100644 index 711735a2b..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/other/models.ts +++ /dev/null @@ -1,52 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Create as $Create } from "/wails/runtime.js"; - -/** - * OtherPerson is like a person, but different. - */ -export class OtherPerson { - /** - * They have a name as well. - */ - "Name": string; - - /** - * But they may have many differences. - */ - "Differences": T[]; - - /** Creates a new OtherPerson instance. */ - constructor($$source: Partial> = {}) { - if (!("Name" in $$source)) { - this["Name"] = ""; - } - if (!("Differences" in $$source)) { - this["Differences"] = []; - } - - Object.assign(this, $$source); - } - - /** - * Given creation functions for each type parameter, - * returns a creation function for a concrete instance - * of the generic class OtherPerson. - */ - static createFrom($$createParamT: (source: any) => T): ($$source?: any) => OtherPerson { - const $$createField1_0 = $$createType0($$createParamT); - return ($$source: any = {}) => { - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - if ("Differences" in $$parsedSource) { - $$parsedSource["Differences"] = $$createField1_0($$parsedSource["Differences"]); - } - return new OtherPerson($$parsedSource as Partial>); - }; - } -} - -// Private type creation functions -const $$createType0 = ($$createParamT: any) => $Create.Array($$createParamT); diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/other/othermethods.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/other/othermethods.ts deleted file mode 100644 index 2e4c173df..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/other/othermethods.ts +++ /dev/null @@ -1,18 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * OtherMethods has another method, but through a private embedded type. - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -/** - * LikeThisOtherOne does nothing as well, but is different. - */ -export function LikeThisOtherOne(): $CancellablePromise { - return $Call.ByName("github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/other.OtherMethods.LikeThisOtherOne"); -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/somemethods.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/somemethods.ts deleted file mode 100644 index fb5f5ce21..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/somemethods.ts +++ /dev/null @@ -1,39 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * SomeMethods exports some methods. - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * LikeThisOne is an example method that does nothing. - */ -export function LikeThisOne(): $CancellablePromise<[$models.Person, $models.HowDifferent, $models.PrivatePerson]> { - return $Call.ByName("github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here.SomeMethods.LikeThisOne").then(($result: any) => { - $result[0] = $$createType0($result[0]); - $result[1] = $$createType1($result[1]); - $result[2] = $$createType2($result[2]); - return $result; - }); -} - -/** - * LikeThisOtherOne does nothing as well, but is different. - */ -export function LikeThisOtherOne(): $CancellablePromise { - return $Call.ByName("github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here.SomeMethods.LikeThisOtherOne"); -} - -// Private type creation functions -const $$createType0 = $models.Person.createFrom; -const $$createType1 = $models.HowDifferent.createFrom($Create.Any); -const $$createType2 = $models.personImpl.createFrom; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/out_of_tree/embedother.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/out_of_tree/embedother.ts deleted file mode 100644 index c82f44866..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/out_of_tree/embedother.ts +++ /dev/null @@ -1,18 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * EmbedOther is even trickier. - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -/** - * LikeThisOtherOne does nothing as well, but is different. - */ -export function LikeThisOtherOne(): $CancellablePromise { - return $Call.ByName("main.EmbedOther.LikeThisOtherOne"); -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/out_of_tree/embedservice.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/out_of_tree/embedservice.ts deleted file mode 100644 index e3b2fe679..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/out_of_tree/embedservice.ts +++ /dev/null @@ -1,39 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * EmbedService is tricky. - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as nobindingshere$0 from "../no_bindings_here/models.js"; - -/** - * LikeThisOne is an example method that does nothing. - */ -export function LikeThisOne(): $CancellablePromise<[nobindingshere$0.Person, nobindingshere$0.HowDifferent, nobindingshere$0.PrivatePerson]> { - return $Call.ByName("main.EmbedService.LikeThisOne").then(($result: any) => { - $result[0] = $$createType0($result[0]); - $result[1] = $$createType1($result[1]); - $result[2] = $$createType2($result[2]); - return $result; - }); -} - -/** - * LikeThisOtherOne does nothing as well, but is different. - */ -export function LikeThisOtherOne(): $CancellablePromise { - return $Call.ByName("main.EmbedService.LikeThisOtherOne"); -} - -// Private type creation functions -const $$createType0 = nobindingshere$0.Person.createFrom; -const $$createType1 = nobindingshere$0.HowDifferent.createFrom($Create.Any); -const $$createType2 = nobindingshere$0.personImpl.createFrom; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/out_of_tree/greetservice.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/out_of_tree/greetservice.ts deleted file mode 100644 index 192340e8e..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/out_of_tree/greetservice.ts +++ /dev/null @@ -1,18 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -/** - * Greet someone - */ -export function Greet($0: string): $CancellablePromise { - return $Call.ByName("main.GreetService.Greet", $0); -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/out_of_tree/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/out_of_tree/index.ts deleted file mode 100644 index e69bebf3b..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/out_of_tree/index.ts +++ /dev/null @@ -1,11 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as EmbedOther from "./embedother.js"; -import * as EmbedService from "./embedservice.js"; -import * as GreetService from "./greetservice.js"; -export { - EmbedOther, - EmbedService, - GreetService -}; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple/greetservice.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple/greetservice.ts deleted file mode 100644 index 460b2b374..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple/greetservice.ts +++ /dev/null @@ -1,10 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -export function Greet(name: string): $CancellablePromise { - return $Call.ByName("main.GreetService.Greet", name); -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple/index.ts deleted file mode 100644 index 5c4ebea4f..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple/index.ts +++ /dev/null @@ -1,9 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -import * as OtherService from "./otherservice.js"; -export { - GreetService, - OtherService -}; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple/otherservice.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple/otherservice.ts deleted file mode 100644 index e437314f4..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple/otherservice.ts +++ /dev/null @@ -1,10 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -export function Hello(): $CancellablePromise { - return $Call.ByName("main.OtherService.Hello"); -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_files/greetservice.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_files/greetservice.ts deleted file mode 100644 index 460b2b374..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_files/greetservice.ts +++ /dev/null @@ -1,10 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -export function Greet(name: string): $CancellablePromise { - return $Call.ByName("main.GreetService.Greet", name); -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_files/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_files/index.ts deleted file mode 100644 index 5c4ebea4f..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_files/index.ts +++ /dev/null @@ -1,9 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -import * as OtherService from "./otherservice.js"; -export { - GreetService, - OtherService -}; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_files/otherservice.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_files/otherservice.ts deleted file mode 100644 index e437314f4..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_files/otherservice.ts +++ /dev/null @@ -1,10 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -export function Hello(): $CancellablePromise { - return $Call.ByName("main.OtherService.Hello"); -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_other/greetservice.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_other/greetservice.ts deleted file mode 100644 index 1a2ffb266..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_other/greetservice.ts +++ /dev/null @@ -1,35 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * Greet does XYZ - */ -export function Greet(name: string): $CancellablePromise { - return $Call.ByName("main.GreetService.Greet", name); -} - -/** - * NewPerson creates a new person - */ -export function NewPerson(name: string): $CancellablePromise<$models.Person | null> { - return $Call.ByName("main.GreetService.NewPerson", name).then(($result: any) => { - return $$createType1($result); - }); -} - -// Private type creation functions -const $$createType0 = $models.Person.createFrom; -const $$createType1 = $Create.Nullable($$createType0); diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_other/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_other/index.ts deleted file mode 100644 index f95c1b558..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_other/index.ts +++ /dev/null @@ -1,11 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; - -export { - Person -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_other/models.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_other/models.ts deleted file mode 100644 index d76f68d9d..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_other/models.ts +++ /dev/null @@ -1,43 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Create as $Create } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as services$0 from "./services/models.js"; - -export class Person { - "Name": string; - "Address": services$0.Address | null; - - /** Creates a new Person instance. */ - constructor($$source: Partial = {}) { - if (!("Name" in $$source)) { - this["Name"] = ""; - } - if (!("Address" in $$source)) { - this["Address"] = null; - } - - Object.assign(this, $$source); - } - - /** - * Creates a new Person instance from a string or object. - */ - static createFrom($$source: any = {}): Person { - const $$createField1_0 = $$createType1; - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - if ("Address" in $$parsedSource) { - $$parsedSource["Address"] = $$createField1_0($$parsedSource["Address"]); - } - return new Person($$parsedSource as Partial); - } -} - -// Private type creation functions -const $$createType0 = services$0.Address.createFrom; -const $$createType1 = $Create.Nullable($$createType0); diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_other/services/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_other/services/index.ts deleted file mode 100644 index e4d86b717..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_other/services/index.ts +++ /dev/null @@ -1,11 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as OtherService from "./otherservice.js"; -export { - OtherService -}; - -export { - Address -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_other/services/models.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_other/services/models.ts deleted file mode 100644 index a4be6e904..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_other/services/models.ts +++ /dev/null @@ -1,35 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Create as $Create } from "/wails/runtime.js"; - -export class Address { - "Street": string; - "State": string; - "Country": string; - - /** Creates a new Address instance. */ - constructor($$source: Partial
                    = {}) { - if (!("Street" in $$source)) { - this["Street"] = ""; - } - if (!("State" in $$source)) { - this["State"] = ""; - } - if (!("Country" in $$source)) { - this["Country"] = ""; - } - - Object.assign(this, $$source); - } - - /** - * Creates a new Address instance from a string or object. - */ - static createFrom($$source: any = {}): Address { - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - return new Address($$parsedSource as Partial
                    ); - } -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_other/services/otherservice.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_other/services/otherservice.ts deleted file mode 100644 index fc2efb6c1..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_other/services/otherservice.ts +++ /dev/null @@ -1,29 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * OtherService is a struct - * that does things - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * Yay does this and that - */ -export function Yay(): $CancellablePromise<$models.Address | null> { - return $Call.ByName("github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_other/services.OtherService.Yay").then(($result: any) => { - return $$createType1($result); - }); -} - -// Private type creation functions -const $$createType0 = $models.Address.createFrom; -const $$createType1 = $Create.Nullable($$createType0); diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_non_pointer_single/greetservice.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_non_pointer_single/greetservice.ts deleted file mode 100644 index 579db20c8..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_non_pointer_single/greetservice.ts +++ /dev/null @@ -1,209 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -export function ArrayInt($in: number[]): $CancellablePromise { - return $Call.ByName("main.GreetService.ArrayInt", $in); -} - -export function BoolInBoolOut($in: boolean): $CancellablePromise { - return $Call.ByName("main.GreetService.BoolInBoolOut", $in); -} - -export function Float32InFloat32Out($in: number): $CancellablePromise { - return $Call.ByName("main.GreetService.Float32InFloat32Out", $in); -} - -export function Float64InFloat64Out($in: number): $CancellablePromise { - return $Call.ByName("main.GreetService.Float64InFloat64Out", $in); -} - -/** - * Greet someone - */ -export function Greet(name: string): $CancellablePromise { - return $Call.ByName("main.GreetService.Greet", name); -} - -export function Int16InIntOut($in: number): $CancellablePromise { - return $Call.ByName("main.GreetService.Int16InIntOut", $in); -} - -export function Int16PointerInAndOutput($in: number | null): $CancellablePromise { - return $Call.ByName("main.GreetService.Int16PointerInAndOutput", $in); -} - -export function Int32InIntOut($in: number): $CancellablePromise { - return $Call.ByName("main.GreetService.Int32InIntOut", $in); -} - -export function Int32PointerInAndOutput($in: number | null): $CancellablePromise { - return $Call.ByName("main.GreetService.Int32PointerInAndOutput", $in); -} - -export function Int64InIntOut($in: number): $CancellablePromise { - return $Call.ByName("main.GreetService.Int64InIntOut", $in); -} - -export function Int64PointerInAndOutput($in: number | null): $CancellablePromise { - return $Call.ByName("main.GreetService.Int64PointerInAndOutput", $in); -} - -export function Int8InIntOut($in: number): $CancellablePromise { - return $Call.ByName("main.GreetService.Int8InIntOut", $in); -} - -export function Int8PointerInAndOutput($in: number | null): $CancellablePromise { - return $Call.ByName("main.GreetService.Int8PointerInAndOutput", $in); -} - -export function IntInIntOut($in: number): $CancellablePromise { - return $Call.ByName("main.GreetService.IntInIntOut", $in); -} - -export function IntPointerInAndOutput($in: number | null): $CancellablePromise { - return $Call.ByName("main.GreetService.IntPointerInAndOutput", $in); -} - -export function IntPointerInputNamedOutputs($in: number | null): $CancellablePromise { - return $Call.ByName("main.GreetService.IntPointerInputNamedOutputs", $in); -} - -export function MapIntInt($in: { [_ in `${number}`]?: number }): $CancellablePromise { - return $Call.ByName("main.GreetService.MapIntInt", $in); -} - -export function MapIntIntPointer($in: { [_ in `${number}`]?: number | null }): $CancellablePromise { - return $Call.ByName("main.GreetService.MapIntIntPointer", $in); -} - -export function MapIntSliceInt($in: { [_ in `${number}`]?: number[] }): $CancellablePromise { - return $Call.ByName("main.GreetService.MapIntSliceInt", $in); -} - -export function MapIntSliceIntInMapIntSliceIntOut($in: { [_ in `${number}`]?: number[] }): $CancellablePromise<{ [_ in `${number}`]?: number[] }> { - return $Call.ByName("main.GreetService.MapIntSliceIntInMapIntSliceIntOut", $in).then(($result: any) => { - return $$createType1($result); - }); -} - -export function NoInputsStringOut(): $CancellablePromise { - return $Call.ByName("main.GreetService.NoInputsStringOut"); -} - -export function PointerBoolInBoolOut($in: boolean | null): $CancellablePromise { - return $Call.ByName("main.GreetService.PointerBoolInBoolOut", $in); -} - -export function PointerFloat32InFloat32Out($in: number | null): $CancellablePromise { - return $Call.ByName("main.GreetService.PointerFloat32InFloat32Out", $in); -} - -export function PointerFloat64InFloat64Out($in: number | null): $CancellablePromise { - return $Call.ByName("main.GreetService.PointerFloat64InFloat64Out", $in); -} - -export function PointerMapIntInt($in: { [_ in `${number}`]?: number } | null): $CancellablePromise { - return $Call.ByName("main.GreetService.PointerMapIntInt", $in); -} - -export function PointerStringInStringOut($in: string | null): $CancellablePromise { - return $Call.ByName("main.GreetService.PointerStringInStringOut", $in); -} - -export function StringArrayInputNamedOutput($in: string[]): $CancellablePromise { - return $Call.ByName("main.GreetService.StringArrayInputNamedOutput", $in).then(($result: any) => { - return $$createType2($result); - }); -} - -export function StringArrayInputNamedOutputs($in: string[]): $CancellablePromise { - return $Call.ByName("main.GreetService.StringArrayInputNamedOutputs", $in).then(($result: any) => { - return $$createType2($result); - }); -} - -export function StringArrayInputStringArrayOut($in: string[]): $CancellablePromise { - return $Call.ByName("main.GreetService.StringArrayInputStringArrayOut", $in).then(($result: any) => { - return $$createType2($result); - }); -} - -export function StringArrayInputStringOut($in: string[]): $CancellablePromise { - return $Call.ByName("main.GreetService.StringArrayInputStringOut", $in); -} - -export function StructInputStructOutput($in: $models.Person): $CancellablePromise<$models.Person> { - return $Call.ByName("main.GreetService.StructInputStructOutput", $in).then(($result: any) => { - return $$createType3($result); - }); -} - -export function StructPointerInputErrorOutput($in: $models.Person | null): $CancellablePromise { - return $Call.ByName("main.GreetService.StructPointerInputErrorOutput", $in); -} - -export function StructPointerInputStructPointerOutput($in: $models.Person | null): $CancellablePromise<$models.Person | null> { - return $Call.ByName("main.GreetService.StructPointerInputStructPointerOutput", $in).then(($result: any) => { - return $$createType4($result); - }); -} - -export function UInt16InUIntOut($in: number): $CancellablePromise { - return $Call.ByName("main.GreetService.UInt16InUIntOut", $in); -} - -export function UInt16PointerInAndOutput($in: number | null): $CancellablePromise { - return $Call.ByName("main.GreetService.UInt16PointerInAndOutput", $in); -} - -export function UInt32InUIntOut($in: number): $CancellablePromise { - return $Call.ByName("main.GreetService.UInt32InUIntOut", $in); -} - -export function UInt32PointerInAndOutput($in: number | null): $CancellablePromise { - return $Call.ByName("main.GreetService.UInt32PointerInAndOutput", $in); -} - -export function UInt64InUIntOut($in: number): $CancellablePromise { - return $Call.ByName("main.GreetService.UInt64InUIntOut", $in); -} - -export function UInt64PointerInAndOutput($in: number | null): $CancellablePromise { - return $Call.ByName("main.GreetService.UInt64PointerInAndOutput", $in); -} - -export function UInt8InUIntOut($in: number): $CancellablePromise { - return $Call.ByName("main.GreetService.UInt8InUIntOut", $in); -} - -export function UInt8PointerInAndOutput($in: number | null): $CancellablePromise { - return $Call.ByName("main.GreetService.UInt8PointerInAndOutput", $in); -} - -export function UIntInUIntOut($in: number): $CancellablePromise { - return $Call.ByName("main.GreetService.UIntInUIntOut", $in); -} - -export function UIntPointerInAndOutput($in: number | null): $CancellablePromise { - return $Call.ByName("main.GreetService.UIntPointerInAndOutput", $in); -} - -// Private type creation functions -const $$createType0 = $Create.Array($Create.Any); -const $$createType1 = $Create.Map($Create.Any, $$createType0); -const $$createType2 = $Create.Array($Create.Any); -const $$createType3 = $models.Person.createFrom; -const $$createType4 = $Create.Nullable($$createType3); diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_non_pointer_single/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_non_pointer_single/index.ts deleted file mode 100644 index f95c1b558..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_non_pointer_single/index.ts +++ /dev/null @@ -1,11 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; - -export { - Person -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_non_pointer_single/models.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_non_pointer_single/models.ts deleted file mode 100644 index cd282c90c..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_non_pointer_single/models.ts +++ /dev/null @@ -1,43 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Create as $Create } from "/wails/runtime.js"; - -export class Person { - "Name": string; - "Parent": Person | null; - "Details": {"Age": number, "Address": {"Street": string}}; - - /** Creates a new Person instance. */ - constructor($$source: Partial = {}) { - if (!("Name" in $$source)) { - this["Name"] = ""; - } - if (!("Parent" in $$source)) { - this["Parent"] = null; - } - if (!("Details" in $$source)) { - this["Details"] = {"Age": 0, "Address": {"Street": ""}}; - } - - Object.assign(this, $$source); - } - - /** - * Creates a new Person instance from a string or object. - */ - static createFrom($$source: any = {}): Person { - const $$createField1_0 = $$createType1; - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - if ("Parent" in $$parsedSource) { - $$parsedSource["Parent"] = $$createField1_0($$parsedSource["Parent"]); - } - return new Person($$parsedSource as Partial); - } -} - -// Private type creation functions -const $$createType0 = Person.createFrom; -const $$createType1 = $Create.Nullable($$createType0); diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_single/greetservice.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_single/greetservice.ts deleted file mode 100644 index 579db20c8..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_single/greetservice.ts +++ /dev/null @@ -1,209 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -export function ArrayInt($in: number[]): $CancellablePromise { - return $Call.ByName("main.GreetService.ArrayInt", $in); -} - -export function BoolInBoolOut($in: boolean): $CancellablePromise { - return $Call.ByName("main.GreetService.BoolInBoolOut", $in); -} - -export function Float32InFloat32Out($in: number): $CancellablePromise { - return $Call.ByName("main.GreetService.Float32InFloat32Out", $in); -} - -export function Float64InFloat64Out($in: number): $CancellablePromise { - return $Call.ByName("main.GreetService.Float64InFloat64Out", $in); -} - -/** - * Greet someone - */ -export function Greet(name: string): $CancellablePromise { - return $Call.ByName("main.GreetService.Greet", name); -} - -export function Int16InIntOut($in: number): $CancellablePromise { - return $Call.ByName("main.GreetService.Int16InIntOut", $in); -} - -export function Int16PointerInAndOutput($in: number | null): $CancellablePromise { - return $Call.ByName("main.GreetService.Int16PointerInAndOutput", $in); -} - -export function Int32InIntOut($in: number): $CancellablePromise { - return $Call.ByName("main.GreetService.Int32InIntOut", $in); -} - -export function Int32PointerInAndOutput($in: number | null): $CancellablePromise { - return $Call.ByName("main.GreetService.Int32PointerInAndOutput", $in); -} - -export function Int64InIntOut($in: number): $CancellablePromise { - return $Call.ByName("main.GreetService.Int64InIntOut", $in); -} - -export function Int64PointerInAndOutput($in: number | null): $CancellablePromise { - return $Call.ByName("main.GreetService.Int64PointerInAndOutput", $in); -} - -export function Int8InIntOut($in: number): $CancellablePromise { - return $Call.ByName("main.GreetService.Int8InIntOut", $in); -} - -export function Int8PointerInAndOutput($in: number | null): $CancellablePromise { - return $Call.ByName("main.GreetService.Int8PointerInAndOutput", $in); -} - -export function IntInIntOut($in: number): $CancellablePromise { - return $Call.ByName("main.GreetService.IntInIntOut", $in); -} - -export function IntPointerInAndOutput($in: number | null): $CancellablePromise { - return $Call.ByName("main.GreetService.IntPointerInAndOutput", $in); -} - -export function IntPointerInputNamedOutputs($in: number | null): $CancellablePromise { - return $Call.ByName("main.GreetService.IntPointerInputNamedOutputs", $in); -} - -export function MapIntInt($in: { [_ in `${number}`]?: number }): $CancellablePromise { - return $Call.ByName("main.GreetService.MapIntInt", $in); -} - -export function MapIntIntPointer($in: { [_ in `${number}`]?: number | null }): $CancellablePromise { - return $Call.ByName("main.GreetService.MapIntIntPointer", $in); -} - -export function MapIntSliceInt($in: { [_ in `${number}`]?: number[] }): $CancellablePromise { - return $Call.ByName("main.GreetService.MapIntSliceInt", $in); -} - -export function MapIntSliceIntInMapIntSliceIntOut($in: { [_ in `${number}`]?: number[] }): $CancellablePromise<{ [_ in `${number}`]?: number[] }> { - return $Call.ByName("main.GreetService.MapIntSliceIntInMapIntSliceIntOut", $in).then(($result: any) => { - return $$createType1($result); - }); -} - -export function NoInputsStringOut(): $CancellablePromise { - return $Call.ByName("main.GreetService.NoInputsStringOut"); -} - -export function PointerBoolInBoolOut($in: boolean | null): $CancellablePromise { - return $Call.ByName("main.GreetService.PointerBoolInBoolOut", $in); -} - -export function PointerFloat32InFloat32Out($in: number | null): $CancellablePromise { - return $Call.ByName("main.GreetService.PointerFloat32InFloat32Out", $in); -} - -export function PointerFloat64InFloat64Out($in: number | null): $CancellablePromise { - return $Call.ByName("main.GreetService.PointerFloat64InFloat64Out", $in); -} - -export function PointerMapIntInt($in: { [_ in `${number}`]?: number } | null): $CancellablePromise { - return $Call.ByName("main.GreetService.PointerMapIntInt", $in); -} - -export function PointerStringInStringOut($in: string | null): $CancellablePromise { - return $Call.ByName("main.GreetService.PointerStringInStringOut", $in); -} - -export function StringArrayInputNamedOutput($in: string[]): $CancellablePromise { - return $Call.ByName("main.GreetService.StringArrayInputNamedOutput", $in).then(($result: any) => { - return $$createType2($result); - }); -} - -export function StringArrayInputNamedOutputs($in: string[]): $CancellablePromise { - return $Call.ByName("main.GreetService.StringArrayInputNamedOutputs", $in).then(($result: any) => { - return $$createType2($result); - }); -} - -export function StringArrayInputStringArrayOut($in: string[]): $CancellablePromise { - return $Call.ByName("main.GreetService.StringArrayInputStringArrayOut", $in).then(($result: any) => { - return $$createType2($result); - }); -} - -export function StringArrayInputStringOut($in: string[]): $CancellablePromise { - return $Call.ByName("main.GreetService.StringArrayInputStringOut", $in); -} - -export function StructInputStructOutput($in: $models.Person): $CancellablePromise<$models.Person> { - return $Call.ByName("main.GreetService.StructInputStructOutput", $in).then(($result: any) => { - return $$createType3($result); - }); -} - -export function StructPointerInputErrorOutput($in: $models.Person | null): $CancellablePromise { - return $Call.ByName("main.GreetService.StructPointerInputErrorOutput", $in); -} - -export function StructPointerInputStructPointerOutput($in: $models.Person | null): $CancellablePromise<$models.Person | null> { - return $Call.ByName("main.GreetService.StructPointerInputStructPointerOutput", $in).then(($result: any) => { - return $$createType4($result); - }); -} - -export function UInt16InUIntOut($in: number): $CancellablePromise { - return $Call.ByName("main.GreetService.UInt16InUIntOut", $in); -} - -export function UInt16PointerInAndOutput($in: number | null): $CancellablePromise { - return $Call.ByName("main.GreetService.UInt16PointerInAndOutput", $in); -} - -export function UInt32InUIntOut($in: number): $CancellablePromise { - return $Call.ByName("main.GreetService.UInt32InUIntOut", $in); -} - -export function UInt32PointerInAndOutput($in: number | null): $CancellablePromise { - return $Call.ByName("main.GreetService.UInt32PointerInAndOutput", $in); -} - -export function UInt64InUIntOut($in: number): $CancellablePromise { - return $Call.ByName("main.GreetService.UInt64InUIntOut", $in); -} - -export function UInt64PointerInAndOutput($in: number | null): $CancellablePromise { - return $Call.ByName("main.GreetService.UInt64PointerInAndOutput", $in); -} - -export function UInt8InUIntOut($in: number): $CancellablePromise { - return $Call.ByName("main.GreetService.UInt8InUIntOut", $in); -} - -export function UInt8PointerInAndOutput($in: number | null): $CancellablePromise { - return $Call.ByName("main.GreetService.UInt8PointerInAndOutput", $in); -} - -export function UIntInUIntOut($in: number): $CancellablePromise { - return $Call.ByName("main.GreetService.UIntInUIntOut", $in); -} - -export function UIntPointerInAndOutput($in: number | null): $CancellablePromise { - return $Call.ByName("main.GreetService.UIntPointerInAndOutput", $in); -} - -// Private type creation functions -const $$createType0 = $Create.Array($Create.Any); -const $$createType1 = $Create.Map($Create.Any, $$createType0); -const $$createType2 = $Create.Array($Create.Any); -const $$createType3 = $models.Person.createFrom; -const $$createType4 = $Create.Nullable($$createType3); diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_single/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_single/index.ts deleted file mode 100644 index f95c1b558..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_single/index.ts +++ /dev/null @@ -1,11 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; - -export { - Person -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_single/models.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_single/models.ts deleted file mode 100644 index cd282c90c..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_single/models.ts +++ /dev/null @@ -1,43 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Create as $Create } from "/wails/runtime.js"; - -export class Person { - "Name": string; - "Parent": Person | null; - "Details": {"Age": number, "Address": {"Street": string}}; - - /** Creates a new Person instance. */ - constructor($$source: Partial = {}) { - if (!("Name" in $$source)) { - this["Name"] = ""; - } - if (!("Parent" in $$source)) { - this["Parent"] = null; - } - if (!("Details" in $$source)) { - this["Details"] = {"Age": 0, "Address": {"Street": ""}}; - } - - Object.assign(this, $$source); - } - - /** - * Creates a new Person instance from a string or object. - */ - static createFrom($$source: any = {}): Person { - const $$createField1_0 = $$createType1; - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - if ("Parent" in $$parsedSource) { - $$parsedSource["Parent"] = $$createField1_0($$parsedSource["Parent"]); - } - return new Person($$parsedSource as Partial); - } -} - -// Private type creation functions -const $$createType0 = Person.createFrom; -const $$createType1 = $Create.Nullable($$createType0); diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single/greetservice.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single/greetservice.ts deleted file mode 100644 index 6a6a881dc..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single/greetservice.ts +++ /dev/null @@ -1,18 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -/** - * Greet someone - */ -export function Greet(name: string): $CancellablePromise { - return $Call.ByName("main.GreetService.Greet", name); -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single/index.ts deleted file mode 100644 index 50e3f0435..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single/index.ts +++ /dev/null @@ -1,7 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_function/greetservice.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_function/greetservice.ts deleted file mode 100644 index 6a6a881dc..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_function/greetservice.ts +++ /dev/null @@ -1,18 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -/** - * Greet someone - */ -export function Greet(name: string): $CancellablePromise { - return $Call.ByName("main.GreetService.Greet", name); -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_function/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_function/index.ts deleted file mode 100644 index 50e3f0435..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_function/index.ts +++ /dev/null @@ -1,7 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_other_function/greetservice.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_other_function/greetservice.ts deleted file mode 100644 index 1a2ffb266..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_other_function/greetservice.ts +++ /dev/null @@ -1,35 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * Greet does XYZ - */ -export function Greet(name: string): $CancellablePromise { - return $Call.ByName("main.GreetService.Greet", name); -} - -/** - * NewPerson creates a new person - */ -export function NewPerson(name: string): $CancellablePromise<$models.Person | null> { - return $Call.ByName("main.GreetService.NewPerson", name).then(($result: any) => { - return $$createType1($result); - }); -} - -// Private type creation functions -const $$createType0 = $models.Person.createFrom; -const $$createType1 = $Create.Nullable($$createType0); diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_other_function/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_other_function/index.ts deleted file mode 100644 index f95c1b558..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_other_function/index.ts +++ /dev/null @@ -1,11 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; - -export { - Person -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_other_function/models.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_other_function/models.ts deleted file mode 100644 index f6eee9de8..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_other_function/models.ts +++ /dev/null @@ -1,47 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Create as $Create } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as services$0 from "./services/models.js"; - -/** - * Person is a person! - * They have a name and an address - */ -export class Person { - "Name": string; - "Address": services$0.Address | null; - - /** Creates a new Person instance. */ - constructor($$source: Partial = {}) { - if (!("Name" in $$source)) { - this["Name"] = ""; - } - if (!("Address" in $$source)) { - this["Address"] = null; - } - - Object.assign(this, $$source); - } - - /** - * Creates a new Person instance from a string or object. - */ - static createFrom($$source: any = {}): Person { - const $$createField1_0 = $$createType1; - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - if ("Address" in $$parsedSource) { - $$parsedSource["Address"] = $$createField1_0($$parsedSource["Address"]); - } - return new Person($$parsedSource as Partial); - } -} - -// Private type creation functions -const $$createType0 = services$0.Address.createFrom; -const $$createType1 = $Create.Nullable($$createType0); diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_other_function/services/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_other_function/services/index.ts deleted file mode 100644 index e4d86b717..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_other_function/services/index.ts +++ /dev/null @@ -1,11 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as OtherService from "./otherservice.js"; -export { - OtherService -}; - -export { - Address -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_other_function/services/models.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_other_function/services/models.ts deleted file mode 100644 index a4be6e904..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_other_function/services/models.ts +++ /dev/null @@ -1,35 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Create as $Create } from "/wails/runtime.js"; - -export class Address { - "Street": string; - "State": string; - "Country": string; - - /** Creates a new Address instance. */ - constructor($$source: Partial
                    = {}) { - if (!("Street" in $$source)) { - this["Street"] = ""; - } - if (!("State" in $$source)) { - this["State"] = ""; - } - if (!("Country" in $$source)) { - this["Country"] = ""; - } - - Object.assign(this, $$source); - } - - /** - * Creates a new Address instance from a string or object. - */ - static createFrom($$source: any = {}): Address { - let $$parsedSource = typeof $$source === 'string' ? JSON.parse($$source) : $$source; - return new Address($$parsedSource as Partial
                    ); - } -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_other_function/services/otherservice.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_other_function/services/otherservice.ts deleted file mode 100644 index 554897ea4..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_other_function/services/otherservice.ts +++ /dev/null @@ -1,29 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * OtherService is a struct - * that does things - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise, Create as $Create } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * Yay does this and that - */ -export function Yay(): $CancellablePromise<$models.Address | null> { - return $Call.ByName("github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_other_function/services.OtherService.Yay").then(($result: any) => { - return $$createType1($result); - }); -} - -// Private type creation functions -const $$createType0 = $models.Address.createFrom; -const $$createType1 = $Create.Nullable($$createType0); diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/warnings.log b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/warnings.log deleted file mode 100644 index ce8369307..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=false/UseNames=true/warnings.log +++ /dev/null @@ -1,83 +0,0 @@ -[warn] /testcases/complex_json/main.go:127:2: event 'collision' has one of multiple definitions here with data type map[string]int -[warn] /testcases/events_only/events.go:20:2: event 'collision' has one of multiple definitions here with data type int -[warn] /testcases/events_only/events.go:21:2: `application.RegisterEvent` called here with non-constant event name -[warn] /testcases/events_only/other.go:10:5: `application.RegisterEvent` is instantiated here but not called -[warn] /testcases/events_only/other.go:13:2: `application.RegisterEvent` called here with non-constant event name -[warn] /testcases/events_only/other.go:17:2: data type []T for event 'parametric' contains unresolved type parameters and will be ignored` -[warn] /testcases/events_only/other.go:22:2: event 'common:ApplicationStarted' is a known system event and cannot be overridden; this call to `application.RegisterEvent` will panic -[warn] /testcases/marshalers/main.go:212:2: event 'collision' has one of multiple definitions here with data type *struct{Field []bool} -[warn] /testcases/marshalers/main.go:214:2: data type encoding/json.Marshaler for event 'interface' is a non-empty interface: emitting events from the frontend with data other than `null` is not supported by encoding/json and will likely result in runtime errors -[warn] dynamically registered event names are not discoverable by the binding generator: it is recommended to invoke `application.RegisterEvent` with constant arguments only -[warn] event 'collision' has multiple conflicting definitions and will be ignored -[warn] events registered through indirect calls are not discoverable by the binding generator: it is recommended to invoke `application.RegisterEvent` directly -[warn] generic wrappers for calls to `application.RegisterEvent` are not analysable by the binding generator: it is recommended to call `application.RegisterEvent` with concrete types only -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *R is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *S is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *T is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *U is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *V is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *X is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *Y is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *Z is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *any is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *complex64 is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *encoding.TextMarshaler is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *float32 is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.CustomInterface is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.EmbeddedInterface is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.InterfaceAlias is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.InterfacePtrAlias is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.InterfacePtrType is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.InterfaceType is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.NonTextMarshaler is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.PointerPtrAlias is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.PointerPtrType is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.PointerType is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.ValuePtrAlias is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.ValuePtrType is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.ValueType is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *int is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *string is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *uint is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type R is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type T is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type W is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type any is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type bool is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type complex64 is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type float32 is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.BadTildeCstrAlias[T] is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.BadTildeCstrAlias[struct{}] is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.BadTildeCstrPtrAlias[T] is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.BadTildeCstrPtrAlias[struct{}] is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.BasicCstrPtrAlias[S] is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.BasicCstrPtrAlias[int] is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.ComparableCstrAlias[R] is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.ComparableCstrAlias[github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.PointerTextMarshaler] is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.ComparableCstrPtrAlias[R] is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.ComparableCstrPtrAlias[int] is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.EmbeddedPointer is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.GoodTildeCstrPtrAlias[U] is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.InterfaceCstrPtrAlias[*github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.PointerTextMarshaler] is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.InterfaceCstrPtrAlias[Y] is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.InterfaceCstrPtrAlias[encoding.TextMarshaler] is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.InterfacePtrAlias is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.InterfacePtrType is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.MixedCstrPtrAlias[X] is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.MixedCstrPtrAlias[github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.StringType] is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.NonBasicCstrPtrAlias[*github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.PointerTextMarshaler] is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.NonBasicCstrPtrAlias[V] is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.NonTextMarshaler is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.PointableCstrAlias[W] is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.PointableCstrAlias[github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.PointerTextMarshaler] is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.PointerAlias is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.PointerCstrPtrAlias[R, Z] is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.PointerCstrPtrAlias[github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.PointerTextMarshaler, *github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.PointerTextMarshaler] is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.PointerCstrPtrAlias[github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.ValueTextMarshaler, *github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.ValueTextMarshaler] is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.PointerPtrType is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.PointerTextMarshaler is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.PointerType is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.ValuePtrType is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.ValueType is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.WrongAlias is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.WrongType is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/encoding/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/encoding/index.ts deleted file mode 100644 index ba2885969..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/encoding/index.ts +++ /dev/null @@ -1,6 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -export type { - TextMarshaler -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/encoding/json/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/encoding/json/index.ts deleted file mode 100644 index 00ec01151..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/encoding/json/index.ts +++ /dev/null @@ -1,6 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -export type { - Marshaler -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/encoding/json/models.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/encoding/json/models.ts deleted file mode 100644 index 8e7f0b3f1..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/encoding/json/models.ts +++ /dev/null @@ -1,8 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * Marshaler is the interface implemented by types that - * can marshal themselves into valid JSON. - */ -export type Marshaler = any; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/encoding/models.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/encoding/models.ts deleted file mode 100644 index 51089b14d..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/encoding/models.ts +++ /dev/null @@ -1,10 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * TextMarshaler is the interface implemented by an object that can - * marshal itself into a textual form. - * - * MarshalText encodes the receiver into UTF-8-encoded text and returns the result. - */ -export type TextMarshaler = any; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/eventcreate.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/eventcreate.ts deleted file mode 100644 index 71a208a3d..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/eventcreate.ts +++ /dev/null @@ -1,9 +0,0 @@ -//@ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Create as $Create } from "/wails/runtime.js"; - -Object.freeze($Create.Events); diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/eventdata.d.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/eventdata.d.ts deleted file mode 100644 index be1730836..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/eventdata.d.ts +++ /dev/null @@ -1,30 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import type { Events } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import type * as json$0 from "../../../../../encoding/json/models.js"; -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import type * as events_only$0 from "./generator/testcases/events_only/models.js"; -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import type * as more$0 from "./generator/testcases/no_bindings_here/more/models.js"; - -declare module "/wails/runtime.js" { - namespace Events { - interface CustomEvents { - "events_only:class": events_only$0.SomeClass; - "events_only:map": { [_ in string]?: number[] | null } | null; - "events_only:nodata": void; - "events_only:other": more$0.StringPtr[] | null; - "events_only:string": string; - "interface": json$0.Marshaler; - "overlap": {"Field": boolean[] | null} | null; - } - } -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/aliases/greetservice.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/aliases/greetservice.ts deleted file mode 100644 index 82fd04182..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/aliases/greetservice.ts +++ /dev/null @@ -1,59 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as nobindingshere$0 from "../no_bindings_here/models.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * Get someone. - */ -export function Get(aliasValue: $models.Alias): $CancellablePromise<$models.Person> { - return $Call.ByID(1928502664, aliasValue); -} - -/** - * Apparently, aliases are all the rage right now. - */ -export function GetButAliased(p: $models.AliasedPerson): $CancellablePromise<$models.StrangelyAliasedPerson> { - return $Call.ByID(1896499664, p); -} - -/** - * Get someone quite different. - */ -export function GetButDifferent(): $CancellablePromise<$models.GenericPerson> { - return $Call.ByID(2240931744); -} - -export function GetButForeignPrivateAlias(): $CancellablePromise { - return $Call.ByID(643456960); -} - -export function GetButGenericAliases(): $CancellablePromise<$models.AliasGroup> { - return $Call.ByID(914093800); -} - -export function GetButSubPackageAlias(): $CancellablePromise<$models.SubPackageAlias> { - return $Call.ByID(1443276371); -} - -/** - * Greet a lot of unusual things. - */ -export function Greet($0: $models.EmptyAliasStruct, $1: $models.EmptyStruct): $CancellablePromise<$models.AliasStruct> { - return $Call.ByID(1411160069, $0, $1); -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/aliases/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/aliases/index.ts deleted file mode 100644 index fe7bfae7b..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/aliases/index.ts +++ /dev/null @@ -1,27 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; - -export type { - Alias, - AliasGroup, - AliasStruct, - AliasedPerson, - EmptyAliasStruct, - EmptyStruct, - GenericAlias, - GenericMapAlias, - GenericPerson, - GenericPersonAlias, - GenericPtrAlias, - IndirectPersonAlias, - OtherAliasStruct, - Person, - StrangelyAliasedPerson, - SubPackageAlias, - TPIndirectPersonAlias -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/aliases/models.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/aliases/models.ts deleted file mode 100644 index 32e6d64cb..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/aliases/models.ts +++ /dev/null @@ -1,135 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as subpkg$0 from "./subpkg/models.js"; - -/** - * A nice type Alias. - */ -export type Alias = number; - -/** - * A class whose fields have various aliased types. - */ -export interface AliasGroup { - "GAi": GenericAlias; - "GAP": GenericAlias>; - "GPAs": GenericPtrAlias; - "GPAP": GenericPtrAlias>; - "GMA": GenericMapAlias; - "GPA": GenericPersonAlias; - "IPA": IndirectPersonAlias; - "TPIPA": TPIndirectPersonAlias; - "SPA": SubPackageAlias; -} - -/** - * A struct alias. - * This should be rendered as a typedef or interface in every mode. - */ -export interface AliasStruct { - /** - * A field with a comment. - */ - "Foo": number[] | null; - - /** - * Definitely not Foo. - */ - "Bar"?: string; - "Baz"?: string; - - /** - * A nested alias struct. - */ - "Other": OtherAliasStruct; -} - -/** - * A class alias. - */ -export type AliasedPerson = Person; - -/** - * An empty struct alias. - */ -export interface EmptyAliasStruct { -} - -/** - * An empty struct. - */ -export interface EmptyStruct { -} - -/** - * A generic alias that forwards to a type parameter. - */ -export type GenericAlias = T; - -/** - * A generic alias that wraps a map. - */ -export type GenericMapAlias = { [_ in string]?: U } | null; - -/** - * A generic struct containing an alias. - */ -export interface GenericPerson { - "Name": T; - "AliasedField": Alias; -} - -/** - * A generic alias that wraps a generic struct. - */ -export type GenericPersonAlias = GenericPerson[] | null>; - -/** - * A generic alias that wraps a pointer type. - */ -export type GenericPtrAlias = GenericAlias | null; - -/** - * An alias that wraps a class through a non-typeparam alias. - */ -export type IndirectPersonAlias = GenericPersonAlias; - -/** - * Another struct alias. - */ -export interface OtherAliasStruct { - "NoMoreIdeas": number[] | null; -} - -/** - * A non-generic struct containing an alias. - */ -export interface Person { - /** - * The Person's name. - */ - "Name": string; - - /** - * A random alias field. - */ - "AliasedField": Alias; -} - -/** - * Another class alias, but ordered after its aliased class. - */ -export type StrangelyAliasedPerson = Person; - -/** - * An alias referencing another package that is not used elsewhere. - */ -export type SubPackageAlias = subpkg$0.SubStruct; - -/** - * An alias that wraps a class through a typeparam alias. - */ -export type TPIndirectPersonAlias = GenericAlias>; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/aliases/subpkg/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/aliases/subpkg/index.ts deleted file mode 100644 index 842f00546..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/aliases/subpkg/index.ts +++ /dev/null @@ -1,6 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -export type { - SubStruct -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/aliases/subpkg/models.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/aliases/subpkg/models.ts deleted file mode 100644 index 729b548db..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/aliases/subpkg/models.ts +++ /dev/null @@ -1,9 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * SubStruct is a type in a subpackage that is only referenced through an alias. - */ -export interface SubStruct { - "SomeField": string[] | null; -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_expressions/config/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_expressions/config/index.ts deleted file mode 100644 index bdcf43c67..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_expressions/config/index.ts +++ /dev/null @@ -1,9 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as Service7 from "./service7.js"; -import * as Service9 from "./service9.js"; -export { - Service7, - Service9 -}; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_expressions/config/service7.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_expressions/config/service7.ts deleted file mode 100644 index 5cba569c9..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_expressions/config/service7.ts +++ /dev/null @@ -1,10 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -export function TestMethod(): $CancellablePromise { - return $Call.ByID(2241101727); -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_expressions/config/service9.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_expressions/config/service9.ts deleted file mode 100644 index dc425cfd5..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_expressions/config/service9.ts +++ /dev/null @@ -1,10 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -export function TestMethod2(): $CancellablePromise { - return $Call.ByID(1556848345); -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_json/greetservice.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_json/greetservice.ts deleted file mode 100644 index a5334fce3..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_json/greetservice.ts +++ /dev/null @@ -1,22 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * Greet does XYZ - */ -export function Greet(person: $models.Person, emb: $models.Embedded1): $CancellablePromise { - return $Call.ByID(1411160069, person, emb); -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_json/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_json/index.ts deleted file mode 100644 index f645e5730..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_json/index.ts +++ /dev/null @@ -1,17 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; - -export { - Title -} from "./models.js"; - -export type { - Embedded1, - Embedded3, - Person -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_json/models.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_json/models.ts deleted file mode 100644 index 7cdb88164..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_json/models.ts +++ /dev/null @@ -1,121 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -export interface Embedded1 { - /** - * Friends should be shadowed in Person by a field of lesser depth - */ - "Friends": number; - - /** - * Vanish should be omitted from Person because there is another field with same depth and no tag - */ - "Vanish": number; - - /** - * StillThere should be shadowed in Person by other field with same depth and a json tag - */ - "StillThere": string; - - /** - * NamingThingsIsHard is a law of programming - */ - "NamingThingsIsHard": `${boolean}`; -} - -export type Embedded3 = string; - -/** - * Person represents a person - */ -export interface Person { - /** - * Titles is optional in JSON - */ - "Titles"?: Title[] | null; - - /** - * Names has a - * multiline comment - */ - "Names": string[] | null; - - /** - * Partner has a custom and complex JSON key - */ - "Partner": Person | null; - "Friends": (Person | null)[] | null; - - /** - * NamingThingsIsHard is a law of programming - */ - "NamingThingsIsHard": `${boolean}`; - - /** - * StillThereButRenamed should shadow in Person the other field with same depth and no json tag - */ - "StillThere": Embedded3 | null; - - /** - * StrangeNumber maps to "-" - */ - "-": number; - - /** - * Embedded3 should appear with key "Embedded3" - */ - "Embedded3": Embedded3; - - /** - * StrangerNumber is serialized as a string - */ - "StrangerNumber": `${number}`; - - /** - * StrangestString is optional and serialized as a JSON string - */ - "StrangestString"?: `"${string}"`; - - /** - * StringStrangest is serialized as a JSON string and optional - */ - "StringStrangest"?: `"${string}"`; - - /** - * embedded4 should be optional and appear with key "emb4" - */ - "emb4"?: embedded4; -} - -/** - * Title is a title - */ -export enum Title { - /** - * The Go zero value for the underlying type of the enum. - */ - $zero = "", - - /** - * Mister is a title - */ - Mister = "Mr", - Miss = "Miss", - Ms = "Ms", - Mrs = "Mrs", - Dr = "Dr", -}; - -export interface embedded4 { - /** - * NamingThingsIsHard is a law of programming - */ - "NamingThingsIsHard": `${boolean}`; - - /** - * Friends should not be shadowed in Person as embedded4 is not embedded - * from encoding/json's point of view; - * however, it should be shadowed in Embedded1 - */ - "Friends": boolean; -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_method/greetservice.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_method/greetservice.ts deleted file mode 100644 index 069794a5b..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_method/greetservice.ts +++ /dev/null @@ -1,24 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * Greet does XYZ - * It has a multiline doc comment - * The comment has even some * / traps!! - */ -export function Greet(str: string, people: $models.Person[] | null, $2: {"AnotherCount": number, "AnotherOne": $models.Person | null}, assoc: { [_ in `${number}`]?: boolean | null } | null, $4: (number | null)[] | null, ...other: string[]): $CancellablePromise<[$models.Person, any, number[] | null]> { - return $Call.ByID(1411160069, str, people, $2, assoc, $4, other); -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_method/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_method/index.ts deleted file mode 100644 index 14252454b..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_method/index.ts +++ /dev/null @@ -1,11 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; - -export type { - Person -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_method/models.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_method/models.ts deleted file mode 100644 index 6691fb86c..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_method/models.ts +++ /dev/null @@ -1,9 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * Person represents a person - */ -export interface Person { - "Name": string; -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/cyclic_imports/greetservice.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/cyclic_imports/greetservice.ts deleted file mode 100644 index e6a04adf3..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/cyclic_imports/greetservice.ts +++ /dev/null @@ -1,22 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * Make a cycle. - */ -export function MakeCycles(): $CancellablePromise<[$models.StructA, $models.StructC]> { - return $Call.ByID(440020721); -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/cyclic_imports/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/cyclic_imports/index.ts deleted file mode 100644 index bbf592890..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/cyclic_imports/index.ts +++ /dev/null @@ -1,13 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; - -export type { - StructA, - StructC, - StructE -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/cyclic_imports/models.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/cyclic_imports/models.ts deleted file mode 100644 index 256987ac8..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/cyclic_imports/models.ts +++ /dev/null @@ -1,21 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -export interface StructA { - "B": structB | null; -} - -export interface StructC { - "D": structD; -} - -export interface StructE { -} - -export interface structB { - "A": StructA | null; -} - -export interface structD { - "E": StructE; -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/cyclic_types/greetservice.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/cyclic_types/greetservice.ts deleted file mode 100644 index 965a057ca..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/cyclic_types/greetservice.ts +++ /dev/null @@ -1,22 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * Make a cycle. - */ -export function MakeCycles(): $CancellablePromise<[$models.Cyclic, $models.GenericCyclic<$models.GenericCyclic>]> { - return $Call.ByID(440020721); -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/cyclic_types/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/cyclic_types/index.ts deleted file mode 100644 index 16cef660c..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/cyclic_types/index.ts +++ /dev/null @@ -1,13 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; - -export type { - Alias, - Cyclic, - GenericCyclic -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/cyclic_types/models.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/cyclic_types/models.ts deleted file mode 100644 index 56d3f00ec..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/cyclic_types/models.ts +++ /dev/null @@ -1,8 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -export type Alias = Cyclic | null; - -export type Cyclic = ({ [_ in string]?: Alias } | null)[] | null; - -export type GenericCyclic = {"X": GenericCyclic | null, "Y": T[] | null}[] | null; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/index.ts deleted file mode 100644 index bb2426022..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/index.ts +++ /dev/null @@ -1,13 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as Service from "./service.js"; -export { - Service -}; - -console.log("Hello everywhere!"); -console.log("Hello everywhere again!"); -console.log("Hello Interfaces!"); -console.log("Hello TS!"); -console.log("Hello TS Interfaces!"); diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/internalservice.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/internalservice.ts deleted file mode 100644 index 9d2a673d6..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/internalservice.ts +++ /dev/null @@ -1,19 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * An exported but internal service. - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -export function Method($0: $models.InternalModel): $CancellablePromise { - return $Call.ByID(538079117, $0); -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/models.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/models.ts deleted file mode 100644 index efe76e58b..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/models.ts +++ /dev/null @@ -1,16 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * An exported but internal model. - */ -export interface InternalModel { - "Field": string; -} - -/** - * An unexported model. - */ -export interface unexportedModel { - "Field": string; -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/otherpackage/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/otherpackage/index.ts deleted file mode 100644 index 82d89784a..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/otherpackage/index.ts +++ /dev/null @@ -1,6 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -export type { - Dummy -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/otherpackage/models.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/otherpackage/models.ts deleted file mode 100644 index 71070d754..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/otherpackage/models.ts +++ /dev/null @@ -1,5 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -export interface Dummy { -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/service.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/service.ts deleted file mode 100644 index e60cbea0c..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/service.ts +++ /dev/null @@ -1,22 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as otherpackage$0 from "./otherpackage/models.js"; - -function InternalMethod($0: string): $CancellablePromise { - return $Call.ByID(3518775569, $0); -} - -export function VisibleMethod($0: otherpackage$0.Dummy): $CancellablePromise { - return $Call.ByID(474018228, $0); -} - -export async function CustomMethod(arg: string): Promise { - await InternalMethod("Hello " + arg + "!"); -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/test.js b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/test.js deleted file mode 100644 index 138385f53..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/test.js +++ /dev/null @@ -1,3 +0,0 @@ -import { CustomMethod } from "./service.js"; - -CustomMethod("everywhere"); diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/test_all.js b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/test_all.js deleted file mode 100644 index 19d5c2f42..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/test_all.js +++ /dev/null @@ -1,3 +0,0 @@ -import { CustomMethod } from "./service.js"; - -CustomMethod("everywhere again"); diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/test_i.js b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/test_i.js deleted file mode 100644 index 442f20472..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/test_i.js +++ /dev/null @@ -1,3 +0,0 @@ -import { CustomMethod } from "./service.js"; - -CustomMethod("Interfaces"); diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/test_t.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/test_t.ts deleted file mode 100644 index 253d3f2f6..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/test_t.ts +++ /dev/null @@ -1,3 +0,0 @@ -import { CustomMethod } from "./service.js"; - -CustomMethod("TS"); diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/test_ti.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/test_ti.ts deleted file mode 100644 index 7400e97aa..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/test_ti.ts +++ /dev/null @@ -1,3 +0,0 @@ -import { CustomMethod } from "./service.js"; - -CustomMethod("TS Interfaces"); diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/unexportedservice.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/unexportedservice.ts deleted file mode 100644 index 57d7f73be..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/unexportedservice.ts +++ /dev/null @@ -1,19 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * An unexported service. - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -export function Method($0: $models.unexportedModel): $CancellablePromise { - return $Call.ByID(37626172, $0); -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/embedded_interface/greetservice.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/embedded_interface/greetservice.ts deleted file mode 100644 index 5a3127774..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/embedded_interface/greetservice.ts +++ /dev/null @@ -1,47 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -/** - * Comment 1. - */ -export function Method1(): $CancellablePromise { - return $Call.ByID(841558284); -} - -/** - * Comment 2. - */ -export function Method2(): $CancellablePromise { - return $Call.ByID(891891141); -} - -/** - * Comment 3a. - * Comment 3b. - */ -export function Method3(): $CancellablePromise { - return $Call.ByID(875113522); -} - -/** - * Comment 4. - */ -export function Method4(): $CancellablePromise { - return $Call.ByID(791225427); -} - -/** - * Comment 5. - */ -export function Method5(): $CancellablePromise { - return $Call.ByID(774447808); -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/embedded_interface/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/embedded_interface/index.ts deleted file mode 100644 index 50e3f0435..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/embedded_interface/index.ts +++ /dev/null @@ -1,7 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/enum/greetservice.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/enum/greetservice.ts deleted file mode 100644 index eda1dd8d0..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/enum/greetservice.ts +++ /dev/null @@ -1,29 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * Greet does XYZ - */ -export function Greet(name: string, title: $models.Title): $CancellablePromise { - return $Call.ByID(1411160069, name, title); -} - -/** - * NewPerson creates a new person - */ -export function NewPerson(name: string): $CancellablePromise<$models.Person | null> { - return $Call.ByID(1661412647, name); -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/enum/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/enum/index.ts deleted file mode 100644 index e66941c16..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/enum/index.ts +++ /dev/null @@ -1,16 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; - -export { - Age, - Title -} from "./models.js"; - -export type { - Person -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/enum/models.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/enum/models.ts deleted file mode 100644 index 74d673e16..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/enum/models.ts +++ /dev/null @@ -1,55 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * Age is an integer with some predefined values - */ -export type Age = number; - -/** - * Predefined constants for type Age. - * @namespace - */ -export const Age = { - NewBorn: 0, - Teenager: 12, - YoungAdult: 18, - - /** - * Oh no, some grey hair! - */ - MiddleAged: 50, - - /** - * Unbelievable! - */ - Mathusalem: 1000, -}; - -/** - * Person represents a person - */ -export interface Person { - "Title": Title; - "Name": string; - "Age": Age; -} - -/** - * Title is a title - */ -export enum Title { - /** - * The Go zero value for the underlying type of the enum. - */ - $zero = "", - - /** - * Mister is a title - */ - Mister = "Mr", - Miss = "Miss", - Ms = "Ms", - Mrs = "Mrs", - Dr = "Dr", -}; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_from_imported_package/greetservice.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_from_imported_package/greetservice.ts deleted file mode 100644 index ade2383a0..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_from_imported_package/greetservice.ts +++ /dev/null @@ -1,22 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as services$0 from "./services/models.js"; - -/** - * Greet does XYZ - */ -export function Greet(name: string, title: services$0.Title): $CancellablePromise { - return $Call.ByID(1411160069, name, title); -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_from_imported_package/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_from_imported_package/index.ts deleted file mode 100644 index 50e3f0435..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_from_imported_package/index.ts +++ /dev/null @@ -1,7 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_from_imported_package/services/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_from_imported_package/services/index.ts deleted file mode 100644 index 01c612edc..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_from_imported_package/services/index.ts +++ /dev/null @@ -1,6 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -export { - Title -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_from_imported_package/services/models.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_from_imported_package/services/models.ts deleted file mode 100644 index 887aee9ba..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_from_imported_package/services/models.ts +++ /dev/null @@ -1,18 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -export enum Title { - /** - * The Go zero value for the underlying type of the enum. - */ - $zero = "", - - /** - * Mister is a title - */ - Mister = "Mr", - Miss = "Miss", - Ms = "Ms", - Mrs = "Mrs", - Dr = "Dr", -}; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_map_keys/enummapservice.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_map_keys/enummapservice.ts deleted file mode 100644 index 9c4eff47a..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_map_keys/enummapservice.ts +++ /dev/null @@ -1,57 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * EnumMapService tests various enum map key scenarios - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * GetColorCodes returns a map with uint8 enum keys - */ -export function GetColorCodes(): $CancellablePromise<{ [_ in $models.Color]?: string } | null> { - return $Call.ByID(2794981443); -} - -/** - * GetNestedEnumMap returns a map with enum keys and complex values - */ -export function GetNestedEnumMap(): $CancellablePromise<{ [_ in $models.Status]?: { [_ in $models.Priority]?: string } | null } | null> { - return $Call.ByID(3603489560); -} - -/** - * GetOptionalEnumMap returns a map with enum keys to optional values - */ -export function GetOptionalEnumMap(): $CancellablePromise<{ [_ in $models.Status]?: string | null } | null> { - return $Call.ByID(1871606385); -} - -/** - * GetPersonsByStatus returns a map with enum keys to struct values - */ -export function GetPersonsByStatus(): $CancellablePromise<{ [_ in $models.Status]?: $models.Person[] | null } | null> { - return $Call.ByID(2189502217); -} - -/** - * GetPriorityWeights returns a map with integer enum keys - */ -export function GetPriorityWeights(): $CancellablePromise<{ [_ in $models.Priority]?: number } | null> { - return $Call.ByID(1542216941); -} - -/** - * GetStatusMessages returns a map with string enum keys - */ -export function GetStatusMessages(): $CancellablePromise<{ [_ in $models.Status]?: string } | null> { - return $Call.ByID(1788640810); -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_map_keys/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_map_keys/index.ts deleted file mode 100644 index cf39671cf..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_map_keys/index.ts +++ /dev/null @@ -1,17 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as EnumMapService from "./enummapservice.js"; -export { - EnumMapService -}; - -export { - Color, - Priority, - Status -} from "./models.js"; - -export type { - Person -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_map_keys/models.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_map_keys/models.ts deleted file mode 100644 index a2fe209a5..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_map_keys/models.ts +++ /dev/null @@ -1,53 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * Color represents color values - */ -export enum Color { - /** - * The Go zero value for the underlying type of the enum. - */ - $zero = 0, - - Red = 1, - Green = 2, - Blue = 3, -}; - -/** - * Person represents a person with status - */ -export interface Person { - "Name": string; - "Status": Status; -} - -/** - * Priority represents priority levels - */ -export enum Priority { - /** - * The Go zero value for the underlying type of the enum. - */ - $zero = 0, - - PriorityLow = 1, - PriorityMedium = 2, - PriorityHigh = 3, -}; - -/** - * Status represents different status values - */ -export enum Status { - /** - * The Go zero value for the underlying type of the enum. - */ - $zero = "", - - StatusPending = "pending", - StatusRunning = "running", - StatusCompleted = "completed", - StatusFailed = "failed", -}; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/events_only/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/events_only/index.ts deleted file mode 100644 index 03b13d1cf..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/events_only/index.ts +++ /dev/null @@ -1,6 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -export type { - SomeClass -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/events_only/models.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/events_only/models.ts deleted file mode 100644 index 316f1bd22..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/events_only/models.ts +++ /dev/null @@ -1,14 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as nobindingshere$0 from "../no_bindings_here/models.js"; - -/** - * SomeClass renders as a TS class. - */ -export interface SomeClass { - "Field": string; - "Meadow": nobindingshere$0.HowDifferent; -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_imported_package/greetservice.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_imported_package/greetservice.ts deleted file mode 100644 index 8519667d5..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_imported_package/greetservice.ts +++ /dev/null @@ -1,29 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * Greet does XYZ - */ -export function Greet(name: string): $CancellablePromise { - return $Call.ByID(1411160069, name); -} - -/** - * NewPerson creates a new person - */ -export function NewPerson(name: string): $CancellablePromise<$models.Person | null> { - return $Call.ByID(1661412647, name); -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_imported_package/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_imported_package/index.ts deleted file mode 100644 index 14252454b..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_imported_package/index.ts +++ /dev/null @@ -1,11 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; - -export type { - Person -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_imported_package/models.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_imported_package/models.ts deleted file mode 100644 index 99b989f07..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_imported_package/models.ts +++ /dev/null @@ -1,14 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as services$0 from "./services/models.js"; - -/** - * Person is a person - */ -export interface Person { - "Name": string; - "Address": services$0.Address | null; -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_imported_package/services/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_imported_package/services/index.ts deleted file mode 100644 index 8857d2bc5..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_imported_package/services/index.ts +++ /dev/null @@ -1,11 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as OtherService from "./otherservice.js"; -export { - OtherService -}; - -export type { - Address -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_imported_package/services/models.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_imported_package/services/models.ts deleted file mode 100644 index b76080cf3..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_imported_package/services/models.ts +++ /dev/null @@ -1,8 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -export interface Address { - "Street": string; - "State": string; - "Country": string; -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_imported_package/services/otherservice.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_imported_package/services/otherservice.ts deleted file mode 100644 index 4cb206cc6..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_imported_package/services/otherservice.ts +++ /dev/null @@ -1,23 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * OtherService is a struct - * that does things - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * Yay does this and that - */ -export function Yay(): $CancellablePromise<$models.Address | null> { - return $Call.ByID(2007737399); -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_nested_imported_package/greetservice.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_nested_imported_package/greetservice.ts deleted file mode 100644 index 8519667d5..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_nested_imported_package/greetservice.ts +++ /dev/null @@ -1,29 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * Greet does XYZ - */ -export function Greet(name: string): $CancellablePromise { - return $Call.ByID(1411160069, name); -} - -/** - * NewPerson creates a new person - */ -export function NewPerson(name: string): $CancellablePromise<$models.Person | null> { - return $Call.ByID(1661412647, name); -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_nested_imported_package/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_nested_imported_package/index.ts deleted file mode 100644 index 14252454b..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_nested_imported_package/index.ts +++ /dev/null @@ -1,11 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; - -export type { - Person -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_nested_imported_package/models.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_nested_imported_package/models.ts deleted file mode 100644 index 70b85519b..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_nested_imported_package/models.ts +++ /dev/null @@ -1,11 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as other$0 from "./services/other/models.js"; - -export interface Person { - "Name": string; - "Address": other$0.Address | null; -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_nested_imported_package/services/other/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_nested_imported_package/services/other/index.ts deleted file mode 100644 index 8857d2bc5..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_nested_imported_package/services/other/index.ts +++ /dev/null @@ -1,11 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as OtherService from "./otherservice.js"; -export { - OtherService -}; - -export type { - Address -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_nested_imported_package/services/other/models.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_nested_imported_package/services/other/models.ts deleted file mode 100644 index b76080cf3..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_nested_imported_package/services/other/models.ts +++ /dev/null @@ -1,8 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -export interface Address { - "Street": string; - "State": string; - "Country": string; -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_nested_imported_package/services/other/otherservice.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_nested_imported_package/services/other/otherservice.ts deleted file mode 100644 index 8879fcfa2..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_nested_imported_package/services/other/otherservice.ts +++ /dev/null @@ -1,23 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * OtherService is a struct - * that does things - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * Yay does this and that - */ -export function Yay(): $CancellablePromise<$models.Address | null> { - return $Call.ByID(2447353446); -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_multiple_files/greetservice.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_multiple_files/greetservice.ts deleted file mode 100644 index 34c4d151a..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_multiple_files/greetservice.ts +++ /dev/null @@ -1,10 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -export function Greet(name: string): $CancellablePromise { - return $Call.ByID(1411160069, name); -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_multiple_files/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_multiple_files/index.ts deleted file mode 100644 index 50e3f0435..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_multiple_files/index.ts +++ /dev/null @@ -1,7 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single/greetservice.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single/greetservice.ts deleted file mode 100644 index 8a2cb7a70..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single/greetservice.ts +++ /dev/null @@ -1,18 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -/** - * Greet someone - */ -export function Greet(name: string): $CancellablePromise { - return $Call.ByID(1411160069, name); -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single/index.ts deleted file mode 100644 index 50e3f0435..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single/index.ts +++ /dev/null @@ -1,7 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single_context/greetservice.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single_context/greetservice.ts deleted file mode 100644 index f9b8d87e2..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single_context/greetservice.ts +++ /dev/null @@ -1,25 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -/** - * Greet someone - */ -export function Greet(name: string): $CancellablePromise { - return $Call.ByID(1411160069, name); -} - -/** - * Greet someone - */ -export function GreetWithContext(name: string): $CancellablePromise { - return $Call.ByID(1310150960, name); -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single_context/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single_context/index.ts deleted file mode 100644 index 50e3f0435..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single_context/index.ts +++ /dev/null @@ -1,7 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single_internal/greetservice.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single_internal/greetservice.ts deleted file mode 100644 index 8a2cb7a70..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single_internal/greetservice.ts +++ /dev/null @@ -1,18 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -/** - * Greet someone - */ -export function Greet(name: string): $CancellablePromise { - return $Call.ByID(1411160069, name); -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single_internal/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single_internal/index.ts deleted file mode 100644 index 50e3f0435..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single_internal/index.ts +++ /dev/null @@ -1,7 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys/index.ts deleted file mode 100644 index de52fd90d..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys/index.ts +++ /dev/null @@ -1,32 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as Service from "./service.js"; -export { - Service -}; - -export type { - BasicCstrAlias, - ComparableCstrAlias, - EmbeddedCustomInterface, - EmbeddedOriginalInterface, - EmbeddedPointer, - EmbeddedPointerPtr, - EmbeddedValue, - EmbeddedValuePtr, - GoodTildeCstrAlias, - IntAlias, - IntType, - InterfaceCstrAlias, - Maps, - MixedCstrAlias, - NonBasicCstrAlias, - PointableCstrAlias, - PointerAlias, - PointerTextMarshaler, - StringAlias, - StringType, - ValueAlias, - ValueTextMarshaler -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys/models.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys/models.ts deleted file mode 100644 index 2f0b0330d..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys/models.ts +++ /dev/null @@ -1,771 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -export type BasicCstrAlias = S; - -export type ComparableCstrAlias = R; - -export type EmbeddedCustomInterface = string; - -export type EmbeddedOriginalInterface = string; - -export type EmbeddedPointer = string; - -export type EmbeddedPointerPtr = string; - -export type EmbeddedValue = string; - -export type EmbeddedValuePtr = string; - -export type GoodTildeCstrAlias = U; - -export type IntAlias = number; - -export type IntType = number; - -export type InterfaceCstrAlias = Y; - -export interface Maps { - /** - * Reject - */ - "Bool": { [_ in string]?: number } | null; - - /** - * Accept - */ - "Int": { [_ in `${number}`]?: number } | null; - - /** - * Accept - */ - "Uint": { [_ in `${number}`]?: number } | null; - - /** - * Reject - */ - "Float": { [_ in string]?: number } | null; - - /** - * Reject - */ - "Complex": { [_ in string]?: number } | null; - - /** - * Accept - */ - "Byte": { [_ in `${number}`]?: number } | null; - - /** - * Accept - */ - "Rune": { [_ in `${number}`]?: number } | null; - - /** - * Accept - */ - "String": { [_ in string]?: number } | null; - - /** - * Reject - */ - "IntPtr": { [_ in string]?: number } | null; - - /** - * Reject - */ - "UintPtr": { [_ in string]?: number } | null; - - /** - * Reject - */ - "FloatPtr": { [_ in string]?: number } | null; - - /** - * Reject - */ - "ComplexPtr": { [_ in string]?: number } | null; - - /** - * Reject - */ - "StringPtr": { [_ in string]?: number } | null; - - /** - * Reject - */ - "NTM": { [_ in string]?: number } | null; - - /** - * Reject - */ - "NTMPtr": { [_ in string]?: number } | null; - - /** - * Accept - */ - "VTM": { [_ in ValueTextMarshaler]?: number } | null; - - /** - * Accept - */ - "VTMPtr": { [_ in ValueTextMarshaler]?: number } | null; - - /** - * Reject - */ - "PTM": { [_ in string]?: number } | null; - - /** - * Accept - */ - "PTMPtr": { [_ in PointerTextMarshaler]?: number } | null; - - /** - * Accept, hide - */ - "JTM": { [_ in string]?: number } | null; - - /** - * Accept, hide - */ - "JTMPtr": { [_ in string]?: number } | null; - - /** - * Reject - */ - "A": { [_ in string]?: number } | null; - - /** - * Reject - */ - "APtr": { [_ in string]?: number } | null; - - /** - * Accept, hide - */ - "TM": { [_ in string]?: number } | null; - - /** - * Reject - */ - "TMPtr": { [_ in string]?: number } | null; - - /** - * Accept, hide - */ - "CI": { [_ in string]?: number } | null; - - /** - * Reject - */ - "CIPtr": { [_ in string]?: number } | null; - - /** - * Accept, hide - */ - "EI": { [_ in string]?: number } | null; - - /** - * Reject - */ - "EIPtr": { [_ in string]?: number } | null; - - /** - * Accept - */ - "EV": { [_ in EmbeddedValue]?: number } | null; - - /** - * Accept - */ - "EVPtr": { [_ in EmbeddedValue]?: number } | null; - - /** - * Accept - */ - "EVP": { [_ in EmbeddedValuePtr]?: number } | null; - - /** - * Accept - */ - "EVPPtr": { [_ in EmbeddedValuePtr]?: number } | null; - - /** - * Reject - */ - "EP": { [_ in string]?: number } | null; - - /** - * Accept - */ - "EPPtr": { [_ in EmbeddedPointer]?: number } | null; - - /** - * Accept - */ - "EPP": { [_ in EmbeddedPointerPtr]?: number } | null; - - /** - * Accept - */ - "EPPPtr": { [_ in EmbeddedPointerPtr]?: number } | null; - - /** - * Accept - */ - "ECI": { [_ in EmbeddedCustomInterface]?: number } | null; - - /** - * Accept - */ - "ECIPtr": { [_ in EmbeddedCustomInterface]?: number } | null; - - /** - * Accept - */ - "EOI": { [_ in EmbeddedOriginalInterface]?: number } | null; - - /** - * Accept - */ - "EOIPtr": { [_ in EmbeddedOriginalInterface]?: number } | null; - - /** - * Reject - */ - "WT": { [_ in string]?: number } | null; - - /** - * Reject - */ - "WA": { [_ in string]?: number } | null; - - /** - * Accept - */ - "ST": { [_ in StringType]?: number } | null; - - /** - * Accept - */ - "SA": { [_ in StringAlias]?: number } | null; - - /** - * Accept - */ - "IntT": { [_ in IntType]?: number } | null; - - /** - * Accept - */ - "IntA": { [_ in IntAlias]?: number } | null; - - /** - * Reject - */ - "VT": { [_ in string]?: number } | null; - - /** - * Reject - */ - "VTPtr": { [_ in string]?: number } | null; - - /** - * Reject - */ - "VPT": { [_ in string]?: number } | null; - - /** - * Reject - */ - "VPTPtr": { [_ in string]?: number } | null; - - /** - * Accept - */ - "VA": { [_ in ValueAlias]?: number } | null; - - /** - * Accept - */ - "VAPtr": { [_ in ValueAlias]?: number } | null; - - /** - * Accept, hide - */ - "VPA": { [_ in string]?: number } | null; - - /** - * Reject - */ - "VPAPtr": { [_ in string]?: number } | null; - - /** - * Reject - */ - "PT": { [_ in string]?: number } | null; - - /** - * Reject - */ - "PTPtr": { [_ in string]?: number } | null; - - /** - * Reject - */ - "PPT": { [_ in string]?: number } | null; - - /** - * Reject - */ - "PPTPtr": { [_ in string]?: number } | null; - - /** - * Reject - */ - "PA": { [_ in string]?: number } | null; - - /** - * Accept - */ - "PAPtr": { [_ in PointerAlias]?: number } | null; - - /** - * Accept, hide - */ - "PPA": { [_ in string]?: number } | null; - - /** - * Reject - */ - "PPAPtr": { [_ in string]?: number } | null; - - /** - * Accept, hide - */ - "IT": { [_ in string]?: number } | null; - - /** - * Reject - */ - "ITPtr": { [_ in string]?: number } | null; - - /** - * Reject - */ - "IPT": { [_ in string]?: number } | null; - - /** - * Reject - */ - "IPTPtr": { [_ in string]?: number } | null; - - /** - * Accept, hide - */ - "IA": { [_ in string]?: number } | null; - - /** - * Reject - */ - "IAPtr": { [_ in string]?: number } | null; - - /** - * Reject - */ - "IPA": { [_ in string]?: number } | null; - - /** - * Reject - */ - "IPAPtr": { [_ in string]?: number } | null; - - /** - * Soft reject - */ - "TPR": { [_ in string]?: number } | null; - - /** - * Soft reject - */ - "TPRPtr": { [_ in string]?: number } | null; - - /** - * Accept, hide - */ - "TPS": { [_ in string]?: number } | null; - - /** - * Soft reject - */ - "TPSPtr": { [_ in string]?: number } | null; - - /** - * Soft reject - */ - "TPT": { [_ in string]?: number } | null; - - /** - * Soft reject - */ - "TPTPtr": { [_ in string]?: number } | null; - - /** - * Accept, hide - */ - "TPU": { [_ in string]?: number } | null; - - /** - * Soft reject - */ - "TPUPtr": { [_ in string]?: number } | null; - - /** - * Accept, hide - */ - "TPV": { [_ in string]?: number } | null; - - /** - * Soft reject - */ - "TPVPtr": { [_ in string]?: number } | null; - - /** - * Soft reject - */ - "TPW": { [_ in string]?: number } | null; - - /** - * Accept, hide - */ - "TPWPtr": { [_ in string]?: number } | null; - - /** - * Accept, hide - */ - "TPX": { [_ in string]?: number } | null; - - /** - * Soft reject - */ - "TPXPtr": { [_ in string]?: number } | null; - - /** - * Accept, hide - */ - "TPY": { [_ in string]?: number } | null; - - /** - * Soft reject - */ - "TPYPtr": { [_ in string]?: number } | null; - - /** - * Accept, hide - */ - "TPZ": { [_ in string]?: number } | null; - - /** - * Soft reject - */ - "TPZPtr": { [_ in string]?: number } | null; - - /** - * Soft reject - */ - "GAR": { [_ in string]?: number } | null; - - /** - * Soft reject - */ - "GARPtr": { [_ in string]?: number } | null; - - /** - * Accept, hide - */ - "GAS": { [_ in string]?: number } | null; - - /** - * Soft reject - */ - "GASPtr": { [_ in string]?: number } | null; - - /** - * Soft reject - */ - "GAT": { [_ in string]?: number } | null; - - /** - * Soft reject - */ - "GATPtr": { [_ in string]?: number } | null; - - /** - * Accept, hide - */ - "GAU": { [_ in string]?: number } | null; - - /** - * Soft reject - */ - "GAUPtr": { [_ in string]?: number } | null; - - /** - * Accept, hide - */ - "GAV": { [_ in string]?: number } | null; - - /** - * Soft reject - */ - "GAVPtr": { [_ in string]?: number } | null; - - /** - * Soft reject - */ - "GAW": { [_ in string]?: number } | null; - - /** - * Accept, hide - */ - "GAWPtr": { [_ in string]?: number } | null; - - /** - * Accept, hide - */ - "GAX": { [_ in string]?: number } | null; - - /** - * Soft reject - */ - "GAXPtr": { [_ in string]?: number } | null; - - /** - * Accept, hide - */ - "GAY": { [_ in string]?: number } | null; - - /** - * Soft reject - */ - "GAYPtr": { [_ in string]?: number } | null; - - /** - * Accept, hide - */ - "GAZ": { [_ in string]?: number } | null; - - /** - * Soft reject - */ - "GAZPtr": { [_ in string]?: number } | null; - - /** - * Accept - */ - "GACi": { [_ in ComparableCstrAlias]?: number } | null; - - /** - * Accept - */ - "GACV": { [_ in ComparableCstrAlias]?: number } | null; - - /** - * Reject - */ - "GACP": { [_ in string]?: number } | null; - - /** - * Reject - */ - "GACiPtr": { [_ in string]?: number } | null; - - /** - * Accept, hide - */ - "GACVPtr": { [_ in string]?: number } | null; - - /** - * Accept, hide - */ - "GACPPtr": { [_ in string]?: number } | null; - - /** - * Accept - */ - "GABi": { [_ in BasicCstrAlias]?: number } | null; - - /** - * Accept - */ - "GABs": { [_ in BasicCstrAlias]?: number } | null; - - /** - * Reject - */ - "GABiPtr": { [_ in string]?: number } | null; - - /** - * Reject - */ - "GABT": { [_ in string]?: number } | null; - - /** - * Reject - */ - "GABTPtr": { [_ in string]?: number } | null; - - /** - * Accept - */ - "GAGT": { [_ in GoodTildeCstrAlias]?: number } | null; - - /** - * Accept, hide - */ - "GAGTPtr": { [_ in string]?: number } | null; - - /** - * Accept - */ - "GANBV": { [_ in NonBasicCstrAlias]?: number } | null; - - /** - * Accept, hide - */ - "GANBP": { [_ in string]?: number } | null; - - /** - * Accept, hide - */ - "GANBVPtr": { [_ in string]?: number } | null; - - /** - * Reject - */ - "GANBPPtr": { [_ in string]?: number } | null; - - /** - * Accept - */ - "GAPlV1": { [_ in PointableCstrAlias]?: number } | null; - - /** - * Accept - */ - "GAPlV2": { [_ in PointableCstrAlias]?: number } | null; - - /** - * Reject - */ - "GAPlP1": { [_ in string]?: number } | null; - - /** - * Accept - */ - "GAPlP2": { [_ in PointableCstrAlias]?: number } | null; - - /** - * Accept, hide - */ - "GAPlVPtr": { [_ in string]?: number } | null; - - /** - * Accept, hide - */ - "GAPlPPtr": { [_ in string]?: number } | null; - - /** - * Accept - */ - "GAMi": { [_ in MixedCstrAlias]?: number } | null; - - /** - * Accept - */ - "GAMS": { [_ in MixedCstrAlias]?: number } | null; - - /** - * Accept - */ - "GAMV": { [_ in MixedCstrAlias]?: number } | null; - - /** - * Reject - */ - "GAMSPtr": { [_ in string]?: number } | null; - - /** - * Accept, hide - */ - "GAMVPtr": { [_ in string]?: number } | null; - - /** - * Accept, hide - */ - "GAII": { [_ in string]?: number } | null; - - /** - * Accept - */ - "GAIV": { [_ in InterfaceCstrAlias]?: number } | null; - - /** - * Accept, hide - */ - "GAIP": { [_ in string]?: number } | null; - - /** - * Reject - */ - "GAIIPtr": { [_ in string]?: number } | null; - - /** - * Accept, hide - */ - "GAIVPtr": { [_ in string]?: number } | null; - - /** - * Reject - */ - "GAIPPtr": { [_ in string]?: number } | null; - - /** - * Accept, hide - */ - "GAPrV": { [_ in string]?: number } | null; - - /** - * Accept, hide - */ - "GAPrP": { [_ in string]?: number } | null; - - /** - * Reject - */ - "GAPrVPtr": { [_ in string]?: number } | null; - - /** - * Reject - */ - "GAPrPPtr": { [_ in string]?: number } | null; -} - -export type MixedCstrAlias = X; - -export type NonBasicCstrAlias = V; - -export type PointableCstrAlias = W; - -export type PointerAlias = PointerTextMarshaler; - -export type PointerTextMarshaler = string; - -export type StringAlias = string; - -export type StringType = string; - -export type ValueAlias = ValueTextMarshaler; - -export type ValueTextMarshaler = string; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys/service.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys/service.ts deleted file mode 100644 index 50d2f6d72..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys/service.ts +++ /dev/null @@ -1,14 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -export function Method(): $CancellablePromise<$models.Maps<$models.PointerTextMarshaler, number, number, $models.ValueTextMarshaler, $models.PointerTextMarshaler | null, $models.ValueTextMarshaler, $models.StringType, $models.ValueTextMarshaler, $models.PointerTextMarshaler | null>> { - return $Call.ByID(4021345184); -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/marshalers/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/marshalers/index.ts deleted file mode 100644 index 7c55b767b..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/marshalers/index.ts +++ /dev/null @@ -1,33 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as Service from "./service.js"; -export { - Service -}; - -export type { - AliasJsonMarshaler, - AliasMarshaler, - AliasNonMarshaler, - AliasTextMarshaler, - Data, - ImplicitJsonButText, - ImplicitJsonMarshaler, - ImplicitMarshaler, - ImplicitNonJson, - ImplicitNonMarshaler, - ImplicitNonText, - ImplicitTextButJson, - ImplicitTextMarshaler, - NonMarshaler, - PointerJsonMarshaler, - PointerMarshaler, - PointerTextMarshaler, - UnderlyingJsonMarshaler, - UnderlyingMarshaler, - UnderlyingTextMarshaler, - ValueJsonMarshaler, - ValueMarshaler, - ValueTextMarshaler -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/marshalers/models.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/marshalers/models.ts deleted file mode 100644 index 02d639994..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/marshalers/models.ts +++ /dev/null @@ -1,309 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as encoding$0 from "../../../../../../../../encoding/models.js"; -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as json$0 from "../../../../../../../../encoding/json/models.js"; - -/** - * any - */ -export type AliasJsonMarshaler = any; - -/** - * any - */ -export type AliasMarshaler = any; - -/** - * struct{} - */ -export interface AliasNonMarshaler { -} - -/** - * string - */ -export type AliasTextMarshaler = string; - -export interface Data { - "NM": NonMarshaler; - - /** - * NonMarshaler | null - */ - "NMPtr": NonMarshaler | null; - "VJM": ValueJsonMarshaler; - - /** - * ValueJsonMarshaler | null - */ - "VJMPtr": ValueJsonMarshaler | null; - "PJM": PointerJsonMarshaler; - - /** - * PointerJsonMarshaler | null - */ - "PJMPtr": PointerJsonMarshaler | null; - "VTM": ValueTextMarshaler; - - /** - * ValueTextMarshaler | null - */ - "VTMPtr": ValueTextMarshaler | null; - "PTM": PointerTextMarshaler; - - /** - * PointerTextMarshaler | null - */ - "PTMPtr": PointerTextMarshaler | null; - "VM": ValueMarshaler; - - /** - * ValueMarshaler | null - */ - "VMPtr": ValueMarshaler | null; - "PM": PointerMarshaler; - - /** - * PointerMarshaler | null - */ - "PMPtr": PointerMarshaler | null; - "UJM": UnderlyingJsonMarshaler; - - /** - * UnderlyingJsonMarshaler | null - */ - "UJMPtr": UnderlyingJsonMarshaler | null; - "UTM": UnderlyingTextMarshaler; - - /** - * UnderlyingTextMarshaler | null - */ - "UTMPtr": UnderlyingTextMarshaler | null; - "UM": UnderlyingMarshaler; - - /** - * UnderlyingMarshaler | null - */ - "UMPtr": UnderlyingMarshaler | null; - - /** - * any - */ - "JM": any; - - /** - * any | null - */ - "JMPtr": any | null; - - /** - * string - */ - "TM": string; - - /** - * string | null - */ - "TMPtr": string | null; - - /** - * any - */ - "CJM": any; - - /** - * any | null - */ - "CJMPtr": any | null; - - /** - * string - */ - "CTM": string; - - /** - * string | null - */ - "CTMPtr": string | null; - - /** - * any - */ - "CM": any; - - /** - * any | null - */ - "CMPtr": any | null; - "ANM": AliasNonMarshaler; - - /** - * AliasNonMarshaler | null - */ - "ANMPtr": AliasNonMarshaler | null; - "AJM": AliasJsonMarshaler; - - /** - * AliasJsonMarshaler | null - */ - "AJMPtr": AliasJsonMarshaler | null; - "ATM": AliasTextMarshaler; - - /** - * AliasTextMarshaler | null - */ - "ATMPtr": AliasTextMarshaler | null; - "AM": AliasMarshaler; - - /** - * AliasMarshaler | null - */ - "AMPtr": AliasMarshaler | null; - "ImJM": ImplicitJsonMarshaler; - - /** - * ImplicitJsonMarshaler | null - */ - "ImJMPtr": ImplicitJsonMarshaler | null; - "ImTM": ImplicitTextMarshaler; - - /** - * ImplicitTextMarshaler | null - */ - "ImTMPtr": ImplicitTextMarshaler | null; - "ImM": ImplicitMarshaler; - - /** - * ImplicitMarshaler | null - */ - "ImMPtr": ImplicitMarshaler | null; - "ImNJ": ImplicitNonJson; - - /** - * ImplicitNonJson | null - */ - "ImNJPtr": ImplicitNonJson | null; - "ImNT": ImplicitNonText; - - /** - * ImplicitNonText | null - */ - "ImNTPtr": ImplicitNonText | null; - "ImNM": ImplicitNonMarshaler; - - /** - * ImplicitNonMarshaler | null - */ - "ImNMPtr": ImplicitNonMarshaler | null; - "ImJbT": ImplicitJsonButText; - - /** - * ImplicitJsonButText | null - */ - "ImJbTPtr": ImplicitJsonButText | null; - "ImTbJ": ImplicitTextButJson; - - /** - * ImplicitTextButJson | null - */ - "ImTbJPtr": ImplicitTextButJson | null; -} - -/** - * any - */ -export type ImplicitJsonButText = any; - -/** - * any - */ -export type ImplicitJsonMarshaler = any; - -/** - * any - */ -export type ImplicitMarshaler = any; - -/** - * string - */ -export type ImplicitNonJson = string; - -/** - * class{ Marshaler, TextMarshaler } - */ -export interface ImplicitNonMarshaler { - "Marshaler": json$0.Marshaler; - "TextMarshaler": encoding$0.TextMarshaler; -} - -/** - * any - */ -export type ImplicitNonText = any; - -/** - * any - */ -export type ImplicitTextButJson = any; - -/** - * string - */ -export type ImplicitTextMarshaler = string; - -/** - * class {} - */ -export interface NonMarshaler { -} - -/** - * any - */ -export type PointerJsonMarshaler = any; - -/** - * any - */ -export type PointerMarshaler = any; - -/** - * string - */ -export type PointerTextMarshaler = string; - -/** - * any - */ -export type UnderlyingJsonMarshaler = any; - -/** - * any - */ -export type UnderlyingMarshaler = any; - -/** - * string - */ -export type UnderlyingTextMarshaler = string; - -/** - * any - */ -export type ValueJsonMarshaler = any; - -/** - * any - */ -export type ValueMarshaler = any; - -/** - * string - */ -export type ValueTextMarshaler = string; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/marshalers/service.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/marshalers/service.ts deleted file mode 100644 index b175ebe96..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/marshalers/service.ts +++ /dev/null @@ -1,14 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -export function Method(): $CancellablePromise<$models.Data> { - return $Call.ByID(4021345184); -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/index.ts deleted file mode 100644 index bf611e486..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/index.ts +++ /dev/null @@ -1,14 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as SomeMethods from "./somemethods.js"; -export { - SomeMethods -}; - -export type { - HowDifferent, - Impersonator, - Person, - PrivatePerson -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/models.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/models.ts deleted file mode 100644 index 45c7f2785..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/models.ts +++ /dev/null @@ -1,64 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as other$0 from "./other/models.js"; - -/** - * HowDifferent is a curious kind of person - * that lets other people decide how they are different. - */ -export interface HowDifferent { - /** - * They have a name as well. - */ - "Name": string; - - /** - * But they may have many differences. - */ - "Differences": ({ [_ in string]?: How } | null)[] | null; -} - -/** - * Impersonator gets their fields from other people. - */ -export type Impersonator = other$0.OtherPerson; - -/** - * Person is not a number. - */ -export interface Person { - /** - * They have a name. - */ - "Name": string; - - /** - * Exactly 4 sketchy friends. - */ - "Friends": Impersonator[]; -} - -/** - * PrivatePerson gets their fields from hidden sources. - */ -export type PrivatePerson = personImpl; - -export interface personImpl { - /** - * Nickname conceals a person's identity. - */ - "Nickname": string; - - /** - * They have a name. - */ - "Name": string; - - /** - * Exactly 4 sketchy friends. - */ - "Friends": Impersonator[]; -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/more/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/more/index.ts deleted file mode 100644 index ac743f356..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/more/index.ts +++ /dev/null @@ -1,6 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -export type { - StringPtr -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/more/models.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/more/models.ts deleted file mode 100644 index 6a5a12300..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/more/models.ts +++ /dev/null @@ -1,7 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * StringPtr is a nullable string. - */ -export type StringPtr = string | null; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/other/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/other/index.ts deleted file mode 100644 index b9f2889db..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/other/index.ts +++ /dev/null @@ -1,11 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as OtherMethods from "./othermethods.js"; -export { - OtherMethods -}; - -export type { - OtherPerson -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/other/models.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/other/models.ts deleted file mode 100644 index 6ca5b82a2..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/other/models.ts +++ /dev/null @@ -1,17 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * OtherPerson is like a person, but different. - */ -export interface OtherPerson { - /** - * They have a name as well. - */ - "Name": string; - - /** - * But they may have many differences. - */ - "Differences": T[] | null; -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/other/othermethods.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/other/othermethods.ts deleted file mode 100644 index c2fb7bc6a..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/other/othermethods.ts +++ /dev/null @@ -1,18 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * OtherMethods has another method, but through a private embedded type. - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -/** - * LikeThisOtherOne does nothing as well, but is different. - */ -export function LikeThisOtherOne(): $CancellablePromise { - return $Call.ByID(3606939272); -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/somemethods.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/somemethods.ts deleted file mode 100644 index 4f623616d..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/somemethods.ts +++ /dev/null @@ -1,29 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * SomeMethods exports some methods. - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * LikeThisOne is an example method that does nothing. - */ -export function LikeThisOne(): $CancellablePromise<[$models.Person, $models.HowDifferent, $models.PrivatePerson]> { - return $Call.ByID(2124352079); -} - -/** - * LikeThisOtherOne does nothing as well, but is different. - */ -export function LikeThisOtherOne(): $CancellablePromise { - return $Call.ByID(4281222271); -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/out_of_tree/embedother.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/out_of_tree/embedother.ts deleted file mode 100644 index d155adc30..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/out_of_tree/embedother.ts +++ /dev/null @@ -1,18 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * EmbedOther is even trickier. - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -/** - * LikeThisOtherOne does nothing as well, but is different. - */ -export function LikeThisOtherOne(): $CancellablePromise { - return $Call.ByID(3566862802); -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/out_of_tree/embedservice.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/out_of_tree/embedservice.ts deleted file mode 100644 index 65098990f..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/out_of_tree/embedservice.ts +++ /dev/null @@ -1,29 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * EmbedService is tricky. - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as nobindingshere$0 from "../no_bindings_here/models.js"; - -/** - * LikeThisOne is an example method that does nothing. - */ -export function LikeThisOne(): $CancellablePromise<[nobindingshere$0.Person, nobindingshere$0.HowDifferent, nobindingshere$0.PrivatePerson]> { - return $Call.ByID(2590614085); -} - -/** - * LikeThisOtherOne does nothing as well, but is different. - */ -export function LikeThisOtherOne(): $CancellablePromise { - return $Call.ByID(773650321); -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/out_of_tree/greetservice.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/out_of_tree/greetservice.ts deleted file mode 100644 index 76375250e..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/out_of_tree/greetservice.ts +++ /dev/null @@ -1,18 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -/** - * Greet someone - */ -export function Greet($0: string): $CancellablePromise { - return $Call.ByID(1411160069, $0); -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/out_of_tree/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/out_of_tree/index.ts deleted file mode 100644 index e69bebf3b..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/out_of_tree/index.ts +++ /dev/null @@ -1,11 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as EmbedOther from "./embedother.js"; -import * as EmbedService from "./embedservice.js"; -import * as GreetService from "./greetservice.js"; -export { - EmbedOther, - EmbedService, - GreetService -}; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple/greetservice.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple/greetservice.ts deleted file mode 100644 index 34c4d151a..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple/greetservice.ts +++ /dev/null @@ -1,10 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -export function Greet(name: string): $CancellablePromise { - return $Call.ByID(1411160069, name); -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple/index.ts deleted file mode 100644 index 5c4ebea4f..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple/index.ts +++ /dev/null @@ -1,9 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -import * as OtherService from "./otherservice.js"; -export { - GreetService, - OtherService -}; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple/otherservice.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple/otherservice.ts deleted file mode 100644 index d27e71304..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple/otherservice.ts +++ /dev/null @@ -1,10 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -export function Hello(): $CancellablePromise { - return $Call.ByID(4249972365); -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_files/greetservice.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_files/greetservice.ts deleted file mode 100644 index 34c4d151a..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_files/greetservice.ts +++ /dev/null @@ -1,10 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -export function Greet(name: string): $CancellablePromise { - return $Call.ByID(1411160069, name); -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_files/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_files/index.ts deleted file mode 100644 index 5c4ebea4f..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_files/index.ts +++ /dev/null @@ -1,9 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -import * as OtherService from "./otherservice.js"; -export { - GreetService, - OtherService -}; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_files/otherservice.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_files/otherservice.ts deleted file mode 100644 index d27e71304..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_files/otherservice.ts +++ /dev/null @@ -1,10 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -export function Hello(): $CancellablePromise { - return $Call.ByID(4249972365); -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_other/greetservice.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_other/greetservice.ts deleted file mode 100644 index 8519667d5..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_other/greetservice.ts +++ /dev/null @@ -1,29 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * Greet does XYZ - */ -export function Greet(name: string): $CancellablePromise { - return $Call.ByID(1411160069, name); -} - -/** - * NewPerson creates a new person - */ -export function NewPerson(name: string): $CancellablePromise<$models.Person | null> { - return $Call.ByID(1661412647, name); -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_other/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_other/index.ts deleted file mode 100644 index 14252454b..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_other/index.ts +++ /dev/null @@ -1,11 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; - -export type { - Person -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_other/models.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_other/models.ts deleted file mode 100644 index 3ab21d612..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_other/models.ts +++ /dev/null @@ -1,11 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as services$0 from "./services/models.js"; - -export interface Person { - "Name": string; - "Address": services$0.Address | null; -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_other/services/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_other/services/index.ts deleted file mode 100644 index 8857d2bc5..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_other/services/index.ts +++ /dev/null @@ -1,11 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as OtherService from "./otherservice.js"; -export { - OtherService -}; - -export type { - Address -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_other/services/models.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_other/services/models.ts deleted file mode 100644 index b76080cf3..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_other/services/models.ts +++ /dev/null @@ -1,8 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -export interface Address { - "Street": string; - "State": string; - "Country": string; -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_other/services/otherservice.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_other/services/otherservice.ts deleted file mode 100644 index 50e62daa4..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_other/services/otherservice.ts +++ /dev/null @@ -1,23 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * OtherService is a struct - * that does things - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * Yay does this and that - */ -export function Yay(): $CancellablePromise<$models.Address | null> { - return $Call.ByID(3568225479); -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_non_pointer_single/greetservice.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_non_pointer_single/greetservice.ts deleted file mode 100644 index ab5e878b1..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_non_pointer_single/greetservice.ts +++ /dev/null @@ -1,190 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -export function ArrayInt($in: number[]): $CancellablePromise { - return $Call.ByID(3862002418, $in); -} - -export function BoolInBoolOut($in: boolean): $CancellablePromise { - return $Call.ByID(2424639793, $in); -} - -export function Float32InFloat32Out($in: number): $CancellablePromise { - return $Call.ByID(3132595881, $in); -} - -export function Float64InFloat64Out($in: number): $CancellablePromise { - return $Call.ByID(2182412247, $in); -} - -/** - * Greet someone - */ -export function Greet(name: string): $CancellablePromise { - return $Call.ByID(1411160069, name); -} - -export function Int16InIntOut($in: number): $CancellablePromise { - return $Call.ByID(3306292566, $in); -} - -export function Int16PointerInAndOutput($in: number | null): $CancellablePromise { - return $Call.ByID(1754277916, $in); -} - -export function Int32InIntOut($in: number): $CancellablePromise { - return $Call.ByID(1909469092, $in); -} - -export function Int32PointerInAndOutput($in: number | null): $CancellablePromise { - return $Call.ByID(4251088558, $in); -} - -export function Int64InIntOut($in: number): $CancellablePromise { - return $Call.ByID(1343888303, $in); -} - -export function Int64PointerInAndOutput($in: number | null): $CancellablePromise { - return $Call.ByID(2205561041, $in); -} - -export function Int8InIntOut($in: number): $CancellablePromise { - return $Call.ByID(572240879, $in); -} - -export function Int8PointerInAndOutput($in: number | null): $CancellablePromise { - return $Call.ByID(2189402897, $in); -} - -export function IntInIntOut($in: number): $CancellablePromise { - return $Call.ByID(642881729, $in); -} - -export function IntPointerInAndOutput($in: number | null): $CancellablePromise { - return $Call.ByID(1066151743, $in); -} - -export function IntPointerInputNamedOutputs($in: number | null): $CancellablePromise { - return $Call.ByID(2718999663, $in); -} - -export function MapIntInt($in: { [_ in `${number}`]?: number } | null): $CancellablePromise { - return $Call.ByID(2386486356, $in); -} - -export function MapIntIntPointer($in: { [_ in `${number}`]?: number | null } | null): $CancellablePromise { - return $Call.ByID(2163571325, $in); -} - -export function MapIntSliceInt($in: { [_ in `${number}`]?: number[] | null } | null): $CancellablePromise { - return $Call.ByID(2900172572, $in); -} - -export function MapIntSliceIntInMapIntSliceIntOut($in: { [_ in `${number}`]?: number[] | null } | null): $CancellablePromise<{ [_ in `${number}`]?: number[] | null } | null> { - return $Call.ByID(881980169, $in); -} - -export function NoInputsStringOut(): $CancellablePromise { - return $Call.ByID(1075577233); -} - -export function PointerBoolInBoolOut($in: boolean | null): $CancellablePromise { - return $Call.ByID(3589606958, $in); -} - -export function PointerFloat32InFloat32Out($in: number | null): $CancellablePromise { - return $Call.ByID(224675106, $in); -} - -export function PointerFloat64InFloat64Out($in: number | null): $CancellablePromise { - return $Call.ByID(2124953624, $in); -} - -export function PointerMapIntInt($in: { [_ in `${number}`]?: number } | null): $CancellablePromise { - return $Call.ByID(3516977899, $in); -} - -export function PointerStringInStringOut($in: string | null): $CancellablePromise { - return $Call.ByID(229603958, $in); -} - -export function StringArrayInputNamedOutput($in: string[] | null): $CancellablePromise { - return $Call.ByID(3678582682, $in); -} - -export function StringArrayInputNamedOutputs($in: string[] | null): $CancellablePromise { - return $Call.ByID(319259595, $in); -} - -export function StringArrayInputStringArrayOut($in: string[] | null): $CancellablePromise { - return $Call.ByID(383995060, $in); -} - -export function StringArrayInputStringOut($in: string[] | null): $CancellablePromise { - return $Call.ByID(1091960237, $in); -} - -export function StructInputStructOutput($in: $models.Person): $CancellablePromise<$models.Person> { - return $Call.ByID(3835643147, $in); -} - -export function StructPointerInputErrorOutput($in: $models.Person | null): $CancellablePromise { - return $Call.ByID(2447692557, $in); -} - -export function StructPointerInputStructPointerOutput($in: $models.Person | null): $CancellablePromise<$models.Person | null> { - return $Call.ByID(2943477349, $in); -} - -export function UInt16InUIntOut($in: number): $CancellablePromise { - return $Call.ByID(3401034892, $in); -} - -export function UInt16PointerInAndOutput($in: number | null): $CancellablePromise { - return $Call.ByID(1236957573, $in); -} - -export function UInt32InUIntOut($in: number): $CancellablePromise { - return $Call.ByID(1160383782, $in); -} - -export function UInt32PointerInAndOutput($in: number | null): $CancellablePromise { - return $Call.ByID(1739300671, $in); -} - -export function UInt64InUIntOut($in: number): $CancellablePromise { - return $Call.ByID(793803239, $in); -} - -export function UInt64PointerInAndOutput($in: number | null): $CancellablePromise { - return $Call.ByID(1403757716, $in); -} - -export function UInt8InUIntOut($in: number): $CancellablePromise { - return $Call.ByID(2988345717, $in); -} - -export function UInt8PointerInAndOutput($in: number | null): $CancellablePromise { - return $Call.ByID(518250834, $in); -} - -export function UIntInUIntOut($in: number): $CancellablePromise { - return $Call.ByID(2836661285, $in); -} - -export function UIntPointerInAndOutput($in: number | null): $CancellablePromise { - return $Call.ByID(1367187362, $in); -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_non_pointer_single/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_non_pointer_single/index.ts deleted file mode 100644 index 14252454b..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_non_pointer_single/index.ts +++ /dev/null @@ -1,11 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; - -export type { - Person -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_non_pointer_single/models.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_non_pointer_single/models.ts deleted file mode 100644 index 5664b79ab..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_non_pointer_single/models.ts +++ /dev/null @@ -1,8 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -export interface Person { - "Name": string; - "Parent": Person | null; - "Details": {"Age": number, "Address": {"Street": string}}; -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_single/greetservice.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_single/greetservice.ts deleted file mode 100644 index ab5e878b1..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_single/greetservice.ts +++ /dev/null @@ -1,190 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -export function ArrayInt($in: number[]): $CancellablePromise { - return $Call.ByID(3862002418, $in); -} - -export function BoolInBoolOut($in: boolean): $CancellablePromise { - return $Call.ByID(2424639793, $in); -} - -export function Float32InFloat32Out($in: number): $CancellablePromise { - return $Call.ByID(3132595881, $in); -} - -export function Float64InFloat64Out($in: number): $CancellablePromise { - return $Call.ByID(2182412247, $in); -} - -/** - * Greet someone - */ -export function Greet(name: string): $CancellablePromise { - return $Call.ByID(1411160069, name); -} - -export function Int16InIntOut($in: number): $CancellablePromise { - return $Call.ByID(3306292566, $in); -} - -export function Int16PointerInAndOutput($in: number | null): $CancellablePromise { - return $Call.ByID(1754277916, $in); -} - -export function Int32InIntOut($in: number): $CancellablePromise { - return $Call.ByID(1909469092, $in); -} - -export function Int32PointerInAndOutput($in: number | null): $CancellablePromise { - return $Call.ByID(4251088558, $in); -} - -export function Int64InIntOut($in: number): $CancellablePromise { - return $Call.ByID(1343888303, $in); -} - -export function Int64PointerInAndOutput($in: number | null): $CancellablePromise { - return $Call.ByID(2205561041, $in); -} - -export function Int8InIntOut($in: number): $CancellablePromise { - return $Call.ByID(572240879, $in); -} - -export function Int8PointerInAndOutput($in: number | null): $CancellablePromise { - return $Call.ByID(2189402897, $in); -} - -export function IntInIntOut($in: number): $CancellablePromise { - return $Call.ByID(642881729, $in); -} - -export function IntPointerInAndOutput($in: number | null): $CancellablePromise { - return $Call.ByID(1066151743, $in); -} - -export function IntPointerInputNamedOutputs($in: number | null): $CancellablePromise { - return $Call.ByID(2718999663, $in); -} - -export function MapIntInt($in: { [_ in `${number}`]?: number } | null): $CancellablePromise { - return $Call.ByID(2386486356, $in); -} - -export function MapIntIntPointer($in: { [_ in `${number}`]?: number | null } | null): $CancellablePromise { - return $Call.ByID(2163571325, $in); -} - -export function MapIntSliceInt($in: { [_ in `${number}`]?: number[] | null } | null): $CancellablePromise { - return $Call.ByID(2900172572, $in); -} - -export function MapIntSliceIntInMapIntSliceIntOut($in: { [_ in `${number}`]?: number[] | null } | null): $CancellablePromise<{ [_ in `${number}`]?: number[] | null } | null> { - return $Call.ByID(881980169, $in); -} - -export function NoInputsStringOut(): $CancellablePromise { - return $Call.ByID(1075577233); -} - -export function PointerBoolInBoolOut($in: boolean | null): $CancellablePromise { - return $Call.ByID(3589606958, $in); -} - -export function PointerFloat32InFloat32Out($in: number | null): $CancellablePromise { - return $Call.ByID(224675106, $in); -} - -export function PointerFloat64InFloat64Out($in: number | null): $CancellablePromise { - return $Call.ByID(2124953624, $in); -} - -export function PointerMapIntInt($in: { [_ in `${number}`]?: number } | null): $CancellablePromise { - return $Call.ByID(3516977899, $in); -} - -export function PointerStringInStringOut($in: string | null): $CancellablePromise { - return $Call.ByID(229603958, $in); -} - -export function StringArrayInputNamedOutput($in: string[] | null): $CancellablePromise { - return $Call.ByID(3678582682, $in); -} - -export function StringArrayInputNamedOutputs($in: string[] | null): $CancellablePromise { - return $Call.ByID(319259595, $in); -} - -export function StringArrayInputStringArrayOut($in: string[] | null): $CancellablePromise { - return $Call.ByID(383995060, $in); -} - -export function StringArrayInputStringOut($in: string[] | null): $CancellablePromise { - return $Call.ByID(1091960237, $in); -} - -export function StructInputStructOutput($in: $models.Person): $CancellablePromise<$models.Person> { - return $Call.ByID(3835643147, $in); -} - -export function StructPointerInputErrorOutput($in: $models.Person | null): $CancellablePromise { - return $Call.ByID(2447692557, $in); -} - -export function StructPointerInputStructPointerOutput($in: $models.Person | null): $CancellablePromise<$models.Person | null> { - return $Call.ByID(2943477349, $in); -} - -export function UInt16InUIntOut($in: number): $CancellablePromise { - return $Call.ByID(3401034892, $in); -} - -export function UInt16PointerInAndOutput($in: number | null): $CancellablePromise { - return $Call.ByID(1236957573, $in); -} - -export function UInt32InUIntOut($in: number): $CancellablePromise { - return $Call.ByID(1160383782, $in); -} - -export function UInt32PointerInAndOutput($in: number | null): $CancellablePromise { - return $Call.ByID(1739300671, $in); -} - -export function UInt64InUIntOut($in: number): $CancellablePromise { - return $Call.ByID(793803239, $in); -} - -export function UInt64PointerInAndOutput($in: number | null): $CancellablePromise { - return $Call.ByID(1403757716, $in); -} - -export function UInt8InUIntOut($in: number): $CancellablePromise { - return $Call.ByID(2988345717, $in); -} - -export function UInt8PointerInAndOutput($in: number | null): $CancellablePromise { - return $Call.ByID(518250834, $in); -} - -export function UIntInUIntOut($in: number): $CancellablePromise { - return $Call.ByID(2836661285, $in); -} - -export function UIntPointerInAndOutput($in: number | null): $CancellablePromise { - return $Call.ByID(1367187362, $in); -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_single/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_single/index.ts deleted file mode 100644 index 14252454b..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_single/index.ts +++ /dev/null @@ -1,11 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; - -export type { - Person -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_single/models.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_single/models.ts deleted file mode 100644 index 5664b79ab..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_single/models.ts +++ /dev/null @@ -1,8 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -export interface Person { - "Name": string; - "Parent": Person | null; - "Details": {"Age": number, "Address": {"Street": string}}; -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single/greetservice.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single/greetservice.ts deleted file mode 100644 index 8a2cb7a70..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single/greetservice.ts +++ /dev/null @@ -1,18 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -/** - * Greet someone - */ -export function Greet(name: string): $CancellablePromise { - return $Call.ByID(1411160069, name); -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single/index.ts deleted file mode 100644 index 50e3f0435..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single/index.ts +++ /dev/null @@ -1,7 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_function/greetservice.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_function/greetservice.ts deleted file mode 100644 index 8a2cb7a70..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_function/greetservice.ts +++ /dev/null @@ -1,18 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -/** - * Greet someone - */ -export function Greet(name: string): $CancellablePromise { - return $Call.ByID(1411160069, name); -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_function/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_function/index.ts deleted file mode 100644 index 50e3f0435..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_function/index.ts +++ /dev/null @@ -1,7 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_other_function/greetservice.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_other_function/greetservice.ts deleted file mode 100644 index 8519667d5..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_other_function/greetservice.ts +++ /dev/null @@ -1,29 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * Greet does XYZ - */ -export function Greet(name: string): $CancellablePromise { - return $Call.ByID(1411160069, name); -} - -/** - * NewPerson creates a new person - */ -export function NewPerson(name: string): $CancellablePromise<$models.Person | null> { - return $Call.ByID(1661412647, name); -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_other_function/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_other_function/index.ts deleted file mode 100644 index 14252454b..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_other_function/index.ts +++ /dev/null @@ -1,11 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; - -export type { - Person -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_other_function/models.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_other_function/models.ts deleted file mode 100644 index f29117203..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_other_function/models.ts +++ /dev/null @@ -1,15 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as services$0 from "./services/models.js"; - -/** - * Person is a person! - * They have a name and an address - */ -export interface Person { - "Name": string; - "Address": services$0.Address | null; -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_other_function/services/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_other_function/services/index.ts deleted file mode 100644 index 8857d2bc5..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_other_function/services/index.ts +++ /dev/null @@ -1,11 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as OtherService from "./otherservice.js"; -export { - OtherService -}; - -export type { - Address -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_other_function/services/models.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_other_function/services/models.ts deleted file mode 100644 index b76080cf3..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_other_function/services/models.ts +++ /dev/null @@ -1,8 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -export interface Address { - "Street": string; - "State": string; - "Country": string; -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_other_function/services/otherservice.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_other_function/services/otherservice.ts deleted file mode 100644 index 79c8907f9..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_other_function/services/otherservice.ts +++ /dev/null @@ -1,23 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * OtherService is a struct - * that does things - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * Yay does this and that - */ -export function Yay(): $CancellablePromise<$models.Address | null> { - return $Call.ByID(1491748400); -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/warnings.log b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/warnings.log deleted file mode 100644 index ce8369307..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=false/warnings.log +++ /dev/null @@ -1,83 +0,0 @@ -[warn] /testcases/complex_json/main.go:127:2: event 'collision' has one of multiple definitions here with data type map[string]int -[warn] /testcases/events_only/events.go:20:2: event 'collision' has one of multiple definitions here with data type int -[warn] /testcases/events_only/events.go:21:2: `application.RegisterEvent` called here with non-constant event name -[warn] /testcases/events_only/other.go:10:5: `application.RegisterEvent` is instantiated here but not called -[warn] /testcases/events_only/other.go:13:2: `application.RegisterEvent` called here with non-constant event name -[warn] /testcases/events_only/other.go:17:2: data type []T for event 'parametric' contains unresolved type parameters and will be ignored` -[warn] /testcases/events_only/other.go:22:2: event 'common:ApplicationStarted' is a known system event and cannot be overridden; this call to `application.RegisterEvent` will panic -[warn] /testcases/marshalers/main.go:212:2: event 'collision' has one of multiple definitions here with data type *struct{Field []bool} -[warn] /testcases/marshalers/main.go:214:2: data type encoding/json.Marshaler for event 'interface' is a non-empty interface: emitting events from the frontend with data other than `null` is not supported by encoding/json and will likely result in runtime errors -[warn] dynamically registered event names are not discoverable by the binding generator: it is recommended to invoke `application.RegisterEvent` with constant arguments only -[warn] event 'collision' has multiple conflicting definitions and will be ignored -[warn] events registered through indirect calls are not discoverable by the binding generator: it is recommended to invoke `application.RegisterEvent` directly -[warn] generic wrappers for calls to `application.RegisterEvent` are not analysable by the binding generator: it is recommended to call `application.RegisterEvent` with concrete types only -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *R is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *S is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *T is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *U is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *V is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *X is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *Y is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *Z is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *any is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *complex64 is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *encoding.TextMarshaler is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *float32 is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.CustomInterface is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.EmbeddedInterface is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.InterfaceAlias is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.InterfacePtrAlias is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.InterfacePtrType is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.InterfaceType is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.NonTextMarshaler is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.PointerPtrAlias is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.PointerPtrType is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.PointerType is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.ValuePtrAlias is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.ValuePtrType is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.ValueType is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *int is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *string is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *uint is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type R is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type T is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type W is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type any is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type bool is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type complex64 is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type float32 is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.BadTildeCstrAlias[T] is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.BadTildeCstrAlias[struct{}] is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.BadTildeCstrPtrAlias[T] is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.BadTildeCstrPtrAlias[struct{}] is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.BasicCstrPtrAlias[S] is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.BasicCstrPtrAlias[int] is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.ComparableCstrAlias[R] is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.ComparableCstrAlias[github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.PointerTextMarshaler] is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.ComparableCstrPtrAlias[R] is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.ComparableCstrPtrAlias[int] is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.EmbeddedPointer is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.GoodTildeCstrPtrAlias[U] is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.InterfaceCstrPtrAlias[*github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.PointerTextMarshaler] is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.InterfaceCstrPtrAlias[Y] is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.InterfaceCstrPtrAlias[encoding.TextMarshaler] is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.InterfacePtrAlias is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.InterfacePtrType is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.MixedCstrPtrAlias[X] is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.MixedCstrPtrAlias[github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.StringType] is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.NonBasicCstrPtrAlias[*github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.PointerTextMarshaler] is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.NonBasicCstrPtrAlias[V] is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.NonTextMarshaler is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.PointableCstrAlias[W] is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.PointableCstrAlias[github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.PointerTextMarshaler] is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.PointerAlias is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.PointerCstrPtrAlias[R, Z] is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.PointerCstrPtrAlias[github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.PointerTextMarshaler, *github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.PointerTextMarshaler] is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.PointerCstrPtrAlias[github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.ValueTextMarshaler, *github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.ValueTextMarshaler] is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.PointerPtrType is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.PointerTextMarshaler is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.PointerType is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.ValuePtrType is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.ValueType is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.WrongAlias is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.WrongType is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/encoding/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/encoding/index.ts deleted file mode 100644 index ba2885969..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/encoding/index.ts +++ /dev/null @@ -1,6 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -export type { - TextMarshaler -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/encoding/json/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/encoding/json/index.ts deleted file mode 100644 index 00ec01151..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/encoding/json/index.ts +++ /dev/null @@ -1,6 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -export type { - Marshaler -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/encoding/json/models.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/encoding/json/models.ts deleted file mode 100644 index 8e7f0b3f1..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/encoding/json/models.ts +++ /dev/null @@ -1,8 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * Marshaler is the interface implemented by types that - * can marshal themselves into valid JSON. - */ -export type Marshaler = any; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/encoding/models.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/encoding/models.ts deleted file mode 100644 index 51089b14d..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/encoding/models.ts +++ /dev/null @@ -1,10 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * TextMarshaler is the interface implemented by an object that can - * marshal itself into a textual form. - * - * MarshalText encodes the receiver into UTF-8-encoded text and returns the result. - */ -export type TextMarshaler = any; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/eventcreate.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/eventcreate.ts deleted file mode 100644 index 71a208a3d..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/eventcreate.ts +++ /dev/null @@ -1,9 +0,0 @@ -//@ts-check -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Create as $Create } from "/wails/runtime.js"; - -Object.freeze($Create.Events); diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/eventdata.d.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/eventdata.d.ts deleted file mode 100644 index be1730836..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/eventdata.d.ts +++ /dev/null @@ -1,30 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import type { Events } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import type * as json$0 from "../../../../../encoding/json/models.js"; -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import type * as events_only$0 from "./generator/testcases/events_only/models.js"; -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import type * as more$0 from "./generator/testcases/no_bindings_here/more/models.js"; - -declare module "/wails/runtime.js" { - namespace Events { - interface CustomEvents { - "events_only:class": events_only$0.SomeClass; - "events_only:map": { [_ in string]?: number[] | null } | null; - "events_only:nodata": void; - "events_only:other": more$0.StringPtr[] | null; - "events_only:string": string; - "interface": json$0.Marshaler; - "overlap": {"Field": boolean[] | null} | null; - } - } -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/aliases/greetservice.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/aliases/greetservice.ts deleted file mode 100644 index ba719d105..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/aliases/greetservice.ts +++ /dev/null @@ -1,59 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as nobindingshere$0 from "../no_bindings_here/models.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * Get someone. - */ -export function Get(aliasValue: $models.Alias): $CancellablePromise<$models.Person> { - return $Call.ByName("main.GreetService.Get", aliasValue); -} - -/** - * Apparently, aliases are all the rage right now. - */ -export function GetButAliased(p: $models.AliasedPerson): $CancellablePromise<$models.StrangelyAliasedPerson> { - return $Call.ByName("main.GreetService.GetButAliased", p); -} - -/** - * Get someone quite different. - */ -export function GetButDifferent(): $CancellablePromise<$models.GenericPerson> { - return $Call.ByName("main.GreetService.GetButDifferent"); -} - -export function GetButForeignPrivateAlias(): $CancellablePromise { - return $Call.ByName("main.GreetService.GetButForeignPrivateAlias"); -} - -export function GetButGenericAliases(): $CancellablePromise<$models.AliasGroup> { - return $Call.ByName("main.GreetService.GetButGenericAliases"); -} - -export function GetButSubPackageAlias(): $CancellablePromise<$models.SubPackageAlias> { - return $Call.ByName("main.GreetService.GetButSubPackageAlias"); -} - -/** - * Greet a lot of unusual things. - */ -export function Greet($0: $models.EmptyAliasStruct, $1: $models.EmptyStruct): $CancellablePromise<$models.AliasStruct> { - return $Call.ByName("main.GreetService.Greet", $0, $1); -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/aliases/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/aliases/index.ts deleted file mode 100644 index fe7bfae7b..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/aliases/index.ts +++ /dev/null @@ -1,27 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; - -export type { - Alias, - AliasGroup, - AliasStruct, - AliasedPerson, - EmptyAliasStruct, - EmptyStruct, - GenericAlias, - GenericMapAlias, - GenericPerson, - GenericPersonAlias, - GenericPtrAlias, - IndirectPersonAlias, - OtherAliasStruct, - Person, - StrangelyAliasedPerson, - SubPackageAlias, - TPIndirectPersonAlias -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/aliases/models.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/aliases/models.ts deleted file mode 100644 index 32e6d64cb..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/aliases/models.ts +++ /dev/null @@ -1,135 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as subpkg$0 from "./subpkg/models.js"; - -/** - * A nice type Alias. - */ -export type Alias = number; - -/** - * A class whose fields have various aliased types. - */ -export interface AliasGroup { - "GAi": GenericAlias; - "GAP": GenericAlias>; - "GPAs": GenericPtrAlias; - "GPAP": GenericPtrAlias>; - "GMA": GenericMapAlias; - "GPA": GenericPersonAlias; - "IPA": IndirectPersonAlias; - "TPIPA": TPIndirectPersonAlias; - "SPA": SubPackageAlias; -} - -/** - * A struct alias. - * This should be rendered as a typedef or interface in every mode. - */ -export interface AliasStruct { - /** - * A field with a comment. - */ - "Foo": number[] | null; - - /** - * Definitely not Foo. - */ - "Bar"?: string; - "Baz"?: string; - - /** - * A nested alias struct. - */ - "Other": OtherAliasStruct; -} - -/** - * A class alias. - */ -export type AliasedPerson = Person; - -/** - * An empty struct alias. - */ -export interface EmptyAliasStruct { -} - -/** - * An empty struct. - */ -export interface EmptyStruct { -} - -/** - * A generic alias that forwards to a type parameter. - */ -export type GenericAlias = T; - -/** - * A generic alias that wraps a map. - */ -export type GenericMapAlias = { [_ in string]?: U } | null; - -/** - * A generic struct containing an alias. - */ -export interface GenericPerson { - "Name": T; - "AliasedField": Alias; -} - -/** - * A generic alias that wraps a generic struct. - */ -export type GenericPersonAlias = GenericPerson[] | null>; - -/** - * A generic alias that wraps a pointer type. - */ -export type GenericPtrAlias = GenericAlias | null; - -/** - * An alias that wraps a class through a non-typeparam alias. - */ -export type IndirectPersonAlias = GenericPersonAlias; - -/** - * Another struct alias. - */ -export interface OtherAliasStruct { - "NoMoreIdeas": number[] | null; -} - -/** - * A non-generic struct containing an alias. - */ -export interface Person { - /** - * The Person's name. - */ - "Name": string; - - /** - * A random alias field. - */ - "AliasedField": Alias; -} - -/** - * Another class alias, but ordered after its aliased class. - */ -export type StrangelyAliasedPerson = Person; - -/** - * An alias referencing another package that is not used elsewhere. - */ -export type SubPackageAlias = subpkg$0.SubStruct; - -/** - * An alias that wraps a class through a typeparam alias. - */ -export type TPIndirectPersonAlias = GenericAlias>; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/aliases/subpkg/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/aliases/subpkg/index.ts deleted file mode 100644 index 842f00546..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/aliases/subpkg/index.ts +++ /dev/null @@ -1,6 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -export type { - SubStruct -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/aliases/subpkg/models.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/aliases/subpkg/models.ts deleted file mode 100644 index 729b548db..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/aliases/subpkg/models.ts +++ /dev/null @@ -1,9 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * SubStruct is a type in a subpackage that is only referenced through an alias. - */ -export interface SubStruct { - "SomeField": string[] | null; -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_expressions/config/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_expressions/config/index.ts deleted file mode 100644 index bdcf43c67..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_expressions/config/index.ts +++ /dev/null @@ -1,9 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as Service7 from "./service7.js"; -import * as Service9 from "./service9.js"; -export { - Service7, - Service9 -}; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_expressions/config/service7.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_expressions/config/service7.ts deleted file mode 100644 index e4281d925..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_expressions/config/service7.ts +++ /dev/null @@ -1,10 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -export function TestMethod(): $CancellablePromise { - return $Call.ByName("github.com/wailsapp/wails/v3/internal/generator/testcases/complex_expressions/config.Service7.TestMethod"); -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_expressions/config/service9.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_expressions/config/service9.ts deleted file mode 100644 index 1c0154b5e..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_expressions/config/service9.ts +++ /dev/null @@ -1,10 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -export function TestMethod2(): $CancellablePromise { - return $Call.ByName("github.com/wailsapp/wails/v3/internal/generator/testcases/complex_expressions/config.Service9.TestMethod2"); -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_json/greetservice.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_json/greetservice.ts deleted file mode 100644 index 9eff81e94..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_json/greetservice.ts +++ /dev/null @@ -1,22 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * Greet does XYZ - */ -export function Greet(person: $models.Person, emb: $models.Embedded1): $CancellablePromise { - return $Call.ByName("main.GreetService.Greet", person, emb); -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_json/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_json/index.ts deleted file mode 100644 index f645e5730..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_json/index.ts +++ /dev/null @@ -1,17 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; - -export { - Title -} from "./models.js"; - -export type { - Embedded1, - Embedded3, - Person -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_json/models.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_json/models.ts deleted file mode 100644 index 7cdb88164..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_json/models.ts +++ /dev/null @@ -1,121 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -export interface Embedded1 { - /** - * Friends should be shadowed in Person by a field of lesser depth - */ - "Friends": number; - - /** - * Vanish should be omitted from Person because there is another field with same depth and no tag - */ - "Vanish": number; - - /** - * StillThere should be shadowed in Person by other field with same depth and a json tag - */ - "StillThere": string; - - /** - * NamingThingsIsHard is a law of programming - */ - "NamingThingsIsHard": `${boolean}`; -} - -export type Embedded3 = string; - -/** - * Person represents a person - */ -export interface Person { - /** - * Titles is optional in JSON - */ - "Titles"?: Title[] | null; - - /** - * Names has a - * multiline comment - */ - "Names": string[] | null; - - /** - * Partner has a custom and complex JSON key - */ - "Partner": Person | null; - "Friends": (Person | null)[] | null; - - /** - * NamingThingsIsHard is a law of programming - */ - "NamingThingsIsHard": `${boolean}`; - - /** - * StillThereButRenamed should shadow in Person the other field with same depth and no json tag - */ - "StillThere": Embedded3 | null; - - /** - * StrangeNumber maps to "-" - */ - "-": number; - - /** - * Embedded3 should appear with key "Embedded3" - */ - "Embedded3": Embedded3; - - /** - * StrangerNumber is serialized as a string - */ - "StrangerNumber": `${number}`; - - /** - * StrangestString is optional and serialized as a JSON string - */ - "StrangestString"?: `"${string}"`; - - /** - * StringStrangest is serialized as a JSON string and optional - */ - "StringStrangest"?: `"${string}"`; - - /** - * embedded4 should be optional and appear with key "emb4" - */ - "emb4"?: embedded4; -} - -/** - * Title is a title - */ -export enum Title { - /** - * The Go zero value for the underlying type of the enum. - */ - $zero = "", - - /** - * Mister is a title - */ - Mister = "Mr", - Miss = "Miss", - Ms = "Ms", - Mrs = "Mrs", - Dr = "Dr", -}; - -export interface embedded4 { - /** - * NamingThingsIsHard is a law of programming - */ - "NamingThingsIsHard": `${boolean}`; - - /** - * Friends should not be shadowed in Person as embedded4 is not embedded - * from encoding/json's point of view; - * however, it should be shadowed in Embedded1 - */ - "Friends": boolean; -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_method/greetservice.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_method/greetservice.ts deleted file mode 100644 index db3c98f3d..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_method/greetservice.ts +++ /dev/null @@ -1,24 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * Greet does XYZ - * It has a multiline doc comment - * The comment has even some * / traps!! - */ -export function Greet(str: string, people: $models.Person[] | null, $2: {"AnotherCount": number, "AnotherOne": $models.Person | null}, assoc: { [_ in `${number}`]?: boolean | null } | null, $4: (number | null)[] | null, ...other: string[]): $CancellablePromise<[$models.Person, any, number[] | null]> { - return $Call.ByName("main.GreetService.Greet", str, people, $2, assoc, $4, other); -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_method/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_method/index.ts deleted file mode 100644 index 14252454b..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_method/index.ts +++ /dev/null @@ -1,11 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; - -export type { - Person -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_method/models.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_method/models.ts deleted file mode 100644 index 6691fb86c..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/complex_method/models.ts +++ /dev/null @@ -1,9 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * Person represents a person - */ -export interface Person { - "Name": string; -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/cyclic_imports/greetservice.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/cyclic_imports/greetservice.ts deleted file mode 100644 index 52f87997c..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/cyclic_imports/greetservice.ts +++ /dev/null @@ -1,22 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * Make a cycle. - */ -export function MakeCycles(): $CancellablePromise<[$models.StructA, $models.StructC]> { - return $Call.ByName("main.GreetService.MakeCycles"); -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/cyclic_imports/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/cyclic_imports/index.ts deleted file mode 100644 index bbf592890..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/cyclic_imports/index.ts +++ /dev/null @@ -1,13 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; - -export type { - StructA, - StructC, - StructE -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/cyclic_imports/models.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/cyclic_imports/models.ts deleted file mode 100644 index 256987ac8..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/cyclic_imports/models.ts +++ /dev/null @@ -1,21 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -export interface StructA { - "B": structB | null; -} - -export interface StructC { - "D": structD; -} - -export interface StructE { -} - -export interface structB { - "A": StructA | null; -} - -export interface structD { - "E": StructE; -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/cyclic_types/greetservice.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/cyclic_types/greetservice.ts deleted file mode 100644 index b7ef0ae3e..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/cyclic_types/greetservice.ts +++ /dev/null @@ -1,22 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * Make a cycle. - */ -export function MakeCycles(): $CancellablePromise<[$models.Cyclic, $models.GenericCyclic<$models.GenericCyclic>]> { - return $Call.ByName("main.GreetService.MakeCycles"); -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/cyclic_types/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/cyclic_types/index.ts deleted file mode 100644 index 16cef660c..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/cyclic_types/index.ts +++ /dev/null @@ -1,13 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; - -export type { - Alias, - Cyclic, - GenericCyclic -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/cyclic_types/models.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/cyclic_types/models.ts deleted file mode 100644 index 56d3f00ec..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/cyclic_types/models.ts +++ /dev/null @@ -1,8 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -export type Alias = Cyclic | null; - -export type Cyclic = ({ [_ in string]?: Alias } | null)[] | null; - -export type GenericCyclic = {"X": GenericCyclic | null, "Y": T[] | null}[] | null; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/index.ts deleted file mode 100644 index bb2426022..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/index.ts +++ /dev/null @@ -1,13 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as Service from "./service.js"; -export { - Service -}; - -console.log("Hello everywhere!"); -console.log("Hello everywhere again!"); -console.log("Hello Interfaces!"); -console.log("Hello TS!"); -console.log("Hello TS Interfaces!"); diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/internalservice.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/internalservice.ts deleted file mode 100644 index faca61bc2..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/internalservice.ts +++ /dev/null @@ -1,19 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * An exported but internal service. - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -export function Method($0: $models.InternalModel): $CancellablePromise { - return $Call.ByName("main.InternalService.Method", $0); -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/models.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/models.ts deleted file mode 100644 index efe76e58b..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/models.ts +++ /dev/null @@ -1,16 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * An exported but internal model. - */ -export interface InternalModel { - "Field": string; -} - -/** - * An unexported model. - */ -export interface unexportedModel { - "Field": string; -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/otherpackage/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/otherpackage/index.ts deleted file mode 100644 index 82d89784a..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/otherpackage/index.ts +++ /dev/null @@ -1,6 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -export type { - Dummy -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/otherpackage/models.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/otherpackage/models.ts deleted file mode 100644 index 71070d754..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/otherpackage/models.ts +++ /dev/null @@ -1,5 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -export interface Dummy { -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/service.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/service.ts deleted file mode 100644 index 84ac0538c..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/service.ts +++ /dev/null @@ -1,22 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as otherpackage$0 from "./otherpackage/models.js"; - -function InternalMethod($0: string): $CancellablePromise { - return $Call.ByName("main.Service.InternalMethod", $0); -} - -export function VisibleMethod($0: otherpackage$0.Dummy): $CancellablePromise { - return $Call.ByName("main.Service.VisibleMethod", $0); -} - -export async function CustomMethod(arg: string): Promise { - await InternalMethod("Hello " + arg + "!"); -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/test.js b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/test.js deleted file mode 100644 index 138385f53..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/test.js +++ /dev/null @@ -1,3 +0,0 @@ -import { CustomMethod } from "./service.js"; - -CustomMethod("everywhere"); diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/test_all.js b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/test_all.js deleted file mode 100644 index 19d5c2f42..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/test_all.js +++ /dev/null @@ -1,3 +0,0 @@ -import { CustomMethod } from "./service.js"; - -CustomMethod("everywhere again"); diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/test_i.js b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/test_i.js deleted file mode 100644 index 442f20472..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/test_i.js +++ /dev/null @@ -1,3 +0,0 @@ -import { CustomMethod } from "./service.js"; - -CustomMethod("Interfaces"); diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/test_t.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/test_t.ts deleted file mode 100644 index 253d3f2f6..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/test_t.ts +++ /dev/null @@ -1,3 +0,0 @@ -import { CustomMethod } from "./service.js"; - -CustomMethod("TS"); diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/test_ti.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/test_ti.ts deleted file mode 100644 index 7400e97aa..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/test_ti.ts +++ /dev/null @@ -1,3 +0,0 @@ -import { CustomMethod } from "./service.js"; - -CustomMethod("TS Interfaces"); diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/unexportedservice.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/unexportedservice.ts deleted file mode 100644 index b49239ada..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/directives/unexportedservice.ts +++ /dev/null @@ -1,19 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * An unexported service. - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -export function Method($0: $models.unexportedModel): $CancellablePromise { - return $Call.ByName("main.unexportedService.Method", $0); -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/embedded_interface/greetservice.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/embedded_interface/greetservice.ts deleted file mode 100644 index 4951af01d..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/embedded_interface/greetservice.ts +++ /dev/null @@ -1,47 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -/** - * Comment 1. - */ -export function Method1(): $CancellablePromise { - return $Call.ByName("main.GreetService.Method1"); -} - -/** - * Comment 2. - */ -export function Method2(): $CancellablePromise { - return $Call.ByName("main.GreetService.Method2"); -} - -/** - * Comment 3a. - * Comment 3b. - */ -export function Method3(): $CancellablePromise { - return $Call.ByName("main.GreetService.Method3"); -} - -/** - * Comment 4. - */ -export function Method4(): $CancellablePromise { - return $Call.ByName("main.GreetService.Method4"); -} - -/** - * Comment 5. - */ -export function Method5(): $CancellablePromise { - return $Call.ByName("main.GreetService.Method5"); -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/embedded_interface/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/embedded_interface/index.ts deleted file mode 100644 index 50e3f0435..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/embedded_interface/index.ts +++ /dev/null @@ -1,7 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/enum/greetservice.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/enum/greetservice.ts deleted file mode 100644 index d857aa9e7..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/enum/greetservice.ts +++ /dev/null @@ -1,29 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * Greet does XYZ - */ -export function Greet(name: string, title: $models.Title): $CancellablePromise { - return $Call.ByName("main.GreetService.Greet", name, title); -} - -/** - * NewPerson creates a new person - */ -export function NewPerson(name: string): $CancellablePromise<$models.Person | null> { - return $Call.ByName("main.GreetService.NewPerson", name); -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/enum/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/enum/index.ts deleted file mode 100644 index e66941c16..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/enum/index.ts +++ /dev/null @@ -1,16 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; - -export { - Age, - Title -} from "./models.js"; - -export type { - Person -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/enum/models.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/enum/models.ts deleted file mode 100644 index 74d673e16..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/enum/models.ts +++ /dev/null @@ -1,55 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * Age is an integer with some predefined values - */ -export type Age = number; - -/** - * Predefined constants for type Age. - * @namespace - */ -export const Age = { - NewBorn: 0, - Teenager: 12, - YoungAdult: 18, - - /** - * Oh no, some grey hair! - */ - MiddleAged: 50, - - /** - * Unbelievable! - */ - Mathusalem: 1000, -}; - -/** - * Person represents a person - */ -export interface Person { - "Title": Title; - "Name": string; - "Age": Age; -} - -/** - * Title is a title - */ -export enum Title { - /** - * The Go zero value for the underlying type of the enum. - */ - $zero = "", - - /** - * Mister is a title - */ - Mister = "Mr", - Miss = "Miss", - Ms = "Ms", - Mrs = "Mrs", - Dr = "Dr", -}; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_from_imported_package/greetservice.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_from_imported_package/greetservice.ts deleted file mode 100644 index 73469c39d..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_from_imported_package/greetservice.ts +++ /dev/null @@ -1,22 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as services$0 from "./services/models.js"; - -/** - * Greet does XYZ - */ -export function Greet(name: string, title: services$0.Title): $CancellablePromise { - return $Call.ByName("main.GreetService.Greet", name, title); -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_from_imported_package/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_from_imported_package/index.ts deleted file mode 100644 index 50e3f0435..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_from_imported_package/index.ts +++ /dev/null @@ -1,7 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_from_imported_package/services/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_from_imported_package/services/index.ts deleted file mode 100644 index 01c612edc..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_from_imported_package/services/index.ts +++ /dev/null @@ -1,6 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -export { - Title -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_from_imported_package/services/models.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_from_imported_package/services/models.ts deleted file mode 100644 index 887aee9ba..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_from_imported_package/services/models.ts +++ /dev/null @@ -1,18 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -export enum Title { - /** - * The Go zero value for the underlying type of the enum. - */ - $zero = "", - - /** - * Mister is a title - */ - Mister = "Mr", - Miss = "Miss", - Ms = "Ms", - Mrs = "Mrs", - Dr = "Dr", -}; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_map_keys/enummapservice.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_map_keys/enummapservice.ts deleted file mode 100644 index c2654cb89..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_map_keys/enummapservice.ts +++ /dev/null @@ -1,57 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * EnumMapService tests various enum map key scenarios - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * GetColorCodes returns a map with uint8 enum keys - */ -export function GetColorCodes(): $CancellablePromise<{ [_ in $models.Color]?: string } | null> { - return $Call.ByName("main.EnumMapService.GetColorCodes"); -} - -/** - * GetNestedEnumMap returns a map with enum keys and complex values - */ -export function GetNestedEnumMap(): $CancellablePromise<{ [_ in $models.Status]?: { [_ in $models.Priority]?: string } | null } | null> { - return $Call.ByName("main.EnumMapService.GetNestedEnumMap"); -} - -/** - * GetOptionalEnumMap returns a map with enum keys to optional values - */ -export function GetOptionalEnumMap(): $CancellablePromise<{ [_ in $models.Status]?: string | null } | null> { - return $Call.ByName("main.EnumMapService.GetOptionalEnumMap"); -} - -/** - * GetPersonsByStatus returns a map with enum keys to struct values - */ -export function GetPersonsByStatus(): $CancellablePromise<{ [_ in $models.Status]?: $models.Person[] | null } | null> { - return $Call.ByName("main.EnumMapService.GetPersonsByStatus"); -} - -/** - * GetPriorityWeights returns a map with integer enum keys - */ -export function GetPriorityWeights(): $CancellablePromise<{ [_ in $models.Priority]?: number } | null> { - return $Call.ByName("main.EnumMapService.GetPriorityWeights"); -} - -/** - * GetStatusMessages returns a map with string enum keys - */ -export function GetStatusMessages(): $CancellablePromise<{ [_ in $models.Status]?: string } | null> { - return $Call.ByName("main.EnumMapService.GetStatusMessages"); -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_map_keys/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_map_keys/index.ts deleted file mode 100644 index cf39671cf..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_map_keys/index.ts +++ /dev/null @@ -1,17 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as EnumMapService from "./enummapservice.js"; -export { - EnumMapService -}; - -export { - Color, - Priority, - Status -} from "./models.js"; - -export type { - Person -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_map_keys/models.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_map_keys/models.ts deleted file mode 100644 index a2fe209a5..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/enum_map_keys/models.ts +++ /dev/null @@ -1,53 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * Color represents color values - */ -export enum Color { - /** - * The Go zero value for the underlying type of the enum. - */ - $zero = 0, - - Red = 1, - Green = 2, - Blue = 3, -}; - -/** - * Person represents a person with status - */ -export interface Person { - "Name": string; - "Status": Status; -} - -/** - * Priority represents priority levels - */ -export enum Priority { - /** - * The Go zero value for the underlying type of the enum. - */ - $zero = 0, - - PriorityLow = 1, - PriorityMedium = 2, - PriorityHigh = 3, -}; - -/** - * Status represents different status values - */ -export enum Status { - /** - * The Go zero value for the underlying type of the enum. - */ - $zero = "", - - StatusPending = "pending", - StatusRunning = "running", - StatusCompleted = "completed", - StatusFailed = "failed", -}; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/events_only/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/events_only/index.ts deleted file mode 100644 index 03b13d1cf..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/events_only/index.ts +++ /dev/null @@ -1,6 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -export type { - SomeClass -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/events_only/models.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/events_only/models.ts deleted file mode 100644 index 316f1bd22..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/events_only/models.ts +++ /dev/null @@ -1,14 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as nobindingshere$0 from "../no_bindings_here/models.js"; - -/** - * SomeClass renders as a TS class. - */ -export interface SomeClass { - "Field": string; - "Meadow": nobindingshere$0.HowDifferent; -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_imported_package/greetservice.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_imported_package/greetservice.ts deleted file mode 100644 index 5a8e9adc3..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_imported_package/greetservice.ts +++ /dev/null @@ -1,29 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * Greet does XYZ - */ -export function Greet(name: string): $CancellablePromise { - return $Call.ByName("main.GreetService.Greet", name); -} - -/** - * NewPerson creates a new person - */ -export function NewPerson(name: string): $CancellablePromise<$models.Person | null> { - return $Call.ByName("main.GreetService.NewPerson", name); -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_imported_package/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_imported_package/index.ts deleted file mode 100644 index 14252454b..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_imported_package/index.ts +++ /dev/null @@ -1,11 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; - -export type { - Person -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_imported_package/models.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_imported_package/models.ts deleted file mode 100644 index 99b989f07..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_imported_package/models.ts +++ /dev/null @@ -1,14 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as services$0 from "./services/models.js"; - -/** - * Person is a person - */ -export interface Person { - "Name": string; - "Address": services$0.Address | null; -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_imported_package/services/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_imported_package/services/index.ts deleted file mode 100644 index 8857d2bc5..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_imported_package/services/index.ts +++ /dev/null @@ -1,11 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as OtherService from "./otherservice.js"; -export { - OtherService -}; - -export type { - Address -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_imported_package/services/models.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_imported_package/services/models.ts deleted file mode 100644 index b76080cf3..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_imported_package/services/models.ts +++ /dev/null @@ -1,8 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -export interface Address { - "Street": string; - "State": string; - "Country": string; -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_imported_package/services/otherservice.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_imported_package/services/otherservice.ts deleted file mode 100644 index c6db3803b..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_imported_package/services/otherservice.ts +++ /dev/null @@ -1,23 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * OtherService is a struct - * that does things - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * Yay does this and that - */ -export function Yay(): $CancellablePromise<$models.Address | null> { - return $Call.ByName("github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_imported_package/services.OtherService.Yay"); -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_nested_imported_package/greetservice.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_nested_imported_package/greetservice.ts deleted file mode 100644 index 5a8e9adc3..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_nested_imported_package/greetservice.ts +++ /dev/null @@ -1,29 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * Greet does XYZ - */ -export function Greet(name: string): $CancellablePromise { - return $Call.ByName("main.GreetService.Greet", name); -} - -/** - * NewPerson creates a new person - */ -export function NewPerson(name: string): $CancellablePromise<$models.Person | null> { - return $Call.ByName("main.GreetService.NewPerson", name); -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_nested_imported_package/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_nested_imported_package/index.ts deleted file mode 100644 index 14252454b..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_nested_imported_package/index.ts +++ /dev/null @@ -1,11 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; - -export type { - Person -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_nested_imported_package/models.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_nested_imported_package/models.ts deleted file mode 100644 index 70b85519b..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_nested_imported_package/models.ts +++ /dev/null @@ -1,11 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as other$0 from "./services/other/models.js"; - -export interface Person { - "Name": string; - "Address": other$0.Address | null; -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_nested_imported_package/services/other/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_nested_imported_package/services/other/index.ts deleted file mode 100644 index 8857d2bc5..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_nested_imported_package/services/other/index.ts +++ /dev/null @@ -1,11 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as OtherService from "./otherservice.js"; -export { - OtherService -}; - -export type { - Address -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_nested_imported_package/services/other/models.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_nested_imported_package/services/other/models.ts deleted file mode 100644 index b76080cf3..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_nested_imported_package/services/other/models.ts +++ /dev/null @@ -1,8 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -export interface Address { - "Street": string; - "State": string; - "Country": string; -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_nested_imported_package/services/other/otherservice.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_nested_imported_package/services/other/otherservice.ts deleted file mode 100644 index b83ce5234..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_nested_imported_package/services/other/otherservice.ts +++ /dev/null @@ -1,23 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * OtherService is a struct - * that does things - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * Yay does this and that - */ -export function Yay(): $CancellablePromise<$models.Address | null> { - return $Call.ByName("github.com/wailsapp/wails/v3/internal/generator/testcases/function_from_nested_imported_package/services/other.OtherService.Yay"); -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_multiple_files/greetservice.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_multiple_files/greetservice.ts deleted file mode 100644 index 41664b850..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_multiple_files/greetservice.ts +++ /dev/null @@ -1,10 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -export function Greet(name: string): $CancellablePromise { - return $Call.ByName("main.GreetService.Greet", name); -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_multiple_files/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_multiple_files/index.ts deleted file mode 100644 index 50e3f0435..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_multiple_files/index.ts +++ /dev/null @@ -1,7 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single/greetservice.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single/greetservice.ts deleted file mode 100644 index 80bebe425..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single/greetservice.ts +++ /dev/null @@ -1,18 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -/** - * Greet someone - */ -export function Greet(name: string): $CancellablePromise { - return $Call.ByName("main.GreetService.Greet", name); -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single/index.ts deleted file mode 100644 index 50e3f0435..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single/index.ts +++ /dev/null @@ -1,7 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single_context/greetservice.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single_context/greetservice.ts deleted file mode 100644 index 63a65248c..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single_context/greetservice.ts +++ /dev/null @@ -1,25 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -/** - * Greet someone - */ -export function Greet(name: string): $CancellablePromise { - return $Call.ByName("main.GreetService.Greet", name); -} - -/** - * Greet someone - */ -export function GreetWithContext(name: string): $CancellablePromise { - return $Call.ByName("main.GreetService.GreetWithContext", name); -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single_context/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single_context/index.ts deleted file mode 100644 index 50e3f0435..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single_context/index.ts +++ /dev/null @@ -1,7 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single_internal/greetservice.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single_internal/greetservice.ts deleted file mode 100644 index 80bebe425..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single_internal/greetservice.ts +++ /dev/null @@ -1,18 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -/** - * Greet someone - */ -export function Greet(name: string): $CancellablePromise { - return $Call.ByName("main.GreetService.Greet", name); -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single_internal/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single_internal/index.ts deleted file mode 100644 index 50e3f0435..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/function_single_internal/index.ts +++ /dev/null @@ -1,7 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys/index.ts deleted file mode 100644 index de52fd90d..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys/index.ts +++ /dev/null @@ -1,32 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as Service from "./service.js"; -export { - Service -}; - -export type { - BasicCstrAlias, - ComparableCstrAlias, - EmbeddedCustomInterface, - EmbeddedOriginalInterface, - EmbeddedPointer, - EmbeddedPointerPtr, - EmbeddedValue, - EmbeddedValuePtr, - GoodTildeCstrAlias, - IntAlias, - IntType, - InterfaceCstrAlias, - Maps, - MixedCstrAlias, - NonBasicCstrAlias, - PointableCstrAlias, - PointerAlias, - PointerTextMarshaler, - StringAlias, - StringType, - ValueAlias, - ValueTextMarshaler -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys/models.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys/models.ts deleted file mode 100644 index 2f0b0330d..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys/models.ts +++ /dev/null @@ -1,771 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -export type BasicCstrAlias = S; - -export type ComparableCstrAlias = R; - -export type EmbeddedCustomInterface = string; - -export type EmbeddedOriginalInterface = string; - -export type EmbeddedPointer = string; - -export type EmbeddedPointerPtr = string; - -export type EmbeddedValue = string; - -export type EmbeddedValuePtr = string; - -export type GoodTildeCstrAlias = U; - -export type IntAlias = number; - -export type IntType = number; - -export type InterfaceCstrAlias = Y; - -export interface Maps { - /** - * Reject - */ - "Bool": { [_ in string]?: number } | null; - - /** - * Accept - */ - "Int": { [_ in `${number}`]?: number } | null; - - /** - * Accept - */ - "Uint": { [_ in `${number}`]?: number } | null; - - /** - * Reject - */ - "Float": { [_ in string]?: number } | null; - - /** - * Reject - */ - "Complex": { [_ in string]?: number } | null; - - /** - * Accept - */ - "Byte": { [_ in `${number}`]?: number } | null; - - /** - * Accept - */ - "Rune": { [_ in `${number}`]?: number } | null; - - /** - * Accept - */ - "String": { [_ in string]?: number } | null; - - /** - * Reject - */ - "IntPtr": { [_ in string]?: number } | null; - - /** - * Reject - */ - "UintPtr": { [_ in string]?: number } | null; - - /** - * Reject - */ - "FloatPtr": { [_ in string]?: number } | null; - - /** - * Reject - */ - "ComplexPtr": { [_ in string]?: number } | null; - - /** - * Reject - */ - "StringPtr": { [_ in string]?: number } | null; - - /** - * Reject - */ - "NTM": { [_ in string]?: number } | null; - - /** - * Reject - */ - "NTMPtr": { [_ in string]?: number } | null; - - /** - * Accept - */ - "VTM": { [_ in ValueTextMarshaler]?: number } | null; - - /** - * Accept - */ - "VTMPtr": { [_ in ValueTextMarshaler]?: number } | null; - - /** - * Reject - */ - "PTM": { [_ in string]?: number } | null; - - /** - * Accept - */ - "PTMPtr": { [_ in PointerTextMarshaler]?: number } | null; - - /** - * Accept, hide - */ - "JTM": { [_ in string]?: number } | null; - - /** - * Accept, hide - */ - "JTMPtr": { [_ in string]?: number } | null; - - /** - * Reject - */ - "A": { [_ in string]?: number } | null; - - /** - * Reject - */ - "APtr": { [_ in string]?: number } | null; - - /** - * Accept, hide - */ - "TM": { [_ in string]?: number } | null; - - /** - * Reject - */ - "TMPtr": { [_ in string]?: number } | null; - - /** - * Accept, hide - */ - "CI": { [_ in string]?: number } | null; - - /** - * Reject - */ - "CIPtr": { [_ in string]?: number } | null; - - /** - * Accept, hide - */ - "EI": { [_ in string]?: number } | null; - - /** - * Reject - */ - "EIPtr": { [_ in string]?: number } | null; - - /** - * Accept - */ - "EV": { [_ in EmbeddedValue]?: number } | null; - - /** - * Accept - */ - "EVPtr": { [_ in EmbeddedValue]?: number } | null; - - /** - * Accept - */ - "EVP": { [_ in EmbeddedValuePtr]?: number } | null; - - /** - * Accept - */ - "EVPPtr": { [_ in EmbeddedValuePtr]?: number } | null; - - /** - * Reject - */ - "EP": { [_ in string]?: number } | null; - - /** - * Accept - */ - "EPPtr": { [_ in EmbeddedPointer]?: number } | null; - - /** - * Accept - */ - "EPP": { [_ in EmbeddedPointerPtr]?: number } | null; - - /** - * Accept - */ - "EPPPtr": { [_ in EmbeddedPointerPtr]?: number } | null; - - /** - * Accept - */ - "ECI": { [_ in EmbeddedCustomInterface]?: number } | null; - - /** - * Accept - */ - "ECIPtr": { [_ in EmbeddedCustomInterface]?: number } | null; - - /** - * Accept - */ - "EOI": { [_ in EmbeddedOriginalInterface]?: number } | null; - - /** - * Accept - */ - "EOIPtr": { [_ in EmbeddedOriginalInterface]?: number } | null; - - /** - * Reject - */ - "WT": { [_ in string]?: number } | null; - - /** - * Reject - */ - "WA": { [_ in string]?: number } | null; - - /** - * Accept - */ - "ST": { [_ in StringType]?: number } | null; - - /** - * Accept - */ - "SA": { [_ in StringAlias]?: number } | null; - - /** - * Accept - */ - "IntT": { [_ in IntType]?: number } | null; - - /** - * Accept - */ - "IntA": { [_ in IntAlias]?: number } | null; - - /** - * Reject - */ - "VT": { [_ in string]?: number } | null; - - /** - * Reject - */ - "VTPtr": { [_ in string]?: number } | null; - - /** - * Reject - */ - "VPT": { [_ in string]?: number } | null; - - /** - * Reject - */ - "VPTPtr": { [_ in string]?: number } | null; - - /** - * Accept - */ - "VA": { [_ in ValueAlias]?: number } | null; - - /** - * Accept - */ - "VAPtr": { [_ in ValueAlias]?: number } | null; - - /** - * Accept, hide - */ - "VPA": { [_ in string]?: number } | null; - - /** - * Reject - */ - "VPAPtr": { [_ in string]?: number } | null; - - /** - * Reject - */ - "PT": { [_ in string]?: number } | null; - - /** - * Reject - */ - "PTPtr": { [_ in string]?: number } | null; - - /** - * Reject - */ - "PPT": { [_ in string]?: number } | null; - - /** - * Reject - */ - "PPTPtr": { [_ in string]?: number } | null; - - /** - * Reject - */ - "PA": { [_ in string]?: number } | null; - - /** - * Accept - */ - "PAPtr": { [_ in PointerAlias]?: number } | null; - - /** - * Accept, hide - */ - "PPA": { [_ in string]?: number } | null; - - /** - * Reject - */ - "PPAPtr": { [_ in string]?: number } | null; - - /** - * Accept, hide - */ - "IT": { [_ in string]?: number } | null; - - /** - * Reject - */ - "ITPtr": { [_ in string]?: number } | null; - - /** - * Reject - */ - "IPT": { [_ in string]?: number } | null; - - /** - * Reject - */ - "IPTPtr": { [_ in string]?: number } | null; - - /** - * Accept, hide - */ - "IA": { [_ in string]?: number } | null; - - /** - * Reject - */ - "IAPtr": { [_ in string]?: number } | null; - - /** - * Reject - */ - "IPA": { [_ in string]?: number } | null; - - /** - * Reject - */ - "IPAPtr": { [_ in string]?: number } | null; - - /** - * Soft reject - */ - "TPR": { [_ in string]?: number } | null; - - /** - * Soft reject - */ - "TPRPtr": { [_ in string]?: number } | null; - - /** - * Accept, hide - */ - "TPS": { [_ in string]?: number } | null; - - /** - * Soft reject - */ - "TPSPtr": { [_ in string]?: number } | null; - - /** - * Soft reject - */ - "TPT": { [_ in string]?: number } | null; - - /** - * Soft reject - */ - "TPTPtr": { [_ in string]?: number } | null; - - /** - * Accept, hide - */ - "TPU": { [_ in string]?: number } | null; - - /** - * Soft reject - */ - "TPUPtr": { [_ in string]?: number } | null; - - /** - * Accept, hide - */ - "TPV": { [_ in string]?: number } | null; - - /** - * Soft reject - */ - "TPVPtr": { [_ in string]?: number } | null; - - /** - * Soft reject - */ - "TPW": { [_ in string]?: number } | null; - - /** - * Accept, hide - */ - "TPWPtr": { [_ in string]?: number } | null; - - /** - * Accept, hide - */ - "TPX": { [_ in string]?: number } | null; - - /** - * Soft reject - */ - "TPXPtr": { [_ in string]?: number } | null; - - /** - * Accept, hide - */ - "TPY": { [_ in string]?: number } | null; - - /** - * Soft reject - */ - "TPYPtr": { [_ in string]?: number } | null; - - /** - * Accept, hide - */ - "TPZ": { [_ in string]?: number } | null; - - /** - * Soft reject - */ - "TPZPtr": { [_ in string]?: number } | null; - - /** - * Soft reject - */ - "GAR": { [_ in string]?: number } | null; - - /** - * Soft reject - */ - "GARPtr": { [_ in string]?: number } | null; - - /** - * Accept, hide - */ - "GAS": { [_ in string]?: number } | null; - - /** - * Soft reject - */ - "GASPtr": { [_ in string]?: number } | null; - - /** - * Soft reject - */ - "GAT": { [_ in string]?: number } | null; - - /** - * Soft reject - */ - "GATPtr": { [_ in string]?: number } | null; - - /** - * Accept, hide - */ - "GAU": { [_ in string]?: number } | null; - - /** - * Soft reject - */ - "GAUPtr": { [_ in string]?: number } | null; - - /** - * Accept, hide - */ - "GAV": { [_ in string]?: number } | null; - - /** - * Soft reject - */ - "GAVPtr": { [_ in string]?: number } | null; - - /** - * Soft reject - */ - "GAW": { [_ in string]?: number } | null; - - /** - * Accept, hide - */ - "GAWPtr": { [_ in string]?: number } | null; - - /** - * Accept, hide - */ - "GAX": { [_ in string]?: number } | null; - - /** - * Soft reject - */ - "GAXPtr": { [_ in string]?: number } | null; - - /** - * Accept, hide - */ - "GAY": { [_ in string]?: number } | null; - - /** - * Soft reject - */ - "GAYPtr": { [_ in string]?: number } | null; - - /** - * Accept, hide - */ - "GAZ": { [_ in string]?: number } | null; - - /** - * Soft reject - */ - "GAZPtr": { [_ in string]?: number } | null; - - /** - * Accept - */ - "GACi": { [_ in ComparableCstrAlias]?: number } | null; - - /** - * Accept - */ - "GACV": { [_ in ComparableCstrAlias]?: number } | null; - - /** - * Reject - */ - "GACP": { [_ in string]?: number } | null; - - /** - * Reject - */ - "GACiPtr": { [_ in string]?: number } | null; - - /** - * Accept, hide - */ - "GACVPtr": { [_ in string]?: number } | null; - - /** - * Accept, hide - */ - "GACPPtr": { [_ in string]?: number } | null; - - /** - * Accept - */ - "GABi": { [_ in BasicCstrAlias]?: number } | null; - - /** - * Accept - */ - "GABs": { [_ in BasicCstrAlias]?: number } | null; - - /** - * Reject - */ - "GABiPtr": { [_ in string]?: number } | null; - - /** - * Reject - */ - "GABT": { [_ in string]?: number } | null; - - /** - * Reject - */ - "GABTPtr": { [_ in string]?: number } | null; - - /** - * Accept - */ - "GAGT": { [_ in GoodTildeCstrAlias]?: number } | null; - - /** - * Accept, hide - */ - "GAGTPtr": { [_ in string]?: number } | null; - - /** - * Accept - */ - "GANBV": { [_ in NonBasicCstrAlias]?: number } | null; - - /** - * Accept, hide - */ - "GANBP": { [_ in string]?: number } | null; - - /** - * Accept, hide - */ - "GANBVPtr": { [_ in string]?: number } | null; - - /** - * Reject - */ - "GANBPPtr": { [_ in string]?: number } | null; - - /** - * Accept - */ - "GAPlV1": { [_ in PointableCstrAlias]?: number } | null; - - /** - * Accept - */ - "GAPlV2": { [_ in PointableCstrAlias]?: number } | null; - - /** - * Reject - */ - "GAPlP1": { [_ in string]?: number } | null; - - /** - * Accept - */ - "GAPlP2": { [_ in PointableCstrAlias]?: number } | null; - - /** - * Accept, hide - */ - "GAPlVPtr": { [_ in string]?: number } | null; - - /** - * Accept, hide - */ - "GAPlPPtr": { [_ in string]?: number } | null; - - /** - * Accept - */ - "GAMi": { [_ in MixedCstrAlias]?: number } | null; - - /** - * Accept - */ - "GAMS": { [_ in MixedCstrAlias]?: number } | null; - - /** - * Accept - */ - "GAMV": { [_ in MixedCstrAlias]?: number } | null; - - /** - * Reject - */ - "GAMSPtr": { [_ in string]?: number } | null; - - /** - * Accept, hide - */ - "GAMVPtr": { [_ in string]?: number } | null; - - /** - * Accept, hide - */ - "GAII": { [_ in string]?: number } | null; - - /** - * Accept - */ - "GAIV": { [_ in InterfaceCstrAlias]?: number } | null; - - /** - * Accept, hide - */ - "GAIP": { [_ in string]?: number } | null; - - /** - * Reject - */ - "GAIIPtr": { [_ in string]?: number } | null; - - /** - * Accept, hide - */ - "GAIVPtr": { [_ in string]?: number } | null; - - /** - * Reject - */ - "GAIPPtr": { [_ in string]?: number } | null; - - /** - * Accept, hide - */ - "GAPrV": { [_ in string]?: number } | null; - - /** - * Accept, hide - */ - "GAPrP": { [_ in string]?: number } | null; - - /** - * Reject - */ - "GAPrVPtr": { [_ in string]?: number } | null; - - /** - * Reject - */ - "GAPrPPtr": { [_ in string]?: number } | null; -} - -export type MixedCstrAlias = X; - -export type NonBasicCstrAlias = V; - -export type PointableCstrAlias = W; - -export type PointerAlias = PointerTextMarshaler; - -export type PointerTextMarshaler = string; - -export type StringAlias = string; - -export type StringType = string; - -export type ValueAlias = ValueTextMarshaler; - -export type ValueTextMarshaler = string; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys/service.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys/service.ts deleted file mode 100644 index 7b59b53ed..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys/service.ts +++ /dev/null @@ -1,14 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -export function Method(): $CancellablePromise<$models.Maps<$models.PointerTextMarshaler, number, number, $models.ValueTextMarshaler, $models.PointerTextMarshaler | null, $models.ValueTextMarshaler, $models.StringType, $models.ValueTextMarshaler, $models.PointerTextMarshaler | null>> { - return $Call.ByName("main.Service.Method"); -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/marshalers/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/marshalers/index.ts deleted file mode 100644 index 7c55b767b..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/marshalers/index.ts +++ /dev/null @@ -1,33 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as Service from "./service.js"; -export { - Service -}; - -export type { - AliasJsonMarshaler, - AliasMarshaler, - AliasNonMarshaler, - AliasTextMarshaler, - Data, - ImplicitJsonButText, - ImplicitJsonMarshaler, - ImplicitMarshaler, - ImplicitNonJson, - ImplicitNonMarshaler, - ImplicitNonText, - ImplicitTextButJson, - ImplicitTextMarshaler, - NonMarshaler, - PointerJsonMarshaler, - PointerMarshaler, - PointerTextMarshaler, - UnderlyingJsonMarshaler, - UnderlyingMarshaler, - UnderlyingTextMarshaler, - ValueJsonMarshaler, - ValueMarshaler, - ValueTextMarshaler -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/marshalers/models.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/marshalers/models.ts deleted file mode 100644 index 02d639994..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/marshalers/models.ts +++ /dev/null @@ -1,309 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as encoding$0 from "../../../../../../../../encoding/models.js"; -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as json$0 from "../../../../../../../../encoding/json/models.js"; - -/** - * any - */ -export type AliasJsonMarshaler = any; - -/** - * any - */ -export type AliasMarshaler = any; - -/** - * struct{} - */ -export interface AliasNonMarshaler { -} - -/** - * string - */ -export type AliasTextMarshaler = string; - -export interface Data { - "NM": NonMarshaler; - - /** - * NonMarshaler | null - */ - "NMPtr": NonMarshaler | null; - "VJM": ValueJsonMarshaler; - - /** - * ValueJsonMarshaler | null - */ - "VJMPtr": ValueJsonMarshaler | null; - "PJM": PointerJsonMarshaler; - - /** - * PointerJsonMarshaler | null - */ - "PJMPtr": PointerJsonMarshaler | null; - "VTM": ValueTextMarshaler; - - /** - * ValueTextMarshaler | null - */ - "VTMPtr": ValueTextMarshaler | null; - "PTM": PointerTextMarshaler; - - /** - * PointerTextMarshaler | null - */ - "PTMPtr": PointerTextMarshaler | null; - "VM": ValueMarshaler; - - /** - * ValueMarshaler | null - */ - "VMPtr": ValueMarshaler | null; - "PM": PointerMarshaler; - - /** - * PointerMarshaler | null - */ - "PMPtr": PointerMarshaler | null; - "UJM": UnderlyingJsonMarshaler; - - /** - * UnderlyingJsonMarshaler | null - */ - "UJMPtr": UnderlyingJsonMarshaler | null; - "UTM": UnderlyingTextMarshaler; - - /** - * UnderlyingTextMarshaler | null - */ - "UTMPtr": UnderlyingTextMarshaler | null; - "UM": UnderlyingMarshaler; - - /** - * UnderlyingMarshaler | null - */ - "UMPtr": UnderlyingMarshaler | null; - - /** - * any - */ - "JM": any; - - /** - * any | null - */ - "JMPtr": any | null; - - /** - * string - */ - "TM": string; - - /** - * string | null - */ - "TMPtr": string | null; - - /** - * any - */ - "CJM": any; - - /** - * any | null - */ - "CJMPtr": any | null; - - /** - * string - */ - "CTM": string; - - /** - * string | null - */ - "CTMPtr": string | null; - - /** - * any - */ - "CM": any; - - /** - * any | null - */ - "CMPtr": any | null; - "ANM": AliasNonMarshaler; - - /** - * AliasNonMarshaler | null - */ - "ANMPtr": AliasNonMarshaler | null; - "AJM": AliasJsonMarshaler; - - /** - * AliasJsonMarshaler | null - */ - "AJMPtr": AliasJsonMarshaler | null; - "ATM": AliasTextMarshaler; - - /** - * AliasTextMarshaler | null - */ - "ATMPtr": AliasTextMarshaler | null; - "AM": AliasMarshaler; - - /** - * AliasMarshaler | null - */ - "AMPtr": AliasMarshaler | null; - "ImJM": ImplicitJsonMarshaler; - - /** - * ImplicitJsonMarshaler | null - */ - "ImJMPtr": ImplicitJsonMarshaler | null; - "ImTM": ImplicitTextMarshaler; - - /** - * ImplicitTextMarshaler | null - */ - "ImTMPtr": ImplicitTextMarshaler | null; - "ImM": ImplicitMarshaler; - - /** - * ImplicitMarshaler | null - */ - "ImMPtr": ImplicitMarshaler | null; - "ImNJ": ImplicitNonJson; - - /** - * ImplicitNonJson | null - */ - "ImNJPtr": ImplicitNonJson | null; - "ImNT": ImplicitNonText; - - /** - * ImplicitNonText | null - */ - "ImNTPtr": ImplicitNonText | null; - "ImNM": ImplicitNonMarshaler; - - /** - * ImplicitNonMarshaler | null - */ - "ImNMPtr": ImplicitNonMarshaler | null; - "ImJbT": ImplicitJsonButText; - - /** - * ImplicitJsonButText | null - */ - "ImJbTPtr": ImplicitJsonButText | null; - "ImTbJ": ImplicitTextButJson; - - /** - * ImplicitTextButJson | null - */ - "ImTbJPtr": ImplicitTextButJson | null; -} - -/** - * any - */ -export type ImplicitJsonButText = any; - -/** - * any - */ -export type ImplicitJsonMarshaler = any; - -/** - * any - */ -export type ImplicitMarshaler = any; - -/** - * string - */ -export type ImplicitNonJson = string; - -/** - * class{ Marshaler, TextMarshaler } - */ -export interface ImplicitNonMarshaler { - "Marshaler": json$0.Marshaler; - "TextMarshaler": encoding$0.TextMarshaler; -} - -/** - * any - */ -export type ImplicitNonText = any; - -/** - * any - */ -export type ImplicitTextButJson = any; - -/** - * string - */ -export type ImplicitTextMarshaler = string; - -/** - * class {} - */ -export interface NonMarshaler { -} - -/** - * any - */ -export type PointerJsonMarshaler = any; - -/** - * any - */ -export type PointerMarshaler = any; - -/** - * string - */ -export type PointerTextMarshaler = string; - -/** - * any - */ -export type UnderlyingJsonMarshaler = any; - -/** - * any - */ -export type UnderlyingMarshaler = any; - -/** - * string - */ -export type UnderlyingTextMarshaler = string; - -/** - * any - */ -export type ValueJsonMarshaler = any; - -/** - * any - */ -export type ValueMarshaler = any; - -/** - * string - */ -export type ValueTextMarshaler = string; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/marshalers/service.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/marshalers/service.ts deleted file mode 100644 index 0de2fecd5..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/marshalers/service.ts +++ /dev/null @@ -1,14 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -export function Method(): $CancellablePromise<$models.Data> { - return $Call.ByName("main.Service.Method"); -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/index.ts deleted file mode 100644 index bf611e486..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/index.ts +++ /dev/null @@ -1,14 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as SomeMethods from "./somemethods.js"; -export { - SomeMethods -}; - -export type { - HowDifferent, - Impersonator, - Person, - PrivatePerson -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/models.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/models.ts deleted file mode 100644 index 45c7f2785..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/models.ts +++ /dev/null @@ -1,64 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as other$0 from "./other/models.js"; - -/** - * HowDifferent is a curious kind of person - * that lets other people decide how they are different. - */ -export interface HowDifferent { - /** - * They have a name as well. - */ - "Name": string; - - /** - * But they may have many differences. - */ - "Differences": ({ [_ in string]?: How } | null)[] | null; -} - -/** - * Impersonator gets their fields from other people. - */ -export type Impersonator = other$0.OtherPerson; - -/** - * Person is not a number. - */ -export interface Person { - /** - * They have a name. - */ - "Name": string; - - /** - * Exactly 4 sketchy friends. - */ - "Friends": Impersonator[]; -} - -/** - * PrivatePerson gets their fields from hidden sources. - */ -export type PrivatePerson = personImpl; - -export interface personImpl { - /** - * Nickname conceals a person's identity. - */ - "Nickname": string; - - /** - * They have a name. - */ - "Name": string; - - /** - * Exactly 4 sketchy friends. - */ - "Friends": Impersonator[]; -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/more/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/more/index.ts deleted file mode 100644 index ac743f356..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/more/index.ts +++ /dev/null @@ -1,6 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -export type { - StringPtr -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/more/models.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/more/models.ts deleted file mode 100644 index 6a5a12300..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/more/models.ts +++ /dev/null @@ -1,7 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * StringPtr is a nullable string. - */ -export type StringPtr = string | null; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/other/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/other/index.ts deleted file mode 100644 index b9f2889db..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/other/index.ts +++ /dev/null @@ -1,11 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as OtherMethods from "./othermethods.js"; -export { - OtherMethods -}; - -export type { - OtherPerson -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/other/models.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/other/models.ts deleted file mode 100644 index 6ca5b82a2..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/other/models.ts +++ /dev/null @@ -1,17 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * OtherPerson is like a person, but different. - */ -export interface OtherPerson { - /** - * They have a name as well. - */ - "Name": string; - - /** - * But they may have many differences. - */ - "Differences": T[] | null; -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/other/othermethods.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/other/othermethods.ts deleted file mode 100644 index e6638332a..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/other/othermethods.ts +++ /dev/null @@ -1,18 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * OtherMethods has another method, but through a private embedded type. - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -/** - * LikeThisOtherOne does nothing as well, but is different. - */ -export function LikeThisOtherOne(): $CancellablePromise { - return $Call.ByName("github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/other.OtherMethods.LikeThisOtherOne"); -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/somemethods.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/somemethods.ts deleted file mode 100644 index e37a596df..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here/somemethods.ts +++ /dev/null @@ -1,29 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * SomeMethods exports some methods. - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * LikeThisOne is an example method that does nothing. - */ -export function LikeThisOne(): $CancellablePromise<[$models.Person, $models.HowDifferent, $models.PrivatePerson]> { - return $Call.ByName("github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here.SomeMethods.LikeThisOne"); -} - -/** - * LikeThisOtherOne does nothing as well, but is different. - */ -export function LikeThisOtherOne(): $CancellablePromise { - return $Call.ByName("github.com/wailsapp/wails/v3/internal/generator/testcases/no_bindings_here.SomeMethods.LikeThisOtherOne"); -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/out_of_tree/embedother.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/out_of_tree/embedother.ts deleted file mode 100644 index ec7619bfc..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/out_of_tree/embedother.ts +++ /dev/null @@ -1,18 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * EmbedOther is even trickier. - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -/** - * LikeThisOtherOne does nothing as well, but is different. - */ -export function LikeThisOtherOne(): $CancellablePromise { - return $Call.ByName("main.EmbedOther.LikeThisOtherOne"); -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/out_of_tree/embedservice.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/out_of_tree/embedservice.ts deleted file mode 100644 index 680b028b4..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/out_of_tree/embedservice.ts +++ /dev/null @@ -1,29 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * EmbedService is tricky. - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as nobindingshere$0 from "../no_bindings_here/models.js"; - -/** - * LikeThisOne is an example method that does nothing. - */ -export function LikeThisOne(): $CancellablePromise<[nobindingshere$0.Person, nobindingshere$0.HowDifferent, nobindingshere$0.PrivatePerson]> { - return $Call.ByName("main.EmbedService.LikeThisOne"); -} - -/** - * LikeThisOtherOne does nothing as well, but is different. - */ -export function LikeThisOtherOne(): $CancellablePromise { - return $Call.ByName("main.EmbedService.LikeThisOtherOne"); -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/out_of_tree/greetservice.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/out_of_tree/greetservice.ts deleted file mode 100644 index 4166b32f7..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/out_of_tree/greetservice.ts +++ /dev/null @@ -1,18 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -/** - * Greet someone - */ -export function Greet($0: string): $CancellablePromise { - return $Call.ByName("main.GreetService.Greet", $0); -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/out_of_tree/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/out_of_tree/index.ts deleted file mode 100644 index e69bebf3b..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/out_of_tree/index.ts +++ /dev/null @@ -1,11 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as EmbedOther from "./embedother.js"; -import * as EmbedService from "./embedservice.js"; -import * as GreetService from "./greetservice.js"; -export { - EmbedOther, - EmbedService, - GreetService -}; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple/greetservice.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple/greetservice.ts deleted file mode 100644 index 41664b850..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple/greetservice.ts +++ /dev/null @@ -1,10 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -export function Greet(name: string): $CancellablePromise { - return $Call.ByName("main.GreetService.Greet", name); -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple/index.ts deleted file mode 100644 index 5c4ebea4f..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple/index.ts +++ /dev/null @@ -1,9 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -import * as OtherService from "./otherservice.js"; -export { - GreetService, - OtherService -}; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple/otherservice.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple/otherservice.ts deleted file mode 100644 index 5a733e6c9..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple/otherservice.ts +++ /dev/null @@ -1,10 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -export function Hello(): $CancellablePromise { - return $Call.ByName("main.OtherService.Hello"); -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_files/greetservice.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_files/greetservice.ts deleted file mode 100644 index 41664b850..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_files/greetservice.ts +++ /dev/null @@ -1,10 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -export function Greet(name: string): $CancellablePromise { - return $Call.ByName("main.GreetService.Greet", name); -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_files/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_files/index.ts deleted file mode 100644 index 5c4ebea4f..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_files/index.ts +++ /dev/null @@ -1,9 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -import * as OtherService from "./otherservice.js"; -export { - GreetService, - OtherService -}; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_files/otherservice.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_files/otherservice.ts deleted file mode 100644 index 5a733e6c9..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_files/otherservice.ts +++ /dev/null @@ -1,10 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -export function Hello(): $CancellablePromise { - return $Call.ByName("main.OtherService.Hello"); -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_other/greetservice.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_other/greetservice.ts deleted file mode 100644 index 5a8e9adc3..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_other/greetservice.ts +++ /dev/null @@ -1,29 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * Greet does XYZ - */ -export function Greet(name: string): $CancellablePromise { - return $Call.ByName("main.GreetService.Greet", name); -} - -/** - * NewPerson creates a new person - */ -export function NewPerson(name: string): $CancellablePromise<$models.Person | null> { - return $Call.ByName("main.GreetService.NewPerson", name); -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_other/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_other/index.ts deleted file mode 100644 index 14252454b..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_other/index.ts +++ /dev/null @@ -1,11 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; - -export type { - Person -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_other/models.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_other/models.ts deleted file mode 100644 index 3ab21d612..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_other/models.ts +++ /dev/null @@ -1,11 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as services$0 from "./services/models.js"; - -export interface Person { - "Name": string; - "Address": services$0.Address | null; -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_other/services/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_other/services/index.ts deleted file mode 100644 index 8857d2bc5..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_other/services/index.ts +++ /dev/null @@ -1,11 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as OtherService from "./otherservice.js"; -export { - OtherService -}; - -export type { - Address -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_other/services/models.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_other/services/models.ts deleted file mode 100644 index b76080cf3..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_other/services/models.ts +++ /dev/null @@ -1,8 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -export interface Address { - "Street": string; - "State": string; - "Country": string; -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_other/services/otherservice.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_other/services/otherservice.ts deleted file mode 100644 index 018d8df30..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_other/services/otherservice.ts +++ /dev/null @@ -1,23 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * OtherService is a struct - * that does things - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * Yay does this and that - */ -export function Yay(): $CancellablePromise<$models.Address | null> { - return $Call.ByName("github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_multiple_other/services.OtherService.Yay"); -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_non_pointer_single/greetservice.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_non_pointer_single/greetservice.ts deleted file mode 100644 index 19cbead4e..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_non_pointer_single/greetservice.ts +++ /dev/null @@ -1,190 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -export function ArrayInt($in: number[]): $CancellablePromise { - return $Call.ByName("main.GreetService.ArrayInt", $in); -} - -export function BoolInBoolOut($in: boolean): $CancellablePromise { - return $Call.ByName("main.GreetService.BoolInBoolOut", $in); -} - -export function Float32InFloat32Out($in: number): $CancellablePromise { - return $Call.ByName("main.GreetService.Float32InFloat32Out", $in); -} - -export function Float64InFloat64Out($in: number): $CancellablePromise { - return $Call.ByName("main.GreetService.Float64InFloat64Out", $in); -} - -/** - * Greet someone - */ -export function Greet(name: string): $CancellablePromise { - return $Call.ByName("main.GreetService.Greet", name); -} - -export function Int16InIntOut($in: number): $CancellablePromise { - return $Call.ByName("main.GreetService.Int16InIntOut", $in); -} - -export function Int16PointerInAndOutput($in: number | null): $CancellablePromise { - return $Call.ByName("main.GreetService.Int16PointerInAndOutput", $in); -} - -export function Int32InIntOut($in: number): $CancellablePromise { - return $Call.ByName("main.GreetService.Int32InIntOut", $in); -} - -export function Int32PointerInAndOutput($in: number | null): $CancellablePromise { - return $Call.ByName("main.GreetService.Int32PointerInAndOutput", $in); -} - -export function Int64InIntOut($in: number): $CancellablePromise { - return $Call.ByName("main.GreetService.Int64InIntOut", $in); -} - -export function Int64PointerInAndOutput($in: number | null): $CancellablePromise { - return $Call.ByName("main.GreetService.Int64PointerInAndOutput", $in); -} - -export function Int8InIntOut($in: number): $CancellablePromise { - return $Call.ByName("main.GreetService.Int8InIntOut", $in); -} - -export function Int8PointerInAndOutput($in: number | null): $CancellablePromise { - return $Call.ByName("main.GreetService.Int8PointerInAndOutput", $in); -} - -export function IntInIntOut($in: number): $CancellablePromise { - return $Call.ByName("main.GreetService.IntInIntOut", $in); -} - -export function IntPointerInAndOutput($in: number | null): $CancellablePromise { - return $Call.ByName("main.GreetService.IntPointerInAndOutput", $in); -} - -export function IntPointerInputNamedOutputs($in: number | null): $CancellablePromise { - return $Call.ByName("main.GreetService.IntPointerInputNamedOutputs", $in); -} - -export function MapIntInt($in: { [_ in `${number}`]?: number } | null): $CancellablePromise { - return $Call.ByName("main.GreetService.MapIntInt", $in); -} - -export function MapIntIntPointer($in: { [_ in `${number}`]?: number | null } | null): $CancellablePromise { - return $Call.ByName("main.GreetService.MapIntIntPointer", $in); -} - -export function MapIntSliceInt($in: { [_ in `${number}`]?: number[] | null } | null): $CancellablePromise { - return $Call.ByName("main.GreetService.MapIntSliceInt", $in); -} - -export function MapIntSliceIntInMapIntSliceIntOut($in: { [_ in `${number}`]?: number[] | null } | null): $CancellablePromise<{ [_ in `${number}`]?: number[] | null } | null> { - return $Call.ByName("main.GreetService.MapIntSliceIntInMapIntSliceIntOut", $in); -} - -export function NoInputsStringOut(): $CancellablePromise { - return $Call.ByName("main.GreetService.NoInputsStringOut"); -} - -export function PointerBoolInBoolOut($in: boolean | null): $CancellablePromise { - return $Call.ByName("main.GreetService.PointerBoolInBoolOut", $in); -} - -export function PointerFloat32InFloat32Out($in: number | null): $CancellablePromise { - return $Call.ByName("main.GreetService.PointerFloat32InFloat32Out", $in); -} - -export function PointerFloat64InFloat64Out($in: number | null): $CancellablePromise { - return $Call.ByName("main.GreetService.PointerFloat64InFloat64Out", $in); -} - -export function PointerMapIntInt($in: { [_ in `${number}`]?: number } | null): $CancellablePromise { - return $Call.ByName("main.GreetService.PointerMapIntInt", $in); -} - -export function PointerStringInStringOut($in: string | null): $CancellablePromise { - return $Call.ByName("main.GreetService.PointerStringInStringOut", $in); -} - -export function StringArrayInputNamedOutput($in: string[] | null): $CancellablePromise { - return $Call.ByName("main.GreetService.StringArrayInputNamedOutput", $in); -} - -export function StringArrayInputNamedOutputs($in: string[] | null): $CancellablePromise { - return $Call.ByName("main.GreetService.StringArrayInputNamedOutputs", $in); -} - -export function StringArrayInputStringArrayOut($in: string[] | null): $CancellablePromise { - return $Call.ByName("main.GreetService.StringArrayInputStringArrayOut", $in); -} - -export function StringArrayInputStringOut($in: string[] | null): $CancellablePromise { - return $Call.ByName("main.GreetService.StringArrayInputStringOut", $in); -} - -export function StructInputStructOutput($in: $models.Person): $CancellablePromise<$models.Person> { - return $Call.ByName("main.GreetService.StructInputStructOutput", $in); -} - -export function StructPointerInputErrorOutput($in: $models.Person | null): $CancellablePromise { - return $Call.ByName("main.GreetService.StructPointerInputErrorOutput", $in); -} - -export function StructPointerInputStructPointerOutput($in: $models.Person | null): $CancellablePromise<$models.Person | null> { - return $Call.ByName("main.GreetService.StructPointerInputStructPointerOutput", $in); -} - -export function UInt16InUIntOut($in: number): $CancellablePromise { - return $Call.ByName("main.GreetService.UInt16InUIntOut", $in); -} - -export function UInt16PointerInAndOutput($in: number | null): $CancellablePromise { - return $Call.ByName("main.GreetService.UInt16PointerInAndOutput", $in); -} - -export function UInt32InUIntOut($in: number): $CancellablePromise { - return $Call.ByName("main.GreetService.UInt32InUIntOut", $in); -} - -export function UInt32PointerInAndOutput($in: number | null): $CancellablePromise { - return $Call.ByName("main.GreetService.UInt32PointerInAndOutput", $in); -} - -export function UInt64InUIntOut($in: number): $CancellablePromise { - return $Call.ByName("main.GreetService.UInt64InUIntOut", $in); -} - -export function UInt64PointerInAndOutput($in: number | null): $CancellablePromise { - return $Call.ByName("main.GreetService.UInt64PointerInAndOutput", $in); -} - -export function UInt8InUIntOut($in: number): $CancellablePromise { - return $Call.ByName("main.GreetService.UInt8InUIntOut", $in); -} - -export function UInt8PointerInAndOutput($in: number | null): $CancellablePromise { - return $Call.ByName("main.GreetService.UInt8PointerInAndOutput", $in); -} - -export function UIntInUIntOut($in: number): $CancellablePromise { - return $Call.ByName("main.GreetService.UIntInUIntOut", $in); -} - -export function UIntPointerInAndOutput($in: number | null): $CancellablePromise { - return $Call.ByName("main.GreetService.UIntPointerInAndOutput", $in); -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_non_pointer_single/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_non_pointer_single/index.ts deleted file mode 100644 index 14252454b..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_non_pointer_single/index.ts +++ /dev/null @@ -1,11 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; - -export type { - Person -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_non_pointer_single/models.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_non_pointer_single/models.ts deleted file mode 100644 index 5664b79ab..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_non_pointer_single/models.ts +++ /dev/null @@ -1,8 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -export interface Person { - "Name": string; - "Parent": Person | null; - "Details": {"Age": number, "Address": {"Street": string}}; -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_single/greetservice.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_single/greetservice.ts deleted file mode 100644 index 19cbead4e..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_single/greetservice.ts +++ /dev/null @@ -1,190 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -export function ArrayInt($in: number[]): $CancellablePromise { - return $Call.ByName("main.GreetService.ArrayInt", $in); -} - -export function BoolInBoolOut($in: boolean): $CancellablePromise { - return $Call.ByName("main.GreetService.BoolInBoolOut", $in); -} - -export function Float32InFloat32Out($in: number): $CancellablePromise { - return $Call.ByName("main.GreetService.Float32InFloat32Out", $in); -} - -export function Float64InFloat64Out($in: number): $CancellablePromise { - return $Call.ByName("main.GreetService.Float64InFloat64Out", $in); -} - -/** - * Greet someone - */ -export function Greet(name: string): $CancellablePromise { - return $Call.ByName("main.GreetService.Greet", name); -} - -export function Int16InIntOut($in: number): $CancellablePromise { - return $Call.ByName("main.GreetService.Int16InIntOut", $in); -} - -export function Int16PointerInAndOutput($in: number | null): $CancellablePromise { - return $Call.ByName("main.GreetService.Int16PointerInAndOutput", $in); -} - -export function Int32InIntOut($in: number): $CancellablePromise { - return $Call.ByName("main.GreetService.Int32InIntOut", $in); -} - -export function Int32PointerInAndOutput($in: number | null): $CancellablePromise { - return $Call.ByName("main.GreetService.Int32PointerInAndOutput", $in); -} - -export function Int64InIntOut($in: number): $CancellablePromise { - return $Call.ByName("main.GreetService.Int64InIntOut", $in); -} - -export function Int64PointerInAndOutput($in: number | null): $CancellablePromise { - return $Call.ByName("main.GreetService.Int64PointerInAndOutput", $in); -} - -export function Int8InIntOut($in: number): $CancellablePromise { - return $Call.ByName("main.GreetService.Int8InIntOut", $in); -} - -export function Int8PointerInAndOutput($in: number | null): $CancellablePromise { - return $Call.ByName("main.GreetService.Int8PointerInAndOutput", $in); -} - -export function IntInIntOut($in: number): $CancellablePromise { - return $Call.ByName("main.GreetService.IntInIntOut", $in); -} - -export function IntPointerInAndOutput($in: number | null): $CancellablePromise { - return $Call.ByName("main.GreetService.IntPointerInAndOutput", $in); -} - -export function IntPointerInputNamedOutputs($in: number | null): $CancellablePromise { - return $Call.ByName("main.GreetService.IntPointerInputNamedOutputs", $in); -} - -export function MapIntInt($in: { [_ in `${number}`]?: number } | null): $CancellablePromise { - return $Call.ByName("main.GreetService.MapIntInt", $in); -} - -export function MapIntIntPointer($in: { [_ in `${number}`]?: number | null } | null): $CancellablePromise { - return $Call.ByName("main.GreetService.MapIntIntPointer", $in); -} - -export function MapIntSliceInt($in: { [_ in `${number}`]?: number[] | null } | null): $CancellablePromise { - return $Call.ByName("main.GreetService.MapIntSliceInt", $in); -} - -export function MapIntSliceIntInMapIntSliceIntOut($in: { [_ in `${number}`]?: number[] | null } | null): $CancellablePromise<{ [_ in `${number}`]?: number[] | null } | null> { - return $Call.ByName("main.GreetService.MapIntSliceIntInMapIntSliceIntOut", $in); -} - -export function NoInputsStringOut(): $CancellablePromise { - return $Call.ByName("main.GreetService.NoInputsStringOut"); -} - -export function PointerBoolInBoolOut($in: boolean | null): $CancellablePromise { - return $Call.ByName("main.GreetService.PointerBoolInBoolOut", $in); -} - -export function PointerFloat32InFloat32Out($in: number | null): $CancellablePromise { - return $Call.ByName("main.GreetService.PointerFloat32InFloat32Out", $in); -} - -export function PointerFloat64InFloat64Out($in: number | null): $CancellablePromise { - return $Call.ByName("main.GreetService.PointerFloat64InFloat64Out", $in); -} - -export function PointerMapIntInt($in: { [_ in `${number}`]?: number } | null): $CancellablePromise { - return $Call.ByName("main.GreetService.PointerMapIntInt", $in); -} - -export function PointerStringInStringOut($in: string | null): $CancellablePromise { - return $Call.ByName("main.GreetService.PointerStringInStringOut", $in); -} - -export function StringArrayInputNamedOutput($in: string[] | null): $CancellablePromise { - return $Call.ByName("main.GreetService.StringArrayInputNamedOutput", $in); -} - -export function StringArrayInputNamedOutputs($in: string[] | null): $CancellablePromise { - return $Call.ByName("main.GreetService.StringArrayInputNamedOutputs", $in); -} - -export function StringArrayInputStringArrayOut($in: string[] | null): $CancellablePromise { - return $Call.ByName("main.GreetService.StringArrayInputStringArrayOut", $in); -} - -export function StringArrayInputStringOut($in: string[] | null): $CancellablePromise { - return $Call.ByName("main.GreetService.StringArrayInputStringOut", $in); -} - -export function StructInputStructOutput($in: $models.Person): $CancellablePromise<$models.Person> { - return $Call.ByName("main.GreetService.StructInputStructOutput", $in); -} - -export function StructPointerInputErrorOutput($in: $models.Person | null): $CancellablePromise { - return $Call.ByName("main.GreetService.StructPointerInputErrorOutput", $in); -} - -export function StructPointerInputStructPointerOutput($in: $models.Person | null): $CancellablePromise<$models.Person | null> { - return $Call.ByName("main.GreetService.StructPointerInputStructPointerOutput", $in); -} - -export function UInt16InUIntOut($in: number): $CancellablePromise { - return $Call.ByName("main.GreetService.UInt16InUIntOut", $in); -} - -export function UInt16PointerInAndOutput($in: number | null): $CancellablePromise { - return $Call.ByName("main.GreetService.UInt16PointerInAndOutput", $in); -} - -export function UInt32InUIntOut($in: number): $CancellablePromise { - return $Call.ByName("main.GreetService.UInt32InUIntOut", $in); -} - -export function UInt32PointerInAndOutput($in: number | null): $CancellablePromise { - return $Call.ByName("main.GreetService.UInt32PointerInAndOutput", $in); -} - -export function UInt64InUIntOut($in: number): $CancellablePromise { - return $Call.ByName("main.GreetService.UInt64InUIntOut", $in); -} - -export function UInt64PointerInAndOutput($in: number | null): $CancellablePromise { - return $Call.ByName("main.GreetService.UInt64PointerInAndOutput", $in); -} - -export function UInt8InUIntOut($in: number): $CancellablePromise { - return $Call.ByName("main.GreetService.UInt8InUIntOut", $in); -} - -export function UInt8PointerInAndOutput($in: number | null): $CancellablePromise { - return $Call.ByName("main.GreetService.UInt8PointerInAndOutput", $in); -} - -export function UIntInUIntOut($in: number): $CancellablePromise { - return $Call.ByName("main.GreetService.UIntInUIntOut", $in); -} - -export function UIntPointerInAndOutput($in: number | null): $CancellablePromise { - return $Call.ByName("main.GreetService.UIntPointerInAndOutput", $in); -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_single/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_single/index.ts deleted file mode 100644 index 14252454b..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_single/index.ts +++ /dev/null @@ -1,11 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; - -export type { - Person -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_single/models.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_single/models.ts deleted file mode 100644 index 5664b79ab..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/struct_literal_single/models.ts +++ /dev/null @@ -1,8 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -export interface Person { - "Name": string; - "Parent": Person | null; - "Details": {"Age": number, "Address": {"Street": string}}; -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single/greetservice.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single/greetservice.ts deleted file mode 100644 index 80bebe425..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single/greetservice.ts +++ /dev/null @@ -1,18 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -/** - * Greet someone - */ -export function Greet(name: string): $CancellablePromise { - return $Call.ByName("main.GreetService.Greet", name); -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single/index.ts deleted file mode 100644 index 50e3f0435..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single/index.ts +++ /dev/null @@ -1,7 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_function/greetservice.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_function/greetservice.ts deleted file mode 100644 index 80bebe425..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_function/greetservice.ts +++ /dev/null @@ -1,18 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -/** - * Greet someone - */ -export function Greet(name: string): $CancellablePromise { - return $Call.ByName("main.GreetService.Greet", name); -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_function/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_function/index.ts deleted file mode 100644 index 50e3f0435..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_function/index.ts +++ /dev/null @@ -1,7 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_other_function/greetservice.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_other_function/greetservice.ts deleted file mode 100644 index 5a8e9adc3..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_other_function/greetservice.ts +++ /dev/null @@ -1,29 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * GreetService is great - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * Greet does XYZ - */ -export function Greet(name: string): $CancellablePromise { - return $Call.ByName("main.GreetService.Greet", name); -} - -/** - * NewPerson creates a new person - */ -export function NewPerson(name: string): $CancellablePromise<$models.Person | null> { - return $Call.ByName("main.GreetService.NewPerson", name); -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_other_function/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_other_function/index.ts deleted file mode 100644 index 14252454b..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_other_function/index.ts +++ /dev/null @@ -1,11 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as GreetService from "./greetservice.js"; -export { - GreetService -}; - -export type { - Person -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_other_function/models.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_other_function/models.ts deleted file mode 100644 index f29117203..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_other_function/models.ts +++ /dev/null @@ -1,15 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as services$0 from "./services/models.js"; - -/** - * Person is a person! - * They have a name and an address - */ -export interface Person { - "Name": string; - "Address": services$0.Address | null; -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_other_function/services/index.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_other_function/services/index.ts deleted file mode 100644 index 8857d2bc5..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_other_function/services/index.ts +++ /dev/null @@ -1,11 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -import * as OtherService from "./otherservice.js"; -export { - OtherService -}; - -export type { - Address -} from "./models.js"; diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_other_function/services/models.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_other_function/services/models.ts deleted file mode 100644 index b76080cf3..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_other_function/services/models.ts +++ /dev/null @@ -1,8 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -export interface Address { - "Street": string; - "State": string; - "Country": string; -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_other_function/services/otherservice.ts b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_other_function/services/otherservice.ts deleted file mode 100644 index c93f85314..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_other_function/services/otherservice.ts +++ /dev/null @@ -1,23 +0,0 @@ -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -/** - * OtherService is a struct - * that does things - * @module - */ - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import { Call as $Call, CancellablePromise as $CancellablePromise } from "/wails/runtime.js"; - -// eslint-disable-next-line @typescript-eslint/ban-ts-comment -// @ts-ignore: Unused imports -import * as $models from "./models.js"; - -/** - * Yay does this and that - */ -export function Yay(): $CancellablePromise<$models.Address | null> { - return $Call.ByName("github.com/wailsapp/wails/v3/internal/generator/testcases/variable_single_from_other_function/services.OtherService.Yay"); -} diff --git a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/warnings.log b/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/warnings.log deleted file mode 100644 index ce8369307..000000000 --- a/v3/internal/generator/testdata/output/lang=TS/UseInterfaces=true/UseNames=true/warnings.log +++ /dev/null @@ -1,83 +0,0 @@ -[warn] /testcases/complex_json/main.go:127:2: event 'collision' has one of multiple definitions here with data type map[string]int -[warn] /testcases/events_only/events.go:20:2: event 'collision' has one of multiple definitions here with data type int -[warn] /testcases/events_only/events.go:21:2: `application.RegisterEvent` called here with non-constant event name -[warn] /testcases/events_only/other.go:10:5: `application.RegisterEvent` is instantiated here but not called -[warn] /testcases/events_only/other.go:13:2: `application.RegisterEvent` called here with non-constant event name -[warn] /testcases/events_only/other.go:17:2: data type []T for event 'parametric' contains unresolved type parameters and will be ignored` -[warn] /testcases/events_only/other.go:22:2: event 'common:ApplicationStarted' is a known system event and cannot be overridden; this call to `application.RegisterEvent` will panic -[warn] /testcases/marshalers/main.go:212:2: event 'collision' has one of multiple definitions here with data type *struct{Field []bool} -[warn] /testcases/marshalers/main.go:214:2: data type encoding/json.Marshaler for event 'interface' is a non-empty interface: emitting events from the frontend with data other than `null` is not supported by encoding/json and will likely result in runtime errors -[warn] dynamically registered event names are not discoverable by the binding generator: it is recommended to invoke `application.RegisterEvent` with constant arguments only -[warn] event 'collision' has multiple conflicting definitions and will be ignored -[warn] events registered through indirect calls are not discoverable by the binding generator: it is recommended to invoke `application.RegisterEvent` directly -[warn] generic wrappers for calls to `application.RegisterEvent` are not analysable by the binding generator: it is recommended to call `application.RegisterEvent` with concrete types only -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *R is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *S is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *T is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *U is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *V is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *X is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *Y is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *Z is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *any is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *complex64 is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *encoding.TextMarshaler is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *float32 is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.CustomInterface is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.EmbeddedInterface is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.InterfaceAlias is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.InterfacePtrAlias is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.InterfacePtrType is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.InterfaceType is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.NonTextMarshaler is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.PointerPtrAlias is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.PointerPtrType is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.PointerType is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.ValuePtrAlias is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.ValuePtrType is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.ValueType is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *int is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *string is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type *uint is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type R is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type T is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type W is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type any is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type bool is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type complex64 is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type float32 is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.BadTildeCstrAlias[T] is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.BadTildeCstrAlias[struct{}] is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.BadTildeCstrPtrAlias[T] is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.BadTildeCstrPtrAlias[struct{}] is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.BasicCstrPtrAlias[S] is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.BasicCstrPtrAlias[int] is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.ComparableCstrAlias[R] is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.ComparableCstrAlias[github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.PointerTextMarshaler] is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.ComparableCstrPtrAlias[R] is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.ComparableCstrPtrAlias[int] is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.EmbeddedPointer is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.GoodTildeCstrPtrAlias[U] is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.InterfaceCstrPtrAlias[*github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.PointerTextMarshaler] is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.InterfaceCstrPtrAlias[Y] is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.InterfaceCstrPtrAlias[encoding.TextMarshaler] is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.InterfacePtrAlias is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.InterfacePtrType is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.MixedCstrPtrAlias[X] is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.MixedCstrPtrAlias[github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.StringType] is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.NonBasicCstrPtrAlias[*github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.PointerTextMarshaler] is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.NonBasicCstrPtrAlias[V] is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.NonTextMarshaler is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.PointableCstrAlias[W] is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.PointableCstrAlias[github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.PointerTextMarshaler] is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.PointerAlias is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.PointerCstrPtrAlias[R, Z] is used as a map key, but some of its instantiations might not implement encoding.TextMarshaler: this might result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.PointerCstrPtrAlias[github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.PointerTextMarshaler, *github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.PointerTextMarshaler] is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.PointerCstrPtrAlias[github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.ValueTextMarshaler, *github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.ValueTextMarshaler] is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.PointerPtrType is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.PointerTextMarshaler is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.PointerType is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.ValuePtrType is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.ValueType is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.WrongAlias is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors -[warn] package github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys: type github.com/wailsapp/wails/v3/internal/generator/testcases/map_keys.WrongType is used as a map key, but does not implement encoding.TextMarshaler: this will likely result in runtime errors diff --git a/v3/internal/generator/testdata/package-lock.json b/v3/internal/generator/testdata/package-lock.json deleted file mode 100644 index 80f5e0882..000000000 --- a/v3/internal/generator/testdata/package-lock.json +++ /dev/null @@ -1,2274 +0,0 @@ -{ - "name": "testdata", - "version": "0.0.0", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "testdata", - "version": "0.0.0", - "devDependencies": { - "madge": "^8.0.0", - "typescript": "^5.7.3" - } - }, - "node_modules/@babel/helper-string-parser": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz", - "integrity": "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-identifier": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz", - "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/parser": { - "version": "7.26.7", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.7.tgz", - "integrity": "sha512-kEvgGGgEjRUutvdVvZhbn/BxVt+5VSpwXz1j3WYXQbXDo8KzFOPNG2GQbdAiNq8g6wn1yKk7C/qrke03a84V+w==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/types": "^7.26.7" - }, - "bin": { - "parser": "bin/babel-parser.js" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@babel/types": { - "version": "7.26.7", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.7.tgz", - "integrity": "sha512-t8kDRGrKXyp6+tjUh7hw2RLyclsW4TRoRvRHtSyAX9Bb5ldlFh+90YAYY6awRXrlB4G5G2izNeGySpATlFzmOg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-string-parser": "^7.25.9", - "@babel/helper-validator-identifier": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@dependents/detective-less": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/@dependents/detective-less/-/detective-less-5.0.0.tgz", - "integrity": "sha512-D/9dozteKcutI5OdxJd8rU+fL6XgaaRg60sPPJWkT33OCiRfkCu5wO5B/yXTaaL2e6EB0lcCBGe5E0XscZCvvQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "gonzales-pe": "^4.3.0", - "node-source-walk": "^7.0.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", - "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@ts-graphviz/adapter": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/@ts-graphviz/adapter/-/adapter-2.0.6.tgz", - "integrity": "sha512-kJ10lIMSWMJkLkkCG5gt927SnGZcBuG0s0HHswGzcHTgvtUe7yk5/3zTEr0bafzsodsOq5Gi6FhQeV775nC35Q==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/ts-graphviz" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/ts-graphviz" - } - ], - "license": "MIT", - "dependencies": { - "@ts-graphviz/common": "^2.1.5" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/@ts-graphviz/ast": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/@ts-graphviz/ast/-/ast-2.0.7.tgz", - "integrity": "sha512-e6+2qtNV99UT6DJSoLbHfkzfyqY84aIuoV8Xlb9+hZAjgpum8iVHprGeAMQ4rF6sKUAxrmY8rfF/vgAwoPc3gw==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/ts-graphviz" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/ts-graphviz" - } - ], - "license": "MIT", - "dependencies": { - "@ts-graphviz/common": "^2.1.5" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/@ts-graphviz/common": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@ts-graphviz/common/-/common-2.1.5.tgz", - "integrity": "sha512-S6/9+T6x8j6cr/gNhp+U2olwo1n0jKj/682QVqsh7yXWV6ednHYqxFw0ZsY3LyzT0N8jaZ6jQY9YD99le3cmvg==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/ts-graphviz" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/ts-graphviz" - } - ], - "license": "MIT", - "engines": { - "node": ">=18" - } - }, - "node_modules/@ts-graphviz/core": { - "version": "2.0.7", - "resolved": "https://registry.npmjs.org/@ts-graphviz/core/-/core-2.0.7.tgz", - "integrity": "sha512-w071DSzP94YfN6XiWhOxnLpYT3uqtxJBDYdh6Jdjzt+Ce6DNspJsPQgpC7rbts/B8tEkq0LHoYuIF/O5Jh5rPg==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/ts-graphviz" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/ts-graphviz" - } - ], - "license": "MIT", - "dependencies": { - "@ts-graphviz/ast": "^2.0.7", - "@ts-graphviz/common": "^2.1.5" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/@typescript-eslint/types": { - "version": "7.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-7.18.0.tgz", - "integrity": "sha512-iZqi+Ds1y4EDYUtlOOC+aUmxnE9xS/yCigkjA7XpTKV6nCBd3Hp/PRGGmdwnfkV2ThMyYldP1wRpm/id99spTQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@typescript-eslint/typescript-estree": { - "version": "7.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-7.18.0.tgz", - "integrity": "sha512-aP1v/BSPnnyhMHts8cf1qQ6Q1IFwwRvAQGRvBFkWlo3/lH29OXA3Pts+c10nxRxIBrDnoMqzhgdwVe5f2D6OzA==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "@typescript-eslint/types": "7.18.0", - "@typescript-eslint/visitor-keys": "7.18.0", - "debug": "^4.3.4", - "globby": "^11.1.0", - "is-glob": "^4.0.3", - "minimatch": "^9.0.4", - "semver": "^7.6.0", - "ts-api-utils": "^1.3.0" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/@typescript-eslint/visitor-keys": { - "version": "7.18.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-7.18.0.tgz", - "integrity": "sha512-cDF0/Gf81QpY3xYyJKDV14Zwdmid5+uuENhjH2EqFaF0ni+yAyq/LzMaIJdhNJXZI7uLzwIlA+V7oWoyn6Curg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/types": "7.18.0", - "eslint-visitor-keys": "^3.4.3" - }, - "engines": { - "node": "^18.18.0 || >=20.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - } - }, - "node_modules/@vue/compiler-core": { - "version": "3.5.13", - "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.13.tgz", - "integrity": "sha512-oOdAkwqUfW1WqpwSYJce06wvt6HljgY3fGeM9NcVA1HaYOij3mZG9Rkysn0OHuyUAGMbEbARIpsG+LPVlBJ5/Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/parser": "^7.25.3", - "@vue/shared": "3.5.13", - "entities": "^4.5.0", - "estree-walker": "^2.0.2", - "source-map-js": "^1.2.0" - } - }, - "node_modules/@vue/compiler-dom": { - "version": "3.5.13", - "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.13.tgz", - "integrity": "sha512-ZOJ46sMOKUjO3e94wPdCzQ6P1Lx/vhp2RSvfaab88Ajexs0AHeV0uasYhi99WPaogmBlRHNRuly8xV75cNTMDA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@vue/compiler-core": "3.5.13", - "@vue/shared": "3.5.13" - } - }, - "node_modules/@vue/compiler-sfc": { - "version": "3.5.13", - "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.13.tgz", - "integrity": "sha512-6VdaljMpD82w6c2749Zhf5T9u5uLBWKnVue6XWxprDobftnletJ8+oel7sexFfM3qIxNmVE7LSFGTpv6obNyaQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/parser": "^7.25.3", - "@vue/compiler-core": "3.5.13", - "@vue/compiler-dom": "3.5.13", - "@vue/compiler-ssr": "3.5.13", - "@vue/shared": "3.5.13", - "estree-walker": "^2.0.2", - "magic-string": "^0.30.11", - "postcss": "^8.4.48", - "source-map-js": "^1.2.0" - } - }, - "node_modules/@vue/compiler-ssr": { - "version": "3.5.13", - "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.13.tgz", - "integrity": "sha512-wMH6vrYHxQl/IybKJagqbquvxpWCuVYpoUJfCqFZwa/JY1GdATAQ+TgVtgrwwMZ0D07QhA99rs/EAAWfvG6KpA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@vue/compiler-dom": "3.5.13", - "@vue/shared": "3.5.13" - } - }, - "node_modules/@vue/shared": { - "version": "3.5.13", - "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.13.tgz", - "integrity": "sha512-/hnE/qP5ZoGpol0a5mDi45bOd7t3tjYJBjsgCsivow7D48cJeV5l05RD82lPqi7gRiphZM37rnhW1l6ZoCNNnQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/any-promise": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", - "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==", - "dev": true, - "license": "MIT" - }, - "node_modules/app-module-path": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/app-module-path/-/app-module-path-2.2.0.tgz", - "integrity": "sha512-gkco+qxENJV+8vFcDiiFhuoSvRXb2a/QPqpSoWhVz829VNJfOTnELbBmPmNKFxf3xdNnw4DWCkzkDaavcX/1YQ==", - "dev": true, - "license": "BSD-2-Clause" - }, - "node_modules/array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/ast-module-types": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/ast-module-types/-/ast-module-types-6.0.0.tgz", - "integrity": "sha512-LFRg7178Fw5R4FAEwZxVqiRI8IxSM+Ay2UBrHoCerXNme+kMMMfz7T3xDGV/c2fer87hcrtgJGsnSOfUrPK6ng==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - } - }, - "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true, - "license": "MIT" - }, - "node_modules/base64-js": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, - "node_modules/bl": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", - "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", - "dev": true, - "license": "MIT", - "dependencies": { - "buffer": "^5.5.0", - "inherits": "^2.0.4", - "readable-stream": "^3.4.0" - } - }, - "node_modules/brace-expansion": { - "version": "1.1.11", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", - "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" - } - }, - "node_modules/braces": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", - "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", - "dev": true, - "license": "MIT", - "dependencies": { - "fill-range": "^7.1.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/buffer": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", - "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT", - "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.1.13" - } - }, - "node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/cli-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", - "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", - "dev": true, - "license": "MIT", - "dependencies": { - "restore-cursor": "^3.1.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cli-spinners": { - "version": "2.9.2", - "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz", - "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/clone": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", - "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.8" - } - }, - "node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true, - "license": "MIT" - }, - "node_modules/commander": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", - "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 10" - } - }, - "node_modules/commondir": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", - "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==", - "dev": true, - "license": "MIT" - }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "dev": true, - "license": "MIT" - }, - "node_modules/debug": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", - "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/deep-extend": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", - "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/defaults": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz", - "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==", - "dev": true, - "license": "MIT", - "dependencies": { - "clone": "^1.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/dependency-tree": { - "version": "11.0.1", - "resolved": "https://registry.npmjs.org/dependency-tree/-/dependency-tree-11.0.1.tgz", - "integrity": "sha512-eCt7HSKIC9NxgIykG2DRq3Aewn9UhVS14MB3rEn6l/AsEI1FBg6ZGSlCU0SZ6Tjm2kkhj6/8c2pViinuyKELhg==", - "dev": true, - "license": "MIT", - "dependencies": { - "commander": "^12.0.0", - "filing-cabinet": "^5.0.1", - "precinct": "^12.0.2", - "typescript": "^5.4.5" - }, - "bin": { - "dependency-tree": "bin/cli.js" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/dependency-tree/node_modules/commander": { - "version": "12.1.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz", - "integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - } - }, - "node_modules/detective-amd": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/detective-amd/-/detective-amd-6.0.0.tgz", - "integrity": "sha512-NTqfYfwNsW7AQltKSEaWR66hGkTeD52Kz3eRQ+nfkA9ZFZt3iifRCWh+yZ/m6t3H42JFwVFTrml/D64R2PAIOA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ast-module-types": "^6.0.0", - "escodegen": "^2.1.0", - "get-amd-module-type": "^6.0.0", - "node-source-walk": "^7.0.0" - }, - "bin": { - "detective-amd": "bin/cli.js" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/detective-cjs": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/detective-cjs/-/detective-cjs-6.0.0.tgz", - "integrity": "sha512-R55jTS6Kkmy6ukdrbzY4x+I7KkXiuDPpFzUViFV/tm2PBGtTCjkh9ZmTuJc1SaziMHJOe636dtiZLEuzBL9drg==", - "dev": true, - "license": "MIT", - "dependencies": { - "ast-module-types": "^6.0.0", - "node-source-walk": "^7.0.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/detective-es6": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/detective-es6/-/detective-es6-5.0.0.tgz", - "integrity": "sha512-NGTnzjvgeMW1khUSEXCzPDoraLenWbUjCFjwxReH+Ir+P6LGjYtaBbAvITWn2H0VSC+eM7/9LFOTAkrta6hNYg==", - "dev": true, - "license": "MIT", - "dependencies": { - "node-source-walk": "^7.0.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/detective-postcss": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/detective-postcss/-/detective-postcss-7.0.0.tgz", - "integrity": "sha512-pSXA6dyqmBPBuERpoOKKTUUjQCZwZPLRbd1VdsTbt6W+m/+6ROl4BbE87yQBUtLoK7yX8pvXHdKyM/xNIW9F7A==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-url": "^1.2.4", - "postcss-values-parser": "^6.0.2" - }, - "engines": { - "node": "^14.0.0 || >=16.0.0" - }, - "peerDependencies": { - "postcss": "^8.4.38" - } - }, - "node_modules/detective-sass": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/detective-sass/-/detective-sass-6.0.0.tgz", - "integrity": "sha512-h5GCfFMkPm4ZUUfGHVPKNHKT8jV7cSmgK+s4dgQH4/dIUNh9/huR1fjEQrblOQNDalSU7k7g+tiW9LJ+nVEUhg==", - "dev": true, - "license": "MIT", - "dependencies": { - "gonzales-pe": "^4.3.0", - "node-source-walk": "^7.0.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/detective-scss": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/detective-scss/-/detective-scss-5.0.0.tgz", - "integrity": "sha512-Y64HyMqntdsCh1qAH7ci95dk0nnpA29g319w/5d/oYcHolcGUVJbIhOirOFjfN1KnMAXAFm5FIkZ4l2EKFGgxg==", - "dev": true, - "license": "MIT", - "dependencies": { - "gonzales-pe": "^4.3.0", - "node-source-walk": "^7.0.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/detective-stylus": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/detective-stylus/-/detective-stylus-5.0.0.tgz", - "integrity": "sha512-KMHOsPY6aq3196WteVhkY5FF+6Nnc/r7q741E+Gq+Ax9mhE2iwj8Hlw8pl+749hPDRDBHZ2WlgOjP+twIG61vQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - } - }, - "node_modules/detective-typescript": { - "version": "13.0.0", - "resolved": "https://registry.npmjs.org/detective-typescript/-/detective-typescript-13.0.0.tgz", - "integrity": "sha512-tcMYfiFWoUejSbvSblw90NDt76/4mNftYCX0SMnVRYzSXv8Fvo06hi4JOPdNvVNxRtCAKg3MJ3cBJh+ygEMH+A==", - "dev": true, - "license": "MIT", - "dependencies": { - "@typescript-eslint/typescript-estree": "^7.6.0", - "ast-module-types": "^6.0.0", - "node-source-walk": "^7.0.0" - }, - "engines": { - "node": "^14.14.0 || >=16.0.0" - }, - "peerDependencies": { - "typescript": "^5.4.4" - } - }, - "node_modules/detective-vue2": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/detective-vue2/-/detective-vue2-2.1.1.tgz", - "integrity": "sha512-/TQ+cs4qmSyhgESjyBXxoUuh36XjS06+UhCItWcGGOpXmU3KBRGRknG+tDzv2dASn1+UJUm2rhpDFa9TWT0dFw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@dependents/detective-less": "^5.0.0", - "@vue/compiler-sfc": "^3.5.13", - "detective-es6": "^5.0.0", - "detective-sass": "^6.0.0", - "detective-scss": "^5.0.0", - "detective-stylus": "^5.0.0", - "detective-typescript": "^13.0.0" - }, - "engines": { - "node": ">=18" - }, - "peerDependencies": { - "typescript": "^5.4.4" - } - }, - "node_modules/dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", - "dev": true, - "license": "MIT", - "dependencies": { - "path-type": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/enhanced-resolve": { - "version": "5.18.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.0.tgz", - "integrity": "sha512-0/r0MySGYG8YqlayBZ6MuCfECmHFdJ5qyPh8s8wa5Hnm6SaFLSK1VYCbj+NKp090Nm1caZhD+QTnmxO7esYGyQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "graceful-fs": "^4.2.4", - "tapable": "^2.2.0" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/entities": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", - "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=0.12" - }, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, - "node_modules/escodegen": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.1.0.tgz", - "integrity": "sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "esprima": "^4.0.1", - "estraverse": "^5.2.0", - "esutils": "^2.0.2" - }, - "bin": { - "escodegen": "bin/escodegen.js", - "esgenerate": "bin/esgenerate.js" - }, - "engines": { - "node": ">=6.0" - }, - "optionalDependencies": { - "source-map": "~0.6.1" - } - }, - "node_modules/eslint-visitor-keys": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/esprima": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", - "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", - "dev": true, - "license": "BSD-2-Clause", - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=4.0" - } - }, - "node_modules/estree-walker": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", - "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", - "dev": true, - "license": "MIT" - }, - "node_modules/esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/fast-glob": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", - "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.8" - }, - "engines": { - "node": ">=8.6.0" - } - }, - "node_modules/fastq": { - "version": "1.18.0", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.18.0.tgz", - "integrity": "sha512-QKHXPW0hD8g4UET03SdOdunzSouc9N4AuHdsX8XNcTsuz+yYFILVNIX4l9yHABMhiEI9Db0JTTIpu0wB+Y1QQw==", - "dev": true, - "license": "ISC", - "dependencies": { - "reusify": "^1.0.4" - } - }, - "node_modules/filing-cabinet": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/filing-cabinet/-/filing-cabinet-5.0.2.tgz", - "integrity": "sha512-RZlFj8lzyu6jqtFBeXNqUjjNG6xm+gwXue3T70pRxw1W40kJwlgq0PSWAmh0nAnn5DHuBIecLXk9+1VKS9ICXA==", - "dev": true, - "license": "MIT", - "dependencies": { - "app-module-path": "^2.2.0", - "commander": "^12.0.0", - "enhanced-resolve": "^5.16.0", - "module-definition": "^6.0.0", - "module-lookup-amd": "^9.0.1", - "resolve": "^1.22.8", - "resolve-dependency-path": "^4.0.0", - "sass-lookup": "^6.0.1", - "stylus-lookup": "^6.0.0", - "tsconfig-paths": "^4.2.0", - "typescript": "^5.4.4" - }, - "bin": { - "filing-cabinet": "bin/cli.js" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/filing-cabinet/node_modules/commander": { - "version": "12.1.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz", - "integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - } - }, - "node_modules/fill-range": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", - "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", - "dev": true, - "license": "MIT", - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "dev": true, - "license": "ISC" - }, - "node_modules/function-bind": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", - "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/get-amd-module-type": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/get-amd-module-type/-/get-amd-module-type-6.0.0.tgz", - "integrity": "sha512-hFM7oivtlgJ3d6XWD6G47l8Wyh/C6vFw5G24Kk1Tbq85yh5gcM8Fne5/lFhiuxB+RT6+SI7I1ThB9lG4FBh3jw==", - "dev": true, - "license": "MIT", - "dependencies": { - "ast-module-types": "^6.0.0", - "node-source-walk": "^7.0.0" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/get-own-enumerable-property-symbols": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.2.tgz", - "integrity": "sha512-I0UBV/XOz1XkIJHEUDMZAbzCThU/H8DxmSfmdGcKPnVhu2VfFqr34jr9777IyaTYvxjedWhqVIilEDsCdP5G6g==", - "dev": true, - "license": "ISC" - }, - "node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "deprecated": "Glob versions prior to v9 are no longer supported", - "dev": true, - "license": "ISC", - "dependencies": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.1.1", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" - }, - "engines": { - "node": "*" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "license": "ISC", - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/globby": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", - "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", - "dev": true, - "license": "MIT", - "dependencies": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.9", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/gonzales-pe": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/gonzales-pe/-/gonzales-pe-4.3.0.tgz", - "integrity": "sha512-otgSPpUmdWJ43VXyiNgEYE4luzHCL2pz4wQ0OnDluC6Eg4Ko3Vexy/SrSynglw/eR+OhkzmqFCZa/OFa/RgAOQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "minimist": "^1.2.5" - }, - "bin": { - "gonzales": "bin/gonzales.js" - }, - "engines": { - "node": ">=0.6.0" - } - }, - "node_modules/graceful-fs": { - "version": "4.2.11", - "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", - "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", - "dev": true, - "license": "ISC" - }, - "node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/hasown": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", - "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "function-bind": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/ieee754": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz", - "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "BSD-3-Clause" - }, - "node_modules/ignore": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", - "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 4" - } - }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", - "dev": true, - "license": "ISC", - "dependencies": { - "once": "^1.3.0", - "wrappy": "1" - } - }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "dev": true, - "license": "ISC" - }, - "node_modules/ini": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", - "dev": true, - "license": "ISC" - }, - "node_modules/is-core-module": { - "version": "2.16.1", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", - "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", - "dev": true, - "license": "MIT", - "dependencies": { - "hasown": "^2.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-interactive": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", - "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/is-obj": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", - "integrity": "sha512-l4RyHgRqGN4Y3+9JHVrNqO+tN0rV5My76uW5/nuO4K1b6vw5G8d/cmFjP9tRfEsdhZNt0IFdZuK/c2Vr4Nb+Qg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-regexp": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-regexp/-/is-regexp-1.0.0.tgz", - "integrity": "sha512-7zjFAPO4/gwyQAAgRRmqeEeyIICSdmCqa3tsVHMdBzaXXRiqopZL4Cyghg/XulGWrtABTpbnYYzzIRffLkP4oA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-unicode-supported": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", - "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/is-url": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/is-url/-/is-url-1.2.4.tgz", - "integrity": "sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww==", - "dev": true, - "license": "MIT" - }, - "node_modules/is-url-superb": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/is-url-superb/-/is-url-superb-4.0.0.tgz", - "integrity": "sha512-GI+WjezhPPcbM+tqE9LnmsY5qqjwHzTvjJ36wxYX5ujNXefSUJ/T17r5bqDV8yLhcgB59KTPNOc9O9cmHTPWsA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/json5": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", - "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", - "dev": true, - "license": "MIT", - "bin": { - "json5": "lib/cli.js" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/log-symbols": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", - "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", - "dev": true, - "license": "MIT", - "dependencies": { - "chalk": "^4.1.0", - "is-unicode-supported": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/madge": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/madge/-/madge-8.0.0.tgz", - "integrity": "sha512-9sSsi3TBPhmkTCIpVQF0SPiChj1L7Rq9kU2KDG1o6v2XH9cCw086MopjVCD+vuoL5v8S77DTbVopTO8OUiQpIw==", - "dev": true, - "license": "MIT", - "dependencies": { - "chalk": "^4.1.2", - "commander": "^7.2.0", - "commondir": "^1.0.1", - "debug": "^4.3.4", - "dependency-tree": "^11.0.0", - "ora": "^5.4.1", - "pluralize": "^8.0.0", - "pretty-ms": "^7.0.1", - "rc": "^1.2.8", - "stream-to-array": "^2.3.0", - "ts-graphviz": "^2.1.2", - "walkdir": "^0.4.1" - }, - "bin": { - "madge": "bin/cli.js" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "type": "individual", - "url": "https://www.paypal.me/pahen" - }, - "peerDependencies": { - "typescript": "^5.4.4" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/magic-string": { - "version": "0.30.17", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz", - "integrity": "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.0" - } - }, - "node_modules/merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 8" - } - }, - "node_modules/micromatch": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", - "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", - "dev": true, - "license": "MIT", - "dependencies": { - "braces": "^3.0.3", - "picomatch": "^2.3.1" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/mimic-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", - "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^1.1.7" - }, - "engines": { - "node": "*" - } - }, - "node_modules/minimist": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", - "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/module-definition": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/module-definition/-/module-definition-6.0.0.tgz", - "integrity": "sha512-sEGP5nKEXU7fGSZUML/coJbrO+yQtxcppDAYWRE9ovWsTbFoUHB2qDUx564WUzDaBHXsD46JBbIK5WVTwCyu3w==", - "dev": true, - "license": "MIT", - "dependencies": { - "ast-module-types": "^6.0.0", - "node-source-walk": "^7.0.0" - }, - "bin": { - "module-definition": "bin/cli.js" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/module-lookup-amd": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/module-lookup-amd/-/module-lookup-amd-9.0.2.tgz", - "integrity": "sha512-p7PzSVEWiW9fHRX9oM+V4aV5B2nCVddVNv4DZ/JB6t9GsXY4E+ZVhPpnwUX7bbJyGeeVZqhS8q/JZ/H77IqPFA==", - "dev": true, - "license": "MIT", - "dependencies": { - "commander": "^12.1.0", - "glob": "^7.2.3", - "requirejs": "^2.3.7", - "requirejs-config-file": "^4.0.0" - }, - "bin": { - "lookup-amd": "bin/cli.js" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/module-lookup-amd/node_modules/commander": { - "version": "12.1.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz", - "integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - } - }, - "node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true, - "license": "MIT" - }, - "node_modules/nanoid": { - "version": "3.3.8", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.8.tgz", - "integrity": "sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "bin": { - "nanoid": "bin/nanoid.cjs" - }, - "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" - } - }, - "node_modules/node-source-walk": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/node-source-walk/-/node-source-walk-7.0.0.tgz", - "integrity": "sha512-1uiY543L+N7Og4yswvlm5NCKgPKDEXd9AUR9Jh3gen6oOeBsesr6LqhXom1er3eRzSUcVRWXzhv8tSNrIfGHKw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/parser": "^7.24.4" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/once": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", - "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dev": true, - "license": "ISC", - "dependencies": { - "wrappy": "1" - } - }, - "node_modules/onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", - "dev": true, - "license": "MIT", - "dependencies": { - "mimic-fn": "^2.1.0" - }, - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ora": { - "version": "5.4.1", - "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", - "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "bl": "^4.1.0", - "chalk": "^4.1.0", - "cli-cursor": "^3.1.0", - "cli-spinners": "^2.5.0", - "is-interactive": "^1.0.0", - "is-unicode-supported": "^0.1.0", - "log-symbols": "^4.1.0", - "strip-ansi": "^6.0.0", - "wcwidth": "^1.0.1" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/parse-ms": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/parse-ms/-/parse-ms-2.1.0.tgz", - "integrity": "sha512-kHt7kzLoS9VBZfUsiKjv43mr91ea+U05EyKkEtqp7vNbHxmaVuEqN7XxeEVnGrMtYOAxGrDElSi96K7EgO1zCA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/path-is-absolute": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", - "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true, - "license": "MIT" - }, - "node_modules/path-type": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", - "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/picocolors": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", - "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", - "dev": true, - "license": "ISC" - }, - "node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/pluralize": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz", - "integrity": "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/postcss": { - "version": "8.5.1", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.1.tgz", - "integrity": "sha512-6oz2beyjc5VMn/KV1pPw8fliQkhBXrVn1Z3TVyqZxU8kZpzEKhBdmCFqI6ZbmGtamQvQGuU1sgPTk8ZrXDD7jQ==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "peer": true, - "dependencies": { - "nanoid": "^3.3.8", - "picocolors": "^1.1.1", - "source-map-js": "^1.2.1" - }, - "engines": { - "node": "^10 || ^12 || >=14" - } - }, - "node_modules/postcss-values-parser": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/postcss-values-parser/-/postcss-values-parser-6.0.2.tgz", - "integrity": "sha512-YLJpK0N1brcNJrs9WatuJFtHaV9q5aAOj+S4DI5S7jgHlRfm0PIbDCAFRYMQD5SHq7Fy6xsDhyutgS0QOAs0qw==", - "dev": true, - "license": "MPL-2.0", - "dependencies": { - "color-name": "^1.1.4", - "is-url-superb": "^4.0.0", - "quote-unquote": "^1.0.0" - }, - "engines": { - "node": ">=10" - }, - "peerDependencies": { - "postcss": "^8.2.9" - } - }, - "node_modules/precinct": { - "version": "12.1.2", - "resolved": "https://registry.npmjs.org/precinct/-/precinct-12.1.2.tgz", - "integrity": "sha512-x2qVN3oSOp3D05ihCd8XdkIPuEQsyte7PSxzLqiRgktu79S5Dr1I75/S+zAup8/0cwjoiJTQztE9h0/sWp9bJQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@dependents/detective-less": "^5.0.0", - "commander": "^12.1.0", - "detective-amd": "^6.0.0", - "detective-cjs": "^6.0.0", - "detective-es6": "^5.0.0", - "detective-postcss": "^7.0.0", - "detective-sass": "^6.0.0", - "detective-scss": "^5.0.0", - "detective-stylus": "^5.0.0", - "detective-typescript": "^13.0.0", - "detective-vue2": "^2.0.3", - "module-definition": "^6.0.0", - "node-source-walk": "^7.0.0", - "postcss": "^8.4.40", - "typescript": "^5.5.4" - }, - "bin": { - "precinct": "bin/cli.js" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/precinct/node_modules/commander": { - "version": "12.1.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz", - "integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - } - }, - "node_modules/pretty-ms": { - "version": "7.0.1", - "resolved": "https://registry.npmjs.org/pretty-ms/-/pretty-ms-7.0.1.tgz", - "integrity": "sha512-973driJZvxiGOQ5ONsFhOF/DtzPMOMtgC11kCpUrPGMTgqp2q/1gwzCquocrN33is0VZ5GFHXZYMM9l6h67v2Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "parse-ms": "^2.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, - "node_modules/quote-unquote": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/quote-unquote/-/quote-unquote-1.0.0.tgz", - "integrity": "sha512-twwRO/ilhlG/FIgYeKGFqyHhoEhqgnKVkcmqMKi2r524gz3ZbDTcyFt38E9xjJI2vT+KbRNHVbnJ/e0I25Azwg==", - "dev": true, - "license": "MIT" - }, - "node_modules/rc": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", - "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", - "dev": true, - "license": "(BSD-2-Clause OR MIT OR Apache-2.0)", - "dependencies": { - "deep-extend": "^0.6.0", - "ini": "~1.3.0", - "minimist": "^1.2.0", - "strip-json-comments": "~2.0.1" - }, - "bin": { - "rc": "cli.js" - } - }, - "node_modules/readable-stream": { - "version": "3.6.2", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", - "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", - "dev": true, - "license": "MIT", - "dependencies": { - "inherits": "^2.0.3", - "string_decoder": "^1.1.1", - "util-deprecate": "^1.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/requirejs": { - "version": "2.3.7", - "resolved": "https://registry.npmjs.org/requirejs/-/requirejs-2.3.7.tgz", - "integrity": "sha512-DouTG8T1WanGok6Qjg2SXuCMzszOo0eHeH9hDZ5Y4x8Je+9JB38HdTLT4/VA8OaUhBa0JPVHJ0pyBkM1z+pDsw==", - "dev": true, - "license": "MIT", - "bin": { - "r_js": "bin/r.js", - "r.js": "bin/r.js" - }, - "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/requirejs-config-file": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/requirejs-config-file/-/requirejs-config-file-4.0.0.tgz", - "integrity": "sha512-jnIre8cbWOyvr8a5F2KuqBnY+SDA4NXr/hzEZJG79Mxm2WiFQz2dzhC8ibtPJS7zkmBEl1mxSwp5HhC1W4qpxw==", - "dev": true, - "license": "MIT", - "dependencies": { - "esprima": "^4.0.0", - "stringify-object": "^3.2.1" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/resolve": { - "version": "1.22.10", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz", - "integrity": "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-core-module": "^2.16.0", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - }, - "bin": { - "resolve": "bin/resolve" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/resolve-dependency-path": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/resolve-dependency-path/-/resolve-dependency-path-4.0.0.tgz", - "integrity": "sha512-hlY1SybBGm5aYN3PC4rp15MzsJLM1w+MEA/4KU3UBPfz4S0lL3FL6mgv7JgaA8a+ZTeEQAiF1a1BuN2nkqiIlg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - } - }, - "node_modules/restore-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", - "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", - "dev": true, - "license": "MIT", - "dependencies": { - "onetime": "^5.1.0", - "signal-exit": "^3.0.2" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/reusify": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", - "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", - "dev": true, - "license": "MIT", - "engines": { - "iojs": ">=1.0.0", - "node": ">=0.10.0" - } - }, - "node_modules/run-parallel": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT", - "dependencies": { - "queue-microtask": "^1.2.2" - } - }, - "node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, - "node_modules/sass-lookup": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/sass-lookup/-/sass-lookup-6.0.1.tgz", - "integrity": "sha512-nl9Wxbj9RjEJA5SSV0hSDoU2zYGtE+ANaDS4OFUR7nYrquvBFvPKZZtQHe3lvnxCcylEDV00KUijjdMTUElcVQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "commander": "^12.0.0" - }, - "bin": { - "sass-lookup": "bin/cli.js" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/sass-lookup/node_modules/commander": { - "version": "12.1.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz", - "integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - } - }, - "node_modules/semver": { - "version": "7.6.3", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", - "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/signal-exit": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true, - "license": "ISC" - }, - "node_modules/slash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", - "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", - "dev": true, - "license": "BSD-3-Clause", - "optional": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/source-map-js": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", - "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/stream-to-array": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/stream-to-array/-/stream-to-array-2.3.0.tgz", - "integrity": "sha512-UsZtOYEn4tWU2RGLOXr/o/xjRBftZRlG3dEWoaHr8j4GuypJ3isitGbVyjQKAuMu+xbiop8q224TjiZWc4XTZA==", - "dev": true, - "license": "MIT", - "dependencies": { - "any-promise": "^1.1.0" - } - }, - "node_modules/string_decoder": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", - "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", - "dev": true, - "license": "MIT", - "dependencies": { - "safe-buffer": "~5.2.0" - } - }, - "node_modules/stringify-object": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/stringify-object/-/stringify-object-3.3.0.tgz", - "integrity": "sha512-rHqiFh1elqCQ9WPLIC8I0Q/g/wj5J1eMkyoiD6eoQApWHP0FtlK7rqnhmabL5VUY9JQCcqwwvlOaSuutekgyrw==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "get-own-enumerable-property-symbols": "^3.0.0", - "is-obj": "^1.0.1", - "is-regexp": "^1.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-bom": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", - "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/strip-json-comments": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", - "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/stylus-lookup": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/stylus-lookup/-/stylus-lookup-6.0.0.tgz", - "integrity": "sha512-RaWKxAvPnIXrdby+UWCr1WRfa+lrPMSJPySte4Q6a+rWyjeJyFOLJxr5GrAVfcMCsfVlCuzTAJ/ysYT8p8do7Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "commander": "^12.0.0" - }, - "bin": { - "stylus-lookup": "bin/cli.js" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/stylus-lookup/node_modules/commander": { - "version": "12.1.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz", - "integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - } - }, - "node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/supports-preserve-symlinks-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/tapable": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", - "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/ts-api-utils": { - "version": "1.4.3", - "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.4.3.tgz", - "integrity": "sha512-i3eMG77UTMD0hZhgRS562pv83RC6ukSAC2GMNWc+9dieh/+jDM5u5YG+NHX6VNDRHQcHwmsTHctP9LhbC3WxVw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=16" - }, - "peerDependencies": { - "typescript": ">=4.2.0" - } - }, - "node_modules/ts-graphviz": { - "version": "2.1.6", - "resolved": "https://registry.npmjs.org/ts-graphviz/-/ts-graphviz-2.1.6.tgz", - "integrity": "sha512-XyLVuhBVvdJTJr2FJJV2L1pc4MwSjMhcunRVgDE9k4wbb2ee7ORYnPewxMWUav12vxyfUM686MSGsqnVRIInuw==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/ts-graphviz" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/ts-graphviz" - } - ], - "license": "MIT", - "dependencies": { - "@ts-graphviz/adapter": "^2.0.6", - "@ts-graphviz/ast": "^2.0.7", - "@ts-graphviz/common": "^2.1.5", - "@ts-graphviz/core": "^2.0.7" - }, - "engines": { - "node": ">=18" - } - }, - "node_modules/tsconfig-paths": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-4.2.0.tgz", - "integrity": "sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg==", - "dev": true, - "license": "MIT", - "dependencies": { - "json5": "^2.2.2", - "minimist": "^1.2.6", - "strip-bom": "^3.0.0" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/typescript": { - "version": "5.7.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.3.tgz", - "integrity": "sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw==", - "dev": true, - "license": "Apache-2.0", - "peer": true, - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=14.17" - } - }, - "node_modules/util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", - "dev": true, - "license": "MIT" - }, - "node_modules/walkdir": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/walkdir/-/walkdir-0.4.1.tgz", - "integrity": "sha512-3eBwRyEln6E1MSzcxcVpQIhRG8Q1jLvEqRmCZqS3dsfXEDR/AhOF4d+jHg1qvDCpYaVRZjENPQyrVxAkQqxPgQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/wcwidth": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", - "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==", - "dev": true, - "license": "MIT", - "dependencies": { - "defaults": "^1.0.3" - } - }, - "node_modules/wrappy": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", - "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "dev": true, - "license": "ISC" - } - } -} diff --git a/v3/internal/generator/testdata/package.json b/v3/internal/generator/testdata/package.json deleted file mode 100644 index 4ad95cc64..000000000 --- a/v3/internal/generator/testdata/package.json +++ /dev/null @@ -1,10 +0,0 @@ -{ - "name": "testdata", - "version": "0.0.0", - "description": "Output from generator testcases. This package.json is here only to pull in the Typescript compiler as a dependency.", - "type": "module", - "devDependencies": { - "typescript": "^5.7.3", - "madge": "^8.0.0" - } -} diff --git a/v3/internal/generator/testdata/tsconfig.json b/v3/internal/generator/testdata/tsconfig.json deleted file mode 100644 index 20c5ee1e0..000000000 --- a/v3/internal/generator/testdata/tsconfig.json +++ /dev/null @@ -1,41 +0,0 @@ -{ - "include": [ - "output/**/*.js", - "output/**/*.ts" - ], - "exclude": [ - "output/**/*.d.ts", - "output/**/*.got.?s" - ], - "references": [ - { "path": "../../runtime/desktop/@wailsio/runtime" } - ], - "compilerOptions": { - "allowJs": true, - - "noEmit": true, - "skipLibCheck": false, - - "target": "ES2015", - "module": "ES2015", - "moduleResolution": "bundler", - "isolatedModules": true, - "verbatimModuleSyntax": true, - - "lib": [ - "DOM", - "ESNext" - ], - - "strict": true, - "noUnusedLocals": true, - "noUnusedParameters": false, - "noImplicitAny": true, - "noImplicitReturns": true, - "noFallthroughCasesInSwitch": true, - - "paths": { - "/wails/runtime.js": ["../../runtime/desktop/@wailsio/runtime"] - } - } -} diff --git a/v3/internal/github/github.go b/v3/internal/github/github.go deleted file mode 100644 index da534177a..000000000 --- a/v3/internal/github/github.go +++ /dev/null @@ -1,142 +0,0 @@ -package github - -import ( - "encoding/json" - "fmt" - "github.com/charmbracelet/glamour/styles" - "io" - "net/http" - "net/url" - "sort" - "strings" - - "github.com/charmbracelet/glamour" -) - -func GetReleaseNotes(tagVersion string, noColour bool) string { - resp, err := http.Get("https://api.github.com/repos/wailsapp/wails/releases/tags/" + url.PathEscape(tagVersion)) - if err != nil { - return "Unable to retrieve release notes. Please check your network connection" - } - body, err := io.ReadAll(resp.Body) - if err != nil { - return "Unable to retrieve release notes. Please check your network connection" - } - - data := map[string]interface{}{} - err = json.Unmarshal(body, &data) - if err != nil { - return "Unable to retrieve release notes. Please check your network connection" - } - - if data["body"] == nil { - return "No release notes found" - } - - result := "# Release Notes for " + tagVersion + "\n" + data["body"].(string) - var renderer *glamour.TermRenderer - - if noColour { - renderer, err = glamour.NewTermRenderer(glamour.WithStyles(styles.NoTTYStyleConfig)) - } else { - renderer, err = glamour.NewTermRenderer(glamour.WithAutoStyle()) - } - if err != nil { - return result - } - result, err = renderer.Render(result) - if err != nil { - return err.Error() - } - return result -} - -// GetVersionTags gets the list of tags on the Wails repo -// It returns a list of sorted tags in descending order -func GetVersionTags() ([]*SemanticVersion, error) { - result := []*SemanticVersion{} - var err error - - resp, err := http.Get("https://api.github.com/repos/wailsapp/wails/tags") - if err != nil { - return result, err - } - body, err := io.ReadAll(resp.Body) - if err != nil { - return result, err - } - - data := []map[string]interface{}{} - err = json.Unmarshal(body, &data) - if err != nil { - return result, err - } - - // Convert tag data to Version structs - for _, tag := range data { - version := tag["name"].(string) - if !strings.HasPrefix(version, "v2") { - continue - } - semver, err := NewSemanticVersion(version) - if err != nil { - return result, err - } - result = append(result, semver) - } - - // Reverse Sort - sort.Sort(sort.Reverse(SemverCollection(result))) - - return result, err -} - -// GetLatestStableRelease gets the latest stable release on GitHub -func GetLatestStableRelease() (result *SemanticVersion, err error) { - tags, err := GetVersionTags() - if err != nil { - return nil, err - } - - for _, tag := range tags { - if tag.IsRelease() { - return tag, nil - } - } - - return nil, fmt.Errorf("no release tag found") -} - -// GetLatestPreRelease gets the latest prerelease on GitHub -func GetLatestPreRelease() (result *SemanticVersion, err error) { - tags, err := GetVersionTags() - if err != nil { - return nil, err - } - - for _, tag := range tags { - if tag.IsPreRelease() { - return tag, nil - } - } - - return nil, fmt.Errorf("no prerelease tag found") -} - -// IsValidTag returns true if the given string is a valid tag -func IsValidTag(tagVersion string) (bool, error) { - if tagVersion[0] == 'v' { - tagVersion = tagVersion[1:] - } - tags, err := GetVersionTags() - if err != nil { - return false, err - } - - for _, tag := range tags { - if tag.String() == tagVersion { - return true, nil - } - } - return false, nil -} diff --git a/v3/internal/github/semver.go b/v3/internal/github/semver.go deleted file mode 100644 index 9062f8820..000000000 --- a/v3/internal/github/semver.go +++ /dev/null @@ -1,106 +0,0 @@ -package github - -import ( - "fmt" - - "github.com/Masterminds/semver" -) - -const majorVersion = 3 - -// SemanticVersion is a struct containing a semantic version -type SemanticVersion struct { - Version *semver.Version -} - -// NewSemanticVersion creates a new SemanticVersion object with the given version string -func NewSemanticVersion(version string) (*SemanticVersion, error) { - semverVersion, err := semver.NewVersion(version) - if err != nil { - return nil, err - } - return &SemanticVersion{ - Version: semverVersion, - }, nil -} - -// IsRelease returns true if it's a release version -func (s *SemanticVersion) IsRelease() bool { - if s.Version.Major() != majorVersion { - return false - } - return len(s.Version.Prerelease()) == 0 && len(s.Version.Metadata()) == 0 -} - -// IsPreRelease returns true if it's a prerelease version -func (s *SemanticVersion) IsPreRelease() bool { - if s.Version.Major() != majorVersion { - return false - } - return len(s.Version.Prerelease()) > 0 -} - -func (s *SemanticVersion) String() string { - return s.Version.String() -} - -// IsGreaterThan returns true if this version is greater than the given version -func (s *SemanticVersion) IsGreaterThan(version *SemanticVersion) (bool, error) { - // Set up new constraint - constraint, err := semver.NewConstraint("> " + version.Version.String()) - if err != nil { - return false, err - } - - // Check if the desired one is greater than the requested on - success, msgs := constraint.Validate(s.Version) - if !success { - return false, msgs[0] - } - return true, nil -} - -// IsGreaterThanOrEqual returns true if this version is greater than or equal the given version -func (s *SemanticVersion) IsGreaterThanOrEqual(version *SemanticVersion) (bool, error) { - // Set up new constraint - constraint, err := semver.NewConstraint(">= " + version.Version.String()) - if err != nil { - return false, err - } - - // Check if the desired one is greater than the requested on - success, msgs := constraint.Validate(s.Version) - if !success { - return false, msgs[0] - } - return true, nil -} - -// MainVersion returns the main version of any version+prerelease+metadata -// EG: MainVersion("1.2.3-pre") => "1.2.3" -func (s *SemanticVersion) MainVersion() *SemanticVersion { - mainVersion := fmt.Sprintf("%d.%d.%d", s.Version.Major(), s.Version.Minor(), s.Version.Patch()) - result, _ := NewSemanticVersion(mainVersion) - return result -} - -// SemverCollection is a collection of SemanticVersion objects -type SemverCollection []*SemanticVersion - -// Len returns the length of a collection. The number of Version instances -// on the slice. -func (c SemverCollection) Len() int { - return len(c) -} - -// Less is needed for the sort interface to compare two Version objects on the -// slice. If checks if one is less than the other. -func (c SemverCollection) Less(i, j int) bool { - return c[i].Version.LessThan(c[j].Version) -} - -// Swap is needed for the sort interface to replace the Version objects -// at two different positions in the slice. -func (c SemverCollection) Swap(i, j int) { - c[i], c[j] = c[j], c[i] -} diff --git a/v3/internal/github/semver_test.go b/v3/internal/github/semver_test.go deleted file mode 100644 index b45e1b3aa..000000000 --- a/v3/internal/github/semver_test.go +++ /dev/null @@ -1,43 +0,0 @@ -package github - -import ( - "github.com/matryer/is" - "testing" -) - -func TestSemanticVersion_IsGreaterThan(t *testing.T) { - is2 := is.New(t) - - alpha1, err := NewSemanticVersion("v3.0.0-alpha.1") - is2.NoErr(err) - - beta1, err := NewSemanticVersion("v3.0.0-beta.1") - is2.NoErr(err) - - v2, err := NewSemanticVersion("v3.0.0") - is2.NoErr(err) - - is2.True(alpha1.IsPreRelease()) - is2.True(beta1.IsPreRelease()) - is2.True(!v2.IsPreRelease()) - is2.True(v2.IsRelease()) - - result, err := beta1.IsGreaterThan(alpha1) - is2.NoErr(err) - is2.True(result) - - result, err = v2.IsGreaterThan(beta1) - is2.NoErr(err) - is2.True(result) - - beta44, err := NewSemanticVersion("v2.0.0-beta.44.2") - is2.NoErr(err) - - rc1, err := NewSemanticVersion("v2.0.0-rc.1") - is2.NoErr(err) - - result, err = rc1.IsGreaterThan(beta44) - is2.NoErr(err) - is2.True(result) - -} diff --git a/v3/internal/go-common-file-dialog/LICENSE b/v3/internal/go-common-file-dialog/LICENSE deleted file mode 100644 index 508b6978e..000000000 --- a/v3/internal/go-common-file-dialog/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2019 Harry Phillips - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/v3/internal/go-common-file-dialog/README.md b/v3/internal/go-common-file-dialog/README.md deleted file mode 100644 index 1cb5902d1..000000000 --- a/v3/internal/go-common-file-dialog/README.md +++ /dev/null @@ -1,31 +0,0 @@ -# Common File Dialog bindings for Golang - -[Project Home](https://github.com/harry1453/go-common-file-dialog) - -This library contains bindings for Windows Vista and -newer's [Common File Dialogs](https://docs.microsoft.com/en-us/windows/win32/shell/common-file-dialog), which is the -standard system dialog for selecting files or folders to open or save. - -The Common File Dialogs have to be accessed via -the [COM Interface](https://en.wikipedia.org/wiki/Component_Object_Model), normally via C++ or via bindings (like in C#) -. - -This library contains bindings for Golang. **It does not require CGO**, and contains empty stubs for non-windows -platforms (so is safe to compile and run on platforms other than windows, but will just return errors at runtime). - -This can be very useful if you want to quickly get a file selector in your Golang application. The `cfdutil` package -contains utility functions with a single call to open and configure a dialog, and then get the result from it. Examples -for this are in [`_examples/usingutil`](_examples/usingutil). Or, if you want finer control over the dialog's operation, -you can use the base package. Examples for this are in [`_examples/notusingutil`](_examples/notusingutil). - -This library is available under the MIT license. - -Currently supported features: - -* Open File Dialog (to open a single file) -* Open Multiple Files Dialog (to open multiple files) -* Open Folder Dialog -* Save File Dialog -* Dialog "roles" to allow Windows to remember different "last locations" for different types of dialog -* Set dialog Title, Default Folder and Initial Folder -* Set dialog File Filters diff --git a/v3/internal/go-common-file-dialog/cfd/CommonFileDialog.go b/v3/internal/go-common-file-dialog/cfd/CommonFileDialog.go deleted file mode 100644 index 58e97aa4e..000000000 --- a/v3/internal/go-common-file-dialog/cfd/CommonFileDialog.go +++ /dev/null @@ -1,72 +0,0 @@ -// Cross-platform. - -// Common File Dialogs -package cfd - -type Dialog interface { - // Show the dialog to the user. - // Blocks until the user has closed the dialog. - Show() error - // Sets the dialog's parent window. Use 0 to set the dialog to have no parent window. - SetParentWindowHandle(hwnd uintptr) - // Show the dialog to the user. - // Blocks until the user has closed the dialog and returns their selection. - // Returns an error if the user cancelled the dialog. - // Do not use for the Open Multiple Files dialog. Use ShowAndGetResults instead. - ShowAndGetResult() (string, error) - // Sets the title of the dialog window. - SetTitle(title string) error - // Sets the "role" of the dialog. This is used to derive the dialog's GUID, which the - // OS will use to differentiate it from dialogs that are intended for other purposes. - // This means that, for example, a dialog with role "Import" will have a different - // previous location that it will open to than a dialog with role "Open". Can be any string. - SetRole(role string) error - // Sets the folder used as a default if there is not a recently used folder value available - SetDefaultFolder(defaultFolder string) error - // Sets the folder that the dialog always opens to. - // If this is set, it will override the "default folder" behaviour and the dialog will always open to this folder. - SetFolder(folder string) error - // Gets the selected file or folder path, as an absolute path eg. "C:\Folder\file.txt" - // Do not use for the Open Multiple Files dialog. Use GetResults instead. - GetResult() (string, error) - // Sets the file name, I.E. the contents of the file name text box. - // For Select Folder Dialog, sets folder name. - SetFileName(fileName string) error - // Release the resources allocated to this Dialog. - // Should be called when the dialog is finished with. - Release() error -} - -type FileDialog interface { - Dialog - // Set the list of file filters that the user can select. - SetFileFilters(fileFilter []FileFilter) error - // Set the selected item from the list of file filters (set using SetFileFilters) by its index. Defaults to 0 (the first item in the list) if not called. - SetSelectedFileFilterIndex(index uint) error - // Sets the default extension applied when a user does not provide one as part of the file name. - // If the user selects a different file filter, the default extension will be automatically updated to match the new file filter. - // For Open / Open Multiple File Dialog, this only has an effect when the user specifies a file name with no extension and a file with the default extension exists. - // For Save File Dialog, this extension will be used whenever a user does not specify an extension. - SetDefaultExtension(defaultExtension string) error -} - -type OpenFileDialog interface { - FileDialog -} - -type OpenMultipleFilesDialog interface { - FileDialog - // Show the dialog to the user. - // Blocks until the user has closed the dialog and returns the selected files. - ShowAndGetResults() ([]string, error) - // Gets the selected file paths, as absolute paths eg. "C:\Folder\file.txt" - GetResults() ([]string, error) -} - -type SelectFolderDialog interface { - Dialog -} - -type SaveFileDialog interface { // TODO Properties - FileDialog -} diff --git a/v3/internal/go-common-file-dialog/cfd/CommonFileDialog_nonWindows.go b/v3/internal/go-common-file-dialog/cfd/CommonFileDialog_nonWindows.go deleted file mode 100644 index 3ab969850..000000000 --- a/v3/internal/go-common-file-dialog/cfd/CommonFileDialog_nonWindows.go +++ /dev/null @@ -1,28 +0,0 @@ -//go:build !windows -// +build !windows - -package cfd - -import "fmt" - -var unsupportedError = fmt.Errorf("common file dialogs are only available on windows") - -// TODO doc -func NewOpenFileDialog(config DialogConfig) (OpenFileDialog, error) { - return nil, unsupportedError -} - -// TODO doc -func NewOpenMultipleFilesDialog(config DialogConfig) (OpenMultipleFilesDialog, error) { - return nil, unsupportedError -} - -// TODO doc -func NewSelectFolderDialog(config DialogConfig) (SelectFolderDialog, error) { - return nil, unsupportedError -} - -// TODO doc -func NewSaveFileDialog(config DialogConfig) (SaveFileDialog, error) { - return nil, unsupportedError -} diff --git a/v3/internal/go-common-file-dialog/cfd/CommonFileDialog_windows.go b/v3/internal/go-common-file-dialog/cfd/CommonFileDialog_windows.go deleted file mode 100644 index 69f46118e..000000000 --- a/v3/internal/go-common-file-dialog/cfd/CommonFileDialog_windows.go +++ /dev/null @@ -1,79 +0,0 @@ -//go:build windows -// +build windows - -package cfd - -import "github.com/go-ole/go-ole" - -func initialize() { - // Swallow error - _ = ole.CoInitializeEx(0, ole.COINIT_APARTMENTTHREADED|ole.COINIT_DISABLE_OLE1DDE) -} - -// TODO doc -func NewOpenFileDialog(config DialogConfig) (OpenFileDialog, error) { - initialize() - - openDialog, err := newIFileOpenDialog() - if err != nil { - return nil, err - } - err = config.apply(openDialog) - if err != nil { - return nil, err - } - return openDialog, nil -} - -// TODO doc -func NewOpenMultipleFilesDialog(config DialogConfig) (OpenMultipleFilesDialog, error) { - initialize() - - openDialog, err := newIFileOpenDialog() - if err != nil { - return nil, err - } - err = config.apply(openDialog) - if err != nil { - return nil, err - } - err = openDialog.setIsMultiselect(true) - if err != nil { - return nil, err - } - return openDialog, nil -} - -// TODO doc -func NewSelectFolderDialog(config DialogConfig) (SelectFolderDialog, error) { - initialize() - - openDialog, err := newIFileOpenDialog() - if err != nil { - return nil, err - } - err = config.apply(openDialog) - if err != nil { - return nil, err - } - err = openDialog.setPickFolders(true) - if err != nil { - return nil, err - } - return openDialog, nil -} - -// TODO doc -func NewSaveFileDialog(config DialogConfig) (SaveFileDialog, error) { - initialize() - - saveDialog, err := newIFileSaveDialog() - if err != nil { - return nil, err - } - err = config.apply(saveDialog) - if err != nil { - return nil, err - } - return saveDialog, nil -} diff --git a/v3/internal/go-common-file-dialog/cfd/DialogConfig.go b/v3/internal/go-common-file-dialog/cfd/DialogConfig.go deleted file mode 100644 index 800573ed2..000000000 --- a/v3/internal/go-common-file-dialog/cfd/DialogConfig.go +++ /dev/null @@ -1,141 +0,0 @@ -// Cross-platform. - -package cfd - -import ( - "reflect" - "fmt" - "os" -) - -type FileFilter struct { - // The display name of the filter (That is shown to the user) - DisplayName string - // The filter pattern. Eg. "*.txt;*.png" to select all txt and png files, "*.*" to select any files, etc. - Pattern string -} - -// Never obfuscate the FileFilter type. -var _ = reflect.TypeOf(FileFilter{}) - -type DialogConfig struct { - // The title of the dialog - Title string - // The role of the dialog. This is used to derive the dialog's GUID, which the - // OS will use to differentiate it from dialogs that are intended for other purposes. - // This means that, for example, a dialog with role "Import" will have a different - // previous location that it will open to than a dialog with role "Open". Can be any string. - Role string - // The default folder - the folder that is used the first time the user opens it - // (after the first time their last used location is used). - DefaultFolder string - // The initial folder - the folder that the dialog always opens to if not empty. - // If this is not empty, it will override the "default folder" behaviour and - // the dialog will always open to this folder. - Folder string - // The file filters that restrict which types of files the dialog is able to choose. - // Ignored by Select Folder Dialog. - FileFilters []FileFilter - // Sets the initially selected file filter. This is an index of FileFilters. - // Ignored by Select Folder Dialog. - SelectedFileFilterIndex uint - // The initial name of the file (I.E. the text in the file name text box) when the user opens the dialog. - // For the Select Folder Dialog, this sets the initial folder name. - FileName string - // The default extension applied when a user does not provide one as part of the file name. - // If the user selects a different file filter, the default extension will be automatically updated to match the new file filter. - // For Open / Open Multiple File Dialog, this only has an effect when the user specifies a file name with no extension and a file with the default extension exists. - // For Save File Dialog, this extension will be used whenever a user does not specify an extension. - // Ignored by Select Folder Dialog. - DefaultExtension string - // ParentWindowHandle is the handle (HWND) to the parent window of the dialog. - // If left as 0 / nil, the dialog will have no parent window. - ParentWindowHandle uintptr -} - -var defaultFilters = []FileFilter{ - { - DisplayName: "All Files (*.*)", - Pattern: "*.*", - }, -} - -func (config *DialogConfig) apply(dialog Dialog) (err error) { - if config.Title != "" { - err = dialog.SetTitle(config.Title) - if err != nil { - return - } - } - - if config.Role != "" { - err = dialog.SetRole(config.Role) - if err != nil { - return - } - } - - if config.Folder != "" { - _, err = os.Stat(config.Folder) - if err != nil { - return - } - err = dialog.SetFolder(config.Folder) - if err != nil { - return - } - } - - if config.DefaultFolder != "" { - _, err = os.Stat(config.DefaultFolder) - if err != nil { - return - } - err = dialog.SetDefaultFolder(config.DefaultFolder) - if err != nil { - return - } - } - - if config.FileName != "" { - err = dialog.SetFileName(config.FileName) - if err != nil { - return - } - } - - dialog.SetParentWindowHandle(config.ParentWindowHandle) - - if dialog, ok := dialog.(FileDialog); ok { - var fileFilters []FileFilter - if config.FileFilters != nil && len(config.FileFilters) > 0 { - fileFilters = config.FileFilters - } else { - fileFilters = defaultFilters - } - err = dialog.SetFileFilters(fileFilters) - if err != nil { - return - } - - if config.SelectedFileFilterIndex != 0 { - if config.SelectedFileFilterIndex > uint(len(fileFilters)) { - err = fmt.Errorf("selected file filter index out of range") - return - } - err = dialog.SetSelectedFileFilterIndex(config.SelectedFileFilterIndex) - if err != nil { - return - } - } - - if config.DefaultExtension != "" { - err = dialog.SetDefaultExtension(config.DefaultExtension) - if err != nil { - return - } - } - } - - return -} diff --git a/v3/internal/go-common-file-dialog/cfd/errors.go b/v3/internal/go-common-file-dialog/cfd/errors.go deleted file mode 100644 index c097c8eb2..000000000 --- a/v3/internal/go-common-file-dialog/cfd/errors.go +++ /dev/null @@ -1,7 +0,0 @@ -package cfd - -import "errors" - -var ( - ErrorCancelled = errors.New("cancelled by user") -) diff --git a/v3/internal/go-common-file-dialog/cfd/iFileOpenDialog.go b/v3/internal/go-common-file-dialog/cfd/iFileOpenDialog.go deleted file mode 100644 index 404dedc22..000000000 --- a/v3/internal/go-common-file-dialog/cfd/iFileOpenDialog.go +++ /dev/null @@ -1,200 +0,0 @@ -//go:build windows -// +build windows - -package cfd - -import ( - "github.com/go-ole/go-ole" - "github.com/google/uuid" - "syscall" - "unsafe" -) - -var ( - fileOpenDialogCLSID = ole.NewGUID("{DC1C5A9C-E88A-4dde-A5A1-60F82A20AEF7}") - fileOpenDialogIID = ole.NewGUID("{d57c7288-d4ad-4768-be02-9d969532d960}") -) - -type iFileOpenDialog struct { - vtbl *iFileOpenDialogVtbl - parentWindowHandle uintptr -} - -type iFileOpenDialogVtbl struct { - iFileDialogVtbl - - GetResults uintptr // func (ppenum **IShellItemArray) HRESULT - GetSelectedItems uintptr -} - -func newIFileOpenDialog() (*iFileOpenDialog, error) { - if unknown, err := ole.CreateInstance(fileOpenDialogCLSID, fileOpenDialogIID); err == nil { - return (*iFileOpenDialog)(unsafe.Pointer(unknown)), nil - } else { - return nil, err - } -} - -func (fileOpenDialog *iFileOpenDialog) Show() error { - return fileOpenDialog.vtbl.show(unsafe.Pointer(fileOpenDialog), fileOpenDialog.parentWindowHandle) -} - -func (fileOpenDialog *iFileOpenDialog) SetParentWindowHandle(hwnd uintptr) { - fileOpenDialog.parentWindowHandle = hwnd -} - -func (fileOpenDialog *iFileOpenDialog) ShowAndGetResult() (string, error) { - isMultiselect, err := fileOpenDialog.isMultiselect() - if err != nil { - return "", err - } - if isMultiselect { - // We should panic as this error is caused by the developer using the library - panic("use ShowAndGetResults for open multiple files dialog") - } - if err := fileOpenDialog.Show(); err != nil { - return "", err - } - return fileOpenDialog.GetResult() -} - -func (fileOpenDialog *iFileOpenDialog) ShowAndGetResults() ([]string, error) { - isMultiselect, err := fileOpenDialog.isMultiselect() - if err != nil { - return nil, err - } - if !isMultiselect { - // We should panic as this error is caused by the developer using the library - panic("use ShowAndGetResult for open single file dialog") - } - if err := fileOpenDialog.Show(); err != nil { - return nil, err - } - return fileOpenDialog.GetResults() -} - -func (fileOpenDialog *iFileOpenDialog) SetTitle(title string) error { - return fileOpenDialog.vtbl.setTitle(unsafe.Pointer(fileOpenDialog), title) -} - -func (fileOpenDialog *iFileOpenDialog) GetResult() (string, error) { - isMultiselect, err := fileOpenDialog.isMultiselect() - if err != nil { - return "", err - } - if isMultiselect { - // We should panic as this error is caused by the developer using the library - panic("use GetResults for open multiple files dialog") - } - return fileOpenDialog.vtbl.getResultString(unsafe.Pointer(fileOpenDialog)) -} - -func (fileOpenDialog *iFileOpenDialog) Release() error { - return fileOpenDialog.vtbl.release(unsafe.Pointer(fileOpenDialog)) -} - -func (fileOpenDialog *iFileOpenDialog) SetDefaultFolder(defaultFolderPath string) error { - return fileOpenDialog.vtbl.setDefaultFolder(unsafe.Pointer(fileOpenDialog), defaultFolderPath) -} - -func (fileOpenDialog *iFileOpenDialog) SetFolder(defaultFolderPath string) error { - return fileOpenDialog.vtbl.setFolder(unsafe.Pointer(fileOpenDialog), defaultFolderPath) -} - -func (fileOpenDialog *iFileOpenDialog) SetFileFilters(filter []FileFilter) error { - return fileOpenDialog.vtbl.setFileTypes(unsafe.Pointer(fileOpenDialog), filter) -} - -func (fileOpenDialog *iFileOpenDialog) SetRole(role string) error { - return fileOpenDialog.vtbl.setClientGuid(unsafe.Pointer(fileOpenDialog), StringToUUID(role)) -} - -// This should only be callable when the user asks for a multi select because -// otherwise they will be given the Dialog interface which does not expose this function. -func (fileOpenDialog *iFileOpenDialog) GetResults() ([]string, error) { - isMultiselect, err := fileOpenDialog.isMultiselect() - if err != nil { - return nil, err - } - if !isMultiselect { - // We should panic as this error is caused by the developer using the library - panic("use GetResult for open single file dialog") - } - return fileOpenDialog.vtbl.getResultsStrings(unsafe.Pointer(fileOpenDialog)) -} - -func (fileOpenDialog *iFileOpenDialog) SetDefaultExtension(defaultExtension string) error { - return fileOpenDialog.vtbl.setDefaultExtension(unsafe.Pointer(fileOpenDialog), defaultExtension) -} - -func (fileOpenDialog *iFileOpenDialog) SetFileName(initialFileName string) error { - return fileOpenDialog.vtbl.setFileName(unsafe.Pointer(fileOpenDialog), initialFileName) -} - -func (fileOpenDialog *iFileOpenDialog) SetSelectedFileFilterIndex(index uint) error { - return fileOpenDialog.vtbl.setSelectedFileFilterIndex(unsafe.Pointer(fileOpenDialog), index) -} - -func (fileOpenDialog *iFileOpenDialog) setPickFolders(pickFolders bool) error { - const FosPickfolders = 0x20 - if pickFolders { - return fileOpenDialog.vtbl.addOption(unsafe.Pointer(fileOpenDialog), FosPickfolders) - } else { - return fileOpenDialog.vtbl.removeOption(unsafe.Pointer(fileOpenDialog), FosPickfolders) - } -} - -const FosAllowMultiselect = 0x200 - -func (fileOpenDialog *iFileOpenDialog) isMultiselect() (bool, error) { - options, err := fileOpenDialog.vtbl.getOptions(unsafe.Pointer(fileOpenDialog)) - if err != nil { - return false, err - } - return options&FosAllowMultiselect != 0, nil -} - -func (fileOpenDialog *iFileOpenDialog) setIsMultiselect(isMultiselect bool) error { - if isMultiselect { - return fileOpenDialog.vtbl.addOption(unsafe.Pointer(fileOpenDialog), FosAllowMultiselect) - } else { - return fileOpenDialog.vtbl.removeOption(unsafe.Pointer(fileOpenDialog), FosAllowMultiselect) - } -} - -func (vtbl *iFileOpenDialogVtbl) getResults(objPtr unsafe.Pointer) (*iShellItemArray, error) { - var shellItemArray *iShellItemArray - ret, _, _ := syscall.SyscallN(vtbl.GetResults, - uintptr(objPtr), - uintptr(unsafe.Pointer(&shellItemArray)), - 0) - return shellItemArray, hresultToError(ret) -} - -func (vtbl *iFileOpenDialogVtbl) getResultsStrings(objPtr unsafe.Pointer) ([]string, error) { - shellItemArray, err := vtbl.getResults(objPtr) - if err != nil { - return nil, err - } - if shellItemArray == nil { - return nil, ErrorCancelled - } - defer shellItemArray.vtbl.release(unsafe.Pointer(shellItemArray)) - count, err := shellItemArray.vtbl.getCount(unsafe.Pointer(shellItemArray)) - if err != nil { - return nil, err - } - var results []string - for i := uintptr(0); i < count; i++ { - newItem, err := shellItemArray.vtbl.getItemAt(unsafe.Pointer(shellItemArray), i) - if err != nil { - return nil, err - } - results = append(results, newItem) - } - return results, nil -} - -func StringToUUID(str string) *ole.GUID { - return ole.NewGUID(uuid.NewSHA1(uuid.Nil, []byte(str)).String()) -} diff --git a/v3/internal/go-common-file-dialog/cfd/iFileSaveDialog.go b/v3/internal/go-common-file-dialog/cfd/iFileSaveDialog.go deleted file mode 100644 index ddee7b246..000000000 --- a/v3/internal/go-common-file-dialog/cfd/iFileSaveDialog.go +++ /dev/null @@ -1,92 +0,0 @@ -//go:build windows -// +build windows - -package cfd - -import ( - "github.com/go-ole/go-ole" - "unsafe" -) - -var ( - saveFileDialogCLSID = ole.NewGUID("{C0B4E2F3-BA21-4773-8DBA-335EC946EB8B}") - saveFileDialogIID = ole.NewGUID("{84bccd23-5fde-4cdb-aea4-af64b83d78ab}") -) - -type iFileSaveDialog struct { - vtbl *iFileSaveDialogVtbl - parentWindowHandle uintptr -} - -type iFileSaveDialogVtbl struct { - iFileDialogVtbl - - SetSaveAsItem uintptr - SetProperties uintptr - SetCollectedProperties uintptr - GetProperties uintptr - ApplyProperties uintptr -} - -func newIFileSaveDialog() (*iFileSaveDialog, error) { - if unknown, err := ole.CreateInstance(saveFileDialogCLSID, saveFileDialogIID); err == nil { - return (*iFileSaveDialog)(unsafe.Pointer(unknown)), nil - } else { - return nil, err - } -} - -func (fileSaveDialog *iFileSaveDialog) Show() error { - return fileSaveDialog.vtbl.show(unsafe.Pointer(fileSaveDialog), fileSaveDialog.parentWindowHandle) -} - -func (fileSaveDialog *iFileSaveDialog) SetParentWindowHandle(hwnd uintptr) { - fileSaveDialog.parentWindowHandle = hwnd -} - -func (fileSaveDialog *iFileSaveDialog) ShowAndGetResult() (string, error) { - if err := fileSaveDialog.Show(); err != nil { - return "", err - } - return fileSaveDialog.GetResult() -} - -func (fileSaveDialog *iFileSaveDialog) SetTitle(title string) error { - return fileSaveDialog.vtbl.setTitle(unsafe.Pointer(fileSaveDialog), title) -} - -func (fileSaveDialog *iFileSaveDialog) GetResult() (string, error) { - return fileSaveDialog.vtbl.getResultString(unsafe.Pointer(fileSaveDialog)) -} - -func (fileSaveDialog *iFileSaveDialog) Release() error { - return fileSaveDialog.vtbl.release(unsafe.Pointer(fileSaveDialog)) -} - -func (fileSaveDialog *iFileSaveDialog) SetDefaultFolder(defaultFolderPath string) error { - return fileSaveDialog.vtbl.setDefaultFolder(unsafe.Pointer(fileSaveDialog), defaultFolderPath) -} - -func (fileSaveDialog *iFileSaveDialog) SetFolder(defaultFolderPath string) error { - return fileSaveDialog.vtbl.setFolder(unsafe.Pointer(fileSaveDialog), defaultFolderPath) -} - -func (fileSaveDialog *iFileSaveDialog) SetFileFilters(filter []FileFilter) error { - return fileSaveDialog.vtbl.setFileTypes(unsafe.Pointer(fileSaveDialog), filter) -} - -func (fileSaveDialog *iFileSaveDialog) SetRole(role string) error { - return fileSaveDialog.vtbl.setClientGuid(unsafe.Pointer(fileSaveDialog), StringToUUID(role)) -} - -func (fileSaveDialog *iFileSaveDialog) SetDefaultExtension(defaultExtension string) error { - return fileSaveDialog.vtbl.setDefaultExtension(unsafe.Pointer(fileSaveDialog), defaultExtension) -} - -func (fileSaveDialog *iFileSaveDialog) SetFileName(initialFileName string) error { - return fileSaveDialog.vtbl.setFileName(unsafe.Pointer(fileSaveDialog), initialFileName) -} - -func (fileSaveDialog *iFileSaveDialog) SetSelectedFileFilterIndex(index uint) error { - return fileSaveDialog.vtbl.setSelectedFileFilterIndex(unsafe.Pointer(fileSaveDialog), index) -} diff --git a/v3/internal/go-common-file-dialog/cfd/iShellItem.go b/v3/internal/go-common-file-dialog/cfd/iShellItem.go deleted file mode 100644 index 080115345..000000000 --- a/v3/internal/go-common-file-dialog/cfd/iShellItem.go +++ /dev/null @@ -1,56 +0,0 @@ -//go:build windows -// +build windows - -package cfd - -import ( - "github.com/go-ole/go-ole" - "syscall" - "unsafe" -) - -var ( - procSHCreateItemFromParsingName = syscall.NewLazyDLL("Shell32.dll").NewProc("SHCreateItemFromParsingName") - iidShellItem = ole.NewGUID("43826d1e-e718-42ee-bc55-a1e261c37bfe") -) - -type iShellItem struct { - vtbl *iShellItemVtbl -} - -type iShellItemVtbl struct { - iUnknownVtbl - BindToHandler uintptr - GetParent uintptr - GetDisplayName uintptr // func (sigdnName SIGDN, ppszName *LPWSTR) HRESULT - GetAttributes uintptr - Compare uintptr -} - -func newIShellItem(path string) (*iShellItem, error) { - var shellItem *iShellItem - pathPtr := ole.SysAllocString(path) - defer func(v *int16) { - _ = ole.SysFreeString(v) - }(pathPtr) - - ret, _, _ := procSHCreateItemFromParsingName.Call( - uintptr(unsafe.Pointer(pathPtr)), - 0, - uintptr(unsafe.Pointer(iidShellItem)), - uintptr(unsafe.Pointer(&shellItem))) - return shellItem, hresultToError(ret) -} - -func (vtbl *iShellItemVtbl) getDisplayName(objPtr unsafe.Pointer) (string, error) { - var ptr *uint16 - ret, _, _ := syscall.SyscallN(vtbl.GetDisplayName, - uintptr(objPtr), - 0x80058000, // SIGDN_FILESYSPATH, - uintptr(unsafe.Pointer(&ptr))) - if err := hresultToError(ret); err != nil { - return "", err - } - defer ole.CoTaskMemFree(uintptr(unsafe.Pointer(ptr))) - return ole.LpOleStrToString(ptr), nil -} diff --git a/v3/internal/go-common-file-dialog/cfd/iShellItemArray.go b/v3/internal/go-common-file-dialog/cfd/iShellItemArray.go deleted file mode 100644 index bdd459402..000000000 --- a/v3/internal/go-common-file-dialog/cfd/iShellItemArray.go +++ /dev/null @@ -1,65 +0,0 @@ -//go:build windows -// +build windows - -package cfd - -import ( - "fmt" - "github.com/go-ole/go-ole" - "syscall" - "unsafe" -) - -const ( - iidShellItemArrayGUID = "{b63ea76d-1f85-456f-a19c-48159efa858b}" -) - -var ( - iidShellItemArray *ole.GUID -) - -func init() { - iidShellItemArray, _ = ole.IIDFromString(iidShellItemArrayGUID) -} - -type iShellItemArray struct { - vtbl *iShellItemArrayVtbl -} - -type iShellItemArrayVtbl struct { - iUnknownVtbl - BindToHandler uintptr - GetPropertyStore uintptr - GetPropertyDescriptionList uintptr - GetAttributes uintptr - GetCount uintptr // func (pdwNumItems *DWORD) HRESULT - GetItemAt uintptr // func (dwIndex DWORD, ppsi **IShellItem) HRESULT - EnumItems uintptr -} - -func (vtbl *iShellItemArrayVtbl) getCount(objPtr unsafe.Pointer) (uintptr, error) { - var count uintptr - ret, _, _ := syscall.SyscallN(vtbl.GetCount, - uintptr(objPtr), - uintptr(unsafe.Pointer(&count))) - if err := hresultToError(ret); err != nil { - return 0, err - } - return count, nil -} - -func (vtbl *iShellItemArrayVtbl) getItemAt(objPtr unsafe.Pointer, index uintptr) (string, error) { - var shellItem *iShellItem - ret, _, _ := syscall.SyscallN(vtbl.GetItemAt, - uintptr(objPtr), - index, - uintptr(unsafe.Pointer(&shellItem))) - if err := hresultToError(ret); err != nil { - return "", err - } - if shellItem == nil { - return "", fmt.Errorf("shellItem is nil") - } - defer shellItem.vtbl.release(unsafe.Pointer(shellItem)) - return shellItem.vtbl.getDisplayName(unsafe.Pointer(shellItem)) -} diff --git a/v3/internal/go-common-file-dialog/cfd/vtblCommon.go b/v3/internal/go-common-file-dialog/cfd/vtblCommon.go deleted file mode 100644 index 21015c27c..000000000 --- a/v3/internal/go-common-file-dialog/cfd/vtblCommon.go +++ /dev/null @@ -1,48 +0,0 @@ -//go:build windows -// +build windows - -package cfd - -type comDlgFilterSpec struct { - pszName *int16 - pszSpec *int16 -} - -type iUnknownVtbl struct { - QueryInterface uintptr - AddRef uintptr - Release uintptr -} - -type iModalWindowVtbl struct { - iUnknownVtbl - Show uintptr // func (hwndOwner HWND) HRESULT -} - -type iFileDialogVtbl struct { - iModalWindowVtbl - SetFileTypes uintptr // func (cFileTypes UINT, rgFilterSpec *COMDLG_FILTERSPEC) HRESULT - SetFileTypeIndex uintptr // func(iFileType UINT) HRESULT - GetFileTypeIndex uintptr - Advise uintptr - Unadvise uintptr - SetOptions uintptr // func (fos FILEOPENDIALOGOPTIONS) HRESULT - GetOptions uintptr // func (pfos *FILEOPENDIALOGOPTIONS) HRESULT - SetDefaultFolder uintptr // func (psi *IShellItem) HRESULT - SetFolder uintptr // func (psi *IShellItem) HRESULT - GetFolder uintptr - GetCurrentSelection uintptr - SetFileName uintptr // func (pszName LPCWSTR) HRESULT - GetFileName uintptr - SetTitle uintptr // func(pszTitle LPCWSTR) HRESULT - SetOkButtonLabel uintptr - SetFileNameLabel uintptr - GetResult uintptr // func (ppsi **IShellItem) HRESULT - AddPlace uintptr - SetDefaultExtension uintptr // func (pszDefaultExtension LPCWSTR) HRESULT - // This can only be used from a callback. - Close uintptr - SetClientGuid uintptr // func (guid REFGUID) HRESULT - ClearClientData uintptr - SetFilter uintptr -} diff --git a/v3/internal/go-common-file-dialog/cfd/vtblCommonFunc.go b/v3/internal/go-common-file-dialog/cfd/vtblCommonFunc.go deleted file mode 100644 index a59ff1ed1..000000000 --- a/v3/internal/go-common-file-dialog/cfd/vtblCommonFunc.go +++ /dev/null @@ -1,226 +0,0 @@ -//go:build windows - -package cfd - -import ( - "fmt" - "strings" - "syscall" - "unsafe" - - "github.com/go-ole/go-ole" -) - -func hresultToError(hr uintptr) error { - if hr < 0 { - return ole.NewError(hr) - } - return nil -} - -func (vtbl *iUnknownVtbl) release(objPtr unsafe.Pointer) error { - ret, _, _ := syscall.SyscallN(vtbl.Release, - uintptr(objPtr), - 0) - return hresultToError(ret) -} - -func (vtbl *iModalWindowVtbl) show(objPtr unsafe.Pointer, hwnd uintptr) error { - ret, _, _ := syscall.SyscallN(vtbl.Show, - uintptr(objPtr), - hwnd) - return hresultToError(ret) -} - -func (vtbl *iFileDialogVtbl) setFileTypes(objPtr unsafe.Pointer, filters []FileFilter) error { - cFileTypes := len(filters) - if cFileTypes < 0 { - return fmt.Errorf("must specify at least one filter") - } - comDlgFilterSpecs := make([]comDlgFilterSpec, cFileTypes) - for i := 0; i < cFileTypes; i++ { - filter := &filters[i] - comDlgFilterSpecs[i] = comDlgFilterSpec{ - pszName: ole.SysAllocString(filter.DisplayName), - pszSpec: ole.SysAllocString(filter.Pattern), - } - } - - // Ensure memory is freed after use - defer func() { - for _, spec := range comDlgFilterSpecs { - ole.SysFreeString(spec.pszName) - ole.SysFreeString(spec.pszSpec) - } - }() - - ret, _, _ := syscall.SyscallN(vtbl.SetFileTypes, - uintptr(objPtr), - uintptr(cFileTypes), - uintptr(unsafe.Pointer(&comDlgFilterSpecs[0]))) - return hresultToError(ret) -} - -// Options are: -// FOS_OVERWRITEPROMPT = 0x2, -// FOS_STRICTFILETYPES = 0x4, -// FOS_NOCHANGEDIR = 0x8, -// FOS_PICKFOLDERS = 0x20, -// FOS_FORCEFILESYSTEM = 0x40, -// FOS_ALLNONSTORAGEITEMS = 0x80, -// FOS_NOVALIDATE = 0x100, -// FOS_ALLOWMULTISELECT = 0x200, -// FOS_PATHMUSTEXIST = 0x800, -// FOS_FILEMUSTEXIST = 0x1000, -// FOS_CREATEPROMPT = 0x2000, -// FOS_SHAREAWARE = 0x4000, -// FOS_NOREADONLYRETURN = 0x8000, -// FOS_NOTESTFILECREATE = 0x10000, -// FOS_HIDEMRUPLACES = 0x20000, -// FOS_HIDEPINNEDPLACES = 0x40000, -// FOS_NODEREFERENCELINKS = 0x100000, -// FOS_OKBUTTONNEEDSINTERACTION = 0x200000, -// FOS_DONTADDTORECENT = 0x2000000, -// FOS_FORCESHOWHIDDEN = 0x10000000, -// FOS_DEFAULTNOMINIMODE = 0x20000000, -// FOS_FORCEPREVIEWPANEON = 0x40000000, -// FOS_SUPPORTSTREAMABLEITEMS = 0x80000000 -func (vtbl *iFileDialogVtbl) setOptions(objPtr unsafe.Pointer, options uint32) error { - ret, _, _ := syscall.SyscallN(vtbl.SetOptions, - uintptr(objPtr), - uintptr(options)) - return hresultToError(ret) -} - -func (vtbl *iFileDialogVtbl) getOptions(objPtr unsafe.Pointer) (uint32, error) { - var options uint32 - ret, _, _ := syscall.SyscallN(vtbl.GetOptions, - uintptr(objPtr), - uintptr(unsafe.Pointer(&options))) - return options, hresultToError(ret) -} - -func (vtbl *iFileDialogVtbl) addOption(objPtr unsafe.Pointer, option uint32) error { - if options, err := vtbl.getOptions(objPtr); err == nil { - return vtbl.setOptions(objPtr, options|option) - } else { - return err - } -} - -func (vtbl *iFileDialogVtbl) removeOption(objPtr unsafe.Pointer, option uint32) error { - if options, err := vtbl.getOptions(objPtr); err == nil { - return vtbl.setOptions(objPtr, options&^option) - } else { - return err - } -} - -func (vtbl *iFileDialogVtbl) setDefaultFolder(objPtr unsafe.Pointer, path string) error { - shellItem, err := newIShellItem(path) - if err != nil { - return err - } - defer shellItem.vtbl.release(unsafe.Pointer(shellItem)) - ret, _, _ := syscall.SyscallN(vtbl.SetDefaultFolder, - uintptr(objPtr), - uintptr(unsafe.Pointer(shellItem))) - return hresultToError(ret) -} - -func (vtbl *iFileDialogVtbl) setFolder(objPtr unsafe.Pointer, path string) error { - shellItem, err := newIShellItem(path) - if err != nil { - return err - } - defer shellItem.vtbl.release(unsafe.Pointer(shellItem)) - ret, _, _ := syscall.SyscallN(vtbl.SetFolder, - uintptr(objPtr), - uintptr(unsafe.Pointer(shellItem))) - return hresultToError(ret) -} - -func (vtbl *iFileDialogVtbl) setTitle(objPtr unsafe.Pointer, title string) error { - titlePtr := ole.SysAllocString(title) - defer ole.SysFreeString(titlePtr) // Ensure the string is freed - ret, _, _ := syscall.SyscallN(vtbl.SetTitle, - uintptr(objPtr), - uintptr(unsafe.Pointer(titlePtr))) - return hresultToError(ret) -} - -func (vtbl *iFileDialogVtbl) close(objPtr unsafe.Pointer) error { - ret, _, _ := syscall.SyscallN(vtbl.Close, - uintptr(objPtr)) - return hresultToError(ret) -} - -func (vtbl *iFileDialogVtbl) getResult(objPtr unsafe.Pointer) (*iShellItem, error) { - var shellItem *iShellItem - ret, _, _ := syscall.SyscallN(vtbl.GetResult, - uintptr(objPtr), - uintptr(unsafe.Pointer(&shellItem))) - return shellItem, hresultToError(ret) -} - -func (vtbl *iFileDialogVtbl) getResultString(objPtr unsafe.Pointer) (string, error) { - shellItem, err := vtbl.getResult(objPtr) - if err != nil { - return "", err - } - if shellItem == nil { - return "", ErrorCancelled - } - defer shellItem.vtbl.release(unsafe.Pointer(shellItem)) - return shellItem.vtbl.getDisplayName(unsafe.Pointer(shellItem)) -} - -func (vtbl *iFileDialogVtbl) setClientGuid(objPtr unsafe.Pointer, guid *ole.GUID) error { - // Ensure the GUID is not nil - if guid == nil { - return fmt.Errorf("guid cannot be nil") - } - - // Call the SetClientGuid method - ret, _, _ := syscall.SyscallN(vtbl.SetClientGuid, - uintptr(objPtr), - uintptr(unsafe.Pointer(guid))) - - // Convert the HRESULT to a Go error - return hresultToError(ret) -} - -func (vtbl *iFileDialogVtbl) setDefaultExtension(objPtr unsafe.Pointer, defaultExtension string) error { - // Ensure the string is not empty before accessing the first character - if len(defaultExtension) > 0 && defaultExtension[0] == '.' { - defaultExtension = strings.TrimPrefix(defaultExtension, ".") - } - - // Allocate memory for the default extension string - defaultExtensionPtr := ole.SysAllocString(defaultExtension) - defer ole.SysFreeString(defaultExtensionPtr) // Ensure the string is freed - - // Call the SetDefaultExtension method - ret, _, _ := syscall.SyscallN(vtbl.SetDefaultExtension, - uintptr(objPtr), - uintptr(unsafe.Pointer(defaultExtensionPtr))) - - // Convert the HRESULT to a Go error - return hresultToError(ret) -} - -func (vtbl *iFileDialogVtbl) setFileName(objPtr unsafe.Pointer, fileName string) error { - fileNamePtr := ole.SysAllocString(fileName) - defer ole.SysFreeString(fileNamePtr) // Ensure the string is freed - ret, _, _ := syscall.SyscallN(vtbl.SetFileName, - uintptr(objPtr), - uintptr(unsafe.Pointer(fileNamePtr))) - return hresultToError(ret) -} - -func (vtbl *iFileDialogVtbl) setSelectedFileFilterIndex(objPtr unsafe.Pointer, index uint) error { - ret, _, _ := syscall.SyscallN(vtbl.SetFileTypeIndex, - uintptr(objPtr), - uintptr(index+1)) // SetFileTypeIndex counts from 1 - return hresultToError(ret) -} diff --git a/v3/internal/go-common-file-dialog/cfdutil/CFDUtil.go b/v3/internal/go-common-file-dialog/cfdutil/CFDUtil.go deleted file mode 100644 index aa3a783b2..000000000 --- a/v3/internal/go-common-file-dialog/cfdutil/CFDUtil.go +++ /dev/null @@ -1,45 +0,0 @@ -package cfdutil - -import ( - "github.com/wailsapp/wails/v3/internal/go-common-file-dialog/cfd" -) - -// TODO doc -func ShowOpenFileDialog(config cfd.DialogConfig) (string, error) { - dialog, err := cfd.NewOpenFileDialog(config) - if err != nil { - return "", err - } - defer dialog.Release() - return dialog.ShowAndGetResult() -} - -// TODO doc -func ShowOpenMultipleFilesDialog(config cfd.DialogConfig) ([]string, error) { - dialog, err := cfd.NewOpenMultipleFilesDialog(config) - if err != nil { - return nil, err - } - defer dialog.Release() - return dialog.ShowAndGetResults() -} - -// TODO doc -func ShowPickFolderDialog(config cfd.DialogConfig) (string, error) { - dialog, err := cfd.NewSelectFolderDialog(config) - if err != nil { - return "", err - } - defer dialog.Release() - return dialog.ShowAndGetResult() -} - -// TODO doc -func ShowSaveFileDialog(config cfd.DialogConfig) (string, error) { - dialog, err := cfd.NewSaveFileDialog(config) - if err != nil { - return "", err - } - defer dialog.Release() - return dialog.ShowAndGetResult() -} diff --git a/v3/internal/go-common-file-dialog/util/util.go b/v3/internal/go-common-file-dialog/util/util.go deleted file mode 100644 index 723fbedc0..000000000 --- a/v3/internal/go-common-file-dialog/util/util.go +++ /dev/null @@ -1,10 +0,0 @@ -package util - -import ( - "github.com/go-ole/go-ole" - "github.com/google/uuid" -) - -func StringToUUID(str string) *ole.GUID { - return ole.NewGUID(uuid.NewSHA1(uuid.Nil, []byte(str)).String()) -} diff --git a/v3/internal/go-common-file-dialog/util/util_test.go b/v3/internal/go-common-file-dialog/util/util_test.go deleted file mode 100644 index 2e8ffeb05..000000000 --- a/v3/internal/go-common-file-dialog/util/util_test.go +++ /dev/null @@ -1,14 +0,0 @@ -package util - -import ( - "github.com/go-ole/go-ole" - "testing" -) - -func TestStringToUUID(t *testing.T) { - generated := *StringToUUID("TestTestTest") - expected := *ole.NewGUID("7933985F-2C87-5A5B-A26E-5D0326829AC2") - if generated != expected { - t.Errorf("not equal. expected %s, found %s", expected.String(), generated.String()) - } -} diff --git a/v3/internal/hash/fnv.go b/v3/internal/hash/fnv.go deleted file mode 100644 index bc18ee817..000000000 --- a/v3/internal/hash/fnv.go +++ /dev/null @@ -1,9 +0,0 @@ -package hash - -import "hash/fnv" - -func Fnv(s string) uint32 { - h := fnv.New32a() - _, _ = h.Write([]byte(s)) // Hash implementations never return errors (see https://pkg.go.dev/hash#Hash) - return h.Sum32() -} diff --git a/v3/internal/keychain/keychain.go b/v3/internal/keychain/keychain.go deleted file mode 100644 index 67e99e5ac..000000000 --- a/v3/internal/keychain/keychain.go +++ /dev/null @@ -1,89 +0,0 @@ -// Package keychain provides secure credential storage using the system keychain. -// On macOS it uses Keychain, on Windows it uses Credential Manager, -// and on Linux it uses Secret Service (via D-Bus). -package keychain - -import ( - "fmt" - "os" - - "github.com/zalando/go-keyring" -) - -const ( - // ServiceName is the service identifier used for all Wails credentials - ServiceName = "wails" - - // Credential keys - KeyWindowsCertPassword = "windows-cert-password" - KeyPGPPassword = "pgp-password" -) - -// Set stores a credential in the system keychain. -// The credential is identified by a key and can be retrieved later with Get. -func Set(key, value string) error { - err := keyring.Set(ServiceName, key, value) - if err != nil { - return fmt.Errorf("failed to store credential in keychain: %w", err) - } - return nil -} - -// Get retrieves a credential from the system keychain. -// Returns the value and nil error if found, or empty string and error if not found. -// Also checks environment variables as a fallback (useful for CI). -func Get(key string) (string, error) { - // First check environment variable (for CI/automation) - envKey := "WAILS_" + toEnvName(key) - if val := os.Getenv(envKey); val != "" { - return val, nil - } - - // Try keychain - value, err := keyring.Get(ServiceName, key) - if err != nil { - if err == keyring.ErrNotFound { - return "", fmt.Errorf("credential %q not found in keychain (set with: wails3 setup signing, or set env var %s)", key, envKey) - } - return "", fmt.Errorf("failed to retrieve credential from keychain: %w", err) - } - return value, nil -} - -// Delete removes a credential from the system keychain. -func Delete(key string) error { - err := keyring.Delete(ServiceName, key) - if err != nil && err != keyring.ErrNotFound { - return fmt.Errorf("failed to delete credential from keychain: %w", err) - } - return nil -} - -// Exists checks if a credential exists in the keychain or environment. -func Exists(key string) bool { - // Check environment variable first - envKey := "WAILS_" + toEnvName(key) - if os.Getenv(envKey) != "" { - return true - } - - // Check keychain - _, err := keyring.Get(ServiceName, key) - return err == nil -} - -// toEnvName converts a key to an environment variable name. -// e.g., "windows-cert-password" -> "WINDOWS_CERT_PASSWORD" -func toEnvName(key string) string { - result := make([]byte, len(key)) - for i, c := range key { - if c == '-' { - result[i] = '_' - } else if c >= 'a' && c <= 'z' { - result[i] = byte(c - 'a' + 'A') - } else { - result[i] = byte(c) - } - } - return string(result) -} diff --git a/v3/internal/libpath/cache_linux.go b/v3/internal/libpath/cache_linux.go deleted file mode 100644 index 5591c6833..000000000 --- a/v3/internal/libpath/cache_linux.go +++ /dev/null @@ -1,79 +0,0 @@ -//go:build linux - -package libpath - -import "sync" - -// pathCache holds cached dynamic library paths to avoid repeated -// expensive filesystem and subprocess operations. -type pathCache struct { - mu sync.RWMutex - flatpak []string - snap []string - nix []string - initOnce sync.Once - inited bool -} - -var cache pathCache - -// init populates the cache with dynamic paths from package managers. -// This is called lazily on first access. -func (c *pathCache) init() { - c.initOnce.Do(func() { - // Discover paths without holding the lock - flatpak := discoverFlatpakLibPaths() - snap := discoverSnapLibPaths() - nix := discoverNixLibPaths() - - // Hold lock only while updating the cache - c.mu.Lock() - c.flatpak = flatpak - c.snap = snap - c.nix = nix - c.inited = true - c.mu.Unlock() - }) -} - -// getFlatpak returns cached Flatpak library paths. -func (c *pathCache) getFlatpak() []string { - c.init() - c.mu.RLock() - defer c.mu.RUnlock() - return c.flatpak -} - -// getSnap returns cached Snap library paths. -func (c *pathCache) getSnap() []string { - c.init() - c.mu.RLock() - defer c.mu.RUnlock() - return c.snap -} - -// getNix returns cached Nix library paths. -func (c *pathCache) getNix() []string { - c.init() - c.mu.RLock() - defer c.mu.RUnlock() - return c.nix -} - -// invalidate clears the cache and forces re-discovery on next access. -func (c *pathCache) invalidate() { - c.mu.Lock() - defer c.mu.Unlock() - c.flatpak = nil - c.snap = nil - c.nix = nil - c.initOnce = sync.Once{} // Reset so init() runs again - c.inited = false -} - -// InvalidateCache clears the cached dynamic library paths. -// Call this if packages are installed or removed during runtime -// and you need to re-discover library paths. -func InvalidateCache() { - cache.invalidate() -} diff --git a/v3/internal/libpath/flatpak_linux.go b/v3/internal/libpath/flatpak_linux.go deleted file mode 100644 index ce83c08c6..000000000 --- a/v3/internal/libpath/flatpak_linux.go +++ /dev/null @@ -1,53 +0,0 @@ -//go:build linux - -package libpath - -import ( - "os" - "os/exec" - "path/filepath" - "strings" -) - -// getFlatpakLibPaths returns cached library paths from installed Flatpak runtimes. -func getFlatpakLibPaths() []string { - return cache.getFlatpak() -} - -// discoverFlatpakLibPaths scans for Flatpak runtime library directories. -// Uses `flatpak --installations` and scans for runtime lib directories. -func discoverFlatpakLibPaths() []string { - var paths []string - - // Get system and user installation directories - installDirs := []string{ - "/var/lib/flatpak", // System default - os.ExpandEnv("$HOME/.local/share/flatpak"), // User default - } - - // Try to get actual installation path from flatpak - if out, err := exec.Command("flatpak", "--installations").Output(); err == nil { - for _, line := range strings.Split(strings.TrimSpace(string(out)), "\n") { - if line != "" { - installDirs = append(installDirs, line) - } - } - } - - // Scan for runtime lib directories - for _, installDir := range installDirs { - runtimeDir := filepath.Join(installDir, "runtime") - if _, err := os.Stat(runtimeDir); err != nil { - continue - } - - // Look for lib directories in runtimes - // Structure: runtime/////files/lib - matches, err := filepath.Glob(filepath.Join(runtimeDir, "*", "*", "*", "*", "files", "lib")) - if err == nil { - paths = append(paths, matches...) - } - } - - return paths -} diff --git a/v3/internal/libpath/libpath.go b/v3/internal/libpath/libpath.go deleted file mode 100644 index 4c32ce518..000000000 --- a/v3/internal/libpath/libpath.go +++ /dev/null @@ -1,104 +0,0 @@ -// Package libpath provides utilities for finding native library paths on Linux. -// -// # Overview -// -// This package helps locate shared libraries (.so files) on Linux systems, -// supporting multiple distributions and package managers. It's particularly -// useful for applications that need to link against libraries like GTK, -// WebKit2GTK, or other system libraries at runtime. -// -// # Search Strategy -// -// The package uses a multi-tier search strategy, trying each method in order -// until a library is found: -// -// 1. pkg-config: Queries the pkg-config database for library paths -// 2. ldconfig: Searches the dynamic linker cache -// 3. Filesystem: Scans common library directories -// -// # Supported Distributions -// -// The package includes default search paths for: -// -// - Debian/Ubuntu (multiarch paths like /usr/lib/x86_64-linux-gnu) -// - Fedora/RHEL/CentOS (/usr/lib64, /usr/lib64/gtk-*) -// - Arch Linux (/usr/lib/webkit2gtk-*, /usr/lib/gtk-*) -// - openSUSE (/usr/lib64/gcc/x86_64-suse-linux) -// - NixOS and Nix package manager -// -// # Package Manager Support -// -// Dynamic paths are discovered from: -// -// - Flatpak: Scans runtime directories via `flatpak --installations` -// - Snap: Globs /snap/*/current/usr/lib* directories -// - Nix: Checks ~/.nix-profile/lib and /run/current-system/sw/lib -// -// # Caching -// -// Dynamic path discovery (Flatpak, Snap, Nix) is cached for performance. -// The cache is populated on first access and persists for the process lifetime. -// Use [InvalidateCache] to force re-discovery if packages are installed/removed -// during runtime. -// -// # Security -// -// The current directory (".") is never included in search paths by default, -// as this is a security risk. Use [FindLibraryPathWithOptions] with -// IncludeCurrentDir if you explicitly need this behavior (not recommended -// for production). -// -// # Performance -// -// Typical lookup times (cached): -// -// - Found via pkg-config: ~2ms (spawns external process) -// - Found via ldconfig: ~1.3ms (spawns external process) -// - Found via filesystem: ~0.1ms (uses cached paths) -// - Not found (worst case): ~20ms (searches all paths) -// -// # Example Usage -// -// // Find a library by its pkg-config name -// path, err := libpath.FindLibraryPath("webkit2gtk-4.1") -// if err != nil { -// log.Fatal("WebKit2GTK not found:", err) -// } -// fmt.Println("Found at:", path) -// -// // Find a specific .so file -// soPath, err := libpath.FindLibraryFile("libgtk-3.so") -// if err != nil { -// log.Fatal("GTK3 library file not found:", err) -// } -// fmt.Println("Library file:", soPath) -// -// // Get all library search paths -// for _, p := range libpath.GetAllLibPaths() { -// fmt.Println(p) -// } -// -// # Multi-Library Search -// -// When you don't know which version of a library is installed, use the -// multi-library search functions: -// -// // Find any available WebKit2GTK version (first found wins) -// match, err := libpath.FindFirstLibrary("webkit2gtk-4.1", "webkit2gtk-4.0", "webkit2gtk-6.0") -// if err != nil { -// log.Fatal("No WebKit2GTK found") -// } -// fmt.Printf("Found %s at %s\n", match.Name, match.Path) -// -// // Prefer newer versions (ordered search) -// match, err := libpath.FindFirstLibraryOrdered("gtk4", "gtk+-3.0") -// -// // Discover all available versions -// matches := libpath.FindAllLibraries("gtk+-3.0", "gtk4", "webkit2gtk-4.0", "webkit2gtk-4.1") -// for _, m := range matches { -// fmt.Printf("Available: %s at %s\n", m.Name, m.Path) -// } -// -// On non-Linux platforms, stub implementations are provided that always -// return [LibraryNotFoundError]. -package libpath diff --git a/v3/internal/libpath/libpath_linux.go b/v3/internal/libpath/libpath_linux.go deleted file mode 100644 index 9b908d405..000000000 --- a/v3/internal/libpath/libpath_linux.go +++ /dev/null @@ -1,551 +0,0 @@ -//go:build linux - -package libpath - -import ( - "context" - "os" - "os/exec" - "path/filepath" - "strings" - "sync" -) - -// Common library search paths on Linux systems -var defaultLibPaths = []string{ - // Standard paths - "/usr/lib", - "/usr/lib64", - "/lib", - "/lib64", - - // Debian/Ubuntu multiarch - "/usr/lib/x86_64-linux-gnu", - "/usr/lib/aarch64-linux-gnu", - "/usr/lib/i386-linux-gnu", - "/usr/lib/arm-linux-gnueabihf", - "/lib/x86_64-linux-gnu", - "/lib/aarch64-linux-gnu", - - // Fedora/RHEL/CentOS - "/usr/lib64/gtk-3.0", - "/usr/lib64/gtk-4.0", - "/usr/lib/gcc/x86_64-redhat-linux", - "/usr/lib/gcc/aarch64-redhat-linux", - - // Arch Linux - "/usr/lib/webkit2gtk-4.0", - "/usr/lib/webkit2gtk-4.1", - "/usr/lib/gtk-3.0", - "/usr/lib/gtk-4.0", - - // openSUSE - "/usr/lib64/gcc/x86_64-suse-linux", - - // Local installations - "/usr/local/lib", - "/usr/local/lib64", -} - -// searchResult holds the result from a parallel search goroutine. -type searchResult struct { - path string - source string // for debugging: "pkg-config", "ldconfig", "filesystem" -} - -// FindLibraryPath attempts to find the path to a library using multiple methods -// in parallel. It searches via pkg-config, ldconfig, and filesystem simultaneously, -// returning as soon as any method finds the library. -// -// The libName should be the pkg-config name (e.g., "gtk+-3.0", "webkit2gtk-4.1"). -// Returns the library directory path and any error encountered. -func FindLibraryPath(libName string) (string, error) { - return findLibraryPathCtx(context.Background(), libName) -} - -// FindLibraryPathSequential is the original sequential implementation. -// Use this if you need deterministic search order (pkg-config → ldconfig → filesystem). -func FindLibraryPathSequential(libName string) (string, error) { - // Try pkg-config first (most reliable when available) - if path, err := findWithPkgConfig(libName); err == nil { - return path, nil - } - - // Try ldconfig cache - if path, err := findWithLdconfig(libName); err == nil { - return path, nil - } - - // Fall back to searching common paths - return findInCommonPaths(libName) -} - -// FindLibraryFile finds the full path to a specific library file (e.g., "libgtk-3.so"). -func FindLibraryFile(fileName string) (string, error) { - // Try ldconfig first - if path, err := findFileWithLdconfig(fileName); err == nil { - return path, nil - } - - // Search all paths including dynamic ones - for _, dir := range GetAllLibPaths() { - // Check exact match - fullPath := filepath.Join(dir, fileName) - if _, err := os.Stat(fullPath); err == nil { - return fullPath, nil - } - - // Check with .so suffix variations - matches, err := filepath.Glob(filepath.Join(dir, fileName+"*")) - if err == nil && len(matches) > 0 { - return matches[0], nil - } - } - - return "", &LibraryNotFoundError{Name: fileName} -} - -// findWithPkgConfig uses pkg-config to find library paths. -func findWithPkgConfig(libName string) (string, error) { - return findWithPkgConfigCtx(context.Background(), libName) -} - -// findWithPkgConfigCtx uses pkg-config to find library paths with context support. -func findWithPkgConfigCtx(ctx context.Context, libName string) (string, error) { - // Check if already cancelled - select { - case <-ctx.Done(): - return "", ctx.Err() - default: - } - - cmd := exec.CommandContext(ctx, "pkg-config", "--libs-only-L", libName) - output, err := cmd.Output() - if err != nil { - return "", err - } - - // Parse -L flags from output - parts := strings.Fields(string(output)) - for _, part := range parts { - if strings.HasPrefix(part, "-L") { - path := strings.TrimPrefix(part, "-L") - if _, err := os.Stat(path); err == nil { - return path, nil - } - } - } - - // Check context before second command - select { - case <-ctx.Done(): - return "", ctx.Err() - default: - } - - // If no -L flag, try --variable=libdir - cmd = exec.CommandContext(ctx, "pkg-config", "--variable=libdir", libName) - output, err = cmd.Output() - if err != nil { - return "", err - } - - path := strings.TrimSpace(string(output)) - if path != "" { - if _, err := os.Stat(path); err == nil { - return path, nil - } - } - - return "", &LibraryNotFoundError{Name: libName} -} - -// findWithLdconfig searches the ldconfig cache for library paths. -func findWithLdconfig(libName string) (string, error) { - return findWithLdconfigCtx(context.Background(), libName) -} - -// findWithLdconfigCtx searches the ldconfig cache for library paths with context support. -func findWithLdconfigCtx(ctx context.Context, libName string) (string, error) { - // Check if already cancelled - select { - case <-ctx.Done(): - return "", ctx.Err() - default: - } - - // Convert pkg-config name to library name pattern - // e.g., "gtk+-3.0" -> "libgtk-3", "webkit2gtk-4.1" -> "libwebkit2gtk-4.1" - searchName := pkgConfigToLibName(libName) - - cmd := exec.CommandContext(ctx, "ldconfig", "-p") - output, err := cmd.Output() - if err != nil { - return "", err - } - - for _, line := range strings.Split(string(output), "\n") { - if strings.Contains(line, searchName) { - // Line format: " libname.so.X (libc6,x86-64) => /path/to/lib" - parts := strings.Split(line, "=>") - if len(parts) == 2 { - libPath := strings.TrimSpace(parts[1]) - return filepath.Dir(libPath), nil - } - } - } - - return "", &LibraryNotFoundError{Name: libName} -} - -// findFileWithLdconfig finds a specific library file using ldconfig. -func findFileWithLdconfig(fileName string) (string, error) { - cmd := exec.Command("ldconfig", "-p") - output, err := cmd.Output() - if err != nil { - return "", err - } - - baseName := strings.TrimSuffix(fileName, ".so") - for _, line := range strings.Split(string(output), "\n") { - if strings.Contains(line, baseName) { - parts := strings.Split(line, "=>") - if len(parts) == 2 { - return strings.TrimSpace(parts[1]), nil - } - } - } - - return "", &LibraryNotFoundError{Name: fileName} -} - -// findInCommonPaths searches common library directories including -// dynamically discovered Flatpak, Snap, and Nix paths. -func findInCommonPaths(libName string) (string, error) { - return findInCommonPathsCtx(context.Background(), libName) -} - -// findInCommonPathsCtx searches common library directories with context support. -func findInCommonPathsCtx(ctx context.Context, libName string) (string, error) { - searchName := pkgConfigToLibName(libName) - - // Search all paths including dynamic ones - allPaths := GetAllLibPaths() - - for _, dir := range allPaths { - // Check if cancelled periodically - select { - case <-ctx.Done(): - return "", ctx.Err() - default: - } - - if _, err := os.Stat(dir); err != nil { - continue - } - - // Look for the library file - pattern := filepath.Join(dir, searchName+"*.so*") - matches, err := filepath.Glob(pattern) - if err == nil && len(matches) > 0 { - return dir, nil - } - - // Also check pkgconfig subdirectory for .pc files - pcPath := filepath.Join(dir, "pkgconfig", libName+".pc") - if _, err := os.Stat(pcPath); err == nil { - return dir, nil - } - } - - return "", &LibraryNotFoundError{Name: libName} -} - -// pkgConfigToLibName converts a pkg-config package name to a library name pattern. -func pkgConfigToLibName(pkgName string) string { - // Common transformations - name := pkgName - - // Remove version suffix like "-3.0", "-4.1" - // but keep it for webkit2gtk-4.1 style names - if strings.HasPrefix(name, "gtk+-") { - // gtk+-3.0 -> libgtk-3 - name = "libgtk-" + strings.TrimPrefix(name, "gtk+-") - name = strings.Split(name, ".")[0] - } else if strings.HasPrefix(name, "webkit2gtk-") { - // webkit2gtk-4.1 -> libwebkit2gtk-4.1 - name = "lib" + name - } else if !strings.HasPrefix(name, "lib") { - name = "lib" + name - } - - return name -} - -// GetAllLibPaths returns all library paths from LD_LIBRARY_PATH, default paths, -// and dynamically discovered paths from Flatpak, Snap, and Nix. -// It does NOT include the current directory for security reasons. -func GetAllLibPaths() []string { - var paths []string - - // Add LD_LIBRARY_PATH entries first (highest priority) - if ldPath := os.Getenv("LD_LIBRARY_PATH"); ldPath != "" { - for _, p := range strings.Split(ldPath, ":") { - if p != "" { - paths = append(paths, p) - } - } - } - - // Add default system paths - paths = append(paths, defaultLibPaths...) - - // Add dynamically discovered paths from package managers - paths = append(paths, getFlatpakLibPaths()...) - paths = append(paths, getSnapLibPaths()...) - paths = append(paths, getNixLibPaths()...) - - return paths -} - -// FindOptions controls library search behavior. -type FindOptions struct { - // IncludeCurrentDir includes "." in the search path. - // WARNING: This is a security risk and should only be used for development. - IncludeCurrentDir bool - - // ExtraPaths are additional paths to search before the defaults. - ExtraPaths []string -} - -// FindLibraryPathWithOptions attempts to find the path to a library with custom options. -func FindLibraryPathWithOptions(libName string, opts FindOptions) (string, error) { - // Try pkg-config first (most reliable when available) - if path, err := findWithPkgConfig(libName); err == nil { - return path, nil - } - - // Try ldconfig cache - if path, err := findWithLdconfig(libName); err == nil { - return path, nil - } - - // Build search paths - include all dynamic paths too - allPaths := GetAllLibPaths() - searchPaths := make([]string, 0, len(opts.ExtraPaths)+len(allPaths)+1) - - if opts.IncludeCurrentDir { - if cwd, err := os.Getwd(); err == nil { - searchPaths = append(searchPaths, cwd) - } - } - - searchPaths = append(searchPaths, opts.ExtraPaths...) - searchPaths = append(searchPaths, allPaths...) - - // Search the paths - searchName := pkgConfigToLibName(libName) - for _, dir := range searchPaths { - if _, err := os.Stat(dir); err != nil { - continue - } - - pattern := filepath.Join(dir, searchName+"*.so*") - matches, err := filepath.Glob(pattern) - if err == nil && len(matches) > 0 { - return dir, nil - } - - pcPath := filepath.Join(dir, "pkgconfig", libName+".pc") - if _, err := os.Stat(pcPath); err == nil { - return dir, nil - } - } - - return "", &LibraryNotFoundError{Name: libName} -} - -// LibraryNotFoundError is returned when a library cannot be found. -type LibraryNotFoundError struct { - Name string -} - -func (e *LibraryNotFoundError) Error() string { - return "library not found: " + e.Name -} - -// LibraryMatch holds information about a found library. -type LibraryMatch struct { - // Name is the pkg-config name that was searched for. - Name string - // Path is the directory containing the library. - Path string -} - -// FindFirstLibrary searches for multiple libraries in parallel and returns -// the first one found. This is useful when you don't know the exact version -// of a library installed (e.g., gtk+-3.0 vs gtk+-4.0). -// -// The search order among candidates is non-deterministic - whichever is found -// first wins. If you need a specific preference order, list preferred libraries -// first and use FindFirstLibraryOrdered instead. -// -// Example: -// -// match, err := FindFirstLibrary("webkit2gtk-4.1", "webkit2gtk-4.0", "webkit2gtk-6.0") -// if err != nil { -// log.Fatal("No WebKit2GTK found") -// } -// fmt.Printf("Found %s at %s\n", match.Name, match.Path) -func FindFirstLibrary(libNames ...string) (*LibraryMatch, error) { - if len(libNames) == 0 { - return nil, &LibraryNotFoundError{Name: "no libraries specified"} - } - - ctx, cancel := context.WithCancel(context.Background()) - defer cancel() - - results := make(chan *LibraryMatch, len(libNames)) - var wg sync.WaitGroup - - for _, name := range libNames { - wg.Add(1) - go func(libName string) { - defer wg.Done() - if path, err := findLibraryPathCtx(ctx, libName); err == nil { - select { - case results <- &LibraryMatch{Name: libName, Path: path}: - case <-ctx.Done(): - } - } - }(name) - } - - // Close results when all goroutines complete - go func() { - wg.Wait() - close(results) - }() - - if result := <-results; result != nil { - return result, nil - } - - return nil, &LibraryNotFoundError{Name: strings.Join(libNames, ", ")} -} - -// FindFirstLibraryOrdered searches for libraries in order of preference, -// returning the first one found. Unlike FindFirstLibrary, this respects -// the order of candidates - earlier entries are preferred. -// -// This is useful when you want to prefer newer library versions: -// -// match, err := FindFirstLibraryOrdered("gtk+-4.0", "gtk+-3.0") -// // Will return gtk+-4.0 if available, otherwise gtk+-3.0 -func FindFirstLibraryOrdered(libNames ...string) (*LibraryMatch, error) { - if len(libNames) == 0 { - return nil, &LibraryNotFoundError{Name: "no libraries specified"} - } - - for _, name := range libNames { - if path, err := FindLibraryPath(name); err == nil { - return &LibraryMatch{Name: name, Path: path}, nil - } - } - - return nil, &LibraryNotFoundError{Name: strings.Join(libNames, ", ")} -} - -// FindAllLibraries searches for multiple libraries in parallel and returns -// all that are found. This is useful for discovering which library versions -// are available on the system. -// -// Example: -// -// matches := FindAllLibraries("gtk+-3.0", "gtk+-4.0", "webkit2gtk-4.0", "webkit2gtk-4.1") -// for _, m := range matches { -// fmt.Printf("Found %s at %s\n", m.Name, m.Path) -// } -func FindAllLibraries(libNames ...string) []LibraryMatch { - if len(libNames) == 0 { - return nil - } - - results := make(chan *LibraryMatch, len(libNames)) - var wg sync.WaitGroup - - for _, name := range libNames { - wg.Add(1) - go func(libName string) { - defer wg.Done() - if path, err := FindLibraryPath(libName); err == nil { - results <- &LibraryMatch{Name: libName, Path: path} - } - }(name) - } - - // Close results when all goroutines complete - go func() { - wg.Wait() - close(results) - }() - - var matches []LibraryMatch - for result := range results { - matches = append(matches, *result) - } - - return matches -} - -// findLibraryPathCtx is FindLibraryPath with context support. -func findLibraryPathCtx(ctx context.Context, libName string) (string, error) { - // Create a child context for this search - ctx, cancel := context.WithCancel(ctx) - defer cancel() - - results := make(chan searchResult, 3) - var wg sync.WaitGroup - wg.Add(3) - - go func() { - defer wg.Done() - if path, err := findWithPkgConfigCtx(ctx, libName); err == nil { - select { - case results <- searchResult{path: path, source: "pkg-config"}: - case <-ctx.Done(): - } - } - }() - - go func() { - defer wg.Done() - if path, err := findWithLdconfigCtx(ctx, libName); err == nil { - select { - case results <- searchResult{path: path, source: "ldconfig"}: - case <-ctx.Done(): - } - } - }() - - go func() { - defer wg.Done() - if path, err := findInCommonPathsCtx(ctx, libName); err == nil { - select { - case results <- searchResult{path: path, source: "filesystem"}: - case <-ctx.Done(): - } - } - }() - - go func() { - wg.Wait() - close(results) - }() - - if result, ok := <-results; ok { - return result.path, nil - } - - return "", &LibraryNotFoundError{Name: libName} -} diff --git a/v3/internal/libpath/libpath_linux_test.go b/v3/internal/libpath/libpath_linux_test.go deleted file mode 100644 index 0f2e91bef..000000000 --- a/v3/internal/libpath/libpath_linux_test.go +++ /dev/null @@ -1,769 +0,0 @@ -//go:build linux - -package libpath - -import ( - "os" - "os/exec" - "path/filepath" - "strings" - "testing" -) - -func TestPkgConfigToLibName(t *testing.T) { - tests := []struct { - input string - expected string - }{ - {"gtk+-3.0", "libgtk-3"}, - {"gtk+-4.0", "libgtk-4"}, - {"webkit2gtk-4.1", "libwebkit2gtk-4.1"}, - {"webkit2gtk-4.0", "libwebkit2gtk-4.0"}, - {"glib-2.0", "libglib-2.0"}, - {"libsoup-3.0", "libsoup-3.0"}, - {"cairo", "libcairo"}, - } - - for _, tt := range tests { - t.Run(tt.input, func(t *testing.T) { - result := pkgConfigToLibName(tt.input) - if result != tt.expected { - t.Errorf("pkgConfigToLibName(%q) = %q, want %q", tt.input, result, tt.expected) - } - }) - } -} - -func TestGetAllLibPaths(t *testing.T) { - paths := GetAllLibPaths() - - if len(paths) == 0 { - t.Error("GetAllLibPaths() returned empty slice") - } - - // Check that default paths are included - hasUsrLib := false - for _, p := range paths { - if p == "/usr/lib" || p == "/usr/lib64" { - hasUsrLib = true - break - } - } - if !hasUsrLib { - t.Error("GetAllLibPaths() should include /usr/lib or /usr/lib64") - } -} - -func TestGetAllLibPaths_WithLDPath(t *testing.T) { - // Save and restore LD_LIBRARY_PATH - original := os.Getenv("LD_LIBRARY_PATH") - defer os.Setenv("LD_LIBRARY_PATH", original) - - testPath := "/test/custom/lib:/another/path" - os.Setenv("LD_LIBRARY_PATH", testPath) - - paths := GetAllLibPaths() - - // First paths should be from LD_LIBRARY_PATH - if len(paths) < 2 { - t.Fatal("Expected at least 2 paths") - } - if paths[0] != "/test/custom/lib" { - t.Errorf("First path should be /test/custom/lib, got %s", paths[0]) - } - if paths[1] != "/another/path" { - t.Errorf("Second path should be /another/path, got %s", paths[1]) - } -} - -func TestLibraryNotFoundError(t *testing.T) { - err := &LibraryNotFoundError{Name: "testlib"} - expected := "library not found: testlib" - if err.Error() != expected { - t.Errorf("Error() = %q, want %q", err.Error(), expected) - } -} - -func TestFindLibraryPath_NotFound(t *testing.T) { - _, err := FindLibraryPath("nonexistent-library-xyz-123") - if err == nil { - t.Error("Expected error for nonexistent library") - } - - var notFoundErr *LibraryNotFoundError - if _, ok := err.(*LibraryNotFoundError); !ok { - t.Errorf("Expected LibraryNotFoundError, got %T", err) - } else { - notFoundErr = err.(*LibraryNotFoundError) - if notFoundErr.Name != "nonexistent-library-xyz-123" { - t.Errorf("Error name = %q, want %q", notFoundErr.Name, "nonexistent-library-xyz-123") - } - } -} - -func TestFindLibraryFile_NotFound(t *testing.T) { - _, err := FindLibraryFile("libnonexistent-xyz-123.so") - if err == nil { - t.Error("Expected error for nonexistent library file") - } -} - -// Integration tests - these depend on system state -// They're skipped if the required tools/libraries aren't available - -func TestFindLibraryPath_WithPkgConfig(t *testing.T) { - // Skip if pkg-config is not available - if _, err := exec.LookPath("pkg-config"); err != nil { - t.Skip("pkg-config not available") - } - - // Try to find a common library that's likely installed - commonLibs := []string{"glib-2.0", "zlib"} - - for _, lib := range commonLibs { - // Check if pkg-config knows about this library - cmd := exec.Command("pkg-config", "--exists", lib) - if cmd.Run() != nil { - continue - } - - t.Run(lib, func(t *testing.T) { - path, err := FindLibraryPath(lib) - if err != nil { - t.Errorf("FindLibraryPath(%q) failed: %v", lib, err) - return - } - - // Verify the path exists - if _, err := os.Stat(path); err != nil { - t.Errorf("Returned path %q does not exist", path) - } - }) - return // Only need to test one - } - - t.Skip("No common libraries found via pkg-config") -} - -func TestFindLibraryFile_Integration(t *testing.T) { - // Try to find libc which should exist on any Linux system - libcNames := []string{"libc.so.6", "libc.so"} - - for _, name := range libcNames { - path, err := FindLibraryFile(name) - if err == nil { - // Verify the path exists - if _, err := os.Stat(path); err != nil { - t.Errorf("Returned path %q does not exist", path) - } - return - } - } - - t.Skip("Could not find libc.so - unusual system configuration") -} - -func TestFindInCommonPaths(t *testing.T) { - // Create a temporary directory structure for testing - tmpDir := t.TempDir() - - // Create a fake library directory with a fake .so file - libDir := filepath.Join(tmpDir, "lib") - if err := os.MkdirAll(libDir, 0755); err != nil { - t.Fatal(err) - } - - // Create a fake library file - fakeLib := filepath.Join(libDir, "libfaketest.so.1") - if err := os.WriteFile(fakeLib, []byte{}, 0644); err != nil { - t.Fatal(err) - } - - // Temporarily add our test dir to defaultLibPaths - originalPaths := defaultLibPaths - defaultLibPaths = append([]string{libDir}, defaultLibPaths...) - defer func() { defaultLibPaths = originalPaths }() - - // Now test finding it - path, err := findInCommonPaths("faketest") - if err != nil { - t.Errorf("findInCommonPaths(\"faketest\") failed: %v", err) - return - } - - if path != libDir { - t.Errorf("findInCommonPaths(\"faketest\") = %q, want %q", path, libDir) - } -} - -func TestFindWithLdconfig(t *testing.T) { - // Skip if ldconfig is not available - if _, err := exec.LookPath("ldconfig"); err != nil { - t.Skip("ldconfig not available") - } - - // Check if we can run ldconfig -p - cmd := exec.Command("ldconfig", "-p") - output, err := cmd.Output() - if err != nil { - t.Skip("ldconfig -p failed") - } - - // Find any library from the output to test with - lines := strings.Split(string(output), "\n") - for _, line := range lines { - if strings.Contains(line, "=>") && strings.Contains(line, "libc.so") { - // We found libc, try to find it - path, err := findWithLdconfig("glib-2.0") // Common library - if err == nil { - if _, statErr := os.Stat(path); statErr != nil { - t.Errorf("Returned path %q does not exist", path) - } - return - } - // If glib not found, that's okay - just means it's not installed - break - } - } -} - -func TestFindLibraryPathWithOptions_IncludeCurrentDir(t *testing.T) { - // Create a temporary directory and change to it - tmpDir := t.TempDir() - - // Create a fake library file in the temp dir - fakeLib := filepath.Join(tmpDir, "libcwdtest.so.1") - if err := os.WriteFile(fakeLib, []byte{}, 0644); err != nil { - t.Fatal(err) - } - - // Save current directory - origDir, err := os.Getwd() - if err != nil { - t.Fatal(err) - } - defer os.Chdir(origDir) - - // Change to temp directory - if err := os.Chdir(tmpDir); err != nil { - t.Fatal(err) - } - - // Without IncludeCurrentDir, should not find it - _, err = FindLibraryPathWithOptions("cwdtest", FindOptions{IncludeCurrentDir: false}) - if err == nil { - t.Error("Expected error without IncludeCurrentDir") - } - - // With IncludeCurrentDir, should find it - path, err := FindLibraryPathWithOptions("cwdtest", FindOptions{IncludeCurrentDir: true}) - if err != nil { - t.Errorf("FindLibraryPathWithOptions with IncludeCurrentDir failed: %v", err) - return - } - - if path != tmpDir { - t.Errorf("Expected path %q, got %q", tmpDir, path) - } -} - -func TestFindLibraryPathWithOptions_ExtraPaths(t *testing.T) { - // Create a temporary directory with a fake library - tmpDir := t.TempDir() - - fakeLib := filepath.Join(tmpDir, "libextratest.so.1") - if err := os.WriteFile(fakeLib, []byte{}, 0644); err != nil { - t.Fatal(err) - } - - // Should find it with ExtraPaths - path, err := FindLibraryPathWithOptions("extratest", FindOptions{ - ExtraPaths: []string{tmpDir}, - }) - if err != nil { - t.Errorf("FindLibraryPathWithOptions with ExtraPaths failed: %v", err) - return - } - - if path != tmpDir { - t.Errorf("Expected path %q, got %q", tmpDir, path) - } -} - -func TestDefaultLibPaths_ContainsDistros(t *testing.T) { - // Verify that paths for various distros are included - expectedPaths := map[string][]string{ - "Debian/Ubuntu": {"/usr/lib/x86_64-linux-gnu", "/usr/lib/aarch64-linux-gnu"}, - "Fedora/RHEL": {"/usr/lib64/gtk-3.0", "/usr/lib64/gtk-4.0"}, - "Arch": {"/usr/lib/webkit2gtk-4.0", "/usr/lib/webkit2gtk-4.1"}, - "openSUSE": {"/usr/lib64/gcc/x86_64-suse-linux"}, - "Local": {"/usr/local/lib", "/usr/local/lib64"}, - } - - for distro, paths := range expectedPaths { - for _, path := range paths { - found := false - for _, defaultPath := range defaultLibPaths { - if defaultPath == path { - found = true - break - } - } - if !found { - t.Errorf("Missing %s path: %s", distro, path) - } - } - } -} - -func TestGetFlatpakLibPaths(t *testing.T) { - // This test just ensures the function doesn't panic - // Actual paths depend on system state - paths := getFlatpakLibPaths() - t.Logf("Found %d Flatpak lib paths", len(paths)) - for _, p := range paths { - t.Logf(" %s", p) - } -} - -func TestGetSnapLibPaths(t *testing.T) { - // This test just ensures the function doesn't panic - // Actual paths depend on system state - paths := getSnapLibPaths() - t.Logf("Found %d Snap lib paths", len(paths)) - for _, p := range paths { - t.Logf(" %s", p) - } -} - -func TestGetNixLibPaths(t *testing.T) { - // This test just ensures the function doesn't panic - paths := getNixLibPaths() - t.Logf("Found %d Nix lib paths", len(paths)) - for _, p := range paths { - t.Logf(" %s", p) - } -} - -func TestGetAllLibPaths_IncludesDynamicPaths(t *testing.T) { - paths := GetAllLibPaths() - - // Should have at least the default paths - if len(paths) < len(defaultLibPaths) { - t.Errorf("GetAllLibPaths returned fewer paths (%d) than defaultLibPaths (%d)", - len(paths), len(defaultLibPaths)) - } - - // Log all paths for debugging - t.Logf("Total paths: %d", len(paths)) -} - -func TestGetAllLibPaths_DoesNotIncludeCurrentDir(t *testing.T) { - paths := GetAllLibPaths() - - for _, p := range paths { - if p == "." { - t.Error("GetAllLibPaths should not include '.' for security reasons") - } - } -} - -func TestInvalidateCache(t *testing.T) { - // First call populates cache - paths1 := GetAllLibPaths() - - // Invalidate and call again - InvalidateCache() - paths2 := GetAllLibPaths() - - // Should get same results (assuming no system changes) - if len(paths1) != len(paths2) { - t.Logf("Path counts differ after invalidation: %d vs %d", len(paths1), len(paths2)) - // This is not necessarily an error, just informational - } - - // Verify cache is working by checking getFlatpakLibPaths is fast - // (would be slow if cache wasn't working) - for i := 0; i < 100; i++ { - _ = getFlatpakLibPaths() - } -} - -func TestFindLibraryPath_ParallelConsistency(t *testing.T) { - // Skip if pkg-config is not available - if _, err := exec.LookPath("pkg-config"); err != nil { - t.Skip("pkg-config not available") - } - - // Check if glib-2.0 is available - cmd := exec.Command("pkg-config", "--exists", "glib-2.0") - if cmd.Run() != nil { - t.Skip("glib-2.0 not installed") - } - - // Run parallel and sequential versions multiple times - // to ensure they return consistent results - for i := 0; i < 10; i++ { - parallelPath, parallelErr := FindLibraryPath("glib-2.0") - seqPath, seqErr := FindLibraryPathSequential("glib-2.0") - - if parallelErr != nil && seqErr == nil { - t.Errorf("Parallel failed but sequential succeeded: %v", parallelErr) - } - if parallelErr == nil && seqErr != nil { - t.Errorf("Sequential failed but parallel succeeded: %v", seqErr) - } - - // Both should find the library (path might differ if found by different methods) - if parallelErr != nil { - t.Errorf("Iteration %d: parallel search failed: %v", i, parallelErr) - } - if seqErr != nil { - t.Errorf("Iteration %d: sequential search failed: %v", i, seqErr) - } - - // Log paths for debugging - t.Logf("Iteration %d: parallel=%s, sequential=%s", i, parallelPath, seqPath) - } -} - -func TestFindLibraryPath_ParallelNotFound(t *testing.T) { - // Both parallel and sequential should return the same error for non-existent libs - _, parallelErr := FindLibraryPath("nonexistent-library-xyz-123") - _, seqErr := FindLibraryPathSequential("nonexistent-library-xyz-123") - - if parallelErr == nil { - t.Error("Parallel search should fail for nonexistent library") - } - if seqErr == nil { - t.Error("Sequential search should fail for nonexistent library") - } - - // Both should return LibraryNotFoundError - if _, ok := parallelErr.(*LibraryNotFoundError); !ok { - t.Errorf("Parallel: expected LibraryNotFoundError, got %T", parallelErr) - } - if _, ok := seqErr.(*LibraryNotFoundError); !ok { - t.Errorf("Sequential: expected LibraryNotFoundError, got %T", seqErr) - } -} - -// Benchmarks - -// BenchmarkFindLibraryPath benchmarks finding a library via the full search chain. -func BenchmarkFindLibraryPath(b *testing.B) { - // Test with glib-2.0 which is commonly installed - if _, err := exec.LookPath("pkg-config"); err != nil { - b.Skip("pkg-config not available") - } - cmd := exec.Command("pkg-config", "--exists", "glib-2.0") - if cmd.Run() != nil { - b.Skip("glib-2.0 not installed") - } - - b.ResetTimer() - for i := 0; i < b.N; i++ { - _, _ = FindLibraryPath("glib-2.0") - } -} - -// BenchmarkFindLibraryPath_NotFound benchmarks the worst case (library not found). -func BenchmarkFindLibraryPath_NotFound(b *testing.B) { - b.ResetTimer() - for i := 0; i < b.N; i++ { - _, _ = FindLibraryPath("nonexistent-library-xyz-123") - } -} - -// BenchmarkFindLibraryFile benchmarks finding a specific library file. -func BenchmarkFindLibraryFile(b *testing.B) { - // libc.so.6 should exist on any Linux system - b.ResetTimer() - for i := 0; i < b.N; i++ { - _, _ = FindLibraryFile("libc.so.6") - } -} - -// BenchmarkGetAllLibPaths benchmarks collecting all library paths. -func BenchmarkGetAllLibPaths(b *testing.B) { - b.ResetTimer() - for i := 0; i < b.N; i++ { - _ = GetAllLibPaths() - } -} - -// BenchmarkFindWithPkgConfig benchmarks pkg-config lookup directly. -func BenchmarkFindWithPkgConfig(b *testing.B) { - if _, err := exec.LookPath("pkg-config"); err != nil { - b.Skip("pkg-config not available") - } - cmd := exec.Command("pkg-config", "--exists", "glib-2.0") - if cmd.Run() != nil { - b.Skip("glib-2.0 not installed") - } - - b.ResetTimer() - for i := 0; i < b.N; i++ { - _, _ = findWithPkgConfig("glib-2.0") - } -} - -// BenchmarkFindWithLdconfig benchmarks ldconfig lookup directly. -func BenchmarkFindWithLdconfig(b *testing.B) { - if _, err := exec.LookPath("ldconfig"); err != nil { - b.Skip("ldconfig not available") - } - - b.ResetTimer() - for i := 0; i < b.N; i++ { - _, _ = findWithLdconfig("glib-2.0") - } -} - -// BenchmarkFindInCommonPaths benchmarks filesystem scanning. -func BenchmarkFindInCommonPaths(b *testing.B) { - b.ResetTimer() - for i := 0; i < b.N; i++ { - _, _ = findInCommonPaths("glib-2.0") - } -} - -// BenchmarkGetFlatpakLibPaths benchmarks Flatpak path discovery. -func BenchmarkGetFlatpakLibPaths(b *testing.B) { - b.ResetTimer() - for i := 0; i < b.N; i++ { - _ = getFlatpakLibPaths() - } -} - -// BenchmarkGetSnapLibPaths benchmarks Snap path discovery. -func BenchmarkGetSnapLibPaths(b *testing.B) { - b.ResetTimer() - for i := 0; i < b.N; i++ { - _ = getSnapLibPaths() - } -} - -// BenchmarkGetNixLibPaths benchmarks Nix path discovery. -func BenchmarkGetNixLibPaths(b *testing.B) { - b.ResetTimer() - for i := 0; i < b.N; i++ { - _ = getNixLibPaths() - } -} - -// BenchmarkPkgConfigToLibName benchmarks the name conversion function. -func BenchmarkPkgConfigToLibName(b *testing.B) { - names := []string{"gtk+-3.0", "webkit2gtk-4.1", "glib-2.0", "cairo", "libsoup-3.0"} - - b.ResetTimer() - for i := 0; i < b.N; i++ { - for _, name := range names { - _ = pkgConfigToLibName(name) - } - } -} - -// BenchmarkFindLibraryPathSequential benchmarks the sequential search. -func BenchmarkFindLibraryPathSequential(b *testing.B) { - if _, err := exec.LookPath("pkg-config"); err != nil { - b.Skip("pkg-config not available") - } - cmd := exec.Command("pkg-config", "--exists", "glib-2.0") - if cmd.Run() != nil { - b.Skip("glib-2.0 not installed") - } - - b.ResetTimer() - for i := 0; i < b.N; i++ { - _, _ = FindLibraryPathSequential("glib-2.0") - } -} - -// BenchmarkFindLibraryPathSequential_NotFound benchmarks the sequential worst case. -func BenchmarkFindLibraryPathSequential_NotFound(b *testing.B) { - b.ResetTimer() - for i := 0; i < b.N; i++ { - _, _ = FindLibraryPathSequential("nonexistent-library-xyz-123") - } -} - -// BenchmarkFindLibraryPathParallel explicitly tests parallel performance. -func BenchmarkFindLibraryPathParallel(b *testing.B) { - if _, err := exec.LookPath("pkg-config"); err != nil { - b.Skip("pkg-config not available") - } - cmd := exec.Command("pkg-config", "--exists", "glib-2.0") - if cmd.Run() != nil { - b.Skip("glib-2.0 not installed") - } - - b.ResetTimer() - for i := 0; i < b.N; i++ { - _, _ = FindLibraryPath("glib-2.0") - } -} - -// Tests for multi-library search functions - -func TestFindFirstLibrary(t *testing.T) { - if _, err := exec.LookPath("pkg-config"); err != nil { - t.Skip("pkg-config not available") - } - - // Test with a mix of existing and non-existing libraries - match, err := FindFirstLibrary("nonexistent-xyz", "glib-2.0", "also-nonexistent") - if err != nil { - t.Skipf("glib-2.0 not installed: %v", err) - } - - if match.Name != "glib-2.0" { - t.Errorf("Expected glib-2.0, got %s", match.Name) - } - if match.Path == "" { - t.Error("Expected non-empty path") - } -} - -func TestFindFirstLibrary_AllNotFound(t *testing.T) { - _, err := FindFirstLibrary("nonexistent-1", "nonexistent-2", "nonexistent-3") - if err == nil { - t.Error("Expected error for all non-existent libraries") - } -} - -func TestFindFirstLibrary_Empty(t *testing.T) { - _, err := FindFirstLibrary() - if err == nil { - t.Error("Expected error for empty library list") - } -} - -func TestFindFirstLibraryOrdered(t *testing.T) { - if _, err := exec.LookPath("pkg-config"); err != nil { - t.Skip("pkg-config not available") - } - - // glib-2.0 should be found, and since it's first, it should be returned - match, err := FindFirstLibraryOrdered("glib-2.0", "nonexistent-xyz") - if err != nil { - t.Skipf("glib-2.0 not installed: %v", err) - } - - if match.Name != "glib-2.0" { - t.Errorf("Expected glib-2.0, got %s", match.Name) - } -} - -func TestFindFirstLibraryOrdered_PreferFirst(t *testing.T) { - if _, err := exec.LookPath("pkg-config"); err != nil { - t.Skip("pkg-config not available") - } - - // Check what GTK versions are available - gtk4Available := exec.Command("pkg-config", "--exists", "gtk4").Run() == nil - gtk3Available := exec.Command("pkg-config", "--exists", "gtk+-3.0").Run() == nil - - if !gtk4Available && !gtk3Available { - t.Skip("Neither GTK3 nor GTK4 installed") - } - - // If both available, test that order is respected - if gtk4Available && gtk3Available { - match, err := FindFirstLibraryOrdered("gtk4", "gtk+-3.0") - if err != nil { - t.Fatalf("Unexpected error: %v", err) - } - if match.Name != "gtk4" { - t.Errorf("Expected gtk4 (first in order), got %s", match.Name) - } - - // Reverse order - match, err = FindFirstLibraryOrdered("gtk+-3.0", "gtk4") - if err != nil { - t.Fatalf("Unexpected error: %v", err) - } - if match.Name != "gtk+-3.0" { - t.Errorf("Expected gtk+-3.0 (first in order), got %s", match.Name) - } - } -} - -func TestFindAllLibraries(t *testing.T) { - if _, err := exec.LookPath("pkg-config"); err != nil { - t.Skip("pkg-config not available") - } - - matches := FindAllLibraries("glib-2.0", "nonexistent-xyz", "zlib") - - // Should find at least glib-2.0 on most systems - if len(matches) == 0 { - t.Skip("No common libraries found") - } - - t.Logf("Found %d libraries:", len(matches)) - for _, m := range matches { - t.Logf(" %s at %s", m.Name, m.Path) - } - - // Verify no duplicates and no nonexistent library - seen := make(map[string]bool) - for _, m := range matches { - if m.Name == "nonexistent-xyz" { - t.Error("Should not have found nonexistent library") - } - if seen[m.Name] { - t.Errorf("Duplicate match for %s", m.Name) - } - seen[m.Name] = true - } -} - -func TestFindAllLibraries_Empty(t *testing.T) { - matches := FindAllLibraries() - if len(matches) != 0 { - t.Error("Expected empty result for empty input") - } -} - -func TestFindAllLibraries_AllNotFound(t *testing.T) { - matches := FindAllLibraries("nonexistent-1", "nonexistent-2") - if len(matches) != 0 { - t.Errorf("Expected empty result, got %d matches", len(matches)) - } -} - -// Benchmarks for multi-library search - -func BenchmarkFindFirstLibrary(b *testing.B) { - if _, err := exec.LookPath("pkg-config"); err != nil { - b.Skip("pkg-config not available") - } - - b.ResetTimer() - for i := 0; i < b.N; i++ { - _, _ = FindFirstLibrary("nonexistent-1", "glib-2.0", "nonexistent-2") - } -} - -func BenchmarkFindFirstLibraryOrdered(b *testing.B) { - if _, err := exec.LookPath("pkg-config"); err != nil { - b.Skip("pkg-config not available") - } - - b.ResetTimer() - for i := 0; i < b.N; i++ { - _, _ = FindFirstLibraryOrdered("nonexistent-1", "glib-2.0", "nonexistent-2") - } -} - -func BenchmarkFindAllLibraries(b *testing.B) { - if _, err := exec.LookPath("pkg-config"); err != nil { - b.Skip("pkg-config not available") - } - - b.ResetTimer() - for i := 0; i < b.N; i++ { - _ = FindAllLibraries("glib-2.0", "zlib", "nonexistent-xyz") - } -} diff --git a/v3/internal/libpath/libpath_other.go b/v3/internal/libpath/libpath_other.go deleted file mode 100644 index d1c7bc77d..000000000 --- a/v3/internal/libpath/libpath_other.go +++ /dev/null @@ -1,73 +0,0 @@ -//go:build !linux - -package libpath - -// FindLibraryPath is a stub for non-Linux platforms. -func FindLibraryPath(libName string) (string, error) { - return "", &LibraryNotFoundError{Name: libName} -} - -// FindLibraryFile is a stub for non-Linux platforms. -func FindLibraryFile(fileName string) (string, error) { - return "", &LibraryNotFoundError{Name: fileName} -} - -// GetAllLibPaths returns an empty slice on non-Linux platforms. -func GetAllLibPaths() []string { - return nil -} - -// InvalidateCache is a no-op on non-Linux platforms. -func InvalidateCache() {} - -// FindOptions controls library search behavior. -type FindOptions struct { - IncludeCurrentDir bool - ExtraPaths []string -} - -// FindLibraryPathWithOptions is a stub for non-Linux platforms. -func FindLibraryPathWithOptions(libName string, opts FindOptions) (string, error) { - return "", &LibraryNotFoundError{Name: libName} -} - -// LibraryNotFoundError is returned when a library cannot be found. -type LibraryNotFoundError struct { - Name string -} - -func (e *LibraryNotFoundError) Error() string { - return "library not found: " + e.Name -} - -// LibraryMatch holds information about a found library. -type LibraryMatch struct { - Name string - Path string -} - -// FindFirstLibrary is a stub for non-Linux platforms. -func FindFirstLibrary(libNames ...string) (*LibraryMatch, error) { - if len(libNames) == 0 { - return nil, &LibraryNotFoundError{Name: "no libraries specified"} - } - return nil, &LibraryNotFoundError{Name: libNames[0]} -} - -// FindFirstLibraryOrdered is a stub for non-Linux platforms. -func FindFirstLibraryOrdered(libNames ...string) (*LibraryMatch, error) { - if len(libNames) == 0 { - return nil, &LibraryNotFoundError{Name: "no libraries specified"} - } - return nil, &LibraryNotFoundError{Name: libNames[0]} -} - -// FindAllLibraries is a stub for non-Linux platforms. -func FindAllLibraries(libNames ...string) []LibraryMatch { - return nil -} - -// FindLibraryPathSequential is a stub for non-Linux platforms. -func FindLibraryPathSequential(libName string) (string, error) { - return "", &LibraryNotFoundError{Name: libName} -} diff --git a/v3/internal/libpath/nix_linux.go b/v3/internal/libpath/nix_linux.go deleted file mode 100644 index 74d8487a9..000000000 --- a/v3/internal/libpath/nix_linux.go +++ /dev/null @@ -1,28 +0,0 @@ -//go:build linux - -package libpath - -import "os" - -// getNixLibPaths returns cached library paths for Nix/NixOS installations. -func getNixLibPaths() []string { - return cache.getNix() -} - -// discoverNixLibPaths scans for Nix library paths. -func discoverNixLibPaths() []string { - var paths []string - - nixProfileLib := os.ExpandEnv("$HOME/.nix-profile/lib") - if _, err := os.Stat(nixProfileLib); err == nil { - paths = append(paths, nixProfileLib) - } - - // System Nix store - packages expose libs through profiles - nixStoreLib := "/run/current-system/sw/lib" - if _, err := os.Stat(nixStoreLib); err == nil { - paths = append(paths, nixStoreLib) - } - - return paths -} diff --git a/v3/internal/libpath/snap_linux.go b/v3/internal/libpath/snap_linux.go deleted file mode 100644 index 99def76ac..000000000 --- a/v3/internal/libpath/snap_linux.go +++ /dev/null @@ -1,42 +0,0 @@ -//go:build linux - -package libpath - -import ( - "os" - "path/filepath" -) - -// getSnapLibPaths returns cached library paths from installed Snap packages. -func getSnapLibPaths() []string { - return cache.getSnap() -} - -// discoverSnapLibPaths scans for Snap package library directories. -// Scans /snap/*/current/usr/lib* directories. -func discoverSnapLibPaths() []string { - var paths []string - - snapDir := "/snap" - if _, err := os.Stat(snapDir); err != nil { - return paths - } - - // Find all snap packages with lib directories - patterns := []string{ - filepath.Join(snapDir, "*", "current", "usr", "lib"), - filepath.Join(snapDir, "*", "current", "usr", "lib64"), - filepath.Join(snapDir, "*", "current", "usr", "lib", "*-linux-gnu"), - filepath.Join(snapDir, "*", "current", "lib"), - filepath.Join(snapDir, "*", "current", "lib", "*-linux-gnu"), - } - - for _, pattern := range patterns { - matches, err := filepath.Glob(pattern) - if err == nil { - paths = append(paths, matches...) - } - } - - return paths -} diff --git a/v3/internal/operatingsystem/os.go b/v3/internal/operatingsystem/os.go deleted file mode 100644 index 2d5656281..000000000 --- a/v3/internal/operatingsystem/os.go +++ /dev/null @@ -1,23 +0,0 @@ -package operatingsystem - -// OS contains information about the operating system -type OS struct { - ID string - Name string - Version string - Branding string -} - -func (o *OS) AsLogSlice() []any { - return []any{ - "ID", o.ID, - "Name", o.Name, - "Version", o.Version, - "Branding", o.Branding, - } -} - -// Info retrieves information about the current platform -func Info() (*OS, error) { - return platformInfo() -} diff --git a/v3/internal/operatingsystem/os_android.go b/v3/internal/operatingsystem/os_android.go deleted file mode 100644 index 494b84d78..000000000 --- a/v3/internal/operatingsystem/os_android.go +++ /dev/null @@ -1,17 +0,0 @@ -//go:build android - -package operatingsystem - -import ( - "fmt" - "runtime" -) - -func platformInfo() (*OS, error) { - return &OS{ - ID: "android", - Name: "Android", - Version: fmt.Sprintf("Go %s", runtime.Version()), - Branding: "Android", - }, nil -} diff --git a/v3/internal/operatingsystem/os_darwin.go b/v3/internal/operatingsystem/os_darwin.go deleted file mode 100644 index 2975c76f1..000000000 --- a/v3/internal/operatingsystem/os_darwin.go +++ /dev/null @@ -1,72 +0,0 @@ -//go:build darwin - -package operatingsystem - -import ( - "os/exec" - "strings" -) - -var macOSNames = map[string]string{ - "10.10": "Yosemite", - "10.11": "El Capitan", - "10.12": "Sierra", - "10.13": "High Sierra", - "10.14": "Mojave", - "10.15": "Catalina", - "11": "Big Sur", - "12": "Monterey", - "13": "Ventura", - "14": "Sonoma", - "15": "Sequoia", - // Add newer versions as they are released... -} - -func getOSName(version string) string { - trimmedVersion := version - if !strings.HasPrefix(version, "10.") { - trimmedVersion = strings.SplitN(version, ".", 2)[0] - } - name, ok := macOSNames[trimmedVersion] - if ok { - return name - } - return "MacOS " + version -} - -func getSysctlValue(key string) (string, error) { - // Run "sysctl" command - command := exec.Command("sysctl", key) - // Capture stdout - var stdout strings.Builder - command.Stdout = &stdout - // Run command - err := command.Run() - if err != nil { - return "", err - } - version := strings.TrimPrefix(stdout.String(), key+": ") - return strings.TrimSpace(version), nil -} - -func platformInfo() (*OS, error) { - // Default value - var result OS - result.ID = "Unknown" - result.Name = "MacOS" - result.Version = "Unknown" - - version, err := getSysctlValue("kern.osproductversion") - if err != nil { - return nil, err - } - result.Version = version - ID, err := getSysctlValue("kern.osversion") - if err != nil { - return nil, err - } - result.ID = ID - result.Branding = getOSName(result.Version) - - return &result, nil -} diff --git a/v3/internal/operatingsystem/os_linux.go b/v3/internal/operatingsystem/os_linux.go deleted file mode 100644 index 04cd39b9a..000000000 --- a/v3/internal/operatingsystem/os_linux.go +++ /dev/null @@ -1,52 +0,0 @@ -//go:build linux && !android - -package operatingsystem - -import ( - "fmt" - "os" - "strings" -) - -// platformInfo is the platform specific method to get system information -func platformInfo() (*OS, error) { - _, err := os.Stat("/etc/os-release") - if os.IsNotExist(err) { - return nil, fmt.Errorf("unable to read system information") - } - - osRelease, _ := os.ReadFile("/etc/os-release") - return parseOsRelease(string(osRelease)), nil -} - -func parseOsRelease(osRelease string) *OS { - - // Default value - var result OS - result.ID = "Unknown" - result.Name = "Unknown" - result.Version = "Unknown" - - // Split into lines - lines := strings.Split(osRelease, "\n") - // Iterate lines - for _, line := range lines { - // Split each line by the equals char - splitLine := strings.SplitN(line, "=", 2) - // Check we have - if len(splitLine) != 2 { - continue - } - switch splitLine[0] { - case "ID": - result.ID = strings.ToLower(strings.Trim(splitLine[1], `"`)) - case "NAME": - result.Name = strings.Trim(splitLine[1], `"`) - case "VERSION_ID": - result.Version = strings.Trim(splitLine[1], `"`) - case "VERSION": - result.Branding = strings.Trim(splitLine[1], `"`) - } - } - return &result -} diff --git a/v3/internal/operatingsystem/os_windows.go b/v3/internal/operatingsystem/os_windows.go deleted file mode 100644 index 2e8c0775b..000000000 --- a/v3/internal/operatingsystem/os_windows.go +++ /dev/null @@ -1,34 +0,0 @@ -//go:build windows - -package operatingsystem - -import ( - "fmt" - "github.com/wailsapp/wails/v3/pkg/w32" - - "golang.org/x/sys/windows/registry" -) - -func platformInfo() (*OS, error) { - // Default value - var result OS - result.ID = "Unknown" - result.Name = "Windows" - result.Version = "Unknown" - - // Credit: https://stackoverflow.com/a/33288328 - // Ignore errors as it isn't a showstopper - key, _ := registry.OpenKey(registry.LOCAL_MACHINE, `SOFTWARE\Microsoft\Windows NT\CurrentVersion`, registry.QUERY_VALUE) - - productName, _, _ := key.GetStringValue("ProductName") - currentBuild, _, _ := key.GetStringValue("CurrentBuildNumber") - displayVersion, _, _ := key.GetStringValue("DisplayVersion") - releaseId, _, _ := key.GetStringValue("ReleaseId") - - result.Name = productName - result.Version = fmt.Sprintf("%s (Build: %s)", releaseId, currentBuild) - result.ID = displayVersion - result.Branding = w32.GetBranding() - - return &result, key.Close() -} diff --git a/v3/internal/operatingsystem/version_windows.go b/v3/internal/operatingsystem/version_windows.go deleted file mode 100644 index a8f53d134..000000000 --- a/v3/internal/operatingsystem/version_windows.go +++ /dev/null @@ -1,62 +0,0 @@ -//go:build windows - -package operatingsystem - -import ( - "strconv" - - "golang.org/x/sys/windows/registry" -) - -type WindowsVersionInfo struct { - Major int - Minor int - Build int - DisplayVersion string -} - -func (w *WindowsVersionInfo) IsWindowsVersionAtLeast(major, minor, buildNumber int) bool { - return w.Major >= major && w.Minor >= minor && w.Build >= buildNumber -} - -func GetWindowsVersionInfo() (*WindowsVersionInfo, error) { - key, err := registry.OpenKey(registry.LOCAL_MACHINE, `SOFTWARE\Microsoft\Windows NT\CurrentVersion`, registry.QUERY_VALUE) - if err != nil { - return nil, err - } - - return &WindowsVersionInfo{ - Major: regDWORDKeyAsInt(key, "CurrentMajorVersionNumber"), - Minor: regDWORDKeyAsInt(key, "CurrentMinorVersionNumber"), - Build: regStringKeyAsInt(key, "CurrentBuildNumber"), - DisplayVersion: regKeyAsString(key, "DisplayVersion"), - }, nil -} - -func regDWORDKeyAsInt(key registry.Key, name string) int { - result, _, err := key.GetIntegerValue(name) - if err != nil { - return -1 - } - return int(result) -} - -func regStringKeyAsInt(key registry.Key, name string) int { - resultStr, _, err := key.GetStringValue(name) - if err != nil { - return -1 - } - result, err := strconv.Atoi(resultStr) - if err != nil { - return -1 - } - return result -} - -func regKeyAsString(key registry.Key, name string) string { - resultStr, _, err := key.GetStringValue(name) - if err != nil { - return "" - } - return resultStr -} diff --git a/v3/internal/operatingsystem/webkit_linux.go b/v3/internal/operatingsystem/webkit_linux.go deleted file mode 100644 index ce74337b0..000000000 --- a/v3/internal/operatingsystem/webkit_linux.go +++ /dev/null @@ -1,42 +0,0 @@ -//go:build linux && cgo && !gtk4 && !android - -package operatingsystem - -/* -#cgo linux pkg-config: gtk+-3.0 webkit2gtk-4.1 -#include -*/ -import "C" -import "fmt" - -type WebkitVersion struct { - Major uint - Minor uint - Micro uint -} - -func GetWebkitVersion() WebkitVersion { - var major, minor, micro C.uint - major = C.webkit_get_major_version() - minor = C.webkit_get_minor_version() - micro = C.webkit_get_micro_version() - return WebkitVersion{ - Major: uint(major), - Minor: uint(minor), - Micro: uint(micro), - } -} - -func (v WebkitVersion) String() string { - return fmt.Sprintf("v%d.%d.%d", v.Major, v.Minor, v.Micro) -} - -func (v WebkitVersion) IsAtLeast(major int, minor int, micro int) bool { - if v.Major != uint(major) { - return v.Major > uint(major) - } - if v.Minor != uint(minor) { - return v.Minor > uint(minor) - } - return v.Micro >= uint(micro) -} diff --git a/v3/internal/operatingsystem/webkit_linux_gtk4.go b/v3/internal/operatingsystem/webkit_linux_gtk4.go deleted file mode 100644 index fb7217e2c..000000000 --- a/v3/internal/operatingsystem/webkit_linux_gtk4.go +++ /dev/null @@ -1,42 +0,0 @@ -//go:build linux && cgo && gtk4 && !android - -package operatingsystem - -/* -#cgo linux pkg-config: gtk4 webkitgtk-6.0 -#include -*/ -import "C" -import "fmt" - -type WebkitVersion struct { - Major uint - Minor uint - Micro uint -} - -func GetWebkitVersion() WebkitVersion { - var major, minor, micro C.uint - major = C.webkit_get_major_version() - minor = C.webkit_get_minor_version() - micro = C.webkit_get_micro_version() - return WebkitVersion{ - Major: uint(major), - Minor: uint(minor), - Micro: uint(micro), - } -} - -func (v WebkitVersion) String() string { - return fmt.Sprintf("v%d.%d.%d", v.Major, v.Minor, v.Micro) -} - -func (v WebkitVersion) IsAtLeast(major int, minor int, micro int) bool { - if v.Major != uint(major) { - return v.Major > uint(major) - } - if v.Minor != uint(minor) { - return v.Minor > uint(minor) - } - return v.Micro >= uint(micro) -} diff --git a/v3/internal/packager/packager.go b/v3/internal/packager/packager.go deleted file mode 100644 index 5cf235d72..000000000 --- a/v3/internal/packager/packager.go +++ /dev/null @@ -1,94 +0,0 @@ -// Package packager provides a simplified interface for creating Linux packages using nfpm -package packager - -import ( - "fmt" - "io" - "os" - - "github.com/goreleaser/nfpm/v2" - _ "github.com/goreleaser/nfpm/v2/apk" // Register APK packager - _ "github.com/goreleaser/nfpm/v2/arch" // Register Arch Linux packager - _ "github.com/goreleaser/nfpm/v2/deb" // Register DEB packager - _ "github.com/goreleaser/nfpm/v2/ipk" // Register IPK packager - _ "github.com/goreleaser/nfpm/v2/rpm" // Register RPM packager -) - -// PackageType represents supported package formats -type PackageType string - -const ( - // DEB is for Debian/Ubuntu packages - DEB PackageType = "deb" - // RPM is for RedHat/CentOS packages - RPM PackageType = "rpm" - // APK is for Alpine Linux packages - APK PackageType = "apk" - // IPK is for OpenWrt packages - IPK PackageType = "ipk" - // ARCH is for Arch Linux packages - ARCH PackageType = "archlinux" -) - -// CreatePackageFromConfig loads a configuration file and creates a package -func CreatePackageFromConfig(pkgType PackageType, configPath string, output string) error { - // Parse nfpm config - config, err := nfpm.ParseFile(configPath) - if err != nil { - return fmt.Errorf("error parsing config file: %w", err) - } - - // Get info for the specified packager - info, err := config.Get(string(pkgType)) - if err != nil { - return fmt.Errorf("error getting packager info: %w", err) - } - - // Get the packager - packager, err := nfpm.Get(string(pkgType)) - if err != nil { - return fmt.Errorf("error getting packager: %w", err) - } - - // Create output file - out, err := os.Create(output) - if err != nil { - return fmt.Errorf("error creating output file: %w", err) - } - defer out.Close() - - // Create the package - if err := packager.Package(info, out); err != nil { - return fmt.Errorf("error creating package: %w", err) - } - - return nil -} - -// CreatePackageFromConfigWriter loads a configuration file and writes the package to the provided writer -func CreatePackageFromConfigWriter(pkgType PackageType, configPath string, output io.Writer) error { - // Parse nfpm config - config, err := nfpm.ParseFile(configPath) - if err != nil { - return fmt.Errorf("error parsing config file: %w", err) - } - - // Get info for the specified packager - info, err := config.Get(string(pkgType)) - if err != nil { - return fmt.Errorf("error getting packager info: %w", err) - } - - // Get the packager - packager, err := nfpm.Get(string(pkgType)) - if err != nil { - return fmt.Errorf("error getting packager: %w", err) - } - - // Create the package - if err := packager.Package(info, output); err != nil { - return fmt.Errorf("error creating package: %w", err) - } - - return nil -} diff --git a/v3/internal/packager/packager_test.go b/v3/internal/packager/packager_test.go deleted file mode 100644 index 3ed4a4f48..000000000 --- a/v3/internal/packager/packager_test.go +++ /dev/null @@ -1,100 +0,0 @@ -package packager - -import ( - "bytes" - "os" - "path/filepath" - "testing" -) - -func TestCreatePackageFromConfig(t *testing.T) { - // Create a temporary file for testing - content := []byte("test content") - tmpfile, err := os.CreateTemp("", "example") - if err != nil { - t.Fatal(err) - } - defer os.Remove(tmpfile.Name()) - - if _, err := tmpfile.Write(content); err != nil { - t.Fatal(err) - } - if err := tmpfile.Close(); err != nil { - t.Fatal(err) - } - - // Create a temporary config file - configContent := []byte(` -name: test-package -version: v1.0.0 -arch: amd64 -description: Test package -maintainer: Test User -license: MIT -contents: -- src: ` + tmpfile.Name() + ` - dst: /usr/local/bin/test-file -`) - - configFile, err := os.CreateTemp("", "config*.yaml") - if err != nil { - t.Fatal(err) - } - defer os.Remove(configFile.Name()) - - if _, err := configFile.Write(configContent); err != nil { - t.Fatal(err) - } - if err := configFile.Close(); err != nil { - t.Fatal(err) - } - - // Test creating packages for each format - formats := []struct { - pkgType PackageType - ext string - }{ - {DEB, "deb"}, - {RPM, "rpm"}, - {APK, "apk"}, - {IPK, "ipk"}, - {ARCH, "pkg.tar.zst"}, - } - - for _, format := range formats { - t.Run(string(format.pkgType), func(t *testing.T) { - // Test file-based package creation - outputPath := filepath.Join(os.TempDir(), "test-package."+format.ext) - err := CreatePackageFromConfig(format.pkgType, configFile.Name(), outputPath) - if err != nil { - t.Errorf("CreatePackageFromConfig failed for %s: %v", format.pkgType, err) - } - defer os.Remove(outputPath) - - // Verify the file was created - if _, err := os.Stat(outputPath); os.IsNotExist(err) { - t.Errorf("Package file was not created for %s", format.pkgType) - } - - // Test writer-based package creation - var buf bytes.Buffer - err = CreatePackageFromConfigWriter(format.pkgType, configFile.Name(), &buf) - if err != nil { - t.Errorf("CreatePackageFromConfigWriter failed for %s: %v", format.pkgType, err) - } - - // Verify some content was written - if buf.Len() == 0 { - t.Errorf("No content was written for %s", format.pkgType) - } - }) - } - - // Test with invalid config file - t.Run("InvalidConfig", func(t *testing.T) { - err := CreatePackageFromConfig(DEB, "nonexistent.yaml", "output.deb") - if err == nil { - t.Error("Expected error for invalid config, got nil") - } - }) -} diff --git a/v3/internal/runtime/.gitignore b/v3/internal/runtime/.gitignore deleted file mode 100644 index 059d2134d..000000000 --- a/v3/internal/runtime/.gitignore +++ /dev/null @@ -1,5 +0,0 @@ -node_modules -.task -*.tsbuildinfo -desktop/@wailsio/runtime/dist/ -desktop/@wailsio/runtime/types/ diff --git a/v3/internal/runtime/README.md b/v3/internal/runtime/README.md deleted file mode 100644 index c4b43d430..000000000 --- a/v3/internal/runtime/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# Runtime - -To rebuild the runtime run `task build` or if you have Wails v3 CLI, you can use `wails3 task build`. diff --git a/v3/internal/runtime/Taskfile.yaml b/v3/internal/runtime/Taskfile.yaml deleted file mode 100644 index 4a2a2ccf3..000000000 --- a/v3/internal/runtime/Taskfile.yaml +++ /dev/null @@ -1,112 +0,0 @@ -# https://taskfile.dev - -version: "3" - -tasks: - install-deps: - internal: true - dir: desktop/@wailsio/runtime - sources: - - package.json - cmds: - - npm install - - check: - dir: desktop/@wailsio/runtime - deps: - - install-deps - cmds: - - npm run check - - test: - dir: desktop/@wailsio/runtime - deps: - - install-deps - cmds: - - npm test - - build:debug: - internal: true - cmds: - - npx esbuild@latest desktop/@wailsio/runtime/src/index.ts --inject:desktop/compiled/main.js --format=esm --target=safari11 --bundle --ignore-annotations --tree-shaking=true --sourcemap=inline --outfile=../assetserver/bundledassets/runtime.debug.js --define:DEBUG=true - - build:production: - internal: true - cmds: - - npx esbuild@latest desktop/@wailsio/runtime/src/index.ts --inject:desktop/compiled/main.js --format=esm --target=safari11 --bundle --ignore-annotations --tree-shaking=true --minify --outfile=../assetserver/bundledassets/runtime.js --define:DEBUG=false --drop:console - - build:docs: - internal: true - dir: desktop/@wailsio/runtime - deps: - - install-deps - cmds: - - npm run build:docs - - build:docs:md: - internal: true - dir: desktop/@wailsio/runtime - deps: - - install-deps - cmds: - - npm run build:docs:md - - build:runtime: - internal: true - deps: - - build:debug - - build:production - - cmds: - - cmd: echo "Runtime build complete." - - build:all: - internal: true - cmds: - - task: generate:events - - task: build:docs - - task: build:runtime - - echo "Build Complete." - - build: - deps: - - install-deps - cmds: - - task: build:all - - docs: - summary: Generate TypeDoc documentation for the runtime - dir: desktop/@wailsio/runtime - deps: - - install-deps - cmds: - - npm run build:docs - - echo "Documentation generated at desktop/@wailsio/runtime/docs/" - - docs:md: - summary: Generate markdown documentation for the runtime - dir: desktop/@wailsio/runtime - deps: - - install-deps - cmds: - - npm run build:docs:md - - echo "Markdown documentation generated" - - generate:events: - dir: ../../tasks/events - cmds: - - go run generate.go - - go fmt ../../pkg/events/events.go - - clean: - summary: Clean built artifacts and documentation - dir: desktop/@wailsio/runtime - cmds: - - npm run clean - - echo "Cleaned runtime artifacts" - - generate: - summary: Generate events only (use runtime:build to rebuild everything) - cmds: - - task: generate:events - - echo "Events generated. Run 'wails3 task runtime:build' to rebuild runtime with updated documentation" diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/docs/.nojekyll b/v3/internal/runtime/desktop/@wailsio/runtime/docs/.nojekyll deleted file mode 100644 index e2ac6616a..000000000 --- a/v3/internal/runtime/desktop/@wailsio/runtime/docs/.nojekyll +++ /dev/null @@ -1 +0,0 @@ -TypeDoc added this file to prevent GitHub Pages from using Jekyll. You can turn off this behavior by setting the `githubPages` option to false. \ No newline at end of file diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/docs/assets/hierarchy.js b/v3/internal/runtime/desktop/@wailsio/runtime/docs/assets/hierarchy.js deleted file mode 100644 index 21e4c9062..000000000 --- a/v3/internal/runtime/desktop/@wailsio/runtime/docs/assets/hierarchy.js +++ /dev/null @@ -1 +0,0 @@ -window.hierarchyData = "eJylj8EKwjAQRP9lzqliitHm6tWDdyklpiuGbhNI4kny71JF8aAieNplh9l5c0EMISfovaob0chVKxDpyGSzCz5BX6DqZhrejASNjfGWmM2BaRfD6BJt3UAQGJzvoeVSCZwjQ8P5TPFoLKX5e9PslEeGgGWTEjRy6qvpS/V0TuLJcR/JT4RKtkVAKfmV58mykOsHyy3iLchHiPuhCDRy9ZL3e+nutnvD3ezf0qVcATe3jnU=" \ No newline at end of file diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/docs/assets/highlight.css b/v3/internal/runtime/desktop/@wailsio/runtime/docs/assets/highlight.css deleted file mode 100644 index 5ee358c5e..000000000 --- a/v3/internal/runtime/desktop/@wailsio/runtime/docs/assets/highlight.css +++ /dev/null @@ -1,78 +0,0 @@ -:root { - --light-hl-0: #0000FF; - --dark-hl-0: #569CD6; - --light-hl-1: #000000; - --dark-hl-1: #D4D4D4; - --light-hl-2: #001080; - --dark-hl-2: #9CDCFE; - --light-hl-3: #795E26; - --dark-hl-3: #DCDCAA; - --light-hl-4: #008000; - --dark-hl-4: #6A9955; - --light-hl-5: #AF00DB; - --dark-hl-5: #C586C0; - --light-hl-6: #A31515; - --dark-hl-6: #CE9178; - --light-hl-7: #0070C1; - --dark-hl-7: #4FC1FF; - --light-code-background: #FFFFFF; - --dark-code-background: #1E1E1E; -} - -@media (prefers-color-scheme: light) { :root { - --hl-0: var(--light-hl-0); - --hl-1: var(--light-hl-1); - --hl-2: var(--light-hl-2); - --hl-3: var(--light-hl-3); - --hl-4: var(--light-hl-4); - --hl-5: var(--light-hl-5); - --hl-6: var(--light-hl-6); - --hl-7: var(--light-hl-7); - --code-background: var(--light-code-background); -} } - -@media (prefers-color-scheme: dark) { :root { - --hl-0: var(--dark-hl-0); - --hl-1: var(--dark-hl-1); - --hl-2: var(--dark-hl-2); - --hl-3: var(--dark-hl-3); - --hl-4: var(--dark-hl-4); - --hl-5: var(--dark-hl-5); - --hl-6: var(--dark-hl-6); - --hl-7: var(--dark-hl-7); - --code-background: var(--dark-code-background); -} } - -:root[data-theme='light'] { - --hl-0: var(--light-hl-0); - --hl-1: var(--light-hl-1); - --hl-2: var(--light-hl-2); - --hl-3: var(--light-hl-3); - --hl-4: var(--light-hl-4); - --hl-5: var(--light-hl-5); - --hl-6: var(--light-hl-6); - --hl-7: var(--light-hl-7); - --code-background: var(--light-code-background); -} - -:root[data-theme='dark'] { - --hl-0: var(--dark-hl-0); - --hl-1: var(--dark-hl-1); - --hl-2: var(--dark-hl-2); - --hl-3: var(--dark-hl-3); - --hl-4: var(--dark-hl-4); - --hl-5: var(--dark-hl-5); - --hl-6: var(--dark-hl-6); - --hl-7: var(--dark-hl-7); - --code-background: var(--dark-code-background); -} - -.hl-0 { color: var(--hl-0); } -.hl-1 { color: var(--hl-1); } -.hl-2 { color: var(--hl-2); } -.hl-3 { color: var(--hl-3); } -.hl-4 { color: var(--hl-4); } -.hl-5 { color: var(--hl-5); } -.hl-6 { color: var(--hl-6); } -.hl-7 { color: var(--hl-7); } -pre, code { background: var(--code-background); } diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/docs/assets/icons.js b/v3/internal/runtime/desktop/@wailsio/runtime/docs/assets/icons.js deleted file mode 100644 index 58882d76d..000000000 --- a/v3/internal/runtime/desktop/@wailsio/runtime/docs/assets/icons.js +++ /dev/null @@ -1,18 +0,0 @@ -(function() { - addIcons(); - function addIcons() { - if (document.readyState === "loading") return document.addEventListener("DOMContentLoaded", addIcons); - const svg = document.body.appendChild(document.createElementNS("http://www.w3.org/2000/svg", "svg")); - svg.innerHTML = `MMNEPVFCICPMFPCPTTAAATR`; - svg.style.display = "none"; - if (location.protocol === "file:") updateUseElements(); - } - - function updateUseElements() { - document.querySelectorAll("use").forEach(el => { - if (el.getAttribute("href").includes("#icon-")) { - el.setAttribute("href", el.getAttribute("href").replace(/.*#/, "#")); - } - }); - } -})() \ No newline at end of file diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/docs/assets/icons.svg b/v3/internal/runtime/desktop/@wailsio/runtime/docs/assets/icons.svg deleted file mode 100644 index 50ad5799d..000000000 --- a/v3/internal/runtime/desktop/@wailsio/runtime/docs/assets/icons.svg +++ /dev/null @@ -1 +0,0 @@ -MMNEPVFCICPMFPCPTTAAATR \ No newline at end of file diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/docs/assets/main.js b/v3/internal/runtime/desktop/@wailsio/runtime/docs/assets/main.js deleted file mode 100644 index 2363f64c2..000000000 --- a/v3/internal/runtime/desktop/@wailsio/runtime/docs/assets/main.js +++ /dev/null @@ -1,60 +0,0 @@ -"use strict"; -window.translations={"copy":"Copy","copied":"Copied!","normally_hidden":"This member is normally hidden due to your filter settings.","hierarchy_expand":"Expand","hierarchy_collapse":"Collapse","folder":"Folder","kind_1":"Project","kind_2":"Module","kind_4":"Namespace","kind_8":"Enumeration","kind_16":"Enumeration Member","kind_32":"Variable","kind_64":"Function","kind_128":"Class","kind_256":"Interface","kind_512":"Constructor","kind_1024":"Property","kind_2048":"Method","kind_4096":"Call Signature","kind_8192":"Index Signature","kind_16384":"Constructor Signature","kind_32768":"Parameter","kind_65536":"Type Literal","kind_131072":"Type Parameter","kind_262144":"Accessor","kind_524288":"Get Signature","kind_1048576":"Set Signature","kind_2097152":"Type Alias","kind_4194304":"Reference","kind_8388608":"Document"}; -"use strict";(()=>{var De=Object.create;var le=Object.defineProperty;var Fe=Object.getOwnPropertyDescriptor;var Ne=Object.getOwnPropertyNames;var Ve=Object.getPrototypeOf,Be=Object.prototype.hasOwnProperty;var qe=(t,e)=>()=>(e||t((e={exports:{}}).exports,e),e.exports);var je=(t,e,n,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let i of Ne(e))!Be.call(t,i)&&i!==n&&le(t,i,{get:()=>e[i],enumerable:!(r=Fe(e,i))||r.enumerable});return t};var $e=(t,e,n)=>(n=t!=null?De(Ve(t)):{},je(e||!t||!t.__esModule?le(n,"default",{value:t,enumerable:!0}):n,t));var pe=qe((de,he)=>{(function(){var t=function(e){var n=new t.Builder;return n.pipeline.add(t.trimmer,t.stopWordFilter,t.stemmer),n.searchPipeline.add(t.stemmer),e.call(n,n),n.build()};t.version="2.3.9";t.utils={},t.utils.warn=function(e){return function(n){e.console&&console.warn&&console.warn(n)}}(this),t.utils.asString=function(e){return e==null?"":e.toString()},t.utils.clone=function(e){if(e==null)return e;for(var n=Object.create(null),r=Object.keys(e),i=0;i0){var d=t.utils.clone(n)||{};d.position=[a,c],d.index=s.length,s.push(new t.Token(r.slice(a,o),d))}a=o+1}}return s},t.tokenizer.separator=/[\s\-]+/;t.Pipeline=function(){this._stack=[]},t.Pipeline.registeredFunctions=Object.create(null),t.Pipeline.registerFunction=function(e,n){n in this.registeredFunctions&&t.utils.warn("Overwriting existing registered function: "+n),e.label=n,t.Pipeline.registeredFunctions[e.label]=e},t.Pipeline.warnIfFunctionNotRegistered=function(e){var n=e.label&&e.label in this.registeredFunctions;n||t.utils.warn(`Function is not registered with pipeline. This may cause problems when serialising the index. -`,e)},t.Pipeline.load=function(e){var n=new t.Pipeline;return e.forEach(function(r){var i=t.Pipeline.registeredFunctions[r];if(i)n.add(i);else throw new Error("Cannot load unregistered function: "+r)}),n},t.Pipeline.prototype.add=function(){var e=Array.prototype.slice.call(arguments);e.forEach(function(n){t.Pipeline.warnIfFunctionNotRegistered(n),this._stack.push(n)},this)},t.Pipeline.prototype.after=function(e,n){t.Pipeline.warnIfFunctionNotRegistered(n);var r=this._stack.indexOf(e);if(r==-1)throw new Error("Cannot find existingFn");r=r+1,this._stack.splice(r,0,n)},t.Pipeline.prototype.before=function(e,n){t.Pipeline.warnIfFunctionNotRegistered(n);var r=this._stack.indexOf(e);if(r==-1)throw new Error("Cannot find existingFn");this._stack.splice(r,0,n)},t.Pipeline.prototype.remove=function(e){var n=this._stack.indexOf(e);n!=-1&&this._stack.splice(n,1)},t.Pipeline.prototype.run=function(e){for(var n=this._stack.length,r=0;r1&&(oe&&(r=s),o!=e);)i=r-n,s=n+Math.floor(i/2),o=this.elements[s*2];if(o==e||o>e)return s*2;if(ol?d+=2:a==l&&(n+=r[c+1]*i[d+1],c+=2,d+=2);return n},t.Vector.prototype.similarity=function(e){return this.dot(e)/this.magnitude()||0},t.Vector.prototype.toArray=function(){for(var e=new Array(this.elements.length/2),n=1,r=0;n0){var o=s.str.charAt(0),a;o in s.node.edges?a=s.node.edges[o]:(a=new t.TokenSet,s.node.edges[o]=a),s.str.length==1&&(a.final=!0),i.push({node:a,editsRemaining:s.editsRemaining,str:s.str.slice(1)})}if(s.editsRemaining!=0){if("*"in s.node.edges)var l=s.node.edges["*"];else{var l=new t.TokenSet;s.node.edges["*"]=l}if(s.str.length==0&&(l.final=!0),i.push({node:l,editsRemaining:s.editsRemaining-1,str:s.str}),s.str.length>1&&i.push({node:s.node,editsRemaining:s.editsRemaining-1,str:s.str.slice(1)}),s.str.length==1&&(s.node.final=!0),s.str.length>=1){if("*"in s.node.edges)var c=s.node.edges["*"];else{var c=new t.TokenSet;s.node.edges["*"]=c}s.str.length==1&&(c.final=!0),i.push({node:c,editsRemaining:s.editsRemaining-1,str:s.str.slice(1)})}if(s.str.length>1){var d=s.str.charAt(0),m=s.str.charAt(1),p;m in s.node.edges?p=s.node.edges[m]:(p=new t.TokenSet,s.node.edges[m]=p),s.str.length==1&&(p.final=!0),i.push({node:p,editsRemaining:s.editsRemaining-1,str:d+s.str.slice(2)})}}}return r},t.TokenSet.fromString=function(e){for(var n=new t.TokenSet,r=n,i=0,s=e.length;i=e;n--){var r=this.uncheckedNodes[n],i=r.child.toString();i in this.minimizedNodes?r.parent.edges[r.char]=this.minimizedNodes[i]:(r.child._str=i,this.minimizedNodes[i]=r.child),this.uncheckedNodes.pop()}};t.Index=function(e){this.invertedIndex=e.invertedIndex,this.fieldVectors=e.fieldVectors,this.tokenSet=e.tokenSet,this.fields=e.fields,this.pipeline=e.pipeline},t.Index.prototype.search=function(e){return this.query(function(n){var r=new t.QueryParser(e,n);r.parse()})},t.Index.prototype.query=function(e){for(var n=new t.Query(this.fields),r=Object.create(null),i=Object.create(null),s=Object.create(null),o=Object.create(null),a=Object.create(null),l=0;l1?this._b=1:this._b=e},t.Builder.prototype.k1=function(e){this._k1=e},t.Builder.prototype.add=function(e,n){var r=e[this._ref],i=Object.keys(this._fields);this._documents[r]=n||{},this.documentCount+=1;for(var s=0;s=this.length)return t.QueryLexer.EOS;var e=this.str.charAt(this.pos);return this.pos+=1,e},t.QueryLexer.prototype.width=function(){return this.pos-this.start},t.QueryLexer.prototype.ignore=function(){this.start==this.pos&&(this.pos+=1),this.start=this.pos},t.QueryLexer.prototype.backup=function(){this.pos-=1},t.QueryLexer.prototype.acceptDigitRun=function(){var e,n;do e=this.next(),n=e.charCodeAt(0);while(n>47&&n<58);e!=t.QueryLexer.EOS&&this.backup()},t.QueryLexer.prototype.more=function(){return this.pos1&&(e.backup(),e.emit(t.QueryLexer.TERM)),e.ignore(),e.more())return t.QueryLexer.lexText},t.QueryLexer.lexEditDistance=function(e){return e.ignore(),e.acceptDigitRun(),e.emit(t.QueryLexer.EDIT_DISTANCE),t.QueryLexer.lexText},t.QueryLexer.lexBoost=function(e){return e.ignore(),e.acceptDigitRun(),e.emit(t.QueryLexer.BOOST),t.QueryLexer.lexText},t.QueryLexer.lexEOS=function(e){e.width()>0&&e.emit(t.QueryLexer.TERM)},t.QueryLexer.termSeparator=t.tokenizer.separator,t.QueryLexer.lexText=function(e){for(;;){var n=e.next();if(n==t.QueryLexer.EOS)return t.QueryLexer.lexEOS;if(n.charCodeAt(0)==92){e.escapeCharacter();continue}if(n==":")return t.QueryLexer.lexField;if(n=="~")return e.backup(),e.width()>0&&e.emit(t.QueryLexer.TERM),t.QueryLexer.lexEditDistance;if(n=="^")return e.backup(),e.width()>0&&e.emit(t.QueryLexer.TERM),t.QueryLexer.lexBoost;if(n=="+"&&e.width()===1||n=="-"&&e.width()===1)return e.emit(t.QueryLexer.PRESENCE),t.QueryLexer.lexText;if(n.match(t.QueryLexer.termSeparator))return t.QueryLexer.lexTerm}},t.QueryParser=function(e,n){this.lexer=new t.QueryLexer(e),this.query=n,this.currentClause={},this.lexemeIdx=0},t.QueryParser.prototype.parse=function(){this.lexer.run(),this.lexemes=this.lexer.lexemes;for(var e=t.QueryParser.parseClause;e;)e=e(this);return this.query},t.QueryParser.prototype.peekLexeme=function(){return this.lexemes[this.lexemeIdx]},t.QueryParser.prototype.consumeLexeme=function(){var e=this.peekLexeme();return this.lexemeIdx+=1,e},t.QueryParser.prototype.nextClause=function(){var e=this.currentClause;this.query.clause(e),this.currentClause={}},t.QueryParser.parseClause=function(e){var n=e.peekLexeme();if(n!=null)switch(n.type){case t.QueryLexer.PRESENCE:return t.QueryParser.parsePresence;case t.QueryLexer.FIELD:return t.QueryParser.parseField;case t.QueryLexer.TERM:return t.QueryParser.parseTerm;default:var r="expected either a field or a term, found "+n.type;throw n.str.length>=1&&(r+=" with value '"+n.str+"'"),new t.QueryParseError(r,n.start,n.end)}},t.QueryParser.parsePresence=function(e){var n=e.consumeLexeme();if(n!=null){switch(n.str){case"-":e.currentClause.presence=t.Query.presence.PROHIBITED;break;case"+":e.currentClause.presence=t.Query.presence.REQUIRED;break;default:var r="unrecognised presence operator'"+n.str+"'";throw new t.QueryParseError(r,n.start,n.end)}var i=e.peekLexeme();if(i==null){var r="expecting term or field, found nothing";throw new t.QueryParseError(r,n.start,n.end)}switch(i.type){case t.QueryLexer.FIELD:return t.QueryParser.parseField;case t.QueryLexer.TERM:return t.QueryParser.parseTerm;default:var r="expecting term or field, found '"+i.type+"'";throw new t.QueryParseError(r,i.start,i.end)}}},t.QueryParser.parseField=function(e){var n=e.consumeLexeme();if(n!=null){if(e.query.allFields.indexOf(n.str)==-1){var r=e.query.allFields.map(function(o){return"'"+o+"'"}).join(", "),i="unrecognised field '"+n.str+"', possible fields: "+r;throw new t.QueryParseError(i,n.start,n.end)}e.currentClause.fields=[n.str];var s=e.peekLexeme();if(s==null){var i="expecting term, found nothing";throw new t.QueryParseError(i,n.start,n.end)}switch(s.type){case t.QueryLexer.TERM:return t.QueryParser.parseTerm;default:var i="expecting term, found '"+s.type+"'";throw new t.QueryParseError(i,s.start,s.end)}}},t.QueryParser.parseTerm=function(e){var n=e.consumeLexeme();if(n!=null){e.currentClause.term=n.str.toLowerCase(),n.str.indexOf("*")!=-1&&(e.currentClause.usePipeline=!1);var r=e.peekLexeme();if(r==null){e.nextClause();return}switch(r.type){case t.QueryLexer.TERM:return e.nextClause(),t.QueryParser.parseTerm;case t.QueryLexer.FIELD:return e.nextClause(),t.QueryParser.parseField;case t.QueryLexer.EDIT_DISTANCE:return t.QueryParser.parseEditDistance;case t.QueryLexer.BOOST:return t.QueryParser.parseBoost;case t.QueryLexer.PRESENCE:return e.nextClause(),t.QueryParser.parsePresence;default:var i="Unexpected lexeme type '"+r.type+"'";throw new t.QueryParseError(i,r.start,r.end)}}},t.QueryParser.parseEditDistance=function(e){var n=e.consumeLexeme();if(n!=null){var r=parseInt(n.str,10);if(isNaN(r)){var i="edit distance must be numeric";throw new t.QueryParseError(i,n.start,n.end)}e.currentClause.editDistance=r;var s=e.peekLexeme();if(s==null){e.nextClause();return}switch(s.type){case t.QueryLexer.TERM:return e.nextClause(),t.QueryParser.parseTerm;case t.QueryLexer.FIELD:return e.nextClause(),t.QueryParser.parseField;case t.QueryLexer.EDIT_DISTANCE:return t.QueryParser.parseEditDistance;case t.QueryLexer.BOOST:return t.QueryParser.parseBoost;case t.QueryLexer.PRESENCE:return e.nextClause(),t.QueryParser.parsePresence;default:var i="Unexpected lexeme type '"+s.type+"'";throw new t.QueryParseError(i,s.start,s.end)}}},t.QueryParser.parseBoost=function(e){var n=e.consumeLexeme();if(n!=null){var r=parseInt(n.str,10);if(isNaN(r)){var i="boost must be numeric";throw new t.QueryParseError(i,n.start,n.end)}e.currentClause.boost=r;var s=e.peekLexeme();if(s==null){e.nextClause();return}switch(s.type){case t.QueryLexer.TERM:return e.nextClause(),t.QueryParser.parseTerm;case t.QueryLexer.FIELD:return e.nextClause(),t.QueryParser.parseField;case t.QueryLexer.EDIT_DISTANCE:return t.QueryParser.parseEditDistance;case t.QueryLexer.BOOST:return t.QueryParser.parseBoost;case t.QueryLexer.PRESENCE:return e.nextClause(),t.QueryParser.parsePresence;default:var i="Unexpected lexeme type '"+s.type+"'";throw new t.QueryParseError(i,s.start,s.end)}}},function(e,n){typeof define=="function"&&define.amd?define(n):typeof de=="object"?he.exports=n():e.lunr=n()}(this,function(){return t})})()});window.translations||={copy:"Copy",copied:"Copied!",normally_hidden:"This member is normally hidden due to your filter settings.",hierarchy_expand:"Expand",hierarchy_collapse:"Collapse",folder:"Folder",kind_1:"Project",kind_2:"Module",kind_4:"Namespace",kind_8:"Enumeration",kind_16:"Enumeration Member",kind_32:"Variable",kind_64:"Function",kind_128:"Class",kind_256:"Interface",kind_512:"Constructor",kind_1024:"Property",kind_2048:"Method",kind_4096:"Call Signature",kind_8192:"Index Signature",kind_16384:"Constructor Signature",kind_32768:"Parameter",kind_65536:"Type Literal",kind_131072:"Type Parameter",kind_262144:"Accessor",kind_524288:"Get Signature",kind_1048576:"Set Signature",kind_2097152:"Type Alias",kind_4194304:"Reference",kind_8388608:"Document"};var ce=[];function G(t,e){ce.push({selector:e,constructor:t})}var J=class{alwaysVisibleMember=null;constructor(){this.createComponents(document.body),this.ensureFocusedElementVisible(),this.listenForCodeCopies(),window.addEventListener("hashchange",()=>this.ensureFocusedElementVisible()),document.body.style.display||(this.ensureFocusedElementVisible(),this.updateIndexVisibility(),this.scrollToHash())}createComponents(e){ce.forEach(n=>{e.querySelectorAll(n.selector).forEach(r=>{r.dataset.hasInstance||(new n.constructor({el:r,app:this}),r.dataset.hasInstance=String(!0))})})}filterChanged(){this.ensureFocusedElementVisible()}showPage(){document.body.style.display&&(document.body.style.removeProperty("display"),this.ensureFocusedElementVisible(),this.updateIndexVisibility(),this.scrollToHash())}scrollToHash(){if(location.hash){let e=document.getElementById(location.hash.substring(1));if(!e)return;e.scrollIntoView({behavior:"instant",block:"start"})}}ensureActivePageVisible(){let e=document.querySelector(".tsd-navigation .current"),n=e?.parentElement;for(;n&&!n.classList.contains(".tsd-navigation");)n instanceof HTMLDetailsElement&&(n.open=!0),n=n.parentElement;if(e&&!ze(e)){let r=e.getBoundingClientRect().top-document.documentElement.clientHeight/4;document.querySelector(".site-menu").scrollTop=r,document.querySelector(".col-sidebar").scrollTop=r}}updateIndexVisibility(){let e=document.querySelector(".tsd-index-content"),n=e?.open;e&&(e.open=!0),document.querySelectorAll(".tsd-index-section").forEach(r=>{r.style.display="block";let i=Array.from(r.querySelectorAll(".tsd-index-link")).every(s=>s.offsetParent==null);r.style.display=i?"none":"block"}),e&&(e.open=n)}ensureFocusedElementVisible(){if(this.alwaysVisibleMember&&(this.alwaysVisibleMember.classList.remove("always-visible"),this.alwaysVisibleMember.firstElementChild.remove(),this.alwaysVisibleMember=null),!location.hash)return;let e=document.getElementById(location.hash.substring(1));if(!e)return;let n=e.parentElement;for(;n&&n.tagName!=="SECTION";)n=n.parentElement;if(!n)return;let r=n.offsetParent==null,i=n;for(;i!==document.body;)i instanceof HTMLDetailsElement&&(i.open=!0),i=i.parentElement;if(n.offsetParent==null){this.alwaysVisibleMember=n,n.classList.add("always-visible");let s=document.createElement("p");s.classList.add("warning"),s.textContent=window.translations.normally_hidden,n.prepend(s)}r&&e.scrollIntoView()}listenForCodeCopies(){document.querySelectorAll("pre > button").forEach(e=>{let n;e.addEventListener("click",()=>{e.previousElementSibling instanceof HTMLElement&&navigator.clipboard.writeText(e.previousElementSibling.innerText.trim()),e.textContent=window.translations.copied,e.classList.add("visible"),clearTimeout(n),n=setTimeout(()=>{e.classList.remove("visible"),n=setTimeout(()=>{e.textContent=window.translations.copy},100)},1e3)})})}};function ze(t){let e=t.getBoundingClientRect(),n=Math.max(document.documentElement.clientHeight,window.innerHeight);return!(e.bottom<0||e.top-n>=0)}var ue=(t,e=100)=>{let n;return()=>{clearTimeout(n),n=setTimeout(()=>t(),e)}};var ge=$e(pe(),1);async function A(t){let e=Uint8Array.from(atob(t),s=>s.charCodeAt(0)),r=new Blob([e]).stream().pipeThrough(new DecompressionStream("deflate")),i=await new Response(r).text();return JSON.parse(i)}async function fe(t,e){if(!window.searchData)return;let n=await A(window.searchData);t.data=n,t.index=ge.Index.load(n.index),e.classList.remove("loading"),e.classList.add("ready")}function ve(){let t=document.getElementById("tsd-search");if(!t)return;let e={base:document.documentElement.dataset.base+"/"},n=document.getElementById("tsd-search-script");t.classList.add("loading"),n&&(n.addEventListener("error",()=>{t.classList.remove("loading"),t.classList.add("failure")}),n.addEventListener("load",()=>{fe(e,t)}),fe(e,t));let r=document.querySelector("#tsd-search input"),i=document.querySelector("#tsd-search .results");if(!r||!i)throw new Error("The input field or the result list wrapper was not found");i.addEventListener("mouseup",()=>{re(t)}),r.addEventListener("focus",()=>t.classList.add("has-focus")),We(t,i,r,e)}function We(t,e,n,r){n.addEventListener("input",ue(()=>{Ue(t,e,n,r)},200)),n.addEventListener("keydown",i=>{i.key=="Enter"?Je(e,t):i.key=="ArrowUp"?(me(e,n,-1),i.preventDefault()):i.key==="ArrowDown"&&(me(e,n,1),i.preventDefault())}),document.body.addEventListener("keypress",i=>{i.altKey||i.ctrlKey||i.metaKey||!n.matches(":focus")&&i.key==="/"&&(i.preventDefault(),n.focus())}),document.body.addEventListener("keyup",i=>{t.classList.contains("has-focus")&&(i.key==="Escape"||!e.matches(":focus-within")&&!n.matches(":focus"))&&(n.blur(),re(t))})}function re(t){t.classList.remove("has-focus")}function Ue(t,e,n,r){if(!r.index||!r.data)return;e.textContent="";let i=n.value.trim(),s;if(i){let o=i.split(" ").map(a=>a.length?`*${a}*`:"").join(" ");s=r.index.search(o)}else s=[];for(let o=0;oa.score-o.score);for(let o=0,a=Math.min(10,s.length);o`,d=ye(l.name,i);globalThis.DEBUG_SEARCH_WEIGHTS&&(d+=` (score: ${s[o].score.toFixed(2)})`),l.parent&&(d=` - ${ye(l.parent,i)}.${d}`);let m=document.createElement("li");m.classList.value=l.classes??"";let p=document.createElement("a");p.href=r.base+l.url,p.innerHTML=c+d,m.append(p),p.addEventListener("focus",()=>{e.querySelector(".current")?.classList.remove("current"),m.classList.add("current")}),e.appendChild(m)}}function me(t,e,n){let r=t.querySelector(".current");if(!r)r=t.querySelector(n==1?"li:first-child":"li:last-child"),r&&r.classList.add("current");else{let i=r;if(n===1)do i=i.nextElementSibling??void 0;while(i instanceof HTMLElement&&i.offsetParent==null);else do i=i.previousElementSibling??void 0;while(i instanceof HTMLElement&&i.offsetParent==null);i?(r.classList.remove("current"),i.classList.add("current")):n===-1&&(r.classList.remove("current"),e.focus())}}function Je(t,e){let n=t.querySelector(".current");if(n||(n=t.querySelector("li:first-child")),n){let r=n.querySelector("a");r&&(window.location.href=r.href),re(e)}}function ye(t,e){if(e==="")return t;let n=t.toLocaleLowerCase(),r=e.toLocaleLowerCase(),i=[],s=0,o=n.indexOf(r);for(;o!=-1;)i.push(ne(t.substring(s,o)),`${ne(t.substring(o,o+r.length))}`),s=o+r.length,o=n.indexOf(r,s);return i.push(ne(t.substring(s))),i.join("")}var Ge={"&":"&","<":"<",">":">","'":"'",'"':"""};function ne(t){return t.replace(/[&<>"'"]/g,e=>Ge[e])}var I=class{el;app;constructor(e){this.el=e.el,this.app=e.app}};var H="mousedown",Ee="mousemove",B="mouseup",X={x:0,y:0},xe=!1,ie=!1,Xe=!1,D=!1,be=/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);document.documentElement.classList.add(be?"is-mobile":"not-mobile");be&&"ontouchstart"in document.documentElement&&(Xe=!0,H="touchstart",Ee="touchmove",B="touchend");document.addEventListener(H,t=>{ie=!0,D=!1;let e=H=="touchstart"?t.targetTouches[0]:t;X.y=e.pageY||0,X.x=e.pageX||0});document.addEventListener(Ee,t=>{if(ie&&!D){let e=H=="touchstart"?t.targetTouches[0]:t,n=X.x-(e.pageX||0),r=X.y-(e.pageY||0);D=Math.sqrt(n*n+r*r)>10}});document.addEventListener(B,()=>{ie=!1});document.addEventListener("click",t=>{xe&&(t.preventDefault(),t.stopImmediatePropagation(),xe=!1)});var Y=class extends I{active;className;constructor(e){super(e),this.className=this.el.dataset.toggle||"",this.el.addEventListener(B,n=>this.onPointerUp(n)),this.el.addEventListener("click",n=>n.preventDefault()),document.addEventListener(H,n=>this.onDocumentPointerDown(n)),document.addEventListener(B,n=>this.onDocumentPointerUp(n))}setActive(e){if(this.active==e)return;this.active=e,document.documentElement.classList.toggle("has-"+this.className,e),this.el.classList.toggle("active",e);let n=(this.active?"to-has-":"from-has-")+this.className;document.documentElement.classList.add(n),setTimeout(()=>document.documentElement.classList.remove(n),500)}onPointerUp(e){D||(this.setActive(!0),e.preventDefault())}onDocumentPointerDown(e){if(this.active){if(e.target.closest(".col-sidebar, .tsd-filter-group"))return;this.setActive(!1)}}onDocumentPointerUp(e){if(!D&&this.active&&e.target.closest(".col-sidebar")){let n=e.target.closest("a");if(n){let r=window.location.href;r.indexOf("#")!=-1&&(r=r.substring(0,r.indexOf("#"))),n.href.substring(0,r.length)==r&&setTimeout(()=>this.setActive(!1),250)}}}};var se;try{se=localStorage}catch{se={getItem(){return null},setItem(){}}}var C=se;var Le=document.head.appendChild(document.createElement("style"));Le.dataset.for="filters";var Z=class extends I{key;value;constructor(e){super(e),this.key=`filter-${this.el.name}`,this.value=this.el.checked,this.el.addEventListener("change",()=>{this.setLocalStorage(this.el.checked)}),this.setLocalStorage(this.fromLocalStorage()),Le.innerHTML+=`html:not(.${this.key}) .tsd-is-${this.el.name} { display: none; } -`,this.app.updateIndexVisibility()}fromLocalStorage(){let e=C.getItem(this.key);return e?e==="true":this.el.checked}setLocalStorage(e){C.setItem(this.key,e.toString()),this.value=e,this.handleValueChange()}handleValueChange(){this.el.checked=this.value,document.documentElement.classList.toggle(this.key,this.value),this.app.filterChanged(),this.app.updateIndexVisibility()}};var oe=new Map,ae=class{open;accordions=[];key;constructor(e,n){this.key=e,this.open=n}add(e){this.accordions.push(e),e.open=this.open,e.addEventListener("toggle",()=>{this.toggle(e.open)})}toggle(e){for(let n of this.accordions)n.open=e;C.setItem(this.key,e.toString())}},K=class extends I{constructor(e){super(e);let n=this.el.querySelector("summary"),r=n.querySelector("a");r&&r.addEventListener("click",()=>{location.assign(r.href)});let i=`tsd-accordion-${n.dataset.key??n.textContent.trim().replace(/\s+/g,"-").toLowerCase()}`,s;if(oe.has(i))s=oe.get(i);else{let o=C.getItem(i),a=o?o==="true":this.el.open;s=new ae(i,a),oe.set(i,s)}s.add(this.el)}};function Se(t){let e=C.getItem("tsd-theme")||"os";t.value=e,we(e),t.addEventListener("change",()=>{C.setItem("tsd-theme",t.value),we(t.value)})}function we(t){document.documentElement.dataset.theme=t}var ee;function Ce(){let t=document.getElementById("tsd-nav-script");t&&(t.addEventListener("load",Te),Te())}async function Te(){let t=document.getElementById("tsd-nav-container");if(!t||!window.navigationData)return;let e=await A(window.navigationData);ee=document.documentElement.dataset.base,ee.endsWith("/")||(ee+="/"),t.innerHTML="";for(let n of e)Ie(n,t,[]);window.app.createComponents(t),window.app.showPage(),window.app.ensureActivePageVisible()}function Ie(t,e,n){let r=e.appendChild(document.createElement("li"));if(t.children){let i=[...n,t.text],s=r.appendChild(document.createElement("details"));s.className=t.class?`${t.class} tsd-accordion`:"tsd-accordion";let o=s.appendChild(document.createElement("summary"));o.className="tsd-accordion-summary",o.dataset.key=i.join("$"),o.innerHTML='',ke(t,o);let a=s.appendChild(document.createElement("div"));a.className="tsd-accordion-details";let l=a.appendChild(document.createElement("ul"));l.className="tsd-nested-navigation";for(let c of t.children)Ie(c,l,i)}else ke(t,r,t.class)}function ke(t,e,n){if(t.path){let r=e.appendChild(document.createElement("a"));if(r.href=ee+t.path,n&&(r.className=n),location.pathname===r.pathname&&!r.href.includes("#")&&r.classList.add("current"),t.kind){let i=window.translations[`kind_${t.kind}`].replaceAll('"',""");r.innerHTML=``}r.appendChild(document.createElement("span")).textContent=t.text}else{let r=e.appendChild(document.createElement("span")),i=window.translations.folder.replaceAll('"',""");r.innerHTML=``,r.appendChild(document.createElement("span")).textContent=t.text}}var te=document.documentElement.dataset.base;te.endsWith("/")||(te+="/");function Pe(){document.querySelector(".tsd-full-hierarchy")?Ye():document.querySelector(".tsd-hierarchy")&&Ze()}function Ye(){document.addEventListener("click",r=>{let i=r.target;for(;i.parentElement&&i.parentElement.tagName!="LI";)i=i.parentElement;i.dataset.dropdown&&(i.dataset.dropdown=String(i.dataset.dropdown!=="true"))});let t=new Map,e=new Set;for(let r of document.querySelectorAll(".tsd-full-hierarchy [data-refl]")){let i=r.querySelector("ul");t.has(r.dataset.refl)?e.add(r.dataset.refl):i&&t.set(r.dataset.refl,i)}for(let r of e)n(r);function n(r){let i=t.get(r).cloneNode(!0);i.querySelectorAll("[id]").forEach(s=>{s.removeAttribute("id")}),i.querySelectorAll("[data-dropdown]").forEach(s=>{s.dataset.dropdown="false"});for(let s of document.querySelectorAll(`[data-refl="${r}"]`)){let o=tt(),a=s.querySelector("ul");s.insertBefore(o,a),o.dataset.dropdown=String(!!a),a||s.appendChild(i.cloneNode(!0))}}}function Ze(){let t=document.getElementById("tsd-hierarchy-script");t&&(t.addEventListener("load",Qe),Qe())}async function Qe(){let t=document.querySelector(".tsd-panel.tsd-hierarchy:has(h4 a)");if(!t||!window.hierarchyData)return;let e=+t.dataset.refl,n=await A(window.hierarchyData),r=t.querySelector("ul"),i=document.createElement("ul");if(i.classList.add("tsd-hierarchy"),Ke(i,n,e),r.querySelectorAll("li").length==i.querySelectorAll("li").length)return;let s=document.createElement("span");s.classList.add("tsd-hierarchy-toggle"),s.textContent=window.translations.hierarchy_expand,t.querySelector("h4 a")?.insertAdjacentElement("afterend",s),s.insertAdjacentText("beforebegin",", "),s.addEventListener("click",()=>{s.textContent===window.translations.hierarchy_expand?(r.insertAdjacentElement("afterend",i),r.remove(),s.textContent=window.translations.hierarchy_collapse):(i.insertAdjacentElement("afterend",r),i.remove(),s.textContent=window.translations.hierarchy_expand)})}function Ke(t,e,n){let r=e.roots.filter(i=>et(e,i,n));for(let i of r)t.appendChild(_e(e,i,n))}function _e(t,e,n,r=new Set){if(r.has(e))return;r.add(e);let i=t.reflections[e],s=document.createElement("li");if(s.classList.add("tsd-hierarchy-item"),e===n){let o=s.appendChild(document.createElement("span"));o.textContent=i.name,o.classList.add("tsd-hierarchy-target")}else{for(let a of i.uniqueNameParents||[]){let l=t.reflections[a],c=s.appendChild(document.createElement("a"));c.textContent=l.name,c.href=te+l.url,c.className=l.class+" tsd-signature-type",s.append(document.createTextNode("."))}let o=s.appendChild(document.createElement("a"));o.textContent=t.reflections[e].name,o.href=te+i.url,o.className=i.class+" tsd-signature-type"}if(i.children){let o=s.appendChild(document.createElement("ul"));o.classList.add("tsd-hierarchy");for(let a of i.children){let l=_e(t,a,n,r);l&&o.appendChild(l)}}return r.delete(e),s}function et(t,e,n){if(e===n)return!0;let r=new Set,i=[t.reflections[e]];for(;i.length;){let s=i.pop();if(!r.has(s)){r.add(s);for(let o of s.children||[]){if(o===n)return!0;i.push(t.reflections[o])}}}return!1}function tt(){let t=document.createElementNS("http://www.w3.org/2000/svg","svg");return t.setAttribute("width","20"),t.setAttribute("height","20"),t.setAttribute("viewBox","0 0 24 24"),t.setAttribute("fill","none"),t.innerHTML='',t}G(Y,"a[data-toggle]");G(K,".tsd-accordion");G(Z,".tsd-filter-item input[type=checkbox]");var Oe=document.getElementById("tsd-theme");Oe&&Se(Oe);var nt=new J;Object.defineProperty(window,"app",{value:nt});ve();Ce();Pe();})(); -/*! Bundled license information: - -lunr/lunr.js: - (** - * lunr - http://lunrjs.com - A bit like Solr, but much smaller and not as bright - 2.3.9 - * Copyright (C) 2020 Oliver Nightingale - * @license MIT - *) - (*! - * lunr.utils - * Copyright (C) 2020 Oliver Nightingale - *) - (*! - * lunr.Set - * Copyright (C) 2020 Oliver Nightingale - *) - (*! - * lunr.tokenizer - * Copyright (C) 2020 Oliver Nightingale - *) - (*! - * lunr.Pipeline - * Copyright (C) 2020 Oliver Nightingale - *) - (*! - * lunr.Vector - * Copyright (C) 2020 Oliver Nightingale - *) - (*! - * lunr.stemmer - * Copyright (C) 2020 Oliver Nightingale - * Includes code from - http://tartarus.org/~martin/PorterStemmer/js.txt - *) - (*! - * lunr.stopWordFilter - * Copyright (C) 2020 Oliver Nightingale - *) - (*! - * lunr.trimmer - * Copyright (C) 2020 Oliver Nightingale - *) - (*! - * lunr.TokenSet - * Copyright (C) 2020 Oliver Nightingale - *) - (*! - * lunr.Index - * Copyright (C) 2020 Oliver Nightingale - *) - (*! - * lunr.Builder - * Copyright (C) 2020 Oliver Nightingale - *) -*/ diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/docs/assets/navigation.js b/v3/internal/runtime/desktop/@wailsio/runtime/docs/assets/navigation.js deleted file mode 100644 index dc1ca645f..000000000 --- a/v3/internal/runtime/desktop/@wailsio/runtime/docs/assets/navigation.js +++ /dev/null @@ -1 +0,0 @@ -window.navigationData = "eJylmVFT4zYQx7+Ln6EtlKMtc9MZIMAxJQ2Nr5OHm5sbxdmAiiJ5ZDmQdvrdb2RJtmzLKyc8wWT/+9uVrNXK8pf/EgVvKrlIPlKuQHLCfk+Okpyo5+Qi2YhVyaD48ZuzffvhWW1YcpS8UL5KLk6PkuyZspUEnlx8qVELylfitcFkjBRFG2MkbdrJ6a//H9WQGymFnOWKCl40qIqwJlmb5ms7GX44PzLxk4tEFatjWhzDm/FLvGj3CiRZMohFcrrDojyKguokY1GcrhfFZ0mxoQXclmxNGYPVHIqSqSg56HXgaAzrgb5Ep82TvivWHP6BTO052LbTu+IvqHqeQyHYFmR0VYZ8Doue0n+jU6w12Hq5fCVUwarBqF3eJlhFB/LTb7+cfDgdleY14RkwpuvDjt3+AhIJi3gFU0ED3rxBViqxXzzntH84s7T2DOecDglnltGe4YxTLNwjkYoShrCt4vAFYjNKQanAjtWPF5C/K3gOUu3+gB0e06kODzUHshKcYXGc5D1BMiGxejaCwwOku0LB5mYLXP1JNoBE6ijDK+2rvxnlOaMZafdCd9rwjG3SWfi48YmuvOTWJc+qg0CLozVt2PmZl89fJVUxhNYgiPTZP/KEEVrTQ/jzciXFa+HXt5sTaxg1H7Mc+N/zh1AyDmMlaC7XhLF+IvrXUVnMS67oBqqjWf8oWGF8CXYU1OLeSdAsworj2WOb3NXufhKamIqjjcgTvtq1y6Dn3V/7Lf/2hHa8+/PafRyM5ktB/Iqvn4kzjXowKajP+r9QJjXIipDRxBlBgD+kCSVMPBX9AVnDqOFclUoNnKgdxkiww9EtZXBLmfJLLwBqZBhsCkVBnsA4YW8wDhtywALo6tWpjI8Q9MBCpGQL+4UIemAhOjtDs4IcMbAvtFbgPV8LzF/bEXc3JxjCadDWAUW7j/UxToO1Dzt9GMZpEMyCSE75E0axErQyq1YeKEzz+6i6XBDKikrf3/0tppGgu39ZKLHpZuStQEvzddi6a6LqPXdJspduU+ml54Sx7tJ4TIgiUawWjUeGzmA95PDxy9u5tWtD2hJJ9etCTavsbcjPvv/NJnxYsu7ajJXdeo04z9Zr3Pcy3EMb98tAH/UIwTp13liBzngWLM7aN8PqcsanJVM0Dxd4zXAitDhvGQk1zernUaV5B0qLQ5kYiBWgWdzP0n4O97N0VAYT2FJ/On1/YxuFaXcAb0vwOP0u0N4OhrpIB3F8gs7GJ5IrmgWeisZY47ghbXKSqVTtWK/YfZQni5W7kQ4NsQ0MjNEfZZpJAB4YpTWMezGALHxz5yBagJ5NKh2KMH9RyNCVWo2I3KfdgRrYixzBKJBN4Q7UdSllq0UGMVaFox4l3RC5i6CsCl3M5nU+8JSr30c95Bu+pVLwDXA1WKQW15GiB980BjMKjHFNcrKkjCrqN0FvrgzIlyHz7iWPwDwVwqJ8K16C/cFijAA7EReX08n5GYKwCpwxn+KE+TTmH8tBK1DGhMiXqQjf69QYJ8JJsCyDra7BaAXKeKC8fEMZlQJlTEmGEqYkQ/3NFzNsydYatLgX04d+ZS+mDyPLuv2RrMlBE4wVGcUcmCCrIXdjjdxJ6dvtwTul2ojfJnVvyIdQvmYEUV9R65t9KjiaYU+4X7aD39vCUnwv7HrEP3BFfLBw9r7vsyS8yIUMnwK6IgyYMaq7hreimpcZZ0NeZMRSPwX9yhR8HfLMCKT7sbvxD33jbrk+gQrMRVMUvh2pKl015r6FsDSTNA/C+ioEWUQyK7DMvn4HHdYHCw==" \ No newline at end of file diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/docs/assets/search.js b/v3/internal/runtime/desktop/@wailsio/runtime/docs/assets/search.js deleted file mode 100644 index 29cc82e52..000000000 --- a/v3/internal/runtime/desktop/@wailsio/runtime/docs/assets/search.js +++ /dev/null @@ -1 +0,0 @@ -window.searchData = "eJy1XW2T2zaS/i/y11mvGnx3XV2VYye7roovWU+yvjtXaosjYWYYU6SOpGbsTeW/XwEgpQbQJJuS/MmuEdDdAB40Gv0AxB+rpn5uV68+/bH6XFTb1as4vFlV+U6uXq3KOt/+tO+KusrL201T7LvVzerQlKtXq/tDtVE/tH/1C7187Hbl6ma1KfO2le3q1Wr1580g/iT99X5fFptc1TyK3dXbQynbv6LfJqUhY/9ebCVhHpakihDiblb7vJFV59hEarl9rJ9ntKgiF2r5x6GguhprUUXO0XJS8p0aeNl4fd//ndvvP+1l9euHHwlzB0F9iWlrB2soS9/kZemZqf7ItdEScDJQixiRg0zTtUm53339L/WfEcnm1/Nlv3s7Lvnd20VyxTpLIBJWh5hJ2x51dF/3EvVJ//MiNSDSo4oPh6ordvL7pqlPGOulGC24xCI1EZxasqmrtmsOm46t5YVdZVyjVZUGZlns7+q82froHH7hQvRWdr/IL9SsP4nqy8z01dEmUs+skvM0nBS8LfKyfmi9Hun/zu2Pd9V9Tdg5SFE/T1s52EFK/5g3VVE9TCjoS1ygw0a+r4GB+0n5/zjI1lo8fRVDkQu0KOf9Q1FSTm7QMhS5QMtt/iRntAxFlmoRUew1xpRyHWBRdbK5zzfSb5pVYakFsBZ4KarePNZ1K98WjVQuqJBnWvBik1cbLWpriZo0i5Y3a6yqcbGZ972QKxvYyLy7Um9qUd+sN1Vg+PdiuzVVzrWzfayfH7WUb9CfH2Rbl0+yfV0WeXu2iU0vJT9KuaKJr8uyfm7fH8qu2JfyVpZyY3nBZabmWtqul9YiaVc0We07vv/Syao939DHYislknHdSWS60YDzUks3eWX60aD0Gxn9i5qrrSr+c775nD/I9nV7uRPotFQ1sfa91Lz9Zv7AIPmn7lE2qo6Ovy+Cca1E3SNRVzT2h6LsZHOufffH2teEQNGhiGHhQPd1r2jOe9m2+cO5Bu2Ota9o0neHrqsrK+RfZtWdFtAZAVc0bJipX8+0a4vqX9Ms2eWbR7k916pT9cuMwjHrEPeyY1aywkUxq5JW4UTHIq1q8g/Vp7uFbuqVAukJA88KpM8zdjby45jJC/wWG7gkkJ4xc3EgvcjYBYH0hJ1LA+lFJi4IpCdMXBpILzKRHZVOGLgsKl2KyMVR6TQqz4tKFxl9QVQ6YfulUemiJiyNSifsPisqXWQsIyqdXphYUekyCMxFpVMDzYpKF5nDiEonDOJGpYtM4kWlE1YtiEoXGcaKSifs4kely8xiRKVTVnGj0jmjcFTaw4odlFLlL4pJZ6fZqEbmLCNbeP4kGzeHO8eWGGSm2Hkj0k+vebe4xCAOhsctYkN4xiSMYNNFU/aYEheh9Mf8TpZMHS/KvvB0E3u7RxS+a9/k1Yavs2g3Q/nL1L6V9/mhnPTott7tscJCxXgQlbsyMcCU4lOpiwbzbdHuy9ym/Oe1vdiaaqwdMGrPiBE/510nm0ncugbsj1XOUI74zCdZdT6va/7MPi1SDZl7gurrRZ3KTA9Xb9CInin5l8jdTFq+ucTm+/sJ0ff3F0l+TZ6AOQl/PXcKZkr+9zvyvFIvXf26UDae428ObVfvHPQh2PdacLGl2pzTMR/zomx1KWuumwMyvQa7zNUUvs27fE6hKnM1heqgy12++TyndCi3UDE+EXQS5p3U8dQtVMM9EUTrYZ0I8qqOeWgrUzqjeHJRYGvcYtDMaOzLXqixldVWsrv3WHq51uA0rr9YmYinvCnyO7QA6Z8XwgYlEsqcOLOk/8pd2v4mO1We8INGTP/7tInGDsrC200jZeXb2P99gZX0UjDIMQWmrRxsGdPwc1PscrSNJrX0hS7T9ObQNNihkJr6Qks1WSxM8W8y6Bu0qN+Xyrdm1Mdi2z2yNLx47otO6tHlR1O/snh4JGN1X9vjUHaROtx3H+RmUpf6/aK++2+W9BdfZhuhLR1R8j88JeO5H46SWRScFPFQMKVsHgUnbUwUOOqsGaSLTGJO/3sREtCR6WkFL4rxZIJdfEzV2DaQUja5zPPU3W7yUv6QW1HNjNZWVbnPJ6ManvLJCYZVzk+xaUWTkwwrmp9mM905589xP5qyl6j7rj5UW3L3Qim8G0pfovLnx69tscnLZar3fa2rmPCxbj6/bmTOVf5cN59zU/4aLV+qfmj7lcx417ph0JxLavfHCpco/lB39q2qGb3NqfxCtWg+fW07ufODU/1nbmxaVE/1Zyq90osxv88sEMYQ+k5B+zZvPr+vyYtivY5TmfP1vMn3+V1RFh2mfD1NuNT5ur6vnoqmrnYjQbBRhQpd0nsfi2qrLgtOdF5f5BItPxbV4cuUDl3gEg3v882U/Pf55hLpr9+/jcMp+brARRo+vJ+U/+H9hdJn7FcFLpqF8u5A7ZNPU1AVWKjBuudxa10fwv7PqDAFFmqwV/Qmr7b4CtGkkhd3p+JT2vo6C8NbX91UdMtRNBrc+qqmY1uOsn/KZuxgD6Hv6Vh6mUqMD+QPZ4DilLwEMa+bDb21G9f0Ijd1JlvqNmaUgcWTjql/21e6hgE/3S7VXk8EoAtVnzHML+q2MLWuYcLPZd7d183uHEP2fd3LzEFuBA3FEKm9++l2MkxDaYN83xUbPxGpJPS/TU8TpZ5eGXb7fEOFMVi0KTSrYSg/QYIYSbfd19LleHx9utQ5SvEEfCoQeYi7zfx0bq/RN2WRXFXiLzBvfW8h7TPHgOvoOUPLHHkzo4zF3jgVx2bprt7SZydIxUPpi1S2et6OLbikXlNlcuFdpHxiAZ7QP7cQM00o2ttidyjzJSNetC2qs1Q94pTMdoUglcwPTI/48f2P3rT++J764MXIFk7pJKawkmF+nJ5VSj8p+YNUX2cZkWx+PFNyK7tfmrxq93VDOWz8M7cbHqZFPnBFWtSD+YKDLxchzC0zLXwdngjtDf6syJzEF31puqM9Q0m41ne/y40+cEARoejXyTYggZuyUIHClpA2/DQpCtP75uDZ2Pc+jr9NyuN/2cOWx/ymx8nAqSaUcvtB/m4uAk81xyt3xabRshc002/EiP/dN/WuaP0TC5N2nCqda4N1wseUVrj72Qj+sfhMLod0Sf6M7R5pCmpC7ou+zmRDXdNHHcbY2cwpA2ZOaM6bMNnVH4vusb+tRF+kmKky7R+mkLZQBxd0o20bMau/ZHW2Waf6Vzbr9xHenGlVX/2qRtXVZpjZZ1tmy7jYPN99o1pjXg0V4TsPvNrPyHsxtdYTZo5rvJVdh3ubobg9VrlYf/WVr7ga5634Gpt8wx60F33hS3U6XnlOqyn+F3EFzSrkqw/+ccgx1afyl2puSyn3bL1D6YtH1/Zps+O71IeN67Vd/LzipS59TPMzubrO6Ve1GlTrDCsWhps+yvmR5reaYlfTiy4D8DRPZDUWTG4ca87O7GVB5nh7O0QyzDe2m6AX+FrviyovS/5ScSp/juaj2v/QkUeVl//pZV/+Nfz0r5nl3c4Imxz62Ml/JNQpOJ1EQXaOHIy3s1BD9yF9o+moOTXWOP1N+r6XVvLiQY773ZOivsqYvp/rtrAOoswo3Z/KX6j5jaw64nz6iN7NUPpSrWVNhJxjSvvCF+p8W7RqnqjzbG+0y84LfE9mxoitqa1OuG2s2hdaZbKWZxolq29i0w/15sC24b4vfLHOZiOdLOys5mYjm6HKpfoPZdnaB2/n1OMaF2r/m+xuFyl/kN0Vdf9vXe8WaP63KX6hXudQ9YzamWPVfK344+dzOk3ZCzW+a/V8InamI2qL9v5Y4XLdi3FdtNdEtjok9qVQkcmC9u9Qlcv1F9Vi/ajKhfqH1nOV707lL9XcN4Kt+VT+Qs1WRDijdZKbZWtUn4l7K59+qeuSvXDVe3XZ7qnr61xowQdZ5l3xJJdGck1f73oR3bJF9Frr5wcVhljs7KziU4XLdXd1s0RzX/xCvbeyWzrcreyuN9K36gLic/61/an6pfZzVOMm5LpWXXX1eK5qiRXf5ZvPD426CPGmLusDezvRyu7uWHUzVL3cnh+afCdL2bJ9QSu7e1TnChYcl1DzVQ4T5rNnpbLnKMF8ZUYeJVxu3fv8i3WtZ96aXf5l8nLPIu1FtVR7UV1N+7mOupXd9X21tmeh49SGXM133spu4WBcbSTsD1PNK57+GtUSzUv2O+219jvWg0hzSk3ZSzUuGdirjOov9cNDKZfvOTpd75r7DmPJ0ujb2HG9GLzvj6XLUd8d11uRfq2Wj8mhuuZ4/FotHYtDdb1x+LVauhs6VNfbD9l31WcUT99WZ+tc4uKu49+UxndsdCmdxRVwpbT+RBDDE2qneOFFej/Ils8TKM1NX+HSHFZebUs53JPQH6Js+PH/o6493JRQn5vdNlfZB1T5/nXbFi27S9oq3+dDjUsZlKYgvpY0Rp/0hc/R6T4P5xJwA4c9TomN1zmLtpo36HdpEdosg0ydb2LQcORxkUXHSt/EpO+/yM1hYR8Ndc4xCJ0z9PYh6JQY0j8UO4dAxefSvizRM/GVCjRJji0YUUle6x9VOU52T6vkfIMI89KznyGa78vnsW/QUHr4C/vU94geR79EQ+rksyZG6W83q6Layi+rV3+shlsrr1biZfAyW92s7gtZbtULuKsha1vv+uv023pz0P/9rS/2T+0/VGFT+q/r1c2n9U0EL4Ms+e23m09DZf2D/sMg4/QXXRFWN5+AqgheRbAqitXNJ3ETxi9FmlkVhVdRWBWD1c2ngKoYeBUDq2K4uvkUUqaGXsXQqhitbj5FVMXIqxhZFePVzaeYqhh7FWOrYrK6+ZTchOJlJkKrYuJVTKyK6VjF1KuYWhWz1c2nlDI18ypmNgAUHjISAT52wAGPRg+JOyDwYwMIFCyAxp6PIbBBBAoaIG6C+GUS2D0FPo7ABhIoeEBAavaxBDaYQEEESByCjyewAQUKJkBiEXxMgQ0qUFABEo/g4wpsYIGCC5DQAh9bYIMLFGSAhBf4+AIbYEJhBkiECR9hwkaYUJgRJMKEjzDhuCjto0iECcJL2QgTCjNCkJV9hAkbYUJhRpAIEz7ChI0woTAjQtK3+ggTNsKEwoyIyMo+woSNMKEwI2Kyso8wYSNMKMyIhKzsI0zYCBMKMyIlK/sIEzbCAoUZQSIs8BEW2AgLFGaCNbkg+QgLbIQFCjMBkJV9hAXOQqhXQnINDYi10EZYoDAT0Ouoj7DARligMBOQCAt8hAU2wgKFmSCiPEngIyywERYozAQxWdlHWGAjLFCYCUiEBT7CAhthgcJMQCIs8BEW2AgLFWaCjDI79BEW2ggLFWZC0oeFPsJCG2GhwkxI+rDQR1hoIywMRj1J6CMsdMKtcNSThETEZSMsjEY9SegjLLQRFsajniT0ERbaCAuTUU8S+ggLbYSF6agzCH2EhTbCwmzUGYQ+wkIbYdF61BlEPsIiG2ERjDqDyEdYZCMsEqPOIPIRFtkIi4JRZxD5CItshEXhqDOIfIRFTlAfjTqDiIjrbYRF8agziHyERTbComTUGUQ+wiIbYZHCTEiGFZGPsMhGWJSN97aPsMhGWLwe7e3YR1hsIyzWPowMaGIfYbGNsFiMdljsIyy2ERYrzIRkvB37CItthMV6z0jG27GPsNhGWKwwE9L7Px9hsbN1VJgJE7IysXu0ERYrzIRkvB37CItthMUaYWQ0FPsIi22ExQozEblWxT7CYhthicJMRK5ViY+wxEZYojATkRMj8RGW2AhLFGYiEp6Jj7DERliiMBORCEt8hCU2whKFmYhEWOIjLLERlujMBImwxEdYYiMsUZiJSIQlPsISJ0GhMBORCEuIHIWNsERhJiIRlvgIS2yEJQozMYmwxEdYYiMsVZiJSYSlPsJSG2GpwkxMIiz1EZbaCEvFaMIh9RGW2ghLFWbi4CZcvwwB7Mo+wlIbYanCTEzCM/URltoISxVmYhKeqY+w1EZYqvNfJDxTH2GpjbBUYSYm4Zn6CEudNJjCTEzCMyUyYTbCUo0wEp6pj7DURlimMJOQ8Mx8hGU2wjKFmYSEZ+YjLLMRlinMJCQ8Mx9hmY2wTGEmIRGW+QjLbIRlCjNJSFb2EZbZCMsUZpKIrOwjLLMRlinMJCTCMh9hmY2wTGdZyZRW5iMssxGW6UxrSlb2EZY5ydZsvMOIfKubcF2P9pj5za6O/tbX1ygbSdkSade1k3ddK+ik5CbH/ObWd1Kv63FvZn5z6zvZ17UCUEonftdE/nXtJGDX0ei4m9/c+k4Odh2PDr35za3vpGHXyehcM7+59Z1M7FqBKSUnuvnNre8kY9c610+nr9dEOnbt4E8n8VM6g03l/L2kv8JTSiexybS/gz+dyk/pPDaV+XdT/zqbn5IrC1DJfzf7rxP6KZ3NpvL/LgGgc/opPf8oCsDlAHRaPxthTQj8uTSAzuxn9PyhiACXCdDJ/YzGH8UFuGSAzu9nNP4oOsDhA0Cn+DMafwQjAA4lADrLn9H4I0gBcFgB0In+jMYfwQuAQwyAzvVnNP4IagAcbgB0uj+j8UewA+DQA6Az/hmNP4IgAIchAJ30hzW9ABAkATgsAejEP6xHqDsCgQ5TADr5P7ICEVwBOGQB6Pz/yApE0AXg8AWgKQBY01OAoAzA4QwgMMQnPQcI2gAc3gA0FQBrehIQ1AE43AFoOgDW9Cwg6ANw+APQlACs6WlAUAjgcAigaYExGBE0Ajg8AgQGh/REIqgEcLgECAwO6ZlE0Ang8AmgKQJY01OJoBTA4RRA0wQwwoATtAI4vAJoqgBGWHCCWgCHWwBNFwDQUCboBXD4BdCUwQgxTDAM4FAMoFmDsfoEDh2WATRxMMLkEzwDOEQDaO4Axth8AoYO2QCaP4ARRp/gG8AhHEBzCDDC6hOcAzikA2geAUaYfYJ3AId4gNDAkEyGA8E9gEM+QGRgSM8kgn8Ah4CAyMCQnkkEBwEOCQGRya/Q3oTgIcAhIiAyJ0LomURwEeCQERAZINIzieAjwCEkQHMMQLP+QHAS4JASoHkGeiYRrAQ4tARopgHEyNEUAocONQGabQBBA5lgJ8ChJ0AzDiBoIBMMBTgUBWjWYcQZECQFOCwFaOIBBL2kEEQFOEwFxONpPiC4CnDICogNCklmCQi+AhzCAmKDQnoiEZwFOKQFaB4CaA4TCN4CHOICNBcBisckcEhwF+CQF6D5CAjoiUTwF+AQGBCnU51I4NAhMUDzEkATokDwGOAQGaC5CaBJUSC4DHDIDND8BAT0VCL4DHAIDdAcBQQjp70IJDqkBmieAgJ6KhC8BjjEBiTmlBy9JhDcBjjkBiQGiTSUCX4DHIIDNGcB9MkJIDgOcEgOSJIJKBM8BzhEB2juAujjF0BwHeCQHaD5C6D5XiD4DnAID0inkEhwHuCQHpDCxFwgeA9wiA8wzAfN/QLBfYBDfkA6cVaToD/A4T8gDSdGkaBAwOFAIDVHNumFkaBBwOFBII0nfCpBhYDDhYCmN4AmooGgQ8DhQyA1QKTdAUGJgMOJQGqASLsDghYBhxcBTXUATUoDQY2Aw41ABhNBKkGPgMOPQGaASPsTgiIBhyMBTXtARA8jQZOAw5OApj6AZriBoErA4UpA0x9As9xA0CXg8CWQmQPE9GQkKBNwOBPQNAjQbDcQtAk4vAloKgRoxhsI6gQc7gQ0HQI06w0EfQIOfyI0HwI08y0IAkU4BIrQhAjQ7LcgGBThMChCMyJAM+CCoFCEQ6EITYnQFJAgKBThUChCUyL07QuCQREOgyI0IwI0CS8ICkU4FIrQlAjQRLwgOBThcChibc6y08erCRJFOCSK0KQIxPQRa4JFEQ6LIjQrAjSvLggaRTg0itC0CNDcuiB4FOHwKELzInQWUxA8inB4FGEuUND8vCCIFOEQKcJcoqA5ekEwKcJhUoS5SEFv2gVBpQiHShHmMgVN9AuCSxEOlyLMhQqa7BcEmSIcMkWYSxU04S8INkU4bIroL1bQU4GgU4RDpwhzuYIm/gXBpwj3foW5YJHQU4G6YuHesdAECST0VKCuWXj3LEwOkZ4K5FULB4nCJBFpKFPXLdz7FpojgYSGMnXlwr1zoUkSSGgkUtcu3HsXhlWhaXlBXb1w714YViWlkUhdv3DvX2iWBGhiXVBXMNw7GJomITcKgrqE4bAqQpMkNC8uCFJFOKSKMKQKTYwLglQRDqkiDKlCM+OCIFWEQ6oIQ6rQ1LggSBXhkCrCkCo0Ny4IUkU4pIowpApNjguCVBEOqSIMqUKz44IgVYRDqgjNkdBnWwTBqQiHUxGGU6HpdUFwKsLhVIThVGh+XRCcinA4FWE4FZpgFwSnIhxORRhOhWbYBcGpCIdTEYZToSl2QZAqwiFVhCFVaI5dEKyKcFgVYVgVmmQXBK0iHFpFGFqFZtkFQasIh1YRhlahaXZB0CrCoVWEoVVonl0QtIpwaBVhaBWaaBcErSIcWkUYWoXeLwqCVhEOrSI0S0KfVBIEqyIcVkVokoQ+qSQIUkU4pIrQHMmIRyY4FeFwKkJTJCO+gKBUhEOpCM2QjGxzCEZl+Ju+J/8km05u35n78p8+mVdv/lj9q79BrzKbWou6TK9yl6/++PPP0535V3/8ia7Nq9+Uprws6+d2dyi7Yl/KVpbmTTAsV2QnscF6gdS6e5SN+t6L/rgFFhkESGRohETAFX18RQe3PcVtD3mi1Ls4WEaGZUQ8Gft9WWxyt88ASeLJ0c9JIwHrEIkIBEvInfqspdXRqUBS1ilPyvFBdGwObpFImILq51Z9deUkJzpJ4fWv+RYlFhGijol5IDdCrI4JEQJj3hAZKZ380llQRpMuSHsoM9v2tbBAjOHHm2d3X3UFPOAnGRlLxMbxIqg5ianSN0qRq1yB9V6/DGojCLWO1+HDWzN4imIYxnFvWdJbqtLcfMHSPCCJpIsYSY+4/Xf8Ts/xFTxsMBaZ8KaxL3Jz+oIRkp2hsVJL/Xmy5fFTRFh0ikXz/IYvutRvReIOxhCPlwwWFtscPzCFLY6xxVyo+qKHj2lh0REWzZvbvmjn5SiMEeyk40XjKLfN8IwnAWccDzCd3OmVJSQIu1zFBHEFPdZ1K7dFo0ersEMAgWSKyAgJee78KFrFFrZQPFK9dwj5MGtk3o3ai/HV+xs+Fkxg9Vhst7KSXzpZtU7AgB2bWe1vViHXA+3zu6IsOsfiDPtK4MKqc+KQMMJjz5TSv9qDxETYmIw5JPqdY3uNBDzE6rQNU9D+rs4bJ2REgrgG1Y57j/DUzZhwwO+34ZbhgK9fenskQNgHyep4T/+f4aeUOWkObVfvpHoXy0JJhDx9whvebd7lWESMpjJzBd7Ku4MTYOJxDXht2sou3zzaOwEcxId9Z0X9fI156+9Wv01vWWcNTshzpdsiL+sH29Vb0QBTinFH1lYF73aCrG8kb80be1cKgxrPjIwtdl/mXjgaotGIeZNV7gorwI5wRMozxny63h5AHHkwt5ojr13hnsILY8YbUFk9FU1d6b9hb40RBsyuOokqqvvank94EANmg70QAvWa4G1JCA+DXH/CE6IW9vuidBaREKGeGSYpQR4mkT0hzyMYW+wUBhr6oI9fIq60/pFFvMxiz5Dyhv++zG33EqOpwlyq+9fUMKaxI86YluCX0bAs3KqMF87gj4BjUXizs+bBSD+ViDsZO4GMN1gP6vUSe4eMdrIZ25DNoWmcKZ+gKc+3Ro26NehoVjCB8yC7fVPscntRSdC8yHgOA70Kh4cKbx7XbEldk1ftvm7sMRPYL0a86OL4ZBw2ynJlvN4e+3I1dpDIPMH0Jo/5vis2TnYEQzPgDePwsVU0hGjuZr1TgnUfBakjM+Y/zG40z9GhLRBq6iCSL4ne9qC5ZBapmxUz3WDvC1KcXloPsbFgitrt840NOytdFfA8lxHTdl/d2APvfUKex/DWc7yXHzJy4XF7wIuXh6/v2k7RksxsafVU26mdFOMXeBuhonbmAM7hB7z1q2jz3VYd+EeRFF50BG9KFm3eWP4C59bUdVW2EMcW3CTBmyxF6yc+cXgQM3u33ebN511tz+HMSsPywumi9bZrGR5uwTZI3ueH0ppoGH0x15zjc5V4Z7XG/p1r0UiwEQMWxjWrLKrDF6uX8PaAGT+rxyg3lhAcjwneamq9aInbhV34mjvD0OuUWFaAZTEdbUvEHSmer8Cdr22xO5S5m0OxNtjchaR91q8u2MkzvH0Cnlcs8ztn1qKhY2a7VQht2JNcAbPYW7MFYZyHptOLNnjkcOp1zWvbTrZt/mDJwdRG0GdYoj5PFTPNM1JNpoQgjUKEV2au7/SKDm4xzgszuTXlOe2V0s4Y8lyMu/nEsyYNhght+I/oczmCyZDVdyr5r+TZKylOrkPEm+f1/b21a0ddxuTT6/t7Z6uE939MQt2OD3Eqisme1dWRG7HTvdiPJsz+rew8IM73MA9Y1NVwuMIShIDNtcV6PhaDGzMTTP+phKn9jBXe40VvmZjRCSzwIsFE0V5W6rEJPGmQG+XJcAJLvCoETDNaP6WGY6eBXoKAh+t93qng2wIBkhfz3PD+8WtbbPKSOOmBnRPTqQ/Snuvmc95IK6mf4unCdEfDTtnvORxNB7wxPD16iXfxeAiyYT/LJMr6V5jw7h2vhEyikGL5BQ7z48GbMxPe/3eQrXfmCkezvM7/v4OdN0dN4zWsyR3SI8SdzUy9K7LCykigqcekEgyjbftuvJ4lAwWW8hZy/xVV7DxxWhF4Lp1IdOLxgmjIjjBpRfS6KrYMZ9GYO+r+fIHdd9gxxNnQdzxQ9QLbvCzy1iHEsX29WOYhlOOD2Li5OD/H3Jg2deedvEuxq+EO6KHqip306Q/r0NsSUSO5TDwUzENibf4kvZUab+N4TRzEjIfaCMFMgrPd5KW8z10iO8W9xkwQ+nvwxDoNxzVISbEpESSGmdxqVZxltQhvH5jHX9xHz3EmD8dZTKaPfLgcy8SIYG5X7TfIsTActDHTFlMPiGPReMFlLmz4NXAsCu/pmPEqftobi8IRNHdCyY5cUBJr5eb5Q/KpbywTL1LMMNp+tRsLw36bmbo7vsKN5WCHLXgOW53cds7PgrVVZUsxT3MjMZgAEMwDyu0o6YRdWMQGhEc6pdaWijnV9VPcKM2Csix9XCGYE/yxfjZHzvyDchhRPZ3APDTpAgF7i+yY0ejzQSIYyCcmN96WUtruEueA1LdAWFLQQ6843Ld2o8xh/dp20hrVFAf7zBDPSNFnI9yMEOBjDcAklI08T5Q1mbjjqUUNjy9a0vAWkBnaedMby+AZ1D062XhMEkI80JopU1qxk/oBZtzjeHonvGnpeRycTwr6ZEDU4595dtx7dh27DrxSMs/D+a/aY4FW0Mhbet3n6bE4PJeY91M6dcC2Vc5on28+5w+yzduR47b4THQw9Cpvbni3jXCCjIka+y163GwcdTBTSfhheSwKRx3MLBJ+JR6Lwu6cmV+hZvzaOoPK6+7nvChb7dmsPkeSmHvNkyB1hUSFu5ZANGeZG/+TQO/EKvIozCXlJMz1uvhkCdOZPOdN5d6wslYBnhTzwC9aipHPyHomJhsohYGiEcx4xpBi9oKA99bhkEpgnhUav/+A72JBynMlzzuHm8Hdx3QUZNoTr6BMpsjifHGsng33ktbR0Pc8ifa5LHynazj6sY4Hibze90NTvA1gHjhSQgrHH+JdAPOcjBLjLsn4XIJgnpFRchrZOof88LUHwclk/Haz2hd7WRaVXL369Nuff/4/xjIYCQ=="; \ No newline at end of file diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/docs/assets/style.css b/v3/internal/runtime/desktop/@wailsio/runtime/docs/assets/style.css deleted file mode 100644 index 2ab8b836e..000000000 --- a/v3/internal/runtime/desktop/@wailsio/runtime/docs/assets/style.css +++ /dev/null @@ -1,1611 +0,0 @@ -@layer typedoc { - :root { - /* Light */ - --light-color-background: #f2f4f8; - --light-color-background-secondary: #eff0f1; - --light-color-warning-text: #222; - --light-color-background-warning: #e6e600; - --light-color-accent: #c5c7c9; - --light-color-active-menu-item: var(--light-color-accent); - --light-color-text: #222; - --light-color-text-aside: #6e6e6e; - - --light-color-icon-background: var(--light-color-background); - --light-color-icon-text: var(--light-color-text); - - --light-color-comment-tag-text: var(--light-color-text); - --light-color-comment-tag: var(--light-color-background); - - --light-color-link: #1f70c2; - --light-color-focus-outline: #3584e4; - - --light-color-ts-keyword: #056bd6; - --light-color-ts-project: #b111c9; - --light-color-ts-module: var(--light-color-ts-project); - --light-color-ts-namespace: var(--light-color-ts-project); - --light-color-ts-enum: #7e6f15; - --light-color-ts-enum-member: var(--light-color-ts-enum); - --light-color-ts-variable: #4760ec; - --light-color-ts-function: #572be7; - --light-color-ts-class: #1f70c2; - --light-color-ts-interface: #108024; - --light-color-ts-constructor: var(--light-color-ts-class); - --light-color-ts-property: #9f5f30; - --light-color-ts-method: #be3989; - --light-color-ts-reference: #ff4d82; - --light-color-ts-call-signature: var(--light-color-ts-method); - --light-color-ts-index-signature: var(--light-color-ts-property); - --light-color-ts-constructor-signature: var( - --light-color-ts-constructor - ); - --light-color-ts-parameter: var(--light-color-ts-variable); - /* type literal not included as links will never be generated to it */ - --light-color-ts-type-parameter: #a55c0e; - --light-color-ts-accessor: #c73c3c; - --light-color-ts-get-signature: var(--light-color-ts-accessor); - --light-color-ts-set-signature: var(--light-color-ts-accessor); - --light-color-ts-type-alias: #d51270; - /* reference not included as links will be colored with the kind that it points to */ - --light-color-document: #000000; - - --light-color-alert-note: #0969d9; - --light-color-alert-tip: #1a7f37; - --light-color-alert-important: #8250df; - --light-color-alert-warning: #9a6700; - --light-color-alert-caution: #cf222e; - - --light-external-icon: url("data:image/svg+xml;utf8,"); - --light-color-scheme: light; - - /* Dark */ - --dark-color-background: #2b2e33; - --dark-color-background-secondary: #1e2024; - --dark-color-background-warning: #bebe00; - --dark-color-warning-text: #222; - --dark-color-accent: #9096a2; - --dark-color-active-menu-item: #5d5d6a; - --dark-color-text: #f5f5f5; - --dark-color-text-aside: #dddddd; - - --dark-color-icon-background: var(--dark-color-background-secondary); - --dark-color-icon-text: var(--dark-color-text); - - --dark-color-comment-tag-text: var(--dark-color-text); - --dark-color-comment-tag: var(--dark-color-background); - - --dark-color-link: #00aff4; - --dark-color-focus-outline: #4c97f2; - - --dark-color-ts-keyword: #3399ff; - --dark-color-ts-project: #e358ff; - --dark-color-ts-module: var(--dark-color-ts-project); - --dark-color-ts-namespace: var(--dark-color-ts-project); - --dark-color-ts-enum: #f4d93e; - --dark-color-ts-enum-member: var(--dark-color-ts-enum); - --dark-color-ts-variable: #798dff; - --dark-color-ts-function: #a280ff; - --dark-color-ts-class: #8ac4ff; - --dark-color-ts-interface: #6cff87; - --dark-color-ts-constructor: var(--dark-color-ts-class); - --dark-color-ts-property: #ff984d; - --dark-color-ts-method: #ff4db8; - --dark-color-ts-reference: #ff4d82; - --dark-color-ts-call-signature: var(--dark-color-ts-method); - --dark-color-ts-index-signature: var(--dark-color-ts-property); - --dark-color-ts-constructor-signature: var(--dark-color-ts-constructor); - --dark-color-ts-parameter: var(--dark-color-ts-variable); - /* type literal not included as links will never be generated to it */ - --dark-color-ts-type-parameter: #e07d13; - --dark-color-ts-accessor: #ff6060; - --dark-color-ts-get-signature: var(--dark-color-ts-accessor); - --dark-color-ts-set-signature: var(--dark-color-ts-accessor); - --dark-color-ts-type-alias: #ff6492; - /* reference not included as links will be colored with the kind that it points to */ - --dark-color-document: #ffffff; - - --dark-color-alert-note: #0969d9; - --dark-color-alert-tip: #1a7f37; - --dark-color-alert-important: #8250df; - --dark-color-alert-warning: #9a6700; - --dark-color-alert-caution: #cf222e; - - --dark-external-icon: url("data:image/svg+xml;utf8,"); - --dark-color-scheme: dark; - } - - @media (prefers-color-scheme: light) { - :root { - --color-background: var(--light-color-background); - --color-background-secondary: var( - --light-color-background-secondary - ); - --color-background-warning: var(--light-color-background-warning); - --color-warning-text: var(--light-color-warning-text); - --color-accent: var(--light-color-accent); - --color-active-menu-item: var(--light-color-active-menu-item); - --color-text: var(--light-color-text); - --color-text-aside: var(--light-color-text-aside); - - --color-icon-background: var(--light-color-icon-background); - --color-icon-text: var(--light-color-icon-text); - - --color-comment-tag-text: var(--light-color-text); - --color-comment-tag: var(--light-color-background); - - --color-link: var(--light-color-link); - --color-focus-outline: var(--light-color-focus-outline); - - --color-ts-keyword: var(--light-color-ts-keyword); - --color-ts-project: var(--light-color-ts-project); - --color-ts-module: var(--light-color-ts-module); - --color-ts-namespace: var(--light-color-ts-namespace); - --color-ts-enum: var(--light-color-ts-enum); - --color-ts-enum-member: var(--light-color-ts-enum-member); - --color-ts-variable: var(--light-color-ts-variable); - --color-ts-function: var(--light-color-ts-function); - --color-ts-class: var(--light-color-ts-class); - --color-ts-interface: var(--light-color-ts-interface); - --color-ts-constructor: var(--light-color-ts-constructor); - --color-ts-property: var(--light-color-ts-property); - --color-ts-method: var(--light-color-ts-method); - --color-ts-reference: var(--light-color-ts-reference); - --color-ts-call-signature: var(--light-color-ts-call-signature); - --color-ts-index-signature: var(--light-color-ts-index-signature); - --color-ts-constructor-signature: var( - --light-color-ts-constructor-signature - ); - --color-ts-parameter: var(--light-color-ts-parameter); - --color-ts-type-parameter: var(--light-color-ts-type-parameter); - --color-ts-accessor: var(--light-color-ts-accessor); - --color-ts-get-signature: var(--light-color-ts-get-signature); - --color-ts-set-signature: var(--light-color-ts-set-signature); - --color-ts-type-alias: var(--light-color-ts-type-alias); - --color-document: var(--light-color-document); - - --color-alert-note: var(--light-color-alert-note); - --color-alert-tip: var(--light-color-alert-tip); - --color-alert-important: var(--light-color-alert-important); - --color-alert-warning: var(--light-color-alert-warning); - --color-alert-caution: var(--light-color-alert-caution); - - --external-icon: var(--light-external-icon); - --color-scheme: var(--light-color-scheme); - } - } - - @media (prefers-color-scheme: dark) { - :root { - --color-background: var(--dark-color-background); - --color-background-secondary: var( - --dark-color-background-secondary - ); - --color-background-warning: var(--dark-color-background-warning); - --color-warning-text: var(--dark-color-warning-text); - --color-accent: var(--dark-color-accent); - --color-active-menu-item: var(--dark-color-active-menu-item); - --color-text: var(--dark-color-text); - --color-text-aside: var(--dark-color-text-aside); - - --color-icon-background: var(--dark-color-icon-background); - --color-icon-text: var(--dark-color-icon-text); - - --color-comment-tag-text: var(--dark-color-text); - --color-comment-tag: var(--dark-color-background); - - --color-link: var(--dark-color-link); - --color-focus-outline: var(--dark-color-focus-outline); - - --color-ts-keyword: var(--dark-color-ts-keyword); - --color-ts-project: var(--dark-color-ts-project); - --color-ts-module: var(--dark-color-ts-module); - --color-ts-namespace: var(--dark-color-ts-namespace); - --color-ts-enum: var(--dark-color-ts-enum); - --color-ts-enum-member: var(--dark-color-ts-enum-member); - --color-ts-variable: var(--dark-color-ts-variable); - --color-ts-function: var(--dark-color-ts-function); - --color-ts-class: var(--dark-color-ts-class); - --color-ts-interface: var(--dark-color-ts-interface); - --color-ts-constructor: var(--dark-color-ts-constructor); - --color-ts-property: var(--dark-color-ts-property); - --color-ts-method: var(--dark-color-ts-method); - --color-ts-reference: var(--dark-color-ts-reference); - --color-ts-call-signature: var(--dark-color-ts-call-signature); - --color-ts-index-signature: var(--dark-color-ts-index-signature); - --color-ts-constructor-signature: var( - --dark-color-ts-constructor-signature - ); - --color-ts-parameter: var(--dark-color-ts-parameter); - --color-ts-type-parameter: var(--dark-color-ts-type-parameter); - --color-ts-accessor: var(--dark-color-ts-accessor); - --color-ts-get-signature: var(--dark-color-ts-get-signature); - --color-ts-set-signature: var(--dark-color-ts-set-signature); - --color-ts-type-alias: var(--dark-color-ts-type-alias); - --color-document: var(--dark-color-document); - - --color-alert-note: var(--dark-color-alert-note); - --color-alert-tip: var(--dark-color-alert-tip); - --color-alert-important: var(--dark-color-alert-important); - --color-alert-warning: var(--dark-color-alert-warning); - --color-alert-caution: var(--dark-color-alert-caution); - - --external-icon: var(--dark-external-icon); - --color-scheme: var(--dark-color-scheme); - } - } - - html { - color-scheme: var(--color-scheme); - } - - body { - margin: 0; - } - - :root[data-theme="light"] { - --color-background: var(--light-color-background); - --color-background-secondary: var(--light-color-background-secondary); - --color-background-warning: var(--light-color-background-warning); - --color-warning-text: var(--light-color-warning-text); - --color-icon-background: var(--light-color-icon-background); - --color-accent: var(--light-color-accent); - --color-active-menu-item: var(--light-color-active-menu-item); - --color-text: var(--light-color-text); - --color-text-aside: var(--light-color-text-aside); - --color-icon-text: var(--light-color-icon-text); - - --color-comment-tag-text: var(--light-color-text); - --color-comment-tag: var(--light-color-background); - - --color-link: var(--light-color-link); - --color-focus-outline: var(--light-color-focus-outline); - - --color-ts-keyword: var(--light-color-ts-keyword); - --color-ts-project: var(--light-color-ts-project); - --color-ts-module: var(--light-color-ts-module); - --color-ts-namespace: var(--light-color-ts-namespace); - --color-ts-enum: var(--light-color-ts-enum); - --color-ts-enum-member: var(--light-color-ts-enum-member); - --color-ts-variable: var(--light-color-ts-variable); - --color-ts-function: var(--light-color-ts-function); - --color-ts-class: var(--light-color-ts-class); - --color-ts-interface: var(--light-color-ts-interface); - --color-ts-constructor: var(--light-color-ts-constructor); - --color-ts-property: var(--light-color-ts-property); - --color-ts-method: var(--light-color-ts-method); - --color-ts-reference: var(--light-color-ts-reference); - --color-ts-call-signature: var(--light-color-ts-call-signature); - --color-ts-index-signature: var(--light-color-ts-index-signature); - --color-ts-constructor-signature: var( - --light-color-ts-constructor-signature - ); - --color-ts-parameter: var(--light-color-ts-parameter); - --color-ts-type-parameter: var(--light-color-ts-type-parameter); - --color-ts-accessor: var(--light-color-ts-accessor); - --color-ts-get-signature: var(--light-color-ts-get-signature); - --color-ts-set-signature: var(--light-color-ts-set-signature); - --color-ts-type-alias: var(--light-color-ts-type-alias); - --color-document: var(--light-color-document); - - --color-note: var(--light-color-note); - --color-tip: var(--light-color-tip); - --color-important: var(--light-color-important); - --color-warning: var(--light-color-warning); - --color-caution: var(--light-color-caution); - - --external-icon: var(--light-external-icon); - --color-scheme: var(--light-color-scheme); - } - - :root[data-theme="dark"] { - --color-background: var(--dark-color-background); - --color-background-secondary: var(--dark-color-background-secondary); - --color-background-warning: var(--dark-color-background-warning); - --color-warning-text: var(--dark-color-warning-text); - --color-icon-background: var(--dark-color-icon-background); - --color-accent: var(--dark-color-accent); - --color-active-menu-item: var(--dark-color-active-menu-item); - --color-text: var(--dark-color-text); - --color-text-aside: var(--dark-color-text-aside); - --color-icon-text: var(--dark-color-icon-text); - - --color-comment-tag-text: var(--dark-color-text); - --color-comment-tag: var(--dark-color-background); - - --color-link: var(--dark-color-link); - --color-focus-outline: var(--dark-color-focus-outline); - - --color-ts-keyword: var(--dark-color-ts-keyword); - --color-ts-project: var(--dark-color-ts-project); - --color-ts-module: var(--dark-color-ts-module); - --color-ts-namespace: var(--dark-color-ts-namespace); - --color-ts-enum: var(--dark-color-ts-enum); - --color-ts-enum-member: var(--dark-color-ts-enum-member); - --color-ts-variable: var(--dark-color-ts-variable); - --color-ts-function: var(--dark-color-ts-function); - --color-ts-class: var(--dark-color-ts-class); - --color-ts-interface: var(--dark-color-ts-interface); - --color-ts-constructor: var(--dark-color-ts-constructor); - --color-ts-property: var(--dark-color-ts-property); - --color-ts-method: var(--dark-color-ts-method); - --color-ts-reference: var(--dark-color-ts-reference); - --color-ts-call-signature: var(--dark-color-ts-call-signature); - --color-ts-index-signature: var(--dark-color-ts-index-signature); - --color-ts-constructor-signature: var( - --dark-color-ts-constructor-signature - ); - --color-ts-parameter: var(--dark-color-ts-parameter); - --color-ts-type-parameter: var(--dark-color-ts-type-parameter); - --color-ts-accessor: var(--dark-color-ts-accessor); - --color-ts-get-signature: var(--dark-color-ts-get-signature); - --color-ts-set-signature: var(--dark-color-ts-set-signature); - --color-ts-type-alias: var(--dark-color-ts-type-alias); - --color-document: var(--dark-color-document); - - --color-note: var(--dark-color-note); - --color-tip: var(--dark-color-tip); - --color-important: var(--dark-color-important); - --color-warning: var(--dark-color-warning); - --color-caution: var(--dark-color-caution); - - --external-icon: var(--dark-external-icon); - --color-scheme: var(--dark-color-scheme); - } - - *:focus-visible, - .tsd-accordion-summary:focus-visible svg { - outline: 2px solid var(--color-focus-outline); - } - - .always-visible, - .always-visible .tsd-signatures { - display: inherit !important; - } - - h1, - h2, - h3, - h4, - h5, - h6 { - line-height: 1.2; - } - - h1 { - font-size: 1.875rem; - margin: 0.67rem 0; - } - - h2 { - font-size: 1.5rem; - margin: 0.83rem 0; - } - - h3 { - font-size: 1.25rem; - margin: 1rem 0; - } - - h4 { - font-size: 1.05rem; - margin: 1.33rem 0; - } - - h5 { - font-size: 1rem; - margin: 1.5rem 0; - } - - h6 { - font-size: 0.875rem; - margin: 2.33rem 0; - } - - dl, - menu, - ol, - ul { - margin: 1em 0; - } - - dd { - margin: 0 0 0 34px; - } - - .container { - max-width: 1700px; - padding: 0 2rem; - } - - /* Footer */ - footer { - border-top: 1px solid var(--color-accent); - padding-top: 1rem; - padding-bottom: 1rem; - max-height: 3.5rem; - } - footer > p { - margin: 0 1em; - } - - .container-main { - margin: 0 auto; - /* toolbar, footer, margin */ - min-height: calc(100vh - 41px - 56px - 4rem); - } - - @keyframes fade-in { - from { - opacity: 0; - } - to { - opacity: 1; - } - } - @keyframes fade-out { - from { - opacity: 1; - visibility: visible; - } - to { - opacity: 0; - } - } - @keyframes fade-in-delayed { - 0% { - opacity: 0; - } - 33% { - opacity: 0; - } - 100% { - opacity: 1; - } - } - @keyframes fade-out-delayed { - 0% { - opacity: 1; - visibility: visible; - } - 66% { - opacity: 0; - } - 100% { - opacity: 0; - } - } - @keyframes pop-in-from-right { - from { - transform: translate(100%, 0); - } - to { - transform: translate(0, 0); - } - } - @keyframes pop-out-to-right { - from { - transform: translate(0, 0); - visibility: visible; - } - to { - transform: translate(100%, 0); - } - } - body { - background: var(--color-background); - font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Noto Sans", - Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji"; - font-size: 16px; - color: var(--color-text); - } - - a { - color: var(--color-link); - text-decoration: none; - } - a:hover { - text-decoration: underline; - } - a.external[target="_blank"] { - background-image: var(--external-icon); - background-position: top 3px right; - background-repeat: no-repeat; - padding-right: 13px; - } - a.tsd-anchor-link { - color: var(--color-text); - } - - code, - pre { - font-family: Menlo, Monaco, Consolas, "Courier New", monospace; - padding: 0.2em; - margin: 0; - font-size: 0.875rem; - border-radius: 0.8em; - } - - pre { - position: relative; - white-space: pre-wrap; - word-wrap: break-word; - padding: 10px; - border: 1px solid var(--color-accent); - margin-bottom: 8px; - } - pre code { - padding: 0; - font-size: 100%; - } - pre > button { - position: absolute; - top: 10px; - right: 10px; - opacity: 0; - transition: opacity 0.1s; - box-sizing: border-box; - } - pre:hover > button, - pre > button.visible { - opacity: 1; - } - - blockquote { - margin: 1em 0; - padding-left: 1em; - border-left: 4px solid gray; - } - - .tsd-typography { - line-height: 1.333em; - } - .tsd-typography ul { - list-style: square; - padding: 0 0 0 20px; - margin: 0; - } - .tsd-typography .tsd-index-panel h3, - .tsd-index-panel .tsd-typography h3, - .tsd-typography h4, - .tsd-typography h5, - .tsd-typography h6 { - font-size: 1em; - } - .tsd-typography h5, - .tsd-typography h6 { - font-weight: normal; - } - .tsd-typography p, - .tsd-typography ul, - .tsd-typography ol { - margin: 1em 0; - } - .tsd-typography table { - border-collapse: collapse; - border: none; - } - .tsd-typography td, - .tsd-typography th { - padding: 6px 13px; - border: 1px solid var(--color-accent); - } - .tsd-typography thead, - .tsd-typography tr:nth-child(even) { - background-color: var(--color-background-secondary); - } - - .tsd-alert { - padding: 8px 16px; - margin-bottom: 16px; - border-left: 0.25em solid var(--alert-color); - } - .tsd-alert blockquote > :last-child, - .tsd-alert > :last-child { - margin-bottom: 0; - } - .tsd-alert-title { - color: var(--alert-color); - display: inline-flex; - align-items: center; - } - .tsd-alert-title span { - margin-left: 4px; - } - - .tsd-alert-note { - --alert-color: var(--color-alert-note); - } - .tsd-alert-tip { - --alert-color: var(--color-alert-tip); - } - .tsd-alert-important { - --alert-color: var(--color-alert-important); - } - .tsd-alert-warning { - --alert-color: var(--color-alert-warning); - } - .tsd-alert-caution { - --alert-color: var(--color-alert-caution); - } - - .tsd-breadcrumb { - margin: 0; - padding: 0; - color: var(--color-text-aside); - } - .tsd-breadcrumb a { - color: var(--color-text-aside); - text-decoration: none; - } - .tsd-breadcrumb a:hover { - text-decoration: underline; - } - .tsd-breadcrumb li { - display: inline; - } - .tsd-breadcrumb li:after { - content: " / "; - } - - .tsd-comment-tags { - display: flex; - flex-direction: column; - } - dl.tsd-comment-tag-group { - display: flex; - align-items: center; - overflow: hidden; - margin: 0.5em 0; - } - dl.tsd-comment-tag-group dt { - display: flex; - margin-right: 0.5em; - font-size: 0.875em; - font-weight: normal; - } - dl.tsd-comment-tag-group dd { - margin: 0; - } - code.tsd-tag { - padding: 0.25em 0.4em; - border: 0.1em solid var(--color-accent); - margin-right: 0.25em; - font-size: 70%; - } - h1 code.tsd-tag:first-of-type { - margin-left: 0.25em; - } - - dl.tsd-comment-tag-group dd:before, - dl.tsd-comment-tag-group dd:after { - content: " "; - } - dl.tsd-comment-tag-group dd pre, - dl.tsd-comment-tag-group dd:after { - clear: both; - } - dl.tsd-comment-tag-group p { - margin: 0; - } - - .tsd-panel.tsd-comment .lead { - font-size: 1.1em; - line-height: 1.333em; - margin-bottom: 2em; - } - .tsd-panel.tsd-comment .lead:last-child { - margin-bottom: 0; - } - - .tsd-filter-visibility h4 { - font-size: 1rem; - padding-top: 0.75rem; - padding-bottom: 0.5rem; - margin: 0; - } - .tsd-filter-item:not(:last-child) { - margin-bottom: 0.5rem; - } - .tsd-filter-input { - display: flex; - width: -moz-fit-content; - width: fit-content; - align-items: center; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; - cursor: pointer; - } - .tsd-filter-input input[type="checkbox"] { - cursor: pointer; - position: absolute; - width: 1.5em; - height: 1.5em; - opacity: 0; - } - .tsd-filter-input input[type="checkbox"]:disabled { - pointer-events: none; - } - .tsd-filter-input svg { - cursor: pointer; - width: 1.5em; - height: 1.5em; - margin-right: 0.5em; - border-radius: 0.33em; - /* Leaving this at full opacity breaks event listeners on Firefox. - Don't remove unless you know what you're doing. */ - opacity: 0.99; - } - .tsd-filter-input input[type="checkbox"]:focus-visible + svg { - outline: 2px solid var(--color-focus-outline); - } - .tsd-checkbox-background { - fill: var(--color-accent); - } - input[type="checkbox"]:checked ~ svg .tsd-checkbox-checkmark { - stroke: var(--color-text); - } - .tsd-filter-input input:disabled ~ svg > .tsd-checkbox-background { - fill: var(--color-background); - stroke: var(--color-accent); - stroke-width: 0.25rem; - } - .tsd-filter-input input:disabled ~ svg > .tsd-checkbox-checkmark { - stroke: var(--color-accent); - } - - .settings-label { - font-weight: bold; - text-transform: uppercase; - display: inline-block; - } - - .tsd-filter-visibility .settings-label { - margin: 0.75rem 0 0.5rem 0; - } - - .tsd-theme-toggle .settings-label { - margin: 0.75rem 0.75rem 0 0; - } - - .tsd-hierarchy h4 label:hover span { - text-decoration: underline; - } - - .tsd-hierarchy { - list-style: square; - margin: 0; - } - .tsd-hierarchy-target { - font-weight: bold; - } - .tsd-hierarchy-toggle { - color: var(--color-link); - cursor: pointer; - } - - .tsd-full-hierarchy:not(:last-child) { - margin-bottom: 1em; - padding-bottom: 1em; - border-bottom: 1px solid var(--color-accent); - } - .tsd-full-hierarchy, - .tsd-full-hierarchy ul { - list-style: none; - margin: 0; - padding: 0; - } - .tsd-full-hierarchy ul { - padding-left: 1.5rem; - } - .tsd-full-hierarchy a { - padding: 0.25rem 0 !important; - font-size: 1rem; - display: inline-flex; - align-items: center; - color: var(--color-text); - } - .tsd-full-hierarchy svg[data-dropdown] { - cursor: pointer; - } - .tsd-full-hierarchy svg[data-dropdown="false"] { - transform: rotate(-90deg); - } - .tsd-full-hierarchy svg[data-dropdown="false"] ~ ul { - display: none; - } - - .tsd-panel-group.tsd-index-group { - margin-bottom: 0; - } - .tsd-index-panel .tsd-index-list { - list-style: none; - line-height: 1.333em; - margin: 0; - padding: 0.25rem 0 0 0; - overflow: hidden; - display: grid; - grid-template-columns: repeat(3, 1fr); - column-gap: 1rem; - grid-template-rows: auto; - } - @media (max-width: 1024px) { - .tsd-index-panel .tsd-index-list { - grid-template-columns: repeat(2, 1fr); - } - } - @media (max-width: 768px) { - .tsd-index-panel .tsd-index-list { - grid-template-columns: repeat(1, 1fr); - } - } - .tsd-index-panel .tsd-index-list li { - -webkit-page-break-inside: avoid; - -moz-page-break-inside: avoid; - -ms-page-break-inside: avoid; - -o-page-break-inside: avoid; - page-break-inside: avoid; - } - - .tsd-flag { - display: inline-block; - padding: 0.25em 0.4em; - border-radius: 4px; - color: var(--color-comment-tag-text); - background-color: var(--color-comment-tag); - text-indent: 0; - font-size: 75%; - line-height: 1; - font-weight: normal; - } - - .tsd-anchor { - position: relative; - top: -100px; - } - - .tsd-member { - position: relative; - } - .tsd-member .tsd-anchor + h3 { - display: flex; - align-items: center; - margin-top: 0; - margin-bottom: 0; - border-bottom: none; - } - - .tsd-navigation.settings { - margin: 1rem 0; - } - .tsd-navigation > a, - .tsd-navigation .tsd-accordion-summary { - width: calc(100% - 0.25rem); - display: flex; - align-items: center; - } - .tsd-navigation a, - .tsd-navigation summary > span, - .tsd-page-navigation a { - display: flex; - width: calc(100% - 0.25rem); - align-items: center; - padding: 0.25rem; - color: var(--color-text); - text-decoration: none; - box-sizing: border-box; - } - .tsd-navigation a.current, - .tsd-page-navigation a.current { - background: var(--color-active-menu-item); - } - .tsd-navigation a:hover, - .tsd-page-navigation a:hover { - text-decoration: underline; - } - .tsd-navigation ul, - .tsd-page-navigation ul { - margin-top: 0; - margin-bottom: 0; - padding: 0; - list-style: none; - } - .tsd-navigation li, - .tsd-page-navigation li { - padding: 0; - max-width: 100%; - } - .tsd-navigation .tsd-nav-link { - display: none; - } - .tsd-nested-navigation { - margin-left: 3rem; - } - .tsd-nested-navigation > li > details { - margin-left: -1.5rem; - } - .tsd-small-nested-navigation { - margin-left: 1.5rem; - } - .tsd-small-nested-navigation > li > details { - margin-left: -1.5rem; - } - - .tsd-page-navigation-section { - margin-left: 10px; - } - .tsd-page-navigation-section > summary { - padding: 0.25rem; - } - .tsd-page-navigation-section > div { - margin-left: 20px; - } - .tsd-page-navigation ul { - padding-left: 1.75rem; - } - - #tsd-sidebar-links a { - margin-top: 0; - margin-bottom: 0.5rem; - line-height: 1.25rem; - } - #tsd-sidebar-links a:last-of-type { - margin-bottom: 0; - } - - a.tsd-index-link { - padding: 0.25rem 0 !important; - font-size: 1rem; - line-height: 1.25rem; - display: inline-flex; - align-items: center; - color: var(--color-text); - } - .tsd-accordion-summary { - list-style-type: none; /* hide marker on non-safari */ - outline: none; /* broken on safari, so just hide it */ - } - .tsd-accordion-summary::-webkit-details-marker { - display: none; /* hide marker on safari */ - } - .tsd-accordion-summary, - .tsd-accordion-summary a { - -moz-user-select: none; - -webkit-user-select: none; - -ms-user-select: none; - user-select: none; - - cursor: pointer; - } - .tsd-accordion-summary a { - width: calc(100% - 1.5rem); - } - .tsd-accordion-summary > * { - margin-top: 0; - margin-bottom: 0; - padding-top: 0; - padding-bottom: 0; - } - .tsd-accordion .tsd-accordion-summary > svg { - margin-left: 0.25rem; - vertical-align: text-top; - } - /* - * We need to be careful to target the arrow indicating whether the accordion - * is open, but not any other SVGs included in the details element. - */ - .tsd-accordion:not([open]) > .tsd-accordion-summary > svg:first-child, - .tsd-accordion:not([open]) > .tsd-accordion-summary > h1 > svg:first-child, - .tsd-accordion:not([open]) > .tsd-accordion-summary > h2 > svg:first-child, - .tsd-accordion:not([open]) > .tsd-accordion-summary > h3 > svg:first-child, - .tsd-accordion:not([open]) > .tsd-accordion-summary > h4 > svg:first-child, - .tsd-accordion:not([open]) > .tsd-accordion-summary > h5 > svg:first-child { - transform: rotate(-90deg); - } - .tsd-index-content > :not(:first-child) { - margin-top: 0.75rem; - } - .tsd-index-heading { - margin-top: 1.5rem; - margin-bottom: 0.75rem; - } - - .tsd-no-select { - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - user-select: none; - } - .tsd-kind-icon { - margin-right: 0.5rem; - width: 1.25rem; - height: 1.25rem; - min-width: 1.25rem; - min-height: 1.25rem; - } - .tsd-signature > .tsd-kind-icon { - margin-right: 0.8rem; - } - - .tsd-panel { - margin-bottom: 2.5rem; - } - .tsd-panel.tsd-member { - margin-bottom: 4rem; - } - .tsd-panel:empty { - display: none; - } - .tsd-panel > h1, - .tsd-panel > h2, - .tsd-panel > h3 { - margin: 1.5rem -1.5rem 0.75rem -1.5rem; - padding: 0 1.5rem 0.75rem 1.5rem; - } - .tsd-panel > h1.tsd-before-signature, - .tsd-panel > h2.tsd-before-signature, - .tsd-panel > h3.tsd-before-signature { - margin-bottom: 0; - border-bottom: none; - } - - .tsd-panel-group { - margin: 2rem 0; - } - .tsd-panel-group.tsd-index-group { - margin: 2rem 0; - } - .tsd-panel-group.tsd-index-group details { - margin: 2rem 0; - } - .tsd-panel-group > .tsd-accordion-summary { - margin-bottom: 1rem; - } - - #tsd-search { - transition: background-color 0.2s; - } - #tsd-search .title { - position: relative; - z-index: 2; - } - #tsd-search .field { - position: absolute; - left: 0; - top: 0; - right: 2.5rem; - height: 100%; - } - #tsd-search .field input { - box-sizing: border-box; - position: relative; - top: -50px; - z-index: 1; - width: 100%; - padding: 0 10px; - opacity: 0; - outline: 0; - border: 0; - background: transparent; - color: var(--color-text); - } - #tsd-search .field label { - position: absolute; - overflow: hidden; - right: -40px; - } - #tsd-search .field input, - #tsd-search .title, - #tsd-toolbar-links a { - transition: opacity 0.2s; - } - #tsd-search .results { - position: absolute; - visibility: hidden; - top: 40px; - width: 100%; - margin: 0; - padding: 0; - list-style: none; - box-shadow: 0 0 4px rgba(0, 0, 0, 0.25); - } - #tsd-search .results li { - background-color: var(--color-background); - line-height: initial; - padding: 4px; - } - #tsd-search .results li:nth-child(even) { - background-color: var(--color-background-secondary); - } - #tsd-search .results li.state { - display: none; - } - #tsd-search .results li.current:not(.no-results), - #tsd-search .results li:hover:not(.no-results) { - background-color: var(--color-accent); - } - #tsd-search .results a { - display: flex; - align-items: center; - padding: 0.25rem; - box-sizing: border-box; - } - #tsd-search .results a:before { - top: 10px; - } - #tsd-search .results span.parent { - color: var(--color-text-aside); - font-weight: normal; - } - #tsd-search.has-focus { - background-color: var(--color-accent); - } - #tsd-search.has-focus .field input { - top: 0; - opacity: 1; - } - #tsd-search.has-focus .title, - #tsd-search.has-focus #tsd-toolbar-links a { - z-index: 0; - opacity: 0; - } - #tsd-search.has-focus .results { - visibility: visible; - } - #tsd-search.loading .results li.state.loading { - display: block; - } - #tsd-search.failure .results li.state.failure { - display: block; - } - - #tsd-toolbar-links { - position: absolute; - top: 0; - right: 2rem; - height: 100%; - display: flex; - align-items: center; - justify-content: flex-end; - } - #tsd-toolbar-links a { - margin-left: 1.5rem; - } - #tsd-toolbar-links a:hover { - text-decoration: underline; - } - - .tsd-signature { - margin: 0 0 1rem 0; - padding: 1rem 0.5rem; - border: 1px solid var(--color-accent); - font-family: Menlo, Monaco, Consolas, "Courier New", monospace; - font-size: 14px; - overflow-x: auto; - } - - .tsd-signature-keyword { - color: var(--color-ts-keyword); - font-weight: normal; - } - - .tsd-signature-symbol { - color: var(--color-text-aside); - font-weight: normal; - } - - .tsd-signature-type { - font-style: italic; - font-weight: normal; - } - - .tsd-signatures { - padding: 0; - margin: 0 0 1em 0; - list-style-type: none; - } - .tsd-signatures .tsd-signature { - margin: 0; - border-color: var(--color-accent); - border-width: 1px 0; - transition: background-color 0.1s; - } - .tsd-signatures .tsd-index-signature:not(:last-child) { - margin-bottom: 1em; - } - .tsd-signatures .tsd-index-signature .tsd-signature { - border-width: 1px; - } - .tsd-description .tsd-signatures .tsd-signature { - border-width: 1px; - } - - ul.tsd-parameter-list, - ul.tsd-type-parameter-list { - list-style: square; - margin: 0; - padding-left: 20px; - } - ul.tsd-parameter-list > li.tsd-parameter-signature, - ul.tsd-type-parameter-list > li.tsd-parameter-signature { - list-style: none; - margin-left: -20px; - } - ul.tsd-parameter-list h5, - ul.tsd-type-parameter-list h5 { - font-size: 16px; - margin: 1em 0 0.5em 0; - } - .tsd-sources { - margin-top: 1rem; - font-size: 0.875em; - } - .tsd-sources a { - color: var(--color-text-aside); - text-decoration: underline; - } - .tsd-sources ul { - list-style: none; - padding: 0; - } - - .tsd-page-toolbar { - position: sticky; - z-index: 1; - top: 0; - left: 0; - width: 100%; - color: var(--color-text); - background: var(--color-background-secondary); - border-bottom: 1px var(--color-accent) solid; - transition: transform 0.3s ease-in-out; - } - .tsd-page-toolbar a { - color: var(--color-text); - text-decoration: none; - } - .tsd-page-toolbar a.title { - font-weight: bold; - } - .tsd-page-toolbar a.title:hover { - text-decoration: underline; - } - .tsd-page-toolbar .tsd-toolbar-contents { - display: flex; - justify-content: space-between; - height: 2.5rem; - margin: 0 auto; - } - .tsd-page-toolbar .table-cell { - position: relative; - white-space: nowrap; - line-height: 40px; - } - .tsd-page-toolbar .table-cell:first-child { - width: 100%; - } - .tsd-page-toolbar .tsd-toolbar-icon { - box-sizing: border-box; - line-height: 0; - padding: 12px 0; - } - - .tsd-widget { - display: inline-block; - overflow: hidden; - opacity: 0.8; - height: 40px; - transition: - opacity 0.1s, - background-color 0.2s; - vertical-align: bottom; - cursor: pointer; - } - .tsd-widget:hover { - opacity: 0.9; - } - .tsd-widget.active { - opacity: 1; - background-color: var(--color-accent); - } - .tsd-widget.no-caption { - width: 40px; - } - .tsd-widget.no-caption:before { - margin: 0; - } - - .tsd-widget.options, - .tsd-widget.menu { - display: none; - } - input[type="checkbox"] + .tsd-widget:before { - background-position: -120px 0; - } - input[type="checkbox"]:checked + .tsd-widget:before { - background-position: -160px 0; - } - - img { - max-width: 100%; - } - - .tsd-member-summary-name { - display: inline-flex; - align-items: center; - padding: 0.25rem; - text-decoration: none; - } - - .tsd-anchor-icon { - display: inline-flex; - align-items: center; - margin-left: 0.5rem; - color: var(--color-text); - } - - .tsd-anchor-icon svg { - width: 1em; - height: 1em; - visibility: hidden; - } - - .tsd-member-summary-name:hover > .tsd-anchor-icon svg, - .tsd-anchor-link:hover > .tsd-anchor-icon svg { - visibility: visible; - } - - .deprecated { - text-decoration: line-through !important; - } - - .warning { - padding: 1rem; - color: var(--color-warning-text); - background: var(--color-background-warning); - } - - .tsd-kind-project { - color: var(--color-ts-project); - } - .tsd-kind-module { - color: var(--color-ts-module); - } - .tsd-kind-namespace { - color: var(--color-ts-namespace); - } - .tsd-kind-enum { - color: var(--color-ts-enum); - } - .tsd-kind-enum-member { - color: var(--color-ts-enum-member); - } - .tsd-kind-variable { - color: var(--color-ts-variable); - } - .tsd-kind-function { - color: var(--color-ts-function); - } - .tsd-kind-class { - color: var(--color-ts-class); - } - .tsd-kind-interface { - color: var(--color-ts-interface); - } - .tsd-kind-constructor { - color: var(--color-ts-constructor); - } - .tsd-kind-property { - color: var(--color-ts-property); - } - .tsd-kind-method { - color: var(--color-ts-method); - } - .tsd-kind-reference { - color: var(--color-ts-reference); - } - .tsd-kind-call-signature { - color: var(--color-ts-call-signature); - } - .tsd-kind-index-signature { - color: var(--color-ts-index-signature); - } - .tsd-kind-constructor-signature { - color: var(--color-ts-constructor-signature); - } - .tsd-kind-parameter { - color: var(--color-ts-parameter); - } - .tsd-kind-type-parameter { - color: var(--color-ts-type-parameter); - } - .tsd-kind-accessor { - color: var(--color-ts-accessor); - } - .tsd-kind-get-signature { - color: var(--color-ts-get-signature); - } - .tsd-kind-set-signature { - color: var(--color-ts-set-signature); - } - .tsd-kind-type-alias { - color: var(--color-ts-type-alias); - } - - /* if we have a kind icon, don't color the text by kind */ - .tsd-kind-icon ~ span { - color: var(--color-text); - } - - * { - scrollbar-width: thin; - scrollbar-color: var(--color-accent) var(--color-icon-background); - } - - *::-webkit-scrollbar { - width: 0.75rem; - } - - *::-webkit-scrollbar-track { - background: var(--color-icon-background); - } - - *::-webkit-scrollbar-thumb { - background-color: var(--color-accent); - border-radius: 999rem; - border: 0.25rem solid var(--color-icon-background); - } - - /* mobile */ - @media (max-width: 769px) { - .tsd-widget.options, - .tsd-widget.menu { - display: inline-block; - } - - .container-main { - display: flex; - } - html .col-content { - float: none; - max-width: 100%; - width: 100%; - } - html .col-sidebar { - position: fixed !important; - overflow-y: auto; - -webkit-overflow-scrolling: touch; - z-index: 1024; - top: 0 !important; - bottom: 0 !important; - left: auto !important; - right: 0 !important; - padding: 1.5rem 1.5rem 0 0; - width: 75vw; - visibility: hidden; - background-color: var(--color-background); - transform: translate(100%, 0); - } - html .col-sidebar > *:last-child { - padding-bottom: 20px; - } - html .overlay { - content: ""; - display: block; - position: fixed; - z-index: 1023; - top: 0; - left: 0; - right: 0; - bottom: 0; - background-color: rgba(0, 0, 0, 0.75); - visibility: hidden; - } - - .to-has-menu .overlay { - animation: fade-in 0.4s; - } - - .to-has-menu .col-sidebar { - animation: pop-in-from-right 0.4s; - } - - .from-has-menu .overlay { - animation: fade-out 0.4s; - } - - .from-has-menu .col-sidebar { - animation: pop-out-to-right 0.4s; - } - - .has-menu body { - overflow: hidden; - } - .has-menu .overlay { - visibility: visible; - } - .has-menu .col-sidebar { - visibility: visible; - transform: translate(0, 0); - display: flex; - flex-direction: column; - gap: 1.5rem; - max-height: 100vh; - padding: 1rem 2rem; - } - .has-menu .tsd-navigation { - max-height: 100%; - } - #tsd-toolbar-links { - display: none; - } - .tsd-navigation .tsd-nav-link { - display: flex; - } - } - - /* one sidebar */ - @media (min-width: 770px) { - .container-main { - display: grid; - grid-template-columns: minmax(0, 1fr) minmax(0, 2fr); - grid-template-areas: "sidebar content"; - margin: 2rem auto; - } - - .col-sidebar { - grid-area: sidebar; - } - .col-content { - grid-area: content; - padding: 0 1rem; - } - } - @media (min-width: 770px) and (max-width: 1399px) { - .col-sidebar { - max-height: calc(100vh - 2rem - 42px); - overflow: auto; - position: sticky; - top: 42px; - padding-top: 1rem; - } - .site-menu { - margin-top: 1rem; - } - } - - /* two sidebars */ - @media (min-width: 1200px) { - .container-main { - grid-template-columns: minmax(0, 1fr) minmax(0, 2.5fr) minmax( - 0, - 20rem - ); - grid-template-areas: "sidebar content toc"; - } - - .col-sidebar { - display: contents; - } - - .page-menu { - grid-area: toc; - padding-left: 1rem; - } - .site-menu { - grid-area: sidebar; - } - - .site-menu { - margin-top: 1rem; - } - - .page-menu, - .site-menu { - max-height: calc(100vh - 2rem - 42px); - overflow: auto; - position: sticky; - top: 42px; - } - } -} diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/docs/classes/Call.RuntimeError.html b/v3/internal/runtime/desktop/@wailsio/runtime/docs/classes/Call.RuntimeError.html deleted file mode 100644 index 0729f9ddc..000000000 --- a/v3/internal/runtime/desktop/@wailsio/runtime/docs/classes/Call.RuntimeError.html +++ /dev/null @@ -1,11 +0,0 @@ -RuntimeError | @wailsio/runtime

                    Exception class that will be thrown in case the bound method returns an error. -The value of the RuntimeError#name property is "RuntimeError".

                    -

                    Hierarchy

                    Constructors

                    Properties

                    Constructors

                    • Constructs a new RuntimeError instance.

                      -

                      Parameters

                      • Optionalmessage: string

                        The error message.

                        -
                      • Optionaloptions: ErrorOptions

                        Options to be forwarded to the Error constructor.

                        -

                      Returns RuntimeError

                    Properties

                    cause?: unknown
                    message: string
                    name: string
                    stack?: string
                    diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/docs/classes/CancelError.html b/v3/internal/runtime/desktop/@wailsio/runtime/docs/classes/CancelError.html deleted file mode 100644 index f8c722aaf..000000000 --- a/v3/internal/runtime/desktop/@wailsio/runtime/docs/classes/CancelError.html +++ /dev/null @@ -1,13 +0,0 @@ -CancelError | @wailsio/runtime

                    Exception class that will be used as rejection reason -in case a CancellablePromise is cancelled successfully.

                    -

                    The value of the name property is the string "CancelError". -The value of the cause property is the cause passed to the cancel method, if any.

                    -

                    Hierarchy

                    Constructors

                    Properties

                    Constructors

                    Properties

                    cause?: unknown
                    message: string
                    name: string
                    stack?: string
                    diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/docs/classes/CancellablePromise.html b/v3/internal/runtime/desktop/@wailsio/runtime/docs/classes/CancellablePromise.html deleted file mode 100644 index 858840242..000000000 --- a/v3/internal/runtime/desktop/@wailsio/runtime/docs/classes/CancellablePromise.html +++ /dev/null @@ -1,274 +0,0 @@ -CancellablePromise | @wailsio/runtime

                    Class CancellablePromise<T>

                    A promise with an attached method for cancelling long-running operations (see CancellablePromise#cancel). -Cancellation can optionally be bound to an AbortSignal -for better composability (see CancellablePromise#cancelOn).

                    -

                    Cancelling a pending promise will result in an immediate rejection -with an instance of CancelError as reason, -but whoever started the promise will be responsible -for actually aborting the underlying operation. -To this purpose, the constructor and all chaining methods -accept optional cancellation callbacks.

                    -

                    If a CancellablePromise still resolves after having been cancelled, -the result will be discarded. If it rejects, the reason -will be reported as an unhandled rejection, -wrapped in a CancelledRejectionError instance. -To facilitate the handling of cancellation requests, -cancelled CancellablePromises will not report unhandled CancelErrors -whose cause field is the same as the one with which the current promise was cancelled.

                    -

                    All usual promise methods are defined and return a CancellablePromise -whose cancel method will cancel the parent operation as well, propagating the cancellation reason -upwards through promise chains. -Conversely, cancelling a promise will not automatically cancel dependent promises downstream:

                    -
                    let root = new CancellablePromise((resolve, reject) => { ... });
                    let child1 = root.then(() => { ... });
                    let child2 = child1.then(() => { ... });
                    let child3 = root.catch(() => { ... });
                    child1.cancel(); // Cancels child1 and root, but not child2 or child3 -
                    - -

                    Cancelling a promise that has already settled is safe and has no consequence.

                    -

                    The cancel method returns a promise that always fulfills -after the whole chain has processed the cancel request -and all attached callbacks up to that moment have run.

                    -

                    All ES2024 promise methods (static and instance) are defined on CancellablePromise, -but actual availability may vary with OS/webview version.

                    -

                    In line with the proposal at https://github.com/tc39/proposal-rm-builtin-subclassing, -CancellablePromise does not support transparent subclassing. -Extenders should take care to provide their own method implementations. -This might be reconsidered in case the proposal is retired.

                    -

                    CancellablePromise is a wrapper around the DOM Promise object -and is compliant with the Promises/A+ specification -(it passes the compliance suite) -if so is the underlying implementation.

                    -

                    Type Parameters

                    • T

                    Hierarchy

                    Implements

                    Constructors

                    • Creates a new CancellablePromise.

                      -

                      Type Parameters

                      • T

                      Parameters

                      • executor: CancellablePromiseExecutor<T>

                        A callback used to initialize the promise. This callback is passed two arguments: -a resolve callback used to resolve the promise with a value -or the result of another promise (possibly cancellable), -and a reject callback used to reject the promise with a provided reason or error. -If the value provided to the resolve callback is a thenable and cancellable object -(it has a then and a cancel method), -cancellation requests will be forwarded to that object and the oncancelled will not be invoked anymore. -If any one of the two callbacks is called after the promise has been cancelled, -the provided values will be cancelled and resolved as usual, -but their results will be discarded. -However, if the resolution process ultimately ends up in a rejection -that is not due to cancellation, the rejection reason -will be wrapped in a CancelledRejectionError -and bubbled up as an unhandled rejection.

                        -
                      • Optionaloncancelled: CancellablePromiseCanceller

                        It is the caller's responsibility to ensure that any operation -started by the executor is properly halted upon cancellation. -This optional callback can be used to that purpose. -It will be called synchronously with a cancellation cause -when cancellation is requested, after the promise has already rejected -with a CancelError, but before -any then/catch/finally callback runs. -If the callback returns a thenable, the promise returned from cancel -will only fulfill after the former has settled. -Unhandled exceptions or rejections from the callback will be wrapped -in a CancelledRejectionError and bubbled up as unhandled rejections. -If the resolve callback is called before cancellation with a cancellable promise, -cancellation requests on this promise will be diverted to that promise, -and the original oncancelled callback will be discarded.

                        -

                      Returns CancellablePromise<T>

                    Properties

                    "[toStringTag]": string

                    Methods

                    • Cancels immediately the execution of the operation associated with this promise. -The promise rejects with a CancelError instance as reason, -with the CancelError#cause property set to the given argument, if any.

                      -

                      Has no effect if called after the promise has already settled; -repeated calls in particular are safe, but only the first one -will set the cancellation cause.

                      -

                      The CancelError exception need not be handled explicitly on the promises that are being cancelled: -cancelling a promise with no attached rejection handler does not trigger an unhandled rejection event. -Therefore, the following idioms are all equally correct:

                      -
                      new CancellablePromise((resolve, reject) => { ... }).cancel();
                      new CancellablePromise((resolve, reject) => { ... }).then(...).cancel();
                      new CancellablePromise((resolve, reject) => { ... }).then(...).catch(...).cancel(); -
                      - -

                      Whenever some cancelled promise in a chain rejects with a CancelError -with the same cancellation cause as itself, the error will be discarded silently. -However, the CancelError will still be delivered to all attached rejection handlers -added by then and related methods:

                      -
                      let cancellable = new CancellablePromise((resolve, reject) => { ... });
                      cancellable.then(() => { ... }).catch(console.log);
                      cancellable.cancel(); // A CancelError is printed to the console. -
                      - -

                      If the CancelError is not handled downstream by the time it reaches -a non-cancelled promise, it will trigger an unhandled rejection event, -just like normal rejections would:

                      -
                      let cancellable = new CancellablePromise((resolve, reject) => { ... });
                      let chained = cancellable.then(() => { ... }).then(() => { ... }); // No catch...
                      cancellable.cancel(); // Unhandled rejection event on chained! -
                      - -

                      Therefore, it is important to either cancel whole promise chains from their tail, -as shown in the correct idioms above, or take care of handling errors everywhere.

                      -

                      Parameters

                      • Optionalcause: any

                      Returns CancellablePromise<void>

                      A cancellable promise that fulfills after the cancel callback (if any) -and all handlers attached up to the call to cancel have run. -If the cancel callback returns a thenable, the promise returned by cancel -will also wait for that thenable to settle. -This enables callers to wait for the cancelled operation to terminate -without being forced to handle potential errors at the call site.

                      -
                      cancellable.cancel().then(() => {
                      // Cleanup finished, it's safe to do something else.
                      }, (err) => {
                      // Unreachable: the promise returned from cancel will never reject.
                      }); -
                      - -

                      Note that the returned promise will not handle implicitly any rejection -that might have occurred already in the cancelled chain. -It will just track whether registered handlers have been executed or not. -Therefore, unhandled rejections will never be silently handled by calling cancel.

                      -
                    • Binds promise cancellation to the abort event of the given AbortSignal. -If the signal has already aborted, the promise will be cancelled immediately. -When either condition is verified, the cancellation cause will be set -to the signal's abort reason (see AbortSignal.reason).

                      -

                      Has no effect if called (or if the signal aborts) after the promise has already settled. -Only the first signal to abort will set the cancellation cause.

                      -

                      For more details about the cancellation process, -see cancel and the CancellablePromise constructor.

                      -

                      This method enables awaiting cancellable promises without having -to store them for future cancellation, e.g.:

                      -
                      await longRunningOperation().cancelOn(signal);
                      -
                      - -

                      instead of:

                      -
                      let promiseToBeCancelled = longRunningOperation();
                      await promiseToBeCancelled; -
                      - -

                      Parameters

                      Returns CancellablePromise<T>

                      This promise, for method chaining.

                      -
                    • Attaches a callback for only the rejection of the Promise.

                      -

                      The optional oncancelled argument will be invoked when the returned promise is cancelled, -with the same semantics as the oncancelled argument of the constructor. -When the parent promise rejects or is cancelled, the onrejected callback will run, -even after the returned promise has been cancelled: -in that case, should it reject or throw, the reason will be wrapped -in a CancelledRejectionError and bubbled up as an unhandled rejection.

                      -

                      It is equivalent to

                      -
                      cancellablePromise.then(undefined, onrejected, oncancelled);
                      -
                      - -

                      and the same caveats apply.

                      -

                      Type Parameters

                      • TResult = never

                      Parameters

                      Returns CancellablePromise<T | TResult>

                      A Promise for the completion of the callback. -Cancellation requests on the returned promise -will propagate up the chain to the parent promise, -but not in the other direction.

                      -

                      The promise returned from cancel will fulfill only after all attached handlers -up the entire promise chain have been run.

                      -

                      If onrejected returns a cancellable promise, -cancellation requests will be diverted to it, -and the specified oncancelled callback will be discarded. -See then for more details.

                      -
                    • Attaches a callback that is invoked when the CancellablePromise is settled (fulfilled or rejected). The -resolved value cannot be accessed or modified from the callback. -The returned promise will settle in the same state as the original one -after the provided callback has completed execution, -unless the callback throws or returns a rejecting promise, -in which case the returned promise will reject as well.

                      -

                      The optional oncancelled argument will be invoked when the returned promise is cancelled, -with the same semantics as the oncancelled argument of the constructor. -Once the parent promise settles, the onfinally callback will run, -even after the returned promise has been cancelled: -in that case, should it reject or throw, the reason will be wrapped -in a CancelledRejectionError and bubbled up as an unhandled rejection.

                      -

                      This method is implemented in terms of then and the same caveats apply. -It is polyfilled, hence available in every OS/webview version.

                      -

                      Parameters

                      Returns CancellablePromise<T>

                      A Promise for the completion of the callback. -Cancellation requests on the returned promise -will propagate up the chain to the parent promise, -but not in the other direction.

                      -

                      The promise returned from cancel will fulfill only after all attached handlers -up the entire promise chain have been run.

                      -

                      If onfinally returns a cancellable promise, -cancellation requests will be diverted to it, -and the specified oncancelled callback will be discarded. -See then for more details.

                      -
                    • Attaches callbacks for the resolution and/or rejection of the CancellablePromise.

                      -

                      The optional oncancelled argument will be invoked when the returned promise is cancelled, -with the same semantics as the oncancelled argument of the constructor. -When the parent promise rejects or is cancelled, the onrejected callback will run, -even after the returned promise has been cancelled: -in that case, should it reject or throw, the reason will be wrapped -in a CancelledRejectionError and bubbled up as an unhandled rejection.

                      -

                      Type Parameters

                      • TResult1 = T
                      • TResult2 = never

                      Parameters

                      Returns CancellablePromise<TResult1 | TResult2>

                      A CancellablePromise for the completion of whichever callback is executed. -The returned promise is hooked up to propagate cancellation requests up the chain, but not down:

                      -
                        -
                      • if the parent promise is cancelled, the onrejected handler will be invoked with a CancelError -and the returned promise will resolve regularly with its result;
                      • -
                      • conversely, if the returned promise is cancelled, the parent promise is cancelled too; -the onrejected handler will still be invoked with the parent's CancelError, -but its result will be discarded -and the returned promise will reject with a CancelError as well.
                      • -
                      -

                      The promise returned from cancel will fulfill only after all attached handlers -up the entire promise chain have been run.

                      -

                      If either callback returns a cancellable promise, -cancellation requests will be diverted to it, -and the specified oncancelled callback will be discarded.

                      -
                    • Takes a callback of any kind (returns or throws, synchronously or asynchronously) and wraps its result -in a Promise.

                      -

                      Type Parameters

                      • T
                      • U extends unknown[]

                      Parameters

                      • callbackFn: (...args: U) => T | PromiseLike<T>

                        A function that is called synchronously. It can do anything: either return -a value, throw an error, or return a promise.

                        -
                      • ...args: U

                        Additional arguments, that will be passed to the callback.

                        -

                      Returns Promise<Awaited<T>>

                      A Promise that is:

                      -
                        -
                      • Already fulfilled, if the callback synchronously returns a value.
                      • -
                      • Already rejected, if the callback synchronously throws an error.
                      • -
                      • Asynchronously fulfilled or rejected, if the callback returns a promise.
                      • -
                      -

                    Static Methods

                    • Creates a CancellablePromise that is resolved with an array of results -when all of the provided Promises resolve, or rejected when any Promise is rejected.

                      -

                      Every one of the provided objects that is a thenable and cancellable object -will be cancelled when the returned promise is cancelled, with the same cause.

                      -

                      Type Parameters

                      • T

                      Parameters

                      Returns CancellablePromise<Awaited<T>[]>

                    • Creates a Promise that is resolved with an array of results when all of the provided Promises -resolve, or rejected when any Promise is rejected.

                      -

                      Type Parameters

                      • T extends [] | readonly unknown[]

                      Parameters

                      • values: T

                        An array of Promises.

                        -

                      Returns CancellablePromise<
                          { -readonly [P in string
                          | number
                          | symbol]: Awaited<T[P<P>]> },
                      >

                      A new Promise.

                      -
                    • The any function returns a promise that is fulfilled by the first given promise to be fulfilled, -or rejected with an AggregateError containing an array of rejection reasons -if all of the given promises are rejected. -It resolves all elements of the passed iterable to promises as it runs this algorithm.

                      -

                      Every one of the provided objects that is a thenable and cancellable object -will be cancelled when the returned promise is cancelled, with the same cause.

                      -

                      Type Parameters

                      • T

                      Parameters

                      Returns CancellablePromise<Awaited<T>>

                    • The any function returns a promise that is fulfilled by the first given promise to be fulfilled, or rejected with an AggregateError containing an array of rejection reasons if all of the given promises are rejected. It resolves all elements of the passed iterable to promises as it runs this algorithm.

                      -

                      Type Parameters

                      • T extends [] | readonly unknown[]

                      Parameters

                      • values: T

                        An array or iterable of Promises.

                        -

                      Returns CancellablePromise<Awaited<T[number]>>

                      A new Promise.

                      -
                    • Creates a new CancellablePromise that resolves after the specified timeout. -The returned promise can be cancelled without consequences.

                      -

                      Parameters

                      • milliseconds: number

                      Returns CancellablePromise<void>

                    • Creates a new CancellablePromise that resolves after -the specified timeout, with the provided value. -The returned promise can be cancelled without consequences.

                      -

                      Type Parameters

                      • T

                      Parameters

                      • milliseconds: number
                      • value: T

                      Returns CancellablePromise<T>

                    • Creates a new CancellablePromise that cancels -after the specified timeout, with the provided cause.

                      -

                      If the AbortSignal.timeout factory method is available, -it is used to base the timeout on active time rather than elapsed time. -Otherwise, timeout falls back to setTimeout.

                      -

                      Type Parameters

                      • T = never

                      Parameters

                      • milliseconds: number
                      • Optionalcause: any

                      Returns CancellablePromise<T>

                    diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/docs/classes/CancelledRejectionError.html b/v3/internal/runtime/desktop/@wailsio/runtime/docs/classes/CancelledRejectionError.html deleted file mode 100644 index 87b2951e8..000000000 --- a/v3/internal/runtime/desktop/@wailsio/runtime/docs/classes/CancelledRejectionError.html +++ /dev/null @@ -1,21 +0,0 @@ -CancelledRejectionError | @wailsio/runtime

                    Class CancelledRejectionError

                    Exception class that will be reported as an unhandled rejection -in case a CancellablePromise rejects after being cancelled, -or when the oncancelled callback throws or rejects.

                    -

                    The value of the name property is the string "CancelledRejectionError". -The value of the cause property is the reason the promise rejected with.

                    -

                    Because the original promise was cancelled, -a wrapper promise will be passed to the unhandled rejection listener instead. -The promise property holds a reference to the original promise.

                    -

                    Hierarchy

                    • Error
                      • CancelledRejectionError

                    Constructors

                    Properties

                    Constructors

                    • Constructs a new CancelledRejectionError instance.

                      -

                      Parameters

                      • promise: CancellablePromise<unknown>

                        The promise that caused the error originally.

                        -
                      • Optionalreason: any

                        The rejection reason.

                        -
                      • Optionalinfo: string

                        An optional informative message specifying the circumstances in which the error was thrown. -Defaults to the string "Unhandled rejection in cancelled promise.".

                        -

                      Returns CancelledRejectionError

                    Properties

                    cause?: unknown
                    message: string
                    name: string
                    promise: CancellablePromise<unknown>

                    Holds a reference to the promise that was cancelled and then rejected.

                    -
                    stack?: string
                    diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/docs/classes/Events.WailsEvent.html b/v3/internal/runtime/desktop/@wailsio/runtime/docs/classes/Events.WailsEvent.html deleted file mode 100644 index d1a7924fb..000000000 --- a/v3/internal/runtime/desktop/@wailsio/runtime/docs/classes/Events.WailsEvent.html +++ /dev/null @@ -1,10 +0,0 @@ -WailsEvent | @wailsio/runtime

                    Represents a system event or a custom event emitted through wails-provided facilities.

                    -

                    Type Parameters

                    Constructors

                    Properties

                    Constructors

                    Properties

                    Optional data associated with the emitted event.

                    -
                    name: E

                    The name of the event.

                    -
                    sender?: string

                    Name of the originating window. Omitted for application events. -Will be overridden if set manually.

                    -
                    diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/docs/classes/_internal_.Window.html b/v3/internal/runtime/desktop/@wailsio/runtime/docs/classes/_internal_.Window.html deleted file mode 100644 index af1191e71..000000000 --- a/v3/internal/runtime/desktop/@wailsio/runtime/docs/classes/_internal_.Window.html +++ /dev/null @@ -1,145 +0,0 @@ -Window | @wailsio/runtime

                    Methods

                    • Gets the specified window.

                      -

                      Parameters

                      • name: string

                        The name of the window to get.

                        -

                      Returns Window

                      The corresponding window object.

                      -
                    • Handles file drops originating from platform-specific code (e.g., macOS/Linux native drag-and-drop). -Gathers information about the drop target element and sends it back to the Go backend.

                      -

                      Parameters

                      • filenames: string[]

                        An array of file paths (strings) that were dropped.

                        -
                      • x: number

                        The x-coordinate of the drop event (CSS pixels).

                        -
                      • y: number

                        The y-coordinate of the drop event (CSS pixels).

                        -

                      Returns void

                    • Returns true if the window is focused.

                      -

                      Returns Promise<boolean>

                      Whether the window is currently focused.

                      -
                    • Returns true if the window is fullscreen.

                      -

                      Returns Promise<boolean>

                      Whether the window is currently fullscreen.

                      -
                    • Returns true if the window is maximised.

                      -

                      Returns Promise<boolean>

                      Whether the window is currently maximised.

                      -
                    • Returns true if the window is minimised.

                      -

                      Returns Promise<boolean>

                      Whether the window is currently minimised.

                      -
                    • Returns true if the window is resizable.

                      -

                      Returns Promise<boolean>

                      Whether the window is currently resizable.

                      -
                    • Restores the window to its previous state if it was previously minimised, maximised or fullscreen.

                      -

                      Returns Promise<void>

                    • Sets the window to be always on top.

                      -

                      Parameters

                      • alwaysOnTop: boolean

                        Whether the window should stay on top.

                        -

                      Returns Promise<void>

                    • Sets the background colour of the window.

                      -

                      Parameters

                      • r: number

                        The desired red component of the window background.

                        -
                      • g: number

                        The desired green component of the window background.

                        -
                      • b: number

                        The desired blue component of the window background.

                        -
                      • a: number

                        The desired alpha component of the window background.

                        -

                      Returns Promise<void>

                    • Removes the window frame and title bar.

                      -

                      Parameters

                      • frameless: boolean

                        Whether the window should be frameless.

                        -

                      Returns Promise<void>

                    • Disables the system fullscreen button.

                      -

                      Parameters

                      • enabled: boolean

                        Whether the fullscreen button should be enabled.

                        -

                      Returns Promise<void>

                    • Sets the maximum size of the window.

                      -

                      Parameters

                      • width: number

                        The desired maximum width of the window.

                        -
                      • height: number

                        The desired maximum height of the window.

                        -

                      Returns Promise<void>

                    • Sets the minimum size of the window.

                      -

                      Parameters

                      • width: number

                        The desired minimum width of the window.

                        -
                      • height: number

                        The desired minimum height of the window.

                        -

                      Returns Promise<void>

                    • Sets the absolute position of the window.

                      -

                      Parameters

                      • x: number

                        The desired horizontal absolute position of the window.

                        -
                      • y: number

                        The desired vertical absolute position of the window.

                        -

                      Returns Promise<void>

                    • Sets the relative position of the window to the screen.

                      -

                      Parameters

                      • x: number

                        The desired horizontal relative position of the window.

                        -
                      • y: number

                        The desired vertical relative position of the window.

                        -

                      Returns Promise<void>

                    • Sets whether the window is resizable.

                      -

                      Parameters

                      • resizable: boolean

                        Whether the window should be resizable.

                        -

                      Returns Promise<void>

                    • Sets the size of the window.

                      -

                      Parameters

                      • width: number

                        The desired width of the window.

                        -
                      • height: number

                        The desired height of the window.

                        -

                      Returns Promise<void>

                    • Sets the title of the window.

                      -

                      Parameters

                      • title: string

                        The desired title of the window.

                        -

                      Returns Promise<void>

                    • Sets the zoom level of the window.

                      -

                      Parameters

                      • zoom: number

                        The desired zoom level.

                        -

                      Returns Promise<void>

                    diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/docs/functions/Application.Hide.html b/v3/internal/runtime/desktop/@wailsio/runtime/docs/functions/Application.Hide.html deleted file mode 100644 index 4828abe86..000000000 --- a/v3/internal/runtime/desktop/@wailsio/runtime/docs/functions/Application.Hide.html +++ /dev/null @@ -1,2 +0,0 @@ -Hide | @wailsio/runtime
                    diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/docs/functions/Application.Quit.html b/v3/internal/runtime/desktop/@wailsio/runtime/docs/functions/Application.Quit.html deleted file mode 100644 index bb3ec1cb1..000000000 --- a/v3/internal/runtime/desktop/@wailsio/runtime/docs/functions/Application.Quit.html +++ /dev/null @@ -1,2 +0,0 @@ -Quit | @wailsio/runtime
                    diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/docs/functions/Application.Show.html b/v3/internal/runtime/desktop/@wailsio/runtime/docs/functions/Application.Show.html deleted file mode 100644 index 83e6d02be..000000000 --- a/v3/internal/runtime/desktop/@wailsio/runtime/docs/functions/Application.Show.html +++ /dev/null @@ -1,2 +0,0 @@ -Show | @wailsio/runtime
                    diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/docs/functions/Browser.OpenURL.html b/v3/internal/runtime/desktop/@wailsio/runtime/docs/functions/Browser.OpenURL.html deleted file mode 100644 index ee1fc3800..000000000 --- a/v3/internal/runtime/desktop/@wailsio/runtime/docs/functions/Browser.OpenURL.html +++ /dev/null @@ -1,3 +0,0 @@ -OpenURL | @wailsio/runtime
                    diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/docs/functions/Call.ByID.html b/v3/internal/runtime/desktop/@wailsio/runtime/docs/functions/Call.ByID.html deleted file mode 100644 index 0b087b923..000000000 --- a/v3/internal/runtime/desktop/@wailsio/runtime/docs/functions/Call.ByID.html +++ /dev/null @@ -1,6 +0,0 @@ -ByID | @wailsio/runtime
                    • Calls a method by its numeric ID with the specified arguments. -See Call for details.

                      -

                      Parameters

                      • methodID: number

                        The ID of the method to call.

                        -
                      • ...args: any[]

                        The arguments to pass to the method.

                        -

                      Returns CancellablePromise<any>

                      The result of the method call.

                      -
                    diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/docs/functions/Call.ByName.html b/v3/internal/runtime/desktop/@wailsio/runtime/docs/functions/Call.ByName.html deleted file mode 100644 index e8e1d3202..000000000 --- a/v3/internal/runtime/desktop/@wailsio/runtime/docs/functions/Call.ByName.html +++ /dev/null @@ -1,6 +0,0 @@ -ByName | @wailsio/runtime
                    • Calls a bound method by name with the specified arguments. -See Call for details.

                      -

                      Parameters

                      • methodName: string

                        The name of the method in the format 'package.struct.method'.

                        -
                      • ...args: any[]

                        The arguments to pass to the method.

                        -

                      Returns CancellablePromise<any>

                      The result of the method call.

                      -
                    diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/docs/functions/Call.Call.html b/v3/internal/runtime/desktop/@wailsio/runtime/docs/functions/Call.Call.html deleted file mode 100644 index 0be8d62e3..000000000 --- a/v3/internal/runtime/desktop/@wailsio/runtime/docs/functions/Call.Call.html +++ /dev/null @@ -1,9 +0,0 @@ -Call | @wailsio/runtime
                    • Call a bound method according to the given call options.

                      -

                      In case of failure, the returned promise will reject with an exception -among ReferenceError (unknown method), TypeError (wrong argument count or type), -RuntimeError (method returned an error), or other (network or internal errors). -The exception might have a "cause" field with the value returned -by the application- or service-level error marshaling functions.

                      -

                      Parameters

                      Returns CancellablePromise<any>

                      The result of the call.

                      -
                    diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/docs/functions/Clipboard.SetText.html b/v3/internal/runtime/desktop/@wailsio/runtime/docs/functions/Clipboard.SetText.html deleted file mode 100644 index 681208368..000000000 --- a/v3/internal/runtime/desktop/@wailsio/runtime/docs/functions/Clipboard.SetText.html +++ /dev/null @@ -1,4 +0,0 @@ -SetText | @wailsio/runtime
                    • Sets the text to the Clipboard.

                      -

                      Parameters

                      • text: string

                        The text to be set to the Clipboard.

                        -

                      Returns Promise<void>

                      A Promise that resolves when the operation is successful.

                      -
                    diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/docs/functions/Clipboard.Text.html b/v3/internal/runtime/desktop/@wailsio/runtime/docs/functions/Clipboard.Text.html deleted file mode 100644 index 4e0514fe5..000000000 --- a/v3/internal/runtime/desktop/@wailsio/runtime/docs/functions/Clipboard.Text.html +++ /dev/null @@ -1,3 +0,0 @@ -Text | @wailsio/runtime
                    diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/docs/functions/Dialogs.Error.html b/v3/internal/runtime/desktop/@wailsio/runtime/docs/functions/Dialogs.Error.html deleted file mode 100644 index 3d47a092f..000000000 --- a/v3/internal/runtime/desktop/@wailsio/runtime/docs/functions/Dialogs.Error.html +++ /dev/null @@ -1,4 +0,0 @@ -Error | @wailsio/runtime
                    diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/docs/functions/Dialogs.Info.html b/v3/internal/runtime/desktop/@wailsio/runtime/docs/functions/Dialogs.Info.html deleted file mode 100644 index 554890e04..000000000 --- a/v3/internal/runtime/desktop/@wailsio/runtime/docs/functions/Dialogs.Info.html +++ /dev/null @@ -1,4 +0,0 @@ -Info | @wailsio/runtime
                    diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/docs/functions/Dialogs.OpenFile.html b/v3/internal/runtime/desktop/@wailsio/runtime/docs/functions/Dialogs.OpenFile.html deleted file mode 100644 index aeee248b4..000000000 --- a/v3/internal/runtime/desktop/@wailsio/runtime/docs/functions/Dialogs.OpenFile.html +++ /dev/null @@ -1,10 +0,0 @@ -OpenFile | @wailsio/runtime
                    • Presents a file selection dialog to pick one or more files to open.

                      -

                      Parameters

                      Returns Promise<string[]>

                      Selected file or list of files, or a blank string/empty list if no file has been selected.

                      -
                    • Presents a file selection dialog to pick one or more files to open.

                      -

                      Parameters

                      Returns Promise<string>

                      Selected file or list of files, or a blank string/empty list if no file has been selected.

                      -
                    • Presents a file selection dialog to pick one or more files to open.

                      -

                      Parameters

                      Returns Promise<string | string[]>

                      Selected file or list of files, or a blank string/empty list if no file has been selected.

                      -
                    diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/docs/functions/Dialogs.Question.html b/v3/internal/runtime/desktop/@wailsio/runtime/docs/functions/Dialogs.Question.html deleted file mode 100644 index 220b94548..000000000 --- a/v3/internal/runtime/desktop/@wailsio/runtime/docs/functions/Dialogs.Question.html +++ /dev/null @@ -1,4 +0,0 @@ -Question | @wailsio/runtime
                    diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/docs/functions/Dialogs.SaveFile.html b/v3/internal/runtime/desktop/@wailsio/runtime/docs/functions/Dialogs.SaveFile.html deleted file mode 100644 index 38321e952..000000000 --- a/v3/internal/runtime/desktop/@wailsio/runtime/docs/functions/Dialogs.SaveFile.html +++ /dev/null @@ -1,4 +0,0 @@ -SaveFile | @wailsio/runtime
                    diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/docs/functions/Dialogs.Warning.html b/v3/internal/runtime/desktop/@wailsio/runtime/docs/functions/Dialogs.Warning.html deleted file mode 100644 index 01d600f5c..000000000 --- a/v3/internal/runtime/desktop/@wailsio/runtime/docs/functions/Dialogs.Warning.html +++ /dev/null @@ -1,4 +0,0 @@ -Warning | @wailsio/runtime
                    diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/docs/functions/Events.Emit.html b/v3/internal/runtime/desktop/@wailsio/runtime/docs/functions/Events.Emit.html deleted file mode 100644 index f7598d66a..000000000 --- a/v3/internal/runtime/desktop/@wailsio/runtime/docs/functions/Events.Emit.html +++ /dev/null @@ -1,8 +0,0 @@ -Emit | @wailsio/runtime
                    • Emits an event.

                      -

                      Type Parameters

                      • E extends string & {} = string & {}

                      Parameters

                      • name: E

                        The name of the event to emit

                        -
                      • data: WailsEventData<E>

                        The data that will be sent with the event

                        -

                      Returns Promise<boolean>

                      A promise that will be fulfilled once the event has been emitted. Resolves to true if the event was cancelled.

                      -
                    • Emits an event.

                      -

                      Type Parameters

                      • E extends string & {} = string & {}

                      Parameters

                      • name: WailsEventData<E> extends null | void ? E : never

                        The name of the event to emit

                        -

                      Returns Promise<boolean>

                      A promise that will be fulfilled once the event has been emitted. Resolves to true if the event was cancelled.

                      -
                    diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/docs/functions/Events.Off.html b/v3/internal/runtime/desktop/@wailsio/runtime/docs/functions/Events.Off.html deleted file mode 100644 index c473825f9..000000000 --- a/v3/internal/runtime/desktop/@wailsio/runtime/docs/functions/Events.Off.html +++ /dev/null @@ -1,3 +0,0 @@ -Off | @wailsio/runtime
                    • Removes event listeners for the specified event names.

                      -

                      Parameters

                      • ...eventNames: [string & {}, ...(string & {})[]]

                        The name of the events to remove listeners for.

                        -

                      Returns void

                    diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/docs/functions/Events.OffAll.html b/v3/internal/runtime/desktop/@wailsio/runtime/docs/functions/Events.OffAll.html deleted file mode 100644 index 1ef26eee0..000000000 --- a/v3/internal/runtime/desktop/@wailsio/runtime/docs/functions/Events.OffAll.html +++ /dev/null @@ -1,2 +0,0 @@ -OffAll | @wailsio/runtime
                    diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/docs/functions/Events.On.html b/v3/internal/runtime/desktop/@wailsio/runtime/docs/functions/Events.On.html deleted file mode 100644 index efa47b7d7..000000000 --- a/v3/internal/runtime/desktop/@wailsio/runtime/docs/functions/Events.On.html +++ /dev/null @@ -1,5 +0,0 @@ -On | @wailsio/runtime
                    • Registers a callback function to be executed when the specified event occurs.

                      -

                      Type Parameters

                      • E extends string & {} = string & {}

                      Parameters

                      • eventName: E

                        The name of the event to register the callback for.

                        -
                      • callback: WailsEventCallback<E>

                        The callback function to be called when the event is triggered.

                        -

                      Returns () => void

                      A function that, when called, will unregister the callback from the event.

                      -
                    diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/docs/functions/Events.OnMultiple.html b/v3/internal/runtime/desktop/@wailsio/runtime/docs/functions/Events.OnMultiple.html deleted file mode 100644 index 138294c31..000000000 --- a/v3/internal/runtime/desktop/@wailsio/runtime/docs/functions/Events.OnMultiple.html +++ /dev/null @@ -1,6 +0,0 @@ -OnMultiple | @wailsio/runtime
                    • Register a callback function to be called multiple times for a specific event.

                      -

                      Type Parameters

                      • E extends string & {} = string & {}

                      Parameters

                      • eventName: E

                        The name of the event to register the callback for.

                        -
                      • callback: WailsEventCallback<E>

                        The callback function to be called when the event is triggered.

                        -
                      • maxCallbacks: number

                        The maximum number of times the callback can be called for the event. Once the maximum number is reached, the callback will no longer be called.

                        -

                      Returns () => void

                      A function that, when called, will unregister the callback from the event.

                      -
                    diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/docs/functions/Events.Once.html b/v3/internal/runtime/desktop/@wailsio/runtime/docs/functions/Events.Once.html deleted file mode 100644 index 3db37510e..000000000 --- a/v3/internal/runtime/desktop/@wailsio/runtime/docs/functions/Events.Once.html +++ /dev/null @@ -1,5 +0,0 @@ -Once | @wailsio/runtime
                    • Registers a callback function to be executed only once for the specified event.

                      -

                      Type Parameters

                      • E extends string & {} = string & {}

                      Parameters

                      • eventName: E

                        The name of the event to register the callback for.

                        -
                      • callback: WailsEventCallback<E>

                        The callback function to be called when the event is triggered.

                        -

                      Returns () => void

                      A function that, when called, will unregister the callback from the event.

                      -
                    diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/docs/functions/Flags.GetFlag.html b/v3/internal/runtime/desktop/@wailsio/runtime/docs/functions/Flags.GetFlag.html deleted file mode 100644 index 2c56d0f1b..000000000 --- a/v3/internal/runtime/desktop/@wailsio/runtime/docs/functions/Flags.GetFlag.html +++ /dev/null @@ -1,4 +0,0 @@ -GetFlag | @wailsio/runtime
                    • Retrieves the value associated with the specified key from the flag map.

                      -

                      Parameters

                      • key: string

                        The key to retrieve the value for.

                        -

                      Returns any

                      The value associated with the specified key.

                      -
                    diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/docs/functions/IOS.Device.Info-1.html b/v3/internal/runtime/desktop/@wailsio/runtime/docs/functions/IOS.Device.Info-1.html deleted file mode 100644 index f9f97e0ed..000000000 --- a/v3/internal/runtime/desktop/@wailsio/runtime/docs/functions/IOS.Device.Info-1.html +++ /dev/null @@ -1 +0,0 @@ -Info | @wailsio/runtime
                    diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/docs/functions/IOS.Haptics.Impact.html b/v3/internal/runtime/desktop/@wailsio/runtime/docs/functions/IOS.Haptics.Impact.html deleted file mode 100644 index 0cd22171f..000000000 --- a/v3/internal/runtime/desktop/@wailsio/runtime/docs/functions/IOS.Haptics.Impact.html +++ /dev/null @@ -1 +0,0 @@ -Impact | @wailsio/runtime
                    diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/docs/functions/Screens.GetAll.html b/v3/internal/runtime/desktop/@wailsio/runtime/docs/functions/Screens.GetAll.html deleted file mode 100644 index 45d99bb96..000000000 --- a/v3/internal/runtime/desktop/@wailsio/runtime/docs/functions/Screens.GetAll.html +++ /dev/null @@ -1,3 +0,0 @@ -GetAll | @wailsio/runtime
                    diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/docs/functions/Screens.GetCurrent.html b/v3/internal/runtime/desktop/@wailsio/runtime/docs/functions/Screens.GetCurrent.html deleted file mode 100644 index b042871d5..000000000 --- a/v3/internal/runtime/desktop/@wailsio/runtime/docs/functions/Screens.GetCurrent.html +++ /dev/null @@ -1,3 +0,0 @@ -GetCurrent | @wailsio/runtime
                    diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/docs/functions/Screens.GetPrimary.html b/v3/internal/runtime/desktop/@wailsio/runtime/docs/functions/Screens.GetPrimary.html deleted file mode 100644 index a7bb9f8c7..000000000 --- a/v3/internal/runtime/desktop/@wailsio/runtime/docs/functions/Screens.GetPrimary.html +++ /dev/null @@ -1,3 +0,0 @@ -GetPrimary | @wailsio/runtime
                    diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/docs/functions/System.Capabilities.html b/v3/internal/runtime/desktop/@wailsio/runtime/docs/functions/System.Capabilities.html deleted file mode 100644 index d8b16a640..000000000 --- a/v3/internal/runtime/desktop/@wailsio/runtime/docs/functions/System.Capabilities.html +++ /dev/null @@ -1,3 +0,0 @@ -Capabilities | @wailsio/runtime
                    • Fetches the capabilities of the application from the server.

                      -

                      Returns Promise<Record<string, any>>

                      A promise that resolves to an object containing the capabilities.

                      -
                    diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/docs/functions/System.Environment.html b/v3/internal/runtime/desktop/@wailsio/runtime/docs/functions/System.Environment.html deleted file mode 100644 index 83e16aed1..000000000 --- a/v3/internal/runtime/desktop/@wailsio/runtime/docs/functions/System.Environment.html +++ /dev/null @@ -1,3 +0,0 @@ -Environment | @wailsio/runtime
                    diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/docs/functions/System.IsAMD64.html b/v3/internal/runtime/desktop/@wailsio/runtime/docs/functions/System.IsAMD64.html deleted file mode 100644 index 8463205b4..000000000 --- a/v3/internal/runtime/desktop/@wailsio/runtime/docs/functions/System.IsAMD64.html +++ /dev/null @@ -1,3 +0,0 @@ -IsAMD64 | @wailsio/runtime
                    • Checks if the current environment architecture is AMD64.

                      -

                      Returns boolean

                      True if the current environment architecture is AMD64, false otherwise.

                      -
                    diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/docs/functions/System.IsARM.html b/v3/internal/runtime/desktop/@wailsio/runtime/docs/functions/System.IsARM.html deleted file mode 100644 index 4e85b9117..000000000 --- a/v3/internal/runtime/desktop/@wailsio/runtime/docs/functions/System.IsARM.html +++ /dev/null @@ -1,3 +0,0 @@ -IsARM | @wailsio/runtime
                    • Checks if the current architecture is ARM.

                      -

                      Returns boolean

                      True if the current architecture is ARM, false otherwise.

                      -
                    diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/docs/functions/System.IsARM64.html b/v3/internal/runtime/desktop/@wailsio/runtime/docs/functions/System.IsARM64.html deleted file mode 100644 index 8b6f9a174..000000000 --- a/v3/internal/runtime/desktop/@wailsio/runtime/docs/functions/System.IsARM64.html +++ /dev/null @@ -1,3 +0,0 @@ -IsARM64 | @wailsio/runtime
                    • Checks if the current environment is ARM64 architecture.

                      -

                      Returns boolean

                      Returns true if the environment is ARM64 architecture, otherwise returns false.

                      -
                    diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/docs/functions/System.IsDarkMode.html b/v3/internal/runtime/desktop/@wailsio/runtime/docs/functions/System.IsDarkMode.html deleted file mode 100644 index 461dc8e2e..000000000 --- a/v3/internal/runtime/desktop/@wailsio/runtime/docs/functions/System.IsDarkMode.html +++ /dev/null @@ -1,3 +0,0 @@ -IsDarkMode | @wailsio/runtime
                    • Retrieves the system dark mode status.

                      -

                      Returns Promise<boolean>

                      A promise that resolves to a boolean value indicating if the system is in dark mode.

                      -
                    diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/docs/functions/System.IsDebug.html b/v3/internal/runtime/desktop/@wailsio/runtime/docs/functions/System.IsDebug.html deleted file mode 100644 index f9fa983df..000000000 --- a/v3/internal/runtime/desktop/@wailsio/runtime/docs/functions/System.IsDebug.html +++ /dev/null @@ -1,3 +0,0 @@ -IsDebug | @wailsio/runtime
                    • Reports whether the app is being run in debug mode.

                      -

                      Returns boolean

                      True if the app is being run in debug mode.

                      -
                    diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/docs/functions/System.IsLinux.html b/v3/internal/runtime/desktop/@wailsio/runtime/docs/functions/System.IsLinux.html deleted file mode 100644 index 98a91aeb2..000000000 --- a/v3/internal/runtime/desktop/@wailsio/runtime/docs/functions/System.IsLinux.html +++ /dev/null @@ -1,3 +0,0 @@ -IsLinux | @wailsio/runtime
                    • Checks if the current operating system is Linux.

                      -

                      Returns boolean

                      Returns true if the current operating system is Linux, false otherwise.

                      -
                    diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/docs/functions/System.IsMac.html b/v3/internal/runtime/desktop/@wailsio/runtime/docs/functions/System.IsMac.html deleted file mode 100644 index ec0843efc..000000000 --- a/v3/internal/runtime/desktop/@wailsio/runtime/docs/functions/System.IsMac.html +++ /dev/null @@ -1,3 +0,0 @@ -IsMac | @wailsio/runtime
                    • Checks if the current environment is a macOS operating system.

                      -

                      Returns boolean

                      True if the environment is macOS, false otherwise.

                      -
                    diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/docs/functions/System.IsWindows.html b/v3/internal/runtime/desktop/@wailsio/runtime/docs/functions/System.IsWindows.html deleted file mode 100644 index 658f88991..000000000 --- a/v3/internal/runtime/desktop/@wailsio/runtime/docs/functions/System.IsWindows.html +++ /dev/null @@ -1,3 +0,0 @@ -IsWindows | @wailsio/runtime
                    • Checks if the current operating system is Windows.

                      -

                      Returns boolean

                      True if the operating system is Windows, otherwise false.

                      -
                    diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/docs/functions/System.invoke.html b/v3/internal/runtime/desktop/@wailsio/runtime/docs/functions/System.invoke.html deleted file mode 100644 index 5a660b237..000000000 --- a/v3/internal/runtime/desktop/@wailsio/runtime/docs/functions/System.invoke.html +++ /dev/null @@ -1 +0,0 @@ -invoke | @wailsio/runtime
                    diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/docs/functions/WML.Enable.html b/v3/internal/runtime/desktop/@wailsio/runtime/docs/functions/WML.Enable.html deleted file mode 100644 index 46bffbe7d..000000000 --- a/v3/internal/runtime/desktop/@wailsio/runtime/docs/functions/WML.Enable.html +++ /dev/null @@ -1,2 +0,0 @@ -Enable | @wailsio/runtime
                    • Schedules an automatic reload of WML to be performed as soon as the document is fully loaded.

                      -

                      Returns void

                    diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/docs/functions/WML.Reload.html b/v3/internal/runtime/desktop/@wailsio/runtime/docs/functions/WML.Reload.html deleted file mode 100644 index 41478c379..000000000 --- a/v3/internal/runtime/desktop/@wailsio/runtime/docs/functions/WML.Reload.html +++ /dev/null @@ -1,2 +0,0 @@ -Reload | @wailsio/runtime
                    • Reloads the WML page by adding necessary event listeners and browser listeners.

                      -

                      Returns void

                    diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/docs/functions/getTransport.html b/v3/internal/runtime/desktop/@wailsio/runtime/docs/functions/getTransport.html deleted file mode 100644 index 76abb135d..000000000 --- a/v3/internal/runtime/desktop/@wailsio/runtime/docs/functions/getTransport.html +++ /dev/null @@ -1,2 +0,0 @@ -getTransport | @wailsio/runtime

                    Function getTransport

                    diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/docs/functions/loadOptionalScript.html b/v3/internal/runtime/desktop/@wailsio/runtime/docs/functions/loadOptionalScript.html deleted file mode 100644 index 54a710f6e..000000000 --- a/v3/internal/runtime/desktop/@wailsio/runtime/docs/functions/loadOptionalScript.html +++ /dev/null @@ -1,4 +0,0 @@ -loadOptionalScript | @wailsio/runtime

                    Function loadOptionalScript

                    • Loads a script from the given URL if it exists. -Uses HEAD request to check existence, then injects a script tag. -Silently ignores if the script doesn't exist.

                      -

                      Parameters

                      • url: string

                      Returns Promise<void>

                    diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/docs/functions/setTransport.html b/v3/internal/runtime/desktop/@wailsio/runtime/docs/functions/setTransport.html deleted file mode 100644 index 365927745..000000000 --- a/v3/internal/runtime/desktop/@wailsio/runtime/docs/functions/setTransport.html +++ /dev/null @@ -1,8 +0,0 @@ -setTransport | @wailsio/runtime

                    Function setTransport

                    • Set a custom transport for all Wails runtime calls. -This allows you to replace the default HTTP fetch transport with -WebSockets, custom protocols, or any other mechanism.

                      -

                      Parameters

                      Returns void

                      import { setTransport } from '/wails/runtime.js';

                      const wsTransport = {
                      call: async (objectID, method, windowName, args) => {
                      // Your WebSocket implementation
                      }
                      };

                      setTransport(wsTransport); -
                      - -
                    diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/docs/hierarchy.html b/v3/internal/runtime/desktop/@wailsio/runtime/docs/hierarchy.html deleted file mode 100644 index 5a5bbddc9..000000000 --- a/v3/internal/runtime/desktop/@wailsio/runtime/docs/hierarchy.html +++ /dev/null @@ -1 +0,0 @@ -@wailsio/runtime
                    diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/docs/index.html b/v3/internal/runtime/desktop/@wailsio/runtime/docs/index.html deleted file mode 100644 index 90f345405..000000000 --- a/v3/internal/runtime/desktop/@wailsio/runtime/docs/index.html +++ /dev/null @@ -1,7 +0,0 @@ -@wailsio/runtime

                    @wailsio/runtime

                    README

                    The index.js file in the compiled directory is the entrypoint for the runtime.js file that may be -loaded at runtime. This will add window.wails and window._wails to the global scope.

                    -

                    NOTE: It is preferable to use the @wailsio/runtime package to use the runtime.

                    -

                    ⚠️ Do not rebuild the runtime manually after updating TS code: -the CI pipeline will take care of this. -PRs that touch build artifacts will be blocked from merging.

                    -
                    diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/docs/interfaces/CancellablePromiseLike.html b/v3/internal/runtime/desktop/@wailsio/runtime/docs/interfaces/CancellablePromiseLike.html deleted file mode 100644 index e7a8ca6f3..000000000 --- a/v3/internal/runtime/desktop/@wailsio/runtime/docs/interfaces/CancellablePromiseLike.html +++ /dev/null @@ -1,3 +0,0 @@ -CancellablePromiseLike | @wailsio/runtime

                    Interface CancellablePromiseLike<T>

                    interface CancellablePromiseLike<T> {
                        cancel(cause?: any): void | PromiseLike<void>;
                        then<TResult1 = T, TResult2 = never>(
                            onfulfilled?:
                                | null
                                | (
                                    value: T,
                                ) => TResult1 | PromiseLike<TResult1> | CancellablePromiseLike<TResult1>,
                            onrejected?:
                                | null
                                | (
                                    reason: any,
                                ) => TResult2 | PromiseLike<TResult2> | CancellablePromiseLike<TResult2>,
                        ): CancellablePromiseLike<TResult1 | TResult2>;
                    }

                    Type Parameters

                    • T

                    Implemented by

                    Methods

                    Methods

                    diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/docs/interfaces/CancellablePromiseWithResolvers.html b/v3/internal/runtime/desktop/@wailsio/runtime/docs/interfaces/CancellablePromiseWithResolvers.html deleted file mode 100644 index 3bd162eae..000000000 --- a/v3/internal/runtime/desktop/@wailsio/runtime/docs/interfaces/CancellablePromiseWithResolvers.html +++ /dev/null @@ -1,7 +0,0 @@ -CancellablePromiseWithResolvers | @wailsio/runtime

                    Interface CancellablePromiseWithResolvers<T>

                    Wraps a cancellable promise along with its resolution methods. -The oncancelled field will be null initially but may be set to provide a custom cancellation function.

                    -
                    interface CancellablePromiseWithResolvers<T> {
                        oncancelled: null | CancellablePromiseCanceller;
                        promise: CancellablePromise<T>;
                        reject: CancellablePromiseRejector;
                        resolve: CancellablePromiseResolver<T>;
                    }

                    Type Parameters

                    • T

                    Properties

                    oncancelled: null | CancellablePromiseCanceller
                    diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/docs/interfaces/Dialogs.Button.html b/v3/internal/runtime/desktop/@wailsio/runtime/docs/interfaces/Dialogs.Button.html deleted file mode 100644 index 737759b54..000000000 --- a/v3/internal/runtime/desktop/@wailsio/runtime/docs/interfaces/Dialogs.Button.html +++ /dev/null @@ -1,7 +0,0 @@ -Button | @wailsio/runtime
                    interface Button {
                        IsCancel?: boolean;
                        IsDefault?: boolean;
                        Label?: string;
                    }

                    Properties

                    IsCancel?: boolean

                    True if the button should cancel an operation when clicked.

                    -
                    IsDefault?: boolean

                    True if the button should be the default action when the user presses enter.

                    -
                    Label?: string

                    Text that appears within the button.

                    -
                    diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/docs/interfaces/Dialogs.FileFilter.html b/v3/internal/runtime/desktop/@wailsio/runtime/docs/interfaces/Dialogs.FileFilter.html deleted file mode 100644 index 1297d44d7..000000000 --- a/v3/internal/runtime/desktop/@wailsio/runtime/docs/interfaces/Dialogs.FileFilter.html +++ /dev/null @@ -1,5 +0,0 @@ -FileFilter | @wailsio/runtime
                    interface FileFilter {
                        DisplayName?: string;
                        Pattern?: string;
                    }

                    Properties

                    Properties

                    DisplayName?: string

                    Display name for the filter, it could be "Text Files", "Images" etc.

                    -
                    Pattern?: string

                    Pattern to match for the filter, e.g. ".txt;.md" for text markdown files.

                    -
                    diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/docs/interfaces/Dialogs.MessageDialogOptions.html b/v3/internal/runtime/desktop/@wailsio/runtime/docs/interfaces/Dialogs.MessageDialogOptions.html deleted file mode 100644 index 8ea47f0ac..000000000 --- a/v3/internal/runtime/desktop/@wailsio/runtime/docs/interfaces/Dialogs.MessageDialogOptions.html +++ /dev/null @@ -1,9 +0,0 @@ -MessageDialogOptions | @wailsio/runtime

                    Interface MessageDialogOptions

                    interface MessageDialogOptions {
                        Buttons?: Button[];
                        Detached?: boolean;
                        Message?: string;
                        Title?: string;
                    }

                    Properties

                    Buttons?: Button[]

                    Array of button options to show in the dialog.

                    -
                    Detached?: boolean

                    True if the dialog should appear detached from the main window (if applicable).

                    -
                    Message?: string

                    The main message to show in the dialog.

                    -
                    Title?: string

                    The title of the dialog window.

                    -
                    diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/docs/interfaces/Dialogs.OpenFileDialogOptions.html b/v3/internal/runtime/desktop/@wailsio/runtime/docs/interfaces/Dialogs.OpenFileDialogOptions.html deleted file mode 100644 index b016009a2..000000000 --- a/v3/internal/runtime/desktop/@wailsio/runtime/docs/interfaces/Dialogs.OpenFileDialogOptions.html +++ /dev/null @@ -1,33 +0,0 @@ -OpenFileDialogOptions | @wailsio/runtime

                    Interface OpenFileDialogOptions

                    interface OpenFileDialogOptions {
                        AllowsMultipleSelection?: boolean;
                        AllowsOtherFiletypes?: boolean;
                        ButtonText?: string;
                        CanChooseDirectories?: boolean;
                        CanChooseFiles?: boolean;
                        CanCreateDirectories?: boolean;
                        CanSelectHiddenExtension?: boolean;
                        Detached?: boolean;
                        Directory?: string;
                        Filters?: FileFilter[];
                        HideExtension?: boolean;
                        Message?: string;
                        ResolvesAliases?: boolean;
                        ShowHiddenFiles?: boolean;
                        Title?: string;
                        TreatsFilePackagesAsDirectories?: boolean;
                    }

                    Properties

                    AllowsMultipleSelection?: boolean

                    Indicates if multiple selection is allowed.

                    -
                    AllowsOtherFiletypes?: boolean

                    Indicates if other file types are allowed.

                    -
                    ButtonText?: string

                    Text to display on the button.

                    -
                    CanChooseDirectories?: boolean

                    Indicates if directories can be chosen.

                    -
                    CanChooseFiles?: boolean

                    Indicates if files can be chosen.

                    -
                    CanCreateDirectories?: boolean

                    Indicates if directories can be created.

                    -
                    CanSelectHiddenExtension?: boolean

                    Indicates if hidden extensions can be selected.

                    -
                    Detached?: boolean

                    Indicates if the dialog should appear detached from the main window.

                    -
                    Directory?: string

                    Directory to open in the dialog.

                    -
                    Filters?: FileFilter[]

                    Array of file filters.

                    -
                    HideExtension?: boolean

                    Indicates if the extension should be hidden.

                    -
                    Message?: string

                    Message to show in the dialog.

                    -
                    ResolvesAliases?: boolean

                    Indicates if aliases should be resolved.

                    -
                    ShowHiddenFiles?: boolean

                    Indicates if hidden files should be shown.

                    -
                    Title?: string

                    Title of the dialog.

                    -
                    TreatsFilePackagesAsDirectories?: boolean

                    Indicates if file packages should be treated as directories.

                    -
                    diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/docs/interfaces/Dialogs.SaveFileDialogOptions.html b/v3/internal/runtime/desktop/@wailsio/runtime/docs/interfaces/Dialogs.SaveFileDialogOptions.html deleted file mode 100644 index bf1438ef1..000000000 --- a/v3/internal/runtime/desktop/@wailsio/runtime/docs/interfaces/Dialogs.SaveFileDialogOptions.html +++ /dev/null @@ -1,33 +0,0 @@ -SaveFileDialogOptions | @wailsio/runtime

                    Interface SaveFileDialogOptions

                    interface SaveFileDialogOptions {
                        AllowsOtherFiletypes?: boolean;
                        ButtonText?: string;
                        CanChooseDirectories?: boolean;
                        CanChooseFiles?: boolean;
                        CanCreateDirectories?: boolean;
                        CanSelectHiddenExtension?: boolean;
                        Detached?: boolean;
                        Directory?: string;
                        Filename?: string;
                        Filters?: FileFilter[];
                        HideExtension?: boolean;
                        Message?: string;
                        ResolvesAliases?: boolean;
                        ShowHiddenFiles?: boolean;
                        Title?: string;
                        TreatsFilePackagesAsDirectories?: boolean;
                    }

                    Properties

                    AllowsOtherFiletypes?: boolean

                    Indicates if other file types are allowed.

                    -
                    ButtonText?: string

                    Text to display on the button.

                    -
                    CanChooseDirectories?: boolean

                    Indicates if directories can be chosen.

                    -
                    CanChooseFiles?: boolean

                    Indicates if files can be chosen.

                    -
                    CanCreateDirectories?: boolean

                    Indicates if directories can be created.

                    -
                    CanSelectHiddenExtension?: boolean

                    Indicates if hidden extensions can be selected.

                    -
                    Detached?: boolean

                    Indicates if the dialog should appear detached from the main window.

                    -
                    Directory?: string

                    Directory to open in the dialog.

                    -
                    Filename?: string

                    Default filename to use in the dialog.

                    -
                    Filters?: FileFilter[]

                    Array of file filters.

                    -
                    HideExtension?: boolean

                    Indicates if the extension should be hidden.

                    -
                    Message?: string

                    Message to show in the dialog.

                    -
                    ResolvesAliases?: boolean

                    Indicates if aliases should be resolved.

                    -
                    ShowHiddenFiles?: boolean

                    Indicates if hidden files should be shown.

                    -
                    Title?: string

                    Title of the dialog.

                    -
                    TreatsFilePackagesAsDirectories?: boolean

                    Indicates if file packages should be treated as directories.

                    -
                    diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/docs/interfaces/Events.CustomEvents.html b/v3/internal/runtime/desktop/@wailsio/runtime/docs/interfaces/Events.CustomEvents.html deleted file mode 100644 index c02514b38..000000000 --- a/v3/internal/runtime/desktop/@wailsio/runtime/docs/interfaces/Events.CustomEvents.html +++ /dev/null @@ -1,3 +0,0 @@ -CustomEvents | @wailsio/runtime

                    A table of data types for all known events. -Will be monkey-patched by the binding generator.

                    -
                    diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/docs/interfaces/IOS.Device.Info.html b/v3/internal/runtime/desktop/@wailsio/runtime/docs/interfaces/IOS.Device.Info.html deleted file mode 100644 index 8e4739b95..000000000 --- a/v3/internal/runtime/desktop/@wailsio/runtime/docs/interfaces/IOS.Device.Info.html +++ /dev/null @@ -1,6 +0,0 @@ -Info | @wailsio/runtime
                    interface Info {
                        constructor: any;
                        isSimulator: boolean;
                        model: string;
                        systemName: string;
                        systemVersion: string;
                    }

                    Constructors

                    constructor: any

                    Properties

                    isSimulator: boolean
                    model: string
                    systemName: string
                    systemVersion: string
                    diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/docs/interfaces/RuntimeTransport.html b/v3/internal/runtime/desktop/@wailsio/runtime/docs/interfaces/RuntimeTransport.html deleted file mode 100644 index 6a07404d7..000000000 --- a/v3/internal/runtime/desktop/@wailsio/runtime/docs/interfaces/RuntimeTransport.html +++ /dev/null @@ -1,11 +0,0 @@ -RuntimeTransport | @wailsio/runtime

                    Interface RuntimeTransport

                    RuntimeTransport defines the interface for custom IPC transport implementations. -Implement this interface to use WebSockets, custom protocols, or any other -transport mechanism instead of the default HTTP fetch.

                    -
                    interface RuntimeTransport {
                        call(
                            objectID: number,
                            method: number,
                            windowName: string,
                            args: any,
                        ): Promise<any>;
                    }

                    Methods

                    Methods

                    • Send a runtime call and return the response.

                      -

                      Parameters

                      • objectID: number

                        The Wails object ID (0=Call, 1=Clipboard, etc.)

                        -
                      • method: number

                        The method ID to call

                        -
                      • windowName: string

                        Optional window name

                        -
                      • args: any

                        Arguments to pass (will be JSON stringified if present)

                        -

                      Returns Promise<any>

                      Promise that resolves with the response data

                      -
                    diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/docs/interfaces/Screens.Rect.html b/v3/internal/runtime/desktop/@wailsio/runtime/docs/interfaces/Screens.Rect.html deleted file mode 100644 index 3c3b36416..000000000 --- a/v3/internal/runtime/desktop/@wailsio/runtime/docs/interfaces/Screens.Rect.html +++ /dev/null @@ -1,9 +0,0 @@ -Rect | @wailsio/runtime
                    interface Rect {
                        Height: number;
                        Width: number;
                        X: number;
                        Y: number;
                    }

                    Properties

                    Properties

                    Height: number

                    The height of the rectangle.

                    -
                    Width: number

                    The width of the rectangle.

                    -
                    X: number

                    The X coordinate of the origin.

                    -
                    Y: number

                    The Y coordinate of the origin.

                    -
                    diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/docs/interfaces/Screens.Screen.html b/v3/internal/runtime/desktop/@wailsio/runtime/docs/interfaces/Screens.Screen.html deleted file mode 100644 index 78e0df769..000000000 --- a/v3/internal/runtime/desktop/@wailsio/runtime/docs/interfaces/Screens.Screen.html +++ /dev/null @@ -1,25 +0,0 @@ -Screen | @wailsio/runtime
                    interface Screen {
                        Bounds: Rect;
                        ID: string;
                        IsPrimary: boolean;
                        Name: string;
                        PhysicalBounds: Rect;
                        PhysicalWorkArea: Rect;
                        Rotation: number;
                        ScaleFactor: number;
                        Size: Screens.Size;
                        WorkArea: Rect;
                        X: number;
                        Y: number;
                    }

                    Properties

                    Bounds: Rect

                    Contains the bounds of the screen in terms of X, Y, Width, and Height.

                    -
                    ID: string

                    Unique identifier for the screen.

                    -
                    IsPrimary: boolean

                    True if this is the primary monitor selected by the user in the operating system.

                    -
                    Name: string

                    Human-readable name of the screen.

                    -
                    PhysicalBounds: Rect

                    Contains the physical bounds of the screen in terms of X, Y, Width, and Height (before scaling).

                    -
                    PhysicalWorkArea: Rect

                    Contains the physical WorkArea of the screen (before scaling).

                    -
                    Rotation: number

                    The rotation of the screen.

                    -
                    ScaleFactor: number

                    The scale factor of the screen (DPI/96). 1 = standard DPI, 2 = HiDPI (Retina), etc.

                    -

                    Contains the width and height of the screen.

                    -
                    WorkArea: Rect

                    Contains the area of the screen that is actually usable (excluding taskbar and other system UI).

                    -
                    X: number

                    The X coordinate of the screen.

                    -
                    Y: number

                    The Y coordinate of the screen.

                    -
                    diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/docs/interfaces/Screens.Size.html b/v3/internal/runtime/desktop/@wailsio/runtime/docs/interfaces/Screens.Size.html deleted file mode 100644 index 03f72fcaf..000000000 --- a/v3/internal/runtime/desktop/@wailsio/runtime/docs/interfaces/Screens.Size.html +++ /dev/null @@ -1,5 +0,0 @@ -Size | @wailsio/runtime
                    interface Size {
                        Height: number;
                        Width: number;
                    }

                    Properties

                    Properties

                    Height: number

                    The height of a rectangular area.

                    -
                    Width: number

                    The width of a rectangular area.

                    -
                    diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/docs/interfaces/System.EnvironmentInfo.html b/v3/internal/runtime/desktop/@wailsio/runtime/docs/interfaces/System.EnvironmentInfo.html deleted file mode 100644 index 16b194a24..000000000 --- a/v3/internal/runtime/desktop/@wailsio/runtime/docs/interfaces/System.EnvironmentInfo.html +++ /dev/null @@ -1,11 +0,0 @@ -EnvironmentInfo | @wailsio/runtime

                    Interface EnvironmentInfo

                    interface EnvironmentInfo {
                        Arch: string;
                        Debug: boolean;
                        OS: string;
                        OSInfo: OSInfo;
                        PlatformInfo: Record<string, any>;
                    }

                    Properties

                    Properties

                    Arch: string

                    The architecture of the system.

                    -
                    Debug: boolean

                    True if the application is running in debug mode, otherwise false.

                    -
                    OS: string

                    The operating system in use.

                    -
                    OSInfo: OSInfo

                    Details of the operating system.

                    -
                    PlatformInfo: Record<string, any>

                    Additional platform information.

                    -
                    diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/docs/interfaces/System.OSInfo.html b/v3/internal/runtime/desktop/@wailsio/runtime/docs/interfaces/System.OSInfo.html deleted file mode 100644 index a008978cf..000000000 --- a/v3/internal/runtime/desktop/@wailsio/runtime/docs/interfaces/System.OSInfo.html +++ /dev/null @@ -1,9 +0,0 @@ -OSInfo | @wailsio/runtime
                    interface OSInfo {
                        Branding: string;
                        ID: string;
                        Name: string;
                        Version: string;
                    }

                    Properties

                    Properties

                    Branding: string

                    The branding of the OS.

                    -
                    ID: string

                    The ID of the OS.

                    -
                    Name: string

                    The name of the OS.

                    -
                    Version: string

                    The version of the OS.

                    -
                    diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/docs/interfaces/_internal_.ErrorOptions.html b/v3/internal/runtime/desktop/@wailsio/runtime/docs/interfaces/_internal_.ErrorOptions.html deleted file mode 100644 index 12c1c1dec..000000000 --- a/v3/internal/runtime/desktop/@wailsio/runtime/docs/interfaces/_internal_.ErrorOptions.html +++ /dev/null @@ -1,2 +0,0 @@ -ErrorOptions | @wailsio/runtime
                    interface ErrorOptions {
                        cause?: unknown;
                    }

                    Properties

                    Properties

                    cause?: unknown
                    diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/docs/interfaces/_internal_.Iterable.html b/v3/internal/runtime/desktop/@wailsio/runtime/docs/interfaces/_internal_.Iterable.html deleted file mode 100644 index 02cc4cf80..000000000 --- a/v3/internal/runtime/desktop/@wailsio/runtime/docs/interfaces/_internal_.Iterable.html +++ /dev/null @@ -1,2 +0,0 @@ -Iterable | @wailsio/runtime

                    Interface Iterable<T, TReturn, TNext>

                    interface Iterable<T, TReturn = any, TNext = any> {
                        "[iterator]"(): Iterator<T, TReturn, TNext>;
                    }

                    Type Parameters

                    • T
                    • TReturn = any
                    • TNext = any

                    Methods

                    Methods

                    diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/docs/interfaces/_internal_.Position.html b/v3/internal/runtime/desktop/@wailsio/runtime/docs/interfaces/_internal_.Position.html deleted file mode 100644 index 8cbcc9c3a..000000000 --- a/v3/internal/runtime/desktop/@wailsio/runtime/docs/interfaces/_internal_.Position.html +++ /dev/null @@ -1,6 +0,0 @@ -Position | @wailsio/runtime

                    A record describing the position of a window.

                    -
                    interface Position {
                        x: number;
                        y: number;
                    }

                    Properties

                    x -y -

                    Properties

                    x: number

                    The horizontal position of the window.

                    -
                    y: number

                    The vertical position of the window.

                    -
                    diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/docs/interfaces/_internal_.PromiseFulfilledResult.html b/v3/internal/runtime/desktop/@wailsio/runtime/docs/interfaces/_internal_.PromiseFulfilledResult.html deleted file mode 100644 index 0f1002ee8..000000000 --- a/v3/internal/runtime/desktop/@wailsio/runtime/docs/interfaces/_internal_.PromiseFulfilledResult.html +++ /dev/null @@ -1,3 +0,0 @@ -PromiseFulfilledResult | @wailsio/runtime

                    Interface PromiseFulfilledResult<T>

                    interface PromiseFulfilledResult<T> {
                        status: "fulfilled";
                        value: T;
                    }

                    Type Parameters

                    • T

                    Properties

                    Properties

                    status: "fulfilled"
                    value: T
                    diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/docs/interfaces/_internal_.PromiseLike.html b/v3/internal/runtime/desktop/@wailsio/runtime/docs/interfaces/_internal_.PromiseLike.html deleted file mode 100644 index 4add9f58e..000000000 --- a/v3/internal/runtime/desktop/@wailsio/runtime/docs/interfaces/_internal_.PromiseLike.html +++ /dev/null @@ -1,6 +0,0 @@ -PromiseLike | @wailsio/runtime
                    interface PromiseLike<T> {
                        then<TResult1 = T, TResult2 = never>(
                            onfulfilled?: null | (value: T) => TResult1 | PromiseLike<TResult1>,
                            onrejected?: null | (reason: any) => TResult2 | PromiseLike<TResult2>,
                        ): PromiseLike<TResult1 | TResult2>;
                    }

                    Type Parameters

                    • T

                    Implemented by

                    Methods

                    Methods

                    diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/docs/interfaces/_internal_.PromiseRejectedResult.html b/v3/internal/runtime/desktop/@wailsio/runtime/docs/interfaces/_internal_.PromiseRejectedResult.html deleted file mode 100644 index a364e257f..000000000 --- a/v3/internal/runtime/desktop/@wailsio/runtime/docs/interfaces/_internal_.PromiseRejectedResult.html +++ /dev/null @@ -1,3 +0,0 @@ -PromiseRejectedResult | @wailsio/runtime
                    interface PromiseRejectedResult {
                        reason: any;
                        status: "rejected";
                    }

                    Properties

                    Properties

                    reason: any
                    status: "rejected"
                    diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/docs/interfaces/_internal_.PromiseWithResolvers.html b/v3/internal/runtime/desktop/@wailsio/runtime/docs/interfaces/_internal_.PromiseWithResolvers.html deleted file mode 100644 index b942f497b..000000000 --- a/v3/internal/runtime/desktop/@wailsio/runtime/docs/interfaces/_internal_.PromiseWithResolvers.html +++ /dev/null @@ -1,4 +0,0 @@ -PromiseWithResolvers | @wailsio/runtime

                    Interface PromiseWithResolvers<T>

                    interface PromiseWithResolvers<T> {
                        promise: Promise<T>;
                        reject: (reason?: any) => void;
                        resolve: (value: T | PromiseLike<T>) => void;
                    }

                    Type Parameters

                    • T

                    Properties

                    Properties

                    promise: Promise<T>
                    reject: (reason?: any) => void
                    resolve: (value: T | PromiseLike<T>) => void
                    diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/docs/interfaces/_internal_.Size.html b/v3/internal/runtime/desktop/@wailsio/runtime/docs/interfaces/_internal_.Size.html deleted file mode 100644 index e7b5f32de..000000000 --- a/v3/internal/runtime/desktop/@wailsio/runtime/docs/interfaces/_internal_.Size.html +++ /dev/null @@ -1,6 +0,0 @@ -Size | @wailsio/runtime

                    A record describing the size of a window.

                    -
                    interface Size {
                        height: number;
                        width: number;
                    }

                    Properties

                    Properties

                    height: number

                    The height of the window.

                    -
                    width: number

                    The width of the window.

                    -
                    diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/docs/modules.html b/v3/internal/runtime/desktop/@wailsio/runtime/docs/modules.html deleted file mode 100644 index a35d3b515..000000000 --- a/v3/internal/runtime/desktop/@wailsio/runtime/docs/modules.html +++ /dev/null @@ -1 +0,0 @@ -@wailsio/runtime
                    diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/docs/modules/Application.html b/v3/internal/runtime/desktop/@wailsio/runtime/docs/modules/Application.html deleted file mode 100644 index e6b5d57c5..000000000 --- a/v3/internal/runtime/desktop/@wailsio/runtime/docs/modules/Application.html +++ /dev/null @@ -1 +0,0 @@ -Application | @wailsio/runtime

                    Namespace Application

                    Functions

                    Hide
                    Quit
                    Show
                    diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/docs/modules/Browser.html b/v3/internal/runtime/desktop/@wailsio/runtime/docs/modules/Browser.html deleted file mode 100644 index 757bf8469..000000000 --- a/v3/internal/runtime/desktop/@wailsio/runtime/docs/modules/Browser.html +++ /dev/null @@ -1 +0,0 @@ -Browser | @wailsio/runtime

                    Namespace Browser

                    Functions

                    OpenURL
                    diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/docs/modules/Call.html b/v3/internal/runtime/desktop/@wailsio/runtime/docs/modules/Call.html deleted file mode 100644 index 8d06195ea..000000000 --- a/v3/internal/runtime/desktop/@wailsio/runtime/docs/modules/Call.html +++ /dev/null @@ -1 +0,0 @@ -Call | @wailsio/runtime

                    Namespace Call

                    Classes

                    RuntimeError

                    Type Aliases

                    CallOptions

                    Functions

                    ByID
                    ByName
                    Call
                    diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/docs/modules/Clipboard.html b/v3/internal/runtime/desktop/@wailsio/runtime/docs/modules/Clipboard.html deleted file mode 100644 index 1d15bfa14..000000000 --- a/v3/internal/runtime/desktop/@wailsio/runtime/docs/modules/Clipboard.html +++ /dev/null @@ -1 +0,0 @@ -Clipboard | @wailsio/runtime

                    Namespace Clipboard

                    Functions

                    SetText
                    Text
                    diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/docs/modules/Dialogs.html b/v3/internal/runtime/desktop/@wailsio/runtime/docs/modules/Dialogs.html deleted file mode 100644 index 256f30a47..000000000 --- a/v3/internal/runtime/desktop/@wailsio/runtime/docs/modules/Dialogs.html +++ /dev/null @@ -1 +0,0 @@ -Dialogs | @wailsio/runtime
                    diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/docs/modules/Events.html b/v3/internal/runtime/desktop/@wailsio/runtime/docs/modules/Events.html deleted file mode 100644 index 4f8d6b611..000000000 --- a/v3/internal/runtime/desktop/@wailsio/runtime/docs/modules/Events.html +++ /dev/null @@ -1 +0,0 @@ -Events | @wailsio/runtime
                    diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/docs/modules/Flags.html b/v3/internal/runtime/desktop/@wailsio/runtime/docs/modules/Flags.html deleted file mode 100644 index 2004c8692..000000000 --- a/v3/internal/runtime/desktop/@wailsio/runtime/docs/modules/Flags.html +++ /dev/null @@ -1 +0,0 @@ -Flags | @wailsio/runtime

                    Namespace Flags

                    Functions

                    GetFlag
                    diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/docs/modules/IOS.Device.html b/v3/internal/runtime/desktop/@wailsio/runtime/docs/modules/IOS.Device.html deleted file mode 100644 index 53e87296b..000000000 --- a/v3/internal/runtime/desktop/@wailsio/runtime/docs/modules/IOS.Device.html +++ /dev/null @@ -1 +0,0 @@ -Device | @wailsio/runtime

                    Interfaces

                    Info

                    Functions

                    Info
                    diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/docs/modules/IOS.Haptics.html b/v3/internal/runtime/desktop/@wailsio/runtime/docs/modules/IOS.Haptics.html deleted file mode 100644 index 9ca587479..000000000 --- a/v3/internal/runtime/desktop/@wailsio/runtime/docs/modules/IOS.Haptics.html +++ /dev/null @@ -1 +0,0 @@ -Haptics | @wailsio/runtime

                    Type Aliases

                    ImpactStyle

                    Functions

                    Impact
                    diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/docs/modules/IOS.html b/v3/internal/runtime/desktop/@wailsio/runtime/docs/modules/IOS.html deleted file mode 100644 index a55f035b1..000000000 --- a/v3/internal/runtime/desktop/@wailsio/runtime/docs/modules/IOS.html +++ /dev/null @@ -1 +0,0 @@ -IOS | @wailsio/runtime

                    Namespace IOS

                    Namespaces

                    Device
                    Haptics
                    diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/docs/modules/Screens.html b/v3/internal/runtime/desktop/@wailsio/runtime/docs/modules/Screens.html deleted file mode 100644 index f25eaabb3..000000000 --- a/v3/internal/runtime/desktop/@wailsio/runtime/docs/modules/Screens.html +++ /dev/null @@ -1 +0,0 @@ -Screens | @wailsio/runtime
                    diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/docs/modules/System.html b/v3/internal/runtime/desktop/@wailsio/runtime/docs/modules/System.html deleted file mode 100644 index bc891a645..000000000 --- a/v3/internal/runtime/desktop/@wailsio/runtime/docs/modules/System.html +++ /dev/null @@ -1 +0,0 @@ -System | @wailsio/runtime
                    diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/docs/modules/WML.html b/v3/internal/runtime/desktop/@wailsio/runtime/docs/modules/WML.html deleted file mode 100644 index e2d7d3912..000000000 --- a/v3/internal/runtime/desktop/@wailsio/runtime/docs/modules/WML.html +++ /dev/null @@ -1 +0,0 @@ -WML | @wailsio/runtime

                    Namespace WML

                    Functions

                    Enable
                    Reload
                    diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/docs/modules/_internal_.html b/v3/internal/runtime/desktop/@wailsio/runtime/docs/modules/_internal_.html deleted file mode 100644 index 7146eb04f..000000000 --- a/v3/internal/runtime/desktop/@wailsio/runtime/docs/modules/_internal_.html +++ /dev/null @@ -1 +0,0 @@ -<internal> | @wailsio/runtime
                    diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/docs/types/Call.CallOptions.html b/v3/internal/runtime/desktop/@wailsio/runtime/docs/types/Call.CallOptions.html deleted file mode 100644 index 4ba71497e..000000000 --- a/v3/internal/runtime/desktop/@wailsio/runtime/docs/types/Call.CallOptions.html +++ /dev/null @@ -1,9 +0,0 @@ -CallOptions | @wailsio/runtime

                    Type Alias CallOptions

                    CallOptions:
                        | { args: any[]; methodID: number; methodName?: never }
                        | { args: any[]; methodID?: never; methodName: string }

                    Holds all required information for a binding call. -May provide either a method ID or a method name, but not both.

                    -

                    Type declaration

                    • { args: any[]; methodID: number; methodName?: never }
                      • args: any[]

                        Arguments to be passed into the bound method.

                        -
                      • methodID: number

                        The numeric ID of the bound method to call.

                        -
                      • OptionalmethodName?: never

                        The fully qualified name of the bound method to call.

                        -
                    • { args: any[]; methodID?: never; methodName: string }
                      • args: any[]

                        Arguments to be passed into the bound method.

                        -
                      • OptionalmethodID?: never

                        The numeric ID of the bound method to call.

                        -
                      • methodName: string

                        The fully qualified name of the bound method to call.

                        -
                    diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/docs/types/Events.WailsEventCallback.html b/v3/internal/runtime/desktop/@wailsio/runtime/docs/types/Events.WailsEventCallback.html deleted file mode 100644 index 4848dc8e5..000000000 --- a/v3/internal/runtime/desktop/@wailsio/runtime/docs/types/Events.WailsEventCallback.html +++ /dev/null @@ -1,2 +0,0 @@ -WailsEventCallback | @wailsio/runtime

                    Type Alias WailsEventCallback<E>

                    WailsEventCallback: (ev: WailsEvent<E>) => void

                    The type of handlers for a given event.

                    -

                    Type Parameters

                    Type declaration

                    diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/docs/types/Events.WailsEventData.html b/v3/internal/runtime/desktop/@wailsio/runtime/docs/types/Events.WailsEventData.html deleted file mode 100644 index a73367389..000000000 --- a/v3/internal/runtime/desktop/@wailsio/runtime/docs/types/Events.WailsEventData.html +++ /dev/null @@ -1,2 +0,0 @@ -WailsEventData | @wailsio/runtime

                    Type Alias WailsEventData<E>

                    WailsEventData: E extends keyof CustomEvents
                        ? CustomEvents[E]
                        : E extends SystemEventName ? void : any

                    The data type associated to a given event.

                    -

                    Type Parameters

                    diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/docs/types/Events.WailsEventName.html b/v3/internal/runtime/desktop/@wailsio/runtime/docs/types/Events.WailsEventName.html deleted file mode 100644 index 7bbb4839b..000000000 --- a/v3/internal/runtime/desktop/@wailsio/runtime/docs/types/Events.WailsEventName.html +++ /dev/null @@ -1,2 +0,0 @@ -WailsEventName | @wailsio/runtime

                    Type Alias WailsEventName<E>

                    WailsEventName: E | string & {}

                    Either a known event name or an arbitrary string.

                    -

                    Type Parameters

                    diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/docs/types/IOS.Haptics.ImpactStyle.html b/v3/internal/runtime/desktop/@wailsio/runtime/docs/types/IOS.Haptics.ImpactStyle.html deleted file mode 100644 index e55fdb123..000000000 --- a/v3/internal/runtime/desktop/@wailsio/runtime/docs/types/IOS.Haptics.ImpactStyle.html +++ /dev/null @@ -1 +0,0 @@ -ImpactStyle | @wailsio/runtime
                    ImpactStyle: "light" | "medium" | "heavy" | "soft" | "rigid"
                    diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/docs/types/_internal_.Awaited.html b/v3/internal/runtime/desktop/@wailsio/runtime/docs/types/_internal_.Awaited.html deleted file mode 100644 index 7d51c3785..000000000 --- a/v3/internal/runtime/desktop/@wailsio/runtime/docs/types/_internal_.Awaited.html +++ /dev/null @@ -1,2 +0,0 @@ -Awaited | @wailsio/runtime
                    Awaited: T extends null
                    | undefined
                        ? T
                        : T extends object & { then(onfulfilled: F, ...args: _): any }
                            ? F extends (value: infer V, ...args: infer _) => any
                                ? Awaited<V>
                                : never
                            : T

                    Recursively unwraps the "awaited type" of a type. Non-promise "thenables" should resolve to never. This emulates the behavior of await.

                    -

                    Type Parameters

                    • T
                    diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/docs/types/_internal_.CancellablePromiseCanceller.html b/v3/internal/runtime/desktop/@wailsio/runtime/docs/types/_internal_.CancellablePromiseCanceller.html deleted file mode 100644 index 3258a70d0..000000000 --- a/v3/internal/runtime/desktop/@wailsio/runtime/docs/types/_internal_.CancellablePromiseCanceller.html +++ /dev/null @@ -1 +0,0 @@ -CancellablePromiseCanceller | @wailsio/runtime

                    Type Alias CancellablePromiseCanceller

                    CancellablePromiseCanceller: (cause?: any) => void | PromiseLike<void>

                    Type declaration

                    diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/docs/types/_internal_.CancellablePromiseExecutor.html b/v3/internal/runtime/desktop/@wailsio/runtime/docs/types/_internal_.CancellablePromiseExecutor.html deleted file mode 100644 index 85b0f8526..000000000 --- a/v3/internal/runtime/desktop/@wailsio/runtime/docs/types/_internal_.CancellablePromiseExecutor.html +++ /dev/null @@ -1 +0,0 @@ -CancellablePromiseExecutor | @wailsio/runtime

                    Type Alias CancellablePromiseExecutor<T>

                    CancellablePromiseExecutor: (
                        resolve: CancellablePromiseResolver<T>,
                        reject: CancellablePromiseRejector,
                    ) => void

                    Type Parameters

                    • T

                    Type declaration

                    diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/docs/types/_internal_.CancellablePromiseRejector.html b/v3/internal/runtime/desktop/@wailsio/runtime/docs/types/_internal_.CancellablePromiseRejector.html deleted file mode 100644 index b75c628c3..000000000 --- a/v3/internal/runtime/desktop/@wailsio/runtime/docs/types/_internal_.CancellablePromiseRejector.html +++ /dev/null @@ -1 +0,0 @@ -CancellablePromiseRejector | @wailsio/runtime

                    Type Alias CancellablePromiseRejector

                    CancellablePromiseRejector: (reason?: any) => void

                    Type declaration

                      • (reason?: any): void
                      • Parameters

                        • Optionalreason: any

                        Returns void

                    diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/docs/types/_internal_.CancellablePromiseResolver.html b/v3/internal/runtime/desktop/@wailsio/runtime/docs/types/_internal_.CancellablePromiseResolver.html deleted file mode 100644 index 81f2b806b..000000000 --- a/v3/internal/runtime/desktop/@wailsio/runtime/docs/types/_internal_.CancellablePromiseResolver.html +++ /dev/null @@ -1 +0,0 @@ -CancellablePromiseResolver | @wailsio/runtime

                    Type Alias CancellablePromiseResolver<T>

                    CancellablePromiseResolver: (
                        value: T | PromiseLike<T> | CancellablePromiseLike<T>,
                    ) => void

                    Type Parameters

                    • T

                    Type declaration

                    diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/docs/types/_internal_.Partial.html b/v3/internal/runtime/desktop/@wailsio/runtime/docs/types/_internal_.Partial.html deleted file mode 100644 index c2c89e799..000000000 --- a/v3/internal/runtime/desktop/@wailsio/runtime/docs/types/_internal_.Partial.html +++ /dev/null @@ -1,2 +0,0 @@ -Partial | @wailsio/runtime
                    Partial: { [P in keyof T]?: T[P] }

                    Make all properties in T optional

                    -

                    Type Parameters

                    • T
                    diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/docs/types/_internal_.PromiseSettledResult.html b/v3/internal/runtime/desktop/@wailsio/runtime/docs/types/_internal_.PromiseSettledResult.html deleted file mode 100644 index c71a7894b..000000000 --- a/v3/internal/runtime/desktop/@wailsio/runtime/docs/types/_internal_.PromiseSettledResult.html +++ /dev/null @@ -1 +0,0 @@ -PromiseSettledResult | @wailsio/runtime

                    Type Alias PromiseSettledResult<T>

                    Type Parameters

                    • T
                    diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/docs/types/_internal_.PropertyKey.html b/v3/internal/runtime/desktop/@wailsio/runtime/docs/types/_internal_.PropertyKey.html deleted file mode 100644 index 3cb0bb269..000000000 --- a/v3/internal/runtime/desktop/@wailsio/runtime/docs/types/_internal_.PropertyKey.html +++ /dev/null @@ -1 +0,0 @@ -PropertyKey | @wailsio/runtime
                    PropertyKey: string | number | symbol
                    diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/docs/types/_internal_.Readonly.html b/v3/internal/runtime/desktop/@wailsio/runtime/docs/types/_internal_.Readonly.html deleted file mode 100644 index 3f66bd1ba..000000000 --- a/v3/internal/runtime/desktop/@wailsio/runtime/docs/types/_internal_.Readonly.html +++ /dev/null @@ -1,2 +0,0 @@ -Readonly | @wailsio/runtime
                    Readonly: { readonly [P in keyof T]: T[P] }

                    Make all properties in T readonly

                    -

                    Type Parameters

                    • T
                    diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/docs/types/_internal_.Record.html b/v3/internal/runtime/desktop/@wailsio/runtime/docs/types/_internal_.Record.html deleted file mode 100644 index 8930f14b9..000000000 --- a/v3/internal/runtime/desktop/@wailsio/runtime/docs/types/_internal_.Record.html +++ /dev/null @@ -1,2 +0,0 @@ -Record | @wailsio/runtime

                    Type Alias Record<K, T>

                    Record: { [P in K]: T }

                    Construct a type with a set of properties K of type T

                    -

                    Type Parameters

                    • K extends keyof any
                    • T
                    diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/docs/types/_internal_.SystemEventName.html b/v3/internal/runtime/desktop/@wailsio/runtime/docs/types/_internal_.SystemEventName.html deleted file mode 100644 index 5710c2b3e..000000000 --- a/v3/internal/runtime/desktop/@wailsio/runtime/docs/types/_internal_.SystemEventName.html +++ /dev/null @@ -1,2 +0,0 @@ -SystemEventName | @wailsio/runtime
                    SystemEventName: {
                        [K in keyof typeof Types]: typeof Types[K][keyof typeof Types[K]]
                    } extends infer M
                        ? M[keyof M]
                        : never

                    Union of all known system event names.

                    -
                    diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/docs/variables/Events.Types.html b/v3/internal/runtime/desktop/@wailsio/runtime/docs/variables/Events.Types.html deleted file mode 100644 index 564d38e84..000000000 --- a/v3/internal/runtime/desktop/@wailsio/runtime/docs/variables/Events.Types.html +++ /dev/null @@ -1 +0,0 @@ -Types | @wailsio/runtime

                    Variable TypesConst

                    Types: Readonly<
                        {
                            Common: Readonly<
                                {
                                    ApplicationLaunchedWithUrl: "common:ApplicationLaunchedWithUrl";
                                    ApplicationOpenedWithFile: "common:ApplicationOpenedWithFile";
                                    ApplicationStarted: "common:ApplicationStarted";
                                    ThemeChanged: "common:ThemeChanged";
                                    WindowClosing: "common:WindowClosing";
                                    WindowDidMove: "common:WindowDidMove";
                                    WindowDidResize: "common:WindowDidResize";
                                    WindowDPIChanged: "common:WindowDPIChanged";
                                    WindowFilesDropped: "common:WindowFilesDropped";
                                    WindowFocus: "common:WindowFocus";
                                    WindowFullscreen: "common:WindowFullscreen";
                                    WindowHide: "common:WindowHide";
                                    WindowLostFocus: "common:WindowLostFocus";
                                    WindowMaximise: "common:WindowMaximise";
                                    WindowMinimise: "common:WindowMinimise";
                                    WindowRestore: "common:WindowRestore";
                                    WindowRuntimeReady: "common:WindowRuntimeReady";
                                    WindowShow: "common:WindowShow";
                                    WindowToggleFrameless: "common:WindowToggleFrameless";
                                    WindowUnFullscreen: "common:WindowUnFullscreen";
                                    WindowUnMaximise: "common:WindowUnMaximise";
                                    WindowUnMinimise: "common:WindowUnMinimise";
                                    WindowZoom: "common:WindowZoom";
                                    WindowZoomIn: "common:WindowZoomIn";
                                    WindowZoomOut: "common:WindowZoomOut";
                                    WindowZoomReset: "common:WindowZoomReset";
                                },
                            >;
                            iOS: Readonly<
                                {
                                    ApplicationDidBecomeActive: "ios:ApplicationDidBecomeActive";
                                    ApplicationDidEnterBackground: "ios:ApplicationDidEnterBackground";
                                    ApplicationDidFinishLaunching: "ios:ApplicationDidFinishLaunching";
                                    ApplicationDidReceiveMemoryWarning: "ios:ApplicationDidReceiveMemoryWarning";
                                    ApplicationWillEnterForeground: "ios:ApplicationWillEnterForeground";
                                    ApplicationWillResignActive: "ios:ApplicationWillResignActive";
                                    ApplicationWillTerminate: "ios:ApplicationWillTerminate";
                                    WebViewDecidePolicyForNavigationAction: "ios:WebViewDecidePolicyForNavigationAction";
                                    WebViewDidFailNavigation: "ios:WebViewDidFailNavigation";
                                    WebViewDidFinishNavigation: "ios:WebViewDidFinishNavigation";
                                    WebViewDidStartNavigation: "ios:WebViewDidStartNavigation";
                                    WindowDidAppear: "ios:WindowDidAppear";
                                    WindowDidDisappear: "ios:WindowDidDisappear";
                                    WindowDidLoad: "ios:WindowDidLoad";
                                    WindowOrientationChanged: "ios:WindowOrientationChanged";
                                    WindowSafeAreaInsetsChanged: "ios:WindowSafeAreaInsetsChanged";
                                    WindowTouchBegan: "ios:WindowTouchBegan";
                                    WindowTouchCancelled: "ios:WindowTouchCancelled";
                                    WindowTouchEnded: "ios:WindowTouchEnded";
                                    WindowTouchMoved: "ios:WindowTouchMoved";
                                    WindowWillAppear: "ios:WindowWillAppear";
                                    WindowWillDisappear: "ios:WindowWillDisappear";
                                },
                            >;
                            Linux: Readonly<
                                {
                                    ApplicationStartup: "linux:ApplicationStartup";
                                    SystemThemeChanged: "linux:SystemThemeChanged";
                                    WindowDeleteEvent: "linux:WindowDeleteEvent";
                                    WindowDidMove: "linux:WindowDidMove";
                                    WindowDidResize: "linux:WindowDidResize";
                                    WindowFocusIn: "linux:WindowFocusIn";
                                    WindowFocusOut: "linux:WindowFocusOut";
                                    WindowLoadCommitted: "linux:WindowLoadCommitted";
                                    WindowLoadFinished: "linux:WindowLoadFinished";
                                    WindowLoadRedirected: "linux:WindowLoadRedirected";
                                    WindowLoadStarted: "linux:WindowLoadStarted";
                                },
                            >;
                            Mac: Readonly<
                                {
                                    ApplicationDidBecomeActive: "mac:ApplicationDidBecomeActive";
                                    ApplicationDidChangeBackingProperties: "mac:ApplicationDidChangeBackingProperties";
                                    ApplicationDidChangeEffectiveAppearance: "mac:ApplicationDidChangeEffectiveAppearance";
                                    ApplicationDidChangeIcon: "mac:ApplicationDidChangeIcon";
                                    ApplicationDidChangeOcclusionState: "mac:ApplicationDidChangeOcclusionState";
                                    ApplicationDidChangeScreenParameters: "mac:ApplicationDidChangeScreenParameters";
                                    ApplicationDidChangeStatusBarFrame: "mac:ApplicationDidChangeStatusBarFrame";
                                    ApplicationDidChangeStatusBarOrientation: "mac:ApplicationDidChangeStatusBarOrientation";
                                    ApplicationDidChangeTheme: "mac:ApplicationDidChangeTheme";
                                    ApplicationDidFinishLaunching: "mac:ApplicationDidFinishLaunching";
                                    ApplicationDidHide: "mac:ApplicationDidHide";
                                    ApplicationDidResignActive: "mac:ApplicationDidResignActive";
                                    ApplicationDidUnhide: "mac:ApplicationDidUnhide";
                                    ApplicationDidUpdate: "mac:ApplicationDidUpdate";
                                    ApplicationShouldHandleReopen: "mac:ApplicationShouldHandleReopen";
                                    ApplicationWillBecomeActive: "mac:ApplicationWillBecomeActive";
                                    ApplicationWillFinishLaunching: "mac:ApplicationWillFinishLaunching";
                                    ApplicationWillHide: "mac:ApplicationWillHide";
                                    ApplicationWillResignActive: "mac:ApplicationWillResignActive";
                                    ApplicationWillTerminate: "mac:ApplicationWillTerminate";
                                    ApplicationWillUnhide: "mac:ApplicationWillUnhide";
                                    ApplicationWillUpdate: "mac:ApplicationWillUpdate";
                                    MenuDidAddItem: "mac:MenuDidAddItem";
                                    MenuDidBeginTracking: "mac:MenuDidBeginTracking";
                                    MenuDidClose: "mac:MenuDidClose";
                                    MenuDidDisplayItem: "mac:MenuDidDisplayItem";
                                    MenuDidEndTracking: "mac:MenuDidEndTracking";
                                    MenuDidHighlightItem: "mac:MenuDidHighlightItem";
                                    MenuDidOpen: "mac:MenuDidOpen";
                                    MenuDidPopUp: "mac:MenuDidPopUp";
                                    MenuDidRemoveItem: "mac:MenuDidRemoveItem";
                                    MenuDidSendAction: "mac:MenuDidSendAction";
                                    MenuDidSendActionToItem: "mac:MenuDidSendActionToItem";
                                    MenuDidUpdate: "mac:MenuDidUpdate";
                                    MenuWillAddItem: "mac:MenuWillAddItem";
                                    MenuWillBeginTracking: "mac:MenuWillBeginTracking";
                                    MenuWillDisplayItem: "mac:MenuWillDisplayItem";
                                    MenuWillEndTracking: "mac:MenuWillEndTracking";
                                    MenuWillHighlightItem: "mac:MenuWillHighlightItem";
                                    MenuWillOpen: "mac:MenuWillOpen";
                                    MenuWillPopUp: "mac:MenuWillPopUp";
                                    MenuWillRemoveItem: "mac:MenuWillRemoveItem";
                                    MenuWillSendAction: "mac:MenuWillSendAction";
                                    MenuWillSendActionToItem: "mac:MenuWillSendActionToItem";
                                    MenuWillUpdate: "mac:MenuWillUpdate";
                                    WebViewDidCommitNavigation: "mac:WebViewDidCommitNavigation";
                                    WebViewDidFinishNavigation: "mac:WebViewDidFinishNavigation";
                                    WebViewDidReceiveServerRedirectForProvisionalNavigation: "mac:WebViewDidReceiveServerRedirectForProvisionalNavigation";
                                    WebViewDidStartProvisionalNavigation: "mac:WebViewDidStartProvisionalNavigation";
                                    WindowDidBecomeKey: "mac:WindowDidBecomeKey";
                                    WindowDidBecomeMain: "mac:WindowDidBecomeMain";
                                    WindowDidBeginSheet: "mac:WindowDidBeginSheet";
                                    WindowDidChangeAlpha: "mac:WindowDidChangeAlpha";
                                    WindowDidChangeBackingLocation: "mac:WindowDidChangeBackingLocation";
                                    WindowDidChangeBackingProperties: "mac:WindowDidChangeBackingProperties";
                                    WindowDidChangeCollectionBehavior: "mac:WindowDidChangeCollectionBehavior";
                                    WindowDidChangeEffectiveAppearance: "mac:WindowDidChangeEffectiveAppearance";
                                    WindowDidChangeOcclusionState: "mac:WindowDidChangeOcclusionState";
                                    WindowDidChangeOrderingMode: "mac:WindowDidChangeOrderingMode";
                                    WindowDidChangeScreen: "mac:WindowDidChangeScreen";
                                    WindowDidChangeScreenParameters: "mac:WindowDidChangeScreenParameters";
                                    WindowDidChangeScreenProfile: "mac:WindowDidChangeScreenProfile";
                                    WindowDidChangeScreenSpace: "mac:WindowDidChangeScreenSpace";
                                    WindowDidChangeScreenSpaceProperties: "mac:WindowDidChangeScreenSpaceProperties";
                                    WindowDidChangeSharingType: "mac:WindowDidChangeSharingType";
                                    WindowDidChangeSpace: "mac:WindowDidChangeSpace";
                                    WindowDidChangeSpaceOrderingMode: "mac:WindowDidChangeSpaceOrderingMode";
                                    WindowDidChangeTitle: "mac:WindowDidChangeTitle";
                                    WindowDidChangeToolbar: "mac:WindowDidChangeToolbar";
                                    WindowDidDeminiaturize: "mac:WindowDidDeminiaturize";
                                    WindowDidEndSheet: "mac:WindowDidEndSheet";
                                    WindowDidEnterFullScreen: "mac:WindowDidEnterFullScreen";
                                    WindowDidEnterVersionBrowser: "mac:WindowDidEnterVersionBrowser";
                                    WindowDidExitFullScreen: "mac:WindowDidExitFullScreen";
                                    WindowDidExitVersionBrowser: "mac:WindowDidExitVersionBrowser";
                                    WindowDidExpose: "mac:WindowDidExpose";
                                    WindowDidFocus: "mac:WindowDidFocus";
                                    WindowDidMiniaturize: "mac:WindowDidMiniaturize";
                                    WindowDidMove: "mac:WindowDidMove";
                                    WindowDidOrderOffScreen: "mac:WindowDidOrderOffScreen";
                                    WindowDidOrderOnScreen: "mac:WindowDidOrderOnScreen";
                                    WindowDidResignKey: "mac:WindowDidResignKey";
                                    WindowDidResignMain: "mac:WindowDidResignMain";
                                    WindowDidResize: "mac:WindowDidResize";
                                    WindowDidUpdate: "mac:WindowDidUpdate";
                                    WindowDidUpdateAlpha: "mac:WindowDidUpdateAlpha";
                                    WindowDidUpdateCollectionBehavior: "mac:WindowDidUpdateCollectionBehavior";
                                    WindowDidUpdateCollectionProperties: "mac:WindowDidUpdateCollectionProperties";
                                    WindowDidUpdateShadow: "mac:WindowDidUpdateShadow";
                                    WindowDidUpdateTitle: "mac:WindowDidUpdateTitle";
                                    WindowDidUpdateToolbar: "mac:WindowDidUpdateToolbar";
                                    WindowDidZoom: "mac:WindowDidZoom";
                                    WindowFileDraggingEntered: "mac:WindowFileDraggingEntered";
                                    WindowFileDraggingExited: "mac:WindowFileDraggingExited";
                                    WindowFileDraggingPerformed: "mac:WindowFileDraggingPerformed";
                                    WindowHide: "mac:WindowHide";
                                    WindowMaximise: "mac:WindowMaximise";
                                    WindowMinimise: "mac:WindowMinimise";
                                    WindowShouldClose: "mac:WindowShouldClose";
                                    WindowShow: "mac:WindowShow";
                                    WindowUnMaximise: "mac:WindowUnMaximise";
                                    WindowUnMinimise: "mac:WindowUnMinimise";
                                    WindowWillBecomeKey: "mac:WindowWillBecomeKey";
                                    WindowWillBecomeMain: "mac:WindowWillBecomeMain";
                                    WindowWillBeginSheet: "mac:WindowWillBeginSheet";
                                    WindowWillChangeOrderingMode: "mac:WindowWillChangeOrderingMode";
                                    WindowWillClose: "mac:WindowWillClose";
                                    WindowWillDeminiaturize: "mac:WindowWillDeminiaturize";
                                    WindowWillEnterFullScreen: "mac:WindowWillEnterFullScreen";
                                    WindowWillEnterVersionBrowser: "mac:WindowWillEnterVersionBrowser";
                                    WindowWillExitFullScreen: "mac:WindowWillExitFullScreen";
                                    WindowWillExitVersionBrowser: "mac:WindowWillExitVersionBrowser";
                                    WindowWillFocus: "mac:WindowWillFocus";
                                    WindowWillMiniaturize: "mac:WindowWillMiniaturize";
                                    WindowWillMove: "mac:WindowWillMove";
                                    WindowWillOrderOffScreen: "mac:WindowWillOrderOffScreen";
                                    WindowWillOrderOnScreen: "mac:WindowWillOrderOnScreen";
                                    WindowWillResignMain: "mac:WindowWillResignMain";
                                    WindowWillResize: "mac:WindowWillResize";
                                    WindowWillUnfocus: "mac:WindowWillUnfocus";
                                    WindowWillUpdate: "mac:WindowWillUpdate";
                                    WindowWillUpdateAlpha: "mac:WindowWillUpdateAlpha";
                                    WindowWillUpdateCollectionBehavior: "mac:WindowWillUpdateCollectionBehavior";
                                    WindowWillUpdateCollectionProperties: "mac:WindowWillUpdateCollectionProperties";
                                    WindowWillUpdateShadow: "mac:WindowWillUpdateShadow";
                                    WindowWillUpdateTitle: "mac:WindowWillUpdateTitle";
                                    WindowWillUpdateToolbar: "mac:WindowWillUpdateToolbar";
                                    WindowWillUpdateVisibility: "mac:WindowWillUpdateVisibility";
                                    WindowWillUseStandardFrame: "mac:WindowWillUseStandardFrame";
                                    WindowZoomIn: "mac:WindowZoomIn";
                                    WindowZoomOut: "mac:WindowZoomOut";
                                    WindowZoomReset: "mac:WindowZoomReset";
                                },
                            >;
                            Windows: Readonly<
                                {
                                    APMPowerSettingChange: "windows:APMPowerSettingChange";
                                    APMPowerStatusChange: "windows:APMPowerStatusChange";
                                    APMResumeAutomatic: "windows:APMResumeAutomatic";
                                    APMResumeSuspend: "windows:APMResumeSuspend";
                                    APMSuspend: "windows:APMSuspend";
                                    ApplicationStarted: "windows:ApplicationStarted";
                                    SystemThemeChanged: "windows:SystemThemeChanged";
                                    WebViewNavigationCompleted: "windows:WebViewNavigationCompleted";
                                    WindowActive: "windows:WindowActive";
                                    WindowBackgroundErase: "windows:WindowBackgroundErase";
                                    WindowClickActive: "windows:WindowClickActive";
                                    WindowClosing: "windows:WindowClosing";
                                    WindowDidMove: "windows:WindowDidMove";
                                    WindowDidResize: "windows:WindowDidResize";
                                    WindowDPIChanged: "windows:WindowDPIChanged";
                                    WindowDragDrop: "windows:WindowDragDrop";
                                    WindowDragEnter: "windows:WindowDragEnter";
                                    WindowDragLeave: "windows:WindowDragLeave";
                                    WindowDragOver: "windows:WindowDragOver";
                                    WindowEndMove: "windows:WindowEndMove";
                                    WindowEndResize: "windows:WindowEndResize";
                                    WindowFullscreen: "windows:WindowFullscreen";
                                    WindowHide: "windows:WindowHide";
                                    WindowInactive: "windows:WindowInactive";
                                    WindowKeyDown: "windows:WindowKeyDown";
                                    WindowKeyUp: "windows:WindowKeyUp";
                                    WindowKillFocus: "windows:WindowKillFocus";
                                    WindowMaximise: "windows:WindowMaximise";
                                    WindowMinimise: "windows:WindowMinimise";
                                    WindowNonClientHit: "windows:WindowNonClientHit";
                                    WindowNonClientMouseDown: "windows:WindowNonClientMouseDown";
                                    WindowNonClientMouseLeave: "windows:WindowNonClientMouseLeave";
                                    WindowNonClientMouseMove: "windows:WindowNonClientMouseMove";
                                    WindowNonClientMouseUp: "windows:WindowNonClientMouseUp";
                                    WindowPaint: "windows:WindowPaint";
                                    WindowRestore: "windows:WindowRestore";
                                    WindowSetFocus: "windows:WindowSetFocus";
                                    WindowShow: "windows:WindowShow";
                                    WindowStartMove: "windows:WindowStartMove";
                                    WindowStartResize: "windows:WindowStartResize";
                                    WindowUnFullscreen: "windows:WindowUnFullscreen";
                                    WindowUnMaximise: "windows:WindowUnMaximise";
                                    WindowUnMinimise: "windows:WindowUnMinimise";
                                    WindowZOrderChanged: "windows:WindowZOrderChanged";
                                },
                            >;
                        },
                    > = ...
                    diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/docs/variables/Window.html b/v3/internal/runtime/desktop/@wailsio/runtime/docs/variables/Window.html deleted file mode 100644 index 8b7134654..000000000 --- a/v3/internal/runtime/desktop/@wailsio/runtime/docs/variables/Window.html +++ /dev/null @@ -1,2 +0,0 @@ -Window | @wailsio/runtime

                    Variable WindowConst

                    Window: Window = ...

                    The window within which the script is running.

                    -
                    diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/docs/variables/clientId.html b/v3/internal/runtime/desktop/@wailsio/runtime/docs/variables/clientId.html deleted file mode 100644 index b1673b468..000000000 --- a/v3/internal/runtime/desktop/@wailsio/runtime/docs/variables/clientId.html +++ /dev/null @@ -1 +0,0 @@ -clientId | @wailsio/runtime

                    Variable clientId

                    clientId: string = ...
                    diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/docs/variables/objectNames.html b/v3/internal/runtime/desktop/@wailsio/runtime/docs/variables/objectNames.html deleted file mode 100644 index 110e6e600..000000000 --- a/v3/internal/runtime/desktop/@wailsio/runtime/docs/variables/objectNames.html +++ /dev/null @@ -1 +0,0 @@ -objectNames | @wailsio/runtime

                    Variable objectNamesConst

                    objectNames: Readonly<
                        {
                            Application: 2;
                            Browser: 9;
                            Call: 0;
                            CancelCall: 10;
                            Clipboard: 1;
                            ContextMenu: 4;
                            Dialog: 5;
                            Events: 3;
                            IOS: 11;
                            Screens: 7;
                            System: 8;
                            Window: 6;
                        },
                    > = ...
                    diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/package-lock.json b/v3/internal/runtime/desktop/@wailsio/runtime/package-lock.json deleted file mode 100644 index d72354832..000000000 --- a/v3/internal/runtime/desktop/@wailsio/runtime/package-lock.json +++ /dev/null @@ -1,3093 +0,0 @@ -{ - "name": "@wailsio/runtime", - "version": "3.0.0-alpha.80", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "@wailsio/runtime", - "version": "3.0.0-alpha.80", - "license": "MIT", - "devDependencies": { - "happy-dom": "^17.1.1", - "promises-aplus-tests": "2.1.2", - "rimraf": "^5.0.5", - "typedoc": "^0.27.7", - "typedoc-plugin-markdown": "^4.4.2", - "typedoc-plugin-mdn-links": "^4.0.13", - "typedoc-plugin-missing-exports": "^3.1.0", - "typescript": "^5.7.3", - "vite": "^5.2.0", - "vitest": "^3.0.6" - } - }, - "node_modules/@esbuild/aix-ppc64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", - "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "aix" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/android-arm": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz", - "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/android-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz", - "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/android-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz", - "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/darwin-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz", - "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/darwin-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz", - "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/freebsd-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz", - "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/freebsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz", - "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-arm": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz", - "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz", - "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-ia32": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz", - "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-loong64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz", - "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==", - "cpu": [ - "loong64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-mips64el": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz", - "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==", - "cpu": [ - "mips64el" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-ppc64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz", - "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-riscv64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz", - "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-s390x": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz", - "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==", - "cpu": [ - "s390x" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz", - "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/netbsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz", - "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/openbsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz", - "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/sunos-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz", - "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/win32-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz", - "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/win32-ia32": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz", - "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/win32-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz", - "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@gerrit0/mini-shiki": { - "version": "1.27.2", - "resolved": "https://registry.npmjs.org/@gerrit0/mini-shiki/-/mini-shiki-1.27.2.tgz", - "integrity": "sha512-GeWyHz8ao2gBiUW4OJnQDxXQnFgZQwwQk05t/CVVgNBN7/rK8XZ7xY6YhLVv9tH3VppWWmr9DCl3MwemB/i+Og==", - "dev": true, - "license": "MIT", - "dependencies": { - "@shikijs/engine-oniguruma": "^1.27.2", - "@shikijs/types": "^1.27.2", - "@shikijs/vscode-textmate": "^10.0.1" - } - }, - "node_modules/@isaacs/cliui": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", - "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", - "dev": true, - "license": "ISC", - "dependencies": { - "string-width": "^5.1.2", - "string-width-cjs": "npm:string-width@^4.2.0", - "strip-ansi": "^7.0.1", - "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", - "wrap-ansi": "^8.1.0", - "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", - "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/@pkgjs/parseargs": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", - "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", - "dev": true, - "license": "MIT", - "optional": true, - "engines": { - "node": ">=14" - } - }, - "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.34.9", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.34.9.tgz", - "integrity": "sha512-qZdlImWXur0CFakn2BJ2znJOdqYZKiedEPEVNTBrpfPjc/YuTGcaYZcdmNFTkUj3DU0ZM/AElcM8Ybww3xVLzA==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/@rollup/rollup-android-arm64": { - "version": "4.34.9", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.34.9.tgz", - "integrity": "sha512-4KW7P53h6HtJf5Y608T1ISKvNIYLWRKMvfnG0c44M6In4DQVU58HZFEVhWINDZKp7FZps98G3gxwC1sb0wXUUg==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.34.9", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.34.9.tgz", - "integrity": "sha512-0CY3/K54slrzLDjOA7TOjN1NuLKERBgk9nY5V34mhmuu673YNb+7ghaDUs6N0ujXR7fz5XaS5Aa6d2TNxZd0OQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.34.9", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.34.9.tgz", - "integrity": "sha512-eOojSEAi/acnsJVYRxnMkPFqcxSMFfrw7r2iD9Q32SGkb/Q9FpUY1UlAu1DH9T7j++gZ0lHjnm4OyH2vCI7l7Q==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.34.9", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.34.9.tgz", - "integrity": "sha512-2lzjQPJbN5UnHm7bHIUKFMulGTQwdvOkouJDpPysJS+QFBGDJqcfh+CxxtG23Ik/9tEvnebQiylYoazFMAgrYw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ] - }, - "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.34.9", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.34.9.tgz", - "integrity": "sha512-SLl0hi2Ah2H7xQYd6Qaiu01kFPzQ+hqvdYSoOtHYg/zCIFs6t8sV95kaoqjzjFwuYQLtOI0RZre/Ke0nPaQV+g==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ] - }, - "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.34.9", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.34.9.tgz", - "integrity": "sha512-88I+D3TeKItrw+Y/2ud4Tw0+3CxQ2kLgu3QvrogZ0OfkmX/DEppehus7L3TS2Q4lpB+hYyxhkQiYPJ6Mf5/dPg==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.34.9", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.34.9.tgz", - "integrity": "sha512-3qyfWljSFHi9zH0KgtEPG4cBXHDFhwD8kwg6xLfHQ0IWuH9crp005GfoUUh/6w9/FWGBwEHg3lxK1iHRN1MFlA==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.34.9", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.34.9.tgz", - "integrity": "sha512-6TZjPHjKZUQKmVKMUowF3ewHxctrRR09eYyvT5eFv8w/fXarEra83A2mHTVJLA5xU91aCNOUnM+DWFMSbQ0Nxw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.34.9", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.34.9.tgz", - "integrity": "sha512-LD2fytxZJZ6xzOKnMbIpgzFOuIKlxVOpiMAXawsAZ2mHBPEYOnLRK5TTEsID6z4eM23DuO88X0Tq1mErHMVq0A==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-loongarch64-gnu": { - "version": "4.34.9", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.34.9.tgz", - "integrity": "sha512-dRAgTfDsn0TE0HI6cmo13hemKpVHOEyeciGtvlBTkpx/F65kTvShtY/EVyZEIfxFkV5JJTuQ9tP5HGBS0hfxIg==", - "cpu": [ - "loong64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { - "version": "4.34.9", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.34.9.tgz", - "integrity": "sha512-PHcNOAEhkoMSQtMf+rJofwisZqaU8iQ8EaSps58f5HYll9EAY5BSErCZ8qBDMVbq88h4UxaNPlbrKqfWP8RfJA==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.34.9", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.34.9.tgz", - "integrity": "sha512-Z2i0Uy5G96KBYKjeQFKbbsB54xFOL5/y1P5wNBsbXB8yE+At3oh0DVMjQVzCJRJSfReiB2tX8T6HUFZ2k8iaKg==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.34.9", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.34.9.tgz", - "integrity": "sha512-U+5SwTMoeYXoDzJX5dhDTxRltSrIax8KWwfaaYcynuJw8mT33W7oOgz0a+AaXtGuvhzTr2tVKh5UO8GVANTxyQ==", - "cpu": [ - "s390x" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.34.9", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.34.9.tgz", - "integrity": "sha512-FwBHNSOjUTQLP4MG7y6rR6qbGw4MFeQnIBrMe161QGaQoBQLqSUEKlHIiVgF3g/mb3lxlxzJOpIBhaP+C+KP2A==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.34.9", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.34.9.tgz", - "integrity": "sha512-cYRpV4650z2I3/s6+5/LONkjIz8MBeqrk+vPXV10ORBnshpn8S32bPqQ2Utv39jCiDcO2eJTuSlPXpnvmaIgRA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.34.9", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.34.9.tgz", - "integrity": "sha512-z4mQK9dAN6byRA/vsSgQiPeuO63wdiDxZ9yg9iyX2QTzKuQM7T4xlBoeUP/J8uiFkqxkcWndWi+W7bXdPbt27Q==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.34.9", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.34.9.tgz", - "integrity": "sha512-KB48mPtaoHy1AwDNkAJfHXvHp24H0ryZog28spEs0V48l3H1fr4i37tiyHsgKZJnCmvxsbATdZGBpbmxTE3a9w==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.34.9", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.34.9.tgz", - "integrity": "sha512-AyleYRPU7+rgkMWbEh71fQlrzRfeP6SyMnRf9XX4fCdDPAJumdSBqYEcWPMzVQ4ScAl7E4oFfK0GUVn77xSwbw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@shikijs/engine-oniguruma": { - "version": "1.29.2", - "resolved": "https://registry.npmjs.org/@shikijs/engine-oniguruma/-/engine-oniguruma-1.29.2.tgz", - "integrity": "sha512-7iiOx3SG8+g1MnlzZVDYiaeHe7Ez2Kf2HrJzdmGwkRisT7r4rak0e655AcM/tF9JG/kg5fMNYlLLKglbN7gBqA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@shikijs/types": "1.29.2", - "@shikijs/vscode-textmate": "^10.0.1" - } - }, - "node_modules/@shikijs/types": { - "version": "1.29.2", - "resolved": "https://registry.npmjs.org/@shikijs/types/-/types-1.29.2.tgz", - "integrity": "sha512-VJjK0eIijTZf0QSTODEXCqinjBn0joAHQ+aPSBzrv4O2d/QSbsMw+ZeSRx03kV34Hy7NzUvV/7NqfYGRLrASmw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@shikijs/vscode-textmate": "^10.0.1", - "@types/hast": "^3.0.4" - } - }, - "node_modules/@shikijs/vscode-textmate": { - "version": "10.0.2", - "resolved": "https://registry.npmjs.org/@shikijs/vscode-textmate/-/vscode-textmate-10.0.2.tgz", - "integrity": "sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg==", - "dev": true, - "license": "MIT" - }, - "node_modules/@sinonjs/commons": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", - "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "type-detect": "4.0.8" - } - }, - "node_modules/@sinonjs/fake-timers": { - "version": "13.0.5", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-13.0.5.tgz", - "integrity": "sha512-36/hTbH2uaWuGVERyC6da9YwGWnzUZXuPro/F2LfsdOsLnCojz/iSH8MxUt/FD2S5XBSVPhmArFUXcpCQ2Hkiw==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "@sinonjs/commons": "^3.0.1" - } - }, - "node_modules/@sinonjs/samsam": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/@sinonjs/samsam/-/samsam-8.0.2.tgz", - "integrity": "sha512-v46t/fwnhejRSFTGqbpn9u+LQ9xJDse10gNnPgAcxgdoCDMXj/G2asWAC/8Qs+BAZDicX+MNZouXT1A7c83kVw==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "@sinonjs/commons": "^3.0.1", - "lodash.get": "^4.4.2", - "type-detect": "^4.1.0" - } - }, - "node_modules/@sinonjs/samsam/node_modules/type-detect": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.1.0.tgz", - "integrity": "sha512-Acylog8/luQ8L7il+geoSxhEkazvkslg7PSNKOX59mbB9cOveP5aq9h74Y7YU8yDpJwetzQQrfIwtf4Wp4LKcw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/@sinonjs/text-encoding": { - "version": "0.7.3", - "resolved": "https://registry.npmjs.org/@sinonjs/text-encoding/-/text-encoding-0.7.3.tgz", - "integrity": "sha512-DE427ROAphMQzU4ENbliGYrBSYPXF+TtLg9S8vzeA+OF4ZKzoDdzfL8sxuMUGS/lgRhM6j1URSk9ghf7Xo1tyA==", - "dev": true, - "license": "(Unlicense OR Apache-2.0)" - }, - "node_modules/@types/estree": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", - "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/hast": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@types/hast/-/hast-3.0.4.tgz", - "integrity": "sha512-WPs+bbQw5aCj+x6laNGWLH3wviHtoCv/P3+otBhbOhJgG8qtpdAMlTCxLtsTWA7LH1Oh/bFCHsBn0TPS5m30EQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/unist": "*" - } - }, - "node_modules/@types/unist": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@types/unist/-/unist-3.0.3.tgz", - "integrity": "sha512-ko/gIFJRv177XgZsZcBwnqJN5x/Gien8qNOn0D5bQU/zAzVf9Zt3BlcUiLqhV9y4ARk0GbT3tnUiPNgnTXzc/Q==", - "dev": true, - "license": "MIT" - }, - "node_modules/@vitest/expect": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-3.0.7.tgz", - "integrity": "sha512-QP25f+YJhzPfHrHfYHtvRn+uvkCFCqFtW9CktfBxmB+25QqWsx7VB2As6f4GmwllHLDhXNHvqedwhvMmSnNmjw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@vitest/spy": "3.0.7", - "@vitest/utils": "3.0.7", - "chai": "^5.2.0", - "tinyrainbow": "^2.0.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/@vitest/mocker": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/@vitest/mocker/-/mocker-3.0.7.tgz", - "integrity": "sha512-qui+3BLz9Eonx4EAuR/i+QlCX6AUZ35taDQgwGkK/Tw6/WgwodSrjN1X2xf69IA/643ZX5zNKIn2svvtZDrs4w==", - "dev": true, - "license": "MIT", - "dependencies": { - "@vitest/spy": "3.0.7", - "estree-walker": "^3.0.3", - "magic-string": "^0.30.17" - }, - "funding": { - "url": "https://opencollective.com/vitest" - }, - "peerDependencies": { - "msw": "^2.4.9", - "vite": "^5.0.0 || ^6.0.0" - }, - "peerDependenciesMeta": { - "msw": { - "optional": true - }, - "vite": { - "optional": true - } - } - }, - "node_modules/@vitest/pretty-format": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/@vitest/pretty-format/-/pretty-format-3.0.7.tgz", - "integrity": "sha512-CiRY0BViD/V8uwuEzz9Yapyao+M9M008/9oMOSQydwbwb+CMokEq3XVaF3XK/VWaOK0Jm9z7ENhybg70Gtxsmg==", - "dev": true, - "license": "MIT", - "dependencies": { - "tinyrainbow": "^2.0.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/@vitest/runner": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-3.0.7.tgz", - "integrity": "sha512-WeEl38Z0S2ZcuRTeyYqaZtm4e26tq6ZFqh5y8YD9YxfWuu0OFiGFUbnxNynwLjNRHPsXyee2M9tV7YxOTPZl2g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@vitest/utils": "3.0.7", - "pathe": "^2.0.3" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/@vitest/snapshot": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-3.0.7.tgz", - "integrity": "sha512-eqTUryJWQN0Rtf5yqCGTQWsCFOQe4eNz5Twsu21xYEcnFJtMU5XvmG0vgebhdLlrHQTSq5p8vWHJIeJQV8ovsA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@vitest/pretty-format": "3.0.7", - "magic-string": "^0.30.17", - "pathe": "^2.0.3" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/@vitest/spy": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-3.0.7.tgz", - "integrity": "sha512-4T4WcsibB0B6hrKdAZTM37ekuyFZt2cGbEGd2+L0P8ov15J1/HUsUaqkXEQPNAWr4BtPPe1gI+FYfMHhEKfR8w==", - "dev": true, - "license": "MIT", - "dependencies": { - "tinyspy": "^3.0.2" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/@vitest/utils": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-3.0.7.tgz", - "integrity": "sha512-xePVpCRfooFX3rANQjwoditoXgWb1MaFbzmGuPP59MK6i13mrnDw/yEIyJudLeW6/38mCNcwCiJIGmpDPibAIg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@vitest/pretty-format": "3.0.7", - "loupe": "^3.1.3", - "tinyrainbow": "^2.0.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/ansi-colors": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", - "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/ansi-regex": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", - "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/ansi-styles": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", - "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", - "dev": true, - "license": "MIT", - "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/anymatch": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", - "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", - "dev": true, - "license": "ISC", - "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/argparse": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", - "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", - "dev": true, - "license": "Python-2.0" - }, - "node_modules/assertion-error": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-2.0.1.tgz", - "integrity": "sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - } - }, - "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "dev": true, - "license": "MIT" - }, - "node_modules/binary-extensions": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", - "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", - "dev": true, - "license": "MIT", - "dependencies": { - "balanced-match": "^1.0.0" - } - }, - "node_modules/braces": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", - "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", - "dev": true, - "license": "MIT", - "dependencies": { - "fill-range": "^7.1.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/browser-stdout": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz", - "integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==", - "dev": true, - "license": "ISC" - }, - "node_modules/cac": { - "version": "6.7.14", - "resolved": "https://registry.npmjs.org/cac/-/cac-6.7.14.tgz", - "integrity": "sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/camelcase": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", - "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/chai": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/chai/-/chai-5.2.0.tgz", - "integrity": "sha512-mCuXncKXk5iCLhfhwTc0izo0gtEmpz5CtG2y8GiOINBlMVS6v8TMRc5TaLWKS6692m9+dVVfzgeVxR5UxWHTYw==", - "dev": true, - "license": "MIT", - "dependencies": { - "assertion-error": "^2.0.1", - "check-error": "^2.1.1", - "deep-eql": "^5.0.1", - "loupe": "^3.1.0", - "pathval": "^2.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/chalk": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", - "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" - } - }, - "node_modules/chalk/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/check-error": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/check-error/-/check-error-2.1.1.tgz", - "integrity": "sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 16" - } - }, - "node_modules/chokidar": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", - "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", - "dev": true, - "license": "MIT", - "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - }, - "engines": { - "node": ">= 8.10.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - } - }, - "node_modules/cliui": { - "version": "8.0.1", - "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", - "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", - "dev": true, - "license": "ISC", - "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/cliui/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/cliui/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true, - "license": "MIT" - }, - "node_modules/cliui/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cliui/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/cliui/node_modules/wrap-ansi": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/color-convert": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "color-name": "~1.1.4" - }, - "engines": { - "node": ">=7.0.0" - } - }, - "node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "dev": true, - "license": "MIT" - }, - "node_modules/cross-spawn": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", - "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", - "dev": true, - "license": "MIT", - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/debug": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", - "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/decamelize": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz", - "integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/deep-eql": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-5.0.2.tgz", - "integrity": "sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/diff": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-5.2.0.tgz", - "integrity": "sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.3.1" - } - }, - "node_modules/eastasianwidth": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", - "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", - "dev": true, - "license": "MIT" - }, - "node_modules/emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", - "dev": true, - "license": "MIT" - }, - "node_modules/entities": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", - "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=0.12" - }, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" - } - }, - "node_modules/es-module-lexer": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.6.0.tgz", - "integrity": "sha512-qqnD1yMU6tk/jnaMosogGySTZP8YtUgAffA9nMN+E/rjxcfRQ6IEk7IiozUjgxKoFHBGjTLnrHB/YC45r/59EQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/esbuild": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", - "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=12" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.21.5", - "@esbuild/android-arm": "0.21.5", - "@esbuild/android-arm64": "0.21.5", - "@esbuild/android-x64": "0.21.5", - "@esbuild/darwin-arm64": "0.21.5", - "@esbuild/darwin-x64": "0.21.5", - "@esbuild/freebsd-arm64": "0.21.5", - "@esbuild/freebsd-x64": "0.21.5", - "@esbuild/linux-arm": "0.21.5", - "@esbuild/linux-arm64": "0.21.5", - "@esbuild/linux-ia32": "0.21.5", - "@esbuild/linux-loong64": "0.21.5", - "@esbuild/linux-mips64el": "0.21.5", - "@esbuild/linux-ppc64": "0.21.5", - "@esbuild/linux-riscv64": "0.21.5", - "@esbuild/linux-s390x": "0.21.5", - "@esbuild/linux-x64": "0.21.5", - "@esbuild/netbsd-x64": "0.21.5", - "@esbuild/openbsd-x64": "0.21.5", - "@esbuild/sunos-x64": "0.21.5", - "@esbuild/win32-arm64": "0.21.5", - "@esbuild/win32-ia32": "0.21.5", - "@esbuild/win32-x64": "0.21.5" - } - }, - "node_modules/escalade": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", - "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/estree-walker": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-3.0.3.tgz", - "integrity": "sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/estree": "^1.0.0" - } - }, - "node_modules/expect-type": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/expect-type/-/expect-type-1.2.0.tgz", - "integrity": "sha512-80F22aiJ3GLyVnS/B3HzgR6RelZVumzj9jkL0Rhz4h0xYbNW9PjlQz5h3J/SShErbXBc295vseR4/MIbVmUbeA==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": ">=12.0.0" - } - }, - "node_modules/fill-range": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", - "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", - "dev": true, - "license": "MIT", - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "license": "MIT", - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/flat": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", - "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", - "dev": true, - "license": "BSD-3-Clause", - "bin": { - "flat": "cli.js" - } - }, - "node_modules/foreground-child": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz", - "integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==", - "dev": true, - "license": "ISC", - "dependencies": { - "cross-spawn": "^7.0.6", - "signal-exit": "^4.0.1" - }, - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "dev": true, - "license": "ISC", - "engines": { - "node": "6.* || 8.* || >= 10.*" - } - }, - "node_modules/glob": { - "version": "10.4.5", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", - "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", - "dev": true, - "license": "ISC", - "dependencies": { - "foreground-child": "^3.1.0", - "jackspeak": "^3.1.2", - "minimatch": "^9.0.4", - "minipass": "^7.1.2", - "package-json-from-dist": "^1.0.0", - "path-scurry": "^1.11.1" - }, - "bin": { - "glob": "dist/esm/bin.mjs" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "license": "ISC", - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/glob/node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/happy-dom": { - "version": "17.1.9", - "resolved": "https://registry.npmjs.org/happy-dom/-/happy-dom-17.1.9.tgz", - "integrity": "sha512-HL26ajjMVe/wr3xlzjF0sCPCiAKaZJcIRFZHmG4yKHRJp4YAkHPG5X6GfWxCeDTpOmuHhNiOyNKUoZjjnm0tjw==", - "dev": true, - "license": "MIT", - "dependencies": { - "webidl-conversions": "^7.0.0", - "whatwg-mimetype": "^3.0.0" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/has-flag": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", - "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/he": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz", - "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==", - "dev": true, - "license": "MIT", - "bin": { - "he": "bin/he" - } - }, - "node_modules/is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, - "license": "MIT", - "dependencies": { - "binary-extensions": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/is-plain-obj": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz", - "integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/is-unicode-supported": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", - "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true, - "license": "ISC" - }, - "node_modules/jackspeak": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", - "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", - "dev": true, - "license": "BlueOak-1.0.0", - "dependencies": { - "@isaacs/cliui": "^8.0.2" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - }, - "optionalDependencies": { - "@pkgjs/parseargs": "^0.11.0" - } - }, - "node_modules/js-yaml": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", - "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", - "dev": true, - "license": "MIT", - "dependencies": { - "argparse": "^2.0.1" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/just-extend": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/just-extend/-/just-extend-6.2.0.tgz", - "integrity": "sha512-cYofQu2Xpom82S6qD778jBDpwvvy39s1l/hrYij2u9AMdQcGRpaBu6kY4mVhuno5kJVi1DAz4aiphA2WI1/OAw==", - "dev": true, - "license": "MIT" - }, - "node_modules/linkify-it": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.0.tgz", - "integrity": "sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "uc.micro": "^2.0.0" - } - }, - "node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "license": "MIT", - "dependencies": { - "p-locate": "^5.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/lodash.get": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", - "integrity": "sha512-z+Uw/vLuy6gQe8cfaFWD7p0wVv8fJl3mbzXh33RS+0oW2wvUqiRXiQ69gLWSLpgB5/6sU+r6BlQR0MBILadqTQ==", - "deprecated": "This package is deprecated. Use the optional chaining (?.) operator instead.", - "dev": true, - "license": "MIT" - }, - "node_modules/log-symbols": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", - "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", - "dev": true, - "license": "MIT", - "dependencies": { - "chalk": "^4.1.0", - "is-unicode-supported": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/loupe": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.1.3.tgz", - "integrity": "sha512-kkIp7XSkP78ZxJEsSxW3712C6teJVoeHHwgo9zJ380de7IYyJ2ISlxojcH2pC5OFLewESmnRi/+XCDIEEVyoug==", - "dev": true, - "license": "MIT" - }, - "node_modules/lru-cache": { - "version": "10.4.3", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", - "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", - "dev": true, - "license": "ISC" - }, - "node_modules/lunr": { - "version": "2.3.9", - "resolved": "https://registry.npmjs.org/lunr/-/lunr-2.3.9.tgz", - "integrity": "sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==", - "dev": true, - "license": "MIT" - }, - "node_modules/magic-string": { - "version": "0.30.17", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz", - "integrity": "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.0" - } - }, - "node_modules/markdown-it": { - "version": "14.1.0", - "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.1.0.tgz", - "integrity": "sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==", - "dev": true, - "license": "MIT", - "dependencies": { - "argparse": "^2.0.1", - "entities": "^4.4.0", - "linkify-it": "^5.0.0", - "mdurl": "^2.0.0", - "punycode.js": "^2.3.1", - "uc.micro": "^2.1.0" - }, - "bin": { - "markdown-it": "bin/markdown-it.mjs" - } - }, - "node_modules/mdurl": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-2.0.0.tgz", - "integrity": "sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==", - "dev": true, - "license": "MIT" - }, - "node_modules/minimatch": { - "version": "5.1.6", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", - "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/minipass": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", - "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=16 || 14 >=14.17" - } - }, - "node_modules/mocha": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/mocha/-/mocha-11.1.0.tgz", - "integrity": "sha512-8uJR5RTC2NgpY3GrYcgpZrsEd9zKbPDpob1RezyR2upGHRQtHWofmzTMzTMSV6dru3tj5Ukt0+Vnq1qhFEEwAg==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-colors": "^4.1.3", - "browser-stdout": "^1.3.1", - "chokidar": "^3.5.3", - "debug": "^4.3.5", - "diff": "^5.2.0", - "escape-string-regexp": "^4.0.0", - "find-up": "^5.0.0", - "glob": "^10.4.5", - "he": "^1.2.0", - "js-yaml": "^4.1.0", - "log-symbols": "^4.1.0", - "minimatch": "^5.1.6", - "ms": "^2.1.3", - "serialize-javascript": "^6.0.2", - "strip-json-comments": "^3.1.1", - "supports-color": "^8.1.1", - "workerpool": "^6.5.1", - "yargs": "^17.7.2", - "yargs-parser": "^21.1.1", - "yargs-unparser": "^2.0.0" - }, - "bin": { - "_mocha": "bin/_mocha", - "mocha": "bin/mocha.js" - }, - "engines": { - "node": "^18.18.0 || ^20.9.0 || >=21.1.0" - } - }, - "node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true, - "license": "MIT" - }, - "node_modules/nanoid": { - "version": "3.3.8", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.8.tgz", - "integrity": "sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "bin": { - "nanoid": "bin/nanoid.cjs" - }, - "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" - } - }, - "node_modules/nise": { - "version": "6.1.1", - "resolved": "https://registry.npmjs.org/nise/-/nise-6.1.1.tgz", - "integrity": "sha512-aMSAzLVY7LyeM60gvBS423nBmIPP+Wy7St7hsb+8/fc1HmeoHJfLO8CKse4u3BtOZvQLJghYPI2i/1WZrEj5/g==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "@sinonjs/commons": "^3.0.1", - "@sinonjs/fake-timers": "^13.0.1", - "@sinonjs/text-encoding": "^0.7.3", - "just-extend": "^6.2.0", - "path-to-regexp": "^8.1.0" - } - }, - "node_modules/normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/p-limit": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", - "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "yocto-queue": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "license": "MIT", - "dependencies": { - "p-limit": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/package-json-from-dist": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", - "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", - "dev": true, - "license": "BlueOak-1.0.0" - }, - "node_modules/path-exists": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", - "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/path-key": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", - "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/path-scurry": { - "version": "1.11.1", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", - "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", - "dev": true, - "license": "BlueOak-1.0.0", - "dependencies": { - "lru-cache": "^10.2.0", - "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" - }, - "engines": { - "node": ">=16 || 14 >=14.18" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/path-to-regexp": { - "version": "8.2.0", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.2.0.tgz", - "integrity": "sha512-TdrF7fW9Rphjq4RjrW0Kp2AW0Ahwu9sRGTkS6bvDi0SCwZlEZYmcfDbEsTz8RVk0EHIS/Vd1bv3JhG+1xZuAyQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=16" - } - }, - "node_modules/pathe": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", - "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", - "dev": true, - "license": "MIT" - }, - "node_modules/pathval": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/pathval/-/pathval-2.0.0.tgz", - "integrity": "sha512-vE7JKRyES09KiunauX7nd2Q9/L7lhok4smP9RZTDeD4MVs72Dp2qNFVz39Nz5a0FVEW0BJR6C0DYrq6unoziZA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 14.16" - } - }, - "node_modules/picocolors": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", - "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", - "dev": true, - "license": "ISC" - }, - "node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/postcss": { - "version": "8.5.3", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.3.tgz", - "integrity": "sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "nanoid": "^3.3.8", - "picocolors": "^1.1.1", - "source-map-js": "^1.2.1" - }, - "engines": { - "node": "^10 || ^12 || >=14" - } - }, - "node_modules/promises-aplus-tests": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/promises-aplus-tests/-/promises-aplus-tests-2.1.2.tgz", - "integrity": "sha512-XiDfjQqx+rHLof8CU9xPOMLsjiXXxr3fkjE7WJjUzXttffB8K/nsnNsPTcwS4VvHliSjGVsYVqIjFeTHw53f5w==", - "dev": true, - "license": "WTFPL", - "dependencies": { - "mocha": "^2.5.3", - "sinon": "^1.10.3", - "underscore": "~1.8.3" - }, - "bin": { - "promises-aplus-tests": "lib/cli.js" - } - }, - "node_modules/punycode.js": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/punycode.js/-/punycode.js-2.3.1.tgz", - "integrity": "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/randombytes": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", - "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "safe-buffer": "^5.1.0" - } - }, - "node_modules/readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dev": true, - "license": "MIT", - "dependencies": { - "picomatch": "^2.2.1" - }, - "engines": { - "node": ">=8.10.0" - } - }, - "node_modules/require-directory": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", - "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/rimraf": { - "version": "5.0.10", - "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.10.tgz", - "integrity": "sha512-l0OE8wL34P4nJH/H2ffoaniAokM2qSmrtXHmlpvYr5AVVX8msAyW0l8NVJFDxlSK4u3Uh/f41cQheDVdnYijwQ==", - "dev": true, - "license": "ISC", - "dependencies": { - "glob": "^10.3.7" - }, - "bin": { - "rimraf": "dist/esm/bin.mjs" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/rollup": { - "version": "4.34.9", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.34.9.tgz", - "integrity": "sha512-nF5XYqWWp9hx/LrpC8sZvvvmq0TeTjQgaZHYmAgwysT9nh8sWnZhBnM8ZyVbbJFIQBLwHDNoMqsBZBbUo4U8sQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/estree": "1.0.6" - }, - "bin": { - "rollup": "dist/bin/rollup" - }, - "engines": { - "node": ">=18.0.0", - "npm": ">=8.0.0" - }, - "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.34.9", - "@rollup/rollup-android-arm64": "4.34.9", - "@rollup/rollup-darwin-arm64": "4.34.9", - "@rollup/rollup-darwin-x64": "4.34.9", - "@rollup/rollup-freebsd-arm64": "4.34.9", - "@rollup/rollup-freebsd-x64": "4.34.9", - "@rollup/rollup-linux-arm-gnueabihf": "4.34.9", - "@rollup/rollup-linux-arm-musleabihf": "4.34.9", - "@rollup/rollup-linux-arm64-gnu": "4.34.9", - "@rollup/rollup-linux-arm64-musl": "4.34.9", - "@rollup/rollup-linux-loongarch64-gnu": "4.34.9", - "@rollup/rollup-linux-powerpc64le-gnu": "4.34.9", - "@rollup/rollup-linux-riscv64-gnu": "4.34.9", - "@rollup/rollup-linux-s390x-gnu": "4.34.9", - "@rollup/rollup-linux-x64-gnu": "4.34.9", - "@rollup/rollup-linux-x64-musl": "4.34.9", - "@rollup/rollup-win32-arm64-msvc": "4.34.9", - "@rollup/rollup-win32-ia32-msvc": "4.34.9", - "@rollup/rollup-win32-x64-msvc": "4.34.9", - "fsevents": "~2.3.2" - } - }, - "node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, - "node_modules/serialize-javascript": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", - "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "randombytes": "^2.1.0" - } - }, - "node_modules/shebang-command": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", - "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", - "dev": true, - "license": "MIT", - "dependencies": { - "shebang-regex": "^3.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/shebang-regex": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", - "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/siginfo": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/siginfo/-/siginfo-2.0.0.tgz", - "integrity": "sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==", - "dev": true, - "license": "ISC" - }, - "node_modules/signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/sinon": { - "version": "19.0.2", - "resolved": "https://registry.npmjs.org/sinon/-/sinon-19.0.2.tgz", - "integrity": "sha512-euuToqM+PjO4UgXeLETsfQiuoyPXlqFezr6YZDFwHR3t4qaX0fZUe1MfPMznTL5f8BWrVS89KduLdMUsxFCO6g==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "@sinonjs/commons": "^3.0.1", - "@sinonjs/fake-timers": "^13.0.2", - "@sinonjs/samsam": "^8.0.1", - "diff": "^7.0.0", - "nise": "^6.1.1", - "supports-color": "^7.2.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/sinon" - } - }, - "node_modules/sinon/node_modules/diff": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/diff/-/diff-7.0.0.tgz", - "integrity": "sha512-PJWHUb1RFevKCwaFA9RlG5tCd+FO5iRh9A8HEtkmBH2Li03iJriB6m6JIN4rGz3K3JLawI7/veA1xzRKP6ISBw==", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.3.1" - } - }, - "node_modules/sinon/node_modules/supports-color": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", - "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", - "dev": true, - "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/source-map-js": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", - "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/stackback": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/stackback/-/stackback-0.0.2.tgz", - "integrity": "sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==", - "dev": true, - "license": "MIT" - }, - "node_modules/std-env": { - "version": "3.8.1", - "resolved": "https://registry.npmjs.org/std-env/-/std-env-3.8.1.tgz", - "integrity": "sha512-vj5lIj3Mwf9D79hBkltk5qmkFI+biIKWS2IBxEyEU3AX1tUf7AoL8nSazCOiiqQsGKIq01SClsKEzweu34uwvA==", - "dev": true, - "license": "MIT" - }, - "node_modules/string-width": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", - "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", - "dev": true, - "license": "MIT", - "dependencies": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/string-width-cjs": { - "name": "string-width", - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/string-width-cjs/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/string-width-cjs/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true, - "license": "MIT" - }, - "node_modules/string-width-cjs/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "node_modules/strip-ansi-cjs": { - "name": "strip-ansi", - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-ansi-cjs/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/strip-json-comments": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz", - "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/supports-color": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", - "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/supports-color?sponsor=1" - } - }, - "node_modules/tinybench": { - "version": "2.9.0", - "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.9.0.tgz", - "integrity": "sha512-0+DUvqWMValLmha6lr4kD8iAMK1HzV0/aKnCtWb9v9641TnP/MFb7Pc2bxoxQjTXAErryXVgUOfv2YqNllqGeg==", - "dev": true, - "license": "MIT" - }, - "node_modules/tinyexec": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-0.3.2.tgz", - "integrity": "sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==", - "dev": true, - "license": "MIT" - }, - "node_modules/tinypool": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/tinypool/-/tinypool-1.0.2.tgz", - "integrity": "sha512-al6n+QEANGFOMf/dmUMsuS5/r9B06uwlyNjZZql/zv8J7ybHCgoihBNORZCY2mzUuAnomQa2JdhyHKzZxPCrFA==", - "dev": true, - "license": "MIT", - "engines": { - "node": "^18.0.0 || >=20.0.0" - } - }, - "node_modules/tinyrainbow": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/tinyrainbow/-/tinyrainbow-2.0.0.tgz", - "integrity": "sha512-op4nsTR47R6p0vMUUoYl/a+ljLFVtlfaXkLQmqfLR1qHma1h/ysYk4hEXZ880bf2CYgTskvTa/e196Vd5dDQXw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/tinyspy": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-3.0.2.tgz", - "integrity": "sha512-n1cw8k1k0x4pgA2+9XrOkFydTerNcJ1zWCO5Nn9scWHTD+5tp8dghT2x1uduQePZTZgd3Tupf+x9BxJjeJi77Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/type-detect": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", - "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/typedoc": { - "version": "0.27.9", - "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.27.9.tgz", - "integrity": "sha512-/z585740YHURLl9DN2jCWe6OW7zKYm6VoQ93H0sxZ1cwHQEQrUn5BJrEnkWhfzUdyO+BLGjnKUZ9iz9hKloFDw==", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@gerrit0/mini-shiki": "^1.24.0", - "lunr": "^2.3.9", - "markdown-it": "^14.1.0", - "minimatch": "^9.0.5", - "yaml": "^2.6.1" - }, - "bin": { - "typedoc": "bin/typedoc" - }, - "engines": { - "node": ">= 18" - }, - "peerDependencies": { - "typescript": "5.0.x || 5.1.x || 5.2.x || 5.3.x || 5.4.x || 5.5.x || 5.6.x || 5.7.x || 5.8.x" - } - }, - "node_modules/typedoc-plugin-markdown": { - "version": "4.4.2", - "resolved": "https://registry.npmjs.org/typedoc-plugin-markdown/-/typedoc-plugin-markdown-4.4.2.tgz", - "integrity": "sha512-kJVkU2Wd+AXQpyL6DlYXXRrfNrHrEIUgiABWH8Z+2Lz5Sq6an4dQ/hfvP75bbokjNDUskOdFlEEm/0fSVyC7eg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 18" - }, - "peerDependencies": { - "typedoc": "0.27.x" - } - }, - "node_modules/typedoc-plugin-mdn-links": { - "version": "4.0.15", - "resolved": "https://registry.npmjs.org/typedoc-plugin-mdn-links/-/typedoc-plugin-mdn-links-4.0.15.tgz", - "integrity": "sha512-ZdZLBVMSJzHckVJt902j5xIbujza5Z8l802sXd6G38bOZS6R+ZkjB6RmSdYdKlxiEle8Yqjxn4lZ2NZIeUe2lA==", - "dev": true, - "license": "MIT", - "peerDependencies": { - "typedoc": "0.26.x || 0.27.x" - } - }, - "node_modules/typedoc-plugin-missing-exports": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/typedoc-plugin-missing-exports/-/typedoc-plugin-missing-exports-3.1.0.tgz", - "integrity": "sha512-Sogbaj+qDa21NjB3SlIw4JXSwmcl/WOjwiPNaVEcPhpNG/MiRTtpwV81cT7h1cbu9StpONFPbddYWR0KV/fTWA==", - "dev": true, - "license": "MIT", - "peerDependencies": { - "typedoc": "0.26.x || 0.27.x" - } - }, - "node_modules/typedoc/node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", - "dev": true, - "license": "ISC", - "dependencies": { - "brace-expansion": "^2.0.1" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/typescript": { - "version": "5.8.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.8.2.tgz", - "integrity": "sha512-aJn6wq13/afZp/jT9QZmwEjDqqvSGp1VT5GVg+f/t6/oVyrgXM6BY1h9BRh/O5p3PlUPAe+WuiEZOmb/49RqoQ==", - "dev": true, - "license": "Apache-2.0", - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=14.17" - } - }, - "node_modules/uc.micro": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-2.1.0.tgz", - "integrity": "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==", - "dev": true, - "license": "MIT" - }, - "node_modules/underscore": { - "version": "1.13.7", - "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.13.7.tgz", - "integrity": "sha512-GMXzWtsc57XAtguZgaQViUOzs0KTkk8ojr3/xAxXLITqf/3EMwxC0inyETfDFjH/Krbhuep0HNbbjI9i/q3F3g==", - "dev": true, - "license": "MIT" - }, - "node_modules/vite": { - "version": "5.4.14", - "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.14.tgz", - "integrity": "sha512-EK5cY7Q1D8JNhSaPKVK4pwBFvaTmZxEnoKXLG/U9gmdDcihQGNzFlgIvaxezFR4glP1LsuiedwMBqCXH3wZccA==", - "dev": true, - "license": "MIT", - "dependencies": { - "esbuild": "^0.21.3", - "postcss": "^8.4.43", - "rollup": "^4.20.0" - }, - "bin": { - "vite": "bin/vite.js" - }, - "engines": { - "node": "^18.0.0 || >=20.0.0" - }, - "funding": { - "url": "https://github.com/vitejs/vite?sponsor=1" - }, - "optionalDependencies": { - "fsevents": "~2.3.3" - }, - "peerDependencies": { - "@types/node": "^18.0.0 || >=20.0.0", - "less": "*", - "lightningcss": "^1.21.0", - "sass": "*", - "sass-embedded": "*", - "stylus": "*", - "sugarss": "*", - "terser": "^5.4.0" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - }, - "less": { - "optional": true - }, - "lightningcss": { - "optional": true - }, - "sass": { - "optional": true - }, - "sass-embedded": { - "optional": true - }, - "stylus": { - "optional": true - }, - "sugarss": { - "optional": true - }, - "terser": { - "optional": true - } - } - }, - "node_modules/vite-node": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-3.0.7.tgz", - "integrity": "sha512-2fX0QwX4GkkkpULXdT1Pf4q0tC1i1lFOyseKoonavXUNlQ77KpW2XqBGGNIm/J4Ows4KxgGJzDguYVPKwG/n5A==", - "dev": true, - "license": "MIT", - "dependencies": { - "cac": "^6.7.14", - "debug": "^4.4.0", - "es-module-lexer": "^1.6.0", - "pathe": "^2.0.3", - "vite": "^5.0.0 || ^6.0.0" - }, - "bin": { - "vite-node": "vite-node.mjs" - }, - "engines": { - "node": "^18.0.0 || ^20.0.0 || >=22.0.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" - } - }, - "node_modules/vitest": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/vitest/-/vitest-3.0.7.tgz", - "integrity": "sha512-IP7gPK3LS3Fvn44x30X1dM9vtawm0aesAa2yBIZ9vQf+qB69NXC5776+Qmcr7ohUXIQuLhk7xQR0aSUIDPqavg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@vitest/expect": "3.0.7", - "@vitest/mocker": "3.0.7", - "@vitest/pretty-format": "^3.0.7", - "@vitest/runner": "3.0.7", - "@vitest/snapshot": "3.0.7", - "@vitest/spy": "3.0.7", - "@vitest/utils": "3.0.7", - "chai": "^5.2.0", - "debug": "^4.4.0", - "expect-type": "^1.1.0", - "magic-string": "^0.30.17", - "pathe": "^2.0.3", - "std-env": "^3.8.0", - "tinybench": "^2.9.0", - "tinyexec": "^0.3.2", - "tinypool": "^1.0.2", - "tinyrainbow": "^2.0.0", - "vite": "^5.0.0 || ^6.0.0", - "vite-node": "3.0.7", - "why-is-node-running": "^2.3.0" - }, - "bin": { - "vitest": "vitest.mjs" - }, - "engines": { - "node": "^18.0.0 || ^20.0.0 || >=22.0.0" - }, - "funding": { - "url": "https://opencollective.com/vitest" - }, - "peerDependencies": { - "@edge-runtime/vm": "*", - "@types/debug": "^4.1.12", - "@types/node": "^18.0.0 || ^20.0.0 || >=22.0.0", - "@vitest/browser": "3.0.7", - "@vitest/ui": "3.0.7", - "happy-dom": "*", - "jsdom": "*" - }, - "peerDependenciesMeta": { - "@edge-runtime/vm": { - "optional": true - }, - "@types/debug": { - "optional": true - }, - "@types/node": { - "optional": true - }, - "@vitest/browser": { - "optional": true - }, - "@vitest/ui": { - "optional": true - }, - "happy-dom": { - "optional": true - }, - "jsdom": { - "optional": true - } - } - }, - "node_modules/webidl-conversions": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", - "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=12" - } - }, - "node_modules/whatwg-mimetype": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-3.0.0.tgz", - "integrity": "sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - } - }, - "node_modules/which": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", - "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", - "dev": true, - "license": "ISC", - "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "node-which": "bin/node-which" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/why-is-node-running": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/why-is-node-running/-/why-is-node-running-2.3.0.tgz", - "integrity": "sha512-hUrmaWBdVDcxvYqnyh09zunKzROWjbZTiNy8dBEjkS7ehEDQibXJ7XvlmtbwuTclUiIyN+CyXQD4Vmko8fNm8w==", - "dev": true, - "license": "MIT", - "dependencies": { - "siginfo": "^2.0.0", - "stackback": "0.0.2" - }, - "bin": { - "why-is-node-running": "cli.js" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/workerpool": { - "version": "6.5.1", - "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.5.1.tgz", - "integrity": "sha512-Fs4dNYcsdpYSAfVxhnl1L5zTksjvOJxtC5hzMNl+1t9B8hTJTdKDyZ5ju7ztgPy+ft9tBFXoOlDNiOT9WUXZlA==", - "dev": true, - "license": "Apache-2.0" - }, - "node_modules/wrap-ansi": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", - "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^6.1.0", - "string-width": "^5.0.1", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/wrap-ansi-cjs": { - "name": "wrap-ansi", - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", - "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/wrap-ansi-cjs/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true, - "license": "MIT" - }, - "node_modules/wrap-ansi-cjs/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/wrap-ansi-cjs/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/wrap-ansi/node_modules/ansi-styles": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/y18n": { - "version": "5.0.8", - "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", - "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=10" - } - }, - "node_modules/yaml": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.7.0.tgz", - "integrity": "sha512-+hSoy/QHluxmC9kCIJyL/uyFmLmc+e5CFR5Wa+bpIhIj85LVb9ZH2nVnqrHoSvKogwODv0ClqZkmiSSaIH5LTA==", - "dev": true, - "license": "ISC", - "bin": { - "yaml": "bin.mjs" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/yargs": { - "version": "17.7.2", - "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", - "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", - "dev": true, - "license": "MIT", - "dependencies": { - "cliui": "^8.0.1", - "escalade": "^3.1.1", - "get-caller-file": "^2.0.5", - "require-directory": "^2.1.1", - "string-width": "^4.2.3", - "y18n": "^5.0.5", - "yargs-parser": "^21.1.1" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/yargs-parser": { - "version": "21.1.1", - "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", - "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=12" - } - }, - "node_modules/yargs-unparser": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz", - "integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==", - "dev": true, - "license": "MIT", - "dependencies": { - "camelcase": "^6.0.0", - "decamelize": "^4.0.0", - "flat": "^5.0.2", - "is-plain-obj": "^2.1.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/yargs/node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/yargs/node_modules/emoji-regex": { - "version": "8.0.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", - "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "dev": true, - "license": "MIT" - }, - "node_modules/yargs/node_modules/string-width": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", - "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", - "dev": true, - "license": "MIT", - "dependencies": { - "emoji-regex": "^8.0.0", - "is-fullwidth-code-point": "^3.0.0", - "strip-ansi": "^6.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/yargs/node_modules/strip-ansi": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", - "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-regex": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/yocto-queue": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", - "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - } - } -} diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/package.json b/v3/internal/runtime/desktop/@wailsio/runtime/package.json deleted file mode 100644 index db253556a..000000000 --- a/v3/internal/runtime/desktop/@wailsio/runtime/package.json +++ /dev/null @@ -1,69 +0,0 @@ -{ - "name": "@wailsio/runtime", - "type": "module", - "version": "3.0.0-alpha.80", - "description": "Wails Runtime", - "types": "types/index.d.ts", - "exports": { - ".": { - "types": "./types/index.d.ts", - "default": "./dist/index.js" - }, - "./plugins/*": { - "types": "./types/plugins/*.d.ts", - "default": "./dist/plugins/*.js" - } - }, - "repository": { - "type": "git", - "url": "git+https://github.com/wailsapp/wails.git", - "directory": "v3/internal/runtime/desktop/@wailsio/runtime" - }, - "author": "The Wails Team", - "license": "MIT", - "homepage": "https://v3.wails.io", - "bugs": { - "url": "https://github.com/wailsapp/wails/issues" - }, - "files": [ - "./dist", - "./types" - ], - "sideEffects": [ - "./dist/index.js", - "./dist/contextmenu.js", - "./dist/drag.js" - ], - "scripts": { - "check": "npx tsc --noEmit", - "test": "npx vitest run", - "clean": "npx rimraf ./dist ./docs ./types ./tsconfig.tsbuildinfo", - "generate:events": "task generate:events", - "generate": "npm run generate:events", - "prebuild": "npm run clean && npm run generate", - "build:code": "npx tsc", - "build:docs": "npx typedoc --gitRevision v3-alpha --plugin typedoc-plugin-mdn-links --plugin typedoc-plugin-missing-exports ./src/index.ts", - "build:docs:md": "npx typedoc --gitRevision v3-alpha --plugin typedoc-plugin-markdown --plugin typedoc-plugin-mdn-links --plugin typedoc-plugin-missing-exports ./src/index.ts", - "build": "npm run build:code & npm run build:docs & wait", - "prepack": "npm run build" - }, - "devDependencies": { - "happy-dom": "^17.1.1", - "promises-aplus-tests": "2.1.2", - "rimraf": "^5.0.5", - "typedoc": "^0.27.7", - "typedoc-plugin-markdown": "^4.4.2", - "typedoc-plugin-mdn-links": "^4.0.13", - "typedoc-plugin-missing-exports": "^3.1.0", - "typescript": "^5.7.3", - "vite": "^5.2.0", - "vitest": "^3.0.6" - }, - "overrides": { - "promises-aplus-tests": { - "mocha": "^11.1.0", - "sinon": "^19.0.2", - "underscore": "^1.13.7" - } - } -} diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/src/application.ts b/v3/internal/runtime/desktop/@wailsio/runtime/src/application.ts deleted file mode 100644 index 57a41ac9e..000000000 --- a/v3/internal/runtime/desktop/@wailsio/runtime/src/application.ts +++ /dev/null @@ -1,37 +0,0 @@ -/* - _ __ _ __ -| | / /___ _(_) /____ -| | /| / / __ `/ / / ___/ -| |/ |/ / /_/ / / (__ ) -|__/|__/\__,_/_/_/____/ -The electron alternative for Go -(c) Lea Anthony 2019-present -*/ - -import { newRuntimeCaller, objectNames } from "./runtime.js"; -const call = newRuntimeCaller(objectNames.Application); - -const HideMethod = 0; -const ShowMethod = 1; -const QuitMethod = 2; - -/** - * Hides a certain method by calling the HideMethod function. - */ -export function Hide(): Promise { - return call(HideMethod); -} - -/** - * Calls the ShowMethod and returns the result. - */ -export function Show(): Promise { - return call(ShowMethod); -} - -/** - * Calls the QuitMethod to terminate the program. - */ -export function Quit(): Promise { - return call(QuitMethod); -} diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/src/browser.ts b/v3/internal/runtime/desktop/@wailsio/runtime/src/browser.ts deleted file mode 100644 index 465310d3d..000000000 --- a/v3/internal/runtime/desktop/@wailsio/runtime/src/browser.ts +++ /dev/null @@ -1,24 +0,0 @@ -/* - _ __ _ __ -| | / /___ _(_) /____ -| | /| / / __ `/ / / ___/ -| |/ |/ / /_/ / / (__ ) -|__/|__/\__,_/_/_/____/ -The electron alternative for Go -(c) Lea Anthony 2019-present -*/ - -import { newRuntimeCaller, objectNames } from "./runtime.js"; - -const call = newRuntimeCaller(objectNames.Browser); - -const BrowserOpenURL = 0; - -/** - * Open a browser window to the given URL. - * - * @param url - The URL to open - */ -export function OpenURL(url: string | URL): Promise { - return call(BrowserOpenURL, {url: url.toString()}); -} diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/src/callable.ts b/v3/internal/runtime/desktop/@wailsio/runtime/src/callable.ts deleted file mode 100644 index e8e2e4087..000000000 --- a/v3/internal/runtime/desktop/@wailsio/runtime/src/callable.ts +++ /dev/null @@ -1,125 +0,0 @@ -// Source: https://github.com/inspect-js/is-callable - -// The MIT License (MIT) -// -// Copyright (c) 2015 Jordan Harband -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -var fnToStr = Function.prototype.toString; -var reflectApply: typeof Reflect.apply | false | null = typeof Reflect === 'object' && Reflect !== null && Reflect.apply; -var badArrayLike: any; -var isCallableMarker: any; -if (typeof reflectApply === 'function' && typeof Object.defineProperty === 'function') { - try { - badArrayLike = Object.defineProperty({}, 'length', { - get: function () { - throw isCallableMarker; - } - }); - isCallableMarker = {}; - // eslint-disable-next-line no-throw-literal - reflectApply(function () { throw 42; }, null, badArrayLike); - } catch (_) { - if (_ !== isCallableMarker) { - reflectApply = null; - } - } -} else { - reflectApply = null; -} - -var constructorRegex = /^\s*class\b/; -var isES6ClassFn = function isES6ClassFunction(value: any): boolean { - try { - var fnStr = fnToStr.call(value); - return constructorRegex.test(fnStr); - } catch (e) { - return false; // not a function - } -}; - -var tryFunctionObject = function tryFunctionToStr(value: any): boolean { - try { - if (isES6ClassFn(value)) { return false; } - fnToStr.call(value); - return true; - } catch (e) { - return false; - } -}; -var toStr = Object.prototype.toString; -var objectClass = '[object Object]'; -var fnClass = '[object Function]'; -var genClass = '[object GeneratorFunction]'; -var ddaClass = '[object HTMLAllCollection]'; // IE 11 -var ddaClass2 = '[object HTML document.all class]'; -var ddaClass3 = '[object HTMLCollection]'; // IE 9-10 -var hasToStringTag = typeof Symbol === 'function' && !!Symbol.toStringTag; // better: use `has-tostringtag` - -var isIE68 = !(0 in [,]); // eslint-disable-line no-sparse-arrays, comma-spacing - -var isDDA: (value: any) => boolean = function isDocumentDotAll() { return false; }; -if (typeof document === 'object') { - // Firefox 3 canonicalizes DDA to undefined when it's not accessed directly - var all = document.all; - if (toStr.call(all) === toStr.call(document.all)) { - isDDA = function isDocumentDotAll(value) { - /* globals document: false */ - // in IE 6-8, typeof document.all is "object" and it's truthy - if ((isIE68 || !value) && (typeof value === 'undefined' || typeof value === 'object')) { - try { - var str = toStr.call(value); - return ( - str === ddaClass - || str === ddaClass2 - || str === ddaClass3 // opera 12.16 - || str === objectClass // IE 6-8 - ) && value('') == null; // eslint-disable-line eqeqeq - } catch (e) { /**/ } - } - return false; - }; - } -} - -function isCallableRefApply(value: T | unknown): value is (...args: any[]) => any { - if (isDDA(value)) { return true; } - if (!value) { return false; } - if (typeof value !== 'function' && typeof value !== 'object') { return false; } - try { - (reflectApply as any)(value, null, badArrayLike); - } catch (e) { - if (e !== isCallableMarker) { return false; } - } - return !isES6ClassFn(value) && tryFunctionObject(value); -} - -function isCallableNoRefApply(value: T | unknown): value is (...args: any[]) => any { - if (isDDA(value)) { return true; } - if (!value) { return false; } - if (typeof value !== 'function' && typeof value !== 'object') { return false; } - if (hasToStringTag) { return tryFunctionObject(value); } - if (isES6ClassFn(value)) { return false; } - var strClass = toStr.call(value); - if (strClass !== fnClass && strClass !== genClass && !(/^\[object HTML/).test(strClass)) { return false; } - return tryFunctionObject(value); -}; - -export default reflectApply ? isCallableRefApply : isCallableNoRefApply; diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/src/calls.ts b/v3/internal/runtime/desktop/@wailsio/runtime/src/calls.ts deleted file mode 100644 index c80529857..000000000 --- a/v3/internal/runtime/desktop/@wailsio/runtime/src/calls.ts +++ /dev/null @@ -1,147 +0,0 @@ -/* - _ __ _ __ -| | / /___ _(_) /____ -| | /| / / __ `/ / / ___/ -| |/ |/ / /_/ / / (__ ) -|__/|__/\__,_/_/_/____/ -The electron alternative for Go -(c) Lea Anthony 2019-present -*/ - -import { CancellablePromise, type CancellablePromiseWithResolvers } from "./cancellable.js"; -import { newRuntimeCaller, objectNames } from "./runtime.js"; -import { nanoid } from "./nanoid.js"; - -// Setup -window._wails = window._wails || {}; - -type PromiseResolvers = Omit, "promise" | "oncancelled"> - -const call = newRuntimeCaller(objectNames.Call); -const cancelCall = newRuntimeCaller(objectNames.CancelCall); -const callResponses = new Map(); - -const CallBinding = 0; -const CancelMethod = 0 - -/** - * Holds all required information for a binding call. - * May provide either a method ID or a method name, but not both. - */ -export type CallOptions = { - /** The numeric ID of the bound method to call. */ - methodID: number; - /** The fully qualified name of the bound method to call. */ - methodName?: never; - /** Arguments to be passed into the bound method. */ - args: any[]; -} | { - /** The numeric ID of the bound method to call. */ - methodID?: never; - /** The fully qualified name of the bound method to call. */ - methodName: string; - /** Arguments to be passed into the bound method. */ - args: any[]; -}; - -/** - * Exception class that will be thrown in case the bound method returns an error. - * The value of the {@link RuntimeError#name} property is "RuntimeError". - */ -export class RuntimeError extends Error { - /** - * Constructs a new RuntimeError instance. - * @param message - The error message. - * @param options - Options to be forwarded to the Error constructor. - */ - constructor(message?: string, options?: ErrorOptions) { - super(message, options); - this.name = "RuntimeError"; - } -} - -/** - * Generates a unique ID using the nanoid library. - * - * @returns A unique ID that does not exist in the callResponses set. - */ -function generateID(): string { - let result; - do { - result = nanoid(); - } while (callResponses.has(result)); - return result; -} - -/** - * Call a bound method according to the given call options. - * - * In case of failure, the returned promise will reject with an exception - * among ReferenceError (unknown method), TypeError (wrong argument count or type), - * {@link RuntimeError} (method returned an error), or other (network or internal errors). - * The exception might have a "cause" field with the value returned - * by the application- or service-level error marshaling functions. - * - * @param options - A method call descriptor. - * @returns The result of the call. - */ -export function Call(options: CallOptions): CancellablePromise { - const id = generateID(); - - const result = CancellablePromise.withResolvers(); - callResponses.set(id, { resolve: result.resolve, reject: result.reject }); - - const request = call(CallBinding, Object.assign({ "call-id": id }, options)); - let running = true; - - request.then((res) => { - running = false; - callResponses.delete(id); - result.resolve(res); - }, (err) => { - running = false; - callResponses.delete(id); - result.reject(err); - }); - - const cancel = () => { - callResponses.delete(id); - return cancelCall(CancelMethod, {"call-id": id}).catch((err) => { - console.error("Error while requesting binding call cancellation:", err); - }); - }; - - result.oncancelled = () => { - if (running) { - return cancel(); - } else { - return request.then(cancel); - } - }; - - return result.promise; -} - -/** - * Calls a bound method by name with the specified arguments. - * See {@link Call} for details. - * - * @param methodName - The name of the method in the format 'package.struct.method'. - * @param args - The arguments to pass to the method. - * @returns The result of the method call. - */ -export function ByName(methodName: string, ...args: any[]): CancellablePromise { - return Call({ methodName, args }); -} - -/** - * Calls a method by its numeric ID with the specified arguments. - * See {@link Call} for details. - * - * @param methodID - The ID of the method to call. - * @param args - The arguments to pass to the method. - * @return The result of the method call. - */ -export function ByID(methodID: number, ...args: any[]): CancellablePromise { - return Call({ methodID, args }); -} diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/src/cancellable.test.js b/v3/internal/runtime/desktop/@wailsio/runtime/src/cancellable.test.js deleted file mode 100644 index b618c1459..000000000 --- a/v3/internal/runtime/desktop/@wailsio/runtime/src/cancellable.test.js +++ /dev/null @@ -1,431 +0,0 @@ -import * as util from "node:util"; -import { describe, it, beforeEach, afterEach, assert, expect, vi } from "vitest"; -import { CancelError, CancellablePromise, CancelledRejectionError } from "./cancellable"; - -// TODO: In order of importance: -// TODO: test cancellation of subpromises the main promise resolves to. -// TODO: test cancellation of promise chains built by calling then() and friends: -// - all promises up the chain should be cancelled; -// - rejection handlers should be always executed with the CancelError of their parent promise in the chain; -// - promises returned from rejection handlers should be cancelled too; -// - if a rejection handler throws or returns a promise that ultimately rejects, -// it should be reported as an unhandled rejection, -// - unless it is a CancelError with the same reason given for cancelling the returned promise. -// TODO: test multiple calls to cancel() (second and later should have no effect). -// TODO: test static factory methods and their cancellation support. - -let expectedUnhandled = new Map(); - -process.on('unhandledRejection', function (error, promise) { - let reason = error; - if (reason instanceof CancelledRejectionError) { - promise = reason.promise; - reason = reason.cause; - } - - let reasons = expectedUnhandled.get(promise); - const callbacks = reasons?.get(reason); - if (callbacks) { - for (const cb of callbacks) { - try { - cb(reason, promise); - } catch (e) { - console.error("Exception in unhandled rejection callback.", e); - } - } - - reasons.delete(reason); - if (reasons.size === 0) { - expectedUnhandled.delete(promise); - } - return; - } - - console.log(util.format("Unhandled rejection.\nReason: %o\nPromise: %o", reason, promise)); - throw error; -}); - -function ignoreUnhandled(reason, promise) { - expectUnhandled(reason, promise, null); -} - -function expectUnhandled(reason, promise, cb) { - let reasons = expectedUnhandled.get(promise); - if (!reasons) { - reasons = new Map(); - expectedUnhandled.set(promise, reasons); - } - let callbacks = reasons.get(reason); - if (!callbacks) { - callbacks = []; - reasons.set(reason, callbacks); - } - if (cb) { - callbacks.push(cb); - } -} - -afterEach(() => { - vi.resetAllMocks(); - vi.restoreAllMocks(); -}); - -const dummyValue = { value: "value" }; -const dummyCause = { dummy: "dummy" }; -const dummyError = new Error("dummy"); -const oncancelled = vi.fn().mockName("oncancelled"); -const sentinel = vi.fn().mockName("sentinel"); -const unhandled = vi.fn().mockName("unhandled"); - -const resolutionPatterns = [ - ["forever", "pending", (test, value, { cls = CancellablePromise, cb = oncancelled } = {}) => test( - new cls(() => {}, cb) - )], - ["already", "fulfilled", (test, value, { cls = CancellablePromise, cb = oncancelled } = {}) => { - const prw = cls.withResolvers(); - prw.oncancelled = cb; - prw.resolve(value ?? dummyValue); - return test(prw.promise); - }], - ["immediately", "fulfilled", (test, value, { cls = CancellablePromise, cb = oncancelled } = {}) => { - const prw = cls.withResolvers(); - prw.oncancelled = cb; - const tp = test(prw.promise); - prw.resolve(value ?? dummyValue); - return tp; - }], - ["eventually", "fulfilled", async (test, value, { cls = CancellablePromise, cb = oncancelled } = {}) => { - const prw = cls.withResolvers(); - prw.oncancelled = cb; - const tp = test(prw.promise); - await new Promise((resolve) => { - setTimeout(() => { - prw.resolve(value ?? dummyValue); - resolve(); - }, 50); - }); - return tp; - }], - ["already", "rejected", (test, reason, { cls = CancellablePromise, cb = oncancelled } = {}) => { - const prw = cls.withResolvers(); - prw.oncancelled = cb; - prw.reject(reason ?? dummyError); - return test(prw.promise); - }], - ["immediately", "rejected", (test, reason, { cls = CancellablePromise, cb = oncancelled } = {}) => { - const prw = cls.withResolvers(); - prw.oncancelled = cb; - const tp = test(prw.promise); - prw.reject(reason ?? dummyError); - return tp; - }], - ["eventually", "rejected", async (test, reason, { cls = CancellablePromise, cb = oncancelled } = {}) => { - const prw = cls.withResolvers(); - prw.oncancelled = cb; - const tp = test(prw.promise); - await new Promise((resolve) => { - setTimeout(() => { - prw.reject(reason ?? dummyError); - resolve(); - }, 50); - }); - return tp; - }], -]; - -describe("CancellablePromise.cancel", ()=> { - it("should suppress its own unhandled cancellation error", async () => { - const p = new CancellablePromise(() => {}); - p.cancel(); - - process.on('unhandledRejection', sentinel); - await new Promise((resolve) => setTimeout(resolve, 100)); - process.off('unhandledRejection', sentinel); - - expect(sentinel).not.toHaveBeenCalled(); - }); - - it.for([ - ["rejections", dummyError], - ["cancellation errors", new CancelError("dummy", { cause: dummyCause })], - ])("should not suppress arbitrary unhandled %s", async ([kind, err]) => { - const p = new CancellablePromise(() => { throw err; }); - p.cancel(); - - await new Promise((resolve) => { - expectUnhandled(err, p, unhandled); - expectUnhandled(err, p, resolve); - }); - - expect(unhandled).toHaveBeenCalledExactlyOnceWith(err, p); - }); - - describe.for(resolutionPatterns)("when applied to %s %s promises", ([time, state, test]) => { - if (time === "already") { - it("should have no effect", () => test(async (promise) => { - promise.then(sentinel, sentinel); - - let reason; - try { - promise.cancel(); - await promise; - assert(state === "fulfilled", "Promise fulfilled unexpectedly"); - } catch (err) { - reason = err; - assert(state === "rejected", "Promise rejected unexpectedly"); - } - - expect(sentinel).toHaveBeenCalled(); - expect(oncancelled).not.toHaveBeenCalled(); - expect(reason).not.toBeInstanceOf(CancelError); - })); - } else { - if (state === "rejected") { - it("should report late rejections as unhandled", () => test(async (promise) => { - promise.cancel(); - - await new Promise((resolve) => { - expectUnhandled(dummyError, promise, unhandled); - expectUnhandled(dummyError, promise, resolve); - }); - - expect(unhandled).toHaveBeenCalledExactlyOnceWith(dummyError, promise); - })); - } - - it("should reject with a CancelError", () => test(async (promise) => { - // Ignore the unhandled rejection from the test promise. - if (state === "rejected") { ignoreUnhandled(dummyError, promise); } - - let reason; - try { - promise.cancel(); - await promise; - } catch (err) { - reason = err; - } - - expect(reason).toBeInstanceOf(CancelError); - })); - - it("should call the oncancelled callback synchronously", () => test(async (promise) => { - // Ignore the unhandled rejection from the test promise. - if (state === "rejected") { ignoreUnhandled(dummyError, promise); } - - try { - promise.cancel(); - sentinel(); - await promise; - } catch {} - - expect(oncancelled).toHaveBeenCalledBefore(sentinel); - })); - - it("should propagate the given cause", () => test(async (promise) => { - // Ignore the unhandled rejection from the test promise. - if (state === "rejected") { ignoreUnhandled(dummyError, promise); } - - let reason; - try { - promise.cancel(dummyCause); - await promise; - } catch (err) { - reason = err; - } - - expect(reason).toBeInstanceOf(CancelError); - expect(reason).toHaveProperty('cause', dummyCause); - expect(oncancelled).toHaveBeenCalledWith(reason.cause); - })); - } - }); -}); - -const onabort = vi.fn().mockName("abort"); - -const abortPatterns = [ - ["never", "standalone", (test) => { - const signal = new AbortSignal(); - signal.addEventListener('abort', onabort, { capture: true }); - return test(signal); - }], - ["already", "standalone", (test) => { - const signal = AbortSignal.abort(dummyCause); - onabort(); - return test(signal); - }], - ["eventually", "standalone", (test) => { - const signal = AbortSignal.timeout(25); - signal.addEventListener('abort', onabort, { capture: true }); - return test(signal); - }], - ["never", "controller-bound", (test) => { - const signal = new AbortController().signal; - signal.addEventListener('abort', onabort, { capture: true }); - return test(signal); - }], - ["already", " controller-bound", (test) => { - const ctrl = new AbortController(); - ctrl.signal.addEventListener('abort', onabort, { capture: true }); - ctrl.abort(dummyCause); - return test(ctrl.signal); - }], - ["immediately", "controller-bound", (test) => { - const ctrl = new AbortController(); - ctrl.signal.addEventListener('abort', onabort, { capture: true }); - const tp = test(ctrl.signal); - ctrl.abort(dummyCause); - return tp; - }], - ["eventually", "controller-bound", (test) => { - const ctrl = new AbortController(); - ctrl.signal.addEventListener('abort', onabort, { capture: true }); - const tp = test(ctrl.signal); - setTimeout(() => ctrl.abort(dummyCause), 25); - return tp; - }] -]; - -describe("CancellablePromise.cancelOn", ()=> { - it("should return the target promise for chaining", () => { - const p = new CancellablePromise(() => {}); - expect(p.cancelOn(AbortSignal.abort())).toBe(p); - }); - - function tests(abortTime, mode, testSignal, resolveTime, state, testPromise) { - if (abortTime !== "never") { - it(`should call CancellablePromise.cancel ${abortTime === "already" ? "immediately" : "on abort"} with the abort reason as cause`, () => testSignal((signal) => testPromise(async (promise) => { - // Ignore the unhandled rejection from the test promise. - if (state === "rejected") { ignoreUnhandled(dummyError, promise); } - - const cancelSpy = vi.spyOn(promise, 'cancel'); - - promise.catch(() => {}); - promise.cancelOn(signal); - - if (signal.aborted) { - sentinel(); - } else { - await new Promise((resolve) => { - signal.onabort = () => { - sentinel(); - resolve(); - }; - }); - } - - expect(cancelSpy).toHaveBeenCalledAfter(onabort); - expect(cancelSpy).toHaveBeenCalledBefore(sentinel); - expect(cancelSpy).toHaveBeenCalledExactlyOnceWith(signal.reason); - }))); - } - - if ( - resolveTime === "already" - || abortTime === "never" - || ( - ["immediately", "eventually"].includes(abortTime) - && ["already", "immediately"].includes(resolveTime) - ) - ) { - it("should have no effect", () => testSignal((signal) => testPromise(async (promise) => { - promise.then(sentinel, sentinel); - - let reason; - try { - if (resolveTime !== "forever") { - await promise.cancelOn(signal); - assert(state === "fulfilled", "Promise fulfilled unexpectedly"); - } else { - await Promise.race([promise, new Promise((resolve) => setTimeout(resolve, 100))]).then(sentinel); - } - } catch (err) { - reason = err; - assert(state === "rejected", "Promise rejected unexpectedly"); - } - - if (abortTime !== "never" && !signal.aborted) { - // Wait for the AbortSignal to have actually aborted. - await new Promise((resolve) => signal.onabort = resolve); - } - - expect(sentinel).toHaveBeenCalled(); - expect(oncancelled).not.toHaveBeenCalled(); - expect(reason).not.toBeInstanceOf(CancelError); - }))); - } else { - if (state === "rejected") { - it("should report late rejections as unhandled", () => testSignal((signal) => testPromise(async (promise) => { - promise.cancelOn(signal); - - await new Promise((resolve) => { - expectUnhandled(dummyError, promise, unhandled); - expectUnhandled(dummyError, promise, resolve); - }); - - expect(unhandled).toHaveBeenCalledExactlyOnceWith(dummyError, promise); - }))); - } - - it("should reject with a CancelError", () => testSignal((signal) => testPromise(async (promise)=> { - // Ignore the unhandled rejection from the test promise. - if (state === "rejected") { ignoreUnhandled(dummyError, promise); } - - let reason; - try { - await promise.cancelOn(signal); - } catch (err) { - reason = err; - } - - expect(reason).toBeInstanceOf(CancelError); - }))); - - it(`should call the oncancelled callback ${abortTime === "already" ? "" : "a"}synchronously`, () => testSignal((signal) => testPromise(async (promise) => { - // Ignore the unhandled rejection from the test promise. - if (state === "rejected") { ignoreUnhandled(dummyError, promise); } - - try { - promise.cancelOn(signal); - sentinel(); - await promise; - } catch {} - - expect(oncancelled).toHaveBeenCalledAfter(onabort); - if (abortTime === "already") { - expect(oncancelled).toHaveBeenCalledBefore(sentinel); - } else { - expect(oncancelled).toHaveBeenCalledAfter(sentinel); - } - }))); - - it("should propagate the abort reason as cause", () => testSignal((signal) => testPromise(async (promise) => { - // Ignore the unhandled rejection from the test promise. - if (state === "rejected") { ignoreUnhandled(dummyError, promise); } - - let reason; - try { - await promise.cancelOn(signal); - } catch (err) { - reason = err; - } - - expect(reason).toBeInstanceOf(CancelError); - expect(reason).toHaveProperty('cause', signal.reason); - expect(oncancelled).toHaveBeenCalledWith(signal.reason); - }))); - } - } - - describe.for(abortPatterns)("when called with %s aborted %s signals", ([abortTime, mode, testSignal]) => { - describe.for(resolutionPatterns)("when applied to %s %s promises", ([resolveTime, state, testPromise]) => { - tests(abortTime, mode, testSignal, resolveTime, state, testPromise); - }); - }); - - describe.for(resolutionPatterns)("when applied to %s %s promises", ([resolveTime, state, testPromise]) => { - describe.for(abortPatterns)("when called with %s aborted %s signals", ([abortTime, mode, testSignal]) => { - tests(abortTime, mode, testSignal, resolveTime, state, testPromise); - }); - }); -}); \ No newline at end of file diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/src/cancellable.ts b/v3/internal/runtime/desktop/@wailsio/runtime/src/cancellable.ts deleted file mode 100644 index 8c16b0cd7..000000000 --- a/v3/internal/runtime/desktop/@wailsio/runtime/src/cancellable.ts +++ /dev/null @@ -1,934 +0,0 @@ -/* - _ __ _ __ -| | / /___ _(_) /____ -| | /| / / __ `/ / / ___/ -| |/ |/ / /_/ / / (__ ) -|__/|__/\__,_/_/_/____/ -The electron alternative for Go -(c) Lea Anthony 2019-present -*/ - -import isCallable from "./callable.js"; - -/** - * Exception class that will be used as rejection reason - * in case a {@link CancellablePromise} is cancelled successfully. - * - * The value of the {@link name} property is the string `"CancelError"`. - * The value of the {@link cause} property is the cause passed to the cancel method, if any. - */ -export class CancelError extends Error { - /** - * Constructs a new `CancelError` instance. - * @param message - The error message. - * @param options - Options to be forwarded to the Error constructor. - */ - constructor(message?: string, options?: ErrorOptions) { - super(message, options); - this.name = "CancelError"; - } -} - -/** - * Exception class that will be reported as an unhandled rejection - * in case a {@link CancellablePromise} rejects after being cancelled, - * or when the `oncancelled` callback throws or rejects. - * - * The value of the {@link name} property is the string `"CancelledRejectionError"`. - * The value of the {@link cause} property is the reason the promise rejected with. - * - * Because the original promise was cancelled, - * a wrapper promise will be passed to the unhandled rejection listener instead. - * The {@link promise} property holds a reference to the original promise. - */ -export class CancelledRejectionError extends Error { - /** - * Holds a reference to the promise that was cancelled and then rejected. - */ - promise: CancellablePromise; - - /** - * Constructs a new `CancelledRejectionError` instance. - * @param promise - The promise that caused the error originally. - * @param reason - The rejection reason. - * @param info - An optional informative message specifying the circumstances in which the error was thrown. - * Defaults to the string `"Unhandled rejection in cancelled promise."`. - */ - constructor(promise: CancellablePromise, reason?: any, info?: string) { - super((info ?? "Unhandled rejection in cancelled promise.") + " Reason: " + errorMessage(reason), { cause: reason }); - this.promise = promise; - this.name = "CancelledRejectionError"; - } -} - -type CancellablePromiseResolver = (value: T | PromiseLike | CancellablePromiseLike) => void; -type CancellablePromiseRejector = (reason?: any) => void; -type CancellablePromiseCanceller = (cause?: any) => void | PromiseLike; -type CancellablePromiseExecutor = (resolve: CancellablePromiseResolver, reject: CancellablePromiseRejector) => void; - -export interface CancellablePromiseLike { - then(onfulfilled?: ((value: T) => TResult1 | PromiseLike | CancellablePromiseLike) | undefined | null, onrejected?: ((reason: any) => TResult2 | PromiseLike | CancellablePromiseLike) | undefined | null): CancellablePromiseLike; - cancel(cause?: any): void | PromiseLike; -} - -/** - * Wraps a cancellable promise along with its resolution methods. - * The `oncancelled` field will be null initially but may be set to provide a custom cancellation function. - */ -export interface CancellablePromiseWithResolvers { - promise: CancellablePromise; - resolve: CancellablePromiseResolver; - reject: CancellablePromiseRejector; - oncancelled: CancellablePromiseCanceller | null; -} - -interface CancellablePromiseState { - readonly root: CancellablePromiseState; - resolving: boolean; - settled: boolean; - reason?: CancelError; -} - -// Private field names. -const barrierSym = Symbol("barrier"); -const cancelImplSym = Symbol("cancelImpl"); -const species: typeof Symbol.species = Symbol.species ?? Symbol("speciesPolyfill"); - -/** - * A promise with an attached method for cancelling long-running operations (see {@link CancellablePromise#cancel}). - * Cancellation can optionally be bound to an {@link AbortSignal} - * for better composability (see {@link CancellablePromise#cancelOn}). - * - * Cancelling a pending promise will result in an immediate rejection - * with an instance of {@link CancelError} as reason, - * but whoever started the promise will be responsible - * for actually aborting the underlying operation. - * To this purpose, the constructor and all chaining methods - * accept optional cancellation callbacks. - * - * If a `CancellablePromise` still resolves after having been cancelled, - * the result will be discarded. If it rejects, the reason - * will be reported as an unhandled rejection, - * wrapped in a {@link CancelledRejectionError} instance. - * To facilitate the handling of cancellation requests, - * cancelled `CancellablePromise`s will _not_ report unhandled `CancelError`s - * whose `cause` field is the same as the one with which the current promise was cancelled. - * - * All usual promise methods are defined and return a `CancellablePromise` - * whose cancel method will cancel the parent operation as well, propagating the cancellation reason - * upwards through promise chains. - * Conversely, cancelling a promise will not automatically cancel dependent promises downstream: - * ```ts - * let root = new CancellablePromise((resolve, reject) => { ... }); - * let child1 = root.then(() => { ... }); - * let child2 = child1.then(() => { ... }); - * let child3 = root.catch(() => { ... }); - * child1.cancel(); // Cancels child1 and root, but not child2 or child3 - * ``` - * Cancelling a promise that has already settled is safe and has no consequence. - * - * The `cancel` method returns a promise that _always fulfills_ - * after the whole chain has processed the cancel request - * and all attached callbacks up to that moment have run. - * - * All ES2024 promise methods (static and instance) are defined on CancellablePromise, - * but actual availability may vary with OS/webview version. - * - * In line with the proposal at https://github.com/tc39/proposal-rm-builtin-subclassing, - * `CancellablePromise` does not support transparent subclassing. - * Extenders should take care to provide their own method implementations. - * This might be reconsidered in case the proposal is retired. - * - * CancellablePromise is a wrapper around the DOM Promise object - * and is compliant with the [Promises/A+ specification](https://promisesaplus.com/) - * (it passes the [compliance suite](https://github.com/promises-aplus/promises-tests)) - * if so is the underlying implementation. - */ -export class CancellablePromise extends Promise implements PromiseLike, CancellablePromiseLike { - // Private fields. - /** @internal */ - private [barrierSym]!: Partial> | null; - /** @internal */ - private readonly [cancelImplSym]!: (reason: CancelError) => void | PromiseLike; - - /** - * Creates a new `CancellablePromise`. - * - * @param executor - A callback used to initialize the promise. This callback is passed two arguments: - * a `resolve` callback used to resolve the promise with a value - * or the result of another promise (possibly cancellable), - * and a `reject` callback used to reject the promise with a provided reason or error. - * If the value provided to the `resolve` callback is a thenable _and_ cancellable object - * (it has a `then` _and_ a `cancel` method), - * cancellation requests will be forwarded to that object and the oncancelled will not be invoked anymore. - * If any one of the two callbacks is called _after_ the promise has been cancelled, - * the provided values will be cancelled and resolved as usual, - * but their results will be discarded. - * However, if the resolution process ultimately ends up in a rejection - * that is not due to cancellation, the rejection reason - * will be wrapped in a {@link CancelledRejectionError} - * and bubbled up as an unhandled rejection. - * @param oncancelled - It is the caller's responsibility to ensure that any operation - * started by the executor is properly halted upon cancellation. - * This optional callback can be used to that purpose. - * It will be called _synchronously_ with a cancellation cause - * when cancellation is requested, _after_ the promise has already rejected - * with a {@link CancelError}, but _before_ - * any {@link then}/{@link catch}/{@link finally} callback runs. - * If the callback returns a thenable, the promise returned from {@link cancel} - * will only fulfill after the former has settled. - * Unhandled exceptions or rejections from the callback will be wrapped - * in a {@link CancelledRejectionError} and bubbled up as unhandled rejections. - * If the `resolve` callback is called before cancellation with a cancellable promise, - * cancellation requests on this promise will be diverted to that promise, - * and the original `oncancelled` callback will be discarded. - */ - constructor(executor: CancellablePromiseExecutor, oncancelled?: CancellablePromiseCanceller) { - let resolve!: (value: T | PromiseLike) => void; - let reject!: (reason?: any) => void; - super((res, rej) => { resolve = res; reject = rej; }); - - if ((this.constructor as any)[species] !== Promise) { - throw new TypeError("CancellablePromise does not support transparent subclassing. Please refrain from overriding the [Symbol.species] static property."); - } - - let promise: CancellablePromiseWithResolvers = { - promise: this, - resolve, - reject, - get oncancelled() { return oncancelled ?? null; }, - set oncancelled(cb) { oncancelled = cb ?? undefined; } - }; - - const state: CancellablePromiseState = { - get root() { return state; }, - resolving: false, - settled: false - }; - - // Setup cancellation system. - void Object.defineProperties(this, { - [barrierSym]: { - configurable: false, - enumerable: false, - writable: true, - value: null - }, - [cancelImplSym]: { - configurable: false, - enumerable: false, - writable: false, - value: cancellerFor(promise, state) - } - }); - - // Run the actual executor. - const rejector = rejectorFor(promise, state); - try { - executor(resolverFor(promise, state), rejector); - } catch (err) { - if (state.resolving) { - console.log("Unhandled exception in CancellablePromise executor.", err); - } else { - rejector(err); - } - } - } - - /** - * Cancels immediately the execution of the operation associated with this promise. - * The promise rejects with a {@link CancelError} instance as reason, - * with the {@link CancelError#cause} property set to the given argument, if any. - * - * Has no effect if called after the promise has already settled; - * repeated calls in particular are safe, but only the first one - * will set the cancellation cause. - * - * The `CancelError` exception _need not_ be handled explicitly _on the promises that are being cancelled:_ - * cancelling a promise with no attached rejection handler does not trigger an unhandled rejection event. - * Therefore, the following idioms are all equally correct: - * ```ts - * new CancellablePromise((resolve, reject) => { ... }).cancel(); - * new CancellablePromise((resolve, reject) => { ... }).then(...).cancel(); - * new CancellablePromise((resolve, reject) => { ... }).then(...).catch(...).cancel(); - * ``` - * Whenever some cancelled promise in a chain rejects with a `CancelError` - * with the same cancellation cause as itself, the error will be discarded silently. - * However, the `CancelError` _will still be delivered_ to all attached rejection handlers - * added by {@link then} and related methods: - * ```ts - * let cancellable = new CancellablePromise((resolve, reject) => { ... }); - * cancellable.then(() => { ... }).catch(console.log); - * cancellable.cancel(); // A CancelError is printed to the console. - * ``` - * If the `CancelError` is not handled downstream by the time it reaches - * a _non-cancelled_ promise, it _will_ trigger an unhandled rejection event, - * just like normal rejections would: - * ```ts - * let cancellable = new CancellablePromise((resolve, reject) => { ... }); - * let chained = cancellable.then(() => { ... }).then(() => { ... }); // No catch... - * cancellable.cancel(); // Unhandled rejection event on chained! - * ``` - * Therefore, it is important to either cancel whole promise chains from their tail, - * as shown in the correct idioms above, or take care of handling errors everywhere. - * - * @returns A cancellable promise that _fulfills_ after the cancel callback (if any) - * and all handlers attached up to the call to cancel have run. - * If the cancel callback returns a thenable, the promise returned by `cancel` - * will also wait for that thenable to settle. - * This enables callers to wait for the cancelled operation to terminate - * without being forced to handle potential errors at the call site. - * ```ts - * cancellable.cancel().then(() => { - * // Cleanup finished, it's safe to do something else. - * }, (err) => { - * // Unreachable: the promise returned from cancel will never reject. - * }); - * ``` - * Note that the returned promise will _not_ handle implicitly any rejection - * that might have occurred already in the cancelled chain. - * It will just track whether registered handlers have been executed or not. - * Therefore, unhandled rejections will never be silently handled by calling cancel. - */ - cancel(cause?: any): CancellablePromise { - return new CancellablePromise((resolve) => { - // INVARIANT: the result of this[cancelImplSym] and the barrier do not ever reject. - // Unfortunately macOS High Sierra does not support Promise.allSettled. - Promise.all([ - this[cancelImplSym](new CancelError("Promise cancelled.", { cause })), - currentBarrier(this) - ]).then(() => resolve(), () => resolve()); - }); - } - - /** - * Binds promise cancellation to the abort event of the given {@link AbortSignal}. - * If the signal has already aborted, the promise will be cancelled immediately. - * When either condition is verified, the cancellation cause will be set - * to the signal's abort reason (see {@link AbortSignal#reason}). - * - * Has no effect if called (or if the signal aborts) _after_ the promise has already settled. - * Only the first signal to abort will set the cancellation cause. - * - * For more details about the cancellation process, - * see {@link cancel} and the `CancellablePromise` constructor. - * - * This method enables `await`ing cancellable promises without having - * to store them for future cancellation, e.g.: - * ```ts - * await longRunningOperation().cancelOn(signal); - * ``` - * instead of: - * ```ts - * let promiseToBeCancelled = longRunningOperation(); - * await promiseToBeCancelled; - * ``` - * - * @returns This promise, for method chaining. - */ - cancelOn(signal: AbortSignal): CancellablePromise { - if (signal.aborted) { - void this.cancel(signal.reason) - } else { - signal.addEventListener('abort', () => void this.cancel(signal.reason), {capture: true}); - } - - return this; - } - - /** - * Attaches callbacks for the resolution and/or rejection of the `CancellablePromise`. - * - * The optional `oncancelled` argument will be invoked when the returned promise is cancelled, - * with the same semantics as the `oncancelled` argument of the constructor. - * When the parent promise rejects or is cancelled, the `onrejected` callback will run, - * _even after the returned promise has been cancelled:_ - * in that case, should it reject or throw, the reason will be wrapped - * in a {@link CancelledRejectionError} and bubbled up as an unhandled rejection. - * - * @param onfulfilled The callback to execute when the Promise is resolved. - * @param onrejected The callback to execute when the Promise is rejected. - * @returns A `CancellablePromise` for the completion of whichever callback is executed. - * The returned promise is hooked up to propagate cancellation requests up the chain, but not down: - * - * - if the parent promise is cancelled, the `onrejected` handler will be invoked with a `CancelError` - * and the returned promise _will resolve regularly_ with its result; - * - conversely, if the returned promise is cancelled, _the parent promise is cancelled too;_ - * the `onrejected` handler will still be invoked with the parent's `CancelError`, - * but its result will be discarded - * and the returned promise will reject with a `CancelError` as well. - * - * The promise returned from {@link cancel} will fulfill only after all attached handlers - * up the entire promise chain have been run. - * - * If either callback returns a cancellable promise, - * cancellation requests will be diverted to it, - * and the specified `oncancelled` callback will be discarded. - */ - then(onfulfilled?: ((value: T) => TResult1 | PromiseLike | CancellablePromiseLike) | undefined | null, onrejected?: ((reason: any) => TResult2 | PromiseLike | CancellablePromiseLike) | undefined | null, oncancelled?: CancellablePromiseCanceller): CancellablePromise { - if (!(this instanceof CancellablePromise)) { - throw new TypeError("CancellablePromise.prototype.then called on an invalid object."); - } - - // NOTE: TypeScript's built-in type for then is broken, - // as it allows specifying an arbitrary TResult1 != T even when onfulfilled is not a function. - // We cannot fix it if we want to CancellablePromise to implement PromiseLike. - - if (!isCallable(onfulfilled)) { onfulfilled = identity as any; } - if (!isCallable(onrejected)) { onrejected = thrower; } - - if (onfulfilled === identity && onrejected == thrower) { - // Shortcut for trivial arguments. - return new CancellablePromise((resolve) => resolve(this as any)); - } - - const barrier: Partial> = {}; - this[barrierSym] = barrier; - - return new CancellablePromise((resolve, reject) => { - void super.then( - (value) => { - if (this[barrierSym] === barrier) { this[barrierSym] = null; } - barrier.resolve?.(); - - try { - resolve(onfulfilled!(value)); - } catch (err) { - reject(err); - } - }, - (reason?) => { - if (this[barrierSym] === barrier) { this[barrierSym] = null; } - barrier.resolve?.(); - - try { - resolve(onrejected!(reason)); - } catch (err) { - reject(err); - } - } - ); - }, async (cause?) => { - //cancelled = true; - try { - return oncancelled?.(cause); - } finally { - await this.cancel(cause); - } - }); - } - - /** - * Attaches a callback for only the rejection of the Promise. - * - * The optional `oncancelled` argument will be invoked when the returned promise is cancelled, - * with the same semantics as the `oncancelled` argument of the constructor. - * When the parent promise rejects or is cancelled, the `onrejected` callback will run, - * _even after the returned promise has been cancelled:_ - * in that case, should it reject or throw, the reason will be wrapped - * in a {@link CancelledRejectionError} and bubbled up as an unhandled rejection. - * - * It is equivalent to - * ```ts - * cancellablePromise.then(undefined, onrejected, oncancelled); - * ``` - * and the same caveats apply. - * - * @returns A Promise for the completion of the callback. - * Cancellation requests on the returned promise - * will propagate up the chain to the parent promise, - * but not in the other direction. - * - * The promise returned from {@link cancel} will fulfill only after all attached handlers - * up the entire promise chain have been run. - * - * If `onrejected` returns a cancellable promise, - * cancellation requests will be diverted to it, - * and the specified `oncancelled` callback will be discarded. - * See {@link then} for more details. - */ - catch(onrejected?: ((reason: any) => (PromiseLike | TResult)) | undefined | null, oncancelled?: CancellablePromiseCanceller): CancellablePromise { - return this.then(undefined, onrejected, oncancelled); - } - - /** - * Attaches a callback that is invoked when the CancellablePromise is settled (fulfilled or rejected). The - * resolved value cannot be accessed or modified from the callback. - * The returned promise will settle in the same state as the original one - * after the provided callback has completed execution, - * unless the callback throws or returns a rejecting promise, - * in which case the returned promise will reject as well. - * - * The optional `oncancelled` argument will be invoked when the returned promise is cancelled, - * with the same semantics as the `oncancelled` argument of the constructor. - * Once the parent promise settles, the `onfinally` callback will run, - * _even after the returned promise has been cancelled:_ - * in that case, should it reject or throw, the reason will be wrapped - * in a {@link CancelledRejectionError} and bubbled up as an unhandled rejection. - * - * This method is implemented in terms of {@link then} and the same caveats apply. - * It is polyfilled, hence available in every OS/webview version. - * - * @returns A Promise for the completion of the callback. - * Cancellation requests on the returned promise - * will propagate up the chain to the parent promise, - * but not in the other direction. - * - * The promise returned from {@link cancel} will fulfill only after all attached handlers - * up the entire promise chain have been run. - * - * If `onfinally` returns a cancellable promise, - * cancellation requests will be diverted to it, - * and the specified `oncancelled` callback will be discarded. - * See {@link then} for more details. - */ - finally(onfinally?: (() => void) | undefined | null, oncancelled?: CancellablePromiseCanceller): CancellablePromise { - if (!(this instanceof CancellablePromise)) { - throw new TypeError("CancellablePromise.prototype.finally called on an invalid object."); - } - - if (!isCallable(onfinally)) { - return this.then(onfinally, onfinally, oncancelled); - } - - return this.then( - (value) => CancellablePromise.resolve(onfinally()).then(() => value), - (reason?) => CancellablePromise.resolve(onfinally()).then(() => { throw reason; }), - oncancelled, - ); - } - - /** - * We use the `[Symbol.species]` static property, if available, - * to disable the built-in automatic subclassing features from {@link Promise}. - * It is critical for performance reasons that extenders do not override this. - * Once the proposal at https://github.com/tc39/proposal-rm-builtin-subclassing - * is either accepted or retired, this implementation will have to be revised accordingly. - * - * @ignore - * @internal - */ - static get [species]() { - return Promise; - } - - /** - * Creates a CancellablePromise that is resolved with an array of results - * when all of the provided Promises resolve, or rejected when any Promise is rejected. - * - * Every one of the provided objects that is a thenable _and_ cancellable object - * will be cancelled when the returned promise is cancelled, with the same cause. - * - * @group Static Methods - */ - static all(values: Iterable>): CancellablePromise[]>; - static all(values: T): CancellablePromise<{ -readonly [P in keyof T]: Awaited; }>; - static all | ArrayLike>(values: T): CancellablePromise { - let collected = Array.from(values); - const promise = collected.length === 0 - ? CancellablePromise.resolve(collected) - : new CancellablePromise((resolve, reject) => { - void Promise.all(collected).then(resolve, reject); - }, (cause?): Promise => cancelAll(promise, collected, cause)); - return promise; - } - - /** - * Creates a CancellablePromise that is resolved with an array of results - * when all of the provided Promises resolve or reject. - * - * Every one of the provided objects that is a thenable _and_ cancellable object - * will be cancelled when the returned promise is cancelled, with the same cause. - * - * @group Static Methods - */ - static allSettled(values: Iterable>): CancellablePromise>[]>; - static allSettled(values: T): CancellablePromise<{ -readonly [P in keyof T]: PromiseSettledResult>; }>; - static allSettled | ArrayLike>(values: T): CancellablePromise { - let collected = Array.from(values); - const promise = collected.length === 0 - ? CancellablePromise.resolve(collected) - : new CancellablePromise((resolve, reject) => { - void Promise.allSettled(collected).then(resolve, reject); - }, (cause?): Promise => cancelAll(promise, collected, cause)); - return promise; - } - - /** - * The any function returns a promise that is fulfilled by the first given promise to be fulfilled, - * or rejected with an AggregateError containing an array of rejection reasons - * if all of the given promises are rejected. - * It resolves all elements of the passed iterable to promises as it runs this algorithm. - * - * Every one of the provided objects that is a thenable _and_ cancellable object - * will be cancelled when the returned promise is cancelled, with the same cause. - * - * @group Static Methods - */ - static any(values: Iterable>): CancellablePromise>; - static any(values: T): CancellablePromise>; - static any | ArrayLike>(values: T): CancellablePromise { - let collected = Array.from(values); - const promise = collected.length === 0 - ? CancellablePromise.resolve(collected) - : new CancellablePromise((resolve, reject) => { - void Promise.any(collected).then(resolve, reject); - }, (cause?): Promise => cancelAll(promise, collected, cause)); - return promise; - } - - /** - * Creates a Promise that is resolved or rejected when any of the provided Promises are resolved or rejected. - * - * Every one of the provided objects that is a thenable _and_ cancellable object - * will be cancelled when the returned promise is cancelled, with the same cause. - * - * @group Static Methods - */ - static race(values: Iterable>): CancellablePromise>; - static race(values: T): CancellablePromise>; - static race | ArrayLike>(values: T): CancellablePromise { - let collected = Array.from(values); - const promise = new CancellablePromise((resolve, reject) => { - void Promise.race(collected).then(resolve, reject); - }, (cause?): Promise => cancelAll(promise, collected, cause)); - return promise; - } - - /** - * Creates a new cancelled CancellablePromise for the provided cause. - * - * @group Static Methods - */ - static cancel(cause?: any): CancellablePromise { - const p = new CancellablePromise(() => {}); - p.cancel(cause); - return p; - } - - /** - * Creates a new CancellablePromise that cancels - * after the specified timeout, with the provided cause. - * - * If the {@link AbortSignal.timeout} factory method is available, - * it is used to base the timeout on _active_ time rather than _elapsed_ time. - * Otherwise, `timeout` falls back to {@link setTimeout}. - * - * @group Static Methods - */ - static timeout(milliseconds: number, cause?: any): CancellablePromise { - const promise = new CancellablePromise(() => {}); - if (AbortSignal && typeof AbortSignal === 'function' && AbortSignal.timeout && typeof AbortSignal.timeout === 'function') { - AbortSignal.timeout(milliseconds).addEventListener('abort', () => void promise.cancel(cause)); - } else { - setTimeout(() => void promise.cancel(cause), milliseconds); - } - return promise; - } - - /** - * Creates a new CancellablePromise that resolves after the specified timeout. - * The returned promise can be cancelled without consequences. - * - * @group Static Methods - */ - static sleep(milliseconds: number): CancellablePromise; - /** - * Creates a new CancellablePromise that resolves after - * the specified timeout, with the provided value. - * The returned promise can be cancelled without consequences. - * - * @group Static Methods - */ - static sleep(milliseconds: number, value: T): CancellablePromise; - static sleep(milliseconds: number, value?: T): CancellablePromise { - return new CancellablePromise((resolve) => { - setTimeout(() => resolve(value!), milliseconds); - }); - } - - /** - * Creates a new rejected CancellablePromise for the provided reason. - * - * @group Static Methods - */ - static reject(reason?: any): CancellablePromise { - return new CancellablePromise((_, reject) => reject(reason)); - } - - /** - * Creates a new resolved CancellablePromise. - * - * @group Static Methods - */ - static resolve(): CancellablePromise; - /** - * Creates a new resolved CancellablePromise for the provided value. - * - * @group Static Methods - */ - static resolve(value: T): CancellablePromise>; - /** - * Creates a new resolved CancellablePromise for the provided value. - * - * @group Static Methods - */ - static resolve(value: T | PromiseLike): CancellablePromise>; - static resolve(value?: T | PromiseLike): CancellablePromise> { - if (value instanceof CancellablePromise) { - // Optimise for cancellable promises. - return value; - } - return new CancellablePromise((resolve) => resolve(value)); - } - - /** - * Creates a new CancellablePromise and returns it in an object, along with its resolve and reject functions - * and a getter/setter for the cancellation callback. - * - * This method is polyfilled, hence available in every OS/webview version. - * - * @group Static Methods - */ - static withResolvers(): CancellablePromiseWithResolvers { - let result: CancellablePromiseWithResolvers = { oncancelled: null } as any; - result.promise = new CancellablePromise((resolve, reject) => { - result.resolve = resolve; - result.reject = reject; - }, (cause?: any) => { result.oncancelled?.(cause); }); - return result; - } -} - -/** - * Returns a callback that implements the cancellation algorithm for the given cancellable promise. - * The promise returned from the resulting function does not reject. - */ -function cancellerFor(promise: CancellablePromiseWithResolvers, state: CancellablePromiseState) { - let cancellationPromise: void | PromiseLike = undefined; - - return (reason: CancelError): void | PromiseLike => { - if (!state.settled) { - state.settled = true; - state.reason = reason; - promise.reject(reason); - - // Attach an error handler that ignores this specific rejection reason and nothing else. - // In theory, a sane underlying implementation at this point - // should always reject with our cancellation reason, - // hence the handler will never throw. - void Promise.prototype.then.call(promise.promise, undefined, (err) => { - if (err !== reason) { - throw err; - } - }); - } - - // If reason is not set, the promise resolved regularly, hence we must not call oncancelled. - // If oncancelled is unset, no need to go any further. - if (!state.reason || !promise.oncancelled) { return; } - - cancellationPromise = new Promise((resolve) => { - try { - resolve(promise.oncancelled!(state.reason!.cause)); - } catch (err) { - Promise.reject(new CancelledRejectionError(promise.promise, err, "Unhandled exception in oncancelled callback.")); - } - }).catch((reason?) => { - Promise.reject(new CancelledRejectionError(promise.promise, reason, "Unhandled rejection in oncancelled callback.")); - }); - - // Unset oncancelled to prevent repeated calls. - promise.oncancelled = null; - - return cancellationPromise; - } -} - -/** - * Returns a callback that implements the resolution algorithm for the given cancellable promise. - */ -function resolverFor(promise: CancellablePromiseWithResolvers, state: CancellablePromiseState): CancellablePromiseResolver { - return (value) => { - if (state.resolving) { return; } - state.resolving = true; - - if (value === promise.promise) { - if (state.settled) { return; } - state.settled = true; - promise.reject(new TypeError("A promise cannot be resolved with itself.")); - return; - } - - if (value != null && (typeof value === 'object' || typeof value === 'function')) { - let then: any; - try { - then = (value as any).then; - } catch (err) { - state.settled = true; - promise.reject(err); - return; - } - - if (isCallable(then)) { - try { - let cancel = (value as any).cancel; - if (isCallable(cancel)) { - const oncancelled = (cause?: any) => { - Reflect.apply(cancel, value, [cause]); - }; - if (state.reason) { - // If already cancelled, propagate cancellation. - // The promise returned from the canceller algorithm does not reject - // so it can be discarded safely. - void cancellerFor({ ...promise, oncancelled }, state)(state.reason); - } else { - promise.oncancelled = oncancelled; - } - } - } catch {} - - const newState: CancellablePromiseState = { - root: state.root, - resolving: false, - get settled() { return this.root.settled }, - set settled(value) { this.root.settled = value; }, - get reason() { return this.root.reason } - }; - - const rejector = rejectorFor(promise, newState); - try { - Reflect.apply(then, value, [resolverFor(promise, newState), rejector]); - } catch (err) { - rejector(err); - } - return; // IMPORTANT! - } - } - - if (state.settled) { return; } - state.settled = true; - promise.resolve(value); - }; -} - -/** - * Returns a callback that implements the rejection algorithm for the given cancellable promise. - */ -function rejectorFor(promise: CancellablePromiseWithResolvers, state: CancellablePromiseState): CancellablePromiseRejector { - return (reason?) => { - if (state.resolving) { return; } - state.resolving = true; - - if (state.settled) { - try { - if (reason instanceof CancelError && state.reason instanceof CancelError && Object.is(reason.cause, state.reason.cause)) { - // Swallow late rejections that are CancelErrors whose cancellation cause is the same as ours. - return; - } - } catch {} - - void Promise.reject(new CancelledRejectionError(promise.promise, reason)); - } else { - state.settled = true; - promise.reject(reason); - } - } -} - -/** - * Cancels all values in an array that look like cancellable thenables. - * Returns a promise that fulfills once all cancellation procedures for the given values have settled. - */ -function cancelAll(parent: CancellablePromise, values: any[], cause?: any): Promise { - const results: Promise[] = []; - - for (const value of values) { - let cancel: CancellablePromiseCanceller; - try { - if (!isCallable(value.then)) { continue; } - cancel = value.cancel; - if (!isCallable(cancel)) { continue; } - } catch { continue; } - - let result: void | PromiseLike; - try { - result = Reflect.apply(cancel, value, [cause]); - } catch (err) { - Promise.reject(new CancelledRejectionError(parent, err, "Unhandled exception in cancel method.")); - continue; - } - - if (!result) { continue; } - results.push( - (result instanceof Promise ? result : Promise.resolve(result)).catch((reason?) => { - Promise.reject(new CancelledRejectionError(parent, reason, "Unhandled rejection in cancel method.")); - }) - ); - } - - return Promise.all(results) as any; -} - -/** - * Returns its argument. - */ -function identity(x: T): T { - return x; -} - -/** - * Throws its argument. - */ -function thrower(reason?: any): never { - throw reason; -} - -/** - * Attempts various strategies to convert an error to a string. - */ -function errorMessage(err: any): string { - try { - if (err instanceof Error || typeof err !== 'object' || err.toString !== Object.prototype.toString) { - return "" + err; - } - } catch {} - - try { - return JSON.stringify(err); - } catch {} - - try { - return Object.prototype.toString.call(err); - } catch {} - - return ""; -} - -/** - * Gets the current barrier promise for the given cancellable promise. If necessary, initialises the barrier. - */ -function currentBarrier(promise: CancellablePromise): Promise { - let pwr: Partial> = promise[barrierSym] ?? {}; - if (!('promise' in pwr)) { - Object.assign(pwr, promiseWithResolvers()); - } - if (promise[barrierSym] == null) { - pwr.resolve!(); - promise[barrierSym] = pwr; - } - return pwr.promise!; -} - -// Polyfill Promise.withResolvers. -let promiseWithResolvers = Promise.withResolvers; -if (promiseWithResolvers && typeof promiseWithResolvers === 'function') { - promiseWithResolvers = promiseWithResolvers.bind(Promise); -} else { - promiseWithResolvers = function (): PromiseWithResolvers { - let resolve!: (value: T | PromiseLike) => void; - let reject!: (reason?: any) => void; - const promise = new Promise((res, rej) => { resolve = res; reject = rej; }); - return { promise, resolve, reject }; - } -} diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/src/clipboard.ts b/v3/internal/runtime/desktop/@wailsio/runtime/src/clipboard.ts deleted file mode 100644 index a6f2f1985..000000000 --- a/v3/internal/runtime/desktop/@wailsio/runtime/src/clipboard.ts +++ /dev/null @@ -1,35 +0,0 @@ -/* - _ __ _ __ -| | / /___ _(_) /____ -| | /| / / __ `/ / / ___/ -| |/ |/ / /_/ / / (__ ) -|__/|__/\__,_/_/_/____/ -The electron alternative for Go -(c) Lea Anthony 2019-present -*/ - -import {newRuntimeCaller, objectNames} from "./runtime.js"; - -const call = newRuntimeCaller(objectNames.Clipboard); - -const ClipboardSetText = 0; -const ClipboardText = 1; - -/** - * Sets the text to the Clipboard. - * - * @param text - The text to be set to the Clipboard. - * @return A Promise that resolves when the operation is successful. - */ -export function SetText(text: string): Promise { - return call(ClipboardSetText, {text}); -} - -/** - * Get the Clipboard text - * - * @returns A promise that resolves with the text from the Clipboard. - */ -export function Text(): Promise { - return call(ClipboardText); -} diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/src/contextmenu.ts b/v3/internal/runtime/desktop/@wailsio/runtime/src/contextmenu.ts deleted file mode 100644 index c1615d1c2..000000000 --- a/v3/internal/runtime/desktop/@wailsio/runtime/src/contextmenu.ts +++ /dev/null @@ -1,94 +0,0 @@ -/* - _ __ _ __ -| | / /___ _(_) /____ -| | /| / / __ `/ / / ___/ -| |/ |/ / /_/ / / (__ ) -|__/|__/\__,_/_/_/____/ -The electron alternative for Go -(c) Lea Anthony 2019-present -*/ - -import { newRuntimeCaller, objectNames } from "./runtime.js"; -import { IsDebug } from "./system.js"; -import { eventTarget } from "./utils.js"; - -// setup -window.addEventListener('contextmenu', contextMenuHandler); - -const call = newRuntimeCaller(objectNames.ContextMenu); - -const ContextMenuOpen = 0; - -function openContextMenu(id: string, x: number, y: number, data: any): void { - void call(ContextMenuOpen, {id, x, y, data}); -} - -function contextMenuHandler(event: MouseEvent) { - const target = eventTarget(event); - - // Check for custom context menu - const customContextMenu = window.getComputedStyle(target).getPropertyValue("--custom-contextmenu").trim(); - - if (customContextMenu) { - event.preventDefault(); - const data = window.getComputedStyle(target).getPropertyValue("--custom-contextmenu-data"); - openContextMenu(customContextMenu, event.clientX, event.clientY, data); - } else { - processDefaultContextMenu(event, target); - } -} - - -/* ---default-contextmenu: auto; (default) will show the default context menu if contentEditable is true OR text has been selected OR element is input or textarea ---default-contextmenu: show; will always show the default context menu ---default-contextmenu: hide; will always hide the default context menu - -This rule is inherited like normal CSS rules, so nesting works as expected -*/ -function processDefaultContextMenu(event: MouseEvent, target: HTMLElement) { - // Debug builds always show the menu - if (IsDebug()) { - return; - } - - // Process default context menu - switch (window.getComputedStyle(target).getPropertyValue("--default-contextmenu").trim()) { - case 'show': - return; - case 'hide': - event.preventDefault(); - return; - } - - // Check if contentEditable is true - if (target.isContentEditable) { - return; - } - - // Check if text has been selected - const selection = window.getSelection(); - const hasSelection = selection && selection.toString().length > 0; - if (hasSelection) { - for (let i = 0; i < selection.rangeCount; i++) { - const range = selection.getRangeAt(i); - const rects = range.getClientRects(); - for (let j = 0; j < rects.length; j++) { - const rect = rects[j]; - if (document.elementFromPoint(rect.left, rect.top) === target) { - return; - } - } - } - } - - // Check if tag is input or textarea. - if (target instanceof HTMLInputElement || target instanceof HTMLTextAreaElement) { - if (hasSelection || (!target.readOnly && !target.disabled)) { - return; - } - } - - // hide default context menu - event.preventDefault(); -} diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/src/create.ts b/v3/internal/runtime/desktop/@wailsio/runtime/src/create.ts deleted file mode 100644 index e009a97b3..000000000 --- a/v3/internal/runtime/desktop/@wailsio/runtime/src/create.ts +++ /dev/null @@ -1,112 +0,0 @@ -/* - _ __ _ __ -| | / /___ _(_) /____ -| | /| / / __ `/ / / ___/ -| |/ |/ / /_/ / / (__ ) -|__/|__/\__,_/_/_/____/ -The electron alternative for Go -(c) Lea Anthony 2019-present -*/ - -/** - * Any is a dummy creation function for simple or unknown types. - */ -export function Any(source: any): T { - return source; -} - -/** - * ByteSlice is a creation function that replaces - * null strings with empty strings. - */ -export function ByteSlice(source: any): string { - return ((source == null) ? "" : source); -} - -/** - * Array takes a creation function for an arbitrary type - * and returns an in-place creation function for an array - * whose elements are of that type. - */ -export function Array(element: (source: any) => T): (source: any) => T[] { - if (element === Any) { - return (source) => (source === null ? [] : source); - } - - return (source) => { - if (source === null) { - return []; - } - for (let i = 0; i < source.length; i++) { - source[i] = element(source[i]); - } - return source; - }; -} - -/** - * Map takes creation functions for two arbitrary types - * and returns an in-place creation function for an object - * whose keys and values are of those types. - */ -export function Map(key: (source: any) => K, value: (source: any) => V): (source: any) => Record { - if (value === Any) { - return (source) => (source === null ? {} : source); - } - - return (source) => { - if (source === null) { - return {}; - } - for (const key in source) { - source[key] = value(source[key]); - } - return source; - }; -} - -/** - * Nullable takes a creation function for an arbitrary type - * and returns a creation function for a nullable value of that type. - */ -export function Nullable(element: (source: any) => T): (source: any) => (T | null) { - if (element === Any) { - return Any; - } - - return (source) => (source === null ? null : element(source)); -} - -/** - * Struct takes an object mapping field names to creation functions - * and returns an in-place creation function for a struct. - */ -export function Struct(createField: Record any>): - = any>(source: any) => U -{ - let allAny = true; - for (const name in createField) { - if (createField[name] !== Any) { - allAny = false; - break; - } - } - if (allAny) { - return Any; - } - - return (source) => { - for (const name in createField) { - if (name in source) { - source[name] = createField[name](source[name]); - } - } - return source; - }; -} - -/** - * Maps known event names to creation functions for their data types. - * Will be monkey-patched by the binding generator. - */ -export const Events: Record any> = {}; diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/src/dialogs.ts b/v3/internal/runtime/desktop/@wailsio/runtime/src/dialogs.ts deleted file mode 100644 index 3ce18ef26..000000000 --- a/v3/internal/runtime/desktop/@wailsio/runtime/src/dialogs.ts +++ /dev/null @@ -1,183 +0,0 @@ -/* - _ __ _ __ -| | / /___ _(_) /____ -| | /| / / __ `/ / / ___/ -| |/ |/ / /_/ / / (__ ) -|__/|__/\__,_/_/_/____/ -The electron alternative for Go -(c) Lea Anthony 2019-present -*/ - -import {newRuntimeCaller, objectNames} from "./runtime.js"; - -// setup -window._wails = window._wails || {}; - -const call = newRuntimeCaller(objectNames.Dialog); - -// Define constants from the `methods` object in Title Case -const DialogInfo = 0; -const DialogWarning = 1; -const DialogError = 2; -const DialogQuestion = 3; -const DialogOpenFile = 4; -const DialogSaveFile = 5; - -export interface OpenFileDialogOptions { - /** Indicates if directories can be chosen. */ - CanChooseDirectories?: boolean; - /** Indicates if files can be chosen. */ - CanChooseFiles?: boolean; - /** Indicates if directories can be created. */ - CanCreateDirectories?: boolean; - /** Indicates if hidden files should be shown. */ - ShowHiddenFiles?: boolean; - /** Indicates if aliases should be resolved. */ - ResolvesAliases?: boolean; - /** Indicates if multiple selection is allowed. */ - AllowsMultipleSelection?: boolean; - /** Indicates if the extension should be hidden. */ - HideExtension?: boolean; - /** Indicates if hidden extensions can be selected. */ - CanSelectHiddenExtension?: boolean; - /** Indicates if file packages should be treated as directories. */ - TreatsFilePackagesAsDirectories?: boolean; - /** Indicates if other file types are allowed. */ - AllowsOtherFiletypes?: boolean; - /** Array of file filters. */ - Filters?: FileFilter[]; - /** Title of the dialog. */ - Title?: string; - /** Message to show in the dialog. */ - Message?: string; - /** Text to display on the button. */ - ButtonText?: string; - /** Directory to open in the dialog. */ - Directory?: string; - /** Indicates if the dialog should appear detached from the main window. */ - Detached?: boolean; -} - -export interface SaveFileDialogOptions { - /** Default filename to use in the dialog. */ - Filename?: string; - /** Indicates if directories can be chosen. */ - CanChooseDirectories?: boolean; - /** Indicates if files can be chosen. */ - CanChooseFiles?: boolean; - /** Indicates if directories can be created. */ - CanCreateDirectories?: boolean; - /** Indicates if hidden files should be shown. */ - ShowHiddenFiles?: boolean; - /** Indicates if aliases should be resolved. */ - ResolvesAliases?: boolean; - /** Indicates if the extension should be hidden. */ - HideExtension?: boolean; - /** Indicates if hidden extensions can be selected. */ - CanSelectHiddenExtension?: boolean; - /** Indicates if file packages should be treated as directories. */ - TreatsFilePackagesAsDirectories?: boolean; - /** Indicates if other file types are allowed. */ - AllowsOtherFiletypes?: boolean; - /** Array of file filters. */ - Filters?: FileFilter[]; - /** Title of the dialog. */ - Title?: string; - /** Message to show in the dialog. */ - Message?: string; - /** Text to display on the button. */ - ButtonText?: string; - /** Directory to open in the dialog. */ - Directory?: string; - /** Indicates if the dialog should appear detached from the main window. */ - Detached?: boolean; -} - -export interface MessageDialogOptions { - /** The title of the dialog window. */ - Title?: string; - /** The main message to show in the dialog. */ - Message?: string; - /** Array of button options to show in the dialog. */ - Buttons?: Button[]; - /** True if the dialog should appear detached from the main window (if applicable). */ - Detached?: boolean; -} - -export interface Button { - /** Text that appears within the button. */ - Label?: string; - /** True if the button should cancel an operation when clicked. */ - IsCancel?: boolean; - /** True if the button should be the default action when the user presses enter. */ - IsDefault?: boolean; -} - -export interface FileFilter { - /** Display name for the filter, it could be "Text Files", "Images" etc. */ - DisplayName?: string; - /** Pattern to match for the filter, e.g. "*.txt;*.md" for text markdown files. */ - Pattern?: string; -} - -/** - * Presents a dialog of specified type with the given options. - * - * @param type - Dialog type. - * @param options - Options for the dialog. - * @returns A promise that resolves with result of dialog. - */ -function dialog(type: number, options: MessageDialogOptions | OpenFileDialogOptions | SaveFileDialogOptions = {}): Promise { - return call(type, options); -} - -/** - * Presents an info dialog. - * - * @param options - Dialog options - * @returns A promise that resolves with the label of the chosen button. - */ -export function Info(options: MessageDialogOptions): Promise { return dialog(DialogInfo, options); } - -/** - * Presents a warning dialog. - * - * @param options - Dialog options. - * @returns A promise that resolves with the label of the chosen button. - */ -export function Warning(options: MessageDialogOptions): Promise { return dialog(DialogWarning, options); } - -/** - * Presents an error dialog. - * - * @param options - Dialog options. - * @returns A promise that resolves with the label of the chosen button. - */ -export function Error(options: MessageDialogOptions): Promise { return dialog(DialogError, options); } - -/** - * Presents a question dialog. - * - * @param options - Dialog options. - * @returns A promise that resolves with the label of the chosen button. - */ -export function Question(options: MessageDialogOptions): Promise { return dialog(DialogQuestion, options); } - -/** - * Presents a file selection dialog to pick one or more files to open. - * - * @param options - Dialog options. - * @returns Selected file or list of files, or a blank string/empty list if no file has been selected. - */ -export function OpenFile(options: OpenFileDialogOptions & { AllowsMultipleSelection: true }): Promise; -export function OpenFile(options: OpenFileDialogOptions & { AllowsMultipleSelection?: false | undefined }): Promise; -export function OpenFile(options: OpenFileDialogOptions): Promise; -export function OpenFile(options: OpenFileDialogOptions): Promise { return dialog(DialogOpenFile, options) ?? []; } - -/** - * Presents a file selection dialog to pick a file to save. - * - * @param options - Dialog options. - * @returns Selected file, or a blank string if no file has been selected. - */ -export function SaveFile(options: SaveFileDialogOptions): Promise { return dialog(DialogSaveFile, options); } diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/src/drag.ts b/v3/internal/runtime/desktop/@wailsio/runtime/src/drag.ts deleted file mode 100644 index 54624f7fc..000000000 --- a/v3/internal/runtime/desktop/@wailsio/runtime/src/drag.ts +++ /dev/null @@ -1,262 +0,0 @@ -/* - _ __ _ __ -| | / /___ _(_) /____ -| | /| / / __ `/ / / ___/ -| |/ |/ / /_/ / / (__ ) -|__/|__/\__,_/_/_/____/ -The electron alternative for Go -(c) Lea Anthony 2019-present -*/ - -import { invoke, IsWindows } from "./system.js"; -import { GetFlag } from "./flags.js"; -import { canTrackButtons, eventTarget } from "./utils.js"; - -// Setup -let canDrag = false; -let dragging = false; - -let resizable = false; -let canResize = false; -let resizing = false; -let resizeEdge: string = ""; -let defaultCursor = "auto"; - -let buttons = 0; -const buttonsTracked = canTrackButtons(); - -window._wails = window._wails || {}; -window._wails.setResizable = (value: boolean): void => { - resizable = value; - if (!resizable) { - // Stop resizing if in progress. - canResize = resizing = false; - setResize(); - } -}; - -// Defer attaching mouse listeners until we know we're not on mobile. -let dragInitDone = false; -function isMobile(): boolean { - const os = (window as any)._wails?.environment?.OS; - if (os === "ios" || os === "android") return true; - // Fallback heuristic if environment not yet set - const ua = navigator.userAgent || navigator.vendor || (window as any).opera || ""; - return /android|iphone|ipad|ipod|iemobile|wpdesktop/i.test(ua); -} -function tryInitDragHandlers(): void { - if (dragInitDone) return; - if (isMobile()) return; - window.addEventListener('mousedown', update, { capture: true }); - window.addEventListener('mousemove', update, { capture: true }); - window.addEventListener('mouseup', update, { capture: true }); - for (const ev of ['click', 'contextmenu', 'dblclick']) { - window.addEventListener(ev, suppressEvent, { capture: true }); - } - dragInitDone = true; -} -// Attempt immediate init (in case environment already present) -tryInitDragHandlers(); -// Also attempt on DOM ready -document.addEventListener('DOMContentLoaded', tryInitDragHandlers, { once: true }); -// As a last resort, poll for environment for a short period -let dragEnvPolls = 0; -const dragEnvPoll = window.setInterval(() => { - if (dragInitDone) { window.clearInterval(dragEnvPoll); return; } - tryInitDragHandlers(); - if (++dragEnvPolls > 100) { window.clearInterval(dragEnvPoll); } -}, 50); - -function suppressEvent(event: Event) { - // Suppress click events while resizing or dragging. - if (dragging || resizing) { - event.stopImmediatePropagation(); - event.stopPropagation(); - event.preventDefault(); - } -} - -// Use constants to avoid comparing strings multiple times. -const MouseDown = 0; -const MouseUp = 1; -const MouseMove = 2; - -function update(event: MouseEvent) { - // Windows suppresses mouse events at the end of dragging or resizing, - // so we need to be smart and synthesize button events. - - let eventType: number, eventButtons = event.buttons; - switch (event.type) { - case 'mousedown': - eventType = MouseDown; - if (!buttonsTracked) { eventButtons = buttons | (1 << event.button); } - break; - case 'mouseup': - eventType = MouseUp; - if (!buttonsTracked) { eventButtons = buttons & ~(1 << event.button); } - break; - default: - eventType = MouseMove; - if (!buttonsTracked) { eventButtons = buttons; } - break; - } - - let released = buttons & ~eventButtons; - let pressed = eventButtons & ~buttons; - - buttons = eventButtons; - - // Synthesize a release-press sequence if we detect a press of an already pressed button. - if (eventType === MouseDown && !(pressed & event.button)) { - released |= (1 << event.button); - pressed |= (1 << event.button); - } - - // Suppress all button events during dragging and resizing, - // unless this is a mouseup event that is ending a drag action. - if ( - eventType !== MouseMove // Fast path for mousemove - && resizing - || ( - dragging - && ( - eventType === MouseDown - || event.button !== 0 - ) - ) - ) { - event.stopImmediatePropagation(); - event.stopPropagation(); - event.preventDefault(); - } - - // Handle releases - if (released & 1) { primaryUp(event); } - // Handle presses - if (pressed & 1) { primaryDown(event); } - - // Handle mousemove - if (eventType === MouseMove) { onMouseMove(event); }; -} - -function primaryDown(event: MouseEvent): void { - // Reset readiness state. - canDrag = false; - canResize = false; - - // Ignore repeated clicks on macOS and Linux. - if (!IsWindows()) { - if (event.type === 'mousedown' && event.button === 0 && event.detail !== 1) { - return; - } - } - - if (resizeEdge) { - // Ready to resize if the primary button was pressed for the first time. - canResize = true; - // Do not start drag operations when on resize edges. - return; - } - - // Retrieve target element - const target = eventTarget(event); - - // Ready to drag if the primary button was pressed for the first time on a draggable element. - // Ignore clicks on the scrollbar. - const style = window.getComputedStyle(target); - canDrag = ( - style.getPropertyValue("--wails-draggable").trim() === "drag" - && ( - event.offsetX - parseFloat(style.paddingLeft) < target.clientWidth - && event.offsetY - parseFloat(style.paddingTop) < target.clientHeight - ) - ); -} - -function primaryUp(event: MouseEvent) { - // Stop dragging and resizing. - canDrag = false; - dragging = false; - canResize = false; - resizing = false; -} - -const cursorForEdge = Object.freeze({ - "se-resize": "nwse-resize", - "sw-resize": "nesw-resize", - "nw-resize": "nwse-resize", - "ne-resize": "nesw-resize", - "w-resize": "ew-resize", - "n-resize": "ns-resize", - "s-resize": "ns-resize", - "e-resize": "ew-resize", -}) - -function setResize(edge?: keyof typeof cursorForEdge): void { - if (edge) { - if (!resizeEdge) { defaultCursor = document.body.style.cursor; } - document.body.style.cursor = cursorForEdge[edge]; - } else if (!edge && resizeEdge) { - document.body.style.cursor = defaultCursor; - } - - resizeEdge = edge || ""; -} - -function onMouseMove(event: MouseEvent): void { - if (canResize && resizeEdge) { - // Start resizing. - resizing = true; - invoke("wails:resize:" + resizeEdge); - } else if (canDrag) { - // Start dragging. - dragging = true; - invoke("wails:drag"); - } - - if (dragging || resizing) { - // Either drag or resize is ongoing, - // reset readiness and stop processing. - canDrag = canResize = false; - return; - } - - if (!resizable || !IsWindows()) { - if (resizeEdge) { setResize(); } - return; - } - - const resizeHandleHeight = GetFlag("system.resizeHandleHeight") || 5; - const resizeHandleWidth = GetFlag("system.resizeHandleWidth") || 5; - - // Extra pixels for the corner areas. - const cornerExtra = GetFlag("resizeCornerExtra") || 10; - - const rightBorder = (window.outerWidth - event.clientX) < resizeHandleWidth; - const leftBorder = event.clientX < resizeHandleWidth; - const topBorder = event.clientY < resizeHandleHeight; - const bottomBorder = (window.outerHeight - event.clientY) < resizeHandleHeight; - - // Adjust for corner areas. - const rightCorner = (window.outerWidth - event.clientX) < (resizeHandleWidth + cornerExtra); - const leftCorner = event.clientX < (resizeHandleWidth + cornerExtra); - const topCorner = event.clientY < (resizeHandleHeight + cornerExtra); - const bottomCorner = (window.outerHeight - event.clientY) < (resizeHandleHeight + cornerExtra); - - if (!leftCorner && !topCorner && !bottomCorner && !rightCorner) { - // Optimisation: out of all corner areas implies out of borders. - setResize(); - } - // Detect corners. - else if (rightCorner && bottomCorner) setResize("se-resize"); - else if (leftCorner && bottomCorner) setResize("sw-resize"); - else if (leftCorner && topCorner) setResize("nw-resize"); - else if (topCorner && rightCorner) setResize("ne-resize"); - // Detect borders. - else if (leftBorder) setResize("w-resize"); - else if (topBorder) setResize("n-resize"); - else if (bottomBorder) setResize("s-resize"); - else if (rightBorder) setResize("e-resize"); - // Out of border area. - else setResize(); -} diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/src/event_types.ts b/v3/internal/runtime/desktop/@wailsio/runtime/src/event_types.ts deleted file mode 100644 index db381077d..000000000 --- a/v3/internal/runtime/desktop/@wailsio/runtime/src/event_types.ts +++ /dev/null @@ -1,260 +0,0 @@ -/* - _ __ _ __ -| | / /___ _(_) /____ -| | /| / / __ `/ / / ___/ -| |/ |/ / /_/ / / (__ ) -|__/|__/\__,_/_/_/____/ -The electron alternative for Go -(c) Lea Anthony 2019-present -*/ - -// Cynhyrchwyd y ffeil hon yn awtomatig. PEIDIWCH Â MODIWL -// This file is automatically generated. DO NOT EDIT - -export const Types = Object.freeze({ - Windows: Object.freeze({ - APMPowerSettingChange: "windows:APMPowerSettingChange", - APMPowerStatusChange: "windows:APMPowerStatusChange", - APMResumeAutomatic: "windows:APMResumeAutomatic", - APMResumeSuspend: "windows:APMResumeSuspend", - APMSuspend: "windows:APMSuspend", - ApplicationStarted: "windows:ApplicationStarted", - SystemThemeChanged: "windows:SystemThemeChanged", - WebViewNavigationCompleted: "windows:WebViewNavigationCompleted", - WindowActive: "windows:WindowActive", - WindowBackgroundErase: "windows:WindowBackgroundErase", - WindowClickActive: "windows:WindowClickActive", - WindowClosing: "windows:WindowClosing", - WindowDidMove: "windows:WindowDidMove", - WindowDidResize: "windows:WindowDidResize", - WindowDPIChanged: "windows:WindowDPIChanged", - WindowDragDrop: "windows:WindowDragDrop", - WindowDragEnter: "windows:WindowDragEnter", - WindowDragLeave: "windows:WindowDragLeave", - WindowDragOver: "windows:WindowDragOver", - WindowEndMove: "windows:WindowEndMove", - WindowEndResize: "windows:WindowEndResize", - WindowFullscreen: "windows:WindowFullscreen", - WindowHide: "windows:WindowHide", - WindowInactive: "windows:WindowInactive", - WindowKeyDown: "windows:WindowKeyDown", - WindowKeyUp: "windows:WindowKeyUp", - WindowKillFocus: "windows:WindowKillFocus", - WindowNonClientHit: "windows:WindowNonClientHit", - WindowNonClientMouseDown: "windows:WindowNonClientMouseDown", - WindowNonClientMouseLeave: "windows:WindowNonClientMouseLeave", - WindowNonClientMouseMove: "windows:WindowNonClientMouseMove", - WindowNonClientMouseUp: "windows:WindowNonClientMouseUp", - WindowPaint: "windows:WindowPaint", - WindowRestore: "windows:WindowRestore", - WindowSetFocus: "windows:WindowSetFocus", - WindowShow: "windows:WindowShow", - WindowStartMove: "windows:WindowStartMove", - WindowStartResize: "windows:WindowStartResize", - WindowUnFullscreen: "windows:WindowUnFullscreen", - WindowZOrderChanged: "windows:WindowZOrderChanged", - WindowMinimise: "windows:WindowMinimise", - WindowUnMinimise: "windows:WindowUnMinimise", - WindowMaximise: "windows:WindowMaximise", - WindowUnMaximise: "windows:WindowUnMaximise", - }), - Mac: Object.freeze({ - ApplicationDidBecomeActive: "mac:ApplicationDidBecomeActive", - ApplicationDidChangeBackingProperties: "mac:ApplicationDidChangeBackingProperties", - ApplicationDidChangeEffectiveAppearance: "mac:ApplicationDidChangeEffectiveAppearance", - ApplicationDidChangeIcon: "mac:ApplicationDidChangeIcon", - ApplicationDidChangeOcclusionState: "mac:ApplicationDidChangeOcclusionState", - ApplicationDidChangeScreenParameters: "mac:ApplicationDidChangeScreenParameters", - ApplicationDidChangeStatusBarFrame: "mac:ApplicationDidChangeStatusBarFrame", - ApplicationDidChangeStatusBarOrientation: "mac:ApplicationDidChangeStatusBarOrientation", - ApplicationDidChangeTheme: "mac:ApplicationDidChangeTheme", - ApplicationDidFinishLaunching: "mac:ApplicationDidFinishLaunching", - ApplicationDidHide: "mac:ApplicationDidHide", - ApplicationDidResignActive: "mac:ApplicationDidResignActive", - ApplicationDidUnhide: "mac:ApplicationDidUnhide", - ApplicationDidUpdate: "mac:ApplicationDidUpdate", - ApplicationShouldHandleReopen: "mac:ApplicationShouldHandleReopen", - ApplicationWillBecomeActive: "mac:ApplicationWillBecomeActive", - ApplicationWillFinishLaunching: "mac:ApplicationWillFinishLaunching", - ApplicationWillHide: "mac:ApplicationWillHide", - ApplicationWillResignActive: "mac:ApplicationWillResignActive", - ApplicationWillTerminate: "mac:ApplicationWillTerminate", - ApplicationWillUnhide: "mac:ApplicationWillUnhide", - ApplicationWillUpdate: "mac:ApplicationWillUpdate", - MenuDidAddItem: "mac:MenuDidAddItem", - MenuDidBeginTracking: "mac:MenuDidBeginTracking", - MenuDidClose: "mac:MenuDidClose", - MenuDidDisplayItem: "mac:MenuDidDisplayItem", - MenuDidEndTracking: "mac:MenuDidEndTracking", - MenuDidHighlightItem: "mac:MenuDidHighlightItem", - MenuDidOpen: "mac:MenuDidOpen", - MenuDidPopUp: "mac:MenuDidPopUp", - MenuDidRemoveItem: "mac:MenuDidRemoveItem", - MenuDidSendAction: "mac:MenuDidSendAction", - MenuDidSendActionToItem: "mac:MenuDidSendActionToItem", - MenuDidUpdate: "mac:MenuDidUpdate", - MenuWillAddItem: "mac:MenuWillAddItem", - MenuWillBeginTracking: "mac:MenuWillBeginTracking", - MenuWillDisplayItem: "mac:MenuWillDisplayItem", - MenuWillEndTracking: "mac:MenuWillEndTracking", - MenuWillHighlightItem: "mac:MenuWillHighlightItem", - MenuWillOpen: "mac:MenuWillOpen", - MenuWillPopUp: "mac:MenuWillPopUp", - MenuWillRemoveItem: "mac:MenuWillRemoveItem", - MenuWillSendAction: "mac:MenuWillSendAction", - MenuWillSendActionToItem: "mac:MenuWillSendActionToItem", - MenuWillUpdate: "mac:MenuWillUpdate", - WebViewDidCommitNavigation: "mac:WebViewDidCommitNavigation", - WebViewDidFinishNavigation: "mac:WebViewDidFinishNavigation", - WebViewDidReceiveServerRedirectForProvisionalNavigation: "mac:WebViewDidReceiveServerRedirectForProvisionalNavigation", - WebViewDidStartProvisionalNavigation: "mac:WebViewDidStartProvisionalNavigation", - WindowDidBecomeKey: "mac:WindowDidBecomeKey", - WindowDidBecomeMain: "mac:WindowDidBecomeMain", - WindowDidBeginSheet: "mac:WindowDidBeginSheet", - WindowDidChangeAlpha: "mac:WindowDidChangeAlpha", - WindowDidChangeBackingLocation: "mac:WindowDidChangeBackingLocation", - WindowDidChangeBackingProperties: "mac:WindowDidChangeBackingProperties", - WindowDidChangeCollectionBehavior: "mac:WindowDidChangeCollectionBehavior", - WindowDidChangeEffectiveAppearance: "mac:WindowDidChangeEffectiveAppearance", - WindowDidChangeOcclusionState: "mac:WindowDidChangeOcclusionState", - WindowDidChangeOrderingMode: "mac:WindowDidChangeOrderingMode", - WindowDidChangeScreen: "mac:WindowDidChangeScreen", - WindowDidChangeScreenParameters: "mac:WindowDidChangeScreenParameters", - WindowDidChangeScreenProfile: "mac:WindowDidChangeScreenProfile", - WindowDidChangeScreenSpace: "mac:WindowDidChangeScreenSpace", - WindowDidChangeScreenSpaceProperties: "mac:WindowDidChangeScreenSpaceProperties", - WindowDidChangeSharingType: "mac:WindowDidChangeSharingType", - WindowDidChangeSpace: "mac:WindowDidChangeSpace", - WindowDidChangeSpaceOrderingMode: "mac:WindowDidChangeSpaceOrderingMode", - WindowDidChangeTitle: "mac:WindowDidChangeTitle", - WindowDidChangeToolbar: "mac:WindowDidChangeToolbar", - WindowDidDeminiaturize: "mac:WindowDidDeminiaturize", - WindowDidEndSheet: "mac:WindowDidEndSheet", - WindowDidEnterFullScreen: "mac:WindowDidEnterFullScreen", - WindowDidEnterVersionBrowser: "mac:WindowDidEnterVersionBrowser", - WindowDidExitFullScreen: "mac:WindowDidExitFullScreen", - WindowDidExitVersionBrowser: "mac:WindowDidExitVersionBrowser", - WindowDidExpose: "mac:WindowDidExpose", - WindowDidFocus: "mac:WindowDidFocus", - WindowDidMiniaturize: "mac:WindowDidMiniaturize", - WindowDidMove: "mac:WindowDidMove", - WindowDidOrderOffScreen: "mac:WindowDidOrderOffScreen", - WindowDidOrderOnScreen: "mac:WindowDidOrderOnScreen", - WindowDidResignKey: "mac:WindowDidResignKey", - WindowDidResignMain: "mac:WindowDidResignMain", - WindowDidResize: "mac:WindowDidResize", - WindowDidUpdate: "mac:WindowDidUpdate", - WindowDidUpdateAlpha: "mac:WindowDidUpdateAlpha", - WindowDidUpdateCollectionBehavior: "mac:WindowDidUpdateCollectionBehavior", - WindowDidUpdateCollectionProperties: "mac:WindowDidUpdateCollectionProperties", - WindowDidUpdateShadow: "mac:WindowDidUpdateShadow", - WindowDidUpdateTitle: "mac:WindowDidUpdateTitle", - WindowDidUpdateToolbar: "mac:WindowDidUpdateToolbar", - WindowDidZoom: "mac:WindowDidZoom", - WindowFileDraggingEntered: "mac:WindowFileDraggingEntered", - WindowFileDraggingExited: "mac:WindowFileDraggingExited", - WindowFileDraggingPerformed: "mac:WindowFileDraggingPerformed", - WindowHide: "mac:WindowHide", - WindowMaximise: "mac:WindowMaximise", - WindowUnMaximise: "mac:WindowUnMaximise", - WindowMinimise: "mac:WindowMinimise", - WindowUnMinimise: "mac:WindowUnMinimise", - WindowShouldClose: "mac:WindowShouldClose", - WindowShow: "mac:WindowShow", - WindowWillBecomeKey: "mac:WindowWillBecomeKey", - WindowWillBecomeMain: "mac:WindowWillBecomeMain", - WindowWillBeginSheet: "mac:WindowWillBeginSheet", - WindowWillChangeOrderingMode: "mac:WindowWillChangeOrderingMode", - WindowWillClose: "mac:WindowWillClose", - WindowWillDeminiaturize: "mac:WindowWillDeminiaturize", - WindowWillEnterFullScreen: "mac:WindowWillEnterFullScreen", - WindowWillEnterVersionBrowser: "mac:WindowWillEnterVersionBrowser", - WindowWillExitFullScreen: "mac:WindowWillExitFullScreen", - WindowWillExitVersionBrowser: "mac:WindowWillExitVersionBrowser", - WindowWillFocus: "mac:WindowWillFocus", - WindowWillMiniaturize: "mac:WindowWillMiniaturize", - WindowWillMove: "mac:WindowWillMove", - WindowWillOrderOffScreen: "mac:WindowWillOrderOffScreen", - WindowWillOrderOnScreen: "mac:WindowWillOrderOnScreen", - WindowWillResignMain: "mac:WindowWillResignMain", - WindowWillResize: "mac:WindowWillResize", - WindowWillUnfocus: "mac:WindowWillUnfocus", - WindowWillUpdate: "mac:WindowWillUpdate", - WindowWillUpdateAlpha: "mac:WindowWillUpdateAlpha", - WindowWillUpdateCollectionBehavior: "mac:WindowWillUpdateCollectionBehavior", - WindowWillUpdateCollectionProperties: "mac:WindowWillUpdateCollectionProperties", - WindowWillUpdateShadow: "mac:WindowWillUpdateShadow", - WindowWillUpdateTitle: "mac:WindowWillUpdateTitle", - WindowWillUpdateToolbar: "mac:WindowWillUpdateToolbar", - WindowWillUpdateVisibility: "mac:WindowWillUpdateVisibility", - WindowWillUseStandardFrame: "mac:WindowWillUseStandardFrame", - WindowZoomIn: "mac:WindowZoomIn", - WindowZoomOut: "mac:WindowZoomOut", - WindowZoomReset: "mac:WindowZoomReset", - }), - Linux: Object.freeze({ - ApplicationStartup: "linux:ApplicationStartup", - SystemThemeChanged: "linux:SystemThemeChanged", - WindowDeleteEvent: "linux:WindowDeleteEvent", - WindowDidMove: "linux:WindowDidMove", - WindowDidResize: "linux:WindowDidResize", - WindowFocusIn: "linux:WindowFocusIn", - WindowFocusOut: "linux:WindowFocusOut", - WindowLoadStarted: "linux:WindowLoadStarted", - WindowLoadRedirected: "linux:WindowLoadRedirected", - WindowLoadCommitted: "linux:WindowLoadCommitted", - WindowLoadFinished: "linux:WindowLoadFinished", - }), - iOS: Object.freeze({ - ApplicationDidBecomeActive: "ios:ApplicationDidBecomeActive", - ApplicationDidEnterBackground: "ios:ApplicationDidEnterBackground", - ApplicationDidFinishLaunching: "ios:ApplicationDidFinishLaunching", - ApplicationDidReceiveMemoryWarning: "ios:ApplicationDidReceiveMemoryWarning", - ApplicationWillEnterForeground: "ios:ApplicationWillEnterForeground", - ApplicationWillResignActive: "ios:ApplicationWillResignActive", - ApplicationWillTerminate: "ios:ApplicationWillTerminate", - WindowDidLoad: "ios:WindowDidLoad", - WindowWillAppear: "ios:WindowWillAppear", - WindowDidAppear: "ios:WindowDidAppear", - WindowWillDisappear: "ios:WindowWillDisappear", - WindowDidDisappear: "ios:WindowDidDisappear", - WindowSafeAreaInsetsChanged: "ios:WindowSafeAreaInsetsChanged", - WindowOrientationChanged: "ios:WindowOrientationChanged", - WindowTouchBegan: "ios:WindowTouchBegan", - WindowTouchMoved: "ios:WindowTouchMoved", - WindowTouchEnded: "ios:WindowTouchEnded", - WindowTouchCancelled: "ios:WindowTouchCancelled", - WebViewDidStartNavigation: "ios:WebViewDidStartNavigation", - WebViewDidFinishNavigation: "ios:WebViewDidFinishNavigation", - WebViewDidFailNavigation: "ios:WebViewDidFailNavigation", - WebViewDecidePolicyForNavigationAction: "ios:WebViewDecidePolicyForNavigationAction", - }), - Common: Object.freeze({ - ApplicationOpenedWithFile: "common:ApplicationOpenedWithFile", - ApplicationStarted: "common:ApplicationStarted", - ApplicationLaunchedWithUrl: "common:ApplicationLaunchedWithUrl", - ThemeChanged: "common:ThemeChanged", - WindowClosing: "common:WindowClosing", - WindowDidMove: "common:WindowDidMove", - WindowDidResize: "common:WindowDidResize", - WindowDPIChanged: "common:WindowDPIChanged", - WindowFilesDropped: "common:WindowFilesDropped", - WindowFocus: "common:WindowFocus", - WindowFullscreen: "common:WindowFullscreen", - WindowHide: "common:WindowHide", - WindowLostFocus: "common:WindowLostFocus", - WindowMaximise: "common:WindowMaximise", - WindowMinimise: "common:WindowMinimise", - WindowToggleFrameless: "common:WindowToggleFrameless", - WindowRestore: "common:WindowRestore", - WindowRuntimeReady: "common:WindowRuntimeReady", - WindowShow: "common:WindowShow", - WindowUnFullscreen: "common:WindowUnFullscreen", - WindowUnMaximise: "common:WindowUnMaximise", - WindowUnMinimise: "common:WindowUnMinimise", - WindowZoom: "common:WindowZoom", - WindowZoomIn: "common:WindowZoomIn", - WindowZoomOut: "common:WindowZoomOut", - WindowZoomReset: "common:WindowZoomReset", - }), -}); diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/src/events.test.js b/v3/internal/runtime/desktop/@wailsio/runtime/src/events.test.js deleted file mode 100644 index e8157a17a..000000000 --- a/v3/internal/runtime/desktop/@wailsio/runtime/src/events.test.js +++ /dev/null @@ -1,155 +0,0 @@ -import { On, Off, OffAll, OnMultiple, WailsEvent, Once } from './events'; -import { eventListeners } from "./listener"; -import { expect, describe, it, vi, afterEach, beforeEach } from 'vitest'; - -const dispatchWailsEvent = window._wails.dispatchWailsEvent; - -afterEach(() => { - OffAll(); - vi.resetAllMocks(); -}); - -describe("OnMultiple", () => { - const testEvent = { name: 'a', data: ["hello", "events"] }; - const cb = vi.fn((ev) => { - expect(ev).toBeInstanceOf(WailsEvent); - expect(ev).toMatchObject(testEvent); - }); - - it("should dispatch a properly initialised WailsEvent", () => { - OnMultiple('a', cb, 5); - dispatchWailsEvent(testEvent); - expect(cb).toHaveBeenCalled(); - }); - - it("should stop after the specified number of times", () => { - OnMultiple('a', cb, 5); - dispatchWailsEvent(testEvent); - dispatchWailsEvent(testEvent); - dispatchWailsEvent(testEvent); - dispatchWailsEvent(testEvent); - dispatchWailsEvent(testEvent); - dispatchWailsEvent(testEvent); - expect(cb).toHaveBeenCalledTimes(5); - }); - - it("should return a cancel fn", () => { - const cancel = OnMultiple('a', cb, 5); - dispatchWailsEvent(testEvent); - dispatchWailsEvent(testEvent); - cancel(); - dispatchWailsEvent(testEvent); - dispatchWailsEvent(testEvent); - expect(cb).toBeCalledTimes(2); - }); -}); - -describe("On", () => { - let testEvent = { name: 'a', data: ["hello", "events"], sender: "window" }; - const cb = vi.fn((ev) => { - expect(ev).toBeInstanceOf(WailsEvent); - expect(ev).toMatchObject(testEvent); - }); - - it("should dispatch a properly initialised WailsEvent", () => { - On('a', cb); - dispatchWailsEvent(testEvent); - expect(cb).toHaveBeenCalled(); - }); - - it("should never stop", () => { - On('a', cb); - expect(eventListeners.get('a')[0].maxCallbacks).toBe(-1); - dispatchWailsEvent(testEvent); - expect(eventListeners.get('a')[0].maxCallbacks).toBe(-1); - }); - - it("should return a cancel fn", () => { - const cancel = On('a', cb) - dispatchWailsEvent(testEvent); - cancel(); - dispatchWailsEvent(testEvent); - expect(cb).toHaveBeenCalledTimes(1); - }); -}); - -describe("Once", () => { - const testEvent = { name: 'a', data: ["hello", "events"] }; - const cb = vi.fn((ev) => { - expect(ev).toBeInstanceOf(WailsEvent); - expect(ev).toMatchObject(testEvent); - }); - - it("should dispatch a properly initialised WailsEvent", () => { - Once('a', cb); - dispatchWailsEvent(testEvent); - expect(cb).toHaveBeenCalled(); - }); - - it("should stop after one time", () => { - Once('a', cb) - dispatchWailsEvent(testEvent); - dispatchWailsEvent(testEvent); - dispatchWailsEvent(testEvent); - expect(cb).toHaveBeenCalledTimes(1); - }); - - it("should return a cancel fn", () => { - const cancel = Once('a', cb) - cancel(); - dispatchWailsEvent(testEvent); - expect(cb).not.toHaveBeenCalled(); - }); -}) - -describe("Off", () => { - const cba = vi.fn(), cbb = vi.fn(), cbc = vi.fn(); - - beforeEach(() => { - On('a', cba); - On('a', cba); - On('a', cba); - On('b', cbb); - On('c', cbc); - On('c', cbc); - }); - - it("should cancel all event listeners for a single type", () => { - Off('a'); - dispatchWailsEvent({ name: 'a' }); - dispatchWailsEvent({ name: 'b' }); - dispatchWailsEvent({ name: 'c' }); - expect(cba).not.toHaveBeenCalled(); - expect(cbb).toHaveBeenCalledTimes(1); - expect(cbc).toHaveBeenCalledTimes(2); - }); - - it("should cancel all event listeners for multiple types", () => { - Off('a', 'c') - dispatchWailsEvent({ name: 'a' }); - dispatchWailsEvent({ name: 'b' }); - dispatchWailsEvent({ name: 'c' }); - expect(cba).not.toHaveBeenCalled(); - expect(cbb).toHaveBeenCalledTimes(1); - expect(cbc).not.toHaveBeenCalled(); - }); -}); - -describe("OffAll", () => { - it("should cancel all event listeners", () => { - const cba = vi.fn(), cbb = vi.fn(), cbc = vi.fn(); - On('a', cba); - On('a', cba); - On('a', cba); - On('b', cbb); - On('c', cbc); - On('c', cbc); - OffAll(); - dispatchWailsEvent({ name: 'a' }); - dispatchWailsEvent({ name: 'b' }); - dispatchWailsEvent({ name: 'c' }); - expect(cba).not.toHaveBeenCalled(); - expect(cbb).not.toHaveBeenCalled(); - expect(cbc).not.toHaveBeenCalled(); - }); -}); diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/src/events.ts b/v3/internal/runtime/desktop/@wailsio/runtime/src/events.ts deleted file mode 100644 index cf6a2581d..000000000 --- a/v3/internal/runtime/desktop/@wailsio/runtime/src/events.ts +++ /dev/null @@ -1,170 +0,0 @@ -/* - _ __ _ __ -| | / /___ _(_) /____ -| | /| / / __ `/ / / ___/ -| |/ |/ / /_/ / / (__ ) -|__/|__/\__,_/_/_/____/ -The electron alternative for Go -(c) Lea Anthony 2019-present -*/ - -import { newRuntimeCaller, objectNames } from "./runtime.js"; -import { eventListeners, Listener, listenerOff } from "./listener.js"; -import { Events as Create } from "./create.js"; -import { Types } from "./event_types.js"; - -// Setup -window._wails = window._wails || {}; -window._wails.dispatchWailsEvent = dispatchWailsEvent; - -const call = newRuntimeCaller(objectNames.Events); -const EmitMethod = 0; - -export * from "./event_types.js"; - -/** - * A table of data types for all known events. - * Will be monkey-patched by the binding generator. - */ -export interface CustomEvents {} - -/** - * Either a known event name or an arbitrary string. - */ -export type WailsEventName = E | (string & {}); - -/** - * Union of all known system event names. - */ -type SystemEventName = { - [K in keyof (typeof Types)]: (typeof Types)[K][keyof ((typeof Types)[K])] -} extends (infer M) ? M[keyof M] : never; - -/** - * The data type associated to a given event. - */ -export type WailsEventData = - E extends keyof CustomEvents ? CustomEvents[E] : (E extends SystemEventName ? void : any); - -/** - * The type of handlers for a given event. - */ -export type WailsEventCallback = (ev: WailsEvent) => void; - -/** - * Represents a system event or a custom event emitted through wails-provided facilities. - */ -export class WailsEvent { - /** - * The name of the event. - */ - name: E; - - /** - * Optional data associated with the emitted event. - */ - data: WailsEventData; - - /** - * Name of the originating window. Omitted for application events. - * Will be overridden if set manually. - */ - sender?: string; - - constructor(name: E, data: WailsEventData); - constructor(name: WailsEventData extends null | void ? E : never) - constructor(name: E, data?: any) { - this.name = name; - this.data = data ?? null; - } -} - -function dispatchWailsEvent(event: any) { - let listeners = eventListeners.get(event.name); - if (!listeners) { - return; - } - - let wailsEvent = new WailsEvent( - event.name, - (event.name in Create) ? Create[event.name](event.data) : event.data - ); - if ('sender' in event) { - wailsEvent.sender = event.sender; - } - - listeners = listeners.filter(listener => !listener.dispatch(wailsEvent)); - if (listeners.length === 0) { - eventListeners.delete(event.name); - } else { - eventListeners.set(event.name, listeners); - } -} - -/** - * Register a callback function to be called multiple times for a specific event. - * - * @param eventName - The name of the event to register the callback for. - * @param callback - The callback function to be called when the event is triggered. - * @param maxCallbacks - The maximum number of times the callback can be called for the event. Once the maximum number is reached, the callback will no longer be called. - * @returns A function that, when called, will unregister the callback from the event. - */ -export function OnMultiple(eventName: E, callback: WailsEventCallback, maxCallbacks: number) { - let listeners = eventListeners.get(eventName) || []; - const thisListener = new Listener(eventName, callback, maxCallbacks); - listeners.push(thisListener); - eventListeners.set(eventName, listeners); - return () => listenerOff(thisListener); -} - -/** - * Registers a callback function to be executed when the specified event occurs. - * - * @param eventName - The name of the event to register the callback for. - * @param callback - The callback function to be called when the event is triggered. - * @returns A function that, when called, will unregister the callback from the event. - */ -export function On(eventName: E, callback: WailsEventCallback): () => void { - return OnMultiple(eventName, callback, -1); -} - -/** - * Registers a callback function to be executed only once for the specified event. - * - * @param eventName - The name of the event to register the callback for. - * @param callback - The callback function to be called when the event is triggered. - * @returns A function that, when called, will unregister the callback from the event. - */ -export function Once(eventName: E, callback: WailsEventCallback): () => void { - return OnMultiple(eventName, callback, 1); -} - -/** - * Removes event listeners for the specified event names. - * - * @param eventNames - The name of the events to remove listeners for. - */ -export function Off(...eventNames: [WailsEventName, ...WailsEventName[]]): void { - eventNames.forEach(eventName => eventListeners.delete(eventName)); -} - -/** - * Removes all event listeners. - */ -export function OffAll(): void { - eventListeners.clear(); -} - -/** - * Emits an event. - * - * @returns A promise that will be fulfilled once the event has been emitted. Resolves to true if the event was cancelled. - * @param name - The name of the event to emit - * @param data - The data that will be sent with the event - */ -export function Emit(name: E, data: WailsEventData): Promise -export function Emit(name: WailsEventData extends null | void ? E : never): Promise -export function Emit(name: WailsEventData, data?: any): Promise { - return call(EmitMethod, new WailsEvent(name, data)) -} - diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/src/flags.ts b/v3/internal/runtime/desktop/@wailsio/runtime/src/flags.ts deleted file mode 100644 index 9e4ad2427..000000000 --- a/v3/internal/runtime/desktop/@wailsio/runtime/src/flags.ts +++ /dev/null @@ -1,23 +0,0 @@ -/* - _ __ _ __ -| | / /___ _(_) /____ -| | /| / / __ `/ / / ___/ -| |/ |/ / /_/ / / (__ ) -|__/|__/\__,_/_/_/____/ -The electron alternative for Go -(c) Lea Anthony 2019-present -*/ - -/** - * Retrieves the value associated with the specified key from the flag map. - * - * @param key - The key to retrieve the value for. - * @return The value associated with the specified key. - */ -export function GetFlag(key: string): any { - try { - return window._wails.flags[key]; - } catch (e) { - throw new Error("Unable to retrieve flag '" + key + "': " + e, { cause: e }); - } -} diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/src/global.d.ts b/v3/internal/runtime/desktop/@wailsio/runtime/src/global.d.ts deleted file mode 100644 index 231896ce1..000000000 --- a/v3/internal/runtime/desktop/@wailsio/runtime/src/global.d.ts +++ /dev/null @@ -1,17 +0,0 @@ -/* - _ __ _ __ -| | / /___ _(_) /____ -| | /| / / __ `/ / / ___/ -| |/ |/ / /_/ / / (__ ) -|__/|__/\__,_/_/_/____/ -The electron alternative for Go -(c) Lea Anthony 2019-present -*/ - -declare global { - interface Window { - _wails: Record; - } -} - -export {}; diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/src/index.ts b/v3/internal/runtime/desktop/@wailsio/runtime/src/index.ts deleted file mode 100644 index 1cdac37c4..000000000 --- a/v3/internal/runtime/desktop/@wailsio/runtime/src/index.ts +++ /dev/null @@ -1,101 +0,0 @@ -/* - _ __ _ __ -| | / /___ _(_) /____ -| | /| / / __ `/ / / ___/ -| |/ |/ / /_/ / / (__ ) -|__/|__/\__,_/_/_/____/ -The electron alternative for Go -(c) Lea Anthony 2019-present -*/ - -// Setup -window._wails = window._wails || {}; - -import "./contextmenu.js"; -import "./drag.js"; - -// Re-export public API -import * as Application from "./application.js"; -import * as Browser from "./browser.js"; -import * as Call from "./calls.js"; -import * as Clipboard from "./clipboard.js"; -import * as Create from "./create.js"; -import * as Dialogs from "./dialogs.js"; -import * as Events from "./events.js"; -import * as Flags from "./flags.js"; -import * as Screens from "./screens.js"; -import * as System from "./system.js"; -import * as IOS from "./ios.js"; -import Window, { handleDragEnter, handleDragLeave, handleDragOver } from "./window.js"; -import * as WML from "./wml.js"; - -export { - Application, - Browser, - Call, - Clipboard, - Dialogs, - Events, - Flags, - Screens, - System, - IOS, - Window, - WML -}; - -/** - * An internal utility consumed by the binding generator. - * - * @ignore - */ -export { Create }; - -export * from "./cancellable.js"; - -// Export transport interfaces and utilities -export { - setTransport, - getTransport, - type RuntimeTransport, - objectNames, - clientId, -} from "./runtime.js"; - -import { clientId } from "./runtime.js"; - -// Notify backend -window._wails.invoke = System.invoke; -window._wails.clientId = clientId; - -// Register platform handlers (internal API) -// Note: Window is the thisWindow instance (default export from window.ts) -// Binding ensures 'this' correctly refers to the current window instance -window._wails.handlePlatformFileDrop = Window.HandlePlatformFileDrop.bind(Window); - -// Linux-specific drag handlers (GTK intercepts DOM drag events) -window._wails.handleDragEnter = handleDragEnter; -window._wails.handleDragLeave = handleDragLeave; -window._wails.handleDragOver = handleDragOver; - -System.invoke("wails:runtime:ready"); - -/** - * Loads a script from the given URL if it exists. - * Uses HEAD request to check existence, then injects a script tag. - * Silently ignores if the script doesn't exist. - */ -export function loadOptionalScript(url: string): Promise { - return fetch(url, { method: 'HEAD' }) - .then(response => { - if (response.ok) { - const script = document.createElement('script'); - script.src = url; - document.head.appendChild(script); - } - }) - .catch(() => {}); // Silently ignore - script is optional -} - -// Load custom.js if available (used by server mode for WebSocket events, etc.) -loadOptionalScript('/wails/custom.js'); diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/src/ios.ts b/v3/internal/runtime/desktop/@wailsio/runtime/src/ios.ts deleted file mode 100644 index 33a428edf..000000000 --- a/v3/internal/runtime/desktop/@wailsio/runtime/src/ios.ts +++ /dev/null @@ -1,36 +0,0 @@ -/* - _ __ _ __ -| | / /___ _(_) /____ -| | /| / / __ `/ / / ___/ -| |/ |/ / /_/ / / (__ ) -|__/|__/\__,_/_/_/____/ -The electron alternative for Go -(c) Lea Anthony 2019-present -*/ - -import { newRuntimeCaller, objectNames } from "./runtime.js"; - -const call = newRuntimeCaller(objectNames.IOS); - -// Method IDs -const HapticsImpact = 0; -const DeviceInfo = 1; - -export namespace Haptics { - export type ImpactStyle = "light"|"medium"|"heavy"|"soft"|"rigid"; - export function Impact(style: ImpactStyle = "medium"): Promise { - return call(HapticsImpact, { style }); - } -} - -export namespace Device { - export interface Info { - model: string; - systemName: string; - systemVersion: string; - isSimulator: boolean; - } - export function Info(): Promise { - return call(DeviceInfo); - } -} diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/src/listener.ts b/v3/internal/runtime/desktop/@wailsio/runtime/src/listener.ts deleted file mode 100644 index 0d74debca..000000000 --- a/v3/internal/runtime/desktop/@wailsio/runtime/src/listener.ts +++ /dev/null @@ -1,52 +0,0 @@ -/* - _ __ _ __ -| | / /___ _(_) /____ -| | /| / / __ `/ / / ___/ -| |/ |/ / /_/ / / (__ ) -|__/|__/\__,_/_/_/____/ -The electron alternative for Go -(c) Lea Anthony 2019-present -*/ - -// The following utilities have been factored out of ./events.ts -// for testing purposes. - -export const eventListeners = new Map(); - -export class Listener { - eventName: string; - callback: (data: any) => void; - maxCallbacks: number; - - constructor(eventName: string, callback: (data: any) => void, maxCallbacks: number) { - this.eventName = eventName; - this.callback = callback; - this.maxCallbacks = maxCallbacks || -1; - } - - dispatch(data: any): boolean { - try { - this.callback(data); - } catch (err) { - console.error(err); - } - - if (this.maxCallbacks === -1) return false; - this.maxCallbacks -= 1; - return this.maxCallbacks === 0; - } -} - -export function listenerOff(listener: Listener): void { - let listeners = eventListeners.get(listener.eventName); - if (!listeners) { - return; - } - - listeners = listeners.filter(l => l !== listener); - if (listeners.length === 0) { - eventListeners.delete(listener.eventName); - } else { - eventListeners.set(listener.eventName, listeners); - } -} diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/src/nanoid.ts b/v3/internal/runtime/desktop/@wailsio/runtime/src/nanoid.ts deleted file mode 100644 index bfe83048f..000000000 --- a/v3/internal/runtime/desktop/@wailsio/runtime/src/nanoid.ts +++ /dev/null @@ -1,42 +0,0 @@ -// Source: https://github.com/ai/nanoid - -// The MIT License (MIT) -// -// Copyright 2017 Andrey Sitnik -// -// Permission is hereby granted, free of charge, to any person obtaining a copy of -// this software and associated documentation files (the "Software"), to deal in -// the Software without restriction, including without limitation the rights to -// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of -// the Software, and to permit persons to whom the Software is furnished to do so, -// subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS -// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR -// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER -// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -// This alphabet uses `A-Za-z0-9_-` symbols. -// The order of characters is optimized for better gzip and brotli compression. -// References to the same file (works both for gzip and brotli): -// `'use`, `andom`, and `rict'` -// References to the brotli default dictionary: -// `-26T`, `1983`, `40px`, `75px`, `bush`, `jack`, `mind`, `very`, and `wolf` -const urlAlphabet = - 'useandom-26T198340PX75pxJACKVERYMINDBUSHWOLF_GQZbfghjklqvwyzrict' - -export function nanoid(size: number = 21): string { - let id = '' - // A compact alternative for `for (var i = 0; i < step; i++)`. - let i = size | 0 - while (i--) { - // `| 0` is more compact and faster than `Math.floor()`. - id += urlAlphabet[(Math.random() * 64) | 0] - } - return id -} diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/src/plugins/vite.ts b/v3/internal/runtime/desktop/@wailsio/runtime/src/plugins/vite.ts deleted file mode 100644 index b661dce82..000000000 --- a/v3/internal/runtime/desktop/@wailsio/runtime/src/plugins/vite.ts +++ /dev/null @@ -1,76 +0,0 @@ -import type {Plugin} from 'vite'; - -/* - _ __ _ __ -| | / /___ _(_) /____ -| | /| / / __ `/ / / ___/ -| |/ |/ / /_/ / / (__ ) -|__/|__/\__,_/_/_/____/ -The electron alternative for Go -(c) Lea Anthony 2019-present -*/ - -const TYPED_EVENTS_MODULE = "\0wailsio_runtime_events_typed"; - -/** - * A plugin that extends the wails runtime with locally generated code - * to provide support for typed custom events. - * With the plugin installed, vite will fail to build the project - * unless wails bindings have been generated first. - * - * @param {string} [bindingsRoot] - The root import path for generated bindings - */ -export default function WailsTypedEvents(bindingsRoot: string): Plugin { - let bindingsId: string, - runtimeId: string, - eventsId: string; - - return { - name: "wails-typed-events", - async buildStart() { - const bindingsPath = `${bindingsRoot}/github.com/wailsapp/wails/v3/internal/eventcreate`; - let resolution = await this.resolve(bindingsPath); - if (!resolution || resolution.external) { - this.error(`Event bindings module not found at import specifier '${bindingsPath}'. Please verify that the wails tool is up to date and the binding generator runs successfully. If you moved the bindings to a custom location, ensure you supplied the correct root path as the first argument to \`wailsTypedEventsPlugin\``); - return; - } - bindingsId = resolution.id; - - resolution = await this.resolve("@wailsio/runtime"); - if (!resolution || resolution.external) { return; } - runtimeId = resolution.id; - - resolution = await this.resolve("./events.js", runtimeId); - if (!resolution || resolution.external) { - this.error("Could not resolve events module within @wailsio/runtime package. Please verify that the module is correctly installed and up to date."); - return; - } - - eventsId = resolution.id; - }, - resolveId: { - order: 'pre', - handler(id, importer) { - if ( - bindingsId !== null - && runtimeId !== null - && eventsId !== null - && importer === runtimeId - && id === "./events.js" - ) { - return TYPED_EVENTS_MODULE; - } - return undefined; - } - }, - load(id) { - if (id === TYPED_EVENTS_MODULE) { - return ( - `import ${JSON.stringify(bindingsId)};\n` - + `export * from ${JSON.stringify(eventsId)};` - ); - } - return undefined; - } - } -} diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/src/promises_aplus.test.js b/v3/internal/runtime/desktop/@wailsio/runtime/src/promises_aplus.test.js deleted file mode 100644 index baf51e3c0..000000000 --- a/v3/internal/runtime/desktop/@wailsio/runtime/src/promises_aplus.test.js +++ /dev/null @@ -1,44 +0,0 @@ -import * as util from "util"; -import * as V from "vitest"; -import { CancellablePromise } from "./cancellable"; - -// The Promises/A+ suite handles some errors late. -process.on('rejectionHandled', function () {}); - -// The Promises/A+ suite leaves some errors unhandled. -process.on('unhandledRejection', function (reason, promise) { - if (promise instanceof CancellablePromise && reason != null && typeof reason === 'object') { - for (const key of ['dummy', 'other', 'sentinel']) { - if (reason[key] === key) { - return; - } - } - } - throw new Error(`Unhandled rejection at: ${util.inspect(promise)}; reason: ${util.inspect(reason)}`, { cause: reason }); -}); - -// Emulate a minimal version of the mocha BDD API using vitest primitives. -global.context = global.describe = V.describe; -global.specify = global.it = function it(desc, fn) { - let viTestFn = fn; - if (fn?.length) { - viTestFn = () => new Promise((done) => fn(done)); - } - V.it(desc, viTestFn); -} -global.before = function(desc, fn) { V.beforeAll(typeof desc === 'function' ? desc : fn) }; -global.after = function(desc, fn) { V.afterAll(typeof desc === 'function' ? desc : fn) }; -global.beforeEach = function(desc, fn) { V.beforeEach(typeof desc === 'function' ? desc : fn) }; -global.afterEach = function(desc, fn) { V.afterEach(typeof desc === 'function' ? desc : fn) }; - -require('promises-aplus-tests').mocha({ - resolved(value) { - return CancellablePromise.resolve(value); - }, - rejected(reason) { - return CancellablePromise.reject(reason); - }, - deferred() { - return CancellablePromise.withResolvers(); - } -}); diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/src/runtime.ts b/v3/internal/runtime/desktop/@wailsio/runtime/src/runtime.ts deleted file mode 100644 index eaa70d838..000000000 --- a/v3/internal/runtime/desktop/@wailsio/runtime/src/runtime.ts +++ /dev/null @@ -1,141 +0,0 @@ -/* - _ __ _ __ -| | / /___ _(_) /____ -| | /| / / __ `/ / / ___/ -| |/ |/ / /_/ / / (__ ) -|__/|__/\__,_/_/_/____/ -The electron alternative for Go -(c) Lea Anthony 2019-present -*/ - -import { nanoid } from "./nanoid.js"; - -const runtimeURL = window.location.origin + "/wails/runtime"; - -// Re-export nanoid for custom transport implementations -export { nanoid }; - -// Object Names -export const objectNames = Object.freeze({ - Call: 0, - Clipboard: 1, - Application: 2, - Events: 3, - ContextMenu: 4, - Dialog: 5, - Window: 6, - Screens: 7, - System: 8, - Browser: 9, - CancelCall: 10, - IOS: 11, -}); -export let clientId = nanoid(); - -/** - * RuntimeTransport defines the interface for custom IPC transport implementations. - * Implement this interface to use WebSockets, custom protocols, or any other - * transport mechanism instead of the default HTTP fetch. - */ -export interface RuntimeTransport { - /** - * Send a runtime call and return the response. - * - * @param objectID - The Wails object ID (0=Call, 1=Clipboard, etc.) - * @param method - The method ID to call - * @param windowName - Optional window name - * @param args - Arguments to pass (will be JSON stringified if present) - * @returns Promise that resolves with the response data - */ - call(objectID: number, method: number, windowName: string, args: any): Promise; -} - -/** - * Custom transport implementation (can be set by user) - */ -let customTransport: RuntimeTransport | null = null; - -/** - * Set a custom transport for all Wails runtime calls. - * This allows you to replace the default HTTP fetch transport with - * WebSockets, custom protocols, or any other mechanism. - * - * @param transport - Your custom transport implementation - * - * @example - * ```typescript - * import { setTransport } from '/wails/runtime.js'; - * - * const wsTransport = { - * call: async (objectID, method, windowName, args) => { - * // Your WebSocket implementation - * } - * }; - * - * setTransport(wsTransport); - * ``` - */ -export function setTransport(transport: RuntimeTransport | null): void { - customTransport = transport; -} - -/** - * Get the current transport (useful for extending/wrapping) - */ -export function getTransport(): RuntimeTransport | null { - return customTransport; -} - -/** - * Creates a new runtime caller with specified ID. - * - * @param object - The object to invoke the method on. - * @param windowName - The name of the window. - * @return The new runtime caller function. - */ -export function newRuntimeCaller(object: number, windowName: string = '') { - return function (method: number, args: any = null) { - return runtimeCallWithID(object, method, windowName, args); - }; -} - -async function runtimeCallWithID(objectID: number, method: number, windowName: string, args: any): Promise { - // Use custom transport if available - if (customTransport) { - return customTransport.call(objectID, method, windowName, args); - } - - // Default HTTP fetch transport - let url = new URL(runtimeURL); - - let body: { object: number; method: number, args?: any } = { - object: objectID, - method - } - if (args !== null && args !== undefined) { - body.args = args; - } - - let headers: Record = { - ["x-wails-client-id"]: clientId, - ["Content-Type"]: "application/json" - } - if (windowName) { - headers["x-wails-window-name"] = windowName; - } - - let response = await fetch(url, { - method: 'POST', - headers, - body: JSON.stringify(body) - }); - if (!response.ok) { - throw new Error(await response.text()); - } - - if ((response.headers.get("Content-Type")?.indexOf("application/json") ?? -1) !== -1) { - return response.json(); - } else { - return response.text(); - } -} diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/src/screens.ts b/v3/internal/runtime/desktop/@wailsio/runtime/src/screens.ts deleted file mode 100644 index c0ecfd7be..000000000 --- a/v3/internal/runtime/desktop/@wailsio/runtime/src/screens.ts +++ /dev/null @@ -1,88 +0,0 @@ -/* - _ __ _ __ -| | / /___ _(_) /____ -| | /| / / __ `/ / / ___/ -| |/ |/ / /_/ / / (__ ) -|__/|__/\__,_/_/_/____/ -The electron alternative for Go -(c) Lea Anthony 2019-present -*/ - -export interface Size { - /** The width of a rectangular area. */ - Width: number; - /** The height of a rectangular area. */ - Height: number; -} - -export interface Rect { - /** The X coordinate of the origin. */ - X: number; - /** The Y coordinate of the origin. */ - Y: number; - /** The width of the rectangle. */ - Width: number; - /** The height of the rectangle. */ - Height: number; -} - -export interface Screen { - /** Unique identifier for the screen. */ - ID: string; - /** Human-readable name of the screen. */ - Name: string; - /** The scale factor of the screen (DPI/96). 1 = standard DPI, 2 = HiDPI (Retina), etc. */ - ScaleFactor: number; - /** The X coordinate of the screen. */ - X: number; - /** The Y coordinate of the screen. */ - Y: number; - /** Contains the width and height of the screen. */ - Size: Size; - /** Contains the bounds of the screen in terms of X, Y, Width, and Height. */ - Bounds: Rect; - /** Contains the physical bounds of the screen in terms of X, Y, Width, and Height (before scaling). */ - PhysicalBounds: Rect; - /** Contains the area of the screen that is actually usable (excluding taskbar and other system UI). */ - WorkArea: Rect; - /** Contains the physical WorkArea of the screen (before scaling). */ - PhysicalWorkArea: Rect; - /** True if this is the primary monitor selected by the user in the operating system. */ - IsPrimary: boolean; - /** The rotation of the screen. */ - Rotation: number; -} - -import { newRuntimeCaller, objectNames } from "./runtime.js"; -const call = newRuntimeCaller(objectNames.Screens); - -const getAll = 0; -const getPrimary = 1; -const getCurrent = 2; - -/** - * Gets all screens. - * - * @returns A promise that resolves to an array of Screen objects. - */ -export function GetAll(): Promise { - return call(getAll); -} - -/** - * Gets the primary screen. - * - * @returns A promise that resolves to the primary screen. - */ -export function GetPrimary(): Promise { - return call(getPrimary); -} - -/** - * Gets the current active screen. - * - * @returns A promise that resolves with the current active screen. - */ -export function GetCurrent(): Promise { - return call(getCurrent); -} diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/src/system.ts b/v3/internal/runtime/desktop/@wailsio/runtime/src/system.ts deleted file mode 100644 index c4fdd6cfe..000000000 --- a/v3/internal/runtime/desktop/@wailsio/runtime/src/system.ts +++ /dev/null @@ -1,159 +0,0 @@ -/* - _ __ _ __ -| | / /___ _(_) /____ -| | /| / / __ `/ / / ___/ -| |/ |/ / /_/ / / (__ ) -|__/|__/\__,_/_/_/____/ -The electron alternative for Go -(c) Lea Anthony 2019-present -*/ - -import { newRuntimeCaller, objectNames } from "./runtime.js"; - -const call = newRuntimeCaller(objectNames.System); - -const SystemIsDarkMode = 0; -const SystemEnvironment = 1; -const SystemCapabilities = 2; - -const _invoke = (function () { - try { - // Windows WebView2 - if ((window as any).chrome?.webview?.postMessage) { - return (window as any).chrome.webview.postMessage.bind((window as any).chrome.webview); - } - // macOS/iOS WKWebView - else if ((window as any).webkit?.messageHandlers?.['external']?.postMessage) { - return (window as any).webkit.messageHandlers['external'].postMessage.bind((window as any).webkit.messageHandlers['external']); - } - // Android WebView - uses addJavascriptInterface which exposes window.wails.invoke - else if ((window as any).wails?.invoke) { - return (msg: any) => (window as any).wails.invoke(typeof msg === 'string' ? msg : JSON.stringify(msg)); - } - } catch(e) {} - - console.warn('\n%c⚠️ Browser Environment Detected %c\n\n%cOnly UI previews are available in the browser. For full functionality, please run the application in desktop mode.\nMore information at: https://v3.wails.io/learn/build/#using-a-browser-for-development\n', - 'background: #ffffff; color: #000000; font-weight: bold; padding: 4px 8px; border-radius: 4px; border: 2px solid #000000;', - 'background: transparent;', - 'color: #ffffff; font-style: italic; font-weight: bold;'); - return null; -})(); - -export function invoke(msg: any): void { - _invoke?.(msg); -} - -/** - * Retrieves the system dark mode status. - * - * @returns A promise that resolves to a boolean value indicating if the system is in dark mode. - */ -export function IsDarkMode(): Promise { - return call(SystemIsDarkMode); -} - -/** - * Fetches the capabilities of the application from the server. - * - * @returns A promise that resolves to an object containing the capabilities. - */ -export async function Capabilities(): Promise> { - return call(SystemCapabilities); -} - -export interface OSInfo { - /** The branding of the OS. */ - Branding: string; - /** The ID of the OS. */ - ID: string; - /** The name of the OS. */ - Name: string; - /** The version of the OS. */ - Version: string; -} - -export interface EnvironmentInfo { - /** The architecture of the system. */ - Arch: string; - /** True if the application is running in debug mode, otherwise false. */ - Debug: boolean; - /** The operating system in use. */ - OS: string; - /** Details of the operating system. */ - OSInfo: OSInfo; - /** Additional platform information. */ - PlatformInfo: Record; -} - -/** - * Retrieves environment details. - * - * @returns A promise that resolves to an object containing OS and system architecture. - */ -export function Environment(): Promise { - return call(SystemEnvironment); -} - -/** - * Checks if the current operating system is Windows. - * - * @return True if the operating system is Windows, otherwise false. - */ -export function IsWindows(): boolean { - return (window as any)._wails?.environment?.OS === "windows"; -} - -/** - * Checks if the current operating system is Linux. - * - * @returns Returns true if the current operating system is Linux, false otherwise. - */ -export function IsLinux(): boolean { - return (window as any)._wails?.environment?.OS === "linux"; -} - -/** - * Checks if the current environment is a macOS operating system. - * - * @returns True if the environment is macOS, false otherwise. - */ -export function IsMac(): boolean { - return (window as any)._wails?.environment?.OS === "darwin"; -} - -/** - * Checks if the current environment architecture is AMD64. - * - * @returns True if the current environment architecture is AMD64, false otherwise. - */ -export function IsAMD64(): boolean { - return (window as any)._wails?.environment?.Arch === "amd64"; -} - -/** - * Checks if the current architecture is ARM. - * - * @returns True if the current architecture is ARM, false otherwise. - */ -export function IsARM(): boolean { - return (window as any)._wails?.environment?.Arch === "arm"; -} - -/** - * Checks if the current environment is ARM64 architecture. - * - * @returns Returns true if the environment is ARM64 architecture, otherwise returns false. - */ -export function IsARM64(): boolean { - return (window as any)._wails?.environment?.Arch === "arm64"; -} - -/** - * Reports whether the app is being run in debug mode. - * - * @returns True if the app is being run in debug mode. - */ -export function IsDebug(): boolean { - return Boolean((window as any)._wails?.environment?.Debug); -} - diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/src/utils.ts b/v3/internal/runtime/desktop/@wailsio/runtime/src/utils.ts deleted file mode 100644 index 35b09463b..000000000 --- a/v3/internal/runtime/desktop/@wailsio/runtime/src/utils.ts +++ /dev/null @@ -1,105 +0,0 @@ -/* - _ __ _ __ -| | / /___ _(_) /____ -| | /| / / __ `/ / / ___/ -| |/ |/ / /_/ / / (__ ) -|__/|__/\__,_/_/_/____/ -The electron alternative for Go -(c) Lea Anthony 2019-present -*/ - -/** - * Logs a message to the console with custom formatting. - * - * @param message - The message to be logged. - */ -export function debugLog(message: any) { - // eslint-disable-next-line - console.log( - '%c wails3 %c ' + message + ' ', - 'background: #aa0000; color: #fff; border-radius: 3px 0px 0px 3px; padding: 1px; font-size: 0.7rem', - 'background: #009900; color: #fff; border-radius: 0px 3px 3px 0px; padding: 1px; font-size: 0.7rem' - ); -} - -/** - * Checks whether the webview supports the {@link MouseEvent#buttons} property. - * Looking at you macOS High Sierra! - */ -export function canTrackButtons(): boolean { - return (new MouseEvent('mousedown')).buttons === 0; -} - -/** - * Checks whether the browser supports removing listeners by triggering an AbortSignal - * (see https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#signal). - */ -export function canAbortListeners() { - if (!EventTarget || !AbortSignal || !AbortController) - return false; - - let result = true; - - const target = new EventTarget(); - const controller = new AbortController(); - target.addEventListener('test', () => { result = false; }, { signal: controller.signal }); - controller.abort(); - target.dispatchEvent(new CustomEvent('test')); - - return result; -} - -/** - * Resolves the closest HTMLElement ancestor of an event's target. - */ -export function eventTarget(event: Event): HTMLElement { - if (event.target instanceof HTMLElement) { - return event.target; - } else if (!(event.target instanceof HTMLElement) && event.target instanceof Node) { - return event.target.parentElement ?? document.body; - } else { - return document.body; - } -} - -/*** - This technique for proper load detection is taken from HTMX: - - BSD 2-Clause License - - Copyright (c) 2020, Big Sky Software - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are met: - - 1. Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - - 2. Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - - THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE - FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER - CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, - OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - - ***/ - -let isReady = false; -document.addEventListener('DOMContentLoaded', () => { isReady = true }); - -export function whenReady(callback: () => void) { - if (isReady || document.readyState === 'complete') { - callback(); - } else { - document.addEventListener('DOMContentLoaded', callback); - } -} diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/src/window.ts b/v3/internal/runtime/desktop/@wailsio/runtime/src/window.ts deleted file mode 100644 index 7a80fc17a..000000000 --- a/v3/internal/runtime/desktop/@wailsio/runtime/src/window.ts +++ /dev/null @@ -1,836 +0,0 @@ -/* - _ __ _ __ -| | / /___ _(_) /____ -| | /| / / __ `/ / / ___/ -| |/ |/ / /_/ / / (__ ) -|__/|__/\__,_/_/_/____/ -The electron alternative for Go -(c) Lea Anthony 2019-present -*/ - -import {newRuntimeCaller, objectNames} from "./runtime.js"; -import type { Screen } from "./screens.js"; - -// Drop target constants -const DROP_TARGET_ATTRIBUTE = 'data-file-drop-target'; -const DROP_TARGET_ACTIVE_CLASS = 'file-drop-target-active'; -let currentDropTarget: Element | null = null; - -const PositionMethod = 0; -const CenterMethod = 1; -const CloseMethod = 2; -const DisableSizeConstraintsMethod = 3; -const EnableSizeConstraintsMethod = 4; -const FocusMethod = 5; -const ForceReloadMethod = 6; -const FullscreenMethod = 7; -const GetScreenMethod = 8; -const GetZoomMethod = 9; -const HeightMethod = 10; -const HideMethod = 11; -const IsFocusedMethod = 12; -const IsFullscreenMethod = 13; -const IsMaximisedMethod = 14; -const IsMinimisedMethod = 15; -const MaximiseMethod = 16; -const MinimiseMethod = 17; -const NameMethod = 18; -const OpenDevToolsMethod = 19; -const RelativePositionMethod = 20; -const ReloadMethod = 21; -const ResizableMethod = 22; -const RestoreMethod = 23; -const SetPositionMethod = 24; -const SetAlwaysOnTopMethod = 25; -const SetBackgroundColourMethod = 26; -const SetFramelessMethod = 27; -const SetFullscreenButtonEnabledMethod = 28; -const SetMaxSizeMethod = 29; -const SetMinSizeMethod = 30; -const SetRelativePositionMethod = 31; -const SetResizableMethod = 32; -const SetSizeMethod = 33; -const SetTitleMethod = 34; -const SetZoomMethod = 35; -const ShowMethod = 36; -const SizeMethod = 37; -const ToggleFullscreenMethod = 38; -const ToggleMaximiseMethod = 39; -const ToggleFramelessMethod = 40; -const UnFullscreenMethod = 41; -const UnMaximiseMethod = 42; -const UnMinimiseMethod = 43; -const WidthMethod = 44; -const ZoomMethod = 45; -const ZoomInMethod = 46; -const ZoomOutMethod = 47; -const ZoomResetMethod = 48; -const SnapAssistMethod = 49; -const FilesDropped = 50; -const PrintMethod = 51; - -/** - * Finds the nearest drop target element by walking up the DOM tree. - */ -function getDropTargetElement(element: Element | null): Element | null { - if (!element) { - return null; - } - return element.closest(`[${DROP_TARGET_ATTRIBUTE}]`); -} - -/** - * Check if we can use WebView2's postMessageWithAdditionalObjects (Windows) - * Also checks that EnableFileDrop is true for this window. - */ -function canResolveFilePaths(): boolean { - // Must have WebView2's postMessageWithAdditionalObjects API (Windows only) - if ((window as any).chrome?.webview?.postMessageWithAdditionalObjects == null) { - return false; - } - // Must have EnableFileDrop set to true for this window - // This flag is set by the Go backend during runtime initialization - return (window as any)._wails?.flags?.enableFileDrop === true; -} - -/** - * Send file drop to backend via WebView2 (Windows only) - */ -function resolveFilePaths(x: number, y: number, files: File[]): void { - if ((window as any).chrome?.webview?.postMessageWithAdditionalObjects) { - (window as any).chrome.webview.postMessageWithAdditionalObjects(`file:drop:${x}:${y}`, files); - } -} - -// Native drag state (Linux/macOS intercept DOM drag events) -let nativeDragActive = false; - -/** - * Cleans up native drag state and hover effects. - * Called on drop or when drag leaves the window. - */ -function cleanupNativeDrag(): void { - nativeDragActive = false; - if (currentDropTarget) { - currentDropTarget.classList.remove(DROP_TARGET_ACTIVE_CLASS); - currentDropTarget = null; - } -} - -/** - * Called from Go when a file drag enters the window on Linux/macOS. - */ -function handleDragEnter(): void { - // Check if file drops are enabled for this window - if ((window as any)._wails?.flags?.enableFileDrop === false) { - return; // File drops disabled, don't activate drag state - } - nativeDragActive = true; -} - -/** - * Called from Go when a file drag leaves the window on Linux/macOS. - */ -function handleDragLeave(): void { - cleanupNativeDrag(); -} - -/** - * Called from Go during file drag to update hover state on Linux/macOS. - * @param x - X coordinate in CSS pixels - * @param y - Y coordinate in CSS pixels - */ -function handleDragOver(x: number, y: number): void { - if (!nativeDragActive) return; - - // Check if file drops are enabled for this window - if ((window as any)._wails?.flags?.enableFileDrop === false) { - return; // File drops disabled, don't show hover effects - } - - const targetElement = document.elementFromPoint(x, y); - const dropTarget = getDropTargetElement(targetElement); - - if (currentDropTarget && currentDropTarget !== dropTarget) { - currentDropTarget.classList.remove(DROP_TARGET_ACTIVE_CLASS); - } - - if (dropTarget) { - dropTarget.classList.add(DROP_TARGET_ACTIVE_CLASS); - currentDropTarget = dropTarget; - } else { - currentDropTarget = null; - } -} - - - -// Export the handlers for use by Go via index.ts -export { handleDragEnter, handleDragLeave, handleDragOver }; - -/** - * A record describing the position of a window. - */ -interface Position { - /** The horizontal position of the window. */ - x: number; - /** The vertical position of the window. */ - y: number; -} - -/** - * A record describing the size of a window. - */ -interface Size { - /** The width of the window. */ - width: number; - /** The height of the window. */ - height: number; -} - -// Private field names. -const callerSym = Symbol("caller"); - -class Window { - // Private fields. - private [callerSym]: (message: number, args?: any) => Promise; - - /** - * Initialises a window object with the specified name. - * - * @private - * @param name - The name of the target window. - */ - constructor(name: string = '') { - this[callerSym] = newRuntimeCaller(objectNames.Window, name) - - // bind instance method to make them easily usable in event handlers - for (const method of Object.getOwnPropertyNames(Window.prototype)) { - if ( - method !== "constructor" - && typeof (this as any)[method] === "function" - ) { - (this as any)[method] = (this as any)[method].bind(this); - } - } - } - - /** - * Gets the specified window. - * - * @param name - The name of the window to get. - * @returns The corresponding window object. - */ - Get(name: string): Window { - return new Window(name); - } - - /** - * Returns the absolute position of the window. - * - * @returns The current absolute position of the window. - */ - Position(): Promise { - return this[callerSym](PositionMethod); - } - - /** - * Centers the window on the screen. - */ - Center(): Promise { - return this[callerSym](CenterMethod); - } - - /** - * Closes the window. - */ - Close(): Promise { - return this[callerSym](CloseMethod); - } - - /** - * Disables min/max size constraints. - */ - DisableSizeConstraints(): Promise { - return this[callerSym](DisableSizeConstraintsMethod); - } - - /** - * Enables min/max size constraints. - */ - EnableSizeConstraints(): Promise { - return this[callerSym](EnableSizeConstraintsMethod); - } - - /** - * Focuses the window. - */ - Focus(): Promise { - return this[callerSym](FocusMethod); - } - - /** - * Forces the window to reload the page assets. - */ - ForceReload(): Promise { - return this[callerSym](ForceReloadMethod); - } - - /** - * Switches the window to fullscreen mode. - */ - Fullscreen(): Promise { - return this[callerSym](FullscreenMethod); - } - - /** - * Returns the screen that the window is on. - * - * @returns The screen the window is currently on. - */ - GetScreen(): Promise { - return this[callerSym](GetScreenMethod); - } - - /** - * Returns the current zoom level of the window. - * - * @returns The current zoom level. - */ - GetZoom(): Promise { - return this[callerSym](GetZoomMethod); - } - - /** - * Returns the height of the window. - * - * @returns The current height of the window. - */ - Height(): Promise { - return this[callerSym](HeightMethod); - } - - /** - * Hides the window. - */ - Hide(): Promise { - return this[callerSym](HideMethod); - } - - /** - * Returns true if the window is focused. - * - * @returns Whether the window is currently focused. - */ - IsFocused(): Promise { - return this[callerSym](IsFocusedMethod); - } - - /** - * Returns true if the window is fullscreen. - * - * @returns Whether the window is currently fullscreen. - */ - IsFullscreen(): Promise { - return this[callerSym](IsFullscreenMethod); - } - - /** - * Returns true if the window is maximised. - * - * @returns Whether the window is currently maximised. - */ - IsMaximised(): Promise { - return this[callerSym](IsMaximisedMethod); - } - - /** - * Returns true if the window is minimised. - * - * @returns Whether the window is currently minimised. - */ - IsMinimised(): Promise { - return this[callerSym](IsMinimisedMethod); - } - - /** - * Maximises the window. - */ - Maximise(): Promise { - return this[callerSym](MaximiseMethod); - } - - /** - * Minimises the window. - */ - Minimise(): Promise { - return this[callerSym](MinimiseMethod); - } - - /** - * Returns the name of the window. - * - * @returns The name of the window. - */ - Name(): Promise { - return this[callerSym](NameMethod); - } - - /** - * Opens the development tools pane. - */ - OpenDevTools(): Promise { - return this[callerSym](OpenDevToolsMethod); - } - - /** - * Returns the relative position of the window to the screen. - * - * @returns The current relative position of the window. - */ - RelativePosition(): Promise { - return this[callerSym](RelativePositionMethod); - } - - /** - * Reloads the page assets. - */ - Reload(): Promise { - return this[callerSym](ReloadMethod); - } - - /** - * Returns true if the window is resizable. - * - * @returns Whether the window is currently resizable. - */ - Resizable(): Promise { - return this[callerSym](ResizableMethod); - } - - /** - * Restores the window to its previous state if it was previously minimised, maximised or fullscreen. - */ - Restore(): Promise { - return this[callerSym](RestoreMethod); - } - - /** - * Sets the absolute position of the window. - * - * @param x - The desired horizontal absolute position of the window. - * @param y - The desired vertical absolute position of the window. - */ - SetPosition(x: number, y: number): Promise { - return this[callerSym](SetPositionMethod, { x, y }); - } - - /** - * Sets the window to be always on top. - * - * @param alwaysOnTop - Whether the window should stay on top. - */ - SetAlwaysOnTop(alwaysOnTop: boolean): Promise { - return this[callerSym](SetAlwaysOnTopMethod, { alwaysOnTop }); - } - - /** - * Sets the background colour of the window. - * - * @param r - The desired red component of the window background. - * @param g - The desired green component of the window background. - * @param b - The desired blue component of the window background. - * @param a - The desired alpha component of the window background. - */ - SetBackgroundColour(r: number, g: number, b: number, a: number): Promise { - return this[callerSym](SetBackgroundColourMethod, { r, g, b, a }); - } - - /** - * Removes the window frame and title bar. - * - * @param frameless - Whether the window should be frameless. - */ - SetFrameless(frameless: boolean): Promise { - return this[callerSym](SetFramelessMethod, { frameless }); - } - - /** - * Disables the system fullscreen button. - * - * @param enabled - Whether the fullscreen button should be enabled. - */ - SetFullscreenButtonEnabled(enabled: boolean): Promise { - return this[callerSym](SetFullscreenButtonEnabledMethod, { enabled }); - } - - /** - * Sets the maximum size of the window. - * - * @param width - The desired maximum width of the window. - * @param height - The desired maximum height of the window. - */ - SetMaxSize(width: number, height: number): Promise { - return this[callerSym](SetMaxSizeMethod, { width, height }); - } - - /** - * Sets the minimum size of the window. - * - * @param width - The desired minimum width of the window. - * @param height - The desired minimum height of the window. - */ - SetMinSize(width: number, height: number): Promise { - return this[callerSym](SetMinSizeMethod, { width, height }); - } - - /** - * Sets the relative position of the window to the screen. - * - * @param x - The desired horizontal relative position of the window. - * @param y - The desired vertical relative position of the window. - */ - SetRelativePosition(x: number, y: number): Promise { - return this[callerSym](SetRelativePositionMethod, { x, y }); - } - - /** - * Sets whether the window is resizable. - * - * @param resizable - Whether the window should be resizable. - */ - SetResizable(resizable: boolean): Promise { - return this[callerSym](SetResizableMethod, { resizable }); - } - - /** - * Sets the size of the window. - * - * @param width - The desired width of the window. - * @param height - The desired height of the window. - */ - SetSize(width: number, height: number): Promise { - return this[callerSym](SetSizeMethod, { width, height }); - } - - /** - * Sets the title of the window. - * - * @param title - The desired title of the window. - */ - SetTitle(title: string): Promise { - return this[callerSym](SetTitleMethod, { title }); - } - - /** - * Sets the zoom level of the window. - * - * @param zoom - The desired zoom level. - */ - SetZoom(zoom: number): Promise { - return this[callerSym](SetZoomMethod, { zoom }); - } - - /** - * Shows the window. - */ - Show(): Promise { - return this[callerSym](ShowMethod); - } - - /** - * Returns the size of the window. - * - * @returns The current size of the window. - */ - Size(): Promise { - return this[callerSym](SizeMethod); - } - - /** - * Toggles the window between fullscreen and normal. - */ - ToggleFullscreen(): Promise { - return this[callerSym](ToggleFullscreenMethod); - } - - /** - * Toggles the window between maximised and normal. - */ - ToggleMaximise(): Promise { - return this[callerSym](ToggleMaximiseMethod); - } - - /** - * Toggles the window between frameless and normal. - */ - ToggleFrameless(): Promise { - return this[callerSym](ToggleFramelessMethod); - } - - /** - * Un-fullscreens the window. - */ - UnFullscreen(): Promise { - return this[callerSym](UnFullscreenMethod); - } - - /** - * Un-maximises the window. - */ - UnMaximise(): Promise { - return this[callerSym](UnMaximiseMethod); - } - - /** - * Un-minimises the window. - */ - UnMinimise(): Promise { - return this[callerSym](UnMinimiseMethod); - } - - /** - * Returns the width of the window. - * - * @returns The current width of the window. - */ - Width(): Promise { - return this[callerSym](WidthMethod); - } - - /** - * Zooms the window. - */ - Zoom(): Promise { - return this[callerSym](ZoomMethod); - } - - /** - * Increases the zoom level of the webview content. - */ - ZoomIn(): Promise { - return this[callerSym](ZoomInMethod); - } - - /** - * Decreases the zoom level of the webview content. - */ - ZoomOut(): Promise { - return this[callerSym](ZoomOutMethod); - } - - /** - * Resets the zoom level of the webview content. - */ - ZoomReset(): Promise { - return this[callerSym](ZoomResetMethod); - } - - /** - * Handles file drops originating from platform-specific code (e.g., macOS/Linux native drag-and-drop). - * Gathers information about the drop target element and sends it back to the Go backend. - * - * @param filenames - An array of file paths (strings) that were dropped. - * @param x - The x-coordinate of the drop event (CSS pixels). - * @param y - The y-coordinate of the drop event (CSS pixels). - */ - HandlePlatformFileDrop(filenames: string[], x: number, y: number): void { - // Check if file drops are enabled for this window - if ((window as any)._wails?.flags?.enableFileDrop === false) { - return; // File drops disabled, ignore the drop - } - - const element = document.elementFromPoint(x, y); - const dropTarget = getDropTargetElement(element); - - if (!dropTarget) { - // Drop was not on a designated drop target - ignore - return; - } - - const elementDetails = { - id: dropTarget.id, - classList: Array.from(dropTarget.classList), - attributes: {} as { [key: string]: string }, - }; - for (let i = 0; i < dropTarget.attributes.length; i++) { - const attr = dropTarget.attributes[i]; - elementDetails.attributes[attr.name] = attr.value; - } - - const payload = { - filenames, - x, - y, - elementDetails, - }; - - this[callerSym](FilesDropped, payload); - - // Clean up native drag state after drop - cleanupNativeDrag(); - } - - /* Triggers Windows 11 Snap Assist feature (Windows only). - * This is equivalent to pressing Win+Z and shows snap layout options. - */ - SnapAssist(): Promise { - return this[callerSym](SnapAssistMethod); - } - - /** - * Opens the print dialog for the window. - */ - Print(): Promise { - return this[callerSym](PrintMethod); - } -} - -/** - * The window within which the script is running. - */ -const thisWindow = new Window(''); - -/** - * Sets up global drag and drop event listeners for file drops. - * Handles visual feedback (hover state) and file drop processing. - */ -function setupDropTargetListeners() { - const docElement = document.documentElement; - let dragEnterCounter = 0; - - docElement.addEventListener('dragenter', (event) => { - if (!event.dataTransfer?.types.includes('Files')) { - return; // Only handle file drags, let other drags pass through - } - event.preventDefault(); // Always prevent default to stop browser navigation - // On Windows, check if file drops are enabled for this window - if ((window as any)._wails?.flags?.enableFileDrop === false) { - event.dataTransfer.dropEffect = 'none'; // Show "no drop" cursor - return; // File drops disabled, don't show hover effects - } - dragEnterCounter++; - - const targetElement = document.elementFromPoint(event.clientX, event.clientY); - const dropTarget = getDropTargetElement(targetElement); - - // Update hover state - if (currentDropTarget && currentDropTarget !== dropTarget) { - currentDropTarget.classList.remove(DROP_TARGET_ACTIVE_CLASS); - } - - if (dropTarget) { - dropTarget.classList.add(DROP_TARGET_ACTIVE_CLASS); - event.dataTransfer.dropEffect = 'copy'; - currentDropTarget = dropTarget; - } else { - event.dataTransfer.dropEffect = 'none'; - currentDropTarget = null; - } - }, false); - - docElement.addEventListener('dragover', (event) => { - if (!event.dataTransfer?.types.includes('Files')) { - return; // Only handle file drags - } - event.preventDefault(); // Always prevent default to stop browser navigation - // On Windows, check if file drops are enabled for this window - if ((window as any)._wails?.flags?.enableFileDrop === false) { - event.dataTransfer.dropEffect = 'none'; // Show "no drop" cursor - return; // File drops disabled, don't show hover effects - } - - // Update drop target as cursor moves - const targetElement = document.elementFromPoint(event.clientX, event.clientY); - const dropTarget = getDropTargetElement(targetElement); - - if (currentDropTarget && currentDropTarget !== dropTarget) { - currentDropTarget.classList.remove(DROP_TARGET_ACTIVE_CLASS); - } - - if (dropTarget) { - if (!dropTarget.classList.contains(DROP_TARGET_ACTIVE_CLASS)) { - dropTarget.classList.add(DROP_TARGET_ACTIVE_CLASS); - } - event.dataTransfer.dropEffect = 'copy'; - currentDropTarget = dropTarget; - } else { - event.dataTransfer.dropEffect = 'none'; - currentDropTarget = null; - } - }, false); - - docElement.addEventListener('dragleave', (event) => { - if (!event.dataTransfer?.types.includes('Files')) { - return; - } - event.preventDefault(); // Always prevent default to stop browser navigation - // On Windows, check if file drops are enabled for this window - if ((window as any)._wails?.flags?.enableFileDrop === false) { - return; - } - - // On Linux/WebKitGTK and macOS, dragleave fires immediately with relatedTarget=null when native - // drag handling is involved. Ignore these spurious events - we'll clean up on drop instead. - if (event.relatedTarget === null) { - return; - } - - dragEnterCounter--; - - if (dragEnterCounter === 0 || - (currentDropTarget && !currentDropTarget.contains(event.relatedTarget as Node))) { - if (currentDropTarget) { - currentDropTarget.classList.remove(DROP_TARGET_ACTIVE_CLASS); - currentDropTarget = null; - } - dragEnterCounter = 0; - } - }, false); - - docElement.addEventListener('drop', (event) => { - if (!event.dataTransfer?.types.includes('Files')) { - return; // Only handle file drops - } - event.preventDefault(); // Always prevent default to stop browser navigation - // On Windows, check if file drops are enabled for this window - if ((window as any)._wails?.flags?.enableFileDrop === false) { - return; - } - dragEnterCounter = 0; - - if (currentDropTarget) { - currentDropTarget.classList.remove(DROP_TARGET_ACTIVE_CLASS); - currentDropTarget = null; - } - - // On Windows, handle file drops via JavaScript - // On macOS/Linux, native code will call HandlePlatformFileDrop - if (canResolveFilePaths()) { - const files: File[] = []; - if (event.dataTransfer.items) { - for (const item of event.dataTransfer.items) { - if (item.kind === 'file') { - const file = item.getAsFile(); - if (file) files.push(file); - } - } - } else if (event.dataTransfer.files) { - for (const file of event.dataTransfer.files) { - files.push(file); - } - } - - if (files.length > 0) { - resolveFilePaths(event.clientX, event.clientY, files); - } - } - }, false); -} - -// Initialize listeners when the script loads -if (typeof window !== "undefined" && typeof document !== "undefined") { - setupDropTargetListeners(); -} - -export default thisWindow; diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/src/wml.ts b/v3/internal/runtime/desktop/@wailsio/runtime/src/wml.ts deleted file mode 100644 index bdf7376cf..000000000 --- a/v3/internal/runtime/desktop/@wailsio/runtime/src/wml.ts +++ /dev/null @@ -1,209 +0,0 @@ -/* - _ __ _ __ -| | / /___ _(_) /____ -| | /| / / __ `/ / / ___/ -| |/ |/ / /_/ / / (__ ) -|__/|__/\__,_/_/_/____/ -The electron alternative for Go -(c) Lea Anthony 2019-present -*/ - -import { OpenURL } from "./browser.js"; -import { Question } from "./dialogs.js"; -import { Emit } from "./events.js"; -import { canAbortListeners, whenReady } from "./utils.js"; -import Window from "./window.js"; - -/** - * Sends an event with the given name and optional data. - * - * @param eventName - - The name of the event to send. - * @param [data=null] - - Optional data to send along with the event. - */ -function sendEvent(eventName: string, data: any = null): void { - Emit(eventName, data); -} - -/** - * Calls a method on a specified window. - * - * @param windowName - The name of the window to call the method on. - * @param methodName - The name of the method to call. - */ -function callWindowMethod(windowName: string, methodName: string) { - const targetWindow = Window.Get(windowName); - const method = (targetWindow as any)[methodName]; - - if (typeof method !== "function") { - console.error(`Window method '${methodName}' not found`); - return; - } - - try { - method.call(targetWindow); - } catch (e) { - console.error(`Error calling window method '${methodName}': `, e); - } -} - -/** - * Responds to a triggering event by running appropriate WML actions for the current target. - */ -function onWMLTriggered(ev: Event): void { - const element = ev.currentTarget as Element; - - function runEffect(choice = "Yes") { - if (choice !== "Yes") - return; - - const eventType = element.getAttribute('wml-event') || element.getAttribute('data-wml-event'); - const targetWindow = element.getAttribute('wml-target-window') || element.getAttribute('data-wml-target-window') || ""; - const windowMethod = element.getAttribute('wml-window') || element.getAttribute('data-wml-window'); - const url = element.getAttribute('wml-openurl') || element.getAttribute('data-wml-openurl'); - - if (eventType !== null) - sendEvent(eventType); - if (windowMethod !== null) - callWindowMethod(targetWindow, windowMethod); - if (url !== null) - void OpenURL(url); - } - - const confirm = element.getAttribute('wml-confirm') || element.getAttribute('data-wml-confirm'); - - if (confirm) { - Question({ - Title: "Confirm", - Message: confirm, - Detached: false, - Buttons: [ - { Label: "Yes" }, - { Label: "No", IsDefault: true } - ] - }).then(runEffect); - } else { - runEffect(); - } -} - -// Private field names. -const controllerSym = Symbol("controller"); -const triggerMapSym = Symbol("triggerMap"); -const elementCountSym = Symbol("elementCount"); - -/** - * AbortControllerRegistry does not actually remember active event listeners: instead - * it ties them to an AbortSignal and uses an AbortController to remove them all at once. - */ -class AbortControllerRegistry { - // Private fields. - [controllerSym]: AbortController; - - constructor() { - this[controllerSym] = new AbortController(); - } - - /** - * Returns an options object for addEventListener that ties the listener - * to the AbortSignal from the current AbortController. - * - * @param element - An HTML element - * @param triggers - The list of active WML trigger events for the specified elements - */ - set(element: Element, triggers: string[]): AddEventListenerOptions { - return { signal: this[controllerSym].signal }; - } - - /** - * Removes all registered event listeners and resets the registry. - */ - reset(): void { - this[controllerSym].abort(); - this[controllerSym] = new AbortController(); - } -} - -/** - * WeakMapRegistry maps active trigger events to each DOM element through a WeakMap. - * This ensures that the mapping remains private to this module, while still allowing garbage - * collection of the involved elements. - */ -class WeakMapRegistry { - /** Stores the current element-to-trigger mapping. */ - [triggerMapSym]: WeakMap; - /** Counts the number of elements with active WML triggers. */ - [elementCountSym]: number; - - constructor() { - this[triggerMapSym] = new WeakMap(); - this[elementCountSym] = 0; - } - - /** - * Sets active triggers for the specified element. - * - * @param element - An HTML element - * @param triggers - The list of active WML trigger events for the specified element - */ - set(element: Element, triggers: string[]): AddEventListenerOptions { - if (!this[triggerMapSym].has(element)) { this[elementCountSym]++; } - this[triggerMapSym].set(element, triggers); - return {}; - } - - /** - * Removes all registered event listeners. - */ - reset(): void { - if (this[elementCountSym] <= 0) - return; - - for (const element of document.body.querySelectorAll('*')) { - if (this[elementCountSym] <= 0) - break; - - const triggers = this[triggerMapSym].get(element); - if (triggers != null) { this[elementCountSym]--; } - - for (const trigger of triggers || []) - element.removeEventListener(trigger, onWMLTriggered); - } - - this[triggerMapSym] = new WeakMap(); - this[elementCountSym] = 0; - } -} - -const triggerRegistry = canAbortListeners() ? new AbortControllerRegistry() : new WeakMapRegistry(); - -/** - * Adds event listeners to the specified element. - */ -function addWMLListeners(element: Element): void { - const triggerRegExp = /\S+/g; - const triggerAttr = (element.getAttribute('wml-trigger') || element.getAttribute('data-wml-trigger') || "click"); - const triggers: string[] = []; - - let match; - while ((match = triggerRegExp.exec(triggerAttr)) !== null) - triggers.push(match[0]); - - const options = triggerRegistry.set(element, triggers); - for (const trigger of triggers) - element.addEventListener(trigger, onWMLTriggered, options); -} - -/** - * Schedules an automatic reload of WML to be performed as soon as the document is fully loaded. - */ -export function Enable(): void { - whenReady(Reload); -} - -/** - * Reloads the WML page by adding necessary event listeners and browser listeners. - */ -export function Reload(): void { - triggerRegistry.reset(); - document.body.querySelectorAll('[wml-event], [wml-window], [wml-openurl], [data-wml-event], [data-wml-window], [data-wml-openurl]').forEach(addWMLListeners); -} diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/tsconfig.json b/v3/internal/runtime/desktop/@wailsio/runtime/tsconfig.json deleted file mode 100644 index 75c3db8e4..000000000 --- a/v3/internal/runtime/desktop/@wailsio/runtime/tsconfig.json +++ /dev/null @@ -1,37 +0,0 @@ -{ - "include": ["src"], - "exclude": ["./src/**/*.test.*"], - "compilerOptions": { - "composite": true, - - "allowJs": false, - - "noEmitOnError": true, - "declaration": true, - "declarationMap": false, - "declarationDir": "types", - "outDir": "dist", - "rootDir": "src", - - "target": "ES2017", - "module": "ES2015", - "moduleResolution": "bundler", - "isolatedModules": true, - "verbatimModuleSyntax": true, - "stripInternal": true, - "skipLibCheck": true, - - "lib": [ - "DOM", - "DOM.Iterable", - "ESNext" - ], - - "strict": true, - "noUnusedLocals": true, - "noUnusedParameters": false, - "noImplicitAny": true, - "noImplicitReturns": true, - "noFallthroughCasesInSwitch": true - } -} diff --git a/v3/internal/runtime/desktop/@wailsio/runtime/vitest.config.ts b/v3/internal/runtime/desktop/@wailsio/runtime/vitest.config.ts deleted file mode 100644 index efb60170a..000000000 --- a/v3/internal/runtime/desktop/@wailsio/runtime/vitest.config.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { defineConfig } from "vitest/config"; - -export default defineConfig({ - test: { - environment: 'happy-dom', - testTimeout: 200 - }, -}); diff --git a/v3/internal/runtime/desktop/README.md b/v3/internal/runtime/desktop/README.md deleted file mode 100644 index 0ca8ed53e..000000000 --- a/v3/internal/runtime/desktop/README.md +++ /dev/null @@ -1,10 +0,0 @@ -# README - -The `index.js` file in the `compiled` directory is the entrypoint for the `runtime.js` file that may be -loaded at runtime. This will add `window.wails` and `window._wails` to the global scope. - -NOTE: It is preferable to use the `@wailsio/runtime` package to use the runtime. - -⚠️ Do not rebuild the runtime manually after updating TS code: -the CI pipeline will take care of this. -PRs that touch build artifacts will be blocked from merging. \ No newline at end of file diff --git a/v3/internal/runtime/desktop/compiled/main.js b/v3/internal/runtime/desktop/compiled/main.js deleted file mode 100644 index d2b21dca1..000000000 --- a/v3/internal/runtime/desktop/compiled/main.js +++ /dev/null @@ -1,22 +0,0 @@ -/* - _ __ _ __ -| | / /___ _(_) /____ -| | /| / / __ `/ / / ___/ -| |/ |/ / /_/ / / (__ ) -|__/|__/\__,_/_/_/____/ -The electron alternative for Go -(c) Lea Anthony 2019-present -*/ - -import * as Runtime from "../@wailsio/runtime/src"; - -// NOTE: the following methods MUST be imported explicitly because of how esbuild injection works -import { Enable as EnableWML } from "../@wailsio/runtime/src/wml"; -import { debugLog } from "../@wailsio/runtime/src/utils"; - -window.wails = Runtime; -EnableWML(); - -if (DEBUG) { - debugLog("Wails Runtime Loaded") -} diff --git a/v3/internal/runtime/package-lock.json b/v3/internal/runtime/package-lock.json deleted file mode 100644 index f75f8cf7b..000000000 --- a/v3/internal/runtime/package-lock.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "name": "runtime", - "lockfileVersion": 3, - "requires": true, - "packages": {} -} diff --git a/v3/internal/runtime/runtime.go b/v3/internal/runtime/runtime.go deleted file mode 100644 index d35ff0552..000000000 --- a/v3/internal/runtime/runtime.go +++ /dev/null @@ -1,21 +0,0 @@ -package runtime - -import ( - "fmt" - - "encoding/json" -) - -var runtimeInit = `window._wails=window._wails||{};window._wails.flags=window._wails.flags||{};window.wails=window.wails||{};` - -func Core(flags map[string]any) string { - flagsStr := "" - if len(flags) > 0 { - f, err := json.Marshal(flags) - if err == nil { - flagsStr += fmt.Sprintf("window._wails.flags=%s;", f) - } - } - - return runtimeInit + flagsStr + invoke + environment -} diff --git a/v3/internal/runtime/runtime_android.go b/v3/internal/runtime/runtime_android.go deleted file mode 100644 index ab212a891..000000000 --- a/v3/internal/runtime/runtime_android.go +++ /dev/null @@ -1,16 +0,0 @@ -//go:build android - -package runtime - -// Android uses window.wails.invoke which is set up via addJavascriptInterface in WailsJSBridge -// We need to log the state to debug why it's not being detected -var invoke = ` -console.log('[Wails Android Runtime] Injecting runtime, window.wails exists:', !!window.wails); -console.log('[Wails Android Runtime] window.wails.invoke exists:', !!(window.wails && window.wails.invoke)); -window._wails.invoke=function(m){ - console.log('[Wails Android Runtime] _wails.invoke called:', m); - return window.wails.invoke(typeof m==='string'?m:JSON.stringify(m)); -}; -console.log('[Wails Android Runtime] Runtime injection complete'); -` -var flags = "" diff --git a/v3/internal/runtime/runtime_darwin.go b/v3/internal/runtime/runtime_darwin.go deleted file mode 100644 index 6b2333690..000000000 --- a/v3/internal/runtime/runtime_darwin.go +++ /dev/null @@ -1,5 +0,0 @@ -//go:build darwin - -package runtime - -var invoke = "window._wails.invoke=function(msg){window.webkit.messageHandlers.external.postMessage(msg);};" diff --git a/v3/internal/runtime/runtime_dev.go b/v3/internal/runtime/runtime_dev.go deleted file mode 100644 index bb52628cf..000000000 --- a/v3/internal/runtime/runtime_dev.go +++ /dev/null @@ -1,10 +0,0 @@ -//go:build !production - -package runtime - -import ( - "fmt" - "runtime" -) - -var environment = fmt.Sprintf(`window._wails.environment={"OS":"%s","Arch":"%s","Debug":true};`, runtime.GOOS, runtime.GOARCH) diff --git a/v3/internal/runtime/runtime_linux.go b/v3/internal/runtime/runtime_linux.go deleted file mode 100644 index a1e0418bd..000000000 --- a/v3/internal/runtime/runtime_linux.go +++ /dev/null @@ -1,5 +0,0 @@ -//go:build linux && !android - -package runtime - -var invoke = "window._wails.invoke=window.webkit.messageHandlers.external.postMessage;" diff --git a/v3/internal/runtime/runtime_prod.go b/v3/internal/runtime/runtime_prod.go deleted file mode 100644 index ec3613551..000000000 --- a/v3/internal/runtime/runtime_prod.go +++ /dev/null @@ -1,8 +0,0 @@ -//go:build production - -package runtime - -import "fmt" -import goruntime "runtime" - -var environment = fmt.Sprintf(`window._wails.environment={"OS":"%s","Arch":"%s","Debug":false};`, goruntime.GOOS, goruntime.GOARCH) diff --git a/v3/internal/runtime/runtime_windows.go b/v3/internal/runtime/runtime_windows.go deleted file mode 100644 index 59fb6a5a6..000000000 --- a/v3/internal/runtime/runtime_windows.go +++ /dev/null @@ -1,5 +0,0 @@ -//go:build windows - -package runtime - -var invoke = `window._wails.invoke=window.chrome.webview.postMessage;` diff --git a/v3/internal/s/s.go b/v3/internal/s/s.go deleted file mode 100644 index 1ce187e07..000000000 --- a/v3/internal/s/s.go +++ /dev/null @@ -1,456 +0,0 @@ -package s - -import ( - "crypto/md5" - "fmt" - "github.com/google/shlex" - "io" - "net/http" - "os" - "os/exec" - "path/filepath" - "strings" -) - -var ( - Output io.Writer = io.Discard - IndentSize int - originalOutput io.Writer - currentIndent int - dryRun bool - deferred []func() -) - -func checkError(err error) { - if err != nil { - println("\nERROR:", err.Error()) - os.Exit(1) - } -} - -func mute() { - originalOutput = Output - Output = io.Discard -} - -func unmute() { - Output = originalOutput -} - -func indent() { - currentIndent += IndentSize -} - -func unindent() { - currentIndent -= IndentSize -} - -func log(message string, args ...interface{}) { - indent := strings.Repeat(" ", currentIndent) - _, err := fmt.Fprintf(Output, indent+message+"\n", args...) - checkError(err) -} - -// RENAME a file or directory -func RENAME(source string, target string) { - log("RENAME %s -> %s", source, target) - err := os.Rename(source, target) - checkError(err) -} - -// MUSTDELETE a file. -func MUSTDELETE(filename string) { - log("DELETE %s", filename) - err := os.Remove(filepath.Join(CWD(), filename)) - checkError(err) -} - -// DELETE a file. -func DELETE(filename string) { - log("DELETE %s", filename) - _ = os.Remove(filepath.Join(CWD(), filename)) -} - -func CONTAINS(list string, item string) bool { - result := strings.Contains(list, item) - listTrimmed := list - if len(listTrimmed) > 30 { - listTrimmed = listTrimmed[:30] + "..." - } - log("CONTAINS %s in %s: %t", item, listTrimmed, result) - return result -} - -func SETENV(key string, value string) { - log("SETENV %s=%s", key, value) - err := os.Setenv(key, value) - checkError(err) -} - -func CD(dir string) { - err := os.Chdir(dir) - checkError(err) - log("CD %s", dir) -} -func MKDIR(path string, mode ...os.FileMode) { - var perms os.FileMode - perms = 0755 - if len(mode) == 1 { - perms = mode[0] - } - log("MKDIR %s (perms: %v)", path, perms) - err := os.MkdirAll(path, perms) - checkError(err) -} - -// ENDIR ensures that the path gets created if it doesn't exist -func ENDIR(path string, mode ...os.FileMode) { - var perms os.FileMode - perms = 0755 - if len(mode) == 1 { - perms = mode[0] - } - _ = os.MkdirAll(path, perms) -} - -// COPYDIR recursively copies a directory tree, attempting to preserve permissions. -// Source directory must exist, destination directory must *not* exist. -// Symlinks are ignored and skipped. -// Credit: https://gist.github.com/r0l1/92462b38df26839a3ca324697c8cba04 -func COPYDIR(src string, dst string) { - log("COPYDIR %s -> %s", src, dst) - src = filepath.Clean(src) - dst = filepath.Clean(dst) - - si, err := os.Stat(src) - checkError(err) - if !si.IsDir() { - checkError(fmt.Errorf("source is not a directory")) - } - - _, err = os.Stat(dst) - if err != nil && !os.IsNotExist(err) { - checkError(err) - } - if err == nil { - checkError(fmt.Errorf("destination already exists")) - } - - indent() - MKDIR(dst) - - entries, err := os.ReadDir(src) - checkError(err) - - for _, entry := range entries { - srcPath := filepath.Join(src, entry.Name()) - dstPath := filepath.Join(dst, entry.Name()) - - if entry.IsDir() { - COPYDIR(srcPath, dstPath) - } else { - // Skip symlinks. - if entry.Type()&os.ModeSymlink != 0 { - continue - } - - COPY(srcPath, dstPath) - } - } - unindent() -} - -// COPYDIR2 recursively copies a directory tree, attempting to preserve permissions. -// Source directory must exist, destination directory can exist. -// Symlinks are ignored and skipped. -// Credit: https://gist.github.com/r0l1/92462b38df26839a3ca324697c8cba04 -func COPYDIR2(src string, dst string) { - log("COPYDIR %s -> %s", src, dst) - src = filepath.Clean(src) - dst = filepath.Clean(dst) - - si, err := os.Stat(src) - checkError(err) - if !si.IsDir() { - checkError(fmt.Errorf("source is not a directory")) - } - - indent() - MKDIR(dst) - - entries, err := os.ReadDir(src) - checkError(err) - - for _, entry := range entries { - srcPath := filepath.Join(src, entry.Name()) - dstPath := filepath.Join(dst, entry.Name()) - - if entry.IsDir() { - COPYDIR(srcPath, dstPath) - } else { - // Skip symlinks. - if entry.Type()&os.ModeSymlink != 0 { - continue - } - - COPY(srcPath, dstPath) - } - } - unindent() -} - -func SYMLINK(source string, target string) { - // trim string to first 30 chars - var trimTarget = target - if len(trimTarget) > 30 { - trimTarget = trimTarget[:30] + "..." - } - log("SYMLINK %s -> %s", source, trimTarget) - err := os.Symlink(source, target) - checkError(err) -} - -// COPY file from source to target -func COPY(source string, target string) { - log("COPY %s -> %s", source, target) - src, err := os.Open(source) - checkError(err) - defer closefile(src) - if ISDIR(target) { - target = filepath.Join(target, filepath.Base(source)) - } - d, err := os.Create(target) - checkError(err) - _, err = io.Copy(d, src) - checkError(err) -} - -// Move file from source to target -func MOVE(source string, target string) { - // If target is a directory, append the source filename - if ISDIR(target) { - target = filepath.Join(target, filepath.Base(source)) - } - log("MOVE %s -> %s", source, target) - err := os.Rename(source, target) - checkError(err) -} - -func CWD() string { - result, err := os.Getwd() - checkError(err) - log("CWD %s", result) - return result -} - -func RMDIR(target string) { - log("RMDIR %s", target) - err := os.RemoveAll(target) - checkError(err) -} - -func RM(target string) { - log("RM %s", target) - err := os.Remove(target) - checkError(err) -} - -func ECHO(message string) { - println(message) -} - -func TOUCH(filepath string) { - log("TOUCH %s", filepath) - f, err := os.Create(filepath) - checkError(err) - closefile(f) -} - -func EXEC(command string) ([]byte, error) { - log("EXEC %s", command) - - // Split input using shlex - args, err := shlex.Split(command) - checkError(err) - // Execute command - cmd := exec.Command(args[0], args[1:]...) - cmd.Dir = CWD() - cmd.Env = os.Environ() - return cmd.CombinedOutput() -} - -func CHMOD(path string, mode os.FileMode) { - log("CHMOD %s %v", path, mode) - err := os.Chmod(path, mode) - checkError(err) -} - -// EXISTS - Returns true if the given path exists -func EXISTS(path string) bool { - _, err := os.Lstat(path) - log("EXISTS %s -> %t", path, err == nil) - return err == nil -} - -// ISDIR returns true if the given directory exists -func ISDIR(path string) bool { - fi, err := os.Lstat(path) - if err != nil { - return false - } - - return fi.Mode().IsDir() -} - -// ISDIREMPTY returns true if the given directory is empty -func ISDIREMPTY(dir string) bool { - - // CREDIT: https://stackoverflow.com/a/30708914/8325411 - f, err := os.Open(dir) - checkError(err) - defer closefile(f) - - _, err = f.Readdirnames(1) // Or f.Readdir(1) - if err == io.EOF { - return true - } - return false -} - -// ISFILE returns true if the given file exists -func ISFILE(path string) bool { - fi, err := os.Lstat(path) - if err != nil { - return false - } - - return fi.Mode().IsRegular() -} - -// SUBDIRS returns a list of subdirectories for the given directory -func SUBDIRS(rootDir string) []string { - var result []string - - // Iterate root dir - err := filepath.Walk(rootDir, func(path string, info os.FileInfo, err error) error { - checkError(err) - // If we have a directory, save it - if info.IsDir() { - result = append(result, path) - } - return nil - }) - checkError(err) - return result -} - -// SAVESTRING will create a file with the given string -func SAVESTRING(filename string, data string) { - log("SAVESTRING %s", filename) - mute() - SAVEBYTES(filename, []byte(data)) - unmute() -} - -// LOADSTRING returns the contents of the given filename as a string -func LOADSTRING(filename string) string { - log("LOADSTRING %s", filename) - mute() - data := LOADBYTES(filename) - unmute() - return string(data) -} - -// SAVEBYTES will create a file with the given string -func SAVEBYTES(filename string, data []byte) { - log("SAVEBYTES %s", filename) - err := os.WriteFile(filename, data, 0755) - checkError(err) -} - -// LOADBYTES returns the contents of the given filename as a string -func LOADBYTES(filename string) []byte { - log("LOADBYTES %s", filename) - data, err := os.ReadFile(filename) - checkError(err) - return data -} - -func closefile(f *os.File) { - err := f.Close() - checkError(err) -} - -// MD5FILE returns the md5sum of the given file -func MD5FILE(filename string) string { - f, err := os.Open(filename) - checkError(err) - defer closefile(f) - - h := md5.New() - _, err = io.Copy(h, f) - checkError(err) - - return fmt.Sprintf("%x", h.Sum(nil)) -} - -// Sub is the substitution type -type Sub map[string]string - -// REPLACEALL replaces all substitution keys with associated values in the given file -func REPLACEALL(filename string, substitutions Sub) { - log("REPLACEALL %s (%v)", filename, substitutions) - data := LOADSTRING(filename) - for old, newText := range substitutions { - data = strings.ReplaceAll(data, old, newText) - } - SAVESTRING(filename, data) -} - -func DOWNLOAD(url string, target string) { - log("DOWNLOAD %s -> %s", url, target) - // create HTTP client - resp, err := http.Get(url) - checkError(err) - defer resp.Body.Close() - - out, err := os.Create(target) - checkError(err) - defer out.Close() - - // Write the body to file - _, err = io.Copy(out, resp.Body) - checkError(err) -} - -func FINDFILES(root string, filenames ...string) []string { - var result []string - // Walk the root directory trying to find all the files - err := filepath.Walk(root, func(path string, info os.FileInfo, err error) error { - checkError(err) - // If we have a file, check if it is in the list - if info.Mode().IsRegular() { - for _, filename := range filenames { - if info.Name() == filename { - result = append(result, path) - } - } - } - return nil - }) - checkError(err) - log("FINDFILES in %s -> [%v]", root, strings.Join(result, ", ")) - return result -} - -func DEFER(fn func()) { - log("DEFER") - deferred = append(deferred, fn) -} - -func CALLDEFER() { - log("CALLDEFER") - for _, fn := range deferred { - fn() - } -} diff --git a/v3/internal/service/service.go b/v3/internal/service/service.go deleted file mode 100644 index 76c1c2560..000000000 --- a/v3/internal/service/service.go +++ /dev/null @@ -1,36 +0,0 @@ -package service - -import ( - "embed" - "fmt" - "io/fs" - "os" - "path/filepath" - - "github.com/wailsapp/wails/v3/internal/flags" - - "github.com/leaanthony/gosod" - - "github.com/samber/lo" -) - -//go:embed template -var serviceTemplate embed.FS - -type TemplateOptions struct { - *flags.ServiceInit -} - -func Install(options *flags.ServiceInit) error { - - if options.OutputDir == "." || options.OutputDir == "" { - options.OutputDir = filepath.Join(lo.Must(os.Getwd()), options.Name) - } - fmt.Printf("Generating service '%s' into '%s'\n", options.Name, options.OutputDir) - tfs, err := fs.Sub(serviceTemplate, "template") - if err != nil { - return err - } - - return gosod.New(tfs).Extract(options.OutputDir, options) -} diff --git a/v3/internal/service/template/README.tmpl.md b/v3/internal/service/template/README.tmpl.md deleted file mode 100644 index 065021b6a..000000000 --- a/v3/internal/service/template/README.tmpl.md +++ /dev/null @@ -1,129 +0,0 @@ -# Wails v3 Service Template - -This README provides an overview of the Wails v3 service template and explains how to adapt it to create your own custom service. - -## Overview - -The service template provides a basic structure for creating a Wails v3 service. A service in Wails v3 is a Go package that can be integrated into your Wails application to provide specific functionality, handle HTTP requests, and interact with the frontend. - -## Template Structure - -The template defines a `MyService` struct and several methods: - -### MyService Struct - -```go -type MyService struct { - ctx context.Context - options application.ServiceOptions -} -``` - -This is the main service struct. You can rename it to better reflect your service's purpose. The struct holds a context and service options, which are set during startup. - -### ServiceName Method - -```go -func (p *MyService) ServiceName() string -``` - -This method returns the name of the service. It's used to identify the service within the Wails application. - -### ServiceStartup Method - -```go -func (p *MyService) ServiceStartup(ctx context.Context, options application.ServiceOptions) error -``` - -This method is called when the app is starting up. Use it to initialize resources, set up connections, or perform any necessary setup tasks. -It receives a context and service options, which are stored in the service struct. - -### ServiceShutdown Method - -```go -func (p *MyService) ServiceShutdown() error -``` - -This method is called when the app is shutting down. Use it to clean up resources, close connections, or perform any necessary cleanup tasks. - -### ServeHTTP Method - -```go -func (p *MyService) ServeHTTP(w http.ResponseWriter, r *http.Request) -``` - -This method handles HTTP requests to the service. It's called when the frontend makes an HTTP request to the backend -at the path specified in the `Route` field of the service options. - -### Service Methods - -```go -func (p *MyService) Greet(name string) string -``` - -This is an example of a service method. You can add as many methods as you need. These methods can be called from the frontend. - -## Adapting the Template - -To create your own service: - -1. Rename the `MyService` struct to reflect your service's purpose (e.g., `DatabaseService`, `AuthService`). -2. Update the `ServiceName` method to return your service's unique identifier. -3. Implement the `ServiceStartup` method to initialize your service. This might include setting up database connections, loading configuration, etc. -4. If needed, implement the `ServiceShutdown` method to properly clean up resources when the application closes. -5. If your service needs to handle HTTP requests, implement the `ServeHTTP` method. Use this to create API endpoints, serve files, or handle any HTTP interactions. -6. Add your own methods to the service. These can include database operations, business logic, or any functionality your service needs to provide. -7. If your service requires configuration, consider adding a `Config` struct and a `New` function to create and configure your service. - -## Example: Database Service - -Here's how you might adapt the template for a database service: - -```go -type DatabaseService struct { - ctx context.Context - options application.ServiceOptions - db *sql.DB -} - -func (s *DatabaseService) Name() string { - return "github.com/myname/DatabaseService" -} - -func (s *DatabaseService) ServiceStartup(ctx context.Context, options application.ServiceOptions) error { - s.ctx = ctx - s.options = options - // Initialize database connection - var err error - s.db, err = sql.Open("mysql", "user:password@/dbname") - return err -} - -func (s *DatabaseService) ServiceShutdown() error { - return s.db.Close() -} - -func (s *DatabaseService) GetUser(id int) (User, error) { - // Implement database query -} - -// Add more methods as needed -``` - -## Long-running tasks - -If your service needs to perform long-running tasks, consider using goroutines and channels to manage these tasks. -You can use the `context.Context` to listen for when the application shuts down: - -```go -func (s *DatabaseService) longRunningTask() { - for { - select { - case <-s.ctx.Done(): - // Cleanup and exit - return - // Perform long-running task - } - } -} -``` diff --git a/v3/internal/service/template/go.mod.tmpl b/v3/internal/service/template/go.mod.tmpl deleted file mode 100644 index dc8719753..000000000 --- a/v3/internal/service/template/go.mod.tmpl +++ /dev/null @@ -1,12 +0,0 @@ -module {{.Name}} - -go 1.23 - -require github.com/wailsapp/wails/v3 v3.0.0-alpha.7 - -require ( - github.com/imdario/mergo v0.3.12 // indirect - github.com/leaanthony/slicer v1.5.0 // indirect - github.com/wailsapp/mimetype v1.4.1 // indirect - golang.org/x/net v0.0.0-20220722155237-a158d28d115b // indirect -) diff --git a/v3/internal/service/template/go.sum b/v3/internal/service/template/go.sum deleted file mode 100644 index 991eadf04..000000000 --- a/v3/internal/service/template/go.sum +++ /dev/null @@ -1,20 +0,0 @@ -github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU= -github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= -github.com/leaanthony/slicer v1.5.0 h1:aHYTN8xbCCLxJmkNKiLB6tgcMARl4eWmH9/F+S/0HtY= -github.com/leaanthony/slicer v1.5.0/go.mod h1:FwrApmf8gOrpzEWM2J/9Lh79tyq8KTX5AzRtwV7m4AY= -github.com/matryer/is v1.4.0 h1:sosSmIWwkYITGrxZ25ULNDeKiMNzFSr4V/eqBQP0PeE= -github.com/wailsapp/mimetype v1.4.1 h1:pQN9ycO7uo4vsUUuPeHEYoUkLVkaRntMnHJxVwYhwHs= -github.com/wailsapp/mimetype v1.4.1/go.mod h1:9aV5k31bBOv5z6u+QP8TltzvNGJPmNJD4XlAL3U+j3o= -github.com/wailsapp/wails/v3 v3.0.0-alpha.7 h1:LNX2EnbxTEYJYICJT8UkuzoGVNalRizTNGBY47endmk= -github.com/wailsapp/wails/v3 v3.0.0-alpha.7/go.mod h1:lBz4zedFxreJBoVpMe9u89oo4IE3IlyHJg5rOWnGNR0= -golang.org/x/net v0.0.0-20210505024714-0287a6fb4125/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20220722155237-a158d28d115b h1:PxfKdU9lEEDYjdIzOtC4qFWgkU2rGHdKlKowJSMN9h0= -golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= -golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/yaml.v2 v2.3.0 h1:clyUAQHOM3G0M3f5vQj7LuJrETvjVot3Z5el9nffUtU= -gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= diff --git a/v3/internal/service/template/service.go.tmpl b/v3/internal/service/template/service.go.tmpl deleted file mode 100644 index 781e9efff..000000000 --- a/v3/internal/service/template/service.go.tmpl +++ /dev/null @@ -1,60 +0,0 @@ -package {{.Name}} - -import ( - "context" - "github.com/wailsapp/wails/v3/pkg/application" -) - -// ---------------- Service Setup ---------------- -// This is the main service struct. It can be named anything you like. -// Both the ServiceStartup() and ServiceShutdown() methods are called synchronously when the app starts and stops. -// Changing the name of this struct will change the name of the services class in the frontend -// Bound methods will exist inside frontend/bindings/github.com/user/{{.Name}} under the name of the struct -type MyService struct{ - ctx context.Context - options application.ServiceOptions -} - -// ServiceName is the name of the service -func (p *MyService) ServiceName() string { - return "{{.Name}}" -} - -// ServiceStartup is called when the app is starting up. You can use this to -// initialise any resources you need. You can also access the application -// instance via the app property. -// OPTIONAL: This method is optional. -func (p *MyService) ServiceStartup(ctx context.Context, options application.ServiceOptions) error { - p.ctx = ctx - p.options = options - return nil -} - -// ServiceShutdown is called when the app is shutting down via runtime.Quit() call -// You can use this to clean up any resources you have allocated -// OPTIONAL: This method is optional. -func (p *MyService) ServiceShutdown() error { - return nil -} - -// ServeHTTP is called when the app is running and the frontend makes an HTTP request to the backend at the path -// specified in the `Route` field of the service Options. -// OPTIONAL: This method is optional. -func (p *MyService) ServeHTTP(w http.ResponseWriter, r *http.Request) { - // You can use the request to get the path, query parameters, headers, etc. - // You can also use the response to set the status code, headers, body etc. - // Consult the net/http documentation for more information: https://pkg.go.dev/net/http - - // Log the request to the console - log.Printf("Received request: %s %s", r.Method, r.URL.Path) -} - -// ---------------- Service Methods ---------------- -// Service methods are just normal Go methods. You can add as many as you like. -// The only requirement is that they are exported (start with a capital letter). -// You can also return any type that is JSON serializable. -// See https://golang.org/pkg/encoding/json/#Marshal for more information. - -func (p *MyService) Greet(name string) string { - return "Hello " + name -} diff --git a/v3/internal/service/template/service.tmpl.yml b/v3/internal/service/template/service.tmpl.yml deleted file mode 100644 index bd018461e..000000000 --- a/v3/internal/service/template/service.tmpl.yml +++ /dev/null @@ -1,8 +0,0 @@ -# This is the plugin definition file for the "{{.Name}}" plugin. -Name: "{{.Name}}" -Description: "{{.Description}}" -Author: "{{.Author}}" -Version: "{{.Version}}" -Website: "{{.Website}}" -Repository: "{{.Repository}}" -License: "{{.License}}" diff --git a/v3/internal/setupwizard/defaults.go b/v3/internal/setupwizard/defaults.go deleted file mode 100644 index a5847cb68..000000000 --- a/v3/internal/setupwizard/defaults.go +++ /dev/null @@ -1,30 +0,0 @@ -package setupwizard - -import ( - "github.com/wailsapp/wails/v3/internal/defaults" -) - -// Re-export types for convenience -type GlobalDefaults = defaults.GlobalDefaults -type AuthorDefaults = defaults.AuthorDefaults -type ProjectDefaults = defaults.ProjectDefaults - -// DefaultGlobalDefaults returns sensible defaults for first-time users -func DefaultGlobalDefaults() GlobalDefaults { - return defaults.Default() -} - -// GetDefaultsPath returns the path to the defaults.yaml file -func GetDefaultsPath() (string, error) { - return defaults.GetDefaultsPath() -} - -// LoadGlobalDefaults loads the global defaults from the config file -func LoadGlobalDefaults() (GlobalDefaults, error) { - return defaults.Load() -} - -// SaveGlobalDefaults saves the global defaults to the config file -func SaveGlobalDefaults(d GlobalDefaults) error { - return defaults.Save(d) -} diff --git a/v3/internal/setupwizard/frontend/dist/assets/index-C9VCVRfM.js b/v3/internal/setupwizard/frontend/dist/assets/index-C9VCVRfM.js deleted file mode 100644 index 3a5ce1f7a..000000000 --- a/v3/internal/setupwizard/frontend/dist/assets/index-C9VCVRfM.js +++ /dev/null @@ -1,48 +0,0 @@ -(function(){const t=document.createElement("link").relList;if(t&&t.supports&&t.supports("modulepreload"))return;for(const i of document.querySelectorAll('link[rel="modulepreload"]'))r(i);new MutationObserver(i=>{for(const s of i)if(s.type==="childList")for(const o of s.addedNodes)o.tagName==="LINK"&&o.rel==="modulepreload"&&r(o)}).observe(document,{childList:!0,subtree:!0});function n(i){const s={};return i.integrity&&(s.integrity=i.integrity),i.referrerPolicy&&(s.referrerPolicy=i.referrerPolicy),i.crossOrigin==="use-credentials"?s.credentials="include":i.crossOrigin==="anonymous"?s.credentials="omit":s.credentials="same-origin",s}function r(i){if(i.ep)return;i.ep=!0;const s=n(i);fetch(i.href,s)}})();function zm(e){return e&&e.__esModule&&Object.prototype.hasOwnProperty.call(e,"default")?e.default:e}var Gd={exports:{}},Ts={},Qd={exports:{}},I={};/** - * @license React - * react.production.min.js - * - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */var qr=Symbol.for("react.element"),Bm=Symbol.for("react.portal"),Um=Symbol.for("react.fragment"),Wm=Symbol.for("react.strict_mode"),bm=Symbol.for("react.profiler"),$m=Symbol.for("react.provider"),Hm=Symbol.for("react.context"),Km=Symbol.for("react.forward_ref"),Gm=Symbol.for("react.suspense"),Qm=Symbol.for("react.memo"),Ym=Symbol.for("react.lazy"),Tu=Symbol.iterator;function Xm(e){return e===null||typeof e!="object"?null:(e=Tu&&e[Tu]||e["@@iterator"],typeof e=="function"?e:null)}var Yd={isMounted:function(){return!1},enqueueForceUpdate:function(){},enqueueReplaceState:function(){},enqueueSetState:function(){}},Xd=Object.assign,Zd={};function Xn(e,t,n){this.props=e,this.context=t,this.refs=Zd,this.updater=n||Yd}Xn.prototype.isReactComponent={};Xn.prototype.setState=function(e,t){if(typeof e!="object"&&typeof e!="function"&&e!=null)throw Error("setState(...): takes an object of state variables to update or a function which returns an object of state variables.");this.updater.enqueueSetState(this,e,t,"setState")};Xn.prototype.forceUpdate=function(e){this.updater.enqueueForceUpdate(this,e,"forceUpdate")};function qd(){}qd.prototype=Xn.prototype;function Ya(e,t,n){this.props=e,this.context=t,this.refs=Zd,this.updater=n||Yd}var Xa=Ya.prototype=new qd;Xa.constructor=Ya;Xd(Xa,Xn.prototype);Xa.isPureReactComponent=!0;var Cu=Array.isArray,Jd=Object.prototype.hasOwnProperty,Za={current:null},ef={key:!0,ref:!0,__self:!0,__source:!0};function tf(e,t,n){var r,i={},s=null,o=null;if(t!=null)for(r in t.ref!==void 0&&(o=t.ref),t.key!==void 0&&(s=""+t.key),t)Jd.call(t,r)&&!ef.hasOwnProperty(r)&&(i[r]=t[r]);var a=arguments.length-2;if(a===1)i.children=n;else if(1>>1,oe=E[H];if(0>>1;Hi($s,V))Qti(ui,$s)?(E[H]=ui,E[Qt]=V,H=Qt):(E[H]=$s,E[Gt]=V,H=Gt);else if(Qti(ui,V))E[H]=ui,E[Qt]=V,H=Qt;else break e}}return L}function i(E,L){var V=E.sortIndex-L.sortIndex;return V!==0?V:E.id-L.id}if(typeof performance=="object"&&typeof performance.now=="function"){var s=performance;e.unstable_now=function(){return s.now()}}else{var o=Date,a=o.now();e.unstable_now=function(){return o.now()-a}}var l=[],u=[],c=1,d=null,f=3,y=!1,v=!1,x=!1,S=typeof setTimeout=="function"?setTimeout:null,m=typeof clearTimeout=="function"?clearTimeout:null,p=typeof setImmediate<"u"?setImmediate:null;typeof navigator<"u"&&navigator.scheduling!==void 0&&navigator.scheduling.isInputPending!==void 0&&navigator.scheduling.isInputPending.bind(navigator.scheduling);function g(E){for(var L=n(u);L!==null;){if(L.callback===null)r(u);else if(L.startTime<=E)r(u),L.sortIndex=L.expirationTime,t(l,L);else break;L=n(u)}}function w(E){if(x=!1,g(E),!v)if(n(l)!==null)v=!0,se(k);else{var L=n(u);L!==null&&B(w,L.startTime-E)}}function k(E,L){v=!1,x&&(x=!1,m(C),C=-1),y=!0;var V=f;try{for(g(L),d=n(l);d!==null&&(!(d.expirationTime>L)||E&&!X());){var H=d.callback;if(typeof H=="function"){d.callback=null,f=d.priorityLevel;var oe=H(d.expirationTime<=L);L=e.unstable_now(),typeof oe=="function"?d.callback=oe:d===n(l)&&r(l),g(L)}else r(l);d=n(l)}if(d!==null)var li=!0;else{var Gt=n(u);Gt!==null&&B(w,Gt.startTime-L),li=!1}return li}finally{d=null,f=V,y=!1}}var T=!1,P=null,C=-1,R=5,M=-1;function X(){return!(e.unstable_now()-ME||125H?(E.sortIndex=V,t(u,E),n(l)===null&&E===n(u)&&(x?(m(C),C=-1):x=!0,B(w,V-H))):(E.sortIndex=oe,t(l,E),v||y||(v=!0,se(k))),E},e.unstable_shouldYield=X,e.unstable_wrapCallback=function(E){var L=f;return function(){var V=f;f=L;try{return E.apply(this,arguments)}finally{f=V}}}})(af);of.exports=af;var l0=of.exports;/** - * @license React - * react-dom.production.min.js - * - * Copyright (c) Facebook, Inc. and its affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */var u0=N,Ae=l0;function j(e){for(var t="https://reactjs.org/docs/error-decoder.html?invariant="+e,n=1;n"u"||typeof window.document>"u"||typeof window.document.createElement>"u"),_o=Object.prototype.hasOwnProperty,c0=/^[:A-Z_a-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD][:A-Z_a-z\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF\uF900-\uFDCF\uFDF0-\uFFFD\-.0-9\u00B7\u0300-\u036F\u203F-\u2040]*$/,ju={},Eu={};function d0(e){return _o.call(Eu,e)?!0:_o.call(ju,e)?!1:c0.test(e)?Eu[e]=!0:(ju[e]=!0,!1)}function f0(e,t,n,r){if(n!==null&&n.type===0)return!1;switch(typeof t){case"function":case"symbol":return!0;case"boolean":return r?!1:n!==null?!n.acceptsBooleans:(e=e.toLowerCase().slice(0,5),e!=="data-"&&e!=="aria-");default:return!1}}function h0(e,t,n,r){if(t===null||typeof t>"u"||f0(e,t,n,r))return!0;if(r)return!1;if(n!==null)switch(n.type){case 3:return!t;case 4:return t===!1;case 5:return isNaN(t);case 6:return isNaN(t)||1>t}return!1}function Se(e,t,n,r,i,s,o){this.acceptsBooleans=t===2||t===3||t===4,this.attributeName=r,this.attributeNamespace=i,this.mustUseProperty=n,this.propertyName=e,this.type=t,this.sanitizeURL=s,this.removeEmptyString=o}var fe={};"children dangerouslySetInnerHTML defaultValue defaultChecked innerHTML suppressContentEditableWarning suppressHydrationWarning style".split(" ").forEach(function(e){fe[e]=new Se(e,0,!1,e,null,!1,!1)});[["acceptCharset","accept-charset"],["className","class"],["htmlFor","for"],["httpEquiv","http-equiv"]].forEach(function(e){var t=e[0];fe[t]=new Se(t,1,!1,e[1],null,!1,!1)});["contentEditable","draggable","spellCheck","value"].forEach(function(e){fe[e]=new Se(e,2,!1,e.toLowerCase(),null,!1,!1)});["autoReverse","externalResourcesRequired","focusable","preserveAlpha"].forEach(function(e){fe[e]=new Se(e,2,!1,e,null,!1,!1)});"allowFullScreen async autoFocus autoPlay controls default defer disabled disablePictureInPicture disableRemotePlayback formNoValidate hidden loop noModule noValidate open playsInline readOnly required reversed scoped seamless itemScope".split(" ").forEach(function(e){fe[e]=new Se(e,3,!1,e.toLowerCase(),null,!1,!1)});["checked","multiple","muted","selected"].forEach(function(e){fe[e]=new Se(e,3,!0,e,null,!1,!1)});["capture","download"].forEach(function(e){fe[e]=new Se(e,4,!1,e,null,!1,!1)});["cols","rows","size","span"].forEach(function(e){fe[e]=new Se(e,6,!1,e,null,!1,!1)});["rowSpan","start"].forEach(function(e){fe[e]=new Se(e,5,!1,e.toLowerCase(),null,!1,!1)});var Ja=/[\-:]([a-z])/g;function el(e){return e[1].toUpperCase()}"accent-height alignment-baseline arabic-form baseline-shift cap-height clip-path clip-rule color-interpolation color-interpolation-filters color-profile color-rendering dominant-baseline enable-background fill-opacity fill-rule flood-color flood-opacity font-family font-size font-size-adjust font-stretch font-style font-variant font-weight glyph-name glyph-orientation-horizontal glyph-orientation-vertical horiz-adv-x horiz-origin-x image-rendering letter-spacing lighting-color marker-end marker-mid marker-start overline-position overline-thickness paint-order panose-1 pointer-events rendering-intent shape-rendering stop-color stop-opacity strikethrough-position strikethrough-thickness stroke-dasharray stroke-dashoffset stroke-linecap stroke-linejoin stroke-miterlimit stroke-opacity stroke-width text-anchor text-decoration text-rendering underline-position underline-thickness unicode-bidi unicode-range units-per-em v-alphabetic v-hanging v-ideographic v-mathematical vector-effect vert-adv-y vert-origin-x vert-origin-y word-spacing writing-mode xmlns:xlink x-height".split(" ").forEach(function(e){var t=e.replace(Ja,el);fe[t]=new Se(t,1,!1,e,null,!1,!1)});"xlink:actuate xlink:arcrole xlink:role xlink:show xlink:title xlink:type".split(" ").forEach(function(e){var t=e.replace(Ja,el);fe[t]=new Se(t,1,!1,e,"http://www.w3.org/1999/xlink",!1,!1)});["xml:base","xml:lang","xml:space"].forEach(function(e){var t=e.replace(Ja,el);fe[t]=new Se(t,1,!1,e,"http://www.w3.org/XML/1998/namespace",!1,!1)});["tabIndex","crossOrigin"].forEach(function(e){fe[e]=new Se(e,1,!1,e.toLowerCase(),null,!1,!1)});fe.xlinkHref=new Se("xlinkHref",1,!1,"xlink:href","http://www.w3.org/1999/xlink",!0,!1);["src","href","action","formAction"].forEach(function(e){fe[e]=new Se(e,1,!1,e.toLowerCase(),null,!0,!0)});function tl(e,t,n,r){var i=fe.hasOwnProperty(t)?fe[t]:null;(i!==null?i.type!==0:r||!(2a||i[o]!==s[a]){var l=` -`+i[o].replace(" at new "," at ");return e.displayName&&l.includes("")&&(l=l.replace("",e.displayName)),l}while(1<=o&&0<=a);break}}}finally{Gs=!1,Error.prepareStackTrace=n}return(e=e?e.displayName||e.name:"")?dr(e):""}function p0(e){switch(e.tag){case 5:return dr(e.type);case 16:return dr("Lazy");case 13:return dr("Suspense");case 19:return dr("SuspenseList");case 0:case 2:case 15:return e=Qs(e.type,!1),e;case 11:return e=Qs(e.type.render,!1),e;case 1:return e=Qs(e.type,!0),e;default:return""}}function Bo(e){if(e==null)return null;if(typeof e=="function")return e.displayName||e.name||null;if(typeof e=="string")return e;switch(e){case vn:return"Fragment";case yn:return"Portal";case Oo:return"Profiler";case nl:return"StrictMode";case Fo:return"Suspense";case zo:return"SuspenseList"}if(typeof e=="object")switch(e.$$typeof){case cf:return(e.displayName||"Context")+".Consumer";case uf:return(e._context.displayName||"Context")+".Provider";case rl:var t=e.render;return e=e.displayName,e||(e=t.displayName||t.name||"",e=e!==""?"ForwardRef("+e+")":"ForwardRef"),e;case il:return t=e.displayName||null,t!==null?t:Bo(e.type)||"Memo";case Ct:t=e._payload,e=e._init;try{return Bo(e(t))}catch{}}return null}function m0(e){var t=e.type;switch(e.tag){case 24:return"Cache";case 9:return(t.displayName||"Context")+".Consumer";case 10:return(t._context.displayName||"Context")+".Provider";case 18:return"DehydratedFragment";case 11:return e=t.render,e=e.displayName||e.name||"",t.displayName||(e!==""?"ForwardRef("+e+")":"ForwardRef");case 7:return"Fragment";case 5:return t;case 4:return"Portal";case 3:return"Root";case 6:return"Text";case 16:return Bo(t);case 8:return t===nl?"StrictMode":"Mode";case 22:return"Offscreen";case 12:return"Profiler";case 21:return"Scope";case 13:return"Suspense";case 19:return"SuspenseList";case 25:return"TracingMarker";case 1:case 0:case 17:case 2:case 14:case 15:if(typeof t=="function")return t.displayName||t.name||null;if(typeof t=="string")return t}return null}function Ft(e){switch(typeof e){case"boolean":case"number":case"string":case"undefined":return e;case"object":return e;default:return""}}function ff(e){var t=e.type;return(e=e.nodeName)&&e.toLowerCase()==="input"&&(t==="checkbox"||t==="radio")}function g0(e){var t=ff(e)?"checked":"value",n=Object.getOwnPropertyDescriptor(e.constructor.prototype,t),r=""+e[t];if(!e.hasOwnProperty(t)&&typeof n<"u"&&typeof n.get=="function"&&typeof n.set=="function"){var i=n.get,s=n.set;return Object.defineProperty(e,t,{configurable:!0,get:function(){return i.call(this)},set:function(o){r=""+o,s.call(this,o)}}),Object.defineProperty(e,t,{enumerable:n.enumerable}),{getValue:function(){return r},setValue:function(o){r=""+o},stopTracking:function(){e._valueTracker=null,delete e[t]}}}}function fi(e){e._valueTracker||(e._valueTracker=g0(e))}function hf(e){if(!e)return!1;var t=e._valueTracker;if(!t)return!0;var n=t.getValue(),r="";return e&&(r=ff(e)?e.checked?"true":"false":e.value),e=r,e!==n?(t.setValue(e),!0):!1}function Gi(e){if(e=e||(typeof document<"u"?document:void 0),typeof e>"u")return null;try{return e.activeElement||e.body}catch{return e.body}}function Uo(e,t){var n=t.checked;return Y({},t,{defaultChecked:void 0,defaultValue:void 0,value:void 0,checked:n??e._wrapperState.initialChecked})}function Du(e,t){var n=t.defaultValue==null?"":t.defaultValue,r=t.checked!=null?t.checked:t.defaultChecked;n=Ft(t.value!=null?t.value:n),e._wrapperState={initialChecked:r,initialValue:n,controlled:t.type==="checkbox"||t.type==="radio"?t.checked!=null:t.value!=null}}function pf(e,t){t=t.checked,t!=null&&tl(e,"checked",t,!1)}function Wo(e,t){pf(e,t);var n=Ft(t.value),r=t.type;if(n!=null)r==="number"?(n===0&&e.value===""||e.value!=n)&&(e.value=""+n):e.value!==""+n&&(e.value=""+n);else if(r==="submit"||r==="reset"){e.removeAttribute("value");return}t.hasOwnProperty("value")?bo(e,t.type,n):t.hasOwnProperty("defaultValue")&&bo(e,t.type,Ft(t.defaultValue)),t.checked==null&&t.defaultChecked!=null&&(e.defaultChecked=!!t.defaultChecked)}function Mu(e,t,n){if(t.hasOwnProperty("value")||t.hasOwnProperty("defaultValue")){var r=t.type;if(!(r!=="submit"&&r!=="reset"||t.value!==void 0&&t.value!==null))return;t=""+e._wrapperState.initialValue,n||t===e.value||(e.value=t),e.defaultValue=t}n=e.name,n!==""&&(e.name=""),e.defaultChecked=!!e._wrapperState.initialChecked,n!==""&&(e.name=n)}function bo(e,t,n){(t!=="number"||Gi(e.ownerDocument)!==e)&&(n==null?e.defaultValue=""+e._wrapperState.initialValue:e.defaultValue!==""+n&&(e.defaultValue=""+n))}var fr=Array.isArray;function Rn(e,t,n,r){if(e=e.options,t){t={};for(var i=0;i"+t.valueOf().toString()+"",t=hi.firstChild;e.firstChild;)e.removeChild(e.firstChild);for(;t.firstChild;)e.appendChild(t.firstChild)}});function Mr(e,t){if(t){var n=e.firstChild;if(n&&n===e.lastChild&&n.nodeType===3){n.nodeValue=t;return}}e.textContent=t}var gr={animationIterationCount:!0,aspectRatio:!0,borderImageOutset:!0,borderImageSlice:!0,borderImageWidth:!0,boxFlex:!0,boxFlexGroup:!0,boxOrdinalGroup:!0,columnCount:!0,columns:!0,flex:!0,flexGrow:!0,flexPositive:!0,flexShrink:!0,flexNegative:!0,flexOrder:!0,gridArea:!0,gridRow:!0,gridRowEnd:!0,gridRowSpan:!0,gridRowStart:!0,gridColumn:!0,gridColumnEnd:!0,gridColumnSpan:!0,gridColumnStart:!0,fontWeight:!0,lineClamp:!0,lineHeight:!0,opacity:!0,order:!0,orphans:!0,tabSize:!0,widows:!0,zIndex:!0,zoom:!0,fillOpacity:!0,floodOpacity:!0,stopOpacity:!0,strokeDasharray:!0,strokeDashoffset:!0,strokeMiterlimit:!0,strokeOpacity:!0,strokeWidth:!0},y0=["Webkit","ms","Moz","O"];Object.keys(gr).forEach(function(e){y0.forEach(function(t){t=t+e.charAt(0).toUpperCase()+e.substring(1),gr[t]=gr[e]})});function vf(e,t,n){return t==null||typeof t=="boolean"||t===""?"":n||typeof t!="number"||t===0||gr.hasOwnProperty(e)&&gr[e]?(""+t).trim():t+"px"}function xf(e,t){e=e.style;for(var n in t)if(t.hasOwnProperty(n)){var r=n.indexOf("--")===0,i=vf(n,t[n],r);n==="float"&&(n="cssFloat"),r?e.setProperty(n,i):e[n]=i}}var v0=Y({menuitem:!0},{area:!0,base:!0,br:!0,col:!0,embed:!0,hr:!0,img:!0,input:!0,keygen:!0,link:!0,meta:!0,param:!0,source:!0,track:!0,wbr:!0});function Ko(e,t){if(t){if(v0[e]&&(t.children!=null||t.dangerouslySetInnerHTML!=null))throw Error(j(137,e));if(t.dangerouslySetInnerHTML!=null){if(t.children!=null)throw Error(j(60));if(typeof t.dangerouslySetInnerHTML!="object"||!("__html"in t.dangerouslySetInnerHTML))throw Error(j(61))}if(t.style!=null&&typeof t.style!="object")throw Error(j(62))}}function Go(e,t){if(e.indexOf("-")===-1)return typeof t.is=="string";switch(e){case"annotation-xml":case"color-profile":case"font-face":case"font-face-src":case"font-face-uri":case"font-face-format":case"font-face-name":case"missing-glyph":return!1;default:return!0}}var Qo=null;function sl(e){return e=e.target||e.srcElement||window,e.correspondingUseElement&&(e=e.correspondingUseElement),e.nodeType===3?e.parentNode:e}var Yo=null,In=null,_n=null;function Vu(e){if(e=ti(e)){if(typeof Yo!="function")throw Error(j(280));var t=e.stateNode;t&&(t=Ns(t),Yo(e.stateNode,e.type,t))}}function wf(e){In?_n?_n.push(e):_n=[e]:In=e}function kf(){if(In){var e=In,t=_n;if(_n=In=null,Vu(e),t)for(e=0;e>>=0,e===0?32:31-(D0(e)/M0|0)|0}var pi=64,mi=4194304;function hr(e){switch(e&-e){case 1:return 1;case 2:return 2;case 4:return 4;case 8:return 8;case 16:return 16;case 32:return 32;case 64:case 128:case 256:case 512:case 1024:case 2048:case 4096:case 8192:case 16384:case 32768:case 65536:case 131072:case 262144:case 524288:case 1048576:case 2097152:return e&4194240;case 4194304:case 8388608:case 16777216:case 33554432:case 67108864:return e&130023424;case 134217728:return 134217728;case 268435456:return 268435456;case 536870912:return 536870912;case 1073741824:return 1073741824;default:return e}}function Zi(e,t){var n=e.pendingLanes;if(n===0)return 0;var r=0,i=e.suspendedLanes,s=e.pingedLanes,o=n&268435455;if(o!==0){var a=o&~i;a!==0?r=hr(a):(s&=o,s!==0&&(r=hr(s)))}else o=n&~i,o!==0?r=hr(o):s!==0&&(r=hr(s));if(r===0)return 0;if(t!==0&&t!==r&&!(t&i)&&(i=r&-r,s=t&-t,i>=s||i===16&&(s&4194240)!==0))return t;if(r&4&&(r|=n&16),t=e.entangledLanes,t!==0)for(e=e.entanglements,t&=r;0n;n++)t.push(e);return t}function Jr(e,t,n){e.pendingLanes|=t,t!==536870912&&(e.suspendedLanes=0,e.pingedLanes=0),e=e.eventTimes,t=31-Je(t),e[t]=n}function R0(e,t){var n=e.pendingLanes&~t;e.pendingLanes=t,e.suspendedLanes=0,e.pingedLanes=0,e.expiredLanes&=t,e.mutableReadLanes&=t,e.entangledLanes&=t,t=e.entanglements;var r=e.eventTimes;for(e=e.expirationTimes;0=vr),Wu=" ",bu=!1;function Uf(e,t){switch(e){case"keyup":return lg.indexOf(t.keyCode)!==-1;case"keydown":return t.keyCode!==229;case"keypress":case"mousedown":case"focusout":return!0;default:return!1}}function Wf(e){return e=e.detail,typeof e=="object"&&"data"in e?e.data:null}var xn=!1;function cg(e,t){switch(e){case"compositionend":return Wf(t);case"keypress":return t.which!==32?null:(bu=!0,Wu);case"textInput":return e=t.data,e===Wu&&bu?null:e;default:return null}}function dg(e,t){if(xn)return e==="compositionend"||!hl&&Uf(e,t)?(e=zf(),Ri=cl=Nt=null,xn=!1,e):null;switch(e){case"paste":return null;case"keypress":if(!(t.ctrlKey||t.altKey||t.metaKey)||t.ctrlKey&&t.altKey){if(t.char&&1=t)return{node:n,offset:t-e};e=r}e:{for(;n;){if(n.nextSibling){n=n.nextSibling;break e}n=n.parentNode}n=void 0}n=Gu(n)}}function Kf(e,t){return e&&t?e===t?!0:e&&e.nodeType===3?!1:t&&t.nodeType===3?Kf(e,t.parentNode):"contains"in e?e.contains(t):e.compareDocumentPosition?!!(e.compareDocumentPosition(t)&16):!1:!1}function Gf(){for(var e=window,t=Gi();t instanceof e.HTMLIFrameElement;){try{var n=typeof t.contentWindow.location.href=="string"}catch{n=!1}if(n)e=t.contentWindow;else break;t=Gi(e.document)}return t}function pl(e){var t=e&&e.nodeName&&e.nodeName.toLowerCase();return t&&(t==="input"&&(e.type==="text"||e.type==="search"||e.type==="tel"||e.type==="url"||e.type==="password")||t==="textarea"||e.contentEditable==="true")}function wg(e){var t=Gf(),n=e.focusedElem,r=e.selectionRange;if(t!==n&&n&&n.ownerDocument&&Kf(n.ownerDocument.documentElement,n)){if(r!==null&&pl(n)){if(t=r.start,e=r.end,e===void 0&&(e=t),"selectionStart"in n)n.selectionStart=t,n.selectionEnd=Math.min(e,n.value.length);else if(e=(t=n.ownerDocument||document)&&t.defaultView||window,e.getSelection){e=e.getSelection();var i=n.textContent.length,s=Math.min(r.start,i);r=r.end===void 0?s:Math.min(r.end,i),!e.extend&&s>r&&(i=r,r=s,s=i),i=Qu(n,s);var o=Qu(n,r);i&&o&&(e.rangeCount!==1||e.anchorNode!==i.node||e.anchorOffset!==i.offset||e.focusNode!==o.node||e.focusOffset!==o.offset)&&(t=t.createRange(),t.setStart(i.node,i.offset),e.removeAllRanges(),s>r?(e.addRange(t),e.extend(o.node,o.offset)):(t.setEnd(o.node,o.offset),e.addRange(t)))}}for(t=[],e=n;e=e.parentNode;)e.nodeType===1&&t.push({element:e,left:e.scrollLeft,top:e.scrollTop});for(typeof n.focus=="function"&&n.focus(),n=0;n=document.documentMode,wn=null,ta=null,wr=null,na=!1;function Yu(e,t,n){var r=n.window===n?n.document:n.nodeType===9?n:n.ownerDocument;na||wn==null||wn!==Gi(r)||(r=wn,"selectionStart"in r&&pl(r)?r={start:r.selectionStart,end:r.selectionEnd}:(r=(r.ownerDocument&&r.ownerDocument.defaultView||window).getSelection(),r={anchorNode:r.anchorNode,anchorOffset:r.anchorOffset,focusNode:r.focusNode,focusOffset:r.focusOffset}),wr&&_r(wr,r)||(wr=r,r=es(ta,"onSelect"),0Tn||(e.current=la[Tn],la[Tn]=null,Tn--)}function z(e,t){Tn++,la[Tn]=e.current,e.current=t}var zt={},ye=bt(zt),je=bt(!1),un=zt;function Wn(e,t){var n=e.type.contextTypes;if(!n)return zt;var r=e.stateNode;if(r&&r.__reactInternalMemoizedUnmaskedChildContext===t)return r.__reactInternalMemoizedMaskedChildContext;var i={},s;for(s in n)i[s]=t[s];return r&&(e=e.stateNode,e.__reactInternalMemoizedUnmaskedChildContext=t,e.__reactInternalMemoizedMaskedChildContext=i),i}function Ee(e){return e=e.childContextTypes,e!=null}function ns(){W(je),W(ye)}function nc(e,t,n){if(ye.current!==zt)throw Error(j(168));z(ye,t),z(je,n)}function nh(e,t,n){var r=e.stateNode;if(t=t.childContextTypes,typeof r.getChildContext!="function")return n;r=r.getChildContext();for(var i in r)if(!(i in t))throw Error(j(108,m0(e)||"Unknown",i));return Y({},n,r)}function rs(e){return e=(e=e.stateNode)&&e.__reactInternalMemoizedMergedChildContext||zt,un=ye.current,z(ye,e),z(je,je.current),!0}function rc(e,t,n){var r=e.stateNode;if(!r)throw Error(j(169));n?(e=nh(e,t,un),r.__reactInternalMemoizedMergedChildContext=e,W(je),W(ye),z(ye,e)):W(je),z(je,n)}var ct=null,Ds=!1,lo=!1;function rh(e){ct===null?ct=[e]:ct.push(e)}function Ag(e){Ds=!0,rh(e)}function $t(){if(!lo&&ct!==null){lo=!0;var e=0,t=O;try{var n=ct;for(O=1;e>=o,i-=o,dt=1<<32-Je(t)+i|n<C?(R=P,P=null):R=P.sibling;var M=f(m,P,g[C],w);if(M===null){P===null&&(P=R);break}e&&P&&M.alternate===null&&t(m,P),p=s(M,p,C),T===null?k=M:T.sibling=M,T=M,P=R}if(C===g.length)return n(m,P),b&&Xt(m,C),k;if(P===null){for(;CC?(R=P,P=null):R=P.sibling;var X=f(m,P,M.value,w);if(X===null){P===null&&(P=R);break}e&&P&&X.alternate===null&&t(m,P),p=s(X,p,C),T===null?k=X:T.sibling=X,T=X,P=R}if(M.done)return n(m,P),b&&Xt(m,C),k;if(P===null){for(;!M.done;C++,M=g.next())M=d(m,M.value,w),M!==null&&(p=s(M,p,C),T===null?k=M:T.sibling=M,T=M);return b&&Xt(m,C),k}for(P=r(m,P);!M.done;C++,M=g.next())M=y(P,m,C,M.value,w),M!==null&&(e&&M.alternate!==null&&P.delete(M.key===null?C:M.key),p=s(M,p,C),T===null?k=M:T.sibling=M,T=M);return e&&P.forEach(function(Ke){return t(m,Ke)}),b&&Xt(m,C),k}function S(m,p,g,w){if(typeof g=="object"&&g!==null&&g.type===vn&&g.key===null&&(g=g.props.children),typeof g=="object"&&g!==null){switch(g.$$typeof){case di:e:{for(var k=g.key,T=p;T!==null;){if(T.key===k){if(k=g.type,k===vn){if(T.tag===7){n(m,T.sibling),p=i(T,g.props.children),p.return=m,m=p;break e}}else if(T.elementType===k||typeof k=="object"&&k!==null&&k.$$typeof===Ct&&oc(k)===T.type){n(m,T.sibling),p=i(T,g.props),p.ref=ar(m,T,g),p.return=m,m=p;break e}n(m,T);break}else t(m,T);T=T.sibling}g.type===vn?(p=on(g.props.children,m.mode,w,g.key),p.return=m,m=p):(w=Wi(g.type,g.key,g.props,null,m.mode,w),w.ref=ar(m,p,g),w.return=m,m=w)}return o(m);case yn:e:{for(T=g.key;p!==null;){if(p.key===T)if(p.tag===4&&p.stateNode.containerInfo===g.containerInfo&&p.stateNode.implementation===g.implementation){n(m,p.sibling),p=i(p,g.children||[]),p.return=m,m=p;break e}else{n(m,p);break}else t(m,p);p=p.sibling}p=yo(g,m.mode,w),p.return=m,m=p}return o(m);case Ct:return T=g._init,S(m,p,T(g._payload),w)}if(fr(g))return v(m,p,g,w);if(nr(g))return x(m,p,g,w);Si(m,g)}return typeof g=="string"&&g!==""||typeof g=="number"?(g=""+g,p!==null&&p.tag===6?(n(m,p.sibling),p=i(p,g),p.return=m,m=p):(n(m,p),p=go(g,m.mode,w),p.return=m,m=p),o(m)):n(m,p)}return S}var $n=ah(!0),lh=ah(!1),os=bt(null),as=null,jn=null,vl=null;function xl(){vl=jn=as=null}function wl(e){var t=os.current;W(os),e._currentValue=t}function da(e,t,n){for(;e!==null;){var r=e.alternate;if((e.childLanes&t)!==t?(e.childLanes|=t,r!==null&&(r.childLanes|=t)):r!==null&&(r.childLanes&t)!==t&&(r.childLanes|=t),e===n)break;e=e.return}}function Fn(e,t){as=e,vl=jn=null,e=e.dependencies,e!==null&&e.firstContext!==null&&(e.lanes&t&&(Ce=!0),e.firstContext=null)}function $e(e){var t=e._currentValue;if(vl!==e)if(e={context:e,memoizedValue:t,next:null},jn===null){if(as===null)throw Error(j(308));jn=e,as.dependencies={lanes:0,firstContext:e}}else jn=jn.next=e;return t}var en=null;function kl(e){en===null?en=[e]:en.push(e)}function uh(e,t,n,r){var i=t.interleaved;return i===null?(n.next=n,kl(t)):(n.next=i.next,i.next=n),t.interleaved=n,gt(e,r)}function gt(e,t){e.lanes|=t;var n=e.alternate;for(n!==null&&(n.lanes|=t),n=e,e=e.return;e!==null;)e.childLanes|=t,n=e.alternate,n!==null&&(n.childLanes|=t),n=e,e=e.return;return n.tag===3?n.stateNode:null}var Pt=!1;function Sl(e){e.updateQueue={baseState:e.memoizedState,firstBaseUpdate:null,lastBaseUpdate:null,shared:{pending:null,interleaved:null,lanes:0},effects:null}}function ch(e,t){e=e.updateQueue,t.updateQueue===e&&(t.updateQueue={baseState:e.baseState,firstBaseUpdate:e.firstBaseUpdate,lastBaseUpdate:e.lastBaseUpdate,shared:e.shared,effects:e.effects})}function ht(e,t){return{eventTime:e,lane:t,tag:0,payload:null,callback:null,next:null}}function Rt(e,t,n){var r=e.updateQueue;if(r===null)return null;if(r=r.shared,_&2){var i=r.pending;return i===null?t.next=t:(t.next=i.next,i.next=t),r.pending=t,gt(e,n)}return i=r.interleaved,i===null?(t.next=t,kl(r)):(t.next=i.next,i.next=t),r.interleaved=t,gt(e,n)}function _i(e,t,n){if(t=t.updateQueue,t!==null&&(t=t.shared,(n&4194240)!==0)){var r=t.lanes;r&=e.pendingLanes,n|=r,t.lanes=n,al(e,n)}}function ac(e,t){var n=e.updateQueue,r=e.alternate;if(r!==null&&(r=r.updateQueue,n===r)){var i=null,s=null;if(n=n.firstBaseUpdate,n!==null){do{var o={eventTime:n.eventTime,lane:n.lane,tag:n.tag,payload:n.payload,callback:n.callback,next:null};s===null?i=s=o:s=s.next=o,n=n.next}while(n!==null);s===null?i=s=t:s=s.next=t}else i=s=t;n={baseState:r.baseState,firstBaseUpdate:i,lastBaseUpdate:s,shared:r.shared,effects:r.effects},e.updateQueue=n;return}e=n.lastBaseUpdate,e===null?n.firstBaseUpdate=t:e.next=t,n.lastBaseUpdate=t}function ls(e,t,n,r){var i=e.updateQueue;Pt=!1;var s=i.firstBaseUpdate,o=i.lastBaseUpdate,a=i.shared.pending;if(a!==null){i.shared.pending=null;var l=a,u=l.next;l.next=null,o===null?s=u:o.next=u,o=l;var c=e.alternate;c!==null&&(c=c.updateQueue,a=c.lastBaseUpdate,a!==o&&(a===null?c.firstBaseUpdate=u:a.next=u,c.lastBaseUpdate=l))}if(s!==null){var d=i.baseState;o=0,c=u=l=null,a=s;do{var f=a.lane,y=a.eventTime;if((r&f)===f){c!==null&&(c=c.next={eventTime:y,lane:0,tag:a.tag,payload:a.payload,callback:a.callback,next:null});e:{var v=e,x=a;switch(f=t,y=n,x.tag){case 1:if(v=x.payload,typeof v=="function"){d=v.call(y,d,f);break e}d=v;break e;case 3:v.flags=v.flags&-65537|128;case 0:if(v=x.payload,f=typeof v=="function"?v.call(y,d,f):v,f==null)break e;d=Y({},d,f);break e;case 2:Pt=!0}}a.callback!==null&&a.lane!==0&&(e.flags|=64,f=i.effects,f===null?i.effects=[a]:f.push(a))}else y={eventTime:y,lane:f,tag:a.tag,payload:a.payload,callback:a.callback,next:null},c===null?(u=c=y,l=d):c=c.next=y,o|=f;if(a=a.next,a===null){if(a=i.shared.pending,a===null)break;f=a,a=f.next,f.next=null,i.lastBaseUpdate=f,i.shared.pending=null}}while(!0);if(c===null&&(l=d),i.baseState=l,i.firstBaseUpdate=u,i.lastBaseUpdate=c,t=i.shared.interleaved,t!==null){i=t;do o|=i.lane,i=i.next;while(i!==t)}else s===null&&(i.shared.lanes=0);fn|=o,e.lanes=o,e.memoizedState=d}}function lc(e,t,n){if(e=t.effects,t.effects=null,e!==null)for(t=0;tn?n:4,e(!0);var r=co.transition;co.transition={};try{e(!1),t()}finally{O=n,co.transition=r}}function Eh(){return He().memoizedState}function _g(e,t,n){var r=_t(e);if(n={lane:r,action:n,hasEagerState:!1,eagerState:null,next:null},Nh(e))Dh(t,n);else if(n=uh(e,t,n,r),n!==null){var i=we();et(n,e,r,i),Mh(n,t,r)}}function Og(e,t,n){var r=_t(e),i={lane:r,action:n,hasEagerState:!1,eagerState:null,next:null};if(Nh(e))Dh(t,i);else{var s=e.alternate;if(e.lanes===0&&(s===null||s.lanes===0)&&(s=t.lastRenderedReducer,s!==null))try{var o=t.lastRenderedState,a=s(o,n);if(i.hasEagerState=!0,i.eagerState=a,tt(a,o)){var l=t.interleaved;l===null?(i.next=i,kl(t)):(i.next=l.next,l.next=i),t.interleaved=i;return}}catch{}finally{}n=uh(e,t,i,r),n!==null&&(i=we(),et(n,e,r,i),Mh(n,t,r))}}function Nh(e){var t=e.alternate;return e===Q||t!==null&&t===Q}function Dh(e,t){kr=cs=!0;var n=e.pending;n===null?t.next=t:(t.next=n.next,n.next=t),e.pending=t}function Mh(e,t,n){if(n&4194240){var r=t.lanes;r&=e.pendingLanes,n|=r,t.lanes=n,al(e,n)}}var ds={readContext:$e,useCallback:he,useContext:he,useEffect:he,useImperativeHandle:he,useInsertionEffect:he,useLayoutEffect:he,useMemo:he,useReducer:he,useRef:he,useState:he,useDebugValue:he,useDeferredValue:he,useTransition:he,useMutableSource:he,useSyncExternalStore:he,useId:he,unstable_isNewReconciler:!1},Fg={readContext:$e,useCallback:function(e,t){return rt().memoizedState=[e,t===void 0?null:t],e},useContext:$e,useEffect:cc,useImperativeHandle:function(e,t,n){return n=n!=null?n.concat([e]):null,Fi(4194308,4,Sh.bind(null,t,e),n)},useLayoutEffect:function(e,t){return Fi(4194308,4,e,t)},useInsertionEffect:function(e,t){return Fi(4,2,e,t)},useMemo:function(e,t){var n=rt();return t=t===void 0?null:t,e=e(),n.memoizedState=[e,t],e},useReducer:function(e,t,n){var r=rt();return t=n!==void 0?n(t):t,r.memoizedState=r.baseState=t,e={pending:null,interleaved:null,lanes:0,dispatch:null,lastRenderedReducer:e,lastRenderedState:t},r.queue=e,e=e.dispatch=_g.bind(null,Q,e),[r.memoizedState,e]},useRef:function(e){var t=rt();return e={current:e},t.memoizedState=e},useState:uc,useDebugValue:Ml,useDeferredValue:function(e){return rt().memoizedState=e},useTransition:function(){var e=uc(!1),t=e[0];return e=Ig.bind(null,e[1]),rt().memoizedState=e,[t,e]},useMutableSource:function(){},useSyncExternalStore:function(e,t,n){var r=Q,i=rt();if(b){if(n===void 0)throw Error(j(407));n=n()}else{if(n=t(),le===null)throw Error(j(349));dn&30||ph(r,t,n)}i.memoizedState=n;var s={value:n,getSnapshot:t};return i.queue=s,cc(gh.bind(null,r,s,e),[e]),r.flags|=2048,$r(9,mh.bind(null,r,s,n,t),void 0,null),n},useId:function(){var e=rt(),t=le.identifierPrefix;if(b){var n=ft,r=dt;n=(r&~(1<<32-Je(r)-1)).toString(32)+n,t=":"+t+"R"+n,n=Wr++,0<\/script>",e=e.removeChild(e.firstChild)):typeof r.is=="string"?e=o.createElement(n,{is:r.is}):(e=o.createElement(n),n==="select"&&(o=e,r.multiple?o.multiple=!0:r.size&&(o.size=r.size))):e=o.createElementNS(e,n),e[it]=t,e[zr]=r,Bh(e,t,!1,!1),t.stateNode=e;e:{switch(o=Go(n,r),n){case"dialog":U("cancel",e),U("close",e),i=r;break;case"iframe":case"object":case"embed":U("load",e),i=r;break;case"video":case"audio":for(i=0;iGn&&(t.flags|=128,r=!0,lr(s,!1),t.lanes=4194304)}else{if(!r)if(e=us(o),e!==null){if(t.flags|=128,r=!0,n=e.updateQueue,n!==null&&(t.updateQueue=n,t.flags|=4),lr(s,!0),s.tail===null&&s.tailMode==="hidden"&&!o.alternate&&!b)return pe(t),null}else 2*J()-s.renderingStartTime>Gn&&n!==1073741824&&(t.flags|=128,r=!0,lr(s,!1),t.lanes=4194304);s.isBackwards?(o.sibling=t.child,t.child=o):(n=s.last,n!==null?n.sibling=o:t.child=o,s.last=o)}return s.tail!==null?(t=s.tail,s.rendering=t,s.tail=t.sibling,s.renderingStartTime=J(),t.sibling=null,n=K.current,z(K,r?n&1|2:n&1),t):(pe(t),null);case 22:case 23:return _l(),r=t.memoizedState!==null,e!==null&&e.memoizedState!==null!==r&&(t.flags|=8192),r&&t.mode&1?De&1073741824&&(pe(t),t.subtreeFlags&6&&(t.flags|=8192)):pe(t),null;case 24:return null;case 25:return null}throw Error(j(156,t.tag))}function Kg(e,t){switch(gl(t),t.tag){case 1:return Ee(t.type)&&ns(),e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 3:return Hn(),W(je),W(ye),Pl(),e=t.flags,e&65536&&!(e&128)?(t.flags=e&-65537|128,t):null;case 5:return Cl(t),null;case 13:if(W(K),e=t.memoizedState,e!==null&&e.dehydrated!==null){if(t.alternate===null)throw Error(j(340));bn()}return e=t.flags,e&65536?(t.flags=e&-65537|128,t):null;case 19:return W(K),null;case 4:return Hn(),null;case 10:return wl(t.type._context),null;case 22:case 23:return _l(),null;case 24:return null;default:return null}}var Ci=!1,me=!1,Gg=typeof WeakSet=="function"?WeakSet:Set,D=null;function En(e,t){var n=e.ref;if(n!==null)if(typeof n=="function")try{n(null)}catch(r){q(e,t,r)}else n.current=null}function wa(e,t,n){try{n()}catch(r){q(e,t,r)}}var kc=!1;function Qg(e,t){if(ra=qi,e=Gf(),pl(e)){if("selectionStart"in e)var n={start:e.selectionStart,end:e.selectionEnd};else e:{n=(n=e.ownerDocument)&&n.defaultView||window;var r=n.getSelection&&n.getSelection();if(r&&r.rangeCount!==0){n=r.anchorNode;var i=r.anchorOffset,s=r.focusNode;r=r.focusOffset;try{n.nodeType,s.nodeType}catch{n=null;break e}var o=0,a=-1,l=-1,u=0,c=0,d=e,f=null;t:for(;;){for(var y;d!==n||i!==0&&d.nodeType!==3||(a=o+i),d!==s||r!==0&&d.nodeType!==3||(l=o+r),d.nodeType===3&&(o+=d.nodeValue.length),(y=d.firstChild)!==null;)f=d,d=y;for(;;){if(d===e)break t;if(f===n&&++u===i&&(a=o),f===s&&++c===r&&(l=o),(y=d.nextSibling)!==null)break;d=f,f=d.parentNode}d=y}n=a===-1||l===-1?null:{start:a,end:l}}else n=null}n=n||{start:0,end:0}}else n=null;for(ia={focusedElem:e,selectionRange:n},qi=!1,D=t;D!==null;)if(t=D,e=t.child,(t.subtreeFlags&1028)!==0&&e!==null)e.return=t,D=e;else for(;D!==null;){t=D;try{var v=t.alternate;if(t.flags&1024)switch(t.tag){case 0:case 11:case 15:break;case 1:if(v!==null){var x=v.memoizedProps,S=v.memoizedState,m=t.stateNode,p=m.getSnapshotBeforeUpdate(t.elementType===t.type?x:Xe(t.type,x),S);m.__reactInternalSnapshotBeforeUpdate=p}break;case 3:var g=t.stateNode.containerInfo;g.nodeType===1?g.textContent="":g.nodeType===9&&g.documentElement&&g.removeChild(g.documentElement);break;case 5:case 6:case 4:case 17:break;default:throw Error(j(163))}}catch(w){q(t,t.return,w)}if(e=t.sibling,e!==null){e.return=t.return,D=e;break}D=t.return}return v=kc,kc=!1,v}function Sr(e,t,n){var r=t.updateQueue;if(r=r!==null?r.lastEffect:null,r!==null){var i=r=r.next;do{if((i.tag&e)===e){var s=i.destroy;i.destroy=void 0,s!==void 0&&wa(t,n,s)}i=i.next}while(i!==r)}}function As(e,t){if(t=t.updateQueue,t=t!==null?t.lastEffect:null,t!==null){var n=t=t.next;do{if((n.tag&e)===e){var r=n.create;n.destroy=r()}n=n.next}while(n!==t)}}function ka(e){var t=e.ref;if(t!==null){var n=e.stateNode;switch(e.tag){case 5:e=n;break;default:e=n}typeof t=="function"?t(e):t.current=e}}function bh(e){var t=e.alternate;t!==null&&(e.alternate=null,bh(t)),e.child=null,e.deletions=null,e.sibling=null,e.tag===5&&(t=e.stateNode,t!==null&&(delete t[it],delete t[zr],delete t[aa],delete t[Mg],delete t[Lg])),e.stateNode=null,e.return=null,e.dependencies=null,e.memoizedProps=null,e.memoizedState=null,e.pendingProps=null,e.stateNode=null,e.updateQueue=null}function $h(e){return e.tag===5||e.tag===3||e.tag===4}function Sc(e){e:for(;;){for(;e.sibling===null;){if(e.return===null||$h(e.return))return null;e=e.return}for(e.sibling.return=e.return,e=e.sibling;e.tag!==5&&e.tag!==6&&e.tag!==18;){if(e.flags&2||e.child===null||e.tag===4)continue e;e.child.return=e,e=e.child}if(!(e.flags&2))return e.stateNode}}function Sa(e,t,n){var r=e.tag;if(r===5||r===6)e=e.stateNode,t?n.nodeType===8?n.parentNode.insertBefore(e,t):n.insertBefore(e,t):(n.nodeType===8?(t=n.parentNode,t.insertBefore(e,n)):(t=n,t.appendChild(e)),n=n._reactRootContainer,n!=null||t.onclick!==null||(t.onclick=ts));else if(r!==4&&(e=e.child,e!==null))for(Sa(e,t,n),e=e.sibling;e!==null;)Sa(e,t,n),e=e.sibling}function Ta(e,t,n){var r=e.tag;if(r===5||r===6)e=e.stateNode,t?n.insertBefore(e,t):n.appendChild(e);else if(r!==4&&(e=e.child,e!==null))for(Ta(e,t,n),e=e.sibling;e!==null;)Ta(e,t,n),e=e.sibling}var ue=null,Ze=!1;function St(e,t,n){for(n=n.child;n!==null;)Hh(e,t,n),n=n.sibling}function Hh(e,t,n){if(st&&typeof st.onCommitFiberUnmount=="function")try{st.onCommitFiberUnmount(Cs,n)}catch{}switch(n.tag){case 5:me||En(n,t);case 6:var r=ue,i=Ze;ue=null,St(e,t,n),ue=r,Ze=i,ue!==null&&(Ze?(e=ue,n=n.stateNode,e.nodeType===8?e.parentNode.removeChild(n):e.removeChild(n)):ue.removeChild(n.stateNode));break;case 18:ue!==null&&(Ze?(e=ue,n=n.stateNode,e.nodeType===8?ao(e.parentNode,n):e.nodeType===1&&ao(e,n),Rr(e)):ao(ue,n.stateNode));break;case 4:r=ue,i=Ze,ue=n.stateNode.containerInfo,Ze=!0,St(e,t,n),ue=r,Ze=i;break;case 0:case 11:case 14:case 15:if(!me&&(r=n.updateQueue,r!==null&&(r=r.lastEffect,r!==null))){i=r=r.next;do{var s=i,o=s.destroy;s=s.tag,o!==void 0&&(s&2||s&4)&&wa(n,t,o),i=i.next}while(i!==r)}St(e,t,n);break;case 1:if(!me&&(En(n,t),r=n.stateNode,typeof r.componentWillUnmount=="function"))try{r.props=n.memoizedProps,r.state=n.memoizedState,r.componentWillUnmount()}catch(a){q(n,t,a)}St(e,t,n);break;case 21:St(e,t,n);break;case 22:n.mode&1?(me=(r=me)||n.memoizedState!==null,St(e,t,n),me=r):St(e,t,n);break;default:St(e,t,n)}}function Tc(e){var t=e.updateQueue;if(t!==null){e.updateQueue=null;var n=e.stateNode;n===null&&(n=e.stateNode=new Gg),t.forEach(function(r){var i=ry.bind(null,e,r);n.has(r)||(n.add(r),r.then(i,i))})}}function Ge(e,t){var n=t.deletions;if(n!==null)for(var r=0;ri&&(i=o),r&=~s}if(r=i,r=J()-r,r=(120>r?120:480>r?480:1080>r?1080:1920>r?1920:3e3>r?3e3:4320>r?4320:1960*Xg(r/1960))-r,10e?16:e,Dt===null)var r=!1;else{if(e=Dt,Dt=null,ps=0,_&6)throw Error(j(331));var i=_;for(_|=4,D=e.current;D!==null;){var s=D,o=s.child;if(D.flags&16){var a=s.deletions;if(a!==null){for(var l=0;lJ()-Rl?sn(e,0):Vl|=n),Ne(e,t)}function Jh(e,t){t===0&&(e.mode&1?(t=mi,mi<<=1,!(mi&130023424)&&(mi=4194304)):t=1);var n=we();e=gt(e,t),e!==null&&(Jr(e,t,n),Ne(e,n))}function ny(e){var t=e.memoizedState,n=0;t!==null&&(n=t.retryLane),Jh(e,n)}function ry(e,t){var n=0;switch(e.tag){case 13:var r=e.stateNode,i=e.memoizedState;i!==null&&(n=i.retryLane);break;case 19:r=e.stateNode;break;default:throw Error(j(314))}r!==null&&r.delete(t),Jh(e,n)}var ep;ep=function(e,t,n){if(e!==null)if(e.memoizedProps!==t.pendingProps||je.current)Ce=!0;else{if(!(e.lanes&n)&&!(t.flags&128))return Ce=!1,$g(e,t,n);Ce=!!(e.flags&131072)}else Ce=!1,b&&t.flags&1048576&&ih(t,ss,t.index);switch(t.lanes=0,t.tag){case 2:var r=t.type;zi(e,t),e=t.pendingProps;var i=Wn(t,ye.current);Fn(t,n),i=El(null,t,r,e,i,n);var s=Nl();return t.flags|=1,typeof i=="object"&&i!==null&&typeof i.render=="function"&&i.$$typeof===void 0?(t.tag=1,t.memoizedState=null,t.updateQueue=null,Ee(r)?(s=!0,rs(t)):s=!1,t.memoizedState=i.state!==null&&i.state!==void 0?i.state:null,Sl(t),i.updater=Ls,t.stateNode=i,i._reactInternals=t,ha(t,r,e,n),t=ga(null,t,r,!0,s,n)):(t.tag=0,b&&s&&ml(t),ve(null,t,i,n),t=t.child),t;case 16:r=t.elementType;e:{switch(zi(e,t),e=t.pendingProps,i=r._init,r=i(r._payload),t.type=r,i=t.tag=sy(r),e=Xe(r,e),i){case 0:t=ma(null,t,r,e,n);break e;case 1:t=vc(null,t,r,e,n);break e;case 11:t=gc(null,t,r,e,n);break e;case 14:t=yc(null,t,r,Xe(r.type,e),n);break e}throw Error(j(306,r,""))}return t;case 0:return r=t.type,i=t.pendingProps,i=t.elementType===r?i:Xe(r,i),ma(e,t,r,i,n);case 1:return r=t.type,i=t.pendingProps,i=t.elementType===r?i:Xe(r,i),vc(e,t,r,i,n);case 3:e:{if(Oh(t),e===null)throw Error(j(387));r=t.pendingProps,s=t.memoizedState,i=s.element,ch(e,t),ls(t,r,null,n);var o=t.memoizedState;if(r=o.element,s.isDehydrated)if(s={element:r,isDehydrated:!1,cache:o.cache,pendingSuspenseBoundaries:o.pendingSuspenseBoundaries,transitions:o.transitions},t.updateQueue.baseState=s,t.memoizedState=s,t.flags&256){i=Kn(Error(j(423)),t),t=xc(e,t,r,n,i);break e}else if(r!==i){i=Kn(Error(j(424)),t),t=xc(e,t,r,n,i);break e}else for(Me=Vt(t.stateNode.containerInfo.firstChild),Le=t,b=!0,qe=null,n=lh(t,null,r,n),t.child=n;n;)n.flags=n.flags&-3|4096,n=n.sibling;else{if(bn(),r===i){t=yt(e,t,n);break e}ve(e,t,r,n)}t=t.child}return t;case 5:return dh(t),e===null&&ca(t),r=t.type,i=t.pendingProps,s=e!==null?e.memoizedProps:null,o=i.children,sa(r,i)?o=null:s!==null&&sa(r,s)&&(t.flags|=32),_h(e,t),ve(e,t,o,n),t.child;case 6:return e===null&&ca(t),null;case 13:return Fh(e,t,n);case 4:return Tl(t,t.stateNode.containerInfo),r=t.pendingProps,e===null?t.child=$n(t,null,r,n):ve(e,t,r,n),t.child;case 11:return r=t.type,i=t.pendingProps,i=t.elementType===r?i:Xe(r,i),gc(e,t,r,i,n);case 7:return ve(e,t,t.pendingProps,n),t.child;case 8:return ve(e,t,t.pendingProps.children,n),t.child;case 12:return ve(e,t,t.pendingProps.children,n),t.child;case 10:e:{if(r=t.type._context,i=t.pendingProps,s=t.memoizedProps,o=i.value,z(os,r._currentValue),r._currentValue=o,s!==null)if(tt(s.value,o)){if(s.children===i.children&&!je.current){t=yt(e,t,n);break e}}else for(s=t.child,s!==null&&(s.return=t);s!==null;){var a=s.dependencies;if(a!==null){o=s.child;for(var l=a.firstContext;l!==null;){if(l.context===r){if(s.tag===1){l=ht(-1,n&-n),l.tag=2;var u=s.updateQueue;if(u!==null){u=u.shared;var c=u.pending;c===null?l.next=l:(l.next=c.next,c.next=l),u.pending=l}}s.lanes|=n,l=s.alternate,l!==null&&(l.lanes|=n),da(s.return,n,t),a.lanes|=n;break}l=l.next}}else if(s.tag===10)o=s.type===t.type?null:s.child;else if(s.tag===18){if(o=s.return,o===null)throw Error(j(341));o.lanes|=n,a=o.alternate,a!==null&&(a.lanes|=n),da(o,n,t),o=s.sibling}else o=s.child;if(o!==null)o.return=s;else for(o=s;o!==null;){if(o===t){o=null;break}if(s=o.sibling,s!==null){s.return=o.return,o=s;break}o=o.return}s=o}ve(e,t,i.children,n),t=t.child}return t;case 9:return i=t.type,r=t.pendingProps.children,Fn(t,n),i=$e(i),r=r(i),t.flags|=1,ve(e,t,r,n),t.child;case 14:return r=t.type,i=Xe(r,t.pendingProps),i=Xe(r.type,i),yc(e,t,r,i,n);case 15:return Rh(e,t,t.type,t.pendingProps,n);case 17:return r=t.type,i=t.pendingProps,i=t.elementType===r?i:Xe(r,i),zi(e,t),t.tag=1,Ee(r)?(e=!0,rs(t)):e=!1,Fn(t,n),Lh(t,r,i),ha(t,r,i,n),ga(null,t,r,!0,e,n);case 19:return zh(e,t,n);case 22:return Ih(e,t,n)}throw Error(j(156,t.tag))};function tp(e,t){return Nf(e,t)}function iy(e,t,n,r){this.tag=e,this.key=n,this.sibling=this.child=this.return=this.stateNode=this.type=this.elementType=null,this.index=0,this.ref=null,this.pendingProps=t,this.dependencies=this.memoizedState=this.updateQueue=this.memoizedProps=null,this.mode=r,this.subtreeFlags=this.flags=0,this.deletions=null,this.childLanes=this.lanes=0,this.alternate=null}function ze(e,t,n,r){return new iy(e,t,n,r)}function Fl(e){return e=e.prototype,!(!e||!e.isReactComponent)}function sy(e){if(typeof e=="function")return Fl(e)?1:0;if(e!=null){if(e=e.$$typeof,e===rl)return 11;if(e===il)return 14}return 2}function Ot(e,t){var n=e.alternate;return n===null?(n=ze(e.tag,t,e.key,e.mode),n.elementType=e.elementType,n.type=e.type,n.stateNode=e.stateNode,n.alternate=e,e.alternate=n):(n.pendingProps=t,n.type=e.type,n.flags=0,n.subtreeFlags=0,n.deletions=null),n.flags=e.flags&14680064,n.childLanes=e.childLanes,n.lanes=e.lanes,n.child=e.child,n.memoizedProps=e.memoizedProps,n.memoizedState=e.memoizedState,n.updateQueue=e.updateQueue,t=e.dependencies,n.dependencies=t===null?null:{lanes:t.lanes,firstContext:t.firstContext},n.sibling=e.sibling,n.index=e.index,n.ref=e.ref,n}function Wi(e,t,n,r,i,s){var o=2;if(r=e,typeof e=="function")Fl(e)&&(o=1);else if(typeof e=="string")o=5;else e:switch(e){case vn:return on(n.children,i,s,t);case nl:o=8,i|=8;break;case Oo:return e=ze(12,n,t,i|2),e.elementType=Oo,e.lanes=s,e;case Fo:return e=ze(13,n,t,i),e.elementType=Fo,e.lanes=s,e;case zo:return e=ze(19,n,t,i),e.elementType=zo,e.lanes=s,e;case df:return Rs(n,i,s,t);default:if(typeof e=="object"&&e!==null)switch(e.$$typeof){case uf:o=10;break e;case cf:o=9;break e;case rl:o=11;break e;case il:o=14;break e;case Ct:o=16,r=null;break e}throw Error(j(130,e==null?e:typeof e,""))}return t=ze(o,n,t,i),t.elementType=e,t.type=r,t.lanes=s,t}function on(e,t,n,r){return e=ze(7,e,r,t),e.lanes=n,e}function Rs(e,t,n,r){return e=ze(22,e,r,t),e.elementType=df,e.lanes=n,e.stateNode={isHidden:!1},e}function go(e,t,n){return e=ze(6,e,null,t),e.lanes=n,e}function yo(e,t,n){return t=ze(4,e.children!==null?e.children:[],e.key,t),t.lanes=n,t.stateNode={containerInfo:e.containerInfo,pendingChildren:null,implementation:e.implementation},t}function oy(e,t,n,r,i){this.tag=t,this.containerInfo=e,this.finishedWork=this.pingCache=this.current=this.pendingChildren=null,this.timeoutHandle=-1,this.callbackNode=this.pendingContext=this.context=null,this.callbackPriority=0,this.eventTimes=Xs(0),this.expirationTimes=Xs(-1),this.entangledLanes=this.finishedLanes=this.mutableReadLanes=this.expiredLanes=this.pingedLanes=this.suspendedLanes=this.pendingLanes=0,this.entanglements=Xs(0),this.identifierPrefix=r,this.onRecoverableError=i,this.mutableSourceEagerHydrationData=null}function zl(e,t,n,r,i,s,o,a,l){return e=new oy(e,t,n,a,l),t===1?(t=1,s===!0&&(t|=8)):t=0,s=ze(3,null,null,t),e.current=s,s.stateNode=e,s.memoizedState={element:r,isDehydrated:n,cache:null,transitions:null,pendingSuspenseBoundaries:null},Sl(s),e}function ay(e,t,n){var r=3"u"||typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE!="function"))try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(sp)}catch(e){console.error(e)}}sp(),sf.exports=Ve;var fy=sf.exports,Lc=fy;Io.createRoot=Lc.createRoot,Io.hydrateRoot=Lc.hydrateRoot;const bl=N.createContext({});function $l(e){const t=N.useRef(null);return t.current===null&&(t.current=e()),t.current}const Hl=typeof window<"u",op=Hl?N.useLayoutEffect:N.useEffect,zs=N.createContext(null);function Kl(e,t){e.indexOf(t)===-1&&e.push(t)}function Gl(e,t){const n=e.indexOf(t);n>-1&&e.splice(n,1)}const vt=(e,t,n)=>n>t?t:n{};const xt={},ap=e=>/^-?(?:\d+(?:\.\d+)?|\.\d+)$/u.test(e);function lp(e){return typeof e=="object"&&e!==null}const up=e=>/^0[^.\s]+$/u.test(e);function Yl(e){let t;return()=>(t===void 0&&(t=e()),t)}const We=e=>e,hy=(e,t)=>n=>t(e(n)),ri=(...e)=>e.reduce(hy),Kr=(e,t,n)=>{const r=t-e;return r===0?1:(n-e)/r};class Xl{constructor(){this.subscriptions=[]}add(t){return Kl(this.subscriptions,t),()=>Gl(this.subscriptions,t)}notify(t,n,r){const i=this.subscriptions.length;if(i)if(i===1)this.subscriptions[0](t,n,r);else for(let s=0;se*1e3,Be=e=>e/1e3;function cp(e,t){return t?e*(1e3/t):0}const dp=(e,t,n)=>(((1-3*n+3*t)*e+(3*n-6*t))*e+3*t)*e,py=1e-7,my=12;function gy(e,t,n,r,i){let s,o,a=0;do o=t+(n-t)/2,s=dp(o,r,i)-e,s>0?n=o:t=o;while(Math.abs(s)>py&&++agy(s,0,1,e,n);return s=>s===0||s===1?s:dp(i(s),t,r)}const fp=e=>t=>t<=.5?e(2*t)/2:(2-e(2*(1-t)))/2,hp=e=>t=>1-e(1-t),pp=ii(.33,1.53,.69,.99),Zl=hp(pp),mp=fp(Zl),gp=e=>(e*=2)<1?.5*Zl(e):.5*(2-Math.pow(2,-10*(e-1))),ql=e=>1-Math.sin(Math.acos(e)),yp=hp(ql),vp=fp(ql),yy=ii(.42,0,1,1),vy=ii(0,0,.58,1),xp=ii(.42,0,.58,1),xy=e=>Array.isArray(e)&&typeof e[0]!="number",wp=e=>Array.isArray(e)&&typeof e[0]=="number",wy={linear:We,easeIn:yy,easeInOut:xp,easeOut:vy,circIn:ql,circInOut:vp,circOut:yp,backIn:Zl,backInOut:mp,backOut:pp,anticipate:gp},ky=e=>typeof e=="string",Ac=e=>{if(wp(e)){Ql(e.length===4);const[t,n,r,i]=e;return ii(t,n,r,i)}else if(ky(e))return wy[e];return e},Ei=["setup","read","resolveKeyframes","preUpdate","update","preRender","render","postRender"];function Sy(e,t){let n=new Set,r=new Set,i=!1,s=!1;const o=new WeakSet;let a={delta:0,timestamp:0,isProcessing:!1};function l(c){o.has(c)&&(u.schedule(c),e()),c(a)}const u={schedule:(c,d=!1,f=!1)=>{const v=f&&i?n:r;return d&&o.add(c),v.has(c)||v.add(c),c},cancel:c=>{r.delete(c),o.delete(c)},process:c=>{if(a=c,i){s=!0;return}i=!0,[n,r]=[r,n],n.forEach(l),n.clear(),i=!1,s&&(s=!1,u.process(c))}};return u}const Ty=40;function kp(e,t){let n=!1,r=!0;const i={delta:0,timestamp:0,isProcessing:!1},s=()=>n=!0,o=Ei.reduce((g,w)=>(g[w]=Sy(s),g),{}),{setup:a,read:l,resolveKeyframes:u,preUpdate:c,update:d,preRender:f,render:y,postRender:v}=o,x=()=>{const g=xt.useManualTiming?i.timestamp:performance.now();n=!1,xt.useManualTiming||(i.delta=r?1e3/60:Math.max(Math.min(g-i.timestamp,Ty),1)),i.timestamp=g,i.isProcessing=!0,a.process(i),l.process(i),u.process(i),c.process(i),d.process(i),f.process(i),y.process(i),v.process(i),i.isProcessing=!1,n&&t&&(r=!1,e(x))},S=()=>{n=!0,r=!0,i.isProcessing||e(x)};return{schedule:Ei.reduce((g,w)=>{const k=o[w];return g[w]=(T,P=!1,C=!1)=>(n||S(),k.schedule(T,P,C)),g},{}),cancel:g=>{for(let w=0;w(bi===void 0&&Pe.set(ce.isProcessing||xt.useManualTiming?ce.timestamp:performance.now()),bi),set:e=>{bi=e,queueMicrotask(Cy)}},Sp=e=>t=>typeof t=="string"&&t.startsWith(e),Jl=Sp("--"),Py=Sp("var(--"),eu=e=>Py(e)?jy.test(e.split("/*")[0].trim()):!1,jy=/var\(--(?:[\w-]+\s*|[\w-]+\s*,(?:\s*[^)(\s]|\s*\((?:[^)(]|\([^)(]*\))*\))+\s*)\)$/iu,Jn={test:e=>typeof e=="number",parse:parseFloat,transform:e=>e},Gr={...Jn,transform:e=>vt(0,1,e)},Ni={...Jn,default:1},Pr=e=>Math.round(e*1e5)/1e5,tu=/-?(?:\d+(?:\.\d+)?|\.\d+)/gu;function Ey(e){return e==null}const Ny=/^(?:#[\da-f]{3,8}|(?:rgb|hsl)a?\((?:-?[\d.]+%?[,\s]+){2}-?[\d.]+%?\s*(?:[,/]\s*)?(?:\b\d+(?:\.\d+)?|\.\d+)?%?\))$/iu,nu=(e,t)=>n=>!!(typeof n=="string"&&Ny.test(n)&&n.startsWith(e)||t&&!Ey(n)&&Object.prototype.hasOwnProperty.call(n,t)),Tp=(e,t,n)=>r=>{if(typeof r!="string")return r;const[i,s,o,a]=r.match(tu);return{[e]:parseFloat(i),[t]:parseFloat(s),[n]:parseFloat(o),alpha:a!==void 0?parseFloat(a):1}},Dy=e=>vt(0,255,e),xo={...Jn,transform:e=>Math.round(Dy(e))},nn={test:nu("rgb","red"),parse:Tp("red","green","blue"),transform:({red:e,green:t,blue:n,alpha:r=1})=>"rgba("+xo.transform(e)+", "+xo.transform(t)+", "+xo.transform(n)+", "+Pr(Gr.transform(r))+")"};function My(e){let t="",n="",r="",i="";return e.length>5?(t=e.substring(1,3),n=e.substring(3,5),r=e.substring(5,7),i=e.substring(7,9)):(t=e.substring(1,2),n=e.substring(2,3),r=e.substring(3,4),i=e.substring(4,5),t+=t,n+=n,r+=r,i+=i),{red:parseInt(t,16),green:parseInt(n,16),blue:parseInt(r,16),alpha:i?parseInt(i,16)/255:1}}const Na={test:nu("#"),parse:My,transform:nn.transform},si=e=>({test:t=>typeof t=="string"&&t.endsWith(e)&&t.split(" ").length===1,parse:parseFloat,transform:t=>`${t}${e}`}),Tt=si("deg"),lt=si("%"),A=si("px"),Ly=si("vh"),Ay=si("vw"),Vc={...lt,parse:e=>lt.parse(e)/100,transform:e=>lt.transform(e*100)},Dn={test:nu("hsl","hue"),parse:Tp("hue","saturation","lightness"),transform:({hue:e,saturation:t,lightness:n,alpha:r=1})=>"hsla("+Math.round(e)+", "+lt.transform(Pr(t))+", "+lt.transform(Pr(n))+", "+Pr(Gr.transform(r))+")"},ee={test:e=>nn.test(e)||Na.test(e)||Dn.test(e),parse:e=>nn.test(e)?nn.parse(e):Dn.test(e)?Dn.parse(e):Na.parse(e),transform:e=>typeof e=="string"?e:e.hasOwnProperty("red")?nn.transform(e):Dn.transform(e),getAnimatableNone:e=>{const t=ee.parse(e);return t.alpha=0,ee.transform(t)}},Vy=/(?:#[\da-f]{3,8}|(?:rgb|hsl)a?\((?:-?[\d.]+%?[,\s]+){2}-?[\d.]+%?\s*(?:[,/]\s*)?(?:\b\d+(?:\.\d+)?|\.\d+)?%?\))/giu;function Ry(e){var t,n;return isNaN(e)&&typeof e=="string"&&(((t=e.match(tu))==null?void 0:t.length)||0)+(((n=e.match(Vy))==null?void 0:n.length)||0)>0}const Cp="number",Pp="color",Iy="var",_y="var(",Rc="${}",Oy=/var\s*\(\s*--(?:[\w-]+\s*|[\w-]+\s*,(?:\s*[^)(\s]|\s*\((?:[^)(]|\([^)(]*\))*\))+\s*)\)|#[\da-f]{3,8}|(?:rgb|hsl)a?\((?:-?[\d.]+%?[,\s]+){2}-?[\d.]+%?\s*(?:[,/]\s*)?(?:\b\d+(?:\.\d+)?|\.\d+)?%?\)|-?(?:\d+(?:\.\d+)?|\.\d+)/giu;function Qr(e){const t=e.toString(),n=[],r={color:[],number:[],var:[]},i=[];let s=0;const a=t.replace(Oy,l=>(ee.test(l)?(r.color.push(s),i.push(Pp),n.push(ee.parse(l))):l.startsWith(_y)?(r.var.push(s),i.push(Iy),n.push(l)):(r.number.push(s),i.push(Cp),n.push(parseFloat(l))),++s,Rc)).split(Rc);return{values:n,split:a,indexes:r,types:i}}function jp(e){return Qr(e).values}function Ep(e){const{split:t,types:n}=Qr(e),r=t.length;return i=>{let s="";for(let o=0;otypeof e=="number"?0:ee.test(e)?ee.getAnimatableNone(e):e;function zy(e){const t=jp(e);return Ep(e)(t.map(Fy))}const Ut={test:Ry,parse:jp,createTransformer:Ep,getAnimatableNone:zy};function wo(e,t,n){return n<0&&(n+=1),n>1&&(n-=1),n<1/6?e+(t-e)*6*n:n<1/2?t:n<2/3?e+(t-e)*(2/3-n)*6:e}function By({hue:e,saturation:t,lightness:n,alpha:r}){e/=360,t/=100,n/=100;let i=0,s=0,o=0;if(!t)i=s=o=n;else{const a=n<.5?n*(1+t):n+t-n*t,l=2*n-a;i=wo(l,a,e+1/3),s=wo(l,a,e),o=wo(l,a,e-1/3)}return{red:Math.round(i*255),green:Math.round(s*255),blue:Math.round(o*255),alpha:r}}function ys(e,t){return n=>n>0?t:e}const G=(e,t,n)=>e+(t-e)*n,ko=(e,t,n)=>{const r=e*e,i=n*(t*t-r)+r;return i<0?0:Math.sqrt(i)},Uy=[Na,nn,Dn],Wy=e=>Uy.find(t=>t.test(e));function Ic(e){const t=Wy(e);if(!t)return!1;let n=t.parse(e);return t===Dn&&(n=By(n)),n}const _c=(e,t)=>{const n=Ic(e),r=Ic(t);if(!n||!r)return ys(e,t);const i={...n};return s=>(i.red=ko(n.red,r.red,s),i.green=ko(n.green,r.green,s),i.blue=ko(n.blue,r.blue,s),i.alpha=G(n.alpha,r.alpha,s),nn.transform(i))},Da=new Set(["none","hidden"]);function by(e,t){return Da.has(e)?n=>n<=0?e:t:n=>n>=1?t:e}function $y(e,t){return n=>G(e,t,n)}function ru(e){return typeof e=="number"?$y:typeof e=="string"?eu(e)?ys:ee.test(e)?_c:Gy:Array.isArray(e)?Np:typeof e=="object"?ee.test(e)?_c:Hy:ys}function Np(e,t){const n=[...e],r=n.length,i=e.map((s,o)=>ru(s)(s,t[o]));return s=>{for(let o=0;o{for(const s in r)n[s]=r[s](i);return n}}function Ky(e,t){const n=[],r={color:0,var:0,number:0};for(let i=0;i{const n=Ut.createTransformer(t),r=Qr(e),i=Qr(t);return r.indexes.var.length===i.indexes.var.length&&r.indexes.color.length===i.indexes.color.length&&r.indexes.number.length>=i.indexes.number.length?Da.has(e)&&!i.values.length||Da.has(t)&&!r.values.length?by(e,t):ri(Np(Ky(r,i),i.values),n):ys(e,t)};function Dp(e,t,n){return typeof e=="number"&&typeof t=="number"&&typeof n=="number"?G(e,t,n):ru(e)(e,t)}const Qy=e=>{const t=({timestamp:n})=>e(n);return{start:(n=!0)=>$.update(t,n),stop:()=>Bt(t),now:()=>ce.isProcessing?ce.timestamp:Pe.now()}},Mp=(e,t,n=10)=>{let r="";const i=Math.max(Math.round(t/n),2);for(let s=0;s=vs?1/0:t}function Yy(e,t=100,n){const r=n({...e,keyframes:[0,t]}),i=Math.min(iu(r),vs);return{type:"keyframes",ease:s=>r.next(i*s).value/t,duration:Be(i)}}const Xy=5;function Lp(e,t,n){const r=Math.max(t-Xy,0);return cp(n-e(r),t-r)}const Z={stiffness:100,damping:10,mass:1,velocity:0,duration:800,bounce:.3,visualDuration:.3,restSpeed:{granular:.01,default:2},restDelta:{granular:.005,default:.5},minDuration:.01,maxDuration:10,minDamping:.05,maxDamping:1},So=.001;function Zy({duration:e=Z.duration,bounce:t=Z.bounce,velocity:n=Z.velocity,mass:r=Z.mass}){let i,s,o=1-t;o=vt(Z.minDamping,Z.maxDamping,o),e=vt(Z.minDuration,Z.maxDuration,Be(e)),o<1?(i=u=>{const c=u*o,d=c*e,f=c-n,y=Ma(u,o),v=Math.exp(-d);return So-f/y*v},s=u=>{const d=u*o*e,f=d*n+n,y=Math.pow(o,2)*Math.pow(u,2)*e,v=Math.exp(-d),x=Ma(Math.pow(u,2),o);return(-i(u)+So>0?-1:1)*((f-y)*v)/x}):(i=u=>{const c=Math.exp(-u*e),d=(u-n)*e+1;return-So+c*d},s=u=>{const c=Math.exp(-u*e),d=(n-u)*(e*e);return c*d});const a=5/e,l=Jy(i,s,a);if(e=at(e),isNaN(l))return{stiffness:Z.stiffness,damping:Z.damping,duration:e};{const u=Math.pow(l,2)*r;return{stiffness:u,damping:o*2*Math.sqrt(r*u),duration:e}}}const qy=12;function Jy(e,t,n){let r=n;for(let i=1;ie[n]!==void 0)}function n1(e){let t={velocity:Z.velocity,stiffness:Z.stiffness,damping:Z.damping,mass:Z.mass,isResolvedFromDuration:!1,...e};if(!Oc(e,t1)&&Oc(e,e1))if(e.visualDuration){const n=e.visualDuration,r=2*Math.PI/(n*1.2),i=r*r,s=2*vt(.05,1,1-(e.bounce||0))*Math.sqrt(i);t={...t,mass:Z.mass,stiffness:i,damping:s}}else{const n=Zy(e);t={...t,...n,mass:Z.mass},t.isResolvedFromDuration=!0}return t}function xs(e=Z.visualDuration,t=Z.bounce){const n=typeof e!="object"?{visualDuration:e,keyframes:[0,1],bounce:t}:e;let{restSpeed:r,restDelta:i}=n;const s=n.keyframes[0],o=n.keyframes[n.keyframes.length-1],a={done:!1,value:s},{stiffness:l,damping:u,mass:c,duration:d,velocity:f,isResolvedFromDuration:y}=n1({...n,velocity:-Be(n.velocity||0)}),v=f||0,x=u/(2*Math.sqrt(l*c)),S=o-s,m=Be(Math.sqrt(l/c)),p=Math.abs(S)<5;r||(r=p?Z.restSpeed.granular:Z.restSpeed.default),i||(i=p?Z.restDelta.granular:Z.restDelta.default);let g;if(x<1){const k=Ma(m,x);g=T=>{const P=Math.exp(-x*m*T);return o-P*((v+x*m*S)/k*Math.sin(k*T)+S*Math.cos(k*T))}}else if(x===1)g=k=>o-Math.exp(-m*k)*(S+(v+m*S)*k);else{const k=m*Math.sqrt(x*x-1);g=T=>{const P=Math.exp(-x*m*T),C=Math.min(k*T,300);return o-P*((v+x*m*S)*Math.sinh(C)+k*S*Math.cosh(C))/k}}const w={calculatedDuration:y&&d||null,next:k=>{const T=g(k);if(y)a.done=k>=d;else{let P=k===0?v:0;x<1&&(P=k===0?at(v):Lp(g,k,T));const C=Math.abs(P)<=r,R=Math.abs(o-T)<=i;a.done=C&&R}return a.value=a.done?o:T,a},toString:()=>{const k=Math.min(iu(w),vs),T=Mp(P=>w.next(k*P).value,k,30);return k+"ms "+T},toTransition:()=>{}};return w}xs.applyToOptions=e=>{const t=Yy(e,100,xs);return e.ease=t.ease,e.duration=at(t.duration),e.type="keyframes",e};function La({keyframes:e,velocity:t=0,power:n=.8,timeConstant:r=325,bounceDamping:i=10,bounceStiffness:s=500,modifyTarget:o,min:a,max:l,restDelta:u=.5,restSpeed:c}){const d=e[0],f={done:!1,value:d},y=C=>a!==void 0&&Cl,v=C=>a===void 0?l:l===void 0||Math.abs(a-C)-x*Math.exp(-C/r),g=C=>m+p(C),w=C=>{const R=p(C),M=g(C);f.done=Math.abs(R)<=u,f.value=f.done?m:M};let k,T;const P=C=>{y(f.value)&&(k=C,T=xs({keyframes:[f.value,v(f.value)],velocity:Lp(g,C,f.value),damping:i,stiffness:s,restDelta:u,restSpeed:c}))};return P(0),{calculatedDuration:null,next:C=>{let R=!1;return!T&&k===void 0&&(R=!0,w(C),P(C)),k!==void 0&&C>=k?T.next(C-k):(!R&&w(C),f)}}}function r1(e,t,n){const r=[],i=n||xt.mix||Dp,s=e.length-1;for(let o=0;ot[0];if(s===2&&t[0]===t[1])return()=>t[1];const o=e[0]===e[1];e[0]>e[s-1]&&(e=[...e].reverse(),t=[...t].reverse());const a=r1(t,r,i),l=a.length,u=c=>{if(o&&c1)for(;du(vt(e[0],e[s-1],c)):u}function s1(e,t){const n=e[e.length-1];for(let r=1;r<=t;r++){const i=Kr(0,t,r);e.push(G(n,1,i))}}function o1(e){const t=[0];return s1(t,e.length-1),t}function a1(e,t){return e.map(n=>n*t)}function l1(e,t){return e.map(()=>t||xp).splice(0,e.length-1)}function jr({duration:e=300,keyframes:t,times:n,ease:r="easeInOut"}){const i=xy(r)?r.map(Ac):Ac(r),s={done:!1,value:t[0]},o=a1(n&&n.length===t.length?n:o1(t),e),a=i1(o,t,{ease:Array.isArray(i)?i:l1(t,i)});return{calculatedDuration:e,next:l=>(s.value=a(l),s.done=l>=e,s)}}const u1=e=>e!==null;function su(e,{repeat:t,repeatType:n="loop"},r,i=1){const s=e.filter(u1),a=i<0||t&&n!=="loop"&&t%2===1?0:s.length-1;return!a||r===void 0?s[a]:r}const c1={decay:La,inertia:La,tween:jr,keyframes:jr,spring:xs};function Ap(e){typeof e.type=="string"&&(e.type=c1[e.type])}class ou{constructor(){this.updateFinished()}get finished(){return this._finished}updateFinished(){this._finished=new Promise(t=>{this.resolve=t})}notifyFinished(){this.resolve()}then(t,n){return this.finished.then(t,n)}}const d1=e=>e/100;class au extends ou{constructor(t){super(),this.state="idle",this.startTime=null,this.isStopped=!1,this.currentTime=0,this.holdTime=null,this.playbackSpeed=1,this.stop=()=>{var r,i;const{motionValue:n}=this.options;n&&n.updatedAt!==Pe.now()&&this.tick(Pe.now()),this.isStopped=!0,this.state!=="idle"&&(this.teardown(),(i=(r=this.options).onStop)==null||i.call(r))},this.options=t,this.initAnimation(),this.play(),t.autoplay===!1&&this.pause()}initAnimation(){const{options:t}=this;Ap(t);const{type:n=jr,repeat:r=0,repeatDelay:i=0,repeatType:s,velocity:o=0}=t;let{keyframes:a}=t;const l=n||jr;l!==jr&&typeof a[0]!="number"&&(this.mixKeyframes=ri(d1,Dp(a[0],a[1])),a=[0,100]);const u=l({...t,keyframes:a});s==="mirror"&&(this.mirroredGenerator=l({...t,keyframes:[...a].reverse(),velocity:-o})),u.calculatedDuration===null&&(u.calculatedDuration=iu(u));const{calculatedDuration:c}=u;this.calculatedDuration=c,this.resolvedDuration=c+i,this.totalDuration=this.resolvedDuration*(r+1)-i,this.generator=u}updateTime(t){const n=Math.round(t-this.startTime)*this.playbackSpeed;this.holdTime!==null?this.currentTime=this.holdTime:this.currentTime=n}tick(t,n=!1){const{generator:r,totalDuration:i,mixKeyframes:s,mirroredGenerator:o,resolvedDuration:a,calculatedDuration:l}=this;if(this.startTime===null)return r.next(0);const{delay:u=0,keyframes:c,repeat:d,repeatType:f,repeatDelay:y,type:v,onUpdate:x,finalKeyframe:S}=this.options;this.speed>0?this.startTime=Math.min(this.startTime,t):this.speed<0&&(this.startTime=Math.min(t-i/this.speed,this.startTime)),n?this.currentTime=t:this.updateTime(t);const m=this.currentTime-u*(this.playbackSpeed>=0?1:-1),p=this.playbackSpeed>=0?m<0:m>i;this.currentTime=Math.max(m,0),this.state==="finished"&&this.holdTime===null&&(this.currentTime=i);let g=this.currentTime,w=r;if(d){const C=Math.min(this.currentTime,i)/a;let R=Math.floor(C),M=C%1;!M&&C>=1&&(M=1),M===1&&R--,R=Math.min(R,d+1),!!(R%2)&&(f==="reverse"?(M=1-M,y&&(M-=y/a)):f==="mirror"&&(w=o)),g=vt(0,1,M)*a}const k=p?{done:!1,value:c[0]}:w.next(g);s&&(k.value=s(k.value));let{done:T}=k;!p&&l!==null&&(T=this.playbackSpeed>=0?this.currentTime>=i:this.currentTime<=0);const P=this.holdTime===null&&(this.state==="finished"||this.state==="running"&&T);return P&&v!==La&&(k.value=su(c,this.options,S,this.speed)),x&&x(k.value),P&&this.finish(),k}then(t,n){return this.finished.then(t,n)}get duration(){return Be(this.calculatedDuration)}get iterationDuration(){const{delay:t=0}=this.options||{};return this.duration+Be(t)}get time(){return Be(this.currentTime)}set time(t){var n;t=at(t),this.currentTime=t,this.startTime===null||this.holdTime!==null||this.playbackSpeed===0?this.holdTime=t:this.driver&&(this.startTime=this.driver.now()-t/this.playbackSpeed),(n=this.driver)==null||n.start(!1)}get speed(){return this.playbackSpeed}set speed(t){this.updateTime(Pe.now());const n=this.playbackSpeed!==t;this.playbackSpeed=t,n&&(this.time=Be(this.currentTime))}play(){var i,s;if(this.isStopped)return;const{driver:t=Qy,startTime:n}=this.options;this.driver||(this.driver=t(o=>this.tick(o))),(s=(i=this.options).onPlay)==null||s.call(i);const r=this.driver.now();this.state==="finished"?(this.updateFinished(),this.startTime=r):this.holdTime!==null?this.startTime=r-this.holdTime:this.startTime||(this.startTime=n??r),this.state==="finished"&&this.speed<0&&(this.startTime+=this.calculatedDuration),this.holdTime=null,this.state="running",this.driver.start()}pause(){this.state="paused",this.updateTime(Pe.now()),this.holdTime=this.currentTime}complete(){this.state!=="running"&&this.play(),this.state="finished",this.holdTime=null}finish(){var t,n;this.notifyFinished(),this.teardown(),this.state="finished",(n=(t=this.options).onComplete)==null||n.call(t)}cancel(){var t,n;this.holdTime=null,this.startTime=0,this.tick(0),this.teardown(),(n=(t=this.options).onCancel)==null||n.call(t)}teardown(){this.state="idle",this.stopDriver(),this.startTime=this.holdTime=null}stopDriver(){this.driver&&(this.driver.stop(),this.driver=void 0)}sample(t){return this.startTime=0,this.tick(t,!0)}attachTimeline(t){var n;return this.options.allowFlatten&&(this.options.type="keyframes",this.options.ease="linear",this.initAnimation()),(n=this.driver)==null||n.stop(),t.observe(this)}}function f1(e){for(let t=1;te*180/Math.PI,Aa=e=>{const t=rn(Math.atan2(e[1],e[0]));return Va(t)},h1={x:4,y:5,translateX:4,translateY:5,scaleX:0,scaleY:3,scale:e=>(Math.abs(e[0])+Math.abs(e[3]))/2,rotate:Aa,rotateZ:Aa,skewX:e=>rn(Math.atan(e[1])),skewY:e=>rn(Math.atan(e[2])),skew:e=>(Math.abs(e[1])+Math.abs(e[2]))/2},Va=e=>(e=e%360,e<0&&(e+=360),e),Fc=Aa,zc=e=>Math.sqrt(e[0]*e[0]+e[1]*e[1]),Bc=e=>Math.sqrt(e[4]*e[4]+e[5]*e[5]),p1={x:12,y:13,z:14,translateX:12,translateY:13,translateZ:14,scaleX:zc,scaleY:Bc,scale:e=>(zc(e)+Bc(e))/2,rotateX:e=>Va(rn(Math.atan2(e[6],e[5]))),rotateY:e=>Va(rn(Math.atan2(-e[2],e[0]))),rotateZ:Fc,rotate:Fc,skewX:e=>rn(Math.atan(e[4])),skewY:e=>rn(Math.atan(e[1])),skew:e=>(Math.abs(e[1])+Math.abs(e[4]))/2};function Ra(e){return e.includes("scale")?1:0}function Ia(e,t){if(!e||e==="none")return Ra(t);const n=e.match(/^matrix3d\(([-\d.e\s,]+)\)$/u);let r,i;if(n)r=p1,i=n;else{const a=e.match(/^matrix\(([-\d.e\s,]+)\)$/u);r=h1,i=a}if(!i)return Ra(t);const s=r[t],o=i[1].split(",").map(g1);return typeof s=="function"?s(o):o[s]}const m1=(e,t)=>{const{transform:n="none"}=getComputedStyle(e);return Ia(n,t)};function g1(e){return parseFloat(e.trim())}const er=["transformPerspective","x","y","z","translateX","translateY","translateZ","scale","scaleX","scaleY","rotate","rotateX","rotateY","rotateZ","skew","skewX","skewY"],tr=new Set(er),Uc=e=>e===Jn||e===A,y1=new Set(["x","y","z"]),v1=er.filter(e=>!y1.has(e));function x1(e){const t=[];return v1.forEach(n=>{const r=e.getValue(n);r!==void 0&&(t.push([n,r.get()]),r.set(n.startsWith("scale")?1:0))}),t}const an={width:({x:e},{paddingLeft:t="0",paddingRight:n="0"})=>e.max-e.min-parseFloat(t)-parseFloat(n),height:({y:e},{paddingTop:t="0",paddingBottom:n="0"})=>e.max-e.min-parseFloat(t)-parseFloat(n),top:(e,{top:t})=>parseFloat(t),left:(e,{left:t})=>parseFloat(t),bottom:({y:e},{top:t})=>parseFloat(t)+(e.max-e.min),right:({x:e},{left:t})=>parseFloat(t)+(e.max-e.min),x:(e,{transform:t})=>Ia(t,"x"),y:(e,{transform:t})=>Ia(t,"y")};an.translateX=an.x;an.translateY=an.y;const ln=new Set;let _a=!1,Oa=!1,Fa=!1;function Vp(){if(Oa){const e=Array.from(ln).filter(r=>r.needsMeasurement),t=new Set(e.map(r=>r.element)),n=new Map;t.forEach(r=>{const i=x1(r);i.length&&(n.set(r,i),r.render())}),e.forEach(r=>r.measureInitialState()),t.forEach(r=>{r.render();const i=n.get(r);i&&i.forEach(([s,o])=>{var a;(a=r.getValue(s))==null||a.set(o)})}),e.forEach(r=>r.measureEndState()),e.forEach(r=>{r.suspendedScrollY!==void 0&&window.scrollTo(0,r.suspendedScrollY)})}Oa=!1,_a=!1,ln.forEach(e=>e.complete(Fa)),ln.clear()}function Rp(){ln.forEach(e=>{e.readKeyframes(),e.needsMeasurement&&(Oa=!0)})}function w1(){Fa=!0,Rp(),Vp(),Fa=!1}class lu{constructor(t,n,r,i,s,o=!1){this.state="pending",this.isAsync=!1,this.needsMeasurement=!1,this.unresolvedKeyframes=[...t],this.onComplete=n,this.name=r,this.motionValue=i,this.element=s,this.isAsync=o}scheduleResolve(){this.state="scheduled",this.isAsync?(ln.add(this),_a||(_a=!0,$.read(Rp),$.resolveKeyframes(Vp))):(this.readKeyframes(),this.complete())}readKeyframes(){const{unresolvedKeyframes:t,name:n,element:r,motionValue:i}=this;if(t[0]===null){const s=i==null?void 0:i.get(),o=t[t.length-1];if(s!==void 0)t[0]=s;else if(r&&n){const a=r.readValue(n,o);a!=null&&(t[0]=a)}t[0]===void 0&&(t[0]=o),i&&s===void 0&&i.set(t[0])}f1(t)}setFinalKeyframe(){}measureInitialState(){}renderEndStyles(){}measureEndState(){}complete(t=!1){this.state="complete",this.onComplete(this.unresolvedKeyframes,this.finalKeyframe,t),ln.delete(this)}cancel(){this.state==="scheduled"&&(ln.delete(this),this.state="pending")}resume(){this.state==="pending"&&this.scheduleResolve()}}const k1=e=>e.startsWith("--");function S1(e,t,n){k1(t)?e.style.setProperty(t,n):e.style[t]=n}const T1=Yl(()=>window.ScrollTimeline!==void 0),C1={};function P1(e,t){const n=Yl(e);return()=>C1[t]??n()}const Ip=P1(()=>{try{document.createElement("div").animate({opacity:0},{easing:"linear(0, 1)"})}catch{return!1}return!0},"linearEasing"),mr=([e,t,n,r])=>`cubic-bezier(${e}, ${t}, ${n}, ${r})`,Wc={linear:"linear",ease:"ease",easeIn:"ease-in",easeOut:"ease-out",easeInOut:"ease-in-out",circIn:mr([0,.65,.55,1]),circOut:mr([.55,0,1,.45]),backIn:mr([.31,.01,.66,-.59]),backOut:mr([.33,1.53,.69,.99])};function _p(e,t){if(e)return typeof e=="function"?Ip()?Mp(e,t):"ease-out":wp(e)?mr(e):Array.isArray(e)?e.map(n=>_p(n,t)||Wc.easeOut):Wc[e]}function j1(e,t,n,{delay:r=0,duration:i=300,repeat:s=0,repeatType:o="loop",ease:a="easeOut",times:l}={},u=void 0){const c={[t]:n};l&&(c.offset=l);const d=_p(a,i);Array.isArray(d)&&(c.easing=d);const f={delay:r,duration:i,easing:Array.isArray(d)?"linear":d,fill:"both",iterations:s+1,direction:o==="reverse"?"alternate":"normal"};return u&&(f.pseudoElement=u),e.animate(c,f)}function Op(e){return typeof e=="function"&&"applyToOptions"in e}function E1({type:e,...t}){return Op(e)&&Ip()?e.applyToOptions(t):(t.duration??(t.duration=300),t.ease??(t.ease="easeOut"),t)}class N1 extends ou{constructor(t){if(super(),this.finishedTime=null,this.isStopped=!1,!t)return;const{element:n,name:r,keyframes:i,pseudoElement:s,allowFlatten:o=!1,finalKeyframe:a,onComplete:l}=t;this.isPseudoElement=!!s,this.allowFlatten=o,this.options=t,Ql(typeof t.type!="string");const u=E1(t);this.animation=j1(n,r,i,u,s),u.autoplay===!1&&this.animation.pause(),this.animation.onfinish=()=>{if(this.finishedTime=this.time,!s){const c=su(i,this.options,a,this.speed);this.updateMotionValue?this.updateMotionValue(c):S1(n,r,c),this.animation.cancel()}l==null||l(),this.notifyFinished()}}play(){this.isStopped||(this.animation.play(),this.state==="finished"&&this.updateFinished())}pause(){this.animation.pause()}complete(){var t,n;(n=(t=this.animation).finish)==null||n.call(t)}cancel(){try{this.animation.cancel()}catch{}}stop(){if(this.isStopped)return;this.isStopped=!0;const{state:t}=this;t==="idle"||t==="finished"||(this.updateMotionValue?this.updateMotionValue():this.commitStyles(),this.isPseudoElement||this.cancel())}commitStyles(){var t,n;this.isPseudoElement||(n=(t=this.animation).commitStyles)==null||n.call(t)}get duration(){var n,r;const t=((r=(n=this.animation.effect)==null?void 0:n.getComputedTiming)==null?void 0:r.call(n).duration)||0;return Be(Number(t))}get iterationDuration(){const{delay:t=0}=this.options||{};return this.duration+Be(t)}get time(){return Be(Number(this.animation.currentTime)||0)}set time(t){this.finishedTime=null,this.animation.currentTime=at(t)}get speed(){return this.animation.playbackRate}set speed(t){t<0&&(this.finishedTime=null),this.animation.playbackRate=t}get state(){return this.finishedTime!==null?"finished":this.animation.playState}get startTime(){return Number(this.animation.startTime)}set startTime(t){this.animation.startTime=t}attachTimeline({timeline:t,observe:n}){var r;return this.allowFlatten&&((r=this.animation.effect)==null||r.updateTiming({easing:"linear"})),this.animation.onfinish=null,t&&T1()?(this.animation.timeline=t,We):n(this)}}const Fp={anticipate:gp,backInOut:mp,circInOut:vp};function D1(e){return e in Fp}function M1(e){typeof e.ease=="string"&&D1(e.ease)&&(e.ease=Fp[e.ease])}const bc=10;class L1 extends N1{constructor(t){M1(t),Ap(t),super(t),t.startTime&&(this.startTime=t.startTime),this.options=t}updateMotionValue(t){const{motionValue:n,onUpdate:r,onComplete:i,element:s,...o}=this.options;if(!n)return;if(t!==void 0){n.set(t);return}const a=new au({...o,autoplay:!1}),l=at(this.finishedTime??this.time);n.setWithVelocity(a.sample(l-bc).value,a.sample(l).value,bc),a.stop()}}const $c=(e,t)=>t==="zIndex"?!1:!!(typeof e=="number"||Array.isArray(e)||typeof e=="string"&&(Ut.test(e)||e==="0")&&!e.startsWith("url("));function A1(e){const t=e[0];if(e.length===1)return!0;for(let n=0;nObject.hasOwnProperty.call(Element.prototype,"animate"));function _1(e){var c;const{motionValue:t,name:n,repeatDelay:r,repeatType:i,damping:s,type:o}=e;if(!(((c=t==null?void 0:t.owner)==null?void 0:c.current)instanceof HTMLElement))return!1;const{onUpdate:l,transformTemplate:u}=t.owner.getProps();return I1()&&n&&R1.has(n)&&(n!=="transform"||!u)&&!l&&!r&&i!=="mirror"&&s!==0&&o!=="inertia"}const O1=40;class F1 extends ou{constructor({autoplay:t=!0,delay:n=0,type:r="keyframes",repeat:i=0,repeatDelay:s=0,repeatType:o="loop",keyframes:a,name:l,motionValue:u,element:c,...d}){var v;super(),this.stop=()=>{var x,S;this._animation&&(this._animation.stop(),(x=this.stopTimeline)==null||x.call(this)),(S=this.keyframeResolver)==null||S.cancel()},this.createdAt=Pe.now();const f={autoplay:t,delay:n,type:r,repeat:i,repeatDelay:s,repeatType:o,name:l,motionValue:u,element:c,...d},y=(c==null?void 0:c.KeyframeResolver)||lu;this.keyframeResolver=new y(a,(x,S,m)=>this.onKeyframesResolved(x,S,f,!m),l,u,c),(v=this.keyframeResolver)==null||v.scheduleResolve()}onKeyframesResolved(t,n,r,i){this.keyframeResolver=void 0;const{name:s,type:o,velocity:a,delay:l,isHandoff:u,onUpdate:c}=r;this.resolvedAt=Pe.now(),V1(t,s,o,a)||((xt.instantAnimations||!l)&&(c==null||c(su(t,r,n))),t[0]=t[t.length-1],za(r),r.repeat=0);const f={startTime:i?this.resolvedAt?this.resolvedAt-this.createdAt>O1?this.resolvedAt:this.createdAt:this.createdAt:void 0,finalKeyframe:n,...r,keyframes:t},y=!u&&_1(f)?new L1({...f,element:f.motionValue.owner.current}):new au(f);y.finished.then(()=>this.notifyFinished()).catch(We),this.pendingTimeline&&(this.stopTimeline=y.attachTimeline(this.pendingTimeline),this.pendingTimeline=void 0),this._animation=y}get finished(){return this._animation?this.animation.finished:this._finished}then(t,n){return this.finished.finally(t).then(()=>{})}get animation(){var t;return this._animation||((t=this.keyframeResolver)==null||t.resume(),w1()),this._animation}get duration(){return this.animation.duration}get iterationDuration(){return this.animation.iterationDuration}get time(){return this.animation.time}set time(t){this.animation.time=t}get speed(){return this.animation.speed}get state(){return this.animation.state}set speed(t){this.animation.speed=t}get startTime(){return this.animation.startTime}attachTimeline(t){return this._animation?this.stopTimeline=this.animation.attachTimeline(t):this.pendingTimeline=t,()=>this.stop()}play(){this.animation.play()}pause(){this.animation.pause()}complete(){this.animation.complete()}cancel(){var t;this._animation&&this.animation.cancel(),(t=this.keyframeResolver)==null||t.cancel()}}const z1=/^var\(--(?:([\w-]+)|([\w-]+), ?([a-zA-Z\d ()%#.,-]+))\)/u;function B1(e){const t=z1.exec(e);if(!t)return[,];const[,n,r,i]=t;return[`--${n??r}`,i]}function zp(e,t,n=1){const[r,i]=B1(e);if(!r)return;const s=window.getComputedStyle(t).getPropertyValue(r);if(s){const o=s.trim();return ap(o)?parseFloat(o):o}return eu(i)?zp(i,t,n+1):i}function uu(e,t){return(e==null?void 0:e[t])??(e==null?void 0:e.default)??e}const Bp=new Set(["width","height","top","left","right","bottom",...er]),U1={test:e=>e==="auto",parse:e=>e},Up=e=>t=>t.test(e),Wp=[Jn,A,lt,Tt,Ay,Ly,U1],Hc=e=>Wp.find(Up(e));function W1(e){return typeof e=="number"?e===0:e!==null?e==="none"||e==="0"||up(e):!0}const b1=new Set(["brightness","contrast","saturate","opacity"]);function $1(e){const[t,n]=e.slice(0,-1).split("(");if(t==="drop-shadow")return e;const[r]=n.match(tu)||[];if(!r)return e;const i=n.replace(r,"");let s=b1.has(t)?1:0;return r!==n&&(s*=100),t+"("+s+i+")"}const H1=/\b([a-z-]*)\(.*?\)/gu,Ba={...Ut,getAnimatableNone:e=>{const t=e.match(H1);return t?t.map($1).join(" "):e}},Kc={...Jn,transform:Math.round},K1={rotate:Tt,rotateX:Tt,rotateY:Tt,rotateZ:Tt,scale:Ni,scaleX:Ni,scaleY:Ni,scaleZ:Ni,skew:Tt,skewX:Tt,skewY:Tt,distance:A,translateX:A,translateY:A,translateZ:A,x:A,y:A,z:A,perspective:A,transformPerspective:A,opacity:Gr,originX:Vc,originY:Vc,originZ:A},cu={borderWidth:A,borderTopWidth:A,borderRightWidth:A,borderBottomWidth:A,borderLeftWidth:A,borderRadius:A,radius:A,borderTopLeftRadius:A,borderTopRightRadius:A,borderBottomRightRadius:A,borderBottomLeftRadius:A,width:A,maxWidth:A,height:A,maxHeight:A,top:A,right:A,bottom:A,left:A,padding:A,paddingTop:A,paddingRight:A,paddingBottom:A,paddingLeft:A,margin:A,marginTop:A,marginRight:A,marginBottom:A,marginLeft:A,backgroundPositionX:A,backgroundPositionY:A,...K1,zIndex:Kc,fillOpacity:Gr,strokeOpacity:Gr,numOctaves:Kc},G1={...cu,color:ee,backgroundColor:ee,outlineColor:ee,fill:ee,stroke:ee,borderColor:ee,borderTopColor:ee,borderRightColor:ee,borderBottomColor:ee,borderLeftColor:ee,filter:Ba,WebkitFilter:Ba},bp=e=>G1[e];function $p(e,t){let n=bp(e);return n!==Ba&&(n=Ut),n.getAnimatableNone?n.getAnimatableNone(t):void 0}const Q1=new Set(["auto","none","0"]);function Y1(e,t,n){let r=0,i;for(;r{t.getValue(l).set(u)}),this.resolveNoneKeyframes()}}function Z1(e,t,n){if(e instanceof EventTarget)return[e];if(typeof e=="string"){let r=document;const i=(n==null?void 0:n[e])??r.querySelectorAll(e);return i?Array.from(i):[]}return Array.from(e)}const Hp=(e,t)=>t&&typeof e=="number"?t.transform(e):e;function Kp(e){return lp(e)&&"offsetHeight"in e}const Gc=30,q1=e=>!isNaN(parseFloat(e));class J1{constructor(t,n={}){this.canTrackVelocity=null,this.events={},this.updateAndNotify=r=>{var s;const i=Pe.now();if(this.updatedAt!==i&&this.setPrevFrameValue(),this.prev=this.current,this.setCurrent(r),this.current!==this.prev&&((s=this.events.change)==null||s.notify(this.current),this.dependents))for(const o of this.dependents)o.dirty()},this.hasAnimated=!1,this.setCurrent(t),this.owner=n.owner}setCurrent(t){this.current=t,this.updatedAt=Pe.now(),this.canTrackVelocity===null&&t!==void 0&&(this.canTrackVelocity=q1(this.current))}setPrevFrameValue(t=this.current){this.prevFrameValue=t,this.prevUpdatedAt=this.updatedAt}onChange(t){return this.on("change",t)}on(t,n){this.events[t]||(this.events[t]=new Xl);const r=this.events[t].add(n);return t==="change"?()=>{r(),$.read(()=>{this.events.change.getSize()||this.stop()})}:r}clearListeners(){for(const t in this.events)this.events[t].clear()}attach(t,n){this.passiveEffect=t,this.stopPassiveEffect=n}set(t){this.passiveEffect?this.passiveEffect(t,this.updateAndNotify):this.updateAndNotify(t)}setWithVelocity(t,n,r){this.set(n),this.prev=void 0,this.prevFrameValue=t,this.prevUpdatedAt=this.updatedAt-r}jump(t,n=!0){this.updateAndNotify(t),this.prev=t,this.prevUpdatedAt=this.prevFrameValue=void 0,n&&this.stop(),this.stopPassiveEffect&&this.stopPassiveEffect()}dirty(){var t;(t=this.events.change)==null||t.notify(this.current)}addDependent(t){this.dependents||(this.dependents=new Set),this.dependents.add(t)}removeDependent(t){this.dependents&&this.dependents.delete(t)}get(){return this.current}getPrevious(){return this.prev}getVelocity(){const t=Pe.now();if(!this.canTrackVelocity||this.prevFrameValue===void 0||t-this.updatedAt>Gc)return 0;const n=Math.min(this.updatedAt-this.prevUpdatedAt,Gc);return cp(parseFloat(this.current)-parseFloat(this.prevFrameValue),n)}start(t){return this.stop(),new Promise(n=>{this.hasAnimated=!0,this.animation=t(n),this.events.animationStart&&this.events.animationStart.notify()}).then(()=>{this.events.animationComplete&&this.events.animationComplete.notify(),this.clearAnimation()})}stop(){this.animation&&(this.animation.stop(),this.events.animationCancel&&this.events.animationCancel.notify()),this.clearAnimation()}isAnimating(){return!!this.animation}clearAnimation(){delete this.animation}destroy(){var t,n;(t=this.dependents)==null||t.clear(),(n=this.events.destroy)==null||n.notify(),this.clearListeners(),this.stop(),this.stopPassiveEffect&&this.stopPassiveEffect()}}function Qn(e,t){return new J1(e,t)}const{schedule:du}=kp(queueMicrotask,!1),Ye={x:!1,y:!1};function Gp(){return Ye.x||Ye.y}function ev(e){return e==="x"||e==="y"?Ye[e]?null:(Ye[e]=!0,()=>{Ye[e]=!1}):Ye.x||Ye.y?null:(Ye.x=Ye.y=!0,()=>{Ye.x=Ye.y=!1})}function Qp(e,t){const n=Z1(e),r=new AbortController,i={passive:!0,...t,signal:r.signal};return[n,i,()=>r.abort()]}function Qc(e){return!(e.pointerType==="touch"||Gp())}function tv(e,t,n={}){const[r,i,s]=Qp(e,n),o=a=>{if(!Qc(a))return;const{target:l}=a,u=t(l,a);if(typeof u!="function"||!l)return;const c=d=>{Qc(d)&&(u(d),l.removeEventListener("pointerleave",c))};l.addEventListener("pointerleave",c,i)};return r.forEach(a=>{a.addEventListener("pointerenter",o,i)}),s}const Yp=(e,t)=>t?e===t?!0:Yp(e,t.parentElement):!1,fu=e=>e.pointerType==="mouse"?typeof e.button!="number"||e.button<=0:e.isPrimary!==!1,nv=new Set(["BUTTON","INPUT","SELECT","TEXTAREA","A"]);function rv(e){return nv.has(e.tagName)||e.tabIndex!==-1}const $i=new WeakSet;function Yc(e){return t=>{t.key==="Enter"&&e(t)}}function To(e,t){e.dispatchEvent(new PointerEvent("pointer"+t,{isPrimary:!0,bubbles:!0}))}const iv=(e,t)=>{const n=e.currentTarget;if(!n)return;const r=Yc(()=>{if($i.has(n))return;To(n,"down");const i=Yc(()=>{To(n,"up")}),s=()=>To(n,"cancel");n.addEventListener("keyup",i,t),n.addEventListener("blur",s,t)});n.addEventListener("keydown",r,t),n.addEventListener("blur",()=>n.removeEventListener("keydown",r),t)};function Xc(e){return fu(e)&&!Gp()}function sv(e,t,n={}){const[r,i,s]=Qp(e,n),o=a=>{const l=a.currentTarget;if(!Xc(a))return;$i.add(l);const u=t(l,a),c=(y,v)=>{window.removeEventListener("pointerup",d),window.removeEventListener("pointercancel",f),$i.has(l)&&$i.delete(l),Xc(y)&&typeof u=="function"&&u(y,{success:v})},d=y=>{c(y,l===window||l===document||n.useGlobalTarget||Yp(l,y.target))},f=y=>{c(y,!1)};window.addEventListener("pointerup",d,i),window.addEventListener("pointercancel",f,i)};return r.forEach(a=>{(n.useGlobalTarget?window:a).addEventListener("pointerdown",o,i),Kp(a)&&(a.addEventListener("focus",u=>iv(u,i)),!rv(a)&&!a.hasAttribute("tabindex")&&(a.tabIndex=0))}),s}function Xp(e){return lp(e)&&"ownerSVGElement"in e}function ov(e){return Xp(e)&&e.tagName==="svg"}const ge=e=>!!(e&&e.getVelocity),av=[...Wp,ee,Ut],lv=e=>av.find(Up(e)),hu=N.createContext({transformPagePoint:e=>e,isStatic:!1,reducedMotion:"never"});function Zc(e,t){if(typeof e=="function")return e(t);e!=null&&(e.current=t)}function uv(...e){return t=>{let n=!1;const r=e.map(i=>{const s=Zc(i,t);return!n&&typeof s=="function"&&(n=!0),s});if(n)return()=>{for(let i=0;i{const{width:u,height:c,top:d,left:f,right:y}=o.current;if(t||!s.current||!u||!c)return;const v=n==="left"?`left: ${f}`:`right: ${y}`;s.current.dataset.motionPopId=i;const x=document.createElement("style");a&&(x.nonce=a);const S=r??document.head;return S.appendChild(x),x.sheet&&x.sheet.insertRule(` - [data-motion-pop-id="${i}"] { - position: absolute !important; - width: ${u}px !important; - height: ${c}px !important; - ${v}px !important; - top: ${d}px !important; - } - `),()=>{S.contains(x)&&S.removeChild(x)}},[t]),h.jsx(dv,{isPresent:t,childRef:s,sizeRef:o,children:N.cloneElement(e,{ref:l})})}const hv=({children:e,initial:t,isPresent:n,onExitComplete:r,custom:i,presenceAffectsLayout:s,mode:o,anchorX:a,root:l})=>{const u=$l(pv),c=N.useId();let d=!0,f=N.useMemo(()=>(d=!1,{id:c,initial:t,isPresent:n,custom:i,onExitComplete:y=>{u.set(y,!0);for(const v of u.values())if(!v)return;r&&r()},register:y=>(u.set(y,!1),()=>u.delete(y))}),[n,u,r]);return s&&d&&(f={...f}),N.useMemo(()=>{u.forEach((y,v)=>u.set(v,!1))},[n]),N.useEffect(()=>{!n&&!u.size&&r&&r()},[n]),o==="popLayout"&&(e=h.jsx(fv,{isPresent:n,anchorX:a,root:l,children:e})),h.jsx(zs.Provider,{value:f,children:e})};function pv(){return new Map}function Zp(e=!0){const t=N.useContext(zs);if(t===null)return[!0,null];const{isPresent:n,onExitComplete:r,register:i}=t,s=N.useId();N.useEffect(()=>{if(e)return i(s)},[e]);const o=N.useCallback(()=>e&&r&&r(s),[s,r,e]);return!n&&r?[!1,o]:[!0]}const Di=e=>e.key||"";function qc(e){const t=[];return N.Children.forEach(e,n=>{N.isValidElement(n)&&t.push(n)}),t}const Jc=({children:e,custom:t,initial:n=!0,onExitComplete:r,presenceAffectsLayout:i=!0,mode:s="sync",propagate:o=!1,anchorX:a="left",root:l})=>{const[u,c]=Zp(o),d=N.useMemo(()=>qc(e),[e]),f=o&&!u?[]:d.map(Di),y=N.useRef(!0),v=N.useRef(d),x=$l(()=>new Map),[S,m]=N.useState(d),[p,g]=N.useState(d);op(()=>{y.current=!1,v.current=d;for(let T=0;T{const P=Di(T),C=o&&!u?!1:d===p||f.includes(P),R=()=>{if(x.has(P))x.set(P,!0);else return;let M=!0;x.forEach(X=>{X||(M=!1)}),M&&(k==null||k(),g(v.current),o&&(c==null||c()),r&&r())};return h.jsx(hv,{isPresent:C,initial:!y.current||n?void 0:!1,custom:t,presenceAffectsLayout:i,mode:s,root:l,onExitComplete:C?void 0:R,anchorX:a,children:T},P)})})},qp=N.createContext({strict:!1}),ed={animation:["animate","variants","whileHover","whileTap","exit","whileInView","whileFocus","whileDrag"],exit:["exit"],drag:["drag","dragControls"],focus:["whileFocus"],hover:["whileHover","onHoverStart","onHoverEnd"],tap:["whileTap","onTap","onTapStart","onTapCancel"],pan:["onPan","onPanStart","onPanSessionStart","onPanEnd"],inView:["whileInView","onViewportEnter","onViewportLeave"],layout:["layout","layoutId"]},Yn={};for(const e in ed)Yn[e]={isEnabled:t=>ed[e].some(n=>!!t[n])};function mv(e){for(const t in e)Yn[t]={...Yn[t],...e[t]}}const gv=new Set(["animate","exit","variants","initial","style","values","variants","transition","transformTemplate","custom","inherit","onBeforeLayoutMeasure","onAnimationStart","onAnimationComplete","onUpdate","onDragStart","onDrag","onDragEnd","onMeasureDragConstraints","onDirectionLock","onDragTransitionEnd","_dragX","_dragY","onHoverStart","onHoverEnd","onViewportEnter","onViewportLeave","globalTapTarget","ignoreStrict","viewport"]);function ws(e){return e.startsWith("while")||e.startsWith("drag")&&e!=="draggable"||e.startsWith("layout")||e.startsWith("onTap")||e.startsWith("onPan")||e.startsWith("onLayout")||gv.has(e)}let Jp=e=>!ws(e);function yv(e){typeof e=="function"&&(Jp=t=>t.startsWith("on")?!ws(t):e(t))}try{yv(require("@emotion/is-prop-valid").default)}catch{}function vv(e,t,n){const r={};for(const i in e)i==="values"&&typeof e.values=="object"||(Jp(i)||n===!0&&ws(i)||!t&&!ws(i)||e.draggable&&i.startsWith("onDrag"))&&(r[i]=e[i]);return r}const Bs=N.createContext({});function Us(e){return e!==null&&typeof e=="object"&&typeof e.start=="function"}function Yr(e){return typeof e=="string"||Array.isArray(e)}const pu=["animate","whileInView","whileFocus","whileHover","whileTap","whileDrag","exit"],mu=["initial",...pu];function Ws(e){return Us(e.animate)||mu.some(t=>Yr(e[t]))}function em(e){return!!(Ws(e)||e.variants)}function xv(e,t){if(Ws(e)){const{initial:n,animate:r}=e;return{initial:n===!1||Yr(n)?n:void 0,animate:Yr(r)?r:void 0}}return e.inherit!==!1?t:{}}function wv(e){const{initial:t,animate:n}=xv(e,N.useContext(Bs));return N.useMemo(()=>({initial:t,animate:n}),[td(t),td(n)])}function td(e){return Array.isArray(e)?e.join(" "):e}const Xr={};function kv(e){for(const t in e)Xr[t]=e[t],Jl(t)&&(Xr[t].isCSSVariable=!0)}function tm(e,{layout:t,layoutId:n}){return tr.has(e)||e.startsWith("origin")||(t||n!==void 0)&&(!!Xr[e]||e==="opacity")}const Sv={x:"translateX",y:"translateY",z:"translateZ",transformPerspective:"perspective"},Tv=er.length;function Cv(e,t,n){let r="",i=!0;for(let s=0;s({style:{},transform:{},transformOrigin:{},vars:{}});function nm(e,t,n){for(const r in t)!ge(t[r])&&!tm(r,n)&&(e[r]=t[r])}function Pv({transformTemplate:e},t){return N.useMemo(()=>{const n=yu();return gu(n,t,e),Object.assign({},n.vars,n.style)},[t])}function jv(e,t){const n=e.style||{},r={};return nm(r,n,e),Object.assign(r,Pv(e,t)),r}function Ev(e,t){const n={},r=jv(e,t);return e.drag&&e.dragListener!==!1&&(n.draggable=!1,r.userSelect=r.WebkitUserSelect=r.WebkitTouchCallout="none",r.touchAction=e.drag===!0?"none":`pan-${e.drag==="x"?"y":"x"}`),e.tabIndex===void 0&&(e.onTap||e.onTapStart||e.whileTap)&&(n.tabIndex=0),n.style=r,n}const Nv={offset:"stroke-dashoffset",array:"stroke-dasharray"},Dv={offset:"strokeDashoffset",array:"strokeDasharray"};function Mv(e,t,n=1,r=0,i=!0){e.pathLength=1;const s=i?Nv:Dv;e[s.offset]=A.transform(-r);const o=A.transform(t),a=A.transform(n);e[s.array]=`${o} ${a}`}function rm(e,{attrX:t,attrY:n,attrScale:r,pathLength:i,pathSpacing:s=1,pathOffset:o=0,...a},l,u,c){if(gu(e,a,u),l){e.style.viewBox&&(e.attrs.viewBox=e.style.viewBox);return}e.attrs=e.style,e.style={};const{attrs:d,style:f}=e;d.transform&&(f.transform=d.transform,delete d.transform),(f.transform||d.transformOrigin)&&(f.transformOrigin=d.transformOrigin??"50% 50%",delete d.transformOrigin),f.transform&&(f.transformBox=(c==null?void 0:c.transformBox)??"fill-box",delete d.transformBox),t!==void 0&&(d.x=t),n!==void 0&&(d.y=n),r!==void 0&&(d.scale=r),i!==void 0&&Mv(d,i,s,o,!1)}const im=()=>({...yu(),attrs:{}}),sm=e=>typeof e=="string"&&e.toLowerCase()==="svg";function Lv(e,t,n,r){const i=N.useMemo(()=>{const s=im();return rm(s,t,sm(r),e.transformTemplate,e.style),{...s.attrs,style:{...s.style}}},[t]);if(e.style){const s={};nm(s,e.style,e),i.style={...s,...i.style}}return i}const Av=["animate","circle","defs","desc","ellipse","g","image","line","filter","marker","mask","metadata","path","pattern","polygon","polyline","rect","stop","switch","symbol","svg","text","tspan","use","view"];function vu(e){return typeof e!="string"||e.includes("-")?!1:!!(Av.indexOf(e)>-1||/[A-Z]/u.test(e))}function Vv(e,t,n,{latestValues:r},i,s=!1){const a=(vu(e)?Lv:Ev)(t,r,i,e),l=vv(t,typeof e=="string",s),u=e!==N.Fragment?{...l,...a,ref:n}:{},{children:c}=t,d=N.useMemo(()=>ge(c)?c.get():c,[c]);return N.createElement(e,{...u,children:d})}function nd(e){const t=[{},{}];return e==null||e.values.forEach((n,r)=>{t[0][r]=n.get(),t[1][r]=n.getVelocity()}),t}function xu(e,t,n,r){if(typeof t=="function"){const[i,s]=nd(r);t=t(n!==void 0?n:e.custom,i,s)}if(typeof t=="string"&&(t=e.variants&&e.variants[t]),typeof t=="function"){const[i,s]=nd(r);t=t(n!==void 0?n:e.custom,i,s)}return t}function Hi(e){return ge(e)?e.get():e}function Rv({scrapeMotionValuesFromProps:e,createRenderState:t},n,r,i){return{latestValues:Iv(n,r,i,e),renderState:t()}}function Iv(e,t,n,r){const i={},s=r(e,{});for(const f in s)i[f]=Hi(s[f]);let{initial:o,animate:a}=e;const l=Ws(e),u=em(e);t&&u&&!l&&e.inherit!==!1&&(o===void 0&&(o=t.initial),a===void 0&&(a=t.animate));let c=n?n.initial===!1:!1;c=c||o===!1;const d=c?a:o;if(d&&typeof d!="boolean"&&!Us(d)){const f=Array.isArray(d)?d:[d];for(let y=0;y(t,n)=>{const r=N.useContext(Bs),i=N.useContext(zs),s=()=>Rv(e,t,r,i);return n?s():$l(s)};function wu(e,t,n){var s;const{style:r}=e,i={};for(const o in r)(ge(r[o])||t.style&&ge(t.style[o])||tm(o,e)||((s=n==null?void 0:n.getValue(o))==null?void 0:s.liveStyle)!==void 0)&&(i[o]=r[o]);return i}const _v=om({scrapeMotionValuesFromProps:wu,createRenderState:yu});function am(e,t,n){const r=wu(e,t,n);for(const i in e)if(ge(e[i])||ge(t[i])){const s=er.indexOf(i)!==-1?"attr"+i.charAt(0).toUpperCase()+i.substring(1):i;r[s]=e[i]}return r}const Ov=om({scrapeMotionValuesFromProps:am,createRenderState:im}),Fv=Symbol.for("motionComponentSymbol");function Mn(e){return e&&typeof e=="object"&&Object.prototype.hasOwnProperty.call(e,"current")}function zv(e,t,n){return N.useCallback(r=>{r&&e.onMount&&e.onMount(r),t&&(r?t.mount(r):t.unmount()),n&&(typeof n=="function"?n(r):Mn(n)&&(n.current=r))},[t])}const ku=e=>e.replace(/([a-z])([A-Z])/gu,"$1-$2").toLowerCase(),Bv="framerAppearId",lm="data-"+ku(Bv),um=N.createContext({});function Uv(e,t,n,r,i){var x,S;const{visualElement:s}=N.useContext(Bs),o=N.useContext(qp),a=N.useContext(zs),l=N.useContext(hu).reducedMotion,u=N.useRef(null);r=r||o.renderer,!u.current&&r&&(u.current=r(e,{visualState:t,parent:s,props:n,presenceContext:a,blockInitialAnimation:a?a.initial===!1:!1,reducedMotionConfig:l}));const c=u.current,d=N.useContext(um);c&&!c.projection&&i&&(c.type==="html"||c.type==="svg")&&Wv(u.current,n,i,d);const f=N.useRef(!1);N.useInsertionEffect(()=>{c&&f.current&&c.update(n,a)});const y=n[lm],v=N.useRef(!!y&&!((x=window.MotionHandoffIsComplete)!=null&&x.call(window,y))&&((S=window.MotionHasOptimisedAnimation)==null?void 0:S.call(window,y)));return op(()=>{c&&(f.current=!0,window.MotionIsMounted=!0,c.updateFeatures(),c.scheduleRenderMicrotask(),v.current&&c.animationState&&c.animationState.animateChanges())}),N.useEffect(()=>{c&&(!v.current&&c.animationState&&c.animationState.animateChanges(),v.current&&(queueMicrotask(()=>{var m;(m=window.MotionHandoffMarkAsComplete)==null||m.call(window,y)}),v.current=!1),c.enteringChildren=void 0)}),c}function Wv(e,t,n,r){const{layoutId:i,layout:s,drag:o,dragConstraints:a,layoutScroll:l,layoutRoot:u,layoutCrossfade:c}=t;e.projection=new n(e.latestValues,t["data-framer-portal-id"]?void 0:cm(e.parent)),e.projection.setOptions({layoutId:i,layout:s,alwaysMeasureLayout:!!o||a&&Mn(a),visualElement:e,animationType:typeof s=="string"?s:"both",initialPromotionConfig:r,crossfade:c,layoutScroll:l,layoutRoot:u})}function cm(e){if(e)return e.options.allowProjection!==!1?e.projection:cm(e.parent)}function Co(e,{forwardMotionProps:t=!1}={},n,r){n&&mv(n);const i=vu(e)?Ov:_v;function s(a,l){let u;const c={...N.useContext(hu),...a,layoutId:bv(a)},{isStatic:d}=c,f=wv(a),y=i(a,d);if(!d&&Hl){$v();const v=Hv(c);u=v.MeasureLayout,f.visualElement=Uv(e,y,c,r,v.ProjectionNode)}return h.jsxs(Bs.Provider,{value:f,children:[u&&f.visualElement?h.jsx(u,{visualElement:f.visualElement,...c}):null,Vv(e,a,zv(y,f.visualElement,l),y,d,t)]})}s.displayName=`motion.${typeof e=="string"?e:`create(${e.displayName??e.name??""})`}`;const o=N.forwardRef(s);return o[Fv]=e,o}function bv({layoutId:e}){const t=N.useContext(bl).id;return t&&e!==void 0?t+"-"+e:e}function $v(e,t){N.useContext(qp).strict}function Hv(e){const{drag:t,layout:n}=Yn;if(!t&&!n)return{};const r={...t,...n};return{MeasureLayout:t!=null&&t.isEnabled(e)||n!=null&&n.isEnabled(e)?r.MeasureLayout:void 0,ProjectionNode:r.ProjectionNode}}function Kv(e,t){if(typeof Proxy>"u")return Co;const n=new Map,r=(s,o)=>Co(s,o,e,t),i=(s,o)=>r(s,o);return new Proxy(i,{get:(s,o)=>o==="create"?r:(n.has(o)||n.set(o,Co(o,void 0,e,t)),n.get(o))})}function dm({top:e,left:t,right:n,bottom:r}){return{x:{min:t,max:n},y:{min:e,max:r}}}function Gv({x:e,y:t}){return{top:t.min,right:e.max,bottom:t.max,left:e.min}}function Qv(e,t){if(!t)return e;const n=t({x:e.left,y:e.top}),r=t({x:e.right,y:e.bottom});return{top:n.y,left:n.x,bottom:r.y,right:r.x}}function Po(e){return e===void 0||e===1}function Ua({scale:e,scaleX:t,scaleY:n}){return!Po(e)||!Po(t)||!Po(n)}function qt(e){return Ua(e)||fm(e)||e.z||e.rotate||e.rotateX||e.rotateY||e.skewX||e.skewY}function fm(e){return rd(e.x)||rd(e.y)}function rd(e){return e&&e!=="0%"}function ks(e,t,n){const r=e-n,i=t*r;return n+i}function id(e,t,n,r,i){return i!==void 0&&(e=ks(e,i,r)),ks(e,n,r)+t}function Wa(e,t=0,n=1,r,i){e.min=id(e.min,t,n,r,i),e.max=id(e.max,t,n,r,i)}function hm(e,{x:t,y:n}){Wa(e.x,t.translate,t.scale,t.originPoint),Wa(e.y,n.translate,n.scale,n.originPoint)}const sd=.999999999999,od=1.0000000000001;function Yv(e,t,n,r=!1){const i=n.length;if(!i)return;t.x=t.y=1;let s,o;for(let a=0;asd&&(t.x=1),t.ysd&&(t.y=1)}function Ln(e,t){e.min=e.min+t,e.max=e.max+t}function ad(e,t,n,r,i=.5){const s=G(e.min,e.max,i);Wa(e,t,n,s,r)}function An(e,t){ad(e.x,t.x,t.scaleX,t.scale,t.originX),ad(e.y,t.y,t.scaleY,t.scale,t.originY)}function pm(e,t){return dm(Qv(e.getBoundingClientRect(),t))}function Xv(e,t,n){const r=pm(e,n),{scroll:i}=t;return i&&(Ln(r.x,i.offset.x),Ln(r.y,i.offset.y)),r}const ld=()=>({translate:0,scale:1,origin:0,originPoint:0}),Vn=()=>({x:ld(),y:ld()}),ud=()=>({min:0,max:0}),ne=()=>({x:ud(),y:ud()}),ba={current:null},mm={current:!1};function Zv(){if(mm.current=!0,!!Hl)if(window.matchMedia){const e=window.matchMedia("(prefers-reduced-motion)"),t=()=>ba.current=e.matches;e.addEventListener("change",t),t()}else ba.current=!1}const qv=new WeakMap;function Jv(e,t,n){for(const r in t){const i=t[r],s=n[r];if(ge(i))e.addValue(r,i);else if(ge(s))e.addValue(r,Qn(i,{owner:e}));else if(s!==i)if(e.hasValue(r)){const o=e.getValue(r);o.liveStyle===!0?o.jump(i):o.hasAnimated||o.set(i)}else{const o=e.getStaticValue(r);e.addValue(r,Qn(o!==void 0?o:i,{owner:e}))}}for(const r in n)t[r]===void 0&&e.removeValue(r);return t}const cd=["AnimationStart","AnimationComplete","Update","BeforeLayoutMeasure","LayoutMeasure","LayoutAnimationStart","LayoutAnimationComplete"];class ex{scrapeMotionValuesFromProps(t,n,r){return{}}constructor({parent:t,props:n,presenceContext:r,reducedMotionConfig:i,blockInitialAnimation:s,visualState:o},a={}){this.current=null,this.children=new Set,this.isVariantNode=!1,this.isControllingVariants=!1,this.shouldReduceMotion=null,this.values=new Map,this.KeyframeResolver=lu,this.features={},this.valueSubscriptions=new Map,this.prevMotionValues={},this.events={},this.propEventSubscriptions={},this.notifyUpdate=()=>this.notify("Update",this.latestValues),this.render=()=>{this.current&&(this.triggerBuild(),this.renderInstance(this.current,this.renderState,this.props.style,this.projection))},this.renderScheduledAt=0,this.scheduleRender=()=>{const f=Pe.now();this.renderScheduledAtthis.bindToMotionValue(i,r)),mm.current||Zv(),this.shouldReduceMotion=this.reducedMotionConfig==="never"?!1:this.reducedMotionConfig==="always"?!0:ba.current,(n=this.parent)==null||n.addChild(this),this.update(this.props,this.presenceContext)}unmount(){var t;this.projection&&this.projection.unmount(),Bt(this.notifyUpdate),Bt(this.render),this.valueSubscriptions.forEach(n=>n()),this.valueSubscriptions.clear(),this.removeFromVariantTree&&this.removeFromVariantTree(),(t=this.parent)==null||t.removeChild(this);for(const n in this.events)this.events[n].clear();for(const n in this.features){const r=this.features[n];r&&(r.unmount(),r.isMounted=!1)}this.current=null}addChild(t){this.children.add(t),this.enteringChildren??(this.enteringChildren=new Set),this.enteringChildren.add(t)}removeChild(t){this.children.delete(t),this.enteringChildren&&this.enteringChildren.delete(t)}bindToMotionValue(t,n){this.valueSubscriptions.has(t)&&this.valueSubscriptions.get(t)();const r=tr.has(t);r&&this.onBindTransform&&this.onBindTransform();const i=n.on("change",o=>{this.latestValues[t]=o,this.props.onUpdate&&$.preRender(this.notifyUpdate),r&&this.projection&&(this.projection.isTransformDirty=!0),this.scheduleRender()});let s;window.MotionCheckAppearSync&&(s=window.MotionCheckAppearSync(this,t,n)),this.valueSubscriptions.set(t,()=>{i(),s&&s(),n.owner&&n.stop()})}sortNodePosition(t){return!this.current||!this.sortInstanceNodePosition||this.type!==t.type?0:this.sortInstanceNodePosition(this.current,t.current)}updateFeatures(){let t="animation";for(t in Yn){const n=Yn[t];if(!n)continue;const{isEnabled:r,Feature:i}=n;if(!this.features[t]&&i&&r(this.props)&&(this.features[t]=new i(this)),this.features[t]){const s=this.features[t];s.isMounted?s.update():(s.mount(),s.isMounted=!0)}}}triggerBuild(){this.build(this.renderState,this.latestValues,this.props)}measureViewportBox(){return this.current?this.measureInstanceViewportBox(this.current,this.props):ne()}getStaticValue(t){return this.latestValues[t]}setStaticValue(t,n){this.latestValues[t]=n}update(t,n){(t.transformTemplate||this.props.transformTemplate)&&this.scheduleRender(),this.prevProps=this.props,this.props=t,this.prevPresenceContext=this.presenceContext,this.presenceContext=n;for(let r=0;rn.variantChildren.delete(t)}addValue(t,n){const r=this.values.get(t);n!==r&&(r&&this.removeValue(t),this.bindToMotionValue(t,n),this.values.set(t,n),this.latestValues[t]=n.get())}removeValue(t){this.values.delete(t);const n=this.valueSubscriptions.get(t);n&&(n(),this.valueSubscriptions.delete(t)),delete this.latestValues[t],this.removeValueFromRenderState(t,this.renderState)}hasValue(t){return this.values.has(t)}getValue(t,n){if(this.props.values&&this.props.values[t])return this.props.values[t];let r=this.values.get(t);return r===void 0&&n!==void 0&&(r=Qn(n===null?void 0:n,{owner:this}),this.addValue(t,r)),r}readValue(t,n){let r=this.latestValues[t]!==void 0||!this.current?this.latestValues[t]:this.getBaseTargetFromProps(this.props,t)??this.readValueFromInstance(this.current,t,this.options);return r!=null&&(typeof r=="string"&&(ap(r)||up(r))?r=parseFloat(r):!lv(r)&&Ut.test(n)&&(r=$p(t,n)),this.setBaseTarget(t,ge(r)?r.get():r)),ge(r)?r.get():r}setBaseTarget(t,n){this.baseTarget[t]=n}getBaseTarget(t){var s;const{initial:n}=this.props;let r;if(typeof n=="string"||typeof n=="object"){const o=xu(this.props,n,(s=this.presenceContext)==null?void 0:s.custom);o&&(r=o[t])}if(n&&r!==void 0)return r;const i=this.getBaseTargetFromProps(this.props,t);return i!==void 0&&!ge(i)?i:this.initialValues[t]!==void 0&&r===void 0?void 0:this.baseTarget[t]}on(t,n){return this.events[t]||(this.events[t]=new Xl),this.events[t].add(n)}notify(t,...n){this.events[t]&&this.events[t].notify(...n)}scheduleRenderMicrotask(){du.render(this.render)}}class gm extends ex{constructor(){super(...arguments),this.KeyframeResolver=X1}sortInstanceNodePosition(t,n){return t.compareDocumentPosition(n)&2?1:-1}getBaseTargetFromProps(t,n){return t.style?t.style[n]:void 0}removeValueFromRenderState(t,{vars:n,style:r}){delete n[t],delete r[t]}handleChildMotionValue(){this.childSubscription&&(this.childSubscription(),delete this.childSubscription);const{children:t}=this.props;ge(t)&&(this.childSubscription=t.on("change",n=>{this.current&&(this.current.textContent=`${n}`)}))}}function ym(e,{style:t,vars:n},r,i){const s=e.style;let o;for(o in t)s[o]=t[o];i==null||i.applyProjectionStyles(s,r);for(o in n)s.setProperty(o,n[o])}function tx(e){return window.getComputedStyle(e)}class nx extends gm{constructor(){super(...arguments),this.type="html",this.renderInstance=ym}readValueFromInstance(t,n){var r;if(tr.has(n))return(r=this.projection)!=null&&r.isProjecting?Ra(n):m1(t,n);{const i=tx(t),s=(Jl(n)?i.getPropertyValue(n):i[n])||0;return typeof s=="string"?s.trim():s}}measureInstanceViewportBox(t,{transformPagePoint:n}){return pm(t,n)}build(t,n,r){gu(t,n,r.transformTemplate)}scrapeMotionValuesFromProps(t,n,r){return wu(t,n,r)}}const vm=new Set(["baseFrequency","diffuseConstant","kernelMatrix","kernelUnitLength","keySplines","keyTimes","limitingConeAngle","markerHeight","markerWidth","numOctaves","targetX","targetY","surfaceScale","specularConstant","specularExponent","stdDeviation","tableValues","viewBox","gradientTransform","pathLength","startOffset","textLength","lengthAdjust"]);function rx(e,t,n,r){ym(e,t,void 0,r);for(const i in t.attrs)e.setAttribute(vm.has(i)?i:ku(i),t.attrs[i])}class ix extends gm{constructor(){super(...arguments),this.type="svg",this.isSVGTag=!1,this.measureInstanceViewportBox=ne}getBaseTargetFromProps(t,n){return t[n]}readValueFromInstance(t,n){if(tr.has(n)){const r=bp(n);return r&&r.default||0}return n=vm.has(n)?n:ku(n),t.getAttribute(n)}scrapeMotionValuesFromProps(t,n,r){return am(t,n,r)}build(t,n,r){rm(t,n,this.isSVGTag,r.transformTemplate,r.style)}renderInstance(t,n,r,i){rx(t,n,r,i)}mount(t){this.isSVGTag=sm(t.tagName),super.mount(t)}}const sx=(e,t)=>vu(e)?new ix(t):new nx(t,{allowProjection:e!==N.Fragment});function Bn(e,t,n){const r=e.getProps();return xu(r,t,n!==void 0?n:r.custom,e)}const $a=e=>Array.isArray(e);function ox(e,t,n){e.hasValue(t)?e.getValue(t).set(n):e.addValue(t,Qn(n))}function ax(e){return $a(e)?e[e.length-1]||0:e}function lx(e,t){const n=Bn(e,t);let{transitionEnd:r={},transition:i={},...s}=n||{};s={...s,...r};for(const o in s){const a=ax(s[o]);ox(e,o,a)}}function ux(e){return!!(ge(e)&&e.add)}function Ha(e,t){const n=e.getValue("willChange");if(ux(n))return n.add(t);if(!n&&xt.WillChange){const r=new xt.WillChange("auto");e.addValue("willChange",r),r.add(t)}}function xm(e){return e.props[lm]}const cx=e=>e!==null;function dx(e,{repeat:t,repeatType:n="loop"},r){const i=e.filter(cx),s=t&&n!=="loop"&&t%2===1?0:i.length-1;return i[s]}const fx={type:"spring",stiffness:500,damping:25,restSpeed:10},hx=e=>({type:"spring",stiffness:550,damping:e===0?2*Math.sqrt(550):30,restSpeed:10}),px={type:"keyframes",duration:.8},mx={type:"keyframes",ease:[.25,.1,.35,1],duration:.3},gx=(e,{keyframes:t})=>t.length>2?px:tr.has(e)?e.startsWith("scale")?hx(t[1]):fx:mx;function yx({when:e,delay:t,delayChildren:n,staggerChildren:r,staggerDirection:i,repeat:s,repeatType:o,repeatDelay:a,from:l,elapsed:u,...c}){return!!Object.keys(c).length}const Su=(e,t,n,r={},i,s)=>o=>{const a=uu(r,e)||{},l=a.delay||r.delay||0;let{elapsed:u=0}=r;u=u-at(l);const c={keyframes:Array.isArray(n)?n:[null,n],ease:"easeOut",velocity:t.getVelocity(),...a,delay:-u,onUpdate:f=>{t.set(f),a.onUpdate&&a.onUpdate(f)},onComplete:()=>{o(),a.onComplete&&a.onComplete()},name:e,motionValue:t,element:s?void 0:i};yx(a)||Object.assign(c,gx(e,c)),c.duration&&(c.duration=at(c.duration)),c.repeatDelay&&(c.repeatDelay=at(c.repeatDelay)),c.from!==void 0&&(c.keyframes[0]=c.from);let d=!1;if((c.type===!1||c.duration===0&&!c.repeatDelay)&&(za(c),c.delay===0&&(d=!0)),(xt.instantAnimations||xt.skipAnimations)&&(d=!0,za(c),c.delay=0),c.allowFlatten=!a.type&&!a.ease,d&&!s&&t.get()!==void 0){const f=dx(c.keyframes,a);if(f!==void 0){$.update(()=>{c.onUpdate(f),c.onComplete()});return}}return a.isSync?new au(c):new F1(c)};function vx({protectedKeys:e,needsAnimating:t},n){const r=e.hasOwnProperty(n)&&t[n]!==!0;return t[n]=!1,r}function wm(e,t,{delay:n=0,transitionOverride:r,type:i}={}){let{transition:s=e.getDefaultTransition(),transitionEnd:o,...a}=t;r&&(s=r);const l=[],u=i&&e.animationState&&e.animationState.getState()[i];for(const c in a){const d=e.getValue(c,e.latestValues[c]??null),f=a[c];if(f===void 0||u&&vx(u,c))continue;const y={delay:n,...uu(s||{},c)},v=d.get();if(v!==void 0&&!d.isAnimating&&!Array.isArray(f)&&f===v&&!y.velocity)continue;let x=!1;if(window.MotionHandoffAnimation){const m=xm(e);if(m){const p=window.MotionHandoffAnimation(m,c,$);p!==null&&(y.startTime=p,x=!0)}}Ha(e,c),d.start(Su(c,d,f,e.shouldReduceMotion&&Bp.has(c)?{type:!1}:y,e,x));const S=d.animation;S&&l.push(S)}return o&&Promise.all(l).then(()=>{$.update(()=>{o&&lx(e,o)})}),l}function km(e,t,n,r=0,i=1){const s=Array.from(e).sort((u,c)=>u.sortNodePosition(c)).indexOf(t),o=e.size,a=(o-1)*r;return typeof n=="function"?n(s,o):i===1?s*r:a-s*r}function Ka(e,t,n={}){var l;const r=Bn(e,t,n.type==="exit"?(l=e.presenceContext)==null?void 0:l.custom:void 0);let{transition:i=e.getDefaultTransition()||{}}=r||{};n.transitionOverride&&(i=n.transitionOverride);const s=r?()=>Promise.all(wm(e,r,n)):()=>Promise.resolve(),o=e.variantChildren&&e.variantChildren.size?(u=0)=>{const{delayChildren:c=0,staggerChildren:d,staggerDirection:f}=i;return xx(e,t,u,c,d,f,n)}:()=>Promise.resolve(),{when:a}=i;if(a){const[u,c]=a==="beforeChildren"?[s,o]:[o,s];return u().then(()=>c())}else return Promise.all([s(),o(n.delay)])}function xx(e,t,n=0,r=0,i=0,s=1,o){const a=[];for(const l of e.variantChildren)l.notify("AnimationStart",t),a.push(Ka(l,t,{...o,delay:n+(typeof r=="function"?0:r)+km(e.variantChildren,l,r,i,s)}).then(()=>l.notify("AnimationComplete",t)));return Promise.all(a)}function wx(e,t,n={}){e.notify("AnimationStart",t);let r;if(Array.isArray(t)){const i=t.map(s=>Ka(e,s,n));r=Promise.all(i)}else if(typeof t=="string")r=Ka(e,t,n);else{const i=typeof t=="function"?Bn(e,t,n.custom):t;r=Promise.all(wm(e,i,n))}return r.then(()=>{e.notify("AnimationComplete",t)})}function Sm(e,t){if(!Array.isArray(t))return!1;const n=t.length;if(n!==e.length)return!1;for(let r=0;rPromise.all(t.map(({animation:n,options:r})=>wx(e,n,r)))}function Px(e){let t=Cx(e),n=dd(),r=!0;const i=l=>(u,c)=>{var f;const d=Bn(e,c,l==="exit"?(f=e.presenceContext)==null?void 0:f.custom:void 0);if(d){const{transition:y,transitionEnd:v,...x}=d;u={...u,...x,...v}}return u};function s(l){t=l(e)}function o(l){const{props:u}=e,c=Tm(e.parent)||{},d=[],f=new Set;let y={},v=1/0;for(let S=0;Sv&&w,R=!1;const M=Array.isArray(g)?g:[g];let X=M.reduce(i(m),{});k===!1&&(X={});const{prevResolvedValues:Ke={}}=p,Ie={...Ke,...X},kt=B=>{C=!0,f.has(B)&&(R=!0,f.delete(B)),p.needsAnimating[B]=!0;const E=e.getValue(B);E&&(E.liveStyle=!1)};for(const B in Ie){const E=X[B],L=Ke[B];if(y.hasOwnProperty(B))continue;let V=!1;$a(E)&&$a(L)?V=!Sm(E,L):V=E!==L,V?E!=null?kt(B):f.add(B):E!==void 0&&f.has(B)?kt(B):p.protectedKeys[B]=!0}p.prevProp=g,p.prevResolvedValues=X,p.isActive&&(y={...y,...X}),r&&e.blockInitialAnimation&&(C=!1);const F=T&&P;C&&(!F||R)&&d.push(...M.map(B=>{const E={type:m};if(typeof B=="string"&&r&&!F&&e.manuallyAnimateOnMount&&e.parent){const{parent:L}=e,V=Bn(L,B);if(L.enteringChildren&&V){const{delayChildren:H}=V.transition||{};E.delay=km(L.enteringChildren,e,H)}}return{animation:B,options:E}}))}if(f.size){const S={};if(typeof u.initial!="boolean"){const m=Bn(e,Array.isArray(u.initial)?u.initial[0]:u.initial);m&&m.transition&&(S.transition=m.transition)}f.forEach(m=>{const p=e.getBaseTarget(m),g=e.getValue(m);g&&(g.liveStyle=!0),S[m]=p??null}),d.push({animation:S})}let x=!!d.length;return r&&(u.initial===!1||u.initial===u.animate)&&!e.manuallyAnimateOnMount&&(x=!1),r=!1,x?t(d):Promise.resolve()}function a(l,u){var d;if(n[l].isActive===u)return Promise.resolve();(d=e.variantChildren)==null||d.forEach(f=>{var y;return(y=f.animationState)==null?void 0:y.setActive(l,u)}),n[l].isActive=u;const c=o(l);for(const f in n)n[f].protectedKeys={};return c}return{animateChanges:o,setActive:a,setAnimateFunction:s,getState:()=>n,reset:()=>{n=dd()}}}function jx(e,t){return typeof t=="string"?t!==e:Array.isArray(t)?!Sm(t,e):!1}function Yt(e=!1){return{isActive:e,protectedKeys:{},needsAnimating:{},prevResolvedValues:{}}}function dd(){return{animate:Yt(!0),whileInView:Yt(),whileHover:Yt(),whileTap:Yt(),whileDrag:Yt(),whileFocus:Yt(),exit:Yt()}}class Ht{constructor(t){this.isMounted=!1,this.node=t}update(){}}class Ex extends Ht{constructor(t){super(t),t.animationState||(t.animationState=Px(t))}updateAnimationControlsSubscription(){const{animate:t}=this.node.getProps();Us(t)&&(this.unmountControls=t.subscribe(this.node))}mount(){this.updateAnimationControlsSubscription()}update(){const{animate:t}=this.node.getProps(),{animate:n}=this.node.prevProps||{};t!==n&&this.updateAnimationControlsSubscription()}unmount(){var t;this.node.animationState.reset(),(t=this.unmountControls)==null||t.call(this)}}let Nx=0;class Dx extends Ht{constructor(){super(...arguments),this.id=Nx++}update(){if(!this.node.presenceContext)return;const{isPresent:t,onExitComplete:n}=this.node.presenceContext,{isPresent:r}=this.node.prevPresenceContext||{};if(!this.node.animationState||t===r)return;const i=this.node.animationState.setActive("exit",!t);n&&!t&&i.then(()=>{n(this.id)})}mount(){const{register:t,onExitComplete:n}=this.node.presenceContext||{};n&&n(this.id),t&&(this.unmount=t(this.id))}unmount(){}}const Mx={animation:{Feature:Ex},exit:{Feature:Dx}};function Zr(e,t,n,r={passive:!0}){return e.addEventListener(t,n,r),()=>e.removeEventListener(t,n)}function oi(e){return{point:{x:e.pageX,y:e.pageY}}}const Lx=e=>t=>fu(t)&&e(t,oi(t));function Er(e,t,n,r){return Zr(e,t,Lx(n),r)}const Cm=1e-4,Ax=1-Cm,Vx=1+Cm,Pm=.01,Rx=0-Pm,Ix=0+Pm;function xe(e){return e.max-e.min}function _x(e,t,n){return Math.abs(e-t)<=n}function fd(e,t,n,r=.5){e.origin=r,e.originPoint=G(t.min,t.max,e.origin),e.scale=xe(n)/xe(t),e.translate=G(n.min,n.max,e.origin)-e.originPoint,(e.scale>=Ax&&e.scale<=Vx||isNaN(e.scale))&&(e.scale=1),(e.translate>=Rx&&e.translate<=Ix||isNaN(e.translate))&&(e.translate=0)}function Nr(e,t,n,r){fd(e.x,t.x,n.x,r?r.originX:void 0),fd(e.y,t.y,n.y,r?r.originY:void 0)}function hd(e,t,n){e.min=n.min+t.min,e.max=e.min+xe(t)}function Ox(e,t,n){hd(e.x,t.x,n.x),hd(e.y,t.y,n.y)}function pd(e,t,n){e.min=t.min-n.min,e.max=e.min+xe(t)}function Ss(e,t,n){pd(e.x,t.x,n.x),pd(e.y,t.y,n.y)}function _e(e){return[e("x"),e("y")]}const jm=({current:e})=>e?e.ownerDocument.defaultView:null,md=(e,t)=>Math.abs(e-t);function Fx(e,t){const n=md(e.x,t.x),r=md(e.y,t.y);return Math.sqrt(n**2+r**2)}class Em{constructor(t,n,{transformPagePoint:r,contextWindow:i=window,dragSnapToOrigin:s=!1,distanceThreshold:o=3}={}){if(this.startEvent=null,this.lastMoveEvent=null,this.lastMoveEventInfo=null,this.handlers={},this.contextWindow=window,this.updatePoint=()=>{if(!(this.lastMoveEvent&&this.lastMoveEventInfo))return;const f=Eo(this.lastMoveEventInfo,this.history),y=this.startEvent!==null,v=Fx(f.offset,{x:0,y:0})>=this.distanceThreshold;if(!y&&!v)return;const{point:x}=f,{timestamp:S}=ce;this.history.push({...x,timestamp:S});const{onStart:m,onMove:p}=this.handlers;y||(m&&m(this.lastMoveEvent,f),this.startEvent=this.lastMoveEvent),p&&p(this.lastMoveEvent,f)},this.handlePointerMove=(f,y)=>{this.lastMoveEvent=f,this.lastMoveEventInfo=jo(y,this.transformPagePoint),$.update(this.updatePoint,!0)},this.handlePointerUp=(f,y)=>{this.end();const{onEnd:v,onSessionEnd:x,resumeAnimation:S}=this.handlers;if(this.dragSnapToOrigin&&S&&S(),!(this.lastMoveEvent&&this.lastMoveEventInfo))return;const m=Eo(f.type==="pointercancel"?this.lastMoveEventInfo:jo(y,this.transformPagePoint),this.history);this.startEvent&&v&&v(f,m),x&&x(f,m)},!fu(t))return;this.dragSnapToOrigin=s,this.handlers=n,this.transformPagePoint=r,this.distanceThreshold=o,this.contextWindow=i||window;const a=oi(t),l=jo(a,this.transformPagePoint),{point:u}=l,{timestamp:c}=ce;this.history=[{...u,timestamp:c}];const{onSessionStart:d}=n;d&&d(t,Eo(l,this.history)),this.removeListeners=ri(Er(this.contextWindow,"pointermove",this.handlePointerMove),Er(this.contextWindow,"pointerup",this.handlePointerUp),Er(this.contextWindow,"pointercancel",this.handlePointerUp))}updateHandlers(t){this.handlers=t}end(){this.removeListeners&&this.removeListeners(),Bt(this.updatePoint)}}function jo(e,t){return t?{point:t(e.point)}:e}function gd(e,t){return{x:e.x-t.x,y:e.y-t.y}}function Eo({point:e},t){return{point:e,delta:gd(e,Nm(t)),offset:gd(e,zx(t)),velocity:Bx(t,.1)}}function zx(e){return e[0]}function Nm(e){return e[e.length-1]}function Bx(e,t){if(e.length<2)return{x:0,y:0};let n=e.length-1,r=null;const i=Nm(e);for(;n>=0&&(r=e[n],!(i.timestamp-r.timestamp>at(t)));)n--;if(!r)return{x:0,y:0};const s=Be(i.timestamp-r.timestamp);if(s===0)return{x:0,y:0};const o={x:(i.x-r.x)/s,y:(i.y-r.y)/s};return o.x===1/0&&(o.x=0),o.y===1/0&&(o.y=0),o}function Ux(e,{min:t,max:n},r){return t!==void 0&&en&&(e=r?G(n,e,r.max):Math.min(e,n)),e}function yd(e,t,n){return{min:t!==void 0?e.min+t:void 0,max:n!==void 0?e.max+n-(e.max-e.min):void 0}}function Wx(e,{top:t,left:n,bottom:r,right:i}){return{x:yd(e.x,n,i),y:yd(e.y,t,r)}}function vd(e,t){let n=t.min-e.min,r=t.max-e.max;return t.max-t.minr?n=Kr(t.min,t.max-r,e.min):r>i&&(n=Kr(e.min,e.max-i,t.min)),vt(0,1,n)}function Hx(e,t){const n={};return t.min!==void 0&&(n.min=t.min-e.min),t.max!==void 0&&(n.max=t.max-e.min),n}const Ga=.35;function Kx(e=Ga){return e===!1?e=0:e===!0&&(e=Ga),{x:xd(e,"left","right"),y:xd(e,"top","bottom")}}function xd(e,t,n){return{min:wd(e,t),max:wd(e,n)}}function wd(e,t){return typeof e=="number"?e:e[t]||0}const Gx=new WeakMap;class Qx{constructor(t){this.openDragLock=null,this.isDragging=!1,this.currentDirection=null,this.originPoint={x:0,y:0},this.constraints=!1,this.hasMutatedConstraints=!1,this.elastic=ne(),this.latestPointerEvent=null,this.latestPanInfo=null,this.visualElement=t}start(t,{snapToCursor:n=!1,distanceThreshold:r}={}){const{presenceContext:i}=this.visualElement;if(i&&i.isPresent===!1)return;const s=d=>{const{dragSnapToOrigin:f}=this.getProps();f?this.pauseAnimation():this.stopAnimation(),n&&this.snapToCursor(oi(d).point)},o=(d,f)=>{const{drag:y,dragPropagation:v,onDragStart:x}=this.getProps();if(y&&!v&&(this.openDragLock&&this.openDragLock(),this.openDragLock=ev(y),!this.openDragLock))return;this.latestPointerEvent=d,this.latestPanInfo=f,this.isDragging=!0,this.currentDirection=null,this.resolveConstraints(),this.visualElement.projection&&(this.visualElement.projection.isAnimationBlocked=!0,this.visualElement.projection.target=void 0),_e(m=>{let p=this.getAxisMotionValue(m).get()||0;if(lt.test(p)){const{projection:g}=this.visualElement;if(g&&g.layout){const w=g.layout.layoutBox[m];w&&(p=xe(w)*(parseFloat(p)/100))}}this.originPoint[m]=p}),x&&$.postRender(()=>x(d,f)),Ha(this.visualElement,"transform");const{animationState:S}=this.visualElement;S&&S.setActive("whileDrag",!0)},a=(d,f)=>{this.latestPointerEvent=d,this.latestPanInfo=f;const{dragPropagation:y,dragDirectionLock:v,onDirectionLock:x,onDrag:S}=this.getProps();if(!y&&!this.openDragLock)return;const{offset:m}=f;if(v&&this.currentDirection===null){this.currentDirection=Yx(m),this.currentDirection!==null&&x&&x(this.currentDirection);return}this.updateAxis("x",f.point,m),this.updateAxis("y",f.point,m),this.visualElement.render(),S&&S(d,f)},l=(d,f)=>{this.latestPointerEvent=d,this.latestPanInfo=f,this.stop(d,f),this.latestPointerEvent=null,this.latestPanInfo=null},u=()=>_e(d=>{var f;return this.getAnimationState(d)==="paused"&&((f=this.getAxisMotionValue(d).animation)==null?void 0:f.play())}),{dragSnapToOrigin:c}=this.getProps();this.panSession=new Em(t,{onSessionStart:s,onStart:o,onMove:a,onSessionEnd:l,resumeAnimation:u},{transformPagePoint:this.visualElement.getTransformPagePoint(),dragSnapToOrigin:c,distanceThreshold:r,contextWindow:jm(this.visualElement)})}stop(t,n){const r=t||this.latestPointerEvent,i=n||this.latestPanInfo,s=this.isDragging;if(this.cancel(),!s||!i||!r)return;const{velocity:o}=i;this.startAnimation(o);const{onDragEnd:a}=this.getProps();a&&$.postRender(()=>a(r,i))}cancel(){this.isDragging=!1;const{projection:t,animationState:n}=this.visualElement;t&&(t.isAnimationBlocked=!1),this.panSession&&this.panSession.end(),this.panSession=void 0;const{dragPropagation:r}=this.getProps();!r&&this.openDragLock&&(this.openDragLock(),this.openDragLock=null),n&&n.setActive("whileDrag",!1)}updateAxis(t,n,r){const{drag:i}=this.getProps();if(!r||!Mi(t,i,this.currentDirection))return;const s=this.getAxisMotionValue(t);let o=this.originPoint[t]+r[t];this.constraints&&this.constraints[t]&&(o=Ux(o,this.constraints[t],this.elastic[t])),s.set(o)}resolveConstraints(){var s;const{dragConstraints:t,dragElastic:n}=this.getProps(),r=this.visualElement.projection&&!this.visualElement.projection.layout?this.visualElement.projection.measure(!1):(s=this.visualElement.projection)==null?void 0:s.layout,i=this.constraints;t&&Mn(t)?this.constraints||(this.constraints=this.resolveRefConstraints()):t&&r?this.constraints=Wx(r.layoutBox,t):this.constraints=!1,this.elastic=Kx(n),i!==this.constraints&&r&&this.constraints&&!this.hasMutatedConstraints&&_e(o=>{this.constraints!==!1&&this.getAxisMotionValue(o)&&(this.constraints[o]=Hx(r.layoutBox[o],this.constraints[o]))})}resolveRefConstraints(){const{dragConstraints:t,onMeasureDragConstraints:n}=this.getProps();if(!t||!Mn(t))return!1;const r=t.current,{projection:i}=this.visualElement;if(!i||!i.layout)return!1;const s=Xv(r,i.root,this.visualElement.getTransformPagePoint());let o=bx(i.layout.layoutBox,s);if(n){const a=n(Gv(o));this.hasMutatedConstraints=!!a,a&&(o=dm(a))}return o}startAnimation(t){const{drag:n,dragMomentum:r,dragElastic:i,dragTransition:s,dragSnapToOrigin:o,onDragTransitionEnd:a}=this.getProps(),l=this.constraints||{},u=_e(c=>{if(!Mi(c,n,this.currentDirection))return;let d=l&&l[c]||{};o&&(d={min:0,max:0});const f=i?200:1e6,y=i?40:1e7,v={type:"inertia",velocity:r?t[c]:0,bounceStiffness:f,bounceDamping:y,timeConstant:750,restDelta:1,restSpeed:10,...s,...d};return this.startAxisValueAnimation(c,v)});return Promise.all(u).then(a)}startAxisValueAnimation(t,n){const r=this.getAxisMotionValue(t);return Ha(this.visualElement,t),r.start(Su(t,r,0,n,this.visualElement,!1))}stopAnimation(){_e(t=>this.getAxisMotionValue(t).stop())}pauseAnimation(){_e(t=>{var n;return(n=this.getAxisMotionValue(t).animation)==null?void 0:n.pause()})}getAnimationState(t){var n;return(n=this.getAxisMotionValue(t).animation)==null?void 0:n.state}getAxisMotionValue(t){const n=`_drag${t.toUpperCase()}`,r=this.visualElement.getProps(),i=r[n];return i||this.visualElement.getValue(t,(r.initial?r.initial[t]:void 0)||0)}snapToCursor(t){_e(n=>{const{drag:r}=this.getProps();if(!Mi(n,r,this.currentDirection))return;const{projection:i}=this.visualElement,s=this.getAxisMotionValue(n);if(i&&i.layout){const{min:o,max:a}=i.layout.layoutBox[n];s.set(t[n]-G(o,a,.5))}})}scalePositionWithinConstraints(){if(!this.visualElement.current)return;const{drag:t,dragConstraints:n}=this.getProps(),{projection:r}=this.visualElement;if(!Mn(n)||!r||!this.constraints)return;this.stopAnimation();const i={x:0,y:0};_e(o=>{const a=this.getAxisMotionValue(o);if(a&&this.constraints!==!1){const l=a.get();i[o]=$x({min:l,max:l},this.constraints[o])}});const{transformTemplate:s}=this.visualElement.getProps();this.visualElement.current.style.transform=s?s({},""):"none",r.root&&r.root.updateScroll(),r.updateLayout(),this.resolveConstraints(),_e(o=>{if(!Mi(o,t,null))return;const a=this.getAxisMotionValue(o),{min:l,max:u}=this.constraints[o];a.set(G(l,u,i[o]))})}addListeners(){if(!this.visualElement.current)return;Gx.set(this.visualElement,this);const t=this.visualElement.current,n=Er(t,"pointerdown",l=>{const{drag:u,dragListener:c=!0}=this.getProps();u&&c&&this.start(l)}),r=()=>{const{dragConstraints:l}=this.getProps();Mn(l)&&l.current&&(this.constraints=this.resolveRefConstraints())},{projection:i}=this.visualElement,s=i.addEventListener("measure",r);i&&!i.layout&&(i.root&&i.root.updateScroll(),i.updateLayout()),$.read(r);const o=Zr(window,"resize",()=>this.scalePositionWithinConstraints()),a=i.addEventListener("didUpdate",({delta:l,hasLayoutChanged:u})=>{this.isDragging&&u&&(_e(c=>{const d=this.getAxisMotionValue(c);d&&(this.originPoint[c]+=l[c].translate,d.set(d.get()+l[c].translate))}),this.visualElement.render())});return()=>{o(),n(),s(),a&&a()}}getProps(){const t=this.visualElement.getProps(),{drag:n=!1,dragDirectionLock:r=!1,dragPropagation:i=!1,dragConstraints:s=!1,dragElastic:o=Ga,dragMomentum:a=!0}=t;return{...t,drag:n,dragDirectionLock:r,dragPropagation:i,dragConstraints:s,dragElastic:o,dragMomentum:a}}}function Mi(e,t,n){return(t===!0||t===e)&&(n===null||n===e)}function Yx(e,t=10){let n=null;return Math.abs(e.y)>t?n="y":Math.abs(e.x)>t&&(n="x"),n}class Xx extends Ht{constructor(t){super(t),this.removeGroupControls=We,this.removeListeners=We,this.controls=new Qx(t)}mount(){const{dragControls:t}=this.node.getProps();t&&(this.removeGroupControls=t.subscribe(this.controls)),this.removeListeners=this.controls.addListeners()||We}unmount(){this.removeGroupControls(),this.removeListeners()}}const kd=e=>(t,n)=>{e&&$.postRender(()=>e(t,n))};class Zx extends Ht{constructor(){super(...arguments),this.removePointerDownListener=We}onPointerDown(t){this.session=new Em(t,this.createPanHandlers(),{transformPagePoint:this.node.getTransformPagePoint(),contextWindow:jm(this.node)})}createPanHandlers(){const{onPanSessionStart:t,onPanStart:n,onPan:r,onPanEnd:i}=this.node.getProps();return{onSessionStart:kd(t),onStart:kd(n),onMove:r,onEnd:(s,o)=>{delete this.session,i&&$.postRender(()=>i(s,o))}}}mount(){this.removePointerDownListener=Er(this.node.current,"pointerdown",t=>this.onPointerDown(t))}update(){this.session&&this.session.updateHandlers(this.createPanHandlers())}unmount(){this.removePointerDownListener(),this.session&&this.session.end()}}const Ki={hasAnimatedSinceResize:!0,hasEverUpdated:!1};function Sd(e,t){return t.max===t.min?0:e/(t.max-t.min)*100}const cr={correct:(e,t)=>{if(!t.target)return e;if(typeof e=="string")if(A.test(e))e=parseFloat(e);else return e;const n=Sd(e,t.target.x),r=Sd(e,t.target.y);return`${n}% ${r}%`}},qx={correct:(e,{treeScale:t,projectionDelta:n})=>{const r=e,i=Ut.parse(e);if(i.length>5)return r;const s=Ut.createTransformer(e),o=typeof i[0]!="number"?1:0,a=n.x.scale*t.x,l=n.y.scale*t.y;i[0+o]/=a,i[1+o]/=l;const u=G(a,l,.5);return typeof i[2+o]=="number"&&(i[2+o]/=u),typeof i[3+o]=="number"&&(i[3+o]/=u),s(i)}};let No=!1;class Jx extends N.Component{componentDidMount(){const{visualElement:t,layoutGroup:n,switchLayoutGroup:r,layoutId:i}=this.props,{projection:s}=t;kv(e2),s&&(n.group&&n.group.add(s),r&&r.register&&i&&r.register(s),No&&s.root.didUpdate(),s.addEventListener("animationComplete",()=>{this.safeToRemove()}),s.setOptions({...s.options,onExitComplete:()=>this.safeToRemove()})),Ki.hasEverUpdated=!0}getSnapshotBeforeUpdate(t){const{layoutDependency:n,visualElement:r,drag:i,isPresent:s}=this.props,{projection:o}=r;return o&&(o.isPresent=s,No=!0,i||t.layoutDependency!==n||n===void 0||t.isPresent!==s?o.willUpdate():this.safeToRemove(),t.isPresent!==s&&(s?o.promote():o.relegate()||$.postRender(()=>{const a=o.getStack();(!a||!a.members.length)&&this.safeToRemove()}))),null}componentDidUpdate(){const{projection:t}=this.props.visualElement;t&&(t.root.didUpdate(),du.postRender(()=>{!t.currentAnimation&&t.isLead()&&this.safeToRemove()}))}componentWillUnmount(){const{visualElement:t,layoutGroup:n,switchLayoutGroup:r}=this.props,{projection:i}=t;No=!0,i&&(i.scheduleCheckAfterUnmount(),n&&n.group&&n.group.remove(i),r&&r.deregister&&r.deregister(i))}safeToRemove(){const{safeToRemove:t}=this.props;t&&t()}render(){return null}}function Dm(e){const[t,n]=Zp(),r=N.useContext(bl);return h.jsx(Jx,{...e,layoutGroup:r,switchLayoutGroup:N.useContext(um),isPresent:t,safeToRemove:n})}const e2={borderRadius:{...cr,applyTo:["borderTopLeftRadius","borderTopRightRadius","borderBottomLeftRadius","borderBottomRightRadius"]},borderTopLeftRadius:cr,borderTopRightRadius:cr,borderBottomLeftRadius:cr,borderBottomRightRadius:cr,boxShadow:qx};function t2(e,t,n){const r=ge(e)?e:Qn(e);return r.start(Su("",r,t,n)),r.animation}const n2=(e,t)=>e.depth-t.depth;class r2{constructor(){this.children=[],this.isDirty=!1}add(t){Kl(this.children,t),this.isDirty=!0}remove(t){Gl(this.children,t),this.isDirty=!0}forEach(t){this.isDirty&&this.children.sort(n2),this.isDirty=!1,this.children.forEach(t)}}function i2(e,t){const n=Pe.now(),r=({timestamp:i})=>{const s=i-n;s>=t&&(Bt(r),e(s-t))};return $.setup(r,!0),()=>Bt(r)}const Mm=["TopLeft","TopRight","BottomLeft","BottomRight"],s2=Mm.length,Td=e=>typeof e=="string"?parseFloat(e):e,Cd=e=>typeof e=="number"||A.test(e);function o2(e,t,n,r,i,s){i?(e.opacity=G(0,n.opacity??1,a2(r)),e.opacityExit=G(t.opacity??1,0,l2(r))):s&&(e.opacity=G(t.opacity??1,n.opacity??1,r));for(let o=0;ort?1:n(Kr(e,t,r))}function jd(e,t){e.min=t.min,e.max=t.max}function Qe(e,t){jd(e.x,t.x),jd(e.y,t.y)}function Ed(e,t){e.translate=t.translate,e.scale=t.scale,e.originPoint=t.originPoint,e.origin=t.origin}function Nd(e,t,n,r,i){return e-=t,e=ks(e,1/n,r),i!==void 0&&(e=ks(e,1/i,r)),e}function u2(e,t=0,n=1,r=.5,i,s=e,o=e){if(lt.test(t)&&(t=parseFloat(t),t=G(o.min,o.max,t/100)-o.min),typeof t!="number")return;let a=G(s.min,s.max,r);e===s&&(a-=t),e.min=Nd(e.min,t,n,a,i),e.max=Nd(e.max,t,n,a,i)}function Dd(e,t,[n,r,i],s,o){u2(e,t[n],t[r],t[i],t.scale,s,o)}const c2=["x","scaleX","originX"],d2=["y","scaleY","originY"];function Md(e,t,n,r){Dd(e.x,t,c2,n?n.x:void 0,r?r.x:void 0),Dd(e.y,t,d2,n?n.y:void 0,r?r.y:void 0)}function Ld(e){return e.translate===0&&e.scale===1}function Am(e){return Ld(e.x)&&Ld(e.y)}function Ad(e,t){return e.min===t.min&&e.max===t.max}function f2(e,t){return Ad(e.x,t.x)&&Ad(e.y,t.y)}function Vd(e,t){return Math.round(e.min)===Math.round(t.min)&&Math.round(e.max)===Math.round(t.max)}function Vm(e,t){return Vd(e.x,t.x)&&Vd(e.y,t.y)}function Rd(e){return xe(e.x)/xe(e.y)}function Id(e,t){return e.translate===t.translate&&e.scale===t.scale&&e.originPoint===t.originPoint}class h2{constructor(){this.members=[]}add(t){Kl(this.members,t),t.scheduleRender()}remove(t){if(Gl(this.members,t),t===this.prevLead&&(this.prevLead=void 0),t===this.lead){const n=this.members[this.members.length-1];n&&this.promote(n)}}relegate(t){const n=this.members.findIndex(i=>t===i);if(n===0)return!1;let r;for(let i=n;i>=0;i--){const s=this.members[i];if(s.isPresent!==!1){r=s;break}}return r?(this.promote(r),!0):!1}promote(t,n){const r=this.lead;if(t!==r&&(this.prevLead=r,this.lead=t,t.show(),r)){r.instance&&r.scheduleRender(),t.scheduleRender(),t.resumeFrom=r,n&&(t.resumeFrom.preserveOpacity=!0),r.snapshot&&(t.snapshot=r.snapshot,t.snapshot.latestValues=r.animationValues||r.latestValues),t.root&&t.root.isUpdating&&(t.isLayoutDirty=!0);const{crossfade:i}=t.options;i===!1&&r.hide()}}exitAnimationComplete(){this.members.forEach(t=>{const{options:n,resumingFrom:r}=t;n.onExitComplete&&n.onExitComplete(),r&&r.options.onExitComplete&&r.options.onExitComplete()})}scheduleRender(){this.members.forEach(t=>{t.instance&&t.scheduleRender(!1)})}removeLeadSnapshot(){this.lead&&this.lead.snapshot&&(this.lead.snapshot=void 0)}}function p2(e,t,n){let r="";const i=e.x.translate/t.x,s=e.y.translate/t.y,o=(n==null?void 0:n.z)||0;if((i||s||o)&&(r=`translate3d(${i}px, ${s}px, ${o}px) `),(t.x!==1||t.y!==1)&&(r+=`scale(${1/t.x}, ${1/t.y}) `),n){const{transformPerspective:u,rotate:c,rotateX:d,rotateY:f,skewX:y,skewY:v}=n;u&&(r=`perspective(${u}px) ${r}`),c&&(r+=`rotate(${c}deg) `),d&&(r+=`rotateX(${d}deg) `),f&&(r+=`rotateY(${f}deg) `),y&&(r+=`skewX(${y}deg) `),v&&(r+=`skewY(${v}deg) `)}const a=e.x.scale*t.x,l=e.y.scale*t.y;return(a!==1||l!==1)&&(r+=`scale(${a}, ${l})`),r||"none"}const Do=["","X","Y","Z"],m2=1e3;let g2=0;function Mo(e,t,n,r){const{latestValues:i}=t;i[e]&&(n[e]=i[e],t.setStaticValue(e,0),r&&(r[e]=0))}function Rm(e){if(e.hasCheckedOptimisedAppear=!0,e.root===e)return;const{visualElement:t}=e.options;if(!t)return;const n=xm(t);if(window.MotionHasOptimisedAnimation(n,"transform")){const{layout:i,layoutId:s}=e.options;window.MotionCancelOptimisedAnimation(n,"transform",$,!(i||s))}const{parent:r}=e;r&&!r.hasCheckedOptimisedAppear&&Rm(r)}function Im({attachResizeListener:e,defaultParent:t,measureScroll:n,checkIsScrollRoot:r,resetTransform:i}){return class{constructor(o={},a=t==null?void 0:t()){this.id=g2++,this.animationId=0,this.animationCommitId=0,this.children=new Set,this.options={},this.isTreeAnimating=!1,this.isAnimationBlocked=!1,this.isLayoutDirty=!1,this.isProjectionDirty=!1,this.isSharedProjectionDirty=!1,this.isTransformDirty=!1,this.updateManuallyBlocked=!1,this.updateBlockedByResize=!1,this.isUpdating=!1,this.isSVG=!1,this.needsReset=!1,this.shouldResetTransform=!1,this.hasCheckedOptimisedAppear=!1,this.treeScale={x:1,y:1},this.eventHandlers=new Map,this.hasTreeAnimated=!1,this.layoutVersion=0,this.updateScheduled=!1,this.scheduleUpdate=()=>this.update(),this.projectionUpdateScheduled=!1,this.checkUpdateFailed=()=>{this.isUpdating&&(this.isUpdating=!1,this.clearAllSnapshots())},this.updateProjection=()=>{this.projectionUpdateScheduled=!1,this.nodes.forEach(x2),this.nodes.forEach(T2),this.nodes.forEach(C2),this.nodes.forEach(w2)},this.resolvedRelativeTargetAt=0,this.linkedParentVersion=0,this.hasProjected=!1,this.isVisible=!0,this.animationProgress=0,this.sharedNodes=new Map,this.latestValues=o,this.root=a?a.root||a:this,this.path=a?[...a.path,a]:[],this.parent=a,this.depth=a?a.depth+1:0;for(let l=0;lthis.root.updateBlockedByResize=!1;$.read(()=>{d=window.innerWidth}),e(o,()=>{const y=window.innerWidth;y!==d&&(d=y,this.root.updateBlockedByResize=!0,c&&c(),c=i2(f,250),Ki.hasAnimatedSinceResize&&(Ki.hasAnimatedSinceResize=!1,this.nodes.forEach(Fd)))})}a&&this.root.registerSharedNode(a,this),this.options.animate!==!1&&u&&(a||l)&&this.addEventListener("didUpdate",({delta:c,hasLayoutChanged:d,hasRelativeLayoutChanged:f,layout:y})=>{if(this.isTreeAnimationBlocked()){this.target=void 0,this.relativeTarget=void 0;return}const v=this.options.transition||u.getDefaultTransition()||D2,{onLayoutAnimationStart:x,onLayoutAnimationComplete:S}=u.getProps(),m=!this.targetLayout||!Vm(this.targetLayout,y),p=!d&&f;if(this.options.layoutRoot||this.resumeFrom||p||d&&(m||!this.currentAnimation)){this.resumeFrom&&(this.resumingFrom=this.resumeFrom,this.resumingFrom.resumingFrom=void 0);const g={...uu(v,"layout"),onPlay:x,onComplete:S};(u.shouldReduceMotion||this.options.layoutRoot)&&(g.delay=0,g.type=!1),this.startAnimation(g),this.setAnimationOrigin(c,p)}else d||Fd(this),this.isLead()&&this.options.onExitComplete&&this.options.onExitComplete();this.targetLayout=y})}unmount(){this.options.layoutId&&this.willUpdate(),this.root.nodes.remove(this);const o=this.getStack();o&&o.remove(this),this.parent&&this.parent.children.delete(this),this.instance=void 0,this.eventHandlers.clear(),Bt(this.updateProjection)}blockUpdate(){this.updateManuallyBlocked=!0}unblockUpdate(){this.updateManuallyBlocked=!1}isUpdateBlocked(){return this.updateManuallyBlocked||this.updateBlockedByResize}isTreeAnimationBlocked(){return this.isAnimationBlocked||this.parent&&this.parent.isTreeAnimationBlocked()||!1}startUpdate(){this.isUpdateBlocked()||(this.isUpdating=!0,this.nodes&&this.nodes.forEach(P2),this.animationId++)}getTransformTemplate(){const{visualElement:o}=this.options;return o&&o.getProps().transformTemplate}willUpdate(o=!0){if(this.root.hasTreeAnimated=!0,this.root.isUpdateBlocked()){this.options.onExitComplete&&this.options.onExitComplete();return}if(window.MotionCancelOptimisedAnimation&&!this.hasCheckedOptimisedAppear&&Rm(this),!this.root.isUpdating&&this.root.startUpdate(),this.isLayoutDirty)return;this.isLayoutDirty=!0;for(let c=0;c{this.isLayoutDirty?this.root.didUpdate():this.root.checkUpdateFailed()})}updateSnapshot(){this.snapshot||!this.instance||(this.snapshot=this.measure(),this.snapshot&&!xe(this.snapshot.measuredBox.x)&&!xe(this.snapshot.measuredBox.y)&&(this.snapshot=void 0))}updateLayout(){if(!this.instance||(this.updateScroll(),!(this.options.alwaysMeasureLayout&&this.isLead())&&!this.isLayoutDirty))return;if(this.resumeFrom&&!this.resumeFrom.instance)for(let l=0;l{const k=w/1e3;zd(d.x,o.x,k),zd(d.y,o.y,k),this.setTargetDelta(d),this.relativeTarget&&this.relativeTargetOrigin&&this.layout&&this.relativeParent&&this.relativeParent.layout&&(Ss(f,this.layout.layoutBox,this.relativeParent.layout.layoutBox),E2(this.relativeTarget,this.relativeTargetOrigin,f,k),g&&f2(this.relativeTarget,g)&&(this.isProjectionDirty=!1),g||(g=ne()),Qe(g,this.relativeTarget)),x&&(this.animationValues=c,o2(c,u,this.latestValues,k,p,m)),this.root.scheduleUpdateProjection(),this.scheduleRender(),this.animationProgress=k},this.mixTargetDelta(this.options.layoutRoot?1e3:0)}startAnimation(o){var a,l,u;this.notifyListeners("animationStart"),(a=this.currentAnimation)==null||a.stop(),(u=(l=this.resumingFrom)==null?void 0:l.currentAnimation)==null||u.stop(),this.pendingAnimation&&(Bt(this.pendingAnimation),this.pendingAnimation=void 0),this.pendingAnimation=$.update(()=>{Ki.hasAnimatedSinceResize=!0,this.motionValue||(this.motionValue=Qn(0)),this.currentAnimation=t2(this.motionValue,[0,1e3],{...o,velocity:0,isSync:!0,onUpdate:c=>{this.mixTargetDelta(c),o.onUpdate&&o.onUpdate(c)},onStop:()=>{},onComplete:()=>{o.onComplete&&o.onComplete(),this.completeAnimation()}}),this.resumingFrom&&(this.resumingFrom.currentAnimation=this.currentAnimation),this.pendingAnimation=void 0})}completeAnimation(){this.resumingFrom&&(this.resumingFrom.currentAnimation=void 0,this.resumingFrom.preserveOpacity=void 0);const o=this.getStack();o&&o.exitAnimationComplete(),this.resumingFrom=this.currentAnimation=this.animationValues=void 0,this.notifyListeners("animationComplete")}finishAnimation(){this.currentAnimation&&(this.mixTargetDelta&&this.mixTargetDelta(m2),this.currentAnimation.stop()),this.completeAnimation()}applyTransformsToTarget(){const o=this.getLead();let{targetWithTransforms:a,target:l,layout:u,latestValues:c}=o;if(!(!a||!l||!u)){if(this!==o&&this.layout&&u&&_m(this.options.animationType,this.layout.layoutBox,u.layoutBox)){l=this.target||ne();const d=xe(this.layout.layoutBox.x);l.x.min=o.target.x.min,l.x.max=l.x.min+d;const f=xe(this.layout.layoutBox.y);l.y.min=o.target.y.min,l.y.max=l.y.min+f}Qe(a,l),An(a,c),Nr(this.projectionDeltaWithTransform,this.layoutCorrected,a,c)}}registerSharedNode(o,a){this.sharedNodes.has(o)||this.sharedNodes.set(o,new h2),this.sharedNodes.get(o).add(a);const u=a.options.initialPromotionConfig;a.promote({transition:u?u.transition:void 0,preserveFollowOpacity:u&&u.shouldPreserveFollowOpacity?u.shouldPreserveFollowOpacity(a):void 0})}isLead(){const o=this.getStack();return o?o.lead===this:!0}getLead(){var a;const{layoutId:o}=this.options;return o?((a=this.getStack())==null?void 0:a.lead)||this:this}getPrevLead(){var a;const{layoutId:o}=this.options;return o?(a=this.getStack())==null?void 0:a.prevLead:void 0}getStack(){const{layoutId:o}=this.options;if(o)return this.root.sharedNodes.get(o)}promote({needsReset:o,transition:a,preserveFollowOpacity:l}={}){const u=this.getStack();u&&u.promote(this,l),o&&(this.projectionDelta=void 0,this.needsReset=!0),a&&this.setOptions({transition:a})}relegate(){const o=this.getStack();return o?o.relegate(this):!1}resetSkewAndRotation(){const{visualElement:o}=this.options;if(!o)return;let a=!1;const{latestValues:l}=o;if((l.z||l.rotate||l.rotateX||l.rotateY||l.rotateZ||l.skewX||l.skewY)&&(a=!0),!a)return;const u={};l.z&&Mo("z",o,u,this.animationValues);for(let c=0;c{var a;return(a=o.currentAnimation)==null?void 0:a.stop()}),this.root.nodes.forEach(_d),this.root.sharedNodes.clear()}}}function y2(e){e.updateLayout()}function v2(e){var n;const t=((n=e.resumeFrom)==null?void 0:n.snapshot)||e.snapshot;if(e.isLead()&&e.layout&&t&&e.hasListeners("didUpdate")){const{layoutBox:r,measuredBox:i}=e.layout,{animationType:s}=e.options,o=t.source!==e.layout.source;s==="size"?_e(d=>{const f=o?t.measuredBox[d]:t.layoutBox[d],y=xe(f);f.min=r[d].min,f.max=f.min+y}):_m(s,t.layoutBox,r)&&_e(d=>{const f=o?t.measuredBox[d]:t.layoutBox[d],y=xe(r[d]);f.max=f.min+y,e.relativeTarget&&!e.currentAnimation&&(e.isProjectionDirty=!0,e.relativeTarget[d].max=e.relativeTarget[d].min+y)});const a=Vn();Nr(a,r,t.layoutBox);const l=Vn();o?Nr(l,e.applyTransform(i,!0),t.measuredBox):Nr(l,r,t.layoutBox);const u=!Am(a);let c=!1;if(!e.resumeFrom){const d=e.getClosestProjectingParent();if(d&&!d.resumeFrom){const{snapshot:f,layout:y}=d;if(f&&y){const v=ne();Ss(v,t.layoutBox,f.layoutBox);const x=ne();Ss(x,r,y.layoutBox),Vm(v,x)||(c=!0),d.options.layoutRoot&&(e.relativeTarget=x,e.relativeTargetOrigin=v,e.relativeParent=d)}}}e.notifyListeners("didUpdate",{layout:r,snapshot:t,delta:l,layoutDelta:a,hasLayoutChanged:u,hasRelativeLayoutChanged:c})}else if(e.isLead()){const{onExitComplete:r}=e.options;r&&r()}e.options.transition=void 0}function x2(e){e.parent&&(e.isProjecting()||(e.isProjectionDirty=e.parent.isProjectionDirty),e.isSharedProjectionDirty||(e.isSharedProjectionDirty=!!(e.isProjectionDirty||e.parent.isProjectionDirty||e.parent.isSharedProjectionDirty)),e.isTransformDirty||(e.isTransformDirty=e.parent.isTransformDirty))}function w2(e){e.isProjectionDirty=e.isSharedProjectionDirty=e.isTransformDirty=!1}function k2(e){e.clearSnapshot()}function _d(e){e.clearMeasurements()}function Od(e){e.isLayoutDirty=!1}function S2(e){const{visualElement:t}=e.options;t&&t.getProps().onBeforeLayoutMeasure&&t.notify("BeforeLayoutMeasure"),e.resetTransform()}function Fd(e){e.finishAnimation(),e.targetDelta=e.relativeTarget=e.target=void 0,e.isProjectionDirty=!0}function T2(e){e.resolveTargetDelta()}function C2(e){e.calcProjection()}function P2(e){e.resetSkewAndRotation()}function j2(e){e.removeLeadSnapshot()}function zd(e,t,n){e.translate=G(t.translate,0,n),e.scale=G(t.scale,1,n),e.origin=t.origin,e.originPoint=t.originPoint}function Bd(e,t,n,r){e.min=G(t.min,n.min,r),e.max=G(t.max,n.max,r)}function E2(e,t,n,r){Bd(e.x,t.x,n.x,r),Bd(e.y,t.y,n.y,r)}function N2(e){return e.animationValues&&e.animationValues.opacityExit!==void 0}const D2={duration:.45,ease:[.4,0,.1,1]},Ud=e=>typeof navigator<"u"&&navigator.userAgent&&navigator.userAgent.toLowerCase().includes(e),Wd=Ud("applewebkit/")&&!Ud("chrome/")?Math.round:We;function bd(e){e.min=Wd(e.min),e.max=Wd(e.max)}function M2(e){bd(e.x),bd(e.y)}function _m(e,t,n){return e==="position"||e==="preserve-aspect"&&!_x(Rd(t),Rd(n),.2)}function L2(e){var t;return e!==e.root&&((t=e.scroll)==null?void 0:t.wasRoot)}const A2=Im({attachResizeListener:(e,t)=>Zr(e,"resize",t),measureScroll:()=>({x:document.documentElement.scrollLeft||document.body.scrollLeft,y:document.documentElement.scrollTop||document.body.scrollTop}),checkIsScrollRoot:()=>!0}),Lo={current:void 0},Om=Im({measureScroll:e=>({x:e.scrollLeft,y:e.scrollTop}),defaultParent:()=>{if(!Lo.current){const e=new A2({});e.mount(window),e.setOptions({layoutScroll:!0}),Lo.current=e}return Lo.current},resetTransform:(e,t)=>{e.style.transform=t!==void 0?t:"none"},checkIsScrollRoot:e=>window.getComputedStyle(e).position==="fixed"}),V2={pan:{Feature:Zx},drag:{Feature:Xx,ProjectionNode:Om,MeasureLayout:Dm}};function $d(e,t,n){const{props:r}=e;e.animationState&&r.whileHover&&e.animationState.setActive("whileHover",n==="Start");const i="onHover"+n,s=r[i];s&&$.postRender(()=>s(t,oi(t)))}class R2 extends Ht{mount(){const{current:t}=this.node;t&&(this.unmount=tv(t,(n,r)=>($d(this.node,r,"Start"),i=>$d(this.node,i,"End"))))}unmount(){}}class I2 extends Ht{constructor(){super(...arguments),this.isActive=!1}onFocus(){let t=!1;try{t=this.node.current.matches(":focus-visible")}catch{t=!0}!t||!this.node.animationState||(this.node.animationState.setActive("whileFocus",!0),this.isActive=!0)}onBlur(){!this.isActive||!this.node.animationState||(this.node.animationState.setActive("whileFocus",!1),this.isActive=!1)}mount(){this.unmount=ri(Zr(this.node.current,"focus",()=>this.onFocus()),Zr(this.node.current,"blur",()=>this.onBlur()))}unmount(){}}function Hd(e,t,n){const{props:r}=e;if(e.current instanceof HTMLButtonElement&&e.current.disabled)return;e.animationState&&r.whileTap&&e.animationState.setActive("whileTap",n==="Start");const i="onTap"+(n==="End"?"":n),s=r[i];s&&$.postRender(()=>s(t,oi(t)))}class _2 extends Ht{mount(){const{current:t}=this.node;t&&(this.unmount=sv(t,(n,r)=>(Hd(this.node,r,"Start"),(i,{success:s})=>Hd(this.node,i,s?"End":"Cancel")),{useGlobalTarget:this.node.props.globalTapTarget}))}unmount(){}}const Qa=new WeakMap,Ao=new WeakMap,O2=e=>{const t=Qa.get(e.target);t&&t(e)},F2=e=>{e.forEach(O2)};function z2({root:e,...t}){const n=e||document;Ao.has(n)||Ao.set(n,{});const r=Ao.get(n),i=JSON.stringify(t);return r[i]||(r[i]=new IntersectionObserver(F2,{root:e,...t})),r[i]}function B2(e,t,n){const r=z2(t);return Qa.set(e,n),r.observe(e),()=>{Qa.delete(e),r.unobserve(e)}}const U2={some:0,all:1};class W2 extends Ht{constructor(){super(...arguments),this.hasEnteredView=!1,this.isInView=!1}startObserver(){this.unmount();const{viewport:t={}}=this.node.getProps(),{root:n,margin:r,amount:i="some",once:s}=t,o={root:n?n.current:void 0,rootMargin:r,threshold:typeof i=="number"?i:U2[i]},a=l=>{const{isIntersecting:u}=l;if(this.isInView===u||(this.isInView=u,s&&!u&&this.hasEnteredView))return;u&&(this.hasEnteredView=!0),this.node.animationState&&this.node.animationState.setActive("whileInView",u);const{onViewportEnter:c,onViewportLeave:d}=this.node.getProps(),f=u?c:d;f&&f(l)};return B2(this.node.current,o,a)}mount(){this.startObserver()}update(){if(typeof IntersectionObserver>"u")return;const{props:t,prevProps:n}=this.node;["amount","margin","root"].some(b2(t,n))&&this.startObserver()}unmount(){}}function b2({viewport:e={}},{viewport:t={}}={}){return n=>e[n]!==t[n]}const $2={inView:{Feature:W2},tap:{Feature:_2},focus:{Feature:I2},hover:{Feature:R2}},H2={layout:{ProjectionNode:Om,MeasureLayout:Dm}},K2={...Mx,...$2,...V2,...H2},be=Kv(K2,sx),Kt="/api";async function G2(){return(await fetch(`${Kt}/state`)).json()}async function Kd(){return(await fetch(`${Kt}/dependencies/check`)).json()}async function Vo(){return(await fetch(`${Kt}/docker/status`)).json()}async function Q2(){return(await fetch(`${Kt}/docker/build`,{method:"POST"})).json()}async function Y2(){return(await fetch(`${Kt}/docker/start-background`,{method:"POST"})).json()}async function X2(){await fetch(`${Kt}/close`)}async function Z2(){return(await fetch(`${Kt}/defaults`)).json()}async function q2(e){return(await fetch(`${Kt}/defaults`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(e)})).json()}const J2="/assets/wails-logo-white-text-B284k7fX.svg",ew="/assets/wails-logo-black-text-Cx-vsZ4W.svg";function tw({className:e="",size:t=240,theme:n="dark"}){const r=n==="dark"?J2:ew;return h.jsx("img",{src:r,alt:"Wails",width:t,className:`object-contain ${e}`,style:{filter:"drop-shadow(0 0 60px rgba(239, 68, 68, 0.4))"}})}const Fm=N.createContext({theme:"dark",toggleTheme:()=>{}}),nw=()=>N.useContext(Fm);function rw(){const{theme:e,toggleTheme:t}=nw();return h.jsx("button",{onClick:t,className:"fixed top-4 left-4 z-50 p-2 rounded-lg bg-gray-200 dark:bg-gray-800 hover:bg-gray-300 dark:hover:bg-gray-700 transition-colors",title:e==="dark"?"Switch to light mode":"Switch to dark mode",children:e==="dark"?h.jsx("svg",{className:"w-5 h-5 text-yellow-500",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",children:h.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M12 3v1m0 16v1m9-9h-1M4 12H3m15.364 6.364l-.707-.707M6.343 6.343l-.707-.707m12.728 0l-.707.707M6.343 17.657l-.707.707M16 12a4 4 0 11-8 0 4 4 0 018 0z"})}):h.jsx("svg",{className:"w-5 h-5 text-gray-700",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",children:h.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M20.354 15.354A9 9 0 018.646 3.646 9.003 9.003 0 0012 21a9.003 9.003 0 008.354-5.646z"})})})}const ai={initial:{opacity:0,x:50},animate:{opacity:1,x:0},exit:{opacity:0,x:-50}};function iw({steps:e,currentStep:t}){const n=e.findIndex(r=>r.id===t);return h.jsx("div",{className:"flex items-center justify-center gap-1 text-[11px] text-gray-500 dark:text-gray-400",children:e.map((r,i)=>h.jsxs("div",{className:"flex items-center",children:[h.jsx("span",{className:i<=n?"text-gray-900 dark:text-white font-medium":"text-gray-400 dark:text-gray-500",children:r.label}),iy.required&&!y.installed).length===0,c=e.filter(y=>!y.installed),d=(()=>{const y=c.filter(m=>{var p;return(p=m.installCommand)==null?void 0:p.startsWith("sudo ")}).map(m=>m.installCommand);if(y.length===0)return null;const v=[],x=[],S=[];for(const m of y)if(m.includes("pacman -S")){const p=m.match(/pacman -S\s+(.+)/);p&&v.push(...p[1].split(/\s+/))}else if(m.includes("apt install")){const p=m.match(/apt install\s+(.+)/);p&&x.push(...p[1].split(/\s+/))}else if(m.includes("dnf install")){const p=m.match(/dnf install\s+(.+)/);p&&S.push(...p[1].split(/\s+/))}return v.length>0?`sudo pacman -S ${v.join(" ")}`:x.length>0?`sudo apt install ${x.join(" ")}`:S.length>0?`sudo dnf install ${S.join(" ")}`:null})(),f=()=>{d&&(navigator.clipboard.writeText(d),a(!0),setTimeout(()=>a(!1),2e3))};return h.jsxs(be.div,{variants:ai,initial:"initial",animate:"animate",exit:"exit",transition:{duration:.2},className:"relative",children:[s&&h.jsx("div",{className:"absolute inset-0 bg-white/80 dark:bg-gray-900/80 rounded-lg flex items-center justify-center z-10",children:h.jsxs("div",{className:"flex flex-col items-center gap-4",children:[h.jsx(be.div,{animate:{rotate:360},transition:{duration:1,repeat:1/0,ease:"linear"},className:"w-8 h-8 border-2 border-gray-400 dark:border-gray-600 border-t-red-500 rounded-full"}),h.jsx("span",{className:"text-sm text-gray-600 dark:text-gray-400",children:"Checking dependencies..."})]})}),h.jsxs("div",{className:"mb-4",children:[h.jsx("h2",{className:"text-xl font-bold mb-1 text-gray-900 dark:text-white",children:"System Dependencies"}),h.jsx("p",{className:"text-sm text-gray-600 dark:text-gray-300",children:"The following dependencies are needed to build Wails applications."})]}),h.jsx("div",{className:"mb-4",children:h.jsx("div",{className:"bg-gray-100 dark:bg-gray-900/50 rounded-lg px-4",children:e.map(y=>h.jsx(ow,{dep:y},y.name))})}),d&&h.jsxs("div",{className:"mb-4 p-3 bg-gray-100 dark:bg-gray-900/50 rounded-lg",children:[h.jsx("div",{className:"text-xs text-gray-600 dark:text-gray-300 mb-2",children:"Install all missing dependencies:"}),h.jsxs("div",{className:"flex items-center gap-2",children:[h.jsx("code",{className:"flex-1 text-xs bg-gray-200 dark:bg-gray-900 text-gray-700 dark:text-gray-300 px-3 py-2 rounded font-mono overflow-x-auto",children:d}),h.jsx("button",{onClick:f,className:"text-gray-500 hover:text-gray-700 dark:hover:text-gray-300 transition-colors p-2",title:"Copy command",children:o?h.jsx("svg",{className:"w-5 h-5 text-green-500 dark:text-green-400",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",children:h.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M5 13l4 4L19 7"})}):h.jsx("svg",{className:"w-5 h-5",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",children:h.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M8 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 012 2v2m-6 12h8a2 2 0 002-2v-8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z"})})})]})]}),u&&h.jsx("div",{className:"rounded-lg p-3 bg-green-500/10 border border-green-500/20",children:h.jsxs("div",{className:"flex items-center gap-2 text-green-600 dark:text-green-400 text-sm",children:[h.jsx("svg",{className:"w-4 h-4",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",children:h.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M9 12l2 2 4-4m6 2a9 9 0 11-18 0 9 9 0 0118 0z"})}),"All required dependencies are installed. You can proceed."]})}),h.jsx(bs,{onBack:n,onNext:t,onCancel:r,nextLabel:"Next",showRetry:!u,onRetry:i})]})}function lw({dockerStatus:e,buildingImage:t,onBuildImage:n,onNext:r,onBack:i,onCancel:s}){return h.jsxs(be.div,{variants:ai,initial:"initial",animate:"animate",exit:"exit",transition:{duration:.2},children:[h.jsxs("div",{className:"mb-6",children:[h.jsx("h2",{className:"text-xl font-bold mb-1 text-gray-900 dark:text-white",children:"Cross-Platform Builds"}),h.jsx("p",{className:"text-sm text-gray-600 dark:text-gray-300",children:"Docker enables building for macOS, Windows, and Linux from any platform."})]}),h.jsx("div",{className:"bg-gray-100 dark:bg-gray-900/50 rounded-lg p-4 mb-6",children:h.jsxs("div",{className:"flex items-start gap-4",children:[h.jsx("div",{className:"w-12 h-12 rounded-xl bg-blue-500/20 flex items-center justify-center flex-shrink-0",children:h.jsx("svg",{className:"w-7 h-7",viewBox:"0 0 756.26 596.9",children:h.jsx("path",{fill:"#1d63ed",d:"M743.96,245.25c-18.54-12.48-67.26-17.81-102.68-8.27-1.91-35.28-20.1-65.01-53.38-90.95l-12.32-8.27-8.21,12.4c-16.14,24.5-22.94,57.14-20.53,86.81,1.9,18.28,8.26,38.83,20.53,53.74-46.1,26.74-88.59,20.67-276.77,20.67H.06c-.85,42.49,5.98,124.23,57.96,190.77,5.74,7.35,12.04,14.46,18.87,21.31,42.26,42.32,106.11,73.35,201.59,73.44,145.66.13,270.46-78.6,346.37-268.97,24.98.41,90.92,4.48,123.19-57.88.79-1.05,8.21-16.54,8.21-16.54l-12.3-8.27ZM189.67,206.39h-81.7v81.7h81.7v-81.7ZM295.22,206.39h-81.7v81.7h81.7v-81.7ZM400.77,206.39h-81.7v81.7h81.7v-81.7ZM506.32,206.39h-81.7v81.7h81.7v-81.7ZM84.12,206.39H2.42v81.7h81.7v-81.7ZM189.67,103.2h-81.7v81.7h81.7v-81.7ZM295.22,103.2h-81.7v81.7h81.7v-81.7ZM400.77,103.2h-81.7v81.7h81.7v-81.7ZM400.77,0h-81.7v81.7h81.7V0Z"})})}),h.jsxs("div",{className:"flex-1",children:[h.jsx("h3",{className:"font-medium text-gray-900 dark:text-white mb-1",children:"Docker Status"}),e?e.installed?e.running?e.imageBuilt?h.jsxs("div",{children:[h.jsxs("div",{className:"flex items-center gap-2 text-green-600 dark:text-green-400 text-sm mb-2",children:[h.jsx("span",{className:"w-2 h-2 rounded-full bg-green-500"}),"Ready for cross-platform builds"]}),h.jsxs("p",{className:"text-xs text-gray-500",children:["Docker ",e.version," • wails-cross image installed"]})]}):t?h.jsxs("div",{children:[h.jsxs("div",{className:"flex items-center gap-2 text-blue-500 dark:text-blue-400 text-sm mb-2",children:[h.jsx(be.span,{className:"w-3 h-3 border-2 border-blue-500 dark:border-blue-400 border-t-transparent rounded-full",animate:{rotate:360},transition:{duration:1,repeat:1/0,ease:"linear"}}),"Building wails-cross image... ",e.pullProgress,"%"]}),h.jsx("div",{className:"h-1.5 bg-gray-300 dark:bg-gray-700 rounded-full overflow-hidden",children:h.jsx(be.div,{className:"h-full bg-blue-500",animate:{width:`${e.pullProgress}%`}})})]}):h.jsxs("div",{children:[h.jsxs("div",{className:"flex items-center gap-2 text-gray-600 dark:text-gray-400 text-sm mb-2",children:[h.jsx("span",{className:"w-2 h-2 rounded-full bg-gray-400 dark:bg-gray-500"}),"Cross-compilation image not installed"]}),h.jsxs("p",{className:"text-xs text-gray-500 mb-3",children:["Docker ",e.version," is running. Build the wails-cross image to enable cross-platform builds."]}),h.jsx("button",{onClick:n,className:"text-sm px-4 py-2 rounded-lg bg-blue-500/20 text-blue-600 dark:text-blue-400 hover:bg-blue-500/30 transition-colors border border-blue-500/30",children:"Build Cross-Compilation Image"})]}):h.jsxs("div",{children:[h.jsxs("div",{className:"flex items-center gap-2 text-yellow-600 dark:text-yellow-400 text-sm mb-2",children:[h.jsx("span",{className:"w-2 h-2 rounded-full bg-yellow-500"}),"Installed but not running"]}),h.jsx("p",{className:"text-xs text-gray-500",children:"Start Docker Desktop to enable cross-platform builds."})]}):h.jsxs("div",{children:[h.jsxs("div",{className:"flex items-center gap-2 text-yellow-600 dark:text-yellow-400 text-sm mb-2",children:[h.jsx("span",{className:"w-2 h-2 rounded-full bg-yellow-500"}),"Not installed"]}),h.jsx("p",{className:"text-xs text-gray-500 mb-2",children:"Docker is optional but required for cross-platform builds."}),h.jsxs("a",{href:"https://docs.docker.com/get-docker/",target:"_blank",rel:"noopener noreferrer",className:"inline-flex items-center gap-1 text-xs text-blue-500 dark:text-blue-400 hover:text-blue-600 dark:hover:text-blue-300",children:["Install Docker Desktop",h.jsx("svg",{className:"w-3 h-3",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",children:h.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14"})})]})]}):h.jsx("div",{className:"text-sm text-gray-600 dark:text-gray-300",children:"Checking Docker..."})]})]})}),h.jsxs("div",{className:"bg-gray-100 dark:bg-gray-900/50 rounded-lg p-4",children:[h.jsx("h3",{className:"text-sm font-medium text-gray-600 dark:text-gray-400 mb-2",children:"What you can build:"}),h.jsxs("div",{className:"grid grid-cols-3 gap-4 text-center text-sm",children:[h.jsxs("div",{className:"py-2",children:[h.jsx("div",{className:"flex justify-center mb-2",children:h.jsx("svg",{className:"w-8 h-8 text-gray-700 dark:text-gray-300",viewBox:"0 0 24 24",fill:"currentColor",children:h.jsx("path",{d:"M18.71 19.5c-.83 1.24-1.71 2.45-3.05 2.47-1.34.03-1.77-.79-3.29-.79-1.53 0-2 .77-3.27.82-1.31.05-2.3-1.32-3.14-2.53C4.25 17 2.94 12.45 4.7 9.39c.87-1.52 2.43-2.48 4.12-2.51 1.28-.02 2.5.87 3.29.87.78 0 2.26-1.07 3.81-.91.65.03 2.47.26 3.64 1.98-.09.06-2.17 1.28-2.15 3.81.03 3.02 2.65 4.03 2.68 4.04-.03.07-.42 1.44-1.38 2.83M13 3.5c.73-.83 1.94-1.46 2.94-1.5.13 1.17-.34 2.35-1.04 3.19-.69.85-1.83 1.51-2.95 1.42-.15-1.15.41-2.35 1.05-3.11z"})})}),h.jsx("div",{className:"text-gray-700 dark:text-gray-300",children:"macOS"}),h.jsx("div",{className:"text-xs text-gray-500",children:".app / .dmg"})]}),h.jsxs("div",{className:"py-2",children:[h.jsx("div",{className:"flex justify-center mb-2",children:h.jsx("svg",{className:"w-8 h-8 text-gray-700 dark:text-gray-300",viewBox:"0 0 24 24",fill:"currentColor",children:h.jsx("path",{d:"M0 3.449L9.75 2.1v9.451H0m10.949-9.602L24 0v11.4H10.949M0 12.6h9.75v9.451L0 20.699M10.949 12.6H24V24l-12.9-1.801"})})}),h.jsx("div",{className:"text-gray-700 dark:text-gray-300",children:"Windows"}),h.jsx("div",{className:"text-xs text-gray-500",children:".exe / .msi"})]}),h.jsxs("div",{className:"py-2",children:[h.jsx("div",{className:"flex justify-center mb-2",children:h.jsx("svg",{className:"w-8 h-8",viewBox:"0 0 1024 1024",fill:"currentColor",children:h.jsx("path",{className:"text-gray-700 dark:text-gray-300",fillRule:"evenodd",clipRule:"evenodd",d:"M186.828,734.721c8.135,22.783-2.97,48.36-25.182,55.53c-12.773,4.121-27.021,5.532-40.519,5.145c-24.764-0.714-32.668,8.165-24.564,31.376c2.795,8.01,6.687,15.644,10.269,23.363c7.095,15.287,7.571,30.475-0.168,45.697c-2.572,5.057-5.055,10.168-7.402,15.337c-9.756,21.488-5.894,30.47,17.115,36.3c18.451,4.676,37.425,7.289,55.885,11.932c40.455,10.175,80.749,21,121.079,31.676c20.128,5.325,40.175,9.878,61.075,3.774c27.01-7.889,41.849-27.507,36.217-54.78c-4.359-21.112-10.586-43.132-21.634-61.314c-26.929-44.322-56.976-86.766-86.174-129.69c-5.666-8.329-12.819-15.753-19.905-22.987c-23.511-24.004-32.83-26.298-64.022-16.059c-7.589-15.327-5.198-31.395-2.56-47.076c1.384-8.231,4.291-16.796,8.718-23.821c18.812-29.824,29.767-62.909,41.471-95.738c13.545-37.999,30.87-73.47,57.108-105.131c21.607-26.074,38.626-55.982,57.303-84.44c6.678-10.173,6.803-21.535,6.23-33.787c-2.976-63.622-6.561-127.301-6.497-190.957c0.081-78.542,65.777-139.631,156.443-127.536c99.935,13.331,159.606,87.543,156.629,188.746c-2.679,91.191,27.38,170.682,89.727,239.686c62.132,68.767,91.194,153.119,96.435,245.38c0.649,11.46-1.686,23.648-5.362,34.583c-2.265,6.744-9.651,11.792-14.808,17.536c-6.984,7.781-14.497,15.142-20.959,23.328c-12.077,15.294-25.419,28.277-45.424,32.573c-30.163,6.475-50.177-2.901-63.81-30.468c-1.797-3.636-3.358-7.432-5.555-10.812c-5.027-7.741-10.067-18.974-20.434-15.568c-6.727,2.206-14.165,11.872-15.412,19.197c-2.738,16.079-5.699,33.882-1.532,49.047c11.975,43.604,9.224,86.688,3.062,130.371c-3.513,24.898-0.414,49.037,23.13,63.504c24.495,15.044,48.407,7.348,70.818-6.976c3.742-2.394,7.25-5.249,10.536-8.252c30.201-27.583,65.316-46.088,104.185-58.488c14.915-4.759,29.613-11.405,42.97-19.554c19.548-11.932,18.82-25.867-0.854-38.036c-7.187-4.445-14.944-8.5-22.984-10.933c-23.398-7.067-34.812-23.963-39.767-46.375c-3.627-16.398-4.646-32.782,4.812-51.731c1.689,10.577,2.771,17.974,4.062,25.334c5.242,29.945,20.805,52.067,48.321,66.04c8.869,4.5,17.161,10.973,24.191,18.055c10.372,10.447,10.407,22.541,0.899,33.911c-4.886,5.837-10.683,11.312-17.052,15.427c-11.894,7.685-23.962,15.532-36.92,21.056c-45.461,19.375-84.188,48.354-120.741,80.964c-19.707,17.582-44.202,15.855-68.188,13.395c-21.502-2.203-38.363-12.167-48.841-31.787c-6.008-11.251-15.755-18.053-28.35-18.262c-42.991-0.722-85.995-0.785-128.993-0.914c-8.92-0.026-17.842,0.962-26.769,1.1c-25.052,0.391-47.926,7.437-68.499,21.808c-5.987,4.186-12.068,8.24-17.954,12.562c-19.389,14.233-40.63,17.873-63.421,10.497c-25.827-8.353-51.076-18.795-77.286-25.591c-38.792-10.057-78.257-17.493-117.348-26.427c-43.557-9.959-51.638-24.855-33.733-65.298c8.605-19.435,8.812-38.251,3.55-58.078c-2.593-9.773-5.126-19.704-6.164-29.72c-1.788-17.258,4.194-24.958,21.341-27.812c12.367-2.059,25.069-2.132,37.423-4.255C165.996,776.175,182.158,759.821,186.828,734.721z M698.246,454.672c9.032,15.582,18.872,30.76,26.936,46.829c20.251,40.355,34.457,82.42,30.25,128.537c-0.871,9.573-2.975,19.332-6.354,28.313c-5.088,13.528-18.494,19.761-33.921,17.5c-13.708-2.007-15.566-12.743-16.583-23.462c-1.035-10.887-1.435-21.864-1.522-32.809c-0.314-39.017-7.915-76.689-22.456-112.7c-5.214-12.915-14.199-24.3-21.373-36.438c-2.792-4.72-6.521-9.291-7.806-14.435c-8.82-35.31-21.052-68.866-43.649-98.164c-11.154-14.454-14.638-31.432-9.843-49.572c1.656-6.269,3.405-12.527,4.695-18.875c3.127-15.406-1.444-22.62-15.969-28.01c-15.509-5.752-30.424-13.273-46.179-18.138c-12.963-4.001-15.764-12.624-15.217-23.948c0.31-6.432,0.895-13.054,2.767-19.159c3.27-10.672,9.56-18.74,21.976-19.737c12.983-1.044,22.973,4.218,28.695,16.137c5.661,11.8,6.941,23.856,1.772,36.459c-4.638,11.314-0.159,17.13,11.52,13.901c4.966-1.373,11.677-7.397,12.217-11.947c2.661-22.318,1.795-44.577-9.871-64.926c-11.181-19.503-31.449-27.798-52.973-21.69c-26.941,7.646-39.878,28.604-37.216,60.306c0.553,6.585,1.117,13.171,1.539,18.14c-15.463-1.116-29.71-2.144-44.146-3.184c-0.73-8.563-0.741-16.346-2.199-23.846c-1.843-9.481-3.939-19.118-7.605-27.993c-4.694-11.357-12.704-20.153-26.378-20.08c-13.304,0.074-20.082,9.253-25.192,19.894c-11.385,23.712-9.122,47.304,1.739,70.415c1.69,3.598,6.099,8.623,8.82,8.369c3.715-0.347,7.016-5.125,11.028-8.443c-17.322-9.889-25.172-30.912-16.872-46.754c3.016-5.758,10.86-10.391,17.474-12.498c8.076-2.575,15.881,2.05,18.515,10.112c3.214,9.837,4.66,20.323,6.051,30.641c0.337,2.494-1.911,6.161-4.06,8.031c-12.73,11.068-25.827,21.713-38.686,32.635c-2.754,2.339-5.533,4.917-7.455,7.921c-5.453,8.523-6.483,16.016,3.903,22.612c6.351,4.035,11.703,10.012,16.616,15.86c7.582,9.018,17.047,14.244,28.521,13.972c46.214-1.09,91.113-6.879,128.25-38.61c1.953-1.668,7.641-1.83,9.262-0.271c1.896,1.823,2.584,6.983,1.334,9.451c-1.418,2.797-5.315,4.806-8.555,6.139c-22.846,9.401-45.863,18.383-68.699,27.808c-22.67,9.355-45.875,13.199-70.216,8.43c-2.864-0.562-5.932-0.076-10.576-0.076c10.396,14.605,21.893,24.62,38.819,23.571c12.759-0.79,26.125-2.244,37.846-6.879c17.618-6.967,33.947-17.144,51.008-25.588c5.737-2.837,11.903-5.131,18.133-6.474c2.185-0.474,5.975,2.106,7.427,4.334c0.804,1.237-1.1,5.309-2.865,6.903c-2.953,2.667-6.796,4.339-10.227,6.488c-21.264,13.325-42.521,26.658-63.771,40.002c-8.235,5.17-16.098,11.071-24.745,15.408c-16.571,8.316-28.156,6.68-40.559-7.016c-10.026-11.072-18.225-23.792-27.376-35.669c-2.98-3.87-6.41-7.393-9.635-11.074c-1.543,26.454-14.954,46.662-26.272,67.665c-12.261,22.755-21.042,45.964-8.633,69.951c-4.075,4.752-7.722,8.13-10.332,12.18c-29.353,45.525-52.72,93.14-52.266,149.186c0.109,13.75-0.516,27.55-1.751,41.24c-0.342,3.793-3.706,9.89-6.374,10.287c-3.868,0.573-10.627-1.946-12.202-5.111c-6.939-13.938-14.946-28.106-17.81-43.101c-3.031-15.865-0.681-32.759-0.681-50.958c-2.558,5.441-5.907,9.771-6.539,14.466c-1.612,11.975-3.841,24.322-2.489,36.14c2.343,20.486,5.578,41.892,21.418,56.922c21.76,20.642,44.75,40.021,67.689,59.375c20.161,17.01,41.426,32.724,61.388,49.954c22.306,19.257,15.029,51.589-13.006,60.711c-2.144,0.697-4.25,1.513-8.117,2.9c20.918,28.527,40.528,56.508,38.477,93.371c23.886-27.406,2.287-47.712-10.241-69.677c6.972-6.97,12.504-8.75,21.861-1.923c10.471,7.639,23.112,15.599,35.46,16.822c62.957,6.229,123.157,2.18,163.56-57.379c2.57-3.788,8.177-5.519,12.37-8.205c1.981,4.603,5.929,9.354,5.596,13.78c-1.266,16.837-3.306,33.673-6.265,50.292c-1.978,11.097-6.572,21.71-8.924,32.766c-1.849,8.696,1.109,15.219,12.607,15.204c1.387-6.761,2.603-13.474,4.154-20.108c10.602-45.342,16.959-90.622,6.691-137.28c-3.4-15.454-2.151-32.381-0.526-48.377c2.256-22.174,12.785-32.192,33.649-37.142c2.765-0.654,6.489-3.506,7.108-6.002c4.621-18.597,18.218-26.026,35.236-28.913c19.98-3.386,39.191-0.066,59.491,10.485c-2.108-3.7-2.525-5.424-3.612-6.181c-8.573-5.968-17.275-11.753-25.307-17.164C776.523,585.58,758.423,514.082,698.246,454.672z M427.12,221.259c1.83-0.584,3.657-1.169,5.486-1.755c-2.37-7.733-4.515-15.555-7.387-23.097c-0.375-0.983-4.506-0.533-6.002-0.668C422.211,205.409,424.666,213.334,427.12,221.259z M565.116,212.853c5.3-12.117-1.433-21.592-14.086-20.792C555.663,198.899,560.315,205.768,565.116,212.853z"})})}),h.jsx("div",{className:"text-gray-700 dark:text-gray-300",children:"Linux"}),h.jsx("div",{className:"text-xs text-gray-500",children:".deb / .rpm / PKGBUILD"})]})]})]}),h.jsx(bs,{onBack:i,onNext:r,onCancel:s,nextLabel:"Next"})]})}function uw({defaults:e,onDefaultsChange:t,onNext:n,onBack:r,onCancel:i,saving:s}){var o,a,l,u,c,d,f,y,v,x;return h.jsxs(be.div,{variants:ai,initial:"initial",animate:"animate",exit:"exit",transition:{duration:.2},children:[h.jsxs("div",{className:"mb-3",children:[h.jsx("h2",{className:"text-lg font-bold mb-0.5 text-gray-900 dark:text-white",children:"Project Defaults"}),h.jsx("p",{className:"text-xs text-gray-600 dark:text-gray-300",children:"Configure defaults for new Wails projects."})]}),h.jsxs("div",{className:"bg-gray-100 dark:bg-gray-900/50 rounded-lg p-3 mb-3",children:[h.jsx("h3",{className:"text-[11px] font-medium text-gray-500 dark:text-gray-400 mb-2",children:"Author Information"}),h.jsxs("div",{className:"grid grid-cols-2 gap-2",children:[h.jsxs("div",{children:[h.jsx("label",{className:"block text-[10px] text-gray-500 mb-0.5",children:"Your Name"}),h.jsx("input",{type:"text",value:e.author.name,onChange:S=>t({...e,author:{...e.author,name:S.target.value}}),placeholder:"John Doe",className:"w-full bg-white dark:bg-gray-800 border border-gray-300 dark:border-gray-700 rounded px-2 py-1 text-xs text-gray-900 dark:text-gray-200 placeholder-gray-400 dark:placeholder-gray-600 focus:border-red-500 focus:outline-none"})]}),h.jsxs("div",{children:[h.jsx("label",{className:"block text-[10px] text-gray-500 mb-0.5",children:"Company"}),h.jsx("input",{type:"text",value:e.author.company,onChange:S=>t({...e,author:{...e.author,company:S.target.value}}),placeholder:"My Company",className:"w-full bg-white dark:bg-gray-800 border border-gray-300 dark:border-gray-700 rounded px-2 py-1 text-xs text-gray-900 dark:text-gray-200 placeholder-gray-400 dark:placeholder-gray-600 focus:border-red-500 focus:outline-none"})]})]})]}),h.jsxs("div",{className:"bg-gray-100 dark:bg-gray-900/50 rounded-lg p-3 mb-3",children:[h.jsx("h3",{className:"text-[11px] font-medium text-gray-500 dark:text-gray-400 mb-2",children:"Project Settings"}),h.jsxs("div",{className:"space-y-2",children:[h.jsxs("div",{className:"grid grid-cols-2 gap-2",children:[h.jsxs("div",{children:[h.jsx("label",{className:"block text-[10px] text-gray-500 mb-0.5",children:"Bundle ID Prefix"}),h.jsx("input",{type:"text",value:e.project.productIdentifierPrefix,onChange:S=>t({...e,project:{...e.project,productIdentifierPrefix:S.target.value}}),placeholder:"com.mycompany",className:"w-full bg-white dark:bg-gray-800 border border-gray-300 dark:border-gray-700 rounded px-2 py-1 text-xs text-gray-900 dark:text-gray-200 placeholder-gray-400 dark:placeholder-gray-600 focus:border-red-500 focus:outline-none font-mono"})]}),h.jsxs("div",{children:[h.jsx("label",{className:"block text-[10px] text-gray-500 mb-0.5",children:"Default Version"}),h.jsx("input",{type:"text",value:e.project.defaultVersion,onChange:S=>t({...e,project:{...e.project,defaultVersion:S.target.value}}),placeholder:"0.1.0",className:"w-full bg-white dark:bg-gray-800 border border-gray-300 dark:border-gray-700 rounded px-2 py-1 text-xs text-gray-900 dark:text-gray-200 placeholder-gray-400 dark:placeholder-gray-600 focus:border-red-500 focus:outline-none font-mono"})]})]}),h.jsxs("div",{children:[h.jsx("label",{className:"block text-[10px] text-gray-500 mb-0.5",children:"Default Template"}),h.jsxs("select",{value:e.project.defaultTemplate,onChange:S=>t({...e,project:{...e.project,defaultTemplate:S.target.value}}),className:"w-full bg-white dark:bg-gray-800 border border-gray-300 dark:border-gray-700 rounded px-2 py-1 text-xs text-gray-900 dark:text-gray-200 focus:border-red-500 focus:outline-none",children:[h.jsx("option",{value:"vanilla",children:"Vanilla (JavaScript)"}),h.jsx("option",{value:"vanilla-ts",children:"Vanilla (TypeScript)"}),h.jsx("option",{value:"react",children:"React"}),h.jsx("option",{value:"react-ts",children:"React (TypeScript)"}),h.jsx("option",{value:"react-swc",children:"React + SWC"}),h.jsx("option",{value:"react-swc-ts",children:"React + SWC (TypeScript)"}),h.jsx("option",{value:"preact",children:"Preact"}),h.jsx("option",{value:"preact-ts",children:"Preact (TypeScript)"}),h.jsx("option",{value:"svelte",children:"Svelte"}),h.jsx("option",{value:"svelte-ts",children:"Svelte (TypeScript)"}),h.jsx("option",{value:"solid",children:"Solid"}),h.jsx("option",{value:"solid-ts",children:"Solid (TypeScript)"}),h.jsx("option",{value:"lit",children:"Lit"}),h.jsx("option",{value:"lit-ts",children:"Lit (TypeScript)"}),h.jsx("option",{value:"vue",children:"Vue"}),h.jsx("option",{value:"vue-ts",children:"Vue (TypeScript)"})]})]})]})]}),h.jsxs("div",{className:"bg-gray-100 dark:bg-gray-900/50 rounded-lg p-3 mb-3",children:[h.jsxs("div",{className:"flex items-center gap-2 mb-1",children:[h.jsx("svg",{className:"w-4 h-4 text-gray-500 dark:text-gray-400",viewBox:"0 0 24 24",fill:"currentColor",children:h.jsx("path",{d:"M18.71 19.5c-.83 1.24-1.71 2.45-3.05 2.47-1.34.03-1.77-.79-3.29-.79-1.53 0-2 .77-3.27.82-1.31.05-2.3-1.32-3.14-2.53C4.25 17 2.94 12.45 4.7 9.39c.87-1.52 2.43-2.48 4.12-2.51 1.28-.02 2.5.87 3.29.87.78 0 2.26-1.07 3.81-.91.65.03 2.47.26 3.64 1.98-.09.06-2.17 1.28-2.15 3.81.03 3.02 2.65 4.03 2.68 4.04-.03.07-.42 1.44-1.38 2.83M13 3.5c.73-.83 1.94-1.46 2.94-1.5.13 1.17-.34 2.35-1.04 3.19-.69.85-1.83 1.51-2.95 1.42-.15-1.15.41-2.35 1.05-3.11z"})}),h.jsx("h3",{className:"text-[11px] font-medium text-gray-500 dark:text-gray-400",children:"macOS Code Signing"}),h.jsx("span",{className:"text-[9px] text-gray-400 dark:text-gray-500",children:"(optional)"})]}),h.jsx("p",{className:"text-[9px] text-gray-400 dark:text-gray-500 mb-2 ml-6",children:"These are public identifiers. App-specific passwords are stored securely in your Keychain."}),h.jsxs("div",{className:"space-y-2",children:[h.jsxs("div",{children:[h.jsx("label",{className:"block text-[10px] text-gray-500 mb-0.5",children:"Developer ID"}),h.jsx("input",{type:"text",value:((a=(o=e.signing)==null?void 0:o.macOS)==null?void 0:a.developerID)||"",onChange:S=>{var m,p,g,w,k,T;return t({...e,signing:{...e.signing,macOS:{...(m=e.signing)==null?void 0:m.macOS,developerID:S.target.value,appleID:((g=(p=e.signing)==null?void 0:p.macOS)==null?void 0:g.appleID)||"",teamID:((k=(w=e.signing)==null?void 0:w.macOS)==null?void 0:k.teamID)||""},windows:((T=e.signing)==null?void 0:T.windows)||{certificatePath:"",timestampServer:""}}})},placeholder:"Developer ID Application: John Doe (TEAMID)",className:"w-full bg-white dark:bg-gray-800 border border-gray-300 dark:border-gray-700 rounded px-2 py-1 text-xs text-gray-900 dark:text-gray-200 placeholder-gray-400 dark:placeholder-gray-600 focus:border-red-500 focus:outline-none font-mono"})]}),h.jsxs("div",{className:"grid grid-cols-2 gap-2",children:[h.jsxs("div",{children:[h.jsx("label",{className:"block text-[10px] text-gray-500 mb-0.5",children:"Apple ID"}),h.jsx("input",{type:"email",value:((u=(l=e.signing)==null?void 0:l.macOS)==null?void 0:u.appleID)||"",onChange:S=>{var m,p,g,w,k,T;return t({...e,signing:{...e.signing,macOS:{...(m=e.signing)==null?void 0:m.macOS,appleID:S.target.value,developerID:((g=(p=e.signing)==null?void 0:p.macOS)==null?void 0:g.developerID)||"",teamID:((k=(w=e.signing)==null?void 0:w.macOS)==null?void 0:k.teamID)||""},windows:((T=e.signing)==null?void 0:T.windows)||{certificatePath:"",timestampServer:""}}})},placeholder:"you@example.com",className:"w-full bg-white dark:bg-gray-800 border border-gray-300 dark:border-gray-700 rounded px-2 py-1 text-xs text-gray-900 dark:text-gray-200 placeholder-gray-400 dark:placeholder-gray-600 focus:border-red-500 focus:outline-none"})]}),h.jsxs("div",{children:[h.jsx("label",{className:"block text-[10px] text-gray-500 mb-0.5",children:"Team ID"}),h.jsx("input",{type:"text",value:((d=(c=e.signing)==null?void 0:c.macOS)==null?void 0:d.teamID)||"",onChange:S=>{var m,p,g,w,k,T;return t({...e,signing:{...e.signing,macOS:{...(m=e.signing)==null?void 0:m.macOS,teamID:S.target.value,developerID:((g=(p=e.signing)==null?void 0:p.macOS)==null?void 0:g.developerID)||"",appleID:((k=(w=e.signing)==null?void 0:w.macOS)==null?void 0:k.appleID)||""},windows:((T=e.signing)==null?void 0:T.windows)||{certificatePath:"",timestampServer:""}}})},placeholder:"ABCD1234EF",className:"w-full bg-white dark:bg-gray-800 border border-gray-300 dark:border-gray-700 rounded px-2 py-1 text-xs text-gray-900 dark:text-gray-200 placeholder-gray-400 dark:placeholder-gray-600 focus:border-red-500 focus:outline-none font-mono"})]})]})]})]}),h.jsxs("div",{className:"bg-gray-100 dark:bg-gray-900/50 rounded-lg p-3 mb-3",children:[h.jsxs("div",{className:"flex items-center gap-2 mb-2",children:[h.jsx("svg",{className:"w-4 h-4 text-gray-500 dark:text-gray-400",viewBox:"0 0 24 24",fill:"currentColor",children:h.jsx("path",{d:"M0 3.449L9.75 2.1v9.451H0m10.949-9.602L24 0v11.4H10.949M0 12.6h9.75v9.451L0 20.699M10.949 12.6H24V24l-12.9-1.801"})}),h.jsx("h3",{className:"text-[11px] font-medium text-gray-500 dark:text-gray-400",children:"Windows Code Signing"}),h.jsx("span",{className:"text-[9px] text-gray-400 dark:text-gray-500",children:"(optional)"})]}),h.jsxs("div",{className:"space-y-2",children:[h.jsxs("div",{children:[h.jsx("label",{className:"block text-[10px] text-gray-500 mb-0.5",children:"Certificate Path (.pfx)"}),h.jsx("input",{type:"text",value:((y=(f=e.signing)==null?void 0:f.windows)==null?void 0:y.certificatePath)||"",onChange:S=>{var m,p,g,w;return t({...e,signing:{...e.signing,macOS:((m=e.signing)==null?void 0:m.macOS)||{developerID:"",appleID:"",teamID:""},windows:{...(p=e.signing)==null?void 0:p.windows,certificatePath:S.target.value,timestampServer:((w=(g=e.signing)==null?void 0:g.windows)==null?void 0:w.timestampServer)||""}}})},placeholder:"/path/to/certificate.pfx",className:"w-full bg-white dark:bg-gray-800 border border-gray-300 dark:border-gray-700 rounded px-2 py-1 text-xs text-gray-900 dark:text-gray-200 placeholder-gray-400 dark:placeholder-gray-600 focus:border-red-500 focus:outline-none font-mono"})]}),h.jsxs("div",{children:[h.jsx("label",{className:"block text-[10px] text-gray-500 mb-0.5",children:"Timestamp Server"}),h.jsx("input",{type:"text",value:((x=(v=e.signing)==null?void 0:v.windows)==null?void 0:x.timestampServer)||"",onChange:S=>{var m,p,g,w;return t({...e,signing:{...e.signing,macOS:((m=e.signing)==null?void 0:m.macOS)||{developerID:"",appleID:"",teamID:""},windows:{...(p=e.signing)==null?void 0:p.windows,timestampServer:S.target.value,certificatePath:((w=(g=e.signing)==null?void 0:g.windows)==null?void 0:w.certificatePath)||""}}})},placeholder:"http://timestamp.digicert.com",className:"w-full bg-white dark:bg-gray-800 border border-gray-300 dark:border-gray-700 rounded px-2 py-1 text-xs text-gray-900 dark:text-gray-200 placeholder-gray-400 dark:placeholder-gray-600 focus:border-red-500 focus:outline-none font-mono"})]})]})]}),h.jsxs("div",{className:"text-[10px] text-gray-500 dark:text-gray-600 mb-3",children:[h.jsx("span",{className:"text-gray-400 dark:text-gray-500",children:"Stored in:"})," ~/.config/wails/defaults.yaml"]}),h.jsx(bs,{onBack:r,onNext:n,onCancel:i,nextLabel:s?"Saving...":"Finish",nextDisabled:s})]})}function cw({status:e,visible:t}){if(!t||!e||!e.installed||!e.running||e.imageBuilt&&e.pullStatus!=="pulling")return null;const n=e.pullStatus==="pulling",r=e.pullProgress||0;return h.jsx(be.div,{initial:{opacity:0,y:-10},animate:{opacity:1,y:0},exit:{opacity:0,y:-10},className:"fixed top-4 right-4 z-50",children:h.jsx("div",{className:"bg-white/95 dark:bg-gray-900/95 border border-gray-200 dark:border-gray-700 rounded-lg shadow-xl px-4 py-3 backdrop-blur-sm min-w-[240px]",children:h.jsxs("div",{className:"flex items-center gap-3",children:[h.jsx("div",{className:"w-8 h-8 rounded-lg bg-blue-500/20 flex items-center justify-center flex-shrink-0",children:h.jsx("svg",{className:"w-5 h-5",viewBox:"0 0 756.26 596.9",children:h.jsx("path",{fill:"#1d63ed",d:"M743.96,245.25c-18.54-12.48-67.26-17.81-102.68-8.27-1.91-35.28-20.1-65.01-53.38-90.95l-12.32-8.27-8.21,12.4c-16.14,24.5-22.94,57.14-20.53,86.81,1.9,18.28,8.26,38.83,20.53,53.74-46.1,26.74-88.59,20.67-276.77,20.67H.06c-.85,42.49,5.98,124.23,57.96,190.77,5.74,7.35,12.04,14.46,18.87,21.31,42.26,42.32,106.11,73.35,201.59,73.44,145.66.13,270.46-78.6,346.37-268.97,24.98.41,90.92,4.48,123.19-57.88.79-1.05,8.21-16.54,8.21-16.54l-12.3-8.27Z"})})}),h.jsx("div",{className:"flex-1 min-w-0",children:n?h.jsxs(h.Fragment,{children:[h.jsxs("div",{className:"flex items-center gap-2 text-blue-600 dark:text-blue-400 text-sm mb-1",children:[h.jsx(be.span,{className:"w-3 h-3 border-2 border-blue-600 dark:border-blue-400 border-t-transparent rounded-full",animate:{rotate:360},transition:{duration:1,repeat:1/0,ease:"linear"}}),h.jsx("span",{className:"truncate",children:"Downloading cross-compile image..."})]}),h.jsxs("div",{className:"flex items-center gap-2",children:[h.jsx("div",{className:"flex-1 h-1.5 bg-gray-200 dark:bg-gray-700 rounded-full overflow-hidden",children:h.jsx(be.div,{className:"h-full bg-blue-500",animate:{width:`${r}%`}})}),h.jsxs("span",{className:"text-xs text-gray-500 tabular-nums",children:[r,"%"]})]})]}):e.imageBuilt?h.jsxs("div",{className:"flex items-center gap-2 text-green-600 dark:text-green-400 text-sm",children:[h.jsx("svg",{className:"w-4 h-4",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",children:h.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M5 13l4 4L19 7"})}),h.jsx("span",{children:"Docker image ready"})]}):h.jsx("div",{className:"text-sm text-gray-600 dark:text-gray-400",children:"Preparing Docker build..."})})]})})})}function Ro({command:e,label:t}){const[n,r]=N.useState(!1),i=()=>{navigator.clipboard.writeText(e),r(!0),setTimeout(()=>r(!1),2e3)};return h.jsxs("div",{children:[h.jsx("p",{className:"text-gray-600 dark:text-gray-400 mb-1",children:t}),h.jsxs("div",{className:"flex items-center gap-2",children:[h.jsx("code",{className:"flex-1 text-green-600 dark:text-green-400 font-mono text-xs bg-gray-100 dark:bg-gray-900 px-2 py-1 rounded",children:e}),h.jsx("button",{onClick:i,className:"text-gray-500 hover:text-gray-700 dark:hover:text-gray-300 transition-colors p-1",title:"Copy command",children:n?h.jsx("svg",{className:"w-4 h-4 text-green-600 dark:text-green-400",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",children:h.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M5 13l4 4L19 7"})}):h.jsx("svg",{className:"w-4 h-4",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",children:h.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M8 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 012 2v2m-6 12h8a2 2 0 002-2v-8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z"})})})]})]})}function dw({onClose:e}){return h.jsxs(be.div,{variants:ai,initial:"initial",animate:"animate",exit:"exit",transition:{duration:.2},className:"text-center py-8",children:[h.jsx(be.div,{initial:{scale:0},animate:{scale:1},transition:{type:"spring",stiffness:200,damping:15},className:"w-16 h-16 rounded-full bg-green-500/20 flex items-center justify-center mx-auto mb-6",children:h.jsx("svg",{className:"w-8 h-8 text-green-600 dark:text-green-400",fill:"none",viewBox:"0 0 24 24",stroke:"currentColor",children:h.jsx("path",{strokeLinecap:"round",strokeLinejoin:"round",strokeWidth:2,d:"M5 13l4 4L19 7"})})}),h.jsx("h2",{className:"text-2xl font-bold mb-2 text-gray-900 dark:text-white",children:"Setup Complete"}),h.jsx("p",{className:"text-gray-600 dark:text-gray-300 mb-8",children:"Your development environment is ready to use."}),h.jsxs("div",{className:"bg-gray-100 dark:bg-gray-900/50 rounded-lg p-4 text-left mb-6 max-w-sm mx-auto",children:[h.jsx("h3",{className:"text-sm font-medium text-gray-600 dark:text-gray-400 mb-3",children:"Next Steps"}),h.jsxs("div",{className:"space-y-3 text-sm",children:[h.jsx(Ro,{command:"wails3 init -n myapp",label:"Create a new project:"}),h.jsx(Ro,{command:"wails3 dev",label:"Start development server:"}),h.jsx(Ro,{command:"wails3 build",label:"Build for production:"})]})]}),h.jsx("button",{onClick:e,className:"px-6 py-2.5 rounded-lg bg-red-600 text-white font-medium hover:bg-red-500 transition-colors",children:"Close"})]})}function fw(){const[e,t]=N.useState("welcome"),[n,r]=N.useState([]),[i,s]=N.useState(null),[o,a]=N.useState(null),[l,u]=N.useState(!1),[c,d]=N.useState(!1),[f,y]=N.useState({author:{name:"",company:""},project:{productIdentifierPrefix:"com.example",defaultTemplate:"vanilla",copyrightTemplate:"© {year}, {company}",descriptionTemplate:"A {name} application",defaultVersion:"0.1.0"}}),[v,x]=N.useState(!1),[S,m]=N.useState(!1),[p,g]=N.useState(()=>{if(typeof window<"u"){const F=localStorage.getItem("wails-setup-theme");if(F==="light"||F==="dark")return F;if(window.matchMedia("(prefers-color-scheme: light)").matches)return"light"}return"dark"}),w=()=>{g(F=>{const se=F==="dark"?"light":"dark";return localStorage.setItem("wails-setup-theme",se),se})};N.useEffect(()=>{p==="dark"?document.documentElement.classList.add("dark"):document.documentElement.classList.remove("dark")},[p]);const k=[{id:"welcome",label:"Welcome"},{id:"dependencies",label:"Dependencies"},{id:"docker",label:"Docker"},{id:"defaults",label:"Defaults"},{id:"complete",label:"Complete"}];N.useEffect(()=>{T()},[]);const T=async()=>{const F=await G2();s(F.system)},P=async()=>{if(e==="welcome"){d(!0);const F=await Kd();r(F),d(!1),t("dependencies")}else if(e==="dependencies"){const F=n.find(se=>se.name==="docker");if(F!=null&&F.installed){const se=await Vo();a(se),X(n)}t("docker")}else if(e==="docker"){const F=await Z2();y(F),t("defaults")}else e==="defaults"&&(x(!0),await q2(f),x(!1),t("complete"))},C=async()=>{d(!0);const F=await Kd();r(F),d(!1)},R=()=>{e==="dependencies"?t("welcome"):e==="docker"?t("dependencies"):e==="defaults"&&t("docker")},M=async()=>{u(!0),await Q2();const F=async()=>{const se=await Vo();a(se),se.pullStatus==="pulling"?setTimeout(F,1e3):u(!1)};F()},X=async F=>{const se=F.find(E=>E.name==="docker");if(!(se!=null&&se.installed)||S)return;m(!0);const B=await Y2();if(a(B.status),B.started&&B.status.pullStatus==="pulling"){u(!0);const E=async()=>{const L=await Vo();a(L),L.pullStatus==="pulling"?setTimeout(E,1e3):u(!1)};setTimeout(E,1e3)}},Ke=async()=>{await X2(),window.close()},Ie=Ke,kt=S&&e==="defaults";return h.jsx(Fm.Provider,{value:{theme:p,toggleTheme:w},children:h.jsxs("div",{className:"min-h-screen bg-gray-50 dark:bg-[#0f0f0f] flex items-center justify-center p-4 transition-colors",children:[h.jsx(rw,{}),h.jsx(Jc,{children:kt&&h.jsx(cw,{status:o,visible:kt})}),h.jsxs("div",{className:"w-full max-w-lg",children:[h.jsxs("div",{className:"flex flex-col items-center mb-4",children:[h.jsx(tw,{size:160,theme:p}),h.jsx("div",{className:"mt-3",children:h.jsx(iw,{steps:k,currentStep:e})})]}),h.jsx("div",{className:"bg-white dark:bg-gray-900/80 border border-gray-200 dark:border-gray-800 rounded-xl p-5 shadow-2xl max-h-[70vh] overflow-y-auto",children:h.jsxs(Jc,{mode:"wait",children:[e==="welcome"&&h.jsx(sw,{system:i,onNext:P,onCancel:Ie,checking:c},"welcome"),e==="dependencies"&&h.jsx(aw,{dependencies:n,onNext:P,onBack:R,onCancel:Ie,onRetry:C,checking:c},"dependencies"),e==="defaults"&&h.jsx(uw,{defaults:f,onDefaultsChange:y,onNext:P,onBack:R,onCancel:Ie,saving:v},"defaults"),e==="docker"&&h.jsx(lw,{dockerStatus:o,buildingImage:l,onBuildImage:M,onNext:P,onBack:R,onCancel:Ie},"docker"),e==="complete"&&h.jsx(dw,{onClose:Ke},"complete")]})}),h.jsx("div",{className:"text-center mt-4 text-xs text-gray-500 dark:text-gray-600",children:"Wails • Build cross-platform apps with Go"})]})]})})}Io.createRoot(document.getElementById("root")).render(h.jsx(t0.StrictMode,{children:h.jsx(fw,{})})); diff --git a/v3/internal/setupwizard/frontend/dist/assets/index-CCNHCwJO.css b/v3/internal/setupwizard/frontend/dist/assets/index-CCNHCwJO.css deleted file mode 100644 index d08fa080b..000000000 --- a/v3/internal/setupwizard/frontend/dist/assets/index-CCNHCwJO.css +++ /dev/null @@ -1 +0,0 @@ -*,:before,:after{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }::backdrop{--tw-border-spacing-x: 0;--tw-border-spacing-y: 0;--tw-translate-x: 0;--tw-translate-y: 0;--tw-rotate: 0;--tw-skew-x: 0;--tw-skew-y: 0;--tw-scale-x: 1;--tw-scale-y: 1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness: proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width: 0px;--tw-ring-offset-color: #fff;--tw-ring-color: rgb(59 130 246 / .5);--tw-ring-offset-shadow: 0 0 #0000;--tw-ring-shadow: 0 0 #0000;--tw-shadow: 0 0 #0000;--tw-shadow-colored: 0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: ;--tw-contain-size: ;--tw-contain-layout: ;--tw-contain-paint: ;--tw-contain-style: }*,:before,:after{box-sizing:border-box;border-width:0;border-style:solid;border-color:#e5e7eb}:before,:after{--tw-content: ""}html,:host{line-height:1.5;-webkit-text-size-adjust:100%;-moz-tab-size:4;-o-tab-size:4;tab-size:4;font-family:Inter,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,sans-serif;font-feature-settings:normal;font-variation-settings:normal;-webkit-tap-highlight-color:transparent}body{margin:0;line-height:inherit}hr{height:0;color:inherit;border-top-width:1px}abbr:where([title]){-webkit-text-decoration:underline dotted;text-decoration:underline dotted}h1,h2,h3,h4,h5,h6{font-size:inherit;font-weight:inherit}a{color:inherit;text-decoration:inherit}b,strong{font-weight:bolder}code,kbd,samp,pre{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace;font-feature-settings:normal;font-variation-settings:normal;font-size:1em}small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}sub{bottom:-.25em}sup{top:-.5em}table{text-indent:0;border-color:inherit;border-collapse:collapse}button,input,optgroup,select,textarea{font-family:inherit;font-feature-settings:inherit;font-variation-settings:inherit;font-size:100%;font-weight:inherit;line-height:inherit;letter-spacing:inherit;color:inherit;margin:0;padding:0}button,select{text-transform:none}button,input:where([type=button]),input:where([type=reset]),input:where([type=submit]){-webkit-appearance:button;background-color:transparent;background-image:none}:-moz-focusring{outline:auto}:-moz-ui-invalid{box-shadow:none}progress{vertical-align:baseline}::-webkit-inner-spin-button,::-webkit-outer-spin-button{height:auto}[type=search]{-webkit-appearance:textfield;outline-offset:-2px}::-webkit-search-decoration{-webkit-appearance:none}::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}summary{display:list-item}blockquote,dl,dd,h1,h2,h3,h4,h5,h6,hr,figure,p,pre{margin:0}fieldset{margin:0;padding:0}legend{padding:0}ol,ul,menu{list-style:none;margin:0;padding:0}dialog{padding:0}textarea{resize:vertical}input::-moz-placeholder,textarea::-moz-placeholder{opacity:1;color:#9ca3af}input::placeholder,textarea::placeholder{opacity:1;color:#9ca3af}button,[role=button]{cursor:pointer}:disabled{cursor:default}img,svg,video,canvas,audio,iframe,embed,object{display:block;vertical-align:middle}img,video{max-width:100%;height:auto}[hidden]:where(:not([hidden=until-found])){display:none}.container{width:100%}@media (min-width: 640px){.container{max-width:640px}}@media (min-width: 768px){.container{max-width:768px}}@media (min-width: 1024px){.container{max-width:1024px}}@media (min-width: 1280px){.container{max-width:1280px}}@media (min-width: 1536px){.container{max-width:1536px}}.\!visible{visibility:visible!important}.visible{visibility:visible}.fixed{position:fixed}.absolute{position:absolute}.relative{position:relative}.inset-0{top:0;right:0;bottom:0;left:0}.left-4{left:1rem}.right-4{right:1rem}.top-4{top:1rem}.z-10{z-index:10}.z-50{z-index:50}.mx-1\.5{margin-left:.375rem;margin-right:.375rem}.mx-auto{margin-left:auto;margin-right:auto}.mb-0\.5{margin-bottom:.125rem}.mb-1{margin-bottom:.25rem}.mb-2{margin-bottom:.5rem}.mb-3{margin-bottom:.75rem}.mb-4{margin-bottom:1rem}.mb-6{margin-bottom:1.5rem}.mb-8{margin-bottom:2rem}.ml-6{margin-left:1.5rem}.mt-0\.5{margin-top:.125rem}.mt-1{margin-top:.25rem}.mt-3{margin-top:.75rem}.mt-4{margin-top:1rem}.block{display:block}.flex{display:flex}.inline-flex{display:inline-flex}.grid{display:grid}.h-1\.5{height:.375rem}.h-12{height:3rem}.h-16{height:4rem}.h-2{height:.5rem}.h-2\.5{height:.625rem}.h-3{height:.75rem}.h-4{height:1rem}.h-5{height:1.25rem}.h-6{height:1.5rem}.h-7{height:1.75rem}.h-8{height:2rem}.h-full{height:100%}.max-h-\[70vh\]{max-height:70vh}.min-h-screen{min-height:100vh}.w-1\.5{width:.375rem}.w-12{width:3rem}.w-16{width:4rem}.w-2{width:.5rem}.w-2\.5{width:.625rem}.w-3{width:.75rem}.w-4{width:1rem}.w-5{width:1.25rem}.w-6{width:1.5rem}.w-7{width:1.75rem}.w-8{width:2rem}.w-full{width:100%}.min-w-0{min-width:0px}.min-w-\[240px\]{min-width:240px}.max-w-lg{max-width:32rem}.max-w-sm{max-width:24rem}.flex-1{flex:1 1 0%}.flex-shrink-0{flex-shrink:0}.animate-spin{animation:spin 1s linear infinite}.cursor-not-allowed{cursor:not-allowed}.grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}.grid-cols-3{grid-template-columns:repeat(3,minmax(0,1fr))}.flex-col{flex-direction:column}.items-start{align-items:flex-start}.items-center{align-items:center}.justify-center{justify-content:center}.justify-between{justify-content:space-between}.gap-1{gap:.25rem}.gap-1\.5{gap:.375rem}.gap-2{gap:.5rem}.gap-3{gap:.75rem}.gap-4{gap:1rem}.gap-y-1\.5{row-gap:.375rem}.space-y-1>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.25rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.25rem * var(--tw-space-y-reverse))}.space-y-2>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.5rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.5rem * var(--tw-space-y-reverse))}.space-y-3>:not([hidden])~:not([hidden]){--tw-space-y-reverse: 0;margin-top:calc(.75rem * calc(1 - var(--tw-space-y-reverse)));margin-bottom:calc(.75rem * var(--tw-space-y-reverse))}.overflow-hidden{overflow:hidden}.overflow-x-auto{overflow-x:auto}.overflow-y-auto{overflow-y:auto}.truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.rounded{border-radius:.25rem}.rounded-full{border-radius:9999px}.rounded-lg{border-radius:.5rem}.rounded-md{border-radius:.375rem}.rounded-xl{border-radius:.75rem}.border{border-width:1px}.border-2{border-width:2px}.border-b{border-bottom-width:1px}.border-t{border-top-width:1px}.border-blue-500{--tw-border-opacity: 1;border-color:rgb(59 130 246 / var(--tw-border-opacity, 1))}.border-blue-500\/30{border-color:#3b82f64d}.border-blue-600{--tw-border-opacity: 1;border-color:rgb(37 99 235 / var(--tw-border-opacity, 1))}.border-gray-200{--tw-border-opacity: 1;border-color:rgb(229 231 235 / var(--tw-border-opacity, 1))}.border-gray-200\/50{border-color:#e5e7eb80}.border-gray-300{--tw-border-opacity: 1;border-color:rgb(209 213 219 / var(--tw-border-opacity, 1))}.border-gray-400{--tw-border-opacity: 1;border-color:rgb(156 163 175 / var(--tw-border-opacity, 1))}.border-green-500\/20{border-color:#22c55e33}.border-t-red-500{--tw-border-opacity: 1;border-top-color:rgb(239 68 68 / var(--tw-border-opacity, 1))}.border-t-transparent{border-top-color:transparent}.bg-blue-500{--tw-bg-opacity: 1;background-color:rgb(59 130 246 / var(--tw-bg-opacity, 1))}.bg-blue-500\/20{background-color:#3b82f633}.bg-blue-600{--tw-bg-opacity: 1;background-color:rgb(37 99 235 / var(--tw-bg-opacity, 1))}.bg-gray-100{--tw-bg-opacity: 1;background-color:rgb(243 244 246 / var(--tw-bg-opacity, 1))}.bg-gray-200{--tw-bg-opacity: 1;background-color:rgb(229 231 235 / var(--tw-bg-opacity, 1))}.bg-gray-300{--tw-bg-opacity: 1;background-color:rgb(209 213 219 / var(--tw-bg-opacity, 1))}.bg-gray-400{--tw-bg-opacity: 1;background-color:rgb(156 163 175 / var(--tw-bg-opacity, 1))}.bg-gray-400\/20{background-color:#9ca3af33}.bg-gray-50{--tw-bg-opacity: 1;background-color:rgb(249 250 251 / var(--tw-bg-opacity, 1))}.bg-green-500{--tw-bg-opacity: 1;background-color:rgb(34 197 94 / var(--tw-bg-opacity, 1))}.bg-green-500\/10{background-color:#22c55e1a}.bg-green-500\/20{background-color:#22c55e33}.bg-red-500\/20{background-color:#ef444433}.bg-red-600{--tw-bg-opacity: 1;background-color:rgb(220 38 38 / var(--tw-bg-opacity, 1))}.bg-white{--tw-bg-opacity: 1;background-color:rgb(255 255 255 / var(--tw-bg-opacity, 1))}.bg-white\/80{background-color:#fffc}.bg-white\/95{background-color:#fffffff2}.bg-yellow-500{--tw-bg-opacity: 1;background-color:rgb(234 179 8 / var(--tw-bg-opacity, 1))}.object-contain{-o-object-fit:contain;object-fit:contain}.p-1{padding:.25rem}.p-2{padding:.5rem}.p-3{padding:.75rem}.p-4{padding:1rem}.p-5{padding:1.25rem}.px-2{padding-left:.5rem;padding-right:.5rem}.px-3{padding-left:.75rem;padding-right:.75rem}.px-4{padding-left:1rem;padding-right:1rem}.px-6{padding-left:1.5rem;padding-right:1.5rem}.py-1{padding-top:.25rem;padding-bottom:.25rem}.py-1\.5{padding-top:.375rem;padding-bottom:.375rem}.py-2{padding-top:.5rem;padding-bottom:.5rem}.py-2\.5{padding-top:.625rem;padding-bottom:.625rem}.py-3{padding-top:.75rem;padding-bottom:.75rem}.py-8{padding-top:2rem;padding-bottom:2rem}.pt-4{padding-top:1rem}.text-left{text-align:left}.text-center{text-align:center}.font-mono{font-family:ui-monospace,SFMono-Regular,Menlo,Monaco,Consolas,Liberation Mono,Courier New,monospace}.text-2xl{font-size:1.5rem;line-height:2rem}.text-\[10px\]{font-size:10px}.text-\[11px\]{font-size:11px}.text-\[9px\]{font-size:9px}.text-lg{font-size:1.125rem;line-height:1.75rem}.text-sm{font-size:.875rem;line-height:1.25rem}.text-xl{font-size:1.25rem;line-height:1.75rem}.text-xs{font-size:.75rem;line-height:1rem}.font-bold{font-weight:700}.font-medium{font-weight:500}.tabular-nums{--tw-numeric-spacing: tabular-nums;font-variant-numeric:var(--tw-ordinal) var(--tw-slashed-zero) var(--tw-numeric-figure) var(--tw-numeric-spacing) var(--tw-numeric-fraction)}.text-blue-500{--tw-text-opacity: 1;color:rgb(59 130 246 / var(--tw-text-opacity, 1))}.text-blue-600{--tw-text-opacity: 1;color:rgb(37 99 235 / var(--tw-text-opacity, 1))}.text-gray-400{--tw-text-opacity: 1;color:rgb(156 163 175 / var(--tw-text-opacity, 1))}.text-gray-500{--tw-text-opacity: 1;color:rgb(107 114 128 / var(--tw-text-opacity, 1))}.text-gray-600{--tw-text-opacity: 1;color:rgb(75 85 99 / var(--tw-text-opacity, 1))}.text-gray-700{--tw-text-opacity: 1;color:rgb(55 65 81 / var(--tw-text-opacity, 1))}.text-gray-900{--tw-text-opacity: 1;color:rgb(17 24 39 / var(--tw-text-opacity, 1))}.text-green-500{--tw-text-opacity: 1;color:rgb(34 197 94 / var(--tw-text-opacity, 1))}.text-green-600{--tw-text-opacity: 1;color:rgb(22 163 74 / var(--tw-text-opacity, 1))}.text-red-500{--tw-text-opacity: 1;color:rgb(239 68 68 / var(--tw-text-opacity, 1))}.text-red-600{--tw-text-opacity: 1;color:rgb(220 38 38 / var(--tw-text-opacity, 1))}.text-white{--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity, 1))}.text-yellow-500{--tw-text-opacity: 1;color:rgb(234 179 8 / var(--tw-text-opacity, 1))}.text-yellow-600{--tw-text-opacity: 1;color:rgb(202 138 4 / var(--tw-text-opacity, 1))}.placeholder-gray-400::-moz-placeholder{--tw-placeholder-opacity: 1;color:rgb(156 163 175 / var(--tw-placeholder-opacity, 1))}.placeholder-gray-400::placeholder{--tw-placeholder-opacity: 1;color:rgb(156 163 175 / var(--tw-placeholder-opacity, 1))}.shadow-2xl{--tw-shadow: 0 25px 50px -12px rgb(0 0 0 / .25);--tw-shadow-colored: 0 25px 50px -12px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.shadow-xl{--tw-shadow: 0 20px 25px -5px rgb(0 0 0 / .1), 0 8px 10px -6px rgb(0 0 0 / .1);--tw-shadow-colored: 0 20px 25px -5px var(--tw-shadow-color), 0 8px 10px -6px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow)}.drop-shadow{--tw-drop-shadow: drop-shadow(0 1px 2px rgb(0 0 0 / .1)) drop-shadow(0 1px 1px rgb(0 0 0 / .06));filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.backdrop-blur-sm{--tw-backdrop-blur: blur(4px);-webkit-backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia);backdrop-filter:var(--tw-backdrop-blur) var(--tw-backdrop-brightness) var(--tw-backdrop-contrast) var(--tw-backdrop-grayscale) var(--tw-backdrop-hue-rotate) var(--tw-backdrop-invert) var(--tw-backdrop-opacity) var(--tw-backdrop-saturate) var(--tw-backdrop-sepia)}.transition{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke,opacity,box-shadow,transform,filter,backdrop-filter;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}.transition-colors{transition-property:color,background-color,border-color,text-decoration-color,fill,stroke;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.15s}:root{--wails-red: #ef4444;--wails-red-dark: #dc2626;--wails-red-light: #f87171;--bg-primary: #0f0f0f;--bg-secondary: #1f2937;--bg-tertiary: #374151}*{box-sizing:border-box}html,body,#root{margin:0;padding:0;min-height:100vh;background:var(--bg-primary);color:#fff;font-family:Inter,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.gradient-text{background:linear-gradient(135deg,#fff,#ef4444);-webkit-background-clip:text;-webkit-text-fill-color:transparent;background-clip:text}.glass-card{background:#1f2937cc;-webkit-backdrop-filter:blur(10px);backdrop-filter:blur(10px);border:1px solid rgba(55,65,81,.5)}.grid-bg{background-image:linear-gradient(rgba(239,68,68,.03) 1px,transparent 1px),linear-gradient(90deg,rgba(239,68,68,.03) 1px,transparent 1px);background-size:40px 40px}.radial-glow{background:radial-gradient(ellipse at center,rgba(239,68,68,.1) 0%,transparent 70%)}::-webkit-scrollbar{width:8px}::-webkit-scrollbar-track{background:var(--bg-primary)}::-webkit-scrollbar-thumb{background:var(--bg-tertiary);border-radius:4px}::-webkit-scrollbar-thumb:hover{background:#4b5563}.btn-primary{border-radius:.75rem;background-image:linear-gradient(to right,var(--tw-gradient-stops));--tw-gradient-from: #ef4444 var(--tw-gradient-from-position);--tw-gradient-to: rgb(239 68 68 / 0) var(--tw-gradient-to-position);--tw-gradient-stops: var(--tw-gradient-from), var(--tw-gradient-to);--tw-gradient-to: #dc2626 var(--tw-gradient-to-position);padding:.75rem 2rem;font-weight:600;--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity, 1));--tw-shadow: 0 10px 15px -3px rgb(0 0 0 / .1), 0 4px 6px -4px rgb(0 0 0 / .1);--tw-shadow-colored: 0 10px 15px -3px var(--tw-shadow-color), 0 4px 6px -4px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow);transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.3s}.btn-primary:hover{--tw-scale-x: 1.05;--tw-scale-y: 1.05;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y));--tw-shadow: 0 20px 25px -5px rgb(0 0 0 / .1), 0 8px 10px -6px rgb(0 0 0 / .1);--tw-shadow-colored: 0 20px 25px -5px var(--tw-shadow-color), 0 8px 10px -6px var(--tw-shadow-color);box-shadow:var(--tw-ring-offset-shadow, 0 0 #0000),var(--tw-ring-shadow, 0 0 #0000),var(--tw-shadow);--tw-shadow-color: rgb(239 68 68 / .3);--tw-shadow: var(--tw-shadow-colored)}.btn-primary:active{--tw-scale-x: .95;--tw-scale-y: .95;transform:translate(var(--tw-translate-x),var(--tw-translate-y)) rotate(var(--tw-rotate)) skew(var(--tw-skew-x)) skewY(var(--tw-skew-y)) scaleX(var(--tw-scale-x)) scaleY(var(--tw-scale-y))}.btn-secondary{border-radius:.75rem;border-width:1px;--tw-border-opacity: 1;border-color:rgb(75 85 99 / var(--tw-border-opacity, 1));background-color:transparent;padding:.75rem 2rem;font-weight:500;--tw-text-opacity: 1;color:rgb(209 213 219 / var(--tw-text-opacity, 1));transition-property:all;transition-timing-function:cubic-bezier(.4,0,.2,1);transition-duration:.3s}.btn-secondary:hover{--tw-border-opacity: 1;border-color:rgb(107 114 128 / var(--tw-border-opacity, 1));background-color:#1f293780;--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity, 1))}@keyframes spin{to{transform:rotate(360deg)}}.spinner{animation:spin 1s linear infinite}.check-path{stroke-dasharray:100;stroke-dashoffset:100;animation:drawCheck .5s ease-out forwards}@media (prefers-reduced-motion: reduce){*,*:before,*:after{animation-duration:.01ms!important;animation-iteration-count:1!important;transition-duration:.01ms!important}}.last\:border-0:last-child{border-width:0px}.hover\:bg-blue-500:hover{--tw-bg-opacity: 1;background-color:rgb(59 130 246 / var(--tw-bg-opacity, 1))}.hover\:bg-blue-500\/30:hover{background-color:#3b82f64d}.hover\:bg-gray-200:hover{--tw-bg-opacity: 1;background-color:rgb(229 231 235 / var(--tw-bg-opacity, 1))}.hover\:bg-gray-300:hover{--tw-bg-opacity: 1;background-color:rgb(209 213 219 / var(--tw-bg-opacity, 1))}.hover\:bg-red-500:hover{--tw-bg-opacity: 1;background-color:rgb(239 68 68 / var(--tw-bg-opacity, 1))}.hover\:text-blue-600:hover{--tw-text-opacity: 1;color:rgb(37 99 235 / var(--tw-text-opacity, 1))}.hover\:text-gray-700:hover{--tw-text-opacity: 1;color:rgb(55 65 81 / var(--tw-text-opacity, 1))}.focus\:border-red-500:focus{--tw-border-opacity: 1;border-color:rgb(239 68 68 / var(--tw-border-opacity, 1))}.focus\:outline-none:focus{outline:2px solid transparent;outline-offset:2px}.dark\:border-blue-400:is(.dark *){--tw-border-opacity: 1;border-color:rgb(96 165 250 / var(--tw-border-opacity, 1))}.dark\:border-gray-600:is(.dark *){--tw-border-opacity: 1;border-color:rgb(75 85 99 / var(--tw-border-opacity, 1))}.dark\:border-gray-700:is(.dark *){--tw-border-opacity: 1;border-color:rgb(55 65 81 / var(--tw-border-opacity, 1))}.dark\:border-gray-800:is(.dark *){--tw-border-opacity: 1;border-color:rgb(31 41 55 / var(--tw-border-opacity, 1))}.dark\:border-gray-800\/50:is(.dark *){border-color:#1f293780}.dark\:bg-\[\#0f0f0f\]:is(.dark *){--tw-bg-opacity: 1;background-color:rgb(15 15 15 / var(--tw-bg-opacity, 1))}.dark\:bg-gray-500:is(.dark *){--tw-bg-opacity: 1;background-color:rgb(107 114 128 / var(--tw-bg-opacity, 1))}.dark\:bg-gray-600\/20:is(.dark *){background-color:#4b556333}.dark\:bg-gray-700:is(.dark *){--tw-bg-opacity: 1;background-color:rgb(55 65 81 / var(--tw-bg-opacity, 1))}.dark\:bg-gray-800:is(.dark *){--tw-bg-opacity: 1;background-color:rgb(31 41 55 / var(--tw-bg-opacity, 1))}.dark\:bg-gray-900:is(.dark *){--tw-bg-opacity: 1;background-color:rgb(17 24 39 / var(--tw-bg-opacity, 1))}.dark\:bg-gray-900\/50:is(.dark *){background-color:#11182780}.dark\:bg-gray-900\/80:is(.dark *){background-color:#111827cc}.dark\:bg-gray-900\/95:is(.dark *){background-color:#111827f2}.dark\:text-blue-400:is(.dark *){--tw-text-opacity: 1;color:rgb(96 165 250 / var(--tw-text-opacity, 1))}.dark\:text-gray-200:is(.dark *){--tw-text-opacity: 1;color:rgb(229 231 235 / var(--tw-text-opacity, 1))}.dark\:text-gray-300:is(.dark *){--tw-text-opacity: 1;color:rgb(209 213 219 / var(--tw-text-opacity, 1))}.dark\:text-gray-400:is(.dark *){--tw-text-opacity: 1;color:rgb(156 163 175 / var(--tw-text-opacity, 1))}.dark\:text-gray-500:is(.dark *){--tw-text-opacity: 1;color:rgb(107 114 128 / var(--tw-text-opacity, 1))}.dark\:text-gray-600:is(.dark *){--tw-text-opacity: 1;color:rgb(75 85 99 / var(--tw-text-opacity, 1))}.dark\:text-green-400:is(.dark *){--tw-text-opacity: 1;color:rgb(74 222 128 / var(--tw-text-opacity, 1))}.dark\:text-red-300:is(.dark *){--tw-text-opacity: 1;color:rgb(252 165 165 / var(--tw-text-opacity, 1))}.dark\:text-red-400:is(.dark *){--tw-text-opacity: 1;color:rgb(248 113 113 / var(--tw-text-opacity, 1))}.dark\:text-white:is(.dark *){--tw-text-opacity: 1;color:rgb(255 255 255 / var(--tw-text-opacity, 1))}.dark\:text-yellow-400:is(.dark *){--tw-text-opacity: 1;color:rgb(250 204 21 / var(--tw-text-opacity, 1))}.dark\:placeholder-gray-600:is(.dark *)::-moz-placeholder{--tw-placeholder-opacity: 1;color:rgb(75 85 99 / var(--tw-placeholder-opacity, 1))}.dark\:placeholder-gray-600:is(.dark *)::placeholder{--tw-placeholder-opacity: 1;color:rgb(75 85 99 / var(--tw-placeholder-opacity, 1))}.dark\:hover\:bg-gray-700:hover:is(.dark *){--tw-bg-opacity: 1;background-color:rgb(55 65 81 / var(--tw-bg-opacity, 1))}.dark\:hover\:text-blue-300:hover:is(.dark *){--tw-text-opacity: 1;color:rgb(147 197 253 / var(--tw-text-opacity, 1))}.dark\:hover\:text-gray-300:hover:is(.dark *){--tw-text-opacity: 1;color:rgb(209 213 219 / var(--tw-text-opacity, 1))} diff --git a/v3/internal/setupwizard/frontend/dist/assets/wails-logo-black-text-Cx-vsZ4W.svg b/v3/internal/setupwizard/frontend/dist/assets/wails-logo-black-text-Cx-vsZ4W.svg deleted file mode 100644 index e90698049..000000000 --- a/v3/internal/setupwizard/frontend/dist/assets/wails-logo-black-text-Cx-vsZ4W.svg +++ /dev/null @@ -1,56 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/v3/internal/setupwizard/frontend/dist/assets/wails-logo-white-text-B284k7fX.svg b/v3/internal/setupwizard/frontend/dist/assets/wails-logo-white-text-B284k7fX.svg deleted file mode 100644 index 5ebf9d616..000000000 --- a/v3/internal/setupwizard/frontend/dist/assets/wails-logo-white-text-B284k7fX.svg +++ /dev/null @@ -1,56 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/v3/internal/setupwizard/frontend/dist/index.html b/v3/internal/setupwizard/frontend/dist/index.html deleted file mode 100644 index 1a00bbd54..000000000 --- a/v3/internal/setupwizard/frontend/dist/index.html +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - Wails Setup Wizard - - - - - - - -
                    - - diff --git a/v3/internal/setupwizard/frontend/dist/wails-logo.png b/v3/internal/setupwizard/frontend/dist/wails-logo.png deleted file mode 100755 index 0f32ab92f..000000000 Binary files a/v3/internal/setupwizard/frontend/dist/wails-logo.png and /dev/null differ diff --git a/v3/internal/setupwizard/frontend/index.html b/v3/internal/setupwizard/frontend/index.html deleted file mode 100644 index ba497ab66..000000000 --- a/v3/internal/setupwizard/frontend/index.html +++ /dev/null @@ -1,15 +0,0 @@ - - - - - - Wails Setup Wizard - - - - - -
                    - - - diff --git a/v3/internal/setupwizard/frontend/package-lock.json b/v3/internal/setupwizard/frontend/package-lock.json deleted file mode 100644 index ec25c0e62..000000000 --- a/v3/internal/setupwizard/frontend/package-lock.json +++ /dev/null @@ -1,2687 +0,0 @@ -{ - "name": "wails-setup-wizard", - "version": "0.0.0", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "name": "wails-setup-wizard", - "version": "0.0.0", - "dependencies": { - "framer-motion": "^12.23.25", - "react": "^18.3.1", - "react-dom": "^18.3.1" - }, - "devDependencies": { - "@types/react": "^18.3.12", - "@types/react-dom": "^18.3.1", - "@vitejs/plugin-react": "^4.3.3", - "autoprefixer": "^10.4.20", - "postcss": "^8.4.47", - "tailwindcss": "^3.4.14", - "typescript": "~5.6.2", - "vite": "^5.4.10" - } - }, - "node_modules/@alloc/quick-lru": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz", - "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@babel/code-frame": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", - "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-validator-identifier": "^7.27.1", - "js-tokens": "^4.0.0", - "picocolors": "^1.1.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/compat-data": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.28.5.tgz", - "integrity": "sha512-6uFXyCayocRbqhZOB+6XcuZbkMNimwfVGFji8CTZnCzOHVGvDqzvitu1re2AU5LROliz7eQPhB8CpAMvnx9EjA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/core": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.5.tgz", - "integrity": "sha512-e7jT4DxYvIDLk1ZHmU/m/mB19rex9sv0c2ftBtjSBv+kVM/902eh0fINUzD7UwLLNR+jU585GxUJ8/EBfAM5fw==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@babel/code-frame": "^7.27.1", - "@babel/generator": "^7.28.5", - "@babel/helper-compilation-targets": "^7.27.2", - "@babel/helper-module-transforms": "^7.28.3", - "@babel/helpers": "^7.28.4", - "@babel/parser": "^7.28.5", - "@babel/template": "^7.27.2", - "@babel/traverse": "^7.28.5", - "@babel/types": "^7.28.5", - "@jridgewell/remapping": "^2.3.5", - "convert-source-map": "^2.0.0", - "debug": "^4.1.0", - "gensync": "^1.0.0-beta.2", - "json5": "^2.2.3", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/babel" - } - }, - "node_modules/@babel/generator": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.5.tgz", - "integrity": "sha512-3EwLFhZ38J4VyIP6WNtt2kUdW9dokXA9Cr4IVIFHuCpZ3H8/YFOl5JjZHisrn1fATPBmKKqXzDFvh9fUwHz6CQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/parser": "^7.28.5", - "@babel/types": "^7.28.5", - "@jridgewell/gen-mapping": "^0.3.12", - "@jridgewell/trace-mapping": "^0.3.28", - "jsesc": "^3.0.2" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-compilation-targets": { - "version": "7.27.2", - "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.2.tgz", - "integrity": "sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/compat-data": "^7.27.2", - "@babel/helper-validator-option": "^7.27.1", - "browserslist": "^4.24.0", - "lru-cache": "^5.1.1", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-globals": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz", - "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-module-imports": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz", - "integrity": "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/traverse": "^7.27.1", - "@babel/types": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-module-transforms": { - "version": "7.28.3", - "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.3.tgz", - "integrity": "sha512-gytXUbs8k2sXS9PnQptz5o0QnpLL51SwASIORY6XaBKF88nsOT0Zw9szLqlSGQDP/4TljBAD5y98p2U1fqkdsw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-module-imports": "^7.27.1", - "@babel/helper-validator-identifier": "^7.27.1", - "@babel/traverse": "^7.28.3" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/helper-plugin-utils": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.27.1.tgz", - "integrity": "sha512-1gn1Up5YXka3YYAHGKpbideQ5Yjf1tDa9qYcgysz+cNCXukyLl6DjPXhD3VRwSb8c0J9tA4b2+rHEZtc6R0tlw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-string-parser": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", - "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-identifier": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz", - "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helper-validator-option": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz", - "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/helpers": { - "version": "7.28.4", - "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.4.tgz", - "integrity": "sha512-HFN59MmQXGHVyYadKLVumYsA9dBFun/ldYxipEjzA4196jpLZd8UjEEBLkbEkvfYreDqJhZxYAWFPtrfhNpj4w==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/template": "^7.27.2", - "@babel/types": "^7.28.4" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/parser": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.5.tgz", - "integrity": "sha512-KKBU1VGYR7ORr3At5HAtUQ+TV3SzRCXmA/8OdDZiLDBIZxVyzXuztPjfLd3BV1PRAQGCMWWSHYhL0F8d5uHBDQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/types": "^7.28.5" - }, - "bin": { - "parser": "bin/babel-parser.js" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@babel/plugin-transform-react-jsx-self": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.27.1.tgz", - "integrity": "sha512-6UzkCs+ejGdZ5mFFC/OCUrv028ab2fp1znZmCZjAOBKiBK2jXD1O+BPSfX8X2qjJ75fZBMSnQn3Rq2mrBJK2mw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-transform-react-jsx-source": { - "version": "7.27.1", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.27.1.tgz", - "integrity": "sha512-zbwoTsBruTeKB9hSq73ha66iFeJHuaFkUbwvqElnygoNbj/jHRsSeokowZFN3CZ64IvEqcmmkVe89OPXc7ldAw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/template": { - "version": "7.27.2", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz", - "integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.27.1", - "@babel/parser": "^7.27.2", - "@babel/types": "^7.27.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/traverse": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.5.tgz", - "integrity": "sha512-TCCj4t55U90khlYkVV/0TfkJkAkUg3jZFA3Neb7unZT8CPok7iiRfaX0F+WnqWqt7OxhOn0uBKXCw4lbL8W0aQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.27.1", - "@babel/generator": "^7.28.5", - "@babel/helper-globals": "^7.28.0", - "@babel/parser": "^7.28.5", - "@babel/template": "^7.27.2", - "@babel/types": "^7.28.5", - "debug": "^4.3.1" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@babel/types": { - "version": "7.28.5", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.5.tgz", - "integrity": "sha512-qQ5m48eI/MFLQ5PxQj4PFaprjyCTLI37ElWMmNs0K8Lk3dVeOdNpB3ks8jc7yM5CDmVC73eMVk/trk3fgmrUpA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-string-parser": "^7.27.1", - "@babel/helper-validator-identifier": "^7.28.5" - }, - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/@esbuild/aix-ppc64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz", - "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "aix" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/android-arm": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz", - "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/android-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz", - "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/android-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz", - "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/darwin-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz", - "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/darwin-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz", - "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/freebsd-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz", - "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/freebsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz", - "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-arm": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz", - "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz", - "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-ia32": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz", - "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-loong64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz", - "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==", - "cpu": [ - "loong64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-mips64el": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz", - "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==", - "cpu": [ - "mips64el" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-ppc64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz", - "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-riscv64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz", - "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-s390x": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz", - "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==", - "cpu": [ - "s390x" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz", - "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/netbsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz", - "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/openbsd-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz", - "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/sunos-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz", - "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/win32-arm64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz", - "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/win32-ia32": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz", - "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/win32-x64": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz", - "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@jridgewell/gen-mapping": { - "version": "0.3.13", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", - "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/sourcemap-codec": "^1.5.0", - "@jridgewell/trace-mapping": "^0.3.24" - } - }, - "node_modules/@jridgewell/remapping": { - "version": "2.3.5", - "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz", - "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.24" - } - }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", - "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.5", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", - "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", - "dev": true, - "license": "MIT" - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.31", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", - "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" - } - }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@rolldown/pluginutils": { - "version": "1.0.0-beta.27", - "resolved": "https://registry.npmjs.org/@rolldown/pluginutils/-/pluginutils-1.0.0-beta.27.tgz", - "integrity": "sha512-+d0F4MKMCbeVUJwG96uQ4SgAznZNSq93I3V+9NHA4OpvqG8mRCpGdKmK8l/dl02h2CCDHwW2FqilnTyDcAnqjA==", - "dev": true, - "license": "MIT" - }, - "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.53.3.tgz", - "integrity": "sha512-mRSi+4cBjrRLoaal2PnqH82Wqyb+d3HsPUN/W+WslCXsZsyHa9ZeQQX/pQsZaVIWDkPcpV6jJ+3KLbTbgnwv8w==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/@rollup/rollup-android-arm64": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.53.3.tgz", - "integrity": "sha512-CbDGaMpdE9sh7sCmTrTUyllhrg65t6SwhjlMJsLr+J8YjFuPmCEjbBSx4Z/e4SmDyH3aB5hGaJUP2ltV/vcs4w==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.53.3.tgz", - "integrity": "sha512-Nr7SlQeqIBpOV6BHHGZgYBuSdanCXuw09hon14MGOLGmXAFYjx1wNvquVPmpZnl0tLjg25dEdr4IQ6GgyToCUA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.53.3.tgz", - "integrity": "sha512-DZ8N4CSNfl965CmPktJ8oBnfYr3F8dTTNBQkRlffnUarJ2ohudQD17sZBa097J8xhQ26AwhHJ5mvUyQW8ddTsQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.53.3.tgz", - "integrity": "sha512-yMTrCrK92aGyi7GuDNtGn2sNW+Gdb4vErx4t3Gv/Tr+1zRb8ax4z8GWVRfr3Jw8zJWvpGHNpss3vVlbF58DZ4w==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ] - }, - "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.53.3.tgz", - "integrity": "sha512-lMfF8X7QhdQzseM6XaX0vbno2m3hlyZFhwcndRMw8fbAGUGL3WFMBdK0hbUBIUYcEcMhVLr1SIamDeuLBnXS+Q==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ] - }, - "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.53.3.tgz", - "integrity": "sha512-k9oD15soC/Ln6d2Wv/JOFPzZXIAIFLp6B+i14KhxAfnq76ajt0EhYc5YPeX6W1xJkAdItcVT+JhKl1QZh44/qw==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.53.3.tgz", - "integrity": "sha512-vTNlKq+N6CK/8UktsrFuc+/7NlEYVxgaEgRXVUVK258Z5ymho29skzW1sutgYjqNnquGwVUObAaxae8rZ6YMhg==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.53.3.tgz", - "integrity": "sha512-RGrFLWgMhSxRs/EWJMIFM1O5Mzuz3Xy3/mnxJp/5cVhZ2XoCAxJnmNsEyeMJtpK+wu0FJFWz+QF4mjCA7AUQ3w==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.53.3.tgz", - "integrity": "sha512-kASyvfBEWYPEwe0Qv4nfu6pNkITLTb32p4yTgzFCocHnJLAHs+9LjUu9ONIhvfT/5lv4YS5muBHyuV84epBo/A==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-loong64-gnu": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loong64-gnu/-/rollup-linux-loong64-gnu-4.53.3.tgz", - "integrity": "sha512-JiuKcp2teLJwQ7vkJ95EwESWkNRFJD7TQgYmCnrPtlu50b4XvT5MOmurWNrCj3IFdyjBQ5p9vnrX4JM6I8OE7g==", - "cpu": [ - "loong64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-ppc64-gnu": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.53.3.tgz", - "integrity": "sha512-EoGSa8nd6d3T7zLuqdojxC20oBfNT8nexBbB/rkxgKj5T5vhpAQKKnD+h3UkoMuTyXkP5jTjK/ccNRmQrPNDuw==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.53.3.tgz", - "integrity": "sha512-4s+Wped2IHXHPnAEbIB0YWBv7SDohqxobiiPA1FIWZpX+w9o2i4LezzH/NkFUl8LRci/8udci6cLq+jJQlh+0g==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-riscv64-musl": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.53.3.tgz", - "integrity": "sha512-68k2g7+0vs2u9CxDt5ktXTngsxOQkSEV/xBbwlqYcUrAVh6P9EgMZvFsnHy4SEiUl46Xf0IObWVbMvPrr2gw8A==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.53.3.tgz", - "integrity": "sha512-VYsFMpULAz87ZW6BVYw3I6sWesGpsP9OPcyKe8ofdg9LHxSbRMd7zrVrr5xi/3kMZtpWL/wC+UIJWJYVX5uTKg==", - "cpu": [ - "s390x" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.53.3.tgz", - "integrity": "sha512-3EhFi1FU6YL8HTUJZ51imGJWEX//ajQPfqWLI3BQq4TlvHy4X0MOr5q3D2Zof/ka0d5FNdPwZXm3Yyib/UEd+w==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.53.3.tgz", - "integrity": "sha512-eoROhjcc6HbZCJr+tvVT8X4fW3/5g/WkGvvmwz/88sDtSJzO7r/blvoBDgISDiCjDRZmHpwud7h+6Q9JxFwq1Q==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-openharmony-arm64": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-openharmony-arm64/-/rollup-openharmony-arm64-4.53.3.tgz", - "integrity": "sha512-OueLAWgrNSPGAdUdIjSWXw+u/02BRTcnfw9PN41D2vq/JSEPnJnVuBgw18VkN8wcd4fjUs+jFHVM4t9+kBSNLw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openharmony" - ] - }, - "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.53.3.tgz", - "integrity": "sha512-GOFuKpsxR/whszbF/bzydebLiXIHSgsEUp6M0JI8dWvi+fFa1TD6YQa4aSZHtpmh2/uAlj/Dy+nmby3TJ3pkTw==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.53.3.tgz", - "integrity": "sha512-iah+THLcBJdpfZ1TstDFbKNznlzoxa8fmnFYK4V67HvmuNYkVdAywJSoteUszvBQ9/HqN2+9AZghbajMsFT+oA==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-x64-gnu": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-gnu/-/rollup-win32-x64-gnu-4.53.3.tgz", - "integrity": "sha512-J9QDiOIZlZLdcot5NXEepDkstocktoVjkaKUtqzgzpt2yWjGlbYiKyp05rWwk4nypbYUNoFAztEgixoLaSETkg==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.53.3.tgz", - "integrity": "sha512-UhTd8u31dXadv0MopwGgNOBpUVROFKWVQgAg5N1ESyCz8AuBcMqm4AuTjrwgQKGDfoFuz02EuMRHQIw/frmYKQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@types/babel__core": { - "version": "7.20.5", - "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", - "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/parser": "^7.20.7", - "@babel/types": "^7.20.7", - "@types/babel__generator": "*", - "@types/babel__template": "*", - "@types/babel__traverse": "*" - } - }, - "node_modules/@types/babel__generator": { - "version": "7.27.0", - "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.27.0.tgz", - "integrity": "sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/types": "^7.0.0" - } - }, - "node_modules/@types/babel__template": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", - "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/parser": "^7.1.0", - "@babel/types": "^7.0.0" - } - }, - "node_modules/@types/babel__traverse": { - "version": "7.28.0", - "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.28.0.tgz", - "integrity": "sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/types": "^7.28.2" - } - }, - "node_modules/@types/estree": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", - "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/prop-types": { - "version": "15.7.15", - "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.15.tgz", - "integrity": "sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/react": { - "version": "18.3.27", - "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.27.tgz", - "integrity": "sha512-cisd7gxkzjBKU2GgdYrTdtQx1SORymWyaAFhaxQPK9bYO9ot3Y5OikQRvY0VYQtvwjeQnizCINJAenh/V7MK2w==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "@types/prop-types": "*", - "csstype": "^3.2.2" - } - }, - "node_modules/@types/react-dom": { - "version": "18.3.7", - "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.7.tgz", - "integrity": "sha512-MEe3UeoENYVFXzoXEWsvcpg6ZvlrFNlOQ7EOsvhI3CfAXwzPfO8Qwuxd40nepsYKqyyVQnTdEfv68q91yLcKrQ==", - "dev": true, - "license": "MIT", - "peerDependencies": { - "@types/react": "^18.0.0" - } - }, - "node_modules/@vitejs/plugin-react": { - "version": "4.7.0", - "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.7.0.tgz", - "integrity": "sha512-gUu9hwfWvvEDBBmgtAowQCojwZmJ5mcLn3aufeCsitijs3+f2NsrPtlAWIR6OPiqljl96GVCUbLe0HyqIpVaoA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/core": "^7.28.0", - "@babel/plugin-transform-react-jsx-self": "^7.27.1", - "@babel/plugin-transform-react-jsx-source": "^7.27.1", - "@rolldown/pluginutils": "1.0.0-beta.27", - "@types/babel__core": "^7.20.5", - "react-refresh": "^0.17.0" - }, - "engines": { - "node": "^14.18.0 || >=16.0.0" - }, - "peerDependencies": { - "vite": "^4.2.0 || ^5.0.0 || ^6.0.0 || ^7.0.0" - } - }, - "node_modules/any-promise": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", - "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==", - "dev": true, - "license": "MIT" - }, - "node_modules/anymatch": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", - "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", - "dev": true, - "license": "ISC", - "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/arg": { - "version": "5.0.2", - "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", - "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==", - "dev": true, - "license": "MIT" - }, - "node_modules/autoprefixer": { - "version": "10.4.22", - "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.22.tgz", - "integrity": "sha512-ARe0v/t9gO28Bznv6GgqARmVqcWOV3mfgUPn9becPHMiD3o9BwlRgaeccZnwTpZ7Zwqrm+c1sUSsMxIzQzc8Xg==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/autoprefixer" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "browserslist": "^4.27.0", - "caniuse-lite": "^1.0.30001754", - "fraction.js": "^5.3.4", - "normalize-range": "^0.1.2", - "picocolors": "^1.1.1", - "postcss-value-parser": "^4.2.0" - }, - "bin": { - "autoprefixer": "bin/autoprefixer" - }, - "engines": { - "node": "^10 || ^12 || >=14" - }, - "peerDependencies": { - "postcss": "^8.1.0" - } - }, - "node_modules/baseline-browser-mapping": { - "version": "2.9.3", - "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.9.3.tgz", - "integrity": "sha512-8QdH6czo+G7uBsNo0GiUfouPN1lRzKdJTGnKXwe12gkFbnnOUaUKGN55dMkfy+mnxmvjwl9zcI4VncczcVXDhA==", - "dev": true, - "license": "Apache-2.0", - "bin": { - "baseline-browser-mapping": "dist/cli.js" - } - }, - "node_modules/binary-extensions": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", - "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/braces": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", - "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", - "dev": true, - "license": "MIT", - "dependencies": { - "fill-range": "^7.1.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/browserslist": { - "version": "4.28.1", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.1.tgz", - "integrity": "sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "peer": true, - "dependencies": { - "baseline-browser-mapping": "^2.9.0", - "caniuse-lite": "^1.0.30001759", - "electron-to-chromium": "^1.5.263", - "node-releases": "^2.0.27", - "update-browserslist-db": "^1.2.0" - }, - "bin": { - "browserslist": "cli.js" - }, - "engines": { - "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" - } - }, - "node_modules/camelcase-css": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", - "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 6" - } - }, - "node_modules/caniuse-lite": { - "version": "1.0.30001759", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001759.tgz", - "integrity": "sha512-Pzfx9fOKoKvevQf8oCXoyNRQ5QyxJj+3O0Rqx2V5oxT61KGx8+n6hV/IUyJeifUci2clnmmKVpvtiqRzgiWjSw==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/caniuse-lite" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "CC-BY-4.0" - }, - "node_modules/chokidar": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", - "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", - "dev": true, - "license": "MIT", - "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" - }, - "engines": { - "node": ">= 8.10.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" - } - }, - "node_modules/chokidar/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "license": "ISC", - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/commander": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", - "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 6" - } - }, - "node_modules/convert-source-map": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", - "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", - "dev": true, - "license": "MIT" - }, - "node_modules/cssesc": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", - "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", - "dev": true, - "license": "MIT", - "bin": { - "cssesc": "bin/cssesc" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/csstype": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", - "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/debug": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", - "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/didyoumean": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", - "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==", - "dev": true, - "license": "Apache-2.0" - }, - "node_modules/dlv": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", - "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==", - "dev": true, - "license": "MIT" - }, - "node_modules/electron-to-chromium": { - "version": "1.5.266", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.266.tgz", - "integrity": "sha512-kgWEglXvkEfMH7rxP5OSZZwnaDWT7J9EoZCujhnpLbfi0bbNtRkgdX2E3gt0Uer11c61qCYktB3hwkAS325sJg==", - "dev": true, - "license": "ISC" - }, - "node_modules/esbuild": { - "version": "0.21.5", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz", - "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=12" - }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.21.5", - "@esbuild/android-arm": "0.21.5", - "@esbuild/android-arm64": "0.21.5", - "@esbuild/android-x64": "0.21.5", - "@esbuild/darwin-arm64": "0.21.5", - "@esbuild/darwin-x64": "0.21.5", - "@esbuild/freebsd-arm64": "0.21.5", - "@esbuild/freebsd-x64": "0.21.5", - "@esbuild/linux-arm": "0.21.5", - "@esbuild/linux-arm64": "0.21.5", - "@esbuild/linux-ia32": "0.21.5", - "@esbuild/linux-loong64": "0.21.5", - "@esbuild/linux-mips64el": "0.21.5", - "@esbuild/linux-ppc64": "0.21.5", - "@esbuild/linux-riscv64": "0.21.5", - "@esbuild/linux-s390x": "0.21.5", - "@esbuild/linux-x64": "0.21.5", - "@esbuild/netbsd-x64": "0.21.5", - "@esbuild/openbsd-x64": "0.21.5", - "@esbuild/sunos-x64": "0.21.5", - "@esbuild/win32-arm64": "0.21.5", - "@esbuild/win32-ia32": "0.21.5", - "@esbuild/win32-x64": "0.21.5" - } - }, - "node_modules/escalade": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", - "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/fast-glob": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz", - "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.8" - }, - "engines": { - "node": ">=8.6.0" - } - }, - "node_modules/fast-glob/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "license": "ISC", - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } - }, - "node_modules/fastq": { - "version": "1.19.1", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz", - "integrity": "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==", - "dev": true, - "license": "ISC", - "dependencies": { - "reusify": "^1.0.4" - } - }, - "node_modules/fill-range": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", - "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", - "dev": true, - "license": "MIT", - "dependencies": { - "to-regex-range": "^5.0.1" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/fraction.js": { - "version": "5.3.4", - "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-5.3.4.tgz", - "integrity": "sha512-1X1NTtiJphryn/uLQz3whtY6jK3fTqoE3ohKs0tT+Ujr1W59oopxmoEh7Lu5p6vBaPbgoM0bzveAW4Qi5RyWDQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": "*" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/rawify" - } - }, - "node_modules/framer-motion": { - "version": "12.23.25", - "resolved": "https://registry.npmjs.org/framer-motion/-/framer-motion-12.23.25.tgz", - "integrity": "sha512-gUHGl2e4VG66jOcH0JHhuJQr6ZNwrET9g31ZG0xdXzT0CznP7fHX4P8Bcvuc4MiUB90ysNnWX2ukHRIggkl6hQ==", - "license": "MIT", - "dependencies": { - "motion-dom": "^12.23.23", - "motion-utils": "^12.23.6", - "tslib": "^2.4.0" - }, - "peerDependencies": { - "@emotion/is-prop-valid": "*", - "react": "^18.0.0 || ^19.0.0", - "react-dom": "^18.0.0 || ^19.0.0" - }, - "peerDependenciesMeta": { - "@emotion/is-prop-valid": { - "optional": true - }, - "react": { - "optional": true - }, - "react-dom": { - "optional": true - } - } - }, - "node_modules/fsevents": { - "version": "2.3.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", - "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" - } - }, - "node_modules/function-bind": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", - "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/gensync": { - "version": "1.0.0-beta.2", - "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz", - "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.9.0" - } - }, - "node_modules/glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "dev": true, - "license": "ISC", - "dependencies": { - "is-glob": "^4.0.3" - }, - "engines": { - "node": ">=10.13.0" - } - }, - "node_modules/hasown": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", - "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "function-bind": "^1.1.2" - }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/is-binary-path": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", - "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", - "dev": true, - "license": "MIT", - "dependencies": { - "binary-extensions": "^2.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/is-core-module": { - "version": "2.16.1", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", - "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", - "dev": true, - "license": "MIT", - "dependencies": { - "hasown": "^2.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/is-extglob": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", - "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-number": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", - "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.12.0" - } - }, - "node_modules/jiti": { - "version": "1.21.7", - "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.7.tgz", - "integrity": "sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==", - "dev": true, - "license": "MIT", - "peer": true, - "bin": { - "jiti": "bin/jiti.js" - } - }, - "node_modules/js-tokens": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", - "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", - "license": "MIT" - }, - "node_modules/jsesc": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", - "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", - "dev": true, - "license": "MIT", - "bin": { - "jsesc": "bin/jsesc" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/json5": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", - "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", - "dev": true, - "license": "MIT", - "bin": { - "json5": "lib/cli.js" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/lilconfig": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz", - "integrity": "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/antonk52" - } - }, - "node_modules/lines-and-columns": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", - "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", - "dev": true, - "license": "MIT" - }, - "node_modules/loose-envify": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", - "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", - "license": "MIT", - "dependencies": { - "js-tokens": "^3.0.0 || ^4.0.0" - }, - "bin": { - "loose-envify": "cli.js" - } - }, - "node_modules/lru-cache": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", - "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", - "dev": true, - "license": "ISC", - "dependencies": { - "yallist": "^3.0.2" - } - }, - "node_modules/merge2": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", - "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 8" - } - }, - "node_modules/micromatch": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", - "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", - "dev": true, - "license": "MIT", - "dependencies": { - "braces": "^3.0.3", - "picomatch": "^2.3.1" - }, - "engines": { - "node": ">=8.6" - } - }, - "node_modules/motion-dom": { - "version": "12.23.23", - "resolved": "https://registry.npmjs.org/motion-dom/-/motion-dom-12.23.23.tgz", - "integrity": "sha512-n5yolOs0TQQBRUFImrRfs/+6X4p3Q4n1dUEqt/H58Vx7OW6RF+foWEgmTVDhIWJIMXOuNNL0apKH2S16en9eiA==", - "license": "MIT", - "dependencies": { - "motion-utils": "^12.23.6" - } - }, - "node_modules/motion-utils": { - "version": "12.23.6", - "resolved": "https://registry.npmjs.org/motion-utils/-/motion-utils-12.23.6.tgz", - "integrity": "sha512-eAWoPgr4eFEOFfg2WjIsMoqJTW6Z8MTUCgn/GZ3VRpClWBdnbjryiA3ZSNLyxCTmCQx4RmYX6jX1iWHbenUPNQ==", - "license": "MIT" - }, - "node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "dev": true, - "license": "MIT" - }, - "node_modules/mz": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", - "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "any-promise": "^1.0.0", - "object-assign": "^4.0.1", - "thenify-all": "^1.0.0" - } - }, - "node_modules/nanoid": { - "version": "3.3.11", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", - "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "bin": { - "nanoid": "bin/nanoid.cjs" - }, - "engines": { - "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" - } - }, - "node_modules/node-releases": { - "version": "2.0.27", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.27.tgz", - "integrity": "sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==", - "dev": true, - "license": "MIT" - }, - "node_modules/normalize-path": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", - "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/normalize-range": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", - "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-assign": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/object-hash": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", - "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 6" - } - }, - "node_modules/path-parse": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", - "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", - "dev": true, - "license": "MIT" - }, - "node_modules/picocolors": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", - "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", - "dev": true, - "license": "ISC" - }, - "node_modules/picomatch": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", - "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/pirates": { - "version": "4.0.7", - "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.7.tgz", - "integrity": "sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 6" - } - }, - "node_modules/postcss": { - "version": "8.5.6", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", - "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/postcss" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "peer": true, - "dependencies": { - "nanoid": "^3.3.11", - "picocolors": "^1.1.1", - "source-map-js": "^1.2.1" - }, - "engines": { - "node": "^10 || ^12 || >=14" - } - }, - "node_modules/postcss-import": { - "version": "15.1.0", - "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz", - "integrity": "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==", - "dev": true, - "license": "MIT", - "dependencies": { - "postcss-value-parser": "^4.0.0", - "read-cache": "^1.0.0", - "resolve": "^1.1.7" - }, - "engines": { - "node": ">=14.0.0" - }, - "peerDependencies": { - "postcss": "^8.0.0" - } - }, - "node_modules/postcss-js": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.1.0.tgz", - "integrity": "sha512-oIAOTqgIo7q2EOwbhb8UalYePMvYoIeRY2YKntdpFQXNosSu3vLrniGgmH9OKs/qAkfoj5oB3le/7mINW1LCfw==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "camelcase-css": "^2.0.1" - }, - "engines": { - "node": "^12 || ^14 || >= 16" - }, - "peerDependencies": { - "postcss": "^8.4.21" - } - }, - "node_modules/postcss-load-config": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-6.0.1.tgz", - "integrity": "sha512-oPtTM4oerL+UXmx+93ytZVN82RrlY/wPUV8IeDxFrzIjXOLF1pN+EmKPLbubvKHT2HC20xXsCAH2Z+CKV6Oz/g==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "lilconfig": "^3.1.1" - }, - "engines": { - "node": ">= 18" - }, - "peerDependencies": { - "jiti": ">=1.21.0", - "postcss": ">=8.0.9", - "tsx": "^4.8.1", - "yaml": "^2.4.2" - }, - "peerDependenciesMeta": { - "jiti": { - "optional": true - }, - "postcss": { - "optional": true - }, - "tsx": { - "optional": true - }, - "yaml": { - "optional": true - } - } - }, - "node_modules/postcss-nested": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.2.0.tgz", - "integrity": "sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/postcss/" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "postcss-selector-parser": "^6.1.1" - }, - "engines": { - "node": ">=12.0" - }, - "peerDependencies": { - "postcss": "^8.2.14" - } - }, - "node_modules/postcss-selector-parser": { - "version": "6.1.2", - "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz", - "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==", - "dev": true, - "license": "MIT", - "dependencies": { - "cssesc": "^3.0.0", - "util-deprecate": "^1.0.2" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/postcss-value-parser": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", - "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/queue-microtask": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", - "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, - "node_modules/react": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", - "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==", - "license": "MIT", - "peer": true, - "dependencies": { - "loose-envify": "^1.1.0" - }, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/react-dom": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", - "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==", - "license": "MIT", - "peer": true, - "dependencies": { - "loose-envify": "^1.1.0", - "scheduler": "^0.23.2" - }, - "peerDependencies": { - "react": "^18.3.1" - } - }, - "node_modules/react-refresh": { - "version": "0.17.0", - "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.17.0.tgz", - "integrity": "sha512-z6F7K9bV85EfseRCp2bzrpyQ0Gkw1uLoCel9XBVWPg/TjRj94SkJzUTGfOa4bs7iJvBWtQG0Wq7wnI0syw3EBQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/read-cache": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", - "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==", - "dev": true, - "license": "MIT", - "dependencies": { - "pify": "^2.3.0" - } - }, - "node_modules/readdirp": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", - "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", - "dev": true, - "license": "MIT", - "dependencies": { - "picomatch": "^2.2.1" - }, - "engines": { - "node": ">=8.10.0" - } - }, - "node_modules/resolve": { - "version": "1.22.11", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.11.tgz", - "integrity": "sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-core-module": "^2.16.1", - "path-parse": "^1.0.7", - "supports-preserve-symlinks-flag": "^1.0.0" - }, - "bin": { - "resolve": "bin/resolve" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/reusify": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz", - "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==", - "dev": true, - "license": "MIT", - "engines": { - "iojs": ">=1.0.0", - "node": ">=0.10.0" - } - }, - "node_modules/rollup": { - "version": "4.53.3", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.53.3.tgz", - "integrity": "sha512-w8GmOxZfBmKknvdXU1sdM9NHcoQejwF/4mNgj2JuEEdRaHwwF12K7e9eXn1nLZ07ad+du76mkVsyeb2rKGllsA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@types/estree": "1.0.8" - }, - "bin": { - "rollup": "dist/bin/rollup" - }, - "engines": { - "node": ">=18.0.0", - "npm": ">=8.0.0" - }, - "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.53.3", - "@rollup/rollup-android-arm64": "4.53.3", - "@rollup/rollup-darwin-arm64": "4.53.3", - "@rollup/rollup-darwin-x64": "4.53.3", - "@rollup/rollup-freebsd-arm64": "4.53.3", - "@rollup/rollup-freebsd-x64": "4.53.3", - "@rollup/rollup-linux-arm-gnueabihf": "4.53.3", - "@rollup/rollup-linux-arm-musleabihf": "4.53.3", - "@rollup/rollup-linux-arm64-gnu": "4.53.3", - "@rollup/rollup-linux-arm64-musl": "4.53.3", - "@rollup/rollup-linux-loong64-gnu": "4.53.3", - "@rollup/rollup-linux-ppc64-gnu": "4.53.3", - "@rollup/rollup-linux-riscv64-gnu": "4.53.3", - "@rollup/rollup-linux-riscv64-musl": "4.53.3", - "@rollup/rollup-linux-s390x-gnu": "4.53.3", - "@rollup/rollup-linux-x64-gnu": "4.53.3", - "@rollup/rollup-linux-x64-musl": "4.53.3", - "@rollup/rollup-openharmony-arm64": "4.53.3", - "@rollup/rollup-win32-arm64-msvc": "4.53.3", - "@rollup/rollup-win32-ia32-msvc": "4.53.3", - "@rollup/rollup-win32-x64-gnu": "4.53.3", - "@rollup/rollup-win32-x64-msvc": "4.53.3", - "fsevents": "~2.3.2" - } - }, - "node_modules/run-parallel": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", - "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT", - "dependencies": { - "queue-microtask": "^1.2.2" - } - }, - "node_modules/scheduler": { - "version": "0.23.2", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz", - "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==", - "license": "MIT", - "dependencies": { - "loose-envify": "^1.1.0" - } - }, - "node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/source-map-js": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", - "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/sucrase": { - "version": "3.35.1", - "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.1.tgz", - "integrity": "sha512-DhuTmvZWux4H1UOnWMB3sk0sbaCVOoQZjv8u1rDoTV0HTdGem9hkAZtl4JZy8P2z4Bg0nT+YMeOFyVr4zcG5Tw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.2", - "commander": "^4.0.0", - "lines-and-columns": "^1.1.6", - "mz": "^2.7.0", - "pirates": "^4.0.1", - "tinyglobby": "^0.2.11", - "ts-interface-checker": "^0.1.9" - }, - "bin": { - "sucrase": "bin/sucrase", - "sucrase-node": "bin/sucrase-node" - }, - "engines": { - "node": ">=16 || 14 >=14.17" - } - }, - "node_modules/supports-preserve-symlinks-flag": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", - "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/tailwindcss": { - "version": "3.4.18", - "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.18.tgz", - "integrity": "sha512-6A2rnmW5xZMdw11LYjhcI5846rt9pbLSabY5XPxo+XWdxwZaFEn47Go4NzFiHu9sNNmr/kXivP1vStfvMaK1GQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@alloc/quick-lru": "^5.2.0", - "arg": "^5.0.2", - "chokidar": "^3.6.0", - "didyoumean": "^1.2.2", - "dlv": "^1.1.3", - "fast-glob": "^3.3.2", - "glob-parent": "^6.0.2", - "is-glob": "^4.0.3", - "jiti": "^1.21.7", - "lilconfig": "^3.1.3", - "micromatch": "^4.0.8", - "normalize-path": "^3.0.0", - "object-hash": "^3.0.0", - "picocolors": "^1.1.1", - "postcss": "^8.4.47", - "postcss-import": "^15.1.0", - "postcss-js": "^4.0.1", - "postcss-load-config": "^4.0.2 || ^5.0 || ^6.0", - "postcss-nested": "^6.2.0", - "postcss-selector-parser": "^6.1.2", - "resolve": "^1.22.8", - "sucrase": "^3.35.0" - }, - "bin": { - "tailwind": "lib/cli.js", - "tailwindcss": "lib/cli.js" - }, - "engines": { - "node": ">=14.0.0" - } - }, - "node_modules/thenify": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", - "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", - "dev": true, - "license": "MIT", - "dependencies": { - "any-promise": "^1.0.0" - } - }, - "node_modules/thenify-all": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", - "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", - "dev": true, - "license": "MIT", - "dependencies": { - "thenify": ">= 3.1.0 < 4" - }, - "engines": { - "node": ">=0.8" - } - }, - "node_modules/tinyglobby": { - "version": "0.2.15", - "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz", - "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "fdir": "^6.5.0", - "picomatch": "^4.0.3" - }, - "engines": { - "node": ">=12.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/SuperchupuDev" - } - }, - "node_modules/tinyglobby/node_modules/fdir": { - "version": "6.5.0", - "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz", - "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=12.0.0" - }, - "peerDependencies": { - "picomatch": "^3 || ^4" - }, - "peerDependenciesMeta": { - "picomatch": { - "optional": true - } - } - }, - "node_modules/tinyglobby/node_modules/picomatch": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", - "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", - "dev": true, - "license": "MIT", - "peer": true, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/to-regex-range": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", - "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "is-number": "^7.0.0" - }, - "engines": { - "node": ">=8.0" - } - }, - "node_modules/ts-interface-checker": { - "version": "0.1.13", - "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz", - "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==", - "dev": true, - "license": "Apache-2.0" - }, - "node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", - "license": "0BSD" - }, - "node_modules/typescript": { - "version": "5.6.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.3.tgz", - "integrity": "sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==", - "dev": true, - "license": "Apache-2.0", - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=14.17" - } - }, - "node_modules/update-browserslist-db": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.2.tgz", - "integrity": "sha512-E85pfNzMQ9jpKkA7+TJAi4TJN+tBCuWh5rUcS/sv6cFi+1q9LYDwDI5dpUL0u/73EElyQ8d3TEaeW4sPedBqYA==", - "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], - "license": "MIT", - "dependencies": { - "escalade": "^3.2.0", - "picocolors": "^1.1.1" - }, - "bin": { - "update-browserslist-db": "cli.js" - }, - "peerDependencies": { - "browserslist": ">= 4.21.0" - } - }, - "node_modules/util-deprecate": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", - "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", - "dev": true, - "license": "MIT" - }, - "node_modules/vite": { - "version": "5.4.21", - "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.21.tgz", - "integrity": "sha512-o5a9xKjbtuhY6Bi5S3+HvbRERmouabWbyUcpXXUA1u+GNUKoROi9byOJ8M0nHbHYHkYICiMlqxkg1KkYmm25Sw==", - "dev": true, - "license": "MIT", - "peer": true, - "dependencies": { - "esbuild": "^0.21.3", - "postcss": "^8.4.43", - "rollup": "^4.20.0" - }, - "bin": { - "vite": "bin/vite.js" - }, - "engines": { - "node": "^18.0.0 || >=20.0.0" - }, - "funding": { - "url": "https://github.com/vitejs/vite?sponsor=1" - }, - "optionalDependencies": { - "fsevents": "~2.3.3" - }, - "peerDependencies": { - "@types/node": "^18.0.0 || >=20.0.0", - "less": "*", - "lightningcss": "^1.21.0", - "sass": "*", - "sass-embedded": "*", - "stylus": "*", - "sugarss": "*", - "terser": "^5.4.0" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - }, - "less": { - "optional": true - }, - "lightningcss": { - "optional": true - }, - "sass": { - "optional": true - }, - "sass-embedded": { - "optional": true - }, - "stylus": { - "optional": true - }, - "sugarss": { - "optional": true - }, - "terser": { - "optional": true - } - } - }, - "node_modules/yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", - "dev": true, - "license": "ISC" - } - } -} diff --git a/v3/internal/setupwizard/frontend/package.json b/v3/internal/setupwizard/frontend/package.json deleted file mode 100644 index f46a9cab6..000000000 --- a/v3/internal/setupwizard/frontend/package.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "name": "wails-setup-wizard", - "private": true, - "version": "0.0.0", - "type": "module", - "scripts": { - "dev": "vite", - "build": "tsc && vite build", - "preview": "vite preview" - }, - "dependencies": { - "framer-motion": "^12.23.25", - "react": "^18.3.1", - "react-dom": "^18.3.1" - }, - "devDependencies": { - "@types/react": "^18.3.12", - "@types/react-dom": "^18.3.1", - "@vitejs/plugin-react": "^4.3.3", - "autoprefixer": "^10.4.20", - "postcss": "^8.4.47", - "tailwindcss": "^3.4.14", - "typescript": "~5.6.2", - "vite": "^5.4.10" - } -} diff --git a/v3/internal/setupwizard/frontend/postcss.config.js b/v3/internal/setupwizard/frontend/postcss.config.js deleted file mode 100644 index 2e7af2b7f..000000000 --- a/v3/internal/setupwizard/frontend/postcss.config.js +++ /dev/null @@ -1,6 +0,0 @@ -export default { - plugins: { - tailwindcss: {}, - autoprefixer: {}, - }, -} diff --git a/v3/internal/setupwizard/frontend/public/wails-logo.png b/v3/internal/setupwizard/frontend/public/wails-logo.png deleted file mode 100755 index 0f32ab92f..000000000 Binary files a/v3/internal/setupwizard/frontend/public/wails-logo.png and /dev/null differ diff --git a/v3/internal/setupwizard/frontend/src/App.tsx b/v3/internal/setupwizard/frontend/src/App.tsx deleted file mode 100644 index 9202e172b..000000000 --- a/v3/internal/setupwizard/frontend/src/App.tsx +++ /dev/null @@ -1,1264 +0,0 @@ -import { useState, useEffect, createContext, useContext } from 'react'; -import { motion, AnimatePresence } from 'framer-motion'; -import type { DependencyStatus, SystemInfo, DockerStatus, GlobalDefaults } from './types'; -import { checkDependencies, getState, getDockerStatus, buildDockerImage, close, getDefaults, saveDefaults, startDockerBuildBackground } from './api'; -import WailsLogo from './components/WailsLogo'; - -type Step = 'welcome' | 'dependencies' | 'defaults' | 'docker' | 'complete'; -type Theme = 'light' | 'dark'; - -// Theme context -const ThemeContext = createContext<{ theme: Theme; toggleTheme: () => void }>({ - theme: 'dark', - toggleTheme: () => {} -}); - -const useTheme = () => useContext(ThemeContext); - -// Theme toggle button component -function ThemeToggle() { - const { theme, toggleTheme } = useTheme(); - - return ( - - ); -} - -// Classic wizard page slide animation -const pageVariants = { - initial: { opacity: 0, x: 50 }, - animate: { opacity: 1, x: 0 }, - exit: { opacity: 0, x: -50 } -}; - -// Wizard step indicator -function StepIndicator({ steps, currentStep }: { steps: { id: Step; label: string }[]; currentStep: Step }) { - const currentIndex = steps.findIndex(s => s.id === currentStep); - - return ( -
                    - {steps.map((step, i) => ( -
                    - - {step.label} - - {i < steps.length - 1 && ( - - )} -
                    - ))} -
                    - ); -} - -// Wizard footer with navigation buttons -function WizardFooter({ - onBack, - onNext, - onCancel, - nextLabel = 'Next', - backLabel = 'Back', - showBack = true, - nextDisabled = false, - showRetry = false, - onRetry -}: { - onBack?: () => void; - onNext: () => void; - onCancel?: () => void; - nextLabel?: string; - backLabel?: string; - showBack?: boolean; - nextDisabled?: boolean; - showRetry?: boolean; - onRetry?: () => void; -}) { - return ( -
                    -
                    - {onCancel && ( - - )} -
                    -
                    - {showBack && onBack && ( - - )} - {showRetry && onRetry && ( - - )} - -
                    -
                    - ); -} - -// Welcome Page -function WelcomePage({ system, onNext, onCancel, checking }: { system: SystemInfo | null; onNext: () => void; onCancel: () => void; checking: boolean }) { - return ( - -
                    -

                    - This wizard will help you set up your development environment. -

                    -
                    - - {system && ( -
                    -

                    System Information

                    -
                    - Operating System - {system.osName || system.os} ({system.arch}) - Wails Version - {system.wailsVersion.replace(/^v+/, '')} - Go Version - {system.goVersion.replace(/^go/, '')} -
                    -
                    - )} - - {checking ? ( -
                    -
                    -
                    - Checking dependencies... -
                    -
                    - ) : ( -
                    -

                    Setup will check:

                    -
                      -
                    • - - Required build dependencies (GTK, WebKit, GCC) -
                    • -
                    • - - Optional tools (npm, Docker) -
                    • -
                    • - - Cross-compilation capabilities -
                    • -
                    -
                    - )} - - - - ); -} - -// Dependency row component -function DependencyRow({ - dep -}: { - dep: DependencyStatus; -}) { - return ( -
                    - {/* Status icon */} -
                    - {dep.installed ? ( -
                    - - - -
                    - ) : dep.required ? ( -
                    - - - -
                    - ) : ( -
                    -
                    -
                    - )} -
                    - - {/* Info */} -
                    -
                    - - {dep.name} - - {!dep.required && ( - (optional) - )} - - {dep.version && ( - {dep.version} - )} -
                    - {dep.message && ( -

                    {dep.message}

                    - )} - - {/* Help URL link for non-system installs */} - {!dep.installed && dep.helpUrl && ( - - )} -
                    -
                    - ); -} - -// Dependencies Page -function DependenciesPage({ - dependencies, - onNext, - onBack, - onCancel, - onRetry, - checking -}: { - dependencies: DependencyStatus[]; - onNext: () => void; - onBack: () => void; - onCancel: () => void; - onRetry: () => void; - checking: boolean; -}) { - const [copied, setCopied] = useState(false); - const missingRequired = dependencies.filter(d => d.required && !d.installed); - const allRequiredInstalled = missingRequired.length === 0; - const missingDeps = dependencies.filter(d => !d.installed); - - // Build combined install command from all missing deps that have system commands (starting with sudo) - const combinedInstallCommand = (() => { - const systemCommands = missingDeps - .filter(d => d.installCommand?.startsWith('sudo ')) - .map(d => d.installCommand!); - - if (systemCommands.length === 0) return null; - - // Extract package names from "sudo pacman -S pkg" style commands - // Group by package manager - const pacmanPkgs: string[] = []; - const aptPkgs: string[] = []; - const dnfPkgs: string[] = []; - - for (const cmd of systemCommands) { - if (cmd.includes('pacman -S')) { - const match = cmd.match(/pacman -S\s+(.+)/); - if (match) pacmanPkgs.push(...match[1].split(/\s+/)); - } else if (cmd.includes('apt install')) { - const match = cmd.match(/apt install\s+(.+)/); - if (match) aptPkgs.push(...match[1].split(/\s+/)); - } else if (cmd.includes('dnf install')) { - const match = cmd.match(/dnf install\s+(.+)/); - if (match) dnfPkgs.push(...match[1].split(/\s+/)); - } - } - - if (pacmanPkgs.length > 0) { - return `sudo pacman -S ${pacmanPkgs.join(' ')}`; - } else if (aptPkgs.length > 0) { - return `sudo apt install ${aptPkgs.join(' ')}`; - } else if (dnfPkgs.length > 0) { - return `sudo dnf install ${dnfPkgs.join(' ')}`; - } - - return null; - })(); - - const copyCommand = () => { - if (combinedInstallCommand) { - navigator.clipboard.writeText(combinedInstallCommand); - setCopied(true); - setTimeout(() => setCopied(false), 2000); - } - }; - - return ( - - {/* Loading overlay for retry */} - {checking && ( -
                    -
                    - - Checking dependencies... -
                    -
                    - )} - -
                    -

                    System Dependencies

                    -

                    - The following dependencies are needed to build Wails applications. -

                    -
                    - - {/* All Dependencies */} -
                    -
                    - {dependencies.map(dep => ( - - ))} -
                    -
                    - - {/* Combined Install Command */} - {combinedInstallCommand && ( -
                    -
                    Install all missing dependencies:
                    -
                    - - {combinedInstallCommand} - - -
                    -
                    - )} - - {/* Status Summary - only show when all required are installed */} - {allRequiredInstalled && ( -
                    -
                    - - - - All required dependencies are installed. You can proceed. -
                    -
                    - )} - - -
                    - ); -} - -// Docker Page -function DockerPage({ - dockerStatus, - buildingImage, - onBuildImage, - onNext, - onBack, - onCancel -}: { - dockerStatus: DockerStatus | null; - buildingImage: boolean; - onBuildImage: () => void; - onNext: () => void; - onBack: () => void; - onCancel: () => void; -}) { - return ( - -
                    -

                    Cross-Platform Builds

                    -

                    - Docker enables building for macOS, Windows, and Linux from any platform. -

                    -
                    - -
                    -
                    -
                    - - - -
                    - -
                    -

                    Docker Status

                    - - {!dockerStatus ? ( -
                    Checking Docker...
                    - ) : !dockerStatus.installed ? ( -
                    -
                    - - Not installed -
                    -

                    - Docker is optional but required for cross-platform builds. -

                    - - Install Docker Desktop - - - - -
                    - ) : !dockerStatus.running ? ( -
                    -
                    - - Installed but not running -
                    -

                    - Start Docker Desktop to enable cross-platform builds. -

                    -
                    - ) : dockerStatus.imageBuilt ? ( -
                    -
                    - - Ready for cross-platform builds -
                    -

                    - Docker {dockerStatus.version} • wails-cross image installed -

                    -
                    - ) : buildingImage ? ( -
                    -
                    - - Building wails-cross image... {dockerStatus.pullProgress}% -
                    -
                    - -
                    -
                    - ) : ( -
                    -
                    - - Cross-compilation image not installed -
                    -

                    - Docker {dockerStatus.version} is running. Build the wails-cross image to enable cross-platform builds. -

                    - -
                    - )} -
                    -
                    -
                    - -
                    -

                    What you can build:

                    -
                    -
                    -
                    - {/* Apple logo */} - - - -
                    -
                    macOS
                    -
                    .app / .dmg
                    -
                    -
                    -
                    - {/* Windows logo */} - - - -
                    -
                    Windows
                    -
                    .exe / .msi
                    -
                    -
                    -
                    - {/* Tux - Linux penguin */} - - - -
                    -
                    Linux
                    -
                    .deb / .rpm / PKGBUILD
                    -
                    -
                    -
                    - - -
                    - ); -} - -// Defaults Page - Configure global defaults for new projects -function DefaultsPage({ - defaults, - onDefaultsChange, - onNext, - onBack, - onCancel, - saving -}: { - defaults: GlobalDefaults; - onDefaultsChange: (defaults: GlobalDefaults) => void; - onNext: () => void; - onBack: () => void; - onCancel: () => void; - saving: boolean; -}) { - return ( - -
                    -

                    Project Defaults

                    -

                    - Configure defaults for new Wails projects. -

                    -
                    - - {/* Author Information */} -
                    -

                    Author Information

                    -
                    -
                    - - onDefaultsChange({ - ...defaults, - author: { ...defaults.author, name: e.target.value } - })} - placeholder="John Doe" - className="w-full bg-white dark:bg-gray-800 border border-gray-300 dark:border-gray-700 rounded px-2 py-1 text-xs text-gray-900 dark:text-gray-200 placeholder-gray-400 dark:placeholder-gray-600 focus:border-red-500 focus:outline-none" - /> -
                    -
                    - - onDefaultsChange({ - ...defaults, - author: { ...defaults.author, company: e.target.value } - })} - placeholder="My Company" - className="w-full bg-white dark:bg-gray-800 border border-gray-300 dark:border-gray-700 rounded px-2 py-1 text-xs text-gray-900 dark:text-gray-200 placeholder-gray-400 dark:placeholder-gray-600 focus:border-red-500 focus:outline-none" - /> -
                    -
                    -
                    - - {/* Project Defaults */} -
                    -

                    Project Settings

                    -
                    -
                    -
                    - - onDefaultsChange({ - ...defaults, - project: { ...defaults.project, productIdentifierPrefix: e.target.value } - })} - placeholder="com.mycompany" - className="w-full bg-white dark:bg-gray-800 border border-gray-300 dark:border-gray-700 rounded px-2 py-1 text-xs text-gray-900 dark:text-gray-200 placeholder-gray-400 dark:placeholder-gray-600 focus:border-red-500 focus:outline-none font-mono" - /> -
                    -
                    - - onDefaultsChange({ - ...defaults, - project: { ...defaults.project, defaultVersion: e.target.value } - })} - placeholder="0.1.0" - className="w-full bg-white dark:bg-gray-800 border border-gray-300 dark:border-gray-700 rounded px-2 py-1 text-xs text-gray-900 dark:text-gray-200 placeholder-gray-400 dark:placeholder-gray-600 focus:border-red-500 focus:outline-none font-mono" - /> -
                    -
                    -
                    - - -
                    -
                    -
                    - - {/* macOS Signing */} -
                    -
                    - - - -

                    macOS Code Signing

                    - (optional) -
                    -

                    These are public identifiers. App-specific passwords are stored securely in your Keychain.

                    -
                    -
                    - - onDefaultsChange({ - ...defaults, - signing: { - ...defaults.signing, - macOS: { ...defaults.signing?.macOS, developerID: e.target.value, appleID: defaults.signing?.macOS?.appleID || '', teamID: defaults.signing?.macOS?.teamID || '' }, - windows: defaults.signing?.windows || { certificatePath: '', timestampServer: '' } - } - })} - placeholder="Developer ID Application: John Doe (TEAMID)" - className="w-full bg-white dark:bg-gray-800 border border-gray-300 dark:border-gray-700 rounded px-2 py-1 text-xs text-gray-900 dark:text-gray-200 placeholder-gray-400 dark:placeholder-gray-600 focus:border-red-500 focus:outline-none font-mono" - /> -
                    -
                    -
                    - - onDefaultsChange({ - ...defaults, - signing: { - ...defaults.signing, - macOS: { ...defaults.signing?.macOS, appleID: e.target.value, developerID: defaults.signing?.macOS?.developerID || '', teamID: defaults.signing?.macOS?.teamID || '' }, - windows: defaults.signing?.windows || { certificatePath: '', timestampServer: '' } - } - })} - placeholder="you@example.com" - className="w-full bg-white dark:bg-gray-800 border border-gray-300 dark:border-gray-700 rounded px-2 py-1 text-xs text-gray-900 dark:text-gray-200 placeholder-gray-400 dark:placeholder-gray-600 focus:border-red-500 focus:outline-none" - /> -
                    -
                    - - onDefaultsChange({ - ...defaults, - signing: { - ...defaults.signing, - macOS: { ...defaults.signing?.macOS, teamID: e.target.value, developerID: defaults.signing?.macOS?.developerID || '', appleID: defaults.signing?.macOS?.appleID || '' }, - windows: defaults.signing?.windows || { certificatePath: '', timestampServer: '' } - } - })} - placeholder="ABCD1234EF" - className="w-full bg-white dark:bg-gray-800 border border-gray-300 dark:border-gray-700 rounded px-2 py-1 text-xs text-gray-900 dark:text-gray-200 placeholder-gray-400 dark:placeholder-gray-600 focus:border-red-500 focus:outline-none font-mono" - /> -
                    -
                    -
                    -
                    - - {/* Windows Signing */} -
                    -
                    - - - -

                    Windows Code Signing

                    - (optional) -
                    -
                    -
                    - - onDefaultsChange({ - ...defaults, - signing: { - ...defaults.signing, - macOS: defaults.signing?.macOS || { developerID: '', appleID: '', teamID: '' }, - windows: { ...defaults.signing?.windows, certificatePath: e.target.value, timestampServer: defaults.signing?.windows?.timestampServer || '' } - } - })} - placeholder="/path/to/certificate.pfx" - className="w-full bg-white dark:bg-gray-800 border border-gray-300 dark:border-gray-700 rounded px-2 py-1 text-xs text-gray-900 dark:text-gray-200 placeholder-gray-400 dark:placeholder-gray-600 focus:border-red-500 focus:outline-none font-mono" - /> -
                    -
                    - - onDefaultsChange({ - ...defaults, - signing: { - ...defaults.signing, - macOS: defaults.signing?.macOS || { developerID: '', appleID: '', teamID: '' }, - windows: { ...defaults.signing?.windows, timestampServer: e.target.value, certificatePath: defaults.signing?.windows?.certificatePath || '' } - } - })} - placeholder="http://timestamp.digicert.com" - className="w-full bg-white dark:bg-gray-800 border border-gray-300 dark:border-gray-700 rounded px-2 py-1 text-xs text-gray-900 dark:text-gray-200 placeholder-gray-400 dark:placeholder-gray-600 focus:border-red-500 focus:outline-none font-mono" - /> -
                    -
                    -
                    - - {/* Info about where this is stored */} -
                    - Stored in: ~/.config/wails/defaults.yaml -
                    - - -
                    - ); -} - -// Persistent Docker status indicator - shown across all pages when Docker build is in progress -function DockerStatusIndicator({ - status, - visible -}: { - status: DockerStatus | null; - visible: boolean; -}) { - if (!visible || !status) return null; - - // Don't show if Docker is not installed/running or if image is already built - if (!status.installed || !status.running) return null; - if (status.imageBuilt && status.pullStatus !== 'pulling') return null; - - const isPulling = status.pullStatus === 'pulling'; - const progress = status.pullProgress || 0; - - return ( - -
                    -
                    - {/* Docker icon */} -
                    - - - -
                    - -
                    - {isPulling ? ( - <> -
                    - - Downloading cross-compile image... -
                    -
                    -
                    - -
                    - {progress}% -
                    - - ) : status.imageBuilt ? ( -
                    - - - - Docker image ready -
                    - ) : ( -
                    - Preparing Docker build... -
                    - )} -
                    -
                    -
                    -
                    - ); -} - -// Copyable command component -function CopyableCommand({ command, label }: { command: string; label: string }) { - const [copied, setCopied] = useState(false); - - const copyCommand = () => { - navigator.clipboard.writeText(command); - setCopied(true); - setTimeout(() => setCopied(false), 2000); - }; - - return ( -
                    -

                    {label}

                    -
                    - - {command} - - -
                    -
                    - ); -} - -// Complete Page -function CompletePage({ onClose }: { onClose: () => void }) { - return ( - - - - - - - -

                    Setup Complete

                    -

                    - Your development environment is ready to use. -

                    - -
                    -

                    Next Steps

                    -
                    - - - -
                    -
                    - - -
                    - ); -} - -// Main App -export default function App() { - const [step, setStep] = useState('welcome'); - const [dependencies, setDependencies] = useState([]); - const [system, setSystem] = useState(null); - const [dockerStatus, setDockerStatus] = useState(null); - const [buildingImage, setBuildingImage] = useState(false); - const [checkingDeps, setCheckingDeps] = useState(false); - const [defaults, setDefaults] = useState({ - author: { name: '', company: '' }, - project: { - productIdentifierPrefix: 'com.example', - defaultTemplate: 'vanilla', - copyrightTemplate: '© {year}, {company}', - descriptionTemplate: 'A {name} application', - defaultVersion: '0.1.0' - } - }); - const [savingDefaults, setSavingDefaults] = useState(false); - const [backgroundDockerStarted, setBackgroundDockerStarted] = useState(false); - const [theme, setTheme] = useState(() => { - // Default to dark, but check for saved preference or system preference - if (typeof window !== 'undefined') { - const saved = localStorage.getItem('wails-setup-theme'); - if (saved === 'light' || saved === 'dark') return saved; - if (window.matchMedia('(prefers-color-scheme: light)').matches) return 'light'; - } - return 'dark'; - }); - - const toggleTheme = () => { - setTheme(prev => { - const next = prev === 'dark' ? 'light' : 'dark'; - localStorage.setItem('wails-setup-theme', next); - return next; - }); - }; - - // Apply theme class to document - useEffect(() => { - if (theme === 'dark') { - document.documentElement.classList.add('dark'); - } else { - document.documentElement.classList.remove('dark'); - } - }, [theme]); - - const steps: { id: Step; label: string }[] = [ - { id: 'welcome', label: 'Welcome' }, - { id: 'dependencies', label: 'Dependencies' }, - { id: 'docker', label: 'Docker' }, - { id: 'defaults', label: 'Defaults' }, - { id: 'complete', label: 'Complete' }, - ]; - - useEffect(() => { - init(); - }, []); - - const init = async () => { - const state = await getState(); - setSystem(state.system); - }; - - const handleNext = async () => { - if (step === 'welcome') { - setCheckingDeps(true); - const deps = await checkDependencies(); - setDependencies(deps); - setCheckingDeps(false); - setStep('dependencies'); - } else if (step === 'dependencies') { - // Check docker status and start background build if available - const dockerDep = dependencies.find(d => d.name === 'docker'); - if (dockerDep?.installed) { - const docker = await getDockerStatus(); - setDockerStatus(docker); - // Start background Docker build (so it downloads while user configures defaults) - startBackgroundDockerBuild(dependencies); - } - setStep('docker'); - } else if (step === 'docker') { - // Load existing defaults when entering defaults page - const loadedDefaults = await getDefaults(); - setDefaults(loadedDefaults); - setStep('defaults'); - } else if (step === 'defaults') { - // Save defaults before proceeding - setSavingDefaults(true); - await saveDefaults(defaults); - setSavingDefaults(false); - setStep('complete'); - } - }; - - const handleRetryDeps = async () => { - setCheckingDeps(true); - const deps = await checkDependencies(); - setDependencies(deps); - setCheckingDeps(false); - }; - - const handleBack = () => { - if (step === 'dependencies') setStep('welcome'); - else if (step === 'docker') setStep('dependencies'); - else if (step === 'defaults') setStep('docker'); - }; - - const handleBuildImage = async () => { - setBuildingImage(true); - await buildDockerImage(); - - const poll = async () => { - const status = await getDockerStatus(); - setDockerStatus(status); - if (status.pullStatus === 'pulling') { - setTimeout(poll, 1000); - } else { - setBuildingImage(false); - } - }; - poll(); - }; - - // Start background Docker build after dependencies check - const startBackgroundDockerBuild = async (deps: DependencyStatus[]) => { - const dockerDep = deps.find(d => d.name === 'docker'); - if (!dockerDep?.installed || backgroundDockerStarted) return; - - setBackgroundDockerStarted(true); - - // Try to start background build - const result = await startDockerBuildBackground(); - setDockerStatus(result.status); - - // If build started, poll for status - if (result.started && result.status.pullStatus === 'pulling') { - setBuildingImage(true); - const poll = async () => { - const status = await getDockerStatus(); - setDockerStatus(status); - if (status.pullStatus === 'pulling') { - setTimeout(poll, 1000); - } else { - setBuildingImage(false); - } - }; - setTimeout(poll, 1000); - } - }; - - const handleClose = async () => { - await close(); - window.close(); - }; - - const handleCancel = handleClose; - - // Show Docker indicator on defaults page when Docker build is in progress (Docker now downloads while user configures) - const showDockerIndicator = backgroundDockerStarted && step === 'defaults'; - - return ( - -
                    - {/* Theme toggle */} - - - {/* Persistent Docker status indicator */} - - {showDockerIndicator && ( - - )} - - -
                    - {/* Header with logo and step indicator */} -
                    - -
                    - -
                    -
                    - - {/* Wizard container */} -
                    - - - {step === 'welcome' && ( - - )} - {step === 'dependencies' && ( - - )} - {step === 'defaults' && ( - - )} - {step === 'docker' && ( - - )} - {step === 'complete' && ( - - )} - -
                    - - {/* Footer */} -
                    - Wails • Build cross-platform apps with Go -
                    -
                    -
                    -
                    - ); -} diff --git a/v3/internal/setupwizard/frontend/src/api.ts b/v3/internal/setupwizard/frontend/src/api.ts deleted file mode 100644 index 73c312b89..000000000 --- a/v3/internal/setupwizard/frontend/src/api.ts +++ /dev/null @@ -1,100 +0,0 @@ -import type { WizardState, DependencyStatus, DockerStatus, UserConfig, WailsConfig, GlobalDefaults } from './types'; - -const API_BASE = '/api'; - -export async function getState(): Promise { - const response = await fetch(`${API_BASE}/state`); - return response.json(); -} - -export async function checkDependencies(): Promise { - const response = await fetch(`${API_BASE}/dependencies/check`); - return response.json(); -} - -export async function getDockerStatus(): Promise { - const response = await fetch(`${API_BASE}/docker/status`); - return response.json(); -} - -export async function buildDockerImage(): Promise<{ status: string }> { - const response = await fetch(`${API_BASE}/docker/build`, { method: 'POST' }); - return response.json(); -} - -export interface DockerStartBackgroundResponse { - started: boolean; - reason?: string; - status: DockerStatus; -} - -export async function startDockerBuildBackground(): Promise { - const response = await fetch(`${API_BASE}/docker/start-background`, { method: 'POST' }); - return response.json(); -} - -export async function detectConfig(): Promise> { - const response = await fetch(`${API_BASE}/config/detect`); - return response.json(); -} - -export async function saveConfig(config: UserConfig): Promise<{ status: string }> { - const response = await fetch(`${API_BASE}/config/save`, { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify(config), - }); - return response.json(); -} - -export async function complete(): Promise<{ status: string; duration: string }> { - const response = await fetch(`${API_BASE}/complete`); - return response.json(); -} - -export async function close(): Promise { - await fetch(`${API_BASE}/close`); -} - -export async function getWailsConfig(): Promise { - const response = await fetch(`${API_BASE}/wails-config`); - return response.json(); -} - -export async function saveWailsConfig(config: WailsConfig): Promise<{ status: string }> { - const response = await fetch(`${API_BASE}/wails-config`, { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify(config), - }); - return response.json(); -} - -export interface InstallResult { - success: boolean; - output: string; - error?: string; -} - -export async function installDependency(command: string): Promise { - const response = await fetch(`${API_BASE}/dependencies/install`, { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify({ command }), - }); - return response.json(); -} - -export async function getDefaults(): Promise { - const response = await fetch(`${API_BASE}/defaults`); - return response.json(); -} - -export async function saveDefaults(defaults: GlobalDefaults): Promise<{ status: string; path: string }> { - const response = await fetch(`${API_BASE}/defaults`, { - method: 'POST', - headers: { 'Content-Type': 'application/json' }, - body: JSON.stringify(defaults), - }); - return response.json(); -} diff --git a/v3/internal/setupwizard/frontend/src/assets/wails-logo-black-text.svg b/v3/internal/setupwizard/frontend/src/assets/wails-logo-black-text.svg deleted file mode 100755 index e90698049..000000000 --- a/v3/internal/setupwizard/frontend/src/assets/wails-logo-black-text.svg +++ /dev/null @@ -1,56 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/v3/internal/setupwizard/frontend/src/assets/wails-logo-white-text.svg b/v3/internal/setupwizard/frontend/src/assets/wails-logo-white-text.svg deleted file mode 100755 index 5ebf9d616..000000000 --- a/v3/internal/setupwizard/frontend/src/assets/wails-logo-white-text.svg +++ /dev/null @@ -1,56 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/v3/internal/setupwizard/frontend/src/components/WailsLogo.tsx b/v3/internal/setupwizard/frontend/src/components/WailsLogo.tsx deleted file mode 100644 index ef873d80c..000000000 --- a/v3/internal/setupwizard/frontend/src/components/WailsLogo.tsx +++ /dev/null @@ -1,25 +0,0 @@ -import wailsLogoWhite from '../assets/wails-logo-white-text.svg'; -import wailsLogoBlack from '../assets/wails-logo-black-text.svg'; - -interface WailsLogoProps { - className?: string; - size?: number; - theme?: 'light' | 'dark'; -} - -export default function WailsLogo({ className = '', size = 240, theme = 'dark' }: WailsLogoProps) { - // White text for dark mode, black text for light mode - const logoSrc = theme === 'dark' ? wailsLogoWhite : wailsLogoBlack; - - return ( - Wails - ); -} diff --git a/v3/internal/setupwizard/frontend/src/index.css b/v3/internal/setupwizard/frontend/src/index.css deleted file mode 100644 index 2edd377fc..000000000 --- a/v3/internal/setupwizard/frontend/src/index.css +++ /dev/null @@ -1,112 +0,0 @@ -@tailwind base; -@tailwind components; -@tailwind utilities; - -:root { - --wails-red: #ef4444; - --wails-red-dark: #dc2626; - --wails-red-light: #f87171; - --bg-primary: #0f0f0f; - --bg-secondary: #1f2937; - --bg-tertiary: #374151; -} - -* { - box-sizing: border-box; -} - -html, body, #root { - margin: 0; - padding: 0; - min-height: 100vh; - background: var(--bg-primary); - color: white; - font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', sans-serif; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; -} - -/* Gradient text utility */ -.gradient-text { - background: linear-gradient(135deg, #ffffff 0%, #ef4444 100%); - -webkit-background-clip: text; - -webkit-text-fill-color: transparent; - background-clip: text; -} - -/* Glass morphism card */ -.glass-card { - background: rgba(31, 41, 55, 0.8); - backdrop-filter: blur(10px); - border: 1px solid rgba(55, 65, 81, 0.5); -} - -/* Subtle grid background */ -.grid-bg { - background-image: - linear-gradient(rgba(239, 68, 68, 0.03) 1px, transparent 1px), - linear-gradient(90deg, rgba(239, 68, 68, 0.03) 1px, transparent 1px); - background-size: 40px 40px; -} - -/* Radial glow */ -.radial-glow { - background: radial-gradient(ellipse at center, rgba(239, 68, 68, 0.1) 0%, transparent 70%); -} - -/* Custom scrollbar */ -::-webkit-scrollbar { - width: 8px; -} - -::-webkit-scrollbar-track { - background: var(--bg-primary); -} - -::-webkit-scrollbar-thumb { - background: var(--bg-tertiary); - border-radius: 4px; -} - -::-webkit-scrollbar-thumb:hover { - background: #4b5563; -} - -/* Button hover effect */ -.btn-primary { - @apply bg-gradient-to-r from-red-500 to-red-600 text-white font-semibold - py-3 px-8 rounded-xl shadow-lg transition-all duration-300 - hover:scale-105 hover:shadow-xl hover:shadow-red-500/30 - active:scale-95; -} - -.btn-secondary { - @apply bg-transparent border border-gray-600 text-gray-300 font-medium - py-3 px-8 rounded-xl transition-all duration-300 - hover:border-gray-500 hover:text-white hover:bg-gray-800/50; -} - -/* Status badge animations */ -@keyframes spin { - to { transform: rotate(360deg); } -} - -.spinner { - animation: spin 1s linear infinite; -} - -/* Draw check animation for success */ -.check-path { - stroke-dasharray: 100; - stroke-dashoffset: 100; - animation: drawCheck 0.5s ease-out forwards; -} - -/* Reduced motion support */ -@media (prefers-reduced-motion: reduce) { - *, *::before, *::after { - animation-duration: 0.01ms !important; - animation-iteration-count: 1 !important; - transition-duration: 0.01ms !important; - } -} diff --git a/v3/internal/setupwizard/frontend/src/main.tsx b/v3/internal/setupwizard/frontend/src/main.tsx deleted file mode 100644 index 964aeb4c7..000000000 --- a/v3/internal/setupwizard/frontend/src/main.tsx +++ /dev/null @@ -1,10 +0,0 @@ -import React from 'react' -import ReactDOM from 'react-dom/client' -import App from './App' -import './index.css' - -ReactDOM.createRoot(document.getElementById('root')!).render( - - - , -) diff --git a/v3/internal/setupwizard/frontend/src/types.ts b/v3/internal/setupwizard/frontend/src/types.ts deleted file mode 100644 index 7545955e0..000000000 --- a/v3/internal/setupwizard/frontend/src/types.ts +++ /dev/null @@ -1,96 +0,0 @@ -export interface DependencyStatus { - name: string; - installed: boolean; - version?: string; - path?: string; - status: 'installed' | 'not_installed' | 'needs_update' | 'checking'; - required: boolean; - message?: string; - installCommand?: string; - helpUrl?: string; -} - -export interface DockerStatus { - installed: boolean; - running: boolean; - version?: string; - imageBuilt: boolean; - imageName: string; - pullProgress: number; - pullStatus: 'idle' | 'pulling' | 'complete' | 'error'; - pullError?: string; -} - -export interface UserConfig { - developerName: string; - email: string; - defaultFramework: string; - projectDirectory: string; - editor: string; -} - -export interface WailsConfig { - info: { - companyName: string; - productName: string; - productIdentifier: string; - description: string; - copyright: string; - comments: string; - version: string; - }; -} - -export interface SystemInfo { - os: string; - arch: string; - wailsVersion: string; - goVersion: string; - homeDir: string; - osName?: string; - osVersion?: string; - gitName?: string; - gitEmail?: string; -} - -export interface WizardState { - currentStep: number; - dependencies: DependencyStatus[]; - docker: DockerStatus; - config: UserConfig; - system: SystemInfo; - startTime: string; -} - -export type Step = 'splash' | 'welcome' | 'dependencies' | 'docker' | 'defaults' | 'config' | 'wails-config' | 'complete'; - -export interface AuthorDefaults { - name: string; - company: string; -} - -export interface ProjectDefaults { - productIdentifierPrefix: string; - defaultTemplate: string; - copyrightTemplate: string; - descriptionTemplate: string; - defaultVersion: string; -} - -export interface SigningDefaults { - macOS: { - developerID: string; // e.g., "Developer ID Application: John Doe (TEAMID)" - appleID: string; // Apple ID for notarization - teamID: string; // Apple Team ID - }; - windows: { - certificatePath: string; // Path to .pfx certificate - timestampServer: string; // e.g., "http://timestamp.digicert.com" - }; -} - -export interface GlobalDefaults { - author: AuthorDefaults; - project: ProjectDefaults; - signing?: SigningDefaults; -} diff --git a/v3/internal/setupwizard/frontend/src/vite-env.d.ts b/v3/internal/setupwizard/frontend/src/vite-env.d.ts deleted file mode 100644 index d786e046b..000000000 --- a/v3/internal/setupwizard/frontend/src/vite-env.d.ts +++ /dev/null @@ -1,6 +0,0 @@ -/// - -declare module '*.svg' { - const content: string; - export default content; -} diff --git a/v3/internal/setupwizard/frontend/tailwind.config.js b/v3/internal/setupwizard/frontend/tailwind.config.js deleted file mode 100644 index eaf94b71a..000000000 --- a/v3/internal/setupwizard/frontend/tailwind.config.js +++ /dev/null @@ -1,57 +0,0 @@ -/** @type {import('tailwindcss').Config} */ -export default { - content: [ - "./index.html", - "./src/**/*.{js,ts,jsx,tsx}", - ], - darkMode: 'class', - theme: { - extend: { - colors: { - 'wails-red': { - DEFAULT: '#ef4444', - dark: '#dc2626', - light: '#f87171', - }, - }, - fontFamily: { - sans: ['Inter', '-apple-system', 'BlinkMacSystemFont', 'Segoe UI', 'Roboto', 'Oxygen', 'Ubuntu', 'Cantarell', 'sans-serif'], - }, - animation: { - 'fade-in': 'fadeIn 0.5s ease-out', - 'slide-up': 'slideUp 0.5s ease-out', - 'scale-in': 'scaleIn 0.3s ease-out', - 'pulse-glow': 'pulseGlow 2s ease-in-out infinite', - 'draw-check': 'drawCheck 0.5s ease-out forwards', - 'shimmer': 'shimmer 2s linear infinite', - }, - keyframes: { - fadeIn: { - '0%': { opacity: '0' }, - '100%': { opacity: '1' }, - }, - slideUp: { - '0%': { opacity: '0', transform: 'translateY(20px)' }, - '100%': { opacity: '1', transform: 'translateY(0)' }, - }, - scaleIn: { - '0%': { opacity: '0', transform: 'scale(0.9)' }, - '100%': { opacity: '1', transform: 'scale(1)' }, - }, - pulseGlow: { - '0%, 100%': { boxShadow: '0 0 20px rgba(239, 68, 68, 0.4)' }, - '50%': { boxShadow: '0 0 40px rgba(239, 68, 68, 0.6)' }, - }, - drawCheck: { - '0%': { strokeDashoffset: '100' }, - '100%': { strokeDashoffset: '0' }, - }, - shimmer: { - '0%': { backgroundPosition: '-200% 0' }, - '100%': { backgroundPosition: '200% 0' }, - }, - }, - }, - }, - plugins: [], -} diff --git a/v3/internal/setupwizard/frontend/tsconfig.json b/v3/internal/setupwizard/frontend/tsconfig.json deleted file mode 100644 index 109f0ac28..000000000 --- a/v3/internal/setupwizard/frontend/tsconfig.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "compilerOptions": { - "target": "ES2020", - "useDefineForClassFields": true, - "lib": ["ES2020", "DOM", "DOM.Iterable"], - "module": "ESNext", - "skipLibCheck": true, - "moduleResolution": "bundler", - "allowImportingTsExtensions": true, - "isolatedModules": true, - "moduleDetection": "force", - "noEmit": true, - "jsx": "react-jsx", - "strict": true, - "noUnusedLocals": true, - "noUnusedParameters": true, - "noFallthroughCasesInSwitch": true - }, - "include": ["src"] -} diff --git a/v3/internal/setupwizard/frontend/vite.config.ts b/v3/internal/setupwizard/frontend/vite.config.ts deleted file mode 100644 index 927fd4858..000000000 --- a/v3/internal/setupwizard/frontend/vite.config.ts +++ /dev/null @@ -1,10 +0,0 @@ -import { defineConfig } from 'vite' -import react from '@vitejs/plugin-react' - -export default defineConfig({ - plugins: [react()], - build: { - outDir: 'dist', - emptyOutDir: true, - }, -}) diff --git a/v3/internal/setupwizard/wizard.go b/v3/internal/setupwizard/wizard.go deleted file mode 100644 index 7073f1fe1..000000000 --- a/v3/internal/setupwizard/wizard.go +++ /dev/null @@ -1,628 +0,0 @@ -package setupwizard - -import ( - "context" - "embed" - "encoding/json" - "fmt" - "io/fs" - "net" - "net/http" - "os" - "os/exec" - "path/filepath" - "runtime" - "strings" - "sync" - "time" - - "github.com/pkg/browser" - "github.com/wailsapp/wails/v3/internal/operatingsystem" - "github.com/wailsapp/wails/v3/internal/version" - "gopkg.in/yaml.v3" -) - -//go:embed frontend/dist/* -var frontendFS embed.FS - -// DependencyStatus represents the status of a dependency -type DependencyStatus struct { - Name string `json:"name"` - Installed bool `json:"installed"` - Version string `json:"version,omitempty"` - Status string `json:"status"` // "installed", "not_installed", "needs_update" - Required bool `json:"required"` - Message string `json:"message,omitempty"` - InstallCommand string `json:"installCommand,omitempty"` - HelpURL string `json:"helpUrl,omitempty"` -} - -// DockerStatus represents Docker installation and image status -type DockerStatus struct { - Installed bool `json:"installed"` - Running bool `json:"running"` - Version string `json:"version,omitempty"` - ImageBuilt bool `json:"imageBuilt"` - ImageName string `json:"imageName"` - PullProgress int `json:"pullProgress"` - PullStatus string `json:"pullStatus"` // "idle", "pulling", "complete", "error" - PullError string `json:"pullError,omitempty"` -} - -// WailsConfigInfo represents the info section of wails.yaml -type WailsConfigInfo struct { - CompanyName string `json:"companyName" yaml:"companyName"` - ProductName string `json:"productName" yaml:"productName"` - ProductIdentifier string `json:"productIdentifier" yaml:"productIdentifier"` - Description string `json:"description" yaml:"description"` - Copyright string `json:"copyright" yaml:"copyright"` - Comments string `json:"comments,omitempty" yaml:"comments,omitempty"` - Version string `json:"version" yaml:"version"` -} - -// WailsConfig represents the wails.yaml configuration -type WailsConfig struct { - Info WailsConfigInfo `json:"info" yaml:"info"` -} - -// SystemInfo contains detected system information -type SystemInfo struct { - OS string `json:"os"` - Arch string `json:"arch"` - WailsVersion string `json:"wailsVersion"` - GoVersion string `json:"goVersion"` - HomeDir string `json:"homeDir"` - OSName string `json:"osName,omitempty"` - OSVersion string `json:"osVersion,omitempty"` -} - -// WizardState represents the complete wizard state -type WizardState struct { - Dependencies []DependencyStatus `json:"dependencies"` - System SystemInfo `json:"system"` - StartTime time.Time `json:"startTime"` -} - -// Wizard is the setup wizard server -type Wizard struct { - server *http.Server - state WizardState - stateMu sync.RWMutex - dockerStatus DockerStatus - dockerMu sync.RWMutex - done chan struct{} - shutdown chan struct{} -} - -// New creates a new setup wizard -func New() *Wizard { - return &Wizard{ - done: make(chan struct{}), - shutdown: make(chan struct{}), - state: WizardState{ - StartTime: time.Now(), - }, - } -} - -// Run starts the wizard and opens it in the browser -func (w *Wizard) Run() error { - // Initialize system info - w.initSystemInfo() - - // Find an available port - listener, err := net.Listen("tcp", "127.0.0.1:0") - if err != nil { - return fmt.Errorf("failed to find available port: %w", err) - } - - port := listener.Addr().(*net.TCPAddr).Port - url := fmt.Sprintf("http://127.0.0.1:%d", port) - - // Set up HTTP routes - mux := http.NewServeMux() - w.setupRoutes(mux) - - w.server = &http.Server{ - Handler: mux, - } - - // Start server in goroutine - go func() { - if err := w.server.Serve(listener); err != nil && err != http.ErrServerClosed { - fmt.Fprintf(os.Stderr, "Server error: %v\n", err) - } - }() - - fmt.Printf("Setup wizard running at %s\n", url) - - // Open browser - if err := browser.OpenURL(url); err != nil { - fmt.Printf("Please open %s in your browser\n", url) - } - - // Wait for completion or shutdown - select { - case <-w.done: - fmt.Println("\nSetup completed successfully!") - case <-w.shutdown: - fmt.Println("\nSetup wizard closed.") - } - - // Shutdown server - ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) - defer cancel() - return w.server.Shutdown(ctx) -} - -func (w *Wizard) setupRoutes(mux *http.ServeMux) { - // API routes - mux.HandleFunc("/api/state", w.handleState) - mux.HandleFunc("/api/dependencies/check", w.handleCheckDependencies) - mux.HandleFunc("/api/dependencies/install", w.handleInstallDependency) - mux.HandleFunc("/api/docker/status", w.handleDockerStatus) - mux.HandleFunc("/api/docker/build", w.handleDockerBuild) - mux.HandleFunc("/api/docker/start-background", w.handleDockerStartBackground) - mux.HandleFunc("/api/wails-config", w.handleWailsConfig) - mux.HandleFunc("/api/defaults", w.handleDefaults) - mux.HandleFunc("/api/complete", w.handleComplete) - mux.HandleFunc("/api/close", w.handleClose) - - // Serve frontend - frontendDist, err := fs.Sub(frontendFS, "frontend/dist") - if err != nil { - panic(err) - } - fileServer := http.FileServer(http.FS(frontendDist)) - - mux.HandleFunc("/", func(rw http.ResponseWriter, r *http.Request) { - // Try to serve the file - path := r.URL.Path - if path == "/" { - path = "/index.html" - } - - // Check if file exists - if _, err := fs.Stat(frontendDist, strings.TrimPrefix(path, "/")); err != nil { - // Serve index.html for SPA routing - r.URL.Path = "/" - } - - fileServer.ServeHTTP(rw, r) - }) -} - -func (w *Wizard) initSystemInfo() { - w.stateMu.Lock() - defer w.stateMu.Unlock() - - homeDir, _ := os.UserHomeDir() - - w.state.System = SystemInfo{ - OS: runtime.GOOS, - Arch: runtime.GOARCH, - WailsVersion: version.String(), - GoVersion: runtime.Version(), - HomeDir: homeDir, - } - - // Get OS details - if info, err := operatingsystem.Info(); err == nil { - w.state.System.OSName = info.Name - w.state.System.OSVersion = info.Version - } -} - -func (w *Wizard) handleState(rw http.ResponseWriter, r *http.Request) { - w.stateMu.RLock() - defer w.stateMu.RUnlock() - - rw.Header().Set("Content-Type", "application/json") - json.NewEncoder(rw).Encode(w.state) -} - -func (w *Wizard) handleCheckDependencies(rw http.ResponseWriter, r *http.Request) { - deps := w.checkAllDependencies() - - w.stateMu.Lock() - w.state.Dependencies = deps - w.stateMu.Unlock() - - rw.Header().Set("Content-Type", "application/json") - json.NewEncoder(rw).Encode(deps) -} - -func (w *Wizard) handleWailsConfig(rw http.ResponseWriter, r *http.Request) { - rw.Header().Set("Content-Type", "application/json") - - // Find wails.yaml in current directory or parent directories - configPath := findWailsConfig() - - switch r.Method { - case http.MethodGet: - if configPath == "" { - json.NewEncoder(rw).Encode(nil) - return - } - - data, err := os.ReadFile(configPath) - if err != nil { - json.NewEncoder(rw).Encode(nil) - return - } - - var config WailsConfig - if err := yaml.Unmarshal(data, &config); err != nil { - json.NewEncoder(rw).Encode(nil) - return - } - - json.NewEncoder(rw).Encode(config) - - case http.MethodPost: - var config WailsConfig - if err := json.NewDecoder(r.Body).Decode(&config); err != nil { - http.Error(rw, err.Error(), http.StatusBadRequest) - return - } - - if configPath == "" { - configPath = "wails.yaml" - } - - data, err := yaml.Marshal(&config) - if err != nil { - http.Error(rw, err.Error(), http.StatusInternalServerError) - return - } - - if err := os.WriteFile(configPath, data, 0644); err != nil { - http.Error(rw, err.Error(), http.StatusInternalServerError) - return - } - - json.NewEncoder(rw).Encode(map[string]string{"status": "saved", "path": configPath}) - - default: - http.Error(rw, "Method not allowed", http.StatusMethodNotAllowed) - } -} - -func findWailsConfig() string { - dir, err := os.Getwd() - if err != nil { - return "" - } - - for { - configPath := filepath.Join(dir, "wails.yaml") - if _, err := os.Stat(configPath); err == nil { - return configPath - } - - parent := filepath.Dir(dir) - if parent == dir { - break - } - dir = parent - } - - return "" -} - -func (w *Wizard) handleComplete(rw http.ResponseWriter, r *http.Request) { - w.stateMu.RLock() - state := w.state - w.stateMu.RUnlock() - - duration := time.Since(state.StartTime) - - response := map[string]interface{}{ - "status": "complete", - "duration": duration.String(), - } - - rw.Header().Set("Content-Type", "application/json") - json.NewEncoder(rw).Encode(response) - - close(w.done) -} - -func (w *Wizard) handleClose(rw http.ResponseWriter, r *http.Request) { - rw.Header().Set("Content-Type", "application/json") - json.NewEncoder(rw).Encode(map[string]string{"status": "closing"}) - - close(w.shutdown) -} - -// execCommand runs a command and returns its output -func execCommand(name string, args ...string) (string, error) { - cmd := exec.Command(name, args...) - output, err := cmd.Output() - return strings.TrimSpace(string(output)), err -} - -// commandExists checks if a command exists in PATH -func commandExists(name string) bool { - _, err := exec.LookPath(name) - return err == nil -} - -func (w *Wizard) handleDockerStatus(rw http.ResponseWriter, r *http.Request) { - status := w.checkDocker() - - w.dockerMu.Lock() - w.dockerStatus = status - w.dockerMu.Unlock() - - rw.Header().Set("Content-Type", "application/json") - json.NewEncoder(rw).Encode(status) -} - -func (w *Wizard) checkDocker() DockerStatus { - status := DockerStatus{ - ImageName: "wails-cross", - PullStatus: "idle", - } - - // Check if Docker is installed - output, err := execCommand("docker", "--version") - if err != nil { - status.Installed = false - return status - } - - status.Installed = true - // Parse version from "Docker version 24.0.7, build afdd53b" - parts := strings.Split(output, ",") - if len(parts) > 0 { - status.Version = strings.TrimPrefix(strings.TrimSpace(parts[0]), "Docker version ") - } - - // Check if Docker daemon is running - if _, err := execCommand("docker", "info"); err != nil { - status.Running = false - return status - } - status.Running = true - - // Check if wails-cross image exists - imageOutput, err := execCommand("docker", "image", "inspect", "wails-cross") - status.ImageBuilt = err == nil && len(imageOutput) > 0 - - return status -} - -func (w *Wizard) handleDockerBuild(rw http.ResponseWriter, r *http.Request) { - if r.Method != http.MethodPost { - http.Error(rw, "Method not allowed", http.StatusMethodNotAllowed) - return - } - - w.dockerMu.Lock() - w.dockerStatus.PullStatus = "pulling" - w.dockerStatus.PullProgress = 0 - w.dockerMu.Unlock() - - // Build the Docker image in background - go func() { - // Run: wails3 task setup:docker - cmd := exec.Command("wails3", "task", "setup:docker") - err := cmd.Run() - - w.dockerMu.Lock() - if err != nil { - w.dockerStatus.PullStatus = "error" - w.dockerStatus.PullError = err.Error() - } else { - w.dockerStatus.PullStatus = "complete" - w.dockerStatus.ImageBuilt = true - } - w.dockerStatus.PullProgress = 100 - w.dockerMu.Unlock() - }() - - // Simulate progress updates while building - go func() { - for i := 0; i < 90; i += 5 { - time.Sleep(2 * time.Second) - w.dockerMu.Lock() - if w.dockerStatus.PullStatus != "pulling" { - w.dockerMu.Unlock() - return - } - w.dockerStatus.PullProgress = i - w.dockerMu.Unlock() - } - }() - - rw.Header().Set("Content-Type", "application/json") - json.NewEncoder(rw).Encode(map[string]string{"status": "started"}) -} - -// handleDockerStartBackground checks if Docker is available and starts building in background -// This is called early in the wizard flow to get a head start on the image build -func (w *Wizard) handleDockerStartBackground(rw http.ResponseWriter, r *http.Request) { - rw.Header().Set("Content-Type", "application/json") - - // Check Docker status first - status := w.checkDocker() - - w.dockerMu.Lock() - w.dockerStatus = status - w.dockerMu.Unlock() - - // Only start build if Docker is installed, running, and image not built yet - if !status.Installed || !status.Running || status.ImageBuilt { - json.NewEncoder(rw).Encode(map[string]interface{}{ - "started": false, - "reason": getDockerNotStartedReason(status), - "status": status, - }) - return - } - - // Check if already building - w.dockerMu.RLock() - alreadyBuilding := w.dockerStatus.PullStatus == "pulling" - w.dockerMu.RUnlock() - - if alreadyBuilding { - json.NewEncoder(rw).Encode(map[string]interface{}{ - "started": false, - "reason": "already_building", - "status": status, - }) - return - } - - // Start building in background - w.dockerMu.Lock() - w.dockerStatus.PullStatus = "pulling" - w.dockerStatus.PullProgress = 0 - w.dockerMu.Unlock() - - // Build the Docker image in background - go func() { - cmd := exec.Command("wails3", "task", "setup:docker") - err := cmd.Run() - - w.dockerMu.Lock() - if err != nil { - w.dockerStatus.PullStatus = "error" - w.dockerStatus.PullError = err.Error() - } else { - w.dockerStatus.PullStatus = "complete" - w.dockerStatus.ImageBuilt = true - } - w.dockerStatus.PullProgress = 100 - w.dockerMu.Unlock() - }() - - // Simulate progress updates while building - go func() { - for i := 0; i < 90; i += 5 { - time.Sleep(2 * time.Second) - w.dockerMu.Lock() - if w.dockerStatus.PullStatus != "pulling" { - w.dockerMu.Unlock() - return - } - w.dockerStatus.PullProgress = i - w.dockerMu.Unlock() - } - }() - - json.NewEncoder(rw).Encode(map[string]interface{}{ - "started": true, - "status": status, - }) -} - -func getDockerNotStartedReason(status DockerStatus) string { - if !status.Installed { - return "not_installed" - } - if !status.Running { - return "not_running" - } - if status.ImageBuilt { - return "already_built" - } - return "unknown" -} - -// InstallRequest represents a request to install a dependency -type InstallRequest struct { - Command string `json:"command"` -} - -// InstallResponse represents the result of an install attempt -type InstallResponse struct { - Success bool `json:"success"` - Output string `json:"output"` - Error string `json:"error,omitempty"` -} - -func (w *Wizard) handleInstallDependency(rw http.ResponseWriter, r *http.Request) { - if r.Method != http.MethodPost { - http.Error(rw, "Method not allowed", http.StatusMethodNotAllowed) - return - } - - var req InstallRequest - if err := json.NewDecoder(r.Body).Decode(&req); err != nil { - http.Error(rw, err.Error(), http.StatusBadRequest) - return - } - - rw.Header().Set("Content-Type", "application/json") - - // Execute the install command - // Split the command into parts - parts := strings.Fields(req.Command) - if len(parts) == 0 { - json.NewEncoder(rw).Encode(InstallResponse{ - Success: false, - Error: "Empty command", - }) - return - } - - cmd := exec.Command(parts[0], parts[1:]...) - output, err := cmd.CombinedOutput() - - if err != nil { - json.NewEncoder(rw).Encode(InstallResponse{ - Success: false, - Output: string(output), - Error: err.Error(), - }) - return - } - - json.NewEncoder(rw).Encode(InstallResponse{ - Success: true, - Output: string(output), - }) -} - -func (w *Wizard) handleDefaults(rw http.ResponseWriter, r *http.Request) { - rw.Header().Set("Content-Type", "application/json") - - switch r.Method { - case http.MethodGet: - defaults, err := LoadGlobalDefaults() - if err != nil { - http.Error(rw, err.Error(), http.StatusInternalServerError) - return - } - - // Try to pre-populate author info from git config if empty - if defaults.Author.Name == "" { - if name, err := execCommand("git", "config", "--global", "user.name"); err == nil && name != "" { - defaults.Author.Name = name - } - } - - json.NewEncoder(rw).Encode(defaults) - - case http.MethodPost: - var defaults GlobalDefaults - if err := json.NewDecoder(r.Body).Decode(&defaults); err != nil { - http.Error(rw, err.Error(), http.StatusBadRequest) - return - } - - if err := SaveGlobalDefaults(defaults); err != nil { - http.Error(rw, err.Error(), http.StatusInternalServerError) - return - } - - path, _ := GetDefaultsPath() - json.NewEncoder(rw).Encode(map[string]string{"status": "saved", "path": path}) - - default: - http.Error(rw, "Method not allowed", http.StatusMethodNotAllowed) - } -} diff --git a/v3/internal/setupwizard/wizard_darwin.go b/v3/internal/setupwizard/wizard_darwin.go deleted file mode 100644 index aab27d118..000000000 --- a/v3/internal/setupwizard/wizard_darwin.go +++ /dev/null @@ -1,135 +0,0 @@ -//go:build darwin - -package setupwizard - -import ( - "os/exec" - "strconv" - "strings" -) - -func (w *Wizard) checkAllDependencies() []DependencyStatus { - var deps []DependencyStatus - - // Check Xcode Command Line Tools - deps = append(deps, checkXcode()) - - // Check npm (common dependency) - deps = append(deps, checkNpm()) - - // Check Docker (optional) - deps = append(deps, checkDocker()) - - return deps -} - -func checkXcode() DependencyStatus { - dep := DependencyStatus{ - Name: "Xcode Command Line Tools", - Required: true, - } - - path, err := execCommand("xcode-select", "-p") - if err != nil { - dep.Status = "not_installed" - dep.Installed = false - dep.Message = "Run: xcode-select --install" - return dep - } - - dep.Installed = true - dep.Status = "installed" - - // Try to get version - cmd := exec.Command("pkgutil", "--pkg-info=com.apple.pkg.CLTools_Executables") - output, err := cmd.Output() - if err == nil { - lines := strings.Split(string(output), "\n") - for _, line := range lines { - if strings.HasPrefix(line, "version:") { - dep.Version = strings.TrimSpace(strings.TrimPrefix(line, "version:")) - break - } - } - } - - _ = path // suppress unused warning - return dep -} - -func checkNpm() DependencyStatus { - dep := DependencyStatus{ - Name: "npm", - Required: true, - } - - version, err := execCommand("npm", "-v") - if err != nil { - dep.Status = "not_installed" - dep.Installed = false - dep.Message = "npm is required. Install Node.js from https://nodejs.org/" - return dep - } - - dep.Version = version - - // Check minimum version (7.0.0) - parts := strings.Split(version, ".") - if len(parts) > 0 { - major, _ := strconv.Atoi(parts[0]) - if major < 7 { - dep.Status = "needs_update" - dep.Installed = true - dep.Message = "npm 7.0.0 or higher is required" - return dep - } - } - - dep.Installed = true - dep.Status = "installed" - return dep -} - -func checkDocker() DependencyStatus { - dep := DependencyStatus{ - Name: "docker", - Required: false, // Optional for cross-compilation - } - - version, err := execCommand("docker", "--version") - if err != nil { - dep.Status = "not_installed" - dep.Installed = false - dep.Message = "Optional - for cross-compilation" - return dep - } - - // Parse version from "Docker version 24.0.7, build afdd53b" - parts := strings.Split(version, ",") - if len(parts) > 0 { - dep.Version = strings.TrimPrefix(strings.TrimSpace(parts[0]), "Docker version ") - } - - // Check if daemon is running - _, err = execCommand("docker", "info") - if err != nil { - dep.Installed = true - dep.Status = "installed" - dep.Message = "Daemon not running" - return dep - } - - // Check for wails-cross image - imageCheck, _ := execCommand("docker", "image", "inspect", "wails-cross") - if imageCheck == "" || strings.Contains(imageCheck, "Error") { - dep.Installed = true - dep.Status = "installed" - dep.Message = "wails-cross image not built" - } else { - dep.Installed = true - dep.Status = "installed" - dep.Message = "Cross-compilation ready" - } - - return dep -} diff --git a/v3/internal/setupwizard/wizard_linux.go b/v3/internal/setupwizard/wizard_linux.go deleted file mode 100644 index c286f504a..000000000 --- a/v3/internal/setupwizard/wizard_linux.go +++ /dev/null @@ -1,139 +0,0 @@ -//go:build linux - -package setupwizard - -import ( - "strconv" - "strings" - - "github.com/wailsapp/wails/v3/internal/doctor/packagemanager" - "github.com/wailsapp/wails/v3/internal/operatingsystem" -) - -func (w *Wizard) checkAllDependencies() []DependencyStatus { - var deps []DependencyStatus - hasNpm := false - - // Get OS info for package manager detection - info, _ := operatingsystem.Info() - - // Find the package manager - pm := packagemanager.Find(info.ID) - if pm != nil { - // Get platform dependencies from the doctor package - platformDeps, _ := packagemanager.Dependencies(pm) - for _, dep := range platformDeps { - if dep.Name == "npm" { - hasNpm = true - } - status := DependencyStatus{ - Name: dep.Name, - Required: !dep.Optional, - } - - if dep.Installed { - status.Installed = true - status.Status = "installed" - status.Version = dep.Version - } else { - status.Installed = false - status.Status = "not_installed" - status.InstallCommand = dep.InstallCommand - } - - deps = append(deps, status) - } - } - - // Check npm (common dependency) - only if not already added by package manager - if !hasNpm { - deps = append(deps, checkNpm()) - } - - // Check Docker (optional) - deps = append(deps, checkDocker()) - - return deps -} - -func checkNpm() DependencyStatus { - dep := DependencyStatus{ - Name: "npm", - Required: false, // Optional - not strictly required for Go-only projects - } - - version, err := execCommand("npm", "-v") - if err != nil { - dep.Status = "not_installed" - dep.Installed = false - dep.Message = "Required for frontend development" - dep.HelpURL = "https://nodejs.org/" - dep.InstallCommand = "Install Node.js from https://nodejs.org/" - return dep - } - - dep.Version = version - - // Check minimum version (7.0.0) - parts := strings.Split(version, ".") - if len(parts) > 0 { - major, _ := strconv.Atoi(parts[0]) - if major < 7 { - dep.Status = "needs_update" - dep.Installed = true - dep.Message = "npm 7.0.0 or higher recommended" - dep.HelpURL = "https://nodejs.org/" - return dep - } - } - - dep.Installed = true - dep.Status = "installed" - return dep -} - -func checkDocker() DependencyStatus { - dep := DependencyStatus{ - Name: "docker", - Required: false, // Optional for cross-compilation - } - - version, err := execCommand("docker", "--version") - if err != nil { - dep.Status = "not_installed" - dep.Installed = false - dep.Message = "Enables cross-platform builds" - dep.HelpURL = "https://docs.docker.com/get-docker/" - dep.InstallCommand = "Install Docker from https://docs.docker.com/get-docker/" - return dep - } - - // Parse version from "Docker version 24.0.7, build afdd53b" - parts := strings.Split(version, ",") - if len(parts) > 0 { - dep.Version = strings.TrimPrefix(strings.TrimSpace(parts[0]), "Docker version ") - } - - // Check if daemon is running - _, err = execCommand("docker", "info") - if err != nil { - dep.Installed = true - dep.Status = "installed" - dep.Message = "Start Docker to enable cross-compilation" - return dep - } - - // Check for wails-cross image - imageCheck, _ := execCommand("docker", "image", "inspect", "wails-cross") - if imageCheck == "" || strings.Contains(imageCheck, "Error") { - dep.Installed = true - dep.Status = "installed" - dep.Message = "Run 'wails3 task setup:docker' to build cross-compilation image" - } else { - dep.Installed = true - dep.Status = "installed" - dep.Message = "Cross-compilation ready" - } - - return dep -} diff --git a/v3/internal/setupwizard/wizard_windows.go b/v3/internal/setupwizard/wizard_windows.go deleted file mode 100644 index afa2653a4..000000000 --- a/v3/internal/setupwizard/wizard_windows.go +++ /dev/null @@ -1,142 +0,0 @@ -//go:build windows - -package setupwizard - -import ( - "os" - "path/filepath" - "strconv" - "strings" -) - -func (w *Wizard) checkAllDependencies() []DependencyStatus { - var deps []DependencyStatus - - // Check WebView2 Runtime - deps = append(deps, checkWebView2()) - - // Check npm (common dependency) - deps = append(deps, checkNpm()) - - // Check Docker (optional) - deps = append(deps, checkDocker()) - - return deps -} - -func checkWebView2() DependencyStatus { - dep := DependencyStatus{ - Name: "WebView2 Runtime", - Required: true, - } - - // Check common installation paths - paths := []string{ - filepath.Join(os.Getenv("PROGRAMFILES(X86)"), "Microsoft", "EdgeWebView", "Application"), - filepath.Join(os.Getenv("LOCALAPPDATA"), "Microsoft", "EdgeWebView", "Application"), - filepath.Join(os.Getenv("PROGRAMFILES"), "Microsoft", "EdgeWebView", "Application"), - } - - for _, path := range paths { - if info, err := os.Stat(path); err == nil && info.IsDir() { - dep.Installed = true - dep.Status = "installed" - - // Try to get version from directory name - entries, _ := os.ReadDir(path) - for _, entry := range entries { - if entry.IsDir() { - name := entry.Name() - // Version directories look like "120.0.2210.91" - if len(name) > 0 && name[0] >= '0' && name[0] <= '9' { - dep.Version = name - break - } - } - } - return dep - } - } - - dep.Status = "not_installed" - dep.Installed = false - dep.Message = "Download from Microsoft Edge WebView2" - return dep -} - -func checkNpm() DependencyStatus { - dep := DependencyStatus{ - Name: "npm", - Required: true, - } - - version, err := execCommand("npm", "-v") - if err != nil { - dep.Status = "not_installed" - dep.Installed = false - dep.Message = "npm is required. Install Node.js from https://nodejs.org/" - return dep - } - - dep.Version = version - - // Check minimum version (7.0.0) - parts := strings.Split(version, ".") - if len(parts) > 0 { - major, _ := strconv.Atoi(parts[0]) - if major < 7 { - dep.Status = "needs_update" - dep.Installed = true - dep.Message = "npm 7.0.0 or higher is required" - return dep - } - } - - dep.Installed = true - dep.Status = "installed" - return dep -} - -func checkDocker() DependencyStatus { - dep := DependencyStatus{ - Name: "docker", - Required: false, // Optional for cross-compilation - } - - version, err := execCommand("docker", "--version") - if err != nil { - dep.Status = "not_installed" - dep.Installed = false - dep.Message = "Optional - for cross-compilation" - return dep - } - - // Parse version from "Docker version 24.0.7, build afdd53b" - parts := strings.Split(version, ",") - if len(parts) > 0 { - dep.Version = strings.TrimPrefix(strings.TrimSpace(parts[0]), "Docker version ") - } - - // Check if daemon is running - _, err = execCommand("docker", "info") - if err != nil { - dep.Installed = true - dep.Status = "installed" - dep.Message = "Daemon not running" - return dep - } - - // Check for wails-cross image - imageCheck, _ := execCommand("docker", "image", "inspect", "wails-cross") - if imageCheck == "" || strings.Contains(imageCheck, "Error") { - dep.Installed = true - dep.Status = "installed" - dep.Message = "wails-cross image not built" - } else { - dep.Installed = true - dep.Status = "installed" - dep.Message = "Cross-compilation ready" - } - - return dep -} diff --git a/v3/internal/signal/signal.go b/v3/internal/signal/signal.go deleted file mode 100644 index 8ac9821d0..000000000 --- a/v3/internal/signal/signal.go +++ /dev/null @@ -1,50 +0,0 @@ -package signal - -import ( - "fmt" - "log/slog" - "os" - "os/signal" - "syscall" -) - -type SignalHandler struct { - cleanup func() - ExitMessage func(sig os.Signal) string - MaxSignal int - Logger *slog.Logger - LogLevel slog.Level -} - -func NewSignalHandler(cleanup func()) *SignalHandler { - return &SignalHandler{ - cleanup: cleanup, - ExitMessage: func(sig os.Signal) string { return fmt.Sprintf("Received signal: %v. Quitting...\n", sig) }, - MaxSignal: 3, - Logger: slog.New(slog.NewTextHandler(os.Stderr, nil)), - LogLevel: slog.LevelInfo, - } -} - -func (s *SignalHandler) Start() { - ctrlC := make(chan os.Signal, s.MaxSignal) - signal.Notify(ctrlC, os.Interrupt, syscall.SIGTERM) - - go func() { - for i := 1; i <= s.MaxSignal; i++ { - sig := <-ctrlC - - if i == 1 { - s.Logger.Info(s.ExitMessage(sig)) - s.cleanup() - break - } else if i < s.MaxSignal { - s.Logger.Info(fmt.Sprintf("Received signal: %v. Press CTRL+C %d more times to force quit...\n", sig, s.MaxSignal-i)) - continue - } else { - s.Logger.Info(fmt.Sprintf("Received signal: %v. Force quitting...\n", sig)) - os.Exit(1) - } - } - }() -} diff --git a/v3/internal/sliceutil/sliceutil.go b/v3/internal/sliceutil/sliceutil.go deleted file mode 100644 index 5023d6110..000000000 --- a/v3/internal/sliceutil/sliceutil.go +++ /dev/null @@ -1,39 +0,0 @@ -// Package sliceutil provides generic utility functions not available in stdlib. -// For most slice operations, use the standard library "slices" package directly. -// This package only contains functions that have no stdlib equivalent. -package sliceutil - -// Unique returns a new slice with duplicate elements removed. -// Preserves the order of first occurrence. -// The original slice is not modified. -// -// Unique returns a new slice containing the first occurrence of each element from the input slice, preserving their original order. -// If the input slice is nil, Unique returns nil. -// The original slice is not modified. -func Unique[T comparable](slice []T) []T { - if slice == nil { - return nil - } - seen := make(map[T]struct{}, len(slice)) - result := make([]T, 0, len(slice)) - for _, v := range slice { - if _, ok := seen[v]; !ok { - seen[v] = struct{}{} - result = append(result, v) - } - } - return result -} - -// FindMapKey returns the first key in map m whose value equals val. -// FindMapKey returns the first key in m whose value equals val. -// If no such key exists it returns the zero value of K and false. If multiple keys map to val, the returned key depends on Go's map iteration order. -func FindMapKey[K comparable, V comparable](m map[K]V, val V) (K, bool) { - for k, v := range m { - if v == val { - return k, true - } - } - var zero K - return zero, false -} \ No newline at end of file diff --git a/v3/internal/sliceutil/sliceutil_test.go b/v3/internal/sliceutil/sliceutil_test.go deleted file mode 100644 index 1b10cc123..000000000 --- a/v3/internal/sliceutil/sliceutil_test.go +++ /dev/null @@ -1,172 +0,0 @@ -package sliceutil - -import ( - "reflect" - "testing" -) - -func TestUnique(t *testing.T) { - tests := []struct { - name string - slice []int - want []int - }{ - { - name: "no duplicates", - slice: []int{1, 2, 3}, - want: []int{1, 2, 3}, - }, - { - name: "with duplicates", - slice: []int{1, 2, 2, 3, 3, 3}, - want: []int{1, 2, 3}, - }, - { - name: "all duplicates", - slice: []int{1, 1, 1}, - want: []int{1}, - }, - { - name: "preserves order", - slice: []int{3, 1, 2, 1, 3, 2}, - want: []int{3, 1, 2}, - }, - { - name: "single element", - slice: []int{1}, - want: []int{1}, - }, - { - name: "empty slice", - slice: []int{}, - want: []int{}, - }, - { - name: "nil slice", - slice: nil, - want: nil, - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - got := Unique(tt.slice) - if !reflect.DeepEqual(got, tt.want) { - t.Errorf("Unique() = %v, want %v", got, tt.want) - } - }) - } -} - -func TestUnique_Strings(t *testing.T) { - slice := []string{"a", "b", "a", "c", "b"} - got := Unique(slice) - want := []string{"a", "b", "c"} - if !reflect.DeepEqual(got, want) { - t.Errorf("Unique() = %v, want %v", got, want) - } -} - -func TestUnique_DoesNotModifyOriginal(t *testing.T) { - original := []int{1, 2, 2, 3} - originalCopy := make([]int, len(original)) - copy(originalCopy, original) - - _ = Unique(original) - - if !reflect.DeepEqual(original, originalCopy) { - t.Errorf("Unique() modified original slice: got %v, want %v", original, originalCopy) - } -} - -func TestFindMapKey(t *testing.T) { - tests := []struct { - name string - m map[string]int - val int - wantKey string - wantFound bool - }{ - { - name: "find existing value", - m: map[string]int{"a": 1, "b": 2, "c": 3}, - val: 2, - wantKey: "b", - wantFound: true, - }, - { - name: "value not found", - m: map[string]int{"a": 1, "b": 2}, - val: 3, - wantKey: "", - wantFound: false, - }, - { - name: "empty map", - m: map[string]int{}, - val: 1, - wantKey: "", - wantFound: false, - }, - { - name: "nil map", - m: nil, - val: 1, - wantKey: "", - wantFound: false, - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - gotKey, gotFound := FindMapKey(tt.m, tt.val) - if gotFound != tt.wantFound { - t.Errorf("FindMapKey() found = %v, want %v", gotFound, tt.wantFound) - } - if gotFound && gotKey != tt.wantKey { - t.Errorf("FindMapKey() key = %v, want %v", gotKey, tt.wantKey) - } - }) - } -} - -func TestFindMapKey_DuplicateValues(t *testing.T) { - // When multiple keys have the same value, any matching key is acceptable - m := map[string]int{"a": 1, "b": 1, "c": 2} - key, found := FindMapKey(m, 1) - if !found { - t.Error("FindMapKey() should find a key") - } - if key != "a" && key != "b" { - t.Errorf("FindMapKey() = %v, want 'a' or 'b'", key) - } -} - -func TestFindMapKey_IntKeys(t *testing.T) { - m := map[int]string{1: "one", 2: "two", 3: "three"} - key, found := FindMapKey(m, "two") - if !found || key != 2 { - t.Errorf("FindMapKey() = (%v, %v), want (2, true)", key, found) - } -} - -// Benchmarks - -func BenchmarkUnique(b *testing.B) { - slice := []int{1, 2, 3, 1, 2, 3, 4, 5, 4, 5, 6, 7, 8, 9, 10} - b.ResetTimer() - for i := 0; i < b.N; i++ { - _ = Unique(slice) - } -} - -func BenchmarkFindMapKey(b *testing.B) { - m := make(map[string]int) - for i := 0; i < 100; i++ { - m[string(rune('a'+i))] = i - } - b.ResetTimer() - for i := 0; i < b.N; i++ { - _, _ = FindMapKey(m, 50) - } -} diff --git a/v3/internal/templates/_common/README.md b/v3/internal/templates/_common/README.md deleted file mode 100644 index ad12c3f40..000000000 --- a/v3/internal/templates/_common/README.md +++ /dev/null @@ -1,59 +0,0 @@ -# Welcome to Your New Wails3 Project! - -Congratulations on generating your Wails3 application! This README will guide you through the next steps to get your project up and running. - -## Getting Started - -1. Navigate to your project directory in the terminal. - -2. To run your application in development mode, use the following command: - - ``` - wails3 dev - ``` - - This will start your application and enable hot-reloading for both frontend and backend changes. - -3. To build your application for production, use: - - ``` - wails3 build - ``` - - This will create a production-ready executable in the `build` directory. - -## Exploring Wails3 Features - -Now that you have your project set up, it's time to explore the features that Wails3 offers: - -1. **Check out the examples**: The best way to learn is by example. Visit the `examples` directory in the `v3/examples` directory to see various sample applications. - -2. **Run an example**: To run any of the examples, navigate to the example's directory and use: - - ``` - go run . - ``` - - Note: Some examples may be under development during the alpha phase. - -3. **Explore the documentation**: Visit the [Wails3 documentation](https://v3.wails.io/) for in-depth guides and API references. - -4. **Join the community**: Have questions or want to share your progress? Join the [Wails Discord](https://discord.gg/JDdSxwjhGf) or visit the [Wails discussions on GitHub](https://github.com/wailsapp/wails/discussions). - -## Project Structure - -Take a moment to familiarize yourself with your project structure: - -- `frontend/`: Contains your frontend code (HTML, CSS, JavaScript/TypeScript) -- `main.go`: The entry point of your Go backend -- `app.go`: Define your application structure and methods here -- `wails.json`: Configuration file for your Wails project - -## Next Steps - -1. Modify the frontend in the `frontend/` directory to create your desired UI. -2. Add backend functionality in `main.go`. -3. Use `wails3 dev` to see your changes in real-time. -4. When ready, build your application with `wails3 build`. - -Happy coding with Wails3! If you encounter any issues or have questions, don't hesitate to consult the documentation or reach out to the Wails community. diff --git a/v3/internal/templates/_common/Taskfile.tmpl.yml b/v3/internal/templates/_common/Taskfile.tmpl.yml deleted file mode 100644 index acf87581f..000000000 --- a/v3/internal/templates/_common/Taskfile.tmpl.yml +++ /dev/null @@ -1,60 +0,0 @@ -version: '3' - -includes: - common: ./build/Taskfile.yml - windows: ./build/windows/Taskfile.yml - darwin: ./build/darwin/Taskfile.yml - linux: ./build/linux/Taskfile.yml - ios: ./build/ios/Taskfile.yml - android: ./build/android/Taskfile.yml - -vars: - APP_NAME: "{{.ProjectName}}" - BIN_DIR: "bin" - VITE_PORT: {{ "'{{.WAILS_VITE_PORT | default 9245}}'" }} - -tasks: - build: - summary: Builds the application - cmds: - - task: "{{ "{{OS}}" }}:build" - - package: - summary: Packages a production build of the application - cmds: - - task: "{{ "{{OS}}" }}:package" - - run: - summary: Runs the application - cmds: - - task: "{{ "{{OS}}" }}:run" - - dev: - summary: Runs the application in development mode - cmds: - - wails3 dev -config ./build/config.yml -port {{ "{{.VITE_PORT}}" }} - - setup:docker: - summary: Builds Docker image for cross-compilation (~800MB download) - cmds: - - task: common:setup:docker - - build:server: - summary: Builds the application in server mode (no GUI, HTTP server only) - cmds: - - task: common:build:server - - run:server: - summary: Runs the application in server mode - cmds: - - task: common:run:server - - build:docker: - summary: Builds a Docker image for server mode deployment - cmds: - - task: common:build:docker - - run:docker: - summary: Builds and runs the Docker image - cmds: - - task: common:run:docker diff --git a/v3/internal/templates/_common/frontend/Inter Font License.txt b/v3/internal/templates/_common/frontend/Inter Font License.txt deleted file mode 100644 index b525cbf3a..000000000 --- a/v3/internal/templates/_common/frontend/Inter Font License.txt +++ /dev/null @@ -1,93 +0,0 @@ -Copyright 2020 The Inter Project Authors (https://github.com/rsms/inter) - -This Font Software is licensed under the SIL Open Font License, Version 1.1. -This license is copied below, and is also available with a FAQ at: -http://scripts.sil.org/OFL - - ------------------------------------------------------------ -SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 ------------------------------------------------------------ - -PREAMBLE -The goals of the Open Font License (OFL) are to stimulate worldwide -development of collaborative font projects, to support the font creation -efforts of academic and linguistic communities, and to provide a free and -open framework in which fonts may be shared and improved in partnership -with others. - -The OFL allows the licensed fonts to be used, studied, modified and -redistributed freely as long as they are not sold by themselves. The -fonts, including any derivative works, can be bundled, embedded, -redistributed and/or sold with any software provided that any reserved -names are not used by derivative works. The fonts and derivatives, -however, cannot be released under any other type of license. The -requirement for fonts to remain under this license does not apply -to any document created using the fonts or their derivatives. - -DEFINITIONS -"Font Software" refers to the set of files released by the Copyright -Holder(s) under this license and clearly marked as such. This may -include source files, build scripts and documentation. - -"Reserved Font Name" refers to any names specified as such after the -copyright statement(s). - -"Original Version" refers to the collection of Font Software components as -distributed by the Copyright Holder(s). - -"Modified Version" refers to any derivative made by adding to, deleting, -or substituting -- in part or in whole -- any of the components of the -Original Version, by changing formats or by porting the Font Software to a -new environment. - -"Author" refers to any designer, engineer, programmer, technical -writer or other person who contributed to the Font Software. - -PERMISSION & CONDITIONS -Permission is hereby granted, free of charge, to any person obtaining -a copy of the Font Software, to use, study, copy, merge, embed, modify, -redistribute, and sell modified and unmodified copies of the Font -Software, subject to the following conditions: - -1) Neither the Font Software nor any of its individual components, -in Original or Modified Versions, may be sold by itself. - -2) Original or Modified Versions of the Font Software may be bundled, -redistributed and/or sold with any software, provided that each copy -contains the above copyright notice and this license. These can be -included either as stand-alone text files, human-readable headers or -in the appropriate machine-readable metadata fields within text or -binary files as long as those fields can be easily viewed by the user. - -3) No Modified Version of the Font Software may use the Reserved Font -Name(s) unless explicit written permission is granted by the corresponding -Copyright Holder. This restriction only applies to the primary font name as -presented to the users. - -4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font -Software shall not be used to promote, endorse or advertise any -Modified Version, except to acknowledge the contribution(s) of the -Copyright Holder(s) and the Author(s) or with their explicit written -permission. - -5) The Font Software, modified or unmodified, in part or in whole, -must be distributed entirely under this license, and must not be -distributed under any other license. The requirement for fonts to -remain under this license does not apply to any document created -using the Font Software. - -TERMINATION -This license becomes null and void if any of the above conditions are -not met. - -DISCLAIMER -THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF -MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT -OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE -COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL -DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM -OTHER DEALINGS IN THE FONT SOFTWARE. diff --git a/v3/internal/templates/_common/gitignore.tmpl b/v3/internal/templates/_common/gitignore.tmpl deleted file mode 100644 index ba8194ab6..000000000 --- a/v3/internal/templates/_common/gitignore.tmpl +++ /dev/null @@ -1,6 +0,0 @@ -.task -bin -frontend/dist -frontend/node_modules -build/linux/appimage/build -build/windows/nsis/MicrosoftEdgeWebview2Setup.exe \ No newline at end of file diff --git a/v3/internal/templates/_common/go.mod.tmpl b/v3/internal/templates/_common/go.mod.tmpl deleted file mode 100644 index f33ac683a..000000000 --- a/v3/internal/templates/_common/go.mod.tmpl +++ /dev/null @@ -1,51 +0,0 @@ -module {{.ModulePath}} - -go 1.24 - -require github.com/wailsapp/wails/v3 {{.WailsVersion}} - -require ( - dario.cat/mergo v1.0.1 // indirect - github.com/Microsoft/go-winio v0.6.2 // indirect - github.com/ProtonMail/go-crypto v1.1.5 // indirect - github.com/adrg/xdg v0.5.3 // indirect - github.com/bep/debounce v1.2.1 // indirect - github.com/cloudflare/circl v1.6.0 // indirect - github.com/cyphar/filepath-securejoin v0.4.1 // indirect - github.com/ebitengine/purego v0.8.2 // indirect - github.com/emirpasic/gods v1.18.1 // indirect - github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect - github.com/go-git/go-billy/v5 v5.6.2 // indirect - github.com/go-git/go-git/v5 v5.13.2 // indirect - github.com/go-ole/go-ole v1.3.0 // indirect - github.com/godbus/dbus/v5 v5.1.0 // indirect - github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect - github.com/google/uuid v1.6.0 // indirect - github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect - github.com/jchv/go-winloader v0.0.0-20210711035445-715c2860da7e // indirect - github.com/kevinburke/ssh_config v1.2.0 // indirect - github.com/leaanthony/go-ansi-parser v1.6.1 // indirect - github.com/leaanthony/u v1.1.1 // indirect - github.com/lmittmann/tint v1.0.7 // indirect - github.com/mattn/go-colorable v0.1.14 // indirect - github.com/mattn/go-isatty v0.0.20 // indirect - github.com/pjbgf/sha1cd v0.3.2 // indirect - github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c // indirect - github.com/pkg/errors v0.9.1 // indirect - github.com/rivo/uniseg v0.4.7 // indirect - github.com/samber/lo v1.49.1 // indirect - github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 // indirect - github.com/skeema/knownhosts v1.3.1 // indirect - github.com/wailsapp/go-webview2 v1.0.19 // indirect - github.com/wailsapp/mimetype v1.4.1 // indirect - github.com/xanzy/ssh-agent v0.3.3 // indirect - golang.org/x/crypto v0.33.0 // indirect - golang.org/x/net v0.35.0 // indirect - golang.org/x/sys v0.30.0 // indirect - golang.org/x/text v0.22.0 // indirect - gopkg.in/ini.v1 v1.67.0 // indirect - gopkg.in/warnings.v0 v0.1.2 // indirect -) -{{if .LocalModulePath}} -replace github.com/wailsapp/wails/v3 => {{.LocalModulePath}}v3 -{{end}} diff --git a/v3/internal/templates/_common/go.sum.tmpl b/v3/internal/templates/_common/go.sum.tmpl deleted file mode 100644 index 977b11504..000000000 --- a/v3/internal/templates/_common/go.sum.tmpl +++ /dev/null @@ -1,146 +0,0 @@ -dario.cat/mergo v1.0.1 h1:Ra4+bf83h2ztPIQYNP99R6m+Y7KfnARDfID+a+vLl4s= -dario.cat/mergo v1.0.1/go.mod h1:uNxQE+84aUszobStD9th8a29P2fMDhsBdgRYvZOxGmk= -github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY= -github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= -github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= -github.com/ProtonMail/go-crypto v1.1.5 h1:eoAQfK2dwL+tFSFpr7TbOaPNUbPiJj4fLYwwGE1FQO4= -github.com/ProtonMail/go-crypto v1.1.5/go.mod h1:rA3QumHc/FZ8pAHreoekgiAbzpNsfQAosU5td4SnOrE= -github.com/adrg/xdg v0.5.3 h1:xRnxJXne7+oWDatRhR1JLnvuccuIeCoBu2rtuLqQB78= -github.com/adrg/xdg v0.5.3/go.mod h1:nlTsY+NNiCBGCK2tpm09vRqfVzrc2fLmXGpBLF0zlTQ= -github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8= -github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4= -github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= -github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= -github.com/bep/debounce v1.2.1 h1:v67fRdBA9UQu2NhLFXrSg0Brw7CexQekrBwDMM8bzeY= -github.com/bep/debounce v1.2.1/go.mod h1:H8yggRPQKLUhUoqrJC1bO2xNya7vanpDl7xR3ISbCJ0= -github.com/cloudflare/circl v1.6.0 h1:cr5JKic4HI+LkINy2lg3W2jF8sHCVTBncJr5gIIq7qk= -github.com/cloudflare/circl v1.6.0/go.mod h1:uddAzsPgqdMAYatqJ0lsjX1oECcQLIlRpzZh3pJrofs= -github.com/cyphar/filepath-securejoin v0.4.1 h1:JyxxyPEaktOD+GAnqIqTf9A8tHyAG22rowi7HkoSU1s= -github.com/cyphar/filepath-securejoin v0.4.1/go.mod h1:Sdj7gXlvMcPZsbhwhQ33GguGLDGQL7h7bg04C/+u9jI= -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= -github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/ebitengine/purego v0.8.2 h1:jPPGWs2sZ1UgOSgD2bClL0MJIqu58nOmIcBuXr62z1I= -github.com/ebitengine/purego v0.8.2/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ= -github.com/elazarl/goproxy v1.4.0 h1:4GyuSbFa+s26+3rmYNSuUVsx+HgPrV1bk1jXI0l9wjM= -github.com/elazarl/goproxy v1.4.0/go.mod h1:X/5W/t+gzDyLfHW4DrMdpjqYjpXsURlBt9lpBDxZZZQ= -github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc= -github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ= -github.com/gliderlabs/ssh v0.3.8 h1:a4YXD1V7xMF9g5nTkdfnja3Sxy1PVDCj1Zg4Wb8vY6c= -github.com/gliderlabs/ssh v0.3.8/go.mod h1:xYoytBv1sV0aL3CavoDuJIQNURXkkfPA/wxQ1pL1fAU= -github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI= -github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmSxCcxctByoQdvwPiA7DTK7jaaFDBTtu0ic= -github.com/go-git/go-billy/v5 v5.6.2 h1:6Q86EsPXMa7c3YZ3aLAQsMA0VlWmy43r6FHqa/UNbRM= -github.com/go-git/go-billy/v5 v5.6.2/go.mod h1:rcFC2rAsp/erv7CMz9GczHcuD0D32fWzH+MJAU+jaUU= -github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399 h1:eMje31YglSBqCdIqdhKBW8lokaMrL3uTkpGYlE2OOT4= -github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399/go.mod h1:1OCfN199q1Jm3HZlxleg+Dw/mwps2Wbk9frAWm+4FII= -github.com/go-git/go-git/v5 v5.13.2 h1:7O7xvsK7K+rZPKW6AQR1YyNhfywkv7B8/FsP3ki6Zv0= -github.com/go-git/go-git/v5 v5.13.2/go.mod h1:hWdW5P4YZRjmpGHwRH2v3zkWcNl6HeXaXQEMGb3NJ9A= -github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE= -github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78= -github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk= -github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= -github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 h1:f+oWsMOmNPc8JmEHVZIycC7hBoQxHH9pNKQORJNozsQ= -github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8/go.mod h1:wcDNUvekVysuuOpQKo3191zZyTpiI6se1N1ULghS0sw= -github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= -github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= -github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A= -github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= -github.com/jchv/go-winloader v0.0.0-20210711035445-715c2860da7e h1:Q3+PugElBCf4PFpxhErSzU3/PY5sFL5Z6rfv4AbGAck= -github.com/jchv/go-winloader v0.0.0-20210711035445-715c2860da7e/go.mod h1:alcuEEnZsY1WQsagKhZDsoPCRoOijYqhZvPwLG0kzVs= -github.com/kevinburke/ssh_config v1.2.0 h1:x584FjTGwHzMwvHx18PXxbBVzfnxogHaAReU4gf13a4= -github.com/kevinburke/ssh_config v1.2.0/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM= -github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= -github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= -github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= -github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= -github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/leaanthony/go-ansi-parser v1.6.1 h1:xd8bzARK3dErqkPFtoF9F3/HgN8UQk0ed1YDKpEz01A= -github.com/leaanthony/go-ansi-parser v1.6.1/go.mod h1:+vva/2y4alzVmmIEpk9QDhA7vLC5zKDTRwfZGOp3IWU= -github.com/leaanthony/u v1.1.1 h1:TUFjwDGlNX+WuwVEzDqQwC2lOv0P4uhTQw7CMFdiK7M= -github.com/leaanthony/u v1.1.1/go.mod h1:9+o6hejoRljvZ3BzdYlVL0JYCwtnAsVuN9pVTQcaRfI= -github.com/lmittmann/tint v1.0.7 h1:D/0OqWZ0YOGZ6AyC+5Y2kD8PBEzBk6rFHVSfOqCkF9Y= -github.com/lmittmann/tint v1.0.7/go.mod h1:HIS3gSy7qNwGCj+5oRjAutErFBl4BzdQP6cJZ0NfMwE= -github.com/matryer/is v1.4.0/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwMRU= -github.com/matryer/is v1.4.1 h1:55ehd8zaGABKLXQUe2awZ99BD/PTc2ls+KV/dXphgEQ= -github.com/matryer/is v1.4.1/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwMRU= -github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE= -github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8= -github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= -github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= -github.com/onsi/gomega v1.34.1 h1:EUMJIKUjM8sKjYbtxQI9A4z2o+rruxnzNvpknOXie6k= -github.com/onsi/gomega v1.34.1/go.mod h1:kU1QgUvBDLXBJq618Xvm2LUX6rSAfRaFRTcdOeDLwwY= -github.com/pjbgf/sha1cd v0.3.2 h1:a9wb0bp1oC2TGwStyn0Umc/IGKQnEgF0vVaZ8QF8eo4= -github.com/pjbgf/sha1cd v0.3.2/go.mod h1:zQWigSxVmsHEZow5qaLtPYxpcKMMQpa09ixqBxuCS6A= -github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmdv1U2eRNDiU2ErMBj1gwrq8eQ= -github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c/go.mod h1:7rwL4CYBLnjLxUqIJNnCWiEdr3bn6IUYi15bNlnbCCU= -github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= -github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= -github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= -github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= -github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= -github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= -github.com/rogpeppe/go-internal v1.12.0/go.mod h1:E+RYuTGaKKdloAfM02xzb0FW3Paa99yedzYV+kq4uf4= -github.com/samber/lo v1.49.1 h1:4BIFyVfuQSEpluc7Fua+j1NolZHiEHEpaSEKdsH0tew= -github.com/samber/lo v1.49.1/go.mod h1:dO6KHFzUKXgP8LDhU0oI8d2hekjXnGOu0DB8Jecxd6o= -github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 h1:n661drycOFuPLCN3Uc8sB6B/s6Z4t2xvBgU1htSHuq8= -github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4= -github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= -github.com/skeema/knownhosts v1.3.1 h1:X2osQ+RAjK76shCbvhHHHVl3ZlgDm8apHEHFqRjnBY8= -github.com/skeema/knownhosts v1.3.1/go.mod h1:r7KTdC8l4uxWRyK2TpQZ/1o5HaSzh06ePQNxPwTcfiY= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= -github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= -github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= -github.com/wailsapp/go-webview2 v1.0.19 h1:7U3QcDj1PrBPaxJNCui2k1SkWml+Q5kvFUFyTImA6NU= -github.com/wailsapp/go-webview2 v1.0.19/go.mod h1:qJmWAmAmaniuKGZPWwne+uor3AHMB5PFhqiK0Bbj8kc= -github.com/wailsapp/mimetype v1.4.1 h1:pQN9ycO7uo4vsUUuPeHEYoUkLVkaRntMnHJxVwYhwHs= -github.com/wailsapp/mimetype v1.4.1/go.mod h1:9aV5k31bBOv5z6u+QP8TltzvNGJPmNJD4XlAL3U+j3o= -github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM= -github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw= -golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.33.0 h1:IOBPskki6Lysi0lo9qQvbxiQ+FvsCC/YWOecCHAixus= -golang.org/x/crypto v0.33.0/go.mod h1:bVdXmD7IV/4GdElGPozy6U7lWdRXA4qyRVGJV57uQ5M= -golang.org/x/exp v0.0.0-20250210185358-939b2ce775ac h1:l5+whBCLH3iH2ZNHYLbAe58bo7yrN4mVcnkHDYz5vvs= -golang.org/x/exp v0.0.0-20250210185358-939b2ce775ac/go.mod h1:hH+7mtFmImwwcMvScyxUhjuVHR3HGaDPMn9rMSUUbxo= -golang.org/x/net v0.0.0-20210505024714-0287a6fb4125/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.35.0 h1:T5GQRQb2y08kTAByq9L4/bz8cipCdA8FbRTXewonqY8= -golang.org/x/net v0.35.0/go.mod h1:EglIi67kWsHKlRzzVMUD93VMSWGFOMSZgxFjparz1Qk= -golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200810151505-1b9f1253b3ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc= -golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.29.0 h1:L6pJp37ocefwRRtYPKSWOWzOtWSxVajvz2ldH/xi3iU= -golang.org/x/term v0.29.0/go.mod h1:6bl4lRlvVuDgSf3179VpIxBF0o10JUpXWOnI7nErv7s= -golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM= -golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= -gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA= -gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= -gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME= -gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= -gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= -gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= -gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/v3/internal/templates/_common/greetservice.go b/v3/internal/templates/_common/greetservice.go deleted file mode 100644 index 8972c39cd..000000000 --- a/v3/internal/templates/_common/greetservice.go +++ /dev/null @@ -1,7 +0,0 @@ -package main - -type GreetService struct{} - -func (g *GreetService) Greet(name string) string { - return "Hello " + name + "!" -} diff --git a/v3/internal/templates/_common/main.go.tmpl b/v3/internal/templates/_common/main.go.tmpl deleted file mode 100644 index 2e81bf2fb..000000000 --- a/v3/internal/templates/_common/main.go.tmpl +++ /dev/null @@ -1,84 +0,0 @@ -package main - -import ( - "embed" - _ "embed" - "log" - "time" - - "github.com/wailsapp/wails/v3/pkg/application" -) - -// Wails uses Go's `embed` package to embed the frontend files into the binary. -// Any files in the frontend/dist folder will be embedded into the binary and -// made available to the frontend. -// See https://pkg.go.dev/embed for more information. - -//go:embed all:frontend/dist -var assets embed.FS - -func init() { - // Register a custom event whose associated data type is string. - // This is not required, but the binding generator will pick up registered events - // and provide a strongly typed JS/TS API for them. - application.RegisterEvent[string]("time") -} - -// main function serves as the application's entry point. It initializes the application, creates a window, -// and starts a goroutine that emits a time-based event every second. It subsequently runs the application and -// logs any error that might occur. -func main() { - - // Create a new Wails application by providing the necessary options. - // Variables 'Name' and 'Description' are for application metadata. - // 'Assets' configures the asset server with the 'FS' variable pointing to the frontend files. - // 'Bind' is a list of Go struct instances. The frontend has access to the methods of these instances. - // 'Mac' options tailor the application when running an macOS. - app := application.New(application.Options{ - Name: "{{.ProjectName}}", - Description: "A demo of using raw HTML & CSS", - Services: []application.Service{ - application.NewService(&GreetService{}), - }, - Assets: application.AssetOptions{ - Handler: application.AssetFileServerFS(assets), - }, - Mac: application.MacOptions{ - ApplicationShouldTerminateAfterLastWindowClosed: true, - }, - }) - - // Create a new window with the necessary options. - // 'Title' is the title of the window. - // 'Mac' options tailor the window when running on macOS. - // 'BackgroundColour' is the background colour of the window. - // 'URL' is the URL that will be loaded into the webview. - app.Window.NewWithOptions(application.WebviewWindowOptions{ - Title: "Window 1", - Mac: application.MacWindow{ - InvisibleTitleBarHeight: 50, - Backdrop: application.MacBackdropTranslucent, - TitleBar: application.MacTitleBarHiddenInset, - }, - BackgroundColour: application.NewRGB(27, 38, 54), - URL: "/", - }) - - // Create a goroutine that emits an event containing the current time every second. - // The frontend can listen to this event and update the UI accordingly. - go func() { - for { - now := time.Now().Format(time.RFC1123) - app.Event.Emit("time", now) - time.Sleep(time.Second) - } - }() - - // Run the application. This blocks until the application has been exited. - err := app.Run() - - // If an error occurred while running the application, log it and exit. - if err != nil { - log.Fatal(err) - } -} diff --git a/v3/internal/templates/base/NEXTSTEPS.md b/v3/internal/templates/base/NEXTSTEPS.md deleted file mode 100644 index 6b2e29a08..000000000 --- a/v3/internal/templates/base/NEXTSTEPS.md +++ /dev/null @@ -1,3 +0,0 @@ -# Next Steps - -For a full guide on how to create templates, see [Creating Custom Templates](https://v3.wails.io/guides/custom-templates). \ No newline at end of file diff --git a/v3/internal/templates/base/frontend/.gitignore b/v3/internal/templates/base/frontend/.gitignore deleted file mode 100644 index a547bf36d..000000000 --- a/v3/internal/templates/base/frontend/.gitignore +++ /dev/null @@ -1,24 +0,0 @@ -# Logs -logs -*.log -npm-debug.log* -yarn-debug.log* -yarn-error.log* -pnpm-debug.log* -lerna-debug.log* - -node_modules -dist -dist-ssr -*.local - -# Editor directories and files -.vscode/* -!.vscode/extensions.json -.idea -.DS_Store -*.suo -*.ntvs* -*.njsproj -*.sln -*.sw? diff --git a/v3/internal/templates/base/frontend/index.html b/v3/internal/templates/base/frontend/index.html deleted file mode 100644 index ec262d00a..000000000 --- a/v3/internal/templates/base/frontend/index.html +++ /dev/null @@ -1,35 +0,0 @@ - - - - - - - - Wails App - - -
                    - -

                    Wails + Javascript

                    -
                    -
                    Please enter your name below 👇
                    -
                    - - -
                    -
                    - -
                    - - - diff --git a/v3/internal/templates/base/frontend/main.js.tmpl b/v3/internal/templates/base/frontend/main.js.tmpl deleted file mode 100644 index 98b43c825..000000000 --- a/v3/internal/templates/base/frontend/main.js.tmpl +++ /dev/null @@ -1,21 +0,0 @@ -import {Events} from "@wailsio/runtime"; -import {GreetService} from "./bindings/{{js .ModulePath}}"; - -const resultElement = document.getElementById('result'); -const timeElement = document.getElementById('time'); - -window.doGreet = () => { - let name = document.getElementById('name').value; - if (!name) { - name = 'anonymous'; - } - GreetService.Greet(name).then((result) => { - resultElement.innerText = result; - }).catch((err) => { - console.log(err); - }); -} - -Events.On('time', (time) => { - timeElement.innerText = time.data; -}); diff --git a/v3/internal/templates/base/frontend/package.json b/v3/internal/templates/base/frontend/package.json deleted file mode 100644 index 9ae87549e..000000000 --- a/v3/internal/templates/base/frontend/package.json +++ /dev/null @@ -1,16 +0,0 @@ -{ - "name": "frontend", - "private": true, - "version": "0.0.0", - "type": "module", - "scripts": { - "dev": "vite", - "build:dev": "vite build --minify false --mode development", - "build": "vite build --mode production", - "preview": "vite preview" - }, - "devDependencies": { - "vite": "^5.0.0", - "@wailsio/runtime": "latest" - } -} \ No newline at end of file diff --git a/v3/internal/templates/ios/frontend/.gitignore b/v3/internal/templates/ios/frontend/.gitignore deleted file mode 100644 index a547bf36d..000000000 --- a/v3/internal/templates/ios/frontend/.gitignore +++ /dev/null @@ -1,24 +0,0 @@ -# Logs -logs -*.log -npm-debug.log* -yarn-debug.log* -yarn-error.log* -pnpm-debug.log* -lerna-debug.log* - -node_modules -dist -dist-ssr -*.local - -# Editor directories and files -.vscode/* -!.vscode/extensions.json -.idea -.DS_Store -*.suo -*.ntvs* -*.njsproj -*.sln -*.sw? diff --git a/v3/internal/templates/ios/frontend/index.html b/v3/internal/templates/ios/frontend/index.html deleted file mode 100644 index 0541019f1..000000000 --- a/v3/internal/templates/ios/frontend/index.html +++ /dev/null @@ -1,36 +0,0 @@ - - - - - - - - - Wails App - - -
                    - -

                    Wails + Javascript

                    -
                    -
                    Please enter your name below 👇
                    -
                    - - -
                    -
                    - -
                    - - - diff --git a/v3/internal/templates/ios/frontend/main.js b/v3/internal/templates/ios/frontend/main.js deleted file mode 100644 index 442ca8474..000000000 --- a/v3/internal/templates/ios/frontend/main.js +++ /dev/null @@ -1,24 +0,0 @@ -import {GreetService} from "./bindings/changeme"; -import {Events} from "@wailsio/runtime"; - -const resultElement = document.getElementById('result'); -const timeElement = document.getElementById('time'); - -window.doGreet = () => { - let name = document.getElementById('name').value; - if (!name) { - name = 'anonymous'; - } - GreetService.Greet(name).then((result) => { - resultElement.innerText = result; - }).catch((err) => { - console.log(err); - }); -} - -Events.On('time', (payload) => { - // payload may be a plain value or an object with a `data` field depending on emitter/runtime - const value = (payload && typeof payload === 'object' && 'data' in payload) ? payload.data : payload; - console.log('[frontend] time event:', payload, '->', value); - timeElement.innerText = value; -}); diff --git a/v3/internal/templates/ios/frontend/package.json b/v3/internal/templates/ios/frontend/package.json deleted file mode 100644 index 0a118e984..000000000 --- a/v3/internal/templates/ios/frontend/package.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "name": "frontend", - "private": true, - "version": "0.0.0", - "type": "module", - "scripts": { - "dev": "vite", - "build:dev": "vite build --minify false --mode development", - "build": "vite build --mode production", - "preview": "vite preview" - }, - "dependencies": { - "@wailsio/runtime": "latest" - }, - "devDependencies": { - "vite": "^5.0.0" - } -} diff --git a/v3/internal/templates/ios/frontend/public/Inter-Medium.ttf b/v3/internal/templates/ios/frontend/public/Inter-Medium.ttf deleted file mode 100644 index a01f3777a..000000000 Binary files a/v3/internal/templates/ios/frontend/public/Inter-Medium.ttf and /dev/null differ diff --git a/v3/internal/templates/ios/frontend/public/javascript.svg b/v3/internal/templates/ios/frontend/public/javascript.svg deleted file mode 100644 index f9abb2b72..000000000 --- a/v3/internal/templates/ios/frontend/public/javascript.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/v3/internal/templates/ios/frontend/public/puppertino/LICENSE b/v3/internal/templates/ios/frontend/public/puppertino/LICENSE deleted file mode 100644 index ed9065e06..000000000 --- a/v3/internal/templates/ios/frontend/public/puppertino/LICENSE +++ /dev/null @@ -1,21 +0,0 @@ -MIT License - -Copyright (c) 2019 Edgar Pérez - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/v3/internal/templates/ios/frontend/public/puppertino/css/actions.css b/v3/internal/templates/ios/frontend/public/puppertino/css/actions.css deleted file mode 100644 index 22a9d5a13..000000000 --- a/v3/internal/templates/ios/frontend/public/puppertino/css/actions.css +++ /dev/null @@ -1,149 +0,0 @@ -:root { - --font: -apple-system, "Inter", sans-serif; - --primary-col-ac: #0f75f5; - --p-modal-bg: rgba(255, 255, 255, 0.8); - --p-modal-bd-color: rgba(0,0,0,.1); - --p-modal-fallback-color: rgba(255,255,255,.95); - --p-actions-static-color: #555761; -} - -.p-modal-opened { - overflow: hidden; -} - -.p-action-background{ - background: rgba(0, 0, 0, 0.7); - height: 100vh; - left: 0; - opacity: 0; - pointer-events: none; - position: fixed; - top: 0; - transition: 0.3s; - width: 100vw; - z-index: 5; -} - -.p-action-background.nowactive { - opacity: 1; - pointer-events: auto; -} - - -.p-action-big-container{ - position:fixed; - width: 100%; - box-sizing: border-box; - padding: 1rem 5vw; - bottom:0; -} - -.p-action-container{ - background: var(--p-modal-bg); - display:block; - margin:auto; - margin-bottom: 10px; - border-radius: 10px; - max-width: 700px; -} - -.p-action-big-container .p-action-container:first-child{ - margin-bottom:10px; -} - -.p-action--intern{ - width: 100%; - display:block; - margin:auto; - font-size: 1rem; - font-weight: 600; - text-align:center; - padding: 15px 0; - border: 0; - border-bottom: 1px solid #bfbfbf; - color: #0f75f5; - text-decoration:none; - background-color: transparent; -} - -.p-action-destructive{ - color: #c6262e; -} - -.p-action-neutral{ - color: var(--p-actions-static-color); -} - -.p-action-cancel, .p-action-container a:last-child{ - border-bottom:none; -} - -.p-action-cancel{ - font-weight:bold; -} - -.p-action-icon{ - position:relative; -} -.p-action-icon svg, .p-action-icon img{ - position:absolute; - left:5%; - top:50%; - transform:translateY(-50%); -} - -.p-action-icon-inline{ - text-align: left; - display: flex; - align-items: center; -} - -.p-action-icon-inline svg, .p-action-icon-inline img{ - margin-left: 5%; - margin-right: 3%; -} - -.p-action-title{ - padding: 30px 15px; - border-bottom: 1px solid #bfbfbf; -} - -.p-action-title--intern,.p-action-text{ - margin:0; - color:var(--p-actions-static-color); -} - -.p-action-title--intern{ - margin-bottom: .3rem; -} - -@supports not (backdrop-filter: blur(10px)) { - .p-action-container { - background: var(--p-modal-fallback-color); - } -} - -.p-action-big-container{ - -webkit-transform: translateY(30%); - transform: translateY(30%); - opacity: 0; - transition: opacity 0.4s, transform 0.4s; - transition-timing-function: ease; - pointer-events: none; -} - -.p-action-big-container.active { - -webkit-transform: translateY(0); - transform: translateY(0); - opacity: 1; - pointer-events: all; -} - - -.p-action-big-container.active .p-action-container { - backdrop-filter: saturate(180%) blur(10px); -} - -.p-action-big-container[aria-hidden="true"] .p-action--intern { - display: none; -} diff --git a/v3/internal/templates/ios/frontend/public/puppertino/css/buttons.css b/v3/internal/templates/ios/frontend/public/puppertino/css/buttons.css deleted file mode 100644 index 4950b0053..000000000 --- a/v3/internal/templates/ios/frontend/public/puppertino/css/buttons.css +++ /dev/null @@ -1,158 +0,0 @@ -@charset "UTF-8"; -:root{ - --p-btn-border: #cacaca; - --p-btn-def-bg: #FFFFFF; - --p-btn-def-col: #000000; - --p-btn-dir-col: #242424; - --p-prim-text-col: #f5f5f5; - --p-btn-scope-unactive: #212136; - --p-btn-scope-action: #212136; -} - -.p-btn { - background: var(--p-btn-def-bg); - border: 1px solid var(--p-btn-border); - border-radius: 10px; - color: var(--p-btn-def-col); - display: inline-block; - font-family: -apple-system, "Inter", sans-serif; - font-size: 1.1rem; - margin: .7rem; - padding: .4rem 1.2rem; - text-decoration: none; - text-align: center; - box-shadow: 0 1px 0.375px rgba(0, 0, 0, 0.05), 0 0.25px 0.375px rgba(0, 0, 0, 0.15); - user-select: none; - cursor: pointer; -} -.p-btn:focus{ - outline: 2px solid #64baff; -} -.p-btn.p-btn-block{ - display: block; -} -.p-btn.p-btn-sm { - padding: .3rem 1.1rem; - font-size: 1rem; -} -.p-btn.p-btn-md { - padding: .8rem 2.4rem; - font-size: 1.6rem; -} -.p-btn.p-btn-lg { - padding: 1.2rem 2.8rem; - font-size: 1.8rem; -} -.p-btn-destructive{ - color: #FF3B30; -} -.p-btn-mob{ - padding: 10px 40px; - background: #227bec; - color: #fff; - border: 0; - box-shadow: inset 0 1px 1px rgb(255 255 255 / 41%), 0px 2px 3px -2px rgba(0,0,0,.3); -} -.p-btn[disabled], -.p-btn:disabled, -.p-btn-disabled{ - filter:contrast(0.5) grayscale(.5) opacity(.8); - cursor: not-allowed; - box-shadow: none; - pointer-events: none; -} - -.p-prim-col { - position: relative; - background: #007AFF; - border: none; - box-shadow: inset 0 1px 1px rgba(255, 255, 255, 0.41), 0px 2px 3px -2px rgba(0, 0, 0, 0.3); - color: var(--p-prim-text-col); - overflow: hidden; /* Ensure the ::before element doesn't overflow */ -} - -.p-prim-col:before { - content: ''; - position: absolute; - top: 0; - left: 0; - width: 100%; - height: 100%; - background: linear-gradient(180deg, rgba(255, 255, 255, 1) 0%, rgba(255, 255, 255, 0) 100%); - opacity: 0.17; - pointer-events: none; -} - -.p-btn.p-prim-col:active { - background: #0f75f5; -} - -.p-btn-more::after { - content: "..."; -} - -.p-btn-round { - border: 0; - border-radius: 50px; - box-shadow: inset 0 1px 1px rgb(255 255 255 / 41%); - padding: 10px 30px; -} - -.p-btn-icon { - align-items: center; - background: var(--p-btn-def-bg); - border: 2px solid currentColor; - border-radius: 50%; - color: #0f75f5; - display: inline-flex; - font-weight: 900; - height: 40px; - width: 40px; - justify-content: center; - margin: 5px; - text-align: center; - text-decoration: none; - box-sizing: border-box; - user-select: none; - vertical-align: bottom; -} - -.p-btn-icon.p-btn-icon-no-border{ - border: 0px; -} - -.p-btn-scope { - background: #8e8e8e; - color: #fff; - margin: 5px; - padding: 2px 20px; - box-shadow: none; -} -.p-btn-scope-unactive { - background: transparent; - border-color: transparent; - color: var(--p-btn-scope-unactive); - transition: border-color 0.2s; -} -.p-btn-scope-unactive:hover { - border-color: var(--p-btn-border); -} - -.p-btn-scope-outline { - background: transparent; - color: var(--p-btn-scope-action); - box-shadow: none; -} - -.p-btn-outline { - background: none; - border-color: currentColor; - box-shadow: none; -} - -.p-btn-outline-dash { - background: none; - border-color: currentColor; - border-style: dashed; - box-shadow: none; -} diff --git a/v3/internal/templates/ios/frontend/public/puppertino/css/cards.css b/v3/internal/templates/ios/frontend/public/puppertino/css/cards.css deleted file mode 100644 index b4fa2e397..000000000 --- a/v3/internal/templates/ios/frontend/public/puppertino/css/cards.css +++ /dev/null @@ -1,55 +0,0 @@ -:root{ - --p-color-card: #1a1a1a; - --p-bg-card: #fff; - --p-bd-card: #c5c5c55e; -} -.p-card { - background: var(--p-bg-card); - border: 1px solid var(--p-bd-card); - color: var(--p-color-card); - display: block; - margin: 15px; - margin-left:7.5px; - margin-right:7.5px; - text-decoration: none; - border-radius: 25px; - padding: 20px 0px; - transition: .3s ease; - box-shadow: 0 0.5px 1px rgba(0, 0, 0, 0.1); -} -.p-card-image > img { - border-bottom: 3px solid var(--accent-article); - display: block; - margin: auto; - width: 100%; -} -.p-card-tags { - display: flex; - overflow: hidden; - position: relative; - width: 100%; -} -.p-card-tags::before { - background: linear-gradient(to right, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0) 75%, white 100%); - content: ""; - height: 100%; - position: absolute; - right: 0; - top: 0; - width: 30%; -} -.p-card-title { - font-size: 2rem; - margin-bottom: 15px; - margin-top: 15px; -} -.p-card-content { - padding: 15px; - padding-top: 15px; -} -.p-card-text { - font-size: 17px; - margin-bottom: 10px; - margin-left: 10px; - margin-top: 0; -} diff --git a/v3/internal/templates/ios/frontend/public/puppertino/css/color_palette.css b/v3/internal/templates/ios/frontend/public/puppertino/css/color_palette.css deleted file mode 100644 index 33a66b91c..000000000 --- a/v3/internal/templates/ios/frontend/public/puppertino/css/color_palette.css +++ /dev/null @@ -1,917 +0,0 @@ -:root{ ---p-strawberry: #c6262e; ---p-strawberry-100: #ff8c82; ---p-strawberry-300: #ed5353; ---p-strawberry-500: #c6262e; ---p-strawberry-700: #a10705; ---p-strawberry-900: #7a0000; - ---p-orange: #f37329; ---p-orange-100: #ffc27d; ---p-orange-300: #ffa154; ---p-orange-500: #f37329; ---p-orange-700: #cc3b02; ---p-orange-900: #a62100; - - ---p-banana: #f9c440; ---p-banana-100: #fff394; ---p-banana-300: #ffe16b; ---p-banana-500: #f9c440; ---p-banana-700: #d48e15; ---p-banana-900: #ad5f00; - ---p-lime: #68b723; ---p-lime-100: #d1ff82; ---p-lime-300: #9bdb4d; ---p-lime-500: #68b723; ---p-lime-700: #3a9104; ---p-lime-900: #206b00; - ---p-mint: #28bca3; ---p-mint-100: #89ffdd; ---p-mint-300: #43d6b5; ---p-mint-500: #28bca3; ---p-mint-700: #0e9a83; ---p-mint-900: #007367; - - ---p-blueberry: #3689e6; ---p-blueberry-100: #8cd5ff; ---p-blueberry-300: #64baff; ---p-blueberry-500: #3689e6; ---p-blueberry-700: #0d52bf; ---p-blueberry-900: #002e99; - ---p-grape: #a56de2; ---p-grape-100: #e4c6fa; ---p-grape-300: #cd9ef7; ---p-grape-500: #a56de2; ---p-grape-700: #7239b3; ---p-grape-900: #452981; - ---p-bubblegum: #de3e80; ---p-bubblegum-100: #fe9ab8; ---p-bubblegum-300: #f4679d; ---p-bubblegum-500: #de3e80; ---p-bubblegum-700: #bc245d; ---p-bubblegum-900: #910e38; - - ---p-cocoa: #715344; ---p-cocoa-100: #a3907c; ---p-cocoa-300: #8a715e; ---p-cocoa-500: #715344; ---p-cocoa-700: #57392d; ---p-cocoa-900: #3d211b; - ---p-silver: #abacae; ---p-silver-100: #fafafa; ---p-silver-300: #d4d4d4; ---p-silver-500: #abacae; ---p-silver-700: #7e8087; ---p-silver-900: #555761; - ---p-slate: #485a6c; ---p-slate-100: #95a3ab; ---p-slate-300: #667885; ---p-slate-500: #485a6c; ---p-slate-700: #273445; ---p-slate-900: #0e141f; - - ---p-dark: #333; ---p-dark-100: #666; ---p-dark-300: #4d4d4d; ---p-dark-500: #333; ---p-dark-700: #1a1a1a; ---p-dark-900: #000; - - ---p-apple-red: rgb(255, 59 , 48); ---p-apple-red-dark: rgb(255, 69 , 58); ---p-apple-orange: rgb(255,149,0); ---p-apple-orange-dark: rgb(255,159,10); ---p-apple-yellow: rgb(255,204,0); ---p-apple-yellow-dark: rgb(255,214,10); ---p-apple-green: rgb(40,205,65); ---p-apple-green-dark: rgb(40,215,75); ---p-apple-mint: rgb(0,199,190); ---p-apple-mint-dark: rgb(102,212,207); ---p-apple-teal: rgb(89, 173, 196); ---p-apple-teal-dark: rgb(106, 196, 220); ---p-apple-cyan: rgb(85,190,240); ---p-apple-cyan-dark: rgb(90,200,245); ---p-apple-blue: rgb(0, 122, 255); ---p-apple-blue-dark: rgb(10, 132, 255); ---p-apple-indigo: rgb(88, 86, 214); ---p-apple-indigo-dark: rgb(94, 92, 230); ---p-apple-purple: rgb(175, 82, 222); ---p-apple-purple-dark: rgb(191, 90, 242); ---p-apple-pink: rgb(255, 45, 85); ---p-apple-pink-dark: rgb(255, 55, 95); ---p-apple-brown: rgb(162, 132, 94); ---p-apple-brown-dark: rgb(172, 142, 104); ---p-apple-gray: rgb(142, 142, 147); ---p-apple-gray-dark: rgb(152, 152, 157); - -} - - -/* -APPLE OFFICIAL COLORS -*/ - -.p-apple-red{ - background: rgb(255, 59 , 48); -} - -.p-apple-red-dark{ - background: rgb(255, 69 , 58); -} - -.p-apple-orange{ - background: rgb(255,149,0); -} - -.p-apple-orange-dark{ - background: rgb(255,159,10); -} - -.p-apple-yellow{ - background: rgb(255,204,0); -} - -.p-apple-yellow-dark{ - background: rgb(255,214,10); -} - -.p-apple-green{ - background: rgb(40,205,65); -} - -.p-apple-green-dark{ - background: rgb(40,215,75); -} - -.p-apple-mint{ - background: rgb(0,199,190); -} - -.p-apple-mint-dark{ - background: rgb(102,212,207); -} - -.p-apple-teal{ - background: rgb(89, 173, 196); -} - -.p-apple-teal-dark{ - background: rgb(106, 196, 220); -} - -.p-apple-cyan{ - background: rgb(85,190,240); -} - -.p-apple-cyan-dark{ - background: rgb(90,200,245); -} - -.p-apple-blue{ - background: rgb(0, 122, 255); -} - -.p-apple-blue-dark{ - background: rgb(10, 132, 255); -} - -.p-apple-indigo{ - background: rgb(88, 86, 214); -} - -.p-apple-indigo-dark{ - background: rgb(94, 92, 230); -} - -.p-apple-purple{ - background: rgb(175, 82, 222); -} - -.p-apple-purple-dark{ - background: rgb(191, 90, 242); -} - -.p-apple-pink{ - background: rgb(255, 45, 85); -} - -.p-apple-pink-dark{ - background: rgb(255, 55, 95); -} - -.p-apple-brown{ - background: rgb(162, 132, 94); -} - -.p-apple-brown-dark{ - background: rgb(172, 142, 104); -} - -.p-apple-gray{ - background: rgb(142, 142, 147); -} - -.p-apple-gray-dark{ - background: rgb(152, 152, 157); -} - -.p-apple-red-color{ - color: rgb(255, 59 , 48); -} - -.p-apple-red-dark-color{ - color: rgb(255, 69 , 58); -} - -.p-apple-orange-color{ - color: rgb(255,149,0); -} - -.p-apple-orange-dark-color{ - color: rgb(255,159,10); -} - -.p-apple-yellow-color{ - color: rgb(255,204,0); -} - -.p-apple-yellow-dark-color{ - color: rgb(255,214,10); -} - -.p-apple-green-color{ - color: rgb(40,205,65); -} - -.p-apple-green-dark-color{ - color: rgb(40,215,75); -} - -.p-apple-mint-color{ - color: rgb(0,199,190); -} - -.p-apple-mint-dark-color{ - color: rgb(102,212,207); -} - -.p-apple-teal-color{ - color: rgb(89, 173, 196); -} - -.p-apple-teal-dark-color{ - color: rgb(106, 196, 220); -} - -.p-apple-cyan-color{ - color: rgb(85,190,240); -} - -.p-apple-cyan-dark-color{ - color: rgb(90,200,245); -} - -.p-apple-blue-color{ - color: rgb(0, 122, 255); -} - -.p-apple-blue-dark-color{ - color: rgb(10, 132, 255); -} - -.p-apple-indigo-color{ - color: rgb(88, 86, 214); -} - -.p-apple-indigo-dark-color{ - color: rgb(94, 92, 230); -} - -.p-apple-purple-color{ - color: rgb(175, 82, 222); -} - -.p-apple-purple-dark-color{ - color: rgb(191, 90, 242); -} - -.p-apple-pink-color{ - color: rgb(255, 45, 85); -} - -.p-apple-pink-dark-color{ - color: rgb(255, 55, 95); -} - -.p-apple-brown-color{ - color: rgb(162, 132, 94); -} - -.p-apple-brown-dark-color{ - color: rgb(172, 142, 104); -} - -.p-apple-gray-color{ - color: rgb(142, 142, 147); -} - -.p-apple-gray-dark-color{ - color: rgb(152, 152, 157); -} - -.p-strawberry { - background: #c6262e; -} - -.p-strawberry-100 { - background: #ff8c82; -} - -.p-strawberry-300 { - background: #ed5353; -} - -.p-strawberry-500 { - background: #c6262e; -} - -.p-strawberry-700 { - background: #a10705; -} - -.p-strawberry-900 { - background: #7a0000; -} - -.p-orange { - background: #f37329; -} - -.p-orange-100 { - background: #ffc27d; -} - -.p-orange-300 { - background: #ffa154; -} - -.p-orange-500 { - background: #f37329; -} - -.p-orange-700 { - background: #cc3b02; -} - -.p-orange-900 { - background: #a62100; -} - -.p-banana { - background: #f9c440; -} - -.p-banana-100 { - background: #fff394; -} - -.p-banana-300 { - background: #ffe16b; -} - -.p-banana-500 { - background: #f9c440; -} - -.p-banana-700 { - background: #d48e15; -} - -.p-banana-900 { - background: #ad5f00; -} - -.p-lime { - background: #68b723; -} - -.p-lime-100 { - background: #d1ff82; -} - -.p-lime-300 { - background: #9bdb4d; -} - -.p-lime-500 { - background: #68b723; -} - -.p-lime-700 { - background: #3a9104; -} - -.p-lime-900 { - background: #206b00; -} - -.p-mint { - background: #28bca3; -} - -.p-mint-100 { - background: #89ffdd; -} - -.p-mint-300 { - background: #43d6b5; -} - -.p-mint-500 { - background: #28bca3; -} - -.p-mint-700 { - background: #0e9a83; -} - -.p-mint-900 { - background: #007367; -} - -.p-blueberry { - background: #3689e6; -} - -.p-blueberry-100 { - background: #8cd5ff; -} - -.p-blueberry-300 { - background: #64baff; -} - -.p-blueberry-500 { - background: #3689e6; -} - -.p-blueberry-700 { - background: #0d52bf; -} - -.p-blueberry-900 { - background: #002e99; -} - -.p-grape { - background: #a56de2; -} - -.p-grape-100 { - background: #e4c6fa; -} - -.p-grape-300 { - background: #cd9ef7; -} - -.p-grape-500 { - background: #a56de2; -} - -.p-grape-700 { - background: #7239b3; -} - -.p-grape-900 { - background: #452981; -} - -.p-bubblegum { - background: #de3e80; -} - -.p-bubblegum-100 { - background: #fe9ab8; -} - -.p-bubblegum-300 { - background: #f4679d; -} - -.p-bubblegum-500 { - background: #de3e80; -} - -.p-bubblegum-700 { - background: #bc245d; -} - -.p-bubblegum-900 { - background: #910e38; -} - -.p-cocoa { - background: #715344; -} - -.p-cocoa-100 { - background: #a3907c; -} - -.p-cocoa-300 { - background: #8a715e; -} - -.p-cocoa-500 { - background: #715344; -} - -.p-cocoa-700 { - background: #57392d; -} - -.p-cocoa-900 { - background: #3d211b; -} - -.p-silver { - background: #abacae; -} - -.p-silver-100 { - background: #fafafa; -} - -.p-silver-300 { - background: #d4d4d4; -} - -.p-silver-500 { - background: #abacae; -} - -.p-silver-700 { - background: #7e8087; -} - -.p-silver-900 { - background: #555761; -} - -.p-slate { - background: #485a6c; -} - -.p-slate-100 { - background: #95a3ab; -} - -.p-slate-300 { - background: #667885; -} - -.p-slate-500 { - background: #485a6c; -} - -.p-slate-700 { - background: #273445; -} - -.p-slate-900 { - background: #0e141f; -} - -.p-dark { - background: #333; -} - -.p-dark-100 { - background: #666; - /* hehe */ -} - -.p-dark-300 { - background: #4d4d4d; -} - -.p-dark-500 { - background: #333; -} - -.p-dark-700 { - background: #1a1a1a; -} - -.p-dark-900 { - background: #000; -} - -.p-white{ - background: #fff; -} - -.p-strawberry-color { - color: #c6262e; -} - -.p-strawberry-100-color { - color: #ff8c82; -} - -.p-strawberry-300-color { - color: #ed5353; -} - -.p-strawberry-500-color { - color: #c6262e; -} - -.p-strawberry-700-color { - color: #a10705; -} - -.p-strawberry-900-color { - color: #7a0000; -} - -.p-orange-color { - color: #f37329; -} - -.p-orange-100-color { - color: #ffc27d; -} - -.p-orange-300-color { - color: #ffa154; -} - -.p-orange-500-color { - color: #f37329; -} - -.p-orange-700-color { - color: #cc3b02; -} - -.p-orange-900-color { - color: #a62100; -} - -.p-banana-color { - color: #f9c440; -} - -.p-banana-100-color { - color: #fff394; -} - -.p-banana-300-color { - color: #ffe16b; -} - -.p-banana-500-color { - color: #f9c440; -} - -.p-banana-700-color { - color: #d48e15; -} - -.p-banana-900-color { - color: #ad5f00; -} - -.p-lime-color { - color: #68b723; -} - -.p-lime-100-color { - color: #d1ff82; -} - -.p-lime-300-color { - color: #9bdb4d; -} - -.p-lime-500-color { - color: #68b723; -} - -.p-lime-700-color { - color: #3a9104; -} - -.p-lime-900-color { - color: #206b00; -} - -.p-mint-color { - color: #28bca3; -} - -.p-mint-100-color { - color: #89ffdd; -} - -.p-mint-300-color { - color: #43d6b5; -} - -.p-mint-500-color { - color: #28bca3; -} - -.p-mint-700-color { - color: #0e9a83; -} - -.p-mint-900-color { - color: #007367; -} - -.p-blueberry-color { - color: #3689e6; -} - -.p-blueberry-100-color { - color: #8cd5ff; -} - -.p-blueberry-300-color { - color: #64baff; -} - -.p-blueberry-500-color { - color: #3689e6; -} - -.p-blueberry-700-color { - color: #0d52bf; -} - -.p-blueberry-900-color { - color: #002e99; -} - -.p-grape-color { - color: #a56de2; -} - -.p-grape-100-color { - color: #e4c6fa; -} - -.p-grape-300-color { - color: #cd9ef7; -} - -.p-grape-500-color { - color: #a56de2; -} - -.p-grape-700-color { - color: #7239b3; -} - -.p-grape-900-color { - color: #452981; -} - -.p-bubblegum-color { - color: #de3e80; -} - -.p-bubblegum-100-color { - color: #fe9ab8; -} - -.p-bubblegum-300-color { - color: #f4679d; -} - -.p-bubblegum-500-color { - color: #de3e80; -} - -.p-bubblegum-700-color { - color: #bc245d; -} - -.p-bubblegum-900-color { - color: #910e38; -} - -.p-cocoa-color { - color: #715344; -} - -.p-cocoa-100-color { - color: #a3907c; -} - -.p-cocoa-300-color { - color: #8a715e; -} - -.p-cocoa-500-color { - color: #715344; -} - -.p-cocoa-700-color { - color: #57392d; -} - -.p-cocoa-900-color { - color: #3d211b; -} - -.p-silver-color { - color: #abacae; -} - -.p-silver-100-color { - color: #fafafa; -} - -.p-silver-300-color { - color: #d4d4d4; -} - -.p-silver-500-color { - color: #abacae; -} - -.p-silver-700-color { - color: #7e8087; -} - -.p-silver-900-color { - color: #555761; -} - -.p-slate-color { - color: #485a6c; -} - -.p-slate-100-color { - color: #95a3ab; -} - -.p-slate-300-color { - color: #667885; -} - -.p-slate-500-color { - color: #485a6c; -} - -.p-slate-700-color { - color: #273445; -} - -.p-slate-900-color { - color: #0e141f; -} - -.p-dark-color { - color: #333; -} - -.p-dark-100-color { - color: #666; - /* hehe */ -} - -.p-dark-300-color { - color: #4d4d4d; -} - -.p-dark-500-color { - color: #333; -} - -.p-dark-700-color { - color: #1a1a1a; -} - -.p-dark-900-color { - color: #000; -} - -.p-white-color{ - color: #fff; -} diff --git a/v3/internal/templates/ios/frontend/public/puppertino/css/dark_mode.css b/v3/internal/templates/ios/frontend/public/puppertino/css/dark_mode.css deleted file mode 100644 index 3c5a03e80..000000000 --- a/v3/internal/templates/ios/frontend/public/puppertino/css/dark_mode.css +++ /dev/null @@ -1 +0,0 @@ -/* Puppertino dark_mode placeholder - local vendored */ diff --git a/v3/internal/templates/ios/frontend/public/puppertino/css/forms.css b/v3/internal/templates/ios/frontend/public/puppertino/css/forms.css deleted file mode 100644 index f2320ab1b..000000000 --- a/v3/internal/templates/ios/frontend/public/puppertino/css/forms.css +++ /dev/null @@ -1,509 +0,0 @@ -:root { - --primary-col:linear-gradient(to bottom, #4fc5fa 0%,#0f75f5 100%); - --primary-col-ac:#0f75f5; - --bg-color-input:#fff; - - --p-checkbox-gradient: linear-gradient(180deg, #4B91F7 0%, #367AF6 100%); - --p-checkbox-border: rgba(0, 0, 0, 0.2); - --p-checkbox-border-active: rgba(0, 0, 0, 0.12); - --p-checkbox-bg: transparent; - --p-checkbox-shadow: inset 0px 1px 2px rgba(0, 0, 0, 0.15), inset 0px 0px 2px rgba(0, 0, 0, 0.10); - - --p-input-bg:#fff; - --p-input-color: rgba(0,0,0,.85); - --p-input-color-plac:rgba(0,0,0,0.25); - - --p-input-color:#808080; - --p-input-bd:rgba(0,0,0,0.15); - --bg-hover-color:#f9f9f9; - --bg-front-col:#000; - --invalid-color:#d6513c; - --valid-color:#94d63c; -} - -.p-dark-mode{ - --p-checkbox-bg: linear-gradient(180deg, rgba(255, 255, 255, 0.1) 0%, rgba(255, 255, 255, 0.13) 100%); - --p-checkbox-shadow: 0px 0px 1px rgba(0, 0, 0, 0.25), inset 0px 0.5px 0px rgba(255, 255, 255, 0.15); - --p-checkbox-border: rgba(0, 0, 0, 0); - - --p-checkbox-gradient: linear-gradient(180deg, #3168DD 0%, #2C5FC8 100%); - --p-checkbox-border-active: rgba(0, 0, 0, 0); -} - -.p-form-select { - border-radius: 5px; - display: inline-block; - font-family: -apple-system, "Inter", sans-serif; - margin: 10px; - position: relative; -} - -.p-form-select > select:focus{ - outline: 2px solid #64baff; -} - -.p-form-select::after { - background: url("data:image/svg+xml,%3Csvg fill='none' xmlns='http://www.w3.org/2000/svg' viewBox='0 0 8 12'%3E%3Cpath d='M.288 4.117 3.16 1.18c.168-.168.336-.246.54-.246a.731.731 0 0 1 .538.246L7.108 4.12c.125.121.184.27.184.45 0 .359-.293.656-.648.656a.655.655 0 0 1-.48-.211L3.701 2.465l-2.469 2.55a.664.664 0 0 1-.48.212.656.656 0 0 1-.465-1.11Zm3.41 7.324a.73.73 0 0 0 .54-.246l2.87-2.941a.601.601 0 0 0 .184-.45.656.656 0 0 0-.648-.656.677.677 0 0 0-.48.211L3.701 9.91 1.233 7.36a.68.68 0 0 0-.48-.212.656.656 0 0 0-.465 1.11l2.871 2.937c.172.168.336.246.54.246Z' fill='white' style='mix-blend-mode:luminosity'/%3E%3C/svg%3E"), #017AFF; - background-size: 100% 75%; - background-position: center; - background-repeat: no-repeat; - border-radius: 5px; - bottom: 0; - content: ""; - display: block; - height: 80%; - pointer-events: none; - position: absolute; - right: 3%; - top: 10%; - width: 20px; -} - -.p-form-select > select { - -webkit-appearance: none; - appearance: none; - background: var(--p-input-bg); - border: 1px solid var(--p-input-bd); - border-radius: 5px; - font-size: 14px; - margin: 0; - outline: none; - padding: 5px 35px 5px 10px; - position: relative; - width: 100%; - color: var(--p-input-color); -} - -.p-form-text:invalid, -.p-form-text-alt:invalid{ - border-color: var(--invalid-color); -} - -.p-form-text:valid, -.p-form-text-alt:valid{ - border-color: var(--valid-color); -} - -.p-form-text:placeholder-shown, -.p-form-text-alt:placeholder-shown{ - border-color: var(--p-input-bd); -} - -.p-form-text { - color: var(--p-input-color); - -webkit-appearance: none; - appearance: none; - background: var(--p-input-bg); - border: 1px solid var(--p-input-bd); - border-radius: 5px; - font-family: -apple-system, "Inter", sans-serif; - font-size: 13px; - margin: 10px; - outline: 0; - padding: 3px 7px; - resize: none; - transition: border-color 200ms; - box-shadow: 0px 0.5px 2.5px rgba(0,0,0,.3), 0px 0px 0px rgba(0,0,0,.1); -} - -.p-form-text-alt { - color: var(--p-input-color); - -webkit-appearance: none; - appearance: none; - box-shadow: none; - background: var(--p-input-bg); - border: 0px; - border-bottom: 2px solid var(--p-input-bd); - padding: 10px; - border-top-left-radius: 3px; - border-top-right-radius: 3px; - margin: 10px; -} - - - -.p-form-text-alt::placeholder, -.p-form-text::placeholder -{ - color: var(--p-input-color-plac); -} - -.p-form-text:active, -.p-form-text:focus -{ - outline: 3px solid rgb(0 122 255 / 50%); -} - -.p-form-text-alt:focus { - outline: 0; - outline: 3px solid rgb(0 122 255 / 50%); - border-color: #3689e6; -} - -.p-form-no-validate:valid, -.p-form-no-validate:invalid{ - border-color: var(--p-input-bd); - color: var(--p-input-color)!important; -} - -.p-form-text:focus { - border-color: rgb(0 122 255); -} - -textarea.p-form-text { - -webkit-appearance: none; - appearance: none; - height: 100px; -} - -.p-form-truncated { - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; -} - -.p-form-text[type=password] { - font-family: caption; -} - -.p-form-label, -.p-form-radio-cont, -.p-form-checkbox-cont, -.p-form-label-inline { - font-family: -apple-system, "Inter", sans-serif; -} - -.p-form-label, .p-form-label-inline { - display: inline-block; -} - -.p-form-label{ - font-size: 11px; -} - -.p-form-label-inline { - background: var(--p-input-bg); - padding: 5px; - border-bottom: 2px solid var(--p-input-bd); - color: #656565; - font-weight: 500; - transition: .3s; -} - -.p-form-label-inline:focus-within { - color: #3689e6; - border-color: #3689e6; -} - -.p-form-label-inline > .p-form-text-alt { - border-bottom: 0px; - padding: 0; - outline: 0; - background: var(--p-input-bg); - -} - -.p-form-label-inline > .p-form-text-alt:-webkit-autofill{ - background: var(--p-input-bg); - -webkit-box-shadow: 0 0 0 30px rgba(0,0,0,0) inset !important; -} - -.p-form-label-inline > .p-form-text-alt:invalid { - color: var(--invalid-color); -} - -.p-form-label-inline > .p-form-text-alt:valid { - color: #3689e6; -} - -.p-form-label-inline > .p-form-text-alt:focus{ - color: var(--p-input-color); -} - -.p-form-radio-cont, -.p-form-checkbox-cont { - align-items: center; - display: inline-flex; - cursor: pointer; - margin: 0 10px; - user-select: none; -} - -.p-form-radio-cont > input + span, -.p-form-checkbox-cont > input + span { - background: var(--p-input-bg); - border: 1px solid var(--p-input-bd); - border-radius: 50%; - display: inline-block; - height: 20px; - margin-right: 5px; - position: relative; - transition: 0.2s; - width: 20px; -} - -.p-form-radio-cont > input + span{ - box-shadow: inset 0px 1px 2px rgba(0,0,0,0.10), inset 0px 0px 2px rgba(0,0,0,0.10); -} - -.p-form-radio-cont > input:focus + span, -.p-form-checkbox-cont > input:focus + span{ - outline: 3px solid rgb(0 122 255 / 50%); -} - -.p-form-radio-cont:hover > input + span{ - background: #f9f9f9; -} - -.p-form-radio-cont > input, -.p-form-checkbox-cont > input { - opacity: 0; - pointer-events: none; - position: absolute; -} - -.p-form-radio-cont > input + span::after { - background: #fff; - border-radius: 50%; - content: ""; - display: block; - height: 30%; - left: calc(50% - 15%); - opacity: 0; - position: absolute; - top: calc(50% - 15%); - transform: scale(2); - transition: opacity 0.2s, transform 0.3s; - width: 30%; -} - -.p-form-radio-cont > input:checked + span { - background: #0f75f5; - box-shadow: 0px 1px 2.5px 1px rgba(0, 122, 255, 0.24), inset 0px 0px 0px 0.5px rgba(0, 122, 255, 0.12); -} - -.p-form-radio-cont > input:checked + span::after { - opacity: 1; - transform: scale(1); -} - -.p-form-checkbox-cont > input + span { - border-radius: 5px; - box-shadow: var(--p-checkbox-shadow); - border: 0.5px solid var(--p-checkbox-border); - background: var(--p-checkbox-bg) -} - -.p-form-checkbox-cont > input:checked + span { - background: var(--p-checkbox-gradient); - border: 0.5px solid var(--p-checkbox-border-active); - box-shadow: 0px 1px 2.5px rgba(0, 122, 255, 0.24), 0px 0px 0px 0.5px rgba(0, 122, 255, 0.12); -} - -.p-form-checkbox-cont > input + span::before{ - content: ""; - display: block; - height: 100%; - width: 100%; - position: absolute; - left: 0%; - top: 0%; - opacity: 0; - transition: opacity 0.2s; - background-image: url("data:image/svg+xml,%3Csvg width='10' height='8' viewBox='0 0 10 8' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M4.10791 7.81299C3.83545 7.81299 3.6084 7.70459 3.42676 7.48779L1.15918 4.74121C1.08008 4.65039 1.02441 4.5625 0.992188 4.47754C0.959961 4.39258 0.943848 4.30469 0.943848 4.21387C0.943848 4.00586 1.0127 3.83447 1.15039 3.69971C1.29102 3.56201 1.4668 3.49316 1.67773 3.49316C1.91211 3.49316 2.10693 3.58838 2.26221 3.77881L4.10791 6.04297L7.68066 0.368652C7.77148 0.230957 7.86523 0.134277 7.96191 0.0786133C8.06152 0.0200195 8.18311 -0.00927734 8.32666 -0.00927734C8.5376 -0.00927734 8.71191 0.0581055 8.84961 0.192871C8.9873 0.327637 9.05615 0.497559 9.05615 0.702637C9.05615 0.778809 9.04297 0.85791 9.0166 0.939941C8.99023 1.02197 8.94922 1.10693 8.89355 1.19482L4.80225 7.45703C4.64111 7.69434 4.40967 7.81299 4.10791 7.81299Z' fill='white'/%3E%3C/svg%3E%0A"); - background-size: 70%; - background-position: center; - background-repeat: no-repeat; -} - -.p-form-checkbox-cont > input + span::after{ - content: ''; - width: 100%; - height: 100%; - position: absolute; - top: 0; - left: 0; - z-index: 9; -} - -.p-form-checkbox-cont > input + span:active::after{ - border-radius: 5px; - backdrop-filter: brightness(1.2); -} - -.p-form-checkbox-cont > input:checked + span::before{ - opacity: 1; -} - - -.p-form-checkbox-cont > input[disabled] + span, -.p-form-radio-cont > input[disabled] ~ span -{ - opacity: .7; - cursor: not-allowed; -} - -.p-form-button { - -webkit-appearance: none; - appearance: none; - background: #fff; - border: 1px solid var(--p-input-bd); - border-radius: 5px; - color: #333230; - display: inline-block; - font-size: 17px; - margin: 10px; - padding: 5px 20px; - text-decoration: none; -} - -.p-form-send { - background: linear-gradient(to bottom, #4fc5fa 0%, #0f75f5 100%); - border: 0; - color: #fff; -} - -.p-form-send:active { - background: #0f75f5; -} - -.p-form-invalid, -.p-form-invalid:placeholder-shown, -.p-form-invalid:valid, -.p-form-invalid:invalid { - border-color: var(--invalid-color); -} - -.p-form-valid, -.p-form-valid:placeholder-shown, -.p-form-valid:valid, -.p-form-valid:invalid { - border-color: var(--valid-color); -} - -.p-form-switch { - --width: 80px; - cursor: pointer; - display: inline-block; -} - -.p-form-switch > input:checked + span::after { - left: calc(100% - calc(var(--width) / 1.8)); -} - -.p-form-switch > input:checked + span { - background: #60c35b; -} - -.p-form-switch > span { - background: #e0e0e0; - border: 1px solid #d3d3d3; - border-radius: 500px; - display: block; - height: calc(var(--width) / 1.6); - position: relative; - transition: all 0.2s; - width: var(--width); -} - -.p-form-switch > span::after { - background: #f9f9f9; - border-radius: 50%; - border: 0.5px solid rgba(0, 0, 0, 0.101987); - box-shadow: 0px 3px 1px rgba(0, 0, 0, 0.1), 0px 1px 1px rgba(0, 0, 0, 0.16), 0px 3px 8px rgba(0, 0, 0, 0.15); - box-sizing: border-box; - content: ""; - height: 84%; - left: 3%; - position: absolute; - top: 6.5%; - transition: all 0.2s; - width: 52.5%; -} - -.p-form-switch > input { - display: none; -} - -.p-chip input{ - opacity: 0; - pointer-events: none; - position: absolute; -} - -.p-chip span{ - padding: .8rem 1rem; - border-radius: 1.6rem; - display:inline-block; - margin:10px; - background: #e4e4e4ca; - color: #3689e6; - transition: .3s; - user-select: none; - cursor:pointer; - font-family: -apple-system, "Inter", sans-serif; - font-size: 1rem; - -webkit-tap-highlight-color: rgba(0, 0, 0, 0); - -moz-tap-highlight-color: rgba(0, 0, 0, 0); - text-align:center; -} - -.p-chip:focus-within span{ - outline: 2px solid #64baff; -} - -.p-chip svg{ - display:block; - margin:auto; -} - - -.p-chip input:checked + span{ - background: #3689e6; - color:#fff; -} - -.p-chip-outline span, .p-chip-outline-to-bg span{ - background: transparent; - color: #3e3e3e; - border: 1px solid currentColor; -} - -.p-chip-outline input:checked + span{ - background: transparent; - color: #3689e6; -} - -.p-chip-radius-b span{ - border-radius: 5px; -} - -.p-chip-dark span{ - color: #3e3e3e; -} - -.p-chip-dark input:checked + span{ - background: #3e3e3e; -} - -.p-chip input:disabled + span, -.p-chip input[disabled] + span{ - opacity: .5; - cursor: not-allowed; -} - -.p-chip-big span{ - font-size: 1.3rem; - padding: 1.5rem; - min-width: 80px; -} - -.p-form-checkbox-cont[disabled], -.p-form-label[disabled], -.p-form-text[disabled], -.p-form-text-alt[disabled], -.p-form-select[disabled], -.p-form-radio-cont[disabled]{ - filter: grayscale(1) opacity(.3); - pointer-events: none; -} diff --git a/v3/internal/templates/ios/frontend/public/puppertino/css/layout.css b/v3/internal/templates/ios/frontend/public/puppertino/css/layout.css deleted file mode 100644 index 1f9b36845..000000000 --- a/v3/internal/templates/ios/frontend/public/puppertino/css/layout.css +++ /dev/null @@ -1,45 +0,0 @@ -.p-large-title{ - font-size: 2.75rem; -} - -.p-layout h1 { - font-size: 2.25rem; -} - -.p-layout h2 { - font-size: 1.75rem; -} - -.p-layout h3 { - font-size: 1.58rem; -} - -.p-headline { - font-size: 1.34rem; - font-weight: bold; -} - -.p-layout p { - font-size: 1.15rem; -} - -.p-layout .link, -.p-layout input { - font-size: 0.813rem; -} - -.p-callout { - font-size: 1.14rem; -} - -.p-subhead { - font-size: 1.167rem; -} - -.p-footnote { - font-size: 1.07rem; -} - -.p-caption { - font-size: 0.91rem; -} diff --git a/v3/internal/templates/ios/frontend/public/puppertino/css/modals.css b/v3/internal/templates/ios/frontend/public/puppertino/css/modals.css deleted file mode 100644 index 4d718c4f7..000000000 --- a/v3/internal/templates/ios/frontend/public/puppertino/css/modals.css +++ /dev/null @@ -1 +0,0 @@ -/* Puppertino modals placeholder - local vendored */ diff --git a/v3/internal/templates/ios/frontend/public/puppertino/css/newfull.css b/v3/internal/templates/ios/frontend/public/puppertino/css/newfull.css deleted file mode 100644 index 622a2f364..000000000 --- a/v3/internal/templates/ios/frontend/public/puppertino/css/newfull.css +++ /dev/null @@ -1,11 +0,0 @@ -@import url('actions.css'); -@import url('buttons.css'); -@import url('layout.css'); -@import url('cards.css'); -@import url('color_palette.css'); -@import url('forms.css'); -@import url('modals.css'); -@import url('segmented-controls.css'); -@import url('shadows.css'); -@import url('tabs.css'); -@import url('dark_mode.css'); diff --git a/v3/internal/templates/ios/frontend/public/puppertino/css/segmented-controls.css b/v3/internal/templates/ios/frontend/public/puppertino/css/segmented-controls.css deleted file mode 100644 index 22819fd5f..000000000 --- a/v3/internal/templates/ios/frontend/public/puppertino/css/segmented-controls.css +++ /dev/null @@ -1 +0,0 @@ -/* Puppertino segmented-controls placeholder - local vendored */ diff --git a/v3/internal/templates/ios/frontend/public/puppertino/css/shadows.css b/v3/internal/templates/ios/frontend/public/puppertino/css/shadows.css deleted file mode 100644 index 060a61658..000000000 --- a/v3/internal/templates/ios/frontend/public/puppertino/css/shadows.css +++ /dev/null @@ -1 +0,0 @@ -/* Puppertino shadows placeholder - local vendored */ diff --git a/v3/internal/templates/ios/frontend/public/puppertino/css/tabs.css b/v3/internal/templates/ios/frontend/public/puppertino/css/tabs.css deleted file mode 100644 index 61d1487ca..000000000 --- a/v3/internal/templates/ios/frontend/public/puppertino/css/tabs.css +++ /dev/null @@ -1 +0,0 @@ -/* Puppertino tabs placeholder - local vendored */ diff --git a/v3/internal/templates/ios/frontend/public/puppertino/puppertino.css b/v3/internal/templates/ios/frontend/public/puppertino/puppertino.css deleted file mode 100644 index 905da220e..000000000 --- a/v3/internal/templates/ios/frontend/public/puppertino/puppertino.css +++ /dev/null @@ -1,1774 +0,0 @@ -@charset "UTF-8"; -.p-btn { - background: #fff; - border: 1px solid #cacaca; - border-radius: 5px; - color: #333230; - display: inline-block; - font-family: -apple-system, "Inter", sans-serif; - font-size: 17px; - margin: 10px; - padding: 5px 20px; - text-decoration: none; - /* text-shadow: 0 1px 1px rgba(0, 0, 0, 0.25); */ -} -.p-btn-mob{ - padding: 10px 40px; - background: #0f75f5; - color: #fff; -} -.p-btn[disabled] { - background: #d3d3d3; - color: #555; - cursor: not-allowed; -} -.p-btn:disabled { - background: #d3d3d3; - color: #555; - cursor: not-allowed; -} -.p-btn-disabled { - background: #d3d3d3; - color: #555; - cursor: not-allowed; -} - -.p-prim-col { - background: linear-gradient(to bottom, #4fc5fa 0%, #0f75f5 100%); - border: 0; - color: #fff; -} - -.p-btn.p-prim-col:active { - background: #0f75f5; -} - -.p-btn-more::after { - content: "..."; -} - -.p-btn-round { - border: 0; - border-radius: 50px; - padding: 10px 30px; -} - -.p-btn-icon { - align-items: center; - background: #fff; - border: 2px solid currentColor; - border-radius: 50%; - box-shadow: 0 3px 10px -8px #000; - color: #0f75f5; - display: inline-flex; - font-weight: 900; - height: 36px; - justify-content: center; - margin: 5px; - text-align: center; - text-decoration: none; - width: 36px; -} - -.p-btn-scope { - background: #8e8e8e; - color: #fff; - margin: 5px; - padding: 2px 20px; -} -.p-btn-scope-unactive { - background: transparent; - border-color: transparent; - color: #212136; - transition: border-color 0.2s; -} -.p-btn-scope-unactive:hover { - border-color: #cacaca; -} -.p-btn-scope-disabled { - background: transparent; - color: #8e8e8e; - cursor: not-allowed; -} -.p-btn-scope-outline { - background: transparent; - color: #212136; -} - -.p-btn-scope-outline { - background: transparent; - color: #212136; -} - -.p-btn-outline { - background: none; - border-color: currentColor; -} - -.p-btn-outline-dash { - background: none; - border-color: currentColor; - border-style: dashed; -} - -.p-btn-direction { - color: #212136; - padding: 5px; - text-decoration: none; -} - -.p-btn-direction.p-btn-d-back::before { - content: "❬"; -} - -.p-btn-direction.p-btn-d-next::after { - content: "❭"; -} - -@media (max-width: 576px) { - .p-btn-big-sm { - border: 0; - border-radius: 0%; - bottom: 0; - font-size: 50px; - left: 0; - margin: 0; - padding: 10px 0; - position: fixed; - text-align: center; - width: 100%; - } -} - -/*END OF BUTTONS*/ - -.p-card { - background: rgba(255, 255, 255, 0.3); - border: 1px solid rgba(0, 0, 0, 0.1); - border-radius: 3px; - box-shadow: 0 8px 10px -8px rgba(0, 0, 0, 0.1); - color: #000; - display: block; - margin-top: 30px; - text-decoration: none; -} -.p-card-image > img { - border-bottom: 3px solid var(--accent-article); - display: block; - margin: auto; - width: 100%; -} -.p-card-tags { - display: flex; - overflow: hidden; - position: relative; - width: 100%; -} -.p-card-tags::before { - background: linear-gradient(to right, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0) 75%, white 100%); - content: ""; - height: 100%; - position: absolute; - right: 0; - top: 0; - width: 30%; -} -.p-card-tags span, -.p-card-tags a { - border: 1px solid #252525; - border-radius: 50px; - color: #252525; - margin: 5px; - padding: 5px 15px; - text-decoration: none; - transition: all 0.2s; -} -.p-card-tags a:hover { - background: #252525; - color: #000; -} -.p-card-title { - font-size: 2rem; - margin-bottom: 15px; - margin-top: 10px; -} -.p-card-content { - padding: 15px; - padding-top: 5px; -} -.p-card-text { - font-size: 17px; - margin-bottom: 10px; - margin-left: 10px; - margin-top: 0; -} - - -/* END OF CARDS*/ - -.p-strawberry { - background: #c6262e; -} - -.p-strawberry-100 { - background: #ff8c82; -} - -.p-strawberry-300 { - background: #ed5353; -} - -.p-strawberry-500 { - background: #c6262e; -} - -.p-strawberry-700 { - background: #a10705; -} - -.p-strawberry-900 { - background: #7a0000; -} - -.p-orange { - background: #f37329; -} - -.p-orange-100 { - background: #ffc27d; -} - -.p-orange-300 { - background: #ffa154; -} - -.p-orange-500 { - background: #f37329; -} - -.p-orange-700 { - background: #cc3b02; -} - -.p-orange-900 { - background: #a62100; -} - -.p-banana { - background: #f9c440; -} - -.p-banana-100 { - background: #fff394; -} - -.p-banana-300 { - background: #ffe16b; -} - -.p-banana-500 { - background: #f9c440; -} - -.p-banana-700 { - background: #d48e15; -} - -.p-banana-900 { - background: #ad5f00; -} - -.p-lime { - background: #68b723; -} - -.p-lime-100 { - background: #d1ff82; -} - -.p-lime-300 { - background: #9bdb4d; -} - -.p-lime-500 { - background: #68b723; -} - -.p-lime-700 { - background: #3a9104; -} - -.p-lime-900 { - background: #206b00; -} - -.p-mint { - background: #28bca3; -} - -.p-mint-100 { - background: #89ffdd; -} - -.p-mint-300 { - background: #43d6b5; -} - -.p-mint-500 { - background: #28bca3; -} - -.p-mint-700 { - background: #0e9a83; -} - -.p-mint-900 { - background: #007367; -} - -.p-blueberry { - background: #3689e6; -} - -.p-blueberry-100 { - background: #8cd5ff; -} - -.p-blueberry-300 { - background: #64baff; -} - -.p-blueberry-500 { - background: #3689e6; -} - -.p-blueberry-700 { - background: #0d52bf; -} - -.p-blueberry-900 { - background: #002e99; -} - -.p-grape { - background: #a56de2; -} - -.p-grape-100 { - background: #e4c6fa; -} - -.p-grape-300 { - background: #cd9ef7; -} - -.p-grape-500 { - background: #a56de2; -} - -.p-grape-700 { - background: #7239b3; -} - -.p-grape-900 { - background: #452981; -} - -.p-bubblegum { - background: #de3e80; -} - -.p-bubblegum-100 { - background: #fe9ab8; -} - -.p-bubblegum-300 { - background: #f4679d; -} - -.p-bubblegum-500 { - background: #de3e80; -} - -.p-bubblegum-700 { - background: #bc245d; -} - -.p-bubblegum-900 { - background: #910e38; -} - -.p-cocoa { - background: #715344; -} - -.p-cocoa-100 { - background: #a3907c; -} - -.p-cocoa-300 { - background: #8a715e; -} - -.p-cocoa-500 { - background: #715344; -} - -.p-cocoa-700 { - background: #57392d; -} - -.p-cocoa-900 { - background: #3d211b; -} - -.p-silver { - background: #abacae; -} - -.p-silver-100 { - background: #fafafa; -} - -.p-silver-300 { - background: #d4d4d4; -} - -.p-silver-500 { - background: #abacae; -} - -.p-silver-700 { - background: #7e8087; -} - -.p-silver-900 { - background: #555761; -} - -.p-slate { - background: #485a6c; -} - -.p-slate-100 { - background: #95a3ab; -} - -.p-slate-300 { - background: #667885; -} - -.p-slate-500 { - background: #485a6c; -} - -.p-slate-700 { - background: #273445; -} - -.p-slate-900 { - background: #0e141f; -} - -.p-dark { - background: #333; -} - -.p-dark-100 { - background: #666; - /* hehe */ -} - -.p-dark-300 { - background: #4d4d4d; -} - -.p-dark-500 { - background: #333; -} - -.p-dark-700 { - background: #1a1a1a; -} - -.p-dark-900 { - background: #000; -} - -.p-strawberry-color { - color: #c6262e; -} - -.p-strawberry-100-color { - color: #ff8c82; -} - -.p-strawberry-300-color { - color: #ed5353; -} - -.p-strawberry-500-color { - color: #c6262e; -} - -.p-strawberry-700-color { - color: #a10705; -} - -.p-strawberry-900-color { - color: #7a0000; -} - -.p-orange-color { - color: #f37329; -} - -.p-orange-100-color { - color: #ffc27d; -} - -.p-orange-300-color { - color: #ffa154; -} - -.p-orange-500-color { - color: #f37329; -} - -.p-orange-700-color { - color: #cc3b02; -} - -.p-orange-900-color { - color: #a62100; -} - -.p-banana-color { - color: #f9c440; -} - -.p-banana-100-color { - color: #fff394; -} - -.p-banana-300-color { - color: #ffe16b; -} - -.p-banana-500-color { - color: #f9c440; -} - -.p-banana-700-color { - color: #d48e15; -} - -.p-banana-900-color { - color: #ad5f00; -} - -.p-lime-color { - color: #68b723; -} - -.p-lime-100-color { - color: #d1ff82; -} - -.p-lime-300-color { - color: #9bdb4d; -} - -.p-lime-500-color { - color: #68b723; -} - -.p-lime-700-color { - color: #3a9104; -} - -.p-lime-900-color { - color: #206b00; -} - -.p-mint-color { - color: #28bca3; -} - -.p-mint-100-color { - color: #89ffdd; -} - -.p-mint-300-color { - color: #43d6b5; -} - -.p-mint-500-color { - color: #28bca3; -} - -.p-mint-700-color { - color: #0e9a83; -} - -.p-mint-900-color { - color: #007367; -} - -.p-blueberry-color { - color: #3689e6; -} - -.p-blueberry-100-color { - color: #8cd5ff; -} - -.p-blueberry-300-color { - color: #64baff; -} - -.p-blueberry-500-color { - color: #3689e6; -} - -.p-blueberry-700-color { - color: #0d52bf; -} - -.p-blueberry-900-color { - color: #002e99; -} - -.p-grape-color { - color: #a56de2; -} - -.p-grape-100-color { - color: #e4c6fa; -} - -.p-grape-300-color { - color: #cd9ef7; -} - -.p-grape-500-color { - color: #a56de2; -} - -.p-grape-700-color { - color: #7239b3; -} - -.p-grape-900-color { - color: #452981; -} - -.p-bubblegum-color { - color: #de3e80; -} - -.p-bubblegum-100-color { - color: #fe9ab8; -} - -.p-bubblegum-300-color { - color: #f4679d; -} - -.p-bubblegum-500-color { - color: #de3e80; -} - -.p-bubblegum-700-color { - color: #bc245d; -} - -.p-bubblegum-900-color { - color: #910e38; -} - -.p-cocoa-color { - color: #715344; -} - -.p-cocoa-100-color { - color: #a3907c; -} - -.p-cocoa-300-color { - color: #8a715e; -} - -.p-cocoa-500-color { - color: #715344; -} - -.p-cocoa-700-color { - color: #57392d; -} - -.p-cocoa-900-color { - color: #3d211b; -} - -.p-silver-color { - color: #abacae; -} - -.p-silver-100-color { - color: #fafafa; -} - -.p-silver-300-color { - color: #d4d4d4; -} - -.p-silver-500-color { - color: #abacae; -} - -.p-silver-700-color { - color: #7e8087; -} - -.p-silver-900-color { - color: #555761; -} - -.p-slate-color { - color: #485a6c; -} - -.p-slate-100-color { - color: #95a3ab; -} - -.p-slate-300-color { - color: #667885; -} - -.p-slate-500-color { - color: #485a6c; -} - -.p-slate-700-color { - color: #273445; -} - -.p-slate-900-color { - color: #0e141f; -} - -.p-dark-color { - color: #333; -} - -.p-dark-100-color { - color: #666; - /* hehe */ -} - -.p-dark-300-color { - color: #4d4d4d; -} - -.p-dark-500-color { - color: #333; -} - -.p-dark-700-color { - color: #1a1a1a; -} - -.p-dark-900-color { - color: #000; -} - -/* END OF COLORS */ - -:root { - --primary-col:linear-gradient(to bottom, #4fc5fa 0%,#0f75f5 100%); - --primary-col-ac:#0f75f5; - --bg-color:#fff; - --bg-hover-color:#f9f9f9; - --bg-front-col:#000; - --invalid-color:#d6513c; - --valid-color:#94d63c; -} - -.p-form-select { - border-radius: 5px; - display: inline-block; - font-family: -apple-system, "Inter", sans-serif; - margin: 10px; - position: relative; -} - -.p-form-select::before { - border-color: #fff transparent transparent; - border-style: solid; - border-width: 5px; - content: ""; - pointer-events: none; - position: absolute; - right: 5px; - top: calc(50% - 3px); - z-index: 3; -} - -.p-form-select::after { - background: linear-gradient(to bottom, #4fc5fa 0%, #0f75f5 100%); - border-bottom-right-radius: 5px; - border-top-right-radius: 5px; - bottom: 0; - content: ""; - display: block; - height: 100%; - pointer-events: none; - position: absolute; - right: 0; - top: 0; - width: 20px; -} - -.p-form-select > select { - -webkit-appearance: none; - background: #fff; - border: 1px solid #cacaca; - border-radius: 5px; - font-size: 14px; - margin: 0; - outline: none; - padding: 5px 30px 5px 10px; - position: relative; - width: 100%; -} - -.p-form-text:invalid, -.p-form-text-alt:invalid, -.p-form-select > select:invalid { - border-color: var(--invalid-color); -} - -.p-form-text:valid, -.p-form-text-alt:valid, -.p-form-select > select:valid { - border-color: var(--valid-color); -} - -.p-form-text:placeholder-shown, -.p-form-text-alt:placeholder-shown, -.p-form-select > select:placeholder-shown { - border-color: #cacaca; -} - -.p-form-text { - -webkit-appearance: none; - box-shadow: none; - background: #fff; - border: 1px solid #cacaca; - border-radius: 5px; - font-family: -apple-system, "Inter", sans-serif; - margin: 10px; - outline: 0; - padding: 5px; - resize: none; - transition: border-color 200ms; -} - -.p-form-text-alt { - -webkit-appearance: none; - box-shadow: none; - background: #fff; - border: 0px; - border-bottom: 2px solid #cacaca; - padding: 10px; - border-top-left-radius: 5px; - border-top-right-radius: 5px; - margin: 10px; -} - -.p-form-text-alt::placeholder { - color: #cacaca; -} - -.p-form-text-alt:focus { - outline: 3px solid #bed8f9; -} - -.p-form-no-validate:valid, -.p-form-no-validate:invalid, -.p-form-no-validate > select:valid, -.p-form-no-validate > select:invalid { - border-color: #cacaca; -} - -.p-form-text:focus { - border-color: #0f75f5; -} - -textarea.p-form-text { - -webkit-appearance: none; - height: 100px; -} - -.p-form-truncated { - overflow: hidden; - text-overflow: ellipsis; - white-space: nowrap; -} - -.p-form-text[type=password] { - font-family: caption; -} - -.p-form-label, -.p-form-radio-cont, -.p-form-checkbox-cont { - font-family: -apple-system, "Inter", sans-serif; -} - -.p-form-label { - display: block; -} - -.p-form-radio-cont, -.p-form-checkbox-cont { - align-items: center; - display: inline-flex; - margin: 0 10px; -} - -.p-form-radio-cont > input + span, -.p-form-checkbox-cont > input + span { - background: #fff; - border: 1px solid #cacaca; - border-radius: 50%; - cursor: pointer; - display: inline-block; - height: 20px; - margin-right: 5px; - position: relative; - transition: background 0.2s; - width: 20px; -} - -.p-form-radio-cont > input + span:hover { - background: #f9f9f9; -} - -.p-form-radio-cont > input, -.p-form-checkbox-cont > input { - opacity: 0; - pointer-events: none; - position: absolute; -} - -.p-form-radio-cont > input + span::after { - background: #fff; - border-radius: 50%; - box-shadow: 0 1px 2px rgba(0, 0, 0, 0.3); - content: ""; - display: block; - height: 30%; - left: calc(50% - 15%); - opacity: 0; - position: absolute; - top: calc(50% - 15%); - transform: scale(2); - transition: opacity 0.2s, transform 0.3s; - width: 30%; -} - -.p-form-radio-cont > input:checked + span { - background: #0f75f5; -} - -.p-form-radio-cont > input:checked + span::after { - opacity: 1; - transform: scale(1); -} - -.p-form-checkbox-cont > input + span { - border-radius: 5px; -} - -.p-form-checkbox-cont > input:checked + span { - background: #0f75f5; -} - -.p-form-checkbox-cont > input + span::before, -.p-form-checkbox-cont > input + span::after { - background: #fff; - border-radius: 20px; - content: ""; - display: block; - height: 8%; - position: absolute; -} - -.p-form-checkbox-cont > input + span::before { - right: 30%; - top: 15%; - transform: rotate(-65deg); - transform-origin: top right; - width: 70%; -} - -.p-form-checkbox-cont > input + span::after { - left: 30%; - top: 43%; - transform: rotate(60deg); - transform-origin: top left; - width: 40%; -} - -.p-form-button { - -webkit-appearance: none; - background: #fff; - border: 1px solid #cacaca; - border-radius: 5px; - color: #333230; - display: inline-block; - font-size: 17px; - margin: 10px; - padding: 5px 20px; - text-decoration: none; - /* text-shadow: 0 1px 1px rgba(0, 0, 0, 0.25); */ -} - -.p-form-send { - background: linear-gradient(to bottom, #4fc5fa 0%, #0f75f5 100%); - border: 0; - color: #fff; -} - -.p-form-send:active { - background: #0f75f5; -} - -.p-form-invalid, -.p-form-invalid:placeholder-shown, -.p-form-invalid:valid, -.p-form-invalid:invalid { - border-color: var(--invalid-color); -} - -.p-form-valid, -.p-form-valid:placeholder-shown, -.p-form-valid:valid, -.p-form-valid:invalid { - border-color: var(--valid-color); -} - -.p-form-switch { - --width: 80px; - cursor: pointer; - display: inline-block; -} - -.p-form-switch > input:checked + span::after { - left: calc(100% - calc(var(--width) / 2.1)); -} - -.p-form-switch > input:checked + span { - background: #60c35b; -} - -.p-form-switch > span { - background: #e0e0e0; - border: 1px solid #d3d3d3; - border-radius: 500px; - display: block; - height: calc(var(--width) / 2); - overflow: hidden; - position: relative; - transition: all 0.2s; - width: var(--width); -} - -.p-form-switch > span::after { - background: #f9f9f9; - border-radius: 50%; - box-shadow: 0px 3px 1px rgba(0, 0, 0, 0.1), 0px 1px 1px rgba(0, 0, 0, 0.16), 0px 3px 8px rgba(0, 0, 0, 0.15); - content: ""; - height: 90%; - left: 3%; - position: absolute; - top: 4.5%; - transition: all 0.2s; - width: 45%; -} - -.p-form-switch > input { - display: none; -} - -input[type=range].p-form-range { - width: 100%; - margin: 11.5px 0; - background-color: transparent; - -webkit-appearance: none; -} -input[type=range].p-form-range:focus { - outline: none; -} -input[type=range].p-form-range::-webkit-slider-runnable-track { - background: #cacaca; - border: 0; - width: 100%; - height: 2px; - cursor: pointer; -} -input[type=range].p-form-range::-webkit-slider-thumb { - margin-top: -11.5px; - width: 25px; - height: 25px; - background: #ffffff; - border: 1px solid rgba(115, 115, 115, 0.6); - border-radius: 30px; - cursor: pointer; - box-shadow: 0 3px 1px rgba(0, 0, 0, 0.1), 0 1px 1px rgba(0, 0, 0, 0.16), 0 3px 8px rgba(0, 0, 0, 0.15); - -webkit-appearance: none; -} -input[type=range].p-form-range:focus::-webkit-slider-runnable-track { - background: #d7d7d7; -} -input[type=range].p-form-range::-moz-range-track { - background: #cacaca; - border: 0; - width: 100%; - height: 2px; - cursor: pointer; -} -input[type=range].p-form-range::-moz-range-thumb { - width: 25px; - height: 25px; - background: #ffffff; - border: 1px solid rgba(115, 115, 115, 0.6); - border-radius: 30px; - box-shadow: 0 3px 1px rgba(0, 0, 0, 0.1), 0 1px 1px rgba(0, 0, 0, 0.16), 0 3px 8px rgba(0, 0, 0, 0.15); - cursor: pointer; -} -input[type=range].p-form-range::-ms-track { - background: transparent; - border-color: transparent; - border-width: 26.5px 0; - color: transparent; - width: 100%; - height: 2px; - cursor: pointer; -} -input[type=range].p-form-range::-ms-fill-lower { - background: #bdbdbd; - border: 0; -} -input[type=range].p-form-range::-ms-fill-upper { - background: #cacaca; - border: 0; -} -input[type=range].p-form-range::-ms-thumb { - width: 25px; - height: 25px; - background: #ffffff; - border: 1px solid rgba(115, 115, 115, 0.6); - border-radius: 30px; - cursor: pointer; - box-shadow: 0 3px 1px rgba(0, 0, 0, 0.1), 0 1px 1px rgba(0, 0, 0, 0.16), 0 3px 8px rgba(0, 0, 0, 0.15); - margin-top: 0px; - /*Needed to keep the Edge thumb centred*/ -} -input[type=range].p-form-range:focus::-ms-fill-lower { - background: #cacaca; -} -input[type=range].p-form-range:focus::-ms-fill-upper { - background: #d7d7d7; -} -/*TODO: Use one of the selectors from https://stackoverflow.com/a/20541859/7077589 and figure out -how to remove the virtical space around the range input in IE*/ -@supports (-ms-ime-align:auto) { - /* Pre-Chromium Edge only styles, selector taken from hhttps://stackoverflow.com/a/32202953/7077589 */ - input[type=range].p-form-range { - margin: 0; - /*Edge starts the margin from the thumb, not the track as other browsers do*/ - } -} - - -/* END OF FORMS */ - -.p-layout .p-large-title { - font-size: 2.75rem; -} - -.p-layout h1 { - font-size: 2.25rem; -} - -.p-layout h2 { - font-size: 1.75rem; -} - -.p-layout h3 { - font-size: 1.58rem; -} - -.p-layout .p-headline { - font-size: 1.34rem; - font-weight: bold; -} - -.p-layout p { - font-size: 1.15rem; -} - -.p-layout a, -.p-layout input { - font-size: 1.14rem; -} - -.p-layout .p-callout { - font-size: 1.14rem; -} - -.p-layout .p-subhead { - font-size: 1.167rem; -} - -.p-layout .p-footnote { - font-size: 1.07rem; -} - -.p-layout .p-caption { - font-size: 0.91rem; -} - -/* END OF LAYOUT */ - -:root { - --font: -apple-system, "Inter", sans-serif; - --bg-hover-color: #f9f9f9; - --primary-col-ac: #0f75f5; -} - -.p-modal-opened { - overflow: hidden; -} - -.p-modal-background { - background: rgba(0, 0, 0, 0.3); - height: 100vh; - left: 0; - opacity: 0; - pointer-events: none; - position: fixed; - top: 0; - transition: all 0.3s; - width: 100vw; - z-index: 5; -} - -.p-modal { - background: rgba(255, 255, 255, 0.85); - border-radius: 20px; - top: calc(50% - 20vh); - bottom: unset; - box-shadow: 0 10px 20px -15px; - font-family: var(--font); - left: calc(50% - 20vw); - opacity: 0; - overflow: hidden; - pointer-events: none; - position: fixed; - text-align: center; - transform: scale(1.5); - transition: opacity 0.3s, transform 0.3s; - width: 40vw; - z-index: 9; -} - -.p-modal.active { - backdrop-filter: saturate(180%) blur(10px); - opacity: 1; - pointer-events: auto; - transform: scale(1); -} - -.p-modal-button-container { - border-radius: 20px; - display: flex; -} - -.p-modal-button-container > a { - border-top: 1px solid rgba(0, 0, 0, 0.1); - color: var(--primary-col-ac); - padding: 30px 0%; - text-decoration: none; - width: 100%; -} - -.p-modal-button-container > a:nth-child(2), -.p-modal-button-container > a:nth-child(3) { - border-left: 1px solid rgba(0, 0, 0, 0.1); -} - -.nowactive { - opacity: 1; - pointer-events: auto; -} - -.p-modal p { - padding: 0% 5%; -} - -@supports not (backdrop-filter: blur(5px)) { - .p-modal { - background: #fff; - } -} -@media (max-width: 568px) { - .p-modal { - bottom: 20%; - left: 15%; - top: unset; - width: 70vw; - } - - .p-modal p { - font-size: 15px; - padding: 0% 10%; - } - - .p-modal-button-container { - display: block; - } - - .p-modal-button-container > a { - border-left: 0 !important; - display: block; - padding: 2vh 0%; - } -} - -/* END OF MODALS */ - -.p-segmented-controls { - --color-segmented: #3689e6; - --color-lighter-segment: #d2e3f9; - background: #fff; - border: 1px solid var(--color-segmented); - border-radius: 5px; - display: flex; - flex-wrap: wrap; - font-family: -apple-system, "Inter", sans-serif; - margin-top: 10px; - overflow: hidden; - width: 100%; -} -.p-segmented-controls a { - color: var(--color-segmented); - flex: auto; - padding: 10px; - text-align: center; - text-decoration: none; - transition: all 0.5s; -} -.p-segmented-controls a.active { - background: var(--color-segmented); - color: #fff; -} -.p-segmented-controls a:not(:first-child) { - border-left: 1px solid currentColor; -} - -.p-segmented-radius { - border-radius: 30px; -} - -.p-segmented-internal-radius a, -.p-segmented-internal-radius a:not(:first-child) { - border: 0; - border-radius: 30px; -} - -.p-segmented-controls-alt a:not(:first-child) { - border: 0; -} -.p-segmented-controls-alt a:not(:first-child).active { - background: var(--color-lighter-segment); - color: var(--color-segmented); - font-weight: bold; -} - -.p-segmented-outline { - border: 2px solid var(--color-segmented); -} -.p-segmented-outline a:not(:first-child) { - border-left: 2px solid var(--color-segmented); -} - -.p-segmented-controls-outline-alt a:not(:first-child) { - border: 2px solid transparent; -} - -.p-segmented-controls-outline-alt { - border-radius: 30px; -} -.p-segmented-controls-outline-alt a { - border: 2px solid transparent; - border-radius: 30px; -} -.p-segmented-controls-outline-alt a.active { - background: #fff; - border-color: var(--color-segmented); - border-radius: 30px; - color: var(--color-segmented); - font-weight: bold; -} - -.p-segmented-grey { - --color-segmented: #555761; - --color-lighter-segment: #d4d4d4; -} - -/* END OF SEGMENTED CONTROLS */ - -.p-shadow-1 { - box-shadow: 0 3px 10px rgba(0, 0, 0, 0.1); -} - -.p-shadow-2 { - box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); -} - -.p-shadow-3 { - box-shadow: 0 10px 18px rgba(0, 0, 0, 0.3); -} - -.p-shadow-4 { - box-shadow: 0 25px 30px rgba(0, 0, 0, 0.2); -} - -.p-to-shadow-4, -.p-to-shadow-3, -.p-to-shadow-2, -.p-to-shadow-1 { - transition-timing-function: ease; - transition: box-shadow 0.5s; -} - -.p-to-shadow-1:hover { - box-shadow: 0 3px 10px rgba(0, 0, 0, 0.1);> -} - -.p-to-shadow-2:hover { - box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2); -} - -.p-to-shadow-3:hover { - box-shadow: 0 10px 18px rgba(0, 0, 0, 0.3); -} - -.p-to-shadow-4:hover { - box-shadow: 0 25px 30px rgba(0, 0, 0, 0.2); -} - - -/* END OF SHADOWS */ - -.p-tabs-container { - background: #e3e3e3; - border: 1px solid #e0e0e0; - padding: 1em; -} - -.p-tabs-container.p-light { - background: none; - border: none; -} - -.p-tabs-container.p-light .p-panels { - margin-top: 0; - border-radius: 0; - padding: 0; -} - -.p-tabs { - display: flex; - justify-content: center; -} - -.p-tabs > :nth-of-type(1) { - border-radius: 5px 0 0 5px; -} - -.p-tabs > :last-child { - border-radius: 0 5px 5px 0; -} - -.p-tab { - margin: 0; - padding: 5px 35px; - background: #fff; - color: #333230; - text-decoration: none; - /* text-shadow: 0 1px 1px rgba(0, 0, 0, 0.25); */ - border: 1px solid #cacaca; - display: inline-block; - font-size: 17px; - font-family: -apple-system, "Inter", sans-serif; - cursor: pointer; -} - -.p-tab:focus { - outline: 0; -} - -.p-is-active { - background: linear-gradient(to bottom, #4fc5fa 0%, #0f75f5 100%); - border: 0; - color: #fff; -} - -.p-panels { - margin-top: 1em; - background: #fff; - border-radius: 3px; - position: relative; - padding: 0.8em; - overflow: hidden; -} - -.p-panel.p-is-active { - opacity: 1; - pointer-events: all; - background: none; - color: inherit; - position: static; -} - -.p-panel { - position: absolute; - opacity: 0; - pointer-events: none; -} - -@media (max-width: 768px) { - .p-tabs { - overflow: auto; - } - .p-tab { - font-size: 0.8em; - padding: 5px 28px; - } - .p-tabs-container { - padding: 0.8em; - } - - .p-panels { - padding: 0.8em; - } -} - -@media screen and (max-width: 496px) { - .p-tab { - text-align: center; - padding: 5px 18px; - } - .p-tabs-container { - padding: 0.5em; - } - - .p-panels { - padding: 0.5em; - margin-top: 0.5em; - } -} - -@media screen and (max-width: 378px) { - .p-tab { - text-align: center; - padding: 5px 10px; - } - .p-tabs-container { - padding: 0.5em; - } - - .p-panels { - padding: 0.5em; - margin-top: 0.5; - } -} - -.p-mobile-tabs { - position: fixed; - bottom: 0; - left: 0; - width: 100%; - padding: 15px 0px; - border-top: 1px solid #949494; - background: rgba(202, 202, 202, 0.8); - backdrop-filter: blur(10px); - display: flex; - font-family: -apple-system, "Inter", sans-serif; -} - -.p-mobile-tabs > div { - flex: auto; - text-align: center; -} - -.p-mobile-tabs a { - text-decoration: none; - color: #555; - transition: color 0.5s; - display: inline-block; - font-size: 0.8rem; -} - -.p-mobile-tabs a.active { - color: #0f75f5; - font-weight: 600; -} - -.p-mobile-tabs svg { - display: block; - margin: auto; - margin-bottom: 0.2rem; -} - -.p-mobile-tabs--content { - display: none; -} - -.p-mobile-tabs--content.active { - display: block; -} - -/* END OF TABS */ - - -.p-action-background{ - background: rgba(0, 0, 0, 0.3); - height: 100vh; - left: 0; - opacity: 0; - pointer-events: none; - position: fixed; - top: 0; - transition: all 0.3s; - width: 100vw; - z-index: 5; -} - -.p-action-background.nowactive { - opacity: 1; - pointer-events: auto; -} - - -.p-action-big-container{ - position:fixed; - width: 100%; - box-sizing: border-box; - padding: 1rem 5vw; - bottom:0; -} - -.p-action-container{ - background: rgba(255, 255, 255, 0.8); - backdrop-filter: blur(10px); - display:block; - margin:auto; - margin-bottom: 10px; - border-radius: 10px; -} - -.p-action-big-container .p-action-container:first-child{ - margin-bottom:10px; -} - -.p-action--intern{ - display:block; - margin:auto; - text-align:center; - padding: 15px 0; - border-bottom: 1px solid #bfbfbf; - font-weight: 500; - color: #0f75f5; - text-decoration:none; -} - -.p-action-destructive{ - color: #c6262e; -} - -.p-action-neutral{ - color: #555761; -} - -.p-action-cancel, .p-action-container a:last-child{ - border-bottom:none; -} - -.p-action-cancel{ - font-weight:bold; -} - -.p-action-icon{ - position:relative; -} -.p-action-icon svg, .p-action-icon img{ - position:absolute; - left:5%; - top:50%; - transform:translateY(-50%); -} - -.p-action-icon-inline{ - text-align: left; - display: flex; - align-items: center; -} - -.p-action-icon-inline svg, .p-action-icon-inline img{ - margin-left: 5%; - margin-right: 3%; -} - -.p-action-title{ - padding: 30px 15px; - border-bottom: 1px solid #bfbfbf; -} - -.p-action-title--intern,.p-action-text{ - margin:0; - color:#555761; -} - -.p-action-title--intern{ - margin-bottom: .3rem; -} - -@supports not (backdrop-filter: blur(10px)) { - .p-action-container { - background: rgba(255,255,255,.95); - } -} - -.p-action-big-container{ - -webkit-transform: translateY(30%); - transform: translateY(30%); - opacity: 0; - transition: opacity 0.4s, transform 0.4s; - transition-timing-function: ease-in-out; -} - -.p-action-big-container.active { --webkit-transform: translateY(0); - transform: translateY(0); - opacity: 1; -} - - -/* END OF ACTIONS */ diff --git a/v3/internal/templates/ios/frontend/public/style.css b/v3/internal/templates/ios/frontend/public/style.css deleted file mode 100644 index 72620de1c..000000000 --- a/v3/internal/templates/ios/frontend/public/style.css +++ /dev/null @@ -1,261 +0,0 @@ -:root { - font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, - sans-serif, "Apple Color Emoji", "Segoe UI Emoji"; - font-size: 16px; - line-height: 24px; - font-weight: 400; - color-scheme: light dark; - /* Desktop defaults (mobile overrides below) */ - --bg: #1C222F; /* rgb(28,34,47) */ - --fg: rgba(255,255,255,0.88); - font-synthesis: none; - text-rendering: optimizeLegibility; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - -webkit-text-size-adjust: 100%; - user-select: none; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; -} - -*, *::before, *::after { - box-sizing: border-box; -} - -/* Prefer system fonts on mobile; remove custom font to reduce bundle size */ - -h3 { - font-size: 3em; - line-height: 1.1; -} - -a { - font-weight: 500; - color: #646cff; - text-decoration: inherit; -} - -a:hover { - color: #535bf2; -} - -/* Remove generic button styling to allow Puppertino .btn to control buttons */ - -.result { - height: 20px; - line-height: 20px; -} - -html, -body { - height: 100%; - width: 100%; - overflow-x: hidden; /* prevent horizontal overflow */ - overflow-y: auto; /* allow vertical scroll if needed */ -} - -body { - margin: 0; - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - min-width: 320px; - /* Use small viewport units to avoid iOS Safari URL bar issues */ - min-height: 100svh; - height: auto; /* avoid forcing overflow */ - /* Equal responsive spacing top & bottom */ - padding-block: clamp(8px, 4vh, 48px); - color: var(--fg); - background-color: var(--bg); -} - -.container { - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - /* Responsive spacing between elements */ - gap: clamp(8px, 2vh, 24px); - width: 100%; - max-width: 480px; - padding-inline: 16px; -} - -h1 { - /* Responsive heading size */ - font-size: clamp(1.6rem, 6vw, 3.2rem); - line-height: 1.1; -} - -#app { - max-width: 1280px; - margin: 0 auto; - /* Responsive inner padding: horizontal only, no extra top/bottom */ - padding: 0 clamp(12px, 4vw, 32px); - text-align: center; -} - -.logo { - /* Consistent visual size across images: fix height, auto width */ - height: clamp(80px, 18vh, 140px); - width: auto; - max-width: 80vw; - padding: 0.5em; - will-change: filter; -} - -.logo:hover { - filter: drop-shadow(0 0 2em #e80000aa); -} - -.logo.vanilla:hover { - filter: drop-shadow(0 0 2em #f7df1eaa); -} - -.result { - height: 20px; - line-height: 20px; - margin: 1.5rem auto; - text-align: center; -} - -.footer { - margin-top: 1rem; - align-content: center; - text-align: center; -} - -/* Mobile-specific light mode */ -@media (max-width: 768px) and (prefers-color-scheme: light) { - :root { - --fg: rgba(255,255,255,0.88); - --bg: #1C222F; /* rgb(28,34,47) */ - } - - a:hover { - color: #747bff; - } - - /* allow Puppertino to style .btn */ - - .input-box .input { - color: #111827; - background-color: #f3f4f6; - border: 1px solid #e5e7eb; /* show border in light mode */ - border-radius: 8px; - } - - button:hover { - border-color: #d1d5db; /* slate-300 */ - } - - .input-box .input:focus { - border-color: #9ca3af; /* gray-400 */ - box-shadow: 0 0 0 3px rgba(59, 130, 246, 0.15); /* subtle focus ring */ - } -} - -/* let Puppertino handle .btn hover */ - -.input-box .input { - border: 1px solid transparent; /* default; themed in media queries */ - border-radius: 8px; - outline: none; - height: 30px; - line-height: 30px; - padding: 0 10px; - color: black; - background-color: rgba(240, 240, 240, 1); - -webkit-font-smoothing: antialiased; -} - -.input-box .input:hover { - background-color: rgba(255, 255, 255, 1); -} - -.input-box .input:focus { - background-color: rgba(255, 255, 255, 1); - outline: 2px solid transparent; - outline-offset: 2px; -} - -/* Mobile-specific dark mode */ -@media (max-width: 768px) and (prefers-color-scheme: dark) { - :root { - color: rgba(255, 255, 255, 0.88); - --fg: rgba(255, 255, 255, 0.88); - --bg: #1C222F; /* rgb(28,34,47) */ - } - - a { - color: #8ea2ff; - } - - a:hover { - color: #aab6ff; - } - - /* allow Puppertino to style .btn in dark mode */ - - .input-box .input { - background-color: #111827; /* gray-900 */ - color: #e5e7eb; - caret-color: #ffffff; - border: 1px solid #374151; /* slate-700 */ - } - - .input-box .input:hover, - .input-box .input:focus { - background-color: #0b1220; - border-color: #4b5563; /* slate-600 */ - } - - /* allow Puppertino to handle active state */ -} - -/* Mobile baseline overrides (apply to both light and dark) */ -@media (max-width: 768px) { - /* Prevent iOS zoom on focus */ - input, textarea, select, button { font-size: 16px; } - - /* let Puppertino define .btn sizing */ - - /* Align input with button and center text nicely */ - .input-box { - display: flex; - align-items: center; - gap: 8px; - } - - .input-box .input { - height: 36px; /* slightly shorter to match button */ - line-height: 1.2; - padding: 0 10px; - } - - /* Lock viewport to device height and remove overflow on mobile */ - html, body { - height: 100dvh; - min-height: 100dvh; - overflow: hidden; - overscroll-behavior: none; /* disable scroll chaining/bounce */ - -webkit-overflow-scrolling: auto; /* avoid momentum scrolling */ - } - - body { - padding-block: 0; /* avoid extra height from block padding */ - padding-top: env(safe-area-inset-top); - padding-bottom: env(safe-area-inset-bottom); - height: 100dvh; - min-height: 100dvh; - position: fixed; /* lock body to viewport */ - inset: 0; /* fill viewport */ - } - - .container { - min-height: calc(100dvh - env(safe-area-inset-top) - env(safe-area-inset-bottom)); - justify-content: center; /* vertical center without needing extra padding */ - } -} \ No newline at end of file diff --git a/v3/internal/templates/ios/frontend/public/wails.png b/v3/internal/templates/ios/frontend/public/wails.png deleted file mode 100644 index 8bdf42483..000000000 Binary files a/v3/internal/templates/ios/frontend/public/wails.png and /dev/null differ diff --git a/v3/internal/templates/ios/template.json b/v3/internal/templates/ios/template.json deleted file mode 100644 index 9780ef660..000000000 --- a/v3/internal/templates/ios/template.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "name": "iOS Vanilla (Puppertino) + Vite", - "shortname": "ios", - "author": "Lea Anthony", - "description": "Vanilla + Vite with iOS-friendly styling and bundled Puppertino", - "helpurl": "https://wails.io", - "version": "v0.0.1", - "schema": 3 -} \ No newline at end of file diff --git a/v3/internal/templates/lit-ts/frontend/.gitignore b/v3/internal/templates/lit-ts/frontend/.gitignore deleted file mode 100644 index a547bf36d..000000000 --- a/v3/internal/templates/lit-ts/frontend/.gitignore +++ /dev/null @@ -1,24 +0,0 @@ -# Logs -logs -*.log -npm-debug.log* -yarn-debug.log* -yarn-error.log* -pnpm-debug.log* -lerna-debug.log* - -node_modules -dist -dist-ssr -*.local - -# Editor directories and files -.vscode/* -!.vscode/extensions.json -.idea -.DS_Store -*.suo -*.ntvs* -*.njsproj -*.sln -*.sw? diff --git a/v3/internal/templates/lit-ts/frontend/index.html b/v3/internal/templates/lit-ts/frontend/index.html deleted file mode 100644 index d01a04294..000000000 --- a/v3/internal/templates/lit-ts/frontend/index.html +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - Wails + Lit + TS - - - - - -

                    Wails + Lit

                    -
                    - - diff --git a/v3/internal/templates/lit-ts/frontend/package.json b/v3/internal/templates/lit-ts/frontend/package.json deleted file mode 100644 index d208c3fbd..000000000 --- a/v3/internal/templates/lit-ts/frontend/package.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "name": "frontend", - "private": true, - "version": "0.0.0", - "type": "module", - "scripts": { - "dev": "vite", - "build:dev": "tsc && vite build --minify false --mode development", - "build": "tsc && vite build --mode production", - "preview": "vite preview" - }, - "dependencies": { - "@wailsio/runtime": "latest", - "lit": "^3.1.0" - }, - "devDependencies": { - "typescript": "^5.2.2", - "vite": "^5.0.0" - } -} diff --git a/v3/internal/templates/lit-ts/frontend/public/Inter-Medium.ttf b/v3/internal/templates/lit-ts/frontend/public/Inter-Medium.ttf deleted file mode 100644 index a01f3777a..000000000 Binary files a/v3/internal/templates/lit-ts/frontend/public/Inter-Medium.ttf and /dev/null differ diff --git a/v3/internal/templates/lit-ts/frontend/public/lit.svg b/v3/internal/templates/lit-ts/frontend/public/lit.svg deleted file mode 100644 index 4a9c1fe66..000000000 --- a/v3/internal/templates/lit-ts/frontend/public/lit.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/v3/internal/templates/lit-ts/frontend/public/style.css b/v3/internal/templates/lit-ts/frontend/public/style.css deleted file mode 100644 index 10550a378..000000000 --- a/v3/internal/templates/lit-ts/frontend/public/style.css +++ /dev/null @@ -1,58 +0,0 @@ -:root { - font-family: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", - "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", - sans-serif; - font-size: 16px; - line-height: 24px; - font-weight: 400; - color-scheme: light dark; - color: rgba(255, 255, 255, 0.87); - background-color: rgba(27, 38, 54, 1); - font-synthesis: none; - text-rendering: optimizeLegibility; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - -webkit-text-size-adjust: 100%; - user-select: none; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; -} - -@font-face { - font-family: "Inter"; - font-style: normal; - font-weight: 400; - src: local(""), - url("./Inter-Medium.ttf") format("truetype"); -} - - -body { - margin: 0; - display: flex; - place-items: center; - place-content: center; - min-width: 320px; - min-height: 100vh; -} - -h1 { - font-size: 3.2em; - line-height: 1.1; -} - -@media (prefers-color-scheme: light) { - :root { - color: #213547; - background-color: #ffffff; - } - - a:hover { - color: #747bff; - } - - button { - background-color: #f9f9f9; - } -} \ No newline at end of file diff --git a/v3/internal/templates/lit-ts/frontend/public/wails.png b/v3/internal/templates/lit-ts/frontend/public/wails.png deleted file mode 100644 index 8bdf42483..000000000 Binary files a/v3/internal/templates/lit-ts/frontend/public/wails.png and /dev/null differ diff --git a/v3/internal/templates/lit-ts/frontend/src/my-element.ts.tmpl b/v3/internal/templates/lit-ts/frontend/src/my-element.ts.tmpl deleted file mode 100644 index 974f812fd..000000000 --- a/v3/internal/templates/lit-ts/frontend/src/my-element.ts.tmpl +++ /dev/null @@ -1,174 +0,0 @@ -import {css, html, LitElement} from 'lit' -import {customElement, property} from 'lit/decorators.js' -import {Events} from "@wailsio/runtime"; -import {GreetService} from '../bindings/{{js .ModulePath}}'; - -/** - * An example element. - * - * @slot - This element has a slot - * @csspart button - The button - */ -@customElement('my-element') -export class MyElement extends LitElement { - - @property() - result: string = 'Please enter your name below 👇' - - @property() - time: string = 'Listening for Time event...' - - @property() - name: string = ''; - - constructor() { - super(); - Events.On('time', (timeValue: { data: string }) => { - this.time = timeValue.data; - }); - } - - - doGreet() { - let name = this.name; - if (!name) { - name = 'anonymous'; - } - GreetService.Greet(name).then((resultValue: string) => { - this.result = resultValue; - }).catch((err: Error) => { - console.log(err); - }); - } - - render() { - return html` -
                    - - -
                    ${this.result}
                    -
                    -
                    - this.name = (e.target as HTMLInputElement).value} type="text" - autocomplete="off"/> - -
                    -
                    - -
                    - ` - } - - - static styles = css` - :host { - max-width: 1280px; - margin: 0 auto; - padding: 2rem; - text-align: center; - } - - h3 { - font-size: 3em; - line-height: 1.1; - } - - a { - font-weight: 500; - color: #646cff; - text-decoration: inherit; - } - - a:hover { - color: #535bf2; - } - - button { - width: 60px; - height: 30px; - line-height: 30px; - border-radius: 3px; - border: none; - margin: 0 0 0 20px; - padding: 0 8px; - cursor: pointer; - } - - .container { - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - } - - .logo { - height: 6em; - padding: 1.5em; - will-change: filter; - } - - .logo:hover { - filter: drop-shadow(0 0 2em #e80000aa); - } - - .logo.lit:hover { - filter: drop-shadow(0 0 2em #325cffaa); - } - - .result { - height: 20px; - line-height: 20px; - margin: 1.5rem auto; - text-align: center; - } - - .footer { - margin-top: 1rem; - align-content: center; - text-align: center; - } - - .input-box .btn:hover { - background-image: linear-gradient(to top, #cfd9df 0%, #e2ebf0 100%); - color: #333333; - } - - .input-box .input { - border: none; - border-radius: 3px; - outline: none; - height: 30px; - line-height: 30px; - padding: 0 10px; - color: black; - background-color: rgba(240, 240, 240, 1); - -webkit-font-smoothing: antialiased; - } - - .input-box .input:hover { - border: none; - background-color: rgba(255, 255, 255, 1); - } - - .input-box .input:focus { - border: none; - background-color: rgba(255, 255, 255, 1); - } - `; -} - -declare global { - interface HTMLElementTagNameMap { - 'my-element': MyElement - } -} diff --git a/v3/internal/templates/lit-ts/frontend/src/vite-env.d.ts b/v3/internal/templates/lit-ts/frontend/src/vite-env.d.ts deleted file mode 100644 index 11f02fe2a..000000000 --- a/v3/internal/templates/lit-ts/frontend/src/vite-env.d.ts +++ /dev/null @@ -1 +0,0 @@ -/// diff --git a/v3/internal/templates/lit-ts/frontend/tsconfig.json b/v3/internal/templates/lit-ts/frontend/tsconfig.json deleted file mode 100644 index 6badd7348..000000000 --- a/v3/internal/templates/lit-ts/frontend/tsconfig.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "compilerOptions": { - "target": "ES2020", - "experimentalDecorators": true, - "useDefineForClassFields": false, - "module": "ESNext", - "lib": ["ES2020", "DOM", "DOM.Iterable"], - "skipLibCheck": true, - - /* Bundler mode */ - "moduleResolution": "bundler", - "allowImportingTsExtensions": true, - "resolveJsonModule": true, - "isolatedModules": true, - "noEmit": true, - - /* Linting */ - "strict": true, - "noUnusedLocals": true, - "noUnusedParameters": false, - "noImplicitAny": false, - "noFallthroughCasesInSwitch": true - }, - "include": ["src", "bindings"] -} diff --git a/v3/internal/templates/lit-ts/frontend/vite.config.ts b/v3/internal/templates/lit-ts/frontend/vite.config.ts deleted file mode 100644 index 56f2d6a8a..000000000 --- a/v3/internal/templates/lit-ts/frontend/vite.config.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { defineConfig } from "vite"; -import wails from "@wailsio/runtime/plugins/vite"; - -// https://vitejs.dev/config/ -export default defineConfig({ - plugins: [wails("./bindings")], -}); diff --git a/v3/internal/templates/lit-ts/template.json b/v3/internal/templates/lit-ts/template.json deleted file mode 100644 index ea0bf57f9..000000000 --- a/v3/internal/templates/lit-ts/template.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "name": "Lit + Vite (Typescript)", - "shortname": "lit-ts", - "author": "Lea Anthony", - "description": "Lit + TS + Vite development server", - "helpurl": "https://wails.io", - "version": "v0.0.1", - "schema": 3 -} \ No newline at end of file diff --git a/v3/internal/templates/lit/frontend/.gitignore b/v3/internal/templates/lit/frontend/.gitignore deleted file mode 100644 index a547bf36d..000000000 --- a/v3/internal/templates/lit/frontend/.gitignore +++ /dev/null @@ -1,24 +0,0 @@ -# Logs -logs -*.log -npm-debug.log* -yarn-debug.log* -yarn-error.log* -pnpm-debug.log* -lerna-debug.log* - -node_modules -dist -dist-ssr -*.local - -# Editor directories and files -.vscode/* -!.vscode/extensions.json -.idea -.DS_Store -*.suo -*.ntvs* -*.njsproj -*.sln -*.sw? diff --git a/v3/internal/templates/lit/frontend/index.html b/v3/internal/templates/lit/frontend/index.html deleted file mode 100644 index 7993cbcef..000000000 --- a/v3/internal/templates/lit/frontend/index.html +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - Wails + Lit - - - - - -

                    Wails + Lit

                    -
                    - - diff --git a/v3/internal/templates/lit/frontend/package.json b/v3/internal/templates/lit/frontend/package.json deleted file mode 100644 index ec30e751a..000000000 --- a/v3/internal/templates/lit/frontend/package.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "name": "frontend", - "private": true, - "version": "0.0.0", - "type": "module", - "scripts": { - "dev": "vite", - "build:dev": "vite build --minify false --mode development", - "build": "vite build --mode production", - "preview": "vite preview" - }, - "dependencies": { - "@wailsio/runtime": "latest", - "lit": "^3.1.0" - }, - "devDependencies": { - "vite": "^5.0.0" - } -} diff --git a/v3/internal/templates/lit/frontend/public/Inter-Medium.ttf b/v3/internal/templates/lit/frontend/public/Inter-Medium.ttf deleted file mode 100644 index a01f3777a..000000000 Binary files a/v3/internal/templates/lit/frontend/public/Inter-Medium.ttf and /dev/null differ diff --git a/v3/internal/templates/lit/frontend/public/lit.svg b/v3/internal/templates/lit/frontend/public/lit.svg deleted file mode 100644 index 4a9c1fe66..000000000 --- a/v3/internal/templates/lit/frontend/public/lit.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/v3/internal/templates/lit/frontend/public/style.css b/v3/internal/templates/lit/frontend/public/style.css deleted file mode 100644 index 10550a378..000000000 --- a/v3/internal/templates/lit/frontend/public/style.css +++ /dev/null @@ -1,58 +0,0 @@ -:root { - font-family: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", - "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", - sans-serif; - font-size: 16px; - line-height: 24px; - font-weight: 400; - color-scheme: light dark; - color: rgba(255, 255, 255, 0.87); - background-color: rgba(27, 38, 54, 1); - font-synthesis: none; - text-rendering: optimizeLegibility; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - -webkit-text-size-adjust: 100%; - user-select: none; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; -} - -@font-face { - font-family: "Inter"; - font-style: normal; - font-weight: 400; - src: local(""), - url("./Inter-Medium.ttf") format("truetype"); -} - - -body { - margin: 0; - display: flex; - place-items: center; - place-content: center; - min-width: 320px; - min-height: 100vh; -} - -h1 { - font-size: 3.2em; - line-height: 1.1; -} - -@media (prefers-color-scheme: light) { - :root { - color: #213547; - background-color: #ffffff; - } - - a:hover { - color: #747bff; - } - - button { - background-color: #f9f9f9; - } -} \ No newline at end of file diff --git a/v3/internal/templates/lit/frontend/public/wails.png b/v3/internal/templates/lit/frontend/public/wails.png deleted file mode 100644 index 8bdf42483..000000000 Binary files a/v3/internal/templates/lit/frontend/public/wails.png and /dev/null differ diff --git a/v3/internal/templates/lit/frontend/src/my-element.js.tmpl b/v3/internal/templates/lit/frontend/src/my-element.js.tmpl deleted file mode 100644 index db7763268..000000000 --- a/v3/internal/templates/lit/frontend/src/my-element.js.tmpl +++ /dev/null @@ -1,159 +0,0 @@ -import {css, html, LitElement} from 'lit' -import {Events} from "@wailsio/runtime"; -import {GreetService} from "../bindings/{{js .ModulePath}}"; - -export class MyElement extends LitElement { - static properties = { - name: {type: String}, - result: {type: String}, - time: {type: String}, - }; - - constructor() { - super(); - this.name = ''; - this.result = 'Please enter your name below 👇'; - this.time = 'Listening for Time event...'; - Events.On('time', (timeValue) => { - this.time = timeValue.data; - }); - } - - doGreet() { - let name = this.name; - if (!name) { - name = 'anonymous'; - } - GreetService.Greet(name).then((resultValue) => { - this.result = resultValue; - }).catch((err) => { - console.log(err); - }); - } - - render() { - return html` -
                    - - -
                    ${this.result}
                    -
                    -
                    - this.name = e.target.value} type="text" - autocomplete="off"/> - -
                    -
                    - -
                    - `; - } - - static styles = css` - :host { - max-width: 1280px; - margin: 0 auto; - padding: 2rem; - text-align: center; - } - - h3 { - font-size: 3em; - line-height: 1.1; - } - - a { - font-weight: 500; - color: #646cff; - text-decoration: inherit; - } - - a:hover { - color: #535bf2; - } - - button { - width: 60px; - height: 30px; - line-height: 30px; - border-radius: 3px; - border: none; - margin: 0 0 0 20px; - padding: 0 8px; - cursor: pointer; - } - - .container { - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; - } - - .logo { - height: 6em; - padding: 1.5em; - will-change: filter; - } - - .logo:hover { - filter: drop-shadow(0 0 2em #e80000aa); - } - - .logo.lit:hover { - filter: drop-shadow(0 0 2em #325cffaa); - } - - .result { - height: 20px; - line-height: 20px; - margin: 1.5rem auto; - text-align: center; - } - - .footer { - margin-top: 1rem; - align-content: center; - text-align: center; - } - - .input-box .btn:hover { - background-image: linear-gradient(to top, #cfd9df 0%, #e2ebf0 100%); - color: #333333; - } - - .input-box .input { - border: none; - border-radius: 3px; - outline: none; - height: 30px; - line-height: 30px; - padding: 0 10px; - color: black; - background-color: rgba(240, 240, 240, 1); - -webkit-font-smoothing: antialiased; - } - - .input-box .input:hover { - border: none; - background-color: rgba(255, 255, 255, 1); - } - - .input-box .input:focus { - border: none; - background-color: rgba(255, 255, 255, 1); - } - `; -} - -window.customElements.define('my-element', MyElement); diff --git a/v3/internal/templates/lit/frontend/src/vite-env.d.ts b/v3/internal/templates/lit/frontend/src/vite-env.d.ts deleted file mode 100644 index 11f02fe2a..000000000 --- a/v3/internal/templates/lit/frontend/src/vite-env.d.ts +++ /dev/null @@ -1 +0,0 @@ -/// diff --git a/v3/internal/templates/lit/frontend/tsconfig.json b/v3/internal/templates/lit/frontend/tsconfig.json deleted file mode 100644 index f103fe3a9..000000000 --- a/v3/internal/templates/lit/frontend/tsconfig.json +++ /dev/null @@ -1,25 +0,0 @@ -/** - * This file tells your IDE where the root of your JavaScript project is, and sets some - * options that it can use to provide autocompletion and other features. - */ -{ - "compilerOptions": { - "allowJs": true, - "moduleResolution": "bundler", - /** - * The target and module can be set to ESNext to allow writing modern JavaScript, - * and Vite will compile down to the level of "build.target" specified in the vite config file. - * Builds will error if you use a feature that cannot be compiled down to the target level. - */ - "target": "ESNext", - "module": "ESNext", - "resolveJsonModule": true, - /** - * Enable checkJs if you'd like type checking in `.js` files. - */ - "checkJs": false, - "strict": true, - "skipLibCheck": true, - }, - "include": ["src", "bindings"] -} diff --git a/v3/internal/templates/lit/frontend/vite.config.js b/v3/internal/templates/lit/frontend/vite.config.js deleted file mode 100644 index 56f2d6a8a..000000000 --- a/v3/internal/templates/lit/frontend/vite.config.js +++ /dev/null @@ -1,7 +0,0 @@ -import { defineConfig } from "vite"; -import wails from "@wailsio/runtime/plugins/vite"; - -// https://vitejs.dev/config/ -export default defineConfig({ - plugins: [wails("./bindings")], -}); diff --git a/v3/internal/templates/lit/template.json b/v3/internal/templates/lit/template.json deleted file mode 100644 index 9c3ba3c61..000000000 --- a/v3/internal/templates/lit/template.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "name": "Lit + Vite", - "shortname": "lit", - "author": "Lea Anthony", - "description": "Lit + Vite development server", - "helpurl": "https://wails.io", - "version": "v0.0.1", - "schema": 3 -} \ No newline at end of file diff --git a/v3/internal/templates/preact-ts/frontend/.gitignore b/v3/internal/templates/preact-ts/frontend/.gitignore deleted file mode 100644 index a547bf36d..000000000 --- a/v3/internal/templates/preact-ts/frontend/.gitignore +++ /dev/null @@ -1,24 +0,0 @@ -# Logs -logs -*.log -npm-debug.log* -yarn-debug.log* -yarn-error.log* -pnpm-debug.log* -lerna-debug.log* - -node_modules -dist -dist-ssr -*.local - -# Editor directories and files -.vscode/* -!.vscode/extensions.json -.idea -.DS_Store -*.suo -*.ntvs* -*.njsproj -*.sln -*.sw? diff --git a/v3/internal/templates/preact-ts/frontend/index.html b/v3/internal/templates/preact-ts/frontend/index.html deleted file mode 100644 index f4addcc25..000000000 --- a/v3/internal/templates/preact-ts/frontend/index.html +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - Wails + Preact - - -
                    - - - diff --git a/v3/internal/templates/preact-ts/frontend/package.json b/v3/internal/templates/preact-ts/frontend/package.json deleted file mode 100644 index b5dd75296..000000000 --- a/v3/internal/templates/preact-ts/frontend/package.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "name": "frontend", - "private": true, - "version": "0.0.0", - "type": "module", - "scripts": { - "dev": "vite", - "build:dev": "tsc && vite build --minify false --mode development", - "build": "tsc && vite build --mode production", - "preview": "vite preview" - }, - "dependencies": { - "@wailsio/runtime": "latest", - "preact": "^10.19.3" - }, - "devDependencies": { - "@preact/preset-vite": "^2.7.0", - "typescript": "^5.2.2", - "vite": "^5.0.8" - } -} diff --git a/v3/internal/templates/preact-ts/frontend/public/Inter-Medium.ttf b/v3/internal/templates/preact-ts/frontend/public/Inter-Medium.ttf deleted file mode 100644 index a01f3777a..000000000 Binary files a/v3/internal/templates/preact-ts/frontend/public/Inter-Medium.ttf and /dev/null differ diff --git a/v3/internal/templates/preact-ts/frontend/public/preact.svg b/v3/internal/templates/preact-ts/frontend/public/preact.svg deleted file mode 100644 index 908f17def..000000000 --- a/v3/internal/templates/preact-ts/frontend/public/preact.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/v3/internal/templates/preact-ts/frontend/public/style.css b/v3/internal/templates/preact-ts/frontend/public/style.css deleted file mode 100644 index c4f073382..000000000 --- a/v3/internal/templates/preact-ts/frontend/public/style.css +++ /dev/null @@ -1,158 +0,0 @@ -:root { - font-family: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", - "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", - sans-serif; - font-size: 16px; - line-height: 24px; - font-weight: 400; - color-scheme: light dark; - color: rgba(255, 255, 255, 0.87); - background-color: rgba(27, 38, 54, 1); - font-synthesis: none; - text-rendering: optimizeLegibility; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - -webkit-text-size-adjust: 100%; - user-select: none; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; -} - -@font-face { - font-family: "Inter"; - font-style: normal; - font-weight: 400; - src: local(""), - url("./Inter-Medium.ttf") format("truetype"); -} - -h3 { - font-size: 3em; - line-height: 1.1; -} - -a { - font-weight: 500; - color: #646cff; - text-decoration: inherit; -} - -a:hover { - color: #535bf2; -} - -button { - width: 60px; - height: 30px; - line-height: 30px; - border-radius: 3px; - border: none; - margin: 0 0 0 20px; - padding: 0 8px; - cursor: pointer; -} - -.result { - height: 20px; - line-height: 20px; -} - -body { - margin: 0; - display: flex; - place-items: center; - place-content: center; - min-width: 320px; - min-height: 100vh; -} - -.container { - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; -} - -h1 { - font-size: 3.2em; - line-height: 1.1; -} - -#app { - max-width: 1280px; - margin: 0 auto; - padding: 2rem; - text-align: center; -} - -.logo { - height: 6em; - padding: 1.5em; - will-change: filter; -} - -.logo:hover { - filter: drop-shadow(0 0 2em #e80000aa); -} - -.logo.preact:hover { - filter: drop-shadow(0 0 2em #673ab8aa); -} - - -.result { - height: 20px; - line-height: 20px; - margin: 1.5rem auto; - text-align: center; -} - -.footer { - margin-top: 1rem; - align-content: center; - text-align: center; -} - -@media (prefers-color-scheme: light) { - :root { - color: #213547; - background-color: #ffffff; - } - - a:hover { - color: #747bff; - } - - button { - background-color: #f9f9f9; - } -} - - -.input-box .btn:hover { - background-image: linear-gradient(to top, #cfd9df 0%, #e2ebf0 100%); - color: #333333; -} - -.input-box .input { - border: none; - border-radius: 3px; - outline: none; - height: 30px; - line-height: 30px; - padding: 0 10px; - color: black; - background-color: rgba(240, 240, 240, 1); - -webkit-font-smoothing: antialiased; -} - -.input-box .input:hover { - border: none; - background-color: rgba(255, 255, 255, 1); -} - -.input-box .input:focus { - border: none; - background-color: rgba(255, 255, 255, 1); -} \ No newline at end of file diff --git a/v3/internal/templates/preact-ts/frontend/public/wails.png b/v3/internal/templates/preact-ts/frontend/public/wails.png deleted file mode 100644 index 8bdf42483..000000000 Binary files a/v3/internal/templates/preact-ts/frontend/public/wails.png and /dev/null differ diff --git a/v3/internal/templates/preact-ts/frontend/src/app.tsx.tmpl b/v3/internal/templates/preact-ts/frontend/src/app.tsx.tmpl deleted file mode 100644 index f8e992d34..000000000 --- a/v3/internal/templates/preact-ts/frontend/src/app.tsx.tmpl +++ /dev/null @@ -1,55 +0,0 @@ -import {useEffect, useState} from 'preact/hooks' -import {Events} from "@wailsio/runtime"; -import {GreetService} from "../bindings/{{js .ModulePath}}"; - -export function App() { - const [name, setName] = useState(''); - const [result, setResult] = useState('Please enter your name below 👇'); - const [time, setTime] = useState('Listening for Time event...'); - - const doGreet = (): void => { - let localName = name; - if (!localName) { - localName = 'anonymous'; - } - GreetService.Greet(localName).then((resultValue: string) => { - setResult(resultValue); - }).catch((err: any) => { - console.log(err); - }); - } - - useEffect(() => { - Events.On('time', (timeValue: any) => { - setTime(timeValue.data); - }); - }, []); - - return ( - <> -
                    - -

                    Wails + Preact

                    -
                    {result}
                    -
                    -
                    - setName(e.currentTarget.value)} - type="text" autocomplete="off"/> - -
                    -
                    -
                    -

                    Click on the Wails logo to learn more

                    -

                    {time}

                    -
                    -
                    - - ) -} diff --git a/v3/internal/templates/preact-ts/frontend/src/main.tsx b/v3/internal/templates/preact-ts/frontend/src/main.tsx deleted file mode 100644 index 2af1859fe..000000000 --- a/v3/internal/templates/preact-ts/frontend/src/main.tsx +++ /dev/null @@ -1,4 +0,0 @@ -import { render } from 'preact' -import { App } from './app' - -render(, document.getElementById('app') as HTMLElement) diff --git a/v3/internal/templates/preact-ts/frontend/src/vite-env.d.ts b/v3/internal/templates/preact-ts/frontend/src/vite-env.d.ts deleted file mode 100644 index 11f02fe2a..000000000 --- a/v3/internal/templates/preact-ts/frontend/src/vite-env.d.ts +++ /dev/null @@ -1 +0,0 @@ -/// diff --git a/v3/internal/templates/preact-ts/frontend/tsconfig.json b/v3/internal/templates/preact-ts/frontend/tsconfig.json deleted file mode 100644 index f109102b4..000000000 --- a/v3/internal/templates/preact-ts/frontend/tsconfig.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "compilerOptions": { - "target": "ES2020", - "useDefineForClassFields": true, - "module": "ESNext", - "lib": ["ES2020", "DOM", "DOM.Iterable"], - "skipLibCheck": true, - "paths": { - "react": ["./node_modules/preact/compat/"], - "react-dom": ["./node_modules/preact/compat/"] - }, - - /* Bundler mode */ - "moduleResolution": "bundler", - "allowImportingTsExtensions": true, - "resolveJsonModule": true, - "isolatedModules": true, - "noEmit": true, - "jsx": "react-jsx", - "jsxImportSource": "preact", - - /* Linting */ - "strict": true, - "noUnusedLocals": true, - "noUnusedParameters": false, - "noImplicitAny": false, - "noFallthroughCasesInSwitch": true - }, - "include": ["src", "bindings"], -} diff --git a/v3/internal/templates/preact-ts/frontend/vite.config.ts b/v3/internal/templates/preact-ts/frontend/vite.config.ts deleted file mode 100644 index 51b2dce5c..000000000 --- a/v3/internal/templates/preact-ts/frontend/vite.config.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { defineConfig } from "vite"; -import preact from "@preact/preset-vite"; -import wails from "@wailsio/runtime/plugins/vite"; - -// https://vitejs.dev/config/ -export default defineConfig({ - plugins: [preact(), wails("./bindings")], -}); diff --git a/v3/internal/templates/preact-ts/template.json b/v3/internal/templates/preact-ts/template.json deleted file mode 100644 index e2b867ebc..000000000 --- a/v3/internal/templates/preact-ts/template.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "name": "Preact + Vite (Typescript)", - "shortname": "preact-ts", - "author": "Lea Anthony", - "description": "Preact + TS + Vite development server", - "helpurl": "https://wails.io", - "version": "v0.0.1", - "schema": 3 -} \ No newline at end of file diff --git a/v3/internal/templates/preact/frontend/.gitignore b/v3/internal/templates/preact/frontend/.gitignore deleted file mode 100644 index a547bf36d..000000000 --- a/v3/internal/templates/preact/frontend/.gitignore +++ /dev/null @@ -1,24 +0,0 @@ -# Logs -logs -*.log -npm-debug.log* -yarn-debug.log* -yarn-error.log* -pnpm-debug.log* -lerna-debug.log* - -node_modules -dist -dist-ssr -*.local - -# Editor directories and files -.vscode/* -!.vscode/extensions.json -.idea -.DS_Store -*.suo -*.ntvs* -*.njsproj -*.sln -*.sw? diff --git a/v3/internal/templates/preact/frontend/index.html b/v3/internal/templates/preact/frontend/index.html deleted file mode 100644 index 3657fd5ef..000000000 --- a/v3/internal/templates/preact/frontend/index.html +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - Wails + Preact - - -
                    - - - diff --git a/v3/internal/templates/preact/frontend/package.json b/v3/internal/templates/preact/frontend/package.json deleted file mode 100644 index 863d1fc23..000000000 --- a/v3/internal/templates/preact/frontend/package.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "name": "frontend", - "private": true, - "version": "0.0.0", - "type": "module", - "scripts": { - "dev": "vite", - "build:dev": "vite build --minify false --mode development", - "build": "vite build --mode production", - "preview": "vite preview" - }, - "dependencies": { - "@wailsio/runtime": "latest", - "preact": "^10.19.3" - }, - "devDependencies": { - "@preact/preset-vite": "^2.7.0", - "vite": "^5.0.8" - } -} diff --git a/v3/internal/templates/preact/frontend/public/Inter-Medium.ttf b/v3/internal/templates/preact/frontend/public/Inter-Medium.ttf deleted file mode 100644 index a01f3777a..000000000 Binary files a/v3/internal/templates/preact/frontend/public/Inter-Medium.ttf and /dev/null differ diff --git a/v3/internal/templates/preact/frontend/public/preact.svg b/v3/internal/templates/preact/frontend/public/preact.svg deleted file mode 100644 index 908f17def..000000000 --- a/v3/internal/templates/preact/frontend/public/preact.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/v3/internal/templates/preact/frontend/public/style.css b/v3/internal/templates/preact/frontend/public/style.css deleted file mode 100644 index c4f073382..000000000 --- a/v3/internal/templates/preact/frontend/public/style.css +++ /dev/null @@ -1,158 +0,0 @@ -:root { - font-family: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", - "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", - sans-serif; - font-size: 16px; - line-height: 24px; - font-weight: 400; - color-scheme: light dark; - color: rgba(255, 255, 255, 0.87); - background-color: rgba(27, 38, 54, 1); - font-synthesis: none; - text-rendering: optimizeLegibility; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - -webkit-text-size-adjust: 100%; - user-select: none; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; -} - -@font-face { - font-family: "Inter"; - font-style: normal; - font-weight: 400; - src: local(""), - url("./Inter-Medium.ttf") format("truetype"); -} - -h3 { - font-size: 3em; - line-height: 1.1; -} - -a { - font-weight: 500; - color: #646cff; - text-decoration: inherit; -} - -a:hover { - color: #535bf2; -} - -button { - width: 60px; - height: 30px; - line-height: 30px; - border-radius: 3px; - border: none; - margin: 0 0 0 20px; - padding: 0 8px; - cursor: pointer; -} - -.result { - height: 20px; - line-height: 20px; -} - -body { - margin: 0; - display: flex; - place-items: center; - place-content: center; - min-width: 320px; - min-height: 100vh; -} - -.container { - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; -} - -h1 { - font-size: 3.2em; - line-height: 1.1; -} - -#app { - max-width: 1280px; - margin: 0 auto; - padding: 2rem; - text-align: center; -} - -.logo { - height: 6em; - padding: 1.5em; - will-change: filter; -} - -.logo:hover { - filter: drop-shadow(0 0 2em #e80000aa); -} - -.logo.preact:hover { - filter: drop-shadow(0 0 2em #673ab8aa); -} - - -.result { - height: 20px; - line-height: 20px; - margin: 1.5rem auto; - text-align: center; -} - -.footer { - margin-top: 1rem; - align-content: center; - text-align: center; -} - -@media (prefers-color-scheme: light) { - :root { - color: #213547; - background-color: #ffffff; - } - - a:hover { - color: #747bff; - } - - button { - background-color: #f9f9f9; - } -} - - -.input-box .btn:hover { - background-image: linear-gradient(to top, #cfd9df 0%, #e2ebf0 100%); - color: #333333; -} - -.input-box .input { - border: none; - border-radius: 3px; - outline: none; - height: 30px; - line-height: 30px; - padding: 0 10px; - color: black; - background-color: rgba(240, 240, 240, 1); - -webkit-font-smoothing: antialiased; -} - -.input-box .input:hover { - border: none; - background-color: rgba(255, 255, 255, 1); -} - -.input-box .input:focus { - border: none; - background-color: rgba(255, 255, 255, 1); -} \ No newline at end of file diff --git a/v3/internal/templates/preact/frontend/public/wails.png b/v3/internal/templates/preact/frontend/public/wails.png deleted file mode 100644 index 8bdf42483..000000000 Binary files a/v3/internal/templates/preact/frontend/public/wails.png and /dev/null differ diff --git a/v3/internal/templates/preact/frontend/src/app.jsx.tmpl b/v3/internal/templates/preact/frontend/src/app.jsx.tmpl deleted file mode 100644 index 45102e3ef..000000000 --- a/v3/internal/templates/preact/frontend/src/app.jsx.tmpl +++ /dev/null @@ -1,52 +0,0 @@ -import { useState, useEffect } from 'preact/hooks' -import {Events} from "@wailsio/runtime"; -import {GreetService} from "../bindings/{{js .ModulePath}}"; - -export function App() { - const [name, setName] = useState(''); - const [result, setResult] = useState('Please enter your name below 👇'); - const [time, setTime] = useState('Listening for Time event...'); - - const doGreet = () => { - let localName = name; - if (!localName) { - localName = 'anonymous'; - } - GreetService.Greet(localName).then((resultValue) => { - setResult(resultValue); - }).catch((err) => { - console.log(err); - }); - } - - useEffect(() => { - Events.On('time', (timeValue) => { - setTime(timeValue.data); - }); - }, []); - - return ( -
                    - -

                    Wails + Preact

                    -
                    {result}
                    -
                    -
                    - setName(e.target.value)} type="text" autoComplete="off"/> - -
                    -
                    -
                    -

                    Click on the Wails logo to learn more

                    -

                    {time}

                    -
                    -
                    - ) -} diff --git a/v3/internal/templates/preact/frontend/src/main.jsx b/v3/internal/templates/preact/frontend/src/main.jsx deleted file mode 100644 index 5867d2a14..000000000 --- a/v3/internal/templates/preact/frontend/src/main.jsx +++ /dev/null @@ -1,4 +0,0 @@ -import { render } from 'preact' -import { App } from './app' - -render(, document.getElementById('app')) diff --git a/v3/internal/templates/preact/frontend/src/vite-env.d.ts b/v3/internal/templates/preact/frontend/src/vite-env.d.ts deleted file mode 100644 index 11f02fe2a..000000000 --- a/v3/internal/templates/preact/frontend/src/vite-env.d.ts +++ /dev/null @@ -1 +0,0 @@ -/// diff --git a/v3/internal/templates/preact/frontend/tsconfig.json b/v3/internal/templates/preact/frontend/tsconfig.json deleted file mode 100644 index 2be606f10..000000000 --- a/v3/internal/templates/preact/frontend/tsconfig.json +++ /dev/null @@ -1,25 +0,0 @@ -/** - * This file tells your IDE where the root of your JavaScript project is, and sets some - * options that it can use to provide autocompletion and other features. - */ -{ - "compilerOptions": { - "allowJs": true, - "moduleResolution": "bundler", - /** - * The target and module can be set to ESNext to allow writing modern JavaScript, - * and Vite will compile down to the level of "build.target" specified in the vite config file. - * Builds will error if you use a feature that cannot be compiled down to the target level. - */ - "target": "ESNext", - "module": "ESNext", - "resolveJsonModule": true, - /** - * Enable checkJs if you'd like type checking in `.js(x)` files. - */ - "checkJs": false, - "strict": true, - "skipLibCheck": true, - }, - "include": ["src", "bindings"] -} diff --git a/v3/internal/templates/preact/frontend/vite.config.js b/v3/internal/templates/preact/frontend/vite.config.js deleted file mode 100644 index 51b2dce5c..000000000 --- a/v3/internal/templates/preact/frontend/vite.config.js +++ /dev/null @@ -1,8 +0,0 @@ -import { defineConfig } from "vite"; -import preact from "@preact/preset-vite"; -import wails from "@wailsio/runtime/plugins/vite"; - -// https://vitejs.dev/config/ -export default defineConfig({ - plugins: [preact(), wails("./bindings")], -}); diff --git a/v3/internal/templates/preact/template.json b/v3/internal/templates/preact/template.json deleted file mode 100644 index c2e58d779..000000000 --- a/v3/internal/templates/preact/template.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "name": "Preact + Vite", - "shortname": "preact", - "author": "Lea Anthony", - "description": "Preact + Vite development server", - "helpurl": "https://wails.io", - "version": "v0.0.1", - "schema": 3 -} \ No newline at end of file diff --git a/v3/internal/templates/qwik-ts/frontend/.gitignore b/v3/internal/templates/qwik-ts/frontend/.gitignore deleted file mode 100644 index a547bf36d..000000000 --- a/v3/internal/templates/qwik-ts/frontend/.gitignore +++ /dev/null @@ -1,24 +0,0 @@ -# Logs -logs -*.log -npm-debug.log* -yarn-debug.log* -yarn-error.log* -pnpm-debug.log* -lerna-debug.log* - -node_modules -dist -dist-ssr -*.local - -# Editor directories and files -.vscode/* -!.vscode/extensions.json -.idea -.DS_Store -*.suo -*.ntvs* -*.njsproj -*.sln -*.sw? diff --git a/v3/internal/templates/qwik-ts/frontend/index.html b/v3/internal/templates/qwik-ts/frontend/index.html deleted file mode 100644 index b45ac182d..000000000 --- a/v3/internal/templates/qwik-ts/frontend/index.html +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - Vite + Qwik - - -
                    - - - diff --git a/v3/internal/templates/qwik-ts/frontend/package.json b/v3/internal/templates/qwik-ts/frontend/package.json deleted file mode 100644 index b3f359a6b..000000000 --- a/v3/internal/templates/qwik-ts/frontend/package.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "name": "quik-ts-latest", - "private": true, - "version": "0.0.0", - "type": "module", - "scripts": { - "dev": "vite", - "build:dev": "tsc && vite build --minify false --mode development", - "build": "tsc && vite build --mode production", - "preview": "vite preview" - }, - "dependencies": { - "@builder.io/qwik": "^1.3.0", - "@wailsio/runtime": "latest" - }, - "devDependencies": { - "typescript": "^5.2.2", - "vite": "^5.0.8" - } -} diff --git a/v3/internal/templates/qwik-ts/frontend/public/Inter-Medium.ttf b/v3/internal/templates/qwik-ts/frontend/public/Inter-Medium.ttf deleted file mode 100644 index a01f3777a..000000000 Binary files a/v3/internal/templates/qwik-ts/frontend/public/Inter-Medium.ttf and /dev/null differ diff --git a/v3/internal/templates/qwik-ts/frontend/public/qwik.svg b/v3/internal/templates/qwik-ts/frontend/public/qwik.svg deleted file mode 100644 index 08a46e2da..000000000 --- a/v3/internal/templates/qwik-ts/frontend/public/qwik.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/v3/internal/templates/qwik-ts/frontend/public/style.css b/v3/internal/templates/qwik-ts/frontend/public/style.css deleted file mode 100644 index c1d8d1a2e..000000000 --- a/v3/internal/templates/qwik-ts/frontend/public/style.css +++ /dev/null @@ -1,157 +0,0 @@ -:root { - font-family: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", - "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", - sans-serif; - font-size: 16px; - line-height: 24px; - font-weight: 400; - color-scheme: light dark; - color: rgba(255, 255, 255, 0.87); - background-color: rgba(27, 38, 54, 1); - font-synthesis: none; - text-rendering: optimizeLegibility; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - -webkit-text-size-adjust: 100%; - user-select: none; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; -} - -@font-face { - font-family: "Inter"; - font-style: normal; - font-weight: 400; - src: local(""), - url("./Inter-Medium.ttf") format("truetype"); -} - -h3 { - font-size: 3em; - line-height: 1.1; -} - -a { - font-weight: 500; - color: #646cff; - text-decoration: inherit; -} - -a:hover { - color: #535bf2; -} - -button { - width: 60px; - height: 30px; - line-height: 30px; - border-radius: 3px; - border: none; - margin: 0 0 0 20px; - padding: 0 8px; - cursor: pointer; -} - -.result { - height: 20px; - line-height: 20px; -} - -body { - margin: 0; - display: flex; - place-items: center; - place-content: center; - min-width: 320px; - min-height: 100vh; -} - -.container { - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; -} - -h1 { - font-size: 3.2em; - line-height: 1.1; -} - -#app { - max-width: 1280px; - margin: 0 auto; - padding: 2rem; - text-align: center; -} - -.logo { - height: 6em; - padding: 1.5em; - will-change: filter; -} - -.logo:hover { - filter: drop-shadow(0 0 2em #e80000aa); -} - -.logo.qwik:hover { - filter: drop-shadow(0 0 2em #673ab8aa); -} - -.result { - height: 20px; - line-height: 20px; - margin: 1.5rem auto; - text-align: center; -} - -.footer { - margin-top: 1rem; - align-content: center; - text-align: center; -} - -@media (prefers-color-scheme: light) { - :root { - color: #213547; - background-color: #ffffff; - } - - a:hover { - color: #747bff; - } - - button { - background-color: #f9f9f9; - } -} - - -.input-box .btn:hover { - background-image: linear-gradient(to top, #cfd9df 0%, #e2ebf0 100%); - color: #333333; -} - -.input-box .input { - border: none; - border-radius: 3px; - outline: none; - height: 30px; - line-height: 30px; - padding: 0 10px; - color: black; - background-color: rgba(240, 240, 240, 1); - -webkit-font-smoothing: antialiased; -} - -.input-box .input:hover { - border: none; - background-color: rgba(255, 255, 255, 1); -} - -.input-box .input:focus { - border: none; - background-color: rgba(255, 255, 255, 1); -} \ No newline at end of file diff --git a/v3/internal/templates/qwik-ts/frontend/public/wails.png b/v3/internal/templates/qwik-ts/frontend/public/wails.png deleted file mode 100644 index 8bdf42483..000000000 Binary files a/v3/internal/templates/qwik-ts/frontend/public/wails.png and /dev/null differ diff --git a/v3/internal/templates/qwik-ts/frontend/src/app.tsx.tmpl b/v3/internal/templates/qwik-ts/frontend/src/app.tsx.tmpl deleted file mode 100644 index 89f38eb25..000000000 --- a/v3/internal/templates/qwik-ts/frontend/src/app.tsx.tmpl +++ /dev/null @@ -1,54 +0,0 @@ -import { component$, useSignal, useVisibleTask$ } from '@builder.io/qwik' -import {Events, WML} from "@wailsio/runtime"; -import {GreetService} from "../bindings/{{js .ModulePath}}"; - -export const App = component$(() => { - const name = useSignal(''); - const result = useSignal('Please enter your name below 👇'); - const time = useSignal('Listening for Time event...'); - - const doGreet = () => { - let localName = name.value; - if (!localName) { - localName = 'anonymous'; - } - GreetService.Greet(localName).then((resultValue: string) => { - result.value = resultValue; - }).catch((err: any) => { - console.log(err); - }); - } - - useVisibleTask$(() => { - Events.On('time', (timeValue: any) => { - time.value = timeValue.data; - }); - // Reload WML so it picks up the wml tags - WML.Reload(); - }); - - return ( -
                    - -

                    Wails + Qwik

                    -
                    {result.value}
                    -
                    -
                    - name.value = (e.target as HTMLInputElement).value} type="text" autocomplete="off"/> - -
                    -
                    - -
                    - ) -}) diff --git a/v3/internal/templates/qwik-ts/frontend/src/main.tsx b/v3/internal/templates/qwik-ts/frontend/src/main.tsx deleted file mode 100644 index 2c779e49e..000000000 --- a/v3/internal/templates/qwik-ts/frontend/src/main.tsx +++ /dev/null @@ -1,6 +0,0 @@ -import '@builder.io/qwik/qwikloader.js' - -import { render } from '@builder.io/qwik' -import { App } from './app.tsx' - -render(document.getElementById('app') as HTMLElement, ) diff --git a/v3/internal/templates/qwik-ts/frontend/src/vite-env.d.ts b/v3/internal/templates/qwik-ts/frontend/src/vite-env.d.ts deleted file mode 100644 index 11f02fe2a..000000000 --- a/v3/internal/templates/qwik-ts/frontend/src/vite-env.d.ts +++ /dev/null @@ -1 +0,0 @@ -/// diff --git a/v3/internal/templates/qwik-ts/frontend/tsconfig.json b/v3/internal/templates/qwik-ts/frontend/tsconfig.json deleted file mode 100644 index 2c7f9d75e..000000000 --- a/v3/internal/templates/qwik-ts/frontend/tsconfig.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "compilerOptions": { - "target": "ES2020", - "useDefineForClassFields": true, - "module": "ESNext", - "lib": ["ES2020", "DOM", "DOM.Iterable"], - "skipLibCheck": true, - - /* Bundler mode */ - "moduleResolution": "bundler", - "allowImportingTsExtensions": true, - "resolveJsonModule": true, - "isolatedModules": true, - "noEmit": true, - "jsx": "react-jsx", - "jsxImportSource": "@builder.io/qwik", - - /* Linting */ - "strict": true, - "noUnusedLocals": true, - "noUnusedParameters": false, - "noImplicitAny": false, - "noFallthroughCasesInSwitch": true - }, - "include": ["src", "bindings"], -} diff --git a/v3/internal/templates/qwik-ts/frontend/vite.config.ts b/v3/internal/templates/qwik-ts/frontend/vite.config.ts deleted file mode 100644 index 3ea402c7b..000000000 --- a/v3/internal/templates/qwik-ts/frontend/vite.config.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { defineConfig } from "vite"; -import { qwikVite } from "@builder.io/qwik/optimizer"; -import wails from "@wailsio/runtime/plugins/vite"; - -// https://vitejs.dev/config/ -export default defineConfig({ - plugins: [ - qwikVite({ - csr: true, - }), - wails("./bindings"), - ], -}); diff --git a/v3/internal/templates/qwik-ts/template.json b/v3/internal/templates/qwik-ts/template.json deleted file mode 100644 index fd27f0b0a..000000000 --- a/v3/internal/templates/qwik-ts/template.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "name": "Qwik + TS + Vite", - "shortname": "qwik", - "author": "Lea Anthony", - "description": "Qwik + TS + Vite development server", - "helpurl": "https://wails.io", - "version": "v0.0.1", - "schema": 3 -} \ No newline at end of file diff --git a/v3/internal/templates/qwik/frontend/.gitignore b/v3/internal/templates/qwik/frontend/.gitignore deleted file mode 100644 index a547bf36d..000000000 --- a/v3/internal/templates/qwik/frontend/.gitignore +++ /dev/null @@ -1,24 +0,0 @@ -# Logs -logs -*.log -npm-debug.log* -yarn-debug.log* -yarn-error.log* -pnpm-debug.log* -lerna-debug.log* - -node_modules -dist -dist-ssr -*.local - -# Editor directories and files -.vscode/* -!.vscode/extensions.json -.idea -.DS_Store -*.suo -*.ntvs* -*.njsproj -*.sln -*.sw? diff --git a/v3/internal/templates/qwik/frontend/index.html b/v3/internal/templates/qwik/frontend/index.html deleted file mode 100644 index 7c6c2a226..000000000 --- a/v3/internal/templates/qwik/frontend/index.html +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - Vite + Qwik - - -
                    - - - diff --git a/v3/internal/templates/qwik/frontend/package.json b/v3/internal/templates/qwik/frontend/package.json deleted file mode 100644 index 3139e426b..000000000 --- a/v3/internal/templates/qwik/frontend/package.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "name": "qwik-latest", - "private": true, - "version": "0.0.0", - "type": "module", - "scripts": { - "dev": "vite", - "build:dev": "vite build --minify false --mode development", - "build": "vite build --mode production", - "preview": "vite preview" - }, - "dependencies": { - "@builder.io/qwik": "^1.3.0", - "@wailsio/runtime": "latest" - }, - "devDependencies": { - "typescript": "^5.2.2", - "vite": "^5.0.8" - } -} diff --git a/v3/internal/templates/qwik/frontend/public/Inter-Medium.ttf b/v3/internal/templates/qwik/frontend/public/Inter-Medium.ttf deleted file mode 100644 index a01f3777a..000000000 Binary files a/v3/internal/templates/qwik/frontend/public/Inter-Medium.ttf and /dev/null differ diff --git a/v3/internal/templates/qwik/frontend/public/qwik.svg b/v3/internal/templates/qwik/frontend/public/qwik.svg deleted file mode 100644 index 08a46e2da..000000000 --- a/v3/internal/templates/qwik/frontend/public/qwik.svg +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/v3/internal/templates/qwik/frontend/public/style.css b/v3/internal/templates/qwik/frontend/public/style.css deleted file mode 100644 index c1d8d1a2e..000000000 --- a/v3/internal/templates/qwik/frontend/public/style.css +++ /dev/null @@ -1,157 +0,0 @@ -:root { - font-family: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", - "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", - sans-serif; - font-size: 16px; - line-height: 24px; - font-weight: 400; - color-scheme: light dark; - color: rgba(255, 255, 255, 0.87); - background-color: rgba(27, 38, 54, 1); - font-synthesis: none; - text-rendering: optimizeLegibility; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - -webkit-text-size-adjust: 100%; - user-select: none; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; -} - -@font-face { - font-family: "Inter"; - font-style: normal; - font-weight: 400; - src: local(""), - url("./Inter-Medium.ttf") format("truetype"); -} - -h3 { - font-size: 3em; - line-height: 1.1; -} - -a { - font-weight: 500; - color: #646cff; - text-decoration: inherit; -} - -a:hover { - color: #535bf2; -} - -button { - width: 60px; - height: 30px; - line-height: 30px; - border-radius: 3px; - border: none; - margin: 0 0 0 20px; - padding: 0 8px; - cursor: pointer; -} - -.result { - height: 20px; - line-height: 20px; -} - -body { - margin: 0; - display: flex; - place-items: center; - place-content: center; - min-width: 320px; - min-height: 100vh; -} - -.container { - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; -} - -h1 { - font-size: 3.2em; - line-height: 1.1; -} - -#app { - max-width: 1280px; - margin: 0 auto; - padding: 2rem; - text-align: center; -} - -.logo { - height: 6em; - padding: 1.5em; - will-change: filter; -} - -.logo:hover { - filter: drop-shadow(0 0 2em #e80000aa); -} - -.logo.qwik:hover { - filter: drop-shadow(0 0 2em #673ab8aa); -} - -.result { - height: 20px; - line-height: 20px; - margin: 1.5rem auto; - text-align: center; -} - -.footer { - margin-top: 1rem; - align-content: center; - text-align: center; -} - -@media (prefers-color-scheme: light) { - :root { - color: #213547; - background-color: #ffffff; - } - - a:hover { - color: #747bff; - } - - button { - background-color: #f9f9f9; - } -} - - -.input-box .btn:hover { - background-image: linear-gradient(to top, #cfd9df 0%, #e2ebf0 100%); - color: #333333; -} - -.input-box .input { - border: none; - border-radius: 3px; - outline: none; - height: 30px; - line-height: 30px; - padding: 0 10px; - color: black; - background-color: rgba(240, 240, 240, 1); - -webkit-font-smoothing: antialiased; -} - -.input-box .input:hover { - border: none; - background-color: rgba(255, 255, 255, 1); -} - -.input-box .input:focus { - border: none; - background-color: rgba(255, 255, 255, 1); -} \ No newline at end of file diff --git a/v3/internal/templates/qwik/frontend/public/wails.png b/v3/internal/templates/qwik/frontend/public/wails.png deleted file mode 100644 index 8bdf42483..000000000 Binary files a/v3/internal/templates/qwik/frontend/public/wails.png and /dev/null differ diff --git a/v3/internal/templates/qwik/frontend/src/app.jsx.tmpl b/v3/internal/templates/qwik/frontend/src/app.jsx.tmpl deleted file mode 100644 index 004a54ace..000000000 --- a/v3/internal/templates/qwik/frontend/src/app.jsx.tmpl +++ /dev/null @@ -1,54 +0,0 @@ -import { component$, useSignal, useVisibleTask$ } from '@builder.io/qwik' -import {Events, WML} from "@wailsio/runtime"; -import {GreetService} from "../bindings/{{js .ModulePath}}"; - -export const App = component$(() => { - const name = useSignal(''); - const result = useSignal('Please enter your name below 👇'); - const time = useSignal('Listening for Time event...'); - - const doGreet = () => { - let localName = name.value; - if (!localName) { - localName = 'anonymous'; - } - GreetService.Greet(localName).then((resultValue) => { - result.value = resultValue; - }).catch((err) => { - console.log(err); - }); - } - - useVisibleTask$(() => { - Events.On('time', (timeValue) => { - time.value = timeValue.data; - }); - // Reload WML so it picks up the wml tags - WML.Reload(); - }); - - return ( -
                    - -

                    Wails + Qwik

                    -
                    {result.value}
                    -
                    -
                    - name.value = e.target.value} type="text" autocomplete="off"/> - -
                    -
                    - -
                    - ) -}) diff --git a/v3/internal/templates/qwik/frontend/src/main.jsx b/v3/internal/templates/qwik/frontend/src/main.jsx deleted file mode 100644 index 93884c8df..000000000 --- a/v3/internal/templates/qwik/frontend/src/main.jsx +++ /dev/null @@ -1,6 +0,0 @@ -import '@builder.io/qwik/qwikloader.js' - -import { render } from '@builder.io/qwik' -import { App } from './app.jsx.tmpl' - -render(document.getElementById('app'), ) diff --git a/v3/internal/templates/qwik/frontend/src/vite-env.d.ts b/v3/internal/templates/qwik/frontend/src/vite-env.d.ts deleted file mode 100644 index 11f02fe2a..000000000 --- a/v3/internal/templates/qwik/frontend/src/vite-env.d.ts +++ /dev/null @@ -1 +0,0 @@ -/// diff --git a/v3/internal/templates/qwik/frontend/tsconfig.json b/v3/internal/templates/qwik/frontend/tsconfig.json deleted file mode 100644 index 2be606f10..000000000 --- a/v3/internal/templates/qwik/frontend/tsconfig.json +++ /dev/null @@ -1,25 +0,0 @@ -/** - * This file tells your IDE where the root of your JavaScript project is, and sets some - * options that it can use to provide autocompletion and other features. - */ -{ - "compilerOptions": { - "allowJs": true, - "moduleResolution": "bundler", - /** - * The target and module can be set to ESNext to allow writing modern JavaScript, - * and Vite will compile down to the level of "build.target" specified in the vite config file. - * Builds will error if you use a feature that cannot be compiled down to the target level. - */ - "target": "ESNext", - "module": "ESNext", - "resolveJsonModule": true, - /** - * Enable checkJs if you'd like type checking in `.js(x)` files. - */ - "checkJs": false, - "strict": true, - "skipLibCheck": true, - }, - "include": ["src", "bindings"] -} diff --git a/v3/internal/templates/qwik/frontend/vite.config.js b/v3/internal/templates/qwik/frontend/vite.config.js deleted file mode 100644 index 3ea402c7b..000000000 --- a/v3/internal/templates/qwik/frontend/vite.config.js +++ /dev/null @@ -1,13 +0,0 @@ -import { defineConfig } from "vite"; -import { qwikVite } from "@builder.io/qwik/optimizer"; -import wails from "@wailsio/runtime/plugins/vite"; - -// https://vitejs.dev/config/ -export default defineConfig({ - plugins: [ - qwikVite({ - csr: true, - }), - wails("./bindings"), - ], -}); diff --git a/v3/internal/templates/qwik/template.json b/v3/internal/templates/qwik/template.json deleted file mode 100644 index 2677702bf..000000000 --- a/v3/internal/templates/qwik/template.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "name": "Qwik + Vite", - "shortname": "qwik", - "author": "Lea Anthony", - "description": "Qwik + Vite development server", - "helpurl": "https://wails.io", - "version": "v0.0.1", - "schema": 3 -} \ No newline at end of file diff --git a/v3/internal/templates/react-swc-ts/frontend/.gitignore b/v3/internal/templates/react-swc-ts/frontend/.gitignore deleted file mode 100644 index a547bf36d..000000000 --- a/v3/internal/templates/react-swc-ts/frontend/.gitignore +++ /dev/null @@ -1,24 +0,0 @@ -# Logs -logs -*.log -npm-debug.log* -yarn-debug.log* -yarn-error.log* -pnpm-debug.log* -lerna-debug.log* - -node_modules -dist -dist-ssr -*.local - -# Editor directories and files -.vscode/* -!.vscode/extensions.json -.idea -.DS_Store -*.suo -*.ntvs* -*.njsproj -*.sln -*.sw? diff --git a/v3/internal/templates/react-swc-ts/frontend/index.html b/v3/internal/templates/react-swc-ts/frontend/index.html deleted file mode 100644 index 0dba04049..000000000 --- a/v3/internal/templates/react-swc-ts/frontend/index.html +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - Wails + React + TS - - -
                    - - - diff --git a/v3/internal/templates/react-swc-ts/frontend/package.json b/v3/internal/templates/react-swc-ts/frontend/package.json deleted file mode 100644 index 0dcc8cdcd..000000000 --- a/v3/internal/templates/react-swc-ts/frontend/package.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "name": "react-ts-latest", - "private": true, - "version": "0.0.0", - "type": "module", - "scripts": { - "dev": "vite", - "build:dev": "tsc && vite build --minify false --mode development", - "build": "tsc && vite build --mode production", - "preview": "vite preview" - }, - "dependencies": { - "@wailsio/runtime": "latest", - "react": "^18.2.0", - "react-dom": "^18.2.0" - }, - "devDependencies": { - "@types/react": "^18.2.43", - "@types/react-dom": "^18.2.17", - "@vitejs/plugin-react-swc": "^3.5.0", - "typescript": "^5.2.2", - "vite": "^5.0.8" - } -} diff --git a/v3/internal/templates/react-swc-ts/frontend/public/Inter-Medium.ttf b/v3/internal/templates/react-swc-ts/frontend/public/Inter-Medium.ttf deleted file mode 100644 index a01f3777a..000000000 Binary files a/v3/internal/templates/react-swc-ts/frontend/public/Inter-Medium.ttf and /dev/null differ diff --git a/v3/internal/templates/react-swc-ts/frontend/public/react.svg b/v3/internal/templates/react-swc-ts/frontend/public/react.svg deleted file mode 100644 index 6c87de9bb..000000000 --- a/v3/internal/templates/react-swc-ts/frontend/public/react.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/v3/internal/templates/react-swc-ts/frontend/public/style.css b/v3/internal/templates/react-swc-ts/frontend/public/style.css deleted file mode 100644 index 0ba9cf5cc..000000000 --- a/v3/internal/templates/react-swc-ts/frontend/public/style.css +++ /dev/null @@ -1,157 +0,0 @@ -:root { - font-family: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", - "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", - sans-serif; - font-size: 16px; - line-height: 24px; - font-weight: 400; - color-scheme: light dark; - color: rgba(255, 255, 255, 0.87); - background-color: rgba(27, 38, 54, 1); - font-synthesis: none; - text-rendering: optimizeLegibility; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - -webkit-text-size-adjust: 100%; - user-select: none; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; -} - -@font-face { - font-family: "Inter"; - font-style: normal; - font-weight: 400; - src: local(""), - url("./Inter-Medium.ttf") format("truetype"); -} - -h3 { - font-size: 3em; - line-height: 1.1; -} - -a { - font-weight: 500; - color: #646cff; - text-decoration: inherit; -} - -a:hover { - color: #535bf2; -} - -button { - width: 60px; - height: 30px; - line-height: 30px; - border-radius: 3px; - border: none; - margin: 0 0 0 20px; - padding: 0 8px; - cursor: pointer; -} - -.result { - height: 20px; - line-height: 20px; -} - -body { - margin: 0; - display: flex; - place-items: center; - place-content: center; - min-width: 320px; - min-height: 100vh; -} - -.container { - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; -} - -h1 { - font-size: 3.2em; - line-height: 1.1; -} - -#app { - max-width: 1280px; - margin: 0 auto; - padding: 2rem; - text-align: center; -} - -.logo { - height: 6em; - padding: 1.5em; - will-change: filter; -} - -.logo:hover { - filter: drop-shadow(0 0 2em #e80000aa); -} - -.logo.react:hover { - filter: drop-shadow(0 0 2em #61dafbaa); -} - -.result { - height: 20px; - line-height: 20px; - margin: 1.5rem auto; - text-align: center; -} - -.footer { - margin-top: 1rem; - align-content: center; - text-align: center; -} - -@media (prefers-color-scheme: light) { - :root { - color: #213547; - background-color: #ffffff; - } - - a:hover { - color: #747bff; - } - - button { - background-color: #f9f9f9; - } -} - - -.input-box .btn:hover { - background-image: linear-gradient(to top, #cfd9df 0%, #e2ebf0 100%); - color: #333333; -} - -.input-box .input { - border: none; - border-radius: 3px; - outline: none; - height: 30px; - line-height: 30px; - padding: 0 10px; - color: black; - background-color: rgba(240, 240, 240, 1); - -webkit-font-smoothing: antialiased; -} - -.input-box .input:hover { - border: none; - background-color: rgba(255, 255, 255, 1); -} - -.input-box .input:focus { - border: none; - background-color: rgba(255, 255, 255, 1); -} diff --git a/v3/internal/templates/react-swc-ts/frontend/public/wails.png b/v3/internal/templates/react-swc-ts/frontend/public/wails.png deleted file mode 100644 index 8bdf42483..000000000 Binary files a/v3/internal/templates/react-swc-ts/frontend/public/wails.png and /dev/null differ diff --git a/v3/internal/templates/react-swc-ts/frontend/src/App.tsx.tmpl b/v3/internal/templates/react-swc-ts/frontend/src/App.tsx.tmpl deleted file mode 100644 index 29c9f2440..000000000 --- a/v3/internal/templates/react-swc-ts/frontend/src/App.tsx.tmpl +++ /dev/null @@ -1,56 +0,0 @@ -import { useState, useEffect } from 'react' -import {Events, WML} from "@wailsio/runtime"; -import {GreetService} from "../bindings/{{js .ModulePath}}"; - -function App() { - const [name, setName] = useState(''); - const [result, setResult] = useState('Please enter your name below 👇'); - const [time, setTime] = useState('Listening for Time event...'); - - const doGreet = () => { - let localName = name; - if (!localName) { - localName = 'anonymous'; - } - GreetService.Greet(localName).then((resultValue: string) => { - setResult(resultValue); - }).catch((err: any) => { - console.log(err); - }); - } - - useEffect(() => { - Events.On('time', (timeValue: any) => { - setTime(timeValue.data); - }); - // Reload WML so it picks up the wml tags - WML.Reload(); - }, []); - - return ( -
                    - -

                    Wails + React

                    -
                    {result}
                    -
                    -
                    - setName(e.target.value)} type="text" autoComplete="off"/> - -
                    -
                    -
                    -

                    Click on the Wails logo to learn more

                    -

                    {time}

                    -
                    -
                    - ) -} - -export default App diff --git a/v3/internal/templates/react-swc-ts/frontend/src/main.tsx b/v3/internal/templates/react-swc-ts/frontend/src/main.tsx deleted file mode 100644 index 3e1823139..000000000 --- a/v3/internal/templates/react-swc-ts/frontend/src/main.tsx +++ /dev/null @@ -1,9 +0,0 @@ -import React from 'react' -import ReactDOM from 'react-dom/client' -import App from './App' - -ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render( - - - , -) diff --git a/v3/internal/templates/react-swc-ts/frontend/src/vite-env.d.ts b/v3/internal/templates/react-swc-ts/frontend/src/vite-env.d.ts deleted file mode 100644 index 11f02fe2a..000000000 --- a/v3/internal/templates/react-swc-ts/frontend/src/vite-env.d.ts +++ /dev/null @@ -1 +0,0 @@ -/// diff --git a/v3/internal/templates/react-swc-ts/frontend/tsconfig.json b/v3/internal/templates/react-swc-ts/frontend/tsconfig.json deleted file mode 100644 index ae81ea6d5..000000000 --- a/v3/internal/templates/react-swc-ts/frontend/tsconfig.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "compilerOptions": { - "target": "ES2020", - "useDefineForClassFields": true, - "lib": ["ES2020", "DOM", "DOM.Iterable"], - "module": "ESNext", - "skipLibCheck": true, - - /* Bundler mode */ - "moduleResolution": "bundler", - "allowImportingTsExtensions": true, - "resolveJsonModule": true, - "isolatedModules": true, - "noEmit": true, - "jsx": "react-jsx", - - /* Linting */ - "strict": true, - "noUnusedLocals": true, - "noUnusedParameters": false, - "noImplicitAny": false, - "noFallthroughCasesInSwitch": true - }, - "include": ["src", "bindings"], -} diff --git a/v3/internal/templates/react-swc-ts/frontend/vite.config.ts b/v3/internal/templates/react-swc-ts/frontend/vite.config.ts deleted file mode 100644 index cd3b2c1c4..000000000 --- a/v3/internal/templates/react-swc-ts/frontend/vite.config.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { defineConfig } from "vite"; -import react from "@vitejs/plugin-react-swc"; -import wails from "@wailsio/runtime/plugins/vite"; - -// https://vitejs.dev/config/ -export default defineConfig({ - plugins: [react(), wails("./bindings")], -}); diff --git a/v3/internal/templates/react-swc-ts/template.json b/v3/internal/templates/react-swc-ts/template.json deleted file mode 100644 index c40ff0772..000000000 --- a/v3/internal/templates/react-swc-ts/template.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "name": "React + SWC + Vite (Typescript)", - "shortname": "react-swc-ts", - "author": "Lea Anthony", - "description": "React + TS + SWC + Vite development server", - "helpurl": "https://wails.io", - "version": "v0.0.1", - "schema": 3 -} \ No newline at end of file diff --git a/v3/internal/templates/react-swc/frontend/.gitignore b/v3/internal/templates/react-swc/frontend/.gitignore deleted file mode 100644 index a547bf36d..000000000 --- a/v3/internal/templates/react-swc/frontend/.gitignore +++ /dev/null @@ -1,24 +0,0 @@ -# Logs -logs -*.log -npm-debug.log* -yarn-debug.log* -yarn-error.log* -pnpm-debug.log* -lerna-debug.log* - -node_modules -dist -dist-ssr -*.local - -# Editor directories and files -.vscode/* -!.vscode/extensions.json -.idea -.DS_Store -*.suo -*.ntvs* -*.njsproj -*.sln -*.sw? diff --git a/v3/internal/templates/react-swc/frontend/index.html b/v3/internal/templates/react-swc/frontend/index.html deleted file mode 100644 index 468143c3d..000000000 --- a/v3/internal/templates/react-swc/frontend/index.html +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - Wails + React - - -
                    - - - diff --git a/v3/internal/templates/react-swc/frontend/package.json b/v3/internal/templates/react-swc/frontend/package.json deleted file mode 100644 index 158ba6880..000000000 --- a/v3/internal/templates/react-swc/frontend/package.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "name": "frontend", - "private": true, - "version": "0.0.0", - "type": "module", - "scripts": { - "dev": "vite", - "build:dev": "vite build --minify false --mode development", - "build": "vite build --mode production", - "preview": "vite preview" - }, - "dependencies": { - "@wailsio/runtime": "latest", - "react": "^18.2.0", - "react-dom": "^18.2.0" - }, - "devDependencies": { - "@types/react": "^18.2.43", - "@types/react-dom": "^18.2.17", - "@vitejs/plugin-react-swc": "^3.5.0", - "vite": "^5.0.8" - } -} diff --git a/v3/internal/templates/react-swc/frontend/public/Inter-Medium.ttf b/v3/internal/templates/react-swc/frontend/public/Inter-Medium.ttf deleted file mode 100644 index a01f3777a..000000000 Binary files a/v3/internal/templates/react-swc/frontend/public/Inter-Medium.ttf and /dev/null differ diff --git a/v3/internal/templates/react-swc/frontend/public/react.svg b/v3/internal/templates/react-swc/frontend/public/react.svg deleted file mode 100644 index 6c87de9bb..000000000 --- a/v3/internal/templates/react-swc/frontend/public/react.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/v3/internal/templates/react-swc/frontend/public/style.css b/v3/internal/templates/react-swc/frontend/public/style.css deleted file mode 100644 index 0ba9cf5cc..000000000 --- a/v3/internal/templates/react-swc/frontend/public/style.css +++ /dev/null @@ -1,157 +0,0 @@ -:root { - font-family: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", - "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", - sans-serif; - font-size: 16px; - line-height: 24px; - font-weight: 400; - color-scheme: light dark; - color: rgba(255, 255, 255, 0.87); - background-color: rgba(27, 38, 54, 1); - font-synthesis: none; - text-rendering: optimizeLegibility; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - -webkit-text-size-adjust: 100%; - user-select: none; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; -} - -@font-face { - font-family: "Inter"; - font-style: normal; - font-weight: 400; - src: local(""), - url("./Inter-Medium.ttf") format("truetype"); -} - -h3 { - font-size: 3em; - line-height: 1.1; -} - -a { - font-weight: 500; - color: #646cff; - text-decoration: inherit; -} - -a:hover { - color: #535bf2; -} - -button { - width: 60px; - height: 30px; - line-height: 30px; - border-radius: 3px; - border: none; - margin: 0 0 0 20px; - padding: 0 8px; - cursor: pointer; -} - -.result { - height: 20px; - line-height: 20px; -} - -body { - margin: 0; - display: flex; - place-items: center; - place-content: center; - min-width: 320px; - min-height: 100vh; -} - -.container { - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; -} - -h1 { - font-size: 3.2em; - line-height: 1.1; -} - -#app { - max-width: 1280px; - margin: 0 auto; - padding: 2rem; - text-align: center; -} - -.logo { - height: 6em; - padding: 1.5em; - will-change: filter; -} - -.logo:hover { - filter: drop-shadow(0 0 2em #e80000aa); -} - -.logo.react:hover { - filter: drop-shadow(0 0 2em #61dafbaa); -} - -.result { - height: 20px; - line-height: 20px; - margin: 1.5rem auto; - text-align: center; -} - -.footer { - margin-top: 1rem; - align-content: center; - text-align: center; -} - -@media (prefers-color-scheme: light) { - :root { - color: #213547; - background-color: #ffffff; - } - - a:hover { - color: #747bff; - } - - button { - background-color: #f9f9f9; - } -} - - -.input-box .btn:hover { - background-image: linear-gradient(to top, #cfd9df 0%, #e2ebf0 100%); - color: #333333; -} - -.input-box .input { - border: none; - border-radius: 3px; - outline: none; - height: 30px; - line-height: 30px; - padding: 0 10px; - color: black; - background-color: rgba(240, 240, 240, 1); - -webkit-font-smoothing: antialiased; -} - -.input-box .input:hover { - border: none; - background-color: rgba(255, 255, 255, 1); -} - -.input-box .input:focus { - border: none; - background-color: rgba(255, 255, 255, 1); -} diff --git a/v3/internal/templates/react-swc/frontend/public/wails.png b/v3/internal/templates/react-swc/frontend/public/wails.png deleted file mode 100644 index 8bdf42483..000000000 Binary files a/v3/internal/templates/react-swc/frontend/public/wails.png and /dev/null differ diff --git a/v3/internal/templates/react-swc/frontend/src/App.jsx.tmpl b/v3/internal/templates/react-swc/frontend/src/App.jsx.tmpl deleted file mode 100644 index 87395733d..000000000 --- a/v3/internal/templates/react-swc/frontend/src/App.jsx.tmpl +++ /dev/null @@ -1,56 +0,0 @@ -import { useState, useEffect } from 'react' -import {Events, WML} from "@wailsio/runtime"; -import {GreetService} from "../bindings/{{js .ModulePath}}"; - -function App() { - const [name, setName] = useState(''); - const [result, setResult] = useState('Please enter your name below 👇'); - const [time, setTime] = useState('Listening for Time event...'); - - const doGreet = () => { - let localName = name; - if (!localName) { - localName = 'anonymous'; - } - GreetService.Greet(localName).then((resultValue) => { - setResult(resultValue); - }).catch((err) => { - console.log(err); - }); - } - - useEffect(() => { - Events.On('time', (timeValue) => { - setTime(timeValue.data); - }); - // Reload WML so it picks up the wml tags - WML.Reload(); - }, []); - - return ( -
                    - -

                    Wails + React

                    -
                    {result}
                    -
                    -
                    - setName(e.target.value)} type="text" autoComplete="off"/> - -
                    -
                    -
                    -

                    Click on the Wails logo to learn more

                    -

                    {time}

                    -
                    -
                    - ) -} - -export default App diff --git a/v3/internal/templates/react-swc/frontend/src/main.jsx b/v3/internal/templates/react-swc/frontend/src/main.jsx deleted file mode 100644 index 1943cc824..000000000 --- a/v3/internal/templates/react-swc/frontend/src/main.jsx +++ /dev/null @@ -1,9 +0,0 @@ -import React from 'react' -import ReactDOM from 'react-dom/client' -import App from './App' - -ReactDOM.createRoot(document.getElementById('root')).render( - - - , -) diff --git a/v3/internal/templates/react-swc/frontend/src/vite-env.d.ts b/v3/internal/templates/react-swc/frontend/src/vite-env.d.ts deleted file mode 100644 index 11f02fe2a..000000000 --- a/v3/internal/templates/react-swc/frontend/src/vite-env.d.ts +++ /dev/null @@ -1 +0,0 @@ -/// diff --git a/v3/internal/templates/react-swc/frontend/tsconfig.json b/v3/internal/templates/react-swc/frontend/tsconfig.json deleted file mode 100644 index 2be606f10..000000000 --- a/v3/internal/templates/react-swc/frontend/tsconfig.json +++ /dev/null @@ -1,25 +0,0 @@ -/** - * This file tells your IDE where the root of your JavaScript project is, and sets some - * options that it can use to provide autocompletion and other features. - */ -{ - "compilerOptions": { - "allowJs": true, - "moduleResolution": "bundler", - /** - * The target and module can be set to ESNext to allow writing modern JavaScript, - * and Vite will compile down to the level of "build.target" specified in the vite config file. - * Builds will error if you use a feature that cannot be compiled down to the target level. - */ - "target": "ESNext", - "module": "ESNext", - "resolveJsonModule": true, - /** - * Enable checkJs if you'd like type checking in `.js(x)` files. - */ - "checkJs": false, - "strict": true, - "skipLibCheck": true, - }, - "include": ["src", "bindings"] -} diff --git a/v3/internal/templates/react-swc/frontend/vite.config.js b/v3/internal/templates/react-swc/frontend/vite.config.js deleted file mode 100644 index cd3b2c1c4..000000000 --- a/v3/internal/templates/react-swc/frontend/vite.config.js +++ /dev/null @@ -1,8 +0,0 @@ -import { defineConfig } from "vite"; -import react from "@vitejs/plugin-react-swc"; -import wails from "@wailsio/runtime/plugins/vite"; - -// https://vitejs.dev/config/ -export default defineConfig({ - plugins: [react(), wails("./bindings")], -}); diff --git a/v3/internal/templates/react-swc/template.json b/v3/internal/templates/react-swc/template.json deleted file mode 100644 index de25db768..000000000 --- a/v3/internal/templates/react-swc/template.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "name": "React + SWC + Vite", - "shortname": "react-swc", - "author": "Lea Anthony", - "description": "React + SWC + Vite development server", - "helpurl": "https://wails.io", - "version": "v0.0.1", - "schema": 3 -} \ No newline at end of file diff --git a/v3/internal/templates/react-ts/frontend/.gitignore b/v3/internal/templates/react-ts/frontend/.gitignore deleted file mode 100644 index a547bf36d..000000000 --- a/v3/internal/templates/react-ts/frontend/.gitignore +++ /dev/null @@ -1,24 +0,0 @@ -# Logs -logs -*.log -npm-debug.log* -yarn-debug.log* -yarn-error.log* -pnpm-debug.log* -lerna-debug.log* - -node_modules -dist -dist-ssr -*.local - -# Editor directories and files -.vscode/* -!.vscode/extensions.json -.idea -.DS_Store -*.suo -*.ntvs* -*.njsproj -*.sln -*.sw? diff --git a/v3/internal/templates/react-ts/frontend/index.html b/v3/internal/templates/react-ts/frontend/index.html deleted file mode 100644 index 0dba04049..000000000 --- a/v3/internal/templates/react-ts/frontend/index.html +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - Wails + React + TS - - -
                    - - - diff --git a/v3/internal/templates/react-ts/frontend/package.json b/v3/internal/templates/react-ts/frontend/package.json deleted file mode 100644 index f718c0073..000000000 --- a/v3/internal/templates/react-ts/frontend/package.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "name": "react-ts-latest", - "private": true, - "version": "0.0.0", - "type": "module", - "scripts": { - "dev": "vite", - "build:dev": "tsc && vite build --minify false --mode development", - "build": "tsc && vite build --mode production", - "preview": "vite preview" - }, - "dependencies": { - "@wailsio/runtime": "latest", - "react": "^18.2.0", - "react-dom": "^18.2.0" - }, - "devDependencies": { - "@types/react": "^18.2.43", - "@types/react-dom": "^18.2.17", - "@vitejs/plugin-react": "^4.2.1", - "typescript": "^5.2.2", - "vite": "^5.0.8" - } -} diff --git a/v3/internal/templates/react-ts/frontend/public/Inter-Medium.ttf b/v3/internal/templates/react-ts/frontend/public/Inter-Medium.ttf deleted file mode 100644 index a01f3777a..000000000 Binary files a/v3/internal/templates/react-ts/frontend/public/Inter-Medium.ttf and /dev/null differ diff --git a/v3/internal/templates/react-ts/frontend/public/react.svg b/v3/internal/templates/react-ts/frontend/public/react.svg deleted file mode 100644 index 6c87de9bb..000000000 --- a/v3/internal/templates/react-ts/frontend/public/react.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/v3/internal/templates/react-ts/frontend/public/style.css b/v3/internal/templates/react-ts/frontend/public/style.css deleted file mode 100644 index 0ba9cf5cc..000000000 --- a/v3/internal/templates/react-ts/frontend/public/style.css +++ /dev/null @@ -1,157 +0,0 @@ -:root { - font-family: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", - "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", - sans-serif; - font-size: 16px; - line-height: 24px; - font-weight: 400; - color-scheme: light dark; - color: rgba(255, 255, 255, 0.87); - background-color: rgba(27, 38, 54, 1); - font-synthesis: none; - text-rendering: optimizeLegibility; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - -webkit-text-size-adjust: 100%; - user-select: none; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; -} - -@font-face { - font-family: "Inter"; - font-style: normal; - font-weight: 400; - src: local(""), - url("./Inter-Medium.ttf") format("truetype"); -} - -h3 { - font-size: 3em; - line-height: 1.1; -} - -a { - font-weight: 500; - color: #646cff; - text-decoration: inherit; -} - -a:hover { - color: #535bf2; -} - -button { - width: 60px; - height: 30px; - line-height: 30px; - border-radius: 3px; - border: none; - margin: 0 0 0 20px; - padding: 0 8px; - cursor: pointer; -} - -.result { - height: 20px; - line-height: 20px; -} - -body { - margin: 0; - display: flex; - place-items: center; - place-content: center; - min-width: 320px; - min-height: 100vh; -} - -.container { - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; -} - -h1 { - font-size: 3.2em; - line-height: 1.1; -} - -#app { - max-width: 1280px; - margin: 0 auto; - padding: 2rem; - text-align: center; -} - -.logo { - height: 6em; - padding: 1.5em; - will-change: filter; -} - -.logo:hover { - filter: drop-shadow(0 0 2em #e80000aa); -} - -.logo.react:hover { - filter: drop-shadow(0 0 2em #61dafbaa); -} - -.result { - height: 20px; - line-height: 20px; - margin: 1.5rem auto; - text-align: center; -} - -.footer { - margin-top: 1rem; - align-content: center; - text-align: center; -} - -@media (prefers-color-scheme: light) { - :root { - color: #213547; - background-color: #ffffff; - } - - a:hover { - color: #747bff; - } - - button { - background-color: #f9f9f9; - } -} - - -.input-box .btn:hover { - background-image: linear-gradient(to top, #cfd9df 0%, #e2ebf0 100%); - color: #333333; -} - -.input-box .input { - border: none; - border-radius: 3px; - outline: none; - height: 30px; - line-height: 30px; - padding: 0 10px; - color: black; - background-color: rgba(240, 240, 240, 1); - -webkit-font-smoothing: antialiased; -} - -.input-box .input:hover { - border: none; - background-color: rgba(255, 255, 255, 1); -} - -.input-box .input:focus { - border: none; - background-color: rgba(255, 255, 255, 1); -} diff --git a/v3/internal/templates/react-ts/frontend/public/wails.png b/v3/internal/templates/react-ts/frontend/public/wails.png deleted file mode 100644 index 8bdf42483..000000000 Binary files a/v3/internal/templates/react-ts/frontend/public/wails.png and /dev/null differ diff --git a/v3/internal/templates/react-ts/frontend/src/App.tsx.tmpl b/v3/internal/templates/react-ts/frontend/src/App.tsx.tmpl deleted file mode 100644 index f6185f2a8..000000000 --- a/v3/internal/templates/react-ts/frontend/src/App.tsx.tmpl +++ /dev/null @@ -1,56 +0,0 @@ -import { useState, useEffect } from 'react' -import {Events, WML} from "@wailsio/runtime"; -import {GreetService} from "../bindings/{{js .ModulePath}}"; - -function App() { - const [name, setName] = useState(''); - const [result, setResult] = useState('Please enter your name below 👇'); - const [time, setTime] = useState('Listening for Time event...'); - - const doGreet = () => { - let localName = name; - if (!localName) { - localName = 'anonymous'; - } - GreetService.Greet(localName).then((resultValue: string) => { - setResult(resultValue); - }).catch((err: any) => { - console.log(err); - }); - } - - useEffect(() => { - Events.On('time', (timeValue: any) => { - setTime(timeValue.data); - }); - // Reload WML so it picks up the wml tags - WML.Reload(); - }, []); - - return ( -
                    - -

                    Wails + React

                    -
                    {result}
                    -
                    -
                    - setName(e.target.value)} type="text" autoComplete="off"/> - -
                    -
                    -
                    -

                    Click on the Wails logo to learn more

                    -

                    {time}

                    -
                    -
                    - ) -} - -export default App diff --git a/v3/internal/templates/react-ts/frontend/src/main.tsx b/v3/internal/templates/react-ts/frontend/src/main.tsx deleted file mode 100644 index 3e1823139..000000000 --- a/v3/internal/templates/react-ts/frontend/src/main.tsx +++ /dev/null @@ -1,9 +0,0 @@ -import React from 'react' -import ReactDOM from 'react-dom/client' -import App from './App' - -ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render( - - - , -) diff --git a/v3/internal/templates/react-ts/frontend/src/vite-env.d.ts b/v3/internal/templates/react-ts/frontend/src/vite-env.d.ts deleted file mode 100644 index 11f02fe2a..000000000 --- a/v3/internal/templates/react-ts/frontend/src/vite-env.d.ts +++ /dev/null @@ -1 +0,0 @@ -/// diff --git a/v3/internal/templates/react-ts/frontend/tsconfig.json b/v3/internal/templates/react-ts/frontend/tsconfig.json deleted file mode 100644 index ae81ea6d5..000000000 --- a/v3/internal/templates/react-ts/frontend/tsconfig.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "compilerOptions": { - "target": "ES2020", - "useDefineForClassFields": true, - "lib": ["ES2020", "DOM", "DOM.Iterable"], - "module": "ESNext", - "skipLibCheck": true, - - /* Bundler mode */ - "moduleResolution": "bundler", - "allowImportingTsExtensions": true, - "resolveJsonModule": true, - "isolatedModules": true, - "noEmit": true, - "jsx": "react-jsx", - - /* Linting */ - "strict": true, - "noUnusedLocals": true, - "noUnusedParameters": false, - "noImplicitAny": false, - "noFallthroughCasesInSwitch": true - }, - "include": ["src", "bindings"], -} diff --git a/v3/internal/templates/react-ts/frontend/vite.config.ts b/v3/internal/templates/react-ts/frontend/vite.config.ts deleted file mode 100644 index a642bc024..000000000 --- a/v3/internal/templates/react-ts/frontend/vite.config.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { defineConfig } from "vite"; -import react from "@vitejs/plugin-react"; -import wails from "@wailsio/runtime/plugins/vite"; - -// https://vitejs.dev/config/ -export default defineConfig({ - plugins: [react(), wails("./bindings")], -}); diff --git a/v3/internal/templates/react-ts/template.json b/v3/internal/templates/react-ts/template.json deleted file mode 100644 index 33dd85583..000000000 --- a/v3/internal/templates/react-ts/template.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "name": "React + Vite (Typescript)", - "shortname": "react-ts", - "author": "Lea Anthony", - "description": "React + Vite development server", - "helpurl": "https://wails.io", - "version": "v0.0.1", - "schema": 3 -} \ No newline at end of file diff --git a/v3/internal/templates/react/frontend/.gitignore b/v3/internal/templates/react/frontend/.gitignore deleted file mode 100644 index a547bf36d..000000000 --- a/v3/internal/templates/react/frontend/.gitignore +++ /dev/null @@ -1,24 +0,0 @@ -# Logs -logs -*.log -npm-debug.log* -yarn-debug.log* -yarn-error.log* -pnpm-debug.log* -lerna-debug.log* - -node_modules -dist -dist-ssr -*.local - -# Editor directories and files -.vscode/* -!.vscode/extensions.json -.idea -.DS_Store -*.suo -*.ntvs* -*.njsproj -*.sln -*.sw? diff --git a/v3/internal/templates/react/frontend/index.html b/v3/internal/templates/react/frontend/index.html deleted file mode 100644 index 468143c3d..000000000 --- a/v3/internal/templates/react/frontend/index.html +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - Wails + React - - -
                    - - - diff --git a/v3/internal/templates/react/frontend/package.json b/v3/internal/templates/react/frontend/package.json deleted file mode 100644 index 59d4d62b3..000000000 --- a/v3/internal/templates/react/frontend/package.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "name": "frontend", - "private": true, - "version": "0.0.0", - "type": "module", - "scripts": { - "dev": "vite", - "build:dev": "vite build --minify false --mode development", - "build": "vite build --mode production", - "preview": "vite preview" - }, - "dependencies": { - "@wailsio/runtime": "latest", - "react": "^18.2.0", - "react-dom": "^18.2.0" - }, - "devDependencies": { - "@types/react": "^18.2.43", - "@types/react-dom": "^18.2.17", - "@vitejs/plugin-react": "^4.2.1", - "vite": "^5.0.8" - } -} diff --git a/v3/internal/templates/react/frontend/public/Inter-Medium.ttf b/v3/internal/templates/react/frontend/public/Inter-Medium.ttf deleted file mode 100644 index a01f3777a..000000000 Binary files a/v3/internal/templates/react/frontend/public/Inter-Medium.ttf and /dev/null differ diff --git a/v3/internal/templates/react/frontend/public/react.svg b/v3/internal/templates/react/frontend/public/react.svg deleted file mode 100644 index 6c87de9bb..000000000 --- a/v3/internal/templates/react/frontend/public/react.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/v3/internal/templates/react/frontend/public/style.css b/v3/internal/templates/react/frontend/public/style.css deleted file mode 100644 index 0ba9cf5cc..000000000 --- a/v3/internal/templates/react/frontend/public/style.css +++ /dev/null @@ -1,157 +0,0 @@ -:root { - font-family: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", - "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", - sans-serif; - font-size: 16px; - line-height: 24px; - font-weight: 400; - color-scheme: light dark; - color: rgba(255, 255, 255, 0.87); - background-color: rgba(27, 38, 54, 1); - font-synthesis: none; - text-rendering: optimizeLegibility; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - -webkit-text-size-adjust: 100%; - user-select: none; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; -} - -@font-face { - font-family: "Inter"; - font-style: normal; - font-weight: 400; - src: local(""), - url("./Inter-Medium.ttf") format("truetype"); -} - -h3 { - font-size: 3em; - line-height: 1.1; -} - -a { - font-weight: 500; - color: #646cff; - text-decoration: inherit; -} - -a:hover { - color: #535bf2; -} - -button { - width: 60px; - height: 30px; - line-height: 30px; - border-radius: 3px; - border: none; - margin: 0 0 0 20px; - padding: 0 8px; - cursor: pointer; -} - -.result { - height: 20px; - line-height: 20px; -} - -body { - margin: 0; - display: flex; - place-items: center; - place-content: center; - min-width: 320px; - min-height: 100vh; -} - -.container { - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; -} - -h1 { - font-size: 3.2em; - line-height: 1.1; -} - -#app { - max-width: 1280px; - margin: 0 auto; - padding: 2rem; - text-align: center; -} - -.logo { - height: 6em; - padding: 1.5em; - will-change: filter; -} - -.logo:hover { - filter: drop-shadow(0 0 2em #e80000aa); -} - -.logo.react:hover { - filter: drop-shadow(0 0 2em #61dafbaa); -} - -.result { - height: 20px; - line-height: 20px; - margin: 1.5rem auto; - text-align: center; -} - -.footer { - margin-top: 1rem; - align-content: center; - text-align: center; -} - -@media (prefers-color-scheme: light) { - :root { - color: #213547; - background-color: #ffffff; - } - - a:hover { - color: #747bff; - } - - button { - background-color: #f9f9f9; - } -} - - -.input-box .btn:hover { - background-image: linear-gradient(to top, #cfd9df 0%, #e2ebf0 100%); - color: #333333; -} - -.input-box .input { - border: none; - border-radius: 3px; - outline: none; - height: 30px; - line-height: 30px; - padding: 0 10px; - color: black; - background-color: rgba(240, 240, 240, 1); - -webkit-font-smoothing: antialiased; -} - -.input-box .input:hover { - border: none; - background-color: rgba(255, 255, 255, 1); -} - -.input-box .input:focus { - border: none; - background-color: rgba(255, 255, 255, 1); -} diff --git a/v3/internal/templates/react/frontend/public/wails.png b/v3/internal/templates/react/frontend/public/wails.png deleted file mode 100644 index 8bdf42483..000000000 Binary files a/v3/internal/templates/react/frontend/public/wails.png and /dev/null differ diff --git a/v3/internal/templates/react/frontend/src/App.jsx.tmpl b/v3/internal/templates/react/frontend/src/App.jsx.tmpl deleted file mode 100644 index 87395733d..000000000 --- a/v3/internal/templates/react/frontend/src/App.jsx.tmpl +++ /dev/null @@ -1,56 +0,0 @@ -import { useState, useEffect } from 'react' -import {Events, WML} from "@wailsio/runtime"; -import {GreetService} from "../bindings/{{js .ModulePath}}"; - -function App() { - const [name, setName] = useState(''); - const [result, setResult] = useState('Please enter your name below 👇'); - const [time, setTime] = useState('Listening for Time event...'); - - const doGreet = () => { - let localName = name; - if (!localName) { - localName = 'anonymous'; - } - GreetService.Greet(localName).then((resultValue) => { - setResult(resultValue); - }).catch((err) => { - console.log(err); - }); - } - - useEffect(() => { - Events.On('time', (timeValue) => { - setTime(timeValue.data); - }); - // Reload WML so it picks up the wml tags - WML.Reload(); - }, []); - - return ( -
                    - -

                    Wails + React

                    -
                    {result}
                    -
                    -
                    - setName(e.target.value)} type="text" autoComplete="off"/> - -
                    -
                    -
                    -

                    Click on the Wails logo to learn more

                    -

                    {time}

                    -
                    -
                    - ) -} - -export default App diff --git a/v3/internal/templates/react/frontend/src/main.jsx b/v3/internal/templates/react/frontend/src/main.jsx deleted file mode 100644 index 1943cc824..000000000 --- a/v3/internal/templates/react/frontend/src/main.jsx +++ /dev/null @@ -1,9 +0,0 @@ -import React from 'react' -import ReactDOM from 'react-dom/client' -import App from './App' - -ReactDOM.createRoot(document.getElementById('root')).render( - - - , -) diff --git a/v3/internal/templates/react/frontend/src/vite-env.d.ts b/v3/internal/templates/react/frontend/src/vite-env.d.ts deleted file mode 100644 index 11f02fe2a..000000000 --- a/v3/internal/templates/react/frontend/src/vite-env.d.ts +++ /dev/null @@ -1 +0,0 @@ -/// diff --git a/v3/internal/templates/react/frontend/tsconfig.json b/v3/internal/templates/react/frontend/tsconfig.json deleted file mode 100644 index 2be606f10..000000000 --- a/v3/internal/templates/react/frontend/tsconfig.json +++ /dev/null @@ -1,25 +0,0 @@ -/** - * This file tells your IDE where the root of your JavaScript project is, and sets some - * options that it can use to provide autocompletion and other features. - */ -{ - "compilerOptions": { - "allowJs": true, - "moduleResolution": "bundler", - /** - * The target and module can be set to ESNext to allow writing modern JavaScript, - * and Vite will compile down to the level of "build.target" specified in the vite config file. - * Builds will error if you use a feature that cannot be compiled down to the target level. - */ - "target": "ESNext", - "module": "ESNext", - "resolveJsonModule": true, - /** - * Enable checkJs if you'd like type checking in `.js(x)` files. - */ - "checkJs": false, - "strict": true, - "skipLibCheck": true, - }, - "include": ["src", "bindings"] -} diff --git a/v3/internal/templates/react/frontend/vite.config.js b/v3/internal/templates/react/frontend/vite.config.js deleted file mode 100644 index a642bc024..000000000 --- a/v3/internal/templates/react/frontend/vite.config.js +++ /dev/null @@ -1,8 +0,0 @@ -import { defineConfig } from "vite"; -import react from "@vitejs/plugin-react"; -import wails from "@wailsio/runtime/plugins/vite"; - -// https://vitejs.dev/config/ -export default defineConfig({ - plugins: [react(), wails("./bindings")], -}); diff --git a/v3/internal/templates/react/template.json b/v3/internal/templates/react/template.json deleted file mode 100644 index c9fff4a20..000000000 --- a/v3/internal/templates/react/template.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "name": "React + Vite", - "shortname": "react", - "author": "Lea Anthony", - "description": "React + Vite development server", - "helpurl": "https://wails.io", - "version": "v0.0.1", - "schema": 3 -} \ No newline at end of file diff --git a/v3/internal/templates/solid-ts/frontend/.gitignore b/v3/internal/templates/solid-ts/frontend/.gitignore deleted file mode 100644 index a547bf36d..000000000 --- a/v3/internal/templates/solid-ts/frontend/.gitignore +++ /dev/null @@ -1,24 +0,0 @@ -# Logs -logs -*.log -npm-debug.log* -yarn-debug.log* -yarn-error.log* -pnpm-debug.log* -lerna-debug.log* - -node_modules -dist -dist-ssr -*.local - -# Editor directories and files -.vscode/* -!.vscode/extensions.json -.idea -.DS_Store -*.suo -*.ntvs* -*.njsproj -*.sln -*.sw? diff --git a/v3/internal/templates/solid-ts/frontend/index.html b/v3/internal/templates/solid-ts/frontend/index.html deleted file mode 100644 index 86dfcc88e..000000000 --- a/v3/internal/templates/solid-ts/frontend/index.html +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - Vite + Solid + TS - - -
                    - - - diff --git a/v3/internal/templates/solid-ts/frontend/package.json b/v3/internal/templates/solid-ts/frontend/package.json deleted file mode 100644 index 741674ea7..000000000 --- a/v3/internal/templates/solid-ts/frontend/package.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "name": "solid-ts", - "private": true, - "version": "0.0.0", - "type": "module", - "scripts": { - "dev": "vite", - "build:dev": "tsc && vite build --minify false --mode development", - "build": "tsc && vite build --mode production", - "preview": "vite preview" - }, - "dependencies": { - "@wailsio/runtime": "latest", - "solid-js": "^1.8.7" - }, - "devDependencies": { - "typescript": "^5.2.2", - "vite": "^5.0.8", - "vite-plugin-solid": "^2.8.0" - } -} diff --git a/v3/internal/templates/solid-ts/frontend/public/Inter-Medium.ttf b/v3/internal/templates/solid-ts/frontend/public/Inter-Medium.ttf deleted file mode 100644 index a01f3777a..000000000 Binary files a/v3/internal/templates/solid-ts/frontend/public/Inter-Medium.ttf and /dev/null differ diff --git a/v3/internal/templates/solid-ts/frontend/public/solid.svg b/v3/internal/templates/solid-ts/frontend/public/solid.svg deleted file mode 100644 index 025aa303c..000000000 --- a/v3/internal/templates/solid-ts/frontend/public/solid.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/v3/internal/templates/solid-ts/frontend/public/style.css b/v3/internal/templates/solid-ts/frontend/public/style.css deleted file mode 100644 index 892241249..000000000 --- a/v3/internal/templates/solid-ts/frontend/public/style.css +++ /dev/null @@ -1,157 +0,0 @@ -:root { - font-family: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", - "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", - sans-serif; - font-size: 16px; - line-height: 24px; - font-weight: 400; - color-scheme: light dark; - color: rgba(255, 255, 255, 0.87); - background-color: rgba(27, 38, 54, 1); - font-synthesis: none; - text-rendering: optimizeLegibility; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - -webkit-text-size-adjust: 100%; - user-select: none; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; -} - -@font-face { - font-family: "Inter"; - font-style: normal; - font-weight: 400; - src: local(""), - url("./Inter-Medium.ttf") format("truetype"); -} - -h3 { - font-size: 3em; - line-height: 1.1; -} - -a { - font-weight: 500; - color: #646cff; - text-decoration: inherit; -} - -a:hover { - color: #535bf2; -} - -button { - width: 60px; - height: 30px; - line-height: 30px; - border-radius: 3px; - border: none; - margin: 0 0 0 20px; - padding: 0 8px; - cursor: pointer; -} - -.result { - height: 20px; - line-height: 20px; -} - -body { - margin: 0; - display: flex; - place-items: center; - place-content: center; - min-width: 320px; - min-height: 100vh; -} - -.container { - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; -} - -h1 { - font-size: 3.2em; - line-height: 1.1; -} - -#app { - max-width: 1280px; - margin: 0 auto; - padding: 2rem; - text-align: center; -} - -.logo { - height: 6em; - padding: 1.5em; - will-change: filter; -} - -.logo:hover { - filter: drop-shadow(0 0 2em #e80000aa); -} - -.logo.solid:hover { - filter: drop-shadow(0 0 2em #61dafbaa); -} - -.result { - height: 20px; - line-height: 20px; - margin: 1.5rem auto; - text-align: center; -} - -.footer { - margin-top: 1rem; - align-content: center; - text-align: center; -} - -@media (prefers-color-scheme: light) { - :root { - color: #213547; - background-color: #ffffff; - } - - a:hover { - color: #747bff; - } - - button { - background-color: #f9f9f9; - } -} - - -.input-box .btn:hover { - background-image: linear-gradient(to top, #cfd9df 0%, #e2ebf0 100%); - color: #333333; -} - -.input-box .input { - border: none; - border-radius: 3px; - outline: none; - height: 30px; - line-height: 30px; - padding: 0 10px; - color: black; - background-color: rgba(240, 240, 240, 1); - -webkit-font-smoothing: antialiased; -} - -.input-box .input:hover { - border: none; - background-color: rgba(255, 255, 255, 1); -} - -.input-box .input:focus { - border: none; - background-color: rgba(255, 255, 255, 1); -} \ No newline at end of file diff --git a/v3/internal/templates/solid-ts/frontend/public/wails.png b/v3/internal/templates/solid-ts/frontend/public/wails.png deleted file mode 100644 index 8bdf42483..000000000 Binary files a/v3/internal/templates/solid-ts/frontend/public/wails.png and /dev/null differ diff --git a/v3/internal/templates/solid-ts/frontend/src/App.tsx.tmpl b/v3/internal/templates/solid-ts/frontend/src/App.tsx.tmpl deleted file mode 100644 index 620959b51..000000000 --- a/v3/internal/templates/solid-ts/frontend/src/App.tsx.tmpl +++ /dev/null @@ -1,54 +0,0 @@ -import { createSignal, onMount } from 'solid-js' -import {Events} from "@wailsio/runtime"; -import {GreetService} from "../bindings/{{js .ModulePath}}"; - -function App() { - const [name, setName] = createSignal(''); - const [result, setResult] = createSignal('Please enter your name below 👇'); - const [time, setTime] = createSignal('Listening for Time event...'); - - const doGreet = () => { - let localName = name(); - if (!localName) { - localName = 'anonymous'; - } - GreetService.Greet(localName).then((resultValue: string) => { - setResult(resultValue); - }).catch((err: any) => { - console.log(err); - }); - } - - onMount(() => { - Events.On('time', (timeValue: any) => { - setTime(timeValue.data); - }); - }); - - return ( -
                    - -

                    Wails + Solid

                    -
                    {result()}
                    -
                    -
                    - setName(e.currentTarget.value)} type="text" autocomplete="off"/> - -
                    -
                    - -
                    - ) -} - -export default App diff --git a/v3/internal/templates/solid-ts/frontend/src/index.tsx b/v3/internal/templates/solid-ts/frontend/src/index.tsx deleted file mode 100644 index ff5c09ee3..000000000 --- a/v3/internal/templates/solid-ts/frontend/src/index.tsx +++ /dev/null @@ -1,7 +0,0 @@ -/* @refresh reload */ -import { render } from 'solid-js/web' -import App from './App' - -const root = document.getElementById('root') - -render(() => , root!) diff --git a/v3/internal/templates/solid-ts/frontend/src/vite-env.d.ts b/v3/internal/templates/solid-ts/frontend/src/vite-env.d.ts deleted file mode 100644 index 11f02fe2a..000000000 --- a/v3/internal/templates/solid-ts/frontend/src/vite-env.d.ts +++ /dev/null @@ -1 +0,0 @@ -/// diff --git a/v3/internal/templates/solid-ts/frontend/tsconfig.json b/v3/internal/templates/solid-ts/frontend/tsconfig.json deleted file mode 100644 index 89492db4a..000000000 --- a/v3/internal/templates/solid-ts/frontend/tsconfig.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "compilerOptions": { - "target": "ES2020", - "useDefineForClassFields": true, - "module": "ESNext", - "lib": ["ES2020", "DOM", "DOM.Iterable"], - "skipLibCheck": true, - - /* Bundler mode */ - "moduleResolution": "bundler", - "allowImportingTsExtensions": true, - "resolveJsonModule": true, - "isolatedModules": true, - "noEmit": true, - "jsx": "preserve", - "jsxImportSource": "solid-js", - - /* Linting */ - "strict": true, - "noUnusedLocals": true, - "noUnusedParameters": false, - "noImplicitAny": false, - "noFallthroughCasesInSwitch": true - }, - "include": ["src", "bindings"], -} diff --git a/v3/internal/templates/solid-ts/frontend/vite.config.ts b/v3/internal/templates/solid-ts/frontend/vite.config.ts deleted file mode 100644 index 9b9614f01..000000000 --- a/v3/internal/templates/solid-ts/frontend/vite.config.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { defineConfig } from "vite"; -import solid from "vite-plugin-solid"; -import wails from "@wailsio/runtime/plugins/vite"; - -export default defineConfig({ - plugins: [solid(), wails("./bindings")], -}); diff --git a/v3/internal/templates/solid-ts/template.json b/v3/internal/templates/solid-ts/template.json deleted file mode 100644 index cc226b409..000000000 --- a/v3/internal/templates/solid-ts/template.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "name": "Solid + Vite (Typescript)", - "shortname": "solid-ts", - "author": "Lea Anthony", - "description": "Solid + TS + Vite development server", - "helpurl": "https://wails.io", - "version": "v0.0.1", - "schema": 3 -} \ No newline at end of file diff --git a/v3/internal/templates/solid/frontend/.gitignore b/v3/internal/templates/solid/frontend/.gitignore deleted file mode 100644 index a547bf36d..000000000 --- a/v3/internal/templates/solid/frontend/.gitignore +++ /dev/null @@ -1,24 +0,0 @@ -# Logs -logs -*.log -npm-debug.log* -yarn-debug.log* -yarn-error.log* -pnpm-debug.log* -lerna-debug.log* - -node_modules -dist -dist-ssr -*.local - -# Editor directories and files -.vscode/* -!.vscode/extensions.json -.idea -.DS_Store -*.suo -*.ntvs* -*.njsproj -*.sln -*.sw? diff --git a/v3/internal/templates/solid/frontend/index.html b/v3/internal/templates/solid/frontend/index.html deleted file mode 100644 index b074274aa..000000000 --- a/v3/internal/templates/solid/frontend/index.html +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - Vite + Solid - - -
                    - - - diff --git a/v3/internal/templates/solid/frontend/package.json b/v3/internal/templates/solid/frontend/package.json deleted file mode 100644 index 03ed9141f..000000000 --- a/v3/internal/templates/solid/frontend/package.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "name": "solid-latest", - "private": true, - "version": "0.0.0", - "type": "module", - "scripts": { - "dev": "vite", - "build:dev": "vite build --minify false --mode development", - "build": "vite build --mode production", - "preview": "vite preview" - }, - "dependencies": { - "@wailsio/runtime": "latest", - "solid-js": "^1.8.7" - }, - "devDependencies": { - "vite": "^5.0.8", - "vite-plugin-solid": "^2.8.0" - } -} diff --git a/v3/internal/templates/solid/frontend/public/Inter-Medium.ttf b/v3/internal/templates/solid/frontend/public/Inter-Medium.ttf deleted file mode 100644 index a01f3777a..000000000 Binary files a/v3/internal/templates/solid/frontend/public/Inter-Medium.ttf and /dev/null differ diff --git a/v3/internal/templates/solid/frontend/public/solid.svg b/v3/internal/templates/solid/frontend/public/solid.svg deleted file mode 100644 index 025aa303c..000000000 --- a/v3/internal/templates/solid/frontend/public/solid.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/v3/internal/templates/solid/frontend/public/style.css b/v3/internal/templates/solid/frontend/public/style.css deleted file mode 100644 index 892241249..000000000 --- a/v3/internal/templates/solid/frontend/public/style.css +++ /dev/null @@ -1,157 +0,0 @@ -:root { - font-family: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", - "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", - sans-serif; - font-size: 16px; - line-height: 24px; - font-weight: 400; - color-scheme: light dark; - color: rgba(255, 255, 255, 0.87); - background-color: rgba(27, 38, 54, 1); - font-synthesis: none; - text-rendering: optimizeLegibility; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - -webkit-text-size-adjust: 100%; - user-select: none; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; -} - -@font-face { - font-family: "Inter"; - font-style: normal; - font-weight: 400; - src: local(""), - url("./Inter-Medium.ttf") format("truetype"); -} - -h3 { - font-size: 3em; - line-height: 1.1; -} - -a { - font-weight: 500; - color: #646cff; - text-decoration: inherit; -} - -a:hover { - color: #535bf2; -} - -button { - width: 60px; - height: 30px; - line-height: 30px; - border-radius: 3px; - border: none; - margin: 0 0 0 20px; - padding: 0 8px; - cursor: pointer; -} - -.result { - height: 20px; - line-height: 20px; -} - -body { - margin: 0; - display: flex; - place-items: center; - place-content: center; - min-width: 320px; - min-height: 100vh; -} - -.container { - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; -} - -h1 { - font-size: 3.2em; - line-height: 1.1; -} - -#app { - max-width: 1280px; - margin: 0 auto; - padding: 2rem; - text-align: center; -} - -.logo { - height: 6em; - padding: 1.5em; - will-change: filter; -} - -.logo:hover { - filter: drop-shadow(0 0 2em #e80000aa); -} - -.logo.solid:hover { - filter: drop-shadow(0 0 2em #61dafbaa); -} - -.result { - height: 20px; - line-height: 20px; - margin: 1.5rem auto; - text-align: center; -} - -.footer { - margin-top: 1rem; - align-content: center; - text-align: center; -} - -@media (prefers-color-scheme: light) { - :root { - color: #213547; - background-color: #ffffff; - } - - a:hover { - color: #747bff; - } - - button { - background-color: #f9f9f9; - } -} - - -.input-box .btn:hover { - background-image: linear-gradient(to top, #cfd9df 0%, #e2ebf0 100%); - color: #333333; -} - -.input-box .input { - border: none; - border-radius: 3px; - outline: none; - height: 30px; - line-height: 30px; - padding: 0 10px; - color: black; - background-color: rgba(240, 240, 240, 1); - -webkit-font-smoothing: antialiased; -} - -.input-box .input:hover { - border: none; - background-color: rgba(255, 255, 255, 1); -} - -.input-box .input:focus { - border: none; - background-color: rgba(255, 255, 255, 1); -} \ No newline at end of file diff --git a/v3/internal/templates/solid/frontend/public/wails.png b/v3/internal/templates/solid/frontend/public/wails.png deleted file mode 100644 index 8bdf42483..000000000 Binary files a/v3/internal/templates/solid/frontend/public/wails.png and /dev/null differ diff --git a/v3/internal/templates/solid/frontend/src/App.jsx.tmpl b/v3/internal/templates/solid/frontend/src/App.jsx.tmpl deleted file mode 100644 index d691909b3..000000000 --- a/v3/internal/templates/solid/frontend/src/App.jsx.tmpl +++ /dev/null @@ -1,54 +0,0 @@ -import { createSignal, onMount } from 'solid-js' -import {Events} from "@wailsio/runtime"; -import {GreetService} from "../bindings/{{js .ModulePath}}"; - -function App() { - const [name, setName] = createSignal(''); - const [result, setResult] = createSignal('Please enter your name below 👇'); - const [time, setTime] = createSignal('Listening for Time event...'); - - const doGreet = () => { - let localName = name(); - if (!localName) { - localName = 'anonymous'; - } - GreetService.Greet(localName).then((resultValue) => { - setResult(resultValue); - }).catch((err) => { - console.log(err); - }); - } - - onMount(() => { - Events.On('time', (timeValue) => { - setTime(timeValue.data); - }); - }); - - return ( -
                    - -

                    Wails + Solid

                    -
                    {result()}
                    -
                    -
                    - setName(e.target.value)} type="text" autocomplete="off"/> - -
                    -
                    -
                    -

                    Click on the Wails logo to learn more

                    -

                    {time()}

                    -
                    -
                    - ) -} - -export default App diff --git a/v3/internal/templates/solid/frontend/src/index.jsx b/v3/internal/templates/solid/frontend/src/index.jsx deleted file mode 100644 index fd6808055..000000000 --- a/v3/internal/templates/solid/frontend/src/index.jsx +++ /dev/null @@ -1,8 +0,0 @@ -/* @refresh reload */ -import { render } from 'solid-js/web' - -import App from './App' - -const root = document.getElementById('root') - -render(() => , root) diff --git a/v3/internal/templates/solid/frontend/src/vite-env.d.ts b/v3/internal/templates/solid/frontend/src/vite-env.d.ts deleted file mode 100644 index 11f02fe2a..000000000 --- a/v3/internal/templates/solid/frontend/src/vite-env.d.ts +++ /dev/null @@ -1 +0,0 @@ -/// diff --git a/v3/internal/templates/solid/frontend/tsconfig.json b/v3/internal/templates/solid/frontend/tsconfig.json deleted file mode 100644 index 2be606f10..000000000 --- a/v3/internal/templates/solid/frontend/tsconfig.json +++ /dev/null @@ -1,25 +0,0 @@ -/** - * This file tells your IDE where the root of your JavaScript project is, and sets some - * options that it can use to provide autocompletion and other features. - */ -{ - "compilerOptions": { - "allowJs": true, - "moduleResolution": "bundler", - /** - * The target and module can be set to ESNext to allow writing modern JavaScript, - * and Vite will compile down to the level of "build.target" specified in the vite config file. - * Builds will error if you use a feature that cannot be compiled down to the target level. - */ - "target": "ESNext", - "module": "ESNext", - "resolveJsonModule": true, - /** - * Enable checkJs if you'd like type checking in `.js(x)` files. - */ - "checkJs": false, - "strict": true, - "skipLibCheck": true, - }, - "include": ["src", "bindings"] -} diff --git a/v3/internal/templates/solid/frontend/vite.config.js b/v3/internal/templates/solid/frontend/vite.config.js deleted file mode 100644 index df7eac4c4..000000000 --- a/v3/internal/templates/solid/frontend/vite.config.js +++ /dev/null @@ -1,8 +0,0 @@ -import { defineConfig } from "vite"; -import solid from "vite-plugin-solid"; -import wails from "@wailsio/runtime/plugins/vite"; - -// https://vitejs.dev/config/ -export default defineConfig({ - plugins: [solid(), wails("./bindings")], -}); diff --git a/v3/internal/templates/solid/template.json b/v3/internal/templates/solid/template.json deleted file mode 100644 index 87591ef3d..000000000 --- a/v3/internal/templates/solid/template.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "name": "Solid + Vite", - "shortname": "solid", - "author": "Lea Anthony", - "description": "Solid + Vite development server", - "helpurl": "https://wails.io", - "version": "v0.0.1", - "schema": 3 -} \ No newline at end of file diff --git a/v3/internal/templates/svelte-ts/frontend/.gitignore b/v3/internal/templates/svelte-ts/frontend/.gitignore deleted file mode 100644 index a547bf36d..000000000 --- a/v3/internal/templates/svelte-ts/frontend/.gitignore +++ /dev/null @@ -1,24 +0,0 @@ -# Logs -logs -*.log -npm-debug.log* -yarn-debug.log* -yarn-error.log* -pnpm-debug.log* -lerna-debug.log* - -node_modules -dist -dist-ssr -*.local - -# Editor directories and files -.vscode/* -!.vscode/extensions.json -.idea -.DS_Store -*.suo -*.ntvs* -*.njsproj -*.sln -*.sw? diff --git a/v3/internal/templates/svelte-ts/frontend/.vscode/extensions.json b/v3/internal/templates/svelte-ts/frontend/.vscode/extensions.json deleted file mode 100644 index bdef82015..000000000 --- a/v3/internal/templates/svelte-ts/frontend/.vscode/extensions.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "recommendations": ["svelte.svelte-vscode"] -} diff --git a/v3/internal/templates/svelte-ts/frontend/index.html b/v3/internal/templates/svelte-ts/frontend/index.html deleted file mode 100644 index 02e1fd7d1..000000000 --- a/v3/internal/templates/svelte-ts/frontend/index.html +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - Wails + Svelte + TS - - -
                    - - - diff --git a/v3/internal/templates/svelte-ts/frontend/package.json b/v3/internal/templates/svelte-ts/frontend/package.json deleted file mode 100644 index c14954e77..000000000 --- a/v3/internal/templates/svelte-ts/frontend/package.json +++ /dev/null @@ -1,25 +0,0 @@ -{ - "name": "frontend", - "private": true, - "version": "0.0.0", - "type": "module", - "scripts": { - "dev": "vite", - "build:dev": "vite build --minify false --mode development", - "build": "vite build --mode production", - "preview": "vite preview", - "check": "svelte-check --tsconfig ./tsconfig.json" - }, - "dependencies": { - "@wailsio/runtime": "latest" - }, - "devDependencies": { - "@sveltejs/vite-plugin-svelte": "^3.0.1", - "@tsconfig/svelte": "^5.0.2", - "svelte": "^4.2.8", - "svelte-check": "^3.6.2", - "tslib": "^2.6.2", - "typescript": "^5.2.2", - "vite": "^5.0.8" - } -} diff --git a/v3/internal/templates/svelte-ts/frontend/public/Inter-Medium.ttf b/v3/internal/templates/svelte-ts/frontend/public/Inter-Medium.ttf deleted file mode 100644 index a01f3777a..000000000 Binary files a/v3/internal/templates/svelte-ts/frontend/public/Inter-Medium.ttf and /dev/null differ diff --git a/v3/internal/templates/svelte-ts/frontend/public/style.css b/v3/internal/templates/svelte-ts/frontend/public/style.css deleted file mode 100644 index 0b9c58279..000000000 --- a/v3/internal/templates/svelte-ts/frontend/public/style.css +++ /dev/null @@ -1,157 +0,0 @@ -:root { - font-family: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", - "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", - sans-serif; - font-size: 16px; - line-height: 24px; - font-weight: 400; - color-scheme: light dark; - color: rgba(255, 255, 255, 0.87); - background-color: rgba(27, 38, 54, 1); - font-synthesis: none; - text-rendering: optimizeLegibility; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - -webkit-text-size-adjust: 100%; - user-select: none; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; -} - -@font-face { - font-family: "Inter"; - font-style: normal; - font-weight: 400; - src: local(""), - url("./Inter-Medium.ttf") format("truetype"); -} - -h3 { - font-size: 3em; - line-height: 1.1; -} - -a { - font-weight: 500; - color: #646cff; - text-decoration: inherit; -} - -a:hover { - color: #535bf2; -} - -button { - width: 60px; - height: 30px; - line-height: 30px; - border-radius: 3px; - border: none; - margin: 0 0 0 20px; - padding: 0 8px; - cursor: pointer; -} - -.result { - height: 20px; - line-height: 20px; -} - -body { - margin: 0; - display: flex; - place-items: center; - place-content: center; - min-width: 320px; - min-height: 100vh; -} - -.container { - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; -} - -h1 { - font-size: 3.2em; - line-height: 1.1; -} - -#app { - max-width: 1280px; - margin: 0 auto; - padding: 2rem; - text-align: center; -} - -.logo { - height: 6em; - padding: 1.5em; - will-change: filter; -} - -.logo:hover { - filter: drop-shadow(0 0 2em #e80000aa); -} - -.logo.vanilla:hover { - filter: drop-shadow(0 0 2em #f7df1eaa); -} - -.result { - height: 20px; - line-height: 20px; - margin: 1.5rem auto; - text-align: center; -} - -.footer { - margin-top: 1rem; - align-content: center; - text-align: center; -} - -@media (prefers-color-scheme: light) { - :root { - color: #213547; - background-color: #ffffff; - } - - a:hover { - color: #747bff; - } - - button { - background-color: #f9f9f9; - } -} - - -.input-box .btn:hover { - background-image: linear-gradient(to top, #cfd9df 0%, #e2ebf0 100%); - color: #333333; -} - -.input-box .input { - border: none; - border-radius: 3px; - outline: none; - height: 30px; - line-height: 30px; - padding: 0 10px; - color: black; - background-color: rgba(240, 240, 240, 1); - -webkit-font-smoothing: antialiased; -} - -.input-box .input:hover { - border: none; - background-color: rgba(255, 255, 255, 1); -} - -.input-box .input:focus { - border: none; - background-color: rgba(255, 255, 255, 1); -} \ No newline at end of file diff --git a/v3/internal/templates/svelte-ts/frontend/public/svelte.svg b/v3/internal/templates/svelte-ts/frontend/public/svelte.svg deleted file mode 100644 index c5e08481f..000000000 --- a/v3/internal/templates/svelte-ts/frontend/public/svelte.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/v3/internal/templates/svelte-ts/frontend/public/wails.png b/v3/internal/templates/svelte-ts/frontend/public/wails.png deleted file mode 100644 index 8bdf42483..000000000 Binary files a/v3/internal/templates/svelte-ts/frontend/public/wails.png and /dev/null differ diff --git a/v3/internal/templates/svelte-ts/frontend/src/App.svelte.tmpl b/v3/internal/templates/svelte-ts/frontend/src/App.svelte.tmpl deleted file mode 100644 index b1a7a7ead..000000000 --- a/v3/internal/templates/svelte-ts/frontend/src/App.svelte.tmpl +++ /dev/null @@ -1,51 +0,0 @@ - - -
                    -
                    - - - - - - -
                    -

                    Wails + Svelte

                    -
                    {result}
                    -
                    -
                    - - -
                    -
                    - -
                    - - diff --git a/v3/internal/templates/svelte-ts/frontend/src/main.ts b/v3/internal/templates/svelte-ts/frontend/src/main.ts deleted file mode 100644 index fb363569d..000000000 --- a/v3/internal/templates/svelte-ts/frontend/src/main.ts +++ /dev/null @@ -1,7 +0,0 @@ -import App from './App.svelte' - -const app = new App({ - target: document.getElementById('app'), -}) - -export default app diff --git a/v3/internal/templates/svelte-ts/frontend/src/vite-env.d.ts b/v3/internal/templates/svelte-ts/frontend/src/vite-env.d.ts deleted file mode 100644 index 4078e7476..000000000 --- a/v3/internal/templates/svelte-ts/frontend/src/vite-env.d.ts +++ /dev/null @@ -1,2 +0,0 @@ -/// -/// diff --git a/v3/internal/templates/svelte-ts/frontend/svelte.config.js b/v3/internal/templates/svelte-ts/frontend/svelte.config.js deleted file mode 100644 index b0683fd24..000000000 --- a/v3/internal/templates/svelte-ts/frontend/svelte.config.js +++ /dev/null @@ -1,7 +0,0 @@ -import { vitePreprocess } from '@sveltejs/vite-plugin-svelte' - -export default { - // Consult https://svelte.dev/docs#compile-time-svelte-preprocess - // for more information about preprocessors - preprocess: vitePreprocess(), -} diff --git a/v3/internal/templates/svelte-ts/frontend/tsconfig.json b/v3/internal/templates/svelte-ts/frontend/tsconfig.json deleted file mode 100644 index 6925f49d7..000000000 --- a/v3/internal/templates/svelte-ts/frontend/tsconfig.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "extends": "@tsconfig/svelte/tsconfig.json", - "compilerOptions": { - "target": "ESNext", - "useDefineForClassFields": true, - "module": "ESNext", - "resolveJsonModule": true, - /** - * Typecheck JS in `.svelte` and `.js` files by default. - * Disable checkJs if you'd like to use dynamic types in JS. - * Note that setting allowJs false does not prevent the use - * of JS in `.svelte` files. - */ - "allowJs": true, - "checkJs": true, - "isolatedModules": true - }, - "include": ["src/**/*.ts", "src/**/*.js", "src/**/*.svelte", "bindings"], -} diff --git a/v3/internal/templates/svelte-ts/frontend/vite.config.ts b/v3/internal/templates/svelte-ts/frontend/vite.config.ts deleted file mode 100644 index a9c90ba39..000000000 --- a/v3/internal/templates/svelte-ts/frontend/vite.config.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { defineConfig } from "vite"; -import { svelte } from "@sveltejs/vite-plugin-svelte"; -import wails from "@wailsio/runtime/plugins/vite"; - -// https://vitejs.dev/config/ -export default defineConfig({ - plugins: [svelte(), wails("./bindings")], -}); diff --git a/v3/internal/templates/svelte-ts/template.json b/v3/internal/templates/svelte-ts/template.json deleted file mode 100644 index 597ae44db..000000000 --- a/v3/internal/templates/svelte-ts/template.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "name": "Svelte + Vite (Typescript)", - "shortname": "svelte-ts", - "author": "Lea Anthony", - "description": "Svelte + TS + Vite development server", - "helpurl": "https://wails.io", - "version": "v0.0.1", - "schema": 3 -} \ No newline at end of file diff --git a/v3/internal/templates/svelte/frontend/.gitignore b/v3/internal/templates/svelte/frontend/.gitignore deleted file mode 100644 index a547bf36d..000000000 --- a/v3/internal/templates/svelte/frontend/.gitignore +++ /dev/null @@ -1,24 +0,0 @@ -# Logs -logs -*.log -npm-debug.log* -yarn-debug.log* -yarn-error.log* -pnpm-debug.log* -lerna-debug.log* - -node_modules -dist -dist-ssr -*.local - -# Editor directories and files -.vscode/* -!.vscode/extensions.json -.idea -.DS_Store -*.suo -*.ntvs* -*.njsproj -*.sln -*.sw? diff --git a/v3/internal/templates/svelte/frontend/.vscode/extensions.json b/v3/internal/templates/svelte/frontend/.vscode/extensions.json deleted file mode 100644 index bdef82015..000000000 --- a/v3/internal/templates/svelte/frontend/.vscode/extensions.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "recommendations": ["svelte.svelte-vscode"] -} diff --git a/v3/internal/templates/svelte/frontend/index.html b/v3/internal/templates/svelte/frontend/index.html deleted file mode 100644 index 20f11c0c0..000000000 --- a/v3/internal/templates/svelte/frontend/index.html +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - Wails + Svelte - - -
                    - - - diff --git a/v3/internal/templates/svelte/frontend/package.json b/v3/internal/templates/svelte/frontend/package.json deleted file mode 100644 index 4655c0e95..000000000 --- a/v3/internal/templates/svelte/frontend/package.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "name": "frontend", - "private": true, - "version": "0.0.0", - "type": "module", - "scripts": { - "dev": "vite", - "build:dev": "vite build --minify false --mode development", - "build": "vite build --mode production", - "preview": "vite preview" - }, - "dependencies": { - "@wailsio/runtime": "latest" - }, - "devDependencies": { - "@sveltejs/vite-plugin-svelte": "^3.0.1", - "svelte": "^4.2.8", - "vite": "^5.0.8" - } -} diff --git a/v3/internal/templates/svelte/frontend/public/Inter-Medium.ttf b/v3/internal/templates/svelte/frontend/public/Inter-Medium.ttf deleted file mode 100644 index a01f3777a..000000000 Binary files a/v3/internal/templates/svelte/frontend/public/Inter-Medium.ttf and /dev/null differ diff --git a/v3/internal/templates/svelte/frontend/public/style.css b/v3/internal/templates/svelte/frontend/public/style.css deleted file mode 100644 index 0b9c58279..000000000 --- a/v3/internal/templates/svelte/frontend/public/style.css +++ /dev/null @@ -1,157 +0,0 @@ -:root { - font-family: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", - "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", - sans-serif; - font-size: 16px; - line-height: 24px; - font-weight: 400; - color-scheme: light dark; - color: rgba(255, 255, 255, 0.87); - background-color: rgba(27, 38, 54, 1); - font-synthesis: none; - text-rendering: optimizeLegibility; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - -webkit-text-size-adjust: 100%; - user-select: none; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; -} - -@font-face { - font-family: "Inter"; - font-style: normal; - font-weight: 400; - src: local(""), - url("./Inter-Medium.ttf") format("truetype"); -} - -h3 { - font-size: 3em; - line-height: 1.1; -} - -a { - font-weight: 500; - color: #646cff; - text-decoration: inherit; -} - -a:hover { - color: #535bf2; -} - -button { - width: 60px; - height: 30px; - line-height: 30px; - border-radius: 3px; - border: none; - margin: 0 0 0 20px; - padding: 0 8px; - cursor: pointer; -} - -.result { - height: 20px; - line-height: 20px; -} - -body { - margin: 0; - display: flex; - place-items: center; - place-content: center; - min-width: 320px; - min-height: 100vh; -} - -.container { - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; -} - -h1 { - font-size: 3.2em; - line-height: 1.1; -} - -#app { - max-width: 1280px; - margin: 0 auto; - padding: 2rem; - text-align: center; -} - -.logo { - height: 6em; - padding: 1.5em; - will-change: filter; -} - -.logo:hover { - filter: drop-shadow(0 0 2em #e80000aa); -} - -.logo.vanilla:hover { - filter: drop-shadow(0 0 2em #f7df1eaa); -} - -.result { - height: 20px; - line-height: 20px; - margin: 1.5rem auto; - text-align: center; -} - -.footer { - margin-top: 1rem; - align-content: center; - text-align: center; -} - -@media (prefers-color-scheme: light) { - :root { - color: #213547; - background-color: #ffffff; - } - - a:hover { - color: #747bff; - } - - button { - background-color: #f9f9f9; - } -} - - -.input-box .btn:hover { - background-image: linear-gradient(to top, #cfd9df 0%, #e2ebf0 100%); - color: #333333; -} - -.input-box .input { - border: none; - border-radius: 3px; - outline: none; - height: 30px; - line-height: 30px; - padding: 0 10px; - color: black; - background-color: rgba(240, 240, 240, 1); - -webkit-font-smoothing: antialiased; -} - -.input-box .input:hover { - border: none; - background-color: rgba(255, 255, 255, 1); -} - -.input-box .input:focus { - border: none; - background-color: rgba(255, 255, 255, 1); -} \ No newline at end of file diff --git a/v3/internal/templates/svelte/frontend/public/svelte.svg b/v3/internal/templates/svelte/frontend/public/svelte.svg deleted file mode 100644 index c5e08481f..000000000 --- a/v3/internal/templates/svelte/frontend/public/svelte.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/v3/internal/templates/svelte/frontend/public/wails.png b/v3/internal/templates/svelte/frontend/public/wails.png deleted file mode 100644 index 8bdf42483..000000000 Binary files a/v3/internal/templates/svelte/frontend/public/wails.png and /dev/null differ diff --git a/v3/internal/templates/svelte/frontend/src/App.svelte.tmpl b/v3/internal/templates/svelte/frontend/src/App.svelte.tmpl deleted file mode 100644 index f2e7aa1b1..000000000 --- a/v3/internal/templates/svelte/frontend/src/App.svelte.tmpl +++ /dev/null @@ -1,51 +0,0 @@ - - -
                    -
                    - - - - - - -
                    -

                    Wails + Svelte

                    -
                    {result}
                    -
                    -
                    - - -
                    -
                    - -
                    - - diff --git a/v3/internal/templates/svelte/frontend/src/main.js b/v3/internal/templates/svelte/frontend/src/main.js deleted file mode 100644 index fb363569d..000000000 --- a/v3/internal/templates/svelte/frontend/src/main.js +++ /dev/null @@ -1,7 +0,0 @@ -import App from './App.svelte' - -const app = new App({ - target: document.getElementById('app'), -}) - -export default app diff --git a/v3/internal/templates/svelte/frontend/src/vite-env.d.ts b/v3/internal/templates/svelte/frontend/src/vite-env.d.ts deleted file mode 100644 index 4078e7476..000000000 --- a/v3/internal/templates/svelte/frontend/src/vite-env.d.ts +++ /dev/null @@ -1,2 +0,0 @@ -/// -/// diff --git a/v3/internal/templates/svelte/frontend/tsconfig.json b/v3/internal/templates/svelte/frontend/tsconfig.json deleted file mode 100644 index 445179f36..000000000 --- a/v3/internal/templates/svelte/frontend/tsconfig.json +++ /dev/null @@ -1,25 +0,0 @@ -/** - * This file tells your IDE where the root of your JavaScript project is, and sets some - * options that it can use to provide autocompletion and other features. - */ -{ - "compilerOptions": { - "allowJs": true, - "moduleResolution": "bundler", - /** - * The target and module can be set to ESNext to allow writing modern JavaScript, - * and Vite will compile down to the level of "build.target" specified in the vite config file. - * Builds will error if you use a feature that cannot be compiled down to the target level. - */ - "target": "ESNext", - "module": "ESNext", - "resolveJsonModule": true, - /** - * Enable checkJs if you'd like type checking in `.svelte` and `.js` files. - */ - "checkJs": false, - "strict": true, - "skipLibCheck": true, - }, - "include": ["src/**/*.d.ts", "src/**/*.js", "src/**/*.svelte", "bindings"] -} diff --git a/v3/internal/templates/svelte/frontend/vite.config.js b/v3/internal/templates/svelte/frontend/vite.config.js deleted file mode 100644 index a9c90ba39..000000000 --- a/v3/internal/templates/svelte/frontend/vite.config.js +++ /dev/null @@ -1,8 +0,0 @@ -import { defineConfig } from "vite"; -import { svelte } from "@sveltejs/vite-plugin-svelte"; -import wails from "@wailsio/runtime/plugins/vite"; - -// https://vitejs.dev/config/ -export default defineConfig({ - plugins: [svelte(), wails("./bindings")], -}); diff --git a/v3/internal/templates/svelte/template.json b/v3/internal/templates/svelte/template.json deleted file mode 100644 index 2a3da7371..000000000 --- a/v3/internal/templates/svelte/template.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "name": "Svelte + Vite", - "shortname": "svelte", - "author": "Lea Anthony", - "description": "Svelte + Vite development server", - "helpurl": "https://wails.io", - "version": "v0.0.1", - "schema": 3 -} \ No newline at end of file diff --git a/v3/internal/templates/sveltekit-ts/frontend/.gitignore b/v3/internal/templates/sveltekit-ts/frontend/.gitignore deleted file mode 100644 index 79518f716..000000000 --- a/v3/internal/templates/sveltekit-ts/frontend/.gitignore +++ /dev/null @@ -1,21 +0,0 @@ -node_modules - -# Output -.output -.vercel -/.svelte-kit -/build - -# OS -.DS_Store -Thumbs.db - -# Env -.env -.env.* -!.env.example -!.env.test - -# Vite -vite.config.js.timestamp-* -vite.config.ts.timestamp-* diff --git a/v3/internal/templates/sveltekit-ts/frontend/.npmrc b/v3/internal/templates/sveltekit-ts/frontend/.npmrc deleted file mode 100644 index b6f27f135..000000000 --- a/v3/internal/templates/sveltekit-ts/frontend/.npmrc +++ /dev/null @@ -1 +0,0 @@ -engine-strict=true diff --git a/v3/internal/templates/sveltekit-ts/frontend/README.md b/v3/internal/templates/sveltekit-ts/frontend/README.md deleted file mode 100644 index 5ce676612..000000000 --- a/v3/internal/templates/sveltekit-ts/frontend/README.md +++ /dev/null @@ -1,38 +0,0 @@ -# create-svelte - -Everything you need to build a Svelte project, powered by [`create-svelte`](https://github.com/sveltejs/kit/tree/main/packages/create-svelte). - -## Creating a project - -If you're seeing this, you've probably already done this step. Congrats! - -```bash -# create a new project in the current directory -npm create svelte@latest - -# create a new project in my-app -npm create svelte@latest my-app -``` - -## Developing - -Once you've created a project and installed dependencies with `npm install` (or `pnpm install` or `yarn`), start a development server: - -```bash -npm run dev - -# or start the server and open the app in a new browser tab -npm run dev -- --open -``` - -## Building - -To create a production version of your app: - -```bash -npm run build -``` - -You can preview the production build with `npm run preview`. - -> To deploy your app, you may need to install an [adapter](https://kit.svelte.dev/docs/adapters) for your target environment. diff --git a/v3/internal/templates/sveltekit-ts/frontend/package.json b/v3/internal/templates/sveltekit-ts/frontend/package.json deleted file mode 100644 index a0418917b..000000000 --- a/v3/internal/templates/sveltekit-ts/frontend/package.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "name": "frontend", - "version": "0.0.1", - "private": true, - "type": "module", - "scripts": { - "dev": "vite dev", - "build:dev": "vite build --minify false --mode development", - "build": "vite build --mode production", - "preview": "vite preview", - "check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json", - "check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch" - }, - "dependencies": { - "@wailsio/runtime": "latest" - }, - "devDependencies": { - "@sveltejs/adapter-static": "^3.0.5", - "@sveltejs/kit": "^2.0.0", - "@sveltejs/vite-plugin-svelte": "^3.0.0", - "svelte": "^4.2.7", - "svelte-check": "^4.0.0", - "typescript": "^5.0.0", - "vite": "^5.0.3" - } -} diff --git a/v3/internal/templates/sveltekit-ts/frontend/src/app.d.ts b/v3/internal/templates/sveltekit-ts/frontend/src/app.d.ts deleted file mode 100644 index 743f07b2e..000000000 --- a/v3/internal/templates/sveltekit-ts/frontend/src/app.d.ts +++ /dev/null @@ -1,13 +0,0 @@ -// See https://kit.svelte.dev/docs/types#app -// for information about these interfaces -declare global { - namespace App { - // interface Error {} - // interface Locals {} - // interface PageData {} - // interface PageState {} - // interface Platform {} - } -} - -export {}; diff --git a/v3/internal/templates/sveltekit-ts/frontend/src/app.html b/v3/internal/templates/sveltekit-ts/frontend/src/app.html deleted file mode 100644 index 2db551d71..000000000 --- a/v3/internal/templates/sveltekit-ts/frontend/src/app.html +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - %sveltekit.head% - - -
                    %sveltekit.body%
                    - - diff --git a/v3/internal/templates/sveltekit-ts/frontend/src/lib/index.ts b/v3/internal/templates/sveltekit-ts/frontend/src/lib/index.ts deleted file mode 100644 index 856f2b6c3..000000000 --- a/v3/internal/templates/sveltekit-ts/frontend/src/lib/index.ts +++ /dev/null @@ -1 +0,0 @@ -// place files you want to import through the `$lib` alias in this folder. diff --git a/v3/internal/templates/sveltekit-ts/frontend/src/routes/+layout.ts b/v3/internal/templates/sveltekit-ts/frontend/src/routes/+layout.ts deleted file mode 100644 index ceccaaf67..000000000 --- a/v3/internal/templates/sveltekit-ts/frontend/src/routes/+layout.ts +++ /dev/null @@ -1,2 +0,0 @@ -export const prerender = true; -export const ssr = false; diff --git a/v3/internal/templates/sveltekit-ts/frontend/src/routes/+page.svelte.tmpl b/v3/internal/templates/sveltekit-ts/frontend/src/routes/+page.svelte.tmpl deleted file mode 100644 index 4191d6c12..000000000 --- a/v3/internal/templates/sveltekit-ts/frontend/src/routes/+page.svelte.tmpl +++ /dev/null @@ -1,50 +0,0 @@ - - -
                    -
                    - - - - - - -
                    -

                    Wails + Svelte

                    -
                    {result}
                    -
                    -
                    - - -
                    -
                    - -
                    - - diff --git a/v3/internal/templates/sveltekit-ts/frontend/static/Inter-Medium.ttf b/v3/internal/templates/sveltekit-ts/frontend/static/Inter-Medium.ttf deleted file mode 100644 index a01f3777a..000000000 Binary files a/v3/internal/templates/sveltekit-ts/frontend/static/Inter-Medium.ttf and /dev/null differ diff --git a/v3/internal/templates/sveltekit-ts/frontend/static/favicon.png b/v3/internal/templates/sveltekit-ts/frontend/static/favicon.png deleted file mode 100644 index 825b9e65a..000000000 Binary files a/v3/internal/templates/sveltekit-ts/frontend/static/favicon.png and /dev/null differ diff --git a/v3/internal/templates/sveltekit-ts/frontend/static/style.css b/v3/internal/templates/sveltekit-ts/frontend/static/style.css deleted file mode 100644 index 0b9c58279..000000000 --- a/v3/internal/templates/sveltekit-ts/frontend/static/style.css +++ /dev/null @@ -1,157 +0,0 @@ -:root { - font-family: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", - "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", - sans-serif; - font-size: 16px; - line-height: 24px; - font-weight: 400; - color-scheme: light dark; - color: rgba(255, 255, 255, 0.87); - background-color: rgba(27, 38, 54, 1); - font-synthesis: none; - text-rendering: optimizeLegibility; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - -webkit-text-size-adjust: 100%; - user-select: none; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; -} - -@font-face { - font-family: "Inter"; - font-style: normal; - font-weight: 400; - src: local(""), - url("./Inter-Medium.ttf") format("truetype"); -} - -h3 { - font-size: 3em; - line-height: 1.1; -} - -a { - font-weight: 500; - color: #646cff; - text-decoration: inherit; -} - -a:hover { - color: #535bf2; -} - -button { - width: 60px; - height: 30px; - line-height: 30px; - border-radius: 3px; - border: none; - margin: 0 0 0 20px; - padding: 0 8px; - cursor: pointer; -} - -.result { - height: 20px; - line-height: 20px; -} - -body { - margin: 0; - display: flex; - place-items: center; - place-content: center; - min-width: 320px; - min-height: 100vh; -} - -.container { - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; -} - -h1 { - font-size: 3.2em; - line-height: 1.1; -} - -#app { - max-width: 1280px; - margin: 0 auto; - padding: 2rem; - text-align: center; -} - -.logo { - height: 6em; - padding: 1.5em; - will-change: filter; -} - -.logo:hover { - filter: drop-shadow(0 0 2em #e80000aa); -} - -.logo.vanilla:hover { - filter: drop-shadow(0 0 2em #f7df1eaa); -} - -.result { - height: 20px; - line-height: 20px; - margin: 1.5rem auto; - text-align: center; -} - -.footer { - margin-top: 1rem; - align-content: center; - text-align: center; -} - -@media (prefers-color-scheme: light) { - :root { - color: #213547; - background-color: #ffffff; - } - - a:hover { - color: #747bff; - } - - button { - background-color: #f9f9f9; - } -} - - -.input-box .btn:hover { - background-image: linear-gradient(to top, #cfd9df 0%, #e2ebf0 100%); - color: #333333; -} - -.input-box .input { - border: none; - border-radius: 3px; - outline: none; - height: 30px; - line-height: 30px; - padding: 0 10px; - color: black; - background-color: rgba(240, 240, 240, 1); - -webkit-font-smoothing: antialiased; -} - -.input-box .input:hover { - border: none; - background-color: rgba(255, 255, 255, 1); -} - -.input-box .input:focus { - border: none; - background-color: rgba(255, 255, 255, 1); -} \ No newline at end of file diff --git a/v3/internal/templates/sveltekit-ts/frontend/static/svelte.svg b/v3/internal/templates/sveltekit-ts/frontend/static/svelte.svg deleted file mode 100644 index c5e08481f..000000000 --- a/v3/internal/templates/sveltekit-ts/frontend/static/svelte.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/v3/internal/templates/sveltekit-ts/frontend/static/wails.png b/v3/internal/templates/sveltekit-ts/frontend/static/wails.png deleted file mode 100644 index 8bdf42483..000000000 Binary files a/v3/internal/templates/sveltekit-ts/frontend/static/wails.png and /dev/null differ diff --git a/v3/internal/templates/sveltekit-ts/frontend/svelte.config.js b/v3/internal/templates/sveltekit-ts/frontend/svelte.config.js deleted file mode 100644 index 7acd75386..000000000 --- a/v3/internal/templates/sveltekit-ts/frontend/svelte.config.js +++ /dev/null @@ -1,21 +0,0 @@ -import adapter from '@sveltejs/adapter-static'; -import { vitePreprocess } from '@sveltejs/vite-plugin-svelte'; - -/** @type {import('@sveltejs/kit').Config} */ -const config = { - preprocess: vitePreprocess(), - kit: { - // adapter-auto only supports some environments, see https://kit.svelte.dev/docs/adapter-auto for a list. - // If your environment is not supported, or you settled on a specific environment, switch out the adapter. - // See https://kit.svelte.dev/docs/adapters for more information about adapters. - adapter: adapter({ - pages: 'dist', - assets: 'dist', - fallback: undefined, - precompress: false, - strict: true - }) - } -}; - -export default config; diff --git a/v3/internal/templates/sveltekit-ts/frontend/tsconfig.json b/v3/internal/templates/sveltekit-ts/frontend/tsconfig.json deleted file mode 100644 index 2de4494e1..000000000 --- a/v3/internal/templates/sveltekit-ts/frontend/tsconfig.json +++ /dev/null @@ -1,21 +0,0 @@ -{ - "extends": "./.svelte-kit/tsconfig.json", - "compilerOptions": { - "allowJs": true, - "checkJs": true, - "esModuleInterop": true, - "forceConsistentCasingInFileNames": true, - "resolveJsonModule": true, - "skipLibCheck": true, - "sourceMap": true, - "strict": true, - "allowUnusedLabels": true, - "noUnusedLocals": false, - "moduleResolution": "bundler" - } - // Path aliases are handled by https://kit.svelte.dev/docs/configuration#alias - // except $lib which is handled by https://kit.svelte.dev/docs/configuration#files - // - // If you want to overwrite includes/excludes, make sure to copy over the relevant includes/excludes - // from the referenced tsconfig.json - TypeScript does not merge them in -} diff --git a/v3/internal/templates/sveltekit-ts/frontend/vite.config.ts b/v3/internal/templates/sveltekit-ts/frontend/vite.config.ts deleted file mode 100644 index 5495c1564..000000000 --- a/v3/internal/templates/sveltekit-ts/frontend/vite.config.ts +++ /dev/null @@ -1,17 +0,0 @@ -import { sveltekit } from "@sveltejs/kit/vite"; -import { defineConfig, searchForWorkspaceRoot } from "vite"; -import wails from "@wailsio/runtime/plugins/vite"; - -export default defineConfig({ - server: { - fs: { - allow: [ - // search up for workspace root - searchForWorkspaceRoot(process.cwd()), - // your custom rules - "./bindings/*", - ], - }, - }, - plugins: [sveltekit(), wails("./bindings")], -}); diff --git a/v3/internal/templates/sveltekit-ts/template.json b/v3/internal/templates/sveltekit-ts/template.json deleted file mode 100644 index f4fab015d..000000000 --- a/v3/internal/templates/sveltekit-ts/template.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "name": "SvelteKit Typescript + Vite", - "shortname": "sveltekit-ts", - "author": "Atterpac", - "description": "SvelteKit + TS + Vite development server", - "helpurl": "https://wails.io", - "version": "v0.0.1", - "schema": 3 -} diff --git a/v3/internal/templates/sveltekit/frontend/.gitignore b/v3/internal/templates/sveltekit/frontend/.gitignore deleted file mode 100644 index 79518f716..000000000 --- a/v3/internal/templates/sveltekit/frontend/.gitignore +++ /dev/null @@ -1,21 +0,0 @@ -node_modules - -# Output -.output -.vercel -/.svelte-kit -/build - -# OS -.DS_Store -Thumbs.db - -# Env -.env -.env.* -!.env.example -!.env.test - -# Vite -vite.config.js.timestamp-* -vite.config.ts.timestamp-* diff --git a/v3/internal/templates/sveltekit/frontend/.npmrc b/v3/internal/templates/sveltekit/frontend/.npmrc deleted file mode 100644 index b6f27f135..000000000 --- a/v3/internal/templates/sveltekit/frontend/.npmrc +++ /dev/null @@ -1 +0,0 @@ -engine-strict=true diff --git a/v3/internal/templates/sveltekit/frontend/README.md b/v3/internal/templates/sveltekit/frontend/README.md deleted file mode 100644 index 5ce676612..000000000 --- a/v3/internal/templates/sveltekit/frontend/README.md +++ /dev/null @@ -1,38 +0,0 @@ -# create-svelte - -Everything you need to build a Svelte project, powered by [`create-svelte`](https://github.com/sveltejs/kit/tree/main/packages/create-svelte). - -## Creating a project - -If you're seeing this, you've probably already done this step. Congrats! - -```bash -# create a new project in the current directory -npm create svelte@latest - -# create a new project in my-app -npm create svelte@latest my-app -``` - -## Developing - -Once you've created a project and installed dependencies with `npm install` (or `pnpm install` or `yarn`), start a development server: - -```bash -npm run dev - -# or start the server and open the app in a new browser tab -npm run dev -- --open -``` - -## Building - -To create a production version of your app: - -```bash -npm run build -``` - -You can preview the production build with `npm run preview`. - -> To deploy your app, you may need to install an [adapter](https://kit.svelte.dev/docs/adapters) for your target environment. diff --git a/v3/internal/templates/sveltekit/frontend/frontend/style.css b/v3/internal/templates/sveltekit/frontend/frontend/style.css deleted file mode 100644 index 0b9c58279..000000000 --- a/v3/internal/templates/sveltekit/frontend/frontend/style.css +++ /dev/null @@ -1,157 +0,0 @@ -:root { - font-family: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", - "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", - sans-serif; - font-size: 16px; - line-height: 24px; - font-weight: 400; - color-scheme: light dark; - color: rgba(255, 255, 255, 0.87); - background-color: rgba(27, 38, 54, 1); - font-synthesis: none; - text-rendering: optimizeLegibility; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - -webkit-text-size-adjust: 100%; - user-select: none; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; -} - -@font-face { - font-family: "Inter"; - font-style: normal; - font-weight: 400; - src: local(""), - url("./Inter-Medium.ttf") format("truetype"); -} - -h3 { - font-size: 3em; - line-height: 1.1; -} - -a { - font-weight: 500; - color: #646cff; - text-decoration: inherit; -} - -a:hover { - color: #535bf2; -} - -button { - width: 60px; - height: 30px; - line-height: 30px; - border-radius: 3px; - border: none; - margin: 0 0 0 20px; - padding: 0 8px; - cursor: pointer; -} - -.result { - height: 20px; - line-height: 20px; -} - -body { - margin: 0; - display: flex; - place-items: center; - place-content: center; - min-width: 320px; - min-height: 100vh; -} - -.container { - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; -} - -h1 { - font-size: 3.2em; - line-height: 1.1; -} - -#app { - max-width: 1280px; - margin: 0 auto; - padding: 2rem; - text-align: center; -} - -.logo { - height: 6em; - padding: 1.5em; - will-change: filter; -} - -.logo:hover { - filter: drop-shadow(0 0 2em #e80000aa); -} - -.logo.vanilla:hover { - filter: drop-shadow(0 0 2em #f7df1eaa); -} - -.result { - height: 20px; - line-height: 20px; - margin: 1.5rem auto; - text-align: center; -} - -.footer { - margin-top: 1rem; - align-content: center; - text-align: center; -} - -@media (prefers-color-scheme: light) { - :root { - color: #213547; - background-color: #ffffff; - } - - a:hover { - color: #747bff; - } - - button { - background-color: #f9f9f9; - } -} - - -.input-box .btn:hover { - background-image: linear-gradient(to top, #cfd9df 0%, #e2ebf0 100%); - color: #333333; -} - -.input-box .input { - border: none; - border-radius: 3px; - outline: none; - height: 30px; - line-height: 30px; - padding: 0 10px; - color: black; - background-color: rgba(240, 240, 240, 1); - -webkit-font-smoothing: antialiased; -} - -.input-box .input:hover { - border: none; - background-color: rgba(255, 255, 255, 1); -} - -.input-box .input:focus { - border: none; - background-color: rgba(255, 255, 255, 1); -} \ No newline at end of file diff --git a/v3/internal/templates/sveltekit/frontend/package.json b/v3/internal/templates/sveltekit/frontend/package.json deleted file mode 100644 index fe7426489..000000000 --- a/v3/internal/templates/sveltekit/frontend/package.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "name": "frontend", - "version": "0.0.1", - "private": true, - "type": "module", - "scripts": { - "dev": "vite dev", - "build:dev": "vite build --minify false --mode development", - "build": "vite build --mode production", - "preview": "vite preview", - "check": "svelte-kit sync && svelte-check --tsconfig ./jsconfig.json", - "check:watch": "svelte-kit sync && svelte-check --tsconfig ./jsconfig.json --watch" - }, - "dependencies": { - "@wailsio/runtime": "latest" - }, - "devDependencies": { - "@sveltejs/adapter-static": "^3.0.5", - "@sveltejs/kit": "^2.0.0", - "@sveltejs/vite-plugin-svelte": "^3.0.0", - "svelte": "^4.2.7", - "vite": "^5.0.3" - } -} diff --git a/v3/internal/templates/sveltekit/frontend/src/app.html b/v3/internal/templates/sveltekit/frontend/src/app.html deleted file mode 100644 index d72bd3485..000000000 --- a/v3/internal/templates/sveltekit/frontend/src/app.html +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - %sveltekit.head% - - -
                    %sveltekit.body%
                    - - diff --git a/v3/internal/templates/sveltekit/frontend/src/lib/index.js b/v3/internal/templates/sveltekit/frontend/src/lib/index.js deleted file mode 100644 index 856f2b6c3..000000000 --- a/v3/internal/templates/sveltekit/frontend/src/lib/index.js +++ /dev/null @@ -1 +0,0 @@ -// place files you want to import through the `$lib` alias in this folder. diff --git a/v3/internal/templates/sveltekit/frontend/src/routes/+layout.js b/v3/internal/templates/sveltekit/frontend/src/routes/+layout.js deleted file mode 100644 index ceccaaf67..000000000 --- a/v3/internal/templates/sveltekit/frontend/src/routes/+layout.js +++ /dev/null @@ -1,2 +0,0 @@ -export const prerender = true; -export const ssr = false; diff --git a/v3/internal/templates/sveltekit/frontend/src/routes/+page.svelte.tmpl b/v3/internal/templates/sveltekit/frontend/src/routes/+page.svelte.tmpl deleted file mode 100644 index 4191d6c12..000000000 --- a/v3/internal/templates/sveltekit/frontend/src/routes/+page.svelte.tmpl +++ /dev/null @@ -1,50 +0,0 @@ - - -
                    -
                    - - - - - - -
                    -

                    Wails + Svelte

                    -
                    {result}
                    -
                    -
                    - - -
                    -
                    - -
                    - - diff --git a/v3/internal/templates/sveltekit/frontend/static/Inter-Medium.ttf b/v3/internal/templates/sveltekit/frontend/static/Inter-Medium.ttf deleted file mode 100644 index a01f3777a..000000000 Binary files a/v3/internal/templates/sveltekit/frontend/static/Inter-Medium.ttf and /dev/null differ diff --git a/v3/internal/templates/sveltekit/frontend/static/style.css b/v3/internal/templates/sveltekit/frontend/static/style.css deleted file mode 100644 index 0b9c58279..000000000 --- a/v3/internal/templates/sveltekit/frontend/static/style.css +++ /dev/null @@ -1,157 +0,0 @@ -:root { - font-family: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", - "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", - sans-serif; - font-size: 16px; - line-height: 24px; - font-weight: 400; - color-scheme: light dark; - color: rgba(255, 255, 255, 0.87); - background-color: rgba(27, 38, 54, 1); - font-synthesis: none; - text-rendering: optimizeLegibility; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - -webkit-text-size-adjust: 100%; - user-select: none; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; -} - -@font-face { - font-family: "Inter"; - font-style: normal; - font-weight: 400; - src: local(""), - url("./Inter-Medium.ttf") format("truetype"); -} - -h3 { - font-size: 3em; - line-height: 1.1; -} - -a { - font-weight: 500; - color: #646cff; - text-decoration: inherit; -} - -a:hover { - color: #535bf2; -} - -button { - width: 60px; - height: 30px; - line-height: 30px; - border-radius: 3px; - border: none; - margin: 0 0 0 20px; - padding: 0 8px; - cursor: pointer; -} - -.result { - height: 20px; - line-height: 20px; -} - -body { - margin: 0; - display: flex; - place-items: center; - place-content: center; - min-width: 320px; - min-height: 100vh; -} - -.container { - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; -} - -h1 { - font-size: 3.2em; - line-height: 1.1; -} - -#app { - max-width: 1280px; - margin: 0 auto; - padding: 2rem; - text-align: center; -} - -.logo { - height: 6em; - padding: 1.5em; - will-change: filter; -} - -.logo:hover { - filter: drop-shadow(0 0 2em #e80000aa); -} - -.logo.vanilla:hover { - filter: drop-shadow(0 0 2em #f7df1eaa); -} - -.result { - height: 20px; - line-height: 20px; - margin: 1.5rem auto; - text-align: center; -} - -.footer { - margin-top: 1rem; - align-content: center; - text-align: center; -} - -@media (prefers-color-scheme: light) { - :root { - color: #213547; - background-color: #ffffff; - } - - a:hover { - color: #747bff; - } - - button { - background-color: #f9f9f9; - } -} - - -.input-box .btn:hover { - background-image: linear-gradient(to top, #cfd9df 0%, #e2ebf0 100%); - color: #333333; -} - -.input-box .input { - border: none; - border-radius: 3px; - outline: none; - height: 30px; - line-height: 30px; - padding: 0 10px; - color: black; - background-color: rgba(240, 240, 240, 1); - -webkit-font-smoothing: antialiased; -} - -.input-box .input:hover { - border: none; - background-color: rgba(255, 255, 255, 1); -} - -.input-box .input:focus { - border: none; - background-color: rgba(255, 255, 255, 1); -} \ No newline at end of file diff --git a/v3/internal/templates/sveltekit/frontend/static/svelte.svg b/v3/internal/templates/sveltekit/frontend/static/svelte.svg deleted file mode 100644 index c5e08481f..000000000 --- a/v3/internal/templates/sveltekit/frontend/static/svelte.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/v3/internal/templates/sveltekit/frontend/static/wails.png b/v3/internal/templates/sveltekit/frontend/static/wails.png deleted file mode 100644 index 8bdf42483..000000000 Binary files a/v3/internal/templates/sveltekit/frontend/static/wails.png and /dev/null differ diff --git a/v3/internal/templates/sveltekit/frontend/svelte.config.js b/v3/internal/templates/sveltekit/frontend/svelte.config.js deleted file mode 100644 index 7f2998d89..000000000 --- a/v3/internal/templates/sveltekit/frontend/svelte.config.js +++ /dev/null @@ -1,19 +0,0 @@ -import adapter from '@sveltejs/adapter-static'; - -/** @type {import('@sveltejs/kit').Config} */ -const config = { - kit: { - // adapter-auto only supports some environments, see https://kit.svelte.dev/docs/adapter-auto for a list. - // If your environment is not supported, or you settled on a specific environment, switch out the adapter. - // See https://kit.svelte.dev/docs/adapters for more information about adapters. - adapter: adapter({ - pages: 'dist', - assets: 'dist', - fallback: undefined, - precompress: false, - strict: true - }) - } -}; - -export default config; diff --git a/v3/internal/templates/sveltekit/frontend/tsconfig.json b/v3/internal/templates/sveltekit/frontend/tsconfig.json deleted file mode 100644 index 3a60c268c..000000000 --- a/v3/internal/templates/sveltekit/frontend/tsconfig.json +++ /dev/null @@ -1,25 +0,0 @@ -/** - * This file tells your IDE where the root of your JavaScript project is, and sets some - * options that it can use to provide autocompletion and other features. - */ -{ - "compilerOptions": { - "allowJs": true, - "moduleResolution": "bundler", - /** - * The target and module can be set to ESNext to allow writing modern JavaScript, - * and Vite will compile down to the level of "build.target" specified in the vite config file. - * Builds will error if you use a feature that cannot be compiled down to the target level. - */ - "target": "ESNext", - "module": "ESNext", - "resolveJsonModule": true, - /** - * Enable checkJs if you'd like type checking in `.svelte` and `.js` files. - */ - "checkJs": false, - "strict": true, - "skipLibCheck": true, - }, - "include": ["src/**/*.d.ts", "src/**/*.js", "src/**/*.svelte", "bindings/**/*.d.ts"] -} diff --git a/v3/internal/templates/sveltekit/frontend/vite.config.js b/v3/internal/templates/sveltekit/frontend/vite.config.js deleted file mode 100644 index d9aa89049..000000000 --- a/v3/internal/templates/sveltekit/frontend/vite.config.js +++ /dev/null @@ -1,18 +0,0 @@ -import { sveltekit } from "@sveltejs/kit/vite"; -import { defineConfig, searchForWorkspaceRoot } from "vite"; -import wails from "@wailsio/runtime/plugins/vite"; - -// https://vitejs.dev/config/ -export default defineConfig({ - plugins: [sveltekit(), wails("./bindings")], - server: { - fs: { - allow: [ - // search up for workspace root - searchForWorkspaceRoot(process.cwd()), - // your custom rules - "./bindings/*", - ], - }, - }, -}); diff --git a/v3/internal/templates/sveltekit/template.json b/v3/internal/templates/sveltekit/template.json deleted file mode 100644 index f81f2813b..000000000 --- a/v3/internal/templates/sveltekit/template.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "name": "SvelteKit Typescript + Vite", - "shortname": "svelte-ts", - "author": "Atterpac", - "description": "SvelteKit + Vite development server", - "helpurl": "https://wails.io", - "version": "v0.0.1", - "schema": 3 -} diff --git a/v3/internal/templates/templates.go b/v3/internal/templates/templates.go deleted file mode 100644 index 9c96655d9..000000000 --- a/v3/internal/templates/templates.go +++ /dev/null @@ -1,483 +0,0 @@ -package templates - -import ( - "embed" - "encoding/json" - "fmt" - "io/fs" - "os" - "os/exec" - "path/filepath" - "runtime" - "strings" - - "github.com/wailsapp/wails/v3/internal/buildinfo" - "github.com/wailsapp/wails/v3/internal/s" - "github.com/wailsapp/wails/v3/internal/version" - - "github.com/go-git/go-git/v5" - "github.com/go-git/go-git/v5/plumbing" - "github.com/pkg/errors" - "github.com/pterm/pterm" - "github.com/wailsapp/wails/v3/internal/debug" - - "github.com/wailsapp/wails/v3/internal/flags" - - "github.com/leaanthony/gosod" - - "github.com/samber/lo" -) - -//go:embed * -var templates embed.FS - -type TemplateData struct { - Name string - Description string - FS fs.FS -} - -var defaultTemplates = []TemplateData{} - -func init() { - dirs, err := templates.ReadDir(".") - if err != nil { - return - } - for _, dir := range dirs { - if strings.HasPrefix(dir.Name(), "_") { - continue - } - if dir.IsDir() { - template, err := parseTemplate(templates, dir.Name()) - if err != nil { - continue - } - defaultTemplates = append(defaultTemplates, - TemplateData{ - Name: dir.Name(), - Description: template.Description, - FS: templates, - }) - } - } -} - -func ValidTemplateName(name string) bool { - return lo.ContainsBy(defaultTemplates, func(template TemplateData) bool { - return template.Name == name - }) -} - -func GetDefaultTemplates() []TemplateData { - return defaultTemplates -} - -type TemplateOptions struct { - *flags.Init - LocalModulePath string - UseTypescript bool - WailsVersion string -} - -func getInternalTemplate(templateName string) (*Template, error) { - templateData, found := lo.Find(defaultTemplates, func(template TemplateData) bool { - return template.Name == templateName - }) - - if !found { - return nil, nil - } - - template, err := parseTemplate(templateData.FS, templateData.Name) - if err != nil { - return nil, err - } - template.source = sourceInternal - return &template, nil -} - -func getLocalTemplate(templateName string) (*Template, error) { - var template Template - var err error - _, err = os.Stat(templateName) - if err != nil { - return nil, nil - } - - template, err = parseTemplate(os.DirFS(templateName), "") - if err != nil { - println("err2 = ", err.Error()) - return nil, err - } - template.source = sourceLocal - - return &template, nil -} - -type BaseTemplate struct { - Name string `json:"name" description:"The name of the template"` - ShortName string `json:"shortname" description:"The short name of the template"` - Author string `json:"author" description:"The author of the template"` - Description string `json:"description" description:"The template description"` - HelpURL string `json:"helpurl" description:"The help url for the template"` - Version string `json:"version" description:"The version of the template" default:"v0.0.1"` - Dir string `json:"-" description:"The directory to generate the template" default:"."` - Frontend string `json:"-" description:"The frontend directory to migrate"` -} - -type source int - -const ( - sourceInternal source = 1 - sourceLocal source = 2 - sourceRemote source = 3 -) - -// Template holds data relating to a template including the metadata stored in template.yaml -type Template struct { - BaseTemplate - Schema uint8 `json:"schema"` - - // Other data - FS fs.FS `json:"-"` - source source - tempDir string -} - -func parseTemplate(template fs.FS, templateName string) (Template, error) { - var result Template - jsonFile := "template.json" - if templateName != "" { - jsonFile = templateName + "/template.json" - } - data, err := fs.ReadFile(template, jsonFile) - if err != nil { - return result, errors.Wrap(err, "Error parsing template") - } - err = json.Unmarshal(data, &result) - if err != nil { - return result, err - } - result.FS = template - - // We need to do a version check here - if result.Schema == 0 { - return result, fmt.Errorf("template not supported by wails 3. This template is probably for wails 2") - } - if result.Schema != 3 { - return result, fmt.Errorf("template version %s is not supported by wails 3. Ensure 'version' is set to 3 in the `template.json` file", result.Version) - } - - return result, nil -} - -// Clones the given uri and returns the temporary cloned directory -func gitclone(uri string) (string, error) { - // Create temporary directory - dirname, err := os.MkdirTemp("", "wails-template-*") - if err != nil { - return "", err - } - - // Parse remote template url and version number - templateInfo := strings.Split(uri, "@") - cloneOption := &git.CloneOptions{ - URL: templateInfo[0], - } - if len(templateInfo) > 1 { - cloneOption.ReferenceName = plumbing.NewTagReferenceName(templateInfo[1]) - } - - _, err = git.PlainClone(dirname, false, cloneOption) - - return dirname, err - -} - -func getRemoteTemplate(uri string) (*Template, error) { - // git clone to temporary dir - var tempDir string - tempDir, err := gitclone(uri) - - if err != nil { - return nil, err - } - // Remove the .git directory - err = os.RemoveAll(filepath.Join(tempDir, ".git")) - if err != nil { - return nil, err - } - - templateFS := os.DirFS(tempDir) - var parsedTemplate Template - parsedTemplate, err = parseTemplate(templateFS, "") - if err != nil { - return nil, err - } - parsedTemplate.tempDir = tempDir - parsedTemplate.source = sourceRemote - return &parsedTemplate, nil -} - -func Install(options *flags.Init) error { - var wd = lo.Must(os.Getwd()) - var projectDir string - if options.ProjectDir == "." || options.ProjectDir == "" { - projectDir = wd - } else { - projectDir = options.ProjectDir - } - var err error - projectDir, err = filepath.Abs(filepath.Join(projectDir, options.ProjectName)) - if err != nil { - return err - } - - buildInfo, err := buildinfo.Get() - if err != nil { - return err - } - - // Calculate relative path from project directory to LocalModulePath - var localModulePath string - - // Use module path if it is set - if buildInfo.Development { - var relativePath string - // Check if the project directory and LocalModulePath are in the same drive - if filepath.VolumeName(wd) != filepath.VolumeName(debug.LocalModulePath) { - relativePath = debug.LocalModulePath - } else { - relativePath, err = filepath.Rel(projectDir, debug.LocalModulePath) - } - if err != nil { - return err - } - localModulePath = filepath.ToSlash(relativePath + "/") - } - UseTypescript := strings.HasSuffix(options.TemplateName, "-ts") - - templateData := TemplateOptions{ - Init: options, - LocalModulePath: localModulePath, - UseTypescript: UseTypescript, - WailsVersion: version.String(), - } - - defer func() { - // if `template.json` exists, remove it - _ = os.Remove(filepath.Join(templateData.ProjectDir, "template.json")) - }() - - var template *Template - - if ValidTemplateName(options.TemplateName) { - template, err = getInternalTemplate(options.TemplateName) - if err != nil { - return err - } - } else { - template, err = getLocalTemplate(options.TemplateName) - if err != nil { - return err - } - if template == nil { - template, err = getRemoteTemplate(options.TemplateName) - } - } - - if template == nil { - return fmt.Errorf("invalid template name: %s. Use -l flag to view available templates or use a valid filepath / url to a template", options.TemplateName) - } - - templateData.ProjectDir = projectDir - - // If project directory already exists and is not empty, error - if _, err := os.Stat(templateData.ProjectDir); !os.IsNotExist(err) { - // Check if the directory is empty - files := lo.Must(os.ReadDir(templateData.ProjectDir)) - if len(files) > 0 { - return fmt.Errorf("project directory '%s' already exists and is not empty", templateData.ProjectDir) - } - } - - if template.source == sourceRemote && !options.SkipWarning { - var confirmed = confirmRemote(template) - if !confirmed { - return nil - } - } - - pterm.Printf("Creating project\n") - pterm.Printf("----------------\n\n") - table := pterm.TableData{ - {"Project Name", options.ProjectName}, - {"Project Directory", filepath.FromSlash(options.ProjectDir)}, - {"Template", template.Name}, - {"Template Source", template.HelpURL}, - {"Template Version", template.Version}, - } - err = pterm.DefaultTable.WithData(table).Render() - if err != nil { - return err - } - - switch template.source { - case sourceInternal: - tfs, err := fs.Sub(template.FS, options.TemplateName) - if err != nil { - return err - } - common, err := fs.Sub(templates, "_common") - if err != nil { - return err - } - err = gosod.New(common).Extract(options.ProjectDir, templateData) - if err != nil { - return err - } - err = gosod.New(tfs).Extract(options.ProjectDir, templateData) - if err != nil { - return err - } - case sourceLocal, sourceRemote: - data := struct { - TemplateOptions - Dir string - Name string - BinaryName string - ProductName string - ProductDescription string - ProductVersion string - ProductCompany string - ProductCopyright string - ProductComments string - ProductIdentifier string - Silent bool - Typescript bool - }{ - Name: options.ProjectName, - Silent: true, - ProductCompany: options.ProductCompany, - ProductName: options.ProductName, - ProductDescription: options.ProductDescription, - ProductVersion: options.ProductVersion, - ProductIdentifier: options.ProductIdentifier, - ProductCopyright: options.ProductCopyright, - ProductComments: options.ProductComments, - Typescript: templateData.UseTypescript, - TemplateOptions: templateData, - } - // If options.ProjectDir does not exist, create it - if _, err := os.Stat(options.ProjectDir); os.IsNotExist(err) { - err = os.Mkdir(options.ProjectDir, 0755) - if err != nil { - return err - } - } - err = gosod.New(template.FS).Extract(options.ProjectDir, data) - if err != nil { - return err - } - - if template.tempDir != "" { - s.RMDIR(template.tempDir) - } - } - if !options.SkipGoModTidy { - err = goModTidy(templateData.ProjectDir) - if err != nil { - return err - } - } - - // Change to project directory - err = os.Chdir(templateData.ProjectDir) - if err != nil { - return err - } - - pterm.Printf("\nProject '%s' created successfully.\n", options.ProjectName) - - return nil - -} - -func GenerateTemplate(options *BaseTemplate) error { - if options.Name == "" { - return fmt.Errorf("please provide a template name using the -name flag") - } - - // Get current directory - baseOutputDir, err := filepath.Abs(options.Dir) - if err != nil { - return err - } - outDir := filepath.Join(baseOutputDir, options.Name) - - // Extract base files - _, filename, _, _ := runtime.Caller(0) - basePath := filepath.Join(filepath.Dir(filename), "_common") - s.COPYDIR2(basePath, outDir) - s.RMDIR(filepath.Join(outDir, "build")) - - // Copy frontend - targetFrontendPath := filepath.Join(outDir, "frontend") - sourceFrontendPath := options.Frontend - if sourceFrontendPath == "" { - sourceFrontendPath = filepath.Join(filepath.Dir(filename), "base", "frontend") - } - s.COPYDIR2(sourceFrontendPath, targetFrontendPath) - - // Copy files from relative directory ../commands/build_assets - // Get the path to THIS file - assetPath := filepath.Join(filepath.Dir(filename), "..", "commands", "build_assets") - assetdir := filepath.Join(outDir, "build") - - s.COPYDIR2(assetPath, assetdir) - - // Copy the template NEXTSTEPS.md - s.COPY(filepath.Join(filepath.Dir(filename), "base", "NEXTSTEPS.md"), filepath.Join(outDir, "NEXTSTEPS.md")) - - // Write the template.json file - templateJSON := filepath.Join(outDir, "template.json") - // Marshall - optionsJSON, err := json.MarshalIndent(&Template{ - BaseTemplate: *options, - Schema: 3, - }, "", " ") - if err != nil { - return err - } - err = os.WriteFile(templateJSON, optionsJSON, 0o755) - if err != nil { - return err - } - - fmt.Printf("Successfully generated template in %s\n", outDir) - return nil -} - -func confirmRemote(template *Template) bool { - pterm.Println(pterm.LightRed("\n--- REMOTE TEMPLATES ---")) - - // Create boxes with the title positioned differently and containing different content - pterm.Println(pterm.LightYellow("You are creating a project using a remote template.\nThe Wails project takes no responsibility for 3rd party templates.\nOnly use remote templates that you trust.")) - - result, _ := pterm.DefaultInteractiveConfirm.WithConfirmText("Are you sure you want to continue?").WithConfirmText("y").WithRejectText("n").Show() - - return result -} - -// goModTidy runs go mod tidy in the given project directory -// It returns an error if the command fails -func goModTidy(projectDir string) error { - cmd := exec.Command("go", "mod", "tidy") - cmd.Dir = projectDir - output, err := cmd.CombinedOutput() - if err != nil { - return fmt.Errorf("failed to run go mod tidy: %w\n%s", err, string(output)) - } - return nil -} diff --git a/v3/internal/templates/vanilla-ts/frontend/.gitignore b/v3/internal/templates/vanilla-ts/frontend/.gitignore deleted file mode 100644 index a547bf36d..000000000 --- a/v3/internal/templates/vanilla-ts/frontend/.gitignore +++ /dev/null @@ -1,24 +0,0 @@ -# Logs -logs -*.log -npm-debug.log* -yarn-debug.log* -yarn-error.log* -pnpm-debug.log* -lerna-debug.log* - -node_modules -dist -dist-ssr -*.local - -# Editor directories and files -.vscode/* -!.vscode/extensions.json -.idea -.DS_Store -*.suo -*.ntvs* -*.njsproj -*.sln -*.sw? diff --git a/v3/internal/templates/vanilla-ts/frontend/index.html b/v3/internal/templates/vanilla-ts/frontend/index.html deleted file mode 100644 index 3eb06610a..000000000 --- a/v3/internal/templates/vanilla-ts/frontend/index.html +++ /dev/null @@ -1,35 +0,0 @@ - - - - - - - - Wails App - - -
                    - -

                    Wails + Typescript

                    -
                    Please enter your name below 👇
                    -
                    -
                    - - -
                    -
                    - -
                    - - - diff --git a/v3/internal/templates/vanilla-ts/frontend/package.json b/v3/internal/templates/vanilla-ts/frontend/package.json deleted file mode 100644 index 2bf167fe2..000000000 --- a/v3/internal/templates/vanilla-ts/frontend/package.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "name": "frontend", - "private": true, - "version": "0.0.0", - "type": "module", - "scripts": { - "dev": "vite", - "build:dev": "vite build --minify false --mode development", - "build": "vite build --mode production", - "preview": "vite preview" - }, - "dependencies": { - "@wailsio/runtime": "latest" - }, - "devDependencies": { - "typescript": "^4.9.3", - "vite": "^5.0.0" - } -} diff --git a/v3/internal/templates/vanilla-ts/frontend/public/Inter-Medium.ttf b/v3/internal/templates/vanilla-ts/frontend/public/Inter-Medium.ttf deleted file mode 100644 index a01f3777a..000000000 Binary files a/v3/internal/templates/vanilla-ts/frontend/public/Inter-Medium.ttf and /dev/null differ diff --git a/v3/internal/templates/vanilla-ts/frontend/public/style.css b/v3/internal/templates/vanilla-ts/frontend/public/style.css deleted file mode 100644 index 0b9c58279..000000000 --- a/v3/internal/templates/vanilla-ts/frontend/public/style.css +++ /dev/null @@ -1,157 +0,0 @@ -:root { - font-family: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", - "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", - sans-serif; - font-size: 16px; - line-height: 24px; - font-weight: 400; - color-scheme: light dark; - color: rgba(255, 255, 255, 0.87); - background-color: rgba(27, 38, 54, 1); - font-synthesis: none; - text-rendering: optimizeLegibility; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - -webkit-text-size-adjust: 100%; - user-select: none; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; -} - -@font-face { - font-family: "Inter"; - font-style: normal; - font-weight: 400; - src: local(""), - url("./Inter-Medium.ttf") format("truetype"); -} - -h3 { - font-size: 3em; - line-height: 1.1; -} - -a { - font-weight: 500; - color: #646cff; - text-decoration: inherit; -} - -a:hover { - color: #535bf2; -} - -button { - width: 60px; - height: 30px; - line-height: 30px; - border-radius: 3px; - border: none; - margin: 0 0 0 20px; - padding: 0 8px; - cursor: pointer; -} - -.result { - height: 20px; - line-height: 20px; -} - -body { - margin: 0; - display: flex; - place-items: center; - place-content: center; - min-width: 320px; - min-height: 100vh; -} - -.container { - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; -} - -h1 { - font-size: 3.2em; - line-height: 1.1; -} - -#app { - max-width: 1280px; - margin: 0 auto; - padding: 2rem; - text-align: center; -} - -.logo { - height: 6em; - padding: 1.5em; - will-change: filter; -} - -.logo:hover { - filter: drop-shadow(0 0 2em #e80000aa); -} - -.logo.vanilla:hover { - filter: drop-shadow(0 0 2em #f7df1eaa); -} - -.result { - height: 20px; - line-height: 20px; - margin: 1.5rem auto; - text-align: center; -} - -.footer { - margin-top: 1rem; - align-content: center; - text-align: center; -} - -@media (prefers-color-scheme: light) { - :root { - color: #213547; - background-color: #ffffff; - } - - a:hover { - color: #747bff; - } - - button { - background-color: #f9f9f9; - } -} - - -.input-box .btn:hover { - background-image: linear-gradient(to top, #cfd9df 0%, #e2ebf0 100%); - color: #333333; -} - -.input-box .input { - border: none; - border-radius: 3px; - outline: none; - height: 30px; - line-height: 30px; - padding: 0 10px; - color: black; - background-color: rgba(240, 240, 240, 1); - -webkit-font-smoothing: antialiased; -} - -.input-box .input:hover { - border: none; - background-color: rgba(255, 255, 255, 1); -} - -.input-box .input:focus { - border: none; - background-color: rgba(255, 255, 255, 1); -} \ No newline at end of file diff --git a/v3/internal/templates/vanilla-ts/frontend/public/typescript.svg b/v3/internal/templates/vanilla-ts/frontend/public/typescript.svg deleted file mode 100644 index d91c910cc..000000000 --- a/v3/internal/templates/vanilla-ts/frontend/public/typescript.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/v3/internal/templates/vanilla-ts/frontend/public/wails.png b/v3/internal/templates/vanilla-ts/frontend/public/wails.png deleted file mode 100644 index 8bdf42483..000000000 Binary files a/v3/internal/templates/vanilla-ts/frontend/public/wails.png and /dev/null differ diff --git a/v3/internal/templates/vanilla-ts/frontend/src/main.ts.tmpl b/v3/internal/templates/vanilla-ts/frontend/src/main.ts.tmpl deleted file mode 100644 index 87dae063f..000000000 --- a/v3/internal/templates/vanilla-ts/frontend/src/main.ts.tmpl +++ /dev/null @@ -1,23 +0,0 @@ -import {Events} from "@wailsio/runtime"; -import {GreetService} from "../bindings/{{js .ModulePath}}"; - -const greetButton = document.getElementById('greet')! as HTMLButtonElement; -const resultElement = document.getElementById('result')! as HTMLDivElement; -const nameElement : HTMLInputElement = document.getElementById('name')! as HTMLInputElement; -const timeElement = document.getElementById('time')! as HTMLDivElement; - -greetButton.addEventListener('click', async () => { - let name = (nameElement as HTMLInputElement).value - if (!name) { - name = 'anonymous'; - } - try { - resultElement.innerText = await GreetService.Greet(name); - } catch (err) { - console.error(err); - } -}); - -Events.On('time', (time) => { - timeElement.innerText = time.data; -}); diff --git a/v3/internal/templates/vanilla-ts/frontend/src/vite-env.d.ts b/v3/internal/templates/vanilla-ts/frontend/src/vite-env.d.ts deleted file mode 100644 index 11f02fe2a..000000000 --- a/v3/internal/templates/vanilla-ts/frontend/src/vite-env.d.ts +++ /dev/null @@ -1 +0,0 @@ -/// diff --git a/v3/internal/templates/vanilla-ts/frontend/tsconfig.json b/v3/internal/templates/vanilla-ts/frontend/tsconfig.json deleted file mode 100644 index 53c9f903e..000000000 --- a/v3/internal/templates/vanilla-ts/frontend/tsconfig.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "compilerOptions": { - "allowJs": true, - - "noEmit": true, - "skipLibCheck": true, - - "module": "ESNext", - "moduleResolution": "bundler", - "resolveJsonModule": true, - "isolatedModules": true, - "verbatimModuleSyntax": true, - - "lib": [ - "DOM", - "DOM.Iterable", - "ESNext", - ], - - "strict": true, - "noUnusedLocals": true, - "noUnusedParameters": false, - "noImplicitAny": false, - "noImplicitReturns": true, - "noFallthroughCasesInSwitch": true, - }, - "include": ["src", "bindings"] -} diff --git a/v3/internal/templates/vanilla-ts/frontend/vite.config.ts b/v3/internal/templates/vanilla-ts/frontend/vite.config.ts deleted file mode 100644 index 56f2d6a8a..000000000 --- a/v3/internal/templates/vanilla-ts/frontend/vite.config.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { defineConfig } from "vite"; -import wails from "@wailsio/runtime/plugins/vite"; - -// https://vitejs.dev/config/ -export default defineConfig({ - plugins: [wails("./bindings")], -}); diff --git a/v3/internal/templates/vanilla-ts/template.json b/v3/internal/templates/vanilla-ts/template.json deleted file mode 100644 index 6d9e55107..000000000 --- a/v3/internal/templates/vanilla-ts/template.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "name": "Vanilla + Vite (Typescript)", - "shortname": "vanilla-ts", - "author": "Lea Anthony", - "description": "Vanilla + TS + Vite development server", - "helpurl": "https://wails.io", - "version": "v0.0.1", - "schema": 3 -} \ No newline at end of file diff --git a/v3/internal/templates/vanilla/frontend/.gitignore b/v3/internal/templates/vanilla/frontend/.gitignore deleted file mode 100644 index a547bf36d..000000000 --- a/v3/internal/templates/vanilla/frontend/.gitignore +++ /dev/null @@ -1,24 +0,0 @@ -# Logs -logs -*.log -npm-debug.log* -yarn-debug.log* -yarn-error.log* -pnpm-debug.log* -lerna-debug.log* - -node_modules -dist -dist-ssr -*.local - -# Editor directories and files -.vscode/* -!.vscode/extensions.json -.idea -.DS_Store -*.suo -*.ntvs* -*.njsproj -*.sln -*.sw? diff --git a/v3/internal/templates/vanilla/frontend/index.html b/v3/internal/templates/vanilla/frontend/index.html deleted file mode 100644 index 798204fa9..000000000 --- a/v3/internal/templates/vanilla/frontend/index.html +++ /dev/null @@ -1,35 +0,0 @@ - - - - - - - - Wails App - - -
                    - -

                    Wails + Javascript

                    -
                    -
                    Please enter your name below 👇
                    -
                    - - -
                    -
                    - -
                    - - - diff --git a/v3/internal/templates/vanilla/frontend/package.json b/v3/internal/templates/vanilla/frontend/package.json deleted file mode 100644 index 0a118e984..000000000 --- a/v3/internal/templates/vanilla/frontend/package.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "name": "frontend", - "private": true, - "version": "0.0.0", - "type": "module", - "scripts": { - "dev": "vite", - "build:dev": "vite build --minify false --mode development", - "build": "vite build --mode production", - "preview": "vite preview" - }, - "dependencies": { - "@wailsio/runtime": "latest" - }, - "devDependencies": { - "vite": "^5.0.0" - } -} diff --git a/v3/internal/templates/vanilla/frontend/public/Inter-Medium.ttf b/v3/internal/templates/vanilla/frontend/public/Inter-Medium.ttf deleted file mode 100644 index a01f3777a..000000000 Binary files a/v3/internal/templates/vanilla/frontend/public/Inter-Medium.ttf and /dev/null differ diff --git a/v3/internal/templates/vanilla/frontend/public/javascript.svg b/v3/internal/templates/vanilla/frontend/public/javascript.svg deleted file mode 100644 index f9abb2b72..000000000 --- a/v3/internal/templates/vanilla/frontend/public/javascript.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/v3/internal/templates/vanilla/frontend/public/style.css b/v3/internal/templates/vanilla/frontend/public/style.css deleted file mode 100644 index 0b9c58279..000000000 --- a/v3/internal/templates/vanilla/frontend/public/style.css +++ /dev/null @@ -1,157 +0,0 @@ -:root { - font-family: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", - "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", - sans-serif; - font-size: 16px; - line-height: 24px; - font-weight: 400; - color-scheme: light dark; - color: rgba(255, 255, 255, 0.87); - background-color: rgba(27, 38, 54, 1); - font-synthesis: none; - text-rendering: optimizeLegibility; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - -webkit-text-size-adjust: 100%; - user-select: none; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; -} - -@font-face { - font-family: "Inter"; - font-style: normal; - font-weight: 400; - src: local(""), - url("./Inter-Medium.ttf") format("truetype"); -} - -h3 { - font-size: 3em; - line-height: 1.1; -} - -a { - font-weight: 500; - color: #646cff; - text-decoration: inherit; -} - -a:hover { - color: #535bf2; -} - -button { - width: 60px; - height: 30px; - line-height: 30px; - border-radius: 3px; - border: none; - margin: 0 0 0 20px; - padding: 0 8px; - cursor: pointer; -} - -.result { - height: 20px; - line-height: 20px; -} - -body { - margin: 0; - display: flex; - place-items: center; - place-content: center; - min-width: 320px; - min-height: 100vh; -} - -.container { - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; -} - -h1 { - font-size: 3.2em; - line-height: 1.1; -} - -#app { - max-width: 1280px; - margin: 0 auto; - padding: 2rem; - text-align: center; -} - -.logo { - height: 6em; - padding: 1.5em; - will-change: filter; -} - -.logo:hover { - filter: drop-shadow(0 0 2em #e80000aa); -} - -.logo.vanilla:hover { - filter: drop-shadow(0 0 2em #f7df1eaa); -} - -.result { - height: 20px; - line-height: 20px; - margin: 1.5rem auto; - text-align: center; -} - -.footer { - margin-top: 1rem; - align-content: center; - text-align: center; -} - -@media (prefers-color-scheme: light) { - :root { - color: #213547; - background-color: #ffffff; - } - - a:hover { - color: #747bff; - } - - button { - background-color: #f9f9f9; - } -} - - -.input-box .btn:hover { - background-image: linear-gradient(to top, #cfd9df 0%, #e2ebf0 100%); - color: #333333; -} - -.input-box .input { - border: none; - border-radius: 3px; - outline: none; - height: 30px; - line-height: 30px; - padding: 0 10px; - color: black; - background-color: rgba(240, 240, 240, 1); - -webkit-font-smoothing: antialiased; -} - -.input-box .input:hover { - border: none; - background-color: rgba(255, 255, 255, 1); -} - -.input-box .input:focus { - border: none; - background-color: rgba(255, 255, 255, 1); -} \ No newline at end of file diff --git a/v3/internal/templates/vanilla/frontend/public/wails.png b/v3/internal/templates/vanilla/frontend/public/wails.png deleted file mode 100644 index 8bdf42483..000000000 Binary files a/v3/internal/templates/vanilla/frontend/public/wails.png and /dev/null differ diff --git a/v3/internal/templates/vanilla/frontend/src/main.js.tmpl b/v3/internal/templates/vanilla/frontend/src/main.js.tmpl deleted file mode 100644 index 2b256789d..000000000 --- a/v3/internal/templates/vanilla/frontend/src/main.js.tmpl +++ /dev/null @@ -1,21 +0,0 @@ -import {Events} from "@wailsio/runtime"; -import {GreetService} from "../bindings/{{js .ModulePath}}"; - -const resultElement = document.getElementById('result'); -const timeElement = document.getElementById('time'); - -window.doGreet = async () => { - let name = document.getElementById('name').value; - if (!name) { - name = 'anonymous'; - } - try { - resultElement.innerText = await GreetService.Greet(name); - } catch (err) { - console.error(err); - } -} - -Events.On('time', (time) => { - timeElement.innerText = time.data; -}); diff --git a/v3/internal/templates/vanilla/frontend/tsconfig.json b/v3/internal/templates/vanilla/frontend/tsconfig.json deleted file mode 100644 index f103fe3a9..000000000 --- a/v3/internal/templates/vanilla/frontend/tsconfig.json +++ /dev/null @@ -1,25 +0,0 @@ -/** - * This file tells your IDE where the root of your JavaScript project is, and sets some - * options that it can use to provide autocompletion and other features. - */ -{ - "compilerOptions": { - "allowJs": true, - "moduleResolution": "bundler", - /** - * The target and module can be set to ESNext to allow writing modern JavaScript, - * and Vite will compile down to the level of "build.target" specified in the vite config file. - * Builds will error if you use a feature that cannot be compiled down to the target level. - */ - "target": "ESNext", - "module": "ESNext", - "resolveJsonModule": true, - /** - * Enable checkJs if you'd like type checking in `.js` files. - */ - "checkJs": false, - "strict": true, - "skipLibCheck": true, - }, - "include": ["src", "bindings"] -} diff --git a/v3/internal/templates/vanilla/frontend/vite.config.js b/v3/internal/templates/vanilla/frontend/vite.config.js deleted file mode 100644 index 56f2d6a8a..000000000 --- a/v3/internal/templates/vanilla/frontend/vite.config.js +++ /dev/null @@ -1,7 +0,0 @@ -import { defineConfig } from "vite"; -import wails from "@wailsio/runtime/plugins/vite"; - -// https://vitejs.dev/config/ -export default defineConfig({ - plugins: [wails("./bindings")], -}); diff --git a/v3/internal/templates/vanilla/template.json b/v3/internal/templates/vanilla/template.json deleted file mode 100644 index 5f8a281a5..000000000 --- a/v3/internal/templates/vanilla/template.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "name": "Vanilla + Vite", - "shortname": "vanilla", - "author": "Lea Anthony", - "description": "Vanilla + Vite development server", - "helpurl": "https://wails.io", - "version": "v0.0.1", - "schema": 3 -} \ No newline at end of file diff --git a/v3/internal/templates/vue-ts/.vscode/extensions.json b/v3/internal/templates/vue-ts/.vscode/extensions.json deleted file mode 100644 index 86c616f02..000000000 --- a/v3/internal/templates/vue-ts/.vscode/extensions.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "recommendations": ["octref.vetur"] -} diff --git a/v3/internal/templates/vue-ts/frontend/.gitignore b/v3/internal/templates/vue-ts/frontend/.gitignore deleted file mode 100644 index a547bf36d..000000000 --- a/v3/internal/templates/vue-ts/frontend/.gitignore +++ /dev/null @@ -1,24 +0,0 @@ -# Logs -logs -*.log -npm-debug.log* -yarn-debug.log* -yarn-error.log* -pnpm-debug.log* -lerna-debug.log* - -node_modules -dist -dist-ssr -*.local - -# Editor directories and files -.vscode/* -!.vscode/extensions.json -.idea -.DS_Store -*.suo -*.ntvs* -*.njsproj -*.sln -*.sw? diff --git a/v3/internal/templates/vue-ts/frontend/.vscode/extensions.json b/v3/internal/templates/vue-ts/frontend/.vscode/extensions.json deleted file mode 100644 index c0a6e5a48..000000000 --- a/v3/internal/templates/vue-ts/frontend/.vscode/extensions.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "recommendations": ["Vue.volar", "Vue.vscode-typescript-vue-plugin"] -} diff --git a/v3/internal/templates/vue-ts/frontend/README.md b/v3/internal/templates/vue-ts/frontend/README.md deleted file mode 100644 index ef72fd524..000000000 --- a/v3/internal/templates/vue-ts/frontend/README.md +++ /dev/null @@ -1,18 +0,0 @@ -# Vue 3 + TypeScript + Vite - -This template should help get you started developing with Vue 3 and TypeScript in Vite. The template uses Vue 3 ` - - diff --git a/v3/internal/templates/vue-ts/frontend/package.json b/v3/internal/templates/vue-ts/frontend/package.json deleted file mode 100644 index dc08ffa11..000000000 --- a/v3/internal/templates/vue-ts/frontend/package.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "name": "frontend", - "private": true, - "version": "0.0.0", - "type": "module", - "scripts": { - "dev": "vite", - "build:dev": "vue-tsc && vite build --minify false --mode development", - "build": "vue-tsc && vite build --mode production", - "preview": "vite preview" - }, - "dependencies": { - "@wailsio/runtime": "latest", - "vue": "^3.2.45" - }, - "devDependencies": { - "@vitejs/plugin-vue": "^4.0.0", - "typescript": "^4.9.3", - "vite": "^5.0.0", - "vue-tsc": "^1.0.11" - } -} diff --git a/v3/internal/templates/vue-ts/frontend/public/Inter-Medium.ttf b/v3/internal/templates/vue-ts/frontend/public/Inter-Medium.ttf deleted file mode 100644 index a01f3777a..000000000 Binary files a/v3/internal/templates/vue-ts/frontend/public/Inter-Medium.ttf and /dev/null differ diff --git a/v3/internal/templates/vue-ts/frontend/public/style.css b/v3/internal/templates/vue-ts/frontend/public/style.css deleted file mode 100644 index 187e7e4b9..000000000 --- a/v3/internal/templates/vue-ts/frontend/public/style.css +++ /dev/null @@ -1,145 +0,0 @@ -:root { - font-family: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", - "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", - sans-serif; - font-size: 16px; - line-height: 24px; - font-weight: 400; - color-scheme: light dark; - color: rgba(255, 255, 255, 0.87); - background-color: rgba(27, 38, 54, 1); - font-synthesis: none; - text-rendering: optimizeLegibility; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - -webkit-text-size-adjust: 100%; -} - -* { - user-select: none; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; -} - -@font-face { - font-family: "Inter"; - font-style: normal; - font-weight: 400; - src: local(""), - url("./Inter-Medium.ttf") format("truetype"); -} - -h3 { - font-size: 3em; - line-height: 1.1; -} - -a { - font-weight: 500; - color: #646cff; - text-decoration: inherit; -} - -a:hover { - color: #535bf2; -} - -button { - width: 60px; - height: 30px; - line-height: 30px; - border-radius: 3px; - border: none; - margin: 0 0 0 20px; - padding: 0 8px; - cursor: pointer; -} - -.result { - height: 20px; - line-height: 20px; -} - -body { - margin: 0; - display: flex; - place-items: center; - place-content: center; - min-width: 320px; - min-height: 100vh; -} - -.container { - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; -} - -h1 { - font-size: 3.2em; - line-height: 1.1; -} - -#app { - max-width: 1280px; - margin: 0 auto; - text-align: center; -} - -.result { - height: 20px; - line-height: 20px; - margin: 1.5rem auto; - text-align: center; -} - -.footer { - margin-top: 1rem; - align-content: center; - text-align: center; -} - -@media (prefers-color-scheme: light) { - :root { - color: #213547; - background-color: #ffffff; - } - - a:hover { - color: #747bff; - } - - button { - background-color: #f9f9f9; - } -} - - -.input-box .btn:hover { - background-image: linear-gradient(to top, #cfd9df 0%, #e2ebf0 100%); - color: #333333; -} - -.input-box .input { - border: none; - border-radius: 3px; - outline: none; - height: 30px; - line-height: 30px; - padding: 0 10px; - color: black; - background-color: rgba(240, 240, 240, 1); - -webkit-font-smoothing: antialiased; -} - -.input-box .input:hover { - border: none; - background-color: rgba(255, 255, 255, 1); -} - -.input-box .input:focus { - border: none; - background-color: rgba(255, 255, 255, 1); -} \ No newline at end of file diff --git a/v3/internal/templates/vue-ts/frontend/public/vue.svg b/v3/internal/templates/vue-ts/frontend/public/vue.svg deleted file mode 100644 index 770e9d333..000000000 --- a/v3/internal/templates/vue-ts/frontend/public/vue.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/v3/internal/templates/vue-ts/frontend/public/wails.png b/v3/internal/templates/vue-ts/frontend/public/wails.png deleted file mode 100644 index 8bdf42483..000000000 Binary files a/v3/internal/templates/vue-ts/frontend/public/wails.png and /dev/null differ diff --git a/v3/internal/templates/vue-ts/frontend/src/App.vue b/v3/internal/templates/vue-ts/frontend/src/App.vue deleted file mode 100644 index 8f62a7e44..000000000 --- a/v3/internal/templates/vue-ts/frontend/src/App.vue +++ /dev/null @@ -1,31 +0,0 @@ - - - - - diff --git a/v3/internal/templates/vue-ts/frontend/src/components/HelloWorld.vue.tmpl b/v3/internal/templates/vue-ts/frontend/src/components/HelloWorld.vue.tmpl deleted file mode 100644 index 9e599ab80..000000000 --- a/v3/internal/templates/vue-ts/frontend/src/components/HelloWorld.vue.tmpl +++ /dev/null @@ -1,47 +0,0 @@ - - - diff --git a/v3/internal/templates/vue-ts/frontend/src/main.ts b/v3/internal/templates/vue-ts/frontend/src/main.ts deleted file mode 100644 index 01433bca2..000000000 --- a/v3/internal/templates/vue-ts/frontend/src/main.ts +++ /dev/null @@ -1,4 +0,0 @@ -import { createApp } from 'vue' -import App from './App.vue' - -createApp(App).mount('#app') diff --git a/v3/internal/templates/vue-ts/frontend/src/vite-env.d.ts b/v3/internal/templates/vue-ts/frontend/src/vite-env.d.ts deleted file mode 100644 index 11f02fe2a..000000000 --- a/v3/internal/templates/vue-ts/frontend/src/vite-env.d.ts +++ /dev/null @@ -1 +0,0 @@ -/// diff --git a/v3/internal/templates/vue-ts/frontend/tsconfig.json b/v3/internal/templates/vue-ts/frontend/tsconfig.json deleted file mode 100644 index 5e8658ed7..000000000 --- a/v3/internal/templates/vue-ts/frontend/tsconfig.json +++ /dev/null @@ -1,19 +0,0 @@ -{ - "compilerOptions": { - "target": "ESNext", - "useDefineForClassFields": true, - "module": "ESNext", - "moduleResolution": "Node", - "strict": true, - "noUnusedParameters": false, - "noImplicitAny": false, - "jsx": "preserve", - "resolveJsonModule": true, - "isolatedModules": true, - "esModuleInterop": true, - "lib": ["ESNext", "DOM"], - "skipLibCheck": true, - "noEmit": true - }, - "include": ["src/**/*.ts", "src/**/*.d.ts", "src/**/*.tsx", "src/**/*.vue", "bindings"], -} diff --git a/v3/internal/templates/vue-ts/frontend/vite.config.ts b/v3/internal/templates/vue-ts/frontend/vite.config.ts deleted file mode 100644 index 16127a822..000000000 --- a/v3/internal/templates/vue-ts/frontend/vite.config.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { defineConfig } from "vite"; -import vue from "@vitejs/plugin-vue"; -import wails from "@wailsio/runtime/plugins/vite"; - -// https://vitejs.dev/config/ -export default defineConfig({ - plugins: [vue(), wails("./bindings")], -}); diff --git a/v3/internal/templates/vue-ts/template.json b/v3/internal/templates/vue-ts/template.json deleted file mode 100644 index d87ef872e..000000000 --- a/v3/internal/templates/vue-ts/template.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "name": "Vue + Vite (Typescript)", - "shortname": "vue-ts", - "author": "Lea Anthony", - "description": "Vue + TS + Vite development server", - "helpurl": "https://wails.io", - "version": "v0.0.1", - "schema": 3 -} \ No newline at end of file diff --git a/v3/internal/templates/vue/.vscode/extensions.json b/v3/internal/templates/vue/.vscode/extensions.json deleted file mode 100644 index 86c616f02..000000000 --- a/v3/internal/templates/vue/.vscode/extensions.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "recommendations": ["octref.vetur"] -} diff --git a/v3/internal/templates/vue/frontend/.gitignore b/v3/internal/templates/vue/frontend/.gitignore deleted file mode 100644 index a547bf36d..000000000 --- a/v3/internal/templates/vue/frontend/.gitignore +++ /dev/null @@ -1,24 +0,0 @@ -# Logs -logs -*.log -npm-debug.log* -yarn-debug.log* -yarn-error.log* -pnpm-debug.log* -lerna-debug.log* - -node_modules -dist -dist-ssr -*.local - -# Editor directories and files -.vscode/* -!.vscode/extensions.json -.idea -.DS_Store -*.suo -*.ntvs* -*.njsproj -*.sln -*.sw? diff --git a/v3/internal/templates/vue/frontend/.vscode/extensions.json b/v3/internal/templates/vue/frontend/.vscode/extensions.json deleted file mode 100644 index c0a6e5a48..000000000 --- a/v3/internal/templates/vue/frontend/.vscode/extensions.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "recommendations": ["Vue.volar", "Vue.vscode-typescript-vue-plugin"] -} diff --git a/v3/internal/templates/vue/frontend/index.html b/v3/internal/templates/vue/frontend/index.html deleted file mode 100644 index 2700f93b9..000000000 --- a/v3/internal/templates/vue/frontend/index.html +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - Wails + Vue - - -
                    - - - diff --git a/v3/internal/templates/vue/frontend/package.json b/v3/internal/templates/vue/frontend/package.json deleted file mode 100644 index 6958956b3..000000000 --- a/v3/internal/templates/vue/frontend/package.json +++ /dev/null @@ -1,20 +0,0 @@ -{ - "name": "frontend", - "private": true, - "version": "0.0.0", - "type": "module", - "scripts": { - "dev": "vite", - "build:dev": "vite build --minify false --mode development", - "build": "vite build --mode production", - "preview": "vite preview" - }, - "dependencies": { - "@wailsio/runtime": "latest", - "vue": "^3.2.45" - }, - "devDependencies": { - "@vitejs/plugin-vue": "^4.0.0", - "vite": "^5.0.0" - } -} diff --git a/v3/internal/templates/vue/frontend/public/Inter-Medium.ttf b/v3/internal/templates/vue/frontend/public/Inter-Medium.ttf deleted file mode 100644 index a01f3777a..000000000 Binary files a/v3/internal/templates/vue/frontend/public/Inter-Medium.ttf and /dev/null differ diff --git a/v3/internal/templates/vue/frontend/public/style.css b/v3/internal/templates/vue/frontend/public/style.css deleted file mode 100644 index 187e7e4b9..000000000 --- a/v3/internal/templates/vue/frontend/public/style.css +++ /dev/null @@ -1,145 +0,0 @@ -:root { - font-family: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", - "Oxygen", "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue", - sans-serif; - font-size: 16px; - line-height: 24px; - font-weight: 400; - color-scheme: light dark; - color: rgba(255, 255, 255, 0.87); - background-color: rgba(27, 38, 54, 1); - font-synthesis: none; - text-rendering: optimizeLegibility; - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - -webkit-text-size-adjust: 100%; -} - -* { - user-select: none; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; -} - -@font-face { - font-family: "Inter"; - font-style: normal; - font-weight: 400; - src: local(""), - url("./Inter-Medium.ttf") format("truetype"); -} - -h3 { - font-size: 3em; - line-height: 1.1; -} - -a { - font-weight: 500; - color: #646cff; - text-decoration: inherit; -} - -a:hover { - color: #535bf2; -} - -button { - width: 60px; - height: 30px; - line-height: 30px; - border-radius: 3px; - border: none; - margin: 0 0 0 20px; - padding: 0 8px; - cursor: pointer; -} - -.result { - height: 20px; - line-height: 20px; -} - -body { - margin: 0; - display: flex; - place-items: center; - place-content: center; - min-width: 320px; - min-height: 100vh; -} - -.container { - display: flex; - flex-direction: column; - align-items: center; - justify-content: center; -} - -h1 { - font-size: 3.2em; - line-height: 1.1; -} - -#app { - max-width: 1280px; - margin: 0 auto; - text-align: center; -} - -.result { - height: 20px; - line-height: 20px; - margin: 1.5rem auto; - text-align: center; -} - -.footer { - margin-top: 1rem; - align-content: center; - text-align: center; -} - -@media (prefers-color-scheme: light) { - :root { - color: #213547; - background-color: #ffffff; - } - - a:hover { - color: #747bff; - } - - button { - background-color: #f9f9f9; - } -} - - -.input-box .btn:hover { - background-image: linear-gradient(to top, #cfd9df 0%, #e2ebf0 100%); - color: #333333; -} - -.input-box .input { - border: none; - border-radius: 3px; - outline: none; - height: 30px; - line-height: 30px; - padding: 0 10px; - color: black; - background-color: rgba(240, 240, 240, 1); - -webkit-font-smoothing: antialiased; -} - -.input-box .input:hover { - border: none; - background-color: rgba(255, 255, 255, 1); -} - -.input-box .input:focus { - border: none; - background-color: rgba(255, 255, 255, 1); -} \ No newline at end of file diff --git a/v3/internal/templates/vue/frontend/public/vue.svg b/v3/internal/templates/vue/frontend/public/vue.svg deleted file mode 100644 index 770e9d333..000000000 --- a/v3/internal/templates/vue/frontend/public/vue.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/v3/internal/templates/vue/frontend/public/wails.png b/v3/internal/templates/vue/frontend/public/wails.png deleted file mode 100644 index 8bdf42483..000000000 Binary files a/v3/internal/templates/vue/frontend/public/wails.png and /dev/null differ diff --git a/v3/internal/templates/vue/frontend/src/App.vue b/v3/internal/templates/vue/frontend/src/App.vue deleted file mode 100644 index 8af6ab35d..000000000 --- a/v3/internal/templates/vue/frontend/src/App.vue +++ /dev/null @@ -1,31 +0,0 @@ - - - - - diff --git a/v3/internal/templates/vue/frontend/src/components/HelloWorld.vue.tmpl b/v3/internal/templates/vue/frontend/src/components/HelloWorld.vue.tmpl deleted file mode 100644 index 99b5f88ce..000000000 --- a/v3/internal/templates/vue/frontend/src/components/HelloWorld.vue.tmpl +++ /dev/null @@ -1,49 +0,0 @@ - - - diff --git a/v3/internal/templates/vue/frontend/src/main.js b/v3/internal/templates/vue/frontend/src/main.js deleted file mode 100644 index 01433bca2..000000000 --- a/v3/internal/templates/vue/frontend/src/main.js +++ /dev/null @@ -1,4 +0,0 @@ -import { createApp } from 'vue' -import App from './App.vue' - -createApp(App).mount('#app') diff --git a/v3/internal/templates/vue/frontend/src/vite-env.d.ts b/v3/internal/templates/vue/frontend/src/vite-env.d.ts deleted file mode 100644 index 11f02fe2a..000000000 --- a/v3/internal/templates/vue/frontend/src/vite-env.d.ts +++ /dev/null @@ -1 +0,0 @@ -/// diff --git a/v3/internal/templates/vue/frontend/tsconfig.json b/v3/internal/templates/vue/frontend/tsconfig.json deleted file mode 100644 index bd83d39fe..000000000 --- a/v3/internal/templates/vue/frontend/tsconfig.json +++ /dev/null @@ -1,25 +0,0 @@ -/** - * This file tells your IDE where the root of your JavaScript project is, and sets some - * options that it can use to provide autocompletion and other features. - */ -{ - "compilerOptions": { - "allowJs": true, - "moduleResolution": "bundler", - /** - * The target and module can be set to ESNext to allow writing modern JavaScript, - * and Vite will compile down to the level of "build.target" specified in the vite config file. - * Builds will error if you use a feature that cannot be compiled down to the target level. - */ - "target": "ESNext", - "module": "ESNext", - "resolveJsonModule": true, - /** - * Enable checkJs if you'd like type checking in `.vue` and `.js` files. - */ - "checkJs": false, - "strict": true, - "skipLibCheck": true, - }, - "include": ["src/**/*.d.ts", "src/**/*.js", "src/**/*.jsx", "src/**/*.vue", "bindings"] -} diff --git a/v3/internal/templates/vue/frontend/vite.config.js b/v3/internal/templates/vue/frontend/vite.config.js deleted file mode 100644 index 16127a822..000000000 --- a/v3/internal/templates/vue/frontend/vite.config.js +++ /dev/null @@ -1,8 +0,0 @@ -import { defineConfig } from "vite"; -import vue from "@vitejs/plugin-vue"; -import wails from "@wailsio/runtime/plugins/vite"; - -// https://vitejs.dev/config/ -export default defineConfig({ - plugins: [vue(), wails("./bindings")], -}); diff --git a/v3/internal/templates/vue/template.json b/v3/internal/templates/vue/template.json deleted file mode 100644 index b6e8faf93..000000000 --- a/v3/internal/templates/vue/template.json +++ /dev/null @@ -1,9 +0,0 @@ -{ - "name": "Vue + Vite", - "shortname": "vue", - "author": "Lea Anthony", - "description": "Vue + Vite development server", - "helpurl": "https://wails.io", - "version": "v0.0.1", - "schema": 3 -} \ No newline at end of file diff --git a/v3/internal/term/term.go b/v3/internal/term/term.go deleted file mode 100644 index 9127ff08a..000000000 --- a/v3/internal/term/term.go +++ /dev/null @@ -1,127 +0,0 @@ -package term - -import ( - "fmt" - "os" - - "github.com/pterm/pterm" - "github.com/wailsapp/wails/v3/internal/generator/config" - "github.com/wailsapp/wails/v3/internal/version" - "golang.org/x/term" -) - -func Header(header string) { - // Print Wails with the current version in white on red background with the header in white with a green background - pterm.BgLightRed.Print(pterm.LightWhite(" Wails (" + version.String() + ") ")) - pterm.BgLightGreen.Println(pterm.LightWhite(" " + header + " ")) -} - -func IsTerminal() bool { - return term.IsTerminal(int(os.Stdout.Fd())) && (os.Getenv("CI") != "true") -} - -type Spinner struct { - spinner *pterm.SpinnerPrinter -} - -func (s Spinner) Logger() config.Logger { - return config.DefaultPtermLogger(s.spinner) -} - -func StartSpinner(text string) Spinner { - if !IsTerminal() { - return Spinner{} - } - spinner, err := pterm.DefaultSpinner.Start(text) - if err != nil { - return Spinner{} - } - spinner.RemoveWhenDone = true - return Spinner{spinner} -} - -func StopSpinner(s Spinner) { - if s.spinner != nil { - _ = s.spinner.Stop() - } -} - -func output(input any, printer pterm.PrefixPrinter, args ...any) { - switch v := input.(type) { - case string: - printer.Printfln(input.(string), args...) - case error: - printer.Println(v.Error()) - default: - printer.Printfln("%v", v) - } -} - -func Info(input any) { - output(input, pterm.Info) -} - -func Infof(input any, args ...interface{}) { - output(input, pterm.Info, args...) -} - -func Warning(input any) { - output(input, pterm.Warning) -} - -func Warningf(input any, args ...any) { - output(input, pterm.Warning, args...) -} - -func Error(input any) { - output(input, pterm.Error) -} - -func Success(input any) { - output(input, pterm.Success) -} - -func Section(s string) { - style := pterm.NewStyle(pterm.BgDefault, pterm.FgLightBlue, pterm.Bold) - style.Println("\n# " + s + " \n") -} - -func DisableColor() { - pterm.DisableColor() -} - -func EnableOutput() { - pterm.EnableOutput() -} - -func DisableOutput() { - pterm.DisableOutput() -} - -func EnableDebug() { - pterm.EnableDebugMessages() -} - -func DisableDebug() { - pterm.DisableDebugMessages() -} - -func Println(s string) { - pterm.Println(s) -} - -func Hyperlink(url, text string) string { - // OSC 8 sequence to start a clickable link - linkStart := "\x1b]8;;" - - // OSC 8 sequence to end a clickable link - linkEnd := "\x1b]8;;\x1b\\" - - // ANSI escape code for underline - underlineStart := "\x1b[4m" - - // ANSI escape code to reset text formatting - resetFormat := "\x1b[0m" - - return fmt.Sprintf("%s%s%s%s%s%s%s", linkStart, url, "\x1b\\", underlineStart, text, resetFormat, linkEnd) -} diff --git a/v3/internal/version/version.go b/v3/internal/version/version.go deleted file mode 100644 index fedd279af..000000000 --- a/v3/internal/version/version.go +++ /dev/null @@ -1,26 +0,0 @@ -package version - -import ( - _ "embed" - "github.com/wailsapp/wails/v3/internal/debug" -) - -//go:embed version.txt -var versionString string - -const DevVersion = "v3.0.0-dev" - -func String() string { - if !IsDev() { - return versionString - } - return DevVersion -} - -func LatestStable() string { - return versionString -} - -func IsDev() bool { - return debug.LocalModulePath != "" -} diff --git a/v3/internal/version/version.txt b/v3/internal/version/version.txt deleted file mode 100644 index 776e58d05..000000000 --- a/v3/internal/version/version.txt +++ /dev/null @@ -1 +0,0 @@ -v3.0.0-alpha.68 \ No newline at end of file diff --git a/v3/old b/v3/old deleted file mode 120000 index 4532eb733..000000000 --- a/v3/old +++ /dev/null @@ -1 +0,0 @@ -../../../GolandProjects/ios \ No newline at end of file diff --git a/v3/pkg/application/TODO.md b/v3/pkg/application/TODO.md deleted file mode 100644 index ae4700425..000000000 --- a/v3/pkg/application/TODO.md +++ /dev/null @@ -1,10 +0,0 @@ - -Features -- [ ] AssetServer -- [ ] Offline page if navigating to external URL -- [x] Application menu - -Bugs -- [ ] Resize Window -- [ ] Fullscreen/Maximise/Minimise/Restore - diff --git a/v3/pkg/application/application.go b/v3/pkg/application/application.go deleted file mode 100644 index cef8f567d..000000000 --- a/v3/pkg/application/application.go +++ /dev/null @@ -1,900 +0,0 @@ -package application - -import ( - "context" - "embed" - "errors" - "fmt" - "io" - "log/slog" - "net/http" - "os" - "runtime" - "slices" - "strconv" - "strings" - "sync" - - "github.com/wailsapp/wails/v3/internal/assetserver" - "github.com/wailsapp/wails/v3/internal/assetserver/bundledassets" - "github.com/wailsapp/wails/v3/internal/assetserver/webview" - "github.com/wailsapp/wails/v3/internal/capabilities" -) - -//go:embed assets/* -var alphaAssets embed.FS - -var globalApplication *App - -// AlphaAssets is the default assets for the alpha application -var AlphaAssets = AssetOptions{ - Handler: BundledAssetFileServer(alphaAssets), -} - -type EventListener struct { - callback func(app *ApplicationEvent) -} - -func Get() *App { - return globalApplication -} - -func New(appOptions Options) *App { - if globalApplication != nil { - return globalApplication - } - - mergeApplicationDefaults(&appOptions) - - result := newApplication(appOptions) - globalApplication = result - fatalHandler(result.handleFatalError) - - if result.Logger == nil { - if result.isDebugMode { - result.Logger = DefaultLogger(result.options.LogLevel) - } else { - result.Logger = slog.New(slog.NewTextHandler(io.Discard, nil)) - } - } - - // Set up signal handling (platform-specific) - result.setupSignalHandler(appOptions) - - result.logStartup() - result.logPlatformInfo() - - result.customEventProcessor = NewWailsEventProcessor(result.Event.dispatch) - - messageProc := NewMessageProcessor(result.Logger) - - // Initialize transport (default to HTTP if not specified) - transport := appOptions.Transport - if transport == nil { - transport = NewHTTPTransport(HTTPTransportWithLogger(result.Logger)) - } - - err := transport.Start(result.ctx, messageProc) - if err != nil { - result.fatal("failed to start custom transport: %w", err) - } - // Register shutdown task to stop transport - result.OnShutdown(func() { - if err := transport.Stop(); err != nil { - result.error("failed to stop custom transport: %w", err) - } - }) - - // Auto-wire events if transport supports event delivery - if eventTransport, ok := transport.(WailsEventListener); ok { - result.wailsEventListeners = append(result.wailsEventListeners, eventTransport) - } else { - // otherwise fallback to IPC - result.wailsEventListeners = append(result.wailsEventListeners, &EventIPCTransport{ - app: result, - }) - } - - middlewares := []assetserver.Middleware{ - func(next http.Handler) http.Handler { - if m := appOptions.Assets.Middleware; m != nil { - return m(next) - } - return next - }, - func(next http.Handler) http.Handler { - return http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) { - path := req.URL.Path - switch path { - case "/wails/runtime.js": - err := assetserver.ServeFile(rw, path, bundledassets.RuntimeJS) - if err != nil { - result.fatal("unable to serve runtime.js: %w", err) - } - case "/wails/transport.js": - err := assetserver.ServeFile(rw, path, transport.JSClient()) - if err != nil { - result.fatal("unable to serve transport.js: %w", err) - } - default: - next.ServeHTTP(rw, req) - } - }) - }, - } - - if handler, ok := transport.(TransportHTTPHandler); ok { - middlewares = append(middlewares, handler.Handler()) - } - - opts := &assetserver.Options{ - Handler: appOptions.Assets.Handler, - Middleware: assetserver.ChainMiddleware(middlewares...), - Logger: result.Logger, - } - - if appOptions.Assets.DisableLogging { - opts.Logger = slog.New(slog.NewTextHandler(io.Discard, nil)) - } - - srv, err := assetserver.NewAssetServer(opts) - if err != nil { - result.fatal("application initialisation failed: %w", err) - } - - result.assets = srv - result.assets.LogDetails() - - // If transport implements AssetServerTransport, configure it to serve assets - if assetTransport, ok := transport.(AssetServerTransport); ok { - err := assetTransport.ServeAssets(srv) - if err != nil { - result.fatal("failed to configure transport for serving assets: %w", err) - } - result.debug("Transport configured to serve assets") - } - - result.bindings = NewBindings(appOptions.MarshalError, appOptions.BindAliases) - result.options.Services = slices.Clone(appOptions.Services) - - // Process keybindings - if result.options.KeyBindings != nil { - result.keyBindings = processKeyBindingOptions(result.options.KeyBindings) - } - - if appOptions.OnShutdown != nil { - result.OnShutdown(appOptions.OnShutdown) - } - - // Initialize single instance manager if enabled - if appOptions.SingleInstance != nil { - manager, err := newSingleInstanceManager(result, appOptions.SingleInstance) - if err != nil { - if errors.Is(err, alreadyRunningError) && manager != nil { - err = manager.notifyFirstInstance() - if err != nil { - globalApplication.error("failed to notify first instance: %w", err) - } - os.Exit(appOptions.SingleInstance.ExitCode) - } - result.fatal("failed to initialize single instance manager: %w", err) - } else { - result.singleInstanceManager = manager - } - } - - return result -} - -func mergeApplicationDefaults(o *Options) { - if o.Name == "" { - o.Name = "My Wails Application" - } - if o.Description == "" { - o.Description = "An application written using Wails" - } - if o.Windows.WndClass == "" { - o.Windows.WndClass = "WailsWebviewWindow" - } -} - -type ( - platformApp interface { - run() error - destroy() - setApplicationMenu(menu *Menu) - name() string - getCurrentWindowID() uint - showAboutDialog(name string, description string, icon []byte) - setIcon(icon []byte) - on(id uint) - dispatchOnMainThread(id uint) - hide() - show() - getPrimaryScreen() (*Screen, error) - getScreens() ([]*Screen, error) - GetFlags(options Options) map[string]any - isOnMainThread() bool - isDarkMode() bool - getAccentColor() string - } - - runnable interface { - Run() - } -) - -// Messages sent from javascript get routed here -type windowMessage struct { - windowId uint - message string - originInfo *OriginInfo -} - -type OriginInfo struct { - Origin string - TopOrigin string - IsMainFrame bool -} - -var windowMessageBuffer = make(chan *windowMessage, 5) - -// DropTargetDetails contains information about the HTML element -// where files were dropped (the element with data-file-drop-target attribute). -type DropTargetDetails struct { - X int `json:"x"` - Y int `json:"y"` - ElementID string `json:"id"` - ClassList []string `json:"classList"` - Attributes map[string]string `json:"attributes,omitempty"` -} - -type dragAndDropMessage struct { - windowId uint - filenames []string - X int - Y int - DropTarget *DropTargetDetails -} - -var windowDragAndDropBuffer = make(chan *dragAndDropMessage, 5) - -func addDragAndDropMessage(windowId uint, filenames []string, dropTarget *DropTargetDetails) { - windowDragAndDropBuffer <- &dragAndDropMessage{ - windowId: windowId, - filenames: filenames, - DropTarget: dropTarget, - } -} - -var _ webview.Request = &webViewAssetRequest{} - -const webViewRequestHeaderWindowId = "x-wails-window-id" -const webViewRequestHeaderWindowName = "x-wails-window-name" - -type webViewAssetRequest struct { - Request webview.Request - windowId uint - windowName string -} - -var windowKeyEvents = make(chan *windowKeyEvent, 5) - -type windowKeyEvent struct { - windowId uint - acceleratorString string -} - -func (r *webViewAssetRequest) URL() (string, error) { - return r.Request.URL() -} - -func (r *webViewAssetRequest) Method() (string, error) { - return r.Request.Method() -} - -func (r *webViewAssetRequest) Header() (http.Header, error) { - h, err := r.Request.Header() - if err != nil { - return nil, err - } - - hh := h.Clone() - hh.Set(webViewRequestHeaderWindowId, strconv.FormatUint(uint64(r.windowId), 10)) - if r.windowName != "" { - hh.Set(webViewRequestHeaderWindowName, r.windowName) - } - return hh, nil -} - -func (r *webViewAssetRequest) Body() (io.ReadCloser, error) { - return r.Request.Body() -} - -func (r *webViewAssetRequest) Response() webview.ResponseWriter { - return r.Request.Response() -} - -func (r *webViewAssetRequest) Close() error { - return r.Request.Close() -} - -var webviewRequests = make(chan *webViewAssetRequest, 5) - -type eventHook struct { - callback func(event *ApplicationEvent) -} - -type App struct { - ctx context.Context - cancel context.CancelFunc - options Options - applicationEventListeners map[uint][]*EventListener - applicationEventListenersLock sync.RWMutex - applicationEventHooks map[uint][]*eventHook - applicationEventHooksLock sync.RWMutex - - // Manager pattern for organized API - Window *WindowManager - ContextMenu *ContextMenuManager - KeyBinding *KeyBindingManager - Browser *BrowserManager - Env *EnvironmentManager - Dialog *DialogManager - Event *EventManager - Menu *MenuManager - Screen *ScreenManager - Clipboard *ClipboardManager - SystemTray *SystemTrayManager - - // Windows - windows map[uint]Window - windowsLock sync.RWMutex - - // System Trays - systemTrays map[uint]*SystemTray - systemTraysLock sync.Mutex - systemTrayID uint - systemTrayIDLock sync.RWMutex - - // MenuItems - menuItems map[uint]*MenuItem - menuItemsLock sync.Mutex - - // Starting and running - starting bool - running bool - runLock sync.Mutex - pendingRun []runnable - - bindings *Bindings - - // platform app - impl platformApp - - // The main application menu (private - use app.Menu.GetApplicationMenu/SetApplicationMenu) - applicationMenu *Menu - - clipboard *Clipboard - customEventProcessor *EventProcessor - Logger *slog.Logger - - contextMenus map[string]*ContextMenu - contextMenusLock sync.RWMutex - - assets *assetserver.AssetServer - startURL string - - // Hooks - windowCreatedCallbacks []func(window Window) - pid int - - // Capabilities - capabilities capabilities.Capabilities - isDebugMode bool - - // Keybindings - keyBindings map[string]func(window Window) - keyBindingsLock sync.RWMutex - - // Shutdown - performingShutdown bool - shutdownLock sync.Mutex - serviceShutdownLock sync.Mutex - - // Shutdown tasks are run when the application is shutting down. - // They are run in the order they are added and run on the main thread. - // The application option `OnShutdown` is run first. - shutdownTasks []func() - - // Platform-specific fields (includes signal handler on desktop) - platformSignalHandler - - // Wails ApplicationEvent Listener related - wailsEventListenerLock sync.Mutex - wailsEventListeners []WailsEventListener - - // singleInstanceManager handles single instance functionality - singleInstanceManager *singleInstanceManager -} - -func (a *App) Config() Options { - return a.options -} - -// Context returns the application context that is canceled when the application shuts down. -// This context should be used for graceful shutdown of goroutines and long-running operations. -func (a *App) Context() context.Context { - return a.ctx -} - -func (a *App) handleWarning(msg string) { - if a.options.WarningHandler != nil { - a.options.WarningHandler(msg) - } else { - a.Logger.Warn(msg) - } -} - -func (a *App) handleError(err error) { - if a.options.ErrorHandler != nil { - a.options.ErrorHandler(err) - } else { - a.Logger.Error(err.Error()) - } -} - -// RegisterService appends the given service to the list of bound services. -// Registered services will be bound and initialised -// in registration order upon calling [App.Run]. -// -// RegisterService will log an error message -// and discard the given service -// if called after [App.Run]. -func (a *App) RegisterService(service Service) { - a.runLock.Lock() - defer a.runLock.Unlock() - - if a.starting || a.running { - a.error( - "services must be registered before running the application. Service '%s' will not be registered.", - getServiceName(service), - ) - return - } - - a.options.Services = append(a.options.Services, service) -} - -func (a *App) handleFatalError(err error) { - a.handleError(&FatalError{err: err}) - os.Exit(1) -} - -func (a *App) init() { - a.ctx, a.cancel = context.WithCancel(context.Background()) - a.applicationEventHooks = make(map[uint][]*eventHook) - a.applicationEventListeners = make(map[uint][]*EventListener) - a.windows = make(map[uint]Window) - a.systemTrays = make(map[uint]*SystemTray) - a.contextMenus = make(map[string]*ContextMenu) - a.keyBindings = make(map[string]func(window Window)) - a.Logger = a.options.Logger - a.pid = os.Getpid() - a.wailsEventListeners = make([]WailsEventListener, 0) - - // Initialize managers - a.Window = newWindowManager(a) - a.ContextMenu = newContextMenuManager(a) - a.KeyBinding = newKeyBindingManager(a) - a.Browser = newBrowserManager(a) - a.Env = newEnvironmentManager(a) - a.Dialog = newDialogManager(a) - a.Event = newEventManager(a) - a.Menu = newMenuManager(a) - a.Screen = newScreenManager(a) - a.Clipboard = newClipboardManager(a) - a.SystemTray = newSystemTrayManager(a) -} - -func (a *App) Capabilities() capabilities.Capabilities { - return a.capabilities -} - -func (a *App) GetPID() int { - return a.pid -} - -func (a *App) info(message string, args ...any) { - if a.Logger != nil { - go func() { - defer handlePanic() - a.Logger.Info(message, args...) - }() - } -} - -func (a *App) debug(message string, args ...any) { - if a.Logger != nil { - go func() { - defer handlePanic() - a.Logger.Debug(message, args...) - }() - } -} - -func (a *App) fatal(message string, args ...any) { - err := fmt.Errorf(message, args...) - a.handleFatalError(err) -} -func (a *App) warning(message string, args ...any) { - msg := fmt.Sprintf(message, args...) - a.handleWarning(msg) -} - -func (a *App) error(message string, args ...any) { - a.handleError(fmt.Errorf(message, args...)) -} - -func (a *App) Run() error { - a.runLock.Lock() - // Prevent double invocations. - if a.starting || a.running { - a.runLock.Unlock() - return errors.New("application is running or a previous run has failed") - } - // Block further service registrations. - a.starting = true - a.runLock.Unlock() - - // Ensure application context is cancelled in case of failures. - defer a.cancel() - - // Call post-create hooks - err := a.preRun() - if err != nil { - return err - } - - a.impl = newPlatformApp(a) - - // Ensure services are shut down in case of failures. - defer a.shutdownServices() - - // Ensure application context is canceled before service shutdown (duplicate calls don't hurt). - defer a.cancel() - - // Startup services before dispatching any events. - // No need to hold the lock here because a.options.Services may only change when a.running is false. - services := a.options.Services - a.options.Services = nil - for i, service := range services { - if err := a.startupService(service); err != nil { - return fmt.Errorf("error starting service '%s': %w", getServiceName(service), err) - } - // Schedule started services for shutdown. - a.options.Services = services[:i+1] - } - - go func() { - for { - event := <-applicationEvents - go a.Event.handleApplicationEvent(event) - } - }() - go func() { - for { - event := <-windowEvents - go a.handleWindowEvent(event) - } - }() - go func() { - for { - request := <-webviewRequests - go a.handleWebViewRequest(request) - } - }() - go func() { - for { - event := <-windowMessageBuffer - go a.handleWindowMessage(event) - } - }() - go func() { - for { - event := <-windowKeyEvents - go a.handleWindowKeyEvent(event) - } - }() - go func() { - for { - dragAndDropMessage := <-windowDragAndDropBuffer - go a.handleDragAndDropMessage(dragAndDropMessage) - } - }() - - go func() { - for { - menuItemID := <-menuItemClicked - go a.Menu.handleMenuItemClicked(menuItemID) - } - }() - - a.runLock.Lock() - a.running = true - a.runLock.Unlock() - - // No need to hold the lock here because - // - a.pendingRun may only change while a.running is false. - // - runnables are scheduled asynchronously anyway. - for _, pending := range a.pendingRun { - go func() { - defer handlePanic() - pending.Run() - }() - } - a.pendingRun = nil - - // set the application menu - if runtime.GOOS == "darwin" { - a.impl.setApplicationMenu(a.applicationMenu) - } - if a.options.Icon != nil { - a.impl.setIcon(a.options.Icon) - } - - return a.impl.run() -} - -func (a *App) startupService(service Service) error { - err := a.bindings.Add(service) - if err != nil { - return fmt.Errorf("cannot bind service methods: %w", err) - } - - if service.options.Route != "" { - handler, ok := service.Instance().(http.Handler) - if !ok { - handler = http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) { - http.Error( - rw, - fmt.Sprintf( - "Service '%s' does not handle HTTP requests", - getServiceName(service), - ), - http.StatusServiceUnavailable, - ) - }) - } - a.assets.AttachServiceHandler(service.options.Route, handler) - } - - if s, ok := service.instance.(ServiceStartup); ok { - a.debug("Starting up service:", "name", getServiceName(service)) - return s.ServiceStartup(a.ctx, service.options) - } - - return nil -} - -func (a *App) shutdownServices() { - // Acquire lock to prevent double calls (defer in Run() + OnShutdown) - a.serviceShutdownLock.Lock() - defer a.serviceShutdownLock.Unlock() - - // Ensure app context is cancelled first (duplicate calls don't hurt). - a.cancel() - - for len(a.options.Services) > 0 { - last := len(a.options.Services) - 1 - service := a.options.Services[last] - a.options.Services = a.options.Services[:last] // Prevent double shutdowns - - if s, ok := service.instance.(ServiceShutdown); ok { - a.debug("Shutting down service:", "name", getServiceName(service)) - if err := s.ServiceShutdown(); err != nil { - a.error("error shutting down service '%s': %w", getServiceName(service), err) - } - } - } -} - -func (a *App) handleDragAndDropMessage(event *dragAndDropMessage) { - defer handlePanic() - a.windowsLock.Lock() - window, ok := a.windows[event.windowId] - a.windowsLock.Unlock() - if !ok { - a.warning("WebviewWindow #%d not found", event.windowId) - return - } - window.handleDragAndDropMessage(event.filenames, event.DropTarget) -} - -func (a *App) handleWindowMessage(event *windowMessage) { - defer handlePanic() - // Get window from window map - a.windowsLock.RLock() - window, ok := a.windows[event.windowId] - // Debug: log all window IDs - var ids []uint - for id := range a.windows { - ids = append(ids, id) - } - a.windowsLock.RUnlock() - - a.debug("handleWindowMessage: Looking for window", "windowId", event.windowId, "availableIDs", ids) - - if !ok { - a.warning("WebviewWindow #%d not found", event.windowId) - return - } - // Check if the message starts with "wails:" - if strings.HasPrefix(event.message, "wails:") { - a.debug("handleWindowMessage: Processing wails message", "message", event.message) - window.HandleMessage(event.message) - } else { - if a.options.RawMessageHandler != nil { - a.options.RawMessageHandler(window, event.message, event.originInfo) - } - } -} - -func (a *App) handleWebViewRequest(request *webViewAssetRequest) { - defer handlePanic() - // Log that we're processing the request - url, _ := request.Request.URL() - a.debug("handleWebViewRequest: Processing request", "url", url) - // IMPORTANT: pass the wrapper request so our injected headers (x-wails-window-id/name) are used - a.assets.ServeWebViewRequest(request) - a.debug("handleWebViewRequest: Request processing complete", "url", url) -} - -func (a *App) handleWindowEvent(event *windowEvent) { - defer handlePanic() - // Get window from window map - a.windowsLock.RLock() - window, ok := a.windows[event.WindowID] - a.windowsLock.RUnlock() - if !ok { - a.warning("Window #%d not found", event.WindowID) - return - } - window.HandleWindowEvent(event.EventID) -} - -// OnShutdown adds a function to be run when the application is shutting down. -func (a *App) OnShutdown(f func()) { - if f == nil { - return - } - - a.shutdownLock.Lock() - - if !a.performingShutdown { - defer a.shutdownLock.Unlock() - a.shutdownTasks = append(a.shutdownTasks, f) - return - } - - a.shutdownLock.Unlock() - InvokeAsync(f) -} - -func (a *App) cleanup() { - a.shutdownLock.Lock() - if a.performingShutdown { - a.shutdownLock.Unlock() - return - } - a.cancel() // Cancel app context before running shutdown hooks. - a.performingShutdown = true - a.shutdownLock.Unlock() - - // No need to hold the lock here because a.shutdownTasks - // may only change while a.performingShutdown is false. - for _, shutdownTask := range a.shutdownTasks { - InvokeSync(shutdownTask) - } - InvokeSync(func() { - a.shutdownServices() - a.windowsLock.Lock() - for _, window := range a.windows { - window.Close() - } - a.windows = nil - a.windowsLock.Unlock() - a.systemTraysLock.Lock() - for _, systray := range a.systemTrays { - systray.destroy() - } - a.systemTrays = nil - a.systemTraysLock.Unlock() - - // Cleanup single instance manager - if a.singleInstanceManager != nil { - a.singleInstanceManager.cleanup() - } - - a.postQuit() - - if a.options.PostShutdown != nil { - a.options.PostShutdown() - } - }) -} - -func (a *App) Quit() { - if a.impl != nil { - InvokeSync(a.impl.destroy) - } -} - -func (a *App) SetIcon(icon []byte) { - if a.impl != nil { - a.impl.setIcon(icon) - } -} - -func (a *App) dispatchOnMainThread(fn func()) { - // If we are on the main thread, just call the function - if a.impl.isOnMainThread() { - fn() - return - } - - mainThreadFunctionStoreLock.Lock() - id := generateFunctionStoreID() - mainThreadFunctionStore[id] = fn - mainThreadFunctionStoreLock.Unlock() - // Call platform specific dispatch function - a.impl.dispatchOnMainThread(id) -} - -func (a *App) Hide() { - if a.impl != nil { - a.impl.hide() - } -} - -func (a *App) Show() { - if a.impl != nil { - a.impl.show() - } -} - -func (a *App) runOrDeferToAppRun(r runnable) { - a.runLock.Lock() - - if !a.running { - defer a.runLock.Unlock() // Defer unlocking for panic tolerance. - a.pendingRun = append(a.pendingRun, r) - return - } - - // Unlock immediately to prevent deadlocks. - // No TOC/TOU risk here because a.running can never switch back to false. - a.runLock.Unlock() - r.Run() -} - -func (a *App) handleWindowKeyEvent(event *windowKeyEvent) { - defer handlePanic() - // Get window from window map - a.windowsLock.RLock() - window, ok := a.windows[event.windowId] - a.windowsLock.RUnlock() - if !ok { - a.warning("WebviewWindow #%d not found", event.windowId) - return - } - // Get callback from window - window.HandleKeyEvent(event.acceleratorString) -} - -func (a *App) shouldQuit() bool { - if a.options.ShouldQuit != nil { - return a.options.ShouldQuit() - } - return true -} diff --git a/v3/pkg/application/application_android.go b/v3/pkg/application/application_android.go deleted file mode 100644 index ce620a603..000000000 --- a/v3/pkg/application/application_android.go +++ /dev/null @@ -1,687 +0,0 @@ -//go:build android && cgo && !server - -package application - -/* -#include -#include -#include - -// Global JavaVM reference for thread attachment -static JavaVM* g_jvm = NULL; - -// Global reference to bridge object (must be a global ref, not local) -static jobject g_bridge = NULL; - -// Cached method ID for executeJavaScript -static jmethodID g_executeJsMethod = NULL; - -// Helper function to convert Java String to C string -static const char* jstringToC(JNIEnv *env, jstring jstr) { - if (jstr == NULL) return NULL; - return (*env)->GetStringUTFChars(env, jstr, NULL); -} - -// Helper function to release Java String -static void releaseJString(JNIEnv *env, jstring jstr, const char* cstr) { - if (jstr != NULL && cstr != NULL) { - (*env)->ReleaseStringUTFChars(env, jstr, cstr); - } -} - -// Helper function to create Java byte array from C data -static jbyteArray createByteArray(JNIEnv *env, const void* data, int len) { - if (data == NULL || len <= 0) return NULL; - jbyteArray arr = (*env)->NewByteArray(env, len); - if (arr != NULL) { - (*env)->SetByteArrayRegion(env, arr, 0, len, (const jbyte*)data); - } - return arr; -} - -// Helper function to create Java String from C string -static jstring createJString(JNIEnv *env, const char* str) { - if (str == NULL) return NULL; - return (*env)->NewStringUTF(env, str); -} - -// Store JavaVM and create global reference to bridge -static void storeBridgeRef(JNIEnv *env, jobject bridge) { - // Get JavaVM - if ((*env)->GetJavaVM(env, &g_jvm) != 0) { - return; - } - - // Create global reference to bridge object - g_bridge = (*env)->NewGlobalRef(env, bridge); - if (g_bridge == NULL) { - return; - } - - // Cache the executeJavaScript method ID - jclass bridgeClass = (*env)->GetObjectClass(env, g_bridge); - if (bridgeClass != NULL) { - g_executeJsMethod = (*env)->GetMethodID(env, bridgeClass, "executeJavaScript", "(Ljava/lang/String;)V"); - (*env)->DeleteLocalRef(env, bridgeClass); - } -} - -// Android logging via __android_log_print -#include -#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, "WailsNative", __VA_ARGS__) - -// Execute JavaScript via the bridge - can be called from any thread -static void executeJavaScriptOnBridge(const char* js) { - LOGD("executeJavaScriptOnBridge called, js length: %d", js ? (int)strlen(js) : -1); - - if (g_jvm == NULL) { - LOGD("executeJavaScriptOnBridge: g_jvm is NULL"); - return; - } - if (g_bridge == NULL) { - LOGD("executeJavaScriptOnBridge: g_bridge is NULL"); - return; - } - if (g_executeJsMethod == NULL) { - LOGD("executeJavaScriptOnBridge: g_executeJsMethod is NULL"); - return; - } - if (js == NULL) { - LOGD("executeJavaScriptOnBridge: js is NULL"); - return; - } - - JNIEnv *env = NULL; - int needsDetach = 0; - - // Get JNIEnv for current thread - jint result = (*g_jvm)->GetEnv(g_jvm, (void**)&env, JNI_VERSION_1_6); - LOGD("executeJavaScriptOnBridge: GetEnv result = %d", result); - if (result == JNI_EDETACHED) { - // Attach current thread to JVM - LOGD("executeJavaScriptOnBridge: Attaching thread"); - if ((*g_jvm)->AttachCurrentThread(g_jvm, &env, NULL) != 0) { - LOGD("executeJavaScriptOnBridge: AttachCurrentThread failed"); - return; - } - needsDetach = 1; - } else if (result != JNI_OK) { - LOGD("executeJavaScriptOnBridge: GetEnv failed with %d", result); - return; - } - - // Create Java string and call method - jstring jJs = (*env)->NewStringUTF(env, js); - LOGD("executeJavaScriptOnBridge: jJs created: %p", jJs); - if (jJs != NULL) { - LOGD("executeJavaScriptOnBridge: Calling Java method"); - (*env)->CallVoidMethod(env, g_bridge, g_executeJsMethod, jJs); - LOGD("executeJavaScriptOnBridge: Java method called"); - (*env)->DeleteLocalRef(env, jJs); - } - - // Check for exceptions - if ((*env)->ExceptionCheck(env)) { - LOGD("executeJavaScriptOnBridge: Exception occurred!"); - (*env)->ExceptionDescribe(env); - (*env)->ExceptionClear(env); - } - - // Detach if we attached - if (needsDetach) { - LOGD("executeJavaScriptOnBridge: Detaching thread"); - (*g_jvm)->DetachCurrentThread(g_jvm); - } - - LOGD("executeJavaScriptOnBridge: Done"); -} -*/ -import "C" - -import ( - "fmt" - "io" - "net/http" - "net/http/httptest" - "strings" - "sync" - "time" - "unsafe" - - "encoding/json" - - "github.com/wailsapp/wails/v3/internal/runtime" -) - -var ( - // Global reference to the app for JNI callbacks - globalApp *App - globalAppLock sync.RWMutex - - // JNI environment and class references - javaVM unsafe.Pointer - bridgeObject unsafe.Pointer - - // Android main function registration - androidMainFunc func() - androidMainLock sync.Mutex - - // App ready signal - appReady = make(chan struct{}) - appReadyOnce sync.Once -) - -func init() { - androidLogf("info", "🤖 [application_android.go] init() called") -} - -// RegisterAndroidMain registers the main function to be called when the Android app starts. -// This should be called from init() in your main.go file for Android builds. -// Example: -// -// func init() { -// application.RegisterAndroidMain(main) -// } -func RegisterAndroidMain(mainFunc func()) { - androidMainLock.Lock() - defer androidMainLock.Unlock() - androidMainFunc = mainFunc - androidLogf("info", "🤖 [application_android.go] Android main function registered") -} - -// signalAppReady signals that the app is ready to serve requests -func signalAppReady() { - appReadyOnce.Do(func() { - close(appReady) - androidLogf("info", "🤖 [application_android.go] App ready signal sent") - }) -} - -// waitForAppReady waits for the app to be ready, with a timeout -func waitForAppReady(timeout time.Duration) bool { - select { - case <-appReady: - return true - case <-time.After(timeout): - return false - } -} - -func androidLogf(level string, format string, a ...interface{}) { - msg := fmt.Sprintf(format, a...) - // For now, just use println - we'll connect to Android's Log.* later - println(fmt.Sprintf("[Android/%s] %s", level, msg)) -} - -func (a *App) platformRun() { - androidLogf("info", "🤖 [application_android.go] platformRun() called") - - // Store global reference for JNI callbacks - globalAppLock.Lock() - globalApp = a - globalAppLock.Unlock() - - // Signal that the app is ready to serve requests - signalAppReady() - - androidLogf("info", "🤖 [application_android.go] App ready, waiting for Android lifecycle...") - - // Block forever - Android manages the app lifecycle via JNI callbacks - select {} -} - -func (a *App) platformQuit() { - androidLogf("info", "🤖 [application_android.go] platformQuit() called") - // Android will handle app termination -} - -func (a *App) isDarkMode() bool { - // TODO: Query Android for dark mode status - return false -} - -func (a *App) isWindows() bool { - return false -} - -// Platform-specific app implementation for Android -type androidApp struct { - parent *App -} - -func newPlatformApp(app *App) *androidApp { - androidLogf("info", "🤖 [application_android.go] newPlatformApp() called") - return &androidApp{ - parent: app, - } -} - -func (a *androidApp) run() error { - androidLogf("info", "🤖 [application_android.go] androidApp.run() called") - - // Emit application started event - a.parent.Event.Emit("ApplicationStarted") - - a.parent.platformRun() - return nil -} - -func (a *androidApp) destroy() { - androidLogf("info", "🤖 [application_android.go] androidApp.destroy() called") -} - -func (a *androidApp) setIcon(_ []byte) { - // Android app icon is set through AndroidManifest.xml -} - -func (a *androidApp) name() string { - return a.parent.options.Name -} - -func (a *androidApp) GetFlags(options Options) map[string]any { - return nil -} - -func (a *androidApp) getAccentColor() string { - return "" -} - -func (a *androidApp) getCurrentWindowID() uint { - return 0 -} - -func (a *androidApp) hide() { - // Android manages app visibility -} - -func (a *androidApp) isDarkMode() bool { - return a.parent.isDarkMode() -} - -func (a *androidApp) on(_ uint) { - // Android event handling -} - -func (a *androidApp) setApplicationMenu(_ *Menu) { - // Android doesn't have application menus in the same way -} - -func (a *androidApp) show() { - // Android manages app visibility -} - -func (a *androidApp) showAboutDialog(_ string, _ string, _ []byte) { - // TODO: Implement Android about dialog -} - -func (a *androidApp) getPrimaryScreen() (*Screen, error) { - screens, err := getScreens() - if err != nil || len(screens) == 0 { - return nil, err - } - return screens[0], nil -} - -func (a *androidApp) getScreens() ([]*Screen, error) { - return getScreens() -} - -func (a *App) logPlatformInfo() { - // Log Android platform info - androidLogf("info", "Platform: Android") -} - -func (a *App) platformEnvironment() map[string]any { - return map[string]any{ - "platform": "android", - } -} - -func fatalHandler(errFunc func(error)) { - // Android fatal handler -} - -// JNI Export Functions - Called from Java - -//export Java_com_wails_app_WailsBridge_nativeInit -func Java_com_wails_app_WailsBridge_nativeInit(env *C.JNIEnv, obj C.jobject, bridge C.jobject) { - androidLogf("info", "🤖 [JNI] nativeInit called") - - // Store references for later use (legacy - keeping for compatibility) - javaVM = unsafe.Pointer(env) - bridgeObject = unsafe.Pointer(bridge) - - // Store JavaVM and bridge global reference for JNI callbacks - C.storeBridgeRef(env, bridge) - androidLogf("info", "🤖 [JNI] Bridge reference stored for JNI callbacks") - - // Start the registered main function in a goroutine - androidMainLock.Lock() - mainFunc := androidMainFunc - androidMainLock.Unlock() - - if mainFunc != nil { - androidLogf("info", "🤖 [JNI] Starting registered main function in goroutine") - go mainFunc() - } else { - androidLogf("warn", "🤖 [JNI] No main function registered! Call application.RegisterAndroidMain(main) in init()") - } - - androidLogf("info", "🤖 [JNI] nativeInit complete") -} - -//export Java_com_wails_app_WailsBridge_nativeShutdown -func Java_com_wails_app_WailsBridge_nativeShutdown(env *C.JNIEnv, obj C.jobject) { - androidLogf("info", "🤖 [JNI] nativeShutdown called") - - globalAppLock.Lock() - if globalApp != nil { - globalApp.Quit() - } - globalAppLock.Unlock() -} - -//export Java_com_wails_app_WailsBridge_nativeOnResume -func Java_com_wails_app_WailsBridge_nativeOnResume(env *C.JNIEnv, obj C.jobject) { - androidLogf("info", "🤖 [JNI] nativeOnResume called") - - globalAppLock.RLock() - app := globalApp - globalAppLock.RUnlock() - - if app != nil { - app.Event.Emit("ApplicationResumed") - } -} - -//export Java_com_wails_app_WailsBridge_nativeOnPause -func Java_com_wails_app_WailsBridge_nativeOnPause(env *C.JNIEnv, obj C.jobject) { - androidLogf("info", "🤖 [JNI] nativeOnPause called") - - globalAppLock.RLock() - app := globalApp - globalAppLock.RUnlock() - - if app != nil { - app.Event.Emit("ApplicationPaused") - } -} - -//export Java_com_wails_app_WailsBridge_nativeOnPageFinished -func Java_com_wails_app_WailsBridge_nativeOnPageFinished(env *C.JNIEnv, obj C.jobject, jurl C.jstring) { - cUrl := C.jstringToC(env, jurl) - defer C.releaseJString(env, jurl, cUrl) - url := C.GoString(cUrl) - - androidLogf("info", "🤖 [JNI] nativeOnPageFinished called: %s", url) - - globalAppLock.RLock() - app := globalApp - globalAppLock.RUnlock() - - if app == nil { - androidLogf("error", "🤖 [JNI] nativeOnPageFinished: app is nil") - return - } - - // Inject the runtime into the first window (with proper locking) - app.windowsLock.RLock() - windowCount := len(app.windows) - androidLogf("info", "🤖 [JNI] nativeOnPageFinished: window count = %d", windowCount) - for id, win := range app.windows { - androidLogf("info", "🤖 [JNI] Found window ID: %d", id) - if win != nil { - androidLogf("info", "🤖 [JNI] Injecting runtime.Core() into window %d", id) - // Get the runtime core JavaScript - runtimeJS := runtime.Core() - androidLogf("info", "🤖 [JNI] Runtime JS length: %d bytes", len(runtimeJS)) - app.windowsLock.RUnlock() - // IMPORTANT: We must bypass win.ExecJS because it queues if runtimeLoaded is false. - // On Android, we need to inject the runtime directly since the runtime hasn't been loaded yet. - // This is the bootstrap injection that enables the runtime to load. - androidLogf("info", "🤖 [JNI] Calling executeJavaScript directly (bypassing queue)") - executeJavaScript(runtimeJS) - // Emit event - app.Event.Emit("PageFinished", url) - return - } - } - app.windowsLock.RUnlock() - - androidLogf("warn", "🤖 [JNI] nativeOnPageFinished: no windows found to inject runtime") - // Emit event even if no windows - app.Event.Emit("PageFinished", url) -} - -//export Java_com_wails_app_WailsBridge_nativeServeAsset -func Java_com_wails_app_WailsBridge_nativeServeAsset(env *C.JNIEnv, obj C.jobject, jpath C.jstring, jmethod C.jstring, jheaders C.jstring) C.jbyteArray { - // Convert Java strings to Go strings - cPath := C.jstringToC(env, jpath) - cMethod := C.jstringToC(env, jmethod) - defer C.releaseJString(env, jpath, cPath) - defer C.releaseJString(env, jmethod, cMethod) - - goPath := C.GoString(cPath) - goMethod := C.GoString(cMethod) - - androidLogf("debug", "🤖 [JNI] nativeServeAsset: %s %s", goMethod, goPath) - - // Wait for the app to be ready (timeout after 10 seconds) - if !waitForAppReady(10 * time.Second) { - androidLogf("error", "🤖 [JNI] Timeout waiting for app to be ready") - return C.createByteArray(env, nil, 0) - } - - globalAppLock.RLock() - app := globalApp - globalAppLock.RUnlock() - - if app == nil || app.assets == nil { - androidLogf("error", "🤖 [JNI] App or assets not initialized after ready signal") - return C.createByteArray(env, nil, 0) - } - - // Serve the asset through the asset server - data, err := serveAssetForAndroid(app, goPath) - if err != nil { - androidLogf("error", "🤖 [JNI] Error serving asset %s: %v", goPath, err) - return C.createByteArray(env, nil, 0) - } - - androidLogf("debug", "🤖 [JNI] Serving asset %s (%d bytes)", goPath, len(data)) - - // Create Java byte array from the data - // Handle empty data case to avoid index out of range panic - if len(data) == 0 { - return C.createByteArray(env, nil, 0) - } - return C.createByteArray(env, unsafe.Pointer(&data[0]), C.int(len(data))) -} - -//export Java_com_wails_app_WailsBridge_nativeHandleMessage -func Java_com_wails_app_WailsBridge_nativeHandleMessage(env *C.JNIEnv, obj C.jobject, jmessage C.jstring) C.jstring { - // Convert Java string to Go string - cMessage := C.jstringToC(env, jmessage) - defer C.releaseJString(env, jmessage, cMessage) - - goMessage := C.GoString(cMessage) - - androidLogf("debug", "🤖 [JNI] nativeHandleMessage: %s", goMessage) - - globalAppLock.RLock() - app := globalApp - globalAppLock.RUnlock() - - if app == nil { - errorResponse := `{"error":"App not initialized"}` - return C.createJString(env, C.CString(errorResponse)) - } - - // Parse and handle the message - response := handleMessageForAndroid(app, goMessage) - return C.createJString(env, C.CString(response)) -} - -//export Java_com_wails_app_WailsBridge_nativeGetAssetMimeType -func Java_com_wails_app_WailsBridge_nativeGetAssetMimeType(env *C.JNIEnv, obj C.jobject, jpath C.jstring) C.jstring { - // Convert Java string to Go string - cPath := C.jstringToC(env, jpath) - defer C.releaseJString(env, jpath, cPath) - - goPath := C.GoString(cPath) - mimeType := getMimeTypeForPath(goPath) - return C.createJString(env, C.CString(mimeType)) -} - -// Helper functions - -func serveAssetForAndroid(app *App, path string) ([]byte, error) { - // Check if this is a runtime call (includes query string) - isRuntimeCall := strings.HasPrefix(path, "/wails/runtime") - - // Normalize path for regular assets (not runtime calls) - if !isRuntimeCall { - if path == "" || path == "/" { - path = "/index.html" - } - } - - // Ensure path starts with / - if len(path) > 0 && path[0] != '/' { - path = "/" + path - } - - // Check if asset server is available - if app.assets == nil { - return nil, fmt.Errorf("asset server not initialized") - } - - // Create a fake HTTP request - fullURL := "https://wails.localhost" + path - androidLogf("debug", "🤖 [serveAssetForAndroid] Creating request for: %s", fullURL) - - req, err := http.NewRequest("GET", fullURL, nil) - if err != nil { - return nil, fmt.Errorf("failed to create request: %w", err) - } - - // For runtime calls (/wails/runtime), we need to add the window ID header - // This is required by the MessageProcessor to route the call correctly - if isRuntimeCall { - // Get the first window (on Android, there's typically only one) - windows := app.Window.GetAll() - androidLogf("debug", "🤖 [serveAssetForAndroid] Runtime call, found %d windows", len(windows)) - if len(windows) > 0 { - // Use the first window's ID - windowID := windows[0].ID() - req.Header.Set("x-wails-window-id", fmt.Sprintf("%d", windowID)) - androidLogf("debug", "🤖 [serveAssetForAndroid] Added window ID header: %d", windowID) - } else { - androidLogf("warn", "🤖 [serveAssetForAndroid] No windows available for runtime call") - } - } - - // Use httptest.ResponseRecorder to capture the response - recorder := httptest.NewRecorder() - - // Serve the request through the asset server - app.assets.ServeHTTP(recorder, req) - - // Check response status - result := recorder.Result() - defer result.Body.Close() - - // Read the response body - body, err := io.ReadAll(result.Body) - if err != nil { - return nil, fmt.Errorf("failed to read response body: %w", err) - } - - androidLogf("debug", "🤖 [serveAssetForAndroid] Response status: %d, body length: %d", result.StatusCode, len(body)) - - // For runtime calls, we need to return the body even for error responses - // so the JavaScript can see the error message - if isRuntimeCall { - if result.StatusCode != http.StatusOK { - androidLogf("warn", "🤖 [serveAssetForAndroid] Runtime call returned status %d: %s", result.StatusCode, string(body)) - } - // Return the body regardless of status - the JS will handle errors - return body, nil - } - - // For regular assets, check status codes - if result.StatusCode == http.StatusNotFound { - return nil, fmt.Errorf("asset not found: %s", path) - } - - if result.StatusCode != http.StatusOK { - return nil, fmt.Errorf("asset server error: status %d for %s", result.StatusCode, path) - } - - return body, nil -} - -func handleMessageForAndroid(app *App, message string) string { - // Parse the message - var msg map[string]interface{} - if err := json.Unmarshal([]byte(message), &msg); err != nil { - return fmt.Sprintf(`{"error":"%s"}`, err.Error()) - } - - // TODO: Route to appropriate handler based on message type - // For now, return success - return `{"success":true}` -} - -func getMimeTypeForPath(path string) string { - // Simple MIME type detection based on extension - switch { - case endsWith(path, ".html"), endsWith(path, ".htm"): - return "text/html" - case endsWith(path, ".js"), endsWith(path, ".mjs"): - return "application/javascript" - case endsWith(path, ".css"): - return "text/css" - case endsWith(path, ".json"): - return "application/json" - case endsWith(path, ".png"): - return "image/png" - case endsWith(path, ".jpg"), endsWith(path, ".jpeg"): - return "image/jpeg" - case endsWith(path, ".gif"): - return "image/gif" - case endsWith(path, ".svg"): - return "image/svg+xml" - case endsWith(path, ".ico"): - return "image/x-icon" - case endsWith(path, ".woff"): - return "font/woff" - case endsWith(path, ".woff2"): - return "font/woff2" - case endsWith(path, ".ttf"): - return "font/ttf" - default: - return "application/octet-stream" - } -} - -func endsWith(s, suffix string) bool { - return len(s) >= len(suffix) && s[len(s)-len(suffix):] == suffix -} - -// executeJavaScript executes JavaScript code in the Android WebView via JNI callback -func executeJavaScript(js string) { - androidLogf("info", "🤖 executeJavaScript called, length: %d", len(js)) - if js == "" { - androidLogf("warn", "🤖 executeJavaScript: empty JS string") - return - } - - // Convert Go string to C string and call the JNI bridge - androidLogf("info", "🤖 executeJavaScript: calling C.executeJavaScriptOnBridge") - cJs := C.CString(js) - defer C.free(unsafe.Pointer(cJs)) - - C.executeJavaScriptOnBridge(cJs) - androidLogf("info", "🤖 executeJavaScript: done") -} diff --git a/v3/pkg/application/application_android_nocgo.go b/v3/pkg/application/application_android_nocgo.go deleted file mode 100644 index 045c5ae3f..000000000 --- a/v3/pkg/application/application_android_nocgo.go +++ /dev/null @@ -1,225 +0,0 @@ -//go:build android && !cgo && !server - -package application - -import ( - "fmt" - "sync" - "unsafe" - - "encoding/json" -) - -var ( - // Global reference to the app for JNI callbacks - globalApp *App - globalAppLock sync.RWMutex - - // JNI environment and class references - javaVM unsafe.Pointer - bridgeObject unsafe.Pointer -) - -func init() { - androidLogf("info", "🤖 [application_android.go] init() called") -} - -func androidLogf(level string, format string, a ...interface{}) { - msg := fmt.Sprintf(format, a...) - // For now, just use println - we'll connect to Android's Log.* later - println(fmt.Sprintf("[Android/%s] %s", level, msg)) -} - -func (a *App) platformRun() { - androidLogf("info", "🤖 [application_android.go] platformRun() called") - - // Store global reference for JNI callbacks - globalAppLock.Lock() - globalApp = a - globalAppLock.Unlock() - - androidLogf("info", "🤖 [application_android.go] Waiting for Android lifecycle...") - - // Block forever - Android manages the app lifecycle via JNI callbacks - select {} -} - -func (a *App) platformQuit() { - androidLogf("info", "🤖 [application_android.go] platformQuit() called") - // Android will handle app termination -} - -func (a *App) isDarkMode() bool { - // TODO: Query Android for dark mode status - return false -} - -func (a *App) isWindows() bool { - return false -} - -// Platform-specific app implementation for Android -type androidApp struct { - parent *App -} - -func newPlatformApp(app *App) *androidApp { - androidLogf("info", "🤖 [application_android.go] newPlatformApp() called") - return &androidApp{ - parent: app, - } -} - -func (a *androidApp) run() error { - androidLogf("info", "🤖 [application_android.go] androidApp.run() called") - - // Wire common events - a.setupCommonEvents() - - // Emit application started event - a.parent.Event.Emit("ApplicationStarted") - - a.parent.platformRun() - return nil -} - -func (a *androidApp) destroy() { - androidLogf("info", "🤖 [application_android.go] androidApp.destroy() called") -} - -func (a *androidApp) setIcon(_ []byte) { - // Android app icon is set through AndroidManifest.xml -} - -func (a *androidApp) name() string { - return a.parent.options.Name -} - -func (a *androidApp) GetFlags(options Options) map[string]any { - return nil -} - -func (a *androidApp) getAccentColor() string { - return "" -} - -func (a *androidApp) getCurrentWindowID() uint { - return 0 -} - -func (a *androidApp) hide() { - // Android manages app visibility -} - -func (a *androidApp) isDarkMode() bool { - return a.parent.isDarkMode() -} - -func (a *androidApp) on(_ uint) { - // Android event handling -} - -func (a *androidApp) setApplicationMenu(_ *Menu) { - // Android doesn't have application menus in the same way -} - -func (a *androidApp) show() { - // Android manages app visibility -} - -func (a *androidApp) showAboutDialog(_ string, _ string, _ []byte) { - // TODO: Implement Android about dialog -} - -func (a *androidApp) getPrimaryScreen() (*Screen, error) { - screens, err := getScreens() - if err != nil || len(screens) == 0 { - return nil, err - } - return screens[0], nil -} - -func (a *androidApp) getScreens() ([]*Screen, error) { - return getScreens() -} - -func (a *App) logPlatformInfo() { - // Log Android platform info - androidLogf("info", "Platform: Android") -} - -func (a *App) platformEnvironment() map[string]any { - return map[string]any{ - "platform": "android", - } -} - -func fatalHandler(errFunc func(error)) { - // Android fatal handler -} - -// Helper functions - -func serveAssetForAndroid(app *App, path string) ([]byte, error) { - // Normalize path - if path == "" || path == "/" { - path = "/index.html" - } - - // TODO: Use the actual asset server to serve the file - // For now, return a placeholder - return nil, fmt.Errorf("asset serving not yet implemented: %s", path) -} - -func handleMessageForAndroid(app *App, message string) string { - // Parse the message - var msg map[string]interface{} - if err := json.Unmarshal([]byte(message), &msg); err != nil { - return fmt.Sprintf(`{"error":"%s"}`, err.Error()) - } - - // TODO: Route to appropriate handler based on message type - // For now, return success - return `{"success":true}` -} - -func getMimeTypeForPath(path string) string { - // Simple MIME type detection based on extension - switch { - case endsWith(path, ".html"), endsWith(path, ".htm"): - return "text/html" - case endsWith(path, ".js"), endsWith(path, ".mjs"): - return "application/javascript" - case endsWith(path, ".css"): - return "text/css" - case endsWith(path, ".json"): - return "application/json" - case endsWith(path, ".png"): - return "image/png" - case endsWith(path, ".jpg"), endsWith(path, ".jpeg"): - return "image/jpeg" - case endsWith(path, ".gif"): - return "image/gif" - case endsWith(path, ".svg"): - return "image/svg+xml" - case endsWith(path, ".ico"): - return "image/x-icon" - case endsWith(path, ".woff"): - return "font/woff" - case endsWith(path, ".woff2"): - return "font/woff2" - case endsWith(path, ".ttf"): - return "font/ttf" - default: - return "application/octet-stream" - } -} - -func endsWith(s, suffix string) bool { - return len(s) >= len(suffix) && s[len(s)-len(suffix):] == suffix -} - -// executeJavaScript is a stub for non-cgo builds -func executeJavaScript(js string) { - androidLogf("warn", "executeJavaScript called but cgo is not enabled") -} diff --git a/v3/pkg/application/application_darwin.go b/v3/pkg/application/application_darwin.go deleted file mode 100644 index 287b66e84..000000000 --- a/v3/pkg/application/application_darwin.go +++ /dev/null @@ -1,747 +0,0 @@ -//go:build darwin && !ios && !server - -package application - -/* - -#cgo CFLAGS: -mmacosx-version-min=10.13 -x objective-c -#cgo LDFLAGS: -framework Cocoa -mmacosx-version-min=10.13 - -#include "application_darwin.h" -#include "application_darwin_delegate.h" -#include "webview_window_darwin.h" -#include - -extern void registerListener(unsigned int event); - -#import -#import - -static AppDelegate *appDelegate = nil; - -static void init(void) { - [NSApplication sharedApplication]; - appDelegate = [[AppDelegate alloc] init]; - [NSApp setDelegate:appDelegate]; - - [NSEvent addLocalMonitorForEventsMatchingMask:NSEventMaskLeftMouseDown handler:^NSEvent * _Nullable(NSEvent * _Nonnull event) { - NSWindow* eventWindow = [event window]; - if (eventWindow == nil ) { - return event; - } - WebviewWindowDelegate* windowDelegate = (WebviewWindowDelegate*)[eventWindow delegate]; - if (windowDelegate == nil) { - return event; - } - if ([windowDelegate respondsToSelector:@selector(handleLeftMouseDown:)]) { - [windowDelegate handleLeftMouseDown:event]; - } - return event; - }]; - - [NSEvent addLocalMonitorForEventsMatchingMask:NSEventMaskLeftMouseUp handler:^NSEvent * _Nullable(NSEvent * _Nonnull event) { - NSWindow* eventWindow = [event window]; - if (eventWindow == nil ) { - return event; - } - WebviewWindowDelegate* windowDelegate = (WebviewWindowDelegate*)[eventWindow delegate]; - if (windowDelegate == nil) { - return event; - } - if ([windowDelegate respondsToSelector:@selector(handleLeftMouseUp:)]) { - [windowDelegate handleLeftMouseUp:eventWindow]; - } - return event; - }]; - - NSDistributedNotificationCenter *center = [NSDistributedNotificationCenter defaultCenter]; - [center addObserver:appDelegate selector:@selector(themeChanged:) name:@"AppleInterfaceThemeChangedNotification" object:nil]; - - // Register the custom URL scheme handler - StartCustomProtocolHandler(); -} - -static bool isDarkMode(void) { - NSUserDefaults* userDefaults = [NSUserDefaults standardUserDefaults]; - if (userDefaults == nil) { - return false; - } - - NSString *interfaceStyle = [userDefaults stringForKey:@"AppleInterfaceStyle"]; - if (interfaceStyle == nil) { - return false; - } - - return [interfaceStyle isEqualToString:@"Dark"]; -} - -static char* getAccentColor(void) { - @autoreleasepool { - NSColor *accentColor; - if (@available(macOS 10.14, *)) { - accentColor = [NSColor controlAccentColor]; - } else { - // Fallback to system blue for older macOS versions - accentColor = [NSColor systemBlueColor]; - } - // Convert to RGB color space - NSColor *rgbColor = [accentColor colorUsingColorSpace:[NSColorSpace sRGBColorSpace]]; - if (rgbColor == nil) { - rgbColor = accentColor; - } - // Get RGB components - CGFloat red, green, blue, alpha; - [rgbColor getRed:&red green:&green blue:&blue alpha:&alpha]; - // Convert to 0-255 range and format as rgb() string - int r = (int)(red * 255); - int g = (int)(green * 255); - int b = (int)(blue * 255); - NSString *colorString = [NSString stringWithFormat:@"rgb(%d,%d,%d)", r, g, b]; - return strdup([colorString UTF8String]); - } -} - -static void setApplicationShouldTerminateAfterLastWindowClosed(bool shouldTerminate) { - // Get the NSApp delegate - AppDelegate *appDelegate = (AppDelegate*)[NSApp delegate]; - // Set the applicationShouldTerminateAfterLastWindowClosed boolean - appDelegate.shouldTerminateWhenLastWindowClosed = shouldTerminate; -} - -static void setActivationPolicy(int policy) { - [NSApp setActivationPolicy:policy]; -} - -static void activateIgnoringOtherApps() { - [NSApp activateIgnoringOtherApps:YES]; -} - -static void run(void) { - @autoreleasepool { - [NSApp run]; - [appDelegate release]; - [NSApp abortModal]; - } -} - -// destroyApp destroys the application -static void destroyApp(void) { - [NSApp terminate:nil]; -} - -// Set the application menu -static void setApplicationMenu(void *menu) { - NSMenu *nsMenu = (__bridge NSMenu *)menu; - [NSApp setMainMenu:menu]; -} - -// Get the application name -static char* getAppName(void) { - NSString *appName = [NSRunningApplication currentApplication].localizedName; - if( appName == nil ) { - appName = [[NSProcessInfo processInfo] processName]; - } - return strdup([appName UTF8String]); -} - -// get the current window ID -static unsigned int getCurrentWindowID(void) { - // AppKit must be accessed on the main thread. This function may be called - // from arbitrary Go goroutines, so we hop to the main queue when needed. - __block unsigned int result = 0; - if (NSApp == nil) { - return result; - } - void (^resolve)(void) = ^{ - NSWindow *window = [NSApp keyWindow]; - if (window == nil) { - window = [NSApp mainWindow]; - } - if (window == nil) { - return; - } - WebviewWindowDelegate *delegate = (WebviewWindowDelegate*)[window delegate]; - if (delegate != nil) { - result = delegate.windowId; - } - }; - if ([NSThread isMainThread]) { - resolve(); - } else { - dispatch_sync(dispatch_get_main_queue(), resolve); - } - return result; -} - -// Set the application icon -static void setApplicationIcon(void *icon, int length) { - // On main thread - dispatch_async(dispatch_get_main_queue(), ^{ - NSImage *image = [[NSImage alloc] initWithData:[NSData dataWithBytes:icon length:length]]; - [NSApp setApplicationIconImage:image]; - }); -} - -// Hide the application -static void hide(void) { - [NSApp hide:nil]; -} - -// Show the application -static void show(void) { - [NSApp unhide:nil]; -} - -static const char* serializationNSDictionary(void *dict) { - @autoreleasepool { - NSDictionary *nsDict = (__bridge NSDictionary *)dict; - - if ([NSJSONSerialization isValidJSONObject:nsDict]) { - NSError *error; - NSData *data = [NSJSONSerialization dataWithJSONObject:nsDict options:kNilOptions error:&error]; - NSString *result = [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding]; - - return strdup([result UTF8String]); - } - } - - return nil; -} - -static void startSingleInstanceListener(const char *uniqueID) { - // Convert to NSString - NSString *uid = [NSString stringWithUTF8String:uniqueID]; - [[NSDistributedNotificationCenter defaultCenter] addObserver:appDelegate - selector:@selector(handleSecondInstanceNotification:) name:uid object:nil]; -} -*/ -import "C" -import ( - "sync" - "time" - "unsafe" - - "encoding/json" - - "github.com/wailsapp/wails/v3/internal/assetserver/webview" - "github.com/wailsapp/wails/v3/internal/operatingsystem" - "github.com/wailsapp/wails/v3/pkg/events" -) - -type macosApp struct { - applicationMenu unsafe.Pointer - parent *App -} - -func (m *macosApp) isDarkMode() bool { - return bool(C.isDarkMode()) -} - -func (m *macosApp) getAccentColor() string { - accentColorC := C.getAccentColor() - defer C.free(unsafe.Pointer(accentColorC)) - return C.GoString(accentColorC) -} - -func getNativeApplication() *macosApp { - return globalApplication.impl.(*macosApp) -} - -func (m *macosApp) hide() { - C.hide() -} - -func (m *macosApp) show() { - C.show() -} - -func (m *macosApp) on(eventID uint) { - C.registerListener(C.uint(eventID)) -} - -func (m *macosApp) setIcon(icon []byte) { - C.setApplicationIcon(unsafe.Pointer(&icon[0]), C.int(len(icon))) -} - -func (m *macosApp) name() string { - appName := C.getAppName() - defer C.free(unsafe.Pointer(appName)) - return C.GoString(appName) -} - -func (m *macosApp) getCurrentWindowID() uint { - return uint(C.getCurrentWindowID()) -} - -func (m *macosApp) setApplicationMenu(menu *Menu) { - if menu == nil { - // Create a default menu for mac - menu = DefaultApplicationMenu() - } - menu.Update() - - // Convert impl to macosMenu object - m.applicationMenu = (menu.impl).(*macosMenu).nsMenu - C.setApplicationMenu(m.applicationMenu) -} - -func (m *macosApp) run() error { - if m.parent.options.SingleInstance != nil { - cUniqueID := C.CString(m.parent.options.SingleInstance.UniqueID) - defer C.free(unsafe.Pointer(cUniqueID)) - C.startSingleInstanceListener(cUniqueID) - } - // Add a hook to the ApplicationDidFinishLaunching event - m.parent.Event.OnApplicationEvent( - events.Mac.ApplicationDidFinishLaunching, - func(*ApplicationEvent) { - C.setApplicationShouldTerminateAfterLastWindowClosed( - C.bool(m.parent.options.Mac.ApplicationShouldTerminateAfterLastWindowClosed), - ) - C.setActivationPolicy(C.int(m.parent.options.Mac.ActivationPolicy)) - C.activateIgnoringOtherApps() - }, - ) - m.setupCommonEvents() - // setup event listeners - for eventID := range m.parent.applicationEventListeners { - m.on(eventID) - } - C.run() - return nil -} - -func (m *macosApp) destroy() { - C.destroyApp() -} - -func (m *macosApp) GetFlags(options Options) map[string]any { - if options.Flags == nil { - options.Flags = make(map[string]any) - } - return options.Flags -} - -func newPlatformApp(app *App) *macosApp { - C.init() - return &macosApp{ - parent: app, - } -} - -//export processApplicationEvent -func processApplicationEvent(eventID C.uint, data unsafe.Pointer) { - event := newApplicationEvent(events.ApplicationEventType(eventID)) - - if data != nil { - dataCStrJSON := C.serializationNSDictionary(data) - if dataCStrJSON != nil { - defer C.free(unsafe.Pointer(dataCStrJSON)) - - dataJSON := C.GoString(dataCStrJSON) - var result map[string]any - err := json.Unmarshal([]byte(dataJSON), &result) - - if err != nil { - panic(err) - } - - event.Context().setData(result) - } - } - - switch event.Id { - case uint(events.Mac.ApplicationDidChangeTheme): - isDark := globalApplication.Env.IsDarkMode() - event.Context().setIsDarkMode(isDark) - } - applicationEvents <- event -} - -//export processWindowEvent -func processWindowEvent(windowID C.uint, eventID C.uint) { - windowEvents <- &windowEvent{ - WindowID: uint(windowID), - EventID: uint(eventID), - } -} - -//export processMessage -func processMessage(windowID C.uint, message *C.char, origin *C.char, isMainFrame bool) { - o := "" - if origin != nil { - o = C.GoString(origin) - } - windowMessageBuffer <- &windowMessage{ - windowId: uint(windowID), - message: C.GoString(message), - originInfo: &OriginInfo{ - Origin: o, - IsMainFrame: isMainFrame, - }, - } -} - -//export processURLRequest -func processURLRequest(windowID C.uint, wkUrlSchemeTask unsafe.Pointer) { - window, ok := globalApplication.Window.GetByID(uint(windowID)) - if !ok || window == nil { - globalApplication.debug("could not find window with id", "windowID", windowID) - return - } - - webviewRequests <- &webViewAssetRequest{ - Request: webview.NewRequest(wkUrlSchemeTask), - windowId: uint(windowID), - windowName: window.Name(), - } -} - -//export processWindowKeyDownEvent -func processWindowKeyDownEvent(windowID C.uint, acceleratorString *C.char) { - windowKeyEvents <- &windowKeyEvent{ - windowId: uint(windowID), - acceleratorString: C.GoString(acceleratorString), - } -} - -//export processDragItems -func processDragItems(windowID C.uint, arr **C.char, length C.int, x C.int, y C.int) { - var filenames []string - // Convert the C array to a Go slice - goSlice := (*[1 << 30]*C.char)(unsafe.Pointer(arr))[:length:length] - for _, str := range goSlice { - filenames = append(filenames, C.GoString(str)) - } - - globalApplication.debug( - "[DragDropDebug] processDragItems called", - "windowID", - windowID, - "fileCount", - len(filenames), - "x", - x, - "y", - y, - ) - targetWindow, ok := globalApplication.Window.GetByID(uint(windowID)) - if !ok || targetWindow == nil { - println("Error: processDragItems could not find window with ID:", uint(windowID)) - return - } - - globalApplication.debug( - "[DragDropDebug] processDragItems: Calling targetWindow.InitiateFrontendDropProcessing", - ) - targetWindow.InitiateFrontendDropProcessing(filenames, int(x), int(y)) -} - -//export macosOnDragEnter -func macosOnDragEnter(windowID C.uint) { - window, ok := globalApplication.Window.GetByID(uint(windowID)) - if !ok || window == nil { - return - } - - // Call JavaScript to show drag entered state - window.ExecJS("window._wails.handleDragEnter();") -} - -//export macosOnDragExit -func macosOnDragExit(windowID C.uint) { - window, ok := globalApplication.Window.GetByID(uint(windowID)) - if !ok || window == nil { - return - } - - // Call JavaScript to clean up drag state - window.ExecJS("window._wails.handleDragLeave();") -} - -var ( - // Pre-allocated buffer for drag JS calls to avoid allocations - dragOverJSBuffer = make([]byte, 128) // Increased for safety - dragOverJSMutex sync.Mutex // Protects dragOverJSBuffer - dragOverJSPrefix = []byte("window._wails.handleDragOver(") - - // Cache window references to avoid repeated lookups - windowImplCache sync.Map // windowID -> *macosWebviewWindow - - // Per-window drag throttle state - dragThrottle sync.Map // windowID -> *dragThrottleState -) - -type dragThrottleState struct { - mu sync.Mutex // Protects all fields below - lastX, lastY int - timer *time.Timer - pendingX int - pendingY int - hasPending bool -} - -// clearWindowDragCache removes cached references for a window -func clearWindowDragCache(windowID uint) { - windowImplCache.Delete(windowID) - - // Cancel any pending timer - if throttleVal, ok := dragThrottle.Load(windowID); ok { - if throttle, ok := throttleVal.(*dragThrottleState); ok { - throttle.mu.Lock() - if throttle.timer != nil { - throttle.timer.Stop() - } - throttle.mu.Unlock() - } - } - dragThrottle.Delete(windowID) -} - -// writeInt writes an integer to a byte slice and returns the number of bytes written -func writeInt(buf []byte, n int) int { - if n < 0 { - if len(buf) == 0 { - return 0 - } - buf[0] = '-' - return 1 + writeInt(buf[1:], -n) - } - if n == 0 { - if len(buf) == 0 { - return 0 - } - buf[0] = '0' - return 1 - } - - // Count digits - tmp := n - digits := 0 - for tmp > 0 { - digits++ - tmp /= 10 - } - - // Bounds check - if digits > len(buf) { - return 0 - } - - // Write digits in reverse - for i := digits - 1; i >= 0; i-- { - buf[i] = byte('0' + n%10) - n /= 10 - } - return digits -} - -//export macosOnDragOver -func macosOnDragOver(windowID C.uint, x C.int, y C.int) { - winID := uint(windowID) - intX, intY := int(x), int(y) - - // Get or create throttle state - throttleKey := winID - throttleVal, _ := dragThrottle.LoadOrStore(throttleKey, &dragThrottleState{ - lastX: intX, - lastY: intY, - }) - throttle := throttleVal.(*dragThrottleState) - - throttle.mu.Lock() - - // Update pending position - throttle.pendingX = intX - throttle.pendingY = intY - throttle.hasPending = true - - // If timer is already running, just update the pending position - if throttle.timer != nil { - throttle.mu.Unlock() - return - } - - // Apply 5-pixel threshold for immediate update - dx := intX - throttle.lastX - dy := intY - throttle.lastY - if dx < 0 { - dx = -dx - } - if dy < 0 { - dy = -dy - } - - // Check if we should send an immediate update - shouldSendNow := dx >= 5 || dy >= 5 - - if shouldSendNow { - // Update last position - throttle.lastX = intX - throttle.lastY = intY - throttle.hasPending = false - - // Send this update immediately (unlock before JS call to avoid deadlock) - throttle.mu.Unlock() - sendDragUpdate(winID, intX, intY) - throttle.mu.Lock() - } - - // Start 50ms timer for next update (whether we sent now or not) - throttle.timer = time.AfterFunc(50*time.Millisecond, func() { - // Execute on main thread to ensure UI updates - InvokeSync(func() { - throttle.mu.Lock() - // Clear timer reference - throttle.timer = nil - - // Send pending update if any - if throttle.hasPending { - pendingX, pendingY := throttle.pendingX, throttle.pendingY - throttle.lastX = pendingX - throttle.lastY = pendingY - throttle.hasPending = false - throttle.mu.Unlock() - sendDragUpdate(winID, pendingX, pendingY) - } else { - throttle.mu.Unlock() - } - }) - }) - throttle.mu.Unlock() -} - -// sendDragUpdate sends the actual drag update to JavaScript -func sendDragUpdate(winID uint, x, y int) { - // Try cached implementation first - var darwinImpl *macosWebviewWindow - var needsExecJS bool - - if cached, found := windowImplCache.Load(winID); found { - darwinImpl = cached.(*macosWebviewWindow) - if darwinImpl != nil && darwinImpl.nsWindow != nil { - needsExecJS = true - } else { - // Invalid cache entry, remove it - windowImplCache.Delete(winID) - } - } - - if !needsExecJS { - // Fallback to full lookup - window, ok := globalApplication.Window.GetByID(winID) - if !ok || window == nil { - return - } - - // Type assert to WebviewWindow - webviewWindow, ok := window.(*WebviewWindow) - if !ok || webviewWindow == nil { - return - } - - // Get implementation - darwinImpl, ok = webviewWindow.impl.(*macosWebviewWindow) - if !ok { - return - } - - // Cache for next time - windowImplCache.Store(winID, darwinImpl) - needsExecJS = true - } - - if !needsExecJS || darwinImpl == nil { - return - } - - // Protect shared buffer access - dragOverJSMutex.Lock() - - // Build JS string with zero allocations - // Format: "window._wails.handleDragOver(X,Y)" - // Max length with int32 coords: 30 + 11 + 1 + 11 + 1 + 1 = 55 bytes - n := copy(dragOverJSBuffer[:], dragOverJSPrefix) - n += writeInt(dragOverJSBuffer[n:], x) - if n < len(dragOverJSBuffer) { - dragOverJSBuffer[n] = ',' - n++ - } - n += writeInt(dragOverJSBuffer[n:], y) - if n < len(dragOverJSBuffer) { - dragOverJSBuffer[n] = ')' - n++ - } - if n < len(dragOverJSBuffer) { - dragOverJSBuffer[n] = 0 // null terminate for C - } else { - // Buffer overflow - this should not happen with 128 byte buffer - dragOverJSMutex.Unlock() - return - } - - // Call JavaScript with zero allocations - darwinImpl.execJSDragOver(dragOverJSBuffer[:n+1]) // Include null terminator - dragOverJSMutex.Unlock() -} - -//export processMenuItemClick -func processMenuItemClick(menuID C.uint) { - menuItemClicked <- uint(menuID) -} - -//export shouldQuitApplication -func shouldQuitApplication() C.bool { - // TODO: This should be configurable - return C.bool(globalApplication.shouldQuit()) -} - -//export cleanup -func cleanup() { - globalApplication.cleanup() -} - -func (a *App) logPlatformInfo() { - info, err := operatingsystem.Info() - if err != nil { - a.error("error getting OS info: %w", err) - return - } - - a.info("Platform Info:", info.AsLogSlice()...) - -} - -func (a *App) platformEnvironment() map[string]any { - return map[string]any{} -} - -func fatalHandler(errFunc func(error)) { - return -} - -//export HandleOpenFile -func HandleOpenFile(filePath *C.char) { - goFilepath := C.GoString(filePath) - // Create new application event context - eventContext := newApplicationEventContext() - eventContext.setOpenedWithFile(goFilepath) - // EmitEvent application started event - applicationEvents <- &ApplicationEvent{ - Id: uint(events.Common.ApplicationOpenedWithFile), - ctx: eventContext, - } -} - -//export HandleOpenURL -func HandleOpenURL(urlCString *C.char) { - urlString := C.GoString(urlCString) - eventContext := newApplicationEventContext() - eventContext.setURL(urlString) - - // Emit the standard event with the URL string as data - applicationEvents <- &ApplicationEvent{ - Id: uint(events.Common.ApplicationLaunchedWithUrl), - ctx: eventContext, - } -} diff --git a/v3/pkg/application/application_darwin.h b/v3/pkg/application/application_darwin.h deleted file mode 100644 index d4f7bc475..000000000 --- a/v3/pkg/application/application_darwin.h +++ /dev/null @@ -1,11 +0,0 @@ -//go:build darwin && !ios - -#ifndef application_h -#define application_h - -static void init(void); -static void run(void); -static void setActivationPolicy(int policy); -static char *getAppName(void); - -#endif \ No newline at end of file diff --git a/v3/pkg/application/application_darwin_delegate.h b/v3/pkg/application/application_darwin_delegate.h deleted file mode 100644 index 4e7722e4a..000000000 --- a/v3/pkg/application/application_darwin_delegate.h +++ /dev/null @@ -1,25 +0,0 @@ -//go:build darwin && !ios - -#ifndef appdelegate_h -#define appdelegate_h - -#import - -@interface AppDelegate : NSResponder -@property bool shouldTerminateWhenLastWindowClosed; -@property bool shuttingDown; -- (BOOL)applicationSupportsSecureRestorableState:(NSApplication *)app; -@end - -extern void HandleOpenFile(char *); - -// Declarations for Apple Event based custom URL handling and universal link -extern void HandleOpenURL(char*); - -@interface CustomProtocolSchemeHandler : NSObject -+ (void)handleGetURLEvent:(NSAppleEventDescriptor *)event withReplyEvent:(NSAppleEventDescriptor *)replyEvent; -@end - -void StartCustomProtocolHandler(void); - -#endif /* appdelegate_h */ diff --git a/v3/pkg/application/application_darwin_delegate.m b/v3/pkg/application/application_darwin_delegate.m deleted file mode 100644 index 6b33c1421..000000000 --- a/v3/pkg/application/application_darwin_delegate.m +++ /dev/null @@ -1,207 +0,0 @@ -//go:build darwin && !ios -#import "application_darwin_delegate.h" -#import "../events/events_darwin.h" -#import // For Apple Event constants -extern bool hasListeners(unsigned int); -extern bool shouldQuitApplication(); -extern void cleanup(); -extern void handleSecondInstanceData(char * message); -@implementation AppDelegate -- (void)dealloc -{ - [super dealloc]; -} --(BOOL)application:(NSApplication *)sender openFile:(NSString *)filename - { - const char* utf8FileName = filename.UTF8String; - HandleOpenFile((char*)utf8FileName); - return YES; - } -- (BOOL)application:(NSApplication *)application continueUserActivity:(NSUserActivity *)userActivity restorationHandler:(void (^)(NSArray> * _Nullable))restorationHandler { - if ([userActivity.activityType isEqualToString:NSUserActivityTypeBrowsingWeb]) { - NSURL *url = userActivity.webpageURL; - if (url) { - HandleOpenURL((char*)[[url absoluteString] UTF8String]); - return YES; - } - } - return NO; -} -// Create the applicationShouldTerminateAfterLastWindowClosed: method -- (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)theApplication -{ - return self.shouldTerminateWhenLastWindowClosed; -} -- (void)themeChanged:(NSNotification *)notification { - if( hasListeners(EventApplicationDidChangeTheme) ) { - processApplicationEvent(EventApplicationDidChangeTheme, NULL); - } -} -- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender { - if( ! shouldQuitApplication() ) { - return NSTerminateCancel; - } - if( !self.shuttingDown ) { - self.shuttingDown = true; - cleanup(); - } - return NSTerminateNow; -} -- (BOOL)applicationSupportsSecureRestorableState:(NSApplication *)app -{ - return YES; -} -- (BOOL)applicationShouldHandleReopen:(NSNotification *)notification - hasVisibleWindows:(BOOL)flag { // Changed from NSApplication to NSNotification - if( hasListeners(EventApplicationShouldHandleReopen) ) { - processApplicationEvent(EventApplicationShouldHandleReopen, @{@"hasVisibleWindows": @(flag)}); - } - return TRUE; -} -- (void)handleSecondInstanceNotification:(NSNotification *)note; -{ - if (note.userInfo[@"message"] != nil) { - NSString *message = note.userInfo[@"message"]; - const char* utf8Message = message.UTF8String; - handleSecondInstanceData((char*)utf8Message); - } -} -// GENERATED EVENTS START -- (void)applicationDidBecomeActive:(NSNotification *)notification { - if( hasListeners(EventApplicationDidBecomeActive) ) { - processApplicationEvent(EventApplicationDidBecomeActive, NULL); - } -} - -- (void)applicationDidChangeBackingProperties:(NSNotification *)notification { - if( hasListeners(EventApplicationDidChangeBackingProperties) ) { - processApplicationEvent(EventApplicationDidChangeBackingProperties, NULL); - } -} - -- (void)applicationDidChangeEffectiveAppearance:(NSNotification *)notification { - if( hasListeners(EventApplicationDidChangeEffectiveAppearance) ) { - processApplicationEvent(EventApplicationDidChangeEffectiveAppearance, NULL); - } -} - -- (void)applicationDidChangeIcon:(NSNotification *)notification { - if( hasListeners(EventApplicationDidChangeIcon) ) { - processApplicationEvent(EventApplicationDidChangeIcon, NULL); - } -} - -- (void)applicationDidChangeOcclusionState:(NSNotification *)notification { - if( hasListeners(EventApplicationDidChangeOcclusionState) ) { - processApplicationEvent(EventApplicationDidChangeOcclusionState, NULL); - } -} - -- (void)applicationDidChangeScreenParameters:(NSNotification *)notification { - if( hasListeners(EventApplicationDidChangeScreenParameters) ) { - processApplicationEvent(EventApplicationDidChangeScreenParameters, NULL); - } -} - -- (void)applicationDidChangeStatusBarFrame:(NSNotification *)notification { - if( hasListeners(EventApplicationDidChangeStatusBarFrame) ) { - processApplicationEvent(EventApplicationDidChangeStatusBarFrame, NULL); - } -} - -- (void)applicationDidChangeStatusBarOrientation:(NSNotification *)notification { - if( hasListeners(EventApplicationDidChangeStatusBarOrientation) ) { - processApplicationEvent(EventApplicationDidChangeStatusBarOrientation, NULL); - } -} - -- (void)applicationDidFinishLaunching:(NSNotification *)notification { - if( hasListeners(EventApplicationDidFinishLaunching) ) { - processApplicationEvent(EventApplicationDidFinishLaunching, NULL); - } -} - -- (void)applicationDidHide:(NSNotification *)notification { - if( hasListeners(EventApplicationDidHide) ) { - processApplicationEvent(EventApplicationDidHide, NULL); - } -} - -- (void)applicationDidResignActive:(NSNotification *)notification { - if( hasListeners(EventApplicationDidResignActive) ) { - processApplicationEvent(EventApplicationDidResignActive, NULL); - } -} - -- (void)applicationDidUnhide:(NSNotification *)notification { - if( hasListeners(EventApplicationDidUnhide) ) { - processApplicationEvent(EventApplicationDidUnhide, NULL); - } -} - -- (void)applicationDidUpdate:(NSNotification *)notification { - if( hasListeners(EventApplicationDidUpdate) ) { - processApplicationEvent(EventApplicationDidUpdate, NULL); - } -} - -- (void)applicationWillBecomeActive:(NSNotification *)notification { - if( hasListeners(EventApplicationWillBecomeActive) ) { - processApplicationEvent(EventApplicationWillBecomeActive, NULL); - } -} - -- (void)applicationWillFinishLaunching:(NSNotification *)notification { - if( hasListeners(EventApplicationWillFinishLaunching) ) { - processApplicationEvent(EventApplicationWillFinishLaunching, NULL); - } -} - -- (void)applicationWillHide:(NSNotification *)notification { - if( hasListeners(EventApplicationWillHide) ) { - processApplicationEvent(EventApplicationWillHide, NULL); - } -} - -- (void)applicationWillResignActive:(NSNotification *)notification { - if( hasListeners(EventApplicationWillResignActive) ) { - processApplicationEvent(EventApplicationWillResignActive, NULL); - } -} - -- (void)applicationWillTerminate:(NSNotification *)notification { - if( hasListeners(EventApplicationWillTerminate) ) { - processApplicationEvent(EventApplicationWillTerminate, NULL); - } -} - -- (void)applicationWillUnhide:(NSNotification *)notification { - if( hasListeners(EventApplicationWillUnhide) ) { - processApplicationEvent(EventApplicationWillUnhide, NULL); - } -} - -- (void)applicationWillUpdate:(NSNotification *)notification { - if( hasListeners(EventApplicationWillUpdate) ) { - processApplicationEvent(EventApplicationWillUpdate, NULL); - } -} - -// GENERATED EVENTS END -@end -// Implementation for Apple Event based custom URL handling -@implementation CustomProtocolSchemeHandler -+ (void)handleGetURLEvent:(NSAppleEventDescriptor *)event withReplyEvent:(NSAppleEventDescriptor *)replyEvent { - NSString *urlStr = [[event paramDescriptorForKeyword:keyDirectObject] stringValue]; - if (urlStr) { - HandleOpenURL((char*)[urlStr UTF8String]); - } -} -@end -void StartCustomProtocolHandler(void) { - NSAppleEventManager *appleEventManager = [NSAppleEventManager sharedAppleEventManager]; - [appleEventManager setEventHandler:[CustomProtocolSchemeHandler class] - andSelector:@selector(handleGetURLEvent:withReplyEvent:) - forEventClass:kInternetEventClass - andEventID: kAEGetURL]; -} diff --git a/v3/pkg/application/application_debug.go b/v3/pkg/application/application_debug.go deleted file mode 100644 index bc850c3e8..000000000 --- a/v3/pkg/application/application_debug.go +++ /dev/null @@ -1,71 +0,0 @@ -//go:build !production - -package application - -import ( - "github.com/go-git/go-git/v5" - "github.com/samber/lo" - "github.com/wailsapp/wails/v3/internal/version" - "path/filepath" - "runtime/debug" -) - -// BuildSettings contains the build settings for the application -var BuildSettings map[string]string - -// BuildInfo contains the build info for the application -var BuildInfo *debug.BuildInfo - -func init() { - var ok bool - BuildInfo, ok = debug.ReadBuildInfo() - if !ok { - return - } - BuildSettings = lo.Associate(BuildInfo.Settings, func(setting debug.BuildSetting) (string, string) { - return setting.Key, setting.Value - }) -} - -// We use this to patch the application to production mode. -func newApplication(options Options) *App { - result := &App{ - isDebugMode: true, - options: options, - } - result.init() - return result -} - -func (a *App) logStartup() { - var args []any - - // BuildInfo is nil when build with garble - if BuildInfo == nil { - return - } - - wailsPackage, _ := lo.Find(BuildInfo.Deps, func(dep *debug.Module) bool { - return dep.Path == "github.com/wailsapp/wails/v3" - }) - - wailsVersion := version.String() - if wailsPackage != nil && wailsPackage.Replace != nil { - wailsVersion = "(local) => " + filepath.ToSlash(wailsPackage.Replace.Path) - // Get the latest commit hash - repo, err := git.PlainOpen(filepath.Join(wailsPackage.Replace.Path, "..")) - if err == nil { - head, err := repo.Head() - if err == nil { - wailsVersion += " (" + head.Hash().String()[:8] + ")" - } - } - } - args = append(args, "Wails", wailsVersion) - args = append(args, "Compiler", BuildInfo.GoVersion) - for key, value := range BuildSettings { - args = append(args, key, value) - } - - a.info("Build Info:", args...) -} diff --git a/v3/pkg/application/application_dev.go b/v3/pkg/application/application_dev.go deleted file mode 100644 index e12033e33..000000000 --- a/v3/pkg/application/application_dev.go +++ /dev/null @@ -1,51 +0,0 @@ -//go:build !production - -package application - -import ( - "net/http" - "time" - - "github.com/wailsapp/wails/v3/internal/assetserver" -) - -var devMode = false - -func (a *App) preRun() error { - // Check for frontend server url - frontendURL := assetserver.GetDevServerURL() - if frontendURL != "" { - devMode = true - // We want to check if the frontend server is running by trying to http get the url - // and if it is not, we wait 500ms and try again for a maximum of 10 times. If it is - // still not available, we return an error. - // This is to allow the frontend server to start up before the backend server. - client := http.Client{} - a.Logger.Info("Waiting for frontend dev server to start...", "url", frontendURL) - for i := 0; i < 10; i++ { - _, err := client.Get(frontendURL) - if err == nil { - a.Logger.Info("Connected to frontend dev server!") - return nil - } - // Wait 500ms - time.Sleep(500 * time.Millisecond) - if i%2 == 0 { - a.Logger.Info("Retrying...") - } - } - a.fatal("unable to connect to frontend server. Please check it is running - FRONTEND_DEVSERVER_URL='%s'", frontendURL) - } - return nil -} - -func (a *App) postQuit() { - if devMode { - a.Logger.Info("The application has terminated, but the watcher is still running.") - a.Logger.Info("To terminate the watcher, press CTRL+C") - } -} - -func (a *App) enableDevTools() { - -} diff --git a/v3/pkg/application/application_ios.go b/v3/pkg/application/application_ios.go deleted file mode 100644 index 6af32bf5e..000000000 --- a/v3/pkg/application/application_ios.go +++ /dev/null @@ -1,462 +0,0 @@ -//go:build ios && !server - -package application - -/* -#cgo CFLAGS: -x objective-c -fobjc-arc -#cgo LDFLAGS: -framework Foundation -framework UIKit -framework WebKit - -#include -#include -#include "application_ios.h" -#include "webview_window_ios.h" - -*/ -import "C" - -import ( - "fmt" - "strings" - "time" - "unsafe" - - "encoding/json" - - "github.com/wailsapp/wails/v3/internal/assetserver/webview" - "github.com/wailsapp/wails/v3/pkg/events" -) - -func iosConsoleLogf(level string, format string, a ...interface{}) { - msg := fmt.Sprintf(format, a...) - clevel := C.CString(level) - cmsg := C.CString(msg) - defer C.free(unsafe.Pointer(clevel)) - defer C.free(unsafe.Pointer(cmsg)) - C.ios_console_log(clevel, cmsg) -} - -func init() { - iosConsoleLogf("info", "🔵 [application_ios.go] START init()") - // For iOS, we need to handle signals differently - // Disable signal handling to avoid conflicts with iOS - // DO NOT call runtime.LockOSThread() - it causes signal handling issues on iOS! - iosConsoleLogf("info", "🔵 [application_ios.go] Skipping runtime.LockOSThread() on iOS") - - // Disable all signal handling on iOS - // iOS apps run in a sandboxed environment where signal handling is restricted - iosConsoleLogf("info", "🔵 [application_ios.go] END init()") -} - -//export init_go -func init_go() { - iosConsoleLogf("info", "🔵 [application_ios.go] init_go() called from iOS") - // This is called from the iOS main function - // to initialize the Go runtime -} - -func (a *App) platformRun() { - iosConsoleLogf("info", "🔵 [application_ios.go] START platformRun()") - - iosConsoleLogf("info", "🔵 [application_ios.go] platformRun called, initializing...") - - // Initialize what we need for the Go side - iosConsoleLogf("info", "🔵 [application_ios.go] About to call C.ios_app_init()") - C.ios_app_init() - iosConsoleLogf("info", "🔵 [application_ios.go] C.ios_app_init() returned") - - // Wait a bit for the UI to be ready (UIApplicationMain is running in main thread) - // The app delegate's didFinishLaunchingWithOptions will be called - iosConsoleLogf("info", "🔵 [application_ios.go] Waiting for UI to be ready...") - time.Sleep(2 * time.Second) // Give the app delegate time to initialize - - // The WebView will be created when the window runs (via app.Window.NewWithOptions in main.go) - iosConsoleLogf("info", "🔵 [application_ios.go] WebView creation will be handled by window manager") - - // UIApplicationMain is running in the main thread (called from main.m) - // We just need to keep the Go runtime alive - iosConsoleLogf("info", "🔵 [application_ios.go] Blocking to keep Go runtime alive...") - select {} // Block forever -} - -func (a *App) platformQuit() { - C.ios_app_quit() -} - -func (a *App) isDarkMode() bool { - return bool(C.ios_is_dark_mode()) -} - -func (a *App) isWindows() bool { - return false -} - -//export LogInfo -func LogInfo(source *C.char, message *C.char) { - goSource := C.GoString(source) - goMessage := C.GoString(message) - - // Add iOS marker for HTML logger - iosConsoleLogf("info", "[iOS-%s] %s", goSource, goMessage) - - if globalApplication != nil && globalApplication.Logger != nil { - globalApplication.info("iOS log", "source", goSource, "message", goMessage) - } -} - -// Platform-specific app implementation for iOS -type iosApp struct { - parent *App -} - -// newPlatformApp creates an iosApp for the provided App and applies iOS-specific -// configuration derived from app.options. It sets input accessory visibility, -// scrolling/bounce/indicator behavior, navigation gestures, link preview, -// media playback, inspector, user agent strings, app background color, and -// native tabs (marshaling items to JSON when enabled). The function invokes -// platform bindings to apply these settings and returns the configured *iosApp. -func newPlatformApp(app *App) *iosApp { - iosConsoleLogf("info", "🔵 [application_ios.go] START newPlatformApp()") - // iOS initialization - result := &iosApp{ - parent: app, - } - // Configure input accessory visibility according to options - // Default: false (show accessory) when not explicitly set to true - disable := false - if app != nil { - disable = app.options.IOS.DisableInputAccessoryView - } - C.ios_set_disable_input_accessory(C.bool(disable)) - iosConsoleLogf("info", "🔵 [application_ios.go] Input accessory view %s", map[bool]string{true: "DISABLED", false: "ENABLED"}[disable]) - - // Scrolling / Bounce / Indicators (defaults enabled; using Disable* flags) - C.ios_set_disable_scroll(C.bool(app.options.IOS.DisableScroll)) - C.ios_set_disable_bounce(C.bool(app.options.IOS.DisableBounce)) - C.ios_set_disable_scroll_indicators(C.bool(app.options.IOS.DisableScrollIndicators)) - - // Navigation gestures (Enable*) - C.ios_set_enable_back_forward_gestures(C.bool(app.options.IOS.EnableBackForwardNavigationGestures)) - - // Link preview (Disable*) - C.ios_set_disable_link_preview(C.bool(app.options.IOS.DisableLinkPreview)) - - // Media playback - C.ios_set_enable_inline_media_playback(C.bool(app.options.IOS.EnableInlineMediaPlayback)) - C.ios_set_enable_autoplay_without_user_action(C.bool(app.options.IOS.EnableAutoplayWithoutUserAction)) - - // Inspector (Disable*) - C.ios_set_disable_inspectable(C.bool(app.options.IOS.DisableInspectable)) - - // User agent strings - if ua := strings.TrimSpace(app.options.IOS.UserAgent); ua != "" { - cua := C.CString(ua) - C.ios_set_user_agent(cua) - C.free(unsafe.Pointer(cua)) - } - if appName := strings.TrimSpace(app.options.IOS.ApplicationNameForUserAgent); appName != "" { - cname := C.CString(appName) - C.ios_set_app_name_for_user_agent(cname) - C.free(unsafe.Pointer(cname)) - } - // App-wide background colour for iOS window (pre-WebView) - if app.options.IOS.AppBackgroundColourSet { - rgba := app.options.IOS.BackgroundColour - C.ios_set_app_background_color( - C.uchar(rgba.Red), C.uchar(rgba.Green), C.uchar(rgba.Blue), C.uchar(rgba.Alpha), C.bool(true), - ) - } else { - // Ensure it's marked as not set to allow delegate to fallback to white - C.ios_set_app_background_color(255, 255, 255, 255, C.bool(false)) - } - // Native tabs option: only enable when explicitly requested - if app.options.IOS.EnableNativeTabs { - if len(app.options.IOS.NativeTabsItems) > 0 { - if data, err := json.Marshal(app.options.IOS.NativeTabsItems); err == nil { - cjson := C.CString(string(data)) - C.ios_native_tabs_set_items_json(cjson) - C.free(unsafe.Pointer(cjson)) - } else if globalApplication != nil { - globalApplication.error("Failed to marshal IOS.NativeTabsItems: %v", err) - } - } - C.ios_native_tabs_set_enabled(C.bool(true)) - } - - iosConsoleLogf("info", "🔵 [application_ios.go] END newPlatformApp() - iosApp created") - return result -} - -func (a *iosApp) run() error { - iosConsoleLogf("info", "🔵 [application_ios.go] START iosApp.run()") - - // Initialize and create the WebView - // UIApplicationMain is already running in the main thread (from main.m) - // Wire common events (e.g. map ApplicationDidFinishLaunching → Common.ApplicationStarted) - a.setupCommonEvents() - iosConsoleLogf("info", "🔵 [application_ios.go] About to call parent.platformRun()") - a.parent.platformRun() - - // platformRun blocks forever with select{} - // If we get here, something went wrong - iosConsoleLogf("error", "🔵 [application_ios.go] ERROR: platformRun() returned unexpectedly") - return nil -} - -func (a *iosApp) destroy() { - iosConsoleLogf("info", "🔵 [application_ios.go] iosApp.destroy() called") - // Cleanup iOS resources -} - -func (a *iosApp) setIcon(_ []byte) { - // iOS app icon is set through Info.plist -} - -func (a *iosApp) name() string { - return a.parent.options.Name -} - -func (a *iosApp) GetFlags(options Options) map[string]any { - return nil -} - -// dispatchOnMainThread is implemented in mainthread_ios.go - -func (a *iosApp) getAccentColor() string { - // iOS accent color - return "" -} - -func (a *iosApp) getCurrentWindowID() uint { - // iOS current window ID - return 0 -} - -func (a *iosApp) hide() { - // iOS hide application - minimize to background -} - -func (a *iosApp) isDarkMode() bool { - return a.parent.isDarkMode() -} - -// isOnMainThread is implemented in mainthread_ios.go - -func (a *iosApp) on(_ uint) { - // iOS event handling -} - -func (a *iosApp) setApplicationMenu(_ *Menu) { - // iOS doesn't have application menus -} - -func (a *iosApp) show() { - // iOS show application -} - -func (a *iosApp) showAboutDialog(_ string, _ string, _ []byte) { - // iOS about dialog -} - -func (a *iosApp) getPrimaryScreen() (*Screen, error) { - screens, err := getScreens() - if err != nil || len(screens) == 0 { - return nil, err - } - return screens[0], nil -} - -func (a *iosApp) getScreens() ([]*Screen, error) { - return getScreens() -} - -func (a *App) logPlatformInfo() { - // Log iOS platform info -} - -func (a *App) platformEnvironment() map[string]any { - return map[string]any{ - "platform": "ios", - } -} - -func fatalHandler(errFunc func(error)) { - // iOS fatal handler -} - -// ExecuteJavaScript runs JavaScript code in the WebView -func (a *App) ExecuteJavaScript(windowID uint, js string) { - cjs := C.CString(js) - defer C.free(unsafe.Pointer(cjs)) - C.ios_execute_javascript(C.uint(windowID), cjs) -} - -// ServeAssetRequest handles requests from the WebView -// -//export ServeAssetRequest -func ServeAssetRequest(windowID C.uint, urlSchemeTask unsafe.Pointer) { - iosConsoleLogf("info", "[iOS-ServeAssetRequest] 🔵 Called with windowID=%d", windowID) - - // Route the request through the webviewRequests channel to use the asset server - go func() { - iosConsoleLogf("info", "[iOS-ServeAssetRequest] 🔵 Inside goroutine") - - // Use the webview package's NewRequest to wrap the task pointer - req := webview.NewRequest(urlSchemeTask) - url, _ := req.URL() - - // Log every single request with clear markers - iosConsoleLogf("info", "===============================================") - iosConsoleLogf("info", "[iOS-REQUEST] 🌐 RECEIVED REQUEST FOR: %s", url) - iosConsoleLogf("info", "===============================================") - - // Special CSS logging with big markers - if strings.Contains(url, ".css") || strings.Contains(url, "style") { - iosConsoleLogf("warn", "🎨🎨🎨🎨🎨🎨🎨🎨🎨🎨🎨🎨🎨🎨🎨") - iosConsoleLogf("warn", "[iOS-CSS] CSS FILE REQUESTED: %s", url) - iosConsoleLogf("warn", "🎨🎨🎨🎨🎨🎨🎨🎨🎨🎨🎨🎨🎨🎨🎨") - } - - // Log images separately - if strings.Contains(url, ".png") || strings.Contains(url, ".jpg") || strings.Contains(url, ".svg") { - iosConsoleLogf("info", "[iOS-IMAGE] 🇼 %s", url) - } - - // Log JS files - if strings.Contains(url, ".js") { - iosConsoleLogf("info", "[iOS-JS] ⚙️ %s", url) - } - - // Try to resolve the window name from the window ID so the AssetServer - // receives both x-wails-window-id and x-wails-window-name headers. - winName := "" - if globalApplication != nil { - if window, ok := globalApplication.Window.GetByID(uint(windowID)); ok && window != nil { - winName = window.Name() - } else { - iosConsoleLogf("warn", "[iOS-ServeAssetRequest] 🟠 Could not resolve window name for id=%d", windowID) - } - } - if winName != "" { - iosConsoleLogf("info", "[iOS-ServeAssetRequest] ✅ Resolved window name: %s (id=%d)", winName, windowID) - } - - request := &webViewAssetRequest{ - Request: req, - windowId: uint(windowID), - windowName: winName, - } - - // Send through the channel to be handled by the asset server - iosConsoleLogf("info", "[iOS-ServeAssetRequest] 🔵 Sending to webviewRequests channel") - webviewRequests <- request - iosConsoleLogf("info", "[iOS-ServeAssetRequest] 🔵 Request sent to channel successfully") - }() -} - -// HandleJSMessage handles messages from JavaScript -// -//export HandleJSMessage -func HandleJSMessage(windowID C.uint, message *C.char) { - msg := C.GoString(message) - - // Try to parse as JSON first - var msgData map[string]interface{} - if err := json.Unmarshal([]byte(msg), &msgData); err == nil && msgData != nil { - if name, ok := msgData["name"].(string); ok && name != "" { - // Special handling for asset debug messages - if name == "asset-debug" { - if data, ok := msgData["data"].(map[string]interface{}); ok { - iosConsoleLogf("info", "🔍 CLIENT ASSET DEBUG: %s %s - %s (status: %v)", - data["type"], data["name"], data["src"], data["status"]) - if contentType, ok := data["contentType"].(map[string]interface{}); ok { - iosConsoleLogf("info", "🔍 CLIENT CONTENT-TYPE: %s = %v", data["name"], contentType) - } - if code, ok := data["code"].(map[string]interface{}); ok { - iosConsoleLogf("info", "🔍 CLIENT HTTP CODE: %s = %v", data["name"], code) - } - if errorMsg, ok := data["error"].(map[string]interface{}); ok { - iosConsoleLogf("error", "🔍 CLIENT ERROR: %s = %v", data["name"], errorMsg) - } - } - return // Don't send asset-debug messages to the main event system - } - - if globalApplication != nil { - globalApplication.info("HandleJSMessage received from client", "name", name) - } - windowMessageBuffer <- &windowMessage{ - windowId: uint(windowID), - message: name, - } - return - } - // Fallback for structured payloads without a "name" field - if name, ok := msgData["message"].(string); ok && name != "" { - if globalApplication != nil { - globalApplication.info("HandleJSMessage received raw message field from client", "name", name) - } - windowMessageBuffer <- &windowMessage{ - windowId: uint(windowID), - message: name, - } - return - } - } else { - if globalApplication != nil { - globalApplication.error("[HandleJSMessage] Failed to parse JSON: %v", err) - } - iosConsoleLogf("warn", "🔍 RAW JS MESSAGE (unparsed JSON): %s", msg) - } - - // If not JSON or JSON without name/message, treat the entire payload as a string event - if msg != "" { - if globalApplication != nil { - globalApplication.info("HandleJSMessage received raw message from client", "message", msg) - } - windowMessageBuffer <- &windowMessage{ - windowId: uint(windowID), - message: msg, - } - return - } - - iosConsoleLogf("warn", "[HandleJSMessage] Ignored empty JS message") -} - -// Note: applicationEvents and windowEvents are already defined in events.go -// We'll use those existing channels - -type iosWindowEvent struct { - WindowID uint - EventID uint -} - -//export processApplicationEvent -func processApplicationEvent(eventID C.uint, data unsafe.Pointer) { - iosConsoleLogf("info", "🔵 [application_ios.go] processApplicationEvent called with eventID: %d", eventID) - - // Create and send the application event - event := newApplicationEvent(events.ApplicationEventType(eventID)) - - // Send to the applicationEvents channel for processing - applicationEvents <- event - - iosConsoleLogf("info", "🔵 [application_ios.go] Application event sent to channel: %d", eventID) -} - -//export processWindowEvent -func processWindowEvent(windowID C.uint, eventID C.uint) { - // For now, just log the event - iosConsoleLogf("info", "iOS: Window event received - Window: %d, Event: %d", windowID, eventID) - windowEvents <- &windowEvent{ - WindowID: uint(windowID), - EventID: uint(eventID), - } -} - -//export hasListeners -func hasListeners(eventID C.uint) C.bool { - // For now, return true to enable all events - // TODO: Check actual listener registration - return C.bool(true) -} \ No newline at end of file diff --git a/v3/pkg/application/application_ios.h b/v3/pkg/application/application_ios.h deleted file mode 100644 index 081298ca1..000000000 --- a/v3/pkg/application/application_ios.h +++ /dev/null @@ -1,123 +0,0 @@ -//go:build ios - -#ifndef APPLICATION_IOS_H -#define APPLICATION_IOS_H - -#include -#import - -// Forward declarations -@class WailsViewController; -@class WailsAppDelegate; - -// Global references -extern WailsAppDelegate *appDelegate; -extern unsigned int nextWindowID; - -// Initialize the iOS application -void ios_app_init(void); - -// Run the iOS application main loop -void ios_app_run(void); - -// Quit the iOS application -void ios_app_quit(void); - -// Check if dark mode is enabled -bool ios_is_dark_mode(void); - -// Configure/show state for iOS WKWebView input accessory view (keyboard toolbar) -// If disabled, the accessory view will be hidden. -void ios_set_disable_input_accessory(bool disabled); -bool ios_is_input_accessory_disabled(void); - -// Scrolling & bounce & indicators -void ios_set_disable_scroll(bool disabled); -bool ios_is_scroll_disabled(void); -void ios_set_disable_bounce(bool disabled); -bool ios_is_bounce_disabled(void); -void ios_set_disable_scroll_indicators(bool disabled); -bool ios_is_scroll_indicators_disabled(void); - -// Navigation gestures -void ios_set_enable_back_forward_gestures(bool enabled); -bool ios_is_back_forward_gestures_enabled(void); - -// Link previews -void ios_set_disable_link_preview(bool disabled); -bool ios_is_link_preview_disabled(void); - -// Media playback -void ios_set_enable_inline_media_playback(bool enabled); -bool ios_is_inline_media_playback_enabled(void); -void ios_set_enable_autoplay_without_user_action(bool enabled); -bool ios_is_autoplay_without_user_action_enabled(void); - -// Inspector -void ios_set_disable_inspectable(bool disabled); -bool ios_is_inspectable_disabled(void); - -// User agent customization -void ios_set_user_agent(const char* ua); -const char* ios_get_user_agent(void); -void ios_set_app_name_for_user_agent(const char* name); -const char* ios_get_app_name_for_user_agent(void); - -// Live runtime mutations (apply to existing WKWebView instances) -// These functions iterate current view controllers and update the active webviews on the main thread. -void ios_runtime_set_scroll_enabled(bool enabled); -void ios_runtime_set_bounce_enabled(bool enabled); -void ios_runtime_set_scroll_indicators_enabled(bool enabled); -void ios_runtime_set_back_forward_gestures_enabled(bool enabled); -void ios_runtime_set_link_preview_enabled(bool enabled); -void ios_runtime_set_inspectable_enabled(bool enabled); -void ios_runtime_set_custom_user_agent(const char* ua); - -// Native bottom tab bar (UITabBar) controls -void ios_native_tabs_set_enabled(bool enabled); -bool ios_native_tabs_is_enabled(void); -void ios_native_tabs_select_index(int index); -// Configure native tabs items as a JSON array: [{"Title":"...","SystemImage":"..."}] -void ios_native_tabs_set_items_json(const char* json); -const char* ios_native_tabs_get_items_json(void); - -// App-wide background colour control -// Setter accepts RGBA (0-255) and a flag indicating whether the colour is intentionally set by the app. -void ios_set_app_background_color(unsigned char r, unsigned char g, unsigned char b, unsigned char a, bool isSet); -// Getter returns true if a colour was set; outputs RGBA components via pointers when non-null. -bool ios_get_app_background_color(unsigned char* r, unsigned char* g, unsigned char* b, unsigned char* a); - -// Create a WebView window and return its ID -unsigned int ios_create_webview(void); - -// Create a WebView window with specified Wails ID and return its native handle -void* ios_create_webview_with_id(unsigned int wailsID); - -// Execute JavaScript in a WebView by ID (legacy) -void ios_execute_javascript(unsigned int windowID, const char* js); - -// Direct JavaScript execution on a specific window handle -void ios_window_exec_js(void* viewController, const char* js); - -// Loaders -void ios_window_load_url(void* viewController, const char* url); -void ios_window_set_html(void* viewController, const char* html); - -// Get the window ID from a native handle -unsigned int ios_window_get_id(void* viewController); - -// Release a native handle when window is destroyed -void ios_window_release_handle(void* viewController); - -// Go callbacks -extern void ServeAssetRequest(unsigned int windowID, void* urlSchemeTask); -extern void HandleJSMessage(unsigned int windowID, char* message); -extern bool hasListeners(unsigned int eventId); - -// iOS Runtime bridges -// Trigger haptic impact with a style: "light"|"medium"|"heavy"|"soft"|"rigid" -void ios_haptics_impact(const char* style); -// Returns a JSON string with basic device info. Caller is responsible for freeing with free(). -const char* ios_device_info_json(void); - -#endif // APPLICATION_IOS_H \ No newline at end of file diff --git a/v3/pkg/application/application_ios.m b/v3/pkg/application/application_ios.m deleted file mode 100644 index 4ea237e87..000000000 --- a/v3/pkg/application/application_ios.m +++ /dev/null @@ -1,324 +0,0 @@ -//go:build ios - -#import -#import -#import "application_ios.h" -#import "application_ios_delegate.h" -#import "webview_window_ios.h" -#import -#import -#import - -// Forward declarations for Go callbacks -void ServeAssetRequest(unsigned int windowID, void* urlSchemeTask); -void HandleJSMessage(unsigned int windowID, char* message); - - -// Global references - declare after interface -WailsAppDelegate *appDelegate = nil; -unsigned int nextWindowID = 1; -static bool g_disableInputAccessory = false; // default: enabled (shown) -// New global flags with sensible iOS defaults -static bool g_disableScroll = false; // default: scrolling enabled -static bool g_disableBounce = false; // default: bounce enabled -static bool g_disableScrollIndicators = false; // default: indicators shown -static bool g_enableBackForwardGestures = false; // default: gestures disabled -static bool g_disableLinkPreview = false; // default: link preview enabled -static bool g_enableInlineMediaPlayback = false; // default: inline playback disabled -static bool g_enableAutoplayNoUserAction = false; // default: autoplay requires user action -static bool g_disableInspectable = false; // default: inspector enabled -static NSString* g_userAgent = nil; -static NSString* g_appNameForUA = nil; // default applied in code when nil -static bool g_enableNativeTabs = false; // default: off -static NSString* g_nativeTabsItemsJSON = nil; // JSON array of items - -// App-wide background colour storage (RGBA 0-255) -static bool g_appBGSet = false; -static unsigned char g_appBG_R = 255; -static unsigned char g_appBG_G = 255; -static unsigned char g_appBG_B = 255; -static unsigned char g_appBG_A = 255; - -// Note: The WailsAppDelegate implementation resides in application_ios_delegate.m - -// C interface implementation -void ios_app_init(void) { - // This will be called from Go's init - // Explicitly reference WailsAppDelegate to ensure the class is linked and registered. - (void)[WailsAppDelegate class]; - // The actual UI startup happens via UIApplicationMain in main.m -} - -void ios_app_run(void) { - // This function is no longer used - UIApplicationMain is called from main.m - // The WailsAppDelegate is automatically instantiated by UIApplicationMain - extern void LogInfo(const char* source, const char* message); - LogInfo("ios_app_run", "⚠️ This function should not be called - UIApplicationMain runs from main.m"); -} - -void ios_app_quit(void) { - dispatch_async(dispatch_get_main_queue(), ^{ - exit(0); - }); -} - -bool ios_is_dark_mode(void) { - if (@available(iOS 13.0, *)) { - UIUserInterfaceStyle style = [[UITraitCollection currentTraitCollection] userInterfaceStyle]; - return style == UIUserInterfaceStyleDark; - } - return false; -} - -void ios_set_disable_input_accessory(bool disabled) { - g_disableInputAccessory = disabled; -} - -bool ios_is_input_accessory_disabled(void) { - return g_disableInputAccessory; -} - -// Scrolling & bounce & indicators -void ios_set_disable_scroll(bool disabled) { g_disableScroll = disabled; } -bool ios_is_scroll_disabled(void) { return g_disableScroll; } -void ios_set_disable_bounce(bool disabled) { g_disableBounce = disabled; } -bool ios_is_bounce_disabled(void) { return g_disableBounce; } -void ios_set_disable_scroll_indicators(bool disabled) { g_disableScrollIndicators = disabled; } -bool ios_is_scroll_indicators_disabled(void) { return g_disableScrollIndicators; } - -// Navigation gestures -void ios_set_enable_back_forward_gestures(bool enabled) { g_enableBackForwardGestures = enabled; } -bool ios_is_back_forward_gestures_enabled(void) { return g_enableBackForwardGestures; } - -// Link previews -void ios_set_disable_link_preview(bool disabled) { g_disableLinkPreview = disabled; } -bool ios_is_link_preview_disabled(void) { return g_disableLinkPreview; } - -// Media playback -void ios_set_enable_inline_media_playback(bool enabled) { g_enableInlineMediaPlayback = enabled; } -bool ios_is_inline_media_playback_enabled(void) { return g_enableInlineMediaPlayback; } -void ios_set_enable_autoplay_without_user_action(bool enabled) { g_enableAutoplayNoUserAction = enabled; } -bool ios_is_autoplay_without_user_action_enabled(void) { return g_enableAutoplayNoUserAction; } - -// Inspector -void ios_set_disable_inspectable(bool disabled) { g_disableInspectable = disabled; } -bool ios_is_inspectable_disabled(void) { return g_disableInspectable; } - -// User agent customization -void ios_set_user_agent(const char* ua) { - if (ua == NULL) { g_userAgent = nil; return; } - g_userAgent = [NSString stringWithUTF8String:ua]; -} -const char* ios_get_user_agent(void) { - if (g_userAgent == nil) return NULL; - return [g_userAgent UTF8String]; -} -void ios_set_app_name_for_user_agent(const char* name) { - if (name == NULL) { g_appNameForUA = nil; return; } - g_appNameForUA = [NSString stringWithUTF8String:name]; -} -const char* ios_get_app_name_for_user_agent(void) { - if (g_appNameForUA == nil) return NULL; - return [g_appNameForUA UTF8String]; -} - -// Live runtime mutations (apply to existing WKWebView instances) -static void forEachViewController(void (^block)(WailsViewController *vc)) { - if (!appDelegate || !appDelegate.viewControllers) return; - void (^applyBlock)(void) = ^{ - for (WailsViewController *vc in appDelegate.viewControllers) { - if (!vc || !vc.webView) continue; - block(vc); - } - }; - if ([NSThread isMainThread]) { - applyBlock(); - } else { - dispatch_async(dispatch_get_main_queue(), applyBlock); - } -} - -void ios_runtime_set_scroll_enabled(bool enabled) { - g_disableScroll = !enabled; - forEachViewController(^(WailsViewController *vc){ - vc.webView.scrollView.scrollEnabled = enabled ? YES : NO; - }); -} - -void ios_runtime_set_bounce_enabled(bool enabled) { - g_disableBounce = !enabled; - forEachViewController(^(WailsViewController *vc){ - UIScrollView *sv = vc.webView.scrollView; - sv.bounces = enabled ? YES : NO; - sv.alwaysBounceVertical = enabled ? YES : NO; - sv.alwaysBounceHorizontal = enabled ? YES : NO; - }); -} - -void ios_runtime_set_scroll_indicators_enabled(bool enabled) { - g_disableScrollIndicators = !enabled; - forEachViewController(^(WailsViewController *vc){ - UIScrollView *sv = vc.webView.scrollView; - sv.showsVerticalScrollIndicator = enabled ? YES : NO; - sv.showsHorizontalScrollIndicator = enabled ? YES : NO; - }); -} - -void ios_runtime_set_back_forward_gestures_enabled(bool enabled) { - g_enableBackForwardGestures = enabled; - forEachViewController(^(WailsViewController *vc){ - vc.webView.allowsBackForwardNavigationGestures = enabled ? YES : NO; - }); -} - -void ios_runtime_set_link_preview_enabled(bool enabled) { - g_disableLinkPreview = !enabled; - forEachViewController(^(WailsViewController *vc){ - vc.webView.allowsLinkPreview = enabled ? YES : NO; - }); -} - -void ios_runtime_set_inspectable_enabled(bool enabled) { - g_disableInspectable = !enabled; - forEachViewController(^(WailsViewController *vc){ - BOOL inspectorOn = enabled ? YES : NO; - if (@available(iOS 16.4, *)) { - vc.webView.inspectable = inspectorOn; - } else { - @try { [vc.webView setValue:@(inspectorOn) forKey:@"inspectable"]; } @catch (__unused NSException *e) {} - } - }); -} - -void ios_runtime_set_custom_user_agent(const char* ua) { - ios_set_user_agent(ua); - NSString *uaStr = (ua ? [NSString stringWithUTF8String:ua] : nil); - forEachViewController(^(WailsViewController *vc){ - vc.webView.customUserAgent = uaStr; - }); -} - -// Forward declaration used by getters -static const char* dupCString(NSString *str); - -// Native bottom tab bar controls -void ios_native_tabs_set_enabled(bool enabled) { - g_enableNativeTabs = enabled; - NSLog(@"[ios_native_tabs_set_enabled] enabled=%d", enabled); - __block NSUInteger count = 0; - forEachViewController(^(WailsViewController *vc){ - count++; - [vc enableNativeTabs:(enabled ? YES : NO)]; - }); - NSLog(@"[ios_native_tabs_set_enabled] applied to %lu view controller(s)", (unsigned long)count); -} - -bool ios_native_tabs_is_enabled(void) { - return g_enableNativeTabs; -} - -void ios_native_tabs_select_index(int index) { - forEachViewController(^(WailsViewController *vc){ - [vc selectNativeTabIndex:(NSInteger)index]; - }); -} - -void ios_native_tabs_set_items_json(const char* json) { - if (json == NULL) { - g_nativeTabsItemsJSON = nil; - NSLog(@"[ios_native_tabs_set_items_json] JSON cleared (nil)"); - return; - } - g_nativeTabsItemsJSON = [NSString stringWithUTF8String:json]; - NSLog(@"[ios_native_tabs_set_items_json] JSON length=%lu", (unsigned long)g_nativeTabsItemsJSON.length); - // Apply to existing controllers if visible - __block NSUInteger refreshed = 0; - forEachViewController(^(WailsViewController *vc){ - if (vc.tabBar && !vc.tabBar.isHidden) { - // Re-enable to rebuild items from JSON - [vc enableNativeTabs:YES]; - refreshed++; - } - }); - NSLog(@"[ios_native_tabs_set_items_json] refreshed %lu visible tab bar(s)", (unsigned long)refreshed); -} - -const char* ios_native_tabs_get_items_json(void) { - return dupCString(g_nativeTabsItemsJSON); -} - -// App-wide background colour control -void ios_set_app_background_color(unsigned char r, unsigned char g, unsigned char b, unsigned char a, bool isSet) { - g_appBGSet = isSet; - if (isSet) { - g_appBG_R = r; g_appBG_G = g; g_appBG_B = b; g_appBG_A = a; - } -} - -bool ios_get_app_background_color(unsigned char* r, unsigned char* g, unsigned char* b, unsigned char* a) { - if (!g_appBGSet) return false; - if (r) *r = g_appBG_R; - if (g) *g = g_appBG_G; - if (b) *b = g_appBG_B; - if (a) *a = g_appBG_A; - return true; -} - - -// iOS Runtime bridges -void ios_haptics_impact(const char* cstyle) { - if (cstyle == NULL) return; - NSString *style = [NSString stringWithUTF8String:cstyle]; - dispatch_async(dispatch_get_main_queue(), ^{ - NSLog(@"[ios_haptics_impact] requested style=%@", style); - if (@available(iOS 13.0, *)) { - UIImpactFeedbackStyle feedbackStyle = UIImpactFeedbackStyleMedium; - if ([style isEqualToString:@"light"]) feedbackStyle = UIImpactFeedbackStyleLight; - else if ([style isEqualToString:@"medium"]) feedbackStyle = UIImpactFeedbackStyleMedium; - else if ([style isEqualToString:@"heavy"]) feedbackStyle = UIImpactFeedbackStyleHeavy; -#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 130000 - else if ([style isEqualToString:@"soft"]) feedbackStyle = UIImpactFeedbackStyleSoft; - else if ([style isEqualToString:@"rigid"]) feedbackStyle = UIImpactFeedbackStyleRigid; -#endif - UIImpactFeedbackGenerator *generator = [[UIImpactFeedbackGenerator alloc] initWithStyle:feedbackStyle]; - [generator prepare]; - [generator impactOccurred]; - #if TARGET_OS_SIMULATOR - NSLog(@"[ios_haptics_impact] Simulator detected: no physical haptic feedback will be felt."); - #else - NSLog(@"[ios_haptics_impact] Haptic impact triggered."); - #endif - } else { - NSLog(@"[ios_haptics_impact] iOS version < 13.0: no haptic API available."); - } - }); -} - -static const char* dupCString(NSString *str) { - if (str == nil) return NULL; - const char* utf8 = [str UTF8String]; - if (utf8 == NULL) return NULL; - size_t len = strlen(utf8) + 1; - char* out = (char*)malloc(len); - if (out) memcpy(out, utf8, len); - return out; -} - -const char* ios_device_info_json(void) { - UIDevice *device = [UIDevice currentDevice]; - struct utsname systemInfo; - uname(&systemInfo); - NSString *model = [NSString stringWithUTF8String:systemInfo.machine]; - NSString *systemName = device.systemName ?: @"iOS"; - NSString *systemVersion = device.systemVersion ?: @""; -#if TARGET_OS_SIMULATOR - BOOL isSimulator = YES; -#else - BOOL isSimulator = NO; -#endif - NSString *json = [NSString stringWithFormat: - @"{\"model\":\"%@\",\"systemName\":\"%@\",\"systemVersion\":\"%@\",\"isSimulator\":%@}", - model, systemName, systemVersion, isSimulator ? @"true" : @"false" - ]; - return dupCString(json); -} diff --git a/v3/pkg/application/application_ios_delegate.h b/v3/pkg/application/application_ios_delegate.h deleted file mode 100644 index 0b0849748..000000000 --- a/v3/pkg/application/application_ios_delegate.h +++ /dev/null @@ -1,15 +0,0 @@ -//go:build ios - -#ifndef application_ios_delegate_h -#define application_ios_delegate_h - -#import - -@class WailsViewController; - -@interface WailsAppDelegate : UIResponder -@property (strong, nonatomic) UIWindow *window; -@property (nonatomic, strong) NSMutableArray *viewControllers; -@end - -#endif /* application_ios_delegate_h */ \ No newline at end of file diff --git a/v3/pkg/application/application_ios_delegate.m b/v3/pkg/application/application_ios_delegate.m deleted file mode 100644 index ef2a59066..000000000 --- a/v3/pkg/application/application_ios_delegate.m +++ /dev/null @@ -1,83 +0,0 @@ -//go:build ios -#import "application_ios_delegate.h" -#import "../events/events_ios.h" -#import "application_ios.h" -extern void processApplicationEvent(unsigned int, void* data); -extern void processWindowEvent(unsigned int, unsigned int); -extern bool hasListeners(unsigned int); -@implementation WailsAppDelegate -- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { - // Set global appDelegate reference and bring up a window if needed - appDelegate = self; - if (self.window == nil) { - self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; - self.window.backgroundColor = [UIColor whiteColor]; - UIViewController *rootVC = [[UIViewController alloc] init]; - rootVC.view.backgroundColor = [UIColor whiteColor]; - self.window.rootViewController = rootVC; - [self.window makeKeyAndVisible]; - } - // Apply app-wide background colour if configured - unsigned char r = 255, g = 255, b = 255, a = 255; - if (ios_get_app_background_color(&r, &g, &b, &a)) { - CGFloat fr = ((CGFloat)r) / 255.0; - CGFloat fg = ((CGFloat)g) / 255.0; - CGFloat fb = ((CGFloat)b) / 255.0; - CGFloat fa = ((CGFloat)a) / 255.0; - UIColor *color = [UIColor colorWithRed:fr green:fg blue:fb alpha:fa]; - self.window.backgroundColor = color; - self.window.rootViewController.view.backgroundColor = color; - } - if (!self.viewControllers) { - self.viewControllers = [NSMutableArray array]; - } - if (hasListeners(EventApplicationDidFinishLaunching)) { - processApplicationEvent(EventApplicationDidFinishLaunching, NULL); - } - return YES; -} -// GENERATED EVENTS START -- (void)applicationDidBecomeActive:(UIApplication *)application { - if( hasListeners(EventApplicationDidBecomeActive) ) { - processApplicationEvent(EventApplicationDidBecomeActive, NULL); - } -} - -- (void)applicationDidEnterBackground:(UIApplication *)application { - if( hasListeners(EventApplicationDidEnterBackground) ) { - processApplicationEvent(EventApplicationDidEnterBackground, NULL); - } -} - -- (void)applicationDidFinishLaunching:(UIApplication *)application { - if( hasListeners(EventApplicationDidFinishLaunching) ) { - processApplicationEvent(EventApplicationDidFinishLaunching, NULL); - } -} - -- (void)applicationDidReceiveMemoryWarning:(UIApplication *)application { - if( hasListeners(EventApplicationDidReceiveMemoryWarning) ) { - processApplicationEvent(EventApplicationDidReceiveMemoryWarning, NULL); - } -} - -- (void)applicationWillEnterForeground:(UIApplication *)application { - if( hasListeners(EventApplicationWillEnterForeground) ) { - processApplicationEvent(EventApplicationWillEnterForeground, NULL); - } -} - -- (void)applicationWillResignActive:(UIApplication *)application { - if( hasListeners(EventApplicationWillResignActive) ) { - processApplicationEvent(EventApplicationWillResignActive, NULL); - } -} - -- (void)applicationWillTerminate:(UIApplication *)application { - if( hasListeners(EventApplicationWillTerminate) ) { - processApplicationEvent(EventApplicationWillTerminate, NULL); - } -} - -// GENERATED EVENTS END -@end diff --git a/v3/pkg/application/application_linux.go b/v3/pkg/application/application_linux.go deleted file mode 100644 index adc214350..000000000 --- a/v3/pkg/application/application_linux.go +++ /dev/null @@ -1,352 +0,0 @@ -//go:build linux && cgo && !gtk4 && !android && !server - -package application - -/* - #include "gtk/gtk.h" - #include "webkit2/webkit2.h" - static guint get_compiled_gtk_major_version() { return GTK_MAJOR_VERSION; } - static guint get_compiled_gtk_minor_version() { return GTK_MINOR_VERSION; } - static guint get_compiled_gtk_micro_version() { return GTK_MICRO_VERSION; } - static guint get_compiled_webkit_major_version() { return WEBKIT_MAJOR_VERSION; } - static guint get_compiled_webkit_minor_version() { return WEBKIT_MINOR_VERSION; } - static guint get_compiled_webkit_micro_version() { return WEBKIT_MICRO_VERSION; } -*/ -import "C" -import ( - "fmt" - "os" - "regexp" - "slices" - "strings" - "sync" - - "path/filepath" - - "github.com/godbus/dbus/v5" - "github.com/wailsapp/wails/v3/internal/operatingsystem" - "github.com/wailsapp/wails/v3/pkg/events" -) - -// sanitizeAppName sanitizes the application name to be a valid GTK/D-Bus application ID. -// Valid IDs contain only alphanumeric characters, hyphens, and underscores. -// They must not start with a digit. -var invalidAppNameChars = regexp.MustCompile(`[^a-zA-Z0-9_-]`) -var leadingDigits = regexp.MustCompile(`^[0-9]+`) - -func sanitizeAppName(name string) string { - // Replace invalid characters with underscores - name = invalidAppNameChars.ReplaceAllString(name, "_") - // Prefix with underscore if starts with digit - name = leadingDigits.ReplaceAllString(name, "_$0") - // Remove consecutive underscores - for strings.Contains(name, "__") { - name = strings.ReplaceAll(name, "__", "_") - } - // Trim leading/trailing underscores - name = strings.Trim(name, "_") - if name == "" { - name = "wailsapp" - } - return strings.ToLower(name) -} - -func init() { - // FIXME: This should be handled appropriately in the individual files most likely. - // Set GDK_BACKEND=x11 if currently unset and XDG_SESSION_TYPE is unset, unspecified or x11 to prevent warnings - if os.Getenv("GDK_BACKEND") == "" && - (os.Getenv("XDG_SESSION_TYPE") == "" || os.Getenv("XDG_SESSION_TYPE") == "unspecified" || os.Getenv("XDG_SESSION_TYPE") == "x11") { - _ = os.Setenv("GDK_BACKEND", "x11") - } - - // Disable DMA-BUF renderer on Wayland with NVIDIA to prevent "Error 71 (Protocol error)" crashes. - // This is a known WebKitGTK issue with NVIDIA proprietary drivers on Wayland. - // See: https://bugs.webkit.org/show_bug.cgi?id=262607 - if os.Getenv("WEBKIT_DISABLE_DMABUF_RENDERER") == "" && - os.Getenv("XDG_SESSION_TYPE") == "wayland" && - isNVIDIAGPU() { - _ = os.Setenv("WEBKIT_DISABLE_DMABUF_RENDERER", "1") - } -} - -// isNVIDIAGPU checks if an NVIDIA GPU is present by looking for the nvidia kernel module. -func isNVIDIAGPU() bool { - // Check if nvidia module is loaded (most reliable for proprietary driver) - if _, err := os.Stat("/sys/module/nvidia"); err == nil { - return true - } - return false -} - -type linuxApp struct { - application pointer - parent *App - - startupActions []func() - - // Native -> uint - windowMap map[windowPointer]uint - windowMapLock sync.Mutex - - theme string - - icon pointer -} - -func (a *linuxApp) GetFlags(options Options) map[string]any { - if options.Flags == nil { - options.Flags = make(map[string]any) - } - return options.Flags -} - -func getNativeApplication() *linuxApp { - return globalApplication.impl.(*linuxApp) -} - -func (a *linuxApp) hide() { - a.hideAllWindows() -} - -func (a *linuxApp) show() { - a.showAllWindows() -} - -func (a *linuxApp) on(eventID uint) { - // TODO: Test register/unregister events - //C.registerApplicationEvent(l.application, C.uint(eventID)) -} - -func (a *linuxApp) name() string { - return appName() -} - -type rnr struct { - f func() -} - -func (r rnr) run() { - r.f() -} - -func (a *linuxApp) setApplicationMenu(menu *Menu) { - // FIXME: How do we avoid putting a menu? - if menu == nil { - // Create a default menu - menu = DefaultApplicationMenu() - globalApplication.applicationMenu = menu - } -} - -func (a *linuxApp) run() error { - - if len(os.Args) == 2 { // Case: program + 1 argument - arg1 := os.Args[1] - // Check if the argument is likely a URL from a custom protocol invocation - if strings.Contains(arg1, "://") { - a.parent.debug("Application launched with argument, potentially a URL from custom protocol", "url", arg1) - eventContext := newApplicationEventContext() - eventContext.setURL(arg1) - applicationEvents <- &ApplicationEvent{ - Id: uint(events.Common.ApplicationLaunchedWithUrl), - ctx: eventContext, - } - } else { - // Check if the argument matches any file associations - if a.parent.options.FileAssociations != nil { - ext := filepath.Ext(arg1) - if slices.Contains(a.parent.options.FileAssociations, ext) { - a.parent.debug("File opened via file association", "file", arg1, "extension", ext) - eventContext := newApplicationEventContext() - eventContext.setOpenedWithFile(arg1) - applicationEvents <- &ApplicationEvent{ - Id: uint(events.Common.ApplicationOpenedWithFile), - ctx: eventContext, - } - return nil - } - } - a.parent.debug("Application launched with single argument (not a URL), potential file open?", "arg", arg1) - } - } else if len(os.Args) > 2 { - // Log if multiple arguments are passed - a.parent.debug("Application launched with multiple arguments", "args", os.Args[1:]) - } - - a.parent.Event.OnApplicationEvent(events.Linux.ApplicationStartup, func(evt *ApplicationEvent) { - // TODO: What should happen here? - }) - a.setupCommonEvents() - a.monitorThemeChanges() - return appRun(a.application) -} - -func (a *linuxApp) unregisterWindow(w windowPointer) { - a.windowMapLock.Lock() - delete(a.windowMap, w) - a.windowMapLock.Unlock() - - // If this was the last window... - if len(a.windowMap) == 0 && !a.parent.options.Linux.DisableQuitOnLastWindowClosed { - a.destroy() - } -} - -func (a *linuxApp) destroy() { - if !globalApplication.shouldQuit() { - return - } - globalApplication.cleanup() - appDestroy(a.application) -} - -func (a *linuxApp) isOnMainThread() bool { - return isOnMainThread() -} - -// register our window to our parent mapping -func (a *linuxApp) registerWindow(window pointer, id uint) { - a.windowMapLock.Lock() - a.windowMap[windowPointer(window)] = id - a.windowMapLock.Unlock() -} - -func (a *linuxApp) isDarkMode() bool { - return strings.Contains(a.theme, "dark") -} - -func (a *linuxApp) getAccentColor() string { - // Linux doesn't have a unified system accent color API - // Return a default blue color - return "rgb(0,122,255)" -} - -func (a *linuxApp) monitorThemeChanges() { - go func() { - defer handlePanic() - conn, err := dbus.ConnectSessionBus() - if err != nil { - a.parent.warning( - "[WARNING] Failed to connect to session bus; monitoring for theme changes will not function: %v", - err, - ) - return - } - defer conn.Close() - - if err = conn.AddMatchSignal( - dbus.WithMatchObjectPath("/org/freedesktop/portal/desktop"), - ); err != nil { - panic(err) - } - - c := make(chan *dbus.Signal, 10) - conn.Signal(c) - - getTheme := func(body []interface{}) (string, bool) { - if len(body) < 2 { - return "", false - } - if entry, ok := body[0].(string); !ok || entry != "org.gnome.desktop.interface" { - return "", false - } - if entry, ok := body[1].(string); ok && entry == "color-scheme" { - return body[2].(dbus.Variant).Value().(string), true - } - return "", false - } - - for v := range c { - theme, ok := getTheme(v.Body) - if !ok { - continue - } - - if theme != a.theme { - a.theme = theme - event := newApplicationEvent(events.Linux.SystemThemeChanged) - event.Context().setIsDarkMode(a.isDarkMode()) - applicationEvents <- event - } - - } - }() -} - -func newPlatformApp(parent *App) *linuxApp { - name := sanitizeAppName(parent.options.Name) - app := &linuxApp{ - parent: parent, - application: appNew(name), - windowMap: map[windowPointer]uint{}, - } - - if parent.options.Linux.ProgramName != "" { - setProgramName(parent.options.Linux.ProgramName) - } - - return app -} - -// logPlatformInfo logs the platform information to the console -func (a *App) logPlatformInfo() { - info, err := operatingsystem.Info() - if err != nil { - a.error("error getting OS info: %w", err) - return - } - - wkVersion := operatingsystem.GetWebkitVersion() - platformInfo := info.AsLogSlice() - platformInfo = append(platformInfo, "Webkit2Gtk", wkVersion) - - a.info("Platform Info:", platformInfo...) -} - -//export processWindowEvent -func processWindowEvent(windowID C.uint, eventID C.uint) { - windowEvents <- &windowEvent{ - WindowID: uint(windowID), - EventID: uint(eventID), - } -} - -func buildVersionString(major, minor, micro C.uint) string { - return fmt.Sprintf("%d.%d.%d", uint(major), uint(minor), uint(micro)) -} - -func (a *App) platformEnvironment() map[string]any { - result := map[string]any{} - result["gtk3-compiled"] = buildVersionString( - C.get_compiled_gtk_major_version(), - C.get_compiled_gtk_minor_version(), - C.get_compiled_gtk_micro_version(), - ) - result["gtk3-runtime"] = buildVersionString( - C.gtk_get_major_version(), - C.gtk_get_minor_version(), - C.gtk_get_micro_version(), - ) - - result["webkit2gtk-compiled"] = buildVersionString( - C.get_compiled_webkit_major_version(), - C.get_compiled_webkit_minor_version(), - C.get_compiled_webkit_micro_version(), - ) - result["webkit2gtk-runtime"] = buildVersionString( - C.webkit_get_major_version(), - C.webkit_get_minor_version(), - C.webkit_get_micro_version(), - ) - - result["compositor"] = detectCompositor() - result["wayland"] = isWayland() - result["focusFollowsMouse"] = detectFocusFollowsMouse() - - return result -} - -func fatalHandler(errFunc func(error)) { - // Stub for windows function - return -} diff --git a/v3/pkg/application/application_linux_gtk4.go b/v3/pkg/application/application_linux_gtk4.go deleted file mode 100644 index 031dedbf6..000000000 --- a/v3/pkg/application/application_linux_gtk4.go +++ /dev/null @@ -1,383 +0,0 @@ -//go:build linux && cgo && gtk4 && !android - -package application - -/* -#include -#include -static guint get_compiled_gtk_major_version() { return GTK_MAJOR_VERSION; } -static guint get_compiled_gtk_minor_version() { return GTK_MINOR_VERSION; } -static guint get_compiled_gtk_micro_version() { return GTK_MICRO_VERSION; } -static guint get_compiled_webkit_major_version() { return WEBKIT_MAJOR_VERSION; } -static guint get_compiled_webkit_minor_version() { return WEBKIT_MINOR_VERSION; } -static guint get_compiled_webkit_micro_version() { return WEBKIT_MICRO_VERSION; } -*/ -import "C" -import ( - "fmt" - "os" - "path/filepath" - "regexp" - "strings" - "sync" - - "github.com/godbus/dbus/v5" - "github.com/wailsapp/wails/v3/internal/operatingsystem" - "github.com/wailsapp/wails/v3/pkg/events" -) - -var invalidAppNameChars = regexp.MustCompile(`[^a-zA-Z0-9_-]`) -var leadingDigits = regexp.MustCompile(`^[0-9]+`) - -func sanitizeAppName(name string) string { - name = invalidAppNameChars.ReplaceAllString(name, "_") - name = leadingDigits.ReplaceAllString(name, "_$0") - for strings.Contains(name, "__") { - name = strings.ReplaceAll(name, "__", "_") - } - name = strings.Trim(name, "_") - if name == "" { - name = "wailsapp" - } - return strings.ToLower(name) -} - -func init() { - // GTK4 experimental notice - fmt.Println("┌────────────────────────────────────────────────────────────────────────┐") - fmt.Println("│ GTK4 + WebKitGTK 6.0 support is EXPERIMENTAL │") - fmt.Println("│ Please report issues: https://github.com/wailsapp/wails/issues/4957 │") - fmt.Println("└────────────────────────────────────────────────────────────────────────┘") - - if os.Getenv("WEBKIT_DISABLE_DMABUF_RENDERER") == "" && - os.Getenv("XDG_SESSION_TYPE") == "wayland" && - isNVIDIAGPU() { - _ = os.Setenv("WEBKIT_DISABLE_DMABUF_RENDERER", "1") - } -} - -func isNVIDIAGPU() bool { - if _, err := os.Stat("/sys/module/nvidia"); err == nil { - return true - } - return false -} - -type linuxApp struct { - application pointer - parent *App - - activated chan struct{} - activatedOnce sync.Once - - windowMap map[windowPointer]uint - windowMapLock sync.Mutex - - theme string - - icon pointer -} - -func (a *linuxApp) GetFlags(options Options) map[string]any { - if options.Flags == nil { - options.Flags = make(map[string]any) - } - return options.Flags -} - -func (a *linuxApp) name() string { - return appName() -} - -func (a *linuxApp) run() error { - return appRun(a.application) -} - -func (a *linuxApp) destroy() { - if !globalApplication.shouldQuit() { - return - } - globalApplication.cleanup() - appDestroy(a.application) -} - -func (a *linuxApp) getApplicationMenu() *Menu { - return nil -} - -func (a *linuxApp) setApplicationMenu(menu *Menu) {} - -func (a *linuxApp) hide() { - a.hideAllWindows() -} - -func (a *linuxApp) show() { - a.showAllWindows() -} - -func (a *linuxApp) on(eventID uint) { -} - -func (a *linuxApp) isOnMainThread() bool { - return isOnMainThread() -} - -func (a *linuxApp) appendGTKVersion(result map[string]string) { - result["GTK"] = fmt.Sprintf("%d.%d.%d", - C.get_compiled_gtk_major_version(), - C.get_compiled_gtk_minor_version(), - C.get_compiled_gtk_micro_version()) - result["WebKit"] = fmt.Sprintf("%d.%d.%d", - C.get_compiled_webkit_major_version(), - C.get_compiled_webkit_minor_version(), - C.get_compiled_webkit_micro_version()) -} - -func (a *linuxApp) init(_ *App, options Options) { - osInfo, _ := operatingsystem.Info() - a.parent.info("Compiled with GTK %d.%d.%d", - C.get_compiled_gtk_major_version(), - C.get_compiled_gtk_minor_version(), - C.get_compiled_gtk_micro_version()) - a.parent.info("Compiled with WebKitGTK %d.%d.%d", - C.get_compiled_webkit_major_version(), - C.get_compiled_webkit_minor_version(), - C.get_compiled_webkit_micro_version()) - a.parent.info("Using %s", osInfo.Name) - - if options.Icon != nil { - a.setIcon(options.Icon) - } - - go listenForSystemThemeChanges(a) -} - -func listenForSystemThemeChanges(a *linuxApp) { - conn, err := dbus.SessionBus() - if err != nil { - a.parent.error("failed to connect to session bus: %v", err) - return - } - - if err = conn.AddMatchSignal( - dbus.WithMatchInterface("org.freedesktop.portal.Settings"), - dbus.WithMatchMember("SettingChanged"), - ); err != nil { - return - } - - c := make(chan *dbus.Signal, 10) - conn.Signal(c) - - for s := range c { - if len(s.Body) < 3 { - continue - } - namespace, ok := s.Body[0].(string) - if !ok || namespace != "org.freedesktop.appearance" { - continue - } - key, ok := s.Body[1].(string) - if !ok || key != "color-scheme" { - continue - } - processApplicationEvent(C.uint(events.Linux.SystemThemeChanged), nil) - } -} - -func (a *linuxApp) registerWindow(window pointer, id uint) { - a.windowMapLock.Lock() - a.windowMap[windowPointer(window)] = id - a.windowMapLock.Unlock() -} - -func (a *linuxApp) unregisterWindow(window windowPointer) { - a.windowMapLock.Lock() - delete(a.windowMap, window) - remainingWindows := len(a.windowMap) - a.windowMapLock.Unlock() - - if remainingWindows == 0 && !a.parent.options.Linux.DisableQuitOnLastWindowClosed { - a.destroy() - } -} - -func newPlatformApp(parent *App) *linuxApp { - name := sanitizeAppName(parent.options.Name) - app := &linuxApp{ - parent: parent, - application: appNew(name), - activated: make(chan struct{}), - windowMap: map[windowPointer]uint{}, - } - - if parent.options.Linux.ProgramName != "" { - setProgramName(parent.options.Linux.ProgramName) - } - - return app -} - -func (a *linuxApp) markActivated() { - a.activatedOnce.Do(func() { - close(a.activated) - }) -} - -func (a *linuxApp) waitForActivation() { - <-a.activated -} - -func (a *linuxApp) getIconForFile(filename string) ([]byte, error) { - if filename == "" { - return nil, nil - } - - ext := filepath.Ext(filename) - iconMap := map[string]string{ - ".txt": "text-x-generic", - ".pdf": "application-pdf", - ".doc": "x-office-document", - ".docx": "x-office-document", - ".xls": "x-office-spreadsheet", - ".xlsx": "x-office-spreadsheet", - ".ppt": "x-office-presentation", - ".pptx": "x-office-presentation", - ".zip": "package-x-generic", - ".tar": "package-x-generic", - ".gz": "package-x-generic", - ".jpg": "image-x-generic", - ".jpeg": "image-x-generic", - ".png": "image-x-generic", - ".gif": "image-x-generic", - ".mp3": "audio-x-generic", - ".wav": "audio-x-generic", - ".mp4": "video-x-generic", - ".avi": "video-x-generic", - ".html": "text-html", - ".css": "text-css", - ".js": "text-javascript", - ".json": "text-json", - ".xml": "text-xml", - } - - iconName := "application-x-generic" - if name, ok := iconMap[ext]; ok { - iconName = name - } - - return getIconBytes(iconName) -} - -func getIconBytes(iconName string) ([]byte, error) { - return nil, fmt.Errorf("icon lookup not implemented for GTK4") -} - -func (a *linuxApp) isDarkMode() bool { - conn, err := dbus.SessionBus() - if err != nil { - return false - } - - obj := conn.Object("org.freedesktop.portal.Desktop", "/org/freedesktop/portal/desktop") - call := obj.Call("org.freedesktop.portal.Settings.Read", 0, "org.freedesktop.appearance", "color-scheme") - if call.Err != nil { - return false - } - - var result dbus.Variant - if err := call.Store(&result); err != nil { - return false - } - - innerVariant := result.Value().(dbus.Variant) - colorScheme, ok := innerVariant.Value().(uint32) - if !ok { - return false - } - - return colorScheme == 1 -} - -func (a *linuxApp) getAccentColor() string { - return "rgb(0,122,255)" -} - -func (a *linuxApp) isVisible() bool { - windows := a.getWindows() - for _, window := range windows { - if C.gtk_widget_is_visible((*C.GtkWidget)(window)) != 0 { - return true - } - } - return false -} - -func getNativeApplication() *linuxApp { - return globalApplication.impl.(*linuxApp) -} - -var _ = dbus.SessionBus -var _ = filepath.Ext -var _ = operatingsystem.Info - -// logPlatformInfo logs the platform information to the console -func (a *App) logPlatformInfo() { - info, err := operatingsystem.Info() - if err != nil { - a.error("error getting OS info: %w", err) - return - } - - platformInfo := info.AsLogSlice() - platformInfo = append(platformInfo, "GTK", fmt.Sprintf("%d.%d.%d", - C.get_compiled_gtk_major_version(), - C.get_compiled_gtk_minor_version(), - C.get_compiled_gtk_micro_version())) - platformInfo = append(platformInfo, "WebKitGTK", fmt.Sprintf("%d.%d.%d", - C.get_compiled_webkit_major_version(), - C.get_compiled_webkit_minor_version(), - C.get_compiled_webkit_micro_version())) - - a.info("Platform Info:", platformInfo...) -} - -func buildVersionString(major, minor, micro C.guint) string { - return fmt.Sprintf("%d.%d.%d", uint(major), uint(minor), uint(micro)) -} - -func (a *App) platformEnvironment() map[string]any { - result := map[string]any{} - result["gtk4-compiled"] = buildVersionString( - C.get_compiled_gtk_major_version(), - C.get_compiled_gtk_minor_version(), - C.get_compiled_gtk_micro_version(), - ) - result["gtk4-runtime"] = buildVersionString( - C.gtk_get_major_version(), - C.gtk_get_minor_version(), - C.gtk_get_micro_version(), - ) - - result["webkitgtk6-compiled"] = buildVersionString( - C.get_compiled_webkit_major_version(), - C.get_compiled_webkit_minor_version(), - C.get_compiled_webkit_micro_version(), - ) - result["webkitgtk6-runtime"] = buildVersionString( - C.webkit_get_major_version(), - C.webkit_get_minor_version(), - C.webkit_get_micro_version(), - ) - - result["compositor"] = detectCompositor() - result["wayland"] = isWayland() - result["focusFollowsMouse"] = detectFocusFollowsMouse() - - return result -} - -func fatalHandler(errFunc func(error)) { - // Stub for windows function - return -} diff --git a/v3/pkg/application/application_options.go b/v3/pkg/application/application_options.go deleted file mode 100644 index 946b8733b..000000000 --- a/v3/pkg/application/application_options.go +++ /dev/null @@ -1,414 +0,0 @@ -package application - -import ( - "io/fs" - "log/slog" - "net/http" - "time" - - "github.com/wailsapp/wails/v3/internal/assetserver" -) - -// Options contains the options for the application -type Options struct { - // Name is the name of the application (used in the default about box) - Name string - - // Description is the description of the application (used in the default about box) - Description string - - // Icon is the icon of the application (used in the default about box) - Icon []byte - - // Mac is the Mac specific configuration for Mac builds - Mac MacOptions - - // Windows is the Windows specific configuration for Windows builds - Windows WindowsOptions - - // Linux is the Linux specific configuration for Linux builds - Linux LinuxOptions - - // IOS is the iOS specific configuration for iOS builds - IOS IOSOptions - - // Android is the Android specific configuration for Android builds - Android AndroidOptions - - // Services allows you to bind Go methods to the frontend. - Services []Service - - // MarshalError will be called if non-nil - // to marshal to JSON the error values returned by service methods. - // - // MarshalError is not allowed to fail, - // but it may return a nil slice to fall back - // to the default error handling mechanism. - // - // If the returned slice is not nil, it must contain valid JSON. - MarshalError func(error) []byte - - // BindAliases allows you to specify alias IDs for your bound methods. - // Example: `BindAliases: map[uint32]uint32{1: 1411160069}` states that alias ID 1 maps to the Go method with ID 1411160069. - BindAliases map[uint32]uint32 - - // Logger is a slog.Logger instance used for logging Wails system messages (not application messages). - // If not defined, a default logger is used. - Logger *slog.Logger - - // LogLevel defines the log level of the Wails system logger. - LogLevel slog.Level - - // Assets are the application assets to be used. - Assets AssetOptions - - // Flags are key value pairs that are available to the frontend. - // This is also used by Wails to provide information to the frontend. - Flags map[string]any - - // PanicHandler is called when a panic occurs - PanicHandler func(*PanicDetails) - - // DisableDefaultSignalHandler disables the default signal handler - DisableDefaultSignalHandler bool - - // KeyBindings is a map of key bindings to functions - KeyBindings map[string]func(window Window) - - // OnShutdown is called when the application is about to terminate. - // This is useful for cleanup tasks. - // The shutdown process blocks until this function returns. - OnShutdown func() - - // PostShutdown is called after the application - // has finished shutting down, just before process termination. - // This is useful for testing and logging purposes - // on platforms where the Run() method does not return. - // When PostShutdown is called, the application instance is not usable anymore. - // The shutdown process blocks until this function returns. - PostShutdown func() - - // ShouldQuit is a function that is called when the user tries to quit the application. - // If the function returns true, the application will quit. - // If the function returns false, the application will not quit. - ShouldQuit func() bool - - // RawMessageHandler is called when the frontend sends a raw message. - // This is useful for implementing custom frontend-to-backend communication. - RawMessageHandler func(window Window, message string, originInfo *OriginInfo) - - // WarningHandler is called when a warning occurs - WarningHandler func(string) - - // ErrorHandler is called when an error occurs - ErrorHandler func(err error) - - // File extensions associated with the application - // Example: [".txt", ".md"] - // The '.' is required - FileAssociations []string - - // SingleInstance options for single instance functionality - SingleInstance *SingleInstanceOptions - - // Transport allows you to provide a custom IPC transport layer. - // When set, Wails will use your transport instead of the default HTTP fetch-based transport. - // This allows you to use WebSockets, custom protocols, or any other transport mechanism - // while retaining all Wails generated bindings and event communication. - // - // The default transport uses HTTP fetch requests to /wails/runtime + events via js.Exec in webview. - // If not specified, the default transport is used. - // - // Example use case: Implementing WebSocket-based or PostMessage IPC. - Transport Transport - - // Server configures the HTTP server for server mode. - // Server mode is enabled by building with the "server" build tag: - // go build -tags server - // - // In server mode, the application runs as an HTTP server without a native window. - // This enables deploying the same Wails application as a web server for: - // - Docker/container deployments - // - Server-side rendering - // - Web-only access without desktop dependencies - Server ServerOptions -} - -// ServerOptions configures the HTTP server for headless mode. -type ServerOptions struct { - // Host is the address to bind to. - // Default: "localhost" for security. Use "0.0.0.0" for all interfaces. - Host string - - // Port is the port to listen on. - // Default: 8080 - Port int - - // ReadTimeout is the maximum duration for reading the entire request. - // Default: 30 seconds - ReadTimeout time.Duration - - // WriteTimeout is the maximum duration before timing out writes of the response. - // Default: 30 seconds - WriteTimeout time.Duration - - // IdleTimeout is the maximum duration to wait for the next request. - // Default: 120 seconds - IdleTimeout time.Duration - - // ShutdownTimeout is the maximum duration to wait for active connections to close. - // Default: 30 seconds - ShutdownTimeout time.Duration - - // TLS configures HTTPS. If nil, HTTP is used. - TLS *TLSOptions -} - -// TLSOptions configures HTTPS for the headless server. -type TLSOptions struct { - // CertFile is the path to the TLS certificate file. - CertFile string - - // KeyFile is the path to the TLS private key file. - KeyFile string -} - -// AssetOptions defines the configuration of the AssetServer. -type AssetOptions struct { - // Handler which serves all the content to the WebView. - Handler http.Handler - - // Middleware is a HTTP Middleware which allows to hook into the AssetServer request chain. It allows to skip the default - // request handler dynamically, e.g. implement specialized Routing etc. - // The Middleware is called to build a new `http.Handler` used by the AssetSever and it also receives the default - // handler used by the AssetServer as an argument. - // - // This middleware injects itself before any of Wails internal middlewares. - // - // If not defined, the default AssetServer request chain is executed. - // - // Multiple Middlewares can be chained together with: - // ChainMiddleware(middleware ...Middleware) Middleware - Middleware Middleware - - // DisableLogging disables logging of the AssetServer. By default, the AssetServer logs every request. - DisableLogging bool -} - -// Middleware defines HTTP middleware that can be applied to the AssetServer. -// The handler passed as next is the next handler in the chain. One can decide to call the next handler -// or implement a specialized handling. -type Middleware func(next http.Handler) http.Handler - -// ChainMiddleware allows chaining multiple middlewares to one middleware. -func ChainMiddleware(middleware ...Middleware) Middleware { - return func(h http.Handler) http.Handler { - for i := len(middleware) - 1; i >= 0; i-- { - h = middleware[i](h) - } - return h - } -} - -// AssetFileServerFS returns a http handler which serves the assets from the fs.FS. -// If an external devserver has been provided 'FRONTEND_DEVSERVER_URL' the files are being served -// from the external server, ignoring the `assets`. -func AssetFileServerFS(assets fs.FS) http.Handler { - return assetserver.NewAssetFileServer(assets) -} - -// BundledAssetFileServer returns a http handler which serves the assets from the fs.FS. -// If an external devserver has been provided 'FRONTEND_DEVSERVER_URL' the files are being served -// from the external server, ignoring the `assets`. -// It also serves the compiled runtime.js file at `/wails/runtime.js`. -// It will provide the production runtime.js file from the embedded assets if the `production` tag is used. -func BundledAssetFileServer(assets fs.FS) http.Handler { - return assetserver.NewBundledAssetFileServer(assets) -} - -/******** Mac Options ********/ - -// ActivationPolicy is the activation policy for the application. -type ActivationPolicy int - -const ( - // ActivationPolicyRegular is used for applications that have a user interface, - ActivationPolicyRegular ActivationPolicy = iota - // ActivationPolicyAccessory is used for applications that do not have a main window, - // such as system tray applications or background applications. - ActivationPolicyAccessory - ActivationPolicyProhibited -) - -// MacOptions contains options for macOS applications. -type MacOptions struct { - // ActivationPolicy is the activation policy for the application. Defaults to - // applicationActivationPolicyRegular. - ActivationPolicy ActivationPolicy - // If set to true, the application will terminate when the last window is closed. - ApplicationShouldTerminateAfterLastWindowClosed bool -} - -/****** Windows Options *******/ - -// WindowsOptions contains options for Windows applications. -type WindowsOptions struct { - - // Window class name - // Default: WailsWebviewWindow - WndClass string - - // WndProcInterceptor is a function that will be called for every message sent in the application. - // Use this to hook into the main message loop. This is useful for handling custom window messages. - // If `shouldReturn` is `true` then `returnCode` will be returned by the main message loop. - // If `shouldReturn` is `false` then returnCode will be ignored and the message will be processed by the main message loop. - WndProcInterceptor func(hwnd uintptr, msg uint32, wParam, lParam uintptr) (returnCode uintptr, shouldReturn bool) - - // DisableQuitOnLastWindowClosed disables the auto quit of the application if the last window has been closed. - DisableQuitOnLastWindowClosed bool - - // Path where the WebView2 stores the user data. If empty %APPDATA%\[BinaryName.exe] will be used. - // If the path is not valid, a messagebox will be displayed with the error and the app will exit with error code. - WebviewUserDataPath string - - // Path to the directory with WebView2 executables. If empty WebView2 installed in the system will be used. - WebviewBrowserPath string - - // EnabledFeatures, DisabledFeatures and AdditionalBrowserArgs configure the WebView2 browser. - // These apply globally to ALL windows because WebView2 shares a single browser environment. - // See: https://learn.microsoft.com/en-us/microsoft-edge/webview2/concepts/webview-features-flags - // AdditionalBrowserArgs must include the "--" prefix, e.g. "--remote-debugging-port=9222" - EnabledFeatures []string - DisabledFeatures []string - AdditionalBrowserArgs []string -} - -/********* Linux Options *********/ - -// LinuxOptions contains options for Linux applications. -type LinuxOptions struct { - // DisableQuitOnLastWindowClosed disables the auto quit of the application if the last window has been closed. - DisableQuitOnLastWindowClosed bool - - // ProgramName is used to set the program's name for the window manager via GTK's g_set_prgname(). - //This name should not be localized. [see the docs] - // - //When a .desktop file is created this value helps with window grouping and desktop icons when the .desktop file's Name - //property differs form the executable's filename. - // - //[see the docs]: https://docs.gtk.org/glib/func.set_prgname.html - ProgramName string -} - -/********* iOS Options *********/ - -// IOSOptions contains options for iOS applications. -type IOSOptions struct { - // DisableInputAccessoryView controls whether the iOS WKWebView shows the - // input accessory toolbar (the bar with Next/Previous/Done) above the keyboard. - // Default: false (accessory bar is shown). - // true => accessory view is disabled/hidden - // false => accessory view is enabled/shown - DisableInputAccessoryView bool - - // Scrolling & Bounce (defaults: scroll/bounce/indicators are enabled on iOS) - // Use Disable* to keep default true behavior without surprising zero-values. - DisableScroll bool - DisableBounce bool - DisableScrollIndicators bool - - // Navigation gestures (default false) - EnableBackForwardNavigationGestures bool - - // Link previews (default true on iOS) - // Use Disable* so default (false) means previews are enabled. - DisableLinkPreview bool - - // Media playback - // Inline playback (default false) -> Enable* - EnableInlineMediaPlayback bool - // Autoplay without user action (default false) -> Enable* - EnableAutoplayWithoutUserAction bool - - // Inspector / Debug (default true in dev) - // Use Disable* so default (false) keeps inspector enabled. - DisableInspectable bool - - // User agent customization - // If empty, defaults apply. ApplicationNameForUserAgent defaults to "wails.io". - UserAgent string - ApplicationNameForUserAgent string - - // App-wide background colour for the main iOS window prior to any WebView creation. - // If AppBackgroundColourSet is true, the delegate will apply this colour to the app window - // during didFinishLaunching. Otherwise, it defaults to white. - AppBackgroundColourSet bool - BackgroundColour RGBA - - // EnableNativeTabs enables a native iOS UITabBar at the bottom of the screen. - // When enabled, the native tab bar will dispatch a 'nativeTabSelected' CustomEvent - // to the window with detail: { index: number }. - // NOTE: If NativeTabsItems has one or more entries, native tabs are auto-enabled - // regardless of this flag, and the provided items will be used. - EnableNativeTabs bool - - // NativeTabsItems configures the labels and optional SF Symbol icons for the - // native UITabBar. If one or more items are provided, native tabs are automatically - // enabled. If empty and EnableNativeTabs is true, default items are used. - NativeTabsItems []NativeTabItem -} - -// NativeTabItem describes a single item in the iOS native UITabBar. -// SystemImage is the SF Symbols name to use for the icon (iOS 13+). If empty or -// unavailable on the current OS, no icon is shown. -type NativeTabItem struct { - Title string `json:"Title"` - SystemImage NativeTabIcon `json:"SystemImage"` -} - -// NativeTabIcon is a string-based enum for SF Symbols. -// It allows using predefined constants for common symbols while still accepting -// any valid SF Symbols name as a plain string. -// -// Example: -// NativeTabsItems: []NativeTabItem{ -// { Title: "Home", SystemImage: NativeTabIconHouse }, -// { Title: "Settings", SystemImage: "gearshape" }, // arbitrary string still allowed -// } -type NativeTabIcon string - -const ( - // Common icons - NativeTabIconNone NativeTabIcon = "" - NativeTabIconHouse NativeTabIcon = "house" - NativeTabIconGear NativeTabIcon = "gear" - NativeTabIconStar NativeTabIcon = "star" - NativeTabIconPerson NativeTabIcon = "person" - NativeTabIconBell NativeTabIcon = "bell" - NativeTabIconMagnify NativeTabIcon = "magnifyingglass" - NativeTabIconList NativeTabIcon = "list.bullet" - NativeTabIconFolder NativeTabIcon = "folder" -) - -/********* Android Options *********/ - -// AndroidOptions contains options for Android applications. -type AndroidOptions struct { - // DisableScroll disables scrolling in the WebView - DisableScroll bool - - // DisableBounce disables the overscroll bounce effect - DisableOverscroll bool - - // EnableZoom allows pinch-to-zoom in the WebView (default: false) - EnableZoom bool - - // UserAgent sets a custom user agent string - UserAgent string - - // BackgroundColour sets the background colour of the WebView - BackgroundColour RGBA - - // DisableHardwareAcceleration disables hardware acceleration for the WebView - DisableHardwareAcceleration bool -} diff --git a/v3/pkg/application/application_options_test.go b/v3/pkg/application/application_options_test.go deleted file mode 100644 index 77ddbe522..000000000 --- a/v3/pkg/application/application_options_test.go +++ /dev/null @@ -1,301 +0,0 @@ -package application - -import ( - "net/http" - "net/http/httptest" - "testing" -) - -func TestActivationPolicy_Constants(t *testing.T) { - if ActivationPolicyRegular != 0 { - t.Error("ActivationPolicyRegular should be 0") - } - if ActivationPolicyAccessory != 1 { - t.Error("ActivationPolicyAccessory should be 1") - } - if ActivationPolicyProhibited != 2 { - t.Error("ActivationPolicyProhibited should be 2") - } -} - -func TestNativeTabIcon_Constants(t *testing.T) { - tests := []struct { - name string - icon NativeTabIcon - expected string - }{ - {"NativeTabIconNone", NativeTabIconNone, ""}, - {"NativeTabIconHouse", NativeTabIconHouse, "house"}, - {"NativeTabIconGear", NativeTabIconGear, "gear"}, - {"NativeTabIconStar", NativeTabIconStar, "star"}, - {"NativeTabIconPerson", NativeTabIconPerson, "person"}, - {"NativeTabIconBell", NativeTabIconBell, "bell"}, - {"NativeTabIconMagnify", NativeTabIconMagnify, "magnifyingglass"}, - {"NativeTabIconList", NativeTabIconList, "list.bullet"}, - {"NativeTabIconFolder", NativeTabIconFolder, "folder"}, - } - - for _, tt := range tests { - if string(tt.icon) != tt.expected { - t.Errorf("%s = %q, want %q", tt.name, string(tt.icon), tt.expected) - } - } -} - -func TestChainMiddleware_Empty(t *testing.T) { - baseHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - w.WriteHeader(http.StatusOK) - w.Write([]byte("base")) - }) - - chained := ChainMiddleware() - handler := chained(baseHandler) - - req := httptest.NewRequest("GET", "/", nil) - rec := httptest.NewRecorder() - - handler.ServeHTTP(rec, req) - - if rec.Code != http.StatusOK { - t.Errorf("Status = %d, want %d", rec.Code, http.StatusOK) - } - if rec.Body.String() != "base" { - t.Errorf("Body = %q, want %q", rec.Body.String(), "base") - } -} - -func TestChainMiddleware_Single(t *testing.T) { - callOrder := []string{} - - middleware := func(next http.Handler) http.Handler { - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - callOrder = append(callOrder, "middleware") - next.ServeHTTP(w, r) - }) - } - - baseHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - callOrder = append(callOrder, "base") - w.WriteHeader(http.StatusOK) - }) - - chained := ChainMiddleware(middleware) - handler := chained(baseHandler) - - req := httptest.NewRequest("GET", "/", nil) - rec := httptest.NewRecorder() - - handler.ServeHTTP(rec, req) - - if len(callOrder) != 2 { - t.Errorf("Expected 2 calls, got %d", len(callOrder)) - } - if callOrder[0] != "middleware" { - t.Errorf("First call should be middleware, got %s", callOrder[0]) - } - if callOrder[1] != "base" { - t.Errorf("Second call should be base, got %s", callOrder[1]) - } -} - -func TestChainMiddleware_Multiple(t *testing.T) { - callOrder := []string{} - - middleware1 := func(next http.Handler) http.Handler { - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - callOrder = append(callOrder, "middleware1") - next.ServeHTTP(w, r) - }) - } - - middleware2 := func(next http.Handler) http.Handler { - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - callOrder = append(callOrder, "middleware2") - next.ServeHTTP(w, r) - }) - } - - middleware3 := func(next http.Handler) http.Handler { - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - callOrder = append(callOrder, "middleware3") - next.ServeHTTP(w, r) - }) - } - - baseHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - callOrder = append(callOrder, "base") - w.WriteHeader(http.StatusOK) - }) - - chained := ChainMiddleware(middleware1, middleware2, middleware3) - handler := chained(baseHandler) - - req := httptest.NewRequest("GET", "/", nil) - rec := httptest.NewRecorder() - - handler.ServeHTTP(rec, req) - - expected := []string{"middleware1", "middleware2", "middleware3", "base"} - if len(callOrder) != len(expected) { - t.Errorf("Expected %d calls, got %d", len(expected), len(callOrder)) - } - for i, v := range expected { - if i < len(callOrder) && callOrder[i] != v { - t.Errorf("Call %d: expected %s, got %s", i, v, callOrder[i]) - } - } -} - -func TestOptions_Defaults(t *testing.T) { - opts := Options{} - - if opts.Name != "" { - t.Error("Name should default to empty string") - } - if opts.Description != "" { - t.Error("Description should default to empty string") - } - if opts.Icon != nil { - t.Error("Icon should default to nil") - } - if opts.Logger != nil { - t.Error("Logger should default to nil") - } - if opts.DisableDefaultSignalHandler != false { - t.Error("DisableDefaultSignalHandler should default to false") - } -} - -func TestMacOptions_Defaults(t *testing.T) { - opts := MacOptions{} - - if opts.ActivationPolicy != ActivationPolicyRegular { - t.Error("ActivationPolicy should default to ActivationPolicyRegular") - } - if opts.ApplicationShouldTerminateAfterLastWindowClosed != false { - t.Error("ApplicationShouldTerminateAfterLastWindowClosed should default to false") - } -} - -func TestWindowsOptions_Defaults(t *testing.T) { - opts := WindowsOptions{} - - if opts.WndClass != "" { - t.Error("WndClass should default to empty string") - } - if opts.DisableQuitOnLastWindowClosed != false { - t.Error("DisableQuitOnLastWindowClosed should default to false") - } - if opts.WebviewUserDataPath != "" { - t.Error("WebviewUserDataPath should default to empty string") - } - if opts.WebviewBrowserPath != "" { - t.Error("WebviewBrowserPath should default to empty string") - } -} - -func TestLinuxOptions_Defaults(t *testing.T) { - opts := LinuxOptions{} - - if opts.DisableQuitOnLastWindowClosed != false { - t.Error("DisableQuitOnLastWindowClosed should default to false") - } - if opts.ProgramName != "" { - t.Error("ProgramName should default to empty string") - } -} - -func TestIOSOptions_Defaults(t *testing.T) { - opts := IOSOptions{} - - if opts.DisableInputAccessoryView != false { - t.Error("DisableInputAccessoryView should default to false") - } - if opts.DisableScroll != false { - t.Error("DisableScroll should default to false") - } - if opts.DisableBounce != false { - t.Error("DisableBounce should default to false") - } - if opts.EnableBackForwardNavigationGestures != false { - t.Error("EnableBackForwardNavigationGestures should default to false") - } - if opts.EnableNativeTabs != false { - t.Error("EnableNativeTabs should default to false") - } -} - -func TestAndroidOptions_Defaults(t *testing.T) { - opts := AndroidOptions{} - - if opts.DisableScroll != false { - t.Error("DisableScroll should default to false") - } - if opts.DisableOverscroll != false { - t.Error("DisableOverscroll should default to false") - } - if opts.EnableZoom != false { - t.Error("EnableZoom should default to false") - } - if opts.DisableHardwareAcceleration != false { - t.Error("DisableHardwareAcceleration should default to false") - } -} - -func TestAssetOptions_Defaults(t *testing.T) { - opts := AssetOptions{} - - if opts.Handler != nil { - t.Error("Handler should default to nil") - } - if opts.Middleware != nil { - t.Error("Middleware should default to nil") - } - if opts.DisableLogging != false { - t.Error("DisableLogging should default to false") - } -} - -func TestNativeTabItem_Fields(t *testing.T) { - item := NativeTabItem{ - Title: "Home", - SystemImage: NativeTabIconHouse, - } - - if item.Title != "Home" { - t.Errorf("Title = %q, want %q", item.Title, "Home") - } - if item.SystemImage != NativeTabIconHouse { - t.Errorf("SystemImage = %q, want %q", item.SystemImage, NativeTabIconHouse) - } -} - -func TestMiddleware_ShortCircuit(t *testing.T) { - shortCircuit := func(next http.Handler) http.Handler { - return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - w.WriteHeader(http.StatusForbidden) - w.Write([]byte("forbidden")) - // Don't call next - }) - } - - baseHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - w.WriteHeader(http.StatusOK) - w.Write([]byte("base")) - }) - - chained := ChainMiddleware(shortCircuit) - handler := chained(baseHandler) - - req := httptest.NewRequest("GET", "/", nil) - rec := httptest.NewRecorder() - - handler.ServeHTTP(rec, req) - - if rec.Code != http.StatusForbidden { - t.Errorf("Status = %d, want %d", rec.Code, http.StatusForbidden) - } - if rec.Body.String() != "forbidden" { - t.Errorf("Body = %q, want %q", rec.Body.String(), "forbidden") - } -} diff --git a/v3/pkg/application/application_production.go b/v3/pkg/application/application_production.go deleted file mode 100644 index 75f86b44d..000000000 --- a/v3/pkg/application/application_production.go +++ /dev/null @@ -1,18 +0,0 @@ -//go:build production - -package application - -func newApplication(options Options) *App { - result := &App{ - isDebugMode: false, - options: options, - } - result.init() - return result -} - -func (a *App) logStartup() {} - -func (a *App) preRun() error { return nil } - -func (a *App) postQuit() error { return nil } diff --git a/v3/pkg/application/application_server.go b/v3/pkg/application/application_server.go deleted file mode 100644 index 41059242f..000000000 --- a/v3/pkg/application/application_server.go +++ /dev/null @@ -1,554 +0,0 @@ -//go:build server - -package application - -import ( - "context" - "errors" - "fmt" - "net" - "net/http" - "os" - "os/signal" - "strconv" - "syscall" - "time" - "unsafe" -) - -// serverApp implements platformApp for server mode. -// It provides a minimal implementation that runs an HTTP server -// without any GUI components. -// -// Server mode is enabled by building with the "server" build tag: -// -// go build -tags server -type serverApp struct { - app *App - server *http.Server - listener net.Listener - broadcaster *WebSocketBroadcaster -} - -// newPlatformApp creates a new server-mode platform app. -// This function is only compiled when building with the "server" tag. -func newPlatformApp(app *App) *serverApp { - app.info("Server mode enabled (built with -tags server)") - return &serverApp{ - app: app, - } -} - -// parsePort parses a port string into an integer. -func parsePort(s string) (int, error) { - p, err := strconv.Atoi(s) - if err != nil { - return 0, err - } - if p < 1 || p > 65535 { - return 0, errors.New("port out of range") - } - return p, nil -} - -// run starts the HTTP server and blocks until shutdown. -func (h *serverApp) run() error { - // Set up common events - h.setupCommonEvents() - - // Create WebSocket broadcaster for events - h.broadcaster = NewWebSocketBroadcaster(h.app) - globalBroadcaster = h.broadcaster // Set global reference for browser ID lookups - h.app.wailsEventListenerLock.Lock() - h.app.wailsEventListeners = append(h.app.wailsEventListeners, h.broadcaster) - h.app.wailsEventListenerLock.Unlock() - - opts := h.app.options.Server - - // Environment variables override config (useful for Docker/containers) - host := os.Getenv("WAILS_SERVER_HOST") - if host == "" { - host = opts.Host - } - if host == "" { - host = "localhost" - } - - port := opts.Port - if envPort := os.Getenv("WAILS_SERVER_PORT"); envPort != "" { - if p, err := parsePort(envPort); err == nil { - port = p - } - } - if port == 0 { - port = 8080 - } - - readTimeout := opts.ReadTimeout - if readTimeout == 0 { - readTimeout = 30 * time.Second - } - - writeTimeout := opts.WriteTimeout - if writeTimeout == 0 { - writeTimeout = 30 * time.Second - } - - idleTimeout := opts.IdleTimeout - if idleTimeout == 0 { - idleTimeout = 120 * time.Second - } - - shutdownTimeout := opts.ShutdownTimeout - if shutdownTimeout == 0 { - shutdownTimeout = 30 * time.Second - } - - addr := fmt.Sprintf("%s:%d", host, port) - - // Create HTTP handler from asset server - handler := h.createHandler() - - h.server = &http.Server{ - Addr: addr, - Handler: handler, - ReadTimeout: readTimeout, - WriteTimeout: writeTimeout, - IdleTimeout: idleTimeout, - } - - // Create listener - var err error - h.listener, err = net.Listen("tcp", addr) - if err != nil { - return fmt.Errorf("failed to listen on %s: %w", addr, err) - } - - h.app.info("Server mode starting", "address", addr) - - // Start server in goroutine - errCh := make(chan error, 1) - go func() { - if opts.TLS != nil { - errCh <- h.server.ServeTLS(h.listener, opts.TLS.CertFile, opts.TLS.KeyFile) - } else { - errCh <- h.server.Serve(h.listener) - } - }() - - // Wait for shutdown signal or error - quit := make(chan os.Signal, 1) - signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM) - - select { - case err := <-errCh: - if err != nil && !errors.Is(err, http.ErrServerClosed) { - return err - } - case <-quit: - h.app.info("Shutdown signal received") - case <-h.app.ctx.Done(): - h.app.info("Application context cancelled") - } - - // Graceful shutdown - ctx, cancel := context.WithTimeout(context.Background(), shutdownTimeout) - defer cancel() - - if err := h.server.Shutdown(ctx); err != nil { - return fmt.Errorf("server shutdown error: %w", err) - } - - h.app.info("Server stopped") - return nil -} - -// customJS is the JavaScript that sets up WebSocket event connection for server mode. -// Events FROM frontend TO backend use the existing HTTP transport. -// This WebSocket is only for receiving broadcast events FROM backend TO all frontends. -const customJS = `(function() { - var protocol = location.protocol === 'https:' ? 'wss:' : 'ws:'; - var clientId = window._wails && window._wails.clientId ? window._wails.clientId : ''; - var wsUrl = protocol + '//' + location.host + '/wails/events' + (clientId ? '?clientId=' + encodeURIComponent(clientId) : ''); - var ws; - - function connect() { - ws = new WebSocket(wsUrl); - ws.onopen = function() { - console.log('[Wails] Event WebSocket connected'); - }; - ws.onmessage = function(e) { - try { - var event = JSON.parse(e.data); - if (window._wails && window._wails.dispatchWailsEvent) { - window._wails.dispatchWailsEvent(event); - } - } catch (err) { - console.error('[Wails] Failed to parse event:', err); - } - }; - ws.onclose = function() { - console.log('[Wails] Event WebSocket disconnected, reconnecting...'); - setTimeout(connect, 1000); - }; - ws.onerror = function() { - ws.close(); - }; - } - - connect(); -})();` - -// createHandler creates the HTTP handler for server mode. -func (h *serverApp) createHandler() http.Handler { - mux := http.NewServeMux() - - // Health check endpoint - mux.HandleFunc("/health", func(w http.ResponseWriter, r *http.Request) { - w.Header().Set("Content-Type", "application/json") - w.WriteHeader(http.StatusOK) - w.Write([]byte(`{"status":"ok"}`)) - }) - - // Serve custom.js for server mode (WebSocket event connection) - mux.HandleFunc("/wails/custom.js", func(w http.ResponseWriter, r *http.Request) { - w.Header().Set("Content-Type", "application/javascript") - w.WriteHeader(http.StatusOK) - w.Write([]byte(customJS)) - }) - - // WebSocket endpoint for events - mux.Handle("/wails/events", h.broadcaster) - - // Serve all other requests through the asset server - mux.Handle("/", h.app.assets) - - return mux -} - -// destroy stops the server and cleans up. -func (h *serverApp) destroy() { - if h.server != nil { - ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) - defer cancel() - h.server.Shutdown(ctx) - } - h.app.cleanup() -} - -// setApplicationMenu is a no-op in server mode. -func (h *serverApp) setApplicationMenu(menu *Menu) { - // No-op: server mode has no GUI -} - -// name returns the application name. -func (h *serverApp) name() string { - return h.app.options.Name -} - -// getCurrentWindowID returns 0 in server mode (no windows). -func (h *serverApp) getCurrentWindowID() uint { - return 0 -} - -// showAboutDialog is a no-op in server mode. -func (h *serverApp) showAboutDialog(name string, description string, icon []byte) { - // No-op: server mode has no GUI - h.app.warning("showAboutDialog called in server mode - operation ignored") -} - -// setIcon is a no-op in server mode. -func (h *serverApp) setIcon(icon []byte) { - // No-op: server mode has no GUI -} - -// on is a no-op in server mode. -func (h *serverApp) on(id uint) { - // No-op: server mode has no platform-specific event handling -} - -// dispatchOnMainThread executes the function directly in server mode. -func (h *serverApp) dispatchOnMainThread(id uint) { - // In server mode, there's no "main thread" concept from GUI frameworks - // Execute the function directly - mainThreadFunctionStoreLock.Lock() - fn, ok := mainThreadFunctionStore[id] - if ok { - delete(mainThreadFunctionStore, id) - } - mainThreadFunctionStoreLock.Unlock() - - if ok && fn != nil { - fn() - } -} - -// hide is a no-op in server mode. -func (h *serverApp) hide() { - // No-op: server mode has no GUI -} - -// show is a no-op in server mode. -func (h *serverApp) show() { - // No-op: server mode has no GUI -} - -// getPrimaryScreen returns nil in server mode. -func (h *serverApp) getPrimaryScreen() (*Screen, error) { - return nil, errors.New("screen information not available in server mode") -} - -// getScreens returns an error in server mode (screen info unavailable). -func (h *serverApp) getScreens() ([]*Screen, error) { - return nil, errors.New("screen information not available in server mode") -} - -// GetFlags returns the application flags for server mode. -func (h *serverApp) GetFlags(options Options) map[string]any { - flags := make(map[string]any) - flags["server"] = true - if options.Flags != nil { - for k, v := range options.Flags { - flags[k] = v - } - } - return flags -} - -// isOnMainThread always returns true in server mode. -func (h *serverApp) isOnMainThread() bool { - // In server mode, there's no main thread concept - return true -} - -// isDarkMode returns false in server mode. -func (h *serverApp) isDarkMode() bool { - return false -} - -// getAccentColor returns empty string in server mode. -func (h *serverApp) getAccentColor() string { - return "" -} - -// logPlatformInfo logs platform info for server mode. -func (a *App) logPlatformInfo() { - a.info("Platform Info:", "mode", "server") -} - -// platformEnvironment returns environment info for server mode. -func (a *App) platformEnvironment() map[string]any { - return map[string]any{ - "mode": "server", - } -} - -// fatalHandler sets up fatal error handling for server mode. -func fatalHandler(errFunc func(error)) { - // In server mode, fatal errors are handled via standard mechanisms -} - -// newClipboardImpl creates a clipboard implementation for server mode. -func newClipboardImpl() clipboardImpl { - return &serverClipboard{} -} - -// serverClipboard is a no-op clipboard for server mode. -type serverClipboard struct{} - -func (c *serverClipboard) setText(text string) bool { - return false -} - -func (c *serverClipboard) text() (string, bool) { - return "", false -} - -// newDialogImpl creates a dialog implementation for server mode. -func newDialogImpl(d *MessageDialog) messageDialogImpl { - return &serverDialog{} -} - -// serverDialog is a no-op dialog for server mode. -type serverDialog struct{} - -func (d *serverDialog) show() { - // No-op in server mode -} - -// newOpenFileDialogImpl creates an open file dialog implementation for server mode. -func newOpenFileDialogImpl(d *OpenFileDialogStruct) openFileDialogImpl { - return &serverOpenFileDialog{} -} - -// serverOpenFileDialog is a no-op open file dialog for server mode. -type serverOpenFileDialog struct{} - -func (d *serverOpenFileDialog) show() (chan string, error) { - ch := make(chan string, 1) - close(ch) - return ch, errors.New("file dialogs not available in server mode") -} - -// newSaveFileDialogImpl creates a save file dialog implementation for server mode. -func newSaveFileDialogImpl(d *SaveFileDialogStruct) saveFileDialogImpl { - return &serverSaveFileDialog{} -} - -// serverSaveFileDialog is a no-op save file dialog for server mode. -type serverSaveFileDialog struct{} - -func (d *serverSaveFileDialog) show() (chan string, error) { - ch := make(chan string, 1) - close(ch) - return ch, errors.New("file dialogs not available in server mode") -} - -// newMenuImpl creates a menu implementation for server mode. -func newMenuImpl(menu *Menu) menuImpl { - return &serverMenu{} -} - -// serverMenu is a no-op menu for server mode. -type serverMenu struct{} - -func (m *serverMenu) update() { - // No-op in server mode -} - -// newPlatformLock creates a platform-specific single instance lock for server mode. -func newPlatformLock(manager *singleInstanceManager) (platformLock, error) { - return &serverLock{}, nil -} - -// serverLock is a basic lock for server mode. -type serverLock struct{} - -func (l *serverLock) acquire(uniqueID string) error { - return nil -} - -func (l *serverLock) release() { - // No-op in server mode -} - -func (l *serverLock) notify(data string) error { - return errors.New("single instance not supported in server mode") -} - -// newSystemTrayImpl creates a system tray implementation for server mode. -func newSystemTrayImpl(s *SystemTray) systemTrayImpl { - return &serverSystemTray{parent: s} -} - -// serverSystemTray is a no-op system tray for server mode. -type serverSystemTray struct { - parent *SystemTray -} - -func (t *serverSystemTray) setLabel(label string) {} -func (t *serverSystemTray) setTooltip(tooltip string) {} -func (t *serverSystemTray) run() {} -func (t *serverSystemTray) setIcon(icon []byte) {} -func (t *serverSystemTray) setMenu(menu *Menu) {} -func (t *serverSystemTray) setIconPosition(pos IconPosition) {} -func (t *serverSystemTray) setTemplateIcon(icon []byte) {} -func (t *serverSystemTray) destroy() {} -func (t *serverSystemTray) setDarkModeIcon(icon []byte) {} -func (t *serverSystemTray) bounds() (*Rect, error) { return nil, errors.New("system tray not available in server mode") } -func (t *serverSystemTray) getScreen() (*Screen, error) { return nil, errors.New("system tray not available in server mode") } -func (t *serverSystemTray) positionWindow(w Window, o int) error { return errors.New("system tray not available in server mode") } -func (t *serverSystemTray) openMenu() {} -func (t *serverSystemTray) Show() {} -func (t *serverSystemTray) Hide() {} - -// newWindowImpl creates a webview window implementation for server mode. -func newWindowImpl(parent *WebviewWindow) *serverWebviewWindow { - return &serverWebviewWindow{parent: parent} -} - -// serverWebviewWindow is a no-op webview window for server mode. -type serverWebviewWindow struct { - parent *WebviewWindow -} - -// All webviewWindowImpl methods as no-ops for server mode -func (w *serverWebviewWindow) setTitle(title string) {} -func (w *serverWebviewWindow) setSize(width, height int) {} -func (w *serverWebviewWindow) setAlwaysOnTop(alwaysOnTop bool) {} -func (w *serverWebviewWindow) setURL(url string) {} -func (w *serverWebviewWindow) setResizable(resizable bool) {} -func (w *serverWebviewWindow) setMinSize(width, height int) {} -func (w *serverWebviewWindow) setMaxSize(width, height int) {} -func (w *serverWebviewWindow) execJS(js string) {} -func (w *serverWebviewWindow) setBackgroundColour(color RGBA) {} -func (w *serverWebviewWindow) run() {} -func (w *serverWebviewWindow) center() {} -func (w *serverWebviewWindow) size() (int, int) { return 0, 0 } -func (w *serverWebviewWindow) width() int { return 0 } -func (w *serverWebviewWindow) height() int { return 0 } -func (w *serverWebviewWindow) destroy() {} -func (w *serverWebviewWindow) reload() {} -func (w *serverWebviewWindow) forceReload() {} -func (w *serverWebviewWindow) openDevTools() {} -func (w *serverWebviewWindow) zoomReset() {} -func (w *serverWebviewWindow) zoomIn() {} -func (w *serverWebviewWindow) zoomOut() {} -func (w *serverWebviewWindow) getZoom() float64 { return 1.0 } -func (w *serverWebviewWindow) setZoom(zoom float64) {} -func (w *serverWebviewWindow) close() {} -func (w *serverWebviewWindow) zoom() {} -func (w *serverWebviewWindow) setHTML(html string) {} -func (w *serverWebviewWindow) on(eventID uint) {} -func (w *serverWebviewWindow) minimise() {} -func (w *serverWebviewWindow) unminimise() {} -func (w *serverWebviewWindow) maximise() {} -func (w *serverWebviewWindow) unmaximise() {} -func (w *serverWebviewWindow) fullscreen() {} -func (w *serverWebviewWindow) unfullscreen() {} -func (w *serverWebviewWindow) isMinimised() bool { return false } -func (w *serverWebviewWindow) isMaximised() bool { return false } -func (w *serverWebviewWindow) isFullscreen() bool { return false } -func (w *serverWebviewWindow) isNormal() bool { return true } -func (w *serverWebviewWindow) isVisible() bool { return false } -func (w *serverWebviewWindow) isFocused() bool { return false } -func (w *serverWebviewWindow) focus() {} -func (w *serverWebviewWindow) show() {} -func (w *serverWebviewWindow) hide() {} -func (w *serverWebviewWindow) getScreen() (*Screen, error) { return nil, errors.New("screens not available in server mode") } -func (w *serverWebviewWindow) setFrameless(frameless bool) {} -func (w *serverWebviewWindow) openContextMenu(menu *Menu, data *ContextMenuData) {} -func (w *serverWebviewWindow) nativeWindow() unsafe.Pointer { return nil } -func (w *serverWebviewWindow) startDrag() error { return errors.New("drag not available in server mode") } -func (w *serverWebviewWindow) startResize(border string) error { return errors.New("resize not available in server mode") } -func (w *serverWebviewWindow) print() error { return errors.New("print not available in server mode") } -func (w *serverWebviewWindow) setEnabled(enabled bool) {} -func (w *serverWebviewWindow) physicalBounds() Rect { return Rect{} } -func (w *serverWebviewWindow) setPhysicalBounds(bounds Rect) {} -func (w *serverWebviewWindow) bounds() Rect { return Rect{} } -func (w *serverWebviewWindow) setBounds(bounds Rect) {} -func (w *serverWebviewWindow) position() (int, int) { return 0, 0 } -func (w *serverWebviewWindow) setPosition(x int, y int) {} -func (w *serverWebviewWindow) relativePosition() (int, int) { return 0, 0 } -func (w *serverWebviewWindow) setRelativePosition(x int, y int) {} -func (w *serverWebviewWindow) flash(enabled bool) {} -func (w *serverWebviewWindow) handleKeyEvent(acceleratorString string) {} -func (w *serverWebviewWindow) getBorderSizes() *LRTB { return &LRTB{} } -func (w *serverWebviewWindow) setMinimiseButtonState(state ButtonState) {} -func (w *serverWebviewWindow) setMaximiseButtonState(state ButtonState) {} -func (w *serverWebviewWindow) setCloseButtonState(state ButtonState) {} -func (w *serverWebviewWindow) isIgnoreMouseEvents() bool { return false } -func (w *serverWebviewWindow) setIgnoreMouseEvents(ignore bool) {} -func (w *serverWebviewWindow) cut() {} -func (w *serverWebviewWindow) copy() {} -func (w *serverWebviewWindow) paste() {} -func (w *serverWebviewWindow) undo() {} -func (w *serverWebviewWindow) delete() {} -func (w *serverWebviewWindow) selectAll() {} -func (w *serverWebviewWindow) redo() {} -func (w *serverWebviewWindow) showMenuBar() {} -func (w *serverWebviewWindow) hideMenuBar() {} -func (w *serverWebviewWindow) toggleMenuBar() {} -func (w *serverWebviewWindow) setMenu(menu *Menu) {} -func (w *serverWebviewWindow) snapAssist() {} -func (w *serverWebviewWindow) setContentProtection(enabled bool) {} diff --git a/v3/pkg/application/application_server_test.go b/v3/pkg/application/application_server_test.go deleted file mode 100644 index 0bb4780dd..000000000 --- a/v3/pkg/application/application_server_test.go +++ /dev/null @@ -1,168 +0,0 @@ -//go:build server - -package application - -import ( - "context" - "net/http" - "sync" - "testing" - "time" -) - -// resetGlobalApp resets the global application state for testing -func resetGlobalApp() { - globalApplication = nil -} - -func TestServerMode_HealthEndpoint(t *testing.T) { - resetGlobalApp() - - // Create a server mode app (server mode is enabled via build tag) - app := New(Options{ - Name: "Test Server", - Server: ServerOptions{ - Host: "127.0.0.1", - Port: 18081, // Use specific port for this test - }, - Assets: AssetOptions{ - Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - w.WriteHeader(http.StatusOK) - w.Write([]byte("OK")) - }), - }, - }) - - // Start app in background - var wg sync.WaitGroup - wg.Add(1) - errCh := make(chan error, 1) - go func() { - defer wg.Done() - errCh <- app.Run() - }() - - // Wait for server to start - time.Sleep(200 * time.Millisecond) - - // Test health endpoint - resp, err := http.Get("http://127.0.0.1:18081/health") - if err != nil { - t.Fatalf("health check failed: %v", err) - } - defer resp.Body.Close() - - if resp.StatusCode != http.StatusOK { - t.Errorf("expected status 200, got %d", resp.StatusCode) - } - - // Shutdown - app.Quit() - - // Wait for shutdown - ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second) - defer cancel() - - select { - case err := <-errCh: - if err != nil { - t.Errorf("app.Run() returned error: %v", err) - } - case <-ctx.Done(): - t.Error("timeout waiting for app shutdown") - } -} - -func TestServerMode_AssetServing(t *testing.T) { - resetGlobalApp() - - testContent := "Hello from server mode!" - - app := New(Options{ - Name: "Test Assets", - Server: ServerOptions{ - Host: "127.0.0.1", - Port: 18082, // Use specific port for this test - }, - Assets: AssetOptions{ - Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - w.WriteHeader(http.StatusOK) - w.Write([]byte(testContent)) - }), - }, - }) - - errCh := make(chan error, 1) - go func() { - errCh <- app.Run() - }() - - time.Sleep(200 * time.Millisecond) - - // Test asset serving - resp, err := http.Get("http://127.0.0.1:18082/") - if err != nil { - t.Fatalf("request failed: %v", err) - } - defer resp.Body.Close() - - if resp.StatusCode != http.StatusOK { - t.Errorf("expected status 200, got %d", resp.StatusCode) - } - - app.Quit() - - ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second) - defer cancel() - - select { - case <-errCh: - case <-ctx.Done(): - t.Error("timeout waiting for app shutdown") - } -} - -func TestServerMode_Defaults(t *testing.T) { - resetGlobalApp() - - app := New(Options{ - Name: "Test Defaults", - Server: ServerOptions{ - Port: 18083, // Use specific port to avoid conflicts - }, - Assets: AssetOptions{ - Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { - w.WriteHeader(http.StatusOK) - }), - }, - }) - - errCh := make(chan error, 1) - go func() { - errCh <- app.Run() - }() - - time.Sleep(200 * time.Millisecond) - - // Should be listening on localhost:18083 - resp, err := http.Get("http://localhost:18083/health") - if err != nil { - t.Fatalf("request to address failed: %v", err) - } - defer resp.Body.Close() - - if resp.StatusCode != http.StatusOK { - t.Errorf("expected status 200, got %d", resp.StatusCode) - } - - app.Quit() - - ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second) - defer cancel() - - select { - case <-errCh: - case <-ctx.Done(): - t.Error("timeout waiting for app shutdown") - } -} diff --git a/v3/pkg/application/application_windows.go b/v3/pkg/application/application_windows.go deleted file mode 100644 index 3b93b9a9c..000000000 --- a/v3/pkg/application/application_windows.go +++ /dev/null @@ -1,449 +0,0 @@ -//go:build windows && !server - -package application - -import ( - "errors" - "os" - "path/filepath" - "slices" - "strings" - "sync" - "sync/atomic" - "syscall" - "time" - "unsafe" - - "github.com/wailsapp/go-webview2/webviewloader" - - "github.com/wailsapp/wails/v3/internal/operatingsystem" - - "github.com/wailsapp/wails/v3/pkg/events" - "github.com/wailsapp/wails/v3/pkg/w32" -) - -var ( - wmTaskbarCreated = w32.RegisterWindowMessage(w32.MustStringToUTF16Ptr("TaskbarCreated")) -) - -type windowsApp struct { - parent *App - - windowClass w32.WNDCLASSEX - instance w32.HINSTANCE - - windowMap map[w32.HWND]*windowsWebviewWindow - windowMapLock sync.RWMutex - - systrayMap map[w32.HMENU]*windowsSystemTray - systrayMapLock sync.RWMutex - - mainThreadID w32.HANDLE - mainThreadWindowHWND w32.HWND - - // Windows hidden by application.Hide() - hiddenWindows []*windowsWebviewWindow - focusedWindow w32.HWND - - // system theme - isCurrentlyDarkMode bool - currentWindowID uint - - // Restart taskbar flag - restartingTaskbar atomic.Bool -} - -func (m *windowsApp) isDarkMode() bool { - return w32.IsCurrentlyDarkMode() -} - -func (m *windowsApp) getAccentColor() string { - accentColor, err := w32.GetAccentColor() - if err != nil { - m.parent.error("failed to get accent color: %w", err) - return "rgb(0,122,255)" - } - - return accentColor -} - -func (m *windowsApp) isOnMainThread() bool { - return m.mainThreadID == w32.GetCurrentThreadId() -} - -func (m *windowsApp) GetFlags(options Options) map[string]any { - if options.Flags == nil { - options.Flags = make(map[string]any) - } - options.Flags["system"] = map[string]any{ - "resizeHandleWidth": w32.GetSystemMetrics(w32.SM_CXSIZEFRAME), - "resizeHandleHeight": w32.GetSystemMetrics(w32.SM_CYSIZEFRAME), - } - return options.Flags -} - -func (m *windowsApp) getWindowForHWND(hwnd w32.HWND) *windowsWebviewWindow { - m.windowMapLock.RLock() - defer m.windowMapLock.RUnlock() - return m.windowMap[hwnd] -} - -func getNativeApplication() *windowsApp { - return globalApplication.impl.(*windowsApp) -} - -func (m *windowsApp) hide() { - // Get the current focussed window - m.focusedWindow = w32.GetForegroundWindow() - - // Iterate over all windows and hide them if they aren't already hidden - for _, window := range m.windowMap { - if window.isVisible() { - // Add to hidden windows - m.hiddenWindows = append(m.hiddenWindows, window) - window.hide() - } - } - // Switch focus to the next application - hwndNext := w32.GetWindow(m.mainThreadWindowHWND, w32.GW_HWNDNEXT) - w32.SetForegroundWindow(hwndNext) -} - -func (m *windowsApp) show() { - // Iterate over all windows and show them if they were previously hidden - for _, window := range m.hiddenWindows { - window.show() - } - // Show the foreground window - w32.SetForegroundWindow(m.focusedWindow) -} - -func (m *windowsApp) on(_ uint) { -} - -func (m *windowsApp) setIcon(_ []byte) { -} - -func (m *windowsApp) name() string { - // appName := C.getAppName() - // defer C.free(unsafe.Pointer(appName)) - // return C.GoString(appName) - return "" -} - -func (m *windowsApp) getCurrentWindowID() uint { - return m.currentWindowID -} - -func (m *windowsApp) setApplicationMenu(menu *Menu) { - if menu == nil { - // Create a default menu for windows - menu = DefaultApplicationMenu() - } - menu.Update() - - m.parent.applicationMenu = menu -} - -func (m *windowsApp) run() error { - m.setupCommonEvents() - for eventID := range m.parent.applicationEventListeners { - m.on(eventID) - } - // EmitEvent application started event - applicationEvents <- &ApplicationEvent{ - Id: uint(events.Windows.ApplicationStarted), - ctx: blankApplicationEventContext, - } - - if len(os.Args) == 2 { // Case: program + 1 argument - arg1 := os.Args[1] - // Check if the argument is likely a URL from a custom protocol invocation - if strings.Contains(arg1, "://") { - m.parent.debug("Application launched with argument, potentially a URL from custom protocol", "url", arg1) - eventContext := newApplicationEventContext() - eventContext.setURL(arg1) - applicationEvents <- &ApplicationEvent{ - Id: uint(events.Common.ApplicationLaunchedWithUrl), - ctx: eventContext, - } - } else { - // If not a URL-like string, check for file association - if m.parent.options.FileAssociations != nil { - ext := filepath.Ext(arg1) - if slices.Contains(m.parent.options.FileAssociations, ext) { - m.parent.debug("Application launched with file via file association", "file", arg1) - eventContext := newApplicationEventContext() - eventContext.setOpenedWithFile(arg1) - applicationEvents <- &ApplicationEvent{ - Id: uint(events.Common.ApplicationOpenedWithFile), - ctx: eventContext, - } - } - } - } - } else if len(os.Args) > 2 { - // Log if multiple arguments are passed, though typical protocol/file launch is a single arg. - m.parent.debug("Application launched with multiple arguments", "args", os.Args[1:]) - } - - _ = m.runMainLoop() - - return nil -} - -func (m *windowsApp) destroy() { - if !globalApplication.shouldQuit() { - return - } - globalApplication.cleanup() - // destroy the main thread window - w32.DestroyWindow(m.mainThreadWindowHWND) - // Post a quit message to the main thread - w32.PostQuitMessage(0) -} - -func (m *windowsApp) init() { - // Register the window class - - icon := w32.LoadIconWithResourceID(m.instance, w32.IDI_APPLICATION) - - m.windowClass.Size = uint32(unsafe.Sizeof(m.windowClass)) - m.windowClass.Style = w32.CS_HREDRAW | w32.CS_VREDRAW - m.windowClass.WndProc = syscall.NewCallback(m.wndProc) - m.windowClass.Instance = m.instance - m.windowClass.Background = w32.COLOR_BTNFACE + 1 - m.windowClass.Icon = icon - m.windowClass.Cursor = w32.LoadCursorWithResourceID(0, w32.IDC_ARROW) - m.windowClass.ClassName = w32.MustStringToUTF16Ptr(m.parent.options.Windows.WndClass) - m.windowClass.MenuName = nil - m.windowClass.IconSm = icon - - if ret := w32.RegisterClassEx(&m.windowClass); ret == 0 { - panic(syscall.GetLastError()) - } - m.isCurrentlyDarkMode = w32.IsCurrentlyDarkMode() -} - -func (m *windowsApp) wndProc(hwnd w32.HWND, msg uint32, wParam, lParam uintptr) uintptr { - - // Handle the invoke callback - if msg == wmInvokeCallback { - m.invokeCallback(wParam, lParam) - return 0 - } - - // If the WndProcInterceptor is set in options, pass the message on - if m.parent.options.Windows.WndProcInterceptor != nil { - returnValue, shouldReturn := m.parent.options.Windows.WndProcInterceptor(hwnd, msg, wParam, lParam) - if shouldReturn { - return returnValue - } - } - - // Handle the main thread window - // Quit the application if requested - // Reprocess and cache screens when display settings change - if hwnd == m.mainThreadWindowHWND { - if msg == w32.WM_ENDSESSION || msg == w32.WM_DESTROY || msg == w32.WM_CLOSE { - globalApplication.Quit() - } - if msg == w32.WM_DISPLAYCHANGE || (msg == w32.WM_SETTINGCHANGE && wParam == w32.SPI_SETWORKAREA) { - err := m.processAndCacheScreens() - if err != nil { - m.parent.handleError(err) - } - } - } - - switch msg { - case wmTaskbarCreated: - if m.restartingTaskbar.Load() { - break - } - m.restartingTaskbar.Store(true) - m.reshowSystrays() - go func() { - // 1 second debounce - time.Sleep(1000) - m.restartingTaskbar.Store(false) - }() - case w32.WM_SETTINGCHANGE: - settingChanged := w32.UTF16PtrToString((*uint16)(unsafe.Pointer(lParam))) - if settingChanged == "ImmersiveColorSet" { - isDarkMode := w32.IsCurrentlyDarkMode() - if isDarkMode != m.isCurrentlyDarkMode { - eventContext := newApplicationEventContext() - eventContext.setIsDarkMode(isDarkMode) - applicationEvents <- &ApplicationEvent{ - Id: uint(events.Windows.SystemThemeChanged), - ctx: eventContext, - } - m.isCurrentlyDarkMode = isDarkMode - } - } - return 0 - case w32.WM_POWERBROADCAST: - switch wParam { - case w32.PBT_APMPOWERSTATUSCHANGE: - applicationEvents <- newApplicationEvent(events.Windows.APMPowerStatusChange) - case w32.PBT_APMSUSPEND: - applicationEvents <- newApplicationEvent(events.Windows.APMSuspend) - case w32.PBT_APMRESUMEAUTOMATIC: - applicationEvents <- newApplicationEvent(events.Windows.APMResumeAutomatic) - case w32.PBT_APMRESUMESUSPEND: - applicationEvents <- newApplicationEvent(events.Windows.APMResumeSuspend) - case w32.PBT_POWERSETTINGCHANGE: - applicationEvents <- newApplicationEvent(events.Windows.APMPowerSettingChange) - } - return 0 - } - - if window, ok := m.windowMap[hwnd]; ok { - return window.WndProc(msg, wParam, lParam) - } - - m.systrayMapLock.Lock() - systray, ok := m.systrayMap[hwnd] - m.systrayMapLock.Unlock() - if ok { - return systray.wndProc(msg, wParam, lParam) - } - - // Dispatch the message to the appropriate window - - return w32.DefWindowProc(hwnd, msg, wParam, lParam) -} - -func (m *windowsApp) registerWindow(result *windowsWebviewWindow) { - m.windowMapLock.Lock() - m.windowMap[result.hwnd] = result - m.windowMapLock.Unlock() -} - -func (m *windowsApp) registerSystemTray(result *windowsSystemTray) { - m.systrayMapLock.Lock() - defer m.systrayMapLock.Unlock() - m.systrayMap[result.hwnd] = result -} - -func (m *windowsApp) unregisterSystemTray(result *windowsSystemTray) { - m.systrayMapLock.Lock() - defer m.systrayMapLock.Unlock() - delete(m.systrayMap, result.hwnd) -} - -func (m *windowsApp) unregisterWindow(w *windowsWebviewWindow) { - m.windowMapLock.Lock() - delete(m.windowMap, w.hwnd) - m.windowMapLock.Unlock() - - // If this was the last window... - if len(m.windowMap) == 0 && !m.parent.options.Windows.DisableQuitOnLastWindowClosed { - w32.PostQuitMessage(0) - } -} - -func (m *windowsApp) reshowSystrays() { - m.systrayMapLock.Lock() - defer m.systrayMapLock.Unlock() - for _, systray := range m.systrayMap { - if _, err := systray.show(); err != nil { - globalApplication.warning("failed to re-add system tray icon: %v", err) - } - } -} - -func setupDPIAwareness() error { - // https://learn.microsoft.com/en-us/windows/win32/hidpi/setting-the-default-dpi-awareness-for-a-process - // https://learn.microsoft.com/en-us/windows/win32/hidpi/high-dpi-desktop-application-development-on-windows - - // Check if DPI awareness has already been set (e.g., via application manifest). - // Windows only allows setting DPI awareness once per process - either via manifest - // or API, not both. If already set, skip the API call to avoid "Access is denied" errors. - // See: https://github.com/wailsapp/wails/issues/4803 - if w32.HasGetProcessDpiAwarenessFunc() { - awareness, err := w32.GetProcessDpiAwareness() - if err == nil && awareness != w32.PROCESS_DPI_UNAWARE { - // DPI awareness already set (likely via manifest), skip API call - return nil - } - } - - if w32.HasSetProcessDpiAwarenessContextFunc() { - // This is most recent version with the best results - // supported beginning with Windows 10, version 1703 - return w32.SetProcessDpiAwarenessContext(w32.DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2) - } - - if w32.HasSetProcessDpiAwarenessFunc() { - // Supported beginning with Windows 8.1 - return w32.SetProcessDpiAwareness(w32.PROCESS_PER_MONITOR_DPI_AWARE) - } - - if w32.HasSetProcessDPIAwareFunc() { - // If none of the above is supported, fallback to SetProcessDPIAware - // which is supported beginning with Windows Vista - return w32.SetProcessDPIAware() - } - - return errors.New("no DPI awareness method supported") -} - -func newPlatformApp(app *App) *windowsApp { - - err := setupDPIAwareness() - if err != nil { - app.handleError(err) - } - - result := &windowsApp{ - parent: app, - instance: w32.GetModuleHandle(""), - windowMap: make(map[w32.HWND]*windowsWebviewWindow), - systrayMap: make(map[w32.HWND]*windowsSystemTray), - } - - err = result.processAndCacheScreens() - if err != nil { - app.handleFatalError(err) - } - - result.init() - result.initMainLoop() - - return result -} - -func (a *App) logPlatformInfo() { - var args []any - args = append(args, "Go-WebView2Loader", webviewloader.UsingGoWebview2Loader) - webviewVersion, err := webviewloader.GetAvailableCoreWebView2BrowserVersionString( - a.options.Windows.WebviewBrowserPath, - ) - if err != nil { - args = append(args, "WebView2", "Error: "+err.Error()) - } else { - args = append(args, "WebView2", webviewVersion) - } - - osInfo, _ := operatingsystem.Info() - args = append(args, osInfo.AsLogSlice()...) - - a.info("Platform Info:", args...) -} - -func (a *App) platformEnvironment() map[string]any { - result := map[string]any{} - webviewVersion, _ := webviewloader.GetAvailableCoreWebView2BrowserVersionString( - a.options.Windows.WebviewBrowserPath, - ) - result["Go-WebView2Loader"] = webviewloader.UsingGoWebview2Loader - result["WebView2"] = webviewVersion - return result -} - -func fatalHandler(errFunc func(error)) { - w32.Fatal = errFunc - return -} diff --git a/v3/pkg/application/assets/alpha/index.html b/v3/pkg/application/assets/alpha/index.html deleted file mode 100644 index 3c685de17..000000000 --- a/v3/pkg/application/assets/alpha/index.html +++ /dev/null @@ -1,81 +0,0 @@ - - - - - Wails Alpha - - - - - - -
                    Alpha
                    -
                    -

                    Documentation

                    -

                    Feedback

                    -
                    - - diff --git a/v3/pkg/application/bindings.go b/v3/pkg/application/bindings.go deleted file mode 100644 index e16948399..000000000 --- a/v3/pkg/application/bindings.go +++ /dev/null @@ -1,427 +0,0 @@ -package application - -import ( - "context" - "encoding/json" - "errors" - "fmt" - "reflect" - "runtime" - "strings" - - "github.com/wailsapp/wails/v3/internal/hash" - "github.com/wailsapp/wails/v3/internal/sliceutil" -) - -// CallOptions defines the options for a method call. -// Field order is optimized to minimize struct padding. -type CallOptions struct { - MethodName string `json:"methodName"` - Args []json.RawMessage `json:"args"` - MethodID uint32 `json:"methodID"` -} - -type ErrorKind string - -const ( - ReferenceError ErrorKind = "ReferenceError" - TypeError ErrorKind = "TypeError" - RuntimeError ErrorKind = "RuntimeError" -) - -// CallError represents an error that occurred during a method call. -// Field order is optimized to minimize struct padding. -type CallError struct { - Message string `json:"message"` - Cause any `json:"cause,omitempty"` - Kind ErrorKind `json:"kind"` -} - -func (e *CallError) Error() string { - return e.Message -} - -// Parameter defines a Go method parameter -type Parameter struct { - Name string `json:"name,omitempty"` - TypeName string `json:"type"` - ReflectType reflect.Type -} - -func newParameter(Name string, Type reflect.Type) *Parameter { - return &Parameter{ - Name: Name, - TypeName: Type.String(), - ReflectType: Type, - } -} - -// IsType returns true if the given -func (p *Parameter) IsType(typename string) bool { - return p.TypeName == typename -} - -// IsError returns true if the parameter type is an error -func (p *Parameter) IsError() bool { - return p.IsType("error") -} - -// BoundMethod defines all the data related to a Go method that is -// bound to the Wails application. -// Field order is optimized to minimize struct padding (136 bytes vs 144 bytes). -type BoundMethod struct { - Method reflect.Value `json:"-"` - Name string `json:"name"` - FQN string `json:"-"` - Comments string `json:"comments,omitempty"` - Inputs []*Parameter `json:"inputs,omitempty"` - Outputs []*Parameter `json:"outputs,omitempty"` - marshalError func(error) []byte - ID uint32 `json:"id"` - needsContext bool - isVariadic bool // cached at registration to avoid reflect call per invocation -} - -type Bindings struct { - marshalError func(error) []byte - boundMethods map[string]*BoundMethod - boundByID map[uint32]*BoundMethod - methodAliases map[uint32]uint32 -} - -func NewBindings(marshalError func(error) []byte, aliases map[uint32]uint32) *Bindings { - return &Bindings{ - marshalError: wrapErrorMarshaler(marshalError, defaultMarshalError), - boundMethods: make(map[string]*BoundMethod), - boundByID: make(map[uint32]*BoundMethod), - methodAliases: aliases, - } -} - -// Add adds the given service to the bindings. -func (b *Bindings) Add(service Service) error { - methods, err := getMethods(service.Instance()) - if err != nil { - return err - } - - marshalError := wrapErrorMarshaler(service.options.MarshalError, defaultMarshalError) - - // Validate and log methods. - for _, method := range methods { - if _, ok := b.boundMethods[method.FQN]; ok { - return fmt.Errorf("bound method '%s' is already registered. Please note that you can register at most one service of each type; additional instances must be wrapped in dedicated structs", method.FQN) - } - if boundMethod, ok := b.boundByID[method.ID]; ok { - return fmt.Errorf("oh wow, we're sorry about this! Amazingly, a hash collision was detected for method '%s' (it generates the same hash as '%s'). To use this method, please rename it. Sorry :(", method.FQN, boundMethod.FQN) - } - - // Log - attrs := []any{"fqn", method.FQN, "id", method.ID} - if alias, ok := sliceutil.FindMapKey(b.methodAliases, method.ID); ok { - attrs = append(attrs, "alias", alias) - } - globalApplication.debug("Registering bound method:", attrs...) - } - - for _, method := range methods { - // Store composite error marshaler - method.marshalError = marshalError - - // Register method - b.boundMethods[method.FQN] = method - b.boundByID[method.ID] = method - } - - return nil -} - -// Get returns the bound method with the given name -func (b *Bindings) Get(options *CallOptions) *BoundMethod { - return b.boundMethods[options.MethodName] -} - -// GetByID returns the bound method with the given ID -func (b *Bindings) GetByID(id uint32) *BoundMethod { - // Check method aliases - if b.methodAliases != nil { - if alias, ok := b.methodAliases[id]; ok { - id = alias - } - } - - return b.boundByID[id] -} - -// internalServiceMethod is a set of methods -// that are handled specially by the binding engine -// and must not be exposed to the frontend. -// -// For simplicity we exclude these by name -// without checking their signatures, -// and so does the binding generator. -var internalServiceMethods = map[string]bool{ - "ServiceName": true, - "ServiceStartup": true, - "ServiceShutdown": true, - "ServeHTTP": true, -} - -var ctxType = reflect.TypeFor[context.Context]() - -// getMethods returns the list of BoundMethod descriptors for the methods of the named pointer type provided by value. -// -// It returns an error if value is not a pointer to a named type, if a function value is supplied (binding functions is deprecated), or if a generic type is supplied. -// The returned BoundMethod slice includes only exported methods that are not listed in internalServiceMethods. Each BoundMethod has its FQN, ID (computed from the FQN), Method reflect.Value, Inputs and Outputs populated, isVariadic cached from the method signature, and needsContext set when the first parameter is context.Context. -func getMethods(value any) ([]*BoundMethod, error) { - // Create result placeholder - var result []*BoundMethod - - // Check type - if !isNamed(value) { - if isFunction(value) { - name := runtime.FuncForPC(reflect.ValueOf(value).Pointer()).Name() - return nil, fmt.Errorf("%s is a function, not a pointer to named type. Wails v2 has deprecated the binding of functions. Please define your functions as methods on a struct and bind a pointer to that struct", name) - } - - return nil, fmt.Errorf("%s is not a pointer to named type", reflect.ValueOf(value).Type().String()) - } else if !isPtr(value) { - return nil, fmt.Errorf("%s is a named type, not a pointer to named type", reflect.ValueOf(value).Type().String()) - } - - // Process Named Type - namedValue := reflect.ValueOf(value) - ptrType := namedValue.Type() - namedType := ptrType.Elem() - typeName := namedType.Name() - packagePath := namedType.PkgPath() - - if strings.Contains(namedType.String(), "[") { - return nil, fmt.Errorf("%s.%s is a generic type. Generic bound types are not supported", packagePath, namedType.String()) - } - - // Process Methods - for i := range ptrType.NumMethod() { - methodName := ptrType.Method(i).Name - method := namedValue.Method(i) - - if internalServiceMethods[methodName] { - continue - } - - fqn := fmt.Sprintf("%s.%s.%s", packagePath, typeName, methodName) - - // Iterate inputs - methodType := method.Type() - - // Create new method with cached flags - boundMethod := &BoundMethod{ - ID: hash.Fnv(fqn), - FQN: fqn, - Name: methodName, - Inputs: nil, - Outputs: nil, - Comments: "", - Method: method, - isVariadic: methodType.IsVariadic(), // cache to avoid reflect call per invocation - } - inputParamCount := methodType.NumIn() - var inputs []*Parameter - for inputIndex := 0; inputIndex < inputParamCount; inputIndex++ { - input := methodType.In(inputIndex) - if inputIndex == 0 && input.AssignableTo(ctxType) { - boundMethod.needsContext = true - } - thisParam := newParameter("", input) - inputs = append(inputs, thisParam) - } - - boundMethod.Inputs = inputs - - outputParamCount := methodType.NumOut() - var outputs []*Parameter - for outputIndex := 0; outputIndex < outputParamCount; outputIndex++ { - output := methodType.Out(outputIndex) - thisParam := newParameter("", output) - outputs = append(outputs, thisParam) - } - boundMethod.Outputs = outputs - - // Save method in result - result = append(result, boundMethod) - - } - - return result, nil -} - -func (b *BoundMethod) String() string { - return b.FQN -} - -var errorType = reflect.TypeFor[error]() - -// Call will attempt to call this bound method with the given args. -// If the call succeeds, result will be either a non-error return value (if there is only one) -// or a slice of non-error return values (if there are more than one). -// -// If the arguments are mistyped or the call returns one or more non-nil error values, -// result is nil and err is an instance of *[CallError]. -func (b *BoundMethod) Call(ctx context.Context, args []json.RawMessage) (result any, err error) { - // Use a defer statement to capture panics - defer handlePanic(handlePanicOptions{skipEnd: 5}) - argCount := len(args) - if b.needsContext { - argCount++ - } - - if argCount != len(b.Inputs) { - err = &CallError{ - Message: fmt.Sprintf("%s expects %d arguments, got %d", b.FQN, len(b.Inputs), argCount), - Kind: TypeError, - } - return - } - - // Use stack-allocated buffer for common case (<=8 args), heap for larger - var argBuffer [8]reflect.Value - var callArgs []reflect.Value - if argCount <= len(argBuffer) { - callArgs = argBuffer[:argCount] - } else { - callArgs = make([]reflect.Value, argCount) - } - base := 0 - - if b.needsContext { - callArgs[0] = reflect.ValueOf(ctx) - base++ - } - - // Iterate over given arguments - for index, arg := range args { - value := reflect.New(b.Inputs[base+index].ReflectType) - err = json.Unmarshal(arg, value.Interface()) - if err != nil { - err = &CallError{ - Message: fmt.Sprintf("could not parse argument #%d: %s", index, err), - Cause: json.RawMessage(b.marshalError(err)), - Kind: TypeError, - } - return - } - callArgs[base+index] = value.Elem() - } - - // Do the call using cached isVariadic flag - var callResults []reflect.Value - if b.isVariadic { - callResults = b.Method.CallSlice(callArgs) - } else { - callResults = b.Method.Call(callArgs) - } - - // Process results - optimized for common case of 0-2 return values - // to avoid slice allocation - var firstResult any - var hasFirstResult bool - var nonErrorOutputs []any // only allocated if >1 non-error results - var errorOutputs []error - - for _, field := range callResults { - if field.Type() == errorType { - if field.IsNil() { - continue - } - if errorOutputs == nil { - errorOutputs = make([]error, 0, len(callResults)) - } - errorOutputs = append(errorOutputs, field.Interface().(error)) - } else if errorOutputs == nil { - // Only collect non-error outputs if no errors yet - val := field.Interface() - if !hasFirstResult { - firstResult = val - hasFirstResult = true - } else if nonErrorOutputs == nil { - // Second result - need to allocate slice - nonErrorOutputs = make([]any, 0, len(callResults)) - nonErrorOutputs = append(nonErrorOutputs, firstResult, val) - } else { - nonErrorOutputs = append(nonErrorOutputs, val) - } - } - } - - if len(errorOutputs) > 0 { - info := make([]json.RawMessage, len(errorOutputs)) - for i, err := range errorOutputs { - info[i] = b.marshalError(err) - } - - cerr := &CallError{ - Message: errors.Join(errorOutputs...).Error(), - Cause: info, - Kind: RuntimeError, - } - if len(info) == 1 { - cerr.Cause = info[0] - } - - err = cerr - } else if nonErrorOutputs != nil { - result = nonErrorOutputs - } else if hasFirstResult { - result = firstResult - } - - return -} - -// wrapErrorMarshaler returns an error marshaling functions -// that calls the primary marshaler first, -// then falls back to the secondary one. -func wrapErrorMarshaler(primary func(error) []byte, secondary func(error) []byte) func(error) []byte { - if primary == nil { - return secondary - } - - return func(err error) []byte { - result := primary(err) - if result == nil { - result = secondary(err) - } - - return result - } -} - -// defaultMarshalError implements the default error marshaling mechanism. -func defaultMarshalError(err error) []byte { - result, jsonErr := json.Marshal(&err) - if jsonErr != nil { - return nil - } - return result -} - -// isPtr returns true if the value given is a pointer. -func isPtr(value interface{}) bool { - return reflect.ValueOf(value).Kind() == reflect.Ptr -} - -// isFunction returns true if the given value is a function -func isFunction(value interface{}) bool { - return reflect.ValueOf(value).Kind() == reflect.Func -} - -// isNamed returns true if the given value is of named type -// or pointer to named type. -func isNamed(value interface{}) bool { - rv := reflect.ValueOf(value) - if rv.Kind() == reflect.Ptr { - rv = rv.Elem() - } - - return rv.Type().Name() != "" -} diff --git a/v3/pkg/application/bindings_bench_test.go b/v3/pkg/application/bindings_bench_test.go deleted file mode 100644 index 2e23cc92d..000000000 --- a/v3/pkg/application/bindings_bench_test.go +++ /dev/null @@ -1,506 +0,0 @@ -//go:build bench - -package application_test - -import ( - "context" - "encoding/json" - "fmt" - "testing" - - "github.com/wailsapp/wails/v3/internal/hash" - "github.com/wailsapp/wails/v3/pkg/application" -) - -// BenchmarkService provides methods with varying complexity for benchmarking -type BenchmarkService struct{} - -func (s *BenchmarkService) NoArgs() {} - -func (s *BenchmarkService) StringArg(str string) string { - return str -} - -func (s *BenchmarkService) IntArg(i int) int { - return i -} - -func (s *BenchmarkService) MultipleArgs(s1 string, i int, b bool) (string, int, bool) { - return s1, i, b -} - -func (s *BenchmarkService) StructArg(p BenchPerson) BenchPerson { - return p -} - -func (s *BenchmarkService) ComplexStruct(c ComplexData) ComplexData { - return c -} - -func (s *BenchmarkService) SliceArg(items []int) []int { - return items -} - -func (s *BenchmarkService) VariadicArg(items ...string) []string { - return items -} - -func (s *BenchmarkService) WithContext(ctx context.Context, s1 string) string { - return s1 -} - -func (s *BenchmarkService) Method1() {} -func (s *BenchmarkService) Method2() {} -func (s *BenchmarkService) Method3() {} -func (s *BenchmarkService) Method4() {} -func (s *BenchmarkService) Method5() {} -func (s *BenchmarkService) Method6() {} -func (s *BenchmarkService) Method7() {} -func (s *BenchmarkService) Method8() {} -func (s *BenchmarkService) Method9() {} -func (s *BenchmarkService) Method10() {} - -type BenchPerson struct { - Name string `json:"name"` - Age int `json:"age"` - Email string `json:"email"` - Address string `json:"address"` -} - -type ComplexData struct { - ID int `json:"id"` - Name string `json:"name"` - Tags []string `json:"tags"` - Metadata map[string]interface{} `json:"metadata"` - Nested *NestedData `json:"nested"` -} - -type NestedData struct { - Value float64 `json:"value"` - Enabled bool `json:"enabled"` -} - -// Helper to create JSON args -func benchArgs(jsonArgs ...string) []json.RawMessage { - args := make([]json.RawMessage, len(jsonArgs)) - for i, j := range jsonArgs { - args[i] = json.RawMessage(j) - } - return args -} - -// BenchmarkMethodBinding measures the cost of registering services with varying method counts -func BenchmarkMethodBinding(b *testing.B) { - // Initialize global application (required for bindings) - _ = application.New(application.Options{}) - - b.Run("SingleService", func(b *testing.B) { - for b.Loop() { - bindings := application.NewBindings(nil, nil) - _ = bindings.Add(application.NewService(&BenchmarkService{})) - } - }) - - b.Run("MultipleServices", func(b *testing.B) { - for b.Loop() { - bindings := application.NewBindings(nil, nil) - _ = bindings.Add(application.NewService(&BenchmarkService{})) - _ = bindings.Add(application.NewService(&BenchPerson{})) // Will fail but tests the path - } - }) -} - -// BenchmarkMethodLookupByID measures method lookup by ID performance -func BenchmarkMethodLookupByID(b *testing.B) { - _ = application.New(application.Options{}) - bindings := application.NewBindings(nil, nil) - _ = bindings.Add(application.NewService(&BenchmarkService{})) - - // Get a valid method ID - callOptions := &application.CallOptions{ - MethodName: "github.com/wailsapp/wails/v3/pkg/application_test.BenchmarkService.StringArg", - } - method := bindings.Get(callOptions) - if method == nil { - b.Fatal("method not found") - } - methodID := method.ID - - b.ResetTimer() - for b.Loop() { - _ = bindings.GetByID(methodID) - } -} - -// BenchmarkMethodLookupByName measures method lookup by name performance -func BenchmarkMethodLookupByName(b *testing.B) { - _ = application.New(application.Options{}) - bindings := application.NewBindings(nil, nil) - _ = bindings.Add(application.NewService(&BenchmarkService{})) - - callOptions := &application.CallOptions{ - MethodName: "github.com/wailsapp/wails/v3/pkg/application_test.BenchmarkService.StringArg", - } - - b.ResetTimer() - for b.Loop() { - _ = bindings.Get(callOptions) - } -} - -// BenchmarkSimpleCall measures the cost of calling a method with a simple string argument -func BenchmarkSimpleCall(b *testing.B) { - _ = application.New(application.Options{}) - bindings := application.NewBindings(nil, nil) - _ = bindings.Add(application.NewService(&BenchmarkService{})) - - callOptions := &application.CallOptions{ - MethodName: "github.com/wailsapp/wails/v3/pkg/application_test.BenchmarkService.StringArg", - } - method := bindings.Get(callOptions) - if method == nil { - b.Fatal("method not found") - } - - args := benchArgs(`"hello world"`) - ctx := context.Background() - - b.ResetTimer() - for b.Loop() { - _, _ = method.Call(ctx, args) - } -} - -// BenchmarkComplexCall measures the cost of calling a method with a complex struct argument -func BenchmarkComplexCall(b *testing.B) { - _ = application.New(application.Options{}) - bindings := application.NewBindings(nil, nil) - _ = bindings.Add(application.NewService(&BenchmarkService{})) - - callOptions := &application.CallOptions{ - MethodName: "github.com/wailsapp/wails/v3/pkg/application_test.BenchmarkService.ComplexStruct", - } - method := bindings.Get(callOptions) - if method == nil { - b.Fatal("method not found") - } - - complexArg := `{ - "id": 12345, - "name": "Test Complex Data", - "tags": ["tag1", "tag2", "tag3", "tag4", "tag5"], - "metadata": {"key1": "value1", "key2": 42, "key3": true}, - "nested": {"value": 3.14159, "enabled": true} - }` - args := benchArgs(complexArg) - ctx := context.Background() - - b.ResetTimer() - for b.Loop() { - _, _ = method.Call(ctx, args) - } -} - -// BenchmarkVariadicCall measures the cost of calling a variadic method -func BenchmarkVariadicCall(b *testing.B) { - _ = application.New(application.Options{}) - bindings := application.NewBindings(nil, nil) - _ = bindings.Add(application.NewService(&BenchmarkService{})) - - callOptions := &application.CallOptions{ - MethodName: "github.com/wailsapp/wails/v3/pkg/application_test.BenchmarkService.VariadicArg", - } - method := bindings.Get(callOptions) - if method == nil { - b.Fatal("method not found") - } - - args := benchArgs(`["one", "two", "three", "four", "five"]`) - ctx := context.Background() - - b.ResetTimer() - for b.Loop() { - _, _ = method.Call(ctx, args) - } -} - -// BenchmarkCallWithContext measures the cost of calling a method that requires context -func BenchmarkCallWithContext(b *testing.B) { - _ = application.New(application.Options{}) - bindings := application.NewBindings(nil, nil) - _ = bindings.Add(application.NewService(&BenchmarkService{})) - - callOptions := &application.CallOptions{ - MethodName: "github.com/wailsapp/wails/v3/pkg/application_test.BenchmarkService.WithContext", - } - method := bindings.Get(callOptions) - if method == nil { - b.Fatal("method not found") - } - - args := benchArgs(`"context test"`) - ctx := context.Background() - - b.ResetTimer() - for b.Loop() { - _, _ = method.Call(ctx, args) - } -} - -// BenchmarkJSONMarshalResult measures JSON marshaling overhead for results -func BenchmarkJSONMarshalResult(b *testing.B) { - person := BenchPerson{ - Name: "John Doe", - Age: 30, - Email: "john@example.com", - Address: "123 Main St, City, Country", - } - - b.Run("SimplePerson", func(b *testing.B) { - for b.Loop() { - _, _ = json.Marshal(person) - } - }) - - complex := ComplexData{ - ID: 12345, - Name: "Complex Test", - Tags: []string{"tag1", "tag2", "tag3", "tag4", "tag5"}, - Metadata: map[string]interface{}{ - "key1": "value1", - "key2": 42, - "key3": true, - }, - Nested: &NestedData{ - Value: 3.14159, - Enabled: true, - }, - } - - b.Run("ComplexData", func(b *testing.B) { - for b.Loop() { - _, _ = json.Marshal(complex) - } - }) -} - -// BenchmarkHashComputation measures the FNV hash computation used for method IDs -func BenchmarkHashComputation(b *testing.B) { - testCases := []struct { - name string - fqn string - }{ - {"Short", "pkg.Service.Method"}, - {"Medium", "github.com/user/project/pkg.Service.Method"}, - {"Long", "github.com/wailsapp/wails/v3/pkg/application_test.BenchmarkService.ComplexStruct"}, - } - - for _, tc := range testCases { - b.Run(tc.name, func(b *testing.B) { - for b.Loop() { - _ = hash.Fnv(tc.fqn) - } - }) - } -} - -// BenchmarkJSONUnmarshal measures JSON unmarshaling overhead for arguments -func BenchmarkJSONUnmarshal(b *testing.B) { - b.Run("String", func(b *testing.B) { - data := []byte(`"hello world"`) - for b.Loop() { - var s string - _ = json.Unmarshal(data, &s) - } - }) - - b.Run("Int", func(b *testing.B) { - data := []byte(`12345`) - for b.Loop() { - var i int - _ = json.Unmarshal(data, &i) - } - }) - - b.Run("Struct", func(b *testing.B) { - data := []byte(`{"name":"John","age":30,"email":"john@example.com","address":"123 Main St"}`) - for b.Loop() { - var p BenchPerson - _ = json.Unmarshal(data, &p) - } - }) - - b.Run("ComplexStruct", func(b *testing.B) { - data := []byte(`{"id":12345,"name":"Test","tags":["a","b","c"],"metadata":{"k":"v"},"nested":{"value":3.14,"enabled":true}}`) - for b.Loop() { - var c ComplexData - _ = json.Unmarshal(data, &c) - } - }) -} - -// BenchmarkMethodLookupWithAliases measures method lookup with alias resolution -func BenchmarkMethodLookupWithAliases(b *testing.B) { - _ = application.New(application.Options{}) - - // Create aliases map - aliases := make(map[uint32]uint32) - for i := uint32(0); i < 100; i++ { - aliases[i+1000] = i - } - - bindings := application.NewBindings(nil, aliases) - _ = bindings.Add(application.NewService(&BenchmarkService{})) - - callOptions := &application.CallOptions{ - MethodName: "github.com/wailsapp/wails/v3/pkg/application_test.BenchmarkService.StringArg", - } - method := bindings.Get(callOptions) - if method == nil { - b.Fatal("method not found") - } - - b.Run("DirectLookup", func(b *testing.B) { - id := method.ID - for b.Loop() { - _ = bindings.GetByID(id) - } - }) - - b.Run("AliasLookup", func(b *testing.B) { - // Add an alias for this method - aliases[9999] = method.ID - for b.Loop() { - _ = bindings.GetByID(9999) - } - }) -} - -// BenchmarkReflectValueCall measures the overhead of reflect.Value.Call -func BenchmarkReflectValueCall(b *testing.B) { - _ = application.New(application.Options{}) - bindings := application.NewBindings(nil, nil) - _ = bindings.Add(application.NewService(&BenchmarkService{})) - - ctx := context.Background() - - b.Run("NoArgs", func(b *testing.B) { - callOptions := &application.CallOptions{ - MethodName: "github.com/wailsapp/wails/v3/pkg/application_test.BenchmarkService.NoArgs", - } - method := bindings.Get(callOptions) - if method == nil { - b.Fatal("method not found") - } - args := benchArgs() - for b.Loop() { - _, _ = method.Call(ctx, args) - } - }) - - b.Run("MultipleArgs", func(b *testing.B) { - callOptions := &application.CallOptions{ - MethodName: "github.com/wailsapp/wails/v3/pkg/application_test.BenchmarkService.MultipleArgs", - } - method := bindings.Get(callOptions) - if method == nil { - b.Fatal("method not found") - } - args := benchArgs(`"test"`, `42`, `true`) - for b.Loop() { - _, _ = method.Call(ctx, args) - } - }) -} - -// BenchmarkBindingsScaling measures how bindings performance scales with service count -func BenchmarkBindingsScaling(b *testing.B) { - _ = application.New(application.Options{}) - - // We can only add one service of each type, so we test lookup scaling - bindings := application.NewBindings(nil, nil) - _ = bindings.Add(application.NewService(&BenchmarkService{})) - - // Generate method names for lookup - methodNames := []string{ - "github.com/wailsapp/wails/v3/pkg/application_test.BenchmarkService.NoArgs", - "github.com/wailsapp/wails/v3/pkg/application_test.BenchmarkService.StringArg", - "github.com/wailsapp/wails/v3/pkg/application_test.BenchmarkService.IntArg", - "github.com/wailsapp/wails/v3/pkg/application_test.BenchmarkService.MultipleArgs", - "github.com/wailsapp/wails/v3/pkg/application_test.BenchmarkService.StructArg", - } - - b.Run("SequentialLookup", func(b *testing.B) { - for b.Loop() { - for _, name := range methodNames { - _ = bindings.Get(&application.CallOptions{MethodName: name}) - } - } - }) -} - -// BenchmarkCallErrorPath measures the cost of error handling in method calls -func BenchmarkCallErrorPath(b *testing.B) { - _ = application.New(application.Options{}) - bindings := application.NewBindings(nil, nil) - _ = bindings.Add(application.NewService(&BenchmarkService{})) - - callOptions := &application.CallOptions{ - MethodName: "github.com/wailsapp/wails/v3/pkg/application_test.BenchmarkService.StringArg", - } - method := bindings.Get(callOptions) - if method == nil { - b.Fatal("method not found") - } - - ctx := context.Background() - - b.Run("WrongArgCount", func(b *testing.B) { - args := benchArgs() // No args when one is expected - for b.Loop() { - _, _ = method.Call(ctx, args) - } - }) - - b.Run("WrongArgType", func(b *testing.B) { - args := benchArgs(`123`) // Int when string is expected - for b.Loop() { - _, _ = method.Call(ctx, args) - } - }) -} - -// BenchmarkSliceArgSizes measures performance with varying slice sizes -func BenchmarkSliceArgSizes(b *testing.B) { - _ = application.New(application.Options{}) - bindings := application.NewBindings(nil, nil) - _ = bindings.Add(application.NewService(&BenchmarkService{})) - - callOptions := &application.CallOptions{ - MethodName: "github.com/wailsapp/wails/v3/pkg/application_test.BenchmarkService.SliceArg", - } - method := bindings.Get(callOptions) - if method == nil { - b.Fatal("method not found") - } - - ctx := context.Background() - - sizes := []int{1, 10, 100, 1000} - for _, size := range sizes { - b.Run(fmt.Sprintf("Size%d", size), func(b *testing.B) { - // Build slice JSON - slice := make([]int, size) - for i := range slice { - slice[i] = i - } - data, _ := json.Marshal(slice) - args := []json.RawMessage{data} - - b.ResetTimer() - for b.Loop() { - _, _ = method.Call(ctx, args) - } - }) - } -} diff --git a/v3/pkg/application/bindings_optimized_bench_test.go b/v3/pkg/application/bindings_optimized_bench_test.go deleted file mode 100644 index 1a9b137f5..000000000 --- a/v3/pkg/application/bindings_optimized_bench_test.go +++ /dev/null @@ -1,469 +0,0 @@ -//go:build bench - -package application - -import ( - "context" - "encoding/json" - "errors" - "fmt" - "reflect" - "sync" - "testing" - - jsonv2 "github.com/go-json-experiment/json" -) - -// This file contains optimized versions of BoundMethod.Call for benchmarking. -// These demonstrate potential optimizations that could be applied. - -// Pools for reducing allocations -var ( - // Pool for []reflect.Value slices (sized for typical arg counts) - callArgsPool = sync.Pool{ - New: func() any { - // Pre-allocate for up to 8 args (covers vast majority of methods) - return make([]reflect.Value, 0, 8) - }, - } - - // Pool for []any slices - anySlicePool = sync.Pool{ - New: func() any { - return make([]any, 0, 4) - }, - } - - // Pool for CallError structs - callErrorPool = sync.Pool{ - New: func() any { - return &CallError{} - }, - } -) - -// CallOptimized is an optimized version of BoundMethod.Call that uses sync.Pool -func (b *BoundMethod) CallOptimized(ctx context.Context, args []json.RawMessage) (result any, err error) { - defer handlePanic(handlePanicOptions{skipEnd: 5}) - - argCount := len(args) - if b.needsContext { - argCount++ - } - - if argCount != len(b.Inputs) { - cerr := callErrorPool.Get().(*CallError) - cerr.Kind = TypeError - cerr.Message = fmt.Sprintf("%s expects %d arguments, got %d", b.FQN, len(b.Inputs), argCount) - cerr.Cause = nil - return nil, cerr - } - - // Get callArgs from pool - callArgs := callArgsPool.Get().([]reflect.Value) - callArgs = callArgs[:0] // Reset length but keep capacity - - // Ensure capacity - if cap(callArgs) < argCount { - callArgs = make([]reflect.Value, 0, argCount) - } - callArgs = callArgs[:argCount] - - base := 0 - if b.needsContext { - callArgs[0] = reflect.ValueOf(ctx) - base++ - } - - // Iterate over given arguments - for index, arg := range args { - value := reflect.New(b.Inputs[base+index].ReflectType) - err = json.Unmarshal(arg, value.Interface()) - if err != nil { - // Return callArgs to pool before returning error - callArgsPool.Put(callArgs[:0]) - - cerr := callErrorPool.Get().(*CallError) - cerr.Kind = TypeError - cerr.Message = fmt.Sprintf("could not parse argument #%d: %s", index, err) - cerr.Cause = json.RawMessage(b.marshalError(err)) - return nil, cerr - } - callArgs[base+index] = value.Elem() - } - - // Do the call - use cached isVariadic flag like production code - var callResults []reflect.Value - if b.isVariadic { - callResults = b.Method.CallSlice(callArgs) - } else { - callResults = b.Method.Call(callArgs) - } - - // Return callArgs to pool - callArgsPool.Put(callArgs[:0]) - - // Get output slice from pool - nonErrorOutputs := anySlicePool.Get().([]any) - nonErrorOutputs = nonErrorOutputs[:0] - defer func() { - anySlicePool.Put(nonErrorOutputs[:0]) - }() - - var errorOutputs []error - - for _, field := range callResults { - if field.Type() == errorType { - if field.IsNil() { - continue - } - if errorOutputs == nil { - errorOutputs = make([]error, 0, len(callResults)-len(nonErrorOutputs)) - nonErrorOutputs = nil - } - errorOutputs = append(errorOutputs, field.Interface().(error)) - } else if nonErrorOutputs != nil { - nonErrorOutputs = append(nonErrorOutputs, field.Interface()) - } - } - - if len(errorOutputs) > 0 { - info := make([]json.RawMessage, len(errorOutputs)) - for i, err := range errorOutputs { - info[i] = b.marshalError(err) - } - - cerr := &CallError{ - Kind: RuntimeError, - Message: errors.Join(errorOutputs...).Error(), - Cause: info, - } - if len(info) == 1 { - cerr.Cause = info[0] - } - return nil, cerr - } - - if len(nonErrorOutputs) == 1 { - result = nonErrorOutputs[0] - } else if len(nonErrorOutputs) > 1 { - // Need to copy since we're returning the pooled slice - resultSlice := make([]any, len(nonErrorOutputs)) - copy(resultSlice, nonErrorOutputs) - result = resultSlice - } - - return result, nil -} - -// Benchmark comparing original vs optimized Call -func BenchmarkCallOriginal(b *testing.B) { - _ = New(Options{}) - bindings := NewBindings(nil, nil) - - service := &benchService{} - _ = bindings.Add(NewService(service)) - - callOptions := &CallOptions{ - MethodName: "github.com/wailsapp/wails/v3/pkg/application.benchService.StringArg", - } - method := bindings.Get(callOptions) - if method == nil { - b.Fatal("method not found") - } - - args := []json.RawMessage{json.RawMessage(`"hello world"`)} - ctx := context.Background() - - b.ResetTimer() - for b.Loop() { - _, _ = method.Call(ctx, args) - } -} - -func BenchmarkCallOptimized(b *testing.B) { - _ = New(Options{}) - bindings := NewBindings(nil, nil) - - service := &benchService{} - _ = bindings.Add(NewService(service)) - - callOptions := &CallOptions{ - MethodName: "github.com/wailsapp/wails/v3/pkg/application.benchService.StringArg", - } - method := bindings.Get(callOptions) - if method == nil { - b.Fatal("method not found") - } - - args := []json.RawMessage{json.RawMessage(`"hello world"`)} - ctx := context.Background() - - b.ResetTimer() - for b.Loop() { - _, _ = method.CallOptimized(ctx, args) - } -} - -// benchService for internal tests -type benchService struct{} - -func (s *benchService) StringArg(str string) string { - return str -} - -func (s *benchService) MultipleArgs(s1 string, i int, b bool) (string, int, bool) { - return s1, i, b -} - -func BenchmarkCallOriginal_MultiArgs(b *testing.B) { - _ = New(Options{}) - bindings := NewBindings(nil, nil) - - service := &benchService{} - _ = bindings.Add(NewService(service)) - - callOptions := &CallOptions{ - MethodName: "github.com/wailsapp/wails/v3/pkg/application.benchService.MultipleArgs", - } - method := bindings.Get(callOptions) - if method == nil { - b.Fatal("method not found") - } - - args := []json.RawMessage{ - json.RawMessage(`"test"`), - json.RawMessage(`42`), - json.RawMessage(`true`), - } - ctx := context.Background() - - b.ResetTimer() - for b.Loop() { - _, _ = method.Call(ctx, args) - } -} - -func BenchmarkCallOptimized_MultiArgs(b *testing.B) { - _ = New(Options{}) - bindings := NewBindings(nil, nil) - - service := &benchService{} - _ = bindings.Add(NewService(service)) - - callOptions := &CallOptions{ - MethodName: "github.com/wailsapp/wails/v3/pkg/application.benchService.MultipleArgs", - } - method := bindings.Get(callOptions) - if method == nil { - b.Fatal("method not found") - } - - args := []json.RawMessage{ - json.RawMessage(`"test"`), - json.RawMessage(`42`), - json.RawMessage(`true`), - } - ctx := context.Background() - - b.ResetTimer() - for b.Loop() { - _, _ = method.CallOptimized(ctx, args) - } -} - -// CallWithJSONv2 uses the new JSON v2 library for unmarshaling -func (b *BoundMethod) CallWithJSONv2(ctx context.Context, args []json.RawMessage) (result any, err error) { - defer handlePanic(handlePanicOptions{skipEnd: 5}) - - argCount := len(args) - if b.needsContext { - argCount++ - } - - if argCount != len(b.Inputs) { - return nil, &CallError{ - Kind: TypeError, - Message: fmt.Sprintf("%s expects %d arguments, got %d", b.FQN, len(b.Inputs), argCount), - } - } - - // Convert inputs to values of appropriate type - callArgs := make([]reflect.Value, argCount) - base := 0 - - if b.needsContext { - callArgs[0] = reflect.ValueOf(ctx) - base++ - } - - // Iterate over given arguments - use JSON v2 for unmarshaling - for index, arg := range args { - value := reflect.New(b.Inputs[base+index].ReflectType) - err = jsonv2.Unmarshal(arg, value.Interface()) - if err != nil { - return nil, &CallError{ - Kind: TypeError, - Message: fmt.Sprintf("could not parse argument #%d: %s", index, err), - Cause: json.RawMessage(b.marshalError(err)), - } - } - callArgs[base+index] = value.Elem() - } - - // Do the call - var callResults []reflect.Value - if b.Method.Type().IsVariadic() { - callResults = b.Method.CallSlice(callArgs) - } else { - callResults = b.Method.Call(callArgs) - } - - var nonErrorOutputs = make([]any, 0, len(callResults)) - var errorOutputs []error - - for _, field := range callResults { - if field.Type() == errorType { - if field.IsNil() { - continue - } - if errorOutputs == nil { - errorOutputs = make([]error, 0, len(callResults)-len(nonErrorOutputs)) - nonErrorOutputs = nil - } - errorOutputs = append(errorOutputs, field.Interface().(error)) - } else if nonErrorOutputs != nil { - nonErrorOutputs = append(nonErrorOutputs, field.Interface()) - } - } - - if len(errorOutputs) > 0 { - info := make([]json.RawMessage, len(errorOutputs)) - for i, err := range errorOutputs { - info[i] = b.marshalError(err) - } - - cerr := &CallError{ - Kind: RuntimeError, - Message: errors.Join(errorOutputs...).Error(), - Cause: info, - } - if len(info) == 1 { - cerr.Cause = info[0] - } - return nil, cerr - } - - if len(nonErrorOutputs) == 1 { - result = nonErrorOutputs[0] - } else if len(nonErrorOutputs) > 1 { - result = nonErrorOutputs - } - - return result, nil -} - -func BenchmarkCallJSONv2(b *testing.B) { - _ = New(Options{}) - bindings := NewBindings(nil, nil) - - service := &benchService{} - _ = bindings.Add(NewService(service)) - - callOptions := &CallOptions{ - MethodName: "github.com/wailsapp/wails/v3/pkg/application.benchService.StringArg", - } - method := bindings.Get(callOptions) - if method == nil { - b.Fatal("method not found") - } - - args := []json.RawMessage{json.RawMessage(`"hello world"`)} - ctx := context.Background() - - b.ResetTimer() - for b.Loop() { - _, _ = method.CallWithJSONv2(ctx, args) - } -} - -func BenchmarkCallJSONv2_MultiArgs(b *testing.B) { - _ = New(Options{}) - bindings := NewBindings(nil, nil) - - service := &benchService{} - _ = bindings.Add(NewService(service)) - - callOptions := &CallOptions{ - MethodName: "github.com/wailsapp/wails/v3/pkg/application.benchService.MultipleArgs", - } - method := bindings.Get(callOptions) - if method == nil { - b.Fatal("method not found") - } - - args := []json.RawMessage{ - json.RawMessage(`"test"`), - json.RawMessage(`42`), - json.RawMessage(`true`), - } - ctx := context.Background() - - b.ResetTimer() - for b.Loop() { - _, _ = method.CallWithJSONv2(ctx, args) - } -} - -// Concurrent benchmark to test pool effectiveness under load -func BenchmarkCallOriginal_Concurrent(b *testing.B) { - _ = New(Options{}) - bindings := NewBindings(nil, nil) - - service := &benchService{} - _ = bindings.Add(NewService(service)) - - callOptions := &CallOptions{ - MethodName: "github.com/wailsapp/wails/v3/pkg/application.benchService.StringArg", - } - method := bindings.Get(callOptions) - if method == nil { - b.Fatal("method not found") - } - - args := []json.RawMessage{json.RawMessage(`"hello world"`)} - ctx := context.Background() - - b.ResetTimer() - b.RunParallel(func(pb *testing.PB) { - for pb.Next() { - _, _ = method.Call(ctx, args) - } - }) -} - -func BenchmarkCallOptimized_Concurrent(b *testing.B) { - _ = New(Options{}) - bindings := NewBindings(nil, nil) - - service := &benchService{} - _ = bindings.Add(NewService(service)) - - callOptions := &CallOptions{ - MethodName: "github.com/wailsapp/wails/v3/pkg/application.benchService.StringArg", - } - method := bindings.Get(callOptions) - if method == nil { - b.Fatal("method not found") - } - - args := []json.RawMessage{json.RawMessage(`"hello world"`)} - ctx := context.Background() - - b.ResetTimer() - b.RunParallel(func(pb *testing.PB) { - for pb.Next() { - _, _ = method.CallOptimized(ctx, args) - } - }) -} diff --git a/v3/pkg/application/bindings_test.go b/v3/pkg/application/bindings_test.go deleted file mode 100644 index d76a8efe0..000000000 --- a/v3/pkg/application/bindings_test.go +++ /dev/null @@ -1,191 +0,0 @@ -package application_test - -import ( - "context" - "encoding/json" - "errors" - "reflect" - "strings" - "testing" - - "github.com/wailsapp/wails/v3/pkg/application" -) - -type TestService struct { -} - -type Person struct { - Name string `json:"name"` -} - -func (t *TestService) Nil() {} - -func (t *TestService) String(s string) string { - return s -} - -func (t *TestService) Multiple(s string, i int, b bool) (string, int, bool) { - return s, i, b -} - -func (t *TestService) Struct(p Person) Person { - return p -} - -func (t *TestService) StructNil(p Person) (Person, error) { - return p, nil -} - -func (t *TestService) StructError(p Person) (Person, error) { - return p, errors.New("error") -} - -func (t *TestService) Variadic(s ...string) []string { - return s -} - -func (t *TestService) PositionalAndVariadic(a int, _ ...string) int { - return a -} - -func (t *TestService) Slice(a []int) []int { - return a -} - -func newArgs(jsonArgs ...string) (args []json.RawMessage) { - for _, j := range jsonArgs { - args = append(args, json.RawMessage(j)) - } - return -} - -func TestBoundMethodCall(t *testing.T) { - tests := []struct { - name string - method string - args []json.RawMessage - err string - expected interface{} - }{ - { - name: "nil", - method: "Nil", - args: []json.RawMessage{}, - err: "", - expected: nil, - }, - { - name: "string", - method: "String", - args: newArgs(`"foo"`), - err: "", - expected: "foo", - }, - { - name: "multiple", - method: "Multiple", - args: newArgs(`"foo"`, "0", "false"), - err: "", - expected: []interface{}{"foo", 0, false}, - }, - { - name: "struct", - method: "Struct", - args: newArgs(`{ "name": "alice" }`), - err: "", - expected: Person{Name: "alice"}, - }, - { - name: "struct, nil error", - method: "StructNil", - args: newArgs(`{ "name": "alice" }`), - err: "", - expected: Person{Name: "alice"}, - }, - { - name: "struct, error", - method: "StructError", - args: newArgs(`{ "name": "alice" }`), - err: "error", - expected: nil, - }, - { - name: "invalid argument count", - method: "Multiple", - args: newArgs(`"foo"`), - err: "expects 3 arguments, got 1", - expected: nil, - }, - { - name: "invalid argument type", - method: "String", - args: newArgs("1"), - err: "could not parse", - expected: nil, - }, - { - name: "variadic, no arguments", - method: "Variadic", - args: newArgs(`[]`), // variadic parameters are passed as arrays - err: "", - expected: []string{}, - }, - { - name: "variadic", - method: "Variadic", - args: newArgs(`["foo", "bar"]`), - err: "", - expected: []string{"foo", "bar"}, - }, - { - name: "positional and variadic", - method: "PositionalAndVariadic", - args: newArgs("42", `[]`), - err: "", - expected: 42, - }, - { - name: "slice", - method: "Slice", - args: newArgs(`[1,2,3]`), - err: "", - expected: []int{1, 2, 3}, - }, - } - - // init globalApplication - _ = application.New(application.Options{}) - - bindings := application.NewBindings(nil, nil) - - err := bindings.Add(application.NewService(&TestService{})) - if err != nil { - t.Fatalf("bindings.Add() error = %v\n", err) - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - callOptions := &application.CallOptions{ - MethodName: "github.com/wailsapp/wails/v3/pkg/application_test.TestService." + tt.method, - } - - method := bindings.Get(callOptions) - if method == nil { - t.Fatalf("bound method not found: %s", callOptions.MethodName) - } - - result, err := method.Call(context.TODO(), tt.args) - if (tt.err == "") != (err == nil) || (err != nil && !strings.Contains(err.Error(), tt.err)) { - expected := tt.err - if expected == "" { - expected = "nil" - } - t.Fatalf("error: %#v, expected error: %v", err, expected) - } - if !reflect.DeepEqual(result, tt.expected) { - t.Fatalf("result: %v, expected result: %v", result, tt.expected) - } - }) - } - -} diff --git a/v3/pkg/application/browser_manager.go b/v3/pkg/application/browser_manager.go deleted file mode 100644 index 3fe81720a..000000000 --- a/v3/pkg/application/browser_manager.go +++ /dev/null @@ -1,27 +0,0 @@ -package application - -import ( - "github.com/pkg/browser" -) - -// BrowserManager manages browser-related operations -type BrowserManager struct { - app *App -} - -// newBrowserManager creates a new BrowserManager instance -func newBrowserManager(app *App) *BrowserManager { - return &BrowserManager{ - app: app, - } -} - -// OpenURL opens a URL in the default browser -func (bm *BrowserManager) OpenURL(url string) error { - return browser.OpenURL(url) -} - -// OpenFile opens a file in the default browser -func (bm *BrowserManager) OpenFile(path string) error { - return browser.OpenFile(path) -} diff --git a/v3/pkg/application/browser_window.go b/v3/pkg/application/browser_window.go deleted file mode 100644 index 5d3749db0..000000000 --- a/v3/pkg/application/browser_window.go +++ /dev/null @@ -1,149 +0,0 @@ -//go:build server - -package application - -import ( - "fmt" - "unsafe" - - "github.com/wailsapp/wails/v3/pkg/events" -) - -// BrowserWindow represents a browser client connection in server mode. -// It implements the Window interface so browser clients can be treated -// uniformly with native windows throughout the codebase. -type BrowserWindow struct { - id uint - name string - clientID string // The runtime's nanoid for this client -} - -// NewBrowserWindow creates a new browser window with the given ID. -func NewBrowserWindow(id uint, clientID string) *BrowserWindow { - return &BrowserWindow{ - id: id, - name: fmt.Sprintf("browser-%d", id), - clientID: clientID, - } -} - -// Core identification methods - -func (b *BrowserWindow) ID() uint { return b.id } -func (b *BrowserWindow) Name() string { return b.name } -func (b *BrowserWindow) ClientID() string { return b.clientID } - -// Event methods - these are meaningful for browser windows - -func (b *BrowserWindow) DispatchWailsEvent(event *CustomEvent) { - // Events are dispatched via WebSocket broadcast, not per-window -} - -func (b *BrowserWindow) EmitEvent(name string, data ...any) bool { - return globalApplication.Event.Emit(name, data...) -} - -// Logging methods - -func (b *BrowserWindow) Error(message string, args ...any) { - globalApplication.error(message, args...) -} - -func (b *BrowserWindow) Info(message string, args ...any) { - globalApplication.info(message, args...) -} - -// No-op methods - these don't apply to browser windows - -func (b *BrowserWindow) Center() {} -func (b *BrowserWindow) Close() {} -func (b *BrowserWindow) DisableSizeConstraints() {} -func (b *BrowserWindow) EnableSizeConstraints() {} -func (b *BrowserWindow) ExecJS(js string) {} -func (b *BrowserWindow) Focus() {} -func (b *BrowserWindow) ForceReload() {} -func (b *BrowserWindow) Fullscreen() Window { return b } -func (b *BrowserWindow) GetBorderSizes() *LRTB { return nil } -func (b *BrowserWindow) GetScreen() (*Screen, error) { return nil, nil } -func (b *BrowserWindow) GetZoom() float64 { return 1.0 } -func (b *BrowserWindow) handleDragAndDropMessage(filenames []string, dropTarget *DropTargetDetails) {} -func (b *BrowserWindow) InitiateFrontendDropProcessing(filenames []string, x int, y int) {} -func (b *BrowserWindow) HandleMessage(message string) {} -func (b *BrowserWindow) HandleWindowEvent(id uint) {} -func (b *BrowserWindow) Height() int { return 0 } -func (b *BrowserWindow) Hide() Window { return b } -func (b *BrowserWindow) HideMenuBar() {} -func (b *BrowserWindow) IsFocused() bool { return false } -func (b *BrowserWindow) IsFullscreen() bool { return false } -func (b *BrowserWindow) IsIgnoreMouseEvents() bool { return false } -func (b *BrowserWindow) IsMaximised() bool { return false } -func (b *BrowserWindow) IsMinimised() bool { return false } -func (b *BrowserWindow) HandleKeyEvent(acceleratorString string) {} -func (b *BrowserWindow) Maximise() Window { return b } -func (b *BrowserWindow) Minimise() Window { return b } -func (b *BrowserWindow) OnWindowEvent(eventType events.WindowEventType, callback func(event *WindowEvent)) func() { - return func() {} -} -func (b *BrowserWindow) OpenContextMenu(data *ContextMenuData) {} -func (b *BrowserWindow) Position() (int, int) { return 0, 0 } -func (b *BrowserWindow) RelativePosition() (int, int) { return 0, 0 } -func (b *BrowserWindow) Reload() {} -func (b *BrowserWindow) Resizable() bool { return false } -func (b *BrowserWindow) Restore() {} -func (b *BrowserWindow) Run() {} -func (b *BrowserWindow) SetPosition(x, y int) {} -func (b *BrowserWindow) SetAlwaysOnTop(b2 bool) Window { return b } -func (b *BrowserWindow) SetBackgroundColour(colour RGBA) Window { return b } -func (b *BrowserWindow) SetFrameless(frameless bool) Window { return b } -func (b *BrowserWindow) SetHTML(html string) Window { return b } -func (b *BrowserWindow) SetMinimiseButtonState(state ButtonState) Window { return b } -func (b *BrowserWindow) SetMaximiseButtonState(state ButtonState) Window { return b } -func (b *BrowserWindow) SetCloseButtonState(state ButtonState) Window { return b } -func (b *BrowserWindow) SetMaxSize(maxWidth, maxHeight int) Window { return b } -func (b *BrowserWindow) SetMinSize(minWidth, minHeight int) Window { return b } -func (b *BrowserWindow) SetRelativePosition(x, y int) Window { return b } -func (b *BrowserWindow) SetResizable(b2 bool) Window { return b } -func (b *BrowserWindow) SetIgnoreMouseEvents(ignore bool) Window { return b } -func (b *BrowserWindow) SetSize(width, height int) Window { return b } -func (b *BrowserWindow) SetTitle(title string) Window { return b } -func (b *BrowserWindow) SetURL(s string) Window { return b } -func (b *BrowserWindow) SetZoom(magnification float64) Window { return b } -func (b *BrowserWindow) Show() Window { return b } -func (b *BrowserWindow) ShowMenuBar() {} -func (b *BrowserWindow) Size() (width int, height int) { return 0, 0 } -func (b *BrowserWindow) OpenDevTools() {} -func (b *BrowserWindow) ToggleFullscreen() {} -func (b *BrowserWindow) ToggleMaximise() {} -func (b *BrowserWindow) ToggleMenuBar() {} -func (b *BrowserWindow) ToggleFrameless() {} -func (b *BrowserWindow) UnFullscreen() {} -func (b *BrowserWindow) UnMaximise() {} -func (b *BrowserWindow) UnMinimise() {} -func (b *BrowserWindow) Width() int { return 0 } -func (b *BrowserWindow) IsVisible() bool { return true } -func (b *BrowserWindow) Bounds() Rect { return Rect{} } -func (b *BrowserWindow) SetBounds(bounds Rect) {} -func (b *BrowserWindow) Zoom() {} -func (b *BrowserWindow) ZoomIn() {} -func (b *BrowserWindow) ZoomOut() {} -func (b *BrowserWindow) ZoomReset() Window { return b } -func (b *BrowserWindow) SetMenu(menu *Menu) {} -func (b *BrowserWindow) SnapAssist() {} -func (b *BrowserWindow) SetContentProtection(protection bool) Window { return b } -func (b *BrowserWindow) NativeWindow() unsafe.Pointer { return nil } -func (b *BrowserWindow) SetEnabled(enabled bool) {} -func (b *BrowserWindow) Flash(enabled bool) {} -func (b *BrowserWindow) Print() error { return nil } -func (b *BrowserWindow) RegisterHook(eventType events.WindowEventType, callback func(event *WindowEvent)) func() { - return func() {} -} -func (b *BrowserWindow) shouldUnconditionallyClose() bool { return true } - -// Editing methods -func (b *BrowserWindow) cut() {} -func (b *BrowserWindow) copy() {} -func (b *BrowserWindow) paste() {} -func (b *BrowserWindow) undo() {} -func (b *BrowserWindow) redo() {} -func (b *BrowserWindow) delete() {} -func (b *BrowserWindow) selectAll() {} diff --git a/v3/pkg/application/clipboard.go b/v3/pkg/application/clipboard.go deleted file mode 100644 index f21b597e2..000000000 --- a/v3/pkg/application/clipboard.go +++ /dev/null @@ -1,26 +0,0 @@ -package application - -type clipboardImpl interface { - setText(text string) bool - text() (string, bool) -} - -type Clipboard struct { - impl clipboardImpl -} - -func newClipboard() *Clipboard { - return &Clipboard{ - impl: newClipboardImpl(), - } -} - -func (c *Clipboard) SetText(text string) bool { - return InvokeSyncWithResult(func() bool { - return c.impl.setText(text) - }) -} - -func (c *Clipboard) Text() (string, bool) { - return InvokeSyncWithResultAndOther(c.impl.text) -} diff --git a/v3/pkg/application/clipboard_android.go b/v3/pkg/application/clipboard_android.go deleted file mode 100644 index 4c44eaa1f..000000000 --- a/v3/pkg/application/clipboard_android.go +++ /dev/null @@ -1,35 +0,0 @@ -//go:build android - -package application - -type androidClipboardImpl struct{} - -func newClipboardImpl() clipboardImpl { - return &androidClipboardImpl{} -} - -func (c *androidClipboardImpl) setText(text string) bool { - // Android clipboard implementation would go here - // TODO: Implement via JNI to Android ClipboardManager - return true -} - -func (c *androidClipboardImpl) text() (string, bool) { - // Android clipboard implementation would go here - // TODO: Implement via JNI to Android ClipboardManager - return "", false -} - -// SetClipboardText sets the clipboard text on Android -func (c *ClipboardManager) SetClipboardText(text string) error { - // Android clipboard implementation would go here - // For now, return nil as a placeholder - return nil -} - -// GetClipboardText gets the clipboard text on Android -func (c *ClipboardManager) GetClipboardText() (string, error) { - // Android clipboard implementation would go here - // For now, return empty string - return "", nil -} diff --git a/v3/pkg/application/clipboard_darwin.go b/v3/pkg/application/clipboard_darwin.go deleted file mode 100644 index 545305913..000000000 --- a/v3/pkg/application/clipboard_darwin.go +++ /dev/null @@ -1,56 +0,0 @@ -//go:build darwin && !ios - -package application - -/* -#cgo CFLAGS: -mmacosx-version-min=10.13 -x objective-c -#cgo LDFLAGS: -framework Cocoa -mmacosx-version-min=10.13 - -#import -#import - -bool setClipboardText(const char* text) { - NSPasteboard *pasteBoard = [NSPasteboard generalPasteboard]; - NSError *error = nil; - NSString *string = [NSString stringWithUTF8String:text]; - [pasteBoard clearContents]; - return [pasteBoard setString:string forType:NSPasteboardTypeString]; -} - -const char* getClipboardText() { - NSPasteboard *pasteboard = [NSPasteboard generalPasteboard]; - NSString *text = [pasteboard stringForType:NSPasteboardTypeString]; - return [text UTF8String]; -} - -*/ -import "C" -import ( - "sync" - "unsafe" -) - -var clipboardLock sync.RWMutex - -type macosClipboard struct{} - -func (m macosClipboard) setText(text string) bool { - clipboardLock.Lock() - defer clipboardLock.Unlock() - cText := C.CString(text) - success := C.setClipboardText(cText) - C.free(unsafe.Pointer(cText)) - return bool(success) -} - -func (m macosClipboard) text() (string, bool) { - clipboardLock.RLock() - defer clipboardLock.RUnlock() - clipboardText := C.getClipboardText() - result := C.GoString(clipboardText) - return result, true -} - -func newClipboardImpl() *macosClipboard { - return &macosClipboard{} -} diff --git a/v3/pkg/application/clipboard_ios.go b/v3/pkg/application/clipboard_ios.go deleted file mode 100644 index e887474c6..000000000 --- a/v3/pkg/application/clipboard_ios.go +++ /dev/null @@ -1,33 +0,0 @@ -//go:build ios - -package application - -type iosClipboardImpl struct{} - -func newClipboardImpl() clipboardImpl { - return &iosClipboardImpl{} -} - -func (c *iosClipboardImpl) setText(text string) bool { - // iOS clipboard implementation would go here - return true -} - -func (c *iosClipboardImpl) text() (string, bool) { - // iOS clipboard implementation would go here - return "", false -} - -// SetClipboardText sets the clipboard text on iOS -func (c *ClipboardManager) SetClipboardText(text string) error { - // iOS clipboard implementation would go here - // For now, return nil as a placeholder - return nil -} - -// GetClipboardText gets the clipboard text on iOS -func (c *ClipboardManager) GetClipboardText() (string, error) { - // iOS clipboard implementation would go here - // For now, return empty string - return "", nil -} diff --git a/v3/pkg/application/clipboard_linux.go b/v3/pkg/application/clipboard_linux.go deleted file mode 100644 index cf1366605..000000000 --- a/v3/pkg/application/clipboard_linux.go +++ /dev/null @@ -1,28 +0,0 @@ -//go:build linux && !android && !server - -package application - -import ( - "sync" -) - -var clipboardLock sync.RWMutex - -type linuxClipboard struct{} - -func (m linuxClipboard) setText(text string) bool { - clipboardLock.Lock() - defer clipboardLock.Unlock() - clipboardSet(text) - return true -} - -func (m linuxClipboard) text() (string, bool) { - clipboardLock.RLock() - defer clipboardLock.RUnlock() - return clipboardGet(), true -} - -func newClipboardImpl() *linuxClipboard { - return &linuxClipboard{} -} diff --git a/v3/pkg/application/clipboard_manager.go b/v3/pkg/application/clipboard_manager.go deleted file mode 100644 index abd0b19c1..000000000 --- a/v3/pkg/application/clipboard_manager.go +++ /dev/null @@ -1,32 +0,0 @@ -package application - -// ClipboardManager manages clipboard operations -type ClipboardManager struct { - app *App - clipboard *Clipboard -} - -// newClipboardManager creates a new ClipboardManager instance -func newClipboardManager(app *App) *ClipboardManager { - return &ClipboardManager{ - app: app, - } -} - -// SetText sets text in the clipboard -func (cm *ClipboardManager) SetText(text string) bool { - return cm.getClipboard().SetText(text) -} - -// Text gets text from the clipboard -func (cm *ClipboardManager) Text() (string, bool) { - return cm.getClipboard().Text() -} - -// getClipboard returns the clipboard instance, creating it if needed (lazy initialization) -func (cm *ClipboardManager) getClipboard() *Clipboard { - if cm.clipboard == nil { - cm.clipboard = newClipboard() - } - return cm.clipboard -} diff --git a/v3/pkg/application/clipboard_windows.go b/v3/pkg/application/clipboard_windows.go deleted file mode 100644 index 507eac3da..000000000 --- a/v3/pkg/application/clipboard_windows.go +++ /dev/null @@ -1,29 +0,0 @@ -//go:build windows - -package application - -import ( - "github.com/wailsapp/wails/v3/pkg/w32" - "sync" -) - -type windowsClipboard struct { - lock sync.RWMutex -} - -func (m *windowsClipboard) setText(text string) bool { - m.lock.Lock() - defer m.lock.Unlock() - return w32.SetClipboardText(text) == nil -} - -func (m *windowsClipboard) text() (string, bool) { - m.lock.Lock() - defer m.lock.Unlock() - text, err := w32.GetClipboardText() - return text, err == nil -} - -func newClipboardImpl() *windowsClipboard { - return &windowsClipboard{} -} diff --git a/v3/pkg/application/context.go b/v3/pkg/application/context.go deleted file mode 100644 index 8ed2cb792..000000000 --- a/v3/pkg/application/context.go +++ /dev/null @@ -1,62 +0,0 @@ -package application - -type Context struct { - // contains filtered or unexported fields - data map[string]any -} - -func newContext() *Context { - return &Context{ - data: make(map[string]any), - } -} - -const ( - clickedMenuItem string = "clickedMenuItem" - menuItemIsChecked string = "menuItemIsChecked" - contextMenuData string = "contextMenuData" -) - -func (c *Context) ClickedMenuItem() *MenuItem { - result, exists := c.data[clickedMenuItem] - if !exists { - return nil - } - return result.(*MenuItem) -} - -func (c *Context) IsChecked() bool { - result, exists := c.data[menuItemIsChecked] - if !exists { - return false - } - return result.(bool) -} -func (c *Context) ContextMenuData() string { - result := c.data[contextMenuData] - if result == nil { - return "" - } - str, ok := result.(string) - if !ok { - return "" - } - return str -} - -func (c *Context) withClickedMenuItem(menuItem *MenuItem) *Context { - c.data[clickedMenuItem] = menuItem - return c -} - -func (c *Context) withChecked(checked bool) { - c.data[menuItemIsChecked] = checked -} - -func (c *Context) withContextMenuData(data *ContextMenuData) *Context { - if data == nil { - return c - } - c.data[contextMenuData] = data.Data - return c -} diff --git a/v3/pkg/application/context_application_event.go b/v3/pkg/application/context_application_event.go deleted file mode 100644 index 32f392455..000000000 --- a/v3/pkg/application/context_application_event.go +++ /dev/null @@ -1,106 +0,0 @@ -package application - -import "log" - -var blankApplicationEventContext = &ApplicationEventContext{} - -const ( - CONTEXT_OPENED_FILES = "openedFiles" - CONTEXT_FILENAME = "filename" - CONTEXT_URL = "url" -) - -// ApplicationEventContext is the context of an application event -type ApplicationEventContext struct { - // contains filtered or unexported fields - data map[string]any -} - -// OpenedFiles returns the opened files from the event context if it was set -func (c ApplicationEventContext) OpenedFiles() []string { - files, ok := c.data[CONTEXT_OPENED_FILES] - if !ok { - return nil - } - result, ok := files.([]string) - if !ok { - return nil - } - return result -} - -func (c ApplicationEventContext) setOpenedFiles(files []string) { - c.data[CONTEXT_OPENED_FILES] = files -} - -func (c ApplicationEventContext) setIsDarkMode(mode bool) { - c.data["isDarkMode"] = mode -} - -func (c ApplicationEventContext) getBool(key string) bool { - mode, ok := c.data[key] - if !ok { - return false - } - result, ok := mode.(bool) - if !ok { - return false - } - return result -} - -// IsDarkMode returns true if the event context has a dark mode -func (c ApplicationEventContext) IsDarkMode() bool { - return c.getBool("isDarkMode") -} - -// HasVisibleWindows returns true if the event context has a visible window -func (c ApplicationEventContext) HasVisibleWindows() bool { - return c.getBool("hasVisibleWindows") -} - -func (c *ApplicationEventContext) setData(data map[string]any) { - c.data = data -} - -func (c *ApplicationEventContext) setOpenedWithFile(filepath string) { - c.data[CONTEXT_FILENAME] = filepath -} - -func (c *ApplicationEventContext) setURL(openedWithURL string) { - c.data[CONTEXT_URL] = openedWithURL -} - -// Filename returns the filename from the event context if it was set -func (c ApplicationEventContext) Filename() string { - filename, ok := c.data[CONTEXT_FILENAME] - if !ok { - return "" - } - result, ok := filename.(string) - if !ok { - return "" - } - return result -} - -// URL returns the URL from the event context if it was set -func (c ApplicationEventContext) URL() string { - url, ok := c.data[CONTEXT_URL] - if !ok { - log.Println("URL not found in event context") - return "" - } - result, ok := url.(string) - if !ok { - log.Println("URL not a string in event context") - return "" - } - return result -} - -func newApplicationEventContext() *ApplicationEventContext { - return &ApplicationEventContext{ - data: make(map[string]any), - } -} diff --git a/v3/pkg/application/context_menu_manager.go b/v3/pkg/application/context_menu_manager.go deleted file mode 100644 index 669e8aca5..000000000 --- a/v3/pkg/application/context_menu_manager.go +++ /dev/null @@ -1,54 +0,0 @@ -package application - -// ContextMenuManager manages all context menu operations -type ContextMenuManager struct { - app *App -} - -// newContextMenuManager creates a new ContextMenuManager instance -func newContextMenuManager(app *App) *ContextMenuManager { - return &ContextMenuManager{ - app: app, - } -} - -// New creates a new context menu -func (cmm *ContextMenuManager) New() *ContextMenu { - return &ContextMenu{ - Menu: NewMenu(), - } -} - -// Add adds a context menu (replaces Register for consistency) -func (cmm *ContextMenuManager) Add(name string, menu *ContextMenu) { - cmm.app.contextMenusLock.Lock() - defer cmm.app.contextMenusLock.Unlock() - cmm.app.contextMenus[name] = menu -} - -// Remove removes a context menu by name (replaces Unregister for consistency) -func (cmm *ContextMenuManager) Remove(name string) { - cmm.app.contextMenusLock.Lock() - defer cmm.app.contextMenusLock.Unlock() - delete(cmm.app.contextMenus, name) -} - -// Get retrieves a context menu by name -func (cmm *ContextMenuManager) Get(name string) (*ContextMenu, bool) { - cmm.app.contextMenusLock.RLock() - defer cmm.app.contextMenusLock.RUnlock() - menu, exists := cmm.app.contextMenus[name] - return menu, exists -} - -// GetAll returns all registered context menus as a slice -func (cmm *ContextMenuManager) GetAll() []*ContextMenu { - cmm.app.contextMenusLock.RLock() - defer cmm.app.contextMenusLock.RUnlock() - - result := make([]*ContextMenu, 0, len(cmm.app.contextMenus)) - for _, menu := range cmm.app.contextMenus { - result = append(result, menu) - } - return result -} diff --git a/v3/pkg/application/context_test.go b/v3/pkg/application/context_test.go deleted file mode 100644 index 268ca5af9..000000000 --- a/v3/pkg/application/context_test.go +++ /dev/null @@ -1,120 +0,0 @@ -package application - -import ( - "testing" -) - -func TestNewContext(t *testing.T) { - ctx := newContext() - if ctx == nil { - t.Fatal("newContext() returned nil") - } - if ctx.data == nil { - t.Error("newContext() should initialize data map") - } -} - -func TestContext_ClickedMenuItem_NotExists(t *testing.T) { - ctx := newContext() - result := ctx.ClickedMenuItem() - if result != nil { - t.Error("ClickedMenuItem() should return nil when not set") - } -} - -func TestContext_ClickedMenuItem_Exists(t *testing.T) { - ctx := newContext() - menuItem := &MenuItem{label: "Test"} - ctx.withClickedMenuItem(menuItem) - - result := ctx.ClickedMenuItem() - if result == nil { - t.Fatal("ClickedMenuItem() should return the menu item") - } - if result != menuItem { - t.Error("ClickedMenuItem() should return the same menu item") - } -} - -func TestContext_IsChecked_NotSet(t *testing.T) { - ctx := newContext() - if ctx.IsChecked() { - t.Error("IsChecked() should return false when not set") - } -} - -func TestContext_IsChecked_True(t *testing.T) { - ctx := newContext() - ctx.withChecked(true) - if !ctx.IsChecked() { - t.Error("IsChecked() should return true when set to true") - } -} - -func TestContext_IsChecked_False(t *testing.T) { - ctx := newContext() - ctx.withChecked(false) - if ctx.IsChecked() { - t.Error("IsChecked() should return false when set to false") - } -} - -func TestContext_ContextMenuData_Empty(t *testing.T) { - ctx := newContext() - result := ctx.ContextMenuData() - if result != "" { - t.Errorf("ContextMenuData() should return empty string when not set, got %q", result) - } -} - -func TestContext_ContextMenuData_Exists(t *testing.T) { - ctx := newContext() - data := &ContextMenuData{Data: "test-data"} - ctx.withContextMenuData(data) - - result := ctx.ContextMenuData() - if result != "test-data" { - t.Errorf("ContextMenuData() = %q, want %q", result, "test-data") - } -} - -func TestContext_ContextMenuData_NilData(t *testing.T) { - ctx := newContext() - ctx.withContextMenuData(nil) - - result := ctx.ContextMenuData() - if result != "" { - t.Errorf("ContextMenuData() should return empty string for nil data, got %q", result) - } -} - -func TestContext_ContextMenuData_WrongType(t *testing.T) { - ctx := newContext() - // Manually set wrong type to test type assertion - ctx.data[contextMenuData] = 123 - - result := ctx.ContextMenuData() - if result != "" { - t.Errorf("ContextMenuData() should return empty string for non-string type, got %q", result) - } -} - -func TestContext_WithClickedMenuItem_Chaining(t *testing.T) { - ctx := newContext() - menuItem := &MenuItem{label: "Test"} - - returnedCtx := ctx.withClickedMenuItem(menuItem) - if returnedCtx != ctx { - t.Error("withClickedMenuItem should return the same context for chaining") - } -} - -func TestContext_WithContextMenuData_Chaining(t *testing.T) { - ctx := newContext() - data := &ContextMenuData{Data: "test"} - - returnedCtx := ctx.withContextMenuData(data) - if returnedCtx != ctx { - t.Error("withContextMenuData should return the same context for chaining") - } -} diff --git a/v3/pkg/application/context_window_event.go b/v3/pkg/application/context_window_event.go deleted file mode 100644 index ad4a97a8a..000000000 --- a/v3/pkg/application/context_window_event.go +++ /dev/null @@ -1,79 +0,0 @@ -package application - -var blankWindowEventContext = &WindowEventContext{} - -const ( - droppedFiles = "droppedFiles" - dropTargetDetailsKey = "dropTargetDetails" -) - -type WindowEventContext struct { - // contains filtered or unexported fields - data map[string]any -} - -func (c WindowEventContext) DroppedFiles() []string { - if c.data == nil { - c.data = make(map[string]any) - } - files, ok := c.data[droppedFiles] - if !ok { - return nil - } - result, ok := files.([]string) - if !ok { - return nil - } - return result -} - -func (c WindowEventContext) setDroppedFiles(files []string) { - if c.data == nil { - c.data = make(map[string]any) - } - c.data[droppedFiles] = files -} - -func (c WindowEventContext) setCoordinates(x, y int) { - if c.data == nil { - c.data = make(map[string]any) - } - c.data["x"] = x - c.data["y"] = y -} - -func (c WindowEventContext) setDropTargetDetails(details *DropTargetDetails) { - if c.data == nil { - c.data = make(map[string]any) - } - if details == nil { - c.data[dropTargetDetailsKey] = nil - return - } - c.data[dropTargetDetailsKey] = details -} - -// DropTargetDetails retrieves information about the drop target element. -func (c WindowEventContext) DropTargetDetails() *DropTargetDetails { - if c.data == nil { - c.data = make(map[string]any) - } - details, ok := c.data[dropTargetDetailsKey] - if !ok { - return nil - } - if details == nil { - return nil - } - result, ok := details.(*DropTargetDetails) - if !ok { - return nil - } - return result -} - -func newWindowEventContext() *WindowEventContext { - return &WindowEventContext{ - data: make(map[string]any), - } -} diff --git a/v3/pkg/application/dialog_manager.go b/v3/pkg/application/dialog_manager.go deleted file mode 100644 index 36e5842de..000000000 --- a/v3/pkg/application/dialog_manager.go +++ /dev/null @@ -1,57 +0,0 @@ -package application - -// DialogManager manages dialog-related operations -type DialogManager struct { - app *App -} - -// newDialogManager creates a new DialogManager instance -func newDialogManager(app *App) *DialogManager { - return &DialogManager{ - app: app, - } -} - -// OpenFile creates a file dialog for selecting files -func (dm *DialogManager) OpenFile() *OpenFileDialogStruct { - return newOpenFileDialog() -} - -// OpenFileWithOptions creates a file dialog with options -func (dm *DialogManager) OpenFileWithOptions(options *OpenFileDialogOptions) *OpenFileDialogStruct { - result := newOpenFileDialog() - result.SetOptions(options) - return result -} - -// SaveFile creates a save file dialog -func (dm *DialogManager) SaveFile() *SaveFileDialogStruct { - return newSaveFileDialog() -} - -// SaveFileWithOptions creates a save file dialog with options -func (dm *DialogManager) SaveFileWithOptions(options *SaveFileDialogOptions) *SaveFileDialogStruct { - result := newSaveFileDialog() - result.SetOptions(options) - return result -} - -// Info creates an information dialog -func (dm *DialogManager) Info() *MessageDialog { - return newMessageDialog(InfoDialogType) -} - -// Question creates a question dialog -func (dm *DialogManager) Question() *MessageDialog { - return newMessageDialog(QuestionDialogType) -} - -// Warning creates a warning dialog -func (dm *DialogManager) Warning() *MessageDialog { - return newMessageDialog(WarningDialogType) -} - -// Error creates an error dialog -func (dm *DialogManager) Error() *MessageDialog { - return newMessageDialog(ErrorDialogType) -} diff --git a/v3/pkg/application/dialogs.go b/v3/pkg/application/dialogs.go deleted file mode 100644 index d61f64886..000000000 --- a/v3/pkg/application/dialogs.go +++ /dev/null @@ -1,494 +0,0 @@ -package application - -import ( - "strings" - "sync" -) - -type DialogType int - -var dialogMapID = make(map[uint]struct{}) -var dialogIDLock sync.RWMutex - -func getDialogID() uint { - dialogIDLock.Lock() - defer dialogIDLock.Unlock() - var dialogID uint - for { - if _, ok := dialogMapID[dialogID]; !ok { - dialogMapID[dialogID] = struct{}{} - break - } - dialogID++ - if dialogID == 0 { - panic("no more dialog IDs") - } - } - return dialogID -} - -func freeDialogID(id uint) { - dialogIDLock.Lock() - defer dialogIDLock.Unlock() - delete(dialogMapID, id) -} - -var openFileResponses = make(map[uint]chan string) -var saveFileResponses = make(map[uint]chan string) - -const ( - InfoDialogType DialogType = iota - QuestionDialogType - WarningDialogType - ErrorDialogType -) - -type Button struct { - Label string - IsCancel bool - IsDefault bool - Callback func() -} - -func (b *Button) OnClick(callback func()) *Button { - b.Callback = callback - return b -} - -func (b *Button) SetAsDefault() *Button { - b.IsDefault = true - return b -} - -func (b *Button) SetAsCancel() *Button { - b.IsCancel = true - return b -} - -type messageDialogImpl interface { - show() -} - -type MessageDialogOptions struct { - DialogType DialogType - Title string - Message string - Buttons []*Button - Icon []byte - window Window -} - -type MessageDialog struct { - MessageDialogOptions - - // platform independent - impl messageDialogImpl -} - -var defaultTitles = map[DialogType]string{ - InfoDialogType: "Information", - QuestionDialogType: "Question", - WarningDialogType: "Warning", - ErrorDialogType: "Error", -} - -func newMessageDialog(dialogType DialogType) *MessageDialog { - return &MessageDialog{ - MessageDialogOptions: MessageDialogOptions{ - DialogType: dialogType, - }, - impl: nil, - } -} - -func (d *MessageDialog) SetTitle(title string) *MessageDialog { - d.Title = title - return d -} - -func (d *MessageDialog) Show() { - if d.impl == nil { - d.impl = newDialogImpl(d) - } - InvokeSync(d.impl.show) -} - -func (d *MessageDialog) SetIcon(icon []byte) *MessageDialog { - d.Icon = icon - return d -} - -func (d *MessageDialog) AddButton(s string) *Button { - result := &Button{ - Label: s, - } - d.Buttons = append(d.Buttons, result) - return result -} - -func (d *MessageDialog) AddButtons(buttons []*Button) *MessageDialog { - d.Buttons = buttons - return d -} - -func (d *MessageDialog) AttachToWindow(window Window) *MessageDialog { - d.window = window - return d -} - -func (d *MessageDialog) SetDefaultButton(button *Button) *MessageDialog { - for _, b := range d.Buttons { - b.IsDefault = false - } - button.IsDefault = true - return d -} - -func (d *MessageDialog) SetCancelButton(button *Button) *MessageDialog { - for _, b := range d.Buttons { - b.IsCancel = false - } - button.IsCancel = true - return d -} - -func (d *MessageDialog) SetMessage(message string) *MessageDialog { - d.Message = message - return d -} - -type openFileDialogImpl interface { - show() (chan string, error) -} - -type FileFilter struct { - DisplayName string // Filter information EG: "Image Files (*.jpg, *.png)" - Pattern string // semicolon separated list of extensions, EG: "*.jpg;*.png" -} - -type OpenFileDialogOptions struct { - CanChooseDirectories bool - CanChooseFiles bool - CanCreateDirectories bool - ShowHiddenFiles bool - ResolvesAliases bool - AllowsMultipleSelection bool - HideExtension bool - CanSelectHiddenExtension bool - TreatsFilePackagesAsDirectories bool - AllowsOtherFileTypes bool - Filters []FileFilter - Window Window - - Title string - Message string - ButtonText string - Directory string -} - -type OpenFileDialogStruct struct { - id uint - canChooseDirectories bool - canChooseFiles bool - canCreateDirectories bool - showHiddenFiles bool - resolvesAliases bool - allowsMultipleSelection bool - hideExtension bool - canSelectHiddenExtension bool - treatsFilePackagesAsDirectories bool - allowsOtherFileTypes bool - filters []FileFilter - - title string - message string - buttonText string - directory string - window Window - - impl openFileDialogImpl -} - -func (d *OpenFileDialogStruct) CanChooseFiles(canChooseFiles bool) *OpenFileDialogStruct { - d.canChooseFiles = canChooseFiles - return d -} - -func (d *OpenFileDialogStruct) CanChooseDirectories(canChooseDirectories bool) *OpenFileDialogStruct { - d.canChooseDirectories = canChooseDirectories - return d -} - -func (d *OpenFileDialogStruct) CanCreateDirectories(canCreateDirectories bool) *OpenFileDialogStruct { - d.canCreateDirectories = canCreateDirectories - return d -} - -func (d *OpenFileDialogStruct) AllowsOtherFileTypes(allowsOtherFileTypes bool) *OpenFileDialogStruct { - d.allowsOtherFileTypes = allowsOtherFileTypes - return d -} - -func (d *OpenFileDialogStruct) ShowHiddenFiles(showHiddenFiles bool) *OpenFileDialogStruct { - d.showHiddenFiles = showHiddenFiles - return d -} - -func (d *OpenFileDialogStruct) HideExtension(hideExtension bool) *OpenFileDialogStruct { - d.hideExtension = hideExtension - return d -} - -func (d *OpenFileDialogStruct) TreatsFilePackagesAsDirectories(treatsFilePackagesAsDirectories bool) *OpenFileDialogStruct { - d.treatsFilePackagesAsDirectories = treatsFilePackagesAsDirectories - return d -} - -func (d *OpenFileDialogStruct) AttachToWindow(window Window) *OpenFileDialogStruct { - d.window = window - return d -} - -func (d *OpenFileDialogStruct) ResolvesAliases(resolvesAliases bool) *OpenFileDialogStruct { - d.resolvesAliases = resolvesAliases - return d -} - -func (d *OpenFileDialogStruct) SetTitle(title string) *OpenFileDialogStruct { - d.title = title - return d -} - -func (d *OpenFileDialogStruct) PromptForSingleSelection() (string, error) { - d.allowsMultipleSelection = false - if d.impl == nil { - d.impl = newOpenFileDialogImpl(d) - } - - var result string - selections, err := InvokeSyncWithResultAndError(d.impl.show) - if err == nil { - result = <-selections - } - - return result, err -} - -// AddFilter adds a filter to the dialog. The filter is a display name and a semicolon separated list of extensions. -// EG: AddFilter("Image Files", "*.jpg;*.png") -func (d *OpenFileDialogStruct) AddFilter(displayName, pattern string) *OpenFileDialogStruct { - d.filters = append(d.filters, FileFilter{ - DisplayName: strings.TrimSpace(displayName), - Pattern: strings.TrimSpace(pattern), - }) - return d -} - -func (d *OpenFileDialogStruct) PromptForMultipleSelection() ([]string, error) { - d.allowsMultipleSelection = true - if d.impl == nil { - d.impl = newOpenFileDialogImpl(d) - } - - selections, err := InvokeSyncWithResultAndError(d.impl.show) - if err != nil { - return nil, err - } - - var result []string - for filename := range selections { - result = append(result, filename) - } - - return result, err -} - -func (d *OpenFileDialogStruct) SetMessage(message string) *OpenFileDialogStruct { - d.message = message - return d -} - -func (d *OpenFileDialogStruct) SetButtonText(text string) *OpenFileDialogStruct { - d.buttonText = text - return d -} - -func (d *OpenFileDialogStruct) SetDirectory(directory string) *OpenFileDialogStruct { - d.directory = directory - return d -} - -func (d *OpenFileDialogStruct) CanSelectHiddenExtension(canSelectHiddenExtension bool) *OpenFileDialogStruct { - d.canSelectHiddenExtension = canSelectHiddenExtension - return d -} - -func (d *OpenFileDialogStruct) SetOptions(options *OpenFileDialogOptions) { - d.title = options.Title - d.message = options.Message - d.buttonText = options.ButtonText - d.directory = options.Directory - d.canChooseDirectories = options.CanChooseDirectories - d.canChooseFiles = options.CanChooseFiles - d.canCreateDirectories = options.CanCreateDirectories - d.showHiddenFiles = options.ShowHiddenFiles - d.resolvesAliases = options.ResolvesAliases - d.allowsMultipleSelection = options.AllowsMultipleSelection - d.hideExtension = options.HideExtension - d.canSelectHiddenExtension = options.CanSelectHiddenExtension - d.treatsFilePackagesAsDirectories = options.TreatsFilePackagesAsDirectories - d.allowsOtherFileTypes = options.AllowsOtherFileTypes - d.filters = options.Filters - d.window = options.Window -} - -func newOpenFileDialog() *OpenFileDialogStruct { - return &OpenFileDialogStruct{ - id: getDialogID(), - canChooseDirectories: false, - canChooseFiles: true, - canCreateDirectories: true, - resolvesAliases: false, - } -} - -func newSaveFileDialog() *SaveFileDialogStruct { - return &SaveFileDialogStruct{ - id: getDialogID(), - canCreateDirectories: true, - } -} - -type SaveFileDialogOptions struct { - CanCreateDirectories bool - ShowHiddenFiles bool - CanSelectHiddenExtension bool - AllowOtherFileTypes bool - HideExtension bool - TreatsFilePackagesAsDirectories bool - Title string - Message string - Directory string - Filename string - ButtonText string - Filters []FileFilter - Window Window -} - -type SaveFileDialogStruct struct { - id uint - canCreateDirectories bool - showHiddenFiles bool - canSelectHiddenExtension bool - allowOtherFileTypes bool - hideExtension bool - treatsFilePackagesAsDirectories bool - message string - directory string - filename string - buttonText string - filters []FileFilter - - window Window - - impl saveFileDialogImpl - title string -} - -type saveFileDialogImpl interface { - show() (chan string, error) -} - -func (d *SaveFileDialogStruct) SetOptions(options *SaveFileDialogOptions) { - d.title = options.Title - d.canCreateDirectories = options.CanCreateDirectories - d.showHiddenFiles = options.ShowHiddenFiles - d.canSelectHiddenExtension = options.CanSelectHiddenExtension - d.allowOtherFileTypes = options.AllowOtherFileTypes - d.hideExtension = options.HideExtension - d.treatsFilePackagesAsDirectories = options.TreatsFilePackagesAsDirectories - d.message = options.Message - d.directory = options.Directory - d.filename = options.Filename - d.buttonText = options.ButtonText - d.filters = options.Filters - d.window = options.Window -} - -// AddFilter adds a filter to the dialog. The filter is a display name and a semicolon separated list of extensions. -// EG: AddFilter("Image Files", "*.jpg;*.png") -func (d *SaveFileDialogStruct) AddFilter(displayName, pattern string) *SaveFileDialogStruct { - d.filters = append(d.filters, FileFilter{ - DisplayName: strings.TrimSpace(displayName), - Pattern: strings.TrimSpace(pattern), - }) - return d -} - -func (d *SaveFileDialogStruct) CanCreateDirectories(canCreateDirectories bool) *SaveFileDialogStruct { - d.canCreateDirectories = canCreateDirectories - return d -} - -func (d *SaveFileDialogStruct) CanSelectHiddenExtension(canSelectHiddenExtension bool) *SaveFileDialogStruct { - d.canSelectHiddenExtension = canSelectHiddenExtension - return d -} - -func (d *SaveFileDialogStruct) ShowHiddenFiles(showHiddenFiles bool) *SaveFileDialogStruct { - d.showHiddenFiles = showHiddenFiles - return d -} - -func (d *SaveFileDialogStruct) SetMessage(message string) *SaveFileDialogStruct { - d.message = message - return d -} - -func (d *SaveFileDialogStruct) SetDirectory(directory string) *SaveFileDialogStruct { - d.directory = directory - return d -} - -func (d *SaveFileDialogStruct) AttachToWindow(window Window) *SaveFileDialogStruct { - d.window = window - return d -} - -func (d *SaveFileDialogStruct) PromptForSingleSelection() (string, error) { - if d.impl == nil { - d.impl = newSaveFileDialogImpl(d) - } - - var result string - selections, err := InvokeSyncWithResultAndError(d.impl.show) - if err == nil { - result = <-selections - } - return result, err -} - -func (d *SaveFileDialogStruct) SetButtonText(text string) *SaveFileDialogStruct { - d.buttonText = text - return d -} - -func (d *SaveFileDialogStruct) SetFilename(filename string) *SaveFileDialogStruct { - d.filename = filename - return d -} - -func (d *SaveFileDialogStruct) AllowsOtherFileTypes(allowOtherFileTypes bool) *SaveFileDialogStruct { - d.allowOtherFileTypes = allowOtherFileTypes - return d -} - -func (d *SaveFileDialogStruct) HideExtension(hideExtension bool) *SaveFileDialogStruct { - d.hideExtension = hideExtension - return d -} - -func (d *SaveFileDialogStruct) TreatsFilePackagesAsDirectories(treatsFilePackagesAsDirectories bool) *SaveFileDialogStruct { - d.treatsFilePackagesAsDirectories = treatsFilePackagesAsDirectories - return d -} diff --git a/v3/pkg/application/dialogs_android.go b/v3/pkg/application/dialogs_android.go deleted file mode 100644 index a962dfba0..000000000 --- a/v3/pkg/application/dialogs_android.go +++ /dev/null @@ -1,90 +0,0 @@ -//go:build android - -package application - -// dialogsImpl implements dialogs for Android -type dialogsImpl struct { - // Android-specific fields if needed -} - -func newDialogsImpl() *dialogsImpl { - return &dialogsImpl{} -} - -// Android dialog implementations would use AlertDialog -// These are placeholder implementations for now - -func (d *dialogsImpl) info(id uint, param MessageDialogOptions) { - // TODO: Implement using AlertDialog -} - -func (d *dialogsImpl) warning(id uint, param MessageDialogOptions) { - // TODO: Implement using AlertDialog -} - -func (d *dialogsImpl) error(id uint, param MessageDialogOptions) { - // TODO: Implement using AlertDialog -} - -func (d *dialogsImpl) question(id uint, param MessageDialogOptions) chan bool { - // TODO: Implement using AlertDialog - ch := make(chan bool, 1) - ch <- false - return ch -} - -func (d *dialogsImpl) openFile(id uint, param OpenFileDialogOptions) chan string { - // TODO: Implement using Android file picker intent - ch := make(chan string, 1) - ch <- "" - return ch -} - -func (d *dialogsImpl) openMultipleFiles(id uint, param OpenFileDialogOptions) chan []string { - // TODO: Implement using Android file picker intent - ch := make(chan []string, 1) - ch <- []string{} - return ch -} - -func (d *dialogsImpl) openDirectory(id uint, param OpenFileDialogOptions) chan string { - // TODO: Implement using Android file picker intent - ch := make(chan string, 1) - ch <- "" - return ch -} - -func (d *dialogsImpl) saveFile(id uint, param SaveFileDialogOptions) chan string { - // TODO: Implement using Android file picker intent - ch := make(chan string, 1) - ch <- "" - return ch -} - -type androidDialog struct { - dialog *MessageDialog -} - -func (d *androidDialog) show() { - // TODO: Implement using AlertDialog -} - -func newDialogImpl(d *MessageDialog) *androidDialog { - return &androidDialog{ - dialog: d, - } -} - -func (d *dialogsImpl) show() (chan string, error) { - ch := make(chan string, 1) - ch <- "" - return ch, nil -} - -func newOpenFileDialogImpl(_ *OpenFileDialogStruct) openFileDialogImpl { - return &dialogsImpl{} -} - -func newSaveFileDialogImpl(_ *SaveFileDialogStruct) saveFileDialogImpl { - return &dialogsImpl{} -} diff --git a/v3/pkg/application/dialogs_darwin.go b/v3/pkg/application/dialogs_darwin.go deleted file mode 100644 index 5ed6f4ab6..000000000 --- a/v3/pkg/application/dialogs_darwin.go +++ /dev/null @@ -1,588 +0,0 @@ -//go:build darwin && !ios - -package application - -/* -#cgo CFLAGS: -mmacosx-version-min=10.13 -x objective-c -#cgo LDFLAGS: -framework Cocoa -mmacosx-version-min=10.13 -framework UniformTypeIdentifiers - -#import - -#import -#import "dialogs_darwin_delegate.h" - -extern void openFileDialogCallback(uint id, char* path); -extern void openFileDialogCallbackEnd(uint id); -extern void saveFileDialogCallback(uint id, char* path); -extern void dialogCallback(int id, int buttonPressed); - -static void showAboutBox(char* title, char *message, void *icon, int length) { - - // run on main thread - NSAlert *alert = [[NSAlert alloc] init]; - if (title != NULL) { - [alert setMessageText:[NSString stringWithUTF8String:title]]; - free(title); - } - if (message != NULL) { - [alert setInformativeText:[NSString stringWithUTF8String:message]]; - free(message); - } - if (icon != NULL) { - NSImage *image = [[NSImage alloc] initWithData:[NSData dataWithBytes:icon length:length]]; - [alert setIcon:image]; - } - [alert setAlertStyle:NSAlertStyleInformational]; - [alert runModal]; -} - - -// Create an NSAlert -static void* createAlert(int alertType, char* title, char *message, void *icon, int length) { - NSAlert *alert = [[NSAlert alloc] init]; - [alert setAlertStyle:alertType]; - if (title != NULL) { - [alert setMessageText:[NSString stringWithUTF8String:title]]; - free(title); - } - if (message != NULL) { - [alert setInformativeText:[NSString stringWithUTF8String:message]]; - free(message); - } - if (icon != NULL) { - NSImage *image = [[NSImage alloc] initWithData:[NSData dataWithBytes:icon length:length]]; - [alert setIcon:image]; - } else { - if(alertType == NSAlertStyleCritical || alertType == NSAlertStyleWarning) { - NSImage *image = [NSImage imageNamed:NSImageNameCaution]; - [alert setIcon:image]; - } else { - NSImage *image = [NSImage imageNamed:NSImageNameInfo]; - [alert setIcon:image]; - } - } - return alert; - -} - -static int getButtonNumber(NSModalResponse response) { - int buttonNumber = 0; - if( response == NSAlertFirstButtonReturn ) { - buttonNumber = 0; - } - else if( response == NSAlertSecondButtonReturn ) { - buttonNumber = 1; - } - else if( response == NSAlertThirdButtonReturn ) { - buttonNumber = 2; - } else { - buttonNumber = 3; - } - return buttonNumber; -} - -// Run the dialog -static void dialogRunModal(void *dialog, void *parent, int callBackID) { - NSAlert *alert = (__bridge NSAlert *)dialog; - - // If the parent is NULL, we are running a modal dialog, otherwise attach the alert to the parent - if( parent == NULL ) { - NSModalResponse response = [alert runModal]; - int returnCode = getButtonNumber(response); - dialogCallback(callBackID, returnCode); - } else { - NSWindow *window = (__bridge NSWindow *)parent; - [alert beginSheetModalForWindow:window completionHandler:^(NSModalResponse response) { - int returnCode = getButtonNumber(response); - dialogCallback(callBackID, returnCode); - }]; - } -} - -// Release the dialog -static void releaseDialog(void *dialog) { - NSAlert *alert = (__bridge NSAlert *)dialog; - [alert release]; -} - -// Add a button to the dialog -static void alertAddButton(void *dialog, char *label, bool isDefault, bool isCancel) { - NSAlert *alert = (__bridge NSAlert *)dialog; - NSButton *button = [alert addButtonWithTitle:[NSString stringWithUTF8String:label]]; - free(label); - if( isDefault ) { - [button setKeyEquivalent:@"\r"]; - } else if( isCancel ) { - [button setKeyEquivalent:@"\033"]; - } else { - [button setKeyEquivalent:@""]; - } -} - -static void processOpenFileDialogResults(NSOpenPanel *panel, NSInteger result, uint dialogID) { - const char *path = NULL; - if (result == NSModalResponseOK) { - NSArray *urls = [panel URLs]; - if ([urls count] > 0) { - NSArray *urls = [panel URLs]; - for (NSURL *url in urls) { - path = [[url path] UTF8String]; - openFileDialogCallback(dialogID, (char *)path); - } - } else { - NSURL *url = [panel URL]; - path = [[url path] UTF8String]; - openFileDialogCallback(dialogID, (char *)path); - } - } - openFileDialogCallbackEnd(dialogID); -} - - -static void showOpenFileDialog(unsigned int dialogID, - bool canChooseFiles, - bool canChooseDirectories, - bool canCreateDirectories, - bool showHiddenFiles, - bool allowsMultipleSelection, - bool resolvesAliases, - bool hideExtension, - bool treatsFilePackagesAsDirectories, - bool allowsOtherFileTypes, - char *filterPatterns, - unsigned int filterPatternsCount, - char* message, - char* directory, - char* buttonText, - - void *window) { - - // run on main thread - NSOpenPanel *panel = [NSOpenPanel openPanel]; - - // print out filterPatterns if length > 0 - if (filterPatternsCount > 0) { - OpenPanelDelegate *delegate = [[OpenPanelDelegate alloc] init]; - [panel setDelegate:delegate]; - // Initialise NSString with bytes and UTF8 encoding - NSString *filterPatternsString = [[NSString alloc] initWithBytes:filterPatterns length:filterPatternsCount encoding:NSUTF8StringEncoding]; - // Convert NSString to NSArray - delegate.allowedExtensions = [filterPatternsString componentsSeparatedByString:@";"]; - - // Use UTType if macOS 11 or higher to add file filters -#if MAC_OS_X_VERSION_MAX_ALLOWED >= 110000 - if (@available(macOS 11, *)) { - NSMutableArray *filterTypes = [NSMutableArray array]; - // Iterate the filtertypes, create uti's that are limited to the file extensions then add - for (NSString *filterType in delegate.allowedExtensions) { - [filterTypes addObject:[UTType typeWithFilenameExtension:filterType]]; - } - [panel setAllowedContentTypes:filterTypes]; - } -#else - [panel setAllowedFileTypes:delegate.allowedExtensions]; -#endif - - // Free the memory - free(filterPatterns); - } - - - if (message != NULL) { - [panel setMessage:[NSString stringWithUTF8String:message]]; - free(message); - } - - if (directory != NULL) { - [panel setDirectoryURL:[NSURL fileURLWithPath:[NSString stringWithUTF8String:directory]]]; - free(directory); - } - - if (buttonText != NULL) { - [panel setPrompt:[NSString stringWithUTF8String:buttonText]]; - free(buttonText); - } - - [panel setCanChooseFiles:canChooseFiles]; - [panel setCanChooseDirectories:canChooseDirectories]; - [panel setCanCreateDirectories:canCreateDirectories]; - [panel setShowsHiddenFiles:showHiddenFiles]; - [panel setAllowsMultipleSelection:allowsMultipleSelection]; - [panel setResolvesAliases:resolvesAliases]; - [panel setExtensionHidden:hideExtension]; - [panel setTreatsFilePackagesAsDirectories:treatsFilePackagesAsDirectories]; - [panel setAllowsOtherFileTypes:allowsOtherFileTypes]; - - - - if (window != NULL) { - [panel beginSheetModalForWindow:(__bridge NSWindow *)window completionHandler:^(NSInteger result) { - processOpenFileDialogResults(panel, result, dialogID); - }]; - } else { - [panel beginWithCompletionHandler:^(NSInteger result) { - processOpenFileDialogResults(panel, result, dialogID); - }]; - } -} - -static void showSaveFileDialog(unsigned int dialogID, - bool canCreateDirectories, - bool showHiddenFiles, - bool canSelectHiddenExtension, - bool hideExtension, - bool treatsFilePackagesAsDirectories, - bool allowOtherFileTypes, - char* message, - char* directory, - char* buttonText, - char* filename, - void *window) { - - NSSavePanel *panel = [NSSavePanel savePanel]; - - if (message != NULL) { - [panel setMessage:[NSString stringWithUTF8String:message]]; - free(message); - } - - if (directory != NULL) { - [panel setDirectoryURL:[NSURL fileURLWithPath:[NSString stringWithUTF8String:directory]]]; - free(directory); - } - - if (filename != NULL) { - [panel setNameFieldStringValue:[NSString stringWithUTF8String:filename]]; - free(filename); - } - - if (buttonText != NULL) { - [panel setPrompt:[NSString stringWithUTF8String:buttonText]]; - free(buttonText); - } - - [panel setCanCreateDirectories:canCreateDirectories]; - [panel setShowsHiddenFiles:showHiddenFiles]; - [panel setCanSelectHiddenExtension:canSelectHiddenExtension]; - [panel setExtensionHidden:hideExtension]; - [panel setTreatsFilePackagesAsDirectories:treatsFilePackagesAsDirectories]; - [panel setAllowsOtherFileTypes:allowOtherFileTypes]; - - if (window != NULL) { - [panel beginSheetModalForWindow:(__bridge NSWindow *)window completionHandler:^(NSInteger result) { - const char *path = NULL; - if (result == NSModalResponseOK) { - NSURL *url = [panel URL]; - path = [[url path] UTF8String]; - } - saveFileDialogCallback(dialogID, (char *)path); - }]; - } else { - [panel beginWithCompletionHandler:^(NSInteger result) { - const char *path = NULL; - if (result == NSModalResponseOK) { - NSURL *url = [panel URL]; - path = [[url path] UTF8String]; - } - saveFileDialogCallback(dialogID, (char *)path); - }]; - } -} - -*/ -import "C" -import ( - "strings" - "sync" - "unsafe" -) - -const NSAlertStyleWarning = C.int(0) -const NSAlertStyleInformational = C.int(1) -const NSAlertStyleCritical = C.int(2) - -var alertTypeMap = map[DialogType]C.int{ - WarningDialogType: NSAlertStyleWarning, - InfoDialogType: NSAlertStyleInformational, - ErrorDialogType: NSAlertStyleCritical, - QuestionDialogType: NSAlertStyleInformational, -} - -type dialogResultCallback func(int) - -var ( - callbacks = make(map[int]dialogResultCallback) - mutex = &sync.Mutex{} -) - -func addDialogCallback(callback dialogResultCallback) int { - mutex.Lock() - defer mutex.Unlock() - - // Find the first free integer key - var id int - for { - if _, exists := callbacks[id]; !exists { - break - } - id++ - } - - // Save the function in the map using the integer key - callbacks[id] = callback - - // Return the key - return id -} - -func removeDialogCallback(id int) { - mutex.Lock() - defer mutex.Unlock() - delete(callbacks, id) -} - -//export dialogCallback -func dialogCallback(id C.int, buttonPressed C.int) { - mutex.Lock() - callback, exists := callbacks[int(id)] - mutex.Unlock() - - if !exists { - return - } - - // Call the function with the button number - callback(int(buttonPressed)) // Replace nil with the actual slice of buttons -} - -func (m *macosApp) showAboutDialog(title string, message string, icon []byte) { - var iconData unsafe.Pointer - if icon != nil { - iconData = unsafe.Pointer(&icon[0]) - } - InvokeAsync(func() { - C.showAboutBox(C.CString(title), C.CString(message), iconData, C.int(len(icon))) - }) -} - -type macosDialog struct { - dialog *MessageDialog - - nsDialog unsafe.Pointer -} - -func (m *macosDialog) show() { - InvokeAsync(func() { - - // Mac can only have 4 Buttons on a dialog - if len(m.dialog.Buttons) > 4 { - m.dialog.Buttons = m.dialog.Buttons[:4] - } - - if m.nsDialog != nil { - C.releaseDialog(m.nsDialog) - } - var title *C.char - if m.dialog.Title != "" { - title = C.CString(m.dialog.Title) - } - var message *C.char - if m.dialog.Message != "" { - message = C.CString(m.dialog.Message) - } - var iconData unsafe.Pointer - var iconLength C.int - if len(m.dialog.Icon) > 0 { - iconData = unsafe.Pointer(&m.dialog.Icon[0]) - iconLength = C.int(len(m.dialog.Icon)) - } else { - // if it's an error, use the application Icon - if m.dialog.DialogType == ErrorDialogType { - if len(globalApplication.options.Icon) > 0 { - iconData = unsafe.Pointer(&globalApplication.options.Icon[0]) - iconLength = C.int(len(globalApplication.options.Icon)) - } - } - } - var parent unsafe.Pointer - if m.dialog.window != nil { - // get NSWindow from window - parent = m.dialog.window.NativeWindow() - } - - alertType, ok := alertTypeMap[m.dialog.DialogType] - if !ok { - alertType = C.NSAlertStyleInformational - } - - m.nsDialog = C.createAlert(alertType, title, message, iconData, iconLength) - - // Reverse the Buttons so that the default is on the right - reversedButtons := make([]*Button, len(m.dialog.Buttons)) - var count = 0 - for i := len(m.dialog.Buttons) - 1; i >= 0; i-- { - button := m.dialog.Buttons[i] - C.alertAddButton(m.nsDialog, C.CString(button.Label), C.bool(button.IsDefault), C.bool(button.IsCancel)) - reversedButtons[count] = m.dialog.Buttons[i] - count++ - } - - var callBackID int - callBackID = addDialogCallback(func(buttonPressed int) { - if len(m.dialog.Buttons) > buttonPressed { - button := reversedButtons[buttonPressed] - if button.Callback != nil { - button.Callback() - } - } - removeDialogCallback(callBackID) - }) - - C.dialogRunModal(m.nsDialog, parent, C.int(callBackID)) - - }) - -} - -func newDialogImpl(d *MessageDialog) *macosDialog { - return &macosDialog{ - dialog: d, - } -} - -type macosOpenFileDialog struct { - dialog *OpenFileDialogStruct -} - -func newOpenFileDialogImpl(d *OpenFileDialogStruct) *macosOpenFileDialog { - return &macosOpenFileDialog{ - dialog: d, - } -} - -func toCString(s string) *C.char { - if s == "" { - return nil - } - return C.CString(s) -} - -func (m *macosOpenFileDialog) show() (chan string, error) { - openFileResponses[m.dialog.id] = make(chan string) - nsWindow := unsafe.Pointer(nil) - if m.dialog.window != nil { - // get NSWindow from window - nsWindow = m.dialog.window.NativeWindow() - } - - // Massage filter patterns into macOS format - // We iterate all filter patterns, tidy them up and then join them with a semicolon - // This should produce a single string of extensions like "png;jpg;gif" - var filterPatterns string - if len(m.dialog.filters) > 0 { - var allPatterns []string - for _, filter := range m.dialog.filters { - patternComponents := strings.Split(filter.Pattern, ";") - for i, component := range patternComponents { - filterPattern := strings.TrimSpace(component) - filterPattern = strings.TrimPrefix(filterPattern, "*.") - patternComponents[i] = filterPattern - } - allPatterns = append(allPatterns, strings.Join(patternComponents, ";")) - } - filterPatterns = strings.Join(allPatterns, ";") - } - C.showOpenFileDialog(C.uint(m.dialog.id), - C.bool(m.dialog.canChooseFiles), - C.bool(m.dialog.canChooseDirectories), - C.bool(m.dialog.canCreateDirectories), - C.bool(m.dialog.showHiddenFiles), - C.bool(m.dialog.allowsMultipleSelection), - C.bool(m.dialog.resolvesAliases), - C.bool(m.dialog.hideExtension), - C.bool(m.dialog.treatsFilePackagesAsDirectories), - C.bool(m.dialog.allowsOtherFileTypes), - toCString(filterPatterns), - C.uint(len(filterPatterns)), - toCString(m.dialog.message), - toCString(m.dialog.directory), - toCString(m.dialog.buttonText), - nsWindow) - - return openFileResponses[m.dialog.id], nil -} - -//export openFileDialogCallback -func openFileDialogCallback(cid C.uint, cpath *C.char) { - path := C.GoString(cpath) - id := uint(cid) - channel, ok := openFileResponses[id] - if ok { - channel <- path - } else { - panic("No channel found for open file dialog") - } -} - -//export openFileDialogCallbackEnd -func openFileDialogCallbackEnd(cid C.uint) { - id := uint(cid) - channel, ok := openFileResponses[id] - if ok { - close(channel) - delete(openFileResponses, id) - freeDialogID(id) - } else { - panic("No channel found for open file dialog") - } -} - -type macosSaveFileDialog struct { - dialog *SaveFileDialogStruct -} - -func newSaveFileDialogImpl(d *SaveFileDialogStruct) *macosSaveFileDialog { - return &macosSaveFileDialog{ - dialog: d, - } -} - -func (m *macosSaveFileDialog) show() (chan string, error) { - saveFileResponses[m.dialog.id] = make(chan string) - nsWindow := unsafe.Pointer(nil) - if m.dialog.window != nil { - // get NSWindow from window - nsWindow = m.dialog.window.NativeWindow() - } - C.showSaveFileDialog(C.uint(m.dialog.id), - C.bool(m.dialog.canCreateDirectories), - C.bool(m.dialog.showHiddenFiles), - C.bool(m.dialog.canSelectHiddenExtension), - C.bool(m.dialog.hideExtension), - C.bool(m.dialog.treatsFilePackagesAsDirectories), - C.bool(m.dialog.allowOtherFileTypes), - toCString(m.dialog.message), - toCString(m.dialog.directory), - toCString(m.dialog.buttonText), - toCString(m.dialog.filename), - nsWindow) - return saveFileResponses[m.dialog.id], nil -} - -//export saveFileDialogCallback -func saveFileDialogCallback(cid C.uint, cpath *C.char) { - // Covert the path to a string - path := C.GoString(cpath) - id := uint(cid) - // put response on channel - channel, ok := saveFileResponses[id] - if ok { - channel <- path - close(channel) - delete(saveFileResponses, id) - freeDialogID(id) - - } else { - panic("No channel found for save file dialog") - } -} diff --git a/v3/pkg/application/dialogs_darwin_delegate.h b/v3/pkg/application/dialogs_darwin_delegate.h deleted file mode 100644 index 7674b3725..000000000 --- a/v3/pkg/application/dialogs_darwin_delegate.h +++ /dev/null @@ -1,18 +0,0 @@ -//go:build darwin && !ios - -#ifndef _DIALOGS_DELEGATE_H_ -#define _DIALOGS_DELEGATE_H_ - -#import - -// Conditionally import UniformTypeIdentifiers based on OS version -#if __MAC_OS_X_VERSION_MAX_ALLOWED >= 110000 -#import -#endif - -// OpenPanel delegate to handle file filtering -@interface OpenPanelDelegate : NSObject -@property (nonatomic, strong) NSArray *allowedExtensions; -@end - -#endif \ No newline at end of file diff --git a/v3/pkg/application/dialogs_darwin_delegate.m b/v3/pkg/application/dialogs_darwin_delegate.m deleted file mode 100644 index 1f26b5507..000000000 --- a/v3/pkg/application/dialogs_darwin_delegate.m +++ /dev/null @@ -1,38 +0,0 @@ -//go:build darwin && !ios - -#import "dialogs_darwin_delegate.h" - -// Override shouldEnableURL -@implementation OpenPanelDelegate -- (BOOL)panel:(id)sender shouldEnableURL:(NSURL *)url { - if (url == nil) { - return NO; - } - - NSFileManager *fileManager = [NSFileManager defaultManager]; - BOOL isDirectory = NO; - if ([fileManager fileExistsAtPath:url.path isDirectory:&isDirectory] && isDirectory) { - return YES; - } - - // If no extensions specified, allow all files - if (self.allowedExtensions == nil || [self.allowedExtensions count] == 0) { - return YES; - } - - NSString *extension = [url.pathExtension lowercaseString]; - if (extension == nil || [extension isEqualToString:@""]) { - return NO; - } - - // Check if the extension is in our allowed list (case insensitive) - for (NSString *allowedExt in self.allowedExtensions) { - if ([[allowedExt lowercaseString] isEqualToString:extension]) { - return YES; - } - } - - return NO; -} - -@end diff --git a/v3/pkg/application/dialogs_ios.go b/v3/pkg/application/dialogs_ios.go deleted file mode 100644 index 5caeed71e..000000000 --- a/v3/pkg/application/dialogs_ios.go +++ /dev/null @@ -1,90 +0,0 @@ -//go:build ios - -package application - -// dialogsImpl implements dialogs for iOS -type dialogsImpl struct { - // iOS-specific fields if needed -} - -func newDialogsImpl() *dialogsImpl { - return &dialogsImpl{} -} - -// iOS dialog implementations would use UIAlertController -// These are placeholder implementations for now - -func (d *dialogsImpl) info(id uint, param MessageDialogOptions) { - // TODO: Implement using UIAlertController -} - -func (d *dialogsImpl) warning(id uint, param MessageDialogOptions) { - // TODO: Implement using UIAlertController -} - -func (d *dialogsImpl) error(id uint, param MessageDialogOptions) { - // TODO: Implement using UIAlertController -} - -func (d *dialogsImpl) question(id uint, param MessageDialogOptions) chan bool { - // TODO: Implement using UIAlertController - ch := make(chan bool, 1) - ch <- false - return ch -} - -func (d *dialogsImpl) openFile(id uint, param OpenFileDialogOptions) chan string { - // TODO: Implement using UIDocumentPickerViewController - ch := make(chan string, 1) - ch <- "" - return ch -} - -func (d *dialogsImpl) openMultipleFiles(id uint, param OpenFileDialogOptions) chan []string { - // TODO: Implement using UIDocumentPickerViewController - ch := make(chan []string, 1) - ch <- []string{} - return ch -} - -func (d *dialogsImpl) openDirectory(id uint, param OpenFileDialogOptions) chan string { - // TODO: Implement using UIDocumentPickerViewController - ch := make(chan string, 1) - ch <- "" - return ch -} - -func (d *dialogsImpl) saveFile(id uint, param SaveFileDialogOptions) chan string { - // TODO: Implement using UIDocumentPickerViewController - ch := make(chan string, 1) - ch <- "" - return ch -} - -type iosDialog struct { - dialog *MessageDialog -} - -func (d *iosDialog) show() { - // TODO: Implement using UIAlertController -} - -func newDialogImpl(d *MessageDialog) *iosDialog { - return &iosDialog{ - dialog: d, - } -} - -func (d *dialogsImpl) show() (chan string, error) { - ch := make(chan string, 1) - ch <- "" - return ch, nil -} - -func newOpenFileDialogImpl(_ *OpenFileDialogStruct) openFileDialogImpl { - return &dialogsImpl{} -} - -func newSaveFileDialogImpl(_ *SaveFileDialogStruct) saveFileDialogImpl { - return &dialogsImpl{} -} \ No newline at end of file diff --git a/v3/pkg/application/dialogs_linux.go b/v3/pkg/application/dialogs_linux.go deleted file mode 100644 index a6025d526..000000000 --- a/v3/pkg/application/dialogs_linux.go +++ /dev/null @@ -1,87 +0,0 @@ -//go:build linux && !android && !server - -package application - -func (a *linuxApp) showAboutDialog(title string, message string, icon []byte) { - window, _ := globalApplication.Window.GetByID(a.getCurrentWindowID()) - var parent uintptr - if window != nil { - nativeWindow := window.NativeWindow() - if nativeWindow != nil { - parent = uintptr(nativeWindow) - } - } - about := newMessageDialog(InfoDialogType) - about.SetTitle(title). - SetMessage(message). - SetIcon(icon) - InvokeAsync(func() { - runQuestionDialog( - pointer(parent), - about, - ) - }) -} - -type linuxDialog struct { - dialog *MessageDialog -} - -func (m *linuxDialog) show() { - windowId := getNativeApplication().getCurrentWindowID() - window, _ := globalApplication.Window.GetByID(windowId) - var parent uintptr - if window != nil { - nativeWindow := window.NativeWindow() - if nativeWindow != nil { - parent = uintptr(nativeWindow) - } - } - - go func() { - response := runQuestionDialog(pointer(parent), m.dialog) - if response >= 0 && response < len(m.dialog.Buttons) { - button := m.dialog.Buttons[response] - if button.Callback != nil { - go func() { - defer handlePanic() - button.Callback() - }() - } - } - }() -} - -func newDialogImpl(d *MessageDialog) *linuxDialog { - return &linuxDialog{ - dialog: d, - } -} - -type linuxOpenFileDialog struct { - dialog *OpenFileDialogStruct -} - -func newOpenFileDialogImpl(d *OpenFileDialogStruct) *linuxOpenFileDialog { - return &linuxOpenFileDialog{ - dialog: d, - } -} - -func (m *linuxOpenFileDialog) show() (chan string, error) { - return runOpenFileDialog(m.dialog) -} - -type linuxSaveFileDialog struct { - dialog *SaveFileDialogStruct -} - -func newSaveFileDialogImpl(d *SaveFileDialogStruct) *linuxSaveFileDialog { - return &linuxSaveFileDialog{ - dialog: d, - } -} - -func (m *linuxSaveFileDialog) show() (chan string, error) { - return runSaveFileDialog(m.dialog) -} diff --git a/v3/pkg/application/dialogs_test.go b/v3/pkg/application/dialogs_test.go deleted file mode 100644 index 60a923cb2..000000000 --- a/v3/pkg/application/dialogs_test.go +++ /dev/null @@ -1,223 +0,0 @@ -package application - -import ( - "testing" -) - -func TestGetDialogID(t *testing.T) { - // Get first dialog ID - id1 := getDialogID() - - // Get second dialog ID - should be different - id2 := getDialogID() - if id1 == id2 { - t.Error("getDialogID should return unique IDs") - } - - // Free first ID - freeDialogID(id1) - - // Get another ID - should recycle the freed id1 or be unique from id2 - id3 := getDialogID() - if id3 == id2 { - t.Error("getDialogID should not return the same ID as an active dialog") - } - // Verify recycling behavior: id3 should either be id1 (recycled) or a new unique ID - if id3 != id1 && id3 <= id2 { - t.Errorf("getDialogID returned unexpected ID: got %d, expected recycled %d or new > %d", id3, id1, id2) - } - - // Cleanup - freeDialogID(id2) - freeDialogID(id3) -} - -func TestFreeDialogID(t *testing.T) { - id := getDialogID() - freeDialogID(id) - - // Should be able to get the same ID again after freeing - newID := getDialogID() - freeDialogID(newID) - // Just verify it doesn't panic -} - -func TestButton_OnClick(t *testing.T) { - button := &Button{Label: "Test"} - called := false - - result := button.OnClick(func() { - called = true - }) - - // Should return the same button for chaining - if result != button { - t.Error("OnClick should return the same button") - } - - // Callback should be set - if button.Callback == nil { - t.Error("Callback should be set") - } - - // Call the callback - button.Callback() - if !called { - t.Error("Callback should have been called") - } -} - -func TestButton_SetAsDefault(t *testing.T) { - button := &Button{Label: "Test"} - - result := button.SetAsDefault() - - // Should return the same button for chaining - if result != button { - t.Error("SetAsDefault should return the same button") - } - - if !button.IsDefault { - t.Error("IsDefault should be true") - } -} - -func TestButton_SetAsCancel(t *testing.T) { - button := &Button{Label: "Test"} - - result := button.SetAsCancel() - - // Should return the same button for chaining - if result != button { - t.Error("SetAsCancel should return the same button") - } - - if !button.IsCancel { - t.Error("IsCancel should be true") - } -} - -func TestButton_Chaining(t *testing.T) { - button := &Button{Label: "OK"} - - button.SetAsDefault().SetAsCancel().OnClick(func() {}) - - if !button.IsDefault { - t.Error("IsDefault should be true after chaining") - } - if !button.IsCancel { - t.Error("IsCancel should be true after chaining") - } - if button.Callback == nil { - t.Error("Callback should be set after chaining") - } -} - -func TestDialogType_Constants(t *testing.T) { - // Verify dialog type constants are distinct - types := []DialogType{InfoDialogType, QuestionDialogType, WarningDialogType, ErrorDialogType} - seen := make(map[DialogType]bool) - - for _, dt := range types { - if seen[dt] { - t.Errorf("DialogType %d is duplicated", dt) - } - seen[dt] = true - } -} - -func TestMessageDialogOptions_Fields(t *testing.T) { - opts := MessageDialogOptions{ - DialogType: InfoDialogType, - Title: "Test Title", - Message: "Test Message", - Buttons: []*Button{{Label: "OK"}}, - Icon: []byte{1, 2, 3}, - } - - if opts.DialogType != InfoDialogType { - t.Error("DialogType not set correctly") - } - if opts.Title != "Test Title" { - t.Error("Title not set correctly") - } - if opts.Message != "Test Message" { - t.Error("Message not set correctly") - } - if len(opts.Buttons) != 1 { - t.Error("Buttons not set correctly") - } - if len(opts.Icon) != 3 { - t.Error("Icon not set correctly") - } -} - -func TestFileFilter_Fields(t *testing.T) { - filter := FileFilter{ - DisplayName: "Image Files (*.jpg, *.png)", - Pattern: "*.jpg;*.png", - } - - if filter.DisplayName != "Image Files (*.jpg, *.png)" { - t.Error("DisplayName not set correctly") - } - if filter.Pattern != "*.jpg;*.png" { - t.Error("Pattern not set correctly") - } -} - -func TestOpenFileDialogOptions_Fields(t *testing.T) { - opts := OpenFileDialogOptions{ - CanChooseDirectories: true, - CanChooseFiles: true, - CanCreateDirectories: true, - ShowHiddenFiles: true, - ResolvesAliases: true, - AllowsMultipleSelection: true, - Title: "Open", - Message: "Select a file", - ButtonText: "Choose", - Directory: "/home", - Filters: []FileFilter{ - {DisplayName: "All Files", Pattern: "*"}, - }, - } - - if !opts.CanChooseDirectories { - t.Error("CanChooseDirectories not set correctly") - } - if !opts.CanChooseFiles { - t.Error("CanChooseFiles not set correctly") - } - if opts.Title != "Open" { - t.Error("Title not set correctly") - } - if len(opts.Filters) != 1 { - t.Error("Filters not set correctly") - } -} - -func TestSaveFileDialogOptions_Fields(t *testing.T) { - opts := SaveFileDialogOptions{ - CanCreateDirectories: true, - ShowHiddenFiles: true, - Title: "Save", - Message: "Save as", - Directory: "/home", - Filename: "file.txt", - ButtonText: "Save", - Filters: []FileFilter{ - {DisplayName: "Text Files", Pattern: "*.txt"}, - }, - } - - if !opts.CanCreateDirectories { - t.Error("CanCreateDirectories not set correctly") - } - if opts.Title != "Save" { - t.Error("Title not set correctly") - } - if opts.Filename != "file.txt" { - t.Error("Filename not set correctly") - } -} diff --git a/v3/pkg/application/dialogs_windows.go b/v3/pkg/application/dialogs_windows.go deleted file mode 100644 index 73084d098..000000000 --- a/v3/pkg/application/dialogs_windows.go +++ /dev/null @@ -1,275 +0,0 @@ -//go:build windows - -package application - -import ( - "path/filepath" - "strings" - - "github.com/wailsapp/wails/v3/internal/go-common-file-dialog/cfd" - "github.com/wailsapp/wails/v3/pkg/w32" - "golang.org/x/sys/windows" -) - -func (m *windowsApp) showAboutDialog(title string, message string, _ []byte) { - about := newDialogImpl(&MessageDialog{ - MessageDialogOptions: MessageDialogOptions{ - DialogType: InfoDialogType, - Title: title, - Message: message, - }, - }) - about.UseAppIcon = true - about.show() -} - -type windowsDialog struct { - dialog *MessageDialog - - //dialogImpl unsafe.Pointer - UseAppIcon bool -} - -func (m *windowsDialog) show() { - - title := w32.MustStringToUTF16Ptr(m.dialog.Title) - message := w32.MustStringToUTF16Ptr(m.dialog.Message) - flags := calculateMessageDialogFlags(m.dialog.MessageDialogOptions) - var button int32 - var err error - - var parentWindow uintptr - if m.dialog.window != nil { - nativeWindow := m.dialog.window.NativeWindow() - if nativeWindow != nil { - parentWindow = uintptr(nativeWindow) - } - } - - if m.UseAppIcon || m.dialog.Icon != nil { - // 3 is the application icon - button, err = w32.MessageBoxWithIcon(parentWindow, message, title, 3, windows.MB_OK|windows.MB_USERICON) - if err != nil { - globalApplication.handleFatalError(err) - } - } else { - button, err = windows.MessageBox(windows.HWND(parentWindow), message, title, flags|windows.MB_SYSTEMMODAL) - if err != nil { - globalApplication.handleFatalError(err) - } - } - // This maps MessageBox return values to strings - responses := []string{"", "Ok", "Cancel", "Abort", "Retry", "Ignore", "Yes", "No", "", "", "Try Again", "Continue"} - result := "Error" - if int(button) < len(responses) { - result = responses[button] - } - // Check if there's a callback for the button pressed - for _, buttonInDialog := range m.dialog.Buttons { - if buttonInDialog.Label == result { - if buttonInDialog.Callback != nil { - buttonInDialog.Callback() - } - } - } -} - -func newDialogImpl(d *MessageDialog) *windowsDialog { - return &windowsDialog{ - dialog: d, - } -} - -type windowOpenFileDialog struct { - dialog *OpenFileDialogStruct -} - -func newOpenFileDialogImpl(d *OpenFileDialogStruct) *windowOpenFileDialog { - return &windowOpenFileDialog{ - dialog: d, - } -} - -func getDefaultFolder(folder string) (string, error) { - if folder == "" { - return "", nil - } - return filepath.Abs(folder) -} - -func (m *windowOpenFileDialog) show() (chan string, error) { - - defaultFolder, err := getDefaultFolder(m.dialog.directory) - if err != nil { - return nil, err - } - - config := cfd.DialogConfig{ - Title: m.dialog.title, - Role: "PickFolder", - FileFilters: convertFilters(m.dialog.filters), - Folder: defaultFolder, - } - - var result []string - if m.dialog.allowsMultipleSelection && !m.dialog.canChooseDirectories { - temp, err := showCfdDialog( - func() (cfd.Dialog, error) { - return cfd.NewOpenMultipleFilesDialog(config) - }, true, m.dialog.window) - if err != nil { - return nil, err - } - result = temp.([]string) - } else { - if m.dialog.canChooseDirectories { - temp, err := showCfdDialog( - func() (cfd.Dialog, error) { - return cfd.NewSelectFolderDialog(config) - }, false, m.dialog.window) - if err != nil { - return nil, err - } - result = []string{temp.(string)} - } else { - temp, err := showCfdDialog( - func() (cfd.Dialog, error) { - return cfd.NewOpenFileDialog(config) - }, false, m.dialog.window) - if err != nil { - return nil, err - } - result = []string{temp.(string)} - } - } - - files := make(chan string) - go func() { - defer handlePanic() - for _, file := range result { - files <- file - } - close(files) - }() - return files, nil -} - -type windowSaveFileDialog struct { - dialog *SaveFileDialogStruct -} - -func newSaveFileDialogImpl(d *SaveFileDialogStruct) *windowSaveFileDialog { - return &windowSaveFileDialog{ - dialog: d, - } -} - -func (m *windowSaveFileDialog) show() (chan string, error) { - files := make(chan string) - defaultFolder, err := getDefaultFolder(m.dialog.directory) - if err != nil { - close(files) - return files, err - } - - config := cfd.DialogConfig{ - Title: m.dialog.title, - Role: "SaveFile", - FileFilters: convertFilters(m.dialog.filters), - FileName: m.dialog.filename, - Folder: defaultFolder, - } - - // Original PR for v2 by @almas1992: https://github.com/wailsapp/wails/pull/3205 - if len(m.dialog.filters) > 0 { - config.DefaultExtension = strings.TrimPrefix(strings.Split(m.dialog.filters[0].Pattern, ";")[0], "*") - } - - result, err := showCfdDialog( - func() (cfd.Dialog, error) { - return cfd.NewSaveFileDialog(config) - }, false, m.dialog.window) - if err != nil { - close(files) - return files, err - } - go func() { - defer handlePanic() - f, ok := result.(string) - if ok { - files <- f - } - close(files) - }() - return files, err -} - -func calculateMessageDialogFlags(options MessageDialogOptions) uint32 { - var flags uint32 - - switch options.DialogType { - case InfoDialogType: - flags = windows.MB_OK | windows.MB_ICONINFORMATION - case ErrorDialogType: - flags = windows.MB_ICONERROR | windows.MB_OK - case QuestionDialogType: - flags = windows.MB_YESNO - for _, button := range options.Buttons { - if strings.TrimSpace(strings.ToLower(button.Label)) == "no" && button.IsDefault { - flags |= windows.MB_DEFBUTTON2 - } - } - case WarningDialogType: - flags = windows.MB_OK | windows.MB_ICONWARNING - } - - return flags -} - -func convertFilters(filters []FileFilter) []cfd.FileFilter { - var result []cfd.FileFilter - for _, filter := range filters { - result = append(result, cfd.FileFilter(filter)) - } - return result -} - -func showCfdDialog(newDlg func() (cfd.Dialog, error), isMultiSelect bool, parentWindow Window) (any, error) { - dlg, err := newDlg() - if err != nil { - return nil, err - } - - // Set parent window if provided - if parentWindow != nil { - nativeWindow := parentWindow.NativeWindow() - if nativeWindow != nil { - dlg.SetParentWindowHandle(uintptr(nativeWindow)) - } - } - - defer func() { - err := dlg.Release() - if err != nil { - globalApplication.error("unable to release dialog: %w", err) - } - }() - - if multi, _ := dlg.(cfd.OpenMultipleFilesDialog); multi != nil && isMultiSelect { - paths, err := multi.ShowAndGetResults() - if err != nil { - return nil, err - } - - for i, path := range paths { - paths[i] = filepath.Clean(path) - } - return paths, nil - } - - path, err := dlg.ShowAndGetResult() - if err != nil { - return nil, err - } - return filepath.Clean(path), nil -} diff --git a/v3/pkg/application/dialogs_windows_test.go b/v3/pkg/application/dialogs_windows_test.go deleted file mode 100644 index af4dabf75..000000000 --- a/v3/pkg/application/dialogs_windows_test.go +++ /dev/null @@ -1,57 +0,0 @@ -//go:build windows - -package application_test - -import ( - "path/filepath" - "testing" - - "github.com/matryer/is" -) - -func TestCleanPath(t *testing.T) { - i := is.New(t) - tests := []struct { - name string - inputPath string - expected string - }{ - { - name: "path with double separators", - inputPath: `C:\\temp\\folder`, - expected: `C:\temp\folder`, - }, - { - name: "path with forward slashes", - inputPath: `C://temp//folder`, - expected: `C:\temp\folder`, - }, - { - name: "path with trailing separator", - inputPath: `C:\\temp\\folder\\`, - expected: `C:\temp\folder`, - }, - { - name: "path with escaped tab character", - inputPath: `C:\\Users\\test\\tab.txt`, - expected: `C:\Users\test\tab.txt`, - }, - { - name: "newline character", - inputPath: `C:\\Users\\test\\newline\\n.txt`, - expected: `C:\Users\test\newline\n.txt`, - }, - { - name: "UNC path with multiple separators", - inputPath: `\\\\\\\\host\\share\\test.txt`, - expected: `\\\\host\share\test.txt`, - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - cleaned := filepath.Clean(tt.inputPath) - i.Equal(cleaned, tt.expected) - }) - } -} diff --git a/v3/pkg/application/environment.go b/v3/pkg/application/environment.go deleted file mode 100644 index 68be3ba06..000000000 --- a/v3/pkg/application/environment.go +++ /dev/null @@ -1,18 +0,0 @@ -package application - -import "github.com/wailsapp/wails/v3/internal/operatingsystem" - -// EnvironmentInfo represents information about the current environment. -// -// Fields: -// - OS: the operating system that the program is running on. -// - Arch: the architecture of the operating system. -// - Debug: indicates whether debug mode is enabled. -// - OSInfo: information about the operating system. -type EnvironmentInfo struct { - OS string - Arch string - Debug bool - OSInfo *operatingsystem.OS - PlatformInfo map[string]any -} diff --git a/v3/pkg/application/environment_linux.go b/v3/pkg/application/environment_linux.go deleted file mode 100644 index 9aa457d99..000000000 --- a/v3/pkg/application/environment_linux.go +++ /dev/null @@ -1,210 +0,0 @@ -//go:build linux - -package application - -import ( - "fmt" - "net" - "os" - "path/filepath" - "strconv" - "strings" -) - -func detectCompositor() string { - if os.Getenv("HYPRLAND_INSTANCE_SIGNATURE") != "" { - return "hyprland" - } - if os.Getenv("SWAYSOCK") != "" { - return "sway" - } - if os.Getenv("I3SOCK") != "" { - return "i3" - } - if desktop := os.Getenv("XDG_CURRENT_DESKTOP"); desktop != "" { - return strings.ToLower(desktop) - } - return "unknown" -} - -func detectFocusFollowsMouse() bool { - compositor := detectCompositor() - switch compositor { - case "hyprland", "sway", "i3": - return true - } - return false -} - -func isWayland() bool { - return os.Getenv("XDG_SESSION_TYPE") == "wayland" || - os.Getenv("WAYLAND_DISPLAY") != "" -} - -func isTilingWM() bool { - switch detectCompositor() { - case "hyprland", "sway", "i3": - return true - } - return false -} - -func getCursorPositionFromCompositor() (x, y int, ok bool) { - switch detectCompositor() { - case "hyprland": - out, err := hyprlandIPC("cursorpos") - if err != nil { - return 0, 0, false - } - return parseCursorPos(strings.TrimSpace(out)) - case "sway": - out, err := swayIPC("get_seats") - if err != nil { - return 0, 0, false - } - return parseSwayCursor(out) - } - return 0, 0, false -} - -func parseCursorPos(s string) (x, y int, ok bool) { - parts := strings.Split(s, ", ") - if len(parts) != 2 { - return 0, 0, false - } - var err error - x, err = strconv.Atoi(strings.TrimSpace(parts[0])) - if err != nil { - return 0, 0, false - } - y, err = strconv.Atoi(strings.TrimSpace(parts[1])) - if err != nil { - return 0, 0, false - } - return x, y, true -} - -func parseSwayCursor(json string) (x, y int, ok bool) { - cursorIdx := strings.Index(json, `"cursor"`) - if cursorIdx == -1 { - return 0, 0, false - } - - xIdx := strings.Index(json[cursorIdx:], `"x"`) - if xIdx == -1 { - return 0, 0, false - } - xStart := cursorIdx + xIdx + 4 - xEnd := strings.IndexAny(json[xStart:], ",}") - if xEnd == -1 { - return 0, 0, false - } - x, _ = strconv.Atoi(strings.TrimSpace(json[xStart : xStart+xEnd])) - - yIdx := strings.Index(json[cursorIdx:], `"y"`) - if yIdx == -1 { - return 0, 0, false - } - yStart := cursorIdx + yIdx + 4 - yEnd := strings.IndexAny(json[yStart:], ",}") - if yEnd == -1 { - return 0, 0, false - } - y, _ = strconv.Atoi(strings.TrimSpace(json[yStart : yStart+yEnd])) - - return x, y, true -} - -func hyprlandIPC(command string) (string, error) { - sig := os.Getenv("HYPRLAND_INSTANCE_SIGNATURE") - if sig == "" { - return "", fmt.Errorf("HYPRLAND_INSTANCE_SIGNATURE not set") - } - - runtimeDir := os.Getenv("XDG_RUNTIME_DIR") - if runtimeDir == "" { - runtimeDir = fmt.Sprintf("/run/user/%d", os.Getuid()) - } - - socketPath := filepath.Join(runtimeDir, "hypr", sig, ".socket.sock") - conn, err := net.Dial("unix", socketPath) - if err != nil { - return "", err - } - defer conn.Close() - - _, err = conn.Write([]byte(command)) - if err != nil { - return "", err - } - - var result strings.Builder - buf := make([]byte, 4096) - for { - n, err := conn.Read(buf) - if n > 0 { - result.Write(buf[:n]) - } - if err != nil { - break - } - if n < len(buf) { - break - } - } - - return result.String(), nil -} - -func swayIPC(command string) (string, error) { - socketPath := os.Getenv("SWAYSOCK") - if socketPath == "" { - return "", fmt.Errorf("SWAYSOCK not set") - } - - conn, err := net.Dial("unix", socketPath) - if err != nil { - return "", err - } - defer conn.Close() - - msgType := uint32(0) - if strings.HasPrefix(command, "get_") { - switch command { - case "get_seats": - msgType = 5 - } - } else { - msgType = 0 - } - - payload := []byte(command) - header := make([]byte, 14) - copy(header[0:6], "i3-ipc") - header[6] = byte(len(payload)) - header[7] = byte(len(payload) >> 8) - header[8] = byte(len(payload) >> 16) - header[9] = byte(len(payload) >> 24) - header[10] = byte(msgType) - header[11] = byte(msgType >> 8) - header[12] = byte(msgType >> 16) - header[13] = byte(msgType >> 24) - - conn.Write(header) - conn.Write(payload) - - respHeader := make([]byte, 14) - _, err = conn.Read(respHeader) - if err != nil { - return "", err - } - - respLen := uint32(respHeader[6]) | uint32(respHeader[7])<<8 | uint32(respHeader[8])<<16 | uint32(respHeader[9])<<24 - respBody := make([]byte, respLen) - _, err = conn.Read(respBody) - if err != nil { - return "", err - } - - return string(respBody), nil -} diff --git a/v3/pkg/application/environment_manager.go b/v3/pkg/application/environment_manager.go deleted file mode 100644 index f9e40093b..000000000 --- a/v3/pkg/application/environment_manager.go +++ /dev/null @@ -1,67 +0,0 @@ -package application - -import ( - "runtime" - - "github.com/wailsapp/wails/v3/internal/fileexplorer" - "github.com/wailsapp/wails/v3/internal/operatingsystem" -) - -// EnvironmentManager manages environment-related operations -type EnvironmentManager struct { - app *App -} - -// newEnvironmentManager creates a new EnvironmentManager instance -func newEnvironmentManager(app *App) *EnvironmentManager { - return &EnvironmentManager{ - app: app, - } -} - -// Info returns environment information -func (em *EnvironmentManager) Info() EnvironmentInfo { - info, _ := operatingsystem.Info() - result := EnvironmentInfo{ - OS: runtime.GOOS, - Arch: runtime.GOARCH, - Debug: em.app.isDebugMode, - OSInfo: info, - } - result.PlatformInfo = em.app.platformEnvironment() - return result -} - -// IsDarkMode returns true if the system is in dark mode -func (em *EnvironmentManager) IsDarkMode() bool { - if em.app.impl == nil { - return false - } - return em.app.impl.isDarkMode() -} - -// GetAccentColor returns the system accent color -func (em *EnvironmentManager) GetAccentColor() string { - if em.app.impl == nil { - return "rgb(0,122,255)" - } - return em.app.impl.getAccentColor() -} - -// OpenFileManager opens the file manager at the specified path, optionally selecting the file -func (em *EnvironmentManager) OpenFileManager(path string, selectFile bool) error { - return InvokeSyncWithError(func() error { - return fileexplorer.OpenFileManager(path, selectFile) - }) -} - -func (em *EnvironmentManager) HasFocusFollowsMouse() bool { - if runtime.GOOS != "linux" { - return false - } - info := em.app.platformEnvironment() - if ffm, ok := info["focusFollowsMouse"].(bool); ok { - return ffm - } - return false -} diff --git a/v3/pkg/application/errors.go b/v3/pkg/application/errors.go deleted file mode 100644 index d0b7edd6b..000000000 --- a/v3/pkg/application/errors.go +++ /dev/null @@ -1,55 +0,0 @@ -package application - -import ( - "fmt" - "os" - "strings" -) - -// FatalError instances are passed to the registered error handler -// in case of catastrophic, unrecoverable failures that require immediate termination. -// FatalError wraps the original error value in an informative message. -// The underlying error may be retrieved through the [FatalError.Unwrap] method. -type FatalError struct { - err error - internal bool -} - -// Internal returns true when the error was triggered from wails' internal code. -func (e *FatalError) Internal() bool { - return e.internal -} - -// Unwrap returns the original cause of the fatal error, -// for easy inspection using the [errors.As] API. -func (e *FatalError) Unwrap() error { - return e.err -} - -func (e *FatalError) Error() string { - var buffer strings.Builder - buffer.WriteString("\n\n******************************** FATAL *********************************\n") - buffer.WriteString("* There has been a catastrophic failure in your application. *\n") - if e.internal { - buffer.WriteString("* Please report this error at https://github.com/wailsapp/wails/issues *\n") - } - buffer.WriteString("**************************** Error Details *****************************\n") - buffer.WriteString(e.err.Error()) - buffer.WriteString("************************************************************************\n") - return buffer.String() -} - -func Fatal(message string, args ...any) { - err := &FatalError{ - err: fmt.Errorf(message, args...), - internal: true, - } - - if globalApplication != nil { - globalApplication.handleError(err) - } else { - fmt.Println(err) - } - - os.Exit(1) -} diff --git a/v3/pkg/application/event_manager.go b/v3/pkg/application/event_manager.go deleted file mode 100644 index 7555ff685..000000000 --- a/v3/pkg/application/event_manager.go +++ /dev/null @@ -1,174 +0,0 @@ -package application - -import ( - "slices" - - "github.com/wailsapp/wails/v3/pkg/events" -) - -// EventManager manages event-related operations -type EventManager struct { - app *App -} - -// newEventManager creates a new EventManager instance -func newEventManager(app *App) *EventManager { - return &EventManager{ - app: app, - } -} - -// Emit emits a custom event with the specified name and associated data. -// It returns a boolean indicating whether the event was cancelled by a hook. -// -// If no data argument is provided, Emit emits an event with nil data. -// When there is exactly one data argument, it will be used as the custom event's data field. -// When more than one argument is provided, the event's data field will be set to the argument slice. -// -// If the given event name is registered, Emit validates the data parameter -// against the expected data type. In case of a mismatch, Emit reports an error -// to the registered error handler for the application and cancels the event. -func (em *EventManager) Emit(name string, data ...any) bool { - event := &CustomEvent{Name: name} - - if len(data) == 1 { - event.Data = data[0] - } else if len(data) > 1 { - event.Data = data - } - - if err := em.app.customEventProcessor.Emit(event); err != nil { - globalApplication.handleError(err) - } - - return event.IsCancelled() -} - -// EmitEvent emits a custom event object (internal use) -// It returns a boolean indicating whether the event was cancelled by a hook. -// -// If the given event name is registered, emitEvent validates the data parameter -// against the expected data type. In case of a mismatch, emitEvent reports an error -// to the registered error handler for the application and cancels the event. -func (em *EventManager) EmitEvent(event *CustomEvent) bool { - if err := em.app.customEventProcessor.Emit(event); err != nil { - globalApplication.handleError(err) - } - - return event.IsCancelled() -} - -// On registers a listener for custom events -func (em *EventManager) On(name string, callback func(event *CustomEvent)) func() { - return em.app.customEventProcessor.On(name, callback) -} - -// Off removes all listeners for a custom event -func (em *EventManager) Off(name string) { - em.app.customEventProcessor.Off(name) -} - -// OnMultiple registers a listener for custom events that will be called N times -func (em *EventManager) OnMultiple(name string, callback func(event *CustomEvent), counter int) { - em.app.customEventProcessor.OnMultiple(name, callback, counter) -} - -// Reset removes all custom event listeners -func (em *EventManager) Reset() { - em.app.customEventProcessor.OffAll() -} - -// OnApplicationEvent registers a listener for application events -func (em *EventManager) OnApplicationEvent(eventType events.ApplicationEventType, callback func(event *ApplicationEvent)) func() { - eventID := uint(eventType) - em.app.applicationEventListenersLock.Lock() - defer em.app.applicationEventListenersLock.Unlock() - listener := &EventListener{ - callback: callback, - } - em.app.applicationEventListeners[eventID] = append(em.app.applicationEventListeners[eventID], listener) - if em.app.impl != nil { - go func() { - defer handlePanic() - em.app.impl.on(eventID) - }() - } - - return func() { - // lock the map - em.app.applicationEventListenersLock.Lock() - defer em.app.applicationEventListenersLock.Unlock() - // Remove listener - em.app.applicationEventListeners[eventID] = slices.DeleteFunc(em.app.applicationEventListeners[eventID], func(l *EventListener) bool { - return l == listener - }) - } -} - -// RegisterApplicationEventHook registers an application event hook -func (em *EventManager) RegisterApplicationEventHook(eventType events.ApplicationEventType, callback func(event *ApplicationEvent)) func() { - eventID := uint(eventType) - em.app.applicationEventHooksLock.Lock() - defer em.app.applicationEventHooksLock.Unlock() - thisHook := &eventHook{ - callback: callback, - } - em.app.applicationEventHooks[eventID] = append(em.app.applicationEventHooks[eventID], thisHook) - - return func() { - em.app.applicationEventHooksLock.Lock() - em.app.applicationEventHooks[eventID] = slices.DeleteFunc(em.app.applicationEventHooks[eventID], func(h *eventHook) bool { - return h == thisHook - }) - em.app.applicationEventHooksLock.Unlock() - } -} - -// Dispatch dispatches an event to listeners (internal use) -func (em *EventManager) dispatch(event *CustomEvent) { - // Snapshot listeners under Lock - em.app.wailsEventListenerLock.Lock() - listeners := slices.Clone(em.app.wailsEventListeners) - em.app.wailsEventListenerLock.Unlock() - - for _, listener := range listeners { - if event.IsCancelled() { - return - } - listener.DispatchWailsEvent(event) - } -} - -// HandleApplicationEvent handles application events (internal use) -func (em *EventManager) handleApplicationEvent(event *ApplicationEvent) { - defer handlePanic() - em.app.applicationEventListenersLock.RLock() - listeners, ok := em.app.applicationEventListeners[event.Id] - em.app.applicationEventListenersLock.RUnlock() - if !ok { - return - } - - // Process Hooks - em.app.applicationEventHooksLock.RLock() - hooks, ok := em.app.applicationEventHooks[event.Id] - em.app.applicationEventHooksLock.RUnlock() - if ok { - for _, thisHook := range hooks { - thisHook.callback(event) - if event.IsCancelled() { - return - } - } - } - - for _, listener := range listeners { - go func() { - if event.IsCancelled() { - return - } - defer handlePanic() - listener.callback(event) - }() - } -} diff --git a/v3/pkg/application/events.go b/v3/pkg/application/events.go deleted file mode 100644 index 577001dbe..000000000 --- a/v3/pkg/application/events.go +++ /dev/null @@ -1,366 +0,0 @@ -package application - -import ( - "fmt" - "reflect" - "slices" - "sync" - "sync/atomic" - - "encoding/json" - - "github.com/wailsapp/wails/v3/pkg/events" -) - -type ApplicationEvent struct { - Id uint - ctx *ApplicationEventContext - cancelled atomic.Bool -} - -func (w *ApplicationEvent) Context() *ApplicationEventContext { - return w.ctx -} - -func newApplicationEvent(id events.ApplicationEventType) *ApplicationEvent { - return &ApplicationEvent{ - Id: uint(id), - ctx: newApplicationEventContext(), - } -} - -func (w *ApplicationEvent) Cancel() { - w.cancelled.Store(true) -} - -func (w *ApplicationEvent) IsCancelled() bool { - return w.cancelled.Load() -} - -var applicationEvents = make(chan *ApplicationEvent, 5) - -type windowEvent struct { - WindowID uint - EventID uint -} - -var windowEvents = make(chan *windowEvent, 5) - -var menuItemClicked = make(chan uint, 5) - -type CustomEvent struct { - Name string `json:"name"` - Data any `json:"data"` - - // Sender records the name of the window sending the event, - // or "" if sent from application. - Sender string `json:"sender,omitempty"` - - cancelled atomic.Bool -} - -func (e *CustomEvent) Cancel() { - e.cancelled.Store(true) -} - -func (e *CustomEvent) IsCancelled() bool { - return e.cancelled.Load() -} - -func (e *CustomEvent) ToJSON() string { - marshal, err := json.Marshal(&e) - if err != nil { - // TODO: Fatal error? log? - return "" - } - return string(marshal) -} - -// WailsEventListener is an interface for receiving all emitted Wails events. -// Used by transport layers (IPC, WebSocket) to broadcast events. -type WailsEventListener interface { - DispatchWailsEvent(event *CustomEvent) -} - -type hook struct { - callback func(*CustomEvent) -} - -// eventListener holds a callback function which is invoked when -// the event listened for is emitted. It has a counter which indicates -// how the total number of events it is interested in. A value of zero -// means it does not expire (default). -type eventListener struct { - callback func(*CustomEvent) // Function to call with emitted event data - counter int // The number of times this callback may be called. -1 = infinite - delete bool // Flag to indicate that this listener should be deleted -} - -// EventProcessor handles custom events -type EventProcessor struct { - // Go event listeners - listeners map[string][]*eventListener - notifyLock sync.RWMutex - dispatchEventToWindows func(*CustomEvent) - hooks map[string][]*hook - hookLock sync.RWMutex -} - -func NewWailsEventProcessor(dispatchEventToWindows func(*CustomEvent)) *EventProcessor { - return &EventProcessor{ - listeners: make(map[string][]*eventListener), - dispatchEventToWindows: dispatchEventToWindows, - hooks: make(map[string][]*hook), - } -} - -// On is the equivalent of Javascript's `addEventListener` -func (e *EventProcessor) On(eventName string, callback func(event *CustomEvent)) func() { - return e.registerListener(eventName, callback, -1) -} - -// OnMultiple is the same as `OnApplicationEvent` but will unregister after `count` events -func (e *EventProcessor) OnMultiple(eventName string, callback func(event *CustomEvent), counter int) func() { - return e.registerListener(eventName, callback, counter) -} - -// Once is the same as `OnApplicationEvent` but will unregister after the first event -func (e *EventProcessor) Once(eventName string, callback func(event *CustomEvent)) func() { - return e.registerListener(eventName, callback, 1) -} - -// Emit sends an event to all listeners. -// -// If the event is globally registered, it validates associated data -// against the expected data type. In case of mismatches, -// it cancels the event and returns an error. -func (e *EventProcessor) Emit(thisEvent *CustomEvent) error { - if thisEvent == nil { - return nil - } - - // Validate data type; in case of mismatches cancel and report error. - if err := validateCustomEvent(thisEvent); err != nil { - thisEvent.Cancel() - return err - } - - // If we have any hooks, run them first and check if the event was cancelled - if e.hooks != nil { - if hooks, ok := e.hooks[thisEvent.Name]; ok { - for _, thisHook := range hooks { - thisHook.callback(thisEvent) - if thisEvent.IsCancelled() { - return nil - } - } - } - } - - go func() { - defer handlePanic() - e.dispatchEventToListeners(thisEvent) - }() - go func() { - defer handlePanic() - e.dispatchEventToWindows(thisEvent) - }() - - return nil -} - -func (e *EventProcessor) Off(eventName string) { - e.unRegisterListener(eventName) -} - -func (e *EventProcessor) OffAll() { - e.notifyLock.Lock() - defer e.notifyLock.Unlock() - e.listeners = make(map[string][]*eventListener) -} - -// registerListener provides a means of subscribing to events of type "eventName" -func (e *EventProcessor) registerListener(eventName string, callback func(*CustomEvent), counter int) func() { - // Create new eventListener - thisListener := &eventListener{ - callback: callback, - counter: counter, - delete: false, - } - e.notifyLock.Lock() - // Append the new listener to the listeners slice - e.listeners[eventName] = append(e.listeners[eventName], thisListener) - e.notifyLock.Unlock() - return func() { - e.notifyLock.Lock() - defer e.notifyLock.Unlock() - - if _, ok := e.listeners[eventName]; !ok { - return - } - e.listeners[eventName] = slices.DeleteFunc(e.listeners[eventName], func(l *eventListener) bool { - return l == thisListener - }) - } -} - -// RegisterHook provides a means of registering methods to be called before emitting the event -func (e *EventProcessor) RegisterHook(eventName string, callback func(*CustomEvent)) func() { - // Create new hook - thisHook := &hook{ - callback: callback, - } - e.hookLock.Lock() - // Append the new listener to the listeners slice - e.hooks[eventName] = append(e.hooks[eventName], thisHook) - e.hookLock.Unlock() - return func() { - e.hookLock.Lock() - defer e.hookLock.Unlock() - - if _, ok := e.hooks[eventName]; !ok { - return - } - e.hooks[eventName] = slices.DeleteFunc(e.hooks[eventName], func(h *hook) bool { - return h == thisHook - }) - } -} - -// unRegisterListener provides a means of unsubscribing to events of type "eventName" -func (e *EventProcessor) unRegisterListener(eventName string) { - e.notifyLock.Lock() - defer e.notifyLock.Unlock() - delete(e.listeners, eventName) -} - -// dispatchEventToListeners calls all registered listeners event name -func (e *EventProcessor) dispatchEventToListeners(event *CustomEvent) { - - e.notifyLock.Lock() - defer e.notifyLock.Unlock() - - listeners := e.listeners[event.Name] - if listeners == nil { - return - } - - // We have a dirty flag to indicate that there are items to delete - itemsToDelete := false - - // Callback in goroutine - for _, listener := range listeners { - if listener.counter > 0 { - listener.counter-- - } - go func() { - if event.IsCancelled() { - return - } - defer handlePanic() - listener.callback(event) - }() - - if listener.counter == 0 { - listener.delete = true - itemsToDelete = true - } - } - - // Do we have items to delete? - if itemsToDelete == true { - e.listeners[event.Name] = slices.DeleteFunc(listeners, func(l *eventListener) bool { - return l.delete == true - }) - } -} - -// Void will be translated by the binding generator to the TypeScript type 'void'. -// It can be used as an event data type to register events that must not have any associated data. -type Void interface { - sentinel() -} - -var registeredEvents sync.Map -var voidType = reflect.TypeFor[Void]() - -// RegisterEvent registers a custom event name and associated data type. -// Events may be registered at most once. -// Duplicate calls for the same event name trigger a panic. -// -// The binding generator emits typing information for all registered custom events. -// [App.EmitEvent] and [Window.EmitEvent] check the data type for registered events. -// Data types are matched exactly and no conversion is performed. -// -// It is recommended to call RegisterEvent directly, -// with constant arguments, and only from init functions. -// Indirect calls or instantiations are not discoverable by the binding generator. -func RegisterEvent[Data any](name string) { - if events.IsKnownEvent(name) { - panic(fmt.Errorf("'%s' is a known system event name", name)) - } - if typ, ok := registeredEvents.Load(name); ok { - panic(fmt.Errorf("event '%s' is already registered with data type %s", name, typ)) - } - - registeredEvents.Store(name, reflect.TypeFor[Data]()) - eventRegistered(name) -} - -func validateCustomEvent(event *CustomEvent) error { - r, ok := registeredEvents.Load(event.Name) - if !ok { - warnAboutUnregisteredEvent(event.Name) - return nil - } - - typ := r.(reflect.Type) - - if typ == voidType { - if event.Data == nil { - return nil - } - } else if typ.Kind() == reflect.Interface { - if reflect.TypeOf(event.Data).Implements(typ) { - return nil - } - } else { - if reflect.TypeOf(event.Data) == typ { - return nil - } - } - - return fmt.Errorf( - "data of type %s for event '%s' does not match registered data type %s", - reflect.TypeOf(event.Data), - event.Name, - typ, - ) -} - -func decodeEventData(name string, data []byte) (result any, err error) { - r, ok := registeredEvents.Load(name) - if !ok { - // Unregistered events unmarshal to any. - err = json.Unmarshal(data, &result) - return - } - - typ := r.(reflect.Type) - - if typ == voidType { - // When typ is voidType, perform a null check - err = json.Unmarshal(data, &result) - if err == nil && result != nil { - err = fmt.Errorf("non-null data for event '%s' does not match registered data type %s", name, typ) - } - } else { - value := reflect.New(typ.(reflect.Type)) - err = json.Unmarshal(data, value.Interface()) - if err == nil { - result = value.Elem().Interface() - } - } - - return -} diff --git a/v3/pkg/application/events_bench_test.go b/v3/pkg/application/events_bench_test.go deleted file mode 100644 index c6ed4341f..000000000 --- a/v3/pkg/application/events_bench_test.go +++ /dev/null @@ -1,380 +0,0 @@ -//go:build bench - -package application_test - -import ( - "fmt" - "sync" - "sync/atomic" - "testing" - - "github.com/wailsapp/wails/v3/pkg/application" -) - -// mockWindowDispatcher implements a no-op dispatcher for benchmarking -type mockWindowDispatcher struct { - count atomic.Int64 -} - -func (m *mockWindowDispatcher) dispatchEventToWindows(event *application.CustomEvent) { - m.count.Add(1) -} - -// BenchmarkEventEmit measures event emission with varying listener counts -func BenchmarkEventEmit(b *testing.B) { - listenerCounts := []int{0, 1, 10, 100} - - for _, count := range listenerCounts { - b.Run(fmt.Sprintf("Listeners%d", count), func(b *testing.B) { - dispatcher := &mockWindowDispatcher{} - processor := application.NewWailsEventProcessor(dispatcher.dispatchEventToWindows) - - // Register listeners - for i := 0; i < count; i++ { - processor.On("benchmark-event", func(event *application.CustomEvent) { - // Minimal work - _ = event.Data - }) - } - - event := &application.CustomEvent{ - Name: "benchmark-event", - Data: "test payload", - } - - b.ResetTimer() - for b.Loop() { - _ = processor.Emit(event) - } - }) - } -} - -// BenchmarkEventRegistration measures the cost of registering event listeners -func BenchmarkEventRegistration(b *testing.B) { - dispatcher := &mockWindowDispatcher{} - - b.Run("SingleRegistration", func(b *testing.B) { - for b.Loop() { - processor := application.NewWailsEventProcessor(dispatcher.dispatchEventToWindows) - processor.On("test-event", func(event *application.CustomEvent) {}) - } - }) - - b.Run("MultipleRegistrations", func(b *testing.B) { - for b.Loop() { - processor := application.NewWailsEventProcessor(dispatcher.dispatchEventToWindows) - for i := 0; i < 10; i++ { - processor.On(fmt.Sprintf("test-event-%d", i), func(event *application.CustomEvent) {}) - } - } - }) - - b.Run("SameEventMultipleListeners", func(b *testing.B) { - for b.Loop() { - processor := application.NewWailsEventProcessor(dispatcher.dispatchEventToWindows) - for i := 0; i < 10; i++ { - processor.On("test-event", func(event *application.CustomEvent) {}) - } - } - }) -} - -// BenchmarkEventUnregistration measures the cost of unregistering event listeners -func BenchmarkEventUnregistration(b *testing.B) { - dispatcher := &mockWindowDispatcher{} - - b.Run("SingleUnregister", func(b *testing.B) { - for b.Loop() { - processor := application.NewWailsEventProcessor(dispatcher.dispatchEventToWindows) - cancel := processor.On("test-event", func(event *application.CustomEvent) {}) - cancel() - } - }) - - b.Run("UnregisterFromMany", func(b *testing.B) { - processor := application.NewWailsEventProcessor(dispatcher.dispatchEventToWindows) - // Pre-register many listeners - cancels := make([]func(), 100) - for i := 0; i < 100; i++ { - cancels[i] = processor.On("test-event", func(event *application.CustomEvent) {}) - } - - b.ResetTimer() - for i := 0; b.Loop(); i++ { - // Re-register to have something to unregister - if i%100 == 0 { - for j := 0; j < 100; j++ { - cancels[j] = processor.On("test-event", func(event *application.CustomEvent) {}) - } - } - cancels[i%100]() - } - }) - - b.Run("OffAllListeners", func(b *testing.B) { - for b.Loop() { - processor := application.NewWailsEventProcessor(dispatcher.dispatchEventToWindows) - for i := 0; i < 10; i++ { - processor.On("test-event", func(event *application.CustomEvent) {}) - } - processor.Off("test-event") - } - }) -} - -// BenchmarkHookExecution measures the cost of hook execution during emit -func BenchmarkHookExecution(b *testing.B) { - hookCounts := []int{0, 1, 5, 10} - - for _, count := range hookCounts { - b.Run(fmt.Sprintf("Hooks%d", count), func(b *testing.B) { - dispatcher := &mockWindowDispatcher{} - processor := application.NewWailsEventProcessor(dispatcher.dispatchEventToWindows) - - // Register hooks - for i := 0; i < count; i++ { - processor.RegisterHook("benchmark-event", func(event *application.CustomEvent) { - // Minimal work - don't cancel - _ = event.Data - }) - } - - event := &application.CustomEvent{ - Name: "benchmark-event", - Data: "test payload", - } - - b.ResetTimer() - for b.Loop() { - _ = processor.Emit(event) - } - }) - } -} - -// BenchmarkConcurrentEmit measures event emission under concurrent load -func BenchmarkConcurrentEmit(b *testing.B) { - concurrencyLevels := []int{1, 4, 16} - - for _, concurrency := range concurrencyLevels { - b.Run(fmt.Sprintf("Goroutines%d", concurrency), func(b *testing.B) { - dispatcher := &mockWindowDispatcher{} - processor := application.NewWailsEventProcessor(dispatcher.dispatchEventToWindows) - - // Register a few listeners - for i := 0; i < 5; i++ { - processor.On("benchmark-event", func(event *application.CustomEvent) { - _ = event.Data - }) - } - - b.ResetTimer() - b.SetParallelism(concurrency) - b.RunParallel(func(pb *testing.PB) { - event := &application.CustomEvent{ - Name: "benchmark-event", - Data: "test payload", - } - for pb.Next() { - _ = processor.Emit(event) - } - }) - }) - } -} - -// BenchmarkEventToJSON measures CustomEvent JSON serialization -func BenchmarkEventToJSON(b *testing.B) { - b.Run("SimpleData", func(b *testing.B) { - event := &application.CustomEvent{ - Name: "test-event", - Data: "simple string payload", - } - for b.Loop() { - _ = event.ToJSON() - } - }) - - b.Run("ComplexData", func(b *testing.B) { - event := &application.CustomEvent{ - Name: "test-event", - Data: map[string]interface{}{ - "id": 12345, - "name": "Test Event", - "tags": []string{"tag1", "tag2", "tag3"}, - "enabled": true, - "nested": map[string]interface{}{ - "value": 3.14159, - }, - }, - } - for b.Loop() { - _ = event.ToJSON() - } - }) - - b.Run("WithSender", func(b *testing.B) { - event := &application.CustomEvent{ - Name: "test-event", - Data: "payload", - Sender: "main-window", - } - for b.Loop() { - _ = event.ToJSON() - } - }) -} - -// BenchmarkAtomicCancel measures the atomic cancel/check operations -func BenchmarkAtomicCancel(b *testing.B) { - b.Run("Cancel", func(b *testing.B) { - for b.Loop() { - event := &application.CustomEvent{ - Name: "test", - Data: nil, - } - event.Cancel() - } - }) - - b.Run("IsCancelled", func(b *testing.B) { - event := &application.CustomEvent{ - Name: "test", - Data: nil, - } - for b.Loop() { - _ = event.IsCancelled() - } - }) - - b.Run("CancelAndCheck", func(b *testing.B) { - for b.Loop() { - event := &application.CustomEvent{ - Name: "test", - Data: nil, - } - event.Cancel() - _ = event.IsCancelled() - } - }) -} - -// BenchmarkEventProcessorCreation measures processor instantiation -func BenchmarkEventProcessorCreation(b *testing.B) { - dispatcher := &mockWindowDispatcher{} - for b.Loop() { - _ = application.NewWailsEventProcessor(dispatcher.dispatchEventToWindows) - } -} - -// BenchmarkOnceEvent measures the Once registration and auto-unregistration -func BenchmarkOnceEvent(b *testing.B) { - dispatcher := &mockWindowDispatcher{} - - b.Run("RegisterAndTrigger", func(b *testing.B) { - for b.Loop() { - processor := application.NewWailsEventProcessor(dispatcher.dispatchEventToWindows) - var wg sync.WaitGroup - wg.Add(1) - processor.Once("once-event", func(event *application.CustomEvent) { - wg.Done() - }) - _ = processor.Emit(&application.CustomEvent{Name: "once-event", Data: nil}) - wg.Wait() - } - }) -} - -// BenchmarkOnMultipleEvent measures the OnMultiple registration -func BenchmarkOnMultipleEvent(b *testing.B) { - dispatcher := &mockWindowDispatcher{} - - b.Run("ThreeEvents", func(b *testing.B) { - for b.Loop() { - processor := application.NewWailsEventProcessor(dispatcher.dispatchEventToWindows) - var wg sync.WaitGroup - wg.Add(3) - processor.OnMultiple("multi-event", func(event *application.CustomEvent) { - wg.Done() - }, 3) - for i := 0; i < 3; i++ { - _ = processor.Emit(&application.CustomEvent{Name: "multi-event", Data: nil}) - } - wg.Wait() - } - }) -} - -// BenchmarkMixedEventOperations simulates realistic event usage patterns -func BenchmarkMixedEventOperations(b *testing.B) { - dispatcher := &mockWindowDispatcher{} - - b.Run("RegisterEmitUnregister", func(b *testing.B) { - processor := application.NewWailsEventProcessor(dispatcher.dispatchEventToWindows) - - for b.Loop() { - cancel := processor.On("mixed-event", func(event *application.CustomEvent) { - _ = event.Data - }) - _ = processor.Emit(&application.CustomEvent{Name: "mixed-event", Data: "test"}) - cancel() - } - }) - - b.Run("HookAndEmit", func(b *testing.B) { - processor := application.NewWailsEventProcessor(dispatcher.dispatchEventToWindows) - processor.RegisterHook("hooked-event", func(event *application.CustomEvent) { - // Validation hook - if event.Data == nil { - event.Cancel() - } - }) - processor.On("hooked-event", func(event *application.CustomEvent) { - _ = event.Data - }) - - event := &application.CustomEvent{Name: "hooked-event", Data: "valid"} - - b.ResetTimer() - for b.Loop() { - _ = processor.Emit(event) - } - }) -} - -// BenchmarkEventNameLookup measures the map lookup performance for event names -func BenchmarkEventNameLookup(b *testing.B) { - dispatcher := &mockWindowDispatcher{} - processor := application.NewWailsEventProcessor(dispatcher.dispatchEventToWindows) - - // Register events with different name lengths - shortName := "evt" - mediumName := "application:user:action" - longName := "com.mycompany.myapp.module.submodule.event.type.action" - - processor.On(shortName, func(event *application.CustomEvent) {}) - processor.On(mediumName, func(event *application.CustomEvent) {}) - processor.On(longName, func(event *application.CustomEvent) {}) - - b.Run("ShortName", func(b *testing.B) { - event := &application.CustomEvent{Name: shortName, Data: nil} - for b.Loop() { - _ = processor.Emit(event) - } - }) - - b.Run("MediumName", func(b *testing.B) { - event := &application.CustomEvent{Name: mediumName, Data: nil} - for b.Loop() { - _ = processor.Emit(event) - } - }) - - b.Run("LongName", func(b *testing.B) { - event := &application.CustomEvent{Name: longName, Data: nil} - for b.Loop() { - _ = processor.Emit(event) - } - }) -} diff --git a/v3/pkg/application/events_common_android.go b/v3/pkg/application/events_common_android.go deleted file mode 100644 index b0aa0b912..000000000 --- a/v3/pkg/application/events_common_android.go +++ /dev/null @@ -1,23 +0,0 @@ -//go:build android - -package application - -import "github.com/wailsapp/wails/v3/pkg/events" - -// Map platform events → common events (same pattern as macOS & others) -var commonApplicationEventMap = map[events.ApplicationEventType]events.ApplicationEventType{ - events.Android.ActivityCreated: events.Common.ApplicationStarted, -} - -// setupCommonEvents forwards Android platform events to their common counterparts -func (a *androidApp) setupCommonEvents() { - for sourceEvent, targetEvent := range commonApplicationEventMap { - sourceEvent := sourceEvent - targetEvent := targetEvent - a.parent.Event.OnApplicationEvent(sourceEvent, func(event *ApplicationEvent) { - event.Id = uint(targetEvent) - androidLogf("info", "[events_common_android.go] Forwarding Android event %d → common %d", sourceEvent, targetEvent) - applicationEvents <- event - }) - } -} diff --git a/v3/pkg/application/events_common_darwin.go b/v3/pkg/application/events_common_darwin.go deleted file mode 100644 index 8bc3a8af7..000000000 --- a/v3/pkg/application/events_common_darwin.go +++ /dev/null @@ -1,36 +0,0 @@ -//go:build darwin && !ios - -package application - -import "github.com/wailsapp/wails/v3/pkg/events" - -var commonApplicationEventMap = map[events.ApplicationEventType]events.ApplicationEventType{ - events.Mac.ApplicationDidFinishLaunching: events.Common.ApplicationStarted, - events.Mac.ApplicationDidChangeTheme: events.Common.ThemeChanged, -} - -func (m *macosApp) setupCommonEvents() { - for sourceEvent, targetEvent := range commonApplicationEventMap { - sourceEvent := sourceEvent - targetEvent := targetEvent - m.parent.Event.OnApplicationEvent(sourceEvent, func(event *ApplicationEvent) { - event.Id = uint(targetEvent) - applicationEvents <- event - }) - } - - // Handle dock icon click (applicationShouldHandleReopen) to show windows - // when there are no visible windows. This provides the expected macOS UX - // where clicking the dock icon shows a hidden app's window. - // Issue #4583: Apps with StartHidden: true should show when dock icon is clicked. - m.parent.Event.OnApplicationEvent(events.Mac.ApplicationShouldHandleReopen, func(event *ApplicationEvent) { - if !event.Context().HasVisibleWindows() { - // Show all windows that are not visible - for _, window := range m.parent.Window.GetAll() { - if !window.IsVisible() { - window.Show() - } - } - } - }) -} diff --git a/v3/pkg/application/events_common_ios.go b/v3/pkg/application/events_common_ios.go deleted file mode 100644 index eadfc2afb..000000000 --- a/v3/pkg/application/events_common_ios.go +++ /dev/null @@ -1,24 +0,0 @@ -//go:build ios - -package application - -import "github.com/wailsapp/wails/v3/pkg/events" - -// Map platform events → common events (same pattern as macOS & others) -var commonApplicationEventMap = map[events.ApplicationEventType]events.ApplicationEventType{ - events.IOS.ApplicationDidFinishLaunching: events.Common.ApplicationStarted, -} - -// setupCommonEvents forwards iOS platform events to their common counterparts -func (i *iosApp) setupCommonEvents() { - for sourceEvent, targetEvent := range commonApplicationEventMap { - sourceEvent := sourceEvent - targetEvent := targetEvent - i.parent.Event.OnApplicationEvent(sourceEvent, func(event *ApplicationEvent) { - event.Id = uint(targetEvent) - // Log the forwarding so we can see every emitted event in iOS NSLog - iosConsoleLogf("info", " [events_common_ios.go] Forwarding iOS event %d → common %d", sourceEvent, targetEvent) - applicationEvents <- event - }) - } -} \ No newline at end of file diff --git a/v3/pkg/application/events_common_linux.go b/v3/pkg/application/events_common_linux.go deleted file mode 100644 index ddff94b7f..000000000 --- a/v3/pkg/application/events_common_linux.go +++ /dev/null @@ -1,21 +0,0 @@ -//go:build linux && !android && !server - -package application - -import "github.com/wailsapp/wails/v3/pkg/events" - -var commonApplicationEventMap = map[events.ApplicationEventType]events.ApplicationEventType{ - events.Linux.ApplicationStartup: events.Common.ApplicationStarted, - events.Linux.SystemThemeChanged: events.Common.ThemeChanged, -} - -func (a *linuxApp) setupCommonEvents() { - for sourceEvent, targetEvent := range commonApplicationEventMap { - sourceEvent := sourceEvent - targetEvent := targetEvent - a.parent.Event.OnApplicationEvent(sourceEvent, func(event *ApplicationEvent) { - event.Id = uint(targetEvent) - applicationEvents <- event - }) - } -} diff --git a/v3/pkg/application/events_common_server.go b/v3/pkg/application/events_common_server.go deleted file mode 100644 index bde9941eb..000000000 --- a/v3/pkg/application/events_common_server.go +++ /dev/null @@ -1,10 +0,0 @@ -//go:build server - -package application - -// setupCommonEvents sets up common application events for server mode. -// In server mode, there are no platform-specific events to map, -// so this is a no-op. -func (h *serverApp) setupCommonEvents() { - // No-op: server mode has no platform-specific events to map -} diff --git a/v3/pkg/application/events_common_windows.go b/v3/pkg/application/events_common_windows.go deleted file mode 100644 index 1c4dd55e6..000000000 --- a/v3/pkg/application/events_common_windows.go +++ /dev/null @@ -1,21 +0,0 @@ -//go:build windows - -package application - -import "github.com/wailsapp/wails/v3/pkg/events" - -var commonApplicationEventMap = map[events.ApplicationEventType]events.ApplicationEventType{ - events.Windows.SystemThemeChanged: events.Common.ThemeChanged, - events.Windows.ApplicationStarted: events.Common.ApplicationStarted, -} - -func (m *windowsApp) setupCommonEvents() { - for sourceEvent, targetEvent := range commonApplicationEventMap { - sourceEvent := sourceEvent - targetEvent := targetEvent - m.parent.Event.OnApplicationEvent(sourceEvent, func(event *ApplicationEvent) { - event.Id = uint(targetEvent) - applicationEvents <- event - }) - } -} diff --git a/v3/pkg/application/events_loose.go b/v3/pkg/application/events_loose.go deleted file mode 100644 index f00715c51..000000000 --- a/v3/pkg/application/events_loose.go +++ /dev/null @@ -1,7 +0,0 @@ -//go:build production || !strictevents - -package application - -func eventRegistered(name string) {} - -func warnAboutUnregisteredEvent(name string) {} diff --git a/v3/pkg/application/events_strict.go b/v3/pkg/application/events_strict.go deleted file mode 100644 index adc19dbd3..000000000 --- a/v3/pkg/application/events_strict.go +++ /dev/null @@ -1,27 +0,0 @@ -//go:build !production && strictevents - -package application - -import ( - "sync" -) - -var knownUnregisteredEvents sync.Map - -func eventRegistered(name string) { - knownUnregisteredEvents.Delete(name) -} - -func warnAboutUnregisteredEvent(name string) { - // Perform a load first to avoid thrashing the map with unnecessary swaps. - if _, known := knownUnregisteredEvents.Load(name); known { - return - } - - // Perform a swap to synchronize with concurrent emissions. - if _, known := knownUnregisteredEvents.Swap(name, true); known { - return - } - - globalApplication.warning("unregistered event name '%s'", name) -} diff --git a/v3/pkg/application/events_test.go b/v3/pkg/application/events_test.go deleted file mode 100644 index c1e621d9c..000000000 --- a/v3/pkg/application/events_test.go +++ /dev/null @@ -1,135 +0,0 @@ -package application_test - -import ( - "sync" - "testing" - - "github.com/wailsapp/wails/v3/pkg/application" - - "github.com/matryer/is" -) - -type mockNotifier struct { - Events []*application.CustomEvent -} - -func (m *mockNotifier) dispatchEventToWindows(event *application.CustomEvent) { - m.Events = append(m.Events, event) -} - -func (m *mockNotifier) Reset() { - m.Events = []*application.CustomEvent{} -} - -func Test_EventsOn(t *testing.T) { - i := is.New(t) - notifier := &mockNotifier{} - eventProcessor := application.NewWailsEventProcessor(notifier.dispatchEventToWindows) - - // Test OnApplicationEvent - eventName := "test" - counter := 0 - var wg sync.WaitGroup - wg.Add(1) - unregisterFn := eventProcessor.On(eventName, func(event *application.CustomEvent) { - // This is called in a goroutine - counter++ - wg.Done() - }) - _ = eventProcessor.Emit(&application.CustomEvent{ - Name: "test", - Data: "test payload", - }) - wg.Wait() - i.Equal(1, counter) - - // Unregister - notifier.Reset() - unregisterFn() - counter = 0 - _ = eventProcessor.Emit(&application.CustomEvent{ - Name: "test", - Data: "test payload", - }) - i.Equal(0, counter) - -} - -func Test_EventsOnce(t *testing.T) { - i := is.New(t) - notifier := &mockNotifier{} - eventProcessor := application.NewWailsEventProcessor(notifier.dispatchEventToWindows) - - // Test OnApplicationEvent - eventName := "test" - counter := 0 - var wg sync.WaitGroup - wg.Add(1) - unregisterFn := eventProcessor.Once(eventName, func(event *application.CustomEvent) { - // This is called in a goroutine - counter++ - wg.Done() - }) - _ = eventProcessor.Emit(&application.CustomEvent{ - Name: "test", - Data: "test payload", - }) - _ = eventProcessor.Emit(&application.CustomEvent{ - Name: "test", - Data: "test payload", - }) - wg.Wait() - i.Equal(1, counter) - - // Unregister - notifier.Reset() - unregisterFn() - counter = 0 - _ = eventProcessor.Emit(&application.CustomEvent{ - Name: "test", - Data: "test payload", - }) - i.Equal(0, counter) - -} -func Test_EventsOnMultiple(t *testing.T) { - i := is.New(t) - notifier := &mockNotifier{} - eventProcessor := application.NewWailsEventProcessor(notifier.dispatchEventToWindows) - - // Test OnApplicationEvent - eventName := "test" - counter := 0 - var wg sync.WaitGroup - wg.Add(2) - unregisterFn := eventProcessor.OnMultiple(eventName, func(event *application.CustomEvent) { - // This is called in a goroutine - counter++ - wg.Done() - }, 2) - _ = eventProcessor.Emit(&application.CustomEvent{ - Name: "test", - Data: "test payload", - }) - _ = eventProcessor.Emit(&application.CustomEvent{ - Name: "test", - Data: "test payload", - }) - _ = eventProcessor.Emit(&application.CustomEvent{ - Name: "test", - Data: "test payload", - }) - wg.Wait() - i.Equal(2, counter) - - // Unregister - notifier.Reset() - unregisterFn() - counter = 0 - _ = eventProcessor.Emit(&application.CustomEvent{ - Name: "test", - Data: "test payload", - }) - i.Equal(0, counter) - -} diff --git a/v3/pkg/application/image.go b/v3/pkg/application/image.go deleted file mode 100644 index 81c519739..000000000 --- a/v3/pkg/application/image.go +++ /dev/null @@ -1,37 +0,0 @@ -package application - -import ( - "bytes" - "image" - "image/draw" - "image/png" -) - -func pngToImage(data []byte) (*image.RGBA, error) { - img, err := png.Decode(bytes.NewReader(data)) - if err != nil { - return nil, err - } - - bounds := img.Bounds() - rgba := image.NewRGBA(bounds) - draw.Draw(rgba, bounds, img, bounds.Min, draw.Src) - return rgba, nil -} - -func ToARGB(img *image.RGBA) (int, int, []byte) { - w, h := img.Bounds().Dx(), img.Bounds().Dy() - data := make([]byte, w*h*4) - i := 0 - for y := 0; y < h; y++ { - for x := 0; x < w; x++ { - r, g, b, a := img.At(x, y).RGBA() - data[i] = byte(a) - data[i+1] = byte(r) - data[i+2] = byte(g) - data[i+3] = byte(b) - i += 4 - } - } - return w, h, data -} diff --git a/v3/pkg/application/init_android.go b/v3/pkg/application/init_android.go deleted file mode 100644 index 6c50e82c6..000000000 --- a/v3/pkg/application/init_android.go +++ /dev/null @@ -1,9 +0,0 @@ -//go:build android - -package application - -func init() { - // On Android, we don't call runtime.LockOSThread() - // The Android runtime handles thread management via JNI - // and calling LockOSThread can interfere with the JNI environment -} diff --git a/v3/pkg/application/init_desktop.go b/v3/pkg/application/init_desktop.go deleted file mode 100644 index a840fed53..000000000 --- a/v3/pkg/application/init_desktop.go +++ /dev/null @@ -1,11 +0,0 @@ -//go:build !ios - -package application - -import "runtime" - -func init() { - // Lock the main thread for desktop platforms - // This ensures UI operations happen on the main thread - runtime.LockOSThread() -} \ No newline at end of file diff --git a/v3/pkg/application/init_ios.go b/v3/pkg/application/init_ios.go deleted file mode 100644 index 63c054294..000000000 --- a/v3/pkg/application/init_ios.go +++ /dev/null @@ -1,9 +0,0 @@ -//go:build ios - -package application - -func init() { - // On iOS, we don't call runtime.LockOSThread() - // The iOS runtime handles thread management differently - // and calling LockOSThread can interfere with signal handling -} diff --git a/v3/pkg/application/internal/tests/services/common.go b/v3/pkg/application/internal/tests/services/common.go deleted file mode 100644 index 9d35da69e..000000000 --- a/v3/pkg/application/internal/tests/services/common.go +++ /dev/null @@ -1,168 +0,0 @@ -package services - -import ( - "context" - "fmt" - "sync/atomic" - "testing" - - "github.com/google/go-cmp/cmp" - "github.com/wailsapp/wails/v3/pkg/application" -) - -type Config struct { - Id int - T *testing.T - Seq *atomic.Int64 - Options application.ServiceOptions - StartupErr bool - ShutdownErr bool -} - -func Configure[T any, P interface { - *T - Configure(Config) -}](srv P, c Config) application.Service { - srv.Configure(c) - return application.NewServiceWithOptions(srv, c.Options) -} - -type Error struct { - Id int -} - -func (e *Error) Error() string { - return fmt.Sprintf("service #%d mock failure", e.Id) -} - -type Startupper struct { - Config - startup int64 -} - -func (s *Startupper) Configure(c Config) { - s.Config = c -} - -func (s *Startupper) Id() int { - return s.Config.Id -} - -func (s *Startupper) StartupSeq() int64 { - return s.startup -} - -func (s *Startupper) ServiceStartup(ctx context.Context, options application.ServiceOptions) error { - if s.startup != 0 { - s.T.Errorf("Double startup for service #%d: first at seq=%d, then at seq=%d", s.Id(), s.startup, s.Seq.Load()) - return nil - } - - s.startup = s.Seq.Add(1) - - if diff := cmp.Diff(s.Options, options); diff != "" { - s.T.Errorf("Options mismatch for service #%d (-want +got):\n%s", s.Id(), diff) - } - - if s.StartupErr { - return &Error{Id: s.Id()} - } else { - return nil - } -} - -type Shutdowner struct { - Config - shutdown int64 -} - -func (s *Shutdowner) Configure(c Config) { - s.Config = c -} - -func (s *Shutdowner) Id() int { - return s.Config.Id -} - -func (s *Shutdowner) ShutdownSeq() int64 { - return s.shutdown -} - -func (s *Shutdowner) ServiceShutdown() error { - if s.shutdown != 0 { - s.T.Errorf("Double shutdown for service #%d: first at seq=%d, then at seq=%d", s.Id(), s.shutdown, s.Seq.Load()) - return nil - } - - s.shutdown = s.Seq.Add(1) - - if s.ShutdownErr { - return &Error{Id: s.Id()} - } else { - return nil - } -} - -type StartupShutdowner struct { - Config - startup int64 - shutdown int64 - ctx context.Context -} - -func (s *StartupShutdowner) Configure(c Config) { - s.Config = c -} - -func (s *StartupShutdowner) Id() int { - return s.Config.Id -} - -func (s *StartupShutdowner) StartupSeq() int64 { - return s.startup -} - -func (s *StartupShutdowner) ShutdownSeq() int64 { - return s.shutdown -} - -func (s *StartupShutdowner) ServiceStartup(ctx context.Context, options application.ServiceOptions) error { - if s.startup != 0 { - s.T.Errorf("Double startup for service #%d: first at seq=%d, then at seq=%d", s.Id(), s.startup, s.Seq.Load()) - return nil - } - - s.startup = s.Seq.Add(1) - s.ctx = ctx - - if diff := cmp.Diff(s.Options, options); diff != "" { - s.T.Errorf("Options mismatch for service #%d (-want +got):\n%s", s.Id(), diff) - } - - if s.StartupErr { - return &Error{Id: s.Id()} - } else { - return nil - } -} - -func (s *StartupShutdowner) ServiceShutdown() error { - if s.shutdown != 0 { - s.T.Errorf("Double shutdown for service #%d: first at seq=%d, then at seq=%d", s.Id(), s.shutdown, s.Seq.Load()) - return nil - } - - s.shutdown = s.Seq.Add(1) - - select { - case <-s.ctx.Done(): - default: - s.T.Errorf("Service #%d shut down before context cancellation", s.Id()) - } - - if s.ShutdownErr { - return &Error{Id: s.Id()} - } else { - return nil - } -} diff --git a/v3/pkg/application/internal/tests/services/shutdown/shutdown_test.go b/v3/pkg/application/internal/tests/services/shutdown/shutdown_test.go deleted file mode 100644 index ad8df141c..000000000 --- a/v3/pkg/application/internal/tests/services/shutdown/shutdown_test.go +++ /dev/null @@ -1,92 +0,0 @@ -package shutdown - -import ( - "sync" - "sync/atomic" - "testing" - - "github.com/wailsapp/wails/v3/pkg/application" - apptest "github.com/wailsapp/wails/v3/pkg/application/internal/tests" - svctest "github.com/wailsapp/wails/v3/pkg/application/internal/tests/services" - "github.com/wailsapp/wails/v3/pkg/events" -) - -func TestMain(m *testing.M) { - apptest.Main(m) -} - -type ( - Service1 struct{ svctest.Shutdowner } - Service2 struct{ svctest.Shutdowner } - Service3 struct{ svctest.Shutdowner } - Service4 struct{ svctest.Shutdowner } - Service5 struct{ svctest.Shutdowner } - Service6 struct{ svctest.Shutdowner } -) - -func TestServiceShutdown(t *testing.T) { - var seq atomic.Int64 - - services := []application.Service{ - svctest.Configure(&Service1{}, svctest.Config{Id: 0, T: t, Seq: &seq}), - svctest.Configure(&Service2{}, svctest.Config{Id: 1, T: t, Seq: &seq}), - svctest.Configure(&Service3{}, svctest.Config{Id: 2, T: t, Seq: &seq}), - svctest.Configure(&Service4{}, svctest.Config{Id: 3, T: t, Seq: &seq}), - svctest.Configure(&Service5{}, svctest.Config{Id: 4, T: t, Seq: &seq}), - svctest.Configure(&Service6{}, svctest.Config{Id: 5, T: t, Seq: &seq}), - } - - app := apptest.New(t, application.Options{ - Services: services[:3], - }) - - var wg sync.WaitGroup - wg.Add(2) - go func() { - app.RegisterService(services[3]) - wg.Done() - }() - go func() { - app.RegisterService(services[4]) - wg.Done() - }() - wg.Wait() - - app.RegisterService(services[5]) - - app.Event.OnApplicationEvent(events.Common.ApplicationStarted, func(*application.ApplicationEvent) { - app.Quit() - }) - - err := apptest.Run(t, app) - if err != nil { - t.Fatal(err) - } - - if count := seq.Load(); count != int64(len(services)) { - t.Errorf("Wrong shutdown call count: wanted %d, got %d", len(services), count) - } - - validate(t, services[0], 5) - validate(t, services[1], 4) - validate(t, services[2], 2, 3) - validate(t, services[3], 1) - validate(t, services[4], 1) - validate(t, services[5], 0) -} - -func validate(t *testing.T, svc application.Service, prev ...int64) { - id := svc.Instance().(interface{ Id() int }).Id() - seq := svc.Instance().(interface{ ShutdownSeq() int64 }).ShutdownSeq() - - if seq == 0 { - t.Errorf("Service #%d did not shut down", id) - return - } - - for _, p := range prev { - if seq <= p { - t.Errorf("Wrong shutdown sequence number for service #%d: wanted >%d, got %d", id, p, seq) - } - } -} diff --git a/v3/pkg/application/internal/tests/services/shutdownerror/shutdownerror_test.go b/v3/pkg/application/internal/tests/services/shutdownerror/shutdownerror_test.go deleted file mode 100644 index 42949b037..000000000 --- a/v3/pkg/application/internal/tests/services/shutdownerror/shutdownerror_test.go +++ /dev/null @@ -1,123 +0,0 @@ -package shutdownerror - -import ( - "errors" - "slices" - "sync" - "sync/atomic" - "testing" - - "github.com/wailsapp/wails/v3/pkg/application" - apptest "github.com/wailsapp/wails/v3/pkg/application/internal/tests" - svctest "github.com/wailsapp/wails/v3/pkg/application/internal/tests/services" - "github.com/wailsapp/wails/v3/pkg/events" -) - -func TestMain(m *testing.M) { - apptest.Main(m) -} - -type ( - Service1 struct{ svctest.Shutdowner } - Service2 struct{ svctest.Shutdowner } - Service3 struct{ svctest.Shutdowner } - Service4 struct{ svctest.Shutdowner } - Service5 struct{ svctest.Shutdowner } - Service6 struct{ svctest.Shutdowner } -) - -func TestServiceShutdownError(t *testing.T) { - var seq atomic.Int64 - - services := []application.Service{ - svctest.Configure(&Service1{}, svctest.Config{Id: 0, T: t, Seq: &seq}), - svctest.Configure(&Service2{}, svctest.Config{Id: 1, T: t, Seq: &seq, ShutdownErr: true}), - svctest.Configure(&Service3{}, svctest.Config{Id: 2, T: t, Seq: &seq}), - svctest.Configure(&Service4{}, svctest.Config{Id: 3, T: t, Seq: &seq}), - svctest.Configure(&Service5{}, svctest.Config{Id: 4, T: t, Seq: &seq, ShutdownErr: true}), - svctest.Configure(&Service6{}, svctest.Config{Id: 5, T: t, Seq: &seq, ShutdownErr: true}), - } - - expectedShutdownErrors := []int{5, 4, 1} - var errCount atomic.Int64 - - var app *application.App - app = apptest.New(t, application.Options{ - Services: services[:3], - ErrorHandler: func(err error) { - var mock *svctest.Error - if !errors.As(err, &mock) { - app.Logger.Error(err.Error()) - return - } - - i := int(errCount.Add(1) - 1) - if i < len(expectedShutdownErrors) && mock.Id == expectedShutdownErrors[i] { - return - } - - cut := min(i, len(expectedShutdownErrors)) - if slices.Contains(expectedShutdownErrors[:cut], mock.Id) { - t.Errorf("Late or duplicate shutdown error for service #%d", mock.Id) - } else if slices.Contains(expectedShutdownErrors[cut:], mock.Id) { - t.Errorf("Early shutdown error for service #%d", mock.Id) - } else { - t.Errorf("Unexpected shutdown error for service #%d", mock.Id) - } - }, - }) - - var wg sync.WaitGroup - wg.Add(2) - go func() { - app.RegisterService(services[3]) - wg.Done() - }() - go func() { - app.RegisterService(services[4]) - wg.Done() - }() - wg.Wait() - - app.RegisterService(services[5]) - - app.Event.OnApplicationEvent(events.Common.ApplicationStarted, func(*application.ApplicationEvent) { - app.Quit() - }) - - err := apptest.Run(t, app) - if err != nil { - t.Fatal(err) - } - - if ec := errCount.Load(); ec != int64(len(expectedShutdownErrors)) { - t.Errorf("Wrong shutdown error count: wanted %d, got %d", len(expectedShutdownErrors), ec) - } - - if count := seq.Load(); count != int64(len(services)) { - t.Errorf("Wrong shutdown call count: wanted %d, got %d", len(services), count) - } - - validate(t, services[0], 5) - validate(t, services[1], 4) - validate(t, services[2], 2, 3) - validate(t, services[3], 1) - validate(t, services[4], 1) - validate(t, services[5], 0) -} - -func validate(t *testing.T, svc application.Service, prev ...int64) { - id := svc.Instance().(interface{ Id() int }).Id() - seq := svc.Instance().(interface{ ShutdownSeq() int64 }).ShutdownSeq() - - if seq == 0 { - t.Errorf("Service #%d did not shut down", id) - return - } - - for _, p := range prev { - if seq <= p { - t.Errorf("Wrong shutdown sequence number for service #%d: wanted >%d, got %d", id, p, seq) - } - } -} diff --git a/v3/pkg/application/internal/tests/services/startup/startup_test.go b/v3/pkg/application/internal/tests/services/startup/startup_test.go deleted file mode 100644 index bf5c2ac96..000000000 --- a/v3/pkg/application/internal/tests/services/startup/startup_test.go +++ /dev/null @@ -1,102 +0,0 @@ -package startup - -import ( - "sync" - "sync/atomic" - "testing" - - "github.com/wailsapp/wails/v3/pkg/application" - apptest "github.com/wailsapp/wails/v3/pkg/application/internal/tests" - svctest "github.com/wailsapp/wails/v3/pkg/application/internal/tests/services" - "github.com/wailsapp/wails/v3/pkg/events" -) - -func TestMain(m *testing.M) { - apptest.Main(m) -} - -type ( - Service1 struct{ svctest.Startupper } - Service2 struct{ svctest.Startupper } - Service3 struct{ svctest.Startupper } - Service4 struct{ svctest.Startupper } - Service5 struct{ svctest.Startupper } - Service6 struct{ svctest.Startupper } -) - -func TestServiceStartup(t *testing.T) { - var seq atomic.Int64 - - services := []application.Service{ - svctest.Configure(&Service1{}, svctest.Config{Id: 0, T: t, Seq: &seq}), - svctest.Configure(&Service2{}, svctest.Config{Id: 1, T: t, Seq: &seq, Options: application.ServiceOptions{ - Name: "I am service 2", - }}), - svctest.Configure(&Service3{}, svctest.Config{Id: 2, T: t, Seq: &seq, Options: application.ServiceOptions{ - Route: "/mounted/here", - }}), - svctest.Configure(&Service4{}, svctest.Config{Id: 3, T: t, Seq: &seq}), - svctest.Configure(&Service5{}, svctest.Config{Id: 4, Seq: &seq, Options: application.ServiceOptions{ - Name: "I am service 5", - Route: "/mounted/there", - }}), - svctest.Configure(&Service6{}, svctest.Config{Id: 5, T: t, Seq: &seq, Options: application.ServiceOptions{ - Name: "I am service 6", - Route: "/mounted/elsewhere", - }}), - } - - app := apptest.New(t, application.Options{ - Services: services[:3], - }) - - var wg sync.WaitGroup - wg.Add(2) - go func() { - app.RegisterService(services[3]) - wg.Done() - }() - go func() { - app.RegisterService(services[4]) - wg.Done() - }() - wg.Wait() - - app.RegisterService(services[5]) - - app.Event.OnApplicationEvent(events.Common.ApplicationStarted, func(*application.ApplicationEvent) { - app.Quit() - }) - - err := apptest.Run(t, app) - if err != nil { - t.Fatal(err) - } - - if count := seq.Load(); count != int64(len(services)) { - t.Errorf("Wrong startup call count: wanted %d, got %d", len(services), count) - } - - validate(t, services[0], 0) - validate(t, services[1], 1) - validate(t, services[2], 2) - validate(t, services[3], 3) - validate(t, services[4], 3) - validate(t, services[5], 4, 5) -} - -func validate(t *testing.T, svc application.Service, prev ...int64) { - id := svc.Instance().(interface{ Id() int }).Id() - seq := svc.Instance().(interface{ StartupSeq() int64 }).StartupSeq() - - if seq == 0 { - t.Errorf("Service #%d did not start up", id) - return - } - - for _, p := range prev { - if seq <= p { - t.Errorf("Wrong startup sequence number for service #%d: wanted >%d, got %d", id, p, seq) - } - } -} diff --git a/v3/pkg/application/internal/tests/services/startuperror/startuperror_test.go b/v3/pkg/application/internal/tests/services/startuperror/startuperror_test.go deleted file mode 100644 index a4a3c5bc4..000000000 --- a/v3/pkg/application/internal/tests/services/startuperror/startuperror_test.go +++ /dev/null @@ -1,114 +0,0 @@ -package startuperror - -import ( - "errors" - "sync" - "sync/atomic" - "testing" - - "github.com/wailsapp/wails/v3/pkg/application" - apptest "github.com/wailsapp/wails/v3/pkg/application/internal/tests" - svctest "github.com/wailsapp/wails/v3/pkg/application/internal/tests/services" - "github.com/wailsapp/wails/v3/pkg/events" -) - -func TestMain(m *testing.M) { - apptest.Main(m) -} - -type ( - Service1 struct{ svctest.Startupper } - Service2 struct{ svctest.Startupper } - Service3 struct{ svctest.Startupper } - Service4 struct{ svctest.Startupper } - Service5 struct{ svctest.Startupper } - Service6 struct{ svctest.Startupper } -) - -func TestServiceStartupError(t *testing.T) { - var seq atomic.Int64 - - services := []application.Service{ - svctest.Configure(&Service1{}, svctest.Config{Id: 0, T: t, Seq: &seq}), - svctest.Configure(&Service2{}, svctest.Config{Id: 1, T: t, Seq: &seq}), - svctest.Configure(&Service3{}, svctest.Config{Id: 2, T: t, Seq: &seq}), - svctest.Configure(&Service4{}, svctest.Config{Id: 3, T: t, Seq: &seq, StartupErr: true}), - svctest.Configure(&Service5{}, svctest.Config{Id: 4, T: t, Seq: &seq, StartupErr: true}), - svctest.Configure(&Service6{}, svctest.Config{Id: 5, T: t, Seq: &seq, StartupErr: true}), - } - - app := apptest.New(t, application.Options{ - Services: services[:3], - }) - - var wg sync.WaitGroup - wg.Add(2) - go func() { - app.RegisterService(services[3]) - wg.Done() - }() - go func() { - app.RegisterService(services[4]) - wg.Done() - }() - wg.Wait() - - app.RegisterService(services[5]) - - app.Event.OnApplicationEvent(events.Common.ApplicationStarted, func(*application.ApplicationEvent) { - t.Errorf("Application started") - app.Quit() - }) - - var mock *svctest.Error - - err := apptest.Run(t, app) - if err != nil { - if !errors.As(err, &mock) { - t.Fatal(err) - } - } - - if mock == nil { - t.Fatal("Wanted startup error for service #3 or #4, got none") - } else if mock.Id != 3 && mock.Id != 4 { - t.Errorf("Wanted startup error for service #3 or #4, got #%d", mock.Id) - } - - if count := seq.Load(); count != 4 { - t.Errorf("Wrong startup call count: wanted %d, got %d", 4, count) - } - - validate(t, services[0], 0) - validate(t, services[1], 1) - validate(t, services[2], 2) - validate(t, services[mock.Id], 3) - - notStarted := 3 - if mock.Id == 3 { - notStarted = 4 - } - - if seq := services[notStarted].Instance().(interface{ StartupSeq() int64 }).StartupSeq(); seq != 0 { - t.Errorf("Service #%d started up unexpectedly at seq=%d", notStarted, seq) - } - if seq := services[5].Instance().(interface{ StartupSeq() int64 }).StartupSeq(); seq != 0 { - t.Errorf("Service #5 started up unexpectedly at seq=%d", seq) - } -} - -func validate(t *testing.T, svc application.Service, prev ...int64) { - id := svc.Instance().(interface{ Id() int }).Id() - seq := svc.Instance().(interface{ StartupSeq() int64 }).StartupSeq() - - if seq == 0 { - t.Errorf("Service #%d did not start up", id) - return - } - - for _, p := range prev { - if seq <= p { - t.Errorf("Wrong startup sequence number for service #%d: wanted >%d, got %d", id, p, seq) - } - } -} diff --git a/v3/pkg/application/internal/tests/services/startupshutdown/startupshutdown_test.go b/v3/pkg/application/internal/tests/services/startupshutdown/startupshutdown_test.go deleted file mode 100644 index 5f8cfc365..000000000 --- a/v3/pkg/application/internal/tests/services/startupshutdown/startupshutdown_test.go +++ /dev/null @@ -1,102 +0,0 @@ -package startupshutdown - -import ( - "sync" - "sync/atomic" - "testing" - - "github.com/wailsapp/wails/v3/pkg/application" - apptest "github.com/wailsapp/wails/v3/pkg/application/internal/tests" - svctest "github.com/wailsapp/wails/v3/pkg/application/internal/tests/services" - "github.com/wailsapp/wails/v3/pkg/events" -) - -func TestMain(m *testing.M) { - apptest.Main(m) -} - -type ( - Service1 struct{ svctest.StartupShutdowner } - Service2 struct{ svctest.StartupShutdowner } - Service3 struct{ svctest.StartupShutdowner } - Service4 struct{ svctest.StartupShutdowner } - Service5 struct{ svctest.StartupShutdowner } - Service6 struct{ svctest.StartupShutdowner } -) - -func TestServiceStartupShutdown(t *testing.T) { - var seq atomic.Int64 - - services := []application.Service{ - svctest.Configure(&Service1{}, svctest.Config{Id: 0, T: t, Seq: &seq}), - svctest.Configure(&Service2{}, svctest.Config{Id: 1, T: t, Seq: &seq}), - svctest.Configure(&Service3{}, svctest.Config{Id: 2, T: t, Seq: &seq}), - svctest.Configure(&Service4{}, svctest.Config{Id: 3, T: t, Seq: &seq}), - svctest.Configure(&Service5{}, svctest.Config{Id: 4, T: t, Seq: &seq}), - svctest.Configure(&Service6{}, svctest.Config{Id: 5, T: t, Seq: &seq}), - } - - app := apptest.New(t, application.Options{ - Services: services[:3], - }) - - var wg sync.WaitGroup - wg.Add(2) - go func() { - app.RegisterService(services[3]) - wg.Done() - }() - go func() { - app.RegisterService(services[4]) - wg.Done() - }() - wg.Wait() - - app.RegisterService(services[5]) - - app.Event.OnApplicationEvent(events.Common.ApplicationStarted, func(*application.ApplicationEvent) { - if count := seq.Load(); count != int64(len(services)) { - t.Errorf("Wrong startup call count: wanted %d, got %d", len(services), count) - } - seq.Store(0) - app.Quit() - }) - - err := apptest.Run(t, app) - if err != nil { - t.Fatal(err) - } - - if count := seq.Load(); count != int64(len(services)) { - t.Errorf("Wrong shutdown call count: wanted %d, got %d", len(services), count) - } - - bound := int64(len(services)) + 1 - validate(t, services[0], bound) - validate(t, services[1], bound) - validate(t, services[2], bound) - validate(t, services[3], bound) - validate(t, services[4], bound) - validate(t, services[5], bound) -} - -func validate(t *testing.T, svc application.Service, bound int64) { - id := svc.Instance().(interface{ Id() int }).Id() - startup := svc.Instance().(interface{ StartupSeq() int64 }).StartupSeq() - shutdown := svc.Instance().(interface{ ShutdownSeq() int64 }).ShutdownSeq() - - if startup == 0 && shutdown == 0 { - t.Errorf("Service #%d did not start nor shut down", id) - return - } else if startup == 0 { - t.Errorf("Service #%d started, but did not shut down", id) - return - } else if shutdown == 0 { - t.Errorf("Service #%d shut down, but did not start", id) - return - } - - if shutdown != bound-startup { - t.Errorf("Wrong sequence numbers for service #%d: wanted either %d..%d or %d..%d, got %d..%d", id, startup, bound-startup, bound-shutdown, shutdown, startup, shutdown) - } -} diff --git a/v3/pkg/application/internal/tests/services/startupshutdownerror/startupshutdownerror_test.go b/v3/pkg/application/internal/tests/services/startupshutdownerror/startupshutdownerror_test.go deleted file mode 100644 index 0ca135269..000000000 --- a/v3/pkg/application/internal/tests/services/startupshutdownerror/startupshutdownerror_test.go +++ /dev/null @@ -1,140 +0,0 @@ -package startupshutdownerror - -import ( - "errors" - "slices" - "sync" - "sync/atomic" - "testing" - - "github.com/wailsapp/wails/v3/pkg/application" - apptest "github.com/wailsapp/wails/v3/pkg/application/internal/tests" - svctest "github.com/wailsapp/wails/v3/pkg/application/internal/tests/services" - "github.com/wailsapp/wails/v3/pkg/events" -) - -func TestMain(m *testing.M) { - apptest.Main(m) -} - -type ( - Service1 struct{ svctest.StartupShutdowner } - Service2 struct{ svctest.StartupShutdowner } - Service3 struct{ svctest.StartupShutdowner } - Service4 struct{ svctest.StartupShutdowner } - Service5 struct{ svctest.StartupShutdowner } - Service6 struct{ svctest.StartupShutdowner } -) - -func TestServiceStartupShutdownError(t *testing.T) { - var seq atomic.Int64 - - services := []application.Service{ - svctest.Configure(&Service1{}, svctest.Config{Id: 0, T: t, Seq: &seq}), - svctest.Configure(&Service2{}, svctest.Config{Id: 1, T: t, Seq: &seq, ShutdownErr: true}), - svctest.Configure(&Service3{}, svctest.Config{Id: 2, T: t, Seq: &seq}), - svctest.Configure(&Service4{}, svctest.Config{Id: 3, T: t, Seq: &seq, StartupErr: true, ShutdownErr: true}), - svctest.Configure(&Service5{}, svctest.Config{Id: 4, T: t, Seq: &seq, StartupErr: true, ShutdownErr: true}), - svctest.Configure(&Service6{}, svctest.Config{Id: 5, T: t, Seq: &seq, StartupErr: true, ShutdownErr: true}), - } - - expectedShutdownErrors := []int{1} - var errCount atomic.Int64 - - var app *application.App - app = apptest.New(t, application.Options{ - Services: services[:3], - ErrorHandler: func(err error) { - var mock *svctest.Error - if !errors.As(err, &mock) { - app.Logger.Error(err.Error()) - return - } - - i := int(errCount.Add(1) - 1) - if i < len(expectedShutdownErrors) && mock.Id == expectedShutdownErrors[i] { - return - } - - cut := min(i, len(expectedShutdownErrors)) - if slices.Contains(expectedShutdownErrors[:cut], mock.Id) { - t.Errorf("Late or duplicate shutdown error for service #%d", mock.Id) - } else if slices.Contains(expectedShutdownErrors[cut:], mock.Id) { - t.Errorf("Early shutdown error for service #%d", mock.Id) - } else { - t.Errorf("Unexpected shutdown error for service #%d", mock.Id) - } - }, - }) - - var wg sync.WaitGroup - wg.Add(2) - go func() { - app.RegisterService(services[3]) - wg.Done() - }() - go func() { - app.RegisterService(services[4]) - wg.Done() - }() - wg.Wait() - - app.RegisterService(services[5]) - - app.Event.OnApplicationEvent(events.Common.ApplicationStarted, func(*application.ApplicationEvent) { - t.Errorf("Application started") - app.Quit() - }) - - var mock *svctest.Error - - err := apptest.Run(t, app) - if err != nil { - if !errors.As(err, &mock) { - t.Fatal(err) - } - } - - if mock == nil { - t.Fatal("Wanted error for service #3 or #4, got none") - } else if mock.Id != 3 && mock.Id != 4 { - t.Errorf("Wanted error for service #3 or #4, got #%d", mock.Id) - } - - if ec := errCount.Load(); ec != int64(len(expectedShutdownErrors)) { - t.Errorf("Wrong shutdown error count: wanted %d, got %d", len(expectedShutdownErrors), ec) - } - - if count := seq.Load(); count != 4+3 { - t.Errorf("Wrong startup+shutdown call count: wanted %d+%d, got %d", 4, 3, count) - } - - validate(t, services[0], true, true) - validate(t, services[1], true, true) - validate(t, services[2], true, true) - validate(t, services[3], mock.Id == 3, false) - validate(t, services[4], mock.Id == 4, false) - validate(t, services[5], false, false) -} - -func validate(t *testing.T, svc application.Service, startup bool, shutdown bool) { - id := svc.Instance().(interface{ Id() int }).Id() - startupSeq := svc.Instance().(interface{ StartupSeq() int64 }).StartupSeq() - shutdownSeq := svc.Instance().(interface{ ShutdownSeq() int64 }).ShutdownSeq() - - if startup != (startupSeq != 0) { - if startupSeq == 0 { - t.Errorf("Service #%d did not start up", id) - } else { - t.Errorf("Unexpected startup for service #%d at seq=%d", id, startupSeq) - } - } - - if shutdown != (shutdownSeq != 0) { - if shutdownSeq == 0 { - t.Errorf("Service #%d did not shut down", id) - } else { - t.Errorf("Unexpected shutdown for service #%d at seq=%d", id, shutdownSeq) - } - } -} diff --git a/v3/pkg/application/internal/tests/utils.go b/v3/pkg/application/internal/tests/utils.go deleted file mode 100644 index ef94ef5ba..000000000 --- a/v3/pkg/application/internal/tests/utils.go +++ /dev/null @@ -1,74 +0,0 @@ -package tests - -import ( - "errors" - "os" - "runtime" - "testing" - - "github.com/wailsapp/wails/v3/pkg/application" -) - -var appChan chan *application.App = make(chan *application.App, 1) -var errChan chan error = make(chan error, 1) -var endChan chan error = make(chan error, 1) - -func init() { runtime.LockOSThread() } - -func New(t *testing.T, options application.Options) *application.App { - var app *application.App - - app = application.Get() - if app != nil { - return app - } - - if options.Name == "" { - options.Name = t.Name() - } - - errorHandler := options.ErrorHandler - options.ErrorHandler = func(err error) { - if fatal := (*application.FatalError)(nil); errors.As(err, &fatal) { - endChan <- err - select {} // Block forever - } else if errorHandler != nil { - errorHandler(err) - } else { - app.Logger.Error(err.Error()) - } - } - - postShutdown := options.PostShutdown - options.PostShutdown = func() { - if postShutdown != nil { - postShutdown() - } - endChan <- nil - select {} // Block forever - } - - return application.New(options) -} - -func Run(t *testing.T, app *application.App) error { - appChan <- app - select { - case err := <-errChan: - return err - case fatal := <-endChan: - if fatal != nil { - t.Fatal(fatal) - } - return fatal - } -} - -func Main(m *testing.M) { - go func() { - os.Exit(m.Run()) - }() - - errChan <- (<-appChan).Run() - select {} // Block forever -} diff --git a/v3/pkg/application/ios_runtime_api.go b/v3/pkg/application/ios_runtime_api.go deleted file mode 100644 index 54434a0ee..000000000 --- a/v3/pkg/application/ios_runtime_api.go +++ /dev/null @@ -1,14 +0,0 @@ -//go:build ios - -package application - -// Exported API for use by applications to mutate iOS WKWebView at runtime. -// These call into the internal platform-specific implementations. - -func IOSSetScrollEnabled(enabled bool) { iosSetScrollEnabled(enabled) } -func IOSSetBounceEnabled(enabled bool) { iosSetBounceEnabled(enabled) } -func IOSSetScrollIndicatorsEnabled(enabled bool) { iosSetScrollIndicatorsEnabled(enabled) } -func IOSSetBackForwardGesturesEnabled(enabled bool) { iosSetBackForwardGesturesEnabled(enabled) } -func IOSSetLinkPreviewEnabled(enabled bool) { iosSetLinkPreviewEnabled(enabled) } -func IOSSetInspectableEnabled(enabled bool) { iosSetInspectableEnabled(enabled) } -func IOSSetCustomUserAgent(ua string) { iosSetCustomUserAgent(ua) } diff --git a/v3/pkg/application/ios_runtime_ios.go b/v3/pkg/application/ios_runtime_ios.go deleted file mode 100644 index 6a388d9a9..000000000 --- a/v3/pkg/application/ios_runtime_ios.go +++ /dev/null @@ -1,79 +0,0 @@ -//go:build ios - -package application - -/* -#cgo CFLAGS: -x objective-c -fmodules -fobjc-arc -#cgo LDFLAGS: -framework UIKit -#include -#include "application_ios.h" -*/ -import "C" -import ( - "unsafe" - - "encoding/json" -) - -// iosHapticsImpact triggers an iOS haptic impact using the provided style. -// The style parameter specifies the impact style name understood by the native haptic engine. -func iosHapticsImpact(style string) { - cstr := C.CString(style) - defer C.free(unsafe.Pointer(cstr)) - C.ios_haptics_impact(cstr) -} - -type deviceInfo struct { - Model string `json:"model"` - SystemName string `json:"systemName"` - SystemVersion string `json:"systemVersion"` - IsSimulator bool `json:"isSimulator"` -} - -func iosDeviceInfo() deviceInfo { - ptr := C.ios_device_info_json() - if ptr == nil { - return deviceInfo{} - } - defer C.free(unsafe.Pointer(ptr)) - goStr := C.GoString(ptr) - var out deviceInfo - _ = json.Unmarshal([]byte(goStr), &out) - return out -} - -// iosSetScrollEnabled sets whether scrolling is enabled in the iOS runtime. -func iosSetScrollEnabled(enabled bool) { C.ios_runtime_set_scroll_enabled(C.bool(enabled)) } -// iosSetBounceEnabled sets whether scroll bounce (rubber-band) behavior is enabled at runtime. -// If enabled is true, scrollable content will bounce when pulled past its edges; if false, that bounce is disabled. -func iosSetBounceEnabled(enabled bool) { C.ios_runtime_set_bounce_enabled(C.bool(enabled)) } -// iosSetScrollIndicatorsEnabled configures whether the iOS runtime shows scroll indicators. -// The enabled parameter controls visibility: true shows indicators, false hides them. -func iosSetScrollIndicatorsEnabled(enabled bool) { - C.ios_runtime_set_scroll_indicators_enabled(C.bool(enabled)) -} -// iosSetBackForwardGesturesEnabled enables back-forward navigation gestures when enabled is true and disables them when enabled is false. -func iosSetBackForwardGesturesEnabled(enabled bool) { - C.ios_runtime_set_back_forward_gestures_enabled(C.bool(enabled)) -} -// iosSetLinkPreviewEnabled sets whether link previews are enabled in the iOS runtime. -// Pass true to enable link previews, false to disable them. -func iosSetLinkPreviewEnabled(enabled bool) { C.ios_runtime_set_link_preview_enabled(C.bool(enabled)) } -// iosSetInspectableEnabled sets whether runtime web content inspection is enabled. -// When enabled is true the runtime allows inspection of web content; when false inspection is disabled. -func iosSetInspectableEnabled(enabled bool) { C.ios_runtime_set_inspectable_enabled(C.bool(enabled)) } -// iosSetCustomUserAgent sets the runtime's custom User-Agent string. -// If ua is an empty string, the custom User-Agent is cleared. -func iosSetCustomUserAgent(ua string) { - var cstr *C.char - if ua != "" { - cstr = C.CString(ua) - defer C.free(unsafe.Pointer(cstr)) - } - C.ios_runtime_set_custom_user_agent(cstr) -} - -// Native tabs -func iosSetNativeTabsEnabled(enabled bool) { C.ios_native_tabs_set_enabled(C.bool(enabled)) } -func iosNativeTabsIsEnabled() bool { return bool(C.ios_native_tabs_is_enabled()) } -func iosSelectNativeTab(index int) { C.ios_native_tabs_select_index(C.int(index)) } \ No newline at end of file diff --git a/v3/pkg/application/ios_runtime_stub.go b/v3/pkg/application/ios_runtime_stub.go deleted file mode 100644 index 09de75b56..000000000 --- a/v3/pkg/application/ios_runtime_stub.go +++ /dev/null @@ -1,27 +0,0 @@ -//go:build !ios - -package application - -func iosHapticsImpact(style string) { - // no-op on non-iOS -} - -type deviceInfo struct { - Model string `json:"model"` - SystemName string `json:"systemName"` - SystemVersion string `json:"systemVersion"` - IsSimulator bool `json:"isSimulator"` -} - -func iosDeviceInfo() deviceInfo { - return deviceInfo{} -} - -// Live mutation stubs -func iosSetScrollEnabled(enabled bool) {} -func iosSetBounceEnabled(enabled bool) {} -func iosSetScrollIndicatorsEnabled(enabled bool) {} -func iosSetBackForwardGesturesEnabled(enabled bool) {} -func iosSetLinkPreviewEnabled(enabled bool) {} -func iosSetInspectableEnabled(enabled bool) {} -func iosSetCustomUserAgent(ua string) {} diff --git a/v3/pkg/application/json_libs_bench_test.go b/v3/pkg/application/json_libs_bench_test.go deleted file mode 100644 index c3e7e4918..000000000 --- a/v3/pkg/application/json_libs_bench_test.go +++ /dev/null @@ -1,314 +0,0 @@ -//go:build bench - -// Disabled: goccy/go-json causes Windows panics. See PR #4859. - -package application_test - -/* -import ( - "encoding/json" - "testing" - - "github.com/bytedance/sonic" - gojson "github.com/goccy/go-json" - jsoniter "github.com/json-iterator/go" -) - -// Test structures matching real Wails binding patterns - -type SimpleBindingArg struct { - Name string `json:"name"` - Value int `json:"value"` -} - -type ComplexBindingArg struct { - ID int `json:"id"` - Name string `json:"name"` - Tags []string `json:"tags"` - Metadata map[string]interface{} `json:"metadata"` - Nested *NestedBindingArg `json:"nested,omitempty"` -} - -type NestedBindingArg struct { - Value float64 `json:"value"` - Enabled bool `json:"enabled"` -} - -// Test data simulating frontend calls -var ( - simpleJSON = []byte(`{"name":"test","value":42}`) - - complexJSON = []byte(`{"id":12345,"name":"Test Complex Data","tags":["tag1","tag2","tag3","tag4","tag5"],"metadata":{"key1":"value1","key2":42,"key3":true},"nested":{"value":3.14159,"enabled":true}}`) - - stringJSON = []byte(`"hello world this is a test string"`) - - multiArgsJSON = [][]byte{ - []byte(`"arg1"`), - []byte(`42`), - []byte(`true`), - []byte(`{"key":"value"}`), - } -) - -// Configure jsoniter for maximum compatibility -var jsoniterStd = jsoniter.ConfigCompatibleWithStandardLibrary - -// ============================================================================ -// UNMARSHAL BENCHMARKS - This is the HOT PATH (bindings.go:289) -// ============================================================================ - -// --- Simple struct unmarshal --- - -func BenchmarkUnmarshal_Simple_StdLib(b *testing.B) { - for b.Loop() { - var arg SimpleBindingArg - _ = json.Unmarshal(simpleJSON, &arg) - } -} - -func BenchmarkUnmarshal_Simple_GoJSON(b *testing.B) { - for b.Loop() { - var arg SimpleBindingArg - _ = gojson.Unmarshal(simpleJSON, &arg) - } -} - -func BenchmarkUnmarshal_Simple_JSONIter(b *testing.B) { - for b.Loop() { - var arg SimpleBindingArg - _ = jsoniterStd.Unmarshal(simpleJSON, &arg) - } -} - -func BenchmarkUnmarshal_Simple_Sonic(b *testing.B) { - for b.Loop() { - var arg SimpleBindingArg - _ = sonic.Unmarshal(simpleJSON, &arg) - } -} - -// --- Complex struct unmarshal --- - -func BenchmarkUnmarshal_Complex_StdLib(b *testing.B) { - for b.Loop() { - var arg ComplexBindingArg - _ = json.Unmarshal(complexJSON, &arg) - } -} - -func BenchmarkUnmarshal_Complex_GoJSON(b *testing.B) { - for b.Loop() { - var arg ComplexBindingArg - _ = gojson.Unmarshal(complexJSON, &arg) - } -} - -func BenchmarkUnmarshal_Complex_JSONIter(b *testing.B) { - for b.Loop() { - var arg ComplexBindingArg - _ = jsoniterStd.Unmarshal(complexJSON, &arg) - } -} - -func BenchmarkUnmarshal_Complex_Sonic(b *testing.B) { - for b.Loop() { - var arg ComplexBindingArg - _ = sonic.Unmarshal(complexJSON, &arg) - } -} - -// --- String unmarshal (most common single arg) --- - -func BenchmarkUnmarshal_String_StdLib(b *testing.B) { - for b.Loop() { - var arg string - _ = json.Unmarshal(stringJSON, &arg) - } -} - -func BenchmarkUnmarshal_String_GoJSON(b *testing.B) { - for b.Loop() { - var arg string - _ = gojson.Unmarshal(stringJSON, &arg) - } -} - -func BenchmarkUnmarshal_String_JSONIter(b *testing.B) { - for b.Loop() { - var arg string - _ = jsoniterStd.Unmarshal(stringJSON, &arg) - } -} - -func BenchmarkUnmarshal_String_Sonic(b *testing.B) { - for b.Loop() { - var arg string - _ = sonic.Unmarshal(stringJSON, &arg) - } -} - -// --- Interface{} unmarshal (dynamic typing) --- - -func BenchmarkUnmarshal_Interface_StdLib(b *testing.B) { - for b.Loop() { - var arg interface{} - _ = json.Unmarshal(complexJSON, &arg) - } -} - -func BenchmarkUnmarshal_Interface_GoJSON(b *testing.B) { - for b.Loop() { - var arg interface{} - _ = gojson.Unmarshal(complexJSON, &arg) - } -} - -func BenchmarkUnmarshal_Interface_JSONIter(b *testing.B) { - for b.Loop() { - var arg interface{} - _ = jsoniterStd.Unmarshal(complexJSON, &arg) - } -} - -func BenchmarkUnmarshal_Interface_Sonic(b *testing.B) { - for b.Loop() { - var arg interface{} - _ = sonic.Unmarshal(complexJSON, &arg) - } -} - -// --- Multi-arg unmarshal (simulating typical method call) --- - -func BenchmarkUnmarshal_MultiArgs_StdLib(b *testing.B) { - for b.Loop() { - var s string - var i int - var bl bool - var m map[string]string - _ = json.Unmarshal(multiArgsJSON[0], &s) - _ = json.Unmarshal(multiArgsJSON[1], &i) - _ = json.Unmarshal(multiArgsJSON[2], &bl) - _ = json.Unmarshal(multiArgsJSON[3], &m) - } -} - -func BenchmarkUnmarshal_MultiArgs_GoJSON(b *testing.B) { - for b.Loop() { - var s string - var i int - var bl bool - var m map[string]string - _ = gojson.Unmarshal(multiArgsJSON[0], &s) - _ = gojson.Unmarshal(multiArgsJSON[1], &i) - _ = gojson.Unmarshal(multiArgsJSON[2], &bl) - _ = gojson.Unmarshal(multiArgsJSON[3], &m) - } -} - -func BenchmarkUnmarshal_MultiArgs_JSONIter(b *testing.B) { - for b.Loop() { - var s string - var i int - var bl bool - var m map[string]string - _ = jsoniterStd.Unmarshal(multiArgsJSON[0], &s) - _ = jsoniterStd.Unmarshal(multiArgsJSON[1], &i) - _ = jsoniterStd.Unmarshal(multiArgsJSON[2], &bl) - _ = jsoniterStd.Unmarshal(multiArgsJSON[3], &m) - } -} - -func BenchmarkUnmarshal_MultiArgs_Sonic(b *testing.B) { - for b.Loop() { - var s string - var i int - var bl bool - var m map[string]string - _ = sonic.Unmarshal(multiArgsJSON[0], &s) - _ = sonic.Unmarshal(multiArgsJSON[1], &i) - _ = sonic.Unmarshal(multiArgsJSON[2], &bl) - _ = sonic.Unmarshal(multiArgsJSON[3], &m) - } -} - -// ============================================================================ -// MARSHAL BENCHMARKS - Result serialization -// ============================================================================ - -type BindingResult struct { - Success bool `json:"success"` - Data interface{} `json:"data,omitempty"` - Error string `json:"error,omitempty"` -} - -var simpleResult = BindingResult{ - Success: true, - Data: "hello world", -} - -var complexResult = BindingResult{ - Success: true, - Data: ComplexBindingArg{ - ID: 12345, - Name: "Result Data", - Tags: []string{"a", "b", "c"}, - Metadata: map[string]interface{}{ - "processed": true, - "count": 100, - }, - Nested: &NestedBindingArg{Value: 2.718, Enabled: true}, - }, -} - -// --- Simple result marshal --- - -func BenchmarkMarshal_Simple_StdLib(b *testing.B) { - for b.Loop() { - _, _ = json.Marshal(simpleResult) - } -} - -func BenchmarkMarshal_Simple_GoJSON(b *testing.B) { - for b.Loop() { - _, _ = gojson.Marshal(simpleResult) - } -} - -func BenchmarkMarshal_Simple_JSONIter(b *testing.B) { - for b.Loop() { - _, _ = jsoniterStd.Marshal(simpleResult) - } -} - -func BenchmarkMarshal_Simple_Sonic(b *testing.B) { - for b.Loop() { - _, _ = sonic.Marshal(simpleResult) - } -} - -// --- Complex result marshal --- - -func BenchmarkMarshal_Complex_StdLib(b *testing.B) { - for b.Loop() { - _, _ = json.Marshal(complexResult) - } -} - -func BenchmarkMarshal_Complex_GoJSON(b *testing.B) { - for b.Loop() { - _, _ = gojson.Marshal(complexResult) - } -} - -func BenchmarkMarshal_Complex_JSONIter(b *testing.B) { - for b.Loop() { - _, _ = jsoniterStd.Marshal(complexResult) - } -} - -func BenchmarkMarshal_Complex_Sonic(b *testing.B) { - for b.Loop() { - _, _ = sonic.Marshal(complexResult) - } -} -*/ diff --git a/v3/pkg/application/json_v2_bench_test.go b/v3/pkg/application/json_v2_bench_test.go deleted file mode 100644 index d7b45193c..000000000 --- a/v3/pkg/application/json_v2_bench_test.go +++ /dev/null @@ -1,270 +0,0 @@ -//go:build bench && goexperiment.jsonv2 - -package application_test - -import ( - "encoding/json" - "encoding/json/jsontext" - jsonv2 "encoding/json/v2" - "testing" -) - -// Benchmark structures matching real Wails usage patterns - -type SimpleArg struct { - Name string `json:"name"` - Value int `json:"value"` -} - -type ComplexArg struct { - ID int `json:"id"` - Name string `json:"name"` - Tags []string `json:"tags"` - Metadata map[string]interface{} `json:"metadata"` - Nested *NestedArg `json:"nested,omitempty"` -} - -type NestedArg struct { - Value float64 `json:"value"` - Enabled bool `json:"enabled"` -} - -type CallResult struct { - Success bool `json:"success"` - Data interface{} `json:"data,omitempty"` - Error string `json:"error,omitempty"` -} - -// Test data -var ( - simpleArgJSON = []byte(`{"name":"test","value":42}`) - complexArgJSON = []byte(`{ - "id": 12345, - "name": "Test Complex Data", - "tags": ["tag1", "tag2", "tag3", "tag4", "tag5"], - "metadata": {"key1": "value1", "key2": 42, "key3": true}, - "nested": {"value": 3.14159, "enabled": true} - }`) - - simpleResult = CallResult{ - Success: true, - Data: "hello world", - } - - complexResult = CallResult{ - Success: true, - Data: ComplexArg{ - ID: 12345, - Name: "Result Data", - Tags: []string{"a", "b", "c"}, - Metadata: map[string]interface{}{ - "processed": true, - "count": 100, - }, - Nested: &NestedArg{Value: 2.718, Enabled: true}, - }, - } -) - -// === UNMARSHAL BENCHMARKS (argument parsing) === - -func BenchmarkJSONv1_Unmarshal_Simple(b *testing.B) { - for b.Loop() { - var arg SimpleArg - _ = json.Unmarshal(simpleArgJSON, &arg) - } -} - -func BenchmarkJSONv2_Unmarshal_Simple(b *testing.B) { - for b.Loop() { - var arg SimpleArg - _ = jsonv2.Unmarshal(simpleArgJSON, &arg) - } -} - -func BenchmarkJSONv1_Unmarshal_Complex(b *testing.B) { - for b.Loop() { - var arg ComplexArg - _ = json.Unmarshal(complexArgJSON, &arg) - } -} - -func BenchmarkJSONv2_Unmarshal_Complex(b *testing.B) { - for b.Loop() { - var arg ComplexArg - _ = jsonv2.Unmarshal(complexArgJSON, &arg) - } -} - -func BenchmarkJSONv1_Unmarshal_Interface(b *testing.B) { - for b.Loop() { - var arg interface{} - _ = json.Unmarshal(complexArgJSON, &arg) - } -} - -func BenchmarkJSONv2_Unmarshal_Interface(b *testing.B) { - for b.Loop() { - var arg interface{} - _ = jsonv2.Unmarshal(complexArgJSON, &arg) - } -} - -// === MARSHAL BENCHMARKS (result serialization) === - -func BenchmarkJSONv1_Marshal_Simple(b *testing.B) { - for b.Loop() { - _, _ = json.Marshal(simpleResult) - } -} - -func BenchmarkJSONv2_Marshal_Simple(b *testing.B) { - for b.Loop() { - _, _ = jsonv2.Marshal(simpleResult) - } -} - -func BenchmarkJSONv1_Marshal_Complex(b *testing.B) { - for b.Loop() { - _, _ = json.Marshal(complexResult) - } -} - -func BenchmarkJSONv2_Marshal_Complex(b *testing.B) { - for b.Loop() { - _, _ = jsonv2.Marshal(complexResult) - } -} - -// === RAW MESSAGE HANDLING (common in Wails bindings) === - -func BenchmarkJSONv1_RawMessage_Unmarshal(b *testing.B) { - raw := json.RawMessage(complexArgJSON) - for b.Loop() { - var arg ComplexArg - _ = json.Unmarshal(raw, &arg) - } -} - -func BenchmarkJSONv2_RawMessage_Unmarshal(b *testing.B) { - raw := jsontext.Value(complexArgJSON) - for b.Loop() { - var arg ComplexArg - _ = jsonv2.Unmarshal(raw, &arg) - } -} - -// === SLICE ARGUMENTS (common pattern) === - -var sliceArgJSON = []byte(`[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]`) -var largeSliceArgJSON = func() []byte { - data, _ := json.Marshal(make([]int, 100)) - return data -}() - -func BenchmarkJSONv1_Unmarshal_Slice(b *testing.B) { - for b.Loop() { - var arg []int - _ = json.Unmarshal(sliceArgJSON, &arg) - } -} - -func BenchmarkJSONv2_Unmarshal_Slice(b *testing.B) { - for b.Loop() { - var arg []int - _ = jsonv2.Unmarshal(sliceArgJSON, &arg) - } -} - -func BenchmarkJSONv1_Unmarshal_LargeSlice(b *testing.B) { - for b.Loop() { - var arg []int - _ = json.Unmarshal(largeSliceArgJSON, &arg) - } -} - -func BenchmarkJSONv2_Unmarshal_LargeSlice(b *testing.B) { - for b.Loop() { - var arg []int - _ = jsonv2.Unmarshal(largeSliceArgJSON, &arg) - } -} - -// === STRING ARGUMENT (most common) === - -var stringArgJSON = []byte(`"hello world this is a test string"`) - -func BenchmarkJSONv1_Unmarshal_String(b *testing.B) { - for b.Loop() { - var arg string - _ = json.Unmarshal(stringArgJSON, &arg) - } -} - -func BenchmarkJSONv2_Unmarshal_String(b *testing.B) { - for b.Loop() { - var arg string - _ = jsonv2.Unmarshal(stringArgJSON, &arg) - } -} - -// === MULTIPLE ARGUMENTS (simulating method call) === - -var multiArgJSON = [][]byte{ - []byte(`"arg1"`), - []byte(`42`), - []byte(`true`), - []byte(`{"key": "value"}`), -} - -func BenchmarkJSONv1_Unmarshal_MultiArgs(b *testing.B) { - for b.Loop() { - var s string - var i int - var bl bool - var m map[string]string - _ = json.Unmarshal(multiArgJSON[0], &s) - _ = json.Unmarshal(multiArgJSON[1], &i) - _ = json.Unmarshal(multiArgJSON[2], &bl) - _ = json.Unmarshal(multiArgJSON[3], &m) - } -} - -func BenchmarkJSONv2_Unmarshal_MultiArgs(b *testing.B) { - for b.Loop() { - var s string - var i int - var bl bool - var m map[string]string - _ = jsonv2.Unmarshal(multiArgJSON[0], &s) - _ = jsonv2.Unmarshal(multiArgJSON[1], &i) - _ = jsonv2.Unmarshal(multiArgJSON[2], &bl) - _ = jsonv2.Unmarshal(multiArgJSON[3], &m) - } -} - -// === ERROR RESPONSE MARSHALING === - -type ErrorResponse struct { - Code int `json:"code"` - Message string `json:"message"` - Details string `json:"details,omitempty"` -} - -var errorResp = ErrorResponse{ - Code: 500, - Message: "Internal server error", - Details: "Something went wrong while processing the request", -} - -func BenchmarkJSONv1_Marshal_Error(b *testing.B) { - for b.Loop() { - _, _ = json.Marshal(errorResp) - } -} - -func BenchmarkJSONv2_Marshal_Error(b *testing.B) { - for b.Loop() { - _, _ = jsonv2.Marshal(errorResp) - } -} diff --git a/v3/pkg/application/key_binding_manager.go b/v3/pkg/application/key_binding_manager.go deleted file mode 100644 index 64346d740..000000000 --- a/v3/pkg/application/key_binding_manager.go +++ /dev/null @@ -1,66 +0,0 @@ -package application - -// KeyBindingManager manages all key binding operations -type KeyBindingManager struct { - app *App -} - -// newKeyBindingManager creates a new KeyBindingManager instance -func newKeyBindingManager(app *App) *KeyBindingManager { - return &KeyBindingManager{ - app: app, - } -} - -// Add adds a key binding -func (kbm *KeyBindingManager) Add(accelerator string, callback func(window Window)) { - kbm.app.keyBindingsLock.Lock() - defer kbm.app.keyBindingsLock.Unlock() - kbm.app.keyBindings[accelerator] = callback -} - -// Remove removes a key binding -func (kbm *KeyBindingManager) Remove(accelerator string) { - kbm.app.keyBindingsLock.Lock() - defer kbm.app.keyBindingsLock.Unlock() - delete(kbm.app.keyBindings, accelerator) -} - -// Process processes a key binding and returns true if handled -func (kbm *KeyBindingManager) Process(accelerator string, window Window) bool { - kbm.app.keyBindingsLock.RLock() - callback, exists := kbm.app.keyBindings[accelerator] - kbm.app.keyBindingsLock.RUnlock() - - if exists && callback != nil { - callback(window) - return true - } - return false -} - -// KeyBinding represents a key binding with its accelerator and callback -type KeyBinding struct { - Accelerator string - Callback func(window Window) -} - -// GetAll returns all registered key bindings as a slice -func (kbm *KeyBindingManager) GetAll() []*KeyBinding { - kbm.app.keyBindingsLock.RLock() - defer kbm.app.keyBindingsLock.RUnlock() - - result := make([]*KeyBinding, 0, len(kbm.app.keyBindings)) - for accelerator, callback := range kbm.app.keyBindings { - result = append(result, &KeyBinding{ - Accelerator: accelerator, - Callback: callback, - }) - } - return result -} - -// HandleWindowKeyEvent handles window key events (internal use) -func (kbm *KeyBindingManager) handleWindowKeyEvent(event *windowKeyEvent) { - kbm.app.handleWindowKeyEvent(event) -} diff --git a/v3/pkg/application/keys.go b/v3/pkg/application/keys.go deleted file mode 100644 index 375b76289..000000000 --- a/v3/pkg/application/keys.go +++ /dev/null @@ -1,220 +0,0 @@ -package application - -import ( - "fmt" - "runtime" - "slices" - "strconv" - "strings" -) - -// modifier is actually a string -type modifier int - -const ( - // CmdOrCtrlKey represents Command on Mac and Control on other platforms - CmdOrCtrlKey modifier = 0 << iota - // OptionOrAltKey represents Option on Mac and Alt on other platforms - OptionOrAltKey modifier = 1 << iota - // ShiftKey represents the shift key on all systems - ShiftKey modifier = 2 << iota - // SuperKey represents Command on Mac and the Windows key on the other platforms - SuperKey modifier = 3 << iota - // ControlKey represents the control key on all systems - ControlKey modifier = 4 << iota -) - -func (m modifier) String() string { - return modifierStringMap[runtime.GOOS][m] -} - -var modifierStringMap = map[string]map[modifier]string{ - "windows": { - CmdOrCtrlKey: "Ctrl", - ControlKey: "Ctrl", - OptionOrAltKey: "Alt", - ShiftKey: "Shift", - SuperKey: "Win", - }, - "darwin": { - CmdOrCtrlKey: "Cmd", - ControlKey: "Ctrl", - OptionOrAltKey: "Option", - ShiftKey: "Shift", - SuperKey: "Cmd", - }, - "linux": { - CmdOrCtrlKey: "Ctrl", - ControlKey: "Ctrl", - OptionOrAltKey: "Alt", - ShiftKey: "Shift", - SuperKey: "Super", - }, -} - -var modifierMap = map[string]modifier{ - "cmdorctrl": CmdOrCtrlKey, - "cmd": CmdOrCtrlKey, - "command": CmdOrCtrlKey, - "ctrl": ControlKey, - "optionoralt": OptionOrAltKey, - "alt": OptionOrAltKey, - "option": OptionOrAltKey, - "shift": ShiftKey, - "super": SuperKey, -} - -// accelerator holds the keyboard shortcut for a menu item -type accelerator struct { - Key string - Modifiers []modifier -} - -func (a *accelerator) clone() *accelerator { - result := *a - return &result -} - -func (a *accelerator) String() string { - var result []string - // Sort modifiers - for _, modifier := range a.Modifiers { - result = append(result, modifier.String()) - } - slices.Sort(result) - if len(a.Key) > 0 { - result = append(result, strings.ToUpper(a.Key)) - } - return strings.Join(result, "+") -} - -var namedKeys = map[string]struct{}{ - "backspace": {}, - "tab": {}, - "return": {}, - "enter": {}, - "escape": {}, - "left": {}, - "right": {}, - "up": {}, - "down": {}, - "space": {}, - "delete": {}, - "home": {}, - "end": {}, - "page up": {}, - "page down": {}, - "f1": {}, - "f2": {}, - "f3": {}, - "f4": {}, - "f5": {}, - "f6": {}, - "f7": {}, - "f8": {}, - "f9": {}, - "f10": {}, - "f11": {}, - "f12": {}, - "f13": {}, - "f14": {}, - "f15": {}, - "f16": {}, - "f17": {}, - "f18": {}, - "f19": {}, - "f20": {}, - "f21": {}, - "f22": {}, - "f23": {}, - "f24": {}, - "f25": {}, - "f26": {}, - "f27": {}, - "f28": {}, - "f29": {}, - "f30": {}, - "f31": {}, - "f32": {}, - "f33": {}, - "f34": {}, - "f35": {}, - "numlock": {}, -} - -func parseKey(key string) (string, bool) { - - // Lowercase! - key = strings.ToLower(key) - - // Check special case - if key == "plus" { - return "+", true - } - - // Handle named keys - _, namedKey := namedKeys[key] - if namedKey { - return key, true - } - - // Check we only have a single character - if len(key) != 1 { - return "", false - } - - runeKey := rune(key[0]) - - // This may be too inclusive - if strconv.IsPrint(runeKey) { - return key, true - } - - return "", false - -} - -// parseAccelerator parses a string into an accelerator -func parseAccelerator(shortcut string) (*accelerator, error) { - - var result accelerator - - // Split the shortcut by + - components := strings.Split(shortcut, "+") - - // If we only have one it should be a key - // We require components - if len(components) == 0 { - return nil, fmt.Errorf("no components given to validateComponents") - } - - modifiers := map[modifier]struct{}{} - - // Check components - for index, component := range components { - - // If last component - if index == len(components)-1 { - processedKey, validKey := parseKey(component) - if !validKey { - return nil, fmt.Errorf("'%s' is not a valid key", component) - } - result.Key = strings.ToLower(processedKey) - continue - } - - // Not last component - needs to be modifier - lowercaseComponent := strings.ToLower(component) - thisModifier, valid := modifierMap[lowercaseComponent] - if !valid { - return nil, fmt.Errorf("'%s' is not a valid modifier", component) - } - // Save this data - modifiers[thisModifier] = struct{}{} - } - // return the keys as a slice - for thisModifier := range modifiers { - result.Modifiers = append(result.Modifiers, thisModifier) - } - return &result, nil -} diff --git a/v3/pkg/application/keys_android.go b/v3/pkg/application/keys_android.go deleted file mode 100644 index d63b07aa6..000000000 --- a/v3/pkg/application/keys_android.go +++ /dev/null @@ -1,9 +0,0 @@ -//go:build android - -package application - -// Android keyboard handling stub - -func acceleratorToString(accelerator *accelerator) string { - return "" -} diff --git a/v3/pkg/application/keys_darwin.go b/v3/pkg/application/keys_darwin.go deleted file mode 100644 index c76db0c5d..000000000 --- a/v3/pkg/application/keys_darwin.go +++ /dev/null @@ -1,28 +0,0 @@ -//go:build darwin && !ios - -package application - -const ( - NSEventModifierFlagShift = 1 << 17 // Set if Shift key is pressed. - NSEventModifierFlagControl = 1 << 18 // Set if Control key is pressed. - NSEventModifierFlagOption = 1 << 19 // Set if Option or Alternate key is pressed. - NSEventModifierFlagCommand = 1 << 20 // Set if Command key is pressed. -) - -// macModifierMap maps accelerator modifiers to macOS modifiers. -var macModifierMap = map[modifier]int{ - CmdOrCtrlKey: NSEventModifierFlagCommand, - ControlKey: NSEventModifierFlagControl, - OptionOrAltKey: NSEventModifierFlagOption, - ShiftKey: NSEventModifierFlagShift, - SuperKey: NSEventModifierFlagCommand, -} - -// toMacModifier converts the accelerator to a macOS modifier. -func toMacModifier(modifiers []modifier) int { - result := 0 - for _, modifier := range modifiers { - result |= macModifierMap[modifier] - } - return result -} diff --git a/v3/pkg/application/keys_ios.go b/v3/pkg/application/keys_ios.go deleted file mode 100644 index 3a3332b0b..000000000 --- a/v3/pkg/application/keys_ios.go +++ /dev/null @@ -1,20 +0,0 @@ -//go:build ios - -package application - -// iOS key codes - these would map to UIKeyCommand -const ( - KeyReturn = "Return" - KeyEscape = "Escape" - KeyDelete = "Delete" - KeyTab = "Tab" - KeySpace = "Space" - KeyUp = "Up" - KeyDown = "Down" - KeyLeft = "Left" - KeyRight = "Right" - KeyHome = "Home" - KeyEnd = "End" - KeyPageUp = "PageUp" - KeyPageDown = "PageDown" -) \ No newline at end of file diff --git a/v3/pkg/application/keys_linux.go b/v3/pkg/application/keys_linux.go deleted file mode 100644 index 542fba95f..000000000 --- a/v3/pkg/application/keys_linux.go +++ /dev/null @@ -1,165 +0,0 @@ -//go:build linux && !android && !server - -package application - -var VirtualKeyCodes = map[uint]string{ - 0xff08: "backspace", - 0xff09: "tab", - 0xff0a: "linefeed", - 0xff0b: "clear", - 0xff0d: "return", - 0xff13: "pause", - 0xff14: "scrolllock", - 0xff15: "sysreq", - 0xff1b: "escape", - 0xffff: "delete", - 0xff50: "home", - 0xff51: "left", - - 0xffe1: "lshift", - 0xffe2: "rshift", - 0xffe3: "lcontrol", - 0xffe4: "rcontrol", - 0xffeb: "lmeta", - 0xffec: "rmeta", - 0xffed: "lalt", - 0xffee: "ralt", - // Multi-Lang - 0xff21: "kanji", - 0xff22: "muhenkan", - 0xff24: "henkan", - 0xff25: "hiragana", - 0xff26: "katakana", - 0xff27: "hiragana/katakana", - 0xff28: "zenkaku", - 0xff29: "hankaku", - 0xff2a: "zenkaku/hankaku", - 0xff2b: "touroku", - 0xff2c: "massyo", - 0xff2d: "kana lock", - 0xff2e: "kana shift", - 0xff2f: "eisu shift", - 0xff30: "eisu toggle", - 0xff37: "kanji bangou", - - // Directions - 0xff52: "up", - 0xff53: "right", - 0xff54: "down", - 0xff55: "pageup", - 0xff56: "pagedown", - 0xff57: "end", - 0xff58: "begin", - - - // Alphabet - 0x41: "a", - 0x42: "b", - 0x43: "c", - 0x44: "d", - 0x45: "e", - 0x46: "f", - 0x47: "g", - 0x48: "h", - 0x49: "i", - 0x4a: "j", - 0x4b: "k", - 0x4c: "l", - 0x4d: "m", - 0x4e: "n", - 0x4f: "o", - 0x50: "p", - 0x51: "q", - 0x52: "r", - 0x53: "s", - 0x54: "t", - 0x55: "u", - 0x56: "v", - 0x57: "w", - 0x58: "x", - 0x59: "y", - 0x5a: "z", - - 0x5b: "lbracket", - 0x5c: "backslash", - 0x5d: "rbracket", - 0x5e: "caret", - 0x5f: "underscore", - 0x60: "grave", - // Capital Alphabet - 0x61: "a", - 0x62: "b", - 0x63: "c", - 0x64: "d", - 0x65: "e", - 0x66: "f", - 0x67: "g", - 0x68: "h", - 0x69: "i", - 0x6a: "j", - 0x6b: "k", - 0x6c: "l", - 0x6d: "m", - 0x6e: "n", - 0x6f: "o", - 0x70: "p", - 0x71: "q", - 0x72: "r", - 0x73: "s", - 0x74: "t", - 0x75: "u", - 0x76: "v", - 0x77: "w", - 0x78: "x", - 0x79: "y", - 0x7a: "z", - 0x7b: "lbrace", - 0x7c: "pipe", - 0x7d: "rbrace", - 0x7e: "tilde", - 0xa1: "exclam", - 0xa2: "cent", - 0xa3: "sterling", - 0xa4: "currency", - 0xa5: "yen", - 0xa6: "brokenbar", - 0xa7: "section", - 0xa8: "diaeresis", - 0xa9: "copyright", - 0xaa: "ordfeminine", - 0xab: "guillemotleft", - 0xad: "hyphen", - 0xae: "registered", - 0xaf: "macron", - 0xb0: "degree", - 0xb1: "plusminus", - 0xb2: "twosuperior", - - // Function Keys - 0xffbe: "f1", - 0xffbf: "f2", - 0xffc0: "f3", - 0xffc1: "f4", - 0xffc2: "f5", - 0xffc3: "f6", - 0xffc4: "f7", - 0xffc5: "f8", - 0xffc6: "f9", - 0xffc7: "f10", - 0xffc8: "f11", - 0xffc9: "f12", - 0xffca: "f13", - 0xffcb: "f14", - 0xffcc: "f15", - 0xffcd: "f16", - 0xffce: "f17", - 0xffcf: "f18", - 0xffd0: "f19", - 0xffd1: "f20", - 0xffd2: "f21", - 0xffd3: "f22", - 0xffd4: "f23", - 0xffd5: "f24", - - -} diff --git a/v3/pkg/application/keys_test.go b/v3/pkg/application/keys_test.go deleted file mode 100644 index 3651395ed..000000000 --- a/v3/pkg/application/keys_test.go +++ /dev/null @@ -1,293 +0,0 @@ -package application - -import ( - "runtime" - "strings" - "testing" -) - -func TestModifier_Constants(t *testing.T) { - // Verify modifier constants are distinct - modifiers := []modifier{CmdOrCtrlKey, OptionOrAltKey, ShiftKey, SuperKey, ControlKey} - seen := make(map[modifier]bool) - for _, m := range modifiers { - if seen[m] { - t.Errorf("Duplicate modifier value: %d", m) - } - seen[m] = true - } - - // CmdOrCtrlKey should be 0 (the base value) - if CmdOrCtrlKey != 0 { - t.Error("CmdOrCtrlKey should be 0") - } -} - -func TestParseKey_Valid(t *testing.T) { - tests := []struct { - input string - expected string - }{ - {"a", "a"}, - {"A", "a"}, - {"z", "z"}, - {"0", "0"}, - {"9", "9"}, - {"+", "+"}, // Single + is a valid printable character - {"plus", "+"}, - {"Plus", "+"}, - {"PLUS", "+"}, - {"backspace", "backspace"}, - {"Backspace", "backspace"}, - {"BACKSPACE", "backspace"}, - {"tab", "tab"}, - {"return", "return"}, - {"enter", "enter"}, - {"escape", "escape"}, - {"left", "left"}, - {"right", "right"}, - {"up", "up"}, - {"down", "down"}, - {"space", "space"}, - {"delete", "delete"}, - {"home", "home"}, - {"end", "end"}, - {"page up", "page up"}, - {"page down", "page down"}, - {"f1", "f1"}, - {"F1", "f1"}, - {"f12", "f12"}, - {"f35", "f35"}, - {"numlock", "numlock"}, - } - - for _, tt := range tests { - result, valid := parseKey(tt.input) - if tt.expected == "" { - if valid { - t.Errorf("parseKey(%q) should be invalid", tt.input) - } - } else { - if !valid { - t.Errorf("parseKey(%q) should be valid", tt.input) - } - if result != tt.expected { - t.Errorf("parseKey(%q) = %q, want %q", tt.input, result, tt.expected) - } - } - } -} - -func TestParseKey_Invalid(t *testing.T) { - tests := []string{ - "abc", // multiple chars - "", // empty - "notakey", // not a named key - "ctrl+a", // shortcut syntax - "backspac", // misspelled - } - - for _, tt := range tests { - _, valid := parseKey(tt) - if valid { - t.Errorf("parseKey(%q) should be invalid", tt) - } - } -} - -func TestParseAccelerator_Valid(t *testing.T) { - tests := []struct { - input string - key string - modCount int - }{ - {"a", "a", 0}, - {"Ctrl+A", "a", 1}, - {"ctrl+a", "a", 1}, - {"Ctrl+Shift+A", "a", 2}, - {"ctrl+shift+a", "a", 2}, - {"Cmd+A", "a", 1}, - {"Command+A", "a", 1}, - {"CmdOrCtrl+A", "a", 1}, - {"Alt+A", "a", 1}, - {"Option+A", "a", 1}, - {"OptionOrAlt+A", "a", 1}, - {"Shift+A", "a", 1}, - {"Super+A", "a", 1}, - {"Ctrl+Shift+Alt+A", "a", 3}, - {"Ctrl+plus", "+", 1}, - {"F1", "f1", 0}, - {"Ctrl+F12", "f12", 1}, - {"Ctrl+Shift+F1", "f1", 2}, - {"Ctrl+backspace", "backspace", 1}, - {"Ctrl+escape", "escape", 1}, - } - - for _, tt := range tests { - acc, err := parseAccelerator(tt.input) - if err != nil { - t.Errorf("parseAccelerator(%q) returned error: %v", tt.input, err) - continue - } - if acc.Key != tt.key { - t.Errorf("parseAccelerator(%q).Key = %q, want %q", tt.input, acc.Key, tt.key) - } - if len(acc.Modifiers) != tt.modCount { - t.Errorf("parseAccelerator(%q) has %d modifiers, want %d", tt.input, len(acc.Modifiers), tt.modCount) - } - } -} - -func TestParseAccelerator_Invalid(t *testing.T) { - tests := []struct { - input string - errMsg string - }{ - {"", "no components"}, - {"Ctrl+", "not a valid key"}, - {"Ctrl+abc", "not a valid key"}, - {"NotAModifier+A", "not a valid modifier"}, - {"Ctrl+Shift+notakey", "not a valid key"}, - } - - for _, tt := range tests { - _, err := parseAccelerator(tt.input) - if err == nil { - t.Errorf("parseAccelerator(%q) should return error", tt.input) - } - } -} - -func TestParseAccelerator_DuplicateModifiers(t *testing.T) { - // Duplicate modifiers should be deduplicated - acc, err := parseAccelerator("Ctrl+Ctrl+A") - if err != nil { - t.Errorf("parseAccelerator returned error: %v", err) - return - } - if len(acc.Modifiers) != 1 { - t.Errorf("Duplicate modifiers should be deduplicated, got %d modifiers", len(acc.Modifiers)) - } -} - -func TestAccelerator_Clone(t *testing.T) { - original := &accelerator{ - Key: "a", - Modifiers: []modifier{ControlKey, ShiftKey}, - } - - clone := original.clone() - - if clone == original { - t.Error("Clone should return a different pointer") - } - if clone.Key != original.Key { - t.Error("Clone should have same Key") - } - // Note: the slice reference is copied, so modifying the clone's slice would affect original - // This is a shallow clone -} - -func TestAccelerator_String(t *testing.T) { - // Test key-only accelerator (platform-independent) - acc := &accelerator{Key: "a", Modifiers: []modifier{}} - result := acc.String() - if result != "A" { - t.Errorf("accelerator.String() = %q, want %q", result, "A") - } - - // Test with ControlKey modifier - output varies by platform - acc = &accelerator{Key: "a", Modifiers: []modifier{ControlKey}} - result = acc.String() - // On macOS: "Ctrl+A", on Linux/Windows: "Ctrl+A" - // The representation should contain the key and be non-empty - if !strings.HasSuffix(result, "+A") && result != "A" { - t.Errorf("accelerator.String() = %q, expected to end with '+A'", result) - } - if result == "" { - t.Error("accelerator.String() should not return empty") - } - - // Test function key with modifier - acc = &accelerator{Key: "f1", Modifiers: []modifier{ControlKey}} - result = acc.String() - if !strings.HasSuffix(result, "+F1") { - t.Errorf("accelerator.String() = %q, expected to end with '+F1'", result) - } -} - -func TestAccelerator_String_PlatformSpecific(t *testing.T) { - // This test documents the expected platform-specific behavior - acc := &accelerator{Key: "a", Modifiers: []modifier{ControlKey}} - result := acc.String() - - switch runtime.GOOS { - case "darwin": - // On macOS, Ctrl key is represented as "Ctrl" (distinct from Cmd) - if !strings.Contains(result, "Ctrl") && !strings.Contains(result, "⌃") { - t.Logf("On macOS, got %q for ControlKey modifier", result) - } - case "linux", "windows": - if !strings.Contains(result, "Ctrl") { - t.Errorf("On %s, expected 'Ctrl' in result, got %q", runtime.GOOS, result) - } - } -} - -func TestAccelerator_StringWithMultipleModifiers(t *testing.T) { - acc := &accelerator{ - Key: "a", - Modifiers: []modifier{ShiftKey, ControlKey}, - } - - result := acc.String() - - // Result should contain both modifiers and the key - if result == "" { - t.Error("String() should not return empty") - } - // The modifiers are sorted, so order is deterministic -} - -func TestModifierMap_Contains(t *testing.T) { - expectedMappings := map[string]modifier{ - "cmdorctrl": CmdOrCtrlKey, - "cmd": CmdOrCtrlKey, - "command": CmdOrCtrlKey, - "ctrl": ControlKey, - "optionoralt": OptionOrAltKey, - "alt": OptionOrAltKey, - "option": OptionOrAltKey, - "shift": ShiftKey, - "super": SuperKey, - } - - for key, expected := range expectedMappings { - actual, ok := modifierMap[key] - if !ok { - t.Errorf("modifierMap should contain key %q", key) - } - if actual != expected { - t.Errorf("modifierMap[%q] = %v, want %v", key, actual, expected) - } - } -} - -func TestNamedKeys_Contains(t *testing.T) { - expectedKeys := []string{ - "backspace", "tab", "return", "enter", "escape", - "left", "right", "up", "down", "space", "delete", - "home", "end", "page up", "page down", - "f1", "f2", "f3", "f4", "f5", "f6", "f7", "f8", "f9", "f10", - "f11", "f12", "f13", "f14", "f15", "f16", "f17", "f18", "f19", "f20", - "f21", "f22", "f23", "f24", "f25", "f26", "f27", "f28", "f29", "f30", - "f31", "f32", "f33", "f34", "f35", - "numlock", - } - - for _, key := range expectedKeys { - if _, ok := namedKeys[key]; !ok { - t.Errorf("namedKeys should contain %q", key) - } - } -} diff --git a/v3/pkg/application/keys_windows.go b/v3/pkg/application/keys_windows.go deleted file mode 100644 index 8011a837d..000000000 --- a/v3/pkg/application/keys_windows.go +++ /dev/null @@ -1,230 +0,0 @@ -//go:build windows - -package application - -var VirtualKeyCodes = map[uint]string{ - 0x01: "lbutton", - 0x02: "rbutton", - 0x03: "cancel", - 0x04: "mbutton", - 0x05: "xbutton1", - 0x06: "xbutton2", - 0x08: "back", - 0x09: "tab", - 0x0C: "clear", - 0x0D: "return", - 0x10: "shift", - 0x11: "ctrl", - 0x12: "menu", - 0x13: "pause", - 0x14: "capital", - 0x15: "kana", - 0x17: "junja", - 0x18: "final", - 0x19: "hanja", - 0x1B: "escape", - 0x1C: "convert", - 0x1D: "nonconvert", - 0x1E: "accept", - 0x1F: "modechange", - 0x20: "space", - 0x21: "prior", - 0x22: "next", - 0x23: "end", - 0x24: "home", - 0x25: "left", - 0x26: "up", - 0x27: "right", - 0x28: "down", - 0x29: "select", - 0x2A: "print", - 0x2B: "execute", - 0x2C: "snapshot", - 0x2D: "insert", - 0x2E: "delete", - 0x2F: "help", - 0x30: "0", - 0x31: "1", - 0x32: "2", - 0x33: "3", - 0x34: "4", - 0x35: "5", - 0x36: "6", - 0x37: "7", - 0x38: "8", - 0x39: "9", - 0x41: "a", - 0x42: "b", - 0x43: "c", - 0x44: "d", - 0x45: "e", - 0x46: "f", - 0x47: "g", - 0x48: "h", - 0x49: "i", - 0x4A: "j", - 0x4B: "k", - 0x4C: "l", - 0x4D: "m", - 0x4E: "n", - 0x4F: "o", - 0x50: "p", - 0x51: "q", - 0x52: "r", - 0x53: "s", - 0x54: "t", - 0x55: "u", - 0x56: "v", - 0x57: "w", - 0x58: "x", - 0x59: "y", - 0x5A: "z", - 0x5B: "lwin", - 0x5C: "rwin", - 0x5D: "apps", - 0x5F: "sleep", - 0x60: "numpad0", - 0x61: "numpad1", - 0x62: "numpad2", - 0x63: "numpad3", - 0x64: "numpad4", - 0x65: "numpad5", - 0x66: "numpad6", - 0x67: "numpad7", - 0x68: "numpad8", - 0x69: "numpad9", - 0x6A: "multiply", - 0x6B: "add", - 0x6C: "separator", - 0x6D: "subtract", - 0x6E: "decimal", - 0x6F: "divide", - 0x70: "f1", - 0x71: "f2", - 0x72: "f3", - 0x73: "f4", - 0x74: "f5", - 0x75: "f6", - 0x76: "f7", - 0x77: "f8", - 0x78: "f9", - 0x79: "f10", - 0x7A: "f11", - 0x7B: "f12", - 0x7C: "f13", - 0x7D: "f14", - 0x7E: "f15", - 0x7F: "f16", - 0x80: "f17", - 0x81: "f18", - 0x82: "f19", - 0x83: "f20", - 0x84: "f21", - 0x85: "f22", - 0x86: "f23", - 0x87: "f24", - 0x88: "navigation_view", - 0x89: "navigation_menu", - 0x8A: "navigation_up", - 0x8B: "navigation_down", - 0x8C: "navigation_left", - 0x8D: "navigation_right", - 0x8E: "navigation_accept", - 0x8F: "navigation_cancel", - 0x90: "numlock", - 0x91: "scroll", - 0x92: "oem_nec_equal", - 0x93: "oem_fj_masshou", - 0x94: "oem_fj_touroku", - 0x95: "oem_fj_loya", - 0x96: "oem_fj_roya", - 0xA0: "lshift", - 0xA1: "rshift", - 0xA2: "lcontrol", - 0xA3: "rcontrol", - 0xA4: "lmenu", - 0xA5: "rmenu", - 0xA6: "browser_back", - 0xA7: "browser_forward", - 0xA8: "browser_refresh", - 0xA9: "browser_stop", - 0xAA: "browser_search", - 0xAB: "browser_favorites", - 0xAC: "browser_home", - 0xAD: "volume_mute", - 0xAE: "volume_down", - 0xAF: "volume_up", - 0xB0: "media_next_track", - 0xB1: "media_prev_track", - 0xB2: "media_stop", - 0xB3: "media_play_pause", - 0xB4: "launch_mail", - 0xB5: "launch_media_select", - 0xB6: "launch_app1", - 0xB7: "launch_app2", - 0xBA: "oem_1", - 0xBB: "oem_plus", - 0xBC: "oem_comma", - 0xBD: "oem_minus", - 0xBE: "oem_period", - 0xBF: "oem_2", - 0xC0: "oem_3", - 0xC3: "gamepad_a", - 0xC4: "gamepad_b", - 0xC5: "gamepad_x", - 0xC6: "gamepad_y", - 0xC7: "gamepad_right_shoulder", - 0xC8: "gamepad_left_shoulder", - 0xC9: "gamepad_left_trigger", - 0xCA: "gamepad_right_trigger", - 0xCB: "gamepad_dpad_up", - 0xCC: "gamepad_dpad_down", - 0xCD: "gamepad_dpad_left", - 0xCE: "gamepad_dpad_right", - 0xCF: "gamepad_menu", - 0xD0: "gamepad_view", - 0xD1: "gamepad_left_thumbstick_button", - 0xD2: "gamepad_right_thumbstick_button", - 0xD3: "gamepad_left_thumbstick_up", - 0xD4: "gamepad_left_thumbstick_down", - 0xD5: "gamepad_left_thumbstick_right", - 0xD6: "gamepad_left_thumbstick_left", - 0xD7: "gamepad_right_thumbstick_up", - 0xD8: "gamepad_right_thumbstick_down", - 0xD9: "gamepad_right_thumbstick_right", - 0xDA: "gamepad_right_thumbstick_left", - 0xDB: "oem_4", - 0xDC: "oem_5", - 0xDD: "oem_6", - 0xDE: "oem_7", - 0xDF: "oem_8", - 0xE1: "oem_ax", - 0xE2: "oem_102", - 0xE3: "ico_help", - 0xE4: "ico_00", - 0xE5: "processkey", - 0xE6: "ico_clear", - 0xE7: "packet", - 0xE9: "oem_reset", - 0xEA: "oem_jump", - 0xEB: "oem_pa1", - 0xEC: "oem_pa2", - 0xED: "oem_pa3", - 0xEE: "oem_wsctrl", - 0xEF: "oem_cusel", - 0xF0: "oem_attn", - 0xF1: "oem_finish", - 0xF2: "oem_copy", - 0xF3: "oem_auto", - 0xF4: "oem_enlw", - 0xF5: "oem_backtab", - 0xF6: "attn", - 0xF7: "crsel", - 0xF8: "exsel", - 0xF9: "ereof", - 0xFA: "play", - 0xFB: "zoom", - 0xFC: "noname", - 0xFD: "pa1", - 0xFE: "oem_clear", -} diff --git a/v3/pkg/application/linux_cgo.go b/v3/pkg/application/linux_cgo.go deleted file mode 100644 index ee7add761..000000000 --- a/v3/pkg/application/linux_cgo.go +++ /dev/null @@ -1,2296 +0,0 @@ -//go:build linux && cgo && !gtk4 && !android && !server - -package application - -import ( - "fmt" - "strings" - "sync" - "time" - "unsafe" - - "github.com/wailsapp/wails/v3/internal/assetserver/webview" - - "github.com/wailsapp/wails/v3/pkg/events" -) - -/* -#cgo linux pkg-config: gtk+-3.0 webkit2gtk-4.1 gdk-3.0 - -#include -#include -#include -#include -#include -#include -// Use NON_UNIQUE to allow multiple instances of the application to run. -// This matches the behavior of gtk_init/gtk_main used in v2. -#define APPLICATION_DEFAULT_FLAGS G_APPLICATION_NON_UNIQUE - -typedef struct CallbackID -{ - unsigned int value; -} CallbackID; - -extern void dispatchOnMainThreadCallback(unsigned int); - -static gboolean dispatchCallback(gpointer data) { - struct CallbackID *args = data; - unsigned int cid = args->value; - dispatchOnMainThreadCallback(cid); - free(args); - - return G_SOURCE_REMOVE; -}; - -static void dispatchOnMainThread(unsigned int id) { - CallbackID *args = malloc(sizeof(CallbackID)); - args->value = id; - g_idle_add((GSourceFunc)dispatchCallback, (gpointer)args); -} - -typedef struct WindowEvent { - uint id; - uint event; -} WindowEvent; - -static void save_window_id(void *object, uint value) -{ - g_object_set_data((GObject *)object, "windowid", GUINT_TO_POINTER((guint)value)); -} - -static void save_webview_to_content_manager(void *contentManager, void *webview) -{ - g_object_set_data(G_OBJECT((WebKitUserContentManager *)contentManager), "webview", webview); -} - -static WebKitWebView* get_webview_from_content_manager(void *contentManager) -{ - return WEBKIT_WEB_VIEW(g_object_get_data(G_OBJECT(contentManager), "webview")); -} - -static guint get_window_id(void *object) -{ - return GPOINTER_TO_UINT(g_object_get_data((GObject *)object, "windowid")); -} - -// exported below -void activateLinux(gpointer data); -extern void emit(WindowEvent* data); -extern gboolean handleConfigureEvent(GtkWidget*, GdkEventConfigure*, uintptr_t); -extern gboolean handleDeleteEvent(GtkWidget*, GdkEvent*, uintptr_t); -extern gboolean handleFocusEvent(GtkWidget*, GdkEvent*, uintptr_t); -extern void handleLoadChanged(WebKitWebView*, WebKitLoadEvent, uintptr_t); -void handleClick(void*); -extern gboolean onButtonEvent(GtkWidget *widget, GdkEventButton *event, uintptr_t user_data); -extern gboolean onMenuButtonEvent(GtkWidget *widget, GdkEventButton *event, uintptr_t user_data); -extern void onUriList(char **extracted, gint x, gint y, gpointer data); -extern void onDragEnter(gpointer data); -extern void onDragLeave(gpointer data); -extern void onDragOver(gint x, gint y, gpointer data); -extern gboolean onKeyPressEvent (GtkWidget *widget, GdkEventKey *event, uintptr_t user_data); -extern void onProcessRequest(WebKitURISchemeRequest *request, uintptr_t user_data); -extern void sendMessageToBackend(WebKitUserContentManager *contentManager, WebKitJavascriptResult *result, void *data); -// exported below (end) - -static void signal_connect(void *widget, char *event, void *cb, void* data) { - // g_signal_connect is a macro and can't be called directly - g_signal_connect(widget, event, cb, data); -} - -static WebKitWebView* webkit_web_view(GtkWidget *webview) { - return WEBKIT_WEB_VIEW(webview); -} - -static void* new_message_dialog(GtkWindow *parent, const gchar *msg, int dialogType, bool hasButtons) { - // gtk_message_dialog_new is variadic! Can't call from cgo directly - GtkWidget *dialog; - int buttonMask; - - // buttons will be added after creation - buttonMask = GTK_BUTTONS_OK; - if (hasButtons) { - buttonMask = GTK_BUTTONS_NONE; - } - - dialog = gtk_message_dialog_new( - parent, - GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT, - dialogType, - buttonMask, - "%s", - msg); - - // g_signal_connect_swapped (dialog, - // "response", - // G_CALLBACK (callback), - // dialog); - return dialog; -}; - -extern void messageDialogCB(gint button); - -static void* gtkFileChooserDialogNew(char* title, GtkWindow* window, GtkFileChooserAction action, char* cancelLabel, char* acceptLabel) { - // gtk_file_chooser_dialog_new is variadic! Can't call from cgo directly - return (GtkFileChooser*)gtk_file_chooser_dialog_new( - title, - window, - action, - cancelLabel, - GTK_RESPONSE_CANCEL, - acceptLabel, - GTK_RESPONSE_ACCEPT, - NULL); -} - -typedef struct Screen { - const char* id; - const char* name; - int p_width; - int p_height; - int width; - int height; - int x; - int y; - int w_width; - int w_height; - int w_x; - int w_y; - float scaleFactor; - double rotation; - bool isPrimary; -} Screen; - -// Signal handler fix for WebKit/GTK compatibility. -// CREDIT: https://github.com/rainycape/magick -// -// WebKit/GTK may install signal handlers without SA_ONSTACK, which causes -// Go to crash when handling signals (e.g., during panic recovery). -// This code adds SA_ONSTACK to signal handlers after WebKit initialization. -// -// Known limitation: Due to Go issue #7227 (golang/go#7227), signals may still -// be delivered on the wrong stack in some cases when C libraries are involved. -// This is a fundamental Go runtime limitation that cannot be fully resolved here. -#include -#include -#include -#include - -static void fix_signal(int signum) { - struct sigaction st; - - if (sigaction(signum, NULL, &st) < 0) { - goto fix_signal_error; - } - st.sa_flags |= SA_ONSTACK; - if (sigaction(signum, &st, NULL) < 0) { - goto fix_signal_error; - } - return; -fix_signal_error: - fprintf(stderr, "error fixing handler for signal %d, please " - "report this issue to " - "https://github.com/wailsapp/wails: %s\n", - signum, strerror(errno)); -} - -static void install_signal_handlers() { - #if defined(SIGCHLD) - fix_signal(SIGCHLD); - #endif - #if defined(SIGHUP) - fix_signal(SIGHUP); - #endif - #if defined(SIGINT) - fix_signal(SIGINT); - #endif - #if defined(SIGQUIT) - fix_signal(SIGQUIT); - #endif - #if defined(SIGABRT) - fix_signal(SIGABRT); - #endif - #if defined(SIGFPE) - fix_signal(SIGFPE); - #endif - #if defined(SIGTERM) - fix_signal(SIGTERM); - #endif - #if defined(SIGBUS) - fix_signal(SIGBUS); - #endif - #if defined(SIGSEGV) - fix_signal(SIGSEGV); - #endif - #if defined(SIGXCPU) - fix_signal(SIGXCPU); - #endif - #if defined(SIGXFSZ) - fix_signal(SIGXFSZ); - #endif -} - -static int GetNumScreens(){ - return 0; -} - -// Handle file drops from the OS - called when drag data is received -static void on_drag_data_received(GtkWidget *widget, GdkDragContext *context, gint x, gint y, - GtkSelectionData *selection_data, guint target_type, guint time, - gpointer data) -{ - // Only process target_type 2 which is our text/uri-list - // Other target types are from internal WebKit drags - if (target_type != 2) { - return; // Don't interfere with internal drags - } - - // Check if we have valid data - if (selection_data == NULL || gtk_selection_data_get_length(selection_data) <= 0) { - gtk_drag_finish(context, FALSE, FALSE, time); - return; - } - - const gchar *uri_data = (const gchar *)gtk_selection_data_get_data(selection_data); - gchar **filenames = g_uri_list_extract_uris(uri_data); - if (filenames == NULL || filenames[0] == NULL) { - if (filenames) g_strfreev(filenames); - gtk_drag_finish(context, FALSE, FALSE, time); - return; - } - - // Build file array for Go - GPtrArray *file_array = g_ptr_array_new(); - int iter = 0; - while (filenames[iter] != NULL) { - char *filename = g_filename_from_uri(filenames[iter], NULL, NULL); - if (filename != NULL) { - g_ptr_array_add(file_array, filename); - } - iter++; - } - g_strfreev(filenames); - - if (file_array->len > 0) { - // Get stored drop coordinates and data pointer - gint drop_x = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(widget), "drop-x")); - gint drop_y = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(widget), "drop-y")); - gpointer drop_data = g_object_get_data(G_OBJECT(widget), "drop-data"); - - // Add NULL terminator and call Go - g_ptr_array_add(file_array, NULL); - onUriList((gchar **)file_array->pdata, drop_x, drop_y, drop_data); - } - - // Cleanup - for (guint i = 0; i < file_array->len; i++) { - gpointer item = g_ptr_array_index(file_array, i); - if (item) g_free(item); - } - g_ptr_array_free(file_array, TRUE); - - // Finish the drag successfully to prevent WebKit from opening the file - gtk_drag_finish(context, TRUE, FALSE, time); -} - -// Track if we've notified about drag entering -static gboolean drag_entered = FALSE; - -// Track if a drag started from within the webview (internal HTML5 drag) -static gboolean internal_drag_active = FALSE; - -// Called when a drag starts FROM this widget (internal drag) -static void on_drag_begin(GtkWidget *widget, GdkDragContext *context, gpointer data) -{ - internal_drag_active = TRUE; -} - -// Called when a drag that started from this widget ends -static void on_drag_end(GtkWidget *widget, GdkDragContext *context, gpointer data) -{ - internal_drag_active = FALSE; -} - -// Check if a drag context contains file URIs (external drop) -// Returns TRUE only for external file manager drops, FALSE for internal HTML5 drags -static gboolean is_file_drag(GdkDragContext *context) -{ - GList *targets = gdk_drag_context_list_targets(context); - - // Internal HTML5 drags have WebKit-specific targets, external file drops have text/uri-list - for (GList *l = targets; l != NULL; l = l->next) { - GdkAtom atom = GDK_POINTER_TO_ATOM(l->data); - gchar *name = gdk_atom_name(atom); - if (name) { - gboolean is_uri = g_strcmp0(name, "text/uri-list") == 0; - g_free(name); - if (is_uri) { - return TRUE; - } - } - } - return FALSE; -} - -// Handle the actual drop - called when user releases mouse button -static gboolean on_drag_drop(GtkWidget *widget, GdkDragContext *context, gint x, gint y, - guint time, gpointer data) -{ - // Only handle external file drops, let WebKit handle internal HTML5 drags - if (!is_file_drag(context)) { - return FALSE; - } - - // Reset drag entered state - drag_entered = FALSE; - - // Store coordinates for use in drag-data-received - g_object_set_data(G_OBJECT(widget), "drop-x", GINT_TO_POINTER(x)); - g_object_set_data(G_OBJECT(widget), "drop-y", GINT_TO_POINTER(y)); - g_object_set_data(G_OBJECT(widget), "drop-data", data); - - // Request the file data - this triggers drag-data-received - GdkAtom target = gdk_atom_intern("text/uri-list", FALSE); - gtk_drag_get_data(widget, context, target, time); - - return TRUE; -} - -// Handle drag-motion for hover effects on external file drags -static gboolean on_drag_motion(GtkWidget *widget, GdkDragContext *context, gint x, gint y, guint time, gpointer data) -{ - // Don't handle internal HTML5 drags - if (internal_drag_active || !is_file_drag(context)) { - return FALSE; - } - - gdk_drag_status(context, GDK_ACTION_COPY, time); - - // Notify JS once when drag enters - if (!drag_entered) { - drag_entered = TRUE; - onDragEnter(data); - } - - // Send position to JS for hover effects (Go side throttles this) - onDragOver(x, y, data); - - return TRUE; -} - -// Handle drag-leave - drag exited the window -static void on_drag_leave(GtkWidget *widget, GdkDragContext *context, guint time, gpointer data) -{ - // Don't handle internal HTML5 drags - if (internal_drag_active || !is_file_drag(context)) { - return; - } - - if (drag_entered) { - drag_entered = FALSE; - onDragLeave(data); - } -} - -// Set up drag and drop handlers for external file drops with hover effects -static void enableDND(GtkWidget *widget, gpointer data) -{ - // Core handlers for file drop - g_signal_connect(G_OBJECT(widget), "drag-data-received", G_CALLBACK(on_drag_data_received), data); - g_signal_connect(G_OBJECT(widget), "drag-drop", G_CALLBACK(on_drag_drop), data); - - // Hover effect handlers - return FALSE for internal drags to let WebKit handle them - g_signal_connect(G_OBJECT(widget), "drag-motion", G_CALLBACK(on_drag_motion), data); - g_signal_connect(G_OBJECT(widget), "drag-leave", G_CALLBACK(on_drag_leave), data); -} - -// Block external file drops - consume the events to prevent WebKit from navigating to files -// Returns TRUE for file drags to consume them, FALSE for internal HTML5 drags to let WebKit handle -static gboolean on_drag_drop_blocked(GtkWidget *widget, GdkDragContext *context, gint x, gint y, - guint time, gpointer data) -{ - if (!is_file_drag(context)) { - return FALSE; // Let WebKit handle internal HTML5 drags - } - // Block external file drops by finishing with failure - gtk_drag_finish(context, FALSE, FALSE, time); - return TRUE; -} - -static gboolean on_drag_motion_blocked(GtkWidget *widget, GdkDragContext *context, gint x, gint y, guint time, gpointer data) -{ - if (internal_drag_active || !is_file_drag(context)) { - return FALSE; // Let WebKit handle internal HTML5 drags - } - // Show "no drop" cursor for external file drags - gdk_drag_status(context, 0, time); - return TRUE; -} - -// Set up handlers that block external file drops while allowing internal HTML5 drag-and-drop -static void disableDND(GtkWidget *widget, gpointer data) -{ - g_signal_connect(G_OBJECT(widget), "drag-drop", G_CALLBACK(on_drag_drop_blocked), data); - g_signal_connect(G_OBJECT(widget), "drag-motion", G_CALLBACK(on_drag_motion_blocked), data); -} -*/ -import "C" - -// Calloc handles alloc/dealloc of C data -type Calloc struct { - pool []unsafe.Pointer -} - -// NewCalloc creates a new allocator -func NewCalloc() Calloc { - return Calloc{} -} - -// String creates a new C string and retains a reference to it -func (c Calloc) String(in string) *C.char { - result := C.CString(in) - c.pool = append(c.pool, unsafe.Pointer(result)) - return result -} - -// Free frees all allocated C memory -func (c Calloc) Free() { - for _, str := range c.pool { - C.free(str) - } - c.pool = []unsafe.Pointer{} -} - -type windowPointer *C.GtkWindow -type identifier C.uint -type pointer unsafe.Pointer -type GSList C.GSList -type GSListPointer *GSList - -// getLinuxWebviewWindow safely extracts a linuxWebviewWindow from a Window interface -// Returns nil if the window is not a WebviewWindow or not a Linux implementation -func getLinuxWebviewWindow(window Window) *linuxWebviewWindow { - if window == nil { - return nil - } - - webviewWindow, ok := window.(*WebviewWindow) - if !ok { - return nil - } - - lw, ok := webviewWindow.impl.(*linuxWebviewWindow) - if !ok { - return nil - } - - return lw -} - -var ( - nilPointer pointer = nil - nilRadioGroup GSListPointer = nil -) - -var ( - gtkSignalToMenuItem map[uint]*MenuItem - mainThreadId *C.GThread -) - -var registerURIScheme sync.Once -var fixSignalHandlers sync.Once - -func init() { - gtkSignalToMenuItem = map[uint]*MenuItem{} - - mainThreadId = C.g_thread_self() -} - -// mainthread stuff -func dispatchOnMainThread(id uint) { - C.dispatchOnMainThread(C.uint(id)) -} - -//export dispatchOnMainThreadCallback -func dispatchOnMainThreadCallback(callbackID C.uint) { - executeOnMainThread(uint(callbackID)) -} - -//export activateLinux -func activateLinux(data pointer) { - processApplicationEvent(C.uint(events.Linux.ApplicationStartup), data) -} - -//export processApplicationEvent -func processApplicationEvent(eventID C.uint, data pointer) { - event := newApplicationEvent(events.ApplicationEventType(eventID)) - - //if data != nil { - // dataCStrJSON := C.serializationNSDictionary(data) - // if dataCStrJSON != nil { - // defer C.free(unsafe.Pointer(dataCStrJSON)) - // - // dataJSON := C.GoString(dataCStrJSON) - // var result map[string]any - // err := json.Unmarshal([]byte(dataJSON), &result) - // - // if err != nil { - // panic(err) - // } - // - // event.Context().setData(result) - // } - //} - - switch event.Id { - case uint(events.Linux.SystemThemeChanged): - isDark := globalApplication.Env.IsDarkMode() - event.Context().setIsDarkMode(isDark) - } - applicationEvents <- event -} - -func isOnMainThread() bool { - threadId := C.g_thread_self() - return threadId == mainThreadId -} - -// implementation below -func appName() string { - name := C.g_get_application_name() - defer C.free(unsafe.Pointer(name)) - return C.GoString(name) -} - -func appNew(name string) pointer { - // Name is already sanitized by sanitizeAppName() in application_linux.go - appId := fmt.Sprintf("org.wails.%s", name) - nameC := C.CString(appId) - defer C.free(unsafe.Pointer(nameC)) - return pointer(C.gtk_application_new(nameC, C.APPLICATION_DEFAULT_FLAGS)) -} - -func setProgramName(prgName string) { - cPrgName := C.CString(prgName) - defer C.free(unsafe.Pointer(cPrgName)) - C.g_set_prgname(cPrgName) -} - -func appRun(app pointer) error { - application := (*C.GApplication)(app) - //TODO: Only set this if we configure it to do so - C.g_application_hold(application) // allows it to run without a window - - signal := C.CString("activate") - defer C.free(unsafe.Pointer(signal)) - C.signal_connect(unsafe.Pointer(application), signal, C.activateLinux, nil) - status := C.g_application_run(application, 0, nil) - C.g_application_release(application) - C.g_object_unref(C.gpointer(app)) - - var err error - if status != 0 { - err = fmt.Errorf("exit code: %d", status) - } - return err -} - -func appDestroy(application pointer) { - C.g_application_quit((*C.GApplication)(application)) -} - -func (w *linuxWebviewWindow) contextMenuSignals(menu pointer) { - c := NewCalloc() - defer c.Free() - winID := unsafe.Pointer(uintptr(C.uint(w.parent.ID()))) - C.signal_connect(unsafe.Pointer(menu), c.String("button-release-event"), C.onMenuButtonEvent, winID) -} - -func (w *linuxWebviewWindow) contextMenuShow(menu pointer, data *ContextMenuData) { - geometry := C.GdkRectangle{ - x: C.int(data.X), - y: C.int(data.Y), - } - event := C.GdkEvent{} - gdkWindow := C.gtk_widget_get_window(w.gtkWidget()) - C.gtk_menu_popup_at_rect( - (*C.GtkMenu)(menu), - gdkWindow, - (*C.GdkRectangle)(&geometry), - C.GDK_GRAVITY_NORTH_WEST, - C.GDK_GRAVITY_NORTH_WEST, - (*C.GdkEvent)(&event), - ) - w.ctxMenuOpened = true -} - -func (a *linuxApp) getCurrentWindowID() uint { - // TODO: Add extra metadata to window and use it! - window := (*C.GtkWindow)(C.gtk_application_get_active_window((*C.GtkApplication)(a.application))) - if window == nil { - return uint(1) - } - identifier, ok := a.windowMap[window] - if ok { - return identifier - } - // FIXME: Should we panic here if not found? - return uint(1) -} - -func (a *linuxApp) getWindows() []pointer { - result := []pointer{} - windows := C.gtk_application_get_windows((*C.GtkApplication)(a.application)) - for { - result = append(result, pointer(windows.data)) - windows = windows.next - if windows == nil { - return result - } - } -} - -func (a *linuxApp) hideAllWindows() { - for _, window := range a.getWindows() { - C.gtk_widget_hide((*C.GtkWidget)(window)) - } -} - -func (a *linuxApp) showAllWindows() { - for _, window := range a.getWindows() { - C.gtk_window_present((*C.GtkWindow)(window)) - } -} - -func (a *linuxApp) setIcon(icon []byte) { - if len(icon) == 0 { - return - } - // Use g_bytes_new instead of g_bytes_new_static because Go memory can be - // moved or freed by the GC. g_bytes_new copies the data to C-owned memory. - gbytes := C.g_bytes_new(C.gconstpointer(unsafe.Pointer(&icon[0])), C.ulong(len(icon))) - defer C.g_bytes_unref(gbytes) - stream := C.g_memory_input_stream_new_from_bytes(gbytes) - defer C.g_object_unref(C.gpointer(stream)) - var gerror *C.GError - pixbuf := C.gdk_pixbuf_new_from_stream(stream, nil, &gerror) - if gerror != nil { - a.parent.error("failed to load application icon: %s", C.GoString(gerror.message)) - C.g_error_free(gerror) - return - } - - a.icon = pointer(pixbuf) -} - -// Clipboard -func clipboardGet() string { - clip := C.gtk_clipboard_get(C.GDK_SELECTION_CLIPBOARD) - text := C.gtk_clipboard_wait_for_text(clip) - return C.GoString(text) -} - -func clipboardSet(text string) { - cText := C.CString(text) - clip := C.gtk_clipboard_get(C.GDK_SELECTION_CLIPBOARD) - C.gtk_clipboard_set_text(clip, cText, -1) - - clip = C.gtk_clipboard_get(C.GDK_SELECTION_PRIMARY) - C.gtk_clipboard_set_text(clip, cText, -1) - C.free(unsafe.Pointer(cText)) -} - -// Menu -func menuAddSeparator(menu *Menu) { - C.gtk_menu_shell_append( - (*C.GtkMenuShell)((menu.impl).(*linuxMenu).native), - C.gtk_separator_menu_item_new()) -} - -func menuAppend(parent *Menu, menu *MenuItem) { - C.gtk_menu_shell_append( - (*C.GtkMenuShell)((parent.impl).(*linuxMenu).native), - (*C.GtkWidget)((menu.impl).(*linuxMenuItem).native), - ) - /* gtk4 - C.gtk_menu_item_set_submenu( - (*C.struct__GtkMenuItem)((menu.impl).(*linuxMenuItem).native), - (*C.struct__GtkWidget)((parent.impl).(*linuxMenu).native), - ) - */ -} - -func menuBarNew() pointer { - return pointer(C.gtk_menu_bar_new()) -} - -func menuNew() pointer { - return pointer(C.gtk_menu_new()) -} - -func menuSetSubmenu(item *MenuItem, menu *Menu) { - C.gtk_menu_item_set_submenu( - (*C.GtkMenuItem)((item.impl).(*linuxMenuItem).native), - (*C.GtkWidget)((menu.impl).(*linuxMenu).native)) -} - -func menuGetRadioGroup(item *linuxMenuItem) *GSList { - return (*GSList)(C.gtk_radio_menu_item_get_group((*C.GtkRadioMenuItem)(item.native))) -} - -func menuClear(menu *Menu) { - menuShell := (*C.GtkMenuShell)((menu.impl).(*linuxMenu).native) - children := C.gtk_container_get_children((*C.GtkContainer)(unsafe.Pointer(menuShell))) - if children != nil { - // Save the original pointer to free later - originalList := children - // Iterate through all children and remove them - for children != nil { - child := (*C.GtkWidget)(children.data) - if child != nil { - C.gtk_container_remove((*C.GtkContainer)(unsafe.Pointer(menuShell)), child) - } - children = children.next - } - C.g_list_free(originalList) - } -} - -//export handleClick -func handleClick(idPtr unsafe.Pointer) { - ident := C.CString("id") - defer C.free(unsafe.Pointer(ident)) - value := C.g_object_get_data((*C.GObject)(idPtr), ident) - id := uint(*(*C.uint)(value)) - item, ok := gtkSignalToMenuItem[id] - if !ok { - return - } - switch item.itemType { - case text, checkbox: - menuItemClicked <- item.id - case radio: - menuItem := (item.impl).(*linuxMenuItem) - if menuItem.isChecked() { - menuItemClicked <- item.id - } - } -} - -func attachMenuHandler(item *MenuItem) uint { - signal := C.CString("activate") - defer C.free(unsafe.Pointer(signal)) - impl := (item.impl).(*linuxMenuItem) - widget := impl.native - flags := C.GConnectFlags(0) - handlerId := C.g_signal_connect_object( - C.gpointer(widget), - signal, - C.GCallback(C.handleClick), - C.gpointer(widget), - flags) - - id := C.uint(item.id) - ident := C.CString("id") - defer C.free(unsafe.Pointer(ident)) - C.g_object_set_data( - (*C.GObject)(widget), - ident, - C.gpointer(&id), - ) - - gtkSignalToMenuItem[item.id] = item - return uint(handlerId) -} - -// menuItem -func menuItemChecked(widget pointer) bool { - if C.gtk_check_menu_item_get_active((*C.GtkCheckMenuItem)(widget)) == C.int(1) { - return true - } - return false -} - -func menuItemNew(label string, bitmap []byte) pointer { - return menuItemAddProperties(C.gtk_menu_item_new(), label, bitmap) -} - -func menuItemDestroy(widget pointer) { - C.gtk_widget_destroy((*C.GtkWidget)(widget)) -} - -func menuItemAddProperties(menuItem *C.GtkWidget, label string, bitmap []byte) pointer { - /* - // FIXME: Support accelerator configuration - activate := C.CString("activate") - defer C.free(unsafe.Pointer(activate)) - accelGroup := C.gtk_accel_group_new() - C.gtk_widget_add_accelerator(menuItem, activate, accelGroup, - C.GDK_KEY_m, C.GDK_CONTROL_MASK, C.GTK_ACCEL_VISIBLE) - */ - cLabel := C.CString(label) - defer C.free(unsafe.Pointer(cLabel)) - lbl := unsafe.Pointer(C.gtk_accel_label_new(cLabel)) - C.gtk_label_set_use_underline((*C.GtkLabel)(lbl), 1) - C.gtk_label_set_xalign((*C.GtkLabel)(lbl), 0.0) - C.gtk_accel_label_set_accel_widget( - (*C.GtkAccelLabel)(lbl), - (*C.GtkWidget)(unsafe.Pointer(menuItem))) - - box := C.gtk_box_new(C.GTK_ORIENTATION_HORIZONTAL, 6) - if img, err := pngToImage(bitmap); err == nil && len(img.Pix) > 0 { - // Use g_bytes_new instead of g_bytes_new_static because Go memory can be - // moved or freed by the GC. g_bytes_new copies the data to C-owned memory. - gbytes := C.g_bytes_new(C.gconstpointer(unsafe.Pointer(&img.Pix[0])), - C.ulong(len(img.Pix))) - defer C.g_bytes_unref(gbytes) - pixBuf := C.gdk_pixbuf_new_from_bytes( - gbytes, - C.GDK_COLORSPACE_RGB, - 1, // has_alpha - 8, - C.int(img.Bounds().Dx()), - C.int(img.Bounds().Dy()), - C.int(img.Stride), - ) - image := C.gtk_image_new_from_pixbuf(pixBuf) - C.gtk_widget_set_visible((*C.GtkWidget)(image), C.gboolean(1)) - C.gtk_container_add( - (*C.GtkContainer)(unsafe.Pointer(box)), - (*C.GtkWidget)(unsafe.Pointer(image))) - } - - C.gtk_box_pack_end( - (*C.GtkBox)(unsafe.Pointer(box)), - (*C.GtkWidget)(lbl), 1, 1, 0) - C.gtk_container_add( - (*C.GtkContainer)(unsafe.Pointer(menuItem)), - (*C.GtkWidget)(unsafe.Pointer(box))) - C.gtk_widget_show_all(menuItem) - return pointer(menuItem) -} - -func menuCheckItemNew(label string, bitmap []byte) pointer { - return menuItemAddProperties(C.gtk_check_menu_item_new(), label, bitmap) -} - -func menuItemSetChecked(widget pointer, checked bool) { - value := C.int(0) - if checked { - value = C.int(1) - } - C.gtk_check_menu_item_set_active( - (*C.GtkCheckMenuItem)(widget), - value) -} - -func menuItemSetDisabled(widget pointer, disabled bool) { - value := C.int(1) - if disabled { - value = C.int(0) - } - C.gtk_widget_set_sensitive( - (*C.GtkWidget)(widget), - value) -} - -func menuItemSetLabel(widget pointer, label string) { - value := C.CString(label) - C.gtk_menu_item_set_label( - (*C.GtkMenuItem)(widget), - value) - C.free(unsafe.Pointer(value)) -} - -func menuItemRemoveBitmap(widget pointer) { - box := C.gtk_bin_get_child((*C.GtkBin)(widget)) - if box == nil { - return - } - - children := C.gtk_container_get_children((*C.GtkContainer)(unsafe.Pointer(box))) - defer C.g_list_free(children) - count := int(C.g_list_length(children)) - if count == 2 { - C.gtk_container_remove((*C.GtkContainer)(unsafe.Pointer(box)), - (*C.GtkWidget)(children.data)) - } -} - -func menuItemSetBitmap(widget pointer, bitmap []byte) { - menuItemRemoveBitmap(widget) - box := C.gtk_bin_get_child((*C.GtkBin)(widget)) - if img, err := pngToImage(bitmap); err == nil && len(img.Pix) > 0 { - // Use g_bytes_new instead of g_bytes_new_static because Go memory can be - // moved or freed by the GC. g_bytes_new copies the data to C-owned memory. - gbytes := C.g_bytes_new(C.gconstpointer(unsafe.Pointer(&img.Pix[0])), - C.ulong(len(img.Pix))) - defer C.g_bytes_unref(gbytes) - pixBuf := C.gdk_pixbuf_new_from_bytes( - gbytes, - C.GDK_COLORSPACE_RGB, - 1, // has_alpha - 8, - C.int(img.Bounds().Dx()), - C.int(img.Bounds().Dy()), - C.int(img.Stride), - ) - image := C.gtk_image_new_from_pixbuf(pixBuf) - C.gtk_widget_set_visible((*C.GtkWidget)(image), C.gboolean(1)) - C.gtk_container_add( - (*C.GtkContainer)(unsafe.Pointer(box)), - (*C.GtkWidget)(unsafe.Pointer(image))) - } - -} - -func menuItemSetToolTip(widget pointer, tooltip string) { - value := C.CString(tooltip) - C.gtk_widget_set_tooltip_text( - (*C.GtkWidget)(widget), - value) - C.free(unsafe.Pointer(value)) -} - -func menuItemSignalBlock(widget pointer, handlerId uint, block bool) { - if block { - C.g_signal_handler_block(C.gpointer(widget), C.ulong(handlerId)) - } else { - C.g_signal_handler_unblock(C.gpointer(widget), C.ulong(handlerId)) - } -} - -func menuRadioItemNew(group *GSList, label string) pointer { - cLabel := C.CString(label) - defer C.free(unsafe.Pointer(cLabel)) - return pointer(C.gtk_radio_menu_item_new_with_label((*C.GSList)(group), cLabel)) -} - -// screen related - -func getScreenByIndex(display *C.struct__GdkDisplay, index int) *Screen { - monitor := C.gdk_display_get_monitor(display, C.int(index)) - // TODO: Do we need to update Screen to contain current info? - // currentMonitor := C.gdk_display_get_monitor_at_window(display, window) - - var geometry C.GdkRectangle - C.gdk_monitor_get_geometry(monitor, &geometry) - primary := false - if C.gdk_monitor_is_primary(monitor) == 1 { - primary = true - } - name := C.gdk_monitor_get_model(monitor) - return &Screen{ - ID: fmt.Sprintf("%d", index), - Name: C.GoString(name), - IsPrimary: primary, - ScaleFactor: float32(C.gdk_monitor_get_scale_factor(monitor)), - X: int(geometry.x), - Y: int(geometry.y), - Size: Size{ - Height: int(geometry.height), - Width: int(geometry.width), - }, - Bounds: Rect{ - X: int(geometry.x), - Y: int(geometry.y), - Height: int(geometry.height), - Width: int(geometry.width), - }, - PhysicalBounds: Rect{ - X: int(geometry.x), - Y: int(geometry.y), - Height: int(geometry.height), - Width: int(geometry.width), - }, - WorkArea: Rect{ - X: int(geometry.x), - Y: int(geometry.y), - Height: int(geometry.height), - Width: int(geometry.width), - }, - PhysicalWorkArea: Rect{ - X: int(geometry.x), - Y: int(geometry.y), - Height: int(geometry.height), - Width: int(geometry.width), - }, - Rotation: 0.0, - } -} - -func getScreens(app pointer) ([]*Screen, error) { - var screens []*Screen - window := C.gtk_application_get_active_window((*C.GtkApplication)(app)) - gdkWindow := C.gtk_widget_get_window((*C.GtkWidget)(unsafe.Pointer(window))) - display := C.gdk_window_get_display(gdkWindow) - count := C.gdk_display_get_n_monitors(display) - for i := 0; i < int(count); i++ { - screens = append(screens, getScreenByIndex(display, i)) - } - return screens, nil -} - -// widgets - -func (w *linuxWebviewWindow) setEnabled(enabled bool) { - var value C.int - if enabled { - value = C.int(1) - } - - C.gtk_widget_set_sensitive(w.gtkWidget(), value) -} - -func widgetSetVisible(widget pointer, hidden bool) { - if hidden { - C.gtk_widget_hide((*C.GtkWidget)(widget)) - } else { - C.gtk_widget_show((*C.GtkWidget)(widget)) - } -} - -func (w *linuxWebviewWindow) close() { - C.gtk_widget_destroy(w.gtkWidget()) - getNativeApplication().unregisterWindow(windowPointer(w.window)) -} - -func (w *linuxWebviewWindow) enableDND() { - // Pass window ID as pointer value (not pointer to ID) - same pattern as other signal handlers - winID := unsafe.Pointer(uintptr(w.parent.id)) - C.enableDND((*C.GtkWidget)(w.webview), C.gpointer(winID)) -} - -func (w *linuxWebviewWindow) disableDND() { - // Block external file drops while allowing internal HTML5 drag-and-drop - winID := unsafe.Pointer(uintptr(w.parent.id)) - C.disableDND((*C.GtkWidget)(w.webview), C.gpointer(winID)) -} - -func (w *linuxWebviewWindow) execJS(js string) { - InvokeAsync(func() { - value := C.CString(js) - C.webkit_web_view_evaluate_javascript(w.webKitWebView(), - value, - C.long(len(js)), - nil, - C.CString(""), - nil, - nil, - nil) - C.free(unsafe.Pointer(value)) - }) -} - -// Preallocated buffer for drag-over JS calls to avoid allocations -// "window._wails.handleDragOver(XXXXX,YYYYY)" is max ~45 chars -var dragOverJSBuffer = C.CString(strings.Repeat(" ", 64)) -var emptyWorldName = C.CString("") - -// execJSDragOver executes JS for drag-over events with zero Go allocations. -// It directly writes to a preallocated C buffer. Must be called from main thread. -func (w *linuxWebviewWindow) execJSDragOver(x, y int) { - // Format: "window._wails.handleDragOver(X,Y)" - // Write directly to C buffer - buf := (*[64]byte)(unsafe.Pointer(dragOverJSBuffer)) - n := copy(buf[:], "window._wails.handleDragOver(") - n += writeInt(buf[n:], x) - buf[n] = ',' - n++ - n += writeInt(buf[n:], y) - buf[n] = ')' - n++ - buf[n] = 0 // null terminate - - C.webkit_web_view_evaluate_javascript(w.webKitWebView(), - dragOverJSBuffer, - C.long(n), - nil, - emptyWorldName, - nil, - nil, - nil) -} - -// writeInt writes an integer to a byte slice and returns the number of bytes written -func writeInt(buf []byte, n int) int { - if n < 0 { - buf[0] = '-' - return 1 + writeInt(buf[1:], -n) - } - if n == 0 { - buf[0] = '0' - return 1 - } - // Count digits - tmp := n - digits := 0 - for tmp > 0 { - digits++ - tmp /= 10 - } - // Write digits in reverse - for i := digits - 1; i >= 0; i-- { - buf[i] = byte('0' + n%10) - n /= 10 - } - return digits -} - -func getMousePosition() (int, int, *Screen) { - var x, y C.gint - var screen *C.GdkScreen - defaultDisplay := C.gdk_display_get_default() - device := C.gdk_seat_get_pointer(C.gdk_display_get_default_seat(defaultDisplay)) - C.gdk_device_get_position(device, &screen, &x, &y) - // Get Monitor for screen - monitor := C.gdk_display_get_monitor_at_point(defaultDisplay, x, y) - geometry := C.GdkRectangle{} - C.gdk_monitor_get_geometry(monitor, &geometry) - scaleFactor := int(C.gdk_monitor_get_scale_factor(monitor)) - return int(x), int(y), &Screen{ - ID: fmt.Sprintf("%d", 0), // A unique identifier for the display - Name: C.GoString(C.gdk_monitor_get_model(monitor)), // The name of the display - ScaleFactor: float32(scaleFactor), // The scale factor of the display - X: int(geometry.x), // The x-coordinate of the top-left corner of the rectangle - Y: int(geometry.y), // The y-coordinate of the top-left corner of the rectangle - Size: Size{ - Height: int(geometry.height), - Width: int(geometry.width), - }, - Bounds: Rect{ - X: int(geometry.x), - Y: int(geometry.y), - Height: int(geometry.height), - Width: int(geometry.width), - }, - WorkArea: Rect{ - X: int(geometry.x), - Y: int(geometry.y), - Height: int(geometry.height), - Width: int(geometry.width), - }, - IsPrimary: false, - Rotation: 0.0, - } -} - -func (w *linuxWebviewWindow) destroy() { - w.parent.markAsDestroyed() - // Free menu - if w.gtkmenu != nil { - C.gtk_widget_destroy((*C.GtkWidget)(w.gtkmenu)) - w.gtkmenu = nil - } - // Free window - C.gtk_widget_destroy(w.gtkWidget()) -} - -func (w *linuxWebviewWindow) fullscreen() { - w.maximise() - //w.lastWidth, w.lastHeight = w.size() - x, y, width, height, scaleFactor := w.getCurrentMonitorGeometry() - if x == -1 && y == -1 && width == -1 && height == -1 { - return - } - physicalWidth := int(float64(width) * scaleFactor) - physicalHeight := int(float64(height) * scaleFactor) - w.setMinMaxSize(0, 0, physicalWidth, physicalHeight) - w.setSize(physicalWidth, physicalHeight) - C.gtk_window_fullscreen(w.gtkWindow()) - w.setRelativePosition(0, 0) -} - -func (w *linuxWebviewWindow) getCurrentMonitor() *C.GdkMonitor { - display := C.gtk_widget_get_display(w.gtkWidget()) - gdkWindow := C.gtk_widget_get_window(w.gtkWidget()) - if gdkWindow != nil { - monitor := C.gdk_display_get_monitor_at_window(display, gdkWindow) - if monitor != nil { - return monitor - } - } - - // Wayland fallback: find monitor containing the current window - n_monitors := C.gdk_display_get_n_monitors(display) - window_x, window_y := w.position() - for i := 0; i < int(n_monitors); i++ { - test_monitor := C.gdk_display_get_monitor(display, C.int(i)) - if test_monitor != nil { - var rect C.GdkRectangle - C.gdk_monitor_get_geometry(test_monitor, &rect) - - // Check if window is within this monitor's bounds - if window_x >= int(rect.x) && window_x < int(rect.x+rect.width) && - window_y >= int(rect.y) && window_y < int(rect.y+rect.height) { - return test_monitor - } - } - } - - return nil -} - -func (w *linuxWebviewWindow) getScreen() (*Screen, error) { - // Get the current screen for the window - monitor := w.getCurrentMonitor() - name := C.gdk_monitor_get_model(monitor) - mx, my, width, height, scaleFactor := w.getCurrentMonitorGeometry() - return &Screen{ - ID: fmt.Sprintf("%d", w.id), // A unique identifier for the display - Name: C.GoString(name), // The name of the display - ScaleFactor: float32(scaleFactor), // The scale factor of the display - X: mx, // The x-coordinate of the top-left corner of the rectangle - Y: my, // The y-coordinate of the top-left corner of the rectangle - Size: Size{ - Height: int(height), - Width: int(width), - }, - Bounds: Rect{ - X: int(mx), - Y: int(my), - Height: int(height), - Width: int(width), - }, - WorkArea: Rect{ - X: int(mx), - Y: int(my), - Height: int(height), - Width: int(width), - }, - PhysicalBounds: Rect{ - X: int(mx), - Y: int(my), - Height: int(height), - Width: int(width), - }, - PhysicalWorkArea: Rect{ - X: int(mx), - Y: int(my), - Height: int(height), - Width: int(width), - }, - IsPrimary: false, - Rotation: 0.0, - }, nil -} - -func (w *linuxWebviewWindow) getCurrentMonitorGeometry() (x int, y int, width int, height int, scaleFactor float64) { - monitor := w.getCurrentMonitor() - if monitor == nil { - // Best effort to find screen resolution of default monitor - display := C.gdk_display_get_default() - monitor = C.gdk_display_get_primary_monitor(display) - if monitor == nil { - return -1, -1, -1, -1, 1 - } - } - var result C.GdkRectangle - C.gdk_monitor_get_geometry(monitor, &result) - // GTK3 only supports integer scale factors - scaleFactor = float64(C.gdk_monitor_get_scale_factor(monitor)) - return int(result.x), int(result.y), int(result.width), int(result.height), scaleFactor -} - -func (w *linuxWebviewWindow) size() (int, int) { - var windowWidth C.int - var windowHeight C.int - C.gtk_window_get_size(w.gtkWindow(), &windowWidth, &windowHeight) - return int(windowWidth), int(windowHeight) -} - -func (w *linuxWebviewWindow) relativePosition() (int, int) { - x, y := w.position() - // The position must be relative to the screen it is on - // We need to get the screen it is on - monitor := w.getCurrentMonitor() - geometry := C.GdkRectangle{} - C.gdk_monitor_get_geometry(monitor, &geometry) - x = x - int(geometry.x) - y = y - int(geometry.y) - - // TODO: Scale based on DPI - - return x, y -} - -func (w *linuxWebviewWindow) gtkWidget() *C.GtkWidget { - return (*C.GtkWidget)(w.window) -} - -func (w *linuxWebviewWindow) windowHide() { - C.gtk_widget_hide(w.gtkWidget()) -} - -func (w *linuxWebviewWindow) isFullscreen() bool { - gdkWindow := C.gtk_widget_get_window(w.gtkWidget()) - state := C.gdk_window_get_state(gdkWindow) - return state&C.GDK_WINDOW_STATE_FULLSCREEN > 0 -} - -func (w *linuxWebviewWindow) isFocused() bool { - // returns true if window is focused - return C.gtk_window_has_toplevel_focus(w.gtkWindow()) == 1 -} - -func (w *linuxWebviewWindow) isMaximised() bool { - gdkwindow := C.gtk_widget_get_window(w.gtkWidget()) - state := C.gdk_window_get_state(gdkwindow) - return state&C.GDK_WINDOW_STATE_MAXIMIZED > 0 && state&C.GDK_WINDOW_STATE_FULLSCREEN == 0 -} - -func (w *linuxWebviewWindow) isMinimised() bool { - gdkwindow := C.gtk_widget_get_window(w.gtkWidget()) - state := C.gdk_window_get_state(gdkwindow) - return state&C.GDK_WINDOW_STATE_ICONIFIED > 0 -} - -func (w *linuxWebviewWindow) isVisible() bool { - if C.gtk_widget_is_visible(w.gtkWidget()) == 1 { - return true - } - return false -} - -func (w *linuxWebviewWindow) maximise() { - C.gtk_window_maximize(w.gtkWindow()) -} - -func (w *linuxWebviewWindow) minimise() { - C.gtk_window_iconify(w.gtkWindow()) -} - -func windowNew(application pointer, menu pointer, _ LinuxMenuStyle, windowId uint, gpuPolicy WebviewGpuPolicy) (window, webview, vbox pointer) { - window = pointer(C.gtk_application_window_new((*C.GtkApplication)(application))) - C.g_object_ref_sink(C.gpointer(window)) - webview = windowNewWebview(windowId, gpuPolicy) - vbox = pointer(C.gtk_box_new(C.GTK_ORIENTATION_VERTICAL, 0)) - name := C.CString("webview-box") - defer C.free(unsafe.Pointer(name)) - C.gtk_widget_set_name((*C.GtkWidget)(vbox), name) - - C.gtk_container_add((*C.GtkContainer)(window), (*C.GtkWidget)(vbox)) - if menu != nil { - C.gtk_box_pack_start((*C.GtkBox)(vbox), (*C.GtkWidget)(menu), 0, 0, 0) - } - C.gtk_box_pack_start((*C.GtkBox)(unsafe.Pointer(vbox)), (*C.GtkWidget)(webview), 1, 1, 0) - return -} - -func windowNewWebview(parentId uint, gpuPolicy WebviewGpuPolicy) pointer { - c := NewCalloc() - defer c.Free() - manager := C.webkit_user_content_manager_new() - C.webkit_user_content_manager_register_script_message_handler(manager, c.String("external")) - webView := C.webkit_web_view_new_with_user_content_manager(manager) - - fixSignalHandlers.Do(func() { - C.install_signal_handlers() - }) - - C.save_webview_to_content_manager(unsafe.Pointer(manager), unsafe.Pointer(webView)) - - // attach window id to both the webview and contentmanager - C.save_window_id(unsafe.Pointer(webView), C.uint(parentId)) - C.save_window_id(unsafe.Pointer(manager), C.uint(parentId)) - - registerURIScheme.Do(func() { - context := C.webkit_web_view_get_context(C.webkit_web_view(webView)) - C.webkit_web_context_register_uri_scheme( - context, - c.String("wails"), - C.WebKitURISchemeRequestCallback(C.onProcessRequest), - nil, - nil) - }) - settings := C.webkit_web_view_get_settings((*C.WebKitWebView)(unsafe.Pointer(webView))) - C.webkit_settings_set_user_agent_with_application_details(settings, c.String("wails.io"), c.String("")) - - switch gpuPolicy { - case WebviewGpuPolicyAlways: - C.webkit_settings_set_hardware_acceleration_policy(settings, C.WEBKIT_HARDWARE_ACCELERATION_POLICY_ALWAYS) - break - case WebviewGpuPolicyOnDemand: - C.webkit_settings_set_hardware_acceleration_policy(settings, C.WEBKIT_HARDWARE_ACCELERATION_POLICY_ON_DEMAND) - break - case WebviewGpuPolicyNever: - C.webkit_settings_set_hardware_acceleration_policy(settings, C.WEBKIT_HARDWARE_ACCELERATION_POLICY_NEVER) - break - default: - C.webkit_settings_set_hardware_acceleration_policy(settings, C.WEBKIT_HARDWARE_ACCELERATION_POLICY_ON_DEMAND) - } - return pointer(webView) -} - -func (w *linuxWebviewWindow) present() { - C.gtk_window_present(w.gtkWindow()) - // gtk_window_unminimize (w.gtkWindow()) /// gtk4 -} - -func (w *linuxWebviewWindow) setSize(width, height int) { - C.gtk_window_resize( - w.gtkWindow(), - C.gint(width), - C.gint(height)) -} - -func (w *linuxWebviewWindow) windowShow() { - if w.gtkWidget() == nil { - return - } - // Realize the window first to ensure it has a valid GdkWindow. - // This prevents crashes on Wayland when appmenu-gtk-module tries to - // set DBus properties for global menu integration before the window - // is fully realized. See: https://github.com/wailsapp/wails/issues/4769 - C.gtk_widget_realize(w.gtkWidget()) - C.gtk_widget_show_all(w.gtkWidget()) -} - -func windowIgnoreMouseEvents(window pointer, webview pointer, ignore bool) { - var enable C.int - if ignore { - enable = 1 - } - gdkWindow := (*C.GdkWindow)(window) - C.gdk_window_set_pass_through(gdkWindow, enable) - C.webkit_web_view_set_editable((*C.WebKitWebView)(webview), C.gboolean(enable)) -} - -func (w *linuxWebviewWindow) webKitWebView() *C.WebKitWebView { - return (*C.WebKitWebView)(w.webview) -} - -func (w *linuxWebviewWindow) setBorderless(borderless bool) { - C.gtk_window_set_decorated(w.gtkWindow(), gtkBool(!borderless)) -} - -func (w *linuxWebviewWindow) setResizable(resizable bool) { - C.gtk_window_set_resizable(w.gtkWindow(), gtkBool(resizable)) -} - -func (w *linuxWebviewWindow) setDefaultSize(width int, height int) { - C.gtk_window_set_default_size(w.gtkWindow(), C.gint(width), C.gint(height)) -} - -func (w *linuxWebviewWindow) setBackgroundColour(colour RGBA) { - rgba := C.GdkRGBA{C.double(colour.Red) / 255.0, C.double(colour.Green) / 255.0, C.double(colour.Blue) / 255.0, C.double(colour.Alpha) / 255.0} - C.webkit_web_view_set_background_color((*C.WebKitWebView)(w.webview), &rgba) - - cssStr := C.CString(fmt.Sprintf("#webview-box {background-color: rgba(%d, %d, %d, %1.1f);}", colour.Red, colour.Green, colour.Blue, float32(colour.Alpha)/255.0)) - provider := C.gtk_css_provider_new() - C.gtk_style_context_add_provider( - C.gtk_widget_get_style_context((*C.GtkWidget)(w.vbox)), - (*C.GtkStyleProvider)(unsafe.Pointer(provider)), - C.GTK_STYLE_PROVIDER_PRIORITY_USER) - C.g_object_unref(C.gpointer(provider)) - C.gtk_css_provider_load_from_data(provider, cssStr, -1, nil) - C.free(unsafe.Pointer(cssStr)) -} - -func getPrimaryScreen() (*Screen, error) { - display := C.gdk_display_get_default() - monitor := C.gdk_display_get_primary_monitor(display) - geometry := C.GdkRectangle{} - C.gdk_monitor_get_geometry(monitor, &geometry) - scaleFactor := int(C.gdk_monitor_get_scale_factor(monitor)) - // get the name for the screen - name := C.gdk_monitor_get_model(monitor) - return &Screen{ - ID: "0", - Name: C.GoString(name), - IsPrimary: true, - X: int(geometry.x), - Y: int(geometry.y), - Size: Size{ - Height: int(geometry.height), - Width: int(geometry.width), - }, - Bounds: Rect{ - X: int(geometry.x), - Y: int(geometry.y), - Height: int(geometry.height), - Width: int(geometry.width), - }, - ScaleFactor: float32(scaleFactor), - }, nil -} - -func windowSetGeometryHints(window pointer, minWidth, minHeight, maxWidth, maxHeight int) { - size := C.GdkGeometry{ - min_width: C.int(minWidth), - min_height: C.int(minHeight), - max_width: C.int(maxWidth), - max_height: C.int(maxHeight), - } - C.gtk_window_set_geometry_hints((*C.GtkWindow)(window), nil, &size, C.GDK_HINT_MAX_SIZE|C.GDK_HINT_MIN_SIZE) -} - -func (w *linuxWebviewWindow) setFrameless(frameless bool) { - C.gtk_window_set_decorated(w.gtkWindow(), gtkBool(!frameless)) - // TODO: Deal with transparency for the titlebar if possible when !frameless - // Perhaps we just make it undecorated and add a menu bar inside? -} - -// TODO: confirm this is working properly -func (w *linuxWebviewWindow) setHTML(html string) { - cHTML := C.CString(html) - uri := C.CString("wails://") - empty := C.CString("") - defer C.free(unsafe.Pointer(cHTML)) - defer C.free(unsafe.Pointer(uri)) - defer C.free(unsafe.Pointer(empty)) - C.webkit_web_view_load_alternate_html( - w.webKitWebView(), - cHTML, - uri, - empty) -} - -func (w *linuxWebviewWindow) setAlwaysOnTop(alwaysOnTop bool) { - C.gtk_window_set_keep_above(w.gtkWindow(), gtkBool(alwaysOnTop)) -} - -func (w *linuxWebviewWindow) flash(_ bool) { -} - -func (w *linuxWebviewWindow) setOpacity(opacity float64) { - C.gtk_widget_set_opacity(w.gtkWidget(), C.double(opacity)) -} - -func (w *linuxWebviewWindow) setTitle(title string) { - if !w.parent.options.Frameless { - cTitle := C.CString(title) - C.gtk_window_set_title(w.gtkWindow(), cTitle) - C.free(unsafe.Pointer(cTitle)) - } -} - -func (w *linuxWebviewWindow) setIcon(icon pointer) { - if icon != nil { - C.gtk_window_set_icon(w.gtkWindow(), (*C.GdkPixbuf)(icon)) - } -} - -func (w *linuxWebviewWindow) gtkWindow() *C.GtkWindow { - return (*C.GtkWindow)(w.window) -} - -func (w *linuxWebviewWindow) setTransparent() { - screen := C.gtk_widget_get_screen(w.gtkWidget()) - visual := C.gdk_screen_get_rgba_visual(screen) - - if visual != nil && C.gdk_screen_is_composited(screen) == C.int(1) { - C.gtk_widget_set_app_paintable(w.gtkWidget(), C.gboolean(1)) - C.gtk_widget_set_visual(w.gtkWidget(), visual) - } -} - -func (w *linuxWebviewWindow) setURL(uri string) { - target := C.CString(uri) - C.webkit_web_view_load_uri(w.webKitWebView(), target) - C.free(unsafe.Pointer(target)) -} - -//export emit -func emit(we *C.WindowEvent) { - window, _ := globalApplication.Window.GetByID(uint(we.id)) - if window != nil { - windowEvents <- &windowEvent{ - WindowID: window.ID(), - EventID: uint(events.WindowEventType(we.event)), - } - } -} - -//export handleConfigureEvent -func handleConfigureEvent(widget *C.GtkWidget, event *C.GdkEventConfigure, data C.uintptr_t) C.gboolean { - window, _ := globalApplication.Window.GetByID(uint(data)) - if window != nil { - lw := getLinuxWebviewWindow(window) - if lw == nil { - return C.gboolean(1) - } - if lw.lastX != int(event.x) || lw.lastY != int(event.y) { - lw.moveDebouncer(func() { - processWindowEvent(C.uint(data), C.uint(events.Linux.WindowDidMove)) - }) - } - - if lw.lastWidth != int(event.width) || lw.lastHeight != int(event.height) { - lw.resizeDebouncer(func() { - processWindowEvent(C.uint(data), C.uint(events.Linux.WindowDidResize)) - }) - } - - lw.lastX = int(event.x) - lw.lastY = int(event.y) - lw.lastWidth = int(event.width) - lw.lastHeight = int(event.height) - } - - return C.gboolean(0) -} - -//export handleDeleteEvent -func handleDeleteEvent(widget *C.GtkWidget, event *C.GdkEvent, data C.uintptr_t) C.gboolean { - processWindowEvent(C.uint(data), C.uint(events.Linux.WindowDeleteEvent)) - return C.gboolean(1) -} - -//export handleFocusEvent -func handleFocusEvent(widget *C.GtkWidget, event *C.GdkEvent, data C.uintptr_t) C.gboolean { - focusEvent := (*C.GdkEventFocus)(unsafe.Pointer(event)) - if focusEvent._type == C.GDK_FOCUS_CHANGE { - if focusEvent.in == C.TRUE { - processWindowEvent(C.uint(data), C.uint(events.Linux.WindowFocusIn)) - } else { - processWindowEvent(C.uint(data), C.uint(events.Linux.WindowFocusOut)) - } - } - return C.gboolean(0) -} - -//export handleLoadChanged -func handleLoadChanged(webview *C.WebKitWebView, event C.WebKitLoadEvent, data C.uintptr_t) { - switch event { - case C.WEBKIT_LOAD_STARTED: - processWindowEvent(C.uint(data), C.uint(events.Linux.WindowLoadStarted)) - case C.WEBKIT_LOAD_REDIRECTED: - processWindowEvent(C.uint(data), C.uint(events.Linux.WindowLoadRedirected)) - case C.WEBKIT_LOAD_COMMITTED: - processWindowEvent(C.uint(data), C.uint(events.Linux.WindowLoadCommitted)) - case C.WEBKIT_LOAD_FINISHED: - processWindowEvent(C.uint(data), C.uint(events.Linux.WindowLoadFinished)) - } -} - -func (w *linuxWebviewWindow) setupSignalHandlers(emit func(e events.WindowEventType)) { - - c := NewCalloc() - defer c.Free() - - winID := unsafe.Pointer(uintptr(C.uint(w.parent.ID()))) - - // Set up the window close event - wv := unsafe.Pointer(w.webview) - C.signal_connect(unsafe.Pointer(w.window), c.String("delete-event"), C.handleDeleteEvent, winID) - C.signal_connect(unsafe.Pointer(w.window), c.String("focus-out-event"), C.handleFocusEvent, winID) - C.signal_connect(wv, c.String("load-changed"), C.handleLoadChanged, winID) - C.signal_connect(unsafe.Pointer(w.window), c.String("configure-event"), C.handleConfigureEvent, winID) - - contentManager := C.webkit_web_view_get_user_content_manager(w.webKitWebView()) - C.signal_connect(unsafe.Pointer(contentManager), c.String("script-message-received::external"), C.sendMessageToBackend, nil) - C.signal_connect(wv, c.String("button-press-event"), C.onButtonEvent, winID) - C.signal_connect(wv, c.String("button-release-event"), C.onButtonEvent, winID) - C.signal_connect(wv, c.String("key-press-event"), C.onKeyPressEvent, winID) -} - -func getMouseButtons() (bool, bool, bool) { - var pointer *C.GdkDevice - var state C.GdkModifierType - pointer = C.gdk_seat_get_pointer(C.gdk_display_get_default_seat(C.gdk_display_get_default())) - C.gdk_device_get_state(pointer, nil, nil, &state) - return state&C.GDK_BUTTON1_MASK > 0, state&C.GDK_BUTTON2_MASK > 0, state&C.GDK_BUTTON3_MASK > 0 -} - -func openDevTools(webview pointer) { - inspector := C.webkit_web_view_get_inspector((*C.WebKitWebView)(webview)) - C.webkit_web_inspector_show(inspector) -} - -func (w *linuxWebviewWindow) startDrag() error { - C.gtk_window_begin_move_drag( - (*C.GtkWindow)(w.window), - C.int(w.drag.MouseButton), - C.int(w.drag.XRoot), - C.int(w.drag.YRoot), - C.uint32_t(w.drag.DragTime)) - return nil -} - -func enableDevTools(webview pointer) { - settings := C.webkit_web_view_get_settings((*C.WebKitWebView)(webview)) - enabled := C.webkit_settings_get_enable_developer_extras(settings) - switch enabled { - case C.int(0): - enabled = C.int(1) - case C.int(1): - enabled = C.int(0) - } - C.webkit_settings_set_enable_developer_extras(settings, enabled) -} - -func (w *linuxWebviewWindow) unfullscreen() { - C.gtk_window_unfullscreen((*C.GtkWindow)(w.window)) - w.unmaximise() -} - -func (w *linuxWebviewWindow) unmaximise() { - C.gtk_window_unmaximize((*C.GtkWindow)(w.window)) -} - -func (w *linuxWebviewWindow) getZoom() float64 { - return float64(C.webkit_web_view_get_zoom_level(w.webKitWebView())) -} - -func (w *linuxWebviewWindow) zoomIn() { - // FIXME: ZoomIn/Out is assumed to be incorrect! - ZoomInFactor := 1.10 - w.setZoom(w.getZoom() * ZoomInFactor) -} - -func (w *linuxWebviewWindow) zoomOut() { - ZoomInFactor := -1.10 - w.setZoom(w.getZoom() * ZoomInFactor) -} - -func (w *linuxWebviewWindow) zoomReset() { - w.setZoom(1.0) -} - -func (w *linuxWebviewWindow) reload() { - uri := C.CString("wails://") - C.webkit_web_view_load_uri(w.webKitWebView(), uri) - C.free(unsafe.Pointer(uri)) -} - -func (w *linuxWebviewWindow) setZoom(zoom float64) { - if zoom < 1 { // 1.0 is the smallest allowable - zoom = 1 - } - C.webkit_web_view_set_zoom_level(w.webKitWebView(), C.double(zoom)) -} - -func (w *linuxWebviewWindow) move(x, y int) { - // Move the window to these coordinates - C.gtk_window_move(w.gtkWindow(), C.int(x), C.int(y)) -} - -func (w *linuxWebviewWindow) position() (int, int) { - var x C.int - var y C.int - C.gtk_window_get_position((*C.GtkWindow)(w.window), &x, &y) - return int(x), int(y) -} - -func (w *linuxWebviewWindow) ignoreMouse(ignore bool) { - if ignore { - C.gtk_widget_set_events((*C.GtkWidget)(unsafe.Pointer(w.window)), C.GDK_ENTER_NOTIFY_MASK|C.GDK_LEAVE_NOTIFY_MASK) - } else { - C.gtk_widget_set_events((*C.GtkWidget)(unsafe.Pointer(w.window)), C.GDK_ALL_EVENTS_MASK) - } -} - -// FIXME Change this to reflect mouse button! -// -//export onButtonEvent -func onButtonEvent(_ *C.GtkWidget, event *C.GdkEventButton, data C.uintptr_t) C.gboolean { - // Constants (defined here to be easier to use with purego) - GdkButtonPress := C.GDK_BUTTON_PRESS // 4 - Gdk2ButtonPress := C.GDK_2BUTTON_PRESS // 5 for double-click - GdkButtonRelease := C.GDK_BUTTON_RELEASE // 7 - - windowId := uint(C.uint(data)) - window, _ := globalApplication.Window.GetByID(windowId) - if window == nil { - return C.gboolean(0) - } - lw := getLinuxWebviewWindow(window) - if lw == nil { - return C.gboolean(0) - } - - if event == nil { - return C.gboolean(0) - } - if event.button == 3 { - return C.gboolean(0) - } - - switch int(event._type) { - case GdkButtonPress: - lw.drag.MouseButton = uint(event.button) - lw.drag.XRoot = int(event.x_root) - lw.drag.YRoot = int(event.y_root) - lw.drag.DragTime = uint32(event.time) - case Gdk2ButtonPress: - // do we need something here? - case GdkButtonRelease: - lw.endDrag(uint(event.button), int(event.x_root), int(event.y_root)) - } - - return C.gboolean(0) -} - -//export onMenuButtonEvent -func onMenuButtonEvent(_ *C.GtkWidget, event *C.GdkEventButton, data C.uintptr_t) C.gboolean { - // Constants (defined here to be easier to use with purego) - GdkButtonRelease := C.GDK_BUTTON_RELEASE // 7 - - windowId := uint(C.uint(data)) - window, _ := globalApplication.Window.GetByID(windowId) - if window == nil { - return C.gboolean(0) - } - lw := getLinuxWebviewWindow(window) - if lw == nil { - return C.gboolean(0) - } - - // prevent custom context menu from closing immediately - if event.button == 3 && int(event._type) == GdkButtonRelease && lw.ctxMenuOpened { - lw.ctxMenuOpened = false - return C.gboolean(1) - } - - return C.gboolean(0) -} - -//export onDragEnter -func onDragEnter(data unsafe.Pointer) { - windowId := uint(uintptr(data)) - targetWindow, ok := globalApplication.Window.GetByID(windowId) - if !ok || targetWindow == nil { - return - } - // HandleDragEnter is Linux-specific (GTK intercepts drag events) - if w, ok := targetWindow.(*WebviewWindow); ok { - w.HandleDragEnter() - } -} - -//export onDragLeave -func onDragLeave(data unsafe.Pointer) { - windowId := uint(uintptr(data)) - targetWindow, ok := globalApplication.Window.GetByID(windowId) - if !ok || targetWindow == nil { - return - } - // HandleDragLeave is Linux-specific (GTK intercepts drag events) - if w, ok := targetWindow.(*WebviewWindow); ok { - w.HandleDragLeave() - } -} - -//export onDragOver -func onDragOver(x C.gint, y C.gint, data unsafe.Pointer) { - windowId := uint(uintptr(data)) - targetWindow, ok := globalApplication.Window.GetByID(windowId) - if !ok || targetWindow == nil { - return - } - // HandleDragOver is Linux-specific (GTK intercepts drag events) - if w, ok := targetWindow.(*WebviewWindow); ok { - w.HandleDragOver(int(x), int(y)) - } -} - -//export onUriList -func onUriList(extracted **C.char, x C.gint, y C.gint, data unsafe.Pointer) { - // Credit: https://groups.google.com/g/golang-nuts/c/bI17Bpck8K4/m/DVDa7EMtDAAJ - offset := unsafe.Sizeof(uintptr(0)) - filenames := []string{} - for *extracted != nil { - filenames = append(filenames, strings.TrimPrefix(C.GoString(*extracted), "file://")) - extracted = (**C.char)(unsafe.Pointer(uintptr(unsafe.Pointer(extracted)) + offset)) - } - - // Window ID is stored as the pointer value itself (not pointing to memory) - // Same pattern as other signal handlers in this file - windowId := uint(uintptr(data)) - targetWindow, ok := globalApplication.Window.GetByID(windowId) - if !ok || targetWindow == nil { - globalApplication.error("onUriList could not find window with ID: %d", windowId) - return - } - - // Send to frontend for drop target detection and filtering - targetWindow.InitiateFrontendDropProcessing(filenames, int(x), int(y)) -} - -var debounceTimer *time.Timer -var isDebouncing bool = false - -//export onKeyPressEvent -func onKeyPressEvent(_ *C.GtkWidget, event *C.GdkEventKey, userData C.uintptr_t) C.gboolean { - // Keypress re-emits if the key is pressed over a certain threshold so we need a debounce - if isDebouncing { - debounceTimer.Reset(50 * time.Millisecond) - return C.gboolean(0) - } - - // Start the debounce - isDebouncing = true - debounceTimer = time.AfterFunc(50*time.Millisecond, func() { - isDebouncing = false - }) - - windowID := uint(C.uint(userData)) - if accelerator, ok := getKeyboardState(event); ok { - windowKeyEvents <- &windowKeyEvent{ - windowId: windowID, - acceleratorString: accelerator, - } - } - return C.gboolean(0) -} - -func getKeyboardState(event *C.GdkEventKey) (string, bool) { - modifiers := uint(event.state) & C.GDK_MODIFIER_MASK - keyCode := uint(event.keyval) - - var acc accelerator - // Check Accelerators - if modifiers&(C.GDK_SHIFT_MASK) != 0 { - acc.Modifiers = append(acc.Modifiers, ShiftKey) - } - if modifiers&(C.GDK_CONTROL_MASK) != 0 { - acc.Modifiers = append(acc.Modifiers, ControlKey) - } - if modifiers&(C.GDK_MOD1_MASK) != 0 { - acc.Modifiers = append(acc.Modifiers, OptionOrAltKey) - } - if modifiers&(C.GDK_SUPER_MASK) != 0 { - acc.Modifiers = append(acc.Modifiers, SuperKey) - } - keyString, ok := VirtualKeyCodes[keyCode] - if !ok { - return "", false - } - acc.Key = keyString - return acc.String(), true -} - -//export onProcessRequest -func onProcessRequest(request *C.WebKitURISchemeRequest, data C.uintptr_t) { - webView := C.webkit_uri_scheme_request_get_web_view(request) - windowId := uint(C.get_window_id(unsafe.Pointer(webView))) - webviewRequests <- &webViewAssetRequest{ - Request: webview.NewRequest(unsafe.Pointer(request)), - windowId: windowId, - windowName: func() string { - if window, ok := globalApplication.Window.GetByID(windowId); ok { - return window.Name() - } - return "" - }(), - } -} - -//export sendMessageToBackend -func sendMessageToBackend(contentManager *C.WebKitUserContentManager, result *C.WebKitJavascriptResult, - data unsafe.Pointer) { - - // Get the windowID from the contentManager - thisWindowID := uint(C.get_window_id(unsafe.Pointer(contentManager))) - - webView := C.get_webview_from_content_manager(unsafe.Pointer(contentManager)) - var origin string - if webView != nil { - currentUri := C.webkit_web_view_get_uri(webView) - if currentUri != nil { - uri := C.g_strdup(currentUri) - defer C.g_free(C.gpointer(uri)) - origin = C.GoString(uri) - } - } - - var msg string - value := C.webkit_javascript_result_get_js_value(result) - message := C.jsc_value_to_string(value) - msg = C.GoString(message) - defer C.g_free(C.gpointer(message)) - windowMessageBuffer <- &windowMessage{ - windowId: thisWindowID, - message: msg, - originInfo: &OriginInfo{ - Origin: origin, - }, - } -} - -func gtkBool(input bool) C.gboolean { - if input { - return C.gboolean(1) - } - return C.gboolean(0) -} - -// dialog related - -func setWindowIcon(window pointer, icon []byte) { - loader := C.gdk_pixbuf_loader_new() - if loader == nil { - return - } - written := C.gdk_pixbuf_loader_write( - loader, - (*C.uchar)(&icon[0]), - C.ulong(len(icon)), - nil) - if written == 0 { - return - } - C.gdk_pixbuf_loader_close(loader, nil) - pixbuf := C.gdk_pixbuf_loader_get_pixbuf(loader) - if pixbuf != nil { - C.gtk_window_set_icon((*C.GtkWindow)(window), pixbuf) - } - C.g_object_unref(C.gpointer(loader)) -} - -//export messageDialogCB -func messageDialogCB(button C.int) { - fmt.Println("messageDialogCB", button) -} - -func runChooserDialog(window pointer, allowMultiple, createFolders, showHidden bool, currentFolder, title string, action int, acceptLabel string, filters []FileFilter, currentName string) (chan string, error) { - titleStr := C.CString(title) - defer C.free(unsafe.Pointer(titleStr)) - cancelStr := C.CString("_Cancel") - defer C.free(unsafe.Pointer(cancelStr)) - acceptLabelStr := C.CString(acceptLabel) - defer C.free(unsafe.Pointer(acceptLabelStr)) - - fc := C.gtkFileChooserDialogNew( - titleStr, - (*C.GtkWindow)(window), - C.GtkFileChooserAction(action), - cancelStr, - acceptLabelStr) - - C.gtk_file_chooser_set_action((*C.GtkFileChooser)(fc), C.GtkFileChooserAction(action)) - - gtkFilters := []*C.GtkFileFilter{} - for _, filter := range filters { - f := C.gtk_file_filter_new() - displayStr := C.CString(filter.DisplayName) - C.gtk_file_filter_set_name(f, displayStr) - C.free(unsafe.Pointer(displayStr)) - patterns := strings.Split(filter.Pattern, ";") - for _, pattern := range patterns { - patternStr := C.CString(strings.TrimSpace(pattern)) - C.gtk_file_filter_add_pattern(f, patternStr) - C.free(unsafe.Pointer(patternStr)) - } - C.gtk_file_chooser_add_filter((*C.GtkFileChooser)(fc), f) - gtkFilters = append(gtkFilters, f) - } - C.gtk_file_chooser_set_select_multiple( - (*C.GtkFileChooser)(fc), - gtkBool(allowMultiple)) - C.gtk_file_chooser_set_create_folders( - (*C.GtkFileChooser)(fc), - gtkBool(createFolders)) - C.gtk_file_chooser_set_show_hidden( - (*C.GtkFileChooser)(fc), - gtkBool(showHidden)) - - if currentFolder != "" { - path := C.CString(currentFolder) - C.gtk_file_chooser_set_current_folder( - (*C.GtkFileChooser)(fc), - path) - C.free(unsafe.Pointer(path)) - } - - // Set the current name for save dialogs to pre-populate the filename - if currentName != "" && action == C.GTK_FILE_CHOOSER_ACTION_SAVE { - nameStr := C.CString(currentName) - C.gtk_file_chooser_set_current_name( - (*C.GtkFileChooser)(fc), - nameStr) - C.free(unsafe.Pointer(nameStr)) - } - - // FIXME: This should be consolidated - duplicate exists in linux_purego.go - buildStringAndFree := func(s C.gpointer) string { - bytes := []byte{} - p := unsafe.Pointer(s) - for { - val := *(*byte)(p) - if val == 0 { // this is the null terminator - break - } - bytes = append(bytes, val) - p = unsafe.Add(p, 1) - } - C.g_free(s) // so we don't have to iterate a second time - return string(bytes) - } - - selections := make(chan string) - // run this on the gtk thread - InvokeAsync(func() { - response := C.gtk_dialog_run((*C.GtkDialog)(fc)) - // Extract results on GTK thread BEFORE destroying widget - var results []string - if response == C.GTK_RESPONSE_ACCEPT { - // No artificial limit - consistent with Windows/macOS behavior - filenames := C.gtk_file_chooser_get_filenames((*C.GtkFileChooser)(fc)) - for iter := filenames; iter != nil; iter = iter.next { - results = append(results, buildStringAndFree(C.gpointer(iter.data))) - } - C.g_slist_free(filenames) - } - // Destroy widget after extracting results (on GTK thread) - C.gtk_widget_destroy((*C.GtkWidget)(unsafe.Pointer(fc))) - // Send results from goroutine (safe - no GTK calls) - go func() { - defer handlePanic() - for _, result := range results { - selections <- result - } - close(selections) - }() - }) - return selections, nil -} - -func runOpenFileDialog(dialog *OpenFileDialogStruct) (chan string, error) { - var action int - - if dialog.canChooseDirectories { - action = C.GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER - } else { - action = C.GTK_FILE_CHOOSER_ACTION_OPEN - } - - window := nilPointer - if dialog.window != nil { - nativeWindow := dialog.window.NativeWindow() - if nativeWindow != nil { - window = pointer(nativeWindow) - } - } - - buttonText := dialog.buttonText - if buttonText == "" { - buttonText = "_Open" - } - - return runChooserDialog( - window, - dialog.allowsMultipleSelection, - dialog.canCreateDirectories, - dialog.showHiddenFiles, - dialog.directory, - dialog.title, - action, - buttonText, - dialog.filters, - "") -} - -func runQuestionDialog(parent pointer, options *MessageDialog) int { - cMsg := C.CString(options.Message) - cTitle := C.CString(options.Title) - defer C.free(unsafe.Pointer(cMsg)) - defer C.free(unsafe.Pointer(cTitle)) - hasButtons := false - if len(options.Buttons) > 0 { - hasButtons = true - } - - dType, ok := map[DialogType]C.int{ - InfoDialogType: C.GTK_MESSAGE_INFO, - // ErrorDialogType: - QuestionDialogType: C.GTK_MESSAGE_QUESTION, - WarningDialogType: C.GTK_MESSAGE_WARNING, - }[options.DialogType] - if !ok { - // FIXME: Add logging here! - dType = C.GTK_MESSAGE_INFO - } - - dialog := C.new_message_dialog((*C.GtkWindow)(parent), cMsg, dType, C.bool(hasButtons)) - if options.Title != "" { - C.gtk_window_set_title( - (*C.GtkWindow)(unsafe.Pointer(dialog)), - cTitle) - } - - if img, err := pngToImage(options.Icon); err == nil && len(img.Pix) > 0 { - // Use g_bytes_new instead of g_bytes_new_static because Go memory can be - // moved or freed by the GC. g_bytes_new copies the data to C-owned memory. - gbytes := C.g_bytes_new( - C.gconstpointer(unsafe.Pointer(&img.Pix[0])), - C.ulong(len(img.Pix))) - defer C.g_bytes_unref(gbytes) - pixBuf := C.gdk_pixbuf_new_from_bytes( - gbytes, - C.GDK_COLORSPACE_RGB, - 1, // has_alpha - 8, - C.int(img.Bounds().Dx()), - C.int(img.Bounds().Dy()), - C.int(img.Stride), - ) - image := C.gtk_image_new_from_pixbuf(pixBuf) - C.gtk_widget_set_visible((*C.GtkWidget)(image), C.gboolean(1)) - contentArea := C.gtk_dialog_get_content_area((*C.GtkDialog)(dialog)) - C.gtk_container_add( - (*C.GtkContainer)(unsafe.Pointer(contentArea)), - (*C.GtkWidget)(image)) - } - for i, button := range options.Buttons { - cLabel := C.CString(button.Label) - defer C.free(unsafe.Pointer(cLabel)) - index := C.int(i) - C.gtk_dialog_add_button( - (*C.GtkDialog)(dialog), cLabel, index) - if button.IsDefault { - C.gtk_dialog_set_default_response((*C.GtkDialog)(dialog), index) - } - } - - defer C.gtk_widget_destroy((*C.GtkWidget)(dialog)) - return int(C.gtk_dialog_run((*C.GtkDialog)(unsafe.Pointer(dialog)))) -} - -func runSaveFileDialog(dialog *SaveFileDialogStruct) (chan string, error) { - window := nilPointer - buttonText := dialog.buttonText - if buttonText == "" { - buttonText = "_Save" - } - results, err := runChooserDialog( - window, - false, // multiple selection - dialog.canCreateDirectories, - dialog.showHiddenFiles, - dialog.directory, - dialog.title, - C.GTK_FILE_CHOOSER_ACTION_SAVE, - buttonText, - dialog.filters, - dialog.filename) - - return results, err -} - -func (w *linuxWebviewWindow) cut() { - //C.webkit_web_view_execute_editing_command(w.webview, C.WEBKIT_EDITING_COMMAND_CUT) -} - -func (w *linuxWebviewWindow) paste() { - //C.webkit_web_view_execute_editing_command(w.webview, C.WEBKIT_EDITING_COMMAND_PASTE) -} - -func (w *linuxWebviewWindow) copy() { - //C.webkit_web_view_execute_editing_command(w.webview, C.WEBKIT_EDITING_COMMAND_COPY) -} - -func (w *linuxWebviewWindow) selectAll() { - //C.webkit_web_view_execute_editing_command(w.webview, C.WEBKIT_EDITING_COMMAND_SELECT_ALL) -} - -func (w *linuxWebviewWindow) undo() { - //C.webkit_web_view_execute_editing_command(w.webview, C.WEBKIT_EDITING_COMMAND_UNDO) -} - -func (w *linuxWebviewWindow) redo() { -} - -func (w *linuxWebviewWindow) delete() { -} diff --git a/v3/pkg/application/linux_cgo_gtk4.c b/v3/pkg/application/linux_cgo_gtk4.c deleted file mode 100644 index e6f6ce499..000000000 --- a/v3/pkg/application/linux_cgo_gtk4.c +++ /dev/null @@ -1,876 +0,0 @@ -//go:build linux && gtk4 - -#include "linux_cgo_gtk4.h" - -#ifdef WAILS_GTK_DEBUG -#define DEBUG_LOG(fmt, ...) fprintf(stderr, "[GTK4] " fmt "\n", ##__VA_ARGS__) -#else -#define DEBUG_LOG(fmt, ...) -#endif - -// ============================================================================ -// Global state -// ============================================================================ - -static GMenu *app_menu_model = NULL; -static GSimpleActionGroup *app_action_group = NULL; - -// ============================================================================ -// Main thread dispatch -// ============================================================================ - -static gboolean dispatchCallback(gpointer data) { - struct CallbackID *args = data; - unsigned int cid = args->value; - dispatchOnMainThreadCallback(cid); - free(args); - return G_SOURCE_REMOVE; -} - -void dispatchOnMainThread(unsigned int id) { - CallbackID *args = malloc(sizeof(CallbackID)); - args->value = id; - g_idle_add((GSourceFunc)dispatchCallback, (gpointer)args); -} - -// ============================================================================ -// Signal handling -// ============================================================================ - -static void fix_signal(int signum) { - struct sigaction st; - - if (sigaction(signum, NULL, &st) < 0) { - goto fix_signal_error; - } - st.sa_flags |= SA_ONSTACK; - if (sigaction(signum, &st, NULL) < 0) { - goto fix_signal_error; - } - return; -fix_signal_error: - fprintf(stderr, "error fixing handler for signal %d, please " - "report this issue to " - "https://github.com/wailsapp/wails: %s\n", - signum, strerror(errno)); -} - -void install_signal_handlers(void) { -#if defined(SIGCHLD) - fix_signal(SIGCHLD); -#endif -#if defined(SIGHUP) - fix_signal(SIGHUP); -#endif -#if defined(SIGINT) - fix_signal(SIGINT); -#endif -#if defined(SIGQUIT) - fix_signal(SIGQUIT); -#endif -#if defined(SIGABRT) - fix_signal(SIGABRT); -#endif -#if defined(SIGFPE) - fix_signal(SIGFPE); -#endif -#if defined(SIGTERM) - fix_signal(SIGTERM); -#endif -#if defined(SIGBUS) - fix_signal(SIGBUS); -#endif -#if defined(SIGSEGV) - fix_signal(SIGSEGV); -#endif -#if defined(SIGXCPU) - fix_signal(SIGXCPU); -#endif -#if defined(SIGXFSZ) - fix_signal(SIGXFSZ); -#endif -} - -// ============================================================================ -// Object data helpers -// ============================================================================ - -void save_window_id(void *object, uint value) { - g_object_set_data((GObject *)object, "windowid", GUINT_TO_POINTER((guint)value)); -} - -guint get_window_id(void *object) { - return GPOINTER_TO_UINT(g_object_get_data((GObject *)object, "windowid")); -} - -void save_webview_to_content_manager(void *contentManager, void *webview) { - g_object_set_data(G_OBJECT((WebKitUserContentManager *)contentManager), "webview", webview); -} - -WebKitWebView* get_webview_from_content_manager(void *contentManager) { - return WEBKIT_WEB_VIEW(g_object_get_data(G_OBJECT(contentManager), "webview")); -} - -// ============================================================================ -// Signal connection (wrapper for macro) -// ============================================================================ - -void signal_connect(void *widget, char *event, void *cb, uintptr_t data) { - g_signal_connect(widget, event, cb, (gpointer)data); -} - -// ============================================================================ -// WebView helpers -// ============================================================================ - -WebKitWebView* webkit_web_view(GtkWidget *webview) { - return WEBKIT_WEB_VIEW(webview); -} - -// WebKitGTK 6.0: webkit_web_view_new_with_user_content_manager() was removed -// Use g_object_new() with the "user-content-manager" property instead -GtkWidget* create_webview_with_user_content_manager(WebKitUserContentManager *manager) { - return GTK_WIDGET(g_object_new(WEBKIT_TYPE_WEB_VIEW, - "user-content-manager", manager, - NULL)); -} - -// ============================================================================ -// Menu system (GMenu/GAction for GTK4) -// ============================================================================ - -static void on_action_activated(GSimpleAction *action, GVariant *parameter, gpointer user_data) { - MenuItemData *data = (MenuItemData *)user_data; - if (data != NULL) { - menuActionActivated(data->id); - } -} - -void init_app_action_group(void) { - if (app_action_group == NULL) { - app_action_group = g_simple_action_group_new(); - } -} - -void set_app_menu_model(GMenu *menu) { - app_menu_model = menu; -} - -GMenuItem* create_menu_item(const char *label, const char *action_name, guint item_id) { - init_app_action_group(); - - char full_action_name[256]; - snprintf(full_action_name, sizeof(full_action_name), "app.%s", action_name); - - GMenuItem *item = g_menu_item_new(label, full_action_name); - - GSimpleAction *action = g_simple_action_new(action_name, NULL); - MenuItemData *data = g_new0(MenuItemData, 1); - data->id = item_id; - data->action = action; - g_signal_connect(action, "activate", G_CALLBACK(on_action_activated), data); - g_action_map_add_action(G_ACTION_MAP(app_action_group), G_ACTION(action)); - - return item; -} - -GMenuItem* create_check_menu_item(const char *label, const char *action_name, guint item_id, gboolean initial_state) { - init_app_action_group(); - - char full_action_name[256]; - snprintf(full_action_name, sizeof(full_action_name), "app.%s", action_name); - - GMenuItem *item = g_menu_item_new(label, full_action_name); - - GSimpleAction *action = g_simple_action_new_stateful(action_name, NULL, g_variant_new_boolean(initial_state)); - MenuItemData *data = g_new0(MenuItemData, 1); - data->id = item_id; - data->action = action; - g_signal_connect(action, "activate", G_CALLBACK(on_action_activated), data); - g_action_map_add_action(G_ACTION_MAP(app_action_group), G_ACTION(action)); - - return item; -} - -static void on_radio_action_activated(GSimpleAction *action, GVariant *parameter, gpointer user_data) { - const gchar *target = g_variant_get_string(parameter, NULL); - g_simple_action_set_state(action, g_variant_new_string(target)); - guint item_id = (guint)atoi(target); - menuActionActivated(item_id); -} - -GMenuItem* create_radio_menu_item(const char *label, const char *action_name, const char *target, const char *initial_value, guint item_id) { - init_app_action_group(); - - char full_action_name[256]; - snprintf(full_action_name, sizeof(full_action_name), "app.%s", action_name); - - GMenuItem *item = g_menu_item_new(label, NULL); - g_menu_item_set_action_and_target(item, full_action_name, "s", target); - - GAction *existing = g_action_map_lookup_action(G_ACTION_MAP(app_action_group), action_name); - if (existing == NULL) { - GSimpleAction *action = g_simple_action_new_stateful( - action_name, - G_VARIANT_TYPE_STRING, - g_variant_new_string(initial_value) - ); - MenuItemData *data = g_new0(MenuItemData, 1); - data->id = item_id; - data->action = action; - g_signal_connect(action, "activate", G_CALLBACK(on_radio_action_activated), data); - g_action_map_add_action(G_ACTION_MAP(app_action_group), G_ACTION(action)); - } - - return item; -} - -GtkWidget* create_menu_bar_from_model(GMenu *menu_model) { - return gtk_popover_menu_bar_new_from_model(G_MENU_MODEL(menu_model)); -} - -GtkWidget* create_header_bar_with_menu(GMenu *menu_model) { - GtkWidget *header_bar = gtk_header_bar_new(); - - GtkWidget *menu_button = gtk_menu_button_new(); - gtk_menu_button_set_icon_name(GTK_MENU_BUTTON(menu_button), "open-menu-symbolic"); - gtk_menu_button_set_menu_model(GTK_MENU_BUTTON(menu_button), G_MENU_MODEL(menu_model)); - gtk_widget_set_tooltip_text(menu_button, "Main Menu"); - gtk_accessible_update_property(GTK_ACCESSIBLE(menu_button), - GTK_ACCESSIBLE_PROPERTY_LABEL, "Main Menu", -1); - - gtk_header_bar_pack_end(GTK_HEADER_BAR(header_bar), menu_button); - - return header_bar; -} - -void attach_action_group_to_widget(GtkWidget *widget) { - init_app_action_group(); - gtk_widget_insert_action_group(widget, "app", G_ACTION_GROUP(app_action_group)); -} - -void set_action_accelerator(GtkApplication *app, const char *action_name, const char *accel) { - if (app == NULL || accel == NULL || strlen(accel) == 0) return; - - char full_action_name[256]; - snprintf(full_action_name, sizeof(full_action_name), "app.%s", action_name); - - const char *accels[] = { accel, NULL }; - gtk_application_set_accels_for_action(app, full_action_name, accels); -} - -char* build_accelerator_string(guint key, GdkModifierType mods) { - return gtk_accelerator_name(key, mods); -} - -void set_action_enabled(const char *action_name, gboolean enabled) { - if (app_action_group == NULL) return; - GAction *action = g_action_map_lookup_action(G_ACTION_MAP(app_action_group), action_name); - if (action != NULL && G_IS_SIMPLE_ACTION(action)) { - g_simple_action_set_enabled(G_SIMPLE_ACTION(action), enabled); - } -} - -void set_action_state(const char *action_name, gboolean state) { - if (app_action_group == NULL) return; - GAction *action = g_action_map_lookup_action(G_ACTION_MAP(app_action_group), action_name); - if (action != NULL && G_IS_SIMPLE_ACTION(action)) { - g_simple_action_set_state(G_SIMPLE_ACTION(action), g_variant_new_boolean(state)); - } -} - -gboolean get_action_state(const char *action_name) { - if (app_action_group == NULL) return FALSE; - GAction *action = g_action_map_lookup_action(G_ACTION_MAP(app_action_group), action_name); - if (action != NULL) { - GVariant *state = g_action_get_state(action); - if (state != NULL) { - gboolean result = g_variant_get_boolean(state); - g_variant_unref(state); - return result; - } - } - return FALSE; -} - -void menu_remove_item(GMenu *menu, gint position) { - g_menu_remove(menu, position); -} - -void menu_insert_item(GMenu *menu, gint position, GMenuItem *item) { - g_menu_insert_item(menu, position, item); -} - -// ============================================================================ -// Window event controllers (GTK4 style) -// ============================================================================ - -void setupWindowEventControllers(GtkWindow *window, GtkWidget *webview, uintptr_t winID) { - // Close request (replaces delete-event) - g_signal_connect(window, "close-request", G_CALLBACK(handleCloseRequest), (gpointer)winID); - - // Window state changes (maximize, fullscreen, etc) - g_signal_connect(window, "notify::maximized", G_CALLBACK(handleNotifyState), (gpointer)winID); - g_signal_connect(window, "notify::fullscreened", G_CALLBACK(handleNotifyState), (gpointer)winID); - - // Focus controller for window - GtkEventController *focus_controller = gtk_event_controller_focus_new(); - gtk_widget_add_controller(GTK_WIDGET(window), focus_controller); - g_signal_connect(focus_controller, "enter", G_CALLBACK(handleFocusEnter), (gpointer)winID); - g_signal_connect(focus_controller, "leave", G_CALLBACK(handleFocusLeave), (gpointer)winID); - - // Click gesture for webview (button press/release) - GtkGesture *click_gesture = gtk_gesture_click_new(); - gtk_gesture_single_set_button(GTK_GESTURE_SINGLE(click_gesture), 0); // Listen to all buttons - gtk_widget_add_controller(webview, GTK_EVENT_CONTROLLER(click_gesture)); - g_signal_connect(click_gesture, "pressed", G_CALLBACK(handleButtonPressed), (gpointer)winID); - g_signal_connect(click_gesture, "released", G_CALLBACK(handleButtonReleased), (gpointer)winID); - - // Key controller for webview - GtkEventController *key_controller = gtk_event_controller_key_new(); - gtk_widget_add_controller(webview, key_controller); - g_signal_connect(key_controller, "key-pressed", G_CALLBACK(handleKeyPressed), (gpointer)winID); -} - -// ============================================================================ -// Window drag/resize (GdkToplevel for GTK4) -// ============================================================================ - -void beginWindowDrag(GtkWindow *window, int button, double x, double y, guint32 timestamp) { - GtkNative *native = gtk_widget_get_native(GTK_WIDGET(window)); - if (native == NULL) return; - - GdkSurface *surface = gtk_native_get_surface(native); - if (surface == NULL || !GDK_IS_TOPLEVEL(surface)) return; - - GdkToplevel *toplevel = GDK_TOPLEVEL(surface); - GdkDevice *device = NULL; - GdkDisplay *display = gdk_surface_get_display(surface); - GdkSeat *seat = gdk_display_get_default_seat(display); - if (seat) { - device = gdk_seat_get_pointer(seat); - } - - gdk_toplevel_begin_move(toplevel, device, button, x, y, timestamp); -} - -void beginWindowResize(GtkWindow *window, GdkSurfaceEdge edge, int button, double x, double y, guint32 timestamp) { - GtkNative *native = gtk_widget_get_native(GTK_WIDGET(window)); - if (native == NULL) return; - - GdkSurface *surface = gtk_native_get_surface(native); - if (surface == NULL || !GDK_IS_TOPLEVEL(surface)) return; - - GdkToplevel *toplevel = GDK_TOPLEVEL(surface); - GdkDevice *device = NULL; - GdkDisplay *display = gdk_surface_get_display(surface); - GdkSeat *seat = gdk_display_get_default_seat(display); - if (seat) { - device = gdk_seat_get_pointer(seat); - } - - gdk_toplevel_begin_resize(toplevel, edge, device, button, x, y, timestamp); -} - -// ============================================================================ -// Drag and drop (GtkDropTarget for GTK4) -// ============================================================================ - -static gboolean on_drop_accept(GtkDropTarget *target, GdkDrop *drop, gpointer data) { - GdkContentFormats *formats = gdk_drop_get_formats(drop); - return gdk_content_formats_contain_gtype(formats, GDK_TYPE_FILE_LIST); -} - -static GdkDragAction on_drop_enter(GtkDropTarget *target, gdouble x, gdouble y, gpointer data) { - onDropEnter((uintptr_t)data); - return GDK_ACTION_COPY; -} - -static void on_drop_leave(GtkDropTarget *target, gpointer data) { - onDropLeave((uintptr_t)data); -} - -static GdkDragAction on_drop_motion(GtkDropTarget *target, gdouble x, gdouble y, gpointer data) { - onDropMotion((gint)x, (gint)y, (uintptr_t)data); - return GDK_ACTION_COPY; -} - -static gboolean on_drop(GtkDropTarget *target, const GValue *value, gdouble x, gdouble y, gpointer data) { - if (!G_VALUE_HOLDS(value, GDK_TYPE_FILE_LIST)) { - return FALSE; - } - - GSList *file_list = g_value_get_boxed(value); - if (file_list == NULL) { - return FALSE; - } - - guint count = g_slist_length(file_list); - if (count == 0) { - return FALSE; - } - - char **paths = g_new0(char*, count + 1); - guint i = 0; - for (GSList *l = file_list; l != NULL; l = l->next) { - GFile *file = G_FILE(l->data); - paths[i++] = g_file_get_path(file); - } - paths[count] = NULL; - - onDropFiles(paths, (gint)x, (gint)y, (uintptr_t)data); - - for (i = 0; i < count; i++) { - g_free(paths[i]); - } - g_free(paths); - - return TRUE; -} - -static void on_motion_enter(GtkDropControllerMotion *ctrl, gdouble x, gdouble y, gpointer data) { - onDropEnter((uintptr_t)data); -} - -static void on_motion_leave(GtkDropControllerMotion *ctrl, gpointer data) { - onDropLeave((uintptr_t)data); -} - -static void on_motion_motion(GtkDropControllerMotion *ctrl, gdouble x, gdouble y, gpointer data) { - onDropMotion((gint)x, (gint)y, (uintptr_t)data); -} - -void enableDND(GtkWidget *widget, uintptr_t winID) { - GtkEventController *motion_ctrl = gtk_drop_controller_motion_new(); - gtk_event_controller_set_propagation_phase(motion_ctrl, GTK_PHASE_CAPTURE); - g_signal_connect(motion_ctrl, "enter", G_CALLBACK(on_motion_enter), (gpointer)winID); - g_signal_connect(motion_ctrl, "leave", G_CALLBACK(on_motion_leave), (gpointer)winID); - g_signal_connect(motion_ctrl, "motion", G_CALLBACK(on_motion_motion), (gpointer)winID); - gtk_widget_add_controller(widget, motion_ctrl); - - GtkDropTarget *target = gtk_drop_target_new(GDK_TYPE_FILE_LIST, GDK_ACTION_COPY); - gtk_event_controller_set_propagation_phase(GTK_EVENT_CONTROLLER(target), GTK_PHASE_CAPTURE); - g_signal_connect(target, "accept", G_CALLBACK(on_drop_accept), (gpointer)winID); - g_signal_connect(target, "enter", G_CALLBACK(on_drop_enter), (gpointer)winID); - g_signal_connect(target, "leave", G_CALLBACK(on_drop_leave), (gpointer)winID); - g_signal_connect(target, "motion", G_CALLBACK(on_drop_motion), (gpointer)winID); - g_signal_connect(target, "drop", G_CALLBACK(on_drop), (gpointer)winID); - gtk_widget_add_controller(widget, GTK_EVENT_CONTROLLER(target)); -} - -void disableDND(GtkWidget *widget, uintptr_t winID) { -} - -// ============================================================================ -// File dialogs (GtkFileDialog for GTK4) -// ============================================================================ - -GtkFileDialog* create_file_dialog(const char *title) { - GtkFileDialog *dialog = gtk_file_dialog_new(); - gtk_file_dialog_set_title(dialog, title); - return dialog; -} - -void add_file_filter(GtkFileDialog *dialog, GListStore *filters, const char *name, const char *pattern) { - GtkFileFilter *filter = gtk_file_filter_new(); - gtk_file_filter_set_name(filter, name); - - gchar **patterns = g_strsplit(pattern, ";", -1); - for (int i = 0; patterns[i] != NULL; i++) { - gchar *p = g_strstrip(patterns[i]); - if (strlen(p) > 0) { - gtk_file_filter_add_pattern(filter, p); - } - } - g_strfreev(patterns); - - g_list_store_append(filters, filter); - g_object_unref(filter); -} - -void set_file_dialog_filters(GtkFileDialog *dialog, GListStore *filters) { - gtk_file_dialog_set_filters(dialog, G_LIST_MODEL(filters)); -} - -// File dialog callbacks - -static void on_file_dialog_open_finish(GObject *source, GAsyncResult *result, gpointer user_data) { - FileDialogData *data = (FileDialogData *)user_data; - GtkFileDialog *dialog = GTK_FILE_DIALOG(source); - GError *error = NULL; - - GFile *file = gtk_file_dialog_open_finish(dialog, result, &error); - - if (error != NULL) { - DEBUG_LOG("open_finish error: %s", error->message); - fileDialogCallback(data->request_id, NULL, 0, TRUE); - g_error_free(error); - } else if (file != NULL) { - char *path = g_file_get_path(file); - char *files[1] = { path }; - fileDialogCallback(data->request_id, files, 1, FALSE); - g_free(path); - g_object_unref(file); - } else { - // Cancelled - no error but no file - fileDialogCallback(data->request_id, NULL, 0, TRUE); - } - - g_free(data); -} - -static void on_file_dialog_open_multiple_finish(GObject *source, GAsyncResult *result, gpointer user_data) { - FileDialogData *data = (FileDialogData *)user_data; - GtkFileDialog *dialog = GTK_FILE_DIALOG(source); - GError *error = NULL; - - GListModel *files = gtk_file_dialog_open_multiple_finish(dialog, result, &error); - - if (error != NULL) { - DEBUG_LOG("open_multiple_finish error: %s", error->message); - fileDialogCallback(data->request_id, NULL, 0, TRUE); - g_error_free(error); - } else if (files != NULL) { - guint n = g_list_model_get_n_items(files); - char **paths = g_new0(char*, n + 1); - - for (guint i = 0; i < n; i++) { - GFile *file = G_FILE(g_list_model_get_item(files, i)); - paths[i] = g_file_get_path(file); - g_object_unref(file); - } - - fileDialogCallback(data->request_id, paths, (int)n, FALSE); - - for (guint i = 0; i < n; i++) { - g_free(paths[i]); - } - g_free(paths); - g_object_unref(files); - } else { - fileDialogCallback(data->request_id, NULL, 0, TRUE); - } - - g_free(data); -} - -static void on_file_dialog_select_folder_finish(GObject *source, GAsyncResult *result, gpointer user_data) { - FileDialogData *data = (FileDialogData *)user_data; - GtkFileDialog *dialog = GTK_FILE_DIALOG(source); - GError *error = NULL; - - GFile *file = gtk_file_dialog_select_folder_finish(dialog, result, &error); - - if (error != NULL) { - DEBUG_LOG("select_folder_finish error: %s", error->message); - fileDialogCallback(data->request_id, NULL, 0, TRUE); - g_error_free(error); - } else if (file != NULL) { - char *path = g_file_get_path(file); - char *files[1] = { path }; - fileDialogCallback(data->request_id, files, 1, FALSE); - g_free(path); - g_object_unref(file); - } else { - fileDialogCallback(data->request_id, NULL, 0, TRUE); - } - - g_free(data); -} - -static void on_file_dialog_select_multiple_folders_finish(GObject *source, GAsyncResult *result, gpointer user_data) { - FileDialogData *data = (FileDialogData *)user_data; - GtkFileDialog *dialog = GTK_FILE_DIALOG(source); - GError *error = NULL; - - GListModel *files = gtk_file_dialog_select_multiple_folders_finish(dialog, result, &error); - - if (error != NULL) { - DEBUG_LOG("select_multiple_folders_finish error: %s", error->message); - fileDialogCallback(data->request_id, NULL, 0, TRUE); - g_error_free(error); - } else if (files != NULL) { - guint n = g_list_model_get_n_items(files); - char **paths = g_new0(char*, n + 1); - - for (guint i = 0; i < n; i++) { - GFile *file = G_FILE(g_list_model_get_item(files, i)); - paths[i] = g_file_get_path(file); - g_object_unref(file); - } - - fileDialogCallback(data->request_id, paths, (int)n, FALSE); - - for (guint i = 0; i < n; i++) { - g_free(paths[i]); - } - g_free(paths); - g_object_unref(files); - } else { - fileDialogCallback(data->request_id, NULL, 0, TRUE); - } - - g_free(data); -} - -static void on_file_dialog_save_finish(GObject *source, GAsyncResult *result, gpointer user_data) { - FileDialogData *data = (FileDialogData *)user_data; - GtkFileDialog *dialog = GTK_FILE_DIALOG(source); - GError *error = NULL; - - GFile *file = gtk_file_dialog_save_finish(dialog, result, &error); - - if (error != NULL) { - DEBUG_LOG("save_finish error: %s", error->message); - fileDialogCallback(data->request_id, NULL, 0, TRUE); - g_error_free(error); - } else if (file != NULL) { - char *path = g_file_get_path(file); - char *files[1] = { path }; - fileDialogCallback(data->request_id, files, 1, FALSE); - g_free(path); - g_object_unref(file); - } else { - fileDialogCallback(data->request_id, NULL, 0, TRUE); - } - - g_free(data); -} - -void show_open_file_dialog(GtkWindow *parent, GtkFileDialog *dialog, guint request_id, gboolean allow_multiple, gboolean is_folder) { - FileDialogData *data = g_new0(FileDialogData, 1); - data->request_id = request_id; - data->allow_multiple = allow_multiple; - data->is_folder = is_folder; - - if (is_folder && allow_multiple) { - gtk_file_dialog_select_multiple_folders(dialog, parent, NULL, on_file_dialog_select_multiple_folders_finish, data); - } else if (is_folder) { - gtk_file_dialog_select_folder(dialog, parent, NULL, on_file_dialog_select_folder_finish, data); - } else if (allow_multiple) { - gtk_file_dialog_open_multiple(dialog, parent, NULL, on_file_dialog_open_multiple_finish, data); - } else { - gtk_file_dialog_open(dialog, parent, NULL, on_file_dialog_open_finish, data); - } -} - -void show_save_file_dialog(GtkWindow *parent, GtkFileDialog *dialog, guint request_id) { - FileDialogData *data = g_new0(FileDialogData, 1); - data->request_id = request_id; - data->is_save = TRUE; - - gtk_file_dialog_save(dialog, parent, NULL, on_file_dialog_save_finish, data); -} - -// ============================================================================ -// Custom Message Dialogs (GtkWindow-based for proper styling) -// ============================================================================ - -typedef struct { - GtkWindow *dialog; - guint request_id; - int button_count; - int cancel_button; - GtkWidget **buttons; -} MessageDialogData; - -static void message_dialog_cleanup(MessageDialogData *data) { - if (data->buttons != NULL) { - g_free(data->buttons); - } - g_free(data); -} - -static void on_message_dialog_button_clicked(GtkButton *button, gpointer user_data) { - MessageDialogData *data = (MessageDialogData *)user_data; - int index = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(button), "button-index")); - - alertDialogCallback(data->request_id, index); - gtk_window_destroy(data->dialog); - message_dialog_cleanup(data); -} - -static gboolean on_message_dialog_close(GtkWindow *window, gpointer user_data) { - MessageDialogData *data = (MessageDialogData *)user_data; - int result = (data->cancel_button >= 0) ? data->cancel_button : -1; - alertDialogCallback(data->request_id, result); - message_dialog_cleanup(data); - return TRUE; -} - -static gboolean on_message_dialog_key_pressed(GtkEventControllerKey *controller, - guint keyval, guint keycode, - GdkModifierType state, gpointer user_data) { - MessageDialogData *data = (MessageDialogData *)user_data; - - if (keyval == GDK_KEY_Escape && data->cancel_button >= 0 && data->cancel_button < data->button_count) { - gtk_widget_activate(data->buttons[data->cancel_button]); - return TRUE; - } - return FALSE; -} - -void show_message_dialog(GtkWindow *parent, const char *heading, const char *body, - const char *icon_name, const unsigned char *icon_data, int icon_data_len, - const char **buttons, int button_count, - int default_button, int cancel_button, int destructive_button, - guint request_id) { - - GtkWidget *dialog = gtk_window_new(); - gtk_window_set_modal(GTK_WINDOW(dialog), TRUE); - gtk_window_set_resizable(GTK_WINDOW(dialog), FALSE); - gtk_window_set_decorated(GTK_WINDOW(dialog), TRUE); - gtk_widget_add_css_class(dialog, "message"); - gtk_widget_set_size_request(dialog, 300, -1); - - if (parent != NULL) { - gtk_window_set_transient_for(GTK_WINDOW(dialog), parent); - } - - MessageDialogData *data = g_new0(MessageDialogData, 1); - data->dialog = GTK_WINDOW(dialog); - data->request_id = request_id; - data->button_count = button_count; - data->cancel_button = cancel_button; - data->buttons = (button_count > 0) ? g_new0(GtkWidget*, button_count) : NULL; - - GtkWidget *content = gtk_box_new(GTK_ORIENTATION_VERTICAL, 12); - gtk_widget_set_margin_start(content, 24); - gtk_widget_set_margin_end(content, 24); - gtk_widget_set_margin_top(content, 24); - gtk_widget_set_margin_bottom(content, 24); - - const int symbolic_icon_size = 32; - GtkWidget *icon_widget = NULL; - if (icon_data != NULL && icon_data_len > 0) { - GBytes *bytes = g_bytes_new(icon_data, icon_data_len); - GdkTexture *texture = gdk_texture_new_from_bytes(bytes, NULL); - g_bytes_unref(bytes); - if (texture != NULL) { - int tex_size = gdk_texture_get_width(texture); - GtkWidget *image = gtk_image_new_from_paintable(GDK_PAINTABLE(texture)); - gtk_image_set_pixel_size(GTK_IMAGE(image), tex_size); - icon_widget = image; - g_object_unref(texture); - } - } else if (icon_name != NULL && strlen(icon_name) > 0) { - icon_widget = gtk_image_new_from_icon_name(icon_name); - gtk_image_set_pixel_size(GTK_IMAGE(icon_widget), symbolic_icon_size); - } - - if (icon_widget != NULL) { - gtk_widget_set_halign(icon_widget, GTK_ALIGN_CENTER); - gtk_widget_set_margin_bottom(icon_widget, 12); - gtk_box_append(GTK_BOX(content), icon_widget); - } - - if (heading != NULL && strlen(heading) > 0) { - GtkWidget *heading_label = gtk_label_new(heading); - gtk_widget_add_css_class(heading_label, "title-2"); - gtk_widget_set_halign(heading_label, GTK_ALIGN_CENTER); - gtk_label_set_wrap(GTK_LABEL(heading_label), TRUE); - gtk_label_set_max_width_chars(GTK_LABEL(heading_label), 50); - gtk_box_append(GTK_BOX(content), heading_label); - } - - if (body != NULL && strlen(body) > 0) { - GtkWidget *body_label = gtk_label_new(body); - gtk_widget_set_halign(body_label, GTK_ALIGN_CENTER); - gtk_label_set_wrap(GTK_LABEL(body_label), TRUE); - gtk_label_set_max_width_chars(GTK_LABEL(body_label), 50); - gtk_widget_add_css_class(body_label, "dim-label"); - gtk_box_append(GTK_BOX(content), body_label); - } - - if (button_count > 0) { - GtkWidget *button_box = gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 8); - gtk_widget_set_halign(button_box, GTK_ALIGN_CENTER); - gtk_widget_set_margin_top(button_box, 12); - - for (int i = 0; i < button_count; i++) { - GtkWidget *btn = gtk_button_new_with_label(buttons[i]); - g_object_set_data(G_OBJECT(btn), "button-index", GINT_TO_POINTER(i)); - g_signal_connect(btn, "clicked", G_CALLBACK(on_message_dialog_button_clicked), data); - data->buttons[i] = btn; - - if (i == default_button) { - gtk_widget_add_css_class(btn, "suggested-action"); - gtk_widget_add_css_class(btn, "default"); - } - if (i == destructive_button) { - gtk_widget_add_css_class(btn, "destructive-action"); - } - - gtk_box_append(GTK_BOX(button_box), btn); - } - - gtk_box_append(GTK_BOX(content), button_box); - } - - gtk_window_set_child(GTK_WINDOW(dialog), content); - - GtkEventController *key_controller = gtk_event_controller_key_new(); - g_signal_connect(key_controller, "key-pressed", G_CALLBACK(on_message_dialog_key_pressed), data); - gtk_widget_add_controller(dialog, key_controller); - - g_signal_connect(dialog, "close-request", G_CALLBACK(on_message_dialog_close), data); - - gtk_window_present(GTK_WINDOW(dialog)); - - if (default_button >= 0 && default_button < button_count) { - gtk_window_set_default_widget(GTK_WINDOW(dialog), data->buttons[default_button]); - gtk_widget_grab_focus(data->buttons[default_button]); - } -} - -// ============================================================================ -// Clipboard (async API for GTK4) -// ============================================================================ - -static char *clipboard_sync_result = NULL; -static gboolean clipboard_sync_done = FALSE; - -static void on_clipboard_sync_finish(GObject *source, GAsyncResult *result, gpointer user_data) { - GdkClipboard *clipboard = GDK_CLIPBOARD(source); - GError *error = NULL; - - clipboard_sync_result = gdk_clipboard_read_text_finish(clipboard, result, &error); - - if (error != NULL) { - DEBUG_LOG("clipboard read error: %s", error->message); - g_error_free(error); - clipboard_sync_result = NULL; - } - clipboard_sync_done = TRUE; -} - -char* clipboard_get_text_sync(void) { - GdkDisplay *display = gdk_display_get_default(); - GdkClipboard *clipboard = gdk_display_get_clipboard(display); - - clipboard_sync_done = FALSE; - clipboard_sync_result = NULL; - - gdk_clipboard_read_text_async(clipboard, NULL, on_clipboard_sync_finish, NULL); - - GMainContext *ctx = g_main_context_default(); - while (!clipboard_sync_done) { - g_main_context_iteration(ctx, TRUE); - } - - return clipboard_sync_result; -} - -void clipboard_free_text(char *text) { - if (text != NULL) { - g_free(text); - } -} - -// ============================================================================ -// Misc -// ============================================================================ - -int GetNumScreens(void) { - return 0; -} diff --git a/v3/pkg/application/linux_cgo_gtk4.go b/v3/pkg/application/linux_cgo_gtk4.go deleted file mode 100644 index c077e2fc9..000000000 --- a/v3/pkg/application/linux_cgo_gtk4.go +++ /dev/null @@ -1,2014 +0,0 @@ -//go:build linux && cgo && gtk4 && !android - -package application - -import ( - "fmt" - "strings" - "sync" - "time" - "unsafe" - - "github.com/wailsapp/wails/v3/internal/assetserver/webview" - "github.com/wailsapp/wails/v3/pkg/events" -) - -/* -#cgo linux pkg-config: gtk4 webkitgtk-6.0 - -#include "linux_cgo_gtk4.h" -*/ -import "C" - -// Calloc handles alloc/dealloc of C data -type Calloc struct { - pool []unsafe.Pointer -} - -// NewCalloc creates a new allocator -func NewCalloc() Calloc { - return Calloc{} -} - -// String creates a new C string and retains a reference to it -func (c Calloc) String(in string) *C.char { - result := C.CString(in) - c.pool = append(c.pool, unsafe.Pointer(result)) - return result -} - -// Free frees all allocated C memory -func (c Calloc) Free() { - for _, str := range c.pool { - C.free(str) - } - c.pool = []unsafe.Pointer{} -} - -type windowPointer *C.GtkWindow -type identifier C.uint -type pointer unsafe.Pointer -type GSList C.GSList -type GSListPointer *GSList - -// getLinuxWebviewWindow safely extracts a linuxWebviewWindow from a Window interface -func getLinuxWebviewWindow(window Window) *linuxWebviewWindow { - if window == nil { - return nil - } - - webviewWindow, ok := window.(*WebviewWindow) - if !ok { - return nil - } - - lw, ok := webviewWindow.impl.(*linuxWebviewWindow) - if !ok { - return nil - } - - return lw -} - -var ( - nilPointer pointer = nil - nilRadioGroup GSListPointer = nil -) - -var ( - gtkSignalToMenuItem map[uint]*MenuItem - mainThreadId *C.GThread -) - -var registerURIScheme sync.Once - -func init() { - gtkSignalToMenuItem = map[uint]*MenuItem{} - mainThreadId = C.g_thread_self() -} - -// mainthread stuff -func dispatchOnMainThread(id uint) { - C.dispatchOnMainThread(C.uint(id)) -} - -//export dispatchOnMainThreadCallback -func dispatchOnMainThreadCallback(callbackID C.uint) { - executeOnMainThread(uint(callbackID)) -} - -//export activateLinux -func activateLinux(data pointer) { - app := getNativeApplication() - app.markActivated() - processApplicationEvent(C.uint(events.Linux.ApplicationStartup), data) -} - -//export processApplicationEvent -func processApplicationEvent(eventID C.uint, data pointer) { - event := newApplicationEvent(events.ApplicationEventType(eventID)) - - switch event.Id { - case uint(events.Linux.SystemThemeChanged): - isDark := globalApplication.Env.IsDarkMode() - event.Context().setIsDarkMode(isDark) - } - applicationEvents <- event -} - -func isOnMainThread() bool { - threadId := C.g_thread_self() - return threadId == mainThreadId -} - -// implementation below -func appName() string { - name := C.g_get_application_name() - defer C.free(unsafe.Pointer(name)) - return C.GoString(name) -} - -func appNew(name string) pointer { - C.install_signal_handlers() - - appId := fmt.Sprintf("org.wails.%s", name) - nameC := C.CString(appId) - defer C.free(unsafe.Pointer(nameC)) - return pointer(C.gtk_application_new(nameC, C.APPLICATION_DEFAULT_FLAGS)) -} - -func setProgramName(prgName string) { - cPrgName := C.CString(prgName) - defer C.free(unsafe.Pointer(cPrgName)) - C.g_set_prgname(cPrgName) -} - -func appRun(app pointer) error { - application := (*C.GApplication)(app) - C.g_application_hold(application) - - signal := C.CString("activate") - defer C.free(unsafe.Pointer(signal)) - C.signal_connect(unsafe.Pointer(application), signal, C.activateLinux, 0) - status := C.g_application_run(application, 0, nil) - C.g_application_release(application) - C.g_object_unref(C.gpointer(app)) - - var err error - if status != 0 { - err = fmt.Errorf("exit code: %d", status) - } - return err -} - -func appDestroy(application pointer) { - C.g_application_quit((*C.GApplication)(application)) -} - -func (w *linuxWebviewWindow) contextMenuSignals(menu pointer) { - // GTK4: Context menus use GtkPopoverMenu, signals handled differently - // TODO: Implement GTK4 context menu signal handling -} - -func (w *linuxWebviewWindow) contextMenuShow(menu pointer, data *ContextMenuData) { - // GTK4: Use GtkPopoverMenu instead of gtk_menu_popup_at_rect - // TODO: Implement GTK4 context menu popup -} - -func (a *linuxApp) getCurrentWindowID() uint { - window := (*C.GtkWindow)(C.gtk_application_get_active_window((*C.GtkApplication)(a.application))) - if window == nil { - return uint(1) - } - identifier, ok := a.windowMap[window] - if ok { - return identifier - } - return uint(1) -} - -func (a *linuxApp) getWindows() []pointer { - result := []pointer{} - windows := C.gtk_application_get_windows((*C.GtkApplication)(a.application)) - for { - result = append(result, pointer(windows.data)) - windows = windows.next - if windows == nil { - return result - } - } -} - -func (a *linuxApp) hideAllWindows() { - for _, window := range a.getWindows() { - C.gtk_widget_set_visible((*C.GtkWidget)(window), C.gboolean(0)) - } -} - -func (a *linuxApp) showAllWindows() { - for _, window := range a.getWindows() { - C.gtk_window_present((*C.GtkWindow)(window)) - } -} - -func (a *linuxApp) setIcon(icon []byte) { - // TODO: Implement GTK4 icon setting using GdkTexture - gbytes := C.g_bytes_new_static(C.gconstpointer(unsafe.Pointer(&icon[0])), C.ulong(len(icon))) - defer C.g_bytes_unref(gbytes) -} - -func clipboardGet() string { - cText := C.clipboard_get_text_sync() - if cText != nil { - result := C.GoString(cText) - C.clipboard_free_text(cText) - return result - } - return "" -} - -func clipboardSet(text string) { - display := C.gdk_display_get_default() - clip := C.gdk_display_get_clipboard(display) - cText := C.CString(text) - C.gdk_clipboard_set_text(clip, cText) - C.free(unsafe.Pointer(cText)) -} - -// Menu - GTK4 uses GMenu/GAction instead of GtkMenu - -var menuItemActionCounter uint32 = 0 -var menuItemActions = make(map[uint]string) -var menuItemIds = make(map[pointer]uint) -var menuItemIdsMutex sync.RWMutex - -func generateActionName(itemId uint) string { - menuItemActionCounter++ - name := fmt.Sprintf("action_%d", menuItemActionCounter) - menuItemActions[itemId] = name - return name -} - -//export menuActionActivated -func menuActionActivated(id C.guint) { - item, ok := gtkSignalToMenuItem[uint(id)] - if !ok { - return - } - switch item.itemType { - case text: - menuItemClicked <- item.id - case checkbox: - impl := item.impl.(*linuxMenuItem) - currentState := impl.isChecked() - impl.setChecked(!currentState) - menuItemClicked <- item.id - case radio: - menuItem := item.impl.(*linuxMenuItem) - if !menuItem.isChecked() { - menuItem.setChecked(true) - menuItemClicked <- item.id - } - } -} - -func menuNewSection() pointer { - return pointer(C.g_menu_new()) -} - -func menuAppendSection(menu *Menu, section pointer) { - if menu.impl == nil { - return - } - impl := menu.impl.(*linuxMenu) - if impl.native == nil { - return - } - gmenu := (*C.GMenu)(impl.native) - C.g_menu_append_section(gmenu, nil, (*C.GMenuModel)(section)) -} - -func menuAppendItemToSection(section pointer, item *MenuItem) { - if item.impl == nil { - return - } - menuImpl := item.impl.(*linuxMenuItem) - if menuImpl.native == nil { - return - } - gsection := (*C.GMenu)(section) - gitem := (*C.GMenuItem)(menuImpl.native) - - menuImpl.parentMenu = section - menuImpl.isHidden = item.hidden - - if !item.hidden { - C.g_menu_append_item(gsection, gitem) - } -} - -var menuItemCounters = make(map[pointer]int) -var menuItemCountersLock sync.Mutex - -func menuAppend(parent *Menu, menu *MenuItem, hidden bool) { - if parent.impl == nil || menu.impl == nil { - return - } - parentImpl := parent.impl.(*linuxMenu) - menuImpl := menu.impl.(*linuxMenuItem) - if parentImpl.native == nil || menuImpl.native == nil { - return - } - gmenu := (*C.GMenu)(parentImpl.native) - gitem := (*C.GMenuItem)(menuImpl.native) - - menuImpl.parentMenu = parentImpl.native - menuImpl.isHidden = hidden - - menuItemCountersLock.Lock() - menuImpl.menuIndex = menuItemCounters[parentImpl.native] - menuItemCounters[parentImpl.native]++ - menuItemCountersLock.Unlock() - - if !hidden { - C.g_menu_append_item(gmenu, gitem) - } -} - -func menuBarNew() pointer { - gmenu := C.g_menu_new() - C.set_app_menu_model(gmenu) - return pointer(gmenu) -} - -func menuNew() pointer { - return pointer(C.g_menu_new()) -} - -func menuSetSubmenu(item *MenuItem, menu *Menu) { - if item.impl == nil || menu.impl == nil { - return - } - itemImpl := item.impl.(*linuxMenuItem) - menuImpl := menu.impl.(*linuxMenu) - if itemImpl.native == nil || menuImpl.native == nil { - return - } - gitem := (*C.GMenuItem)(itemImpl.native) - gmenu := (*C.GMenu)(menuImpl.native) - C.g_menu_item_set_submenu(gitem, (*C.GMenuModel)(unsafe.Pointer(gmenu))) -} - -func menuGetRadioGroup(item *linuxMenuItem) *GSList { - return nil -} - -//export handleClick -func handleClick(idPtr unsafe.Pointer) { -} - -func attachMenuHandler(item *MenuItem) uint { - gtkSignalToMenuItem[item.id] = item - return item.id -} - -func menuItemChecked(widget pointer) bool { - if widget == nil { - return false - } - menuItemIdsMutex.RLock() - itemId, exists := menuItemIds[widget] - menuItemIdsMutex.RUnlock() - if !exists { - return false - } - actionName, ok := menuItemActions[itemId] - if !ok { - return false - } - cName := C.CString(actionName) - defer C.free(unsafe.Pointer(cName)) - return C.get_action_state(cName) != 0 -} - -func menuItemNew(label string, bitmap []byte) pointer { - return nil -} - -func menuItemNewWithId(label string, bitmap []byte, itemId uint) pointer { - cLabel := C.CString(label) - defer C.free(unsafe.Pointer(cLabel)) - actionName := generateActionName(itemId) - cAction := C.CString(actionName) - defer C.free(unsafe.Pointer(cAction)) - - gitem := C.create_menu_item(cLabel, cAction, C.guint(itemId)) - - menuItemIdsMutex.Lock() - menuItemIds[pointer(gitem)] = itemId - menuItemIdsMutex.Unlock() - return pointer(gitem) -} - -func menuItemDestroy(widget pointer) { - if widget != nil { - C.g_object_unref(C.gpointer(widget)) - } -} - -func menuItemSetHidden(item *linuxMenuItem, hidden bool) { - if item.parentMenu == nil { - return - } - gmenu := (*C.GMenu)(item.parentMenu) - gitem := (*C.GMenuItem)(item.native) - - if hidden { - C.menu_remove_item(gmenu, C.gint(item.menuIndex)) - } else { - C.menu_insert_item(gmenu, C.gint(item.menuIndex), gitem) - } -} - -func menuItemAddProperties(menuItem *C.GtkWidget, label string, bitmap []byte) pointer { - return nil -} - -func menuCheckItemNew(label string, bitmap []byte) pointer { - return nil -} - -func menuCheckItemNewWithId(label string, bitmap []byte, itemId uint, checked bool) pointer { - cLabel := C.CString(label) - defer C.free(unsafe.Pointer(cLabel)) - actionName := generateActionName(itemId) - cAction := C.CString(actionName) - defer C.free(unsafe.Pointer(cAction)) - - initialState := C.gboolean(0) - if checked { - initialState = C.gboolean(1) - } - - gitem := C.create_check_menu_item(cLabel, cAction, C.guint(itemId), initialState) - - menuItemIdsMutex.Lock() - menuItemIds[pointer(gitem)] = itemId - menuItemIdsMutex.Unlock() - return pointer(gitem) -} - -func menuItemSetChecked(widget pointer, checked bool) { - if widget == nil { - return - } - menuItemIdsMutex.RLock() - itemId, exists := menuItemIds[widget] - menuItemIdsMutex.RUnlock() - if !exists { - return - } - actionName, ok := menuItemActions[itemId] - if !ok { - return - } - cName := C.CString(actionName) - defer C.free(unsafe.Pointer(cName)) - state := C.gboolean(0) - if checked { - state = C.gboolean(1) - } - C.set_action_state(cName, state) -} - -func menuItemSetDisabled(widget pointer, disabled bool) { - if widget == nil { - return - } - menuItemIdsMutex.RLock() - itemId, exists := menuItemIds[widget] - menuItemIdsMutex.RUnlock() - if !exists { - return - } - actionName, ok := menuItemActions[itemId] - if !ok { - return - } - cName := C.CString(actionName) - defer C.free(unsafe.Pointer(cName)) - enabled := C.gboolean(1) - if disabled { - enabled = C.gboolean(0) - } - C.set_action_enabled(cName, enabled) -} - -func menuItemSetLabel(widget pointer, label string) { - if widget == nil { - return - } - cLabel := C.CString(label) - defer C.free(unsafe.Pointer(cLabel)) - C.g_menu_item_set_label((*C.GMenuItem)(widget), cLabel) -} - -func menuItemRemoveBitmap(widget pointer) { -} - -func menuItemSetBitmap(widget pointer, bitmap []byte) { -} - -func menuItemSetToolTip(widget pointer, tooltip string) { -} - -func menuItemSignalBlock(widget pointer, handlerId uint, block bool) { -} - -func menuRadioItemNew(group *GSList, label string) pointer { - return nil -} - -func menuRadioItemNewWithId(label string, itemId uint, checked bool) pointer { - cLabel := C.CString(label) - defer C.free(unsafe.Pointer(cLabel)) - actionName := generateActionName(itemId) - cAction := C.CString(actionName) - defer C.free(unsafe.Pointer(cAction)) - - initialState := C.gboolean(0) - if checked { - initialState = C.gboolean(1) - } - - gitem := C.create_check_menu_item(cLabel, cAction, C.guint(itemId), initialState) - - menuItemIdsMutex.Lock() - menuItemIds[pointer(gitem)] = itemId - menuItemIdsMutex.Unlock() - return pointer(gitem) -} - -func menuRadioItemNewWithGroup(label string, itemId uint, groupId uint, checkedId uint) pointer { - cLabel := C.CString(label) - defer C.free(unsafe.Pointer(cLabel)) - - actionName := fmt.Sprintf("radio_group_%d", groupId) - cAction := C.CString(actionName) - defer C.free(unsafe.Pointer(cAction)) - - targetValue := fmt.Sprintf("%d", itemId) - cTarget := C.CString(targetValue) - defer C.free(unsafe.Pointer(cTarget)) - - initialValue := fmt.Sprintf("%d", checkedId) - cInitial := C.CString(initialValue) - defer C.free(unsafe.Pointer(cInitial)) - - gitem := C.create_radio_menu_item(cLabel, cAction, cTarget, cInitial, C.guint(itemId)) - - menuItemIdsMutex.Lock() - menuItemIds[pointer(gitem)] = itemId - menuItemIdsMutex.Unlock() - return pointer(gitem) -} - -// Keyboard accelerator support for GTK4 menus - -// namedKeysToGTK maps Wails key names to GDK keysym values -// These are X11 keysym values that GDK uses -var namedKeysToGTK = map[string]C.guint{ - "backspace": C.guint(0xff08), - "tab": C.guint(0xff09), - "return": C.guint(0xff0d), - "enter": C.guint(0xff0d), - "escape": C.guint(0xff1b), - "left": C.guint(0xff51), - "right": C.guint(0xff53), - "up": C.guint(0xff52), - "down": C.guint(0xff54), - "space": C.guint(0xff80), - "delete": C.guint(0xff9f), - "home": C.guint(0xff95), - "end": C.guint(0xff9c), - "page up": C.guint(0xff9a), - "page down": C.guint(0xff9b), - "f1": C.guint(0xffbe), - "f2": C.guint(0xffbf), - "f3": C.guint(0xffc0), - "f4": C.guint(0xffc1), - "f5": C.guint(0xffc2), - "f6": C.guint(0xffc3), - "f7": C.guint(0xffc4), - "f8": C.guint(0xffc5), - "f9": C.guint(0xffc6), - "f10": C.guint(0xffc7), - "f11": C.guint(0xffc8), - "f12": C.guint(0xffc9), - "f13": C.guint(0xffca), - "f14": C.guint(0xffcb), - "f15": C.guint(0xffcc), - "f16": C.guint(0xffcd), - "f17": C.guint(0xffce), - "f18": C.guint(0xffcf), - "f19": C.guint(0xffd0), - "f20": C.guint(0xffd1), - "f21": C.guint(0xffd2), - "f22": C.guint(0xffd3), - "f23": C.guint(0xffd4), - "f24": C.guint(0xffd5), - "f25": C.guint(0xffd6), - "f26": C.guint(0xffd7), - "f27": C.guint(0xffd8), - "f28": C.guint(0xffd9), - "f29": C.guint(0xffda), - "f30": C.guint(0xffdb), - "f31": C.guint(0xffdc), - "f32": C.guint(0xffdd), - "f33": C.guint(0xffde), - "f34": C.guint(0xffdf), - "f35": C.guint(0xffe0), - "numlock": C.guint(0xff7f), -} - -// parseKeyGTK converts a Wails key string to a GDK keysym value -func parseKeyGTK(key string) C.guint { - // Check named keys first - if result, found := namedKeysToGTK[key]; found { - return result - } - // For single character keys, convert using gdk_unicode_to_keyval - if len(key) != 1 { - return C.guint(0) - } - keyval := rune(key[0]) - return C.gdk_unicode_to_keyval(C.guint(keyval)) -} - -// parseModifiersGTK converts Wails modifiers to GDK modifier type -func parseModifiersGTK(modifiers []modifier) C.GdkModifierType { - var result C.GdkModifierType - - for _, mod := range modifiers { - switch mod { - case ShiftKey: - result |= C.GDK_SHIFT_MASK - case ControlKey, CmdOrCtrlKey: - result |= C.GDK_CONTROL_MASK - case OptionOrAltKey: - result |= C.GDK_ALT_MASK - case SuperKey: - result |= C.GDK_SUPER_MASK - } - } - return result -} - -// acceleratorToGTK converts a Wails accelerator to GTK key/modifiers -func acceleratorToGTK(accel *accelerator) (C.guint, C.GdkModifierType) { - key := parseKeyGTK(accel.Key) - mods := parseModifiersGTK(accel.Modifiers) - return key, mods -} - -// setMenuItemAccelerator sets the keyboard accelerator for a menu item -// This uses gtk_application_set_accels_for_action to register the shortcut -func setMenuItemAccelerator(itemId uint, accel *accelerator) { - if accel == nil { - return - } - - // Look up the action name for this menu item - actionName, ok := menuItemActions[itemId] - if !ok { - return - } - - // Get the GtkApplication pointer - app := getNativeApplication() - if app == nil || app.application == nil { - return - } - - // Convert accelerator to GTK format - key, mods := acceleratorToGTK(accel) - if key == 0 { - return - } - - // Build accelerator string using GTK's function - accelString := C.build_accelerator_string(key, mods) - if accelString == nil { - return - } - defer C.g_free(C.gpointer(accelString)) - - // Set the accelerator on the application - cActionName := C.CString(actionName) - defer C.free(unsafe.Pointer(cActionName)) - C.set_action_accelerator((*C.GtkApplication)(app.application), cActionName, accelString) -} - -// screen related -func getScreenByIndex(display *C.GdkDisplay, index int) *Screen { - monitors := C.gdk_display_get_monitors(display) - monitor := (*C.GdkMonitor)(C.g_list_model_get_item(monitors, C.guint(index))) - if monitor == nil { - return nil - } - defer C.g_object_unref(C.gpointer(monitor)) - - var geometry C.GdkRectangle - C.gdk_monitor_get_geometry(monitor, &geometry) - // Use gdk_monitor_get_scale (GTK 4.14+) for fractional scaling support - scaleFactor := float64(C.gdk_monitor_get_scale(monitor)) - name := C.gdk_monitor_get_model(monitor) - - // GTK4's gdk_monitor_get_geometry returns logical (DIP) coordinates. - // PhysicalBounds needs physical pixel dimensions for proper DPI scaling. - x := int(geometry.x) - y := int(geometry.y) - width := int(geometry.width) - height := int(geometry.height) - - return &Screen{ - ID: fmt.Sprintf("%d", index), - Name: C.GoString(name), - IsPrimary: index == 0, - ScaleFactor: float32(scaleFactor), - X: x, - Y: y, - Size: Size{ - Height: height, - Width: width, - }, - Bounds: Rect{ - X: x, - Y: y, - Height: height, - Width: width, - }, - PhysicalBounds: Rect{ - X: int(float64(x) * scaleFactor), - Y: int(float64(y) * scaleFactor), - Height: int(float64(height) * scaleFactor), - Width: int(float64(width) * scaleFactor), - }, - WorkArea: Rect{ - X: x, - Y: y, - Height: height, - Width: width, - }, - PhysicalWorkArea: Rect{ - X: int(float64(x) * scaleFactor), - Y: int(float64(y) * scaleFactor), - Height: int(float64(height) * scaleFactor), - Width: int(float64(width) * scaleFactor), - }, - Rotation: 0.0, - } -} - -func getScreens(app pointer) ([]*Screen, error) { - var screens []*Screen - display := C.gdk_display_get_default() - monitors := C.gdk_display_get_monitors(display) - count := C.g_list_model_get_n_items(monitors) - for i := 0; i < int(count); i++ { - screens = append(screens, getScreenByIndex(display, i)) - } - return screens, nil -} - -// widgets -func (w *linuxWebviewWindow) setEnabled(enabled bool) { - C.gtk_widget_set_sensitive(w.gtkWidget(), C.gboolean(btoi(enabled))) -} - -func btoi(b bool) int { - if b { - return 1 - } - return 0 -} - -func widgetSetVisible(widget pointer, hidden bool) { - C.gtk_widget_set_visible((*C.GtkWidget)(widget), C.gboolean(btoi(!hidden))) -} - -func (w *linuxWebviewWindow) close() { - C.gtk_window_destroy(w.gtkWindow()) - getNativeApplication().unregisterWindow(windowPointer(w.window)) -} - -func (w *linuxWebviewWindow) enableDND() { - C.enableDND((*C.GtkWidget)(w.webview), C.uintptr_t(w.parent.id)) -} - -func (w *linuxWebviewWindow) disableDND() { - C.disableDND((*C.GtkWidget)(w.webview), C.uintptr_t(w.parent.id)) -} - -func (w *linuxWebviewWindow) execJS(js string) { - InvokeAsync(func() { - value := C.CString(js) - defer C.free(unsafe.Pointer(value)) - // WebKitGTK 6.0 uses webkit_web_view_evaluate_javascript - C.webkit_web_view_evaluate_javascript(w.webKitWebView(), - value, - C.gssize(len(js)), - nil, - nil, - nil, - nil, - nil) - }) -} - -// Preallocated buffer for drag-over JS calls -var dragOverJSBuffer = C.CString(strings.Repeat(" ", 64)) -var emptyWorldName = C.CString("") - -func (w *linuxWebviewWindow) execJSDragOver(x, y int) { - buf := (*[64]byte)(unsafe.Pointer(dragOverJSBuffer)) - n := copy(buf[:], "window._wails.handleDragOver(") - n += writeInt(buf[n:], x) - buf[n] = ',' - n++ - n += writeInt(buf[n:], y) - buf[n] = ')' - n++ - buf[n] = 0 - - C.webkit_web_view_evaluate_javascript(w.webKitWebView(), - dragOverJSBuffer, - C.gssize(n), - nil, - emptyWorldName, - nil, - nil, - nil) -} - -func writeInt(buf []byte, n int) int { - if n < 0 { - buf[0] = '-' - return 1 + writeInt(buf[1:], -n) - } - if n == 0 { - buf[0] = '0' - return 1 - } - tmp := n - digits := 0 - for tmp > 0 { - digits++ - tmp /= 10 - } - for i := digits - 1; i >= 0; i-- { - buf[i] = byte('0' + n%10) - n /= 10 - } - return digits -} - -func getMousePosition() (int, int, *Screen) { - display := C.gdk_display_get_default() - if display == nil { - return 0, 0, nil - } - - monitors := C.gdk_display_get_monitors(display) - if monitors == nil { - return 0, 0, nil - } - - n := C.g_list_model_get_n_items(monitors) - if n == 0 { - return 0, 0, nil - } - - var primaryMonitor *C.GdkMonitor - for i := C.guint(0); i < n; i++ { - mon := (*C.GdkMonitor)(C.g_list_model_get_item(monitors, i)) - if mon != nil { - primaryMonitor = mon - break - } - } - - if primaryMonitor == nil { - return 0, 0, nil - } - - var geometry C.GdkRectangle - C.gdk_monitor_get_geometry(primaryMonitor, &geometry) - // Use gdk_monitor_get_scale (GTK 4.14+) for fractional scaling support - scaleFactor := float64(C.gdk_monitor_get_scale(primaryMonitor)) - name := C.gdk_monitor_get_model(primaryMonitor) - - // GTK4's gdk_monitor_get_geometry returns logical (DIP) coordinates. - // PhysicalBounds needs physical pixel dimensions for proper DPI scaling. - x := int(geometry.x) - y := int(geometry.y) - width := int(geometry.width) - height := int(geometry.height) - - screen := &Screen{ - ID: "0", - Name: C.GoString(name), - ScaleFactor: float32(scaleFactor), - X: x, - Y: y, - Size: Size{ - Height: height, - Width: width, - }, - Bounds: Rect{ - X: x, - Y: y, - Height: height, - Width: width, - }, - WorkArea: Rect{ - X: x, - Y: y, - Height: height, - Width: width, - }, - PhysicalBounds: Rect{ - X: int(float64(x) * scaleFactor), - Y: int(float64(y) * scaleFactor), - Height: int(float64(height) * scaleFactor), - Width: int(float64(width) * scaleFactor), - }, - PhysicalWorkArea: Rect{ - X: int(float64(x) * scaleFactor), - Y: int(float64(y) * scaleFactor), - Height: int(float64(height) * scaleFactor), - Width: int(float64(width) * scaleFactor), - }, - IsPrimary: true, - } - - centerX := x + width/2 - centerY := y + height/2 - - return centerX, centerY, screen -} - -func (w *linuxWebviewWindow) destroy() { - w.parent.markAsDestroyed() - if w.gtkmenu != nil { - // GTK4: Different menu destruction - w.gtkmenu = nil - } - C.gtk_window_destroy(w.gtkWindow()) -} - -func (w *linuxWebviewWindow) fullscreen() { - C.gtk_window_fullscreen(w.gtkWindow()) -} - -func (w *linuxWebviewWindow) getCurrentMonitor() *C.GdkMonitor { - display := C.gtk_widget_get_display(w.gtkWidget()) - surface := C.gtk_native_get_surface((*C.GtkNative)(unsafe.Pointer(w.gtkWindow()))) - if surface != nil { - monitor := C.gdk_display_get_monitor_at_surface(display, surface) - if monitor != nil { - return monitor - } - } - return nil -} - -func (w *linuxWebviewWindow) getScreen() (*Screen, error) { - monitor := w.getCurrentMonitor() - if monitor == nil { - return nil, fmt.Errorf("no monitor found") - } - name := C.gdk_monitor_get_model(monitor) - var geometry C.GdkRectangle - C.gdk_monitor_get_geometry(monitor, &geometry) - // Use gdk_monitor_get_scale (GTK 4.14+) for fractional scaling support - scaleFactor := float64(C.gdk_monitor_get_scale(monitor)) - - // GTK4's gdk_monitor_get_geometry returns logical (DIP) coordinates. - // PhysicalBounds needs physical pixel dimensions for proper DPI scaling. - x := int(geometry.x) - y := int(geometry.y) - width := int(geometry.width) - height := int(geometry.height) - - return &Screen{ - ID: fmt.Sprintf("%d", w.id), - Name: C.GoString(name), - ScaleFactor: float32(scaleFactor), - X: x, - Y: y, - Size: Size{ - Height: height, - Width: width, - }, - Bounds: Rect{ - X: x, - Y: y, - Height: height, - Width: width, - }, - WorkArea: Rect{ - X: x, - Y: y, - Height: height, - Width: width, - }, - PhysicalBounds: Rect{ - X: int(float64(x) * scaleFactor), - Y: int(float64(y) * scaleFactor), - Height: int(float64(height) * scaleFactor), - Width: int(float64(width) * scaleFactor), - }, - PhysicalWorkArea: Rect{ - X: int(float64(x) * scaleFactor), - Y: int(float64(y) * scaleFactor), - Height: int(float64(height) * scaleFactor), - Width: int(float64(width) * scaleFactor), - }, - IsPrimary: false, - Rotation: 0.0, - }, nil -} - -func (w *linuxWebviewWindow) getCurrentMonitorGeometry() (x int, y int, width int, height int, scaleFactor float64) { - monitor := w.getCurrentMonitor() - if monitor == nil { - return -1, -1, -1, -1, 1 - } - var result C.GdkRectangle - C.gdk_monitor_get_geometry(monitor, &result) - // Use gdk_monitor_get_scale (GTK 4.14+) for fractional scaling support - scaleFactor = float64(C.gdk_monitor_get_scale(monitor)) - return int(result.x), int(result.y), int(result.width), int(result.height), scaleFactor -} - -func (w *linuxWebviewWindow) size() (int, int) { - var width, height C.int - C.gtk_window_get_default_size(w.gtkWindow(), &width, &height) - if width <= 0 || height <= 0 { - width = C.int(C.gtk_widget_get_width(w.gtkWidget())) - height = C.int(C.gtk_widget_get_height(w.gtkWidget())) - } - return int(width), int(height) -} - -func (w *linuxWebviewWindow) relativePosition() (int, int) { - // GTK4/Wayland: Window positioning is not reliable - // This is a documented limitation - return 0, 0 -} - -func (w *linuxWebviewWindow) gtkWidget() *C.GtkWidget { - return (*C.GtkWidget)(w.window) -} - -func (w *linuxWebviewWindow) windowHide() { - C.gtk_widget_set_visible(w.gtkWidget(), C.gboolean(0)) -} - -func (w *linuxWebviewWindow) isFullscreen() bool { - return C.gtk_window_is_fullscreen(w.gtkWindow()) != 0 -} - -func (w *linuxWebviewWindow) isFocused() bool { - return C.gtk_window_is_active(w.gtkWindow()) != 0 -} - -func (w *linuxWebviewWindow) isMaximised() bool { - return C.gtk_window_is_maximized(w.gtkWindow()) != 0 && !w.isFullscreen() -} - -func (w *linuxWebviewWindow) isMinimised() bool { - surface := C.gtk_native_get_surface((*C.GtkNative)(unsafe.Pointer(w.gtkWindow()))) - if surface == nil { - return false - } - state := C.gdk_toplevel_get_state((*C.GdkToplevel)(unsafe.Pointer(surface))) - return state&C.GDK_TOPLEVEL_STATE_MINIMIZED != 0 -} - -func (w *linuxWebviewWindow) isVisible() bool { - return C.gtk_widget_is_visible(w.gtkWidget()) != 0 -} - -func (w *linuxWebviewWindow) maximise() { - C.gtk_window_maximize(w.gtkWindow()) -} - -func (w *linuxWebviewWindow) minimise() { - C.gtk_window_minimize(w.gtkWindow()) -} - -func windowNew(application pointer, menu pointer, menuStyle LinuxMenuStyle, windowId uint, gpuPolicy WebviewGpuPolicy) (window, webview, vbox pointer) { - window = pointer(C.gtk_application_window_new((*C.GtkApplication)(application))) - C.g_object_ref_sink(C.gpointer(window)) - - C.attach_action_group_to_widget((*C.GtkWidget)(window)) - - webview = windowNewWebview(windowId, gpuPolicy) - vbox = pointer(C.gtk_box_new(C.GTK_ORIENTATION_VERTICAL, 0)) - name := C.CString("webview-box") - defer C.free(unsafe.Pointer(name)) - C.gtk_widget_set_name((*C.GtkWidget)(vbox), name) - - C.gtk_window_set_child((*C.GtkWindow)(window), (*C.GtkWidget)(vbox)) - - if menu != nil { - switch menuStyle { - case LinuxMenuStylePrimaryMenu: - headerBar := C.create_header_bar_with_menu((*C.GMenu)(menu)) - C.gtk_window_set_titlebar((*C.GtkWindow)(window), headerBar) - default: - menuBar := C.create_menu_bar_from_model((*C.GMenu)(menu)) - C.gtk_box_prepend((*C.GtkBox)(vbox), menuBar) - } - } - - C.gtk_box_append((*C.GtkBox)(vbox), (*C.GtkWidget)(webview)) - C.gtk_widget_set_vexpand((*C.GtkWidget)(webview), C.gboolean(1)) - C.gtk_widget_set_hexpand((*C.GtkWidget)(webview), C.gboolean(1)) - return -} - -func windowNewWebview(parentId uint, gpuPolicy WebviewGpuPolicy) pointer { - c := NewCalloc() - defer c.Free() - manager := C.webkit_user_content_manager_new() - // WebKitGTK 6.0: register_script_message_handler signature changed - C.webkit_user_content_manager_register_script_message_handler(manager, c.String("external"), nil) - - // WebKitGTK 6.0: Create network session first - networkSession := C.webkit_network_session_get_default() - - // Create web view with settings - settings := C.webkit_settings_new() - // WebKitGTK 6.0: webkit_web_view_new_with_user_content_manager() was removed - // Use create_webview_with_user_content_manager() helper instead - webView := C.create_webview_with_user_content_manager(manager) - - C.save_webview_to_content_manager(unsafe.Pointer(manager), unsafe.Pointer(webView)) - C.save_window_id(unsafe.Pointer(webView), C.uint(parentId)) - C.save_window_id(unsafe.Pointer(manager), C.uint(parentId)) - - // GPU policy - // WebKitGTK 6.0: WEBKIT_HARDWARE_ACCELERATION_POLICY_ON_DEMAND was removed - // Only ALWAYS and NEVER are available - switch gpuPolicy { - case WebviewGpuPolicyNever: - C.webkit_settings_set_hardware_acceleration_policy(settings, C.WEBKIT_HARDWARE_ACCELERATION_POLICY_NEVER) - case WebviewGpuPolicyAlways: - C.webkit_settings_set_hardware_acceleration_policy(settings, C.WEBKIT_HARDWARE_ACCELERATION_POLICY_ALWAYS) - default: - // Default to ALWAYS (was ON_DEMAND in older WebKitGTK) - C.webkit_settings_set_hardware_acceleration_policy(settings, C.WEBKIT_HARDWARE_ACCELERATION_POLICY_ALWAYS) - } - - C.webkit_web_view_set_settings(C.webkit_web_view((*C.GtkWidget)(webView)), settings) - - // Register URI scheme handler - registerURIScheme.Do(func() { - webContext := C.webkit_web_view_get_context(C.webkit_web_view((*C.GtkWidget)(webView))) - cScheme := C.CString("wails") - defer C.free(unsafe.Pointer(cScheme)) - C.webkit_web_context_register_uri_scheme(webContext, cScheme, - (*[0]byte)(C.onProcessRequest), nil, nil) - }) - - _ = networkSession - return pointer(webView) -} - -func gtkBool(b bool) C.gboolean { - if b { - return C.gboolean(1) - } - return C.gboolean(0) -} - -func (w *linuxWebviewWindow) gtkWindow() *C.GtkWindow { - return (*C.GtkWindow)(w.window) -} - -func (w *linuxWebviewWindow) webKitWebView() *C.WebKitWebView { - return C.webkit_web_view((*C.GtkWidget)(w.webview)) -} - -func (w *linuxWebviewWindow) present() { - C.gtk_window_present(w.gtkWindow()) -} - -func (w *linuxWebviewWindow) setTitle(title string) { - if !w.parent.options.Frameless { - cTitle := C.CString(title) - C.gtk_window_set_title(w.gtkWindow(), cTitle) - C.free(unsafe.Pointer(cTitle)) - } -} - -func (w *linuxWebviewWindow) setSize(width, height int) { - C.gtk_window_set_default_size(w.gtkWindow(), C.int(width), C.int(height)) -} - -func (w *linuxWebviewWindow) setDefaultSize(width int, height int) { - C.gtk_window_set_default_size(w.gtkWindow(), C.int(width), C.int(height)) -} - -func windowSetGeometryHints(window pointer, minWidth, minHeight, maxWidth, maxHeight int) { - w := (*C.GtkWidget)(window) - if minWidth > 0 && minHeight > 0 { - C.gtk_widget_set_size_request(w, C.int(minWidth), C.int(minHeight)) - } -} - -func (w *linuxWebviewWindow) setResizable(resizable bool) { - C.gtk_window_set_resizable(w.gtkWindow(), gtkBool(resizable)) -} - -func (w *linuxWebviewWindow) move(x, y int) { -} - -func (w *linuxWebviewWindow) position() (int, int) { - // GTK4/Wayland: Cannot reliably get window position - return 0, 0 -} - -func (w *linuxWebviewWindow) unfullscreen() { - C.gtk_window_unfullscreen(w.gtkWindow()) - w.unmaximise() -} - -func (w *linuxWebviewWindow) unmaximise() { - C.gtk_window_unmaximize(w.gtkWindow()) -} - -func (w *linuxWebviewWindow) windowShow() { - if w.gtkWidget() == nil { - return - } - C.gtk_widget_set_visible(w.gtkWidget(), gtkBool(true)) -} - -func (w *linuxWebviewWindow) setAlwaysOnTop(alwaysOnTop bool) { - // GTK4: No direct equivalent - compositor-dependent -} - -func (w *linuxWebviewWindow) setBorderless(borderless bool) { - C.gtk_window_set_decorated(w.gtkWindow(), gtkBool(!borderless)) -} - -func (w *linuxWebviewWindow) setFrameless(frameless bool) { - C.gtk_window_set_decorated(w.gtkWindow(), gtkBool(!frameless)) -} - -func (w *linuxWebviewWindow) setTransparent() { - // GTK4: Transparency via CSS - different from GTK3 -} - -func (w *linuxWebviewWindow) setBackgroundColour(colour RGBA) { - rgba := C.GdkRGBA{C.float(colour.Red) / 255.0, C.float(colour.Green) / 255.0, C.float(colour.Blue) / 255.0, C.float(colour.Alpha) / 255.0} - C.webkit_web_view_set_background_color(w.webKitWebView(), &rgba) -} - -func (w *linuxWebviewWindow) setIcon(icon pointer) { - // GTK4: Window icons handled differently - no gtk_window_set_icon -} - -func (w *linuxWebviewWindow) startDrag() error { - C.beginWindowDrag( - w.gtkWindow(), - C.int(w.drag.MouseButton), - C.double(w.drag.XRoot), - C.double(w.drag.YRoot), - C.guint32(w.drag.DragTime)) - return nil -} - -// startResize is handled by webview_window_linux.go -// GTK4-specific resize using beginWindowResize can be added via a helper function - -func (w *linuxWebviewWindow) getZoom() float64 { - return float64(C.webkit_web_view_get_zoom_level(w.webKitWebView())) -} - -func (w *linuxWebviewWindow) setZoom(zoom float64) { - if zoom < 1 { - zoom = 1 - } - C.webkit_web_view_set_zoom_level(w.webKitWebView(), C.gdouble(zoom)) -} - -func (w *linuxWebviewWindow) zoomIn() { - w.setZoom(w.getZoom() * 1.10) -} - -func (w *linuxWebviewWindow) zoomOut() { - w.setZoom(w.getZoom() / 1.10) -} - -func (w *linuxWebviewWindow) zoomReset() { - w.setZoom(1.0) -} - -func (w *linuxWebviewWindow) reload() { - uri := C.CString("wails://") - C.webkit_web_view_load_uri(w.webKitWebView(), uri) - C.free(unsafe.Pointer(uri)) -} - -func (w *linuxWebviewWindow) setURL(uri string) { - target := C.CString(uri) - C.webkit_web_view_load_uri(w.webKitWebView(), target) - C.free(unsafe.Pointer(target)) -} - -func (w *linuxWebviewWindow) setHTML(html string) { - cHTML := C.CString(html) - uri := C.CString("wails://") - empty := C.CString("") - defer C.free(unsafe.Pointer(cHTML)) - defer C.free(unsafe.Pointer(uri)) - defer C.free(unsafe.Pointer(empty)) - C.webkit_web_view_load_alternate_html(w.webKitWebView(), cHTML, uri, empty) -} - -func (w *linuxWebviewWindow) flash(_ bool) {} - -func (w *linuxWebviewWindow) setOpacity(opacity float64) { - C.gtk_widget_set_opacity(w.gtkWidget(), C.double(opacity)) -} - -func (w *linuxWebviewWindow) ignoreMouse(ignore bool) { - // GTK4: Input handling is different -} - -func (w *linuxWebviewWindow) copy() { - w.execJS("document.execCommand('copy')") -} - -func (w *linuxWebviewWindow) cut() { - w.execJS("document.execCommand('cut')") -} - -func (w *linuxWebviewWindow) paste() { - w.execJS("document.execCommand('paste')") -} - -func (w *linuxWebviewWindow) delete() { - w.execJS("document.execCommand('delete')") -} - -func (w *linuxWebviewWindow) selectAll() { - w.execJS("document.execCommand('selectAll')") -} - -func (w *linuxWebviewWindow) undo() { - w.execJS("document.execCommand('undo')") -} - -func (w *linuxWebviewWindow) redo() { - w.execJS("document.execCommand('redo')") -} - -func (w *linuxWebviewWindow) setupSignalHandlers(emit func(e events.WindowEventType)) { - c := NewCalloc() - defer c.Free() - - winID := C.uintptr_t(w.parent.ID()) - - C.setupWindowEventControllers(w.gtkWindow(), (*C.GtkWidget)(w.webview), winID) - - wv := unsafe.Pointer(w.webview) - C.signal_connect(wv, c.String("load-changed"), C.handleLoadChanged, winID) - - contentManager := C.webkit_web_view_get_user_content_manager(w.webKitWebView()) - C.signal_connect(unsafe.Pointer(contentManager), c.String("script-message-received::external"), C.sendMessageToBackend, 0) -} - -//export handleCloseRequest -func handleCloseRequest(window *C.GtkWindow, data C.uintptr_t) C.gboolean { - processWindowEvent(C.uint(data), C.uint(events.Linux.WindowDeleteEvent)) - return C.gboolean(1) -} - -//export handleNotifyState -func handleNotifyState(object *C.GObject, pspec *C.GParamSpec, data C.uintptr_t) { - windowId := uint(data) - window, ok := globalApplication.Window.GetByID(windowId) - if !ok || window == nil { - return - } - - lw := getLinuxWebviewWindow(window) - if lw == nil { - return - } - - if lw.isMaximised() { - processWindowEvent(C.uint(data), C.uint(events.Linux.WindowDidResize)) - } - if lw.isFullscreen() { - processWindowEvent(C.uint(data), C.uint(events.Linux.WindowDidResize)) - } -} - -//export handleFocusEnter -func handleFocusEnter(controller *C.GtkEventController, data C.uintptr_t) C.gboolean { - processWindowEvent(C.uint(data), C.uint(events.Linux.WindowFocusIn)) - return C.gboolean(0) -} - -//export handleFocusLeave -func handleFocusLeave(controller *C.GtkEventController, data C.uintptr_t) C.gboolean { - processWindowEvent(C.uint(data), C.uint(events.Linux.WindowFocusOut)) - return C.gboolean(0) -} - -//export handleLoadChanged -func handleLoadChanged(wv *C.WebKitWebView, event C.WebKitLoadEvent, data C.uintptr_t) { - switch event { - case C.WEBKIT_LOAD_STARTED: - processWindowEvent(C.uint(data), C.uint(events.Linux.WindowLoadStarted)) - case C.WEBKIT_LOAD_REDIRECTED: - processWindowEvent(C.uint(data), C.uint(events.Linux.WindowLoadRedirected)) - case C.WEBKIT_LOAD_COMMITTED: - processWindowEvent(C.uint(data), C.uint(events.Linux.WindowLoadCommitted)) - case C.WEBKIT_LOAD_FINISHED: - processWindowEvent(C.uint(data), C.uint(events.Linux.WindowLoadFinished)) - } -} - -//export handleButtonPressed -func handleButtonPressed(gesture *C.GtkGestureClick, nPress C.gint, x C.gdouble, y C.gdouble, data C.uintptr_t) { - windowId := uint(data) - window, ok := globalApplication.Window.GetByID(windowId) - if !ok || window == nil { - return - } - - lw := getLinuxWebviewWindow(window) - if lw == nil { - return - } - - button := C.gtk_gesture_single_get_current_button((*C.GtkGestureSingle)(unsafe.Pointer(gesture))) - lw.drag.MouseButton = uint(button) - lw.drag.XRoot = int(x) - lw.drag.YRoot = int(y) - lw.drag.DragTime = uint32(C.GDK_CURRENT_TIME) -} - -//export handleButtonReleased -func handleButtonReleased(gesture *C.GtkGestureClick, nPress C.gint, x C.gdouble, y C.gdouble, data C.uintptr_t) { - windowId := uint(data) - window, ok := globalApplication.Window.GetByID(windowId) - if !ok || window == nil { - return - } - - lw := getLinuxWebviewWindow(window) - if lw == nil { - return - } - - button := C.gtk_gesture_single_get_current_button((*C.GtkGestureSingle)(unsafe.Pointer(gesture))) - lw.endDrag(uint(button), int(x), int(y)) -} - -//export handleKeyPressed -func handleKeyPressed(controller *C.GtkEventControllerKey, keyval C.guint, keycode C.guint, state C.GdkModifierType, data C.uintptr_t) C.gboolean { - windowID := uint(data) - - modifiers := uint(state) - var acc accelerator - - if modifiers&C.GDK_SHIFT_MASK != 0 { - acc.Modifiers = append(acc.Modifiers, ShiftKey) - } - if modifiers&C.GDK_CONTROL_MASK != 0 { - acc.Modifiers = append(acc.Modifiers, ControlKey) - } - if modifiers&C.GDK_ALT_MASK != 0 { - acc.Modifiers = append(acc.Modifiers, OptionOrAltKey) - } - if modifiers&C.GDK_SUPER_MASK != 0 { - acc.Modifiers = append(acc.Modifiers, SuperKey) - } - - keyString, ok := VirtualKeyCodes[uint(keyval)] - if !ok { - return C.gboolean(0) - } - acc.Key = keyString - - windowKeyEvents <- &windowKeyEvent{ - windowId: windowID, - acceleratorString: acc.String(), - } - - return C.gboolean(0) -} - -//export onDropEnter -func onDropEnter(data C.uintptr_t) { - windowId := uint(data) - targetWindow, ok := globalApplication.Window.GetByID(windowId) - if !ok || targetWindow == nil { - return - } - if w, ok := targetWindow.(*WebviewWindow); ok { - w.HandleDragEnter() - } -} - -//export onDropLeave -func onDropLeave(data C.uintptr_t) { - windowId := uint(data) - targetWindow, ok := globalApplication.Window.GetByID(windowId) - if !ok || targetWindow == nil { - return - } - if w, ok := targetWindow.(*WebviewWindow); ok { - w.HandleDragLeave() - } -} - -//export onDropMotion -func onDropMotion(x C.gint, y C.gint, data C.uintptr_t) { - windowId := uint(data) - targetWindow, ok := globalApplication.Window.GetByID(windowId) - if !ok || targetWindow == nil { - return - } - if w, ok := targetWindow.(*WebviewWindow); ok { - w.HandleDragOver(int(x), int(y)) - } -} - -//export onDropFiles -func onDropFiles(paths **C.char, x C.gint, y C.gint, data C.uintptr_t) { - windowId := uint(data) - targetWindow, ok := globalApplication.Window.GetByID(windowId) - if !ok || targetWindow == nil { - return - } - - offset := unsafe.Sizeof(uintptr(0)) - var filenames []string - for *paths != nil { - filenames = append(filenames, C.GoString(*paths)) - paths = (**C.char)(unsafe.Pointer(uintptr(unsafe.Pointer(paths)) + offset)) - } - - targetWindow.InitiateFrontendDropProcessing(filenames, int(x), int(y)) -} - -//export processWindowEvent -func processWindowEvent(windowID C.uint, eventID C.uint) { - windowEvents <- &windowEvent{ - WindowID: uint(windowID), - EventID: uint(eventID), - } -} - -//export onProcessRequest -func onProcessRequest(request *C.WebKitURISchemeRequest, data C.uintptr_t) { - webView := C.webkit_uri_scheme_request_get_web_view(request) - windowId := uint(C.get_window_id(unsafe.Pointer(webView))) - webviewRequests <- &webViewAssetRequest{ - Request: webview.NewRequest(unsafe.Pointer(request)), - windowId: windowId, - windowName: func() string { - if window, ok := globalApplication.Window.GetByID(windowId); ok { - return window.Name() - } - return "" - }(), - } -} - -// WebKitGTK 6.0: callback now receives JSCValue directly instead of WebKitJavascriptResult -// -//export sendMessageToBackend -func sendMessageToBackend(contentManager *C.WebKitUserContentManager, value *C.JSCValue, - data unsafe.Pointer) { - - // Get the windowID from the contentManager - thisWindowID := uint(C.get_window_id(unsafe.Pointer(contentManager))) - - webView := C.get_webview_from_content_manager(unsafe.Pointer(contentManager)) - var origin string - if webView != nil { - currentUri := C.webkit_web_view_get_uri(webView) - if currentUri != nil { - uri := C.g_strdup(currentUri) - defer C.g_free(C.gpointer(uri)) - origin = C.GoString(uri) - } - } - - // WebKitGTK 6.0: JSCValue is passed directly, no need for webkit_javascript_result_get_js_value - message := C.jsc_value_to_string(value) - msg := C.GoString(message) - defer C.g_free(C.gpointer(message)) - windowMessageBuffer <- &windowMessage{ - windowId: thisWindowID, - message: msg, - originInfo: &OriginInfo{ - Origin: origin, - }, - } -} - -// ============================================================================ -// GTK4 Dialog System - Go wrapper functions -// ============================================================================ - -// Dialog request tracking -var ( - dialogRequestCounter uint32 - dialogRequestMutex sync.Mutex - fileDialogCallbacks = make(map[uint]chan string) - alertDialogCallbacks = make(map[uint]chan int) -) - -func nextDialogRequestID() uint { - dialogRequestMutex.Lock() - defer dialogRequestMutex.Unlock() - dialogRequestCounter++ - return uint(dialogRequestCounter) -} - -//export fileDialogCallback -func fileDialogCallback(requestID C.uint, files **C.char, count C.int, cancelled C.gboolean) { - dialogRequestMutex.Lock() - ch, ok := fileDialogCallbacks[uint(requestID)] - if ok { - delete(fileDialogCallbacks, uint(requestID)) - } - dialogRequestMutex.Unlock() - - if !ok { - return - } - - if cancelled != 0 { - close(ch) - return - } - - if count > 0 && files != nil { - slice := unsafe.Slice(files, int(count)) - for _, cstr := range slice { - if cstr != nil { - ch <- C.GoString(cstr) - } - } - } - close(ch) -} - -//export alertDialogCallback -func alertDialogCallback(requestID C.uint, buttonIndex C.int) { - dialogRequestMutex.Lock() - ch, ok := alertDialogCallbacks[uint(requestID)] - if ok { - delete(alertDialogCallbacks, uint(requestID)) - } - dialogRequestMutex.Unlock() - - if !ok { - return - } - - ch <- int(buttonIndex) - close(ch) -} - -func runChooserDialog(window pointer, allowMultiple, createFolders, showHidden bool, currentFolder, title string, action int, acceptLabel string, filters []FileFilter) (chan string, error) { - requestID := nextDialogRequestID() - resultChan := make(chan string, 100) - - dialogRequestMutex.Lock() - fileDialogCallbacks[requestID] = resultChan - dialogRequestMutex.Unlock() - - InvokeAsync(func() { - cTitle := C.CString(title) - defer C.free(unsafe.Pointer(cTitle)) - - dialog := C.create_file_dialog(cTitle) - - // Create filter list if we have filters - if len(filters) > 0 { - filterStore := C.g_list_store_new(C.gtk_file_filter_get_type()) - defer C.g_object_unref(C.gpointer(filterStore)) - - for _, filter := range filters { - cName := C.CString(filter.DisplayName) - cPattern := C.CString(filter.Pattern) - C.add_file_filter(dialog, filterStore, cName, cPattern) - C.free(unsafe.Pointer(cName)) - C.free(unsafe.Pointer(cPattern)) - } - C.set_file_dialog_filters(dialog, filterStore) - } - - if currentFolder != "" { - cFolder := C.CString(currentFolder) - file := C.g_file_new_for_path(cFolder) - C.gtk_file_dialog_set_initial_folder(dialog, file) - C.g_object_unref(C.gpointer(file)) - C.free(unsafe.Pointer(cFolder)) - } - - if acceptLabel != "" { - cLabel := C.CString(acceptLabel) - C.gtk_file_dialog_set_accept_label(dialog, cLabel) - C.free(unsafe.Pointer(cLabel)) - } - - var parent *C.GtkWindow - if window != nil { - parent = (*C.GtkWindow)(window) - } - - isFolder := action == 2 - isSave := action == 1 - - if isSave { - C.show_save_file_dialog(parent, dialog, C.uint(requestID)) - } else { - C.show_open_file_dialog(parent, dialog, C.uint(requestID), gtkBool(allowMultiple), gtkBool(isFolder)) - } - }) - - return resultChan, nil -} - -func runOpenFileDialog(dialog *OpenFileDialogStruct) (chan string, error) { - var action int - - if dialog.canChooseDirectories { - action = 2 // GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER - } else { - action = 0 // GTK_FILE_CHOOSER_ACTION_OPEN - } - - window := nilPointer - if dialog.window != nil { - nativeWindow := dialog.window.NativeWindow() - if nativeWindow != nil { - window = pointer(nativeWindow) - } - } - - buttonText := dialog.buttonText - if buttonText == "" { - buttonText = "_Open" - } - - return runChooserDialog( - window, - dialog.allowsMultipleSelection, - false, // createFolders not applicable for open - dialog.showHiddenFiles, - dialog.directory, - dialog.title, - action, - buttonText, - dialog.filters, - ) -} - -func runSaveFileDialog(dialog *SaveFileDialogStruct) (chan string, error) { - window := nilPointer - if dialog.window != nil { - nativeWindow := dialog.window.NativeWindow() - if nativeWindow != nil { - window = pointer(nativeWindow) - } - } - - buttonText := dialog.buttonText - if buttonText == "" { - buttonText = "_Save" - } - - return runChooserDialog( - window, - false, - dialog.canCreateDirectories, - dialog.showHiddenFiles, - dialog.directory, - dialog.title, - 1, // GTK_FILE_CHOOSER_ACTION_SAVE - buttonText, - dialog.filters, - ) -} - -func dialogTypeToIconName(dialogType DialogType) string { - switch dialogType { - case InfoDialogType: - return "dialog-information-symbolic" - case WarningDialogType: - return "dialog-warning-symbolic" - case ErrorDialogType: - return "dialog-error-symbolic" - case QuestionDialogType: - return "dialog-question-symbolic" - default: - return "" - } -} - -func runQuestionDialog(parent pointer, options *MessageDialog) int { - requestID := nextDialogRequestID() - resultChan := make(chan int, 1) - - dialogRequestMutex.Lock() - alertDialogCallbacks[requestID] = resultChan - dialogRequestMutex.Unlock() - - InvokeAsync(func() { - cHeading := C.CString(options.Title) - defer C.free(unsafe.Pointer(cHeading)) - - var cBody *C.char - if options.Message != "" { - cBody = C.CString(options.Message) - defer C.free(unsafe.Pointer(cBody)) - } - - var cIconName *C.char - var iconData *C.uchar - var iconDataLen C.int - if len(options.Icon) > 0 { - iconData = (*C.uchar)(unsafe.Pointer(&options.Icon[0])) - iconDataLen = C.int(len(options.Icon)) - } else { - iconName := dialogTypeToIconName(options.DialogType) - if iconName != "" { - cIconName = C.CString(iconName) - defer C.free(unsafe.Pointer(cIconName)) - } - } - - buttons := options.Buttons - if len(buttons) == 0 { - buttons = []*Button{{Label: "OK", IsDefault: true}} - } - - buttonLabels := make([]*C.char, len(buttons)+1) - for i, btn := range buttons { - buttonLabels[i] = C.CString(btn.Label) - } - buttonLabels[len(buttons)] = nil - - defer func() { - for _, label := range buttonLabels[:len(buttons)] { - C.free(unsafe.Pointer(label)) - } - }() - - defaultButton := -1 - cancelButton := -1 - destructiveButton := -1 - for i, btn := range buttons { - if btn.IsDefault { - defaultButton = i - } - if btn.IsCancel { - cancelButton = i - } - } - - if options.DialogType == ErrorDialogType || options.DialogType == WarningDialogType { - if defaultButton >= 0 && !buttons[defaultButton].IsCancel { - destructiveButton = defaultButton - defaultButton = -1 - } - } - - var parentWindow *C.GtkWindow - if parent != nil { - parentWindow = (*C.GtkWindow)(parent) - } - - C.show_message_dialog( - parentWindow, - cHeading, - cBody, - cIconName, - iconData, - iconDataLen, - (**C.char)(unsafe.Pointer(&buttonLabels[0])), - C.int(len(buttons)), - C.int(defaultButton), - C.int(cancelButton), - C.int(destructiveButton), - C.uint(requestID), - ) - }) - - // Wait for result - result := <-resultChan - return result -} - -func getPrimaryScreen() (*Screen, error) { - display := C.gdk_display_get_default() - monitors := C.gdk_display_get_monitors(display) - if monitors == nil { - return nil, fmt.Errorf("no monitors found") - } - count := C.g_list_model_get_n_items(monitors) - if count == 0 { - return nil, fmt.Errorf("no monitors found") - } - monitor := (*C.GdkMonitor)(C.g_list_model_get_item(monitors, 0)) - if monitor == nil { - return nil, fmt.Errorf("failed to get primary monitor") - } - defer C.g_object_unref(C.gpointer(monitor)) - - var geometry C.GdkRectangle - C.gdk_monitor_get_geometry(monitor, &geometry) - // Use gdk_monitor_get_scale (GTK 4.14+) for fractional scaling support - scaleFactor := float64(C.gdk_monitor_get_scale(monitor)) - name := C.gdk_monitor_get_model(monitor) - - // GTK4's gdk_monitor_get_geometry returns logical (DIP) coordinates. - // PhysicalBounds needs physical pixel dimensions for proper DPI scaling. - x := int(geometry.x) - y := int(geometry.y) - width := int(geometry.width) - height := int(geometry.height) - - return &Screen{ - ID: "0", - Name: C.GoString(name), - IsPrimary: true, - X: x, - Y: y, - Size: Size{ - Height: height, - Width: width, - }, - Bounds: Rect{ - X: x, - Y: y, - Height: height, - Width: width, - }, - ScaleFactor: float32(scaleFactor), - WorkArea: Rect{ - X: x, - Y: y, - Height: height, - Width: width, - }, - PhysicalBounds: Rect{ - X: int(float64(x) * scaleFactor), - Y: int(float64(y) * scaleFactor), - Height: int(float64(height) * scaleFactor), - Width: int(float64(width) * scaleFactor), - }, - PhysicalWorkArea: Rect{ - X: int(float64(x) * scaleFactor), - Y: int(float64(y) * scaleFactor), - Height: int(float64(height) * scaleFactor), - Width: int(float64(width) * scaleFactor), - }, - Rotation: 0.0, - }, nil -} - -func openDevTools(wv pointer) { - inspector := C.webkit_web_view_get_inspector((*C.WebKitWebView)(wv)) - C.webkit_web_inspector_show(inspector) -} - -func enableDevTools(wv pointer) { - settings := C.webkit_web_view_get_settings((*C.WebKitWebView)(wv)) - enabled := C.webkit_settings_get_enable_developer_extras(settings) - if enabled == 0 { - C.webkit_settings_set_enable_developer_extras(settings, C.gboolean(1)) - } else { - C.webkit_settings_set_enable_developer_extras(settings, C.gboolean(0)) - } -} - -var _ = time.Now -var _ = events.Linux -var _ = strings.TrimSpace diff --git a/v3/pkg/application/linux_cgo_gtk4.h b/v3/pkg/application/linux_cgo_gtk4.h deleted file mode 100644 index 777f4d42e..000000000 --- a/v3/pkg/application/linux_cgo_gtk4.h +++ /dev/null @@ -1,198 +0,0 @@ -//go:build linux && gtk4 - -#ifndef LINUX_CGO_GTK4_H -#define LINUX_CGO_GTK4_H - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -// Application flags for GTK4 -#define APPLICATION_DEFAULT_FLAGS G_APPLICATION_DEFAULT_FLAGS - -// ============================================================================ -// Type definitions -// ============================================================================ - -typedef struct CallbackID { - unsigned int value; -} CallbackID; - -typedef struct WindowEvent { - uint id; - uint event; -} WindowEvent; - -typedef struct Screen { - const char* id; - const char* name; - int p_width; - int p_height; - int x; - int y; - int w_width; - int w_height; - int w_x; - int w_y; - float scaleFactor; - double rotation; - bool isPrimary; -} Screen; - -typedef struct MenuItemData { - guint id; - GSimpleAction *action; -} MenuItemData; - -typedef struct FileDialogData { - guint request_id; - gboolean allow_multiple; - gboolean is_save; - gboolean is_folder; -} FileDialogData; - -typedef struct AlertDialogData { - guint request_id; -} AlertDialogData; - -// ============================================================================ -// External Go callback declarations (implemented in Go with //export) -// ============================================================================ - -extern void dispatchOnMainThreadCallback(unsigned int); -extern void emit(WindowEvent* data); -extern gboolean handleCloseRequest(GtkWindow*, uintptr_t); -extern void handleNotifyState(GObject*, GParamSpec*, uintptr_t); -extern gboolean handleFocusEnter(GtkEventController*, uintptr_t); -extern gboolean handleFocusLeave(GtkEventController*, uintptr_t); -extern void handleLoadChanged(WebKitWebView*, WebKitLoadEvent, uintptr_t); -extern void handleButtonPressed(GtkGestureClick*, gint, gdouble, gdouble, uintptr_t); -extern void handleButtonReleased(GtkGestureClick*, gint, gdouble, gdouble, uintptr_t); -extern gboolean handleKeyPressed(GtkEventControllerKey*, guint, guint, GdkModifierType, uintptr_t); -extern void onProcessRequest(WebKitURISchemeRequest *request, uintptr_t user_data); -extern void sendMessageToBackend(WebKitUserContentManager *contentManager, JSCValue *value, void *data); -extern void menuActionActivated(guint id); -extern void fileDialogCallback(guint request_id, char **files, int count, gboolean cancelled); -extern void alertDialogCallback(guint request_id, int button_index); -extern void onDropEnter(uintptr_t); -extern void onDropLeave(uintptr_t); -extern void onDropMotion(gint, gint, uintptr_t); -extern void onDropFiles(char**, gint, gint, uintptr_t); - -// Forward declaration for activate callback -void activateLinux(gpointer data); - -// ============================================================================ -// Main thread dispatch -// ============================================================================ - -void dispatchOnMainThread(unsigned int id); - -// ============================================================================ -// Signal handling -// ============================================================================ - -void install_signal_handlers(void); - -// ============================================================================ -// Object data helpers -// ============================================================================ - -void save_window_id(void *object, uint value); -guint get_window_id(void *object); -void save_webview_to_content_manager(void *contentManager, void *webview); -WebKitWebView* get_webview_from_content_manager(void *contentManager); - -// ============================================================================ -// Signal connection (wrapper for macro) -// ============================================================================ - -void signal_connect(void *widget, char *event, void *cb, uintptr_t data); - -// ============================================================================ -// WebView helpers -// ============================================================================ - -WebKitWebView* webkit_web_view(GtkWidget *webview); -GtkWidget* create_webview_with_user_content_manager(WebKitUserContentManager *manager); - -// ============================================================================ -// Menu system (GMenu/GAction for GTK4) -// ============================================================================ - -void init_app_action_group(void); -void set_app_menu_model(GMenu *menu); -GMenuItem* create_menu_item(const char *label, const char *action_name, guint item_id); -GMenuItem* create_check_menu_item(const char *label, const char *action_name, guint item_id, gboolean initial_state); -GMenuItem* create_radio_menu_item(const char *label, const char *action_name, const char *target, const char *initial_value, guint item_id); -GtkWidget* create_menu_bar_from_model(GMenu *menu_model); -GtkWidget* create_header_bar_with_menu(GMenu *menu_model); -void attach_action_group_to_widget(GtkWidget *widget); -void set_action_accelerator(GtkApplication *app, const char *action_name, const char *accel); -char* build_accelerator_string(guint key, GdkModifierType mods); -void set_action_enabled(const char *action_name, gboolean enabled); -void set_action_state(const char *action_name, gboolean state); -gboolean get_action_state(const char *action_name); -void menu_remove_item(GMenu *menu, gint position); -void menu_insert_item(GMenu *menu, gint position, GMenuItem *item); - -// ============================================================================ -// Window event controllers (GTK4 style) -// ============================================================================ - -void setupWindowEventControllers(GtkWindow *window, GtkWidget *webview, uintptr_t winID); - -// ============================================================================ -// Window drag/resize (GdkToplevel for GTK4) -// ============================================================================ - -void beginWindowDrag(GtkWindow *window, int button, double x, double y, guint32 timestamp); -void beginWindowResize(GtkWindow *window, GdkSurfaceEdge edge, int button, double x, double y, guint32 timestamp); - -// ============================================================================ -// Drag and drop (GtkDropTarget for GTK4) -// ============================================================================ - -void enableDND(GtkWidget *widget, uintptr_t winID); -void disableDND(GtkWidget *widget, uintptr_t winID); - -// ============================================================================ -// File dialogs (GtkFileDialog for GTK4) -// ============================================================================ - -GtkFileDialog* create_file_dialog(const char *title); -void add_file_filter(GtkFileDialog *dialog, GListStore *filters, const char *name, const char *pattern); -void set_file_dialog_filters(GtkFileDialog *dialog, GListStore *filters); -void show_open_file_dialog(GtkWindow *parent, GtkFileDialog *dialog, guint request_id, gboolean allow_multiple, gboolean is_folder); -void show_save_file_dialog(GtkWindow *parent, GtkFileDialog *dialog, guint request_id); - -// ============================================================================ -// Message dialogs (custom GtkWindow-based for proper styling) -// ============================================================================ - -void show_message_dialog(GtkWindow *parent, const char *heading, const char *body, - const char *icon_name, const unsigned char *icon_data, int icon_data_len, - const char **buttons, int button_count, - int default_button, int cancel_button, int destructive_button, - guint request_id); - -// ============================================================================ -// Clipboard (GTK4) -// ============================================================================ - -char* clipboard_get_text_sync(void); -void clipboard_free_text(char *text); - -// ============================================================================ -// Misc -// ============================================================================ - -int GetNumScreens(void); - -#endif // LINUX_CGO_GTK4_H diff --git a/v3/pkg/application/linux_purego.go b/v3/pkg/application/linux_purego.go deleted file mode 100644 index 7b2e17235..000000000 --- a/v3/pkg/application/linux_purego.go +++ /dev/null @@ -1,1275 +0,0 @@ -//go:build linux && purego - -package application - -import ( - "fmt" - "os" - "unsafe" - - "github.com/ebitengine/purego" - "github.com/wailsapp/wails/v3/internal/assetserver/webview" - "github.com/wailsapp/wails/v3/pkg/events" -) - -type windowPointer uintptr -type identifier uint -type pointer uintptr - -// type GSList uintptr -type GSList struct { - data pointer - next *GSList -} - -type GSListPointer *GSList - -const ( - nilPointer pointer = 0 -) - -const ( - GSourceRemove int = 0 - - // https://gitlab.gnome.org/GNOME/gtk/-/blob/gtk-3-24/gdk/gdkwindow.h#L121 - GdkHintMinSize = 1 << 1 - GdkHintMaxSize = 1 << 2 - // https://gitlab.gnome.org/GNOME/gtk/-/blob/gtk-3-24/gdk/gdkevents.h#L512 - GdkWindowStateIconified = 1 << 1 - GdkWindowStateMaximized = 1 << 2 - GdkWindowStateFullscreen = 1 << 4 - - // https://gitlab.gnome.org/GNOME/gtk/-/blob/gtk-3-24/gtk/gtkmessagedialog.h#L87 - GtkButtonsNone int = 0 - GtkButtonsOk = 1 - GtkButtonsClose = 2 - GtkButtonsCancel = 3 - GtkButtonsYesNo = 4 - GtkButtonsOkCancel = 5 - - // https://gitlab.gnome.org/GNOME/gtk/-/blob/gtk-3-24/gtk/gtkdialog.h#L36 - GtkDialogModal = 1 << 0 - GtkDialogDestroyWithParent = 1 << 1 - GtkDialogUseHeaderBar = 1 << 2 // actions in header bar instead of action area - - GtkOrientationVertical = 1 - - // enum GtkMessageType - GtkMessageInfo = 0 - GtkMessageWarning = 1 - GtkMessageQuestion = 2 - GtkMessageError = 3 -) - -type GdkGeometry struct { - minWidth int32 - minHeight int32 - maxWidth int32 - maxHeight int32 - baseWidth int32 - baseHeight int32 - widthInc int32 - heightInc int32 - padding int32 - minAspect float64 - maxAspect float64 - GdkGravity int32 -} - -var ( - nilRadioGroup GSListPointer = nil - gtkSignalHandlers map[pointer]uint = map[pointer]uint{} - gtkSignalToMenuItem map[pointer]*MenuItem = map[pointer]*MenuItem{} - mainThreadId uint64 -) - -const ( - // TODO: map distro => so filename - with fallback? - gtk3 = "libgtk-3.so.0" - gtk4 = "libgtk-4.so.1" - webkit4 = "libwebkit2gtk-4.1.so.0" -) - -var ( - gtk uintptr - gtkVersion int - webkit uintptr - - // function references - gApplicationHold func(pointer) - gApplicationQuit func(pointer) - gApplicationName func() string - gApplicationRelease func(pointer) - gApplicationRun func(pointer, int, []string) int - gBytesNew func(uintptr, int) uintptr - gBytesNewStatic func(uintptr, int) uintptr - gBytesUnref func(uintptr) - gFree func(pointer) - gIdleAdd func(uintptr) - gListFree func(*GList) - gObjectRefSink func(pointer) - gObjectUnref func(pointer) - gSignalConnectData func(pointer, string, uintptr, pointer, bool, int) int - gSignalConnectObject func(pointer, string, pointer, pointer, int) uint - gSignalHandlerBlock func(pointer, uint) - gSignalHandlerUnblock func(pointer, uint) - gThreadSelf func() uint64 - - // gdk functions - gdkDisplayGetMonitor func(pointer, int) pointer - gdkDisplayGetMonitorAtWindow func(pointer, pointer) pointer - gdkDisplayGetNMonitors func(pointer) int - gdkMonitorGetGeometry func(pointer, pointer) pointer - gdkMonitorGetScaleFactor func(pointer) int - gdkMonitorIsPrimary func(pointer) int - gdkPixbufNewFromBytes func(uintptr, int, int, int, int, int, int) pointer - gdkRgbaParse func(pointer, string) bool - gdkScreenGetRgbaVisual func(pointer) pointer - gdkScreenIsComposited func(pointer) int - gdkWindowGetState func(pointer) int - gdkWindowGetDisplay func(pointer) pointer - - // gtk functions - gtkApplicationNew func(string, uint) pointer - gtkApplicationGetActiveWindow func(pointer) pointer - gtkApplicationGetWindows func(pointer) *GList - gtkApplicationWindowNew func(pointer) pointer - gtkBoxNew func(int, int) pointer - gtkBoxPackStart func(pointer, pointer, int, int, int) - gtkCheckMenuItemGetActive func(pointer) int - gtkCheckMenuItemNewWithLabel func(string) pointer - gtkCheckMenuItemSetActive func(pointer, int) - gtkContainerAdd func(pointer, pointer) - gtkContainerGetChildren func(pointer) *GList - gtkContainerRemove func(pointer, pointer) - gtkCSSProviderLoadFromData func(pointer, string, int, pointer) - gtkCSSProviderNew func() pointer - gtkDialogAddButton func(pointer, string, int) - gtkDialogGetContentArea func(pointer) pointer - gtkDialogRun func(pointer) int - gtkDialogSetDefaultResponse func(pointer, int) - gtkDragDestSet func(pointer, uint, pointer, uint, uint) - gtkFileChooserAddFilter func(pointer, pointer) - gtkFileChooserDialogNew func(string, pointer, int, string, int, string, int, pointer) pointer - gtkFileChooserGetFilenames func(pointer) *GSList - gtkFileChooserSetAction func(pointer, int) - gtkFileChooserSetCreateFolders func(pointer, bool) - gtkFileChooserSetCurrentFolder func(pointer, string) - gtkFileChooserSetCurrentName func(pointer, string) - gtkFileChooserSetSelectMultiple func(pointer, bool) - gtkFileChooserSetShowHidden func(pointer, bool) - gtkFileFilterAddPattern func(pointer, string) - gtkFileFilterNew func() pointer - gtkFileFilterSetName func(pointer, string) - gtkImageNewFromPixbuf func(pointer) pointer - gtkMenuBarNew func() pointer - gtkMenuItemNewWithLabel func(string) pointer - gtkMenuItemSetLabel func(pointer, string) - gtkMenuItemSetSubmenu func(pointer, pointer) - gtkMenuNew func() pointer - gtkMenuShellAppend func(pointer, pointer) - gtkMessageDialogNew func(pointer, int, int, int, string) pointer - gtkRadioMenuItemGetGroup func(pointer) GSListPointer - gtkRadioMenuItemNewWithLabel func(GSListPointer, string) pointer - gtkSeparatorMenuItemNew func() pointer - gtkStyleContextAddProvider func(pointer, pointer, int) - gtkTargetEntryFree func(pointer) - gtkTargetEntryNew func(string, int, uint) pointer - gtkWidgetDestroy func(pointer) - gtkWidgetGetDisplay func(pointer) pointer - gtkWidgetGetScreen func(pointer) pointer - gtkWidgetGetStyleContext func(pointer) pointer - gtkWidgetGetWindow func(pointer) pointer - gtkWidgetHide func(pointer) - gtkWidgetIsVisible func(pointer) bool - gtkWidgetRealize func(pointer) - gtkWidgetShow func(pointer) - gtkWidgetShowAll func(pointer) - gtkWidgetSetAppPaintable func(pointer, int) - gtkWidgetSetName func(pointer, string) - gtkWidgetSetSensitive func(pointer, int) - gtkWidgetSetToolTipText func(pointer, string) - gtkWidgetSetVisual func(pointer, pointer) - gtkWindowClose func(pointer) - gtkWindowFullScreen func(pointer) - gtkWindowGetPosition func(pointer, *int, *int) bool - gtkWindowGetSize func(pointer, *int, *int) - gtkWindowHasToplevelFocus func(pointer) int - gtkWindowKeepAbove func(pointer, bool) - gtkWindowMaximize func(pointer) - gtkWindowMinimize func(pointer) - gtkWindowMove func(pointer, int, int) - gtkWindowPresent func(pointer) - gtkWindowResize func(pointer, int, int) - gtkWindowSetDecorated func(pointer, int) - gtkWindowSetGeometryHints func(pointer, pointer, pointer, int) - gtkWindowSetKeepAbove func(pointer, bool) - gtkWindowSetResizable func(pointer, bool) - gtkWindowSetTitle func(pointer, string) - gtkWindowUnfullscreen func(pointer) - gtkWindowUnmaximize func(pointer) - - // webkit - webkitNewWithUserContentManager func(pointer) pointer - webkitRegisterUriScheme func(pointer, string, pointer, int, int) - webkitSettingsGetEnableDeveloperExtras func(pointer) bool - webkitSettingsSetHardwareAccelerationPolicy func(pointer, int) - webkitSettingsSetEnableDeveloperExtras func(pointer, bool) - webkitSettingsSetUserAgentWithApplicationDetails func(pointer, string, string) - webkitUserContentManagerNew func() pointer - webkitUserContentManagerRegisterScriptMessageHandler func(pointer, string) - webkitWebContextGetDefault func() pointer - webkitWebViewEvaluateJS func(pointer, string, int, pointer, string, pointer, pointer, pointer) - webkitWebViewGetSettings func(pointer) pointer - webkitWebViewGetZoom func(pointer) float64 - webkitWebViewLoadAlternateHTML func(pointer, string, string, *string) - webkitWebViewLoadUri func(pointer, string) - webkitWebViewSetBackgroundColor func(pointer, pointer) - webkitWebViewSetSettings func(pointer, pointer) - webkitWebViewSetZoomLevel func(pointer, float64) -) - -func init() { - // needed for GTK4 to function - _ = os.Setenv("GDK_BACKEND", "x11") - var err error - - // gtk, err = purego.Dlopen(gtk4, purego.RTLD_NOW|purego.RTLD_GLOBAL) - // if err == nil { - // version = 4 - // return - // } - - // log.Println("Failed to open GTK4: Falling back to GTK3") - - gtk, err = purego.Dlopen(gtk3, purego.RTLD_NOW|purego.RTLD_GLOBAL) - if err != nil { - panic(err) - } - gtkVersion = 3 - - webkit, err = purego.Dlopen(webkit4, purego.RTLD_NOW|purego.RTLD_GLOBAL) - if err != nil { - panic(err) - } - - // Function registration - // GLib - purego.RegisterLibFunc(&gApplicationHold, gtk, "g_application_hold") - purego.RegisterLibFunc(&gApplicationName, gtk, "g_get_application_name") - purego.RegisterLibFunc(&gApplicationQuit, gtk, "g_application_quit") - purego.RegisterLibFunc(&gApplicationRelease, gtk, "g_application_release") - purego.RegisterLibFunc(&gApplicationRun, gtk, "g_application_run") - purego.RegisterLibFunc(&gBytesNew, gtk, "g_bytes_new") - purego.RegisterLibFunc(&gBytesNewStatic, gtk, "g_bytes_new_static") - purego.RegisterLibFunc(&gBytesUnref, gtk, "g_bytes_unref") - purego.RegisterLibFunc(&gFree, gtk, "g_free") - purego.RegisterLibFunc(&gIdleAdd, gtk, "g_idle_add") - purego.RegisterLibFunc(&gListFree, gtk, "g_list_free") - purego.RegisterLibFunc(&gObjectRefSink, gtk, "g_object_ref_sink") - purego.RegisterLibFunc(&gObjectUnref, gtk, "g_object_unref") - purego.RegisterLibFunc(&gSignalConnectData, gtk, "g_signal_connect_data") - purego.RegisterLibFunc(&gSignalConnectObject, gtk, "g_signal_connect_object") - purego.RegisterLibFunc(&gSignalHandlerBlock, gtk, "g_signal_handler_block") - purego.RegisterLibFunc(&gSignalHandlerUnblock, gtk, "g_signal_handler_unblock") - purego.RegisterLibFunc(&gThreadSelf, gtk, "g_thread_self") - - // GDK - purego.RegisterLibFunc(&gdkDisplayGetMonitor, gtk, "gdk_display_get_monitor") - purego.RegisterLibFunc(&gdkDisplayGetMonitorAtWindow, gtk, "gdk_display_get_monitor_at_window") - purego.RegisterLibFunc(&gdkDisplayGetNMonitors, gtk, "gdk_display_get_n_monitors") - purego.RegisterLibFunc(&gdkMonitorGetGeometry, gtk, "gdk_monitor_get_geometry") - purego.RegisterLibFunc(&gdkMonitorGetScaleFactor, gtk, "gdk_monitor_get_scale_factor") - purego.RegisterLibFunc(&gdkMonitorIsPrimary, gtk, "gdk_monitor_is_primary") - purego.RegisterLibFunc(&gdkPixbufNewFromBytes, gtk, "gdk_pixbuf_new_from_bytes") - purego.RegisterLibFunc(&gdkRgbaParse, gtk, "gdk_rgba_parse") - purego.RegisterLibFunc(&gdkScreenGetRgbaVisual, gtk, "gdk_screen_get_rgba_visual") - purego.RegisterLibFunc(&gdkScreenIsComposited, gtk, "gdk_screen_is_composited") - purego.RegisterLibFunc(&gdkWindowGetDisplay, gtk, "gdk_window_get_display") - purego.RegisterLibFunc(&gdkWindowGetState, gtk, "gdk_window_get_state") - - // GTK3 - purego.RegisterLibFunc(>kApplicationNew, gtk, "gtk_application_new") - purego.RegisterLibFunc(>kApplicationGetActiveWindow, gtk, "gtk_application_get_active_window") - purego.RegisterLibFunc(>kApplicationGetWindows, gtk, "gtk_application_get_windows") - purego.RegisterLibFunc(>kApplicationWindowNew, gtk, "gtk_application_window_new") - purego.RegisterLibFunc(>kBoxNew, gtk, "gtk_box_new") - purego.RegisterLibFunc(>kBoxPackStart, gtk, "gtk_box_pack_start") - purego.RegisterLibFunc(>kCheckMenuItemGetActive, gtk, "gtk_check_menu_item_get_active") - purego.RegisterLibFunc(>kCheckMenuItemNewWithLabel, gtk, "gtk_check_menu_item_new_with_label") - purego.RegisterLibFunc(>kCheckMenuItemSetActive, gtk, "gtk_check_menu_item_set_active") - purego.RegisterLibFunc(>kContainerAdd, gtk, "gtk_container_add") - purego.RegisterLibFunc(>kContainerGetChildren, gtk, "gtk_container_get_children") - purego.RegisterLibFunc(>kContainerRemove, gtk, "gtk_container_remove") - purego.RegisterLibFunc(>kCSSProviderLoadFromData, gtk, "gtk_css_provider_load_from_data") - purego.RegisterLibFunc(>kDialogAddButton, gtk, "gtk_dialog_add_button") - purego.RegisterLibFunc(>kDialogGetContentArea, gtk, "gtk_dialog_get_content_area") - purego.RegisterLibFunc(>kDialogRun, gtk, "gtk_dialog_run") - purego.RegisterLibFunc(>kDialogSetDefaultResponse, gtk, "gtk_dialog_set_default_response") - purego.RegisterLibFunc(>kDragDestSet, gtk, "gtk_drag_dest_set") - purego.RegisterLibFunc(>kFileChooserAddFilter, gtk, "gtk_file_chooser_add_filter") - purego.RegisterLibFunc(>kFileChooserDialogNew, gtk, "gtk_file_chooser_dialog_new") - purego.RegisterLibFunc(>kFileChooserGetFilenames, gtk, "gtk_file_chooser_get_filenames") - purego.RegisterLibFunc(>kFileChooserSetAction, gtk, "gtk_file_chooser_set_action") - purego.RegisterLibFunc(>kFileChooserSetCreateFolders, gtk, "gtk_file_chooser_set_create_folders") - purego.RegisterLibFunc(>kFileChooserSetCurrentFolder, gtk, "gtk_file_chooser_set_current_folder") - purego.RegisterLibFunc(>kFileChooserSetCurrentName, gtk, "gtk_file_chooser_set_current_name") - purego.RegisterLibFunc(>kFileChooserSetSelectMultiple, gtk, "gtk_file_chooser_set_select_multiple") - purego.RegisterLibFunc(>kFileChooserSetShowHidden, gtk, "gtk_file_chooser_set_show_hidden") - purego.RegisterLibFunc(>kFileFilterAddPattern, gtk, "gtk_file_filter_add_pattern") - purego.RegisterLibFunc(>kFileFilterNew, gtk, "gtk_file_filter_new") - purego.RegisterLibFunc(>kFileFilterSetName, gtk, "gtk_file_filter_set_name") - purego.RegisterLibFunc(>kImageNewFromPixbuf, gtk, "gtk_image_new_from_pixbuf") - purego.RegisterLibFunc(>kMenuItemSetLabel, gtk, "gtk_menu_item_set_label") - purego.RegisterLibFunc(>kMenuBarNew, gtk, "gtk_menu_bar_new") - purego.RegisterLibFunc(>kMenuItemNewWithLabel, gtk, "gtk_menu_item_new_with_label") - purego.RegisterLibFunc(>kMenuItemSetSubmenu, gtk, "gtk_menu_item_set_submenu") - purego.RegisterLibFunc(>kMenuNew, gtk, "gtk_menu_new") - purego.RegisterLibFunc(>kMenuShellAppend, gtk, "gtk_menu_shell_append") - purego.RegisterLibFunc(>kMessageDialogNew, gtk, "gtk_message_dialog_new") - purego.RegisterLibFunc(>kRadioMenuItemGetGroup, gtk, "gtk_radio_menu_item_get_group") - purego.RegisterLibFunc(>kRadioMenuItemNewWithLabel, gtk, "gtk_radio_menu_item_new_with_label") - purego.RegisterLibFunc(>kSeparatorMenuItemNew, gtk, "gtk_separator_menu_item_new") - purego.RegisterLibFunc(>kStyleContextAddProvider, gtk, "gtk_style_context_add_provider") - purego.RegisterLibFunc(>kTargetEntryFree, gtk, "gtk_target_entry_free") - purego.RegisterLibFunc(>kTargetEntryNew, gtk, "gtk_target_entry_new") - purego.RegisterLibFunc(>kWidgetDestroy, gtk, "gtk_widget_destroy") - purego.RegisterLibFunc(>kWidgetGetDisplay, gtk, "gtk_widget_get_display") - purego.RegisterLibFunc(>kWidgetGetScreen, gtk, "gtk_widget_get_screen") - purego.RegisterLibFunc(>kWidgetGetStyleContext, gtk, "gtk_widget_get_style_context") - purego.RegisterLibFunc(>kWidgetGetWindow, gtk, "gtk_widget_get_window") - purego.RegisterLibFunc(>kWidgetHide, gtk, "gtk_widget_hide") - purego.RegisterLibFunc(>kWidgetIsVisible, gtk, "gtk_widget_is_visible") - purego.RegisterLibFunc(>kWidgetRealize, gtk, "gtk_widget_realize") - purego.RegisterLibFunc(>kWidgetSetAppPaintable, gtk, "gtk_widget_set_app_paintable") - purego.RegisterLibFunc(>kWidgetSetName, gtk, "gtk_widget_set_name") - purego.RegisterLibFunc(>kWidgetSetSensitive, gtk, "gtk_widget_set_sensitive") - purego.RegisterLibFunc(>kWidgetSetToolTipText, gtk, "gtk_widget_set_tooltip_text") - purego.RegisterLibFunc(>kWidgetSetVisual, gtk, "gtk_widget_set_visual") - purego.RegisterLibFunc(>kWidgetShow, gtk, "gtk_widget_show") - purego.RegisterLibFunc(>kWidgetShowAll, gtk, "gtk_widget_show_all") - purego.RegisterLibFunc(>kWindowFullScreen, gtk, "gtk_window_fullscreen") - purego.RegisterLibFunc(>kWindowClose, gtk, "gtk_window_close") - purego.RegisterLibFunc(>kWindowGetPosition, gtk, "gtk_window_get_position") - purego.RegisterLibFunc(>kWindowGetSize, gtk, "gtk_window_get_size") - purego.RegisterLibFunc(>kWindowMaximize, gtk, "gtk_window_maximize") - purego.RegisterLibFunc(>kWindowMove, gtk, "gtk_window_move") - purego.RegisterLibFunc(>kWindowPresent, gtk, "gtk_window_present") - //purego.RegisterLibFunc(>kWindowPresent, gtk, "gtk_window_unminimize") // gtk4 - purego.RegisterLibFunc(>kWindowHasToplevelFocus, gtk, "gtk_window_has_toplevel_focus") - purego.RegisterLibFunc(>kWindowMinimize, gtk, "gtk_window_iconify") // gtk3 - // purego.RegisterLibFunc(>kWindowMinimize, gtk, "gtk_window_minimize") // gtk4 - purego.RegisterLibFunc(>kWindowResize, gtk, "gtk_window_resize") - purego.RegisterLibFunc(>kWindowSetGeometryHints, gtk, "gtk_window_set_geometry_hints") - purego.RegisterLibFunc(>kWindowSetDecorated, gtk, "gtk_window_set_decorated") - purego.RegisterLibFunc(>kWindowKeepAbove, gtk, "gtk_window_set_keep_above") - purego.RegisterLibFunc(>kWindowSetResizable, gtk, "gtk_window_set_resizable") - purego.RegisterLibFunc(>kWindowSetTitle, gtk, "gtk_window_set_title") - purego.RegisterLibFunc(>kWindowUnfullscreen, gtk, "gtk_window_unfullscreen") - purego.RegisterLibFunc(>kWindowUnmaximize, gtk, "gtk_window_unmaximize") - - // webkit - purego.RegisterLibFunc(&webkitNewWithUserContentManager, webkit, "webkit_web_view_new_with_user_content_manager") - purego.RegisterLibFunc(&webkitRegisterUriScheme, webkit, "webkit_web_context_register_uri_scheme") - purego.RegisterLibFunc(&webkitSettingsGetEnableDeveloperExtras, webkit, "webkit_settings_get_enable_developer_extras") - purego.RegisterLibFunc(&webkitSettingsSetEnableDeveloperExtras, webkit, "webkit_settings_set_enable_developer_extras") - purego.RegisterLibFunc(&webkitSettingsSetHardwareAccelerationPolicy, webkit, "webkit_settings_set_hardware_acceleration_policy") - purego.RegisterLibFunc(&webkitSettingsSetUserAgentWithApplicationDetails, webkit, "webkit_settings_set_user_agent_with_application_details") - purego.RegisterLibFunc(&webkitUserContentManagerNew, webkit, "webkit_user_content_manager_new") - purego.RegisterLibFunc(&webkitUserContentManagerRegisterScriptMessageHandler, webkit, "webkit_user_content_manager_register_script_message_handler") - purego.RegisterLibFunc(&webkitWebContextGetDefault, webkit, "webkit_web_context_get_default") - purego.RegisterLibFunc(&webkitWebViewEvaluateJS, webkit, "webkit_web_view_evaluate_javascript") - purego.RegisterLibFunc(&webkitWebViewGetSettings, webkit, "webkit_web_view_get_settings") - purego.RegisterLibFunc(&webkitWebViewGetZoom, webkit, "webkit_web_view_get_zoom_level") - purego.RegisterLibFunc(&webkitWebViewLoadAlternateHTML, webkit, "webkit_web_view_load_alternate_html") - purego.RegisterLibFunc(&webkitWebViewLoadUri, webkit, "webkit_web_view_load_uri") - purego.RegisterLibFunc(&webkitWebViewSetBackgroundColor, webkit, "webkit_web_view_set_background_color") - purego.RegisterLibFunc(&webkitWebViewSetSettings, webkit, "webkit_web_view_set_settings") - purego.RegisterLibFunc(&webkitWebViewSetZoomLevel, webkit, "webkit_web_view_set_zoom_level") -} - -// mainthread stuff -func dispatchOnMainThread(id uint) { - gIdleAdd(purego.NewCallback(func(pointer) int { - executeOnMainThread(id) - return GSourceRemove - })) -} - -// implementation below -func appName() string { - return gApplicationName() -} - -func appNew(name string) pointer { - // Use NON_UNIQUE to allow multiple instances of the application to run - // This matches the behavior of gtk_init/gtk_main used in v2 - // G_APPLICATION_NON_UNIQUE = (1 << 5) = 32 - GApplicationNonUnique := uint(32) - - // Name is already sanitized by sanitizeAppName() in application_linux.go - identifier := fmt.Sprintf("org.wails.%s", name) - - return pointer(gtkApplicationNew(identifier, GApplicationNonUnique)) -} - -func appRun(application pointer) error { - mainThreadId = gThreadSelf() - fmt.Println("linux_purego: appRun threadID", mainThreadId) - - app := pointer(application) - activate := func() { - // TODO: Do we care? - fmt.Println("linux.activated!") - gApplicationHold(app) // allow running without a window - } - gSignalConnectData( - application, - "activate", - purego.NewCallback(activate), - app, - false, - 0) - - status := gApplicationRun(app, 0, nil) - gApplicationRelease(app) - gObjectUnref(app) - - var err error - if status != 0 { - err = fmt.Errorf("exit code: %d", status) - } - return err -} - -func appDestroy(application pointer) { - gApplicationQuit(pointer(application)) -} - -func getCurrentWindowID(application pointer, windows map[windowPointer]uint) uint { - // TODO: Add extra metadata to window and use it! - window := gtkApplicationGetActiveWindow(pointer(application)) - identifier, ok := windows[windowPointer(window)] - if ok { - return identifier - } - // FIXME: Should we panic here if not found? - return uint(1) -} - -type GList struct { - data pointer - next *GList - prev *GList -} - -func getWindows(application pointer) []pointer { - result := []pointer{} - windows := gtkApplicationGetWindows(pointer(application)) - // FIXME: Need to make a struct here to deal with response data - for { - result = append(result, pointer(windows.data)) - windows = windows.next - if windows == nil { - return result - } - } -} - -func hideAllWindows(application pointer) { - for _, window := range getWindows(application) { - gtkWidgetHide(window) - } -} - -func showAllWindows(application pointer) { - for _, window := range getWindows(application) { - gtkWidgetShowAll(window) - } -} - -// Menu -func menuAddSeparator(menu *Menu) { - gtkMenuShellAppend( - pointer((menu.impl).(*linuxMenu).native), - gtkSeparatorMenuItemNew()) -} - -func menuAppend(parent *Menu, menu *MenuItem) { - // TODO: override this with the GTK4 version if needed - possibly rename to imply it's an alias - gtkMenuShellAppend( - pointer((parent.impl).(*linuxMenu).native), - pointer((menu.impl).(*linuxMenuItem).native)) - - /* gtk4 - C.gtk_menu_item_set_submenu( - (*C.struct__GtkMenuItem)((menu.impl).(*linuxMenuItem).native), - (*C.struct__GtkWidget)((parent.impl).(*linuxMenu).native), - ) - */ -} - -func menuBarNew() pointer { - return pointer(gtkMenuBarNew()) -} - -func menuNew() pointer { - return pointer(gtkMenuNew()) -} - -func menuSetSubmenu(item *MenuItem, menu *Menu) { - // FIXME: How is this different than `menuAppend` above? - gtkMenuItemSetSubmenu( - pointer((item.impl).(*linuxMenuItem).native), - pointer((menu.impl).(*linuxMenu).native)) -} - -func menuGetRadioGroup(item *linuxMenuItem) *GSList { - return (*GSList)(gtkRadioMenuItemGetGroup(pointer(item.native))) -} - -func menuClear(menu *Menu) { - menuShell := pointer((menu.impl).(*linuxMenu).native) - children := gtkContainerGetChildren(menuShell) - if children != nil { - // Save the original pointer to free later - originalList := children - // Iterate through all children and remove them - for children != nil { - child := children.data - if child != nilPointer { - gtkContainerRemove(menuShell, child) - } - children = children.next - } - gListFree(originalList) - } -} - -func attachMenuHandler(item *MenuItem) { - handleClick := func() { - item := item - switch item.itemType { - case text, checkbox: - menuItemClicked <- item.id - case radio: - menuItem := (item.impl).(*linuxMenuItem) - if menuItem.isChecked() { - menuItemClicked <- item.id - } - } - } - - impl := (item.impl).(*linuxMenuItem) - widget := impl.native - flags := 0 - handlerId := gSignalConnectObject( - pointer(widget), - "activate", - pointer(purego.NewCallback(handleClick)), - pointer(widget), - flags) - impl.handlerId = uint(handlerId) -} - -// menuItem -func menuItemChecked(widget pointer) bool { - if gtkCheckMenuItemGetActive(widget) == 1 { - return true - } - return false -} - -func menuItemNew(label string) pointer { - return pointer(gtkMenuItemNewWithLabel(label)) -} - -func menuCheckItemNew(label string) pointer { - return pointer(gtkCheckMenuItemNewWithLabel(label)) -} - -func menuItemSetChecked(widget pointer, checked bool) { - value := 0 - if checked { - value = 1 - } - gtkCheckMenuItemSetActive(pointer(widget), value) -} - -func menuItemSetDisabled(widget pointer, disabled bool) { - value := 1 - if disabled { - value = 0 - } - gtkWidgetSetSensitive(widget, value) -} - -func menuItemSetLabel(widget pointer, label string) { - gtkMenuItemSetLabel( - pointer(widget), - label) -} - -func menuItemSetToolTip(widget pointer, tooltip string) { - gtkWidgetSetToolTipText( - pointer(widget), - tooltip) -} - -func menuItemSignalBlock(widget pointer, handlerId uint, block bool) { - if block { - gSignalHandlerBlock(widget, handlerId) - } else { - gSignalHandlerUnblock(widget, handlerId) - } -} - -func menuRadioItemNew(group GSListPointer, label string) pointer { - return pointer(gtkRadioMenuItemNewWithLabel(group, label)) -} - -// screen related - -func getScreenByIndex(display pointer, index int) *Screen { - monitor := gdkDisplayGetMonitor(display, index) - // TODO: Do we need to update Screen to contain current info? - // currentMonitor := C.gdk_display_get_monitor_at_window(display, window) - - geometry := struct { - x int32 - y int32 - width int32 - height int32 - }{} - result := pointer(unsafe.Pointer(&geometry)) - gdkMonitorGetGeometry(monitor, result) - - primary := false - if gdkMonitorIsPrimary(monitor) == 1 { - primary = true - } - - return &Screen{ - IsPrimary: primary, - ScaleFactor: 1.0, - X: int(geometry.x), - Y: int(geometry.y), - Size: Size{ - Height: int(geometry.height), - Width: int(geometry.width), - }, - } -} - -func getScreens(app pointer) ([]*Screen, error) { - var screens []*Screen - window := gtkApplicationGetActiveWindow(app) - display := gdkWindowGetDisplay(window) - count := gdkDisplayGetNMonitors(display) - for i := 0; i < int(count); i++ { - screens = append(screens, getScreenByIndex(display, i)) - } - return screens, nil -} - -// widgets -func widgetSetSensitive(widget pointer, enabled bool) { - value := 0 - if enabled { - value = 1 - } - gtkWidgetSetSensitive(widget, value) -} - -func widgetSetVisible(widget pointer, hidden bool) { - if hidden { - gtkWidgetHide(widget) - } else { - gtkWidgetShow(widget) - } -} - -// window related functions -func windowClose(window pointer) { - gtkWindowClose(window) -} - -func windowEnableDND(id uint, webview pointer) { - targetentry := gtkTargetEntryNew("text/uri-list", 0, id) - defer gtkTargetEntryFree(targetentry) - - GtkDestDefaultDrop := uint(0) - GdkActionCopy := uint(0) //? - gtkDragDestSet(webview, GtkDestDefaultDrop, targetentry, 1, GdkActionCopy) - - // FIXME: enable and process - /* gSignalConnectData(webview, - "drag-data-received", - purego.NewCallback(onDragNDrop), - 0, - false, - 0)*/ -} - -func windowExecJS(webview pointer, js string) { - webkitWebViewEvaluateJS( - webview, - js, - len(js), - 0, - "", - 0, - 0, - 0) -} - -func windowDestroy(window pointer) { - // Should this truly 'destroy' ? - gtkWindowClose(window) -} - -func windowFullscreen(window pointer) { - gtkWindowFullScreen(window) -} - -func windowGetPosition(window pointer) (int, int) { - var x, y int - gtkWindowGetPosition(window, &x, &y) - return x, y -} - -func windowGetCurrentMonitor(window pointer) pointer { - // Get the monitor that the window is currently on - display := gtkWidgetGetDisplay(window) - window = gtkWidgetGetWindow(window) - if window == 0 { - return 0 - } - return gdkDisplayGetMonitorAtWindow(display, window) -} - -func windowGetCurrentMonitorGeometry(window pointer) (x int, y int, width int, height int, scaleFactor int) { - monitor := windowGetCurrentMonitor(window) - if monitor == 0 { - return -1, -1, -1, -1, 1 - } - - result := struct { - x int32 - y int32 - width int32 - height int32 - }{} - gdkMonitorGetGeometry(monitor, pointer(unsafe.Pointer(&result))) - return int(result.x), int(result.y), int(result.width), int(result.height), gdkMonitorGetScaleFactor(monitor) -} - -func windowGetRelativePosition(window pointer) (int, int) { - absX, absY := windowGetPosition(window) - x, y, _, _, _ := windowGetCurrentMonitorGeometry(window) - - relX := absX - x - relY := absY - y - - // TODO: Scale based on DPI - return relX, relY -} - -func windowGetSize(window pointer) (int, int) { - // TODO: dispatchOnMainThread? - var width, height int - gtkWindowGetSize(window, &width, &height) - return width, height -} - -func windowGetPosition(window pointer) (int, int) { - // TODO: dispatchOnMainThread? - var x, y int - gtkWindowGetPosition(window, &x, &y) - return x, y -} - -func windowHide(window pointer) { - gtkWidgetHide(window) -} - -func windowIsFocused(window pointer) bool { - return gtkWindowHasToplevelFocus(window) == 1 -} - -func windowIsFullscreen(window pointer) bool { - gdkwindow := gtkWidgetGetWindow(window) - state := gdkWindowGetState(gdkwindow) - return state&GdkWindowStateFullscreen > 0 -} - -func windowIsMaximized(window pointer) bool { - gdkwindow := gtkWidgetGetWindow(window) - state := gdkWindowGetState(gdkwindow) - return state&GdkWindowStateMaximized > 0 && state&GdkWindowStateFullscreen == 0 -} - -func windowIsMinimized(window pointer) bool { - gdkwindow := gtkWidgetGetWindow(window) - state := gdkWindowGetState(gdkwindow) - return state&GdkWindowStateIconified > 0 -} - -func windowIsVisible(window pointer) bool { - // TODO: validate this works.. (used a `bool` in the registration) - return gtkWidgetIsVisible(window) -} - -func windowMaximize(window pointer) { - gtkWindowMaximize(window) -} - -func windowMinimize(window pointer) { - gtkWindowMinimize(window) -} - -func windowNew(application pointer, menu pointer, windowId uint, gpuPolicy int) (pointer, pointer, pointer) { - window := gtkApplicationWindowNew(application) - gObjectRefSink(window) - webview := windowNewWebview(windowId, gpuPolicy) - vbox := gtkBoxNew(GtkOrientationVertical, 0) - gtkContainerAdd(window, vbox) - gtkWidgetSetName(vbox, "webview-box") - - if menu != 0 { - gtkBoxPackStart(vbox, menu, 0, 0, 0) - } - gtkBoxPackStart(vbox, webview, 1, 1, 0) - return pointer(window), pointer(webview), pointer(vbox) -} - -func windowNewWebview(parentId uint, gpuPolicy int) pointer { - manager := webkitUserContentManagerNew() - webkitUserContentManagerRegisterScriptMessageHandler(manager, "external") - wv := webkitNewWithUserContentManager(manager) - if !registered { - webkitRegisterUriScheme( - webkitWebContextGetDefault(), - "wails", - pointer(purego.NewCallback(func(request uintptr) { - webviewRequests <- &webViewAssetRequest{ - Request: webview.NewRequest(request), - windowId: parentId, - windowName: func() string { - if window, ok := globalApplication.Window.GetByID(parentId); ok { - return window.Name() - } - return "" - }(), - } - })), - 0, - 0, - ) - registered = true - } - - settings := webkitWebViewGetSettings(wv) - webkitSettingsSetUserAgentWithApplicationDetails( - settings, - "wails.io", - "") - webkitSettingsSetHardwareAccelerationPolicy(settings, gpuPolicy) - webkitWebViewSetSettings(wv, settings) - return wv -} - -func windowPresent(window pointer) { - gtkWindowPresent(pointer(window)) -} - -func windowReload(webview pointer, address string) { - webkitWebViewLoadUri(pointer(webview), address) -} - -func windowResize(window pointer, width, height int) { - gtkWindowResize(window, width, height) -} - -func windowShow(window pointer) { - // Realize the window first to ensure it has a valid GdkWindow. - // This prevents crashes on Wayland when appmenu-gtk-module tries to - // set DBus properties for global menu integration before the window - // is fully realized. See: https://github.com/wailsapp/wails/issues/4769 - gtkWidgetRealize(pointer(window)) - gtkWidgetShowAll(pointer(window)) -} - -func windowSetBackgroundColour(vbox, webview pointer, colour RGBA) { - const GtkStyleProviderPriorityUser = 800 - - // FIXME: Use a struct! - rgba := make([]byte, 4*8) // C.sizeof_GdkRGBA == 32 - rgbaPointer := pointer(unsafe.Pointer(&rgba[0])) - if !gdkRgbaParse( - rgbaPointer, - fmt.Sprintf("rgba(%v,%v,%v,%v)", - colour.Red, - colour.Green, - colour.Blue, - float32(colour.Alpha)/255.0, - )) { - return - } - webkitWebViewSetBackgroundColor(pointer(webview), rgbaPointer) - - colour.Alpha = 255 - css := fmt.Sprintf("#webview-box {background-color: rgba(%d, %d, %d, %1.1f);}", colour.Red, colour.Green, colour.Blue, float32(colour.Alpha)/255.0) - provider := gtkCSSProviderNew() - defer gObjectUnref(provider) - gtkStyleContextAddProvider( - gtkWidgetGetStyleContext(vbox), - provider, - GtkStyleProviderPriorityUser, - ) - gtkCSSProviderLoadFromData(provider, css, -1, 0) -} - -func windowSetGeometryHints(window pointer, minWidth, minHeight, maxWidth, maxHeight int) { - size := GdkGeometry{ - minWidth: int32(minWidth), - minHeight: int32(minHeight), - maxWidth: int32(maxWidth), - maxHeight: int32(maxHeight), - } - gtkWindowSetGeometryHints( - pointer(window), - pointer(0), - pointer(unsafe.Pointer(&size)), - GdkHintMinSize|GdkHintMaxSize) -} - -func windowSetFrameless(window pointer, frameless bool) { - decorated := 1 - if frameless { - decorated = 0 - } - gtkWindowSetDecorated(pointer(window), decorated) - - // TODO: Deal with transparency for the titlebar if possible when !frameless - // Perhaps we just make it undecorated and add a menu bar inside? -} - -// TODO: confirm this is working properly -func windowSetHTML(webview pointer, html string) { - webkitWebViewLoadAlternateHTML(webview, html, "wails://", nil) -} - -func windowSetKeepAbove(window pointer, alwaysOnTop bool) { - gtkWindowKeepAbove(window, alwaysOnTop) -} - -func windowSetResizable(window pointer, resizable bool) { - // FIXME: Does this work? - gtkWindowSetResizable( - pointer(window), - resizable, - ) -} - -func windowSetTitle(window pointer, title string) { - gtkWindowSetTitle(pointer(window), title) -} - -func windowSetTransparent(window pointer) { - screen := gtkWidgetGetScreen(pointer(window)) - visual := gdkScreenGetRgbaVisual(screen) - if visual == 0 { - return - } - if gdkScreenIsComposited(screen) == 1 { - gtkWidgetSetAppPaintable(pointer(window), 1) - gtkWidgetSetVisual(pointer(window), visual) - } -} - -func windowSetURL(webview pointer, uri string) { - webkitWebViewLoadUri(webview, uri) -} - -func windowSetupSignalHandlers(windowId uint, window, webview pointer, emit func(e events.WindowEventType)) { - handleDelete := purego.NewCallback(func(pointer) { - emit(events.Common.WindowClosing) - }) - gSignalConnectData(window, "delete-event", handleDelete, 0, false, 0) - - /* - event = C.CString("load-changed") - defer C.free(unsafe.Pointer(event)) - C.signal_connect(webview, event, C.webviewLoadChanged, unsafe.Pointer(&w.parent.id)) - */ - - // TODO: Handle mouse button / drag events - /* id := C.uint(windowId) - event = C.CString("button-press-event") - C.signal_connect((*C.GtkWidget)(unsafe.Pointer(webview)), event, C.onButtonEvent, unsafe.Pointer(&id)) - C.free(unsafe.Pointer(event)) - event = C.CString("button-release-event") - defer C.free(unsafe.Pointer(event)) - C.signal_connect((*C.GtkWidget)(unsafe.Pointer(webview)), event, onButtonEvent, unsafe.Pointer(&id)) - */ -} - -func windowOpenDevTools(webview pointer) { - settings := webkitWebViewGetSettings(pointer(webview)) - webkitSettingsSetEnableDeveloperExtras( - settings, - !webkitSettingsGetEnableDeveloperExtras(settings)) -} - -func windowUnfullscreen(window pointer) { - gtkWindowUnfullscreen(window) -} - -func windowUnmaximize(window pointer) { - gtkWindowUnmaximize(window) -} - -func windowZoom(webview pointer) float64 { - return webkitWebViewGetZoom(webview) -} - -func windowZoomIn(webview pointer) { - ZoomInFactor := 1.10 - windowZoomSet(webview, windowZoom(webview)*ZoomInFactor) -} -func windowZoomOut(webview pointer) { - ZoomOutFactor := -1.10 - windowZoomSet(webview, windowZoom(webview)*ZoomOutFactor) -} - -func windowZoomSet(webview pointer, zoom float64) { - if zoom < 1.0 { // 1.0 is the smallest allowable - zoom = 1.0 - } - webkitWebViewSetZoomLevel(webview, zoom) -} - -func windowMove(window pointer, x, y int) { - gtkWindowMove(window, x, y) -} - -func runChooserDialog(window pointer, allowMultiple, createFolders, showHidden bool, currentFolder, title string, action int, acceptLabel string, filters []FileFilter, currentName string) ([]string, error) { - GtkResponseCancel := 0 - GtkResponseAccept := 1 - - fc := gtkFileChooserDialogNew( - title, - window, - action, - "_Cancel", - GtkResponseCancel, - acceptLabel, - GtkResponseAccept, - 0) - - gtkFileChooserSetAction(fc, action) - - gtkFilters := []pointer{} - for _, filter := range filters { - f := gtkFileFilterNew() - gtkFileFilterSetName(f, filter.DisplayName) - gtkFileFilterAddPattern(f, filter.Pattern) - gtkFileChooserAddFilter(fc, f) - gtkFilters = append(gtkFilters, f) - } - gtkFileChooserSetSelectMultiple(fc, allowMultiple) - gtkFileChooserSetCreateFolders(fc, createFolders) - gtkFileChooserSetShowHidden(fc, showHidden) - - if currentFolder != "" { - gtkFileChooserSetCurrentFolder(fc, currentFolder) - } - - // Set the current name for save dialogs to pre-populate the filename - const GtkFileChooserActionSave = 1 - if currentName != "" && action == GtkFileChooserActionSave { - gtkFileChooserSetCurrentName(fc, currentName) - } - - buildStringAndFree := func(s pointer) string { - bytes := []byte{} - p := unsafe.Pointer(s) - for { - val := *(*byte)(p) - if val == 0 { // this is the null terminator - break - } - bytes = append(bytes, val) - p = unsafe.Add(p, 1) - } - gFree(s) // so we don't have to iterate a second time - return string(bytes) - } - - response := gtkDialogRun(fc) - selections := []string{} - if response == GtkResponseAccept { - filenames := gtkFileChooserGetFilenames(fc) - iter := filenames - count := 0 - for { - selections = append(selections, buildStringAndFree(iter.data)) - iter = iter.next - if iter == nil || count == 1024 { - break - } - count++ - } - } - defer gtkWidgetDestroy(fc) - return selections, nil -} - -// dialog related -func runOpenFileDialog(dialog *OpenFileDialogStruct) ([]string, error) { - const GtkFileChooserActionOpen = 0 - const GtkFileChooserActionSelectFolder = 2 - - var action int - - if dialog.canChooseDirectories { - action = GtkFileChooserActionSelectFolder - } else { - action = GtkFileChooserActionOpen - } - - window := pointer(0) - if dialog.window != nil { - nativeWindow := dialog.window.NativeWindow() - if nativeWindow != nil { - window = pointer(uintptr(nativeWindow)) - } - } - - buttonText := dialog.buttonText - if buttonText == "" { - buttonText = "_Open" - } - - return runChooserDialog( - window, - dialog.allowsMultipleSelection, - dialog.canCreateDirectories, - dialog.showHiddenFiles, - dialog.directory, - dialog.title, - GtkFileChooserActionOpen, - buttonText, - dialog.filters, - "") -} - -func runQuestionDialog(parent pointer, options *MessageDialog) int { - dType, ok := map[DialogType]int{ - InfoDialogType: GtkMessageInfo, - WarningDialogType: GtkMessageWarning, - QuestionDialogType: GtkMessageQuestion, - }[options.DialogType] - if !ok { - // FIXME: Add logging here! - dType = GtkMessageInfo - } - buttonMask := GtkButtonsOk - if len(options.Buttons) > 0 { - buttonMask = GtkButtonsNone - } - - dialog := gtkMessageDialogNew( - pointer(parent), - GtkDialogModal|GtkDialogDestroyWithParent, - dType, - buttonMask, - options.Message) - - if options.Title != "" { - gtkWindowSetTitle(dialog, options.Title) - } - - GdkColorspaceRGB := 0 - - if img, err := pngToImage(options.Icon); err == nil && len(img.Pix) > 0 { - // Use gBytesNew instead of gBytesNewStatic because Go memory can be - // moved or freed by the GC. gBytesNew copies the data to C-owned memory. - gbytes := gBytesNew(uintptr(unsafe.Pointer(&img.Pix[0])), len(img.Pix)) - - defer gBytesUnref(gbytes) - pixBuf := gdkPixbufNewFromBytes( - gbytes, - GdkColorspaceRGB, - 1, // has_alpha - 8, - img.Bounds().Dx(), - img.Bounds().Dy(), - img.Stride, - ) - image := gtkImageNewFromPixbuf(pixBuf) - widgetSetVisible(image, false) - contentArea := gtkDialogGetContentArea(dialog) - gtkContainerAdd(contentArea, image) - } - - for i, button := range options.Buttons { - gtkDialogAddButton( - dialog, - button.Label, - i, - ) - if button.IsDefault { - gtkDialogSetDefaultResponse(dialog, i) - } - } - defer gtkWidgetDestroy(dialog) - return gtkDialogRun(dialog) -} - -func runSaveFileDialog(dialog *SaveFileDialogStruct) (string, error) { - const GtkFileChooserActionSave = 1 - - window := pointer(0) - buttonText := dialog.buttonText - if buttonText == "" { - buttonText = "_Save" - } - results, err := runChooserDialog( - window, - false, // multiple selection - dialog.canCreateDirectories, - dialog.showHiddenFiles, - dialog.directory, - dialog.title, - GtkFileChooserActionSave, - buttonText, - dialog.filters, - dialog.filename) - - if err != nil || len(results) == 0 { - return "", err - } - - return results[0], nil -} - -func isOnMainThread() bool { - return mainThreadId == gThreadSelf() -} - -// linuxWebviewWindow show/hide methods for purego implementation -func (w *linuxWebviewWindow) windowShow() { - if w.window == 0 { - return - } - windowShow(w.window) -} - -func (w *linuxWebviewWindow) windowHide() { - if w.window == 0 { - return - } - windowHide(w.window) -} diff --git a/v3/pkg/application/logger_dev.go b/v3/pkg/application/logger_dev.go deleted file mode 100644 index d69ec631c..000000000 --- a/v3/pkg/application/logger_dev.go +++ /dev/null @@ -1,20 +0,0 @@ -//go:build !windows && !production && !ios - -package application - -import ( - "log/slog" - "os" - "time" - - "github.com/lmittmann/tint" - "github.com/mattn/go-isatty" -) - -func DefaultLogger(level slog.Leveler) *slog.Logger { - return slog.New(tint.NewHandler(os.Stderr, &tint.Options{ - TimeFormat: time.Kitchen, - NoColor: !isatty.IsTerminal(os.Stderr.Fd()), - Level: level, - })) -} diff --git a/v3/pkg/application/logger_dev_windows.go b/v3/pkg/application/logger_dev_windows.go deleted file mode 100644 index 20d20c376..000000000 --- a/v3/pkg/application/logger_dev_windows.go +++ /dev/null @@ -1,21 +0,0 @@ -//go:build windows && !production - -package application - -import ( - "log/slog" - "os" - "time" - - "github.com/lmittmann/tint" - "github.com/mattn/go-colorable" - "github.com/mattn/go-isatty" -) - -func DefaultLogger(level slog.Leveler) *slog.Logger { - return slog.New(tint.NewHandler(colorable.NewColorable(os.Stderr), &tint.Options{ - TimeFormat: time.StampMilli, - NoColor: !isatty.IsTerminal(os.Stderr.Fd()), - Level: level, - })) -} diff --git a/v3/pkg/application/logger_ios.go b/v3/pkg/application/logger_ios.go deleted file mode 100644 index 584e96609..000000000 --- a/v3/pkg/application/logger_ios.go +++ /dev/null @@ -1,128 +0,0 @@ -//go:build ios - -package application - -/* -#cgo CFLAGS: -x objective-c -fobjc-arc -#cgo LDFLAGS: -framework Foundation -framework UIKit -framework WebKit -#include "webview_window_ios.h" -*/ -import "C" - -import ( - "bytes" - "context" - "log/slog" - "strings" - "time" - "unsafe" - - "encoding/json" -) - -// iosConsoleHandler implements slog.Handler and forwards records to the WKWebView console. -type iosConsoleHandler struct { - level slog.Leveler - attrs []slog.Attr - group string -} - -func (h *iosConsoleHandler) Enabled(_ context.Context, lvl slog.Level) bool { - if h.level == nil { - return true - } - return lvl >= h.level.Level() -} - -func (h *iosConsoleHandler) Handle(_ context.Context, r slog.Record) error { - // Build a compact log line - var b bytes.Buffer - b.WriteString(r.Time.Format(time.Kitchen)) - b.WriteString(" ") - if h.group != "" { - b.WriteString("[") - b.WriteString(h.group) - b.WriteString("] ") - } - b.WriteString(r.Message) - - writeAttr := func(a slog.Attr) { - // Resolve attr values - a.Value = a.Value.Resolve() - b.WriteString(" ") - b.WriteString(a.Key) - b.WriteString("=") - // Use JSON for complex values - switch a.Value.Kind() { - case slog.KindString: - b.WriteString(strconvQuote(a.Value.String())) - default: - js, _ := json.Marshal(a.Value.Any()) - b.Write(js) - } - } - - for _, a := range h.attrs { - writeAttr(a) - } - r.Attrs(func(a slog.Attr) bool { writeAttr(a); return true }) - - lvl := levelToConsole(r.Level) - - msg := b.String() - cmsg := C.CString(msg) - defer C.free(unsafe.Pointer(cmsg)) - clvl := C.CString(lvl) - defer C.free(unsafe.Pointer(clvl)) - C.ios_console_log(clvl, cmsg) - return nil -} - -func (h *iosConsoleHandler) WithAttrs(attrs []slog.Attr) slog.Handler { - clone := *h - clone.attrs = append(append([]slog.Attr{}, h.attrs...), attrs...) - return &clone -} - -func (h *iosConsoleHandler) WithGroup(name string) slog.Handler { - clone := *h - if clone.group == "" { - clone.group = name - } else if name != "" { - clone.group = clone.group + "." + name - } - return &clone -} - -func levelToConsole(l slog.Level) string { - switch { - case l <= slog.LevelDebug: - return "debug" - case l <= slog.LevelInfo: - return "info" - case l <= slog.LevelWarn: - return "warn" - default: - return "error" - } -} - -// strconvQuote quotes a string for compact key=value output (no surrounding quotes if no spaces). -func strconvQuote(s string) string { - if strings.IndexFunc(s, func(r rune) bool { return r == ' ' || r == '\n' || r == '\t' }) >= 0 { - bs, _ := json.Marshal(s) - return string(bs) - } - return s -} - -// DefaultLogger for iOS forwards all logs to the browser console. -func DefaultLogger(level slog.Leveler) *slog.Logger { - // Ensure there's always a leveler - if level == nil { - var lv slog.LevelVar - lv.Set(slog.LevelInfo) - level = &lv - } - return slog.New(&iosConsoleHandler{level: level}) -} diff --git a/v3/pkg/application/logger_prod.go b/v3/pkg/application/logger_prod.go deleted file mode 100644 index eed0fb154..000000000 --- a/v3/pkg/application/logger_prod.go +++ /dev/null @@ -1,12 +0,0 @@ -//go:build production && !ios - -package application - -import ( - "io" - "log/slog" -) - -func DefaultLogger(level slog.Leveler) *slog.Logger { - return slog.New(slog.NewTextHandler(io.Discard, nil)) -} diff --git a/v3/pkg/application/mainthread.go b/v3/pkg/application/mainthread.go deleted file mode 100644 index 6eb40ba9d..000000000 --- a/v3/pkg/application/mainthread.go +++ /dev/null @@ -1,87 +0,0 @@ -package application - -import ( - "sync" -) - -var mainThreadFunctionStore = make(map[uint]func()) -var mainThreadFunctionStoreLock sync.RWMutex - -func generateFunctionStoreID() uint { - startID := 0 - for { - if _, ok := mainThreadFunctionStore[uint(startID)]; !ok { - return uint(startID) - } - startID++ - if startID == 0 { - Fatal("Too many functions have been dispatched to the main thread") - } - } -} - -func InvokeSync(fn func()) { - var wg sync.WaitGroup - wg.Add(1) - globalApplication.dispatchOnMainThread(func() { - defer handlePanic() - fn() - wg.Done() - }) - wg.Wait() -} - -func InvokeSyncWithResult[T any](fn func() T) (res T) { - var wg sync.WaitGroup - wg.Add(1) - globalApplication.dispatchOnMainThread(func() { - defer handlePanic() - res = fn() - wg.Done() - }) - wg.Wait() - return res -} - -func InvokeSyncWithError(fn func() error) (err error) { - var wg sync.WaitGroup - wg.Add(1) - globalApplication.dispatchOnMainThread(func() { - defer handlePanic() - err = fn() - wg.Done() - }) - wg.Wait() - return -} - -func InvokeSyncWithResultAndError[T any](fn func() (T, error)) (res T, err error) { - var wg sync.WaitGroup - wg.Add(1) - globalApplication.dispatchOnMainThread(func() { - defer handlePanic() - res, err = fn() - wg.Done() - }) - wg.Wait() - return res, err -} - -func InvokeSyncWithResultAndOther[T any, U any](fn func() (T, U)) (res T, other U) { - var wg sync.WaitGroup - wg.Add(1) - globalApplication.dispatchOnMainThread(func() { - defer handlePanic() - res, other = fn() - wg.Done() - }) - wg.Wait() - return res, other -} - -func InvokeAsync(fn func()) { - globalApplication.dispatchOnMainThread(func() { - defer handlePanic() - fn() - }) -} diff --git a/v3/pkg/application/mainthread_android.go b/v3/pkg/application/mainthread_android.go deleted file mode 100644 index 396bffba7..000000000 --- a/v3/pkg/application/mainthread_android.go +++ /dev/null @@ -1,25 +0,0 @@ -//go:build android - -package application - -// isOnMainThread returns whether the current goroutine is on the main thread -func (a *androidApp) isOnMainThread() bool { - // On Android, Go runs in its own thread separate from the UI thread - // UI operations need to be dispatched via JNI to the main thread - return false -} - -// dispatchOnMainThread executes a function on the Android main/UI thread -func (a *androidApp) dispatchOnMainThread(id uint) { - // TODO: Implement via JNI callback to Activity.runOnUiThread() - // For now, execute the callback directly - mainThreadFunctionStoreLock.RLock() - fn := mainThreadFunctionStore[id] - if fn == nil { - mainThreadFunctionStoreLock.RUnlock() - return - } - delete(mainThreadFunctionStore, id) - mainThreadFunctionStoreLock.RUnlock() - fn() -} diff --git a/v3/pkg/application/mainthread_darwin.go b/v3/pkg/application/mainthread_darwin.go deleted file mode 100644 index 5e7e32c67..000000000 --- a/v3/pkg/application/mainthread_darwin.go +++ /dev/null @@ -1,45 +0,0 @@ -//go:build darwin && !ios - -package application - -/* -#cgo CFLAGS: -mmacosx-version-min=10.13 -x objective-c -#cgo LDFLAGS: -framework Cocoa - -#include "Cocoa/Cocoa.h" - -extern void dispatchOnMainThreadCallback(unsigned int); - -static void dispatchOnMainThread(unsigned int id) { - dispatch_async(dispatch_get_main_queue(), ^{ - dispatchOnMainThreadCallback(id); - }); -} - -static bool onMainThread() { - return [NSThread isMainThread]; -} - -*/ -import "C" - -func (m *macosApp) isOnMainThread() bool { - return bool(C.onMainThread()) -} - -func (m *macosApp) dispatchOnMainThread(id uint) { - C.dispatchOnMainThread(C.uint(id)) -} - -//export dispatchOnMainThreadCallback -func dispatchOnMainThreadCallback(callbackID C.uint) { - mainThreadFunctionStoreLock.RLock() - id := uint(callbackID) - fn := mainThreadFunctionStore[id] - if fn == nil { - Fatal("dispatchCallback called with invalid id: %v", id) - } - delete(mainThreadFunctionStore, id) - mainThreadFunctionStoreLock.RUnlock() - fn() -} diff --git a/v3/pkg/application/mainthread_ios.go b/v3/pkg/application/mainthread_ios.go deleted file mode 100644 index dd13808de..000000000 --- a/v3/pkg/application/mainthread_ios.go +++ /dev/null @@ -1,44 +0,0 @@ -//go:build ios - -package application - -/* -#cgo CFLAGS: -x objective-c -#cgo LDFLAGS: -framework Foundation -framework UIKit -#import -#import - -extern void dispatchOnMainThreadCallback(unsigned int); - -static void dispatchOnMainThread(unsigned int id) { - dispatch_async(dispatch_get_main_queue(), ^{ - dispatchOnMainThreadCallback(id); - }); -} - -static bool onMainThread() { - return [NSThread isMainThread]; -} -*/ -import "C" - -func (a *iosApp) isOnMainThread() bool { - return bool(C.onMainThread()) -} - -func (a *iosApp) dispatchOnMainThread(id uint) { - C.dispatchOnMainThread(C.uint(id)) -} - -//export dispatchOnMainThreadCallback -func dispatchOnMainThreadCallback(callbackID C.uint) { - mainThreadFunctionStoreLock.RLock() - id := uint(callbackID) - fn := mainThreadFunctionStore[id] - if fn == nil { - Fatal("dispatchCallback called with invalid id: %v", id) - } - delete(mainThreadFunctionStore, id) - mainThreadFunctionStoreLock.RUnlock() - fn() -} diff --git a/v3/pkg/application/mainthread_linux.go b/v3/pkg/application/mainthread_linux.go deleted file mode 100644 index 5154109d3..000000000 --- a/v3/pkg/application/mainthread_linux.go +++ /dev/null @@ -1,18 +0,0 @@ -//go:build linux && !android && !server - -package application - -func (a *linuxApp) dispatchOnMainThread(id uint) { - dispatchOnMainThread(id) -} - -func executeOnMainThread(callbackID uint) { - mainThreadFunctionStoreLock.RLock() - fn := mainThreadFunctionStore[callbackID] - if fn == nil { - Fatal("dispatchCallback called with invalid id: %v", callbackID) - } - delete(mainThreadFunctionStore, callbackID) - mainThreadFunctionStoreLock.RUnlock() - fn() -} diff --git a/v3/pkg/application/mainthread_windows.go b/v3/pkg/application/mainthread_windows.go deleted file mode 100644 index ddee96339..000000000 --- a/v3/pkg/application/mainthread_windows.go +++ /dev/null @@ -1,127 +0,0 @@ -//go:build windows - -package application - -import ( - "runtime" - "sort" - "unsafe" - - "github.com/wailsapp/wails/v3/pkg/w32" -) - -var ( - wmInvokeCallback uint32 -) - -func init() { - wmInvokeCallback = w32.RegisterWindowMessage(w32.MustStringToUTF16Ptr("WailsV0.InvokeCallback")) -} - -// initMainLoop must be called with the same OSThread that is used to call runMainLoop() later. -func (m *windowsApp) initMainLoop() { - runtime.LockOSThread() - defer runtime.UnlockOSThread() - if m.mainThreadWindowHWND != 0 { - panic("initMainLoop was already called") - } - - // We need a hidden window so we can PostMessage to it, if we don't use PostMessage for dispatching to a HWND - // messages might get lost if a modal inner loop is being run. - // We had this once in V2: https://github.com/wailsapp/wails/issues/969 - // See: https://devblogs.microsoft.com/oldnewthing/20050426-18/?p=35783 - // See also: https://learn.microsoft.com/en-us/windows/win32/winmsg/using-messages-and-message-queues#creating-a-message-loop - // > Because the system directs messages to individual windows in an application, a thread must create at least one window before starting its message loop. - m.mainThreadWindowHWND = w32.CreateWindowEx( - 0, - w32.MustStringToUTF16Ptr(m.parent.options.Windows.WndClass), - w32.MustStringToUTF16Ptr("__wails_hidden_mainthread"), - w32.WS_DISABLED, - w32.CW_USEDEFAULT, - w32.CW_USEDEFAULT, - 0, - 0, - 0, - 0, - w32.GetModuleHandle(""), - nil) - - m.mainThreadID, _ = w32.GetWindowThreadProcessId(m.mainThreadWindowHWND) -} - -func (m *windowsApp) runMainLoop() int { - runtime.LockOSThread() - defer runtime.UnlockOSThread() - if m.invokeRequired() { - panic("invokeRequired for runMainLoop, the mainloop must be running on the same OSThread as the mainThreadWindow has been created on") - } - - msg := (*w32.MSG)(unsafe.Pointer(w32.GlobalAlloc(0, uint32(unsafe.Sizeof(w32.MSG{}))))) - defer w32.GlobalFree(w32.HGLOBAL(unsafe.Pointer(msg))) - - for w32.GetMessage(msg, 0, 0, 0) != 0 { - w32.TranslateMessage(msg) - w32.DispatchMessage(msg) - } - - return int(msg.WParam) -} - -func (m *windowsApp) dispatchOnMainThread(id uint) { - mainThreadHWND := m.mainThreadWindowHWND - if mainThreadHWND == 0 { - panic("initMainLoop was not called") - } - - runtime.LockOSThread() - defer runtime.UnlockOSThread() - if m.invokeRequired() { - w32.PostMessage(mainThreadHWND, wmInvokeCallback, uintptr(id), 0) - } else { - mainThreadFunctionStoreLock.Lock() - fn := mainThreadFunctionStore[id] - delete(mainThreadFunctionStore, id) - mainThreadFunctionStoreLock.Unlock() - - if fn == nil { - Fatal("dispatchOnMainThread called with invalid id: %v", id) - } - fn() - } -} - -func (m *windowsApp) invokeRequired() bool { - mainThreadID := m.mainThreadID - if mainThreadID == 0 { - panic("initMainLoop was not called") - } - - return mainThreadID != w32.GetCurrentThreadId() -} - -func (m *windowsApp) invokeCallback(wParam, lParam uintptr) { - // TODO: Should we invoke just one or all queued? In v2 we always invoked all pendings... - runtime.LockOSThread() - defer runtime.UnlockOSThread() - if m.invokeRequired() { - panic("invokeCallback must always be called on the MainOSThread") - } - - mainThreadFunctionStoreLock.Lock() - fnIDs := make([]uint, 0, len(mainThreadFunctionStore)) - for id := range mainThreadFunctionStore { - fnIDs = append(fnIDs, id) - } - sort.Slice(fnIDs, func(i, j int) bool { return fnIDs[i] < fnIDs[j] }) - - fns := make([]func(), len(fnIDs)) - for i, id := range fnIDs { - fns[i] = mainThreadFunctionStore[id] - delete(mainThreadFunctionStore, id) - } - mainThreadFunctionStoreLock.Unlock() - - for _, fn := range fns { - fn() - } -} diff --git a/v3/pkg/application/menu.go b/v3/pkg/application/menu.go deleted file mode 100644 index 96a971da1..000000000 --- a/v3/pkg/application/menu.go +++ /dev/null @@ -1,233 +0,0 @@ -package application - -type menuImpl interface { - update() -} - -type ContextMenu struct { - *Menu - name string -} - -func NewContextMenu(name string) *ContextMenu { - result := &ContextMenu{ - Menu: NewMenu(), - name: name, - } - result.Update() - return result -} - -func (m *ContextMenu) Update() { - m.Menu.Update() - globalApplication.ContextMenu.Add(m.name, m) -} - -func (m *ContextMenu) Destroy() { - globalApplication.ContextMenu.Remove(m.name) -} - -type Menu struct { - items []*MenuItem - label string - - impl menuImpl -} - -func NewMenu() *Menu { - return &Menu{} -} - -func (m *Menu) Add(label string) *MenuItem { - result := NewMenuItem(label) - m.items = append(m.items, result) - return result -} - -func (m *Menu) AddSeparator() { - result := NewMenuItemSeparator() - m.items = append(m.items, result) -} - -func (m *Menu) AddCheckbox(label string, enabled bool) *MenuItem { - result := NewMenuItemCheckbox(label, enabled) - m.items = append(m.items, result) - return result -} - -func (m *Menu) AddRadio(label string, enabled bool) *MenuItem { - result := NewMenuItemRadio(label, enabled) - m.items = append(m.items, result) - return result -} - -func (m *Menu) Update() { - m.processRadioGroups() - if m.impl == nil { - m.impl = newMenuImpl(m) - } - m.impl.update() -} - -// Clear all menu items -func (m *Menu) Clear() { - for _, item := range m.items { - removeMenuItemByID(item.id) - } - m.items = nil -} - -func (m *Menu) Destroy() { - for _, item := range m.items { - item.Destroy() - } - m.items = nil -} - -func (m *Menu) AddSubmenu(s string) *Menu { - result := NewSubMenuItem(s) - m.items = append(m.items, result) - return result.submenu -} - -func (m *Menu) AddRole(role Role) *Menu { - result := NewRole(role) - if result != nil { - m.items = append(m.items, result) - } - return m -} - -func (m *Menu) processRadioGroups() { - var radioGroup []*MenuItem - - closeOutRadioGroups := func() { - if len(radioGroup) > 0 { - for _, item := range radioGroup { - item.radioGroupMembers = radioGroup - } - radioGroup = []*MenuItem{} - } - } - - for _, item := range m.items { - if item.itemType != radio { - closeOutRadioGroups() - } - if item.itemType == submenu { - item.submenu.processRadioGroups() - continue - } - if item.itemType == radio { - radioGroup = append(radioGroup, item) - } - } - closeOutRadioGroups() -} - -func (m *Menu) SetLabel(label string) { - m.label = label -} - -func (m *Menu) setContextData(data *ContextMenuData) { - for _, item := range m.items { - item.setContextData(data) - } -} - -// FindByLabel recursively searches for a menu item with the given label -// and returns the first match, or nil if not found. -func (m *Menu) FindByLabel(label string) *MenuItem { - for _, item := range m.items { - if item.label == label { - return item - } - if item.submenu != nil { - found := item.submenu.FindByLabel(label) - if found != nil { - return found - } - } - } - return nil -} - -// FindByRole recursively searches for a menu item with the given role -// and returns the first match, or nil if not found. -func (m *Menu) FindByRole(role Role) *MenuItem { - for _, item := range m.items { - if item.role == role { - return item - } - if item.submenu != nil { - found := item.submenu.FindByRole(role) - if found != nil { - return found - } - } - } - return nil -} - -func (m *Menu) RemoveMenuItem(target *MenuItem) { - for i, item := range m.items { - if item == target { - // Remove the item from the slice - m.items = append(m.items[:i], m.items[i+1:]...) - break - } - if item.submenu != nil { - item.submenu.RemoveMenuItem(target) - } - } -} - -// ItemAt returns the menu item at the given index, or nil if the index is out of bounds. -func (m *Menu) ItemAt(index int) *MenuItem { - if index < 0 || index >= len(m.items) { - return nil - } - return m.items[index] -} - -// Clone recursively clones the menu and all its submenus. -func (m *Menu) Clone() *Menu { - result := &Menu{ - label: m.label, - } - for _, item := range m.items { - result.items = append(result.items, item.Clone()) - } - return result -} - -// Append menu to an existing menu -func (m *Menu) Append(in *Menu) { - if in == nil { - return - } - m.items = append(m.items, in.items...) -} - -// Prepend menu before an existing menu -func (m *Menu) Prepend(in *Menu) { - m.items = append(in.items, m.items...) -} - -func (a *App) NewMenu() *Menu { - return a.Menu.New() -} - -func NewMenuFromItems(item *MenuItem, items ...*MenuItem) *Menu { - result := &Menu{ - items: []*MenuItem{item}, - } - result.items = append(result.items, items...) - return result -} - -func NewSubmenu(s string, items *Menu) *MenuItem { - result := NewSubMenuItem(s) - result.submenu = items - return result -} diff --git a/v3/pkg/application/menu_android.go b/v3/pkg/application/menu_android.go deleted file mode 100644 index 8bb4a48d1..000000000 --- a/v3/pkg/application/menu_android.go +++ /dev/null @@ -1,26 +0,0 @@ -//go:build android - -package application - -// Android menu stubs - Android doesn't have traditional application menus - -func (m *Menu) handleStyleChange() {} - -type androidMenu struct { - menu *Menu -} - -func newMenuImpl(menu *Menu) *androidMenu { - return &androidMenu{ - menu: menu, - } -} - -func (m *androidMenu) update() { - // Android doesn't have traditional menus -} - -func defaultApplicationMenu() *Menu { - // No application menu on Android - return nil -} diff --git a/v3/pkg/application/menu_darwin.go b/v3/pkg/application/menu_darwin.go deleted file mode 100644 index 1a6e4a8d6..000000000 --- a/v3/pkg/application/menu_darwin.go +++ /dev/null @@ -1,135 +0,0 @@ -//go:build darwin && !ios && !server - -package application - -/* -#cgo CFLAGS: -mmacosx-version-min=10.10 -x objective-c -#cgo LDFLAGS: -framework Cocoa - -#include "menuitem_darwin.h" - -extern void setMenuItemChecked(void*, unsigned int, bool); -extern void setMenuItemBitmap(void*, unsigned char*, int); - -// Clear and release all menu items in the menu -void clearMenu(void* nsMenu) { - NSMenu *menu = (NSMenu *)nsMenu; - [menu removeAllItems]; -} - - -// Create a new NSMenu -void* createNSMenu(char* label) { - NSMenu *menu = [[NSMenu alloc] init]; - if( label != NULL && strlen(label) > 0 ) { - menu.title = [NSString stringWithUTF8String:label]; - free(label); - } - [menu setAutoenablesItems:NO]; - return (void*)menu; -} - -void addMenuItem(void* nsMenu, void* nsMenuItem) { - NSMenu *menu = (NSMenu *)nsMenu; - [menu addItem:nsMenuItem]; -} - -// add seperator to menu -void addMenuSeparator(void* nsMenu) { - NSMenu *menu = (NSMenu *)nsMenu; - [menu addItem:[NSMenuItem separatorItem]]; -} - -// Set the submenu of a menu item -void setMenuItemSubmenu(void* nsMenuItem, void* nsMenu) { - NSMenuItem *menuItem = (NSMenuItem *)nsMenuItem; - NSMenu *menu = (NSMenu *)nsMenu; - [menuItem setSubmenu:menu]; -} - -// Add services menu -static void addServicesMenu(void* menu) { - NSMenu *nsMenu = (__bridge NSMenu *)menu; - [NSApp setServicesMenu:nsMenu]; -} - -// Add windows menu -void addWindowsMenu(void* menu) { - NSMenu *nsMenu = (__bridge NSMenu *)menu; - [NSApp setWindowsMenu:nsMenu]; -} - - -*/ -import "C" -import "unsafe" - -type macosMenu struct { - menu *Menu - - nsMenu unsafe.Pointer -} - -func newMenuImpl(menu *Menu) *macosMenu { - result := &macosMenu{ - menu: menu, - } - return result -} - -func (m *macosMenu) update() { - InvokeSync(func() { - if m.nsMenu == nil { - m.nsMenu = C.createNSMenu(C.CString(m.menu.label)) - } else { - C.clearMenu(m.nsMenu) - } - m.processMenu(m.nsMenu, m.menu) - }) -} - -func (m *macosMenu) processMenu(parent unsafe.Pointer, menu *Menu) { - for _, item := range menu.items { - switch item.itemType { - case submenu: - submenu := item.submenu - nsSubmenu := C.createNSMenu(C.CString(item.label)) - m.processMenu(nsSubmenu, submenu) - menuItem := newMenuItemImpl(item) - item.impl = menuItem - C.addMenuItem(parent, menuItem.nsMenuItem) - C.setMenuItemSubmenu(menuItem.nsMenuItem, nsSubmenu) - if item.role == ServicesMenu { - C.addServicesMenu(nsSubmenu) - } - if item.role == WindowMenu { - C.addWindowsMenu(nsSubmenu) - } - case text, checkbox, radio: - menuItem := newMenuItemImpl(item) - item.impl = menuItem - if item.hidden { - menuItem.setHidden(true) - } - C.addMenuItem(parent, menuItem.nsMenuItem) - case separator: - C.addMenuSeparator(parent) - } - if item.bitmap != nil { - macMenuItem := item.impl.(*macosMenuItem) - C.setMenuItemBitmap(macMenuItem.nsMenuItem, (*C.uchar)(&item.bitmap[0]), C.int(len(item.bitmap))) - } - - } -} - -func DefaultApplicationMenu() *Menu { - menu := NewMenu() - menu.AddRole(AppMenu) - menu.AddRole(FileMenu) - menu.AddRole(EditMenu) - menu.AddRole(ViewMenu) - menu.AddRole(WindowMenu) - menu.AddRole(HelpMenu) - return menu -} diff --git a/v3/pkg/application/menu_internal_test.go b/v3/pkg/application/menu_internal_test.go deleted file mode 100644 index 488e9a520..000000000 --- a/v3/pkg/application/menu_internal_test.go +++ /dev/null @@ -1,403 +0,0 @@ -package application - -import ( - "testing" -) - -func TestNewMenu(t *testing.T) { - menu := NewMenu() - if menu == nil { - t.Fatal("NewMenu returned nil") - } - if menu.items != nil { - t.Error("items should be nil initially") - } -} - -func TestMenu_Add(t *testing.T) { - menu := NewMenu() - - item := menu.Add("Test Item") - if item == nil { - t.Fatal("Add returned nil") - } - if item.label != "Test Item" { - t.Errorf("label = %q, want %q", item.label, "Test Item") - } - if len(menu.items) != 1 { - t.Errorf("items count = %d, want 1", len(menu.items)) - } - - // Clean up - menu.Destroy() -} - -func TestMenu_AddSeparator(t *testing.T) { - menu := NewMenu() - - menu.AddSeparator() - if len(menu.items) != 1 { - t.Errorf("items count = %d, want 1", len(menu.items)) - } - if menu.items[0].itemType != separator { - t.Error("item should be a separator") - } - - // Clean up - menu.Destroy() -} - -func TestMenu_AddCheckbox(t *testing.T) { - menu := NewMenu() - - item := menu.AddCheckbox("Check Me", true) - if item == nil { - t.Fatal("AddCheckbox returned nil") - } - if item.label != "Check Me" { - t.Errorf("label = %q, want %q", item.label, "Check Me") - } - if item.itemType != checkbox { - t.Error("item should be a checkbox") - } - if !item.checked { - t.Error("checkbox should be checked") - } - - // Clean up - menu.Destroy() -} - -func TestMenu_AddRadio(t *testing.T) { - menu := NewMenu() - - item := menu.AddRadio("Radio Option", false) - if item == nil { - t.Fatal("AddRadio returned nil") - } - if item.label != "Radio Option" { - t.Errorf("label = %q, want %q", item.label, "Radio Option") - } - if item.itemType != radio { - t.Error("item should be a radio") - } - if item.checked { - t.Error("radio should not be checked") - } - - // Clean up - menu.Destroy() -} - -func TestMenu_AddSubmenu(t *testing.T) { - menu := NewMenu() - - subMenu := menu.AddSubmenu("Submenu") - if subMenu == nil { - t.Fatal("AddSubmenu returned nil") - } - if len(menu.items) != 1 { - t.Errorf("items count = %d, want 1", len(menu.items)) - } - if menu.items[0].itemType != submenu { - t.Error("item should be a submenu") - } - - // Clean up - menu.Destroy() -} - -func TestMenu_SetLabel(t *testing.T) { - menu := NewMenu() - - menu.SetLabel("My Menu") - if menu.label != "My Menu" { - t.Errorf("label = %q, want %q", menu.label, "My Menu") - } -} - -func TestMenu_ItemAt(t *testing.T) { - menu := NewMenu() - menu.Add("Item 0") - menu.Add("Item 1") - menu.Add("Item 2") - - item := menu.ItemAt(1) - if item == nil { - t.Fatal("ItemAt returned nil") - } - if item.label != "Item 1" { - t.Errorf("label = %q, want %q", item.label, "Item 1") - } - - // Clean up - menu.Destroy() -} - -func TestMenu_ItemAt_OutOfBounds(t *testing.T) { - menu := NewMenu() - menu.Add("Item") - - if menu.ItemAt(-1) != nil { - t.Error("ItemAt(-1) should return nil") - } - if menu.ItemAt(1) != nil { - t.Error("ItemAt(1) should return nil for single item menu") - } - if menu.ItemAt(100) != nil { - t.Error("ItemAt(100) should return nil") - } - - // Clean up - menu.Destroy() -} - -func TestMenu_FindByLabel(t *testing.T) { - menu := NewMenu() - menu.Add("First") - menu.Add("Second") - menu.Add("Third") - - found := menu.FindByLabel("Second") - if found == nil { - t.Fatal("FindByLabel returned nil") - } - if found.label != "Second" { - t.Errorf("label = %q, want %q", found.label, "Second") - } - - // Clean up - menu.Destroy() -} - -func TestMenu_FindByLabel_NotFound(t *testing.T) { - menu := NewMenu() - menu.Add("First") - - found := menu.FindByLabel("NonExistent") - if found != nil { - t.Error("FindByLabel should return nil for non-existent label") - } - - // Clean up - menu.Destroy() -} - -func TestMenu_FindByLabel_InSubmenu(t *testing.T) { - menu := NewMenu() - submenu := menu.AddSubmenu("Submenu") - submenu.Add("Nested Item") - - found := menu.FindByLabel("Nested Item") - if found == nil { - t.Fatal("FindByLabel should find item in submenu") - } - if found.label != "Nested Item" { - t.Errorf("label = %q, want %q", found.label, "Nested Item") - } - - // Clean up - menu.Destroy() -} - -func TestMenu_RemoveMenuItem(t *testing.T) { - menu := NewMenu() - item1 := menu.Add("First") - item2 := menu.Add("Second") - menu.Add("Third") - - menu.RemoveMenuItem(item2) - if len(menu.items) != 2 { - t.Errorf("items count = %d, want 2", len(menu.items)) - } - if menu.FindByLabel("Second") != nil { - t.Error("Second item should be removed") - } - - // Clean up - removeMenuItemByID(item1.id) -} - -func TestMenu_Clear(t *testing.T) { - menu := NewMenu() - menu.Add("First") - menu.Add("Second") - menu.Add("Third") - - menu.Clear() - if menu.items != nil { - t.Error("items should be nil after Clear") - } -} - -func TestMenu_Append(t *testing.T) { - menu1 := NewMenu() - menu1.Add("Item 1") - - menu2 := NewMenu() - menu2.Add("Item 2") - menu2.Add("Item 3") - - menu1.Append(menu2) - if len(menu1.items) != 3 { - t.Errorf("items count = %d, want 3", len(menu1.items)) - } - - // Clean up - menu1.Destroy() -} - -func TestMenu_Append_Nil(t *testing.T) { - menu := NewMenu() - menu.Add("Item") - - menu.Append(nil) - if len(menu.items) != 1 { - t.Error("Append(nil) should not change menu") - } - - // Clean up - menu.Destroy() -} - -func TestMenu_Prepend(t *testing.T) { - menu1 := NewMenu() - menu1.Add("Item 3") - - menu2 := NewMenu() - menu2.Add("Item 1") - menu2.Add("Item 2") - - menu1.Prepend(menu2) - if len(menu1.items) != 3 { - t.Errorf("items count = %d, want 3", len(menu1.items)) - } - if menu1.items[0].label != "Item 1" { - t.Errorf("First item should be 'Item 1', got %q", menu1.items[0].label) - } - - // Clean up - menu1.Destroy() -} - -func TestMenu_Clone(t *testing.T) { - menu := NewMenu() - menu.SetLabel("Original Menu") - menu.Add("Item 1") - menu.Add("Item 2") - - clone := menu.Clone() - if clone == menu { - t.Error("Clone should return different pointer") - } - if clone.label != menu.label { - t.Error("Clone should have same label") - } - if len(clone.items) != len(menu.items) { - t.Error("Clone should have same number of items") - } - - // Clean up - menu.Destroy() - clone.Destroy() -} - -func TestNewMenuFromItems(t *testing.T) { - item1 := NewMenuItem("Item 1") - item2 := NewMenuItem("Item 2") - item3 := NewMenuItem("Item 3") - - menu := NewMenuFromItems(item1, item2, item3) - if menu == nil { - t.Fatal("NewMenuFromItems returned nil") - } - if len(menu.items) != 3 { - t.Errorf("items count = %d, want 3", len(menu.items)) - } - - // Clean up - menu.Destroy() -} - -func TestNewSubmenu(t *testing.T) { - items := NewMenu() - items.Add("Sub Item 1") - items.Add("Sub Item 2") - - item := NewSubmenu("My Submenu", items) - if item == nil { - t.Fatal("NewSubmenu returned nil") - } - if item.label != "My Submenu" { - t.Errorf("label = %q, want %q", item.label, "My Submenu") - } - if item.submenu != items { - t.Error("submenu should be the provided menu") - } - - // Clean up - removeMenuItemByID(item.id) -} - -func TestMenu_ProcessRadioGroups(t *testing.T) { - menu := NewMenu() - - // Add some non-radio items - menu.Add("Regular Item") - - // Add a group of radio items - radio1 := menu.AddRadio("Radio 1", true) - radio2 := menu.AddRadio("Radio 2", false) - radio3 := menu.AddRadio("Radio 3", false) - - // Add separator to end the group - menu.AddSeparator() - - // Add another group - radio4 := menu.AddRadio("Radio A", true) - radio5 := menu.AddRadio("Radio B", false) - - // Process radio groups - menu.processRadioGroups() - - // First group should be linked - if len(radio1.radioGroupMembers) != 3 { - t.Errorf("First group should have 3 members, got %d", len(radio1.radioGroupMembers)) - } - if len(radio2.radioGroupMembers) != 3 { - t.Errorf("radio2 should have 3 members, got %d", len(radio2.radioGroupMembers)) - } - if len(radio3.radioGroupMembers) != 3 { - t.Errorf("radio3 should have 3 members, got %d", len(radio3.radioGroupMembers)) - } - - // Second group should be linked - if len(radio4.radioGroupMembers) != 2 { - t.Errorf("Second group should have 2 members, got %d", len(radio4.radioGroupMembers)) - } - if len(radio5.radioGroupMembers) != 2 { - t.Errorf("radio5 should have 2 members, got %d", len(radio5.radioGroupMembers)) - } - - // Clean up - menu.Destroy() -} - -func TestMenu_SetContextData(t *testing.T) { - menu := NewMenu() - menu.Add("Item 1") - menu.Add("Item 2") - - data := &ContextMenuData{Data: "test-data"} - menu.setContextData(data) - - // Verify data was set on items - for _, item := range menu.items { - if item.contextMenuData != data { - t.Error("Context data should be set on all items") - } - } - - // Clean up - menu.Destroy() -} diff --git a/v3/pkg/application/menu_ios.go b/v3/pkg/application/menu_ios.go deleted file mode 100644 index f5f7dcbb0..000000000 --- a/v3/pkg/application/menu_ios.go +++ /dev/null @@ -1,24 +0,0 @@ -//go:build ios - -package application - -// iOS menu stubs - iOS doesn't have traditional menus - -// iOS doesn't have traditional menus like desktop platforms -// These are placeholder implementations - -func (m *Menu) handleStyleChange() {} - -type iosMenu struct { - menu *Menu -} - -func newMenuImpl(menu *Menu) *iosMenu { - return &iosMenu{ - menu: menu, - } -} - -func (m *iosMenu) update() { - // iOS doesn't have traditional menus -} \ No newline at end of file diff --git a/v3/pkg/application/menu_linux.go b/v3/pkg/application/menu_linux.go deleted file mode 100644 index ac413db02..000000000 --- a/v3/pkg/application/menu_linux.go +++ /dev/null @@ -1,121 +0,0 @@ -//go:build linux && !android && !gtk4 && !server - -package application - -type linuxMenu struct { - menu *Menu - native pointer -} - -func newMenuImpl(menu *Menu) *linuxMenu { - result := &linuxMenu{ - menu: menu, - native: menuBarNew(), - } - return result -} - -func (m *linuxMenu) run() { - m.update() -} - -func (m *linuxMenu) update() { - m.processMenu(m.menu) -} - -func (m *linuxMenu) processMenu(menu *Menu) { - if menu.impl == nil { - menu.impl = &linuxMenu{ - menu: menu, - native: menuNew(), - } - } else { - // Clear existing menu items before rebuilding (prevents appending on Update()) - menuClear(menu) - } - var currentRadioGroup GSListPointer - - for _, item := range menu.items { - // drop the group if we have run out of radio items - if item.itemType != radio { - currentRadioGroup = nilRadioGroup - } - - switch item.itemType { - case submenu: - menuItem := newMenuItemImpl(item) - item.impl = menuItem - m.processMenu(item.submenu) - m.addSubMenuToItem(item.submenu, item) - m.addMenuItem(menu, item) - case text, checkbox: - menuItem := newMenuItemImpl(item) - item.impl = menuItem - m.addMenuItem(menu, item) - case radio: - menuItem := newRadioItemImpl(item, currentRadioGroup) - item.impl = menuItem - m.addMenuItem(menu, item) - currentRadioGroup = menuGetRadioGroup(menuItem) - case separator: - m.addMenuSeparator(menu) - } - - } - - for _, item := range menu.items { - if item.callback != nil { - m.attachHandler(item) - } - } - -} - -func (m *linuxMenu) attachHandler(item *MenuItem) { - (item.impl).(*linuxMenuItem).handlerId = attachMenuHandler(item) -} - -func (m *linuxMenu) addSubMenuToItem(menu *Menu, item *MenuItem) { - if menu.impl == nil { - menu.impl = &linuxMenu{ - menu: menu, - native: menuNew(), - } - } - menuSetSubmenu(item, menu) -} - -func (m *linuxMenu) addMenuItem(parent *Menu, menu *MenuItem) { - menuAppend(parent, menu) -} - -func (m *linuxMenu) addMenuSeparator(menu *Menu) { - menuAddSeparator(menu) - -} - -func (m *linuxMenu) addServicesMenu(menu *Menu) { - // FIXME: Should this be required? -} - -func (l *linuxMenu) createMenu(name string, items []*MenuItem) *Menu { - impl := newMenuImpl(&Menu{label: name}) - menu := &Menu{ - label: name, - items: items, - impl: impl, - } - impl.menu = menu - return menu -} - -func DefaultApplicationMenu() *Menu { - menu := NewMenu() - menu.AddRole(AppMenu) - menu.AddRole(FileMenu) - menu.AddRole(EditMenu) - menu.AddRole(ViewMenu) - menu.AddRole(WindowMenu) - menu.AddRole(HelpMenu) - return menu -} diff --git a/v3/pkg/application/menu_linux_gtk4.go b/v3/pkg/application/menu_linux_gtk4.go deleted file mode 100644 index e5bee364f..000000000 --- a/v3/pkg/application/menu_linux_gtk4.go +++ /dev/null @@ -1,181 +0,0 @@ -//go:build linux && !android && gtk4 - -package application - -type linuxMenu struct { - menu *Menu - native pointer - processed bool -} - -func newMenuImpl(menu *Menu) *linuxMenu { - result := &linuxMenu{ - menu: menu, - native: menuBarNew(), - } - return result -} - -func (m *linuxMenu) run() { - m.update() -} - -func (m *linuxMenu) update() { - m.processMenu(m.menu) -} - -var radioGroupCounter uint = 0 - -func (m *linuxMenu) processMenu(menu *Menu) { - if menu.impl == nil { - menu.impl = &linuxMenu{ - menu: menu, - native: menuNew(), - } - } - - impl := menu.impl.(*linuxMenu) - if impl.processed { - // Menu already processed, skip re-processing to avoid duplicates - return - } - impl.processed = true - - var currentRadioGroup uint = 0 - var checkedRadioId uint = 0 - - hasSeparators := false - for _, item := range menu.items { - if item.itemType == separator { - hasSeparators = true - break - } - } - - // GMenu uses sections for visual separators - // Only use sections if the menu has separators - var currentSection pointer - var hasSectionItems bool - if hasSeparators { - currentSection = menuNewSection() - hasSectionItems = false - } - - for _, item := range menu.items { - if item.itemType != radio { - currentRadioGroup = 0 - checkedRadioId = 0 - } - - switch item.itemType { - case submenu: - menuItem := newMenuItemImpl(item) - item.impl = menuItem - m.processMenu(item.submenu) - m.addSubMenuToItem(item.submenu, item) - if hasSeparators { - m.addMenuItemToSection(currentSection, item) - hasSectionItems = true - } else { - m.addMenuItem(menu, item) - } - case text: - menuItem := newMenuItemImpl(item) - item.impl = menuItem - if hasSeparators { - m.addMenuItemToSection(currentSection, item) - hasSectionItems = true - } else { - m.addMenuItem(menu, item) - } - case checkbox: - menuItem := newCheckMenuItemImpl(item) - item.impl = menuItem - if hasSeparators { - m.addMenuItemToSection(currentSection, item) - hasSectionItems = true - } else { - m.addMenuItem(menu, item) - } - case radio: - if currentRadioGroup == 0 { - radioGroupCounter++ - currentRadioGroup = radioGroupCounter - } - if item.checked { - checkedRadioId = item.id - } - menuItem := newRadioMenuItemImpl(item, currentRadioGroup, checkedRadioId) - item.impl = menuItem - if hasSeparators { - m.addMenuItemToSection(currentSection, item) - hasSectionItems = true - } else { - m.addMenuItem(menu, item) - } - case separator: - if hasSectionItems { - menuAppendSection(menu, currentSection) - currentSection = menuNewSection() - hasSectionItems = false - } - } - } - - if hasSeparators && hasSectionItems { - menuAppendSection(menu, currentSection) - } - - for _, item := range menu.items { - if item.callback != nil { - m.attachHandler(item) - } - } -} - -func (m *linuxMenu) attachHandler(item *MenuItem) { - (item.impl).(*linuxMenuItem).handlerId = attachMenuHandler(item) -} - -func (m *linuxMenu) addSubMenuToItem(menu *Menu, item *MenuItem) { - if menu.impl == nil { - menu.impl = &linuxMenu{ - menu: menu, - native: menuNew(), - } - } - menuSetSubmenu(item, menu) -} - -func (m *linuxMenu) addMenuItem(parent *Menu, item *MenuItem) { - menuAppend(parent, item, item.hidden) -} - -func (m *linuxMenu) addMenuItemToSection(section pointer, item *MenuItem) { - menuAppendItemToSection(section, item) -} - -func (m *linuxMenu) addServicesMenu(menu *Menu) { -} - -func (l *linuxMenu) createMenu(name string, items []*MenuItem) *Menu { - impl := newMenuImpl(&Menu{label: name}) - menu := &Menu{ - label: name, - items: items, - impl: impl, - } - impl.menu = menu - return menu -} - -func DefaultApplicationMenu() *Menu { - menu := NewMenu() - menu.AddRole(AppMenu) - menu.AddRole(FileMenu) - menu.AddRole(EditMenu) - menu.AddRole(ViewMenu) - menu.AddRole(WindowMenu) - menu.AddRole(HelpMenu) - return menu -} diff --git a/v3/pkg/application/menu_manager.go b/v3/pkg/application/menu_manager.go deleted file mode 100644 index 4c3a36c83..000000000 --- a/v3/pkg/application/menu_manager.go +++ /dev/null @@ -1,55 +0,0 @@ -package application - -// MenuManager manages menu-related operations -type MenuManager struct { - app *App -} - -// newMenuManager creates a new MenuManager instance -func newMenuManager(app *App) *MenuManager { - return &MenuManager{ - app: app, - } -} - -// Set sets the application menu -func (mm *MenuManager) Set(menu *Menu) { - mm.SetApplicationMenu(menu) -} - -// SetApplicationMenu sets the application menu -func (mm *MenuManager) SetApplicationMenu(menu *Menu) { - mm.app.applicationMenu = menu - if mm.app.impl != nil { - mm.app.impl.setApplicationMenu(menu) - } -} - -// GetApplicationMenu returns the current application menu -func (mm *MenuManager) GetApplicationMenu() *Menu { - return mm.app.applicationMenu -} - -// New creates a new menu -func (mm *MenuManager) New() *Menu { - return &Menu{} -} - -// ShowAbout shows the about dialog -func (mm *MenuManager) ShowAbout() { - if mm.app.impl != nil { - mm.app.impl.showAboutDialog(mm.app.options.Name, mm.app.options.Description, mm.app.options.Icon) - } -} - -// handleMenuItemClicked handles menu item click events (internal use) -func (mm *MenuManager) handleMenuItemClicked(menuItemID uint) { - defer handlePanic() - - menuItem := getMenuItemByID(menuItemID) - if menuItem == nil { - mm.app.warning("MenuItem #%d not found", menuItemID) - return - } - menuItem.handleClick() -} diff --git a/v3/pkg/application/menu_test.go b/v3/pkg/application/menu_test.go deleted file mode 100644 index 88aeb5724..000000000 --- a/v3/pkg/application/menu_test.go +++ /dev/null @@ -1,140 +0,0 @@ -package application_test - -import ( - "testing" - - "github.com/wailsapp/wails/v3/pkg/application" -) - -func TestMenu_FindByLabel(t *testing.T) { - tests := []struct { - name string - menu *application.Menu - label string - shouldError bool - }{ - { - name: "Find top-level item", - menu: application.NewMenuFromItems( - application.NewMenuItem("Target"), - ), - label: "Target", - shouldError: false, - }, - { - name: "Find item in submenu", - menu: application.NewMenuFromItems( - application.NewMenuItem("Item 1"), - application.NewSubmenu("Submenu", application.NewMenuFromItems( - application.NewMenuItem("Subitem 1"), - application.NewMenuItem("Target"), - )), - ), - label: "Target", - shouldError: false, - }, - { - name: "Not find item", - menu: application.NewMenuFromItems( - application.NewMenuItem("Item 1"), - application.NewSubmenu("Submenu", application.NewMenuFromItems( - application.NewMenuItem("Subitem 1"), - application.NewMenuItem("Target"), - )), - ), - label: "Random", - shouldError: true, - }, - } - - for _, test := range tests { - t.Run(test.name, func(t *testing.T) { - found := test.menu.FindByLabel(test.label) - if test.shouldError && found != nil { - t.Errorf("Expected error, but found %v", found) - } - if !test.shouldError && found == nil { - t.Errorf("Expected item, but found none") - } - }) - } -} - -func TestMenu_ItemAt(t *testing.T) { - tests := []struct { - name string - menu *application.Menu - index int - shouldError bool - }{ - { - name: "Valid index", - menu: application.NewMenuFromItems( - application.NewMenuItem("Item 1"), - application.NewMenuItem("Item 2"), - application.NewMenuItem("Target"), - ), - index: 2, - shouldError: false, - }, - { - name: "Index out of bounds (negative)", - menu: application.NewMenuFromItems( - application.NewMenuItem("Item 1"), - application.NewMenuItem("Item 2"), - ), - index: -1, - shouldError: true, - }, - { - name: "Index out of bounds (too large)", - menu: application.NewMenuFromItems( - application.NewMenuItem("Item 1"), - application.NewMenuItem("Item 2"), - ), - index: 2, - shouldError: true, - }, - } - - for _, test := range tests { - t.Run(test.name, func(t *testing.T) { - item := test.menu.ItemAt(test.index) - if test.shouldError && item != nil { - t.Errorf("Expected error, but found %v", item) - } - if !test.shouldError && item == nil { - t.Errorf("Expected item, but found none") - } - }) - } -} - -func TestMenu_RemoveMenuItem(t *testing.T) { - itemToRemove := application.NewMenuItem("Target") - itemToKeep := application.NewMenuItem("Item 1") - - tests := []struct { - name string - menu *application.Menu - item *application.MenuItem - shouldFind bool - }{ - { - name: "Remove existing item", - menu: application.NewMenuFromItems(itemToKeep, itemToRemove), - item: itemToRemove, - shouldFind: false, - }, - } - - for _, test := range tests { - t.Run(test.name, func(t *testing.T) { - test.menu.RemoveMenuItem(test.item) - found := test.menu.FindByLabel(test.item.Label()) - if !test.shouldFind && found != nil { - t.Errorf("Expected item to be removed, but found %v", found) - } - }) - } -} diff --git a/v3/pkg/application/menu_windows.go b/v3/pkg/application/menu_windows.go deleted file mode 100644 index 758fae985..000000000 --- a/v3/pkg/application/menu_windows.go +++ /dev/null @@ -1,142 +0,0 @@ -//go:build windows && !server - -package application - -import ( - "github.com/wailsapp/wails/v3/pkg/w32" -) - -type windowsMenu struct { - menu *Menu - parentWindow *windowsWebviewWindow - - hWnd w32.HWND - hMenu w32.HMENU - currentMenuID int - menuMapping map[int]*MenuItem - checkboxItems []*Menu -} - -func newMenuImpl(menu *Menu) *windowsMenu { - result := &windowsMenu{ - menu: menu, - menuMapping: make(map[int]*MenuItem), - } - - return result -} - -func (w *windowsMenu) update() { - if w.hMenu != 0 { - w32.DestroyMenu(w.hMenu) - } - w.hMenu = w32.NewPopupMenu() - w.processMenu(w.hMenu, w.menu) -} - -func (w *windowsMenu) processMenu(parentMenu w32.HMENU, inputMenu *Menu) { - for _, item := range inputMenu.items { - w.currentMenuID++ - itemID := w.currentMenuID - w.menuMapping[itemID] = item - - menuItemImpl := newMenuItemImpl(item, parentMenu, itemID) - menuItemImpl.parent = inputMenu - item.impl = menuItemImpl - - if item.Hidden() { - if item.accelerator != nil && item.callback != nil { - if w.parentWindow != nil { - w.parentWindow.parent.removeMenuBinding(item.accelerator) - } else { - globalApplication.KeyBinding.Remove(item.accelerator.String()) - } - } - } - - flags := uint32(w32.MF_STRING) - if item.disabled { - flags = flags | w32.MF_GRAYED - } - if item.checked { - flags = flags | w32.MF_CHECKED - } - if item.IsSeparator() { - flags = flags | w32.MF_SEPARATOR - } - if item.itemType == radio { - flags = flags | w32.MFT_RADIOCHECK - } - - if item.submenu != nil { - flags = flags | w32.MF_POPUP - newSubmenu := w32.CreateMenu() - w.processMenu(newSubmenu, item.submenu) - itemID = int(newSubmenu) - } - - thisText := item.Label() - if item.accelerator != nil && item.callback != nil { - if w.parentWindow != nil { - w.parentWindow.parent.addMenuBinding(item.accelerator, item) - } else { - globalApplication.KeyBinding.Add(item.accelerator.String(), func(w Window) { - item.handleClick() - }) - } - thisText = thisText + "\t" + item.accelerator.String() - } - var menuText = w32.MustStringToUTF16Ptr(thisText) - - // If the item is hidden, don't append - if item.Hidden() { - continue - } - - w32.AppendMenu(parentMenu, flags, uintptr(itemID), menuText) - if item.bitmap != nil { - if err := w32.SetMenuIcons(parentMenu, itemID, item.bitmap, nil); err != nil { - globalApplication.fatal("error setting menu icons: %w", err) - } - } - } -} - -func (w *windowsMenu) ShowAtCursor() { - InvokeSync(func() { - x, y, ok := w32.GetCursorPos() - if !ok { - return - } - w.ShowAt(x, y) - }) -} - -func (w *windowsMenu) ShowAt(x int, y int) { - w.update() - w32.TrackPopupMenuEx(w.hMenu, - w32.TPM_LEFTALIGN, - int32(x), - int32(y), - w.hWnd, - nil) - w32.PostMessage(w.hWnd, w32.WM_NULL, 0, 0) -} - -func (w *windowsMenu) ProcessCommand(cmdMsgID int) { - item := w.menuMapping[cmdMsgID] - if item == nil { - return - } - item.handleClick() -} - -func DefaultApplicationMenu() *Menu { - menu := NewMenu() - menu.AddRole(FileMenu) - menu.AddRole(EditMenu) - menu.AddRole(ViewMenu) - menu.AddRole(WindowMenu) - menu.AddRole(HelpMenu) - return menu -} diff --git a/v3/pkg/application/menuitem.go b/v3/pkg/application/menuitem.go deleted file mode 100644 index 5d11a87c7..000000000 --- a/v3/pkg/application/menuitem.go +++ /dev/null @@ -1,456 +0,0 @@ -package application - -import ( - "sync" - "sync/atomic" -) - -type menuItemType int - -const ( - text menuItemType = iota - separator - checkbox - radio - submenu -) - -var menuItemID uintptr -var menuItemMap = make(map[uint]*MenuItem) -var menuItemMapLock sync.Mutex - -func addToMenuItemMap(menuItem *MenuItem) { - menuItemMapLock.Lock() - menuItemMap[menuItem.id] = menuItem - menuItemMapLock.Unlock() -} - -func getMenuItemByID(id uint) *MenuItem { - menuItemMapLock.Lock() - defer menuItemMapLock.Unlock() - return menuItemMap[id] -} - -func removeMenuItemByID(id uint) { - menuItemMapLock.Lock() - defer menuItemMapLock.Unlock() - delete(menuItemMap, id) -} - -type menuItemImpl interface { - setTooltip(s string) - setLabel(s string) - setDisabled(disabled bool) - setChecked(checked bool) - setAccelerator(accelerator *accelerator) - setHidden(hidden bool) - setBitmap(bitmap []byte) - destroy() -} - -type MenuItem struct { - id uint - label string - tooltip string - disabled bool - checked bool - hidden bool - bitmap []byte - submenu *Menu - callback func(*Context) - itemType menuItemType - accelerator *accelerator - role Role - contextMenuData *ContextMenuData - - impl menuItemImpl - radioGroupMembers []*MenuItem -} - -func NewMenuItem(label string) *MenuItem { - result := &MenuItem{ - id: uint(atomic.AddUintptr(&menuItemID, 1)), - label: label, - itemType: text, - } - addToMenuItemMap(result) - return result -} - -func NewMenuItemSeparator() *MenuItem { - result := &MenuItem{ - id: uint(atomic.AddUintptr(&menuItemID, 1)), - itemType: separator, - } - return result -} - -func NewMenuItemCheckbox(label string, checked bool) *MenuItem { - result := &MenuItem{ - id: uint(atomic.AddUintptr(&menuItemID, 1)), - label: label, - checked: checked, - itemType: checkbox, - } - addToMenuItemMap(result) - return result -} - -func NewMenuItemRadio(label string, checked bool) *MenuItem { - result := &MenuItem{ - id: uint(atomic.AddUintptr(&menuItemID, 1)), - label: label, - checked: checked, - itemType: radio, - } - addToMenuItemMap(result) - return result -} - -func NewSubMenuItem(label string) *MenuItem { - result := &MenuItem{ - id: uint(atomic.AddUintptr(&menuItemID, 1)), - label: label, - itemType: submenu, - submenu: &Menu{ - label: label, - }, - } - addToMenuItemMap(result) - return result -} - -func NewRole(role Role) *MenuItem { - var result *MenuItem - switch role { - case AppMenu: - result = NewAppMenu() - case EditMenu: - result = NewEditMenu() - case FileMenu: - result = NewFileMenu() - case ViewMenu: - result = NewViewMenu() - case ServicesMenu: - return NewServicesMenu() - case SpeechMenu: - result = NewSpeechMenu() - case WindowMenu: - result = NewWindowMenu() - case HelpMenu: - result = NewHelpMenu() - case Hide: - result = NewHideMenuItem() - case Front: - result = NewFrontMenuItem() - case HideOthers: - result = NewHideOthersMenuItem() - case UnHide: - result = NewUnhideMenuItem() - case Undo: - result = NewUndoMenuItem() - case Redo: - result = NewRedoMenuItem() - case Cut: - result = NewCutMenuItem() - case Copy: - result = NewCopyMenuItem() - case Paste: - result = NewPasteMenuItem() - case PasteAndMatchStyle: - result = NewPasteAndMatchStyleMenuItem() - case SelectAll: - result = NewSelectAllMenuItem() - case Delete: - result = NewDeleteMenuItem() - case Quit: - result = NewQuitMenuItem() - case CloseWindow: - result = NewCloseMenuItem() - case About: - result = NewAboutMenuItem() - case Reload: - result = NewReloadMenuItem() - case ForceReload: - result = NewForceReloadMenuItem() - case ToggleFullscreen: - result = NewToggleFullscreenMenuItem() - case OpenDevTools: - result = NewOpenDevToolsMenuItem() - case ResetZoom: - result = NewZoomResetMenuItem() - case ZoomIn: - result = NewZoomInMenuItem() - case ZoomOut: - result = NewZoomOutMenuItem() - case Minimise: - result = NewMinimiseMenuItem() - case Zoom: - result = NewZoomMenuItem() - case FullScreen: - result = NewFullScreenMenuItem() - case Print: - result = NewPrintMenuItem() - case PageLayout: - result = NewPageLayoutMenuItem() - case NoRole: - case ShowAll: - result = NewShowAllMenuItem() - case BringAllToFront: - result = NewBringAllToFrontMenuItem() - case NewFile: - result = NewNewFileMenuItem() - case Open: - result = NewOpenMenuItem() - case Save: - result = NewSaveMenuItem() - case SaveAs: - result = NewSaveAsMenuItem() - case StartSpeaking: - result = NewStartSpeakingMenuItem() - case StopSpeaking: - result = NewStopSpeakingMenuItem() - case Revert: - result = NewRevertMenuItem() - case Find: - result = NewFindMenuItem() - case FindAndReplace: - result = NewFindAndReplaceMenuItem() - case FindNext: - result = NewFindNextMenuItem() - case FindPrevious: - result = NewFindPreviousMenuItem() - case Help: - result = NewHelpMenuItem() - - default: - globalApplication.error("no support for role: %v", role) - } - - if result != nil { - result.role = role - } - - return result -} - -func NewServicesMenu() *MenuItem { - serviceMenu := NewSubMenuItem("Services") - serviceMenu.role = ServicesMenu - return serviceMenu -} - -func (m *MenuItem) handleClick() { - var ctx = newContext(). - withClickedMenuItem(m). - withContextMenuData(m.contextMenuData) - if m.itemType == checkbox { - m.checked = !m.checked - ctx.withChecked(m.checked) - if m.impl != nil { - m.impl.setChecked(m.checked) - } - } - if m.itemType == radio { - for _, member := range m.radioGroupMembers { - member.checked = false - if member.impl != nil { - member.impl.setChecked(false) - } - } - m.checked = true - ctx.withChecked(true) - if m.impl != nil { - m.impl.setChecked(true) - } - } - if m.callback != nil { - go func() { - defer handlePanic() - m.callback(ctx) - }() - } -} - -func (m *MenuItem) SetAccelerator(shortcut string) *MenuItem { - accelerator, err := parseAccelerator(shortcut) - if err != nil { - globalApplication.error("invalid accelerator: %w", err) - return m - } - m.accelerator = accelerator - if m.impl != nil { - m.impl.setAccelerator(accelerator) - } - return m -} - -func (m *MenuItem) GetAccelerator() string { - if m.accelerator == nil { - return "" - } - return m.accelerator.String() -} - -func (m *MenuItem) RemoveAccelerator() { - m.accelerator = nil -} - -func (m *MenuItem) SetTooltip(s string) *MenuItem { - m.tooltip = s - if m.impl != nil { - m.impl.setTooltip(s) - } - return m -} - -func (m *MenuItem) SetRole(role Role) *MenuItem { - m.role = role - return m -} - -func (m *MenuItem) SetLabel(s string) *MenuItem { - m.label = s - if m.impl != nil { - m.impl.setLabel(s) - } - return m -} - -func (m *MenuItem) SetEnabled(enabled bool) *MenuItem { - m.disabled = !enabled - if m.impl != nil { - m.impl.setDisabled(m.disabled) - } - return m -} - -func (m *MenuItem) SetBitmap(bitmap []byte) *MenuItem { - m.bitmap = bitmap - if m.impl != nil { - m.impl.setBitmap(bitmap) - } - return m -} - -func (m *MenuItem) SetChecked(checked bool) *MenuItem { - m.checked = checked - if m.impl != nil { - m.impl.setChecked(m.checked) - } - return m -} - -func (m *MenuItem) SetHidden(hidden bool) *MenuItem { - m.hidden = hidden - if m.impl != nil { - m.impl.setHidden(m.hidden) - } - return m -} - -// GetSubmenu returns the submenu of the MenuItem. -// If the MenuItem is not a submenu, it returns nil. -func (m *MenuItem) GetSubmenu() *Menu { - return m.submenu -} - -func (m *MenuItem) Checked() bool { - return m.checked -} - -func (m *MenuItem) IsSeparator() bool { - return m.itemType == separator -} - -func (m *MenuItem) IsSubmenu() bool { - return m.itemType == submenu -} - -func (m *MenuItem) IsCheckbox() bool { - return m.itemType == checkbox -} - -func (m *MenuItem) IsRadio() bool { - return m.itemType == radio -} - -func (m *MenuItem) Hidden() bool { - return m.hidden -} - -func (m *MenuItem) OnClick(f func(*Context)) *MenuItem { - m.callback = f - return m -} - -func (m *MenuItem) Label() string { - return m.label -} - -func (m *MenuItem) Tooltip() string { - return m.tooltip -} - -func (m *MenuItem) Enabled() bool { - return !m.disabled -} - -func (m *MenuItem) setContextData(data *ContextMenuData) { - m.contextMenuData = data - if m.submenu != nil { - m.submenu.setContextData(data) - } -} - -// Clone returns a deep copy of the MenuItem -func (m *MenuItem) Clone() *MenuItem { - result := &MenuItem{ - id: m.id, - label: m.label, - tooltip: m.tooltip, - disabled: m.disabled, - checked: m.checked, - hidden: m.hidden, - bitmap: m.bitmap, - callback: m.callback, - itemType: m.itemType, - role: m.role, - } - if m.submenu != nil { - result.submenu = m.submenu.Clone() - } - if m.accelerator != nil { - result.accelerator = m.accelerator.clone() - } - if m.contextMenuData != nil { - result.contextMenuData = m.contextMenuData.clone() - } - return result -} - -func (m *MenuItem) Destroy() { - - removeMenuItemByID(m.id) - - // Clean up resources - if m.impl != nil { - m.impl.destroy() - } - if m.submenu != nil { - m.submenu.Destroy() - m.submenu = nil - } - - if m.contextMenuData != nil { - m.contextMenuData = nil - } - - if m.accelerator != nil { - m.accelerator = nil - } - - m.callback = nil - m.radioGroupMembers = nil - -} diff --git a/v3/pkg/application/menuitem_android.go b/v3/pkg/application/menuitem_android.go deleted file mode 100644 index 0c78d1cf8..000000000 --- a/v3/pkg/application/menuitem_android.go +++ /dev/null @@ -1,24 +0,0 @@ -//go:build android - -package application - -import "unsafe" - -// Android doesn't have traditional menu items like desktop platforms -// These are placeholder implementations - -func (m *MenuItem) handleStyleChange() {} - -func (m *MenuItem) handleLabelChange() {} - -func (m *MenuItem) handleCheckedChange() {} - -func (m *MenuItem) handleEnabledChange() {} - -func (m *MenuItem) handleTooltipChange() {} - -func (m *MenuItem) handleSubmenuChange() {} - -func (m *MenuItem) nativeMenuItem() unsafe.Pointer { - return nil -} diff --git a/v3/pkg/application/menuitem_darwin.go b/v3/pkg/application/menuitem_darwin.go deleted file mode 100644 index 953a73804..000000000 --- a/v3/pkg/application/menuitem_darwin.go +++ /dev/null @@ -1,388 +0,0 @@ -//go:build darwin && !ios - -package application - -/* -#cgo CFLAGS: -mmacosx-version-min=10.13 -x objective-c -#cgo LDFLAGS: -framework Cocoa -framework WebKit - -#include "Cocoa/Cocoa.h" -#include "menuitem_darwin.h" -#include "application_darwin.h" - -#define unicode(input) [NSString stringWithFormat:@"%C", input] - -// Create menu item -void* newMenuItem(unsigned int menuItemID, char *label, bool disabled, char* tooltip, char* selector) { - MenuItem *menuItem = [MenuItem new]; - - // Label - menuItem.title = [NSString stringWithUTF8String:label]; - - // Always set the action regardless of disabled state - if (selector != NULL) { - menuItem.action = NSSelectorFromString([NSString stringWithUTF8String:selector]); - menuItem.target = disabled ? nil : nil; // Role-based actions always use responder chain - } else { - menuItem.action = @selector(handleClick); - menuItem.target = disabled ? nil : menuItem; // Custom callbacks need target=menuItem when enabled - } - menuItem.menuItemID = menuItemID; - - menuItem.enabled = !disabled; - - // Tooltip - if( tooltip != NULL ) { - menuItem.toolTip = [NSString stringWithUTF8String:tooltip]; - free(tooltip); - } - - // Set the tag - [menuItem setTag:menuItemID]; - - return (void*)menuItem; -} - -// set menu item label -void setMenuItemLabel(void* nsMenuItem, char *label) { - dispatch_async(dispatch_get_main_queue(), ^{ - MenuItem *menuItem = (MenuItem *)nsMenuItem; - menuItem.title = [NSString stringWithUTF8String:label]; - free(label); - }); -} - -// set menu item disabled -void setMenuItemDisabled(void* nsMenuItem, bool disabled) { - dispatch_async(dispatch_get_main_queue(), ^{ - MenuItem *menuItem = (MenuItem *)nsMenuItem; - [menuItem setEnabled:!disabled]; - // Handle target based on whether item uses custom selector or handleClick - if( disabled ) { - [menuItem setTarget:nil]; - } else { - // Check if this menu item uses a custom selector (role-based) - // by checking if the action is handleClick or something else - if ([menuItem action] == @selector(handleClick)) { - // This is a custom callback menu item, set target to self - [menuItem setTarget:menuItem]; - } else { - // This is a role-based menu item, target should be nil - // to allow the action to be sent up the responder chain - [menuItem setTarget:nil]; - } - } - }); -} - -// set menu item hidden -void setMenuItemHidden(void* nsMenuItem, bool hidden) { - dispatch_async(dispatch_get_main_queue(), ^{ - MenuItem *menuItem = (MenuItem *)nsMenuItem; - [menuItem setHidden:hidden]; - }); -} - -// set menu item tooltip -void setMenuItemTooltip(void* nsMenuItem, char *tooltip) { - dispatch_async(dispatch_get_main_queue(), ^{ - MenuItem *menuItem = (MenuItem *)nsMenuItem; - menuItem.toolTip = [NSString stringWithUTF8String:tooltip]; - free(tooltip); - }); -} - -// Check menu item -void setMenuItemChecked(void* nsMenuItem, bool checked) { - dispatch_async(dispatch_get_main_queue(), ^{ - MenuItem *menuItem = (MenuItem *)nsMenuItem; - menuItem.state = checked ? NSControlStateValueOn : NSControlStateValueOff; - }); -} - -NSString* translateKey(NSString* key) { - - // Guard against no accelerator key - if( key == NULL ) { - return @""; - } - - if( [key isEqualToString:@"backspace"] ) { - return unicode(0x0008); - } - if( [key isEqualToString:@"tab"] ) { - return unicode(0x0009); - } - if( [key isEqualToString:@"return"] ) { - return unicode(0x000d); - } - if( [key isEqualToString:@"enter"] ) { - return unicode(0x000d); - } - if( [key isEqualToString:@"escape"] ) { - return unicode(0x001b); - } - if( [key isEqualToString:@"left"] ) { - return unicode(0xf702); - } - if( [key isEqualToString:@"right"] ) { - return unicode(0xf703); - } - if( [key isEqualToString:@"up"] ) { - return unicode(0xf700); - } - if( [key isEqualToString:@"down"] ) { - return unicode(0xf701); - } - if( [key isEqualToString:@"space"] ) { - return unicode(0x0020); - } - if( [key isEqualToString:@"delete"] ) { - return unicode(0x007f); - } - if( [key isEqualToString:@"home"] ) { - return unicode(0x2196); - } - if( [key isEqualToString:@"end"] ) { - return unicode(0x2198); - } - if( [key isEqualToString:@"page up"] ) { - return unicode(0x21de); - } - if( [key isEqualToString:@"page down"] ) { - return unicode(0x21df); - } - if( [key isEqualToString:@"f1"] ) { - return unicode(0xf704); - } - if( [key isEqualToString:@"f2"] ) { - return unicode(0xf705); - } - if( [key isEqualToString:@"f3"] ) { - return unicode(0xf706); - } - if( [key isEqualToString:@"f4"] ) { - return unicode(0xf707); - } - if( [key isEqualToString:@"f5"] ) { - return unicode(0xf708); - } - if( [key isEqualToString:@"f6"] ) { - return unicode(0xf709); - } - if( [key isEqualToString:@"f7"] ) { - return unicode(0xf70a); - } - if( [key isEqualToString:@"f8"] ) { - return unicode(0xf70b); - } - if( [key isEqualToString:@"f9"] ) { - return unicode(0xf70c); - } - if( [key isEqualToString:@"f10"] ) { - return unicode(0xf70d); - } - if( [key isEqualToString:@"f11"] ) { - return unicode(0xf70e); - } - if( [key isEqualToString:@"f12"] ) { - return unicode(0xf70f); - } - if( [key isEqualToString:@"f13"] ) { - return unicode(0xf710); - } - if( [key isEqualToString:@"f14"] ) { - return unicode(0xf711); - } - if( [key isEqualToString:@"f15"] ) { - return unicode(0xf712); - } - if( [key isEqualToString:@"f16"] ) { - return unicode(0xf713); - } - if( [key isEqualToString:@"f17"] ) { - return unicode(0xf714); - } - if( [key isEqualToString:@"f18"] ) { - return unicode(0xf715); - } - if( [key isEqualToString:@"f19"] ) { - return unicode(0xf716); - } - if( [key isEqualToString:@"f20"] ) { - return unicode(0xf717); - } - if( [key isEqualToString:@"f21"] ) { - return unicode(0xf718); - } - if( [key isEqualToString:@"f22"] ) { - return unicode(0xf719); - } - if( [key isEqualToString:@"f23"] ) { - return unicode(0xf71a); - } - if( [key isEqualToString:@"f24"] ) { - return unicode(0xf71b); - } - if( [key isEqualToString:@"f25"] ) { - return unicode(0xf71c); - } - if( [key isEqualToString:@"f26"] ) { - return unicode(0xf71d); - } - if( [key isEqualToString:@"f27"] ) { - return unicode(0xf71e); - } - if( [key isEqualToString:@"f28"] ) { - return unicode(0xf71f); - } - if( [key isEqualToString:@"f29"] ) { - return unicode(0xf720); - } - if( [key isEqualToString:@"f30"] ) { - return unicode(0xf721); - } - if( [key isEqualToString:@"f31"] ) { - return unicode(0xf722); - } - if( [key isEqualToString:@"f32"] ) { - return unicode(0xf723); - } - if( [key isEqualToString:@"f33"] ) { - return unicode(0xf724); - } - if( [key isEqualToString:@"f34"] ) { - return unicode(0xf725); - } - if( [key isEqualToString:@"f35"] ) { - return unicode(0xf726); - } - if( [key isEqualToString:@"numLock"] ) { - return unicode(0xf739); - } - return key; -} - -// Set the menuitem key equivalent -void setMenuItemKeyEquivalent(void* nsMenuItem, char *key, int modifier) { - MenuItem *menuItem = (MenuItem *)nsMenuItem; - NSString *nskey = [NSString stringWithUTF8String:key]; - menuItem.keyEquivalent = translateKey(nskey); - menuItem.keyEquivalentModifierMask = modifier; - free(key); -} - -// Call the copy selector on the pasteboard -static void copyToPasteboard(char *text) { - NSPasteboard *pasteboard = [NSPasteboard generalPasteboard]; - [pasteboard clearContents]; - [pasteboard setString:[NSString stringWithUTF8String:text] forType:NSPasteboardTypeString]; -} - -// Call the paste selector on the pasteboard -static char *pasteFromPasteboard(void) { - NSPasteboard *pasteboard = [NSPasteboard generalPasteboard]; - NSString *text = [pasteboard stringForType:NSPasteboardTypeString]; - if( text == nil ) { - return NULL; - } - return strdup([text UTF8String]); -} - -void performSelectorOnMainThreadForFirstResponder(SEL selector) { - NSWindow *activeWindow = [[NSApplication sharedApplication] keyWindow]; - if (activeWindow) { - [activeWindow performSelectorOnMainThread:selector withObject:nil waitUntilDone:YES]; - } -} - -void setMenuItemBitmap(void* nsMenuItem, unsigned char *bitmap, int length) { - MenuItem *menuItem = (MenuItem *)nsMenuItem; - NSImage *image = [[NSImage alloc] initWithData:[NSData dataWithBytes:bitmap length:length]]; - [menuItem setImage:image]; -} - -void destroyMenuItem(void* nsMenuItem) { - MenuItem *menuItem = (MenuItem *)nsMenuItem; - [menuItem release]; -} -*/ -import "C" -import ( - "unsafe" -) - -type macosMenuItem struct { - menuItem *MenuItem - - nsMenuItem unsafe.Pointer -} - -func (m macosMenuItem) setTooltip(tooltip string) { - C.setMenuItemTooltip(m.nsMenuItem, C.CString(tooltip)) -} - -func (m macosMenuItem) setLabel(s string) { - C.setMenuItemLabel(m.nsMenuItem, C.CString(s)) -} - -func (m macosMenuItem) setDisabled(disabled bool) { - C.setMenuItemDisabled(m.nsMenuItem, C.bool(disabled)) -} - -func (m macosMenuItem) setChecked(checked bool) { - C.setMenuItemChecked(m.nsMenuItem, C.bool(checked)) -} - -func (m macosMenuItem) setHidden(hidden bool) { - C.setMenuItemHidden(m.nsMenuItem, C.bool(hidden)) -} - -func (m macosMenuItem) setBitmap(bitmap []byte) { - C.setMenuItemBitmap(m.nsMenuItem, (*C.uchar)(&bitmap[0]), C.int(len(bitmap))) -} - -func (m macosMenuItem) setAccelerator(accelerator *accelerator) { - // Set the keyboard shortcut of the menu item - var modifier C.int - var key *C.char - if accelerator != nil { - modifier = C.int(toMacModifier(accelerator.Modifiers)) - key = C.CString(accelerator.Key) - } - - // Convert the key to a string - C.setMenuItemKeyEquivalent(m.nsMenuItem, key, modifier) -} - -func (m macosMenuItem) destroy() { - C.destroyMenuItem(m.nsMenuItem) -} - -func newMenuItemImpl(item *MenuItem) *macosMenuItem { - result := &macosMenuItem{ - menuItem: item, - } - - selector := getSelectorForRole(item.role) - if selector != nil { - defer C.free(unsafe.Pointer(selector)) - } - result.nsMenuItem = unsafe.Pointer(C.newMenuItem( - C.uint(item.id), - C.CString(item.label), - C.bool(item.disabled), - C.CString(item.tooltip), - selector, - )) - - switch item.itemType { - case checkbox, radio: - C.setMenuItemChecked(result.nsMenuItem, C.bool(item.checked)) - } - - if item.accelerator != nil { - result.setAccelerator(item.accelerator) - } - return result -} diff --git a/v3/pkg/application/menuitem_darwin.h b/v3/pkg/application/menuitem_darwin.h deleted file mode 100644 index 8260d4dfd..000000000 --- a/v3/pkg/application/menuitem_darwin.h +++ /dev/null @@ -1,17 +0,0 @@ -#ifndef MenuItemDelegate_h -#define MenuItemDelegate_h - -#import - -extern void processMenuItemClick(unsigned int); - -@interface MenuItem : NSMenuItem - -@property unsigned int menuItemID; - -- (void) handleClick; - -@end - - -#endif /* MenuItemDelegate_h */ diff --git a/v3/pkg/application/menuitem_darwin.m b/v3/pkg/application/menuitem_darwin.m deleted file mode 100644 index 5eeb9707d..000000000 --- a/v3/pkg/application/menuitem_darwin.m +++ /dev/null @@ -1,13 +0,0 @@ -//go:build darwin && !ios - -#import - -#import "menuitem_darwin.h" - -@implementation MenuItem - -- (void) handleClick { - processMenuItemClick(self.menuItemID); -} - -@end diff --git a/v3/pkg/application/menuitem_dev.go b/v3/pkg/application/menuitem_dev.go deleted file mode 100644 index 4ce99fd66..000000000 --- a/v3/pkg/application/menuitem_dev.go +++ /dev/null @@ -1,14 +0,0 @@ -//go:build !production || devtools - -package application - -func NewOpenDevToolsMenuItem() *MenuItem { - return NewMenuItem("Open Developer Tools"). - SetAccelerator("Alt+Command+I"). - OnClick(func(ctx *Context) { - currentWindow := globalApplication.Window.Current() - if currentWindow != nil { - currentWindow.OpenDevTools() - } - }) -} diff --git a/v3/pkg/application/menuitem_internal_test.go b/v3/pkg/application/menuitem_internal_test.go deleted file mode 100644 index 12843d4c8..000000000 --- a/v3/pkg/application/menuitem_internal_test.go +++ /dev/null @@ -1,413 +0,0 @@ -package application - -import ( - "testing" -) - -func TestMenuItemType_Constants(t *testing.T) { - // Verify menu item type constants are distinct - if text != 0 { - t.Error("text should be 0") - } - if separator != 1 { - t.Error("separator should be 1") - } - if checkbox != 2 { - t.Error("checkbox should be 2") - } - if radio != 3 { - t.Error("radio should be 3") - } - if submenu != 4 { - t.Error("submenu should be 4") - } -} - -func TestNewMenuItem(t *testing.T) { - item := NewMenuItem("Test Label") - - if item == nil { - t.Fatal("NewMenuItem returned nil") - } - if item.label != "Test Label" { - t.Errorf("label = %q, want %q", item.label, "Test Label") - } - if item.itemType != text { - t.Error("itemType should be text") - } - if item.id == 0 { - t.Error("id should be non-zero") - } - - // Clean up - removeMenuItemByID(item.id) -} - -func TestNewMenuItemSeparator(t *testing.T) { - item := NewMenuItemSeparator() - - if item == nil { - t.Fatal("NewMenuItemSeparator returned nil") - } - if item.itemType != separator { - t.Error("itemType should be separator") - } -} - -func TestNewMenuItemCheckbox(t *testing.T) { - item := NewMenuItemCheckbox("Checkbox", true) - - if item == nil { - t.Fatal("NewMenuItemCheckbox returned nil") - } - if item.label != "Checkbox" { - t.Errorf("label = %q, want %q", item.label, "Checkbox") - } - if item.itemType != checkbox { - t.Error("itemType should be checkbox") - } - if !item.checked { - t.Error("checked should be true") - } - - // Clean up - removeMenuItemByID(item.id) -} - -func TestNewMenuItemCheckbox_Unchecked(t *testing.T) { - item := NewMenuItemCheckbox("Unchecked", false) - - if item.checked { - t.Error("checked should be false") - } - - // Clean up - removeMenuItemByID(item.id) -} - -func TestNewMenuItemRadio(t *testing.T) { - item := NewMenuItemRadio("Radio", true) - - if item == nil { - t.Fatal("NewMenuItemRadio returned nil") - } - if item.label != "Radio" { - t.Errorf("label = %q, want %q", item.label, "Radio") - } - if item.itemType != radio { - t.Error("itemType should be radio") - } - if !item.checked { - t.Error("checked should be true") - } - - // Clean up - removeMenuItemByID(item.id) -} - -func TestNewSubMenuItem(t *testing.T) { - item := NewSubMenuItem("Submenu") - - if item == nil { - t.Fatal("NewSubMenuItem returned nil") - } - if item.label != "Submenu" { - t.Errorf("label = %q, want %q", item.label, "Submenu") - } - if item.itemType != submenu { - t.Error("itemType should be submenu") - } - if item.submenu == nil { - t.Error("submenu should not be nil") - } - if item.submenu.label != "Submenu" { - t.Errorf("submenu.label = %q, want %q", item.submenu.label, "Submenu") - } - - // Clean up - removeMenuItemByID(item.id) -} - -func TestMenuItemMap_AddGetRemove(t *testing.T) { - item := NewMenuItem("Test") - id := item.id - - // Item should be in map - retrieved := getMenuItemByID(id) - if retrieved != item { - t.Error("getMenuItemByID should return the same item") - } - - // Remove item - removeMenuItemByID(id) - - // Item should be gone - retrieved = getMenuItemByID(id) - if retrieved != nil { - t.Error("getMenuItemByID should return nil after removal") - } -} - -func TestGetMenuItemByID_NotFound(t *testing.T) { - result := getMenuItemByID(999999) - if result != nil { - t.Error("getMenuItemByID should return nil for non-existent ID") - } -} - -func TestMenuItem_UniqueIDs(t *testing.T) { - item1 := NewMenuItem("Item 1") - item2 := NewMenuItem("Item 2") - item3 := NewMenuItem("Item 3") - - if item1.id == item2.id || item2.id == item3.id || item1.id == item3.id { - t.Error("Menu items should have unique IDs") - } - - // Clean up - removeMenuItemByID(item1.id) - removeMenuItemByID(item2.id) - removeMenuItemByID(item3.id) -} - -func TestMenuItem_Label(t *testing.T) { - item := NewMenuItem("Original") - - if item.Label() != "Original" { - t.Errorf("Label() = %q, want %q", item.Label(), "Original") - } - - item.SetLabel("Updated") - if item.label != "Updated" { - t.Errorf("label = %q, want %q", item.label, "Updated") - } - - // Clean up - removeMenuItemByID(item.id) -} - -func TestMenuItem_Enabled(t *testing.T) { - item := NewMenuItem("Test") - - if item.disabled { - t.Error("disabled should default to false") - } - - item.SetEnabled(false) - if !item.disabled { - t.Error("disabled should be true after SetEnabled(false)") - } - - item.SetEnabled(true) - if item.disabled { - t.Error("disabled should be false after SetEnabled(true)") - } - - // Clean up - removeMenuItemByID(item.id) -} - -func TestMenuItem_Checked(t *testing.T) { - item := NewMenuItemCheckbox("Test", false) - - if item.checked { - t.Error("checked should be false") - } - - item.SetChecked(true) - if !item.checked { - t.Error("checked should be true after SetChecked(true)") - } - - item.SetChecked(false) - if item.checked { - t.Error("checked should be false after SetChecked(false)") - } - - // Clean up - removeMenuItemByID(item.id) -} - -func TestMenuItem_Hidden(t *testing.T) { - item := NewMenuItem("Test") - - if item.hidden { - t.Error("hidden should default to false") - } - - item.SetHidden(true) - if !item.hidden { - t.Error("hidden should be true after SetHidden(true)") - } - - item.SetHidden(false) - if item.hidden { - t.Error("hidden should be false after SetHidden(false)") - } - - // Clean up - removeMenuItemByID(item.id) -} - -func TestMenuItem_Tooltip(t *testing.T) { - item := NewMenuItem("Test") - - if item.tooltip != "" { - t.Error("tooltip should default to empty string") - } - - item.SetTooltip("Tooltip text") - if item.tooltip != "Tooltip text" { - t.Errorf("tooltip = %q, want %q", item.tooltip, "Tooltip text") - } - - // Clean up - removeMenuItemByID(item.id) -} - -func TestMenuItem_Bitmap(t *testing.T) { - item := NewMenuItem("Test") - - if item.bitmap != nil { - t.Error("bitmap should default to nil") - } - - bitmap := []byte{0x89, 0x50, 0x4E, 0x47} - item.SetBitmap(bitmap) - if len(item.bitmap) != 4 { - t.Error("bitmap should be set") - } - - // Clean up - removeMenuItemByID(item.id) -} - -func TestMenuItem_OnClick(t *testing.T) { - item := NewMenuItem("Test") - - if item.callback != nil { - t.Error("callback should default to nil") - } - - called := false - item.OnClick(func(ctx *Context) { - called = true - }) - - if item.callback == nil { - t.Error("callback should be set after OnClick") - } - - // Call the callback - item.callback(nil) - if !called { - t.Error("callback should have been called") - } - - // Clean up - removeMenuItemByID(item.id) -} - -func TestMenuItem_SetAccelerator(t *testing.T) { - item := NewMenuItem("Test") - - if item.accelerator != nil { - t.Error("accelerator should default to nil") - } - - result := item.SetAccelerator("Ctrl+A") - if result != item { - t.Error("SetAccelerator should return the same item for chaining") - } - - if item.accelerator == nil { - t.Error("accelerator should be set after SetAccelerator") - } - - // Clean up - removeMenuItemByID(item.id) -} - -func TestMenuItem_GetAccelerator(t *testing.T) { - item := NewMenuItem("Test") - - if item.GetAccelerator() != "" { - t.Error("GetAccelerator should return empty string when not set") - } - - item.SetAccelerator("Ctrl+B") - acc := item.GetAccelerator() - if acc == "" { - t.Error("GetAccelerator should return non-empty string when set") - } - - // Clean up - removeMenuItemByID(item.id) -} - -func TestMenuItem_RemoveAccelerator(t *testing.T) { - item := NewMenuItem("Test") - item.SetAccelerator("Ctrl+C") - - item.RemoveAccelerator() - if item.accelerator != nil { - t.Error("accelerator should be nil after RemoveAccelerator") - } - - // Clean up - removeMenuItemByID(item.id) -} - -func TestMenuItem_Clone(t *testing.T) { - original := NewMenuItem("Original") - original.SetTooltip("Tooltip") - original.SetChecked(true) - original.SetEnabled(false) - - clone := original.Clone() - - if clone == original { - t.Error("Clone should return a different pointer") - } - if clone.label != original.label { - t.Error("Clone should have same label") - } - if clone.tooltip != original.tooltip { - t.Error("Clone should have same tooltip") - } - if clone.checked != original.checked { - t.Error("Clone should have same checked state") - } - if clone.disabled != original.disabled { - t.Error("Clone should have same disabled state") - } - // Note: Clone preserves the ID (shallow clone behavior) - - // Clean up - removeMenuItemByID(original.id) - removeMenuItemByID(clone.id) -} - -func TestMenuItem_Chaining(t *testing.T) { - item := NewMenuItem("Test"). - SetTooltip("Tooltip"). - SetEnabled(false). - SetHidden(true). - SetAccelerator("Ctrl+X") - - if item.tooltip != "Tooltip" { - t.Error("Chaining SetTooltip failed") - } - if !item.disabled { - t.Error("Chaining SetEnabled failed") - } - if !item.hidden { - t.Error("Chaining SetHidden failed") - } - if item.accelerator == nil { - t.Error("Chaining SetAccelerator failed") - } - - // Clean up - removeMenuItemByID(item.id) -} diff --git a/v3/pkg/application/menuitem_ios.go b/v3/pkg/application/menuitem_ios.go deleted file mode 100644 index 31709fe96..000000000 --- a/v3/pkg/application/menuitem_ios.go +++ /dev/null @@ -1,24 +0,0 @@ -//go:build ios - -package application - -import "unsafe" - -// iOS doesn't have traditional menu items like desktop platforms -// These are placeholder implementations - -func (m *MenuItem) handleStyleChange() {} - -func (m *MenuItem) handleLabelChange() {} - -func (m *MenuItem) handleCheckedChange() {} - -func (m *MenuItem) handleEnabledChange() {} - -func (m *MenuItem) handleTooltipChange() {} - -func (m *MenuItem) handleSubmenuChange() {} - -func (m *MenuItem) nativeMenuItem() unsafe.Pointer { - return nil -} \ No newline at end of file diff --git a/v3/pkg/application/menuitem_linux.go b/v3/pkg/application/menuitem_linux.go deleted file mode 100644 index c52c5f3fc..000000000 --- a/v3/pkg/application/menuitem_linux.go +++ /dev/null @@ -1,436 +0,0 @@ -//go:build linux && !android && !gtk4 && !server - -package application - -import ( - "fmt" - "runtime" -) - -type linuxMenuItem struct { - menuItem *MenuItem - native pointer - handlerId uint -} - -func (l linuxMenuItem) setTooltip(tooltip string) { - InvokeSync(func() { - l.blockSignal() - defer l.unBlockSignal() - menuItemSetToolTip(l.native, tooltip) - }) -} - -func (l linuxMenuItem) destroy() { - InvokeSync(func() { - l.blockSignal() - defer l.unBlockSignal() - menuItemDestroy(l.native) - }) -} - -func (l linuxMenuItem) blockSignal() { - if l.handlerId != 0 { - menuItemSignalBlock(l.native, l.handlerId, true) - } -} -func (l linuxMenuItem) setBitmap(data []byte) { - InvokeSync(func() { - l.blockSignal() - defer l.unBlockSignal() - menuItemSetBitmap(l.native, data) - }) -} - -func (l linuxMenuItem) unBlockSignal() { - if l.handlerId != 0 { - menuItemSignalBlock(l.native, l.handlerId, false) - } -} - -func (l linuxMenuItem) setLabel(s string) { - InvokeSync(func() { - l.blockSignal() - defer l.unBlockSignal() - menuItemSetLabel(l.native, s) - }) -} - -func (l linuxMenuItem) isChecked() bool { - return menuItemChecked(l.native) -} - -func (l linuxMenuItem) setDisabled(disabled bool) { - InvokeSync(func() { - l.blockSignal() - defer l.unBlockSignal() - menuItemSetDisabled(l.native, disabled) - }) -} - -func (l linuxMenuItem) setChecked(checked bool) { - InvokeSync(func() { - l.blockSignal() - defer l.unBlockSignal() - menuItemSetChecked(l.native, checked) - }) -} - -func (l linuxMenuItem) setHidden(hidden bool) { - InvokeSync(func() { - l.blockSignal() - defer l.unBlockSignal() - widgetSetVisible(l.native, hidden) - }) -} - -func (l linuxMenuItem) setAccelerator(accelerator *accelerator) { - fmt.Println("setAccelerator", accelerator) - // Set the keyboard shortcut of the menu item - // var modifier C.int - // var key *C.char - if accelerator != nil { - // modifier = C.int(toMacModifier(accelerator.Modifiers)) - // key = C.CString(accelerator.Key) - } - - // Convert the key to a string - // C.setMenuItemKeyEquivalent(m.nsMenuItem, key, modifier) -} - -func newMenuItemImpl(item *MenuItem) *linuxMenuItem { - result := &linuxMenuItem{ - menuItem: item, - } - switch item.itemType { - case text: - result.native = menuItemNew(item.label, item.bitmap) - - case checkbox: - result.native = menuCheckItemNew(item.label, item.bitmap) - result.setChecked(item.checked) - if item.accelerator != nil { - result.setAccelerator(item.accelerator) - } - case submenu: - result.native = menuItemNew(item.label, item.bitmap) - - default: - panic(fmt.Sprintf("Unknown menu type: %v", item.itemType)) - } - result.setDisabled(result.menuItem.disabled) - return result -} - -func newRadioItemImpl(item *MenuItem, group GSListPointer) *linuxMenuItem { - result := &linuxMenuItem{ - menuItem: item, - native: menuRadioItemNew(group, item.label), - } - result.setChecked(item.checked) - result.setDisabled(result.menuItem.disabled) - return result -} - -func newSpeechMenu() *MenuItem { - speechMenu := NewMenu() - speechMenu.Add("Start Speaking"). - SetAccelerator("CmdOrCtrl+OptionOrAlt+Shift+."). - OnClick(func(ctx *Context) { - // C.startSpeaking() - }) - speechMenu.Add("Stop Speaking"). - SetAccelerator("CmdOrCtrl+OptionOrAlt+Shift+,"). - OnClick(func(ctx *Context) { - // C.stopSpeaking() - }) - subMenu := NewSubMenuItem("Speech") - subMenu.submenu = speechMenu - return subMenu -} - -func newFrontMenuItem() *MenuItem { - panic("implement me") -} - -func newHideMenuItem() *MenuItem { - return NewMenuItem("Hide " + globalApplication.options.Name). - SetAccelerator("CmdOrCtrl+h"). - OnClick(func(ctx *Context) { - - // C.hideApplication() - }) -} - -func newHideOthersMenuItem() *MenuItem { - return NewMenuItem("Hide Others"). - SetAccelerator("CmdOrCtrl+OptionOrAlt+h"). - OnClick(func(ctx *Context) { - // C.hideOthers() - }) -} - -func newUnhideMenuItem() *MenuItem { - return NewMenuItem("Show All"). - OnClick(func(ctx *Context) { - // C.showAll() - }) -} - -func newUndoMenuItem() *MenuItem { - return NewMenuItem("Undo"). - SetAccelerator("CmdOrCtrl+z"). - OnClick(func(ctx *Context) { - // C.undo() - }) -} - -// newRedoMenuItem creates a new menu item for redoing the last action -func newRedoMenuItem() *MenuItem { - return NewMenuItem("Redo"). - SetAccelerator("CmdOrCtrl+Shift+z"). - OnClick(func(ctx *Context) { - // C.redo() - }) -} - -func newCutMenuItem() *MenuItem { - return NewMenuItem("Cut"). - SetAccelerator("CmdOrCtrl+x"). - OnClick(func(ctx *Context) { - // C.cut() - }) -} - -func newCopyMenuItem() *MenuItem { - return NewMenuItem("Copy"). - SetAccelerator("CmdOrCtrl+c"). - OnClick(func(ctx *Context) { - // C.copy() - }) -} - -func newPasteMenuItem() *MenuItem { - return NewMenuItem("Paste"). - SetAccelerator("CmdOrCtrl+v"). - OnClick(func(ctx *Context) { - // C.paste() - }) -} - -func newPasteAndMatchStyleMenuItem() *MenuItem { - return NewMenuItem("Paste and Match Style"). - SetAccelerator("CmdOrCtrl+OptionOrAlt+Shift+v"). - OnClick(func(ctx *Context) { - // C.pasteAndMatchStyle() - }) -} - -func newDeleteMenuItem() *MenuItem { - return NewMenuItem("Delete"). - SetAccelerator("backspace"). - OnClick(func(ctx *Context) { - // C.delete() - }) -} - -func newQuitMenuItem() *MenuItem { - return NewMenuItem("Quit " + globalApplication.options.Name). - SetAccelerator("CmdOrCtrl+q"). - OnClick(func(ctx *Context) { - globalApplication.Quit() - }) -} - -func newSelectAllMenuItem() *MenuItem { - return NewMenuItem("Select All"). - SetAccelerator("CmdOrCtrl+a"). - OnClick(func(ctx *Context) { - // C.selectAll() - }) -} - -func newAboutMenuItem() *MenuItem { - return NewMenuItem("About " + globalApplication.options.Name). - OnClick(func(ctx *Context) { - globalApplication.Menu.ShowAbout() - }) -} - -func newCloseMenuItem() *MenuItem { - return NewMenuItem("Close"). - SetAccelerator("CmdOrCtrl+w"). - OnClick(func(ctx *Context) { - currentWindow := globalApplication.Window.Current() - if currentWindow != nil { - currentWindow.Close() - } - }) -} - -func newReloadMenuItem() *MenuItem { - return NewMenuItem("Reload"). - SetAccelerator("CmdOrCtrl+r"). - OnClick(func(ctx *Context) { - currentWindow := globalApplication.Window.Current() - if currentWindow != nil { - currentWindow.Reload() - } - }) -} - -func newForceReloadMenuItem() *MenuItem { - return NewMenuItem("Force Reload"). - SetAccelerator("CmdOrCtrl+Shift+r"). - OnClick(func(ctx *Context) { - currentWindow := globalApplication.Window.Current() - if currentWindow != nil { - currentWindow.ForceReload() - } - }) -} - -func newToggleFullscreenMenuItem() *MenuItem { - result := NewMenuItem("Toggle Full Screen"). - OnClick(func(ctx *Context) { - currentWindow := globalApplication.Window.Current() - if currentWindow != nil { - currentWindow.ToggleFullscreen() - } - }) - if runtime.GOOS == "darwin" { - result.SetAccelerator("Ctrl+Command+F") - } else { - result.SetAccelerator("F11") - } - return result -} - -func newZoomResetMenuItem() *MenuItem { - // reset zoom menu item - return NewMenuItem("Actual Size"). - SetAccelerator("CmdOrCtrl+0"). - OnClick(func(ctx *Context) { - currentWindow := globalApplication.Window.Current() - if currentWindow != nil { - currentWindow.ZoomReset() - } - }) -} - -func newZoomInMenuItem() *MenuItem { - return NewMenuItem("Zoom In"). - SetAccelerator("CmdOrCtrl+plus"). - OnClick(func(ctx *Context) { - currentWindow := globalApplication.Window.Current() - if currentWindow != nil { - currentWindow.ZoomIn() - } - }) -} - -func newZoomOutMenuItem() *MenuItem { - return NewMenuItem("Zoom Out"). - SetAccelerator("CmdOrCtrl+-"). - OnClick(func(ctx *Context) { - currentWindow := globalApplication.Window.Current() - if currentWindow != nil { - currentWindow.ZoomOut() - } - }) -} - -func newMinimizeMenuItem() *MenuItem { - return NewMenuItem("Minimize"). - SetAccelerator("CmdOrCtrl+M"). - OnClick(func(ctx *Context) { - currentWindow := globalApplication.Window.Current() - if currentWindow != nil { - currentWindow.Minimise() - } - }) -} - -func newZoomMenuItem() *MenuItem { - return NewMenuItem("Zoom"). - OnClick(func(ctx *Context) { - currentWindow := globalApplication.Window.Current() - if currentWindow != nil { - currentWindow.Zoom() - } - }) -} - -func newFullScreenMenuItem() *MenuItem { - return NewMenuItem("Fullscreen"). - OnClick(func(ctx *Context) { - currentWindow := globalApplication.Window.Current() - if currentWindow != nil { - currentWindow.Fullscreen() - } - }) -} - -func newPrintMenuItem() *MenuItem { - panic("Implement me") -} - -func newPageLayoutMenuItem() *MenuItem { - panic("Implement me") -} - -func newShowAllMenuItem() *MenuItem { - panic("Implement me") -} - -func newBringAllToFrontMenuItem() *MenuItem { - panic("Implement me") -} - -func newNewFileMenuItem() *MenuItem { - panic("Implement me") -} - -func newOpenMenuItem() *MenuItem { - panic("Implement me") -} - -func newSaveMenuItem() *MenuItem { - panic("Implement me") -} - -func newSaveAsMenuItem() *MenuItem { - panic("Implement me") -} - -func newStartSpeakingMenuItem() *MenuItem { - panic("Implement me") -} - -func newStopSpeakingMenuItem() *MenuItem { - panic("Implement me") -} - -func newRevertMenuItem() *MenuItem { - panic("Implement me") -} - -func newFindMenuItem() *MenuItem { - panic("Implement me") -} - -func newFindAndReplaceMenuItem() *MenuItem { - panic("Implement me") -} - -func newFindNextMenuItem() *MenuItem { - panic("Implement me") -} - -func newFindPreviousMenuItem() *MenuItem { - panic("Implement me") -} - -func newHelpMenuItem() *MenuItem { - panic("Implement me") -} diff --git a/v3/pkg/application/menuitem_linux_gtk4.go b/v3/pkg/application/menuitem_linux_gtk4.go deleted file mode 100644 index f0b08b85f..000000000 --- a/v3/pkg/application/menuitem_linux_gtk4.go +++ /dev/null @@ -1,399 +0,0 @@ -//go:build linux && !android && gtk4 - -package application - -import ( - "fmt" - "runtime" -) - -type linuxMenuItem struct { - menuItem *MenuItem - native pointer - handlerId uint - parentMenu pointer - menuIndex int - isHidden bool -} - -func (l linuxMenuItem) setTooltip(tooltip string) { - InvokeSync(func() { - menuItemSetToolTip(l.native, tooltip) - }) -} - -func (l linuxMenuItem) destroy() { - InvokeSync(func() { - menuItemDestroy(l.native) - }) -} - -func (l linuxMenuItem) blockSignal() { -} - -func (l linuxMenuItem) setBitmap(data []byte) { - InvokeSync(func() { - menuItemSetBitmap(l.native, data) - }) -} - -func (l linuxMenuItem) unBlockSignal() { -} - -func (l linuxMenuItem) setLabel(s string) { - InvokeSync(func() { - menuItemSetLabel(l.native, s) - }) -} - -func (l linuxMenuItem) isChecked() bool { - return menuItemChecked(l.native) -} - -func (l linuxMenuItem) setDisabled(disabled bool) { - InvokeSync(func() { - menuItemSetDisabled(l.native, disabled) - }) -} - -func (l linuxMenuItem) setChecked(checked bool) { - InvokeSync(func() { - menuItemSetChecked(l.native, checked) - }) -} - -func (l *linuxMenuItem) setHidden(hidden bool) { - if l.isHidden == hidden { - return - } - InvokeSync(func() { - menuItemSetHidden(l, hidden) - }) - l.isHidden = hidden -} - -func (l linuxMenuItem) setAccelerator(accelerator *accelerator) { - if accelerator == nil || l.menuItem == nil { - return - } - InvokeSync(func() { - setMenuItemAccelerator(l.menuItem.id, accelerator) - }) -} - -func newMenuItemImpl(item *MenuItem) *linuxMenuItem { - result := &linuxMenuItem{ - menuItem: item, - } - switch item.itemType { - case text: - result.native = menuItemNewWithId(item.label, item.bitmap, item.id) - case submenu: - result.native = menuItemNewWithId(item.label, item.bitmap, item.id) - default: - panic(fmt.Sprintf("Unknown menu type for newMenuItemImpl: %v", item.itemType)) - } - if item.accelerator != nil { - result.setAccelerator(item.accelerator) - } - result.setDisabled(result.menuItem.disabled) - return result -} - -func newCheckMenuItemImpl(item *MenuItem) *linuxMenuItem { - result := &linuxMenuItem{ - menuItem: item, - native: menuCheckItemNewWithId(item.label, item.bitmap, item.id, item.checked), - } - if item.accelerator != nil { - result.setAccelerator(item.accelerator) - } - result.setDisabled(result.menuItem.disabled) - return result -} - -func newRadioMenuItemImpl(item *MenuItem, groupId uint, checkedId uint) *linuxMenuItem { - result := &linuxMenuItem{ - menuItem: item, - native: menuRadioItemNewWithGroup(item.label, item.id, groupId, checkedId), - } - if item.accelerator != nil { - result.setAccelerator(item.accelerator) - } - result.setDisabled(result.menuItem.disabled) - return result -} - -func newSpeechMenu() *MenuItem { - speechMenu := NewMenu() - speechMenu.Add("Start Speaking"). - SetAccelerator("CmdOrCtrl+OptionOrAlt+Shift+."). - OnClick(func(ctx *Context) {}) - speechMenu.Add("Stop Speaking"). - SetAccelerator("CmdOrCtrl+OptionOrAlt+Shift+,"). - OnClick(func(ctx *Context) {}) - subMenu := NewSubMenuItem("Speech") - subMenu.submenu = speechMenu - return subMenu -} - -func newFrontMenuItem() *MenuItem { - panic("implement me") -} - -func newHideMenuItem() *MenuItem { - return NewMenuItem("Hide " + globalApplication.options.Name). - SetAccelerator("CmdOrCtrl+h"). - OnClick(func(ctx *Context) {}) -} - -func newHideOthersMenuItem() *MenuItem { - return NewMenuItem("Hide Others"). - SetAccelerator("CmdOrCtrl+OptionOrAlt+h"). - OnClick(func(ctx *Context) {}) -} - -func newUnhideMenuItem() *MenuItem { - return NewMenuItem("Show All"). - OnClick(func(ctx *Context) {}) -} - -func newUndoMenuItem() *MenuItem { - return NewMenuItem("Undo"). - SetAccelerator("CmdOrCtrl+z"). - OnClick(func(ctx *Context) {}) -} - -func newRedoMenuItem() *MenuItem { - return NewMenuItem("Redo"). - SetAccelerator("CmdOrCtrl+Shift+z"). - OnClick(func(ctx *Context) {}) -} - -func newCutMenuItem() *MenuItem { - return NewMenuItem("Cut"). - SetAccelerator("CmdOrCtrl+x"). - OnClick(func(ctx *Context) {}) -} - -func newCopyMenuItem() *MenuItem { - return NewMenuItem("Copy"). - SetAccelerator("CmdOrCtrl+c"). - OnClick(func(ctx *Context) {}) -} - -func newPasteMenuItem() *MenuItem { - return NewMenuItem("Paste"). - SetAccelerator("CmdOrCtrl+v"). - OnClick(func(ctx *Context) {}) -} - -func newPasteAndMatchStyleMenuItem() *MenuItem { - return NewMenuItem("Paste and Match Style"). - SetAccelerator("CmdOrCtrl+OptionOrAlt+Shift+v"). - OnClick(func(ctx *Context) {}) -} - -func newDeleteMenuItem() *MenuItem { - return NewMenuItem("Delete"). - SetAccelerator("backspace"). - OnClick(func(ctx *Context) {}) -} - -func newQuitMenuItem() *MenuItem { - return NewMenuItem("Quit " + globalApplication.options.Name). - SetAccelerator("CmdOrCtrl+q"). - OnClick(func(ctx *Context) { - globalApplication.Quit() - }) -} - -func newSelectAllMenuItem() *MenuItem { - return NewMenuItem("Select All"). - SetAccelerator("CmdOrCtrl+a"). - OnClick(func(ctx *Context) {}) -} - -func newAboutMenuItem() *MenuItem { - return NewMenuItem("About " + globalApplication.options.Name). - OnClick(func(ctx *Context) { - globalApplication.Menu.ShowAbout() - }) -} - -func newCloseMenuItem() *MenuItem { - return NewMenuItem("Close"). - SetAccelerator("CmdOrCtrl+w"). - OnClick(func(ctx *Context) { - currentWindow := globalApplication.Window.Current() - if currentWindow != nil { - currentWindow.Close() - } - }) -} - -func newReloadMenuItem() *MenuItem { - return NewMenuItem("Reload"). - SetAccelerator("CmdOrCtrl+r"). - OnClick(func(ctx *Context) { - currentWindow := globalApplication.Window.Current() - if currentWindow != nil { - currentWindow.Reload() - } - }) -} - -func newForceReloadMenuItem() *MenuItem { - return NewMenuItem("Force Reload"). - SetAccelerator("CmdOrCtrl+Shift+r"). - OnClick(func(ctx *Context) { - currentWindow := globalApplication.Window.Current() - if currentWindow != nil { - currentWindow.ForceReload() - } - }) -} - -func newToggleFullscreenMenuItem() *MenuItem { - result := NewMenuItem("Toggle Full Screen"). - OnClick(func(ctx *Context) { - currentWindow := globalApplication.Window.Current() - if currentWindow != nil { - currentWindow.ToggleFullscreen() - } - }) - if runtime.GOOS == "darwin" { - result.SetAccelerator("Ctrl+Command+F") - } else { - result.SetAccelerator("F11") - } - return result -} - -func newZoomResetMenuItem() *MenuItem { - return NewMenuItem("Actual Size"). - SetAccelerator("CmdOrCtrl+0"). - OnClick(func(ctx *Context) { - currentWindow := globalApplication.Window.Current() - if currentWindow != nil { - currentWindow.ZoomReset() - } - }) -} - -func newZoomInMenuItem() *MenuItem { - return NewMenuItem("Zoom In"). - SetAccelerator("CmdOrCtrl+plus"). - OnClick(func(ctx *Context) { - currentWindow := globalApplication.Window.Current() - if currentWindow != nil { - currentWindow.ZoomIn() - } - }) -} - -func newZoomOutMenuItem() *MenuItem { - return NewMenuItem("Zoom Out"). - SetAccelerator("CmdOrCtrl+-"). - OnClick(func(ctx *Context) { - currentWindow := globalApplication.Window.Current() - if currentWindow != nil { - currentWindow.ZoomOut() - } - }) -} - -func newMinimizeMenuItem() *MenuItem { - return NewMenuItem("Minimize"). - SetAccelerator("CmdOrCtrl+M"). - OnClick(func(ctx *Context) { - currentWindow := globalApplication.Window.Current() - if currentWindow != nil { - currentWindow.Minimise() - } - }) -} - -func newZoomMenuItem() *MenuItem { - return NewMenuItem("Zoom"). - OnClick(func(ctx *Context) { - currentWindow := globalApplication.Window.Current() - if currentWindow != nil { - currentWindow.Zoom() - } - }) -} - -func newFullScreenMenuItem() *MenuItem { - return NewMenuItem("Fullscreen"). - OnClick(func(ctx *Context) { - currentWindow := globalApplication.Window.Current() - if currentWindow != nil { - currentWindow.Fullscreen() - } - }) -} - -func newPrintMenuItem() *MenuItem { - panic("Implement me") -} - -func newPageLayoutMenuItem() *MenuItem { - panic("Implement me") -} - -func newShowAllMenuItem() *MenuItem { - panic("Implement me") -} - -func newBringAllToFrontMenuItem() *MenuItem { - panic("Implement me") -} - -func newNewFileMenuItem() *MenuItem { - panic("Implement me") -} - -func newOpenMenuItem() *MenuItem { - panic("Implement me") -} - -func newSaveMenuItem() *MenuItem { - panic("Implement me") -} - -func newSaveAsMenuItem() *MenuItem { - panic("Implement me") -} - -func newStartSpeakingMenuItem() *MenuItem { - panic("Implement me") -} - -func newStopSpeakingMenuItem() *MenuItem { - panic("Implement me") -} - -func newRevertMenuItem() *MenuItem { - panic("Implement me") -} - -func newFindMenuItem() *MenuItem { - panic("Implement me") -} - -func newFindAndReplaceMenuItem() *MenuItem { - panic("Implement me") -} - -func newFindNextMenuItem() *MenuItem { - panic("Implement me") -} - -func newFindPreviousMenuItem() *MenuItem { - panic("Implement me") -} - -func newHelpMenuItem() *MenuItem { - panic("Implement me") -} diff --git a/v3/pkg/application/menuitem_production.go b/v3/pkg/application/menuitem_production.go deleted file mode 100644 index b5aac387f..000000000 --- a/v3/pkg/application/menuitem_production.go +++ /dev/null @@ -1,7 +0,0 @@ -//go:build production && !devtools - -package application - -func NewOpenDevToolsMenuItem() *MenuItem { - return nil -} diff --git a/v3/pkg/application/menuitem_roles.go b/v3/pkg/application/menuitem_roles.go deleted file mode 100644 index f36908884..000000000 --- a/v3/pkg/application/menuitem_roles.go +++ /dev/null @@ -1,358 +0,0 @@ -package application - -import "runtime" - -func NewSpeechMenu() *MenuItem { - speechMenu := NewMenu() - speechMenu.AddRole(StartSpeaking) - speechMenu.AddRole(StopSpeaking) - subMenu := NewSubMenuItem("Speech") - subMenu.submenu = speechMenu - return subMenu -} - -func NewHideMenuItem() *MenuItem { - return NewMenuItem("Hide " + globalApplication.options.Name). - SetAccelerator("CmdOrCtrl+h"). - SetRole(Hide) -} - -func NewHideOthersMenuItem() *MenuItem { - return NewMenuItem("Hide Others"). - SetAccelerator("CmdOrCtrl+OptionOrAlt+h"). - SetRole(HideOthers) -} - -func NewFrontMenuItem() *MenuItem { - return NewMenuItem("Bring All to Front") -} - -func NewUnhideMenuItem() *MenuItem { - return NewMenuItem("Show All") -} - -func NewUndoMenuItem() *MenuItem { - result := NewMenuItem("Undo"). - SetAccelerator("CmdOrCtrl+z") - if runtime.GOOS != "darwin" { - result.OnClick(func(ctx *Context) { - currentWindow := globalApplication.Window.Current() - if currentWindow != nil { - currentWindow.undo() - } - }) - } - return result -} - -// NewRedoMenuItem creates a new menu item for redoing the last action -func NewRedoMenuItem() *MenuItem { - result := NewMenuItem("Redo"). - SetAccelerator("CmdOrCtrl+Shift+z") - if runtime.GOOS != "darwin" { - result.OnClick(func(ctx *Context) { - currentWindow := globalApplication.Window.Current() - if currentWindow != nil { - currentWindow.redo() - } - }) - } - return result -} - -func NewCutMenuItem() *MenuItem { - result := NewMenuItem("Cut"). - SetAccelerator("CmdOrCtrl+x") - - if runtime.GOOS != "darwin" { - result.OnClick(func(ctx *Context) { - currentWindow := globalApplication.Window.Current() - if currentWindow != nil { - currentWindow.cut() - } - }) - } - return result -} - -func NewCopyMenuItem() *MenuItem { - result := NewMenuItem("Copy"). - SetAccelerator("CmdOrCtrl+c") - - if runtime.GOOS != "darwin" { - result.OnClick(func(ctx *Context) { - currentWindow := globalApplication.Window.Current() - if currentWindow != nil { - currentWindow.copy() - } - }) - } - return result -} - -func NewPasteMenuItem() *MenuItem { - result := NewMenuItem("Paste"). - SetAccelerator("CmdOrCtrl+v") - - if runtime.GOOS != "darwin" { - result.OnClick(func(ctx *Context) { - currentWindow := globalApplication.Window.Current() - if currentWindow != nil { - currentWindow.paste() - } - }) - } - return result -} - -func NewPasteAndMatchStyleMenuItem() *MenuItem { - return NewMenuItem("Paste and Match Style"). - SetAccelerator("CmdOrCtrl+OptionOrAlt+Shift+v") -} - -func NewDeleteMenuItem() *MenuItem { - result := NewMenuItem("Delete"). - SetAccelerator("backspace") - - if runtime.GOOS != "darwin" { - result.OnClick(func(ctx *Context) { - currentWindow := globalApplication.Window.Current() - if currentWindow != nil { - currentWindow.delete() - } - }) - } - return result -} - -func NewQuitMenuItem() *MenuItem { - label := "Quit" - if runtime.GOOS == "darwin" { - if globalApplication.options.Name != "" { - label += " " + globalApplication.options.Name - } - } - return NewMenuItem(label). - SetAccelerator("CmdOrCtrl+q"). - OnClick(func(ctx *Context) { - globalApplication.Quit() - }) -} - -func NewSelectAllMenuItem() *MenuItem { - result := NewMenuItem("Select All"). - SetAccelerator("CmdOrCtrl+a") - - if runtime.GOOS != "darwin" { - result.OnClick(func(ctx *Context) { - currentWindow := globalApplication.Window.Current() - if currentWindow != nil { - currentWindow.selectAll() - } - }) - } - return result -} - -func NewAboutMenuItem() *MenuItem { - label := "About" - if globalApplication.options.Name != "" { - label += " " + globalApplication.options.Name - } - return NewMenuItem(label). - OnClick(func(ctx *Context) { - globalApplication.Menu.ShowAbout() - }) -} - -func NewCloseMenuItem() *MenuItem { - return NewMenuItem("Close"). - SetAccelerator("CmdOrCtrl+w"). - OnClick(func(ctx *Context) { - currentWindow := globalApplication.Window.Current() - if currentWindow != nil { - currentWindow.Close() - } - }) -} - -func NewReloadMenuItem() *MenuItem { - return NewMenuItem("Reload"). - SetAccelerator("CmdOrCtrl+r"). - OnClick(func(ctx *Context) { - currentWindow := globalApplication.Window.Current() - if currentWindow != nil { - currentWindow.Reload() - } - }) -} - -func NewForceReloadMenuItem() *MenuItem { - return NewMenuItem("Force Reload"). - SetAccelerator("CmdOrCtrl+Shift+r"). - OnClick(func(ctx *Context) { - currentWindow := globalApplication.Window.Current() - if currentWindow != nil { - currentWindow.ForceReload() - } - }) -} - -func NewToggleFullscreenMenuItem() *MenuItem { - result := NewMenuItem("Toggle Full Screen"). - SetAccelerator("Ctrl+Command+F"). - OnClick(func(ctx *Context) { - currentWindow := globalApplication.Window.Current() - if currentWindow != nil { - currentWindow.ToggleFullscreen() - } - }) - if runtime.GOOS != "darwin" { - result.SetAccelerator("F11") - } - return result -} - -func NewZoomResetMenuItem() *MenuItem { - // reset zoom menu item - return NewMenuItem("Actual Size"). - SetAccelerator("CmdOrCtrl+0"). - OnClick(func(ctx *Context) { - currentWindow := globalApplication.Window.Current() - if currentWindow != nil { - currentWindow.ZoomReset() - } - }) -} - -func NewZoomInMenuItem() *MenuItem { - return NewMenuItem("Zoom In"). - SetAccelerator("CmdOrCtrl+plus"). - OnClick(func(ctx *Context) { - currentWindow := globalApplication.Window.Current() - if currentWindow != nil { - currentWindow.ZoomIn() - } - }) -} - -func NewZoomOutMenuItem() *MenuItem { - return NewMenuItem("Zoom Out"). - SetAccelerator("CmdOrCtrl+-"). - OnClick(func(ctx *Context) { - currentWindow := globalApplication.Window.Current() - if currentWindow != nil { - currentWindow.ZoomOut() - } - }) -} - -func NewMinimiseMenuItem() *MenuItem { - return NewMenuItem("Minimize"). - SetAccelerator("CmdOrCtrl+M"). - OnClick(func(ctx *Context) { - currentWindow := globalApplication.Window.Current() - if currentWindow != nil { - currentWindow.Minimise() - } - }) -} - -func NewZoomMenuItem() *MenuItem { - return NewMenuItem("Zoom"). - OnClick(func(ctx *Context) { - currentWindow := globalApplication.Window.Current() - if currentWindow != nil { - currentWindow.Zoom() - } - }) -} - -func NewFullScreenMenuItem() *MenuItem { - return NewMenuItem("Fullscreen"). - OnClick(func(ctx *Context) { - currentWindow := globalApplication.Window.Current() - if currentWindow != nil { - currentWindow.Fullscreen() - } - }) -} - -func NewPrintMenuItem() *MenuItem { - return NewMenuItem("Print"). - SetAccelerator("CmdOrCtrl+p") -} - -func NewPageLayoutMenuItem() *MenuItem { - return NewMenuItem("Page Setup..."). - SetAccelerator("CmdOrCtrl+Shift+p") -} - -func NewShowAllMenuItem() *MenuItem { - return NewMenuItem("Show All") -} - -func NewBringAllToFrontMenuItem() *MenuItem { - return NewMenuItem("Bring All to Front") -} - -func NewNewFileMenuItem() *MenuItem { - return NewMenuItem("New File"). - SetAccelerator("CmdOrCtrl+n") -} - -func NewOpenMenuItem() *MenuItem { - return NewMenuItem("Open..."). - SetAccelerator("CmdOrCtrl+o"). - SetRole(Open) -} - -func NewSaveMenuItem() *MenuItem { - return NewMenuItem("Save"). - SetAccelerator("CmdOrCtrl+s") -} - -func NewSaveAsMenuItem() *MenuItem { - return NewMenuItem("Save As..."). - SetAccelerator("CmdOrCtrl+Shift+s") -} - -func NewStartSpeakingMenuItem() *MenuItem { - return NewMenuItem("Start Speaking"). - SetAccelerator("CmdOrCtrl+OptionOrAlt+Shift+.") -} - -func NewStopSpeakingMenuItem() *MenuItem { - return NewMenuItem("Stop Speaking"). - SetAccelerator("CmdOrCtrl+OptionOrAlt+Shift+,") -} - -func NewRevertMenuItem() *MenuItem { - return NewMenuItem("Revert"). - SetAccelerator("CmdOrCtrl+r") -} - -func NewFindMenuItem() *MenuItem { - return NewMenuItem("Find..."). - SetAccelerator("CmdOrCtrl+f") -} - -func NewFindAndReplaceMenuItem() *MenuItem { - return NewMenuItem("Find and Replace..."). - SetAccelerator("CmdOrCtrl+Shift+f") -} - -func NewFindNextMenuItem() *MenuItem { - return NewMenuItem("Find Next"). - SetAccelerator("CmdOrCtrl+g") -} - -func NewFindPreviousMenuItem() *MenuItem { - return NewMenuItem("Find Previous"). - SetAccelerator("CmdOrCtrl+Shift+g") -} - -func NewHelpMenuItem() *MenuItem { - return NewMenuItem("Help"). - SetAccelerator("CmdOrCtrl+?") -} diff --git a/v3/pkg/application/menuitem_selectors_darwin.go b/v3/pkg/application/menuitem_selectors_darwin.go deleted file mode 100644 index 3fd001897..000000000 --- a/v3/pkg/application/menuitem_selectors_darwin.go +++ /dev/null @@ -1,57 +0,0 @@ -// File: v3/pkg/application/menuitem_selectors_darwin.go - -//go:build darwin - -package application - -import "C" - -var roleToSelector = map[Role]string{ - //AppMenu: "", // This is a special case, handled separately - About: "orderFrontStandardAboutPanel:", - //ServicesMenu: "", // This is a submenu, no direct selector - Hide: "hide:", - HideOthers: "hideOtherApplications:", - ShowAll: "unhideAllApplications:", - Quit: "terminate:", - //WindowMenu: "", // This is a submenu, no direct selector - Minimise: "performMiniaturize:", - Zoom: "performZoom:", - BringAllToFront: "arrangeInFront:", - CloseWindow: "performClose:", - //EditMenu: "", // This is a submenu, no direct selector - Undo: "undo:", - Redo: "redo:", - Cut: "cut:", - Copy: "copy:", - Paste: "paste:", - Delete: "delete:", - SelectAll: "selectAll:", - //FindMenu: "", // This is a submenu, no direct selector - Find: "performTextFinderAction:", - FindAndReplace: "performTextFinderAction:", - FindNext: "performTextFinderAction:", - FindPrevious: "performTextFinderAction:", - //ViewMenu: "", // This is a submenu, no direct selector - ToggleFullscreen: "toggleFullScreen:", - //FileMenu: "", // This is a submenu, no direct selector - NewFile: "newDocument:", - Open: "openDocument:", - Save: "saveDocument:", - SaveAs: "saveDocumentAs:", - StartSpeaking: "startSpeaking:", - StopSpeaking: "stopSpeaking:", - Revert: "revertDocumentToSaved:", - Print: "printDocument:", - PageLayout: "runPageLayout:", - //HelpMenu: "", // This is a submenu, no direct selector - Help: "showHelp:", - //No: "", // No specific selector for this role -} - -func getSelectorForRole(role Role) *C.char { - if selector, ok := roleToSelector[role]; ok && selector != "" { - return C.CString(selector) - } - return nil -} diff --git a/v3/pkg/application/menuitem_test.go b/v3/pkg/application/menuitem_test.go deleted file mode 100644 index b2178876f..000000000 --- a/v3/pkg/application/menuitem_test.go +++ /dev/null @@ -1,61 +0,0 @@ -package application_test - -import ( - "testing" - - "github.com/wailsapp/wails/v3/pkg/application" -) - -func TestMenuItem_GetAccelerator(t *testing.T) { - tests := []struct { - name string - menuItem *application.MenuItem - expectedAcc string - }{ - { - name: "Get existing accelerator", - menuItem: application.NewMenuItem("Item 1").SetAccelerator("ctrl+a"), - expectedAcc: "Ctrl+A", - }, - { - name: "Get non-existing accelerator", - menuItem: application.NewMenuItem("Item 2"), - expectedAcc: "", - }, - } - - for _, test := range tests { - t.Run(test.name, func(t *testing.T) { - acc := test.menuItem.GetAccelerator() - if acc != test.expectedAcc { - t.Errorf("Expected accelerator to be %v, but got %v", test.expectedAcc, acc) - } - }) - } -} - -func TestMenuItem_RemoveAccelerator(t *testing.T) { - tests := []struct { - name string - menuItem *application.MenuItem - }{ - { - name: "Remove existing accelerator", - menuItem: application.NewMenuItem("Item 1").SetAccelerator("Ctrl+A"), - }, - { - name: "Remove non-existing accelerator", - menuItem: application.NewMenuItem("Item 2"), - }, - } - - for _, test := range tests { - t.Run(test.name, func(t *testing.T) { - test.menuItem.RemoveAccelerator() - acc := test.menuItem.GetAccelerator() - if acc != "" { - t.Errorf("Expected accelerator to be removed, but got %v", acc) - } - }) - } -} diff --git a/v3/pkg/application/menuitem_windows.go b/v3/pkg/application/menuitem_windows.go deleted file mode 100644 index 941bf2388..000000000 --- a/v3/pkg/application/menuitem_windows.go +++ /dev/null @@ -1,172 +0,0 @@ -//go:build windows - -package application - -import ( - "unsafe" - - "github.com/wailsapp/wails/v3/pkg/w32" -) - -type windowsMenuItem struct { - parent *Menu - menuItem *MenuItem - - hMenu w32.HMENU - id int - label string - disabled bool - checked bool - itemType menuItemType - hidden bool - submenu w32.HMENU -} - -func (m *windowsMenuItem) setHidden(hidden bool) { - if hidden && !m.hidden { - m.hidden = true - // Remove from parent menu - w32.RemoveMenu(m.hMenu, m.id, w32.MF_BYCOMMAND) - } else if !hidden && m.hidden { - m.hidden = false - // Reinsert into parent menu at correct visible position - var pos int - for _, item := range m.parent.items { - if item == m.menuItem { - break - } - if item.hidden == false { - pos++ - } - } - w32.InsertMenuItem(m.hMenu, uint32(pos), true, m.getMenuInfo()) - } -} - -func (m *windowsMenuItem) Checked() bool { - return m.checked -} - -func (m *windowsMenuItem) IsSeparator() bool { - return m.itemType == separator -} - -func (m *windowsMenuItem) IsCheckbox() bool { - return m.itemType == checkbox -} - -func (m *windowsMenuItem) IsRadio() bool { - return m.itemType == radio -} - -func (m *windowsMenuItem) Enabled() bool { - return !m.disabled -} - -func (m *windowsMenuItem) update() { - w32.SetMenuItemInfo(m.hMenu, uint32(m.id), false, m.getMenuInfo()) -} - -func (m *windowsMenuItem) setLabel(label string) { - m.label = label - m.update() -} - -func (m *windowsMenuItem) setDisabled(disabled bool) { - m.disabled = disabled - m.update() -} - -func (m *windowsMenuItem) setChecked(checked bool) { - m.checked = checked - m.update() -} - -func (m *windowsMenuItem) destroy() { - w32.RemoveMenu(m.hMenu, m.id, w32.MF_BYCOMMAND) -} - -func (m *windowsMenuItem) setAccelerator(accelerator *accelerator) { - //// Set the keyboard shortcut of the menu item - //var modifier C.int - //var key *C.char - //if accelerator != nil { - // modifier = C.int(toMacModifier(accelerator.Modifiers)) - // key = C.CString(accelerator.Key) - //} - // - //// Convert the key to a string - //C.setMenuItemKeyEquivalent(m.nsMenuItem, key, modifier) -} - -func (m *windowsMenuItem) setBitmap(bitmap []byte) { - if m.menuItem.bitmap == nil { - return - } - - // Set the icon - err := w32.SetMenuIcons(m.hMenu, m.id, bitmap, nil) - if err != nil { - globalApplication.error("unable to set bitmap on menu item: %w", err) - return - } - m.update() -} - -func newMenuItemImpl(item *MenuItem, parentMenu w32.HMENU, ID int) *windowsMenuItem { - result := &windowsMenuItem{ - menuItem: item, - hMenu: parentMenu, - id: ID, - disabled: item.disabled, - checked: item.checked, - itemType: item.itemType, - label: item.label, - hidden: item.hidden, - } - - return result -} - -func (m *windowsMenuItem) setTooltip(_ string) { - // Unsupported -} - -func (m *windowsMenuItem) getMenuInfo() *w32.MENUITEMINFO { - var mii w32.MENUITEMINFO - mii.CbSize = uint32(unsafe.Sizeof(mii)) - mii.FMask = w32.MIIM_FTYPE | w32.MIIM_ID | w32.MIIM_STATE | w32.MIIM_STRING - if m.IsSeparator() { - mii.FType = w32.MFT_SEPARATOR - } else { - mii.FType = w32.MFT_STRING - if m.IsRadio() { - mii.FType |= w32.MFT_RADIOCHECK - } - thisText := m.label - if m.menuItem.accelerator != nil { - thisText += "\t" + m.menuItem.accelerator.String() - } - mii.DwTypeData = w32.MustStringToUTF16Ptr(thisText) - mii.Cch = uint32(len([]rune(thisText))) - } - mii.WID = uint32(m.id) - if m.Enabled() { - mii.FState &^= w32.MFS_DISABLED - } else { - mii.FState |= w32.MFS_DISABLED - } - - if m.IsCheckbox() || m.IsRadio() { - mii.FMask |= w32.MIIM_CHECKMARKS - } - if m.Checked() { - mii.FState |= w32.MFS_CHECKED - } - - if m.menuItem.submenu != nil { - mii.FMask |= w32.MIIM_SUBMENU - mii.HSubMenu = m.submenu - } - return &mii -} diff --git a/v3/pkg/application/messageprocessor.go b/v3/pkg/application/messageprocessor.go deleted file mode 100644 index a8b845470..000000000 --- a/v3/pkg/application/messageprocessor.go +++ /dev/null @@ -1,205 +0,0 @@ -package application - -import ( - "context" - "log/slog" - "slices" - "strconv" - "sync" - - "github.com/wailsapp/wails/v3/pkg/errs" -) - -// TODO maybe we could use a new struct that has the targetWindow as an attribute so we could get rid of passing the targetWindow -// as parameter through every function call. - -const ( - callRequest = 0 - clipboardRequest = 1 - applicationRequest = 2 - eventsRequest = 3 - contextMenuRequest = 4 - dialogRequest = 5 - windowRequest = 6 - screensRequest = 7 - systemRequest = 8 - browserRequest = 9 - cancelCallRequest = 10 - iosRequest = 11 - androidRequest = 12 -) - -var objectNames = map[int]string{ - callRequest: "Call", - clipboardRequest: "Clipboard", - applicationRequest: "Application", - eventsRequest: "Events", - contextMenuRequest: "ContextMenu", - dialogRequest: "Dialog", - windowRequest: "Window", - screensRequest: "Screens", - systemRequest: "System", - browserRequest: "Browser", - cancelCallRequest: "CancelCall", - iosRequest: "iOS", - androidRequest: "Android", -} - -type RuntimeRequest struct { - // Object identifies which Wails subsystem to call (Call=0, Clipboard=1, etc.) - // See objectNames in runtime.ts - Object int `json:"object"` - - // Method identifies which method within the object to call - Method int `json:"method"` - - // Args contains the method arguments - Args *Args `json:"args"` - - // WebviewWindowName identifies the source window by name (optional, sent via header x-wails-window-name) - WebviewWindowName string `json:"webviewWindowName,omitempty"` - - // WebviewWindowID identifies the source window (optional, sent via header x-wails-window-id) - WebviewWindowID uint32 `json:"webviewWindowId,omitempty"` - - // ClientID identifies the frontend client (sent via header x-wails-client-id) - ClientID string `json:"clientId,omitempty"` -} - -type MessageProcessor struct { - logger *slog.Logger - - runningCalls map[string]context.CancelFunc - l sync.Mutex -} - -func NewMessageProcessor(logger *slog.Logger) *MessageProcessor { - return &MessageProcessor{ - logger: logger, - runningCalls: map[string]context.CancelFunc{}, - } -} - -func (m *MessageProcessor) HandleRuntimeCallWithIDs(ctx context.Context, req *RuntimeRequest) (resp any, err error) { - defer func() { - if handlePanic() { - // TODO: return panic error itself? - err = errs.NewInvalidRuntimeCallErrorf("runtime panic detected!") - } - }() - targetWindow, nameOrID := m.getTargetWindow(req) - - var windowNotRequiredRequests = []int{callRequest, eventsRequest, applicationRequest, systemRequest} - - // Some operations (calls, events, application) don't require a window - // This is useful for browser-based deployments with custom transports - windowRequired := !slices.Contains(windowNotRequiredRequests, req.Object) - if windowRequired && targetWindow == nil { - return nil, errs.NewInvalidRuntimeCallErrorf("window '%s' not found", nameOrID) - } - - m.logRuntimeCall(req) - - switch req.Object { - case windowRequest: - return m.processWindowMethod(req, targetWindow) - case clipboardRequest: - return m.processClipboardMethod(req) - case dialogRequest: - return m.processDialogMethod(req, targetWindow) - case eventsRequest: - return m.processEventsMethod(req, targetWindow) - case applicationRequest: - return m.processApplicationMethod(req) - case contextMenuRequest: - return m.processContextMenuMethod(req, targetWindow) - case screensRequest: - return m.processScreensMethod(req) - case callRequest: - return m.processCallMethod(ctx, req, targetWindow) - case systemRequest: - return m.processSystemMethod(req) - case browserRequest: - return m.processBrowserMethod(req) - case cancelCallRequest: - return m.processCallCancelMethod(req) - case iosRequest: - return m.processIOSMethod(req, targetWindow) - case androidRequest: - return m.processAndroidMethod(req, targetWindow) - default: - return nil, errs.NewInvalidRuntimeCallErrorf("unknown object %d", req.Object) - } -} - -func (m *MessageProcessor) getTargetWindow(req *RuntimeRequest) (Window, string) { - // Check for browser window first (server mode) - if req.ClientID != "" { - if browserWindow := GetBrowserWindow(req.ClientID); browserWindow != nil { - return browserWindow, browserWindow.Name() - } - } - if req.WebviewWindowName != "" { - window, _ := globalApplication.Window.GetByName(req.WebviewWindowName) - return window, req.WebviewWindowName - } - if req.WebviewWindowID == 0 { - // No window specified - return the first available window - // This is useful for custom transports that don't have automatic window context - windows := globalApplication.Window.GetAll() - if len(windows) > 0 { - return windows[0], "" - } - return nil, "" - } - targetWindow, _ := globalApplication.Window.GetByID(uint(req.WebviewWindowID)) - if targetWindow == nil { - m.Error("Window ID not found:", "id", req.WebviewWindowID) - return nil, strconv.Itoa(int(req.WebviewWindowID)) - } - return targetWindow, strconv.Itoa(int(req.WebviewWindowID)) -} - -func (m *MessageProcessor) Error(message string, args ...any) { - m.logger.Error(message, args...) -} - -func (m *MessageProcessor) Debug(message string, args ...any) { - m.logger.Debug(message, args...) -} - -func (m *MessageProcessor) logRuntimeCall(req *RuntimeRequest) { - objectName := objectNames[req.Object] - - methodName := "" - switch req.Object { - case callRequest: - return // logs done separately in call processor - case clipboardRequest: - methodName = clipboardMethods[req.Method] - case applicationRequest: - methodName = applicationMethodNames[req.Method] - case eventsRequest: - methodName = eventsMethodNames[req.Method] - case contextMenuRequest: - methodName = contextmenuMethodNames[req.Method] - case dialogRequest: - methodName = dialogMethodNames[req.Method] - case windowRequest: - methodName = windowMethodNames[req.Method] - case screensRequest: - methodName = screensMethodNames[req.Method] - case systemRequest: - methodName = systemMethodNames[req.Method] - case browserRequest: - methodName = browserMethodNames[req.Method] - case cancelCallRequest: - methodName = "Cancel" - case iosRequest: - methodName = iosMethodNames[req.Method] - case androidRequest: - methodName = androidMethodNames[req.Method] - } - - m.Debug("Runtime call:", "method", objectName+"."+methodName, "args", req.Args.String()) -} diff --git a/v3/pkg/application/messageprocessor_android.go b/v3/pkg/application/messageprocessor_android.go deleted file mode 100644 index 791cfa07e..000000000 --- a/v3/pkg/application/messageprocessor_android.go +++ /dev/null @@ -1,70 +0,0 @@ -//go:build android - -package application - -import ( - "github.com/wailsapp/wails/v3/pkg/errs" -) - -const ( - AndroidHapticsVibrate = 0 - AndroidDeviceInfo = 1 - AndroidToast = 2 -) - -var androidMethodNames = map[int]string{ - AndroidHapticsVibrate: "Haptics.Vibrate", - AndroidDeviceInfo: "Device.Info", - AndroidToast: "Toast.Show", -} - -func (m *MessageProcessor) processAndroidMethod(req *RuntimeRequest, window Window) (any, error) { - args := req.Args.AsMap() - - switch req.Method { - case AndroidHapticsVibrate: - duration := 100 // default 100ms - if d := args.Int("duration"); d != nil { - duration = *d - } - androidHapticsVibrate(duration) - return unit, nil - case AndroidDeviceInfo: - return androidDeviceInfo(), nil - case AndroidToast: - message := "" - if s := args.String("message"); s != nil { - message = *s - } - androidShowToast(message) - return unit, nil - default: - return nil, errs.NewInvalidAndroidCallErrorf("unknown method: %d", req.Method) - } -} - -// processIOSMethod is a stub on Android -func (m *MessageProcessor) processIOSMethod(req *RuntimeRequest, window Window) (any, error) { - return nil, errs.NewInvalidIOSCallErrorf("iOS methods not available on Android") -} - -// Android-specific runtime functions (stubs for now) - -func androidHapticsVibrate(durationMs int) { - // TODO: Implement via JNI to Android Vibrator service - androidLogf("debug", "Haptics vibrate: %dms", durationMs) -} - -func androidDeviceInfo() map[string]interface{} { - // TODO: Implement via JNI to get actual device info - return map[string]interface{}{ - "platform": "android", - "model": "Unknown", - "version": "Unknown", - } -} - -func androidShowToast(message string) { - // TODO: Implement via JNI to Android Toast - androidLogf("debug", "Toast: %s", message) -} diff --git a/v3/pkg/application/messageprocessor_application.go b/v3/pkg/application/messageprocessor_application.go deleted file mode 100644 index 18dc99850..000000000 --- a/v3/pkg/application/messageprocessor_application.go +++ /dev/null @@ -1,35 +0,0 @@ -package application - -import ( - "github.com/wailsapp/wails/v3/pkg/errs" -) - -const ( - ApplicationHide = 0 - ApplicationShow = 1 - ApplicationQuit = 2 -) - -var applicationMethodNames = map[int]string{ - ApplicationQuit: "Quit", - ApplicationHide: "Hide", - ApplicationShow: "Show", -} - -func (m *MessageProcessor) processApplicationMethod( - req *RuntimeRequest, -) (any, error) { - switch req.Method { - case ApplicationQuit: - globalApplication.Quit() - return unit, nil - case ApplicationHide: - globalApplication.Hide() - return unit, nil - case ApplicationShow: - globalApplication.Show() - return unit, nil - default: - return nil, errs.NewInvalidApplicationCallErrorf("unknown method %d", req.Method) - } -} diff --git a/v3/pkg/application/messageprocessor_args.go b/v3/pkg/application/messageprocessor_args.go deleted file mode 100644 index bb3ffc6d0..000000000 --- a/v3/pkg/application/messageprocessor_args.go +++ /dev/null @@ -1,124 +0,0 @@ -package application - -import ( - "fmt" - - "encoding/json" -) - -type Args struct { - rawData json.RawMessage -} - -func (a *Args) UnmarshalJSON(data []byte) error { - a.rawData = data - - return nil -} - -func (a *Args) String() string { return string(a.rawData) } - -func (a *Args) AsMap() *MapArgs { - m := make(map[string]interface{}) - if a.rawData == nil { - return &MapArgs{ - data: m, - } - } - err := json.Unmarshal(a.rawData, &m) - if err != nil { - return &MapArgs{ - data: m, - } - } - return &MapArgs{data: m} -} - -func (a *Args) ToStruct(str any) error { - return json.Unmarshal(a.rawData, str) -} - -type MapArgs struct { - data map[string]interface{} -} - -func (a *MapArgs) String(key string) *string { - if a == nil { - return nil - } - if val := a.data[key]; val != nil { - result := fmt.Sprintf("%v", val) - return &result - } - return nil -} - -func (a *MapArgs) Int(s string) *int { - if a == nil { - return nil - } - if val := a.data[s]; val != nil { - return convertNumber[int](val) - } - return nil -} - -func convertNumber[T int | int8 | int16 | int32 | int64 | uint | uint8 | uint16 | uint32 | uint64](val any) *T { - if val == nil { - return nil - } - var result T - switch v := val.(type) { - case T: - result = v - case float64: - result = T(v) - default: - return nil - } - return &result -} - -func (a *MapArgs) UInt8(s string) *uint8 { - if a == nil { - return nil - } - if val := a.data[s]; val != nil { - return convertNumber[uint8](val) - } - return nil -} - -func (a *MapArgs) UInt(s string) *uint { - if a == nil { - return nil - } - if val := a.data[s]; val != nil { - return convertNumber[uint](val) - } - return nil -} - -func (a *MapArgs) Float64(s string) *float64 { - if a == nil { - return nil - } - if val := a.data[s]; val != nil { - if result, ok := val.(float64); ok { - return &result - } - } - return nil -} - -func (a *MapArgs) Bool(s string) *bool { - if a == nil { - return nil - } - if val := a.data[s]; val != nil { - if result, ok := val.(bool); ok { - return &result - } - } - return nil -} diff --git a/v3/pkg/application/messageprocessor_browser.go b/v3/pkg/application/messageprocessor_browser.go deleted file mode 100644 index cd2ea7ac7..000000000 --- a/v3/pkg/application/messageprocessor_browser.go +++ /dev/null @@ -1,39 +0,0 @@ -package application - -import ( - "github.com/pkg/browser" - "github.com/wailsapp/wails/v3/pkg/errs" -) - -const ( - BrowserOpenURL = 0 -) - -var browserMethodNames = map[int]string{ - BrowserOpenURL: "OpenURL", -} - -func (m *MessageProcessor) processBrowserMethod(req *RuntimeRequest) (any, error) { - switch req.Method { - case BrowserOpenURL: - url := req.Args.AsMap().String("url") - if url == nil { - return nil, errs.NewInvalidBrowserCallErrorf("missing argument 'url'") - } - - sanitizedURL, err := ValidateAndSanitizeURL(*url) - if err != nil { - return nil, errs.WrapInvalidBrowserCallErrorf(err, "invalid URL") - } - - err = browser.OpenURL(sanitizedURL) - if err != nil { - m.Error("OpenURL: invalid URL - %s", err.Error()) - return nil, errs.WrapInvalidBrowserCallErrorf(err, "OpenURL failed") - } - - return unit, nil - default: - return nil, errs.NewInvalidBrowserCallErrorf("unknown method: %d", req.Method) - } -} diff --git a/v3/pkg/application/messageprocessor_call.go b/v3/pkg/application/messageprocessor_call.go deleted file mode 100644 index 71f60a00e..000000000 --- a/v3/pkg/application/messageprocessor_call.go +++ /dev/null @@ -1,137 +0,0 @@ -package application - -import ( - "context" - "errors" - - "encoding/json" - - "github.com/wailsapp/wails/v3/pkg/errs" -) - -type contextKey string - -const ( - CallBinding = 0 - WindowKey contextKey = "Window" -) - -func (m *MessageProcessor) processCallCancelMethod(req *RuntimeRequest) (any, error) { - callID := req.Args.AsMap().String("call-id") - if callID == nil || *callID == "" { - return nil, errs.NewInvalidBindingCallErrorf("missing argument 'call-id'") - } - - var cancel func() - func() { - m.l.Lock() - defer m.l.Unlock() - cancel = m.runningCalls[*callID] - }() - - if cancel != nil { - cancel() - m.Debug("Binding call cancelled:", "id", *callID) - } - return unit, nil -} - -func (m *MessageProcessor) processCallMethod(ctx context.Context, req *RuntimeRequest, window Window) (any, error) { - callID := req.Args.AsMap().String("call-id") - if callID == nil || *callID == "" { - return nil, errs.NewInvalidBindingCallErrorf("missing argument 'call-id'") - } - - switch req.Method { - case CallBinding: - var options CallOptions - err := req.Args.ToStruct(&options) - if err != nil { - return nil, errs.WrapInvalidBindingCallErrorf(err, "error parsing call options") - } - - // Log call - var methodRef any = options.MethodName - if options.MethodName == "" { - methodRef = options.MethodID - } - m.Debug("Binding call started:", "id", *callID, "method", methodRef) - - ctx, cancel := context.WithCancel(context.WithoutCancel(ctx)) - - // Schedule cancel in case panics happen before starting the call. - cancelRequired := true - defer func() { - if cancelRequired { - cancel() - } - }() - - ambiguousID := false - func() { - m.l.Lock() - defer m.l.Unlock() - - if m.runningCalls[*callID] != nil { - ambiguousID = true - } else { - m.runningCalls[*callID] = cancel - } - }() - - if ambiguousID { - return nil, errs.NewInvalidBindingCallErrorf("ambiguous call id: %s", *callID) - } - - defer func() { - m.l.Lock() - defer m.l.Unlock() - delete(m.runningCalls, *callID) - }() - defer cancel() - - var boundMethod *BoundMethod - if options.MethodName != "" { - boundMethod = globalApplication.bindings.Get(&options) - if boundMethod == nil { - return nil, errs.NewBindingCallFailedErrorf("unknown bound method name '%s'", options.MethodName) - } - } else { - boundMethod = globalApplication.bindings.GetByID(options.MethodID) - if boundMethod == nil { - return nil, errs.NewBindingCallFailedErrorf("unknown bound method id %d", options.MethodID) - } - } - - jsonArgs, _ := json.Marshal(options.Args) - var result any - defer func() { - var jsonResult []byte - jsonResult, _ = json.Marshal(result) - m.Debug("Binding call complete:", "id", *callID, "method", boundMethod, "args", string(jsonArgs), "result", string(jsonResult)) - }() - - // Set the context values for the window - if window != nil { - ctx = context.WithValue(ctx, WindowKey, window) - } - - result, err = boundMethod.Call(ctx, options.Args) - if cerr := (*CallError)(nil); errors.As(err, &cerr) { - switch cerr.Kind { - case ReferenceError, TypeError: - return nil, errs.WrapBindingCallFailedErrorf(cerr, "failed to call binding") - case RuntimeError: - - return nil, errs.WrapBindingCallFailedErrorf(cerr, "Bound method returned an error") - } - } - if err != nil { - return nil, errs.WrapBindingCallFailedErrorf(err, "failed to call binding") - } - return result, nil - - default: - return nil, errs.NewInvalidBindingCallErrorf("unknown method: %d", req.Method) - } -} diff --git a/v3/pkg/application/messageprocessor_clipboard.go b/v3/pkg/application/messageprocessor_clipboard.go deleted file mode 100644 index 27eabe817..000000000 --- a/v3/pkg/application/messageprocessor_clipboard.go +++ /dev/null @@ -1,37 +0,0 @@ -package application - -import ( - "github.com/wailsapp/wails/v3/pkg/errs" -) - -const ( - ClipboardSetText = 0 - ClipboardText = 1 -) - -var clipboardMethods = map[int]string{ - ClipboardSetText: "SetText", - ClipboardText: "Text", -} - -func (m *MessageProcessor) processClipboardMethod(req *RuntimeRequest) (any, error) { - args := req.Args.AsMap() - - var text string - - switch req.Method { - case ClipboardSetText: - textp := args.String("text") - if textp == nil { - return nil, errs.NewInvalidClipboardCallErrorf("missing argument 'text'") - } - text = *textp - globalApplication.Clipboard.SetText(text) - return unit, nil - case ClipboardText: - text, _ = globalApplication.Clipboard.Text() - return text, nil - default: - return nil, errs.NewInvalidClipboardCallErrorf("unknown method: %d", req.Method) - } -} diff --git a/v3/pkg/application/messageprocessor_contextmenu.go b/v3/pkg/application/messageprocessor_contextmenu.go deleted file mode 100644 index 9529b34e4..000000000 --- a/v3/pkg/application/messageprocessor_contextmenu.go +++ /dev/null @@ -1,46 +0,0 @@ -package application - -import ( - "github.com/wailsapp/wails/v3/pkg/errs" -) - -type ContextMenuData struct { - Id string `json:"id"` - X int `json:"x"` - Y int `json:"y"` - Data string `json:"data"` -} - -func (d ContextMenuData) clone() *ContextMenuData { - return &ContextMenuData{ - Id: d.Id, - X: d.X, - Y: d.Y, - Data: d.Data, - } -} - -const ( - ContextMenuOpen = 0 -) - -var contextmenuMethodNames = map[int]string{ - ContextMenuOpen: "Open", -} - -func (m *MessageProcessor) processContextMenuMethod(req *RuntimeRequest, window Window) (any, error) { - switch req.Method { - case ContextMenuOpen: - var data ContextMenuData - err := req.Args.ToStruct(&data) - if err != nil { - return nil, errs.WrapInvalidContextMenuCallErrorf(err, "error parsing parameters") - } - - window.OpenContextMenu(&data) - - return unit, err - default: - return nil, errs.NewInvalidContextMenuCallErrorf("unknown method: %d", req.Method) - } -} diff --git a/v3/pkg/application/messageprocessor_dialog.go b/v3/pkg/application/messageprocessor_dialog.go deleted file mode 100644 index 097bd7d7f..000000000 --- a/v3/pkg/application/messageprocessor_dialog.go +++ /dev/null @@ -1,126 +0,0 @@ -package application - -import ( - "runtime" - - "github.com/wailsapp/wails/v3/pkg/errs" -) - -const ( - DialogInfo = 0 - DialogWarning = 1 - DialogError = 2 - DialogQuestion = 3 - DialogOpenFile = 4 - DialogSaveFile = 5 -) - -var dialogMethodNames = map[int]string{ - DialogInfo: "Info", - DialogWarning: "Warning", - DialogError: "Error", - DialogQuestion: "Question", - DialogOpenFile: "OpenFile", - DialogSaveFile: "SaveFile", -} - -func (m *MessageProcessor) processDialogMethod(req *RuntimeRequest, window Window) (any, error) { - args := req.Args.AsMap() - - switch req.Method { - case DialogInfo, DialogWarning, DialogError, DialogQuestion: - var options MessageDialogOptions - err := req.Args.ToStruct(&options) - if err != nil { - return nil, errs.WrapInvalidDialogCallErrorf(err, "error parsing dialog options") - } - if len(options.Buttons) == 0 { - switch runtime.GOOS { - case "darwin": - options.Buttons = []*Button{{Label: "OK", IsDefault: true}} - } - } - var dialog *MessageDialog - switch req.Method { - case DialogInfo: - dialog = newMessageDialog(InfoDialogType) - case DialogWarning: - dialog = newMessageDialog(WarningDialogType) - case DialogError: - dialog = newMessageDialog(ErrorDialogType) - case DialogQuestion: - dialog = newMessageDialog(QuestionDialogType) - } - var detached = args.Bool("Detached") - if detached == nil || !*detached { - dialog.AttachToWindow(window) - } - - dialog.SetTitle(options.Title) - dialog.SetMessage(options.Message) - - resp := make(chan string, 1) - for _, button := range options.Buttons { - label := button.Label - button.OnClick(func() { - select { - case resp <- label: - default: - } - }) - } - dialog.AddButtons(options.Buttons) - dialog.Show() - - response := <-resp - return response, nil - - case DialogOpenFile: - var options OpenFileDialogOptions - err := req.Args.ToStruct(&options) - if err != nil { - return nil, errs.WrapInvalidDialogCallErrorf(err, "error parsing dialog options") - } - var detached = args.Bool("Detached") - if detached == nil || !*detached { - options.Window = window - } - dialog := globalApplication.Dialog.OpenFileWithOptions(&options) - - if options.AllowsMultipleSelection { - files, err := dialog.PromptForMultipleSelection() - if err != nil { - return nil, errs.WrapInvalidDialogCallErrorf(err, "Dialog.OpenFile failed: error getting selection") - } - - return files, nil - } else { - file, err := dialog.PromptForSingleSelection() - if err != nil { - return nil, errs.WrapInvalidDialogCallErrorf(err, "Dialog.OpenFile failed, error getting selection") - } - return file, nil - } - - case DialogSaveFile: - var options SaveFileDialogOptions - err := req.Args.ToStruct(&options) - if err != nil { - return nil, errs.WrapInvalidDialogCallErrorf(err, "error parsing dialog options") - } - var detached = args.Bool("Detached") - if detached == nil || !*detached { - options.Window = window - } - dialog := globalApplication.Dialog.SaveFileWithOptions(&options) - - file, err := dialog.PromptForSingleSelection() - if err != nil { - return nil, errs.WrapInvalidDialogCallErrorf(err, "Dialog.SaveFile failed: error getting selection") - } - return file, nil - - default: - return nil, errs.NewInvalidDialogCallErrorf("unknown method: %d", req.Method) - } -} diff --git a/v3/pkg/application/messageprocessor_events.go b/v3/pkg/application/messageprocessor_events.go deleted file mode 100644 index ea4e5882e..000000000 --- a/v3/pkg/application/messageprocessor_events.go +++ /dev/null @@ -1,50 +0,0 @@ -package application - -import ( - "encoding/json" - - "github.com/wailsapp/wails/v3/pkg/errs" -) - -const ( - EventsEmit = 0 -) - -var eventsMethodNames = map[int]string{ - EventsEmit: "Emit", -} - -func (m *MessageProcessor) processEventsMethod(req *RuntimeRequest, window Window) (any, error) { - switch req.Method { - case EventsEmit: - var event CustomEvent - var options struct { - Name *string `json:"name"` - Data json.RawMessage `json:"data"` - } - - err := req.Args.ToStruct(&options) - if err != nil { - return nil, errs.WrapInvalidEventsCallErrorf(err, "error parsing event") - } - if options.Name == nil { - return nil, errs.NewInvalidEventsCallErrorf("missing event name") - } - - data, err := decodeEventData(*options.Name, options.Data) - if err != nil { - return nil, errs.WrapInvalidEventsCallErrorf(err, "error parsing event data") - } - - event.Name = *options.Name - event.Data = data - if window != nil { - event.Sender = window.Name() - } - globalApplication.Event.EmitEvent(&event) - - return event.IsCancelled(), nil - default: - return nil, errs.NewInvalidEventsCallErrorf("unknown method: %d", req.Method) - } -} diff --git a/v3/pkg/application/messageprocessor_ios.go b/v3/pkg/application/messageprocessor_ios.go deleted file mode 100644 index dbc4ad187..000000000 --- a/v3/pkg/application/messageprocessor_ios.go +++ /dev/null @@ -1,105 +0,0 @@ -//go:build ios - -package application - -import ( - "github.com/wailsapp/wails/v3/pkg/errs" -) - -const ( - IOSHapticsImpact = 0 - IOSDeviceInfo = 1 - IOSScrollSetEnabled = 2 - IOSScrollSetBounceEnabled = 3 - IOSScrollSetIndicatorsEnabled = 4 - IOSNavigationSetBackForwardGestures = 5 - IOSLinksSetPreviewEnabled = 6 - IOSDebugSetInspectableEnabled = 7 - IOSUserAgentSet = 8 -) - -var iosMethodNames = map[int]string{ - IOSHapticsImpact: "Haptics.Impact", - IOSDeviceInfo: "Device.Info", - IOSScrollSetEnabled: "Scroll.SetEnabled", - IOSScrollSetBounceEnabled: "Scroll.SetBounceEnabled", - IOSScrollSetIndicatorsEnabled: "Scroll.SetIndicatorsEnabled", - IOSNavigationSetBackForwardGestures: "Navigation.SetBackForwardGesturesEnabled", - IOSLinksSetPreviewEnabled: "Links.SetPreviewEnabled", - IOSDebugSetInspectableEnabled: "Debug.SetInspectableEnabled", - IOSUserAgentSet: "UserAgent.Set", -} - -func (m *MessageProcessor) processIOSMethod(req *RuntimeRequest, window Window) (any, error) { - args := req.Args.AsMap() - - switch req.Method { - case IOSHapticsImpact: - style := "medium" - if s := args.String("style"); s != nil { - style = *s - } - iosHapticsImpact(style) - return unit, nil - case IOSDeviceInfo: - return iosDeviceInfo(), nil - case IOSScrollSetEnabled: - enabled := true - if b := args.Bool("enabled"); b != nil { - enabled = *b - } - iosSetScrollEnabled(enabled) - return unit, nil - case IOSScrollSetBounceEnabled: - enabled := true - if b := args.Bool("enabled"); b != nil { - enabled = *b - } - iosSetBounceEnabled(enabled) - return unit, nil - case IOSScrollSetIndicatorsEnabled: - enabled := true - if b := args.Bool("enabled"); b != nil { - enabled = *b - } - iosSetScrollIndicatorsEnabled(enabled) - return unit, nil - case IOSNavigationSetBackForwardGestures: - enabled := false - if b := args.Bool("enabled"); b != nil { - enabled = *b - } - iosSetBackForwardGesturesEnabled(enabled) - return unit, nil - case IOSLinksSetPreviewEnabled: - enabled := true - if b := args.Bool("enabled"); b != nil { - enabled = *b - } - iosSetLinkPreviewEnabled(enabled) - return unit, nil - case IOSDebugSetInspectableEnabled: - enabled := true - if b := args.Bool("enabled"); b != nil { - enabled = *b - } - iosSetInspectableEnabled(enabled) - return unit, nil - case IOSUserAgentSet: - ua := "" - if s := args.String("ua"); s != nil { - ua = *s - } else if s2 := args.String("userAgent"); s2 != nil { - ua = *s2 - } - iosSetCustomUserAgent(ua) - return unit, nil - default: - return nil, errs.NewInvalidIOSCallErrorf("unknown method: %d", req.Method) - } -} - -// processAndroidMethod is a stub on iOS -func (m *MessageProcessor) processAndroidMethod(req *RuntimeRequest, window Window) (any, error) { - return nil, errs.NewInvalidAndroidCallErrorf("Android methods not available on iOS") -} diff --git a/v3/pkg/application/messageprocessor_mobile_stub.go b/v3/pkg/application/messageprocessor_mobile_stub.go deleted file mode 100644 index d59a26694..000000000 --- a/v3/pkg/application/messageprocessor_mobile_stub.go +++ /dev/null @@ -1,21 +0,0 @@ -//go:build !ios && !android - -package application - -import ( - "github.com/wailsapp/wails/v3/pkg/errs" -) - -// Empty method name maps for logging on non-mobile platforms -var iosMethodNames = map[int]string{} -var androidMethodNames = map[int]string{} - -// processIOSMethod is a stub for non-mobile platforms -func (m *MessageProcessor) processIOSMethod(req *RuntimeRequest, window Window) (any, error) { - return nil, errs.NewInvalidIOSCallErrorf("iOS methods not available on this platform") -} - -// processAndroidMethod is a stub for non-mobile platforms -func (m *MessageProcessor) processAndroidMethod(req *RuntimeRequest, window Window) (any, error) { - return nil, errs.NewInvalidAndroidCallErrorf("Android methods not available on this platform") -} diff --git a/v3/pkg/application/messageprocessor_screens.go b/v3/pkg/application/messageprocessor_screens.go deleted file mode 100644 index 6fbadad12..000000000 --- a/v3/pkg/application/messageprocessor_screens.go +++ /dev/null @@ -1,34 +0,0 @@ -package application - -import ( - "github.com/wailsapp/wails/v3/pkg/errs" -) - -const ( - ScreensGetAll = 0 - ScreensGetPrimary = 1 - ScreensGetCurrent = 2 -) - -var screensMethodNames = map[int]string{ - ScreensGetAll: "GetAll", - ScreensGetPrimary: "GetPrimary", - ScreensGetCurrent: "GetCurrent", -} - -func (m *MessageProcessor) processScreensMethod(req *RuntimeRequest) (any, error) { - switch req.Method { - case ScreensGetAll: - return globalApplication.Screen.GetAll(), nil - case ScreensGetPrimary: - return globalApplication.Screen.GetPrimary(), nil - case ScreensGetCurrent: - screen, err := globalApplication.Window.Current().GetScreen() - if err != nil { - return nil, errs.WrapInvalidScreensCallErrorf(err, "Window.GetScreen failed") - } - return screen, nil - default: - return nil, errs.NewInvalidScreensCallErrorf("Unknown method: %d", req.Method) - } -} diff --git a/v3/pkg/application/messageprocessor_system.go b/v3/pkg/application/messageprocessor_system.go deleted file mode 100644 index 5e2b004df..000000000 --- a/v3/pkg/application/messageprocessor_system.go +++ /dev/null @@ -1,35 +0,0 @@ -package application - -import ( - "github.com/wailsapp/wails/v3/pkg/errs" -) - -const ( - SystemIsDarkMode = 0 - Environment = 1 - Capabilities = 2 - Flags = 3 -) - -var systemMethodNames = map[int]string{ - SystemIsDarkMode: "IsDarkMode", - Environment: "Environment", - Capabilities: "Capabilities", - Flags: "Flags", -} - -func (m *MessageProcessor) processSystemMethod(req *RuntimeRequest) (any, error) { - switch req.Method { - case SystemIsDarkMode: - return globalApplication.Env.IsDarkMode(), nil - case Environment: - return globalApplication.Env.Info(), nil - case Capabilities: - return globalApplication.capabilities, nil - case Flags: - flags := globalApplication.impl.GetFlags(globalApplication.options) - return flags, nil - default: - return nil, errs.NewInvalidSystemCallErrorf("unknown method: %d", req.Method) - } -} diff --git a/v3/pkg/application/messageprocessor_window.go b/v3/pkg/application/messageprocessor_window.go deleted file mode 100644 index 1baf57606..000000000 --- a/v3/pkg/application/messageprocessor_window.go +++ /dev/null @@ -1,415 +0,0 @@ -package application - -import ( - "fmt" - - "github.com/wailsapp/wails/v3/pkg/errs" -) - -const ( - WindowPosition = 0 - WindowCenter = 1 - WindowClose = 2 - WindowDisableSizeConstraints = 3 - WindowEnableSizeConstraints = 4 - WindowFocus = 5 - WindowForceReload = 6 - WindowFullscreen = 7 - WindowGetScreen = 8 - WindowGetZoom = 9 - WindowHeight = 10 - WindowHide = 11 - WindowIsFocused = 12 - WindowIsFullscreen = 13 - WindowIsMaximised = 14 - WindowIsMinimised = 15 - WindowMaximise = 16 - WindowMinimise = 17 - WindowName = 18 - WindowOpenDevTools = 19 - WindowRelativePosition = 20 - WindowReload = 21 - WindowResizable = 22 - WindowRestore = 23 - WindowSetPosition = 24 - WindowSetAlwaysOnTop = 25 - WindowSetBackgroundColour = 26 - WindowSetFrameless = 27 - WindowSetFullscreenButtonEnabled = 28 - WindowSetMaxSize = 29 - WindowSetMinSize = 30 - WindowSetRelativePosition = 31 - WindowSetResizable = 32 - WindowSetSize = 33 - WindowSetTitle = 34 - WindowSetZoom = 35 - WindowShow = 36 - WindowSize = 37 - WindowToggleFullscreen = 38 - WindowToggleMaximise = 39 - WindowToggleFrameless = 40 - WindowUnFullscreen = 41 - WindowUnMaximise = 42 - WindowUnMinimise = 43 - WindowWidth = 44 - WindowZoom = 45 - WindowZoomIn = 46 - WindowZoomOut = 47 - WindowZoomReset = 48 - WindowSnapAssist = 49 - WindowFilesDropped = 50 - WindowPrint = 51 -) - -var windowMethodNames = map[int]string{ - WindowPosition: "Position", - WindowCenter: "Center", - WindowClose: "Close", - WindowDisableSizeConstraints: "DisableSizeConstraints", - WindowEnableSizeConstraints: "EnableSizeConstraints", - WindowFocus: "Focus", - WindowForceReload: "ForceReload", - WindowFullscreen: "Fullscreen", - WindowGetScreen: "GetScreen", - WindowGetZoom: "GetZoom", - WindowHeight: "Height", - WindowHide: "Hide", - WindowIsFocused: "IsFocused", - WindowIsFullscreen: "IsFullscreen", - WindowIsMaximised: "IsMaximised", - WindowIsMinimised: "IsMinimised", - WindowMaximise: "Maximise", - WindowMinimise: "Minimise", - WindowName: "Name", - WindowOpenDevTools: "OpenDevTools", - WindowRelativePosition: "RelativePosition", - WindowReload: "Reload", - WindowResizable: "Resizable", - WindowRestore: "Restore", - WindowSetPosition: "SetPosition", - WindowSetAlwaysOnTop: "SetAlwaysOnTop", - WindowSetBackgroundColour: "SetBackgroundColour", - WindowSetFrameless: "SetFrameless", - WindowSetFullscreenButtonEnabled: "SetFullscreenButtonEnabled", - WindowSetMaxSize: "SetMaxSize", - WindowSetMinSize: "SetMinSize", - WindowSetRelativePosition: "SetRelativePosition", - WindowSetResizable: "SetResizable", - WindowSetSize: "SetSize", - WindowSetTitle: "SetTitle", - WindowSetZoom: "SetZoom", - WindowShow: "Show", - WindowSize: "Size", - WindowToggleFullscreen: "ToggleFullscreen", - WindowToggleMaximise: "ToggleMaximise", - WindowToggleFrameless: "ToggleFrameless", - WindowUnFullscreen: "UnFullscreen", - WindowUnMaximise: "UnMaximise", - WindowUnMinimise: "UnMinimise", - WindowWidth: "Width", - WindowZoom: "Zoom", - WindowZoomIn: "ZoomIn", - WindowZoomOut: "ZoomOut", - WindowZoomReset: "ZoomReset", - WindowFilesDropped: "FilesDropped", - WindowSnapAssist: "SnapAssist", - WindowPrint: "Print", -} - -var unit = struct{}{} - -func (m *MessageProcessor) processWindowMethod( - req *RuntimeRequest, - window Window, -) (any, error) { - args := req.Args.AsMap() - - switch req.Method { - case WindowPosition: - x, y := window.Position() - return map[string]interface{}{ - "x": x, - "y": y, - }, nil - case WindowCenter: - window.Center() - return unit, nil - case WindowClose: - window.Close() - return unit, nil - case WindowDisableSizeConstraints: - window.DisableSizeConstraints() - return unit, nil - case WindowEnableSizeConstraints: - window.EnableSizeConstraints() - return unit, nil - case WindowFocus: - window.Focus() - return unit, nil - case WindowForceReload: - window.ForceReload() - return unit, nil - case WindowFullscreen: - window.Fullscreen() - return unit, nil - case WindowGetScreen: - screen, err := window.GetScreen() - if err != nil { - return nil, fmt.Errorf("Window.GetScreen failed: %w", err) - } - return screen, nil - case WindowGetZoom: - return window.GetZoom(), nil - case WindowHeight: - return window.Height(), nil - case WindowHide: - window.Hide() - return unit, nil - case WindowIsFocused: - return window.IsFocused(), nil - case WindowIsFullscreen: - return window.IsFullscreen(), nil - case WindowIsMaximised: - return window.IsMaximised(), nil - case WindowIsMinimised: - return window.IsMinimised(), nil - case WindowMaximise: - window.Maximise() - return unit, nil - case WindowMinimise: - window.Minimise() - return unit, nil - case WindowName: - return window.Name(), nil - case WindowRelativePosition: - x, y := window.RelativePosition() - return map[string]interface{}{ - "x": x, - "y": y, - }, nil - case WindowReload: - window.Reload() - return unit, nil - case WindowResizable: - return window.Resizable(), nil - case WindowRestore: - window.Restore() - return unit, nil - case WindowSetPosition: - x := args.Int("x") - if x == nil { - return nil, errs.NewInvalidWindowCallErrorf("missing or invalid argument 'x'") - } - y := args.Int("y") - if y == nil { - return nil, errs.NewInvalidWindowCallErrorf("missing or invalid argument 'y'") - } - window.SetPosition(*x, *y) - return unit, nil - case WindowSetAlwaysOnTop: - alwaysOnTop := args.Bool("alwaysOnTop") - if alwaysOnTop == nil { - return nil, errs.NewInvalidWindowCallErrorf("missing or invalid argument 'alwaysOnTop'") - } - window.SetAlwaysOnTop(*alwaysOnTop) - return unit, nil - case WindowSetBackgroundColour: - r := args.UInt8("r") - if r == nil { - return nil, errs.NewInvalidWindowCallErrorf("missing or invalid argument 'r'") - } - g := args.UInt8("g") - if g == nil { - return nil, errs.NewInvalidWindowCallErrorf("missing or invalid argument 'g'") - } - b := args.UInt8("b") - if b == nil { - return nil, errs.NewInvalidWindowCallErrorf("missing or invalid argument 'b'") - } - a := args.UInt8("a") - if a == nil { - return nil, errs.NewInvalidWindowCallErrorf("missing or invalid argument 'a'") - } - window.SetBackgroundColour(RGBA{ - Red: *r, - Green: *g, - Blue: *b, - Alpha: *a, - }) - return unit, nil - case WindowSetFrameless: - frameless := args.Bool("frameless") - if frameless == nil { - return nil, errs.NewInvalidWindowCallErrorf("missing or invalid argument 'frameless'") - } - window.SetFrameless(*frameless) - return unit, nil - case WindowSetMaxSize: - width := args.Int("width") - if width == nil { - return nil, errs.NewInvalidWindowCallErrorf("missing or invalid argument 'width'") - } - height := args.Int("height") - if height == nil { - return nil, errs.NewInvalidWindowCallErrorf("missing or invalid argument 'height'") - } - window.SetMaxSize(*width, *height) - return unit, nil - case WindowSetMinSize: - width := args.Int("width") - if width == nil { - return nil, errs.NewInvalidWindowCallErrorf("missing or invalid argument 'width'") - } - height := args.Int("height") - if height == nil { - return nil, errs.NewInvalidWindowCallErrorf("missing or invalid argument 'height'") - } - window.SetMinSize(*width, *height) - return unit, nil - case WindowSetRelativePosition: - x := args.Int("x") - if x == nil { - return nil, errs.NewInvalidWindowCallErrorf("missing or invalid argument 'x'") - } - y := args.Int("y") - if y == nil { - return nil, errs.NewInvalidWindowCallErrorf("missing or invalid argument 'y'") - } - window.SetRelativePosition(*x, *y) - return unit, nil - case WindowSetResizable: - resizable := args.Bool("resizable") - if resizable == nil { - return nil, errs.NewInvalidWindowCallErrorf("missing or invalid argument 'resizable'") - } - window.SetResizable(*resizable) - return unit, nil - case WindowSetSize: - width := args.Int("width") - if width == nil { - return nil, errs.NewInvalidWindowCallErrorf("missing or invalid argument 'width'") - } - height := args.Int("height") - if height == nil { - return nil, errs.NewInvalidWindowCallErrorf("missing or invalid argument 'height'") - } - window.SetSize(*width, *height) - return unit, nil - case WindowSetTitle: - title := args.String("title") - if title == nil { - return nil, errs.NewInvalidWindowCallErrorf("missing or invalid argument 'title'") - } - window.SetTitle(*title) - return unit, nil - case WindowSetZoom: - zoom := args.Float64("zoom") - if zoom == nil { - return nil, errs.NewInvalidWindowCallErrorf("missing or invalid argument 'zoom'") - } - window.SetZoom(*zoom) - return unit, nil - case WindowShow: - window.Show() - return unit, nil - case WindowSize: - width, height := window.Size() - return map[string]interface{}{ - "width": width, - "height": height, - }, nil - case WindowOpenDevTools: - window.OpenDevTools() - return unit, nil - case WindowToggleFullscreen: - window.ToggleFullscreen() - return unit, nil - case WindowToggleMaximise: - window.ToggleMaximise() - return unit, nil - case WindowToggleFrameless: - window.ToggleFrameless() - return unit, nil - case WindowUnFullscreen: - window.UnFullscreen() - return unit, nil - case WindowUnMaximise: - window.UnMaximise() - return unit, nil - case WindowUnMinimise: - window.UnMinimise() - return unit, nil - case WindowWidth: - return window.Width(), nil - case WindowZoom: - window.Zoom() - return unit, nil - case WindowZoomIn: - window.ZoomIn() - return unit, nil - case WindowZoomOut: - window.ZoomOut() - return unit, nil - case WindowZoomReset: - window.ZoomReset() - return unit, nil - case WindowFilesDropped: - var payload fileDropPayload - err := req.Args.ToStruct(&payload) - if err != nil { - return nil, errs.WrapInvalidWindowCallErrorf(err, "error decoding file drop payload") - } - m.Debug( - "[DragDropDebug] processWindowMethod: Decoded payload from 'args'", - "payload", - fmt.Sprintf("%+v", payload), - ) - - dropTarget := &DropTargetDetails{ - X: payload.X, - Y: payload.Y, - ElementID: payload.ElementDetails.ID, - ClassList: payload.ElementDetails.ClassList, - Attributes: payload.ElementDetails.Attributes, - } - - wvWindow, ok := window.(*WebviewWindow) - if !ok { - return nil, errs.NewInvalidWindowCallErrorf("target window is not a WebviewWindow") - } - - msg := &dragAndDropMessage{ - windowId: wvWindow.id, - filenames: payload.Filenames, - DropTarget: dropTarget, - } - windowDragAndDropBuffer <- msg - return unit, nil - case WindowSnapAssist: - window.SnapAssist() - return unit, nil - case WindowPrint: - err := window.Print() - if err != nil { - return nil, fmt.Errorf("Window.Print failed: %w", err) - } - return unit, nil - default: - return nil, errs.NewInvalidWindowCallErrorf("Unknown method %d", req.Method) - } -} - -// ElementDetailsPayload holds detailed information about the drop target element. -type ElementDetailsPayload struct { - ID string `json:"id"` - ClassList []string `json:"classList"` - Attributes map[string]string `json:"attributes"` -} - -// Define a struct for the JSON payload from HandlePlatformFileDrop -type fileDropPayload struct { - Filenames []string `json:"filenames"` - X int `json:"x"` - Y int `json:"y"` - ElementDetails ElementDetailsPayload `json:"elementDetails"` -} diff --git a/v3/pkg/application/panic_handler.go b/v3/pkg/application/panic_handler.go deleted file mode 100644 index 53f42a309..000000000 --- a/v3/pkg/application/panic_handler.go +++ /dev/null @@ -1,104 +0,0 @@ -package application - -import ( - "fmt" - "runtime" - "runtime/debug" - "strings" - "time" -) - -func getStackTrace(skipStart int, skipEnd int) string { - // Get all program counters first - pc := make([]uintptr, 32) - n := runtime.Callers(skipStart+1, pc) - if n == 0 { - return "" - } - - pc = pc[:n] - frames := runtime.CallersFrames(pc) - - // Collect all frames first - var allFrames []runtime.Frame - for { - frame, more := frames.Next() - allFrames = append(allFrames, frame) - if !more { - break - } - } - - // Remove frames from the end - if len(allFrames) > skipEnd { - allFrames = allFrames[:len(allFrames)-skipEnd] - } - - // Build the output string - var builder strings.Builder - for _, frame := range allFrames { - fmt.Fprintf(&builder, "%s\n\tat %s:%d\n", - frame.Function, frame.File, frame.Line) - } - return builder.String() -} - -type handlePanicOptions struct { - skipEnd int -} - -type PanicDetails struct { - StackTrace string - Error error - Time time.Time - FullStackTrace string -} - -func newPanicDetails(err error, trace string) *PanicDetails { - return &PanicDetails{ - Error: err, - Time: time.Now(), - StackTrace: trace, - FullStackTrace: string(debug.Stack()), - } -} - -// handlePanic handles any panics -// Returns the error if there was one -func handlePanic(options ...handlePanicOptions) bool { - // Try to recover - e := recover() - if e == nil { - return false - } - - // Get the error - err, ok := e.(error) - if !ok { - err = fmt.Errorf("%v", e) - } - - // Get the stack trace - var stackTrace string - skipEnd := 0 - if len(options) > 0 { - skipEnd = options[0].skipEnd - } - stackTrace = getStackTrace(3, skipEnd) - - processPanic(newPanicDetails(err, stackTrace)) - return false -} - -func processPanic(panicDetails *PanicDetails) { - h := globalApplication.options.PanicHandler - if h != nil { - h(panicDetails) - return - } - defaultPanicHandler(panicDetails) -} - -func defaultPanicHandler(panicDetails *PanicDetails) { - globalApplication.fatal("panic error: %w\n%s", panicDetails.Error, panicDetails.StackTrace) -} diff --git a/v3/pkg/application/parameter_test.go b/v3/pkg/application/parameter_test.go deleted file mode 100644 index 3a106e48e..000000000 --- a/v3/pkg/application/parameter_test.go +++ /dev/null @@ -1,118 +0,0 @@ -package application - -import ( - "reflect" - "testing" -) - -func TestParameter_IsType(t *testing.T) { - param := &Parameter{ - Name: "test", - TypeName: "string", - } - - if !param.IsType("string") { - t.Error("IsType should return true for matching type") - } - - if param.IsType("int") { - t.Error("IsType should return false for non-matching type") - } -} - -func TestParameter_IsError(t *testing.T) { - errorParam := &Parameter{ - Name: "err", - TypeName: "error", - } - - if !errorParam.IsError() { - t.Error("IsError should return true for error type") - } - - stringParam := &Parameter{ - Name: "s", - TypeName: "string", - } - - if stringParam.IsError() { - t.Error("IsError should return false for non-error type") - } -} - -func TestNewParameter(t *testing.T) { - stringType := reflect.TypeOf("") - param := newParameter("myParam", stringType) - - if param.Name != "myParam" { - t.Errorf("Name = %q, want %q", param.Name, "myParam") - } - - if param.TypeName != "string" { - t.Errorf("TypeName = %q, want %q", param.TypeName, "string") - } - - if param.ReflectType != stringType { - t.Error("ReflectType not set correctly") - } -} - -func TestCallError_Error(t *testing.T) { - err := &CallError{ - Kind: ReferenceError, - Message: "test error", - } - - if err.Error() != "test error" { - t.Errorf("Error() = %q, want %q", err.Error(), "test error") - } -} - -func TestCallError_Kinds(t *testing.T) { - tests := []struct { - kind ErrorKind - expected string - }{ - {ReferenceError, "ReferenceError"}, - {TypeError, "TypeError"}, - {RuntimeError, "RuntimeError"}, - } - - for _, tt := range tests { - if string(tt.kind) != tt.expected { - t.Errorf("ErrorKind = %q, want %q", string(tt.kind), tt.expected) - } - } -} - -func TestCallError_WithCause(t *testing.T) { - cause := map[string]string{"detail": "some detail"} - err := &CallError{ - Kind: RuntimeError, - Message: "runtime error occurred", - Cause: cause, - } - - if err.Error() != "runtime error occurred" { - t.Error("Error() should return the message") - } - - if err.Cause == nil { - t.Error("Cause should be set") - } -} - -func TestCallOptions_Fields(t *testing.T) { - opts := CallOptions{ - MethodID: 12345, - MethodName: "TestService.Method", - } - - if opts.MethodID != 12345 { - t.Error("MethodID not set correctly") - } - - if opts.MethodName != "TestService.Method" { - t.Error("MethodName not set correctly") - } -} diff --git a/v3/pkg/application/path.go b/v3/pkg/application/path.go deleted file mode 100644 index 44066fa96..000000000 --- a/v3/pkg/application/path.go +++ /dev/null @@ -1,133 +0,0 @@ -package application - -import "github.com/adrg/xdg" - -type PathType int - -const ( - // PathHome is the user's home directory. - PathHome PathType = iota - - // PathDataHome defines the base directory relative to which user-specific - // data files should be stored. This directory is defined by the - // $XDG_DATA_HOME environment variable. If the variable is not set, - // a default equal to $HOME/.local/share should be used. - PathDataHome - - // PathConfigHome defines the base directory relative to which user-specific - // configuration files should be written. This directory is defined by - // the $XDG_CONFIG_HOME environment variable. If the variable is - // not set, a default equal to $HOME/.config should be used. - PathConfigHome - - // PathStateHome defines the base directory relative to which user-specific - // state files should be stored. This directory is defined by the - // $XDG_STATE_HOME environment variable. If the variable is not set, - // a default equal to ~/.local/state should be used. - PathStateHome - - // PathCacheHome defines the base directory relative to which user-specific - // non-essential (cached) data should be written. This directory is - // defined by the $XDG_CACHE_HOME environment variable. If the variable - // is not set, a default equal to $HOME/.cache should be used. - PathCacheHome - - // PathRuntimeDir defines the base directory relative to which user-specific - // non-essential runtime files and other file objects (such as sockets, - // named pipes, etc.) should be stored. This directory is defined by the - // $XDG_RUNTIME_DIR environment variable. If the variable is not set, - // applications should fall back to a replacement directory with similar - // capabilities. Applications should use this directory for communication - // and synchronization purposes and should not place larger files in it, - // since it might reside in runtime memory and cannot necessarily be - // swapped out to disk. - PathRuntimeDir - - // PathDesktop defines the location of the user's desktop directory. - PathDesktop - - // PathDownload defines a suitable location for user downloaded files. - PathDownload - - // PathDocuments defines a suitable location for user document files. - PathDocuments - - // PathMusic defines a suitable location for user audio files. - PathMusic - - // PathPictures defines a suitable location for user image files. - PathPictures - - // PathVideos defines a suitable location for user video files. - PathVideos - - // PathTemplates defines a suitable location for user template files. - PathTemplates - - // PathPublicShare defines a suitable location for user shared files. - PathPublicShare -) - -var paths = map[PathType]string{ - PathHome: xdg.Home, - PathDataHome: xdg.DataHome, - PathConfigHome: xdg.ConfigHome, - PathStateHome: xdg.StateHome, - PathCacheHome: xdg.CacheHome, - PathRuntimeDir: xdg.RuntimeDir, - PathDesktop: xdg.UserDirs.Desktop, - PathDownload: xdg.UserDirs.Download, - PathDocuments: xdg.UserDirs.Documents, - PathMusic: xdg.UserDirs.Music, - PathPictures: xdg.UserDirs.Pictures, - PathVideos: xdg.UserDirs.Videos, - PathTemplates: xdg.UserDirs.Templates, - PathPublicShare: xdg.UserDirs.PublicShare, -} - -type PathTypes int - -const ( - // PathsDataDirs defines the preference-ordered set of base directories to - // search for data files in addition to the DataHome base directory. - // This set of directories is defined by the $XDG_DATA_DIRS environment - // variable. If the variable is not set, the default directories - // to be used are /usr/local/share and /usr/share, in that order. The - // DataHome directory is considered more important than any of the - // directories defined by DataDirs. Therefore, user data files should be - // written relative to the DataHome directory, if possible. - PathsDataDirs PathTypes = iota - - // PathsConfigDirs defines the preference-ordered set of base directories - // search for configuration files in addition to the ConfigHome base - // directory. This set of directories is defined by the $XDG_CONFIG_DIRS - // environment variable. If the variable is not set, a default equal - // to /etc/xdg should be used. The ConfigHome directory is considered - // more important than any of the directories defined by ConfigDirs. - // Therefore, user config files should be written relative to the - // ConfigHome directory, if possible. - PathsConfigDirs - - // PathsFontDirs defines the common locations where font files are stored. - PathsFontDirs - - // PathsApplicationDirs defines the common locations of applications. - PathsApplicationDirs -) - -var pathdirs = map[PathTypes][]string{ - PathsDataDirs: xdg.DataDirs, - PathsConfigDirs: xdg.ConfigDirs, - PathsFontDirs: xdg.FontDirs, - PathsApplicationDirs: xdg.ApplicationDirs, -} - -// Path returns the path for the given selector -func Path(selector PathType) string { - return paths[selector] -} - -// Paths returns the paths for the given selector -func Paths(selector PathTypes) []string { - return pathdirs[selector] -} diff --git a/v3/pkg/application/popupmenu_windows.go b/v3/pkg/application/popupmenu_windows.go deleted file mode 100644 index ed809a130..000000000 --- a/v3/pkg/application/popupmenu_windows.go +++ /dev/null @@ -1,314 +0,0 @@ -package application - -import ( - "sync/atomic" - "unsafe" - - "github.com/wailsapp/wails/v3/pkg/w32" -) - -const ( - MenuItemMsgID = w32.WM_APP + 1024 -) - -type RadioGroupMember struct { - ID int - MenuItem *MenuItem -} - -type RadioGroup []*RadioGroupMember - -func (r *RadioGroup) Add(id int, item *MenuItem) { - *r = append(*r, &RadioGroupMember{ - ID: id, - MenuItem: item, - }) -} - -func (r *RadioGroup) Bounds() (int, int) { - p := *r - return p[0].ID, p[len(p)-1].ID -} - -func (r *RadioGroup) MenuID(item *MenuItem) int { - for _, member := range *r { - if member.MenuItem == item { - return member.ID - } - } - panic("RadioGroup.MenuID: item not found:") -} - -type Win32Menu struct { - isPopup bool - menu w32.HMENU - parentWindow *windowsWebviewWindow - parent w32.HWND - menuMapping map[int]*MenuItem - checkboxItems map[*MenuItem][]int - radioGroups map[*MenuItem][]*RadioGroup - menuData *Menu - currentMenuID int - onMenuClose func() - onMenuOpen func() - isShowing atomic.Bool // guards against concurrent TrackPopupMenuEx calls -} - -func (p *Win32Menu) newMenu() w32.HMENU { - if p.isPopup { - return w32.NewPopupMenu() - } - return w32.CreateMenu() -} - -func (p *Win32Menu) buildMenu(parentMenu w32.HMENU, inputMenu *Menu) { - currentRadioGroup := RadioGroup{} - for _, item := range inputMenu.items { - p.currentMenuID++ - itemID := p.currentMenuID - p.menuMapping[itemID] = item - - menuItemImpl := newMenuItemImpl(item, parentMenu, itemID) - menuItemImpl.parent = inputMenu - item.impl = menuItemImpl - - if item.Hidden() { - if item.accelerator != nil { - if p.parentWindow != nil { - // Remove the accelerator from the keybindings - p.parentWindow.parent.removeMenuBinding(item.accelerator) - } else { - // Remove the global keybindings - globalApplication.KeyBinding.Remove(item.accelerator.String()) - } - } - } - - flags := uint32(w32.MF_STRING) - if item.disabled { - flags = flags | w32.MF_GRAYED - } - if item.checked { - flags = flags | w32.MF_CHECKED - } - if item.IsSeparator() { - flags = flags | w32.MF_SEPARATOR - } - - if item.checked && item.IsRadio() { - flags = flags | w32.MFT_RADIOCHECK - } - - if item.IsCheckbox() { - p.checkboxItems[item] = append(p.checkboxItems[item], itemID) - } - if item.IsRadio() { - currentRadioGroup.Add(itemID, item) - } else { - if len(currentRadioGroup) > 0 { - for _, radioMember := range currentRadioGroup { - currentRadioGroup := currentRadioGroup - p.radioGroups[radioMember.MenuItem] = append(p.radioGroups[radioMember.MenuItem], ¤tRadioGroup) - } - currentRadioGroup = RadioGroup{} - } - } - - if item.submenu != nil { - flags = flags | w32.MF_POPUP - newSubmenu := p.newMenu() - p.buildMenu(newSubmenu, item.submenu) - itemID = int(newSubmenu) - menuItemImpl.submenu = newSubmenu - } - - var menuText = item.Label() - if item.accelerator != nil { - menuText = menuText + "\t" + item.accelerator.String() - if item.callback != nil { - if p.parentWindow != nil { - p.parentWindow.parent.addMenuBinding(item.accelerator, item) - } else { - globalApplication.KeyBinding.Add(item.accelerator.String(), func(w Window) { - item.handleClick() - }) - } - } - } - - // If the item is hidden, don't append - if item.Hidden() { - continue - } - - ok := w32.AppendMenu(parentMenu, flags, uintptr(itemID), w32.MustStringToUTF16Ptr(menuText)) - if !ok { - globalApplication.fatal("error adding menu item '%s'", menuText) - } - if item.bitmap != nil { - if err := w32.SetMenuIcons(parentMenu, itemID, item.bitmap, nil); err != nil { - globalApplication.fatal("error setting menu icons: %w", err) - } - } - } - if len(currentRadioGroup) > 0 { - for _, radioMember := range currentRadioGroup { - currentRadioGroup := currentRadioGroup - p.radioGroups[radioMember.MenuItem] = append(p.radioGroups[radioMember.MenuItem], ¤tRadioGroup) - } - currentRadioGroup = RadioGroup{} - } -} - -func (p *Win32Menu) Update() { - p.menu = p.newMenu() - p.menuMapping = make(map[int]*MenuItem) - p.currentMenuID = MenuItemMsgID - p.buildMenu(p.menu, p.menuData) - p.updateRadioGroups() -} - -func NewPopupMenu(parent w32.HWND, inputMenu *Menu) *Win32Menu { - result := &Win32Menu{ - isPopup: true, - parent: parent, - menuData: inputMenu, - checkboxItems: make(map[*MenuItem][]int), - radioGroups: make(map[*MenuItem][]*RadioGroup), - } - result.Update() - return result -} -func NewApplicationMenu(parent *windowsWebviewWindow, inputMenu *Menu) *Win32Menu { - result := &Win32Menu{ - parentWindow: parent, - parent: parent.hwnd, - menuData: inputMenu, - checkboxItems: make(map[*MenuItem][]int), - radioGroups: make(map[*MenuItem][]*RadioGroup), - } - result.Update() - return result -} - -func (p *Win32Menu) ShowAt(x int, y int) { - // Prevent concurrent menu displays - TrackPopupMenuEx is blocking and - // calling it while another popup is showing causes "TrackPopupMenu failed" - if !p.isShowing.CompareAndSwap(false, true) { - return - } - defer p.isShowing.Store(false) - - w32.SetForegroundWindow(p.parent) - - if p.onMenuOpen != nil { - p.onMenuOpen() - } - - // Get screen dimensions to determine menu positioning - monitor := w32.MonitorFromWindow(p.parent, w32.MONITOR_DEFAULTTONEAREST) - var monitorInfo w32.MONITORINFO - monitorInfo.CbSize = uint32(unsafe.Sizeof(monitorInfo)) - if !w32.GetMonitorInfo(monitor, &monitorInfo) { - globalApplication.fatal("GetMonitorInfo failed") - } - - // Set flags to always position the menu above the cursor - menuFlags := uint32(w32.TPM_LEFTALIGN | w32.TPM_BOTTOMALIGN) - - // Check if we're close to the right edge of the screen - // If so, right-align the menu with some padding - if x > int(monitorInfo.RcWork.Right)-200 { // Assuming 200px as a reasonable menu width - menuFlags = uint32(w32.TPM_RIGHTALIGN | w32.TPM_BOTTOMALIGN) - // Add a small padding (10px) from the right edge - x = int(monitorInfo.RcWork.Right) - 10 - } - - if !w32.TrackPopupMenuEx(p.menu, menuFlags, int32(x), int32(y), p.parent, nil) { - // TrackPopupMenuEx can fail if called during menu transitions or rapid clicks. - // This is not fatal - just skip this menu display attempt. - globalApplication.debug("TrackPopupMenu failed - menu may already be showing") - return - } - - if p.onMenuClose != nil { - p.onMenuClose() - } - - if !w32.PostMessage(p.parent, w32.WM_NULL, 0, 0) { - globalApplication.fatal("PostMessage failed") - } - -} - -func (p *Win32Menu) ShowAtCursor() { - x, y, ok := w32.GetCursorPos() - if ok == false { - globalApplication.fatal("GetCursorPos failed") - } - - p.ShowAt(x, y) -} - -func (p *Win32Menu) ProcessCommand(cmdMsgID int) bool { - item := p.menuMapping[cmdMsgID] - if item == nil { - return false - } - if item.IsRadio() { - if item.checked { - return true - } - item.checked = true - p.updateRadioGroup(item) - } - if item.callback != nil { - item.handleClick() - } - return true -} - -func (p *Win32Menu) Destroy() { - w32.DestroyMenu(p.menu) -} - -func (p *Win32Menu) UpdateMenuItem(item *MenuItem) { - if item.IsCheckbox() { - for _, itemID := range p.checkboxItems[item] { - var checkState uint = w32.MF_UNCHECKED - if item.checked { - checkState = w32.MF_CHECKED - } - w32.CheckMenuItem(p.menu, uintptr(itemID), checkState) - } - return - } - if item.IsRadio() && item.checked == true { - p.updateRadioGroup(item) - } -} - -func (p *Win32Menu) updateRadioGroups() { - for menuItem := range p.radioGroups { - if menuItem.checked { - p.updateRadioGroup(menuItem) - } - } -} - -func (p *Win32Menu) updateRadioGroup(item *MenuItem) { - for _, radioGroup := range p.radioGroups[item] { - thisMenuID := radioGroup.MenuID(item) - startID, endID := radioGroup.Bounds() - w32.CheckRadio(p.menu, startID, endID, thisMenuID) - - } -} - -func (p *Win32Menu) OnMenuOpen(fn func()) { - p.onMenuOpen = fn -} - -func (p *Win32Menu) OnMenuClose(fn func()) { - p.onMenuClose = fn -} diff --git a/v3/pkg/application/roles.go b/v3/pkg/application/roles.go deleted file mode 100644 index 78bbf2c38..000000000 --- a/v3/pkg/application/roles.go +++ /dev/null @@ -1,164 +0,0 @@ -package application - -import "runtime" - -// Heavily inspired by Electron (c) 2013-2020 Github Inc. -// Electron License: https://github.com/electron/electron/blob/master/LICENSE - -// Role is a type to identify menu roles -type Role uint - -// These constants need to be kept in sync with `v2/internal/frontend/desktop/darwin/Role.h` -const ( - NoRole Role = iota - AppMenu Role = iota - EditMenu Role = iota - ViewMenu Role = iota - WindowMenu Role = iota - ServicesMenu Role = iota - HelpMenu Role = iota - - Hide Role = iota - HideOthers Role = iota - ShowAll Role = iota - BringAllToFront Role = iota - UnHide Role = iota - About Role = iota - Undo Role = iota - Redo Role = iota - Cut Role = iota - Copy Role = iota - Paste Role = iota - PasteAndMatchStyle Role = iota - SelectAll Role = iota - Delete Role = iota - SpeechMenu Role = iota - Quit Role = iota - FileMenu Role = iota - CloseWindow Role = iota - Reload Role = iota - ForceReload Role = iota - OpenDevTools Role = iota - ResetZoom Role = iota - ZoomIn Role = iota - ZoomOut Role = iota - ToggleFullscreen Role = iota - - Minimise Role = iota - Zoom Role = iota - FullScreen Role = iota - - NewFile Role = iota - Open Role = iota - Save Role = iota - SaveAs Role = iota - StartSpeaking Role = iota - StopSpeaking Role = iota - Revert Role = iota - Print Role = iota - PageLayout Role = iota - Find Role = iota - FindAndReplace Role = iota - FindNext Role = iota - FindPrevious Role = iota - Front Role = iota - Help Role = iota -) - -func NewFileMenu() *MenuItem { - fileMenu := NewMenu() - if runtime.GOOS == "darwin" { - fileMenu.AddRole(CloseWindow) - } else { - fileMenu.AddRole(Quit) - } - subMenu := NewSubMenuItem("File") - subMenu.submenu = fileMenu - return subMenu -} - -func NewViewMenu() *MenuItem { - viewMenu := NewMenu() - viewMenu.AddRole(Reload) - viewMenu.AddRole(ForceReload) - addDevToolMenuItem(viewMenu) - viewMenu.AddSeparator() - viewMenu.AddRole(ResetZoom) - viewMenu.AddRole(ZoomIn) - viewMenu.AddRole(ZoomOut) - viewMenu.AddSeparator() - viewMenu.AddRole(ToggleFullscreen) - subMenu := NewSubMenuItem("View") - subMenu.submenu = viewMenu - return subMenu -} - -func NewAppMenu() *MenuItem { - if runtime.GOOS != "darwin" { - return nil - } - appMenu := NewMenu() - appMenu.AddRole(About) - appMenu.AddSeparator() - appMenu.AddRole(ServicesMenu) - appMenu.AddSeparator() - appMenu.AddRole(Hide) - appMenu.AddRole(HideOthers) - appMenu.AddRole(UnHide) - appMenu.AddSeparator() - appMenu.AddRole(Quit) - subMenu := NewSubMenuItem(globalApplication.options.Name) - subMenu.submenu = appMenu - return subMenu -} - -func NewEditMenu() *MenuItem { - editMenu := NewMenu() - editMenu.AddRole(Undo) - editMenu.AddRole(Redo) - editMenu.AddSeparator() - editMenu.AddRole(Cut) - editMenu.AddRole(Copy) - editMenu.AddRole(Paste) - if runtime.GOOS == "darwin" { - editMenu.AddRole(PasteAndMatchStyle) - editMenu.AddRole(Delete) - editMenu.AddRole(SelectAll) - editMenu.AddSeparator() - editMenu.AddRole(SpeechMenu) - } else { - editMenu.AddRole(Delete) - editMenu.AddSeparator() - editMenu.AddRole(SelectAll) - } - subMenu := NewSubMenuItem("Edit") - subMenu.submenu = editMenu - return subMenu -} - -func NewWindowMenu() *MenuItem { - menu := NewMenu() - menu.AddRole(Minimise) - menu.AddRole(Zoom) - if runtime.GOOS == "darwin" { - menu.AddSeparator() - menu.AddRole(Front) - //menu.AddSeparator() - //menu.AddRole(Window) - } else { - menu.AddRole(CloseWindow) - } - subMenu := NewSubMenuItem("Window") - subMenu.submenu = menu - return subMenu -} - -func NewHelpMenu() *MenuItem { - menu := NewMenu() - menu.Add("Learn More").OnClick(func(ctx *Context) { - globalApplication.Window.Current().SetURL("https://wails.io") - }) - subMenu := NewSubMenuItem("Help") - subMenu.submenu = menu - return subMenu -} diff --git a/v3/pkg/application/roles_dev.go b/v3/pkg/application/roles_dev.go deleted file mode 100644 index 1c03e398d..000000000 --- a/v3/pkg/application/roles_dev.go +++ /dev/null @@ -1,7 +0,0 @@ -//go:build !production || devtools - -package application - -func addDevToolMenuItem(viewMenu *Menu) { - viewMenu.AddRole(OpenDevTools) -} diff --git a/v3/pkg/application/roles_production.go b/v3/pkg/application/roles_production.go deleted file mode 100644 index d1af8dba7..000000000 --- a/v3/pkg/application/roles_production.go +++ /dev/null @@ -1,5 +0,0 @@ -//go:build production && !devtools - -package application - -func addDevToolMenuItem(viewMenu *Menu) {} diff --git a/v3/pkg/application/screen_android.go b/v3/pkg/application/screen_android.go deleted file mode 100644 index 03f03f280..000000000 --- a/v3/pkg/application/screen_android.go +++ /dev/null @@ -1,32 +0,0 @@ -//go:build android - -package application - -// getScreens returns the available screens for Android -func getScreens() ([]*Screen, error) { - // Android typically has one main display - // TODO: Support for multi-display via DisplayManager - return []*Screen{ - { - ID: "main", - Name: "Main Display", - IsPrimary: true, - Size: Size{ - Width: 1080, - Height: 2400, - }, - Bounds: Rect{ - X: 0, - Y: 0, - Width: 1080, - Height: 2400, - }, - WorkArea: Rect{ - X: 0, - Y: 0, - Width: 1080, - Height: 2340, // Minus navigation bar - }, - }, - }, nil -} diff --git a/v3/pkg/application/screen_darwin.go b/v3/pkg/application/screen_darwin.go deleted file mode 100644 index ba9859ff0..000000000 --- a/v3/pkg/application/screen_darwin.go +++ /dev/null @@ -1,194 +0,0 @@ -//go:build darwin && !ios - -package application - -/* -#cgo CFLAGS: -x objective-c -#cgo LDFLAGS: -framework Foundation -framework Cocoa -framework WebKit -framework AppKit -#import -#import -#import -#import -#include - -typedef struct Screen { - const char* id; - const char* name; - int p_width; - int p_height; - int width; - int height; - int x; - int y; - int w_width; - int w_height; - int w_x; - int w_y; - float scaleFactor; - double rotation; - bool isPrimary; -} Screen; - - -int GetNumScreens(){ - return [[NSScreen screens] count]; -} - -Screen processScreen(NSScreen* screen){ - Screen returnScreen; - returnScreen.scaleFactor = screen.backingScaleFactor; - - // screen bounds - returnScreen.height = screen.frame.size.height; - returnScreen.width = screen.frame.size.width; - returnScreen.x = screen.frame.origin.x; - returnScreen.y = screen.frame.origin.y; - - // work area - NSRect workArea = [screen visibleFrame]; - returnScreen.w_height = workArea.size.height; - returnScreen.w_width = workArea.size.width; - returnScreen.w_x = workArea.origin.x; - returnScreen.w_y = workArea.origin.y; - - - // adapted from https://stackoverflow.com/a/1237490/4188138 - NSDictionary* screenDictionary = [screen deviceDescription]; - NSNumber* screenID = [screenDictionary objectForKey:@"NSScreenNumber"]; - CGDirectDisplayID displayID = [screenID unsignedIntValue]; - returnScreen.id = [[NSString stringWithFormat:@"%d", displayID] UTF8String]; - - // Get physical monitor size - NSValue *sizeValue = [screenDictionary objectForKey:@"NSDeviceSize"]; - NSSize physicalSize = sizeValue.sizeValue; - returnScreen.p_height = physicalSize.height; - returnScreen.p_width = physicalSize.width; - - // Get the rotation - double rotation = CGDisplayRotation(displayID); - returnScreen.rotation = rotation; - -#if MAC_OS_X_VERSION_MAX_ALLOWED >= 101500 - if( @available(macOS 10.15, *) ){ - returnScreen.name = [screen.localizedName UTF8String]; - } -#endif - return returnScreen; -} - -// Get primary screen -Screen GetPrimaryScreen(){ - // Get primary screen - NSScreen *mainScreen = [NSScreen mainScreen]; - return processScreen(mainScreen); -} - -Screen* getAllScreens() { - NSArray *screens = [NSScreen screens]; - Screen* returnScreens = malloc(sizeof(Screen) * screens.count); - for (int i = 0; i < screens.count; i++) { - NSScreen* screen = [screens objectAtIndex:i]; - returnScreens[i] = processScreen(screen); - } - return returnScreens; -} - -Screen getScreenForWindow(void* window){ - NSScreen* screen = ((NSWindow*)window).screen; - return processScreen(screen); -} - -// Get the screen for the system tray -Screen getScreenForSystemTray(void* nsStatusItem) { - NSStatusItem *statusItem = (NSStatusItem *)nsStatusItem; - NSRect frame = statusItem.button.frame; - NSArray *screens = NSScreen.screens; - NSScreen *associatedScreen = nil; - - for (NSScreen *screen in screens) { - if (NSPointInRect(frame.origin, screen.frame)) { - associatedScreen = screen; - break; - } - } - return processScreen(associatedScreen); -} - -void* getWindowForSystray(void* nsStatusItem) { - NSStatusItem *statusItem = (NSStatusItem *)nsStatusItem; - return statusItem.button.window; -} - - -*/ -import "C" -import "unsafe" - -func cScreenToScreen(screen C.Screen) *Screen { - - return &Screen{ - Size: Size{ - Width: int(screen.p_width), - Height: int(screen.p_height), - }, - Bounds: Rect{ - X: int(screen.x), - Y: int(screen.y), - Height: int(screen.height), - Width: int(screen.width), - }, - PhysicalBounds: Rect{ - X: int(screen.x), - Y: int(screen.y), - Height: int(screen.height), - Width: int(screen.width), - }, - WorkArea: Rect{ - X: int(screen.w_x), - Y: int(screen.w_y), - Height: int(screen.w_height), - Width: int(screen.w_width), - }, - PhysicalWorkArea: Rect{ - X: int(screen.w_x), - Y: int(screen.w_y), - Height: int(screen.w_height), - Width: int(screen.w_width), - }, - ScaleFactor: float32(screen.scaleFactor), - ID: C.GoString(screen.id), - Name: C.GoString(screen.name), - IsPrimary: bool(screen.isPrimary), - Rotation: float32(screen.rotation), - } -} - -func (m *macosApp) getPrimaryScreen() (*Screen, error) { - cScreen := C.GetPrimaryScreen() - return cScreenToScreen(cScreen), nil -} - -func (m *macosApp) getScreens() ([]*Screen, error) { - cScreens := C.getAllScreens() - defer C.free(unsafe.Pointer(cScreens)) - numScreens := int(C.GetNumScreens()) - displays := make([]*Screen, numScreens) - cScreenHeaders := (*[1 << 30]C.Screen)(unsafe.Pointer(cScreens))[:numScreens:numScreens] - for i := 0; i < numScreens; i++ { - displays[i] = cScreenToScreen(cScreenHeaders[i]) - } - return displays, nil -} - -func getScreenForWindow(window *macosWebviewWindow) (*Screen, error) { - cScreen := C.getScreenForWindow(window.nsWindow) - return cScreenToScreen(cScreen), nil -} - -func getScreenForSystray(systray *macosSystemTray) (*Screen, error) { - // Get the Window for the status item - // https://stackoverflow.com/a/5875019/4188138 - window := C.getWindowForSystray(systray.nsStatusItem) - cScreen := C.getScreenForWindow(window) - return cScreenToScreen(cScreen), nil -} diff --git a/v3/pkg/application/screen_ios.go b/v3/pkg/application/screen_ios.go deleted file mode 100644 index 7c3dfdbdd..000000000 --- a/v3/pkg/application/screen_ios.go +++ /dev/null @@ -1,33 +0,0 @@ -//go:build ios - -package application - -// getScreens returns all screens on iOS - Screen type is defined in screenmanager.go - -// getScreens returns all screens on iOS -func getScreens() ([]*Screen, error) { - // iOS typically has one screen - // This would need proper implementation with UIScreen - mainRect := Rect{ - X: 0, - Y: 0, - Width: 1170, // iPhone 12 Pro width - Height: 2532, // iPhone 12 Pro height - } - return []*Screen{ - { - ID: "main", - Name: "Main Screen", - ScaleFactor: 3.0, // iPhone 12 Pro scale - X: 0, - Y: 0, - Size: Size{Width: 1170, Height: 2532}, - Bounds: mainRect, - PhysicalBounds: mainRect, - WorkArea: mainRect, - PhysicalWorkArea: mainRect, - IsPrimary: true, - Rotation: 0, - }, - }, nil -} \ No newline at end of file diff --git a/v3/pkg/application/screen_linux.go b/v3/pkg/application/screen_linux.go deleted file mode 100644 index 60507f554..000000000 --- a/v3/pkg/application/screen_linux.go +++ /dev/null @@ -1,37 +0,0 @@ -//go:build linux && !android && !server - -package application - -import ( - "sync" -) - -func (a *linuxApp) getPrimaryScreen() (*Screen, error) { - var wg sync.WaitGroup - var screen *Screen - var err error - wg.Add(1) - InvokeSync(func() { - screen, err = getPrimaryScreen() - wg.Done() - }) - wg.Wait() - return screen, err -} - -func (a *linuxApp) getScreens() ([]*Screen, error) { - var wg sync.WaitGroup - var screens []*Screen - var err error - wg.Add(1) - InvokeSync(func() { - screens, err = getScreens(a.application) - wg.Done() - }) - wg.Wait() - return screens, err -} - -func getScreenForWindow(window *linuxWebviewWindow) (*Screen, error) { - return window.getScreen() -} diff --git a/v3/pkg/application/screen_windows.go b/v3/pkg/application/screen_windows.go deleted file mode 100644 index b6328f809..000000000 --- a/v3/pkg/application/screen_windows.go +++ /dev/null @@ -1,88 +0,0 @@ -//go:build windows - -package application - -import ( - "errors" - "strconv" - - "github.com/wailsapp/wails/v3/pkg/w32" - "golang.org/x/sys/windows" -) - -func (m *windowsApp) processAndCacheScreens() error { - allScreens, err := w32.GetAllScreens() - if err != nil { - return err - } - - // Convert result to []*Screen - var screens []*Screen - - for _, screen := range allScreens { - x := int(screen.MONITORINFOEX.RcMonitor.Left) - y := int(screen.MONITORINFOEX.RcMonitor.Top) - right := int(screen.MONITORINFOEX.RcMonitor.Right) - bottom := int(screen.MONITORINFOEX.RcMonitor.Bottom) - width := right - x - height := bottom - y - - workArea := Rect{ - X: int(screen.MONITORINFOEX.RcWork.Left), - Y: int(screen.MONITORINFOEX.RcWork.Top), - Width: int(screen.MONITORINFOEX.RcWork.Right - screen.MONITORINFOEX.RcWork.Left), - Height: int(screen.MONITORINFOEX.RcWork.Bottom - screen.MONITORINFOEX.RcWork.Top), - } - - screens = append(screens, &Screen{ - ID: hMonitorToScreenID(screen.HMonitor), - Name: windows.UTF16ToString(screen.MONITORINFOEX.SzDevice[:]), - X: x, - Y: y, - Size: Size{Width: width, Height: height}, - Bounds: Rect{X: x, Y: y, Width: width, Height: height}, - PhysicalBounds: Rect{X: x, Y: y, Width: width, Height: height}, - WorkArea: workArea, - PhysicalWorkArea: workArea, - IsPrimary: screen.IsPrimary, - ScaleFactor: screen.ScaleFactor, - Rotation: 0, - }) - } - - err = m.parent.Screen.LayoutScreens(screens) - if err != nil { - return err - } - - return nil -} - -// NOTE: should be moved to *App after DPI is implemented in all platforms -func (m *windowsApp) getScreens() ([]*Screen, error) { - return m.parent.Screen.screens, nil -} - -// NOTE: should be moved to *App after DPI is implemented in all platforms -func (m *windowsApp) getPrimaryScreen() (*Screen, error) { - return m.parent.Screen.primaryScreen, nil -} - -func getScreenForWindow(window *windowsWebviewWindow) (*Screen, error) { - return ScreenNearestPhysicalRect(window.physicalBounds()), nil -} - -func getScreenForWindowHwnd(hwnd w32.HWND) (*Screen, error) { - hMonitor := w32.MonitorFromWindow(hwnd, w32.MONITOR_DEFAULTTONEAREST) - screenID := hMonitorToScreenID(hMonitor) - for _, screen := range globalApplication.Screen.screens { - if screen.ID == screenID { - return screen, nil - } - } - return nil, errors.New("screen not found for window") -} - -func hMonitorToScreenID(hMonitor uintptr) string { - return strconv.Itoa(int(hMonitor)) -} diff --git a/v3/pkg/application/screenmanager.go b/v3/pkg/application/screenmanager.go deleted file mode 100644 index 6caa1cd33..000000000 --- a/v3/pkg/application/screenmanager.go +++ /dev/null @@ -1,875 +0,0 @@ -package application - -import ( - "errors" - "math" - "sort" -) - -// Heavily inspired by the Chromium project (Copyright 2015 The Chromium Authors) -// Chromium License: https://chromium.googlesource.com/chromium/src/+/HEAD/LICENSE - -type ScreenManager struct { - app *App - screens []*Screen - primaryScreen *Screen -} - -// newScreenManager creates a new ScreenManager instance -func newScreenManager(app *App) *ScreenManager { - return &ScreenManager{ - app: app, - } -} - -type Screen struct { - ID string // A unique identifier for the display - Name string // The name of the display - ScaleFactor float32 // The scale factor of the display (DPI/96) - X int // The x-coordinate of the top-left corner of the rectangle - Y int // The y-coordinate of the top-left corner of the rectangle - Size Size // The size of the display - Bounds Rect // The bounds of the display - PhysicalBounds Rect // The physical bounds of the display (before scaling) - WorkArea Rect // The work area of the display - PhysicalWorkArea Rect // The physical work area of the display (before scaling) - IsPrimary bool // Whether this is the primary display - Rotation float32 // The rotation of the display -} - -type Rect struct { - X int - Y int - Width int - Height int -} - -type Point struct { - X int - Y int -} -type Size struct { - Width int - Height int -} - -type Alignment int -type OffsetReference int - -const ( - TOP Alignment = iota - RIGHT - BOTTOM - LEFT -) - -const ( - BEGIN OffsetReference = iota // TOP or LEFT - END // BOTTOM or RIGHT -) - -// ScreenPlacement specifies where the screen (S) is placed relative to -// parent (P) screen. In the following example, (S) is RIGHT aligned to (P) -// with a positive offset and a BEGIN (top) offset reference. -// -// . +------------+ + -// . | | | offset -// . | P | v -// . | +--------+ -// . | | | -// . +------------+ S | -// . | | -// . +--------+ -type ScreenPlacement struct { - screen *Screen - parent *Screen - alignment Alignment - offset int - offsetReference OffsetReference -} - -func (r Rect) Origin() Point { - return Point{ - X: r.X, - Y: r.Y, - } -} - -func (s Screen) Origin() Point { - return Point{ - X: s.X, - Y: s.Y, - } -} - -func (r Rect) Corner() Point { - return Point{ - X: r.right(), - Y: r.bottom(), - } -} - -func (r Rect) InsideCorner() Point { - return Point{ - X: r.right() - 1, - Y: r.bottom() - 1, - } -} - -func (r Rect) right() int { - return r.X + r.Width -} - -func (r Rect) bottom() int { - return r.Y + r.Height -} - -func (s Screen) right() int { - return s.Bounds.right() -} - -func (s Screen) bottom() int { - return s.Bounds.bottom() -} - -func (s Screen) scale(value int, toDip bool) int { - // Round up when scaling down and round down when scaling up. - // This mix rounding strategy prevents drift over time when applying multiple scaling back and forth. - // In addition, It has been shown that using this approach minimized rounding issues and improved overall - // precision when converting between DIP and physical coordinates. - if toDip { - return int(math.Ceil(float64(value) / float64(s.ScaleFactor))) - } else { - return int(math.Floor(float64(value) * float64(s.ScaleFactor))) - } -} - -func (r Rect) Size() Size { - return Size{ - Width: r.Width, - Height: r.Height, - } -} - -func (r Rect) IsEmpty() bool { - return r.Width <= 0 || r.Height <= 0 -} - -func (r Rect) Contains(pt Point) bool { - return pt.X >= r.X && pt.X < r.X+r.Width && pt.Y >= r.Y && pt.Y < r.Y+r.Height -} - -// Get intersection with another rect -func (r Rect) Intersect(otherRect Rect) Rect { - if r.IsEmpty() || otherRect.IsEmpty() { - return Rect{} - } - - maxLeft := max(r.X, otherRect.X) - maxTop := max(r.Y, otherRect.Y) - minRight := min(r.right(), otherRect.right()) - minBottom := min(r.bottom(), otherRect.bottom()) - - if minRight > maxLeft && minBottom > maxTop { - return Rect{ - X: maxLeft, - Y: maxTop, - Width: minRight - maxLeft, - Height: minBottom - maxTop, - } - } - return Rect{} -} - -// Check if screens intersects another screen -func (s *Screen) intersects(otherScreen *Screen) bool { - maxLeft := max(s.X, otherScreen.X) - maxTop := max(s.Y, otherScreen.Y) - minRight := min(s.right(), otherScreen.right()) - minBottom := min(s.bottom(), otherScreen.bottom()) - - return minRight > maxLeft && minBottom > maxTop -} - -// Get distance from another rect (squared) -func (r Rect) distanceFromRectSquared(otherRect Rect) int { - // If they intersect, return negative area of intersection - intersection := r.Intersect(otherRect) - if !intersection.IsEmpty() { - return -(intersection.Width * intersection.Height) - } - - dX := max(0, max(r.X-otherRect.right(), otherRect.X-r.right())) - dY := max(0, max(r.Y-otherRect.bottom(), otherRect.Y-r.bottom())) - - // Distance squared - return dX*dX + dY*dY -} - -// Apply screen placement -func (p ScreenPlacement) apply() { - parentBounds := p.parent.Bounds - screenBounds := p.screen.Bounds - - newX := parentBounds.X - newY := parentBounds.Y - offset := p.offset - - if p.alignment == TOP || p.alignment == BOTTOM { - if p.offsetReference == END { - offset = parentBounds.Width - offset - screenBounds.Width - } - offset = min(offset, parentBounds.Width) - offset = max(offset, -screenBounds.Width) - newX += offset - if p.alignment == TOP { - newY -= screenBounds.Height - } else { - newY += parentBounds.Height - } - } else { - if p.offsetReference == END { - offset = parentBounds.Height - offset - screenBounds.Height - } - offset = min(offset, parentBounds.Height) - offset = max(offset, -screenBounds.Height) - newY += offset - if p.alignment == LEFT { - newX -= screenBounds.Width - } else { - newX += parentBounds.Width - } - } - - p.screen.move(newX, newY) -} - -func (s *Screen) absoluteToRelativeDipPoint(dipPoint Point) Point { - return Point{ - X: dipPoint.X - s.Bounds.X, - Y: dipPoint.Y - s.Bounds.Y, - } -} - -func (s *Screen) relativeToAbsoluteDipPoint(dipPoint Point) Point { - return Point{ - X: dipPoint.X + s.Bounds.X, - Y: dipPoint.Y + s.Bounds.Y, - } -} - -func (s *Screen) absoluteToRelativePhysicalPoint(physicalPoint Point) Point { - return Point{ - X: physicalPoint.X - s.PhysicalBounds.X, - Y: physicalPoint.Y - s.PhysicalBounds.Y, - } -} - -func (s *Screen) relativeToAbsolutePhysicalPoint(physicalPoint Point) Point { - return Point{ - X: physicalPoint.X + s.PhysicalBounds.X, - Y: physicalPoint.Y + s.PhysicalBounds.Y, - } -} - -func (s *Screen) move(newX, newY int) { - workAreaOffsetX := s.WorkArea.X - s.X - workAreaOffsetY := s.WorkArea.Y - s.Y - - s.X = newX - s.Y = newY - s.Bounds.X = newX - s.Bounds.Y = newY - s.WorkArea.X = newX + workAreaOffsetX - s.WorkArea.Y = newY + workAreaOffsetY -} - -func (s *Screen) applyDPIScaling() { - if s.ScaleFactor == 1 { - return - } - workAreaOffsetX := s.WorkArea.X - s.Bounds.X - workAreaOffsetY := s.WorkArea.Y - s.Bounds.Y - - s.WorkArea.X = s.Bounds.X + s.scale(workAreaOffsetX, true) - s.WorkArea.Y = s.Bounds.Y + s.scale(workAreaOffsetY, true) - - s.Bounds.Width = s.scale(s.PhysicalBounds.Width, true) - s.Bounds.Height = s.scale(s.PhysicalBounds.Height, true) - s.WorkArea.Width = s.scale(s.PhysicalWorkArea.Width, true) - s.WorkArea.Height = s.scale(s.PhysicalWorkArea.Height, true) - - s.Size.Width = s.Bounds.Width - s.Size.Height = s.Bounds.Height -} - -func (s *Screen) dipToPhysicalPoint(dipPoint Point, isCorner bool) Point { - relativePoint := s.absoluteToRelativeDipPoint(dipPoint) - scaledRelativePoint := Point{ - X: s.scale(relativePoint.X, false), - Y: s.scale(relativePoint.Y, false), - } - // Align edge points (fixes rounding issues) - edgeOffset := 1 - if isCorner { - edgeOffset = 0 - } - if relativePoint.X == s.Bounds.Width-edgeOffset { - scaledRelativePoint.X = s.PhysicalBounds.Width - edgeOffset - } - if relativePoint.Y == s.Bounds.Height-edgeOffset { - scaledRelativePoint.Y = s.PhysicalBounds.Height - edgeOffset - } - return s.relativeToAbsolutePhysicalPoint(scaledRelativePoint) -} - -func (s *Screen) physicalToDipPoint(physicalPoint Point, isCorner bool) Point { - relativePoint := s.absoluteToRelativePhysicalPoint(physicalPoint) - scaledRelativePoint := Point{ - X: s.scale(relativePoint.X, true), - Y: s.scale(relativePoint.Y, true), - } - // Align edge points (fixes rounding issues) - edgeOffset := 1 - if isCorner { - edgeOffset = 0 - } - if relativePoint.X == s.PhysicalBounds.Width-edgeOffset { - scaledRelativePoint.X = s.Bounds.Width - edgeOffset - } - if relativePoint.Y == s.PhysicalBounds.Height-edgeOffset { - scaledRelativePoint.Y = s.Bounds.Height - edgeOffset - } - return s.relativeToAbsoluteDipPoint(scaledRelativePoint) -} - -func (s *Screen) dipToPhysicalRect(dipRect Rect) Rect { - origin := s.dipToPhysicalPoint(dipRect.Origin(), false) - corner := s.dipToPhysicalPoint(dipRect.Corner(), true) - - return Rect{ - X: origin.X, - Y: origin.Y, - Width: corner.X - origin.X, - Height: corner.Y - origin.Y, - } -} - -func (s *Screen) physicalToDipRect(physicalRect Rect) Rect { - origin := s.physicalToDipPoint(physicalRect.Origin(), false) - corner := s.physicalToDipPoint(physicalRect.Corner(), true) - - return Rect{ - X: origin.X, - Y: origin.Y, - Width: corner.X - origin.X, - Height: corner.Y - origin.Y, - } -} - -// Layout screens in the virtual space with DIP calculations and cache the screens -// for future coordinate transformation between the physical and logical (DIP) space -func (m *ScreenManager) LayoutScreens(screens []*Screen) error { - if screens == nil || len(screens) == 0 { - return errors.New("screens parameter is nil or empty") - } - m.screens = screens - - err := m.calculateScreensDipCoordinates() - if err != nil { - return err - } - - return nil -} - -func (m *ScreenManager) GetAll() []*Screen { - return m.screens -} - -func (m *ScreenManager) GetPrimary() *Screen { - return m.primaryScreen -} - -// Reference: https://source.chromium.org/chromium/chromium/src/+/main:ui/display/win/screen_win.cc;l=317 -func (m *ScreenManager) calculateScreensDipCoordinates() error { - remainingScreens := []*Screen{} - - // Find the primary screen - m.primaryScreen = nil - for _, screen := range m.screens { - if screen.IsPrimary { - m.primaryScreen = screen - } else { - remainingScreens = append(remainingScreens, screen) - } - } - if m.primaryScreen == nil { - return errors.New("no primary screen found") - } else if len(remainingScreens) != len(m.screens)-1 { - return errors.New("invalid primary screen found") - } - - // Build screens tree using the primary screen as root - screensPlacements := []ScreenPlacement{} - availableParents := []*Screen{m.primaryScreen} - for len(availableParents) > 0 { - // Pop a parent - end := len(availableParents) - 1 - parent := availableParents[end] - availableParents = availableParents[:end] - // Find touching screens - for _, child := range m.findAndRemoveTouchingScreens(parent, &remainingScreens) { - screenPlacement := m.calculateScreenPlacement(child, parent) - screensPlacements = append(screensPlacements, screenPlacement) - availableParents = append(availableParents, child) - } - } - - // Apply screens DPI scaling and placement starting with - // the primary screen and then dependent screens - m.primaryScreen.applyDPIScaling() - for _, placement := range screensPlacements { - placement.screen.applyDPIScaling() - placement.apply() - } - - // Now that all the placements have been applied, - // we must detect and fix any overlapping screens. - m.deIntersectScreens(screensPlacements) - - return nil -} - -// Returns a ScreenPlacement for |screen| relative to |parent|. -// Note that ScreenPlacement's are always in DIPs, so this also performs the -// required scaling. -// References: -// - https://github.com/chromium/chromium/blob/main/ui/display/win/scaling_util.h#L25 -// - https://github.com/chromium/chromium/blob/main/ui/display/win/scaling_util.cc#L142 -func (m *ScreenManager) calculateScreenPlacement(screen, parent *Screen) ScreenPlacement { - // Examples (The offset is indicated by the arrow.): - // Scaled and Unscaled Coordinates - // +--------------+ + Since both screens are of the same scale - // | | | factor, relative positions remain the same. - // | Parent | V - // | 1x +----------+ - // | | | - // +--------------+ Screen | - // | 1x | - // +----------+ - // - // Unscaled Coordinates - // +--------------+ The 2x screen is offset to maintain a - // | | similar neighboring relationship with the 1x - // | Parent | parent. Screen's position is based off of the - // | 1x +----------+ percentage position along its parent. This - // | | | percentage position is preserved in the scaled - // +--------------+ Screen | coordinates. - // | 2x | - // +----------+ - // Scaled Coordinates - // +--------------+ + - // | | | - // | Parent | V - // | 1x +-----+ - // | | S 2x| - // +--------------+-----+ - // - // - // Unscaled Coordinates - // +--------------+ The parent screen has a 2x scale factor. - // | | The offset is adjusted to maintain the - // | | relative positioning of the 1x screen in - // | Parent +----------+ the scaled coordinate space. Screen's - // | 2x | | position is based off of the percentage - // | | Screen | position along its parent. This percentage - // | | 1x | position is preserved in the scaled - // +--------------+ | coordinates. - // | | - // +----------+ - // Scaled Coordinates - // +-------+ + - // | | V - // | Parent+----------+ - // | 2x | | - // +-------+ Screen | - // | 1x | - // | | - // | | - // +----------+ - // - // Unscaled Coordinates - // +----------+ In this case, parent lies between the top and - // | | bottom of parent. The roles are reversed when - // +-------+ | this occurs, and screen is placed to maintain - // | | Screen | parent's relative position along screen. - // | Parent| 1x | - // | 2x | | - // +-------+ | - // +----------+ - // Scaled Coordinates - // ^ +----------+ - // | | | - // + +----+ | - // |Prnt| Screen | - // | 2x | 1x | - // +----+ | - // | | - // +----------+ - // - // Scaled and Unscaled Coordinates - // +--------+ If the two screens are bottom aligned or - // | | right aligned, the ScreenPlacement will - // | +--------+ have an offset of 0 relative to the - // | | | end of the screen. - // | | | - // +--------+--------+ - - placement := ScreenPlacement{ - screen: screen, - parent: parent, - alignment: m.getScreenAlignment(screen, parent), - offset: 0, - offsetReference: BEGIN, - } - - screenBegin, screenEnd := 0, 0 - parentBegin, parentEnd := 0, 0 - - switch placement.alignment { - case TOP, BOTTOM: - screenBegin = screen.X - screenEnd = screen.right() - parentBegin = parent.X - parentEnd = parent.right() - case LEFT, RIGHT: - screenBegin = screen.Y - screenEnd = screen.bottom() - parentBegin = parent.Y - parentEnd = parent.bottom() - } - - // Since we're calculating offsets, make everything relative to parentBegin - parentEnd -= parentBegin - screenBegin -= parentBegin - screenEnd -= parentBegin - parentBegin = 0 - - // There are a few ways lines can intersect: - // End Aligned - // SCREEN's offset is relative to the END (BOTTOM or RIGHT). - // +-PARENT----------------+ - // +-SCREEN-------------+ - // - // Positioning based off of |screenBegin|. - // SCREEN's offset is simply a percentage of its position on PARENT. - // +-PARENT----------------+ - // ^+-SCREEN------------+ - // - // Positioning based off of |screenEnd|. - // SCREEN's offset is dependent on the percentage of its end position on PARENT. - // +-PARENT----------------+ - // +-SCREEN------------+^ - // - // Positioning based off of |parentBegin| on SCREEN. - // SCREEN's offset is dependent on the percentage of its position on PARENT. - // +-PARENT----------------+ - // ^+-SCREEN--------------------------+ - - if screenEnd == parentEnd { - placement.offsetReference = END - placement.offset = 0 - } else if screenBegin >= parentBegin { - placement.offsetReference = BEGIN - placement.offset = m.scaleOffset(parentEnd, parent.ScaleFactor, screenBegin) - } else if screenEnd <= parentEnd { - placement.offsetReference = END - placement.offset = m.scaleOffset(parentEnd, parent.ScaleFactor, parentEnd-screenEnd) - } else { - placement.offsetReference = BEGIN - placement.offset = m.scaleOffset(screenEnd-screenBegin, screen.ScaleFactor, screenBegin) - } - - return placement -} - -// Get screen alignment relative to parent (TOP, RIGHT, BOTTOM, LEFT) -func (m *ScreenManager) getScreenAlignment(screen, parent *Screen) Alignment { - maxLeft := max(screen.X, parent.X) - maxTop := max(screen.Y, parent.Y) - minRight := min(screen.right(), parent.right()) - minBottom := min(screen.bottom(), parent.bottom()) - - // Corners touching - if maxLeft == minRight && maxTop == minBottom { - if screen.Y == maxTop { - return BOTTOM - } else if parent.X == maxLeft { - return LEFT - } - return TOP - } - - // Vertical edge touching - if maxLeft == minRight { - if screen.X == maxLeft { - return RIGHT - } else { - return LEFT - } - } - - // Horizontal edge touching - if maxTop == minBottom { - if screen.Y == maxTop { - return BOTTOM - } else { - return TOP - } - } - - return -1 // Shouldn't be reached -} - -func (m *ScreenManager) deIntersectScreens(screensPlacements []ScreenPlacement) { - parentIDMap := make(map[string]string) - for _, placement := range screensPlacements { - parentIDMap[placement.screen.ID] = placement.parent.ID - } - - treeDepthMap := make(map[string]int) - for _, screen := range m.screens { - id, ok, depth := screen.ID, true, 0 - const maxDepth = 100 - for id != m.primaryScreen.ID && depth < maxDepth { - depth++ - id, ok = parentIDMap[id] - if !ok { - depth = maxDepth - } - } - treeDepthMap[screen.ID] = depth - } - - sortedScreens := make([]*Screen, len(m.screens)) - copy(sortedScreens, m.screens) - - // Sort the screens first by their depth in the screen hierarchy tree, - // and then by distance from screen origin to primary origin. This way we - // process the screens starting at the root (the primary screen), in the - // order of their descendance spanning out from the primary screen. - sort.Slice(sortedScreens, func(i, j int) bool { - s1, s2 := m.screens[i], m.screens[j] - s1_depth := treeDepthMap[s1.ID] - s2_depth := treeDepthMap[s2.ID] - - if s1_depth != s2_depth { - return s1_depth < s2_depth - } - - // Distance squared - s1_distance := s1.X*s1.X + s1.Y*s1.Y - s2_distance := s2.X*s2.X + s2.Y*s2.Y - if s1_distance != s2_distance { - return s1_distance < s2_distance - } - - return s1.ID < s2.ID - }) - - for i := 1; i < len(sortedScreens); i++ { - targetScreen := sortedScreens[i] - for j := 0; j < i; j++ { - sourceScreen := sortedScreens[j] - if targetScreen.intersects(sourceScreen) { - m.fixScreenIntersection(targetScreen, sourceScreen) - } - } - } -} - -// Offset the target screen along either X or Y axis away from the origin -// so that it removes the intersection with the source screen -// This function assume both screens already intersect. -func (m *ScreenManager) fixScreenIntersection(targetScreen, sourceScreen *Screen) { - offsetX, offsetY := 0, 0 - - if targetScreen.X >= 0 { - offsetX = sourceScreen.right() - targetScreen.X - } else { - offsetX = -(targetScreen.right() - sourceScreen.X) - } - - if targetScreen.Y >= 0 { - offsetY = sourceScreen.bottom() - targetScreen.Y - } else { - offsetY = -(targetScreen.bottom() - sourceScreen.Y) - } - - // Choose the smaller offset (X or Y) - if math.Abs(float64(offsetX)) <= math.Abs(float64(offsetY)) { - offsetY = 0 - } else { - offsetX = 0 - } - - // Apply the offset - newX := targetScreen.X + offsetX - newY := targetScreen.Y + offsetY - targetScreen.move(newX, newY) -} - -func (m *ScreenManager) findAndRemoveTouchingScreens(parent *Screen, screens *[]*Screen) []*Screen { - touchingScreens := []*Screen{} - remainingScreens := []*Screen{} - - for _, screen := range *screens { - if m.areScreensTouching(parent, screen) { - touchingScreens = append(touchingScreens, screen) - } else { - remainingScreens = append(remainingScreens, screen) - } - } - *screens = remainingScreens - return touchingScreens -} - -func (m *ScreenManager) areScreensTouching(a, b *Screen) bool { - maxLeft := max(a.X, b.X) - maxTop := max(a.Y, b.Y) - minRight := min(a.right(), b.right()) - minBottom := min(a.bottom(), b.bottom()) - return (maxLeft == minRight && maxTop <= minBottom) || (maxTop == minBottom && maxLeft <= minRight) -} - -// Scale |unscaledOffset| to the same relative position on |unscaledLength| -// based off of |unscaledLength|'s |scaleFactor| -func (m *ScreenManager) scaleOffset(unscaledLength int, scaleFactor float32, unscaledOffset int) int { - scaledLength := float32(unscaledLength) / scaleFactor - percent := float32(unscaledOffset) / float32(unscaledLength) - return int(math.Floor(float64(scaledLength * percent))) -} - -func (m *ScreenManager) screenNearestPoint(point Point, isPhysical bool) *Screen { - for _, screen := range m.screens { - if isPhysical { - if screen.PhysicalBounds.Contains(point) { - return screen - } - } else { - if screen.Bounds.Contains(point) { - return screen - } - } - } - return m.primaryScreen -} - -func (m *ScreenManager) screenNearestRect(rect Rect, isPhysical bool, excludedScreens map[string]bool) *Screen { - var nearestScreen *Screen - var distance, nearestScreenDistance int - for _, screen := range m.screens { - if excludedScreens[screen.ID] { - continue - } - if isPhysical { - distance = rect.distanceFromRectSquared(screen.PhysicalBounds) - } else { - distance = rect.distanceFromRectSquared(screen.Bounds) - } - if nearestScreen == nil || distance < nearestScreenDistance { - nearestScreen = screen - nearestScreenDistance = distance - } - } - if !isPhysical && len(excludedScreens) < len(m.screens)-1 { - // Make sure to give the same screen that would be given by the physical rect - // of this dip rect so transforming back and forth always gives the same result. - // This is important because it could happen that a dip rect intersects Screen1 - // more than Screen2 but in the physical layout Screen2 will scale up or Screen1 - // will scale down causing the intersection area to change so transforming back - // would give a different rect. - physicalRect := nearestScreen.dipToPhysicalRect(rect) - physicalRectScreen := m.screenNearestRect(physicalRect, true, nil) - if nearestScreen != physicalRectScreen { - if excludedScreens == nil { - excludedScreens = make(map[string]bool) - } - excludedScreens[nearestScreen.ID] = true - return m.screenNearestRect(rect, isPhysical, excludedScreens) - } - } - return nearestScreen -} - -func (m *ScreenManager) DipToPhysicalPoint(dipPoint Point) Point { - screen := m.ScreenNearestDipPoint(dipPoint) - return screen.dipToPhysicalPoint(dipPoint, false) -} - -func (m *ScreenManager) PhysicalToDipPoint(physicalPoint Point) Point { - screen := m.ScreenNearestPhysicalPoint(physicalPoint) - return screen.physicalToDipPoint(physicalPoint, false) -} - -func (m *ScreenManager) DipToPhysicalRect(dipRect Rect) Rect { - screen := m.ScreenNearestDipRect(dipRect) - return screen.dipToPhysicalRect(dipRect) -} - -func (m *ScreenManager) PhysicalToDipRect(physicalRect Rect) Rect { - screen := m.ScreenNearestPhysicalRect(physicalRect) - return screen.physicalToDipRect(physicalRect) -} - -func (m *ScreenManager) ScreenNearestPhysicalPoint(physicalPoint Point) *Screen { - return m.screenNearestPoint(physicalPoint, true) -} - -func (m *ScreenManager) ScreenNearestDipPoint(dipPoint Point) *Screen { - return m.screenNearestPoint(dipPoint, false) -} - -func (m *ScreenManager) ScreenNearestPhysicalRect(physicalRect Rect) *Screen { - return m.screenNearestRect(physicalRect, true, nil) -} - -func (m *ScreenManager) ScreenNearestDipRect(dipRect Rect) *Screen { - return m.screenNearestRect(dipRect, false, nil) -} - -// ================================================================================================ -// Exported application-level methods for internal convenience and availability to application devs - -func DipToPhysicalPoint(dipPoint Point) Point { - return globalApplication.Screen.DipToPhysicalPoint(dipPoint) -} - -func PhysicalToDipPoint(physicalPoint Point) Point { - return globalApplication.Screen.PhysicalToDipPoint(physicalPoint) -} - -func DipToPhysicalRect(dipRect Rect) Rect { - return globalApplication.Screen.DipToPhysicalRect(dipRect) -} - -func PhysicalToDipRect(physicalRect Rect) Rect { - return globalApplication.Screen.PhysicalToDipRect(physicalRect) -} - -func ScreenNearestPhysicalPoint(physicalPoint Point) *Screen { - return globalApplication.Screen.ScreenNearestPhysicalPoint(physicalPoint) -} - -func ScreenNearestDipPoint(dipPoint Point) *Screen { - return globalApplication.Screen.ScreenNearestDipPoint(dipPoint) -} - -func ScreenNearestPhysicalRect(physicalRect Rect) *Screen { - return globalApplication.Screen.ScreenNearestPhysicalRect(physicalRect) -} - -func ScreenNearestDipRect(dipRect Rect) *Screen { - return globalApplication.Screen.ScreenNearestDipRect(dipRect) -} diff --git a/v3/pkg/application/screenmanager_internal_test.go b/v3/pkg/application/screenmanager_internal_test.go deleted file mode 100644 index 9445c1f6d..000000000 --- a/v3/pkg/application/screenmanager_internal_test.go +++ /dev/null @@ -1,435 +0,0 @@ -package application - -import ( - "testing" -) - -func TestAlignment_Constants(t *testing.T) { - if TOP != 0 { - t.Error("TOP should be 0") - } - if RIGHT != 1 { - t.Error("RIGHT should be 1") - } - if BOTTOM != 2 { - t.Error("BOTTOM should be 2") - } - if LEFT != 3 { - t.Error("LEFT should be 3") - } -} - -func TestOffsetReference_Constants(t *testing.T) { - if BEGIN != 0 { - t.Error("BEGIN should be 0") - } - if END != 1 { - t.Error("END should be 1") - } -} - -func TestRect_Origin(t *testing.T) { - rect := Rect{X: 10, Y: 20, Width: 100, Height: 200} - origin := rect.Origin() - - if origin.X != 10 { - t.Errorf("origin.X = %d, want 10", origin.X) - } - if origin.Y != 20 { - t.Errorf("origin.Y = %d, want 20", origin.Y) - } -} - -func TestRect_Corner(t *testing.T) { - rect := Rect{X: 10, Y: 20, Width: 100, Height: 200} - corner := rect.Corner() - - if corner.X != 110 { // 10 + 100 - t.Errorf("corner.X = %d, want 110", corner.X) - } - if corner.Y != 220 { // 20 + 200 - t.Errorf("corner.Y = %d, want 220", corner.Y) - } -} - -func TestRect_InsideCorner(t *testing.T) { - rect := Rect{X: 10, Y: 20, Width: 100, Height: 200} - inside := rect.InsideCorner() - - if inside.X != 109 { // 10 + 100 - 1 - t.Errorf("inside.X = %d, want 109", inside.X) - } - if inside.Y != 219 { // 20 + 200 - 1 - t.Errorf("inside.Y = %d, want 219", inside.Y) - } -} - -func TestRect_right(t *testing.T) { - rect := Rect{X: 10, Y: 20, Width: 100, Height: 200} - if rect.right() != 110 { - t.Errorf("right() = %d, want 110", rect.right()) - } -} - -func TestRect_bottom(t *testing.T) { - rect := Rect{X: 10, Y: 20, Width: 100, Height: 200} - if rect.bottom() != 220 { - t.Errorf("bottom() = %d, want 220", rect.bottom()) - } -} - -func TestRect_Size(t *testing.T) { - rect := Rect{X: 10, Y: 20, Width: 100, Height: 200} - size := rect.Size() - - if size.Width != 100 { - t.Errorf("Width = %d, want 100", size.Width) - } - if size.Height != 200 { - t.Errorf("Height = %d, want 200", size.Height) - } -} - -func TestRect_IsEmpty(t *testing.T) { - tests := []struct { - rect Rect - expected bool - }{ - {Rect{X: 0, Y: 0, Width: 0, Height: 0}, true}, - {Rect{X: 0, Y: 0, Width: 100, Height: 0}, true}, - {Rect{X: 0, Y: 0, Width: 0, Height: 100}, true}, - {Rect{X: 0, Y: 0, Width: -1, Height: 100}, true}, - {Rect{X: 0, Y: 0, Width: 100, Height: -1}, true}, - {Rect{X: 0, Y: 0, Width: 100, Height: 200}, false}, - {Rect{X: 10, Y: 20, Width: 1, Height: 1}, false}, - } - - for _, tt := range tests { - result := tt.rect.IsEmpty() - if result != tt.expected { - t.Errorf("Rect%v.IsEmpty() = %v, want %v", tt.rect, result, tt.expected) - } - } -} - -func TestRect_Contains(t *testing.T) { - rect := Rect{X: 10, Y: 20, Width: 100, Height: 200} - - tests := []struct { - point Point - expected bool - }{ - {Point{X: 10, Y: 20}, true}, // top-left corner - {Point{X: 50, Y: 100}, true}, // inside - {Point{X: 109, Y: 219}, true}, // inside corner - {Point{X: 110, Y: 220}, false}, // corner (exclusive) - {Point{X: 0, Y: 0}, false}, // outside - {Point{X: 9, Y: 20}, false}, // left of rect - {Point{X: 10, Y: 19}, false}, // above rect - {Point{X: 111, Y: 100}, false}, // right of rect - {Point{X: 50, Y: 221}, false}, // below rect - } - - for _, tt := range tests { - result := rect.Contains(tt.point) - if result != tt.expected { - t.Errorf("Rect%v.Contains(%v) = %v, want %v", rect, tt.point, result, tt.expected) - } - } -} - -func TestRect_Intersect(t *testing.T) { - tests := []struct { - name string - r1 Rect - r2 Rect - expected Rect - }{ - { - name: "overlapping", - r1: Rect{X: 0, Y: 0, Width: 100, Height: 100}, - r2: Rect{X: 50, Y: 50, Width: 100, Height: 100}, - expected: Rect{X: 50, Y: 50, Width: 50, Height: 50}, - }, - { - name: "no overlap - horizontal", - r1: Rect{X: 0, Y: 0, Width: 100, Height: 100}, - r2: Rect{X: 200, Y: 0, Width: 100, Height: 100}, - expected: Rect{}, - }, - { - name: "no overlap - vertical", - r1: Rect{X: 0, Y: 0, Width: 100, Height: 100}, - r2: Rect{X: 0, Y: 200, Width: 100, Height: 100}, - expected: Rect{}, - }, - { - name: "contained", - r1: Rect{X: 0, Y: 0, Width: 100, Height: 100}, - r2: Rect{X: 25, Y: 25, Width: 50, Height: 50}, - expected: Rect{X: 25, Y: 25, Width: 50, Height: 50}, - }, - { - name: "identical", - r1: Rect{X: 10, Y: 20, Width: 100, Height: 100}, - r2: Rect{X: 10, Y: 20, Width: 100, Height: 100}, - expected: Rect{X: 10, Y: 20, Width: 100, Height: 100}, - }, - { - name: "empty rect 1", - r1: Rect{}, - r2: Rect{X: 0, Y: 0, Width: 100, Height: 100}, - expected: Rect{}, - }, - { - name: "empty rect 2", - r1: Rect{X: 0, Y: 0, Width: 100, Height: 100}, - r2: Rect{}, - expected: Rect{}, - }, - { - name: "touching edges - no intersection", - r1: Rect{X: 0, Y: 0, Width: 100, Height: 100}, - r2: Rect{X: 100, Y: 0, Width: 100, Height: 100}, - expected: Rect{}, - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - result := tt.r1.Intersect(tt.r2) - if result != tt.expected { - t.Errorf("Intersect: got %v, want %v", result, tt.expected) - } - }) - } -} - -func TestRect_distanceFromRectSquared(t *testing.T) { - tests := []struct { - name string - r1 Rect - r2 Rect - expected int - }{ - { - name: "overlapping - negative area", - r1: Rect{X: 0, Y: 0, Width: 100, Height: 100}, - r2: Rect{X: 50, Y: 50, Width: 100, Height: 100}, - expected: -(50 * 50), // intersection area - }, - { - name: "horizontal gap", - r1: Rect{X: 0, Y: 0, Width: 100, Height: 100}, - r2: Rect{X: 110, Y: 0, Width: 100, Height: 100}, - expected: 100, // gap of 10, squared - }, - { - name: "vertical gap", - r1: Rect{X: 0, Y: 0, Width: 100, Height: 100}, - r2: Rect{X: 0, Y: 120, Width: 100, Height: 100}, - expected: 400, // gap of 20, squared - }, - { - name: "diagonal gap", - r1: Rect{X: 0, Y: 0, Width: 100, Height: 100}, - r2: Rect{X: 110, Y: 110, Width: 100, Height: 100}, - expected: 200, // dX=10, dY=10, 10^2 + 10^2 = 200 - }, - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - result := tt.r1.distanceFromRectSquared(tt.r2) - if result != tt.expected { - t.Errorf("distanceFromRectSquared: got %d, want %d", result, tt.expected) - } - }) - } -} - -func TestScreen_Origin(t *testing.T) { - screen := Screen{X: 100, Y: 200} - origin := screen.Origin() - - if origin.X != 100 { - t.Errorf("origin.X = %d, want 100", origin.X) - } - if origin.Y != 200 { - t.Errorf("origin.Y = %d, want 200", origin.Y) - } -} - -func TestScreen_scale(t *testing.T) { - screen := Screen{ScaleFactor: 2.0} - - tests := []struct { - value int - toDip bool - expected int - }{ - {100, true, 50}, // to DIP: 100 / 2 = 50 - {100, false, 200}, // to physical: 100 * 2 = 200 - {101, true, 51}, // to DIP: ceil(101 / 2) = 51 - {101, false, 202}, // to physical: floor(101 * 2) = 202 - {0, true, 0}, - {0, false, 0}, - } - - for _, tt := range tests { - result := screen.scale(tt.value, tt.toDip) - if result != tt.expected { - t.Errorf("scale(%d, %v) = %d, want %d", tt.value, tt.toDip, result, tt.expected) - } - } -} - -func TestScreen_scale_1_5(t *testing.T) { - screen := Screen{ScaleFactor: 1.5} - - tests := []struct { - value int - toDip bool - expected int - }{ - {150, true, 100}, // to DIP: ceil(150 / 1.5) = 100 - {100, false, 150}, // to physical: floor(100 * 1.5) = 150 - {100, true, 67}, // to DIP: ceil(100 / 1.5) = 67 - {67, false, 100}, // to physical: floor(67 * 1.5) = 100 - } - - for _, tt := range tests { - result := screen.scale(tt.value, tt.toDip) - if result != tt.expected { - t.Errorf("scale(%d, %v) with factor 1.5 = %d, want %d", tt.value, tt.toDip, result, tt.expected) - } - } -} - -func TestScreen_right(t *testing.T) { - screen := Screen{ - Bounds: Rect{X: 100, Y: 0, Width: 200, Height: 100}, - } - if screen.right() != 300 { - t.Errorf("right() = %d, want 300", screen.right()) - } -} - -func TestScreen_bottom(t *testing.T) { - screen := Screen{ - Bounds: Rect{X: 0, Y: 100, Width: 100, Height: 200}, - } - if screen.bottom() != 300 { - t.Errorf("bottom() = %d, want 300", screen.bottom()) - } -} - -func TestScreen_intersects(t *testing.T) { - screen1 := &Screen{ - X: 0, - Y: 0, - Bounds: Rect{X: 0, Y: 0, Width: 100, Height: 100}, - } - - screen2 := &Screen{ - X: 50, - Y: 50, - Bounds: Rect{X: 50, Y: 50, Width: 100, Height: 100}, - } - - screen3 := &Screen{ - X: 200, - Y: 0, - Bounds: Rect{X: 200, Y: 0, Width: 100, Height: 100}, - } - - if !screen1.intersects(screen2) { - t.Error("screen1 and screen2 should intersect") - } - if screen1.intersects(screen3) { - t.Error("screen1 and screen3 should not intersect") - } -} - -func TestPoint_Fields(t *testing.T) { - pt := Point{X: 10, Y: 20} - if pt.X != 10 || pt.Y != 20 { - t.Error("Point fields not set correctly") - } -} - -func TestSize_Fields(t *testing.T) { - size := Size{Width: 100, Height: 200} - if size.Width != 100 || size.Height != 200 { - t.Error("Size fields not set correctly") - } -} - -func TestScreen_Fields(t *testing.T) { - screen := Screen{ - ID: "display-1", - Name: "Primary Display", - ScaleFactor: 2.0, - X: 0, - Y: 0, - Size: Size{Width: 1920, Height: 1080}, - Bounds: Rect{X: 0, Y: 0, Width: 1920, Height: 1080}, - IsPrimary: true, - Rotation: 0, - } - - if screen.ID != "display-1" { - t.Error("ID not set correctly") - } - if screen.Name != "Primary Display" { - t.Error("Name not set correctly") - } - if screen.ScaleFactor != 2.0 { - t.Error("ScaleFactor not set correctly") - } - if !screen.IsPrimary { - t.Error("IsPrimary not set correctly") - } -} - -func TestScreenPlacement_Fields(t *testing.T) { - parent := &Screen{ID: "parent"} - child := &Screen{ID: "child"} - - placement := ScreenPlacement{ - screen: child, - parent: parent, - alignment: RIGHT, - offset: 100, - offsetReference: BEGIN, - } - - if placement.screen != child { - t.Error("screen not set correctly") - } - if placement.parent != parent { - t.Error("parent not set correctly") - } - if placement.alignment != RIGHT { - t.Error("alignment not set correctly") - } - if placement.offset != 100 { - t.Error("offset not set correctly") - } - if placement.offsetReference != BEGIN { - t.Error("offsetReference not set correctly") - } -} - -func TestNewScreenManager(t *testing.T) { - sm := newScreenManager(nil) - if sm == nil { - t.Fatal("newScreenManager returned nil") - } - if sm.screens != nil { - t.Error("screens should be nil initially") - } - if sm.primaryScreen != nil { - t.Error("primaryScreen should be nil initially") - } -} diff --git a/v3/pkg/application/screenmanager_test.go b/v3/pkg/application/screenmanager_test.go deleted file mode 100644 index 1e58e3fd1..000000000 --- a/v3/pkg/application/screenmanager_test.go +++ /dev/null @@ -1,716 +0,0 @@ -package application_test - -import ( - "fmt" - "math" - "slices" - "strconv" - "testing" - - "github.com/matryer/is" - "github.com/wailsapp/wails/v3/pkg/application" -) - -type ScreenDef struct { - id int - w, h int - s float32 - parent ScreenDefParent - name string -} - -type ScreenDefParent struct { - id int - align string - offset int -} - -type ScreensLayout struct { - name string - screens []ScreenDef -} - -type ParsedLayout struct { - name string - screens []*application.Screen -} - -func exampleLayouts() []ParsedLayout { - layouts := [][]ScreensLayout{ - { - // Normal examples (demonstrate real life scenarios) - { - name: "Single 4k monitor", - screens: []ScreenDef{ - {id: 1, w: 3840, h: 2160, s: 163.0 / 96, name: `27" 4K UHD 163DPI`}, - }, - }, - { - name: "Two monitors", - screens: []ScreenDef{ - {id: 1, w: 3840, h: 2160, s: 163.0 / 96, name: `27" 4K UHD 163DPI`}, - {id: 2, w: 1920, h: 1080, s: 1, parent: ScreenDefParent{id: 1, align: "r", offset: 0}, name: `23" FHD 96DPI`}, - }, - }, - { - name: "Two monitors (2)", - screens: []ScreenDef{ - {id: 1, w: 1920, h: 1080, s: 1, name: `23" FHD 96DPI`}, - {id: 2, w: 1920, h: 1080, s: 1.25, parent: ScreenDefParent{id: 1, align: "r", offset: 0}, name: `23" FHD 96DPI (125%)`}, - }, - }, - { - name: "Three monitors", - screens: []ScreenDef{ - {id: 1, w: 3840, h: 2160, s: 163.0 / 96, name: `27" 4K UHD 163DPI`}, - {id: 2, w: 1920, h: 1080, s: 1, parent: ScreenDefParent{id: 1, align: "r", offset: 0}, name: `23" FHD 96DPI`}, - {id: 3, w: 1920, h: 1080, s: 1.25, parent: ScreenDefParent{id: 1, align: "l", offset: 0}, name: `23" FHD 96DPI (125%)`}, - }, - }, - { - name: "Four monitors", - screens: []ScreenDef{ - {id: 1, w: 3840, h: 2160, s: 163.0 / 96, name: `27" 4K UHD 163DPI`}, - {id: 2, w: 1920, h: 1080, s: 1, parent: ScreenDefParent{id: 1, align: "r", offset: 0}, name: `23" FHD 96DPI`}, - {id: 3, w: 1920, h: 1080, s: 1.25, parent: ScreenDefParent{id: 2, align: "b", offset: 0}, name: `23" FHD 96DPI (125%)`}, - {id: 4, w: 1080, h: 1920, s: 1, parent: ScreenDefParent{id: 1, align: "l", offset: 0}, name: `23" FHD (90deg)`}, - }, - }, - }, - { - // Test cases examples (demonstrate the algorithm basics) - { - name: "Child scaled, Start offset", - screens: []ScreenDef{ - {id: 1, w: 1200, h: 1200, s: 1, name: "Parent"}, - {id: 2, w: 1200, h: 1200, s: 1.5, parent: ScreenDefParent{id: 1, align: "r", offset: 600}, name: "Child"}, - }, - }, - { - name: "Child scaled, End offset", - screens: []ScreenDef{ - {id: 1, w: 1200, h: 1200, s: 1, name: "Parent"}, - {id: 2, w: 1200, h: 1200, s: 1.5, parent: ScreenDefParent{id: 1, align: "r", offset: -600}, name: "Child"}, - }, - }, - { - name: "Parent scaled, Start offset percent", - screens: []ScreenDef{ - {id: 1, w: 1200, h: 1200, s: 1.5, name: "Parent"}, - {id: 2, w: 1200, h: 1200, s: 1, parent: ScreenDefParent{id: 1, align: "r", offset: 600}, name: "Child"}, - }, - }, - { - name: "Parent scaled, End offset percent", - screens: []ScreenDef{ - {id: 1, w: 1200, h: 1200, s: 1.5, name: "Parent"}, - {id: 2, w: 1200, h: 1200, s: 1, parent: ScreenDefParent{id: 1, align: "r", offset: -600}, name: "Child"}, - }, - }, - { - name: "Parent scaled, Start align", - screens: []ScreenDef{ - {id: 1, w: 1200, h: 1200, s: 1.5, name: "Parent"}, - {id: 2, w: 1200, h: 1100, s: 1, parent: ScreenDefParent{id: 1, align: "r", offset: 0}, name: "Child"}, - }, - }, - { - name: "Parent scaled, End align", - screens: []ScreenDef{ - {id: 1, w: 1200, h: 1200, s: 1.5, name: "Parent"}, - {id: 2, w: 1200, h: 1200, s: 1, parent: ScreenDefParent{id: 1, align: "r", offset: 0}, name: "Child"}, - }, - }, - { - name: "Parent scaled, in-between", - screens: []ScreenDef{ - {id: 1, w: 1200, h: 1200, s: 1.5, name: "Parent"}, - {id: 2, w: 1200, h: 1500, s: 1, parent: ScreenDefParent{id: 1, align: "r", offset: -250}, name: "Child"}, - }, - }, - }, - { - // Edge cases examples - { - name: "Parent order (5 is parent of 4)", - screens: []ScreenDef{ - {id: 1, w: 1920, h: 1080, s: 1}, - {id: 2, w: 1024, h: 600, s: 1.25, parent: ScreenDefParent{id: 1, align: "r", offset: -200}}, - {id: 3, w: 800, h: 800, s: 1.25, parent: ScreenDefParent{id: 2, align: "b", offset: 0}}, - {id: 4, w: 800, h: 1080, s: 1.5, parent: ScreenDefParent{id: 2, align: "re", offset: 100}}, - {id: 5, w: 600, h: 600, s: 1, parent: ScreenDefParent{id: 3, align: "r", offset: 100}}, - }, - }, - { - name: "de-intersection reparent", - screens: []ScreenDef{ - {id: 1, w: 1920, h: 1080, s: 1}, - {id: 2, w: 1680, h: 1050, s: 1.25, parent: ScreenDefParent{id: 1, align: "r", offset: 10}}, - {id: 3, w: 1440, h: 900, s: 1.5, parent: ScreenDefParent{id: 1, align: "le", offset: 150}}, - {id: 4, w: 1024, h: 768, s: 1, parent: ScreenDefParent{id: 3, align: "bc", offset: -200}}, - {id: 5, w: 1024, h: 768, s: 1.25, parent: ScreenDefParent{id: 4, align: "r", offset: 400}}, - }, - }, - { - name: "de-intersection (unattached child)", - screens: []ScreenDef{ - {id: 1, w: 1920, h: 1080, s: 1}, - {id: 2, w: 1024, h: 768, s: 1.5, parent: ScreenDefParent{id: 1, align: "le", offset: 10}}, - {id: 3, w: 1024, h: 768, s: 1.25, parent: ScreenDefParent{id: 2, align: "b", offset: 100}}, - {id: 4, w: 1024, h: 768, s: 1, parent: ScreenDefParent{id: 3, align: "r", offset: 500}}, - }, - }, - { - name: "Multiple de-intersection", - screens: []ScreenDef{ - {id: 1, w: 1920, h: 1080, s: 1}, - {id: 2, w: 1024, h: 768, s: 1, parent: ScreenDefParent{id: 1, align: "be", offset: 0}}, - {id: 3, w: 1024, h: 768, s: 1, parent: ScreenDefParent{id: 2, align: "b", offset: 300}}, - {id: 4, w: 1024, h: 768, s: 1.5, parent: ScreenDefParent{id: 2, align: "le", offset: 100}}, - {id: 5, w: 1024, h: 768, s: 1, parent: ScreenDefParent{id: 4, align: "be", offset: 100}}, - }, - }, - { - name: "Multiple de-intersection (left-side)", - screens: []ScreenDef{ - {id: 1, w: 1920, h: 1080, s: 1}, - {id: 2, w: 1024, h: 768, s: 1, parent: ScreenDefParent{id: 1, align: "le", offset: 0}}, - {id: 3, w: 1024, h: 768, s: 1, parent: ScreenDefParent{id: 2, align: "b", offset: 300}}, - {id: 4, w: 1024, h: 768, s: 1.5, parent: ScreenDefParent{id: 2, align: "le", offset: 100}}, - {id: 5, w: 1024, h: 768, s: 1, parent: ScreenDefParent{id: 4, align: "be", offset: 100}}, - }, - }, - { - name: "Parent de-intersection child offset", - screens: []ScreenDef{ - {id: 1, w: 1600, h: 1600, s: 1.5}, - {id: 2, w: 800, h: 800, s: 1, parent: ScreenDefParent{id: 1, align: "r", offset: 0}}, - {id: 3, w: 800, h: 800, s: 1, parent: ScreenDefParent{id: 1, align: "r", offset: 800}}, - {id: 4, w: 800, h: 1600, s: 1, parent: ScreenDefParent{id: 2, align: "r", offset: 0}}, - }, - }, - }, - } - - parsedLayouts := []ParsedLayout{} - - for _, section := range layouts { - for _, layout := range section { - parsedLayouts = append(parsedLayouts, parseLayout(layout)) - } - } - - return parsedLayouts -} - -// Parse screens layout from easy-to-define ScreenDef for testing to actual Screens layout -func parseLayout(layout ScreensLayout) ParsedLayout { - screens := []*application.Screen{} - - for _, screen := range layout.screens { - var x, y int - w := screen.w - h := screen.h - - if screen.parent.id > 0 { - idx := slices.IndexFunc(screens, func(s *application.Screen) bool { return s.ID == strconv.Itoa(screen.parent.id) }) - parent := screens[idx].Bounds - offset := screen.parent.offset - align := screen.parent.align - align2 := "" - - if len(align) == 2 { - align2 = string(align[1]) - align = string(align[0]) - } - - x = parent.X - y = parent.Y - // t: top, b: bottom, l: left, r: right, e: edge, c: corner - if align == "t" || align == "b" { - x += offset - if align2 == "e" || align2 == "c" { - x += parent.Width - } - if align2 == "e" { - x -= w - } - if align == "t" { - y -= h - } else { - y += parent.Height - } - } else { - y += offset - if align2 == "e" || align2 == "c" { - y += parent.Height - } - if align2 == "e" { - y -= h - } - if align == "l" { - x -= w - } else { - x += parent.Width - } - } - } - name := screen.name - if name == "" { - name = "Display" + strconv.Itoa(screen.id) - } - screens = append(screens, &application.Screen{ - ID: strconv.Itoa(screen.id), - Name: name, - ScaleFactor: float32(math.Round(float64(screen.s)*100) / 100), - X: x, - Y: y, - Size: application.Size{Width: w, Height: h}, - Bounds: application.Rect{X: x, Y: y, Width: w, Height: h}, - PhysicalBounds: application.Rect{X: x, Y: y, Width: w, Height: h}, - WorkArea: application.Rect{X: x, Y: y, Width: w, Height: h - int(40*screen.s)}, - PhysicalWorkArea: application.Rect{X: x, Y: y, Width: w, Height: h - int(40*screen.s)}, - IsPrimary: screen.id == 1, - Rotation: 0, - }) - } - return ParsedLayout{ - name: layout.name, - screens: screens, - } -} - -func matchRects(r1, r2 application.Rect) error { - threshold := 1.0 - if math.Abs(float64(r1.X-r2.X)) > threshold || - math.Abs(float64(r1.Y-r2.Y)) > threshold || - math.Abs(float64(r1.Width-r2.Width)) > threshold || - math.Abs(float64(r1.Height-r2.Height)) > threshold { - return fmt.Errorf("%v != %v", r1, r2) - } - return nil -} - -// Test screens layout (DPI transformation) -func TestScreenManager_ScreensLayout(t *testing.T) { - sm := application.ScreenManager{} - - t.Run("Child scaled", func(t *testing.T) { - is := is.New(t) - - layout := parseLayout(ScreensLayout{screens: []ScreenDef{ - {id: 1, w: 1200, h: 1200, s: 1}, - {id: 2, w: 1200, h: 1200, s: 1.5, parent: ScreenDefParent{id: 1, align: "r", offset: 600}}, - }}) - err := sm.LayoutScreens(layout.screens) - is.NoErr(err) - - screens := sm.GetAll() - is.Equal(len(screens), 2) // 2 screens - is.Equal(screens[0].PhysicalBounds, application.Rect{X: 0, Y: 0, Width: 1200, Height: 1200}) // Parent physical bounds - is.Equal(screens[0].Bounds, screens[0].PhysicalBounds) // Parent no scaling - is.Equal(screens[1].PhysicalBounds, application.Rect{X: 1200, Y: 600, Width: 1200, Height: 1200}) // Child physical bounds - is.Equal(screens[1].Bounds, application.Rect{X: 1200, Y: 600, Width: 800, Height: 800}) // Child DIP bounds - }) - - t.Run("Parent scaled", func(t *testing.T) { - is := is.New(t) - - layout := parseLayout(ScreensLayout{screens: []ScreenDef{ - {id: 1, w: 1200, h: 1200, s: 1.5}, - {id: 2, w: 1200, h: 1200, s: 1, parent: ScreenDefParent{id: 1, align: "r", offset: 600}}, - }}) - - err := sm.LayoutScreens(layout.screens) - is.NoErr(err) - - screens := sm.GetAll() - is.Equal(len(screens), 2) // 2 screens - is.Equal(screens[0].PhysicalBounds, application.Rect{X: 0, Y: 0, Width: 1200, Height: 1200}) // Parent physical bounds - is.Equal(screens[0].Bounds, application.Rect{X: 0, Y: 0, Width: 800, Height: 800}) // Parent DIP bounds - is.Equal(screens[1].PhysicalBounds, application.Rect{X: 1200, Y: 600, Width: 1200, Height: 1200}) // Child physical bounds - is.Equal(screens[1].Bounds, application.Rect{X: 800, Y: 400, Width: 1200, Height: 1200}) // Child DIP bounds - }) -} - -// Test basic transformation between physical and DIP coordinates -func TestScreenManager_BasicTranformation(t *testing.T) { - sm := application.ScreenManager{} - is := is.New(t) - layout := parseLayout(ScreensLayout{screens: []ScreenDef{ - {id: 1, w: 1200, h: 1200, s: 1}, - {id: 2, w: 1200, h: 1200, s: 1.5, parent: ScreenDefParent{id: 1, align: "r", offset: 600}}, - }}) - - err := sm.LayoutScreens(layout.screens) - is.NoErr(err) - - pt := application.Point{X: 100, Y: 100} - is.Equal(sm.DipToPhysicalPoint(pt), pt) // DipToPhysicalPoint screen1 - is.Equal(sm.PhysicalToDipPoint(pt), pt) // PhysicalToDipPoint screen1 - - ptDip := application.Point{X: 1300, Y: 700} - ptPhysical := application.Point{X: 1350, Y: 750} - is.Equal(sm.DipToPhysicalPoint(ptDip), ptPhysical) // DipToPhysicalPoint screen2 - is.Equal(sm.PhysicalToDipPoint(ptPhysical), ptDip) // PhysicalToDipPoint screen2 - - rect := application.Rect{X: 100, Y: 100, Width: 200, Height: 300} - is.Equal(sm.DipToPhysicalRect(rect), rect) // DipToPhysicalRect screen1 - is.Equal(sm.PhysicalToDipRect(rect), rect) // DipToPhysicalRect screen1 - - rectDip := application.Rect{X: 1300, Y: 700, Width: 200, Height: 300} - rectPhysical := application.Rect{X: 1350, Y: 750, Width: 300, Height: 450} - is.Equal(sm.DipToPhysicalRect(rectDip), rectPhysical) // DipToPhysicalRect screen2 - is.Equal(sm.PhysicalToDipRect(rectPhysical), rectDip) // DipToPhysicalRect screen2 - - rectDip = application.Rect{X: 2200, Y: 250, Width: 200, Height: 300} - rectPhysical = application.Rect{X: 2700, Y: 75, Width: 300, Height: 450} - is.Equal(sm.DipToPhysicalRect(rectDip), rectPhysical) // DipToPhysicalRect outside screen2 - is.Equal(sm.PhysicalToDipRect(rectPhysical), rectDip) // DipToPhysicalRect outside screen2 -} - -func TestScreenManager_PrimaryScreen(t *testing.T) { - sm := application.ScreenManager{} - is := is.New(t) - - for _, layout := range exampleLayouts() { - err := sm.LayoutScreens(layout.screens) - is.NoErr(err) - is.Equal(sm.GetPrimary(), layout.screens[0]) // Primary screen - } - - layout := parseLayout(ScreensLayout{screens: []ScreenDef{ - {id: 1, w: 1200, h: 1200, s: 1.5}, - {id: 2, w: 1200, h: 1200, s: 1, parent: ScreenDefParent{id: 1, align: "r", offset: 600}}, - }}) - - layout.screens[0], layout.screens[1] = layout.screens[1], layout.screens[0] - err := sm.LayoutScreens(layout.screens) - is.NoErr(err) - is.Equal(sm.GetPrimary(), layout.screens[1]) // Primary screen - - layout.screens[1].IsPrimary = false - err = sm.LayoutScreens(layout.screens) - is.True(err != nil) // Should error when no primary screen found -} - -// Test edge alignment between transformation -// (points and rects on the screen edge should transform to the same precise edge position) -func TestScreenManager_EdgeAlign(t *testing.T) { - sm := application.ScreenManager{} - is := is.New(t) - - for _, layout := range exampleLayouts() { - err := sm.LayoutScreens(layout.screens) - is.NoErr(err) - for _, screen := range sm.GetAll() { - ptOriginDip := screen.Bounds.Origin() - ptOriginPhysical := screen.PhysicalBounds.Origin() - ptCornerDip := screen.Bounds.InsideCorner() - ptCornerPhysical := screen.PhysicalBounds.InsideCorner() - - is.Equal(sm.DipToPhysicalPoint(ptOriginDip), ptOriginPhysical) // DipToPhysicalPoint Origin - is.Equal(sm.PhysicalToDipPoint(ptOriginPhysical), ptOriginDip) // PhysicalToDipPoint Origin - is.Equal(sm.DipToPhysicalPoint(ptCornerDip), ptCornerPhysical) // DipToPhysicalPoint Corner - is.Equal(sm.PhysicalToDipPoint(ptCornerPhysical), ptCornerDip) // PhysicalToDipPoint Corner - - rectOriginDip := application.Rect{X: ptOriginDip.X, Y: ptOriginDip.Y, Width: 100, Height: 100} - rectOriginPhysical := application.Rect{X: ptOriginPhysical.X, Y: ptOriginPhysical.Y, Width: 100, Height: 100} - rectCornerDip := application.Rect{X: ptCornerDip.X - 99, Y: ptCornerDip.Y - 99, Width: 100, Height: 100} - rectCornerPhysical := application.Rect{X: ptCornerPhysical.X - 99, Y: ptCornerPhysical.Y - 99, Width: 100, Height: 100} - - is.Equal(sm.DipToPhysicalRect(rectOriginDip).Origin(), rectOriginPhysical.Origin()) // DipToPhysicalRect Origin - is.Equal(sm.PhysicalToDipRect(rectOriginPhysical).Origin(), rectOriginDip.Origin()) // PhysicalToDipRect Origin - is.Equal(sm.DipToPhysicalRect(rectCornerDip).Corner(), rectCornerPhysical.Corner()) // DipToPhysicalRect Corner - is.Equal(sm.PhysicalToDipRect(rectCornerPhysical).Corner(), rectCornerDip.Corner()) // PhysicalToDipRect Corner - } - } -} - -func TestScreenManager_ProbePoints(t *testing.T) { - sm := application.ScreenManager{} - is := is.New(t) - threshold := 1.0 - steps := 3 - - for _, layout := range exampleLayouts() { - err := sm.LayoutScreens(layout.screens) - is.NoErr(err) - for _, screen := range sm.GetAll() { - for i := 0; i <= 1; i++ { - isDip := (i == 0) - - var b application.Rect - if isDip { - b = screen.Bounds - } else { - b = screen.PhysicalBounds - } - - xStep := b.Width / steps - yStep := b.Height / steps - if xStep < 1 { - xStep = 1 - } - if yStep < 1 { - yStep = 1 - } - pt := b.Origin() - xDone := false - yDone := false - - for !yDone { - if pt.Y > b.InsideCorner().Y { - pt.Y = b.InsideCorner().Y - yDone = true - } - - pt.X = b.X - xDone = false - - for !xDone { - if pt.X > b.InsideCorner().X { - pt.X = b.InsideCorner().X - xDone = true - } - var ptDblTransformed application.Point - - if isDip { - ptDblTransformed = sm.PhysicalToDipPoint(sm.DipToPhysicalPoint(pt)) - } else { - ptDblTransformed = sm.DipToPhysicalPoint(sm.PhysicalToDipPoint(pt)) - } - - is.True(math.Abs(float64(ptDblTransformed.X-pt.X)) <= threshold) - is.True(math.Abs(float64(ptDblTransformed.Y-pt.Y)) <= threshold) - pt.X += xStep - } - pt.Y += yStep - } - } - } - } -} - -// Test transformation drift over time -func TestScreenManager_TransformationDrift(t *testing.T) { - sm := application.ScreenManager{} - is := is.New(t) - - for _, layout := range exampleLayouts() { - err := sm.LayoutScreens(layout.screens) - is.NoErr(err) - for _, screen := range sm.GetAll() { - rectPhysicalOriginal := application.Rect{ - X: screen.PhysicalBounds.X + 100, - Y: screen.PhysicalBounds.Y + 100, - Width: 123, - Height: 123, - } - - // Slide the position to catch any rounding errors - for i := 0; i < 10; i++ { - rectPhysicalOriginal.X++ - rectPhysicalOriginal.Y++ - rectPhysical := rectPhysicalOriginal - // Transform back and forth several times to make sure no drift is introduced over time - for j := 0; j < 10; j++ { - rectDip := sm.PhysicalToDipRect(rectPhysical) - rectPhysical = sm.DipToPhysicalRect(rectDip) - } - is.NoErr(matchRects(rectPhysical, rectPhysicalOriginal)) - } - } - } -} - -func TestScreenManager_ScreenNearestRect(t *testing.T) { - sm := application.ScreenManager{} - is := is.New(t) - - layout := parseLayout(ScreensLayout{screens: []ScreenDef{ - {id: 1, w: 3840, h: 2160, s: 163.0 / 96, name: `27" 4K UHD 163DPI`}, - {id: 2, w: 1920, h: 1080, s: 1, parent: ScreenDefParent{id: 1, align: "r", offset: 0}, name: `23" FHD 96DPI`}, - {id: 3, w: 1920, h: 1080, s: 1.25, parent: ScreenDefParent{id: 1, align: "l", offset: 0}, name: `23" FHD 96DPI (125%)`}, - }}) - err := sm.LayoutScreens(layout.screens) - is.NoErr(err) - - type Rects map[string][]application.Rect - - t.Run("DIP rects", func(t *testing.T) { - is := is.New(t) - rects := Rects{ - "1": []application.Rect{ - {X: -150, Y: 260, Width: 400, Height: 300}, - {X: -250, Y: 750, Width: 400, Height: 300}, - {X: -450, Y: 950, Width: 400, Height: 300}, - {X: 800, Y: 1350, Width: 400, Height: 300}, - {X: 2000, Y: 100, Width: 400, Height: 300}, - {X: 2100, Y: 950, Width: 400, Height: 300}, - {X: 2350, Y: 1200, Width: 400, Height: 300}, - }, - "2": []application.Rect{ - {X: 2100, Y: 50, Width: 400, Height: 300}, - {X: 2150, Y: 950, Width: 400, Height: 300}, - {X: 2450, Y: 1150, Width: 400, Height: 300}, - {X: 4300, Y: 400, Width: 400, Height: 300}, - }, - "3": []application.Rect{ - {X: -2000, Y: 100, Width: 400, Height: 300}, - {X: -220, Y: 200, Width: 400, Height: 300}, - {X: -300, Y: 750, Width: 400, Height: 300}, - {X: -500, Y: 900, Width: 400, Height: 300}, - }, - } - - for screenID, screenRects := range rects { - for _, rect := range screenRects { - screen := sm.ScreenNearestDipRect(rect) - is.Equal(screen.ID, screenID) - } - } - }) - t.Run("Physical rects", func(t *testing.T) { - is := is.New(t) - rects := Rects{ - "1": []application.Rect{ - {X: -150, Y: 100, Width: 400, Height: 300}, - {X: -250, Y: 1500, Width: 400, Height: 300}, - {X: 3600, Y: 100, Width: 400, Height: 300}, - }, - "2": []application.Rect{ - {X: 3700, Y: 100, Width: 400, Height: 300}, - {X: 4000, Y: 1150, Width: 400, Height: 300}, - }, - "3": []application.Rect{ - {X: -250, Y: 100, Width: 400, Height: 300}, - {X: -300, Y: 950, Width: 400, Height: 300}, - {X: -1000, Y: 1000, Width: 400, Height: 300}, - }, - } - - for screenID, screenRects := range rects { - for _, rect := range screenRects { - screen := sm.ScreenNearestPhysicalRect(rect) - is.Equal(screen.ID, screenID) - } - } - }) - - // DIP rect is near screen1 but when transformed becomes near screen2. - // To have a consistent transformation back & forth, screen nearest physical rect - // should be the one given by ScreenNearestDipRect - t.Run("Edge case 1", func(t *testing.T) { - is := is.New(t) - layout := parseLayout(ScreensLayout{screens: []ScreenDef{ - {id: 1, w: 1200, h: 1200, s: 1}, - {id: 2, w: 1200, h: 1300, s: 1.5, parent: ScreenDefParent{id: 1, align: "r", offset: -20}}, - }}) - err := sm.LayoutScreens(layout.screens) - is.NoErr(err) - - rectDip := application.Rect{X: 1020, Y: 800, Width: 400, Height: 300} - rectPhysical := sm.DipToPhysicalRect(rectDip) - - screenDip := sm.ScreenNearestDipRect(rectDip) - screenPhysical := sm.ScreenNearestPhysicalRect(rectPhysical) - is.Equal(screenDip.ID, "2") // screenDip - is.Equal(screenPhysical.ID, "2") // screenPhysical - - rectDblTransformed := sm.PhysicalToDipRect(rectPhysical) - is.NoErr(matchRects(rectDblTransformed, rectDip)) // double transformation - }) -} - -// Unsolved edge cases -func TestScreenManager_UnsolvedEdgeCases(t *testing.T) { - sm := application.ScreenManager{} - is := is.New(t) - - // Edge case 1: invalid DIP rect location - // there could be a setup where some dip rects locations are invalid, meaning that there's no - // physical rect that could produce that dip rect at this location - // Not sure how to solve this scenario - t.Run("Edge case 1: invalid dip rect", func(t *testing.T) { - t.Skip("Unsolved edge case") - is := is.New(t) - layout := parseLayout(ScreensLayout{screens: []ScreenDef{ - {id: 1, w: 1200, h: 1200, s: 1}, - {id: 2, w: 1200, h: 1100, s: 1.5, parent: ScreenDefParent{id: 1, align: "r", offset: 0}}, - }}) - err := sm.LayoutScreens(layout.screens) - is.NoErr(err) - - rectDip := application.Rect{X: 1050, Y: 700, Width: 400, Height: 300} - rectPhysical := sm.DipToPhysicalRect(rectDip) - - screenDip := sm.ScreenNearestDipRect(rectDip) - screenPhysical := sm.ScreenNearestPhysicalRect(rectPhysical) - is.Equal(screenDip.ID, screenPhysical.ID) - - rectDblTransformed := sm.PhysicalToDipRect(rectPhysical) - is.NoErr(matchRects(rectDblTransformed, rectDip)) // double transformation - }) - - // Edge case 2: physical rect that changes when double transformed - // there could be a setup where a dip rect at some locations could be produced by two different physical rects - // causing one of these physical rects to be changed to the other when double transformed - // Not sure how to solve this scenario - t.Run("Edge case 2: changed physical rect", func(t *testing.T) { - t.Skip("Unsolved edge case") - is := is.New(t) - layout := parseLayout(ScreensLayout{screens: []ScreenDef{ - {id: 1, w: 1200, h: 1200, s: 1.5}, - {id: 2, w: 1200, h: 900, s: 1, parent: ScreenDefParent{id: 1, align: "r", offset: 0}}, - }}) - err := sm.LayoutScreens(layout.screens) - is.NoErr(err) - - rectPhysical := application.Rect{X: 1050, Y: 890, Width: 400, Height: 300} - rectDblTransformed := sm.DipToPhysicalRect(sm.PhysicalToDipRect(rectPhysical)) - is.NoErr(matchRects(rectDblTransformed, rectPhysical)) // double transformation - }) -} - -func BenchmarkScreenManager_LayoutScreens(b *testing.B) { - sm := application.ScreenManager{} - layouts := exampleLayouts() - screens := layouts[3].screens - - b.ResetTimer() - - for i := 0; i < b.N; i++ { - sm.LayoutScreens(screens) - } -} - -func BenchmarkScreenManager_TransformPoint(b *testing.B) { - sm := application.ScreenManager{} - layouts := exampleLayouts() - screens := layouts[3].screens - sm.LayoutScreens(screens) - - pt := application.Point{X: 500, Y: 500} - - b.ResetTimer() - - for i := 0; i < b.N; i++ { - sm.DipToPhysicalPoint(pt) - } -} - -func BenchmarkScreenManager_TransformRect(b *testing.B) { - sm := application.ScreenManager{} - layouts := exampleLayouts() - screens := layouts[3].screens - sm.LayoutScreens(screens) - - rect := application.Rect{X: 500, Y: 500, Width: 800, Height: 600} - - b.ResetTimer() - - for i := 0; i < b.N; i++ { - sm.DipToPhysicalRect(rect) - } -} diff --git a/v3/pkg/application/services.go b/v3/pkg/application/services.go deleted file mode 100644 index 607e4c586..000000000 --- a/v3/pkg/application/services.go +++ /dev/null @@ -1,134 +0,0 @@ -package application - -import ( - "context" - "reflect" -) - -// Service wraps a bound type instance. -// The zero value of Service is invalid. -// Valid values may only be obtained by calling [NewService]. -type Service struct { - instance any - options ServiceOptions -} - -// ServiceOptions provides optional parameters for calls to [NewService]. -type ServiceOptions struct { - // Name can be set to override the name of the service - // for logging and debugging purposes. - // - // If empty, it will default - // either to the value obtained through the [ServiceName] interface, - // or to the type name. - Name string - - // If the service instance implements [http.Handler], - // it will be mounted on the internal asset server - // at the prefix specified by Route. - Route string - - // MarshalError will be called if non-nil - // to marshal to JSON the error values returned by this service's methods. - // - // MarshalError is not allowed to fail, - // but it may return a nil slice to fall back - // to the globally configured error handler. - // - // If the returned slice is not nil, it must contain valid JSON. - MarshalError func(error) []byte -} - -// DefaultServiceOptions specifies the default values of service options, -// used when no [ServiceOptions] instance is provided to [NewService]. -var DefaultServiceOptions = ServiceOptions{} - -// NewService returns a Service value wrapping the given pointer. -// If T is not a concrete named type, the returned value is invalid. -func NewService[T any](instance *T) Service { - return Service{instance, DefaultServiceOptions} -} - -// NewServiceWithOptions returns a Service value wrapping the given pointer -// and specifying the given service options. -// If T is not a concrete named type, the returned value is invalid. -func NewServiceWithOptions[T any](instance *T, options ServiceOptions) Service { - service := NewService(instance) // Delegate to NewService so that the static analyser may detect T. Do not remove this call. - service.options = options - return service -} - -// Instance returns the service instance provided to [NewService]. -func (s Service) Instance() any { - return s.instance -} - -// ServiceName returns the name of the service -// -// This is an *optional* method that may be implemented by service instances. -// It is used for logging and debugging purposes. -// -// If a non-empty name is provided with [ServiceOptions], -// it takes precedence over the one returned by the ServiceName method. -type ServiceName interface { - ServiceName() string -} - -// ServiceStartup is an *optional* method that may be implemented by service instances. -// -// This method will be called during application startup and will receive a copy of the options -// specified at creation time. It can be used for initialising resources. -// -// The context will be valid as long as the application is running, -// and will be cancelled right before shutdown. -// -// Services are guaranteed to receive the startup notification -// in the exact order in which they were either -// listed in [Options.Services] or registered with [App.RegisterService], -// with those from [Options.Services] coming first. -// -// If the return value is non-nil, the startup process aborts -// and [App.Run] returns the error wrapped with [fmt.Errorf] -// in a user-friendly message comprising the service name. -// The original error can be retrieved either by calling the Unwrap method -// or through the [errors.As] API. -// -// When that happens, service instances that have been already initialised -// receive a shutdown notification. -type ServiceStartup interface { - ServiceStartup(ctx context.Context, options ServiceOptions) error -} - -// ServiceShutdown is an *optional* method that may be implemented by service instances. -// -// This method will be called during application shutdown. It can be used for cleaning up resources. -// If a service has received a startup notification, -// then it is guaranteed to receive a shutdown notification too, -// except in case of unhandled panics during shutdown. -// -// Services receive shutdown notifications in reverse registration order, -// after all user-provided shutdown hooks have run (see [App.OnShutdown]). -// -// If the return value is non-nil, it is passed to the application's -// configured error handler at [Options.ErrorHandler], -// wrapped with [fmt.Errorf] in a user-friendly message comprising the service name. -// The default behaviour is to log the error along with the service name. -// The original error can be retrieved either by calling the Unwrap method -// or through the [errors.As] API. -type ServiceShutdown interface { - ServiceShutdown() error -} - -func getServiceName(service Service) string { - if service.options.Name != "" { - return service.options.Name - } - - // Check if the service implements the ServiceName interface - if s, ok := service.Instance().(ServiceName); ok { - return s.ServiceName() - } - - // Finally, get the name from the type. - return reflect.TypeOf(service.Instance()).Elem().String() -} diff --git a/v3/pkg/application/services_test.go b/v3/pkg/application/services_test.go deleted file mode 100644 index 79fbb64ea..000000000 --- a/v3/pkg/application/services_test.go +++ /dev/null @@ -1,203 +0,0 @@ -package application - -import ( - "context" - "testing" -) - -// Test service implementations -type testService struct { - name string -} - -func (s *testService) ServiceName() string { - return s.name -} - -type testServiceWithStartup struct { - started bool -} - -func (s *testServiceWithStartup) ServiceStartup(ctx context.Context, options ServiceOptions) error { - s.started = true - return nil -} - -type testServiceWithShutdown struct { - shutdown bool -} - -func (s *testServiceWithShutdown) ServiceShutdown() error { - s.shutdown = true - return nil -} - -type testServiceNoInterface struct { - value int -} - -func TestNewService(t *testing.T) { - svc := &testService{name: "test"} - service := NewService(svc) - - if service.instance == nil { - t.Error("NewService should set instance") - } - if service.Instance() != svc { - t.Error("Instance() should return the original service") - } -} - -func TestNewServiceWithOptions(t *testing.T) { - svc := &testService{name: "original"} - opts := ServiceOptions{ - Name: "custom-name", - Route: "/api", - } - service := NewServiceWithOptions(svc, opts) - - if service.Instance() != svc { - t.Error("Instance() should return the original service") - } - if service.options.Name != "custom-name" { - t.Errorf("options.Name = %q, want %q", service.options.Name, "custom-name") - } - if service.options.Route != "/api" { - t.Errorf("options.Route = %q, want %q", service.options.Route, "/api") - } -} - -func TestGetServiceName_FromOptions(t *testing.T) { - svc := &testService{name: "service-name"} - opts := ServiceOptions{Name: "options-name"} - service := NewServiceWithOptions(svc, opts) - - name := getServiceName(service) - if name != "options-name" { - t.Errorf("getServiceName() = %q, want %q (options takes precedence)", name, "options-name") - } -} - -func TestGetServiceName_FromInterface(t *testing.T) { - svc := &testService{name: "interface-name"} - service := NewService(svc) - - name := getServiceName(service) - if name != "interface-name" { - t.Errorf("getServiceName() = %q, want %q (from interface)", name, "interface-name") - } -} - -func TestGetServiceName_FromType(t *testing.T) { - svc := &testServiceNoInterface{value: 42} - service := NewService(svc) - - name := getServiceName(service) - // Should contain the type name - if name == "" { - t.Error("getServiceName() should return type name for services without ServiceName interface") - } - // The name should contain "testServiceNoInterface" - expected := "application.testServiceNoInterface" - if name != expected { - t.Errorf("getServiceName() = %q, want %q", name, expected) - } -} - -func TestService_Instance(t *testing.T) { - svc := &testService{name: "test"} - service := NewService(svc) - - instance := service.Instance() - if instance == nil { - t.Error("Instance() should not return nil") - } - - // Type assertion to verify it's the correct type - if _, ok := instance.(*testService); !ok { - t.Error("Instance() should return the correct type") - } -} - -func TestDefaultServiceOptions(t *testing.T) { - // Verify DefaultServiceOptions is zero-valued - if DefaultServiceOptions.Name != "" { - t.Errorf("DefaultServiceOptions.Name should be empty, got %q", DefaultServiceOptions.Name) - } - if DefaultServiceOptions.Route != "" { - t.Errorf("DefaultServiceOptions.Route should be empty, got %q", DefaultServiceOptions.Route) - } - if DefaultServiceOptions.MarshalError != nil { - t.Error("DefaultServiceOptions.MarshalError should be nil") - } -} - -func TestNewService_UsesDefaultOptions(t *testing.T) { - svc := &testService{name: "test"} - service := NewService(svc) - - // Service created with NewService should use DefaultServiceOptions - if service.options.Name != DefaultServiceOptions.Name { - t.Error("NewService should use DefaultServiceOptions") - } -} - -func TestServiceOptions_WithMarshalError(t *testing.T) { - customMarshal := func(err error) []byte { - return []byte(`{"error": "custom"}`) - } - - svc := &testService{name: "test"} - opts := ServiceOptions{ - MarshalError: customMarshal, - } - service := NewServiceWithOptions(svc, opts) - - if service.options.MarshalError == nil { - t.Error("MarshalError should be set") - } - - result := service.options.MarshalError(nil) - expected := `{"error": "custom"}` - if string(result) != expected { - t.Errorf("MarshalError result = %q, want %q", string(result), expected) - } -} - -func TestServiceStartupInterface(t *testing.T) { - svc := &testServiceWithStartup{} - service := NewService(svc) - - // Verify the service implements ServiceStartup - instance := service.Instance() - if startup, ok := instance.(ServiceStartup); ok { - err := startup.ServiceStartup(context.Background(), ServiceOptions{}) - if err != nil { - t.Errorf("ServiceStartup returned error: %v", err) - } - if !svc.started { - t.Error("ServiceStartup should have been called") - } - } else { - t.Error("testServiceWithStartup should implement ServiceStartup") - } -} - -func TestServiceShutdownInterface(t *testing.T) { - svc := &testServiceWithShutdown{} - service := NewService(svc) - - // Verify the service implements ServiceShutdown - instance := service.Instance() - if shutdown, ok := instance.(ServiceShutdown); ok { - err := shutdown.ServiceShutdown() - if err != nil { - t.Errorf("ServiceShutdown returned error: %v", err) - } - if !svc.shutdown { - t.Error("ServiceShutdown should have been called") - } - } else { - t.Error("testServiceWithShutdown should implement ServiceShutdown") - } -} diff --git a/v3/pkg/application/signal_handler_android.go b/v3/pkg/application/signal_handler_android.go deleted file mode 100644 index 61c8a297c..000000000 --- a/v3/pkg/application/signal_handler_android.go +++ /dev/null @@ -1,19 +0,0 @@ -//go:build android - -package application - -import ( - "os" -) - -// setupSignalHandler sets up signal handling for Android -// On Android, we don't handle Unix signals directly as the app lifecycle -// is managed by the Android runtime -func setupSignalHandler() { - // No-op on Android - lifecycle managed by Android framework -} - -// handleSignal processes a signal -func handleSignal(_ os.Signal) { - // No-op on Android -} diff --git a/v3/pkg/application/signal_handler_desktop.go b/v3/pkg/application/signal_handler_desktop.go deleted file mode 100644 index c4f756c94..000000000 --- a/v3/pkg/application/signal_handler_desktop.go +++ /dev/null @@ -1,20 +0,0 @@ -//go:build !ios - -package application - -import ( - "os" - - "github.com/wailsapp/wails/v3/internal/signal" -) - -// setupSignalHandler sets up signal handling for desktop platforms -func (a *App) setupSignalHandler(options Options) { - if !options.DisableDefaultSignalHandler { - a.signalHandler = signal.NewSignalHandler(a.Quit) - a.signalHandler.Logger = a.Logger - a.signalHandler.ExitMessage = func(sig os.Signal) string { - return "Quitting application..." - } - } -} diff --git a/v3/pkg/application/signal_handler_ios.go b/v3/pkg/application/signal_handler_ios.go deleted file mode 100644 index b16713811..000000000 --- a/v3/pkg/application/signal_handler_ios.go +++ /dev/null @@ -1,11 +0,0 @@ -//go:build ios - -package application - -// setupSignalHandler is a no-op on iOS as signal handling is not supported -// iOS apps run in a sandboxed environment where signal handling is restricted -// and can cause crashes if attempted -func (app *App) setupSignalHandler(options Options) { - // No signal handling on iOS - the OS manages app lifecycle - // Signal handlers would cause crashes due to iOS sandbox restrictions -} \ No newline at end of file diff --git a/v3/pkg/application/signal_handler_types_android.go b/v3/pkg/application/signal_handler_types_android.go deleted file mode 100644 index ed5835c20..000000000 --- a/v3/pkg/application/signal_handler_types_android.go +++ /dev/null @@ -1,8 +0,0 @@ -//go:build android - -package application - -import "os" - -// signalType is a placeholder type for Android where signals are not used -type signalType = os.Signal diff --git a/v3/pkg/application/signal_handler_types_desktop.go b/v3/pkg/application/signal_handler_types_desktop.go deleted file mode 100644 index 5b7e5c7d9..000000000 --- a/v3/pkg/application/signal_handler_types_desktop.go +++ /dev/null @@ -1,10 +0,0 @@ -//go:build !ios - -package application - -import "github.com/wailsapp/wails/v3/internal/signal" - -// platformSignalHandler holds the signal handler for desktop platforms -type platformSignalHandler struct { - signalHandler *signal.SignalHandler -} \ No newline at end of file diff --git a/v3/pkg/application/signal_handler_types_ios.go b/v3/pkg/application/signal_handler_types_ios.go deleted file mode 100644 index 1e5c640d7..000000000 --- a/v3/pkg/application/signal_handler_types_ios.go +++ /dev/null @@ -1,8 +0,0 @@ -//go:build ios - -package application - -// platformSignalHandler is empty on iOS as signal handling is not supported -type platformSignalHandler struct { - // No signal handler on iOS -} \ No newline at end of file diff --git a/v3/pkg/application/single_instance.go b/v3/pkg/application/single_instance.go deleted file mode 100644 index 7f04320eb..000000000 --- a/v3/pkg/application/single_instance.go +++ /dev/null @@ -1,216 +0,0 @@ -package application - -import ( - "crypto/aes" - "crypto/cipher" - "crypto/rand" - "encoding/base64" - "errors" - "os" - "path/filepath" - "sync" - - "encoding/json" -) - -var alreadyRunningError = errors.New("application is already running") -var secondInstanceBuffer = make(chan string, 1) -var once sync.Once - -// SecondInstanceData contains information about the second instance launch -type SecondInstanceData struct { - Args []string `json:"args"` - WorkingDir string `json:"workingDir"` - AdditionalData map[string]string `json:"additionalData,omitempty"` -} - -// SingleInstanceOptions defines options for single instance functionality -type SingleInstanceOptions struct { - // UniqueID is used to identify the application instance - // This should be unique per application, e.g. "com.myapp.myapplication" - UniqueID string - - // OnSecondInstanceLaunch is called when a second instance of the application is launched - // The callback receives data about the second instance launch - OnSecondInstanceLaunch func(data SecondInstanceData) - - // AdditionalData allows passing custom data from second instance to first - AdditionalData map[string]string - - // ExitCode is the exit code to use when the second instance exits - ExitCode int - - // EncryptionKey is a 32-byte key used for encrypting instance communication - // If not provided (zero array), data will be sent unencrypted - EncryptionKey [32]byte -} - -// platformLock is the interface that platform-specific lock implementations must implement -type platformLock interface { - // acquire attempts to acquire the lock - acquire(uniqueID string) error - // release releases the lock and cleans up resources - release() - // notify sends data to the first instance - notify(data string) error -} - -// singleInstanceManager handles the single instance functionality -type singleInstanceManager struct { - options *SingleInstanceOptions - lock platformLock - app *App -} - -func newSingleInstanceManager(app *App, options *SingleInstanceOptions) (*singleInstanceManager, error) { - if options == nil { - return nil, nil - } - - manager := &singleInstanceManager{ - options: options, - app: app, - } - - // Launch second instance data listener - once.Do(func() { - go func() { - defer handlePanic() - for encryptedData := range secondInstanceBuffer { - var secondInstanceData SecondInstanceData - var jsonData []byte - var err error - - // Check if encryption key is non-zero - var zeroKey [32]byte - if options.EncryptionKey != zeroKey { - // Try to decrypt the data - jsonData, err = decrypt(options.EncryptionKey, encryptedData) - if err != nil { - continue // Skip invalid data - } - } else { - jsonData = []byte(encryptedData) - } - - if err := json.Unmarshal(jsonData, &secondInstanceData); err == nil && manager.options.OnSecondInstanceLaunch != nil { - manager.options.OnSecondInstanceLaunch(secondInstanceData) - } - } - }() - }) - - // Create platform-specific lock - lock, err := newPlatformLock(manager) - if err != nil { - return nil, err - } - - manager.lock = lock - - // Try to acquire the lock - err = lock.acquire(options.UniqueID) - if err != nil { - return manager, err - } - - return manager, nil -} - -func (m *singleInstanceManager) cleanup() { - if m == nil || m.lock == nil { - return - } - m.lock.release() -} - -// encrypt encrypts data using AES-256-GCM -func encrypt(key [32]byte, plaintext []byte) (string, error) { - block, err := aes.NewCipher(key[:]) - if err != nil { - return "", err - } - - nonce := make([]byte, 12) - if _, err := rand.Read(nonce); err != nil { - return "", err - } - - aesgcm, err := cipher.NewGCM(block) - if err != nil { - return "", err - } - - ciphertext := aesgcm.Seal(nil, nonce, plaintext, nil) - encrypted := append(nonce, ciphertext...) - return base64.StdEncoding.EncodeToString(encrypted), nil -} - -// decrypt decrypts data using AES-256-GCM -func decrypt(key [32]byte, encrypted string) ([]byte, error) { - data, err := base64.StdEncoding.DecodeString(encrypted) - if err != nil { - return nil, err - } - - if len(data) < 12 { - return nil, errors.New("invalid encrypted data") - } - - block, err := aes.NewCipher(key[:]) - if err != nil { - return nil, err - } - - aesgcm, err := cipher.NewGCM(block) - if err != nil { - return nil, err - } - - nonce := data[:12] - ciphertext := data[12:] - - return aesgcm.Open(nil, nonce, ciphertext, nil) -} - -// notifyFirstInstance sends data to the first instance of the application -func (m *singleInstanceManager) notifyFirstInstance() error { - data := SecondInstanceData{ - Args: os.Args, - WorkingDir: getCurrentWorkingDir(), - AdditionalData: m.options.AdditionalData, - } - - serialized, err := json.Marshal(data) - if err != nil { - return err - } - - // Check if encryption key is non-zero - var zeroKey [32]byte - if m.options.EncryptionKey != zeroKey { - encrypted, err := encrypt(m.options.EncryptionKey, serialized) - if err != nil { - return err - } - return m.lock.notify(encrypted) - } - - return m.lock.notify(string(serialized)) -} - -func getCurrentWorkingDir() string { - dir, err := os.Getwd() - if err != nil { - return "" - } - return dir -} - -// getLockPath returns the path to the lock file for Unix systems -func getLockPath(uniqueID string) string { - // Use system temp directory - tmpDir := os.TempDir() - lockFileName := uniqueID + ".lock" - return filepath.Join(tmpDir, lockFileName) -} diff --git a/v3/pkg/application/single_instance_android.go b/v3/pkg/application/single_instance_android.go deleted file mode 100644 index e08cbc172..000000000 --- a/v3/pkg/application/single_instance_android.go +++ /dev/null @@ -1,33 +0,0 @@ -//go:build android - -package application - -// setupSingleInstance sets up single instance on Android -func (a *App) setupSingleInstance() error { - // Android apps handle single instance via launch mode in manifest - return nil -} - -type androidLock struct { - manager *singleInstanceManager -} - -func newPlatformLock(manager *singleInstanceManager) (platformLock, error) { - return &androidLock{ - manager: manager, - }, nil -} - -func (l *androidLock) acquire(uniqueID string) error { - // Android apps handle single instance via launch mode in manifest - return nil -} - -func (l *androidLock) release() { - // Android apps handle single instance via launch mode in manifest -} - -func (l *androidLock) notify(data string) error { - // Android apps handle single instance via launch mode in manifest - return nil -} diff --git a/v3/pkg/application/single_instance_darwin.go b/v3/pkg/application/single_instance_darwin.go deleted file mode 100644 index 546bf7259..000000000 --- a/v3/pkg/application/single_instance_darwin.go +++ /dev/null @@ -1,96 +0,0 @@ -//go:build darwin && !ios - -package application - -/* -#cgo CFLAGS: -x objective-c -#cgo LDFLAGS: -framework Foundation -framework Cocoa - -#include -#import -#import - -static void SendDataToFirstInstance(char *singleInstanceUniqueId, char* message) { - [[NSDistributedNotificationCenter defaultCenter] - postNotificationName:[NSString stringWithUTF8String:singleInstanceUniqueId] - object:nil - userInfo:@{@"message": [NSString stringWithUTF8String:message]} - deliverImmediately:YES]; -} - -*/ -import "C" -import ( - "os" - "syscall" - "unsafe" -) - -type darwinLock struct { - file *os.File - uniqueID string - manager *singleInstanceManager -} - -func newPlatformLock(manager *singleInstanceManager) (platformLock, error) { - return &darwinLock{ - manager: manager, - }, nil -} - -func (l *darwinLock) acquire(uniqueID string) error { - l.uniqueID = uniqueID - lockFilePath := os.TempDir() - lockFileName := uniqueID + ".lock" - var err error - l.file, err = createLockFile(lockFilePath + "/" + lockFileName) - if err != nil { - return alreadyRunningError - } - return nil -} - -func (l *darwinLock) release() { - if l.file != nil { - syscall.Flock(int(l.file.Fd()), syscall.LOCK_UN) - l.file.Close() - os.Remove(l.file.Name()) - l.file = nil - } -} - -func (l *darwinLock) notify(data string) error { - singleInstanceUniqueId := C.CString(l.uniqueID) - defer C.free(unsafe.Pointer(singleInstanceUniqueId)) - cData := C.CString(data) - defer C.free(unsafe.Pointer(cData)) - - C.SendDataToFirstInstance(singleInstanceUniqueId, cData) - - os.Exit(l.manager.options.ExitCode) - return nil -} - -// CreateLockFile tries to create a file with given name and acquire an -// exclusive lock on it. If the file already exists AND is still locked, it will -// fail. -func createLockFile(filename string) (*os.File, error) { - file, err := os.OpenFile(filename, os.O_WRONLY|os.O_CREATE, 0600) - if err != nil { - return nil, err - } - - err = syscall.Flock(int(file.Fd()), syscall.LOCK_EX|syscall.LOCK_NB) - if err != nil { - file.Close() - return nil, err - } - - return file, nil -} - -//export handleSecondInstanceData -func handleSecondInstanceData(secondInstanceMessage *C.char) { - message := C.GoString(secondInstanceMessage) - secondInstanceBuffer <- message -} diff --git a/v3/pkg/application/single_instance_ios.go b/v3/pkg/application/single_instance_ios.go deleted file mode 100644 index fd7e8eae3..000000000 --- a/v3/pkg/application/single_instance_ios.go +++ /dev/null @@ -1,33 +0,0 @@ -//go:build ios - -package application - -// setupSingleInstance sets up single instance on iOS -func (a *App) setupSingleInstance() error { - // iOS apps are always single instance - return nil -} - -type iosLock struct { - manager *singleInstanceManager -} - -func newPlatformLock(manager *singleInstanceManager) (platformLock, error) { - return &iosLock{ - manager: manager, - }, nil -} - -func (l *iosLock) acquire(uniqueID string) error { - // iOS apps are always single instance - return nil -} - -func (l *iosLock) release() { - // iOS apps are always single instance -} - -func (l *iosLock) notify(data string) error { - // iOS apps are always single instance - return nil -} \ No newline at end of file diff --git a/v3/pkg/application/single_instance_linux.go b/v3/pkg/application/single_instance_linux.go deleted file mode 100644 index 1d2a55c18..000000000 --- a/v3/pkg/application/single_instance_linux.go +++ /dev/null @@ -1,101 +0,0 @@ -//go:build linux && !android && !server - -package application - -import ( - "errors" - "os" - "strings" - "sync" - "syscall" - - "github.com/godbus/dbus/v5" -) - -type dbusHandler func(string) - -var setup sync.Once - -func (f dbusHandler) SendMessage(message string) *dbus.Error { - f(message) - return nil -} - -type linuxLock struct { - file *os.File - uniqueID string - dbusPath string - dbusName string - manager *singleInstanceManager -} - -func newPlatformLock(manager *singleInstanceManager) (platformLock, error) { - return &linuxLock{ - manager: manager, - }, nil -} - -func (l *linuxLock) acquire(uniqueID string) error { - if uniqueID == "" { - return errors.New("UniqueID is required for single instance lock") - } - - id := "wails_app_" + strings.ReplaceAll(strings.ReplaceAll(uniqueID, "-", "_"), ".", "_") - - l.dbusName = "org." + id + ".SingleInstance" - l.dbusPath = "/org/" + id + "/SingleInstance" - - conn, err := dbus.ConnectSessionBus() - // if we will reach any error during establishing connection or sending message we will just continue. - // It should not be the case that such thing will happen actually, but just in case. - if err != nil { - return err - } - - setup.Do(func() { - f := dbusHandler(func(message string) { - secondInstanceBuffer <- message - }) - - err = conn.Export(f, dbus.ObjectPath(l.dbusPath), l.dbusName) - }) - if err != nil { - return err - } - - reply, err := conn.RequestName(l.dbusName, dbus.NameFlagDoNotQueue) - if err != nil { - return err - } - - // if name already taken, try to send args to existing instance, if no success just launch new instance - if reply == dbus.RequestNameReplyExists { - return alreadyRunningError - } - return nil -} - -func (l *linuxLock) release() { - if l.file != nil { - syscall.Flock(int(l.file.Fd()), syscall.LOCK_UN) - l.file.Close() - os.Remove(l.file.Name()) - l.file = nil - } -} - -func (l *linuxLock) notify(data string) error { - conn, err := dbus.ConnectSessionBus() - // if we will reach any error during establishing connection or sending message we will just continue. - // It should not be the case that such thing will happen actually, but just in case. - if err != nil { - return err - } - - err = conn.Object(l.dbusName, dbus.ObjectPath(l.dbusPath)).Call(l.dbusName+".SendMessage", 0, data).Store() - if err != nil { - return err - } - os.Exit(l.manager.options.ExitCode) - return nil -} diff --git a/v3/pkg/application/single_instance_test.go b/v3/pkg/application/single_instance_test.go deleted file mode 100644 index 230f8e07d..000000000 --- a/v3/pkg/application/single_instance_test.go +++ /dev/null @@ -1,229 +0,0 @@ -package application - -import ( - "os" - "path/filepath" - "testing" -) - -func TestEncryptDecrypt(t *testing.T) { - key := [32]byte{ - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, - 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, - } - - plaintext := []byte("Hello, World! This is a test message.") - - encrypted, err := encrypt(key, plaintext) - if err != nil { - t.Fatalf("encrypt failed: %v", err) - } - - if encrypted == "" { - t.Error("encrypted should not be empty") - } - - if encrypted == string(plaintext) { - t.Error("encrypted should be different from plaintext") - } - - decrypted, err := decrypt(key, encrypted) - if err != nil { - t.Fatalf("decrypt failed: %v", err) - } - - if string(decrypted) != string(plaintext) { - t.Errorf("decrypted = %q, want %q", string(decrypted), string(plaintext)) - } -} - -func TestEncryptDecrypt_EmptyData(t *testing.T) { - key := [32]byte{ - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, - 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, - } - - plaintext := []byte{} - - encrypted, err := encrypt(key, plaintext) - if err != nil { - t.Fatalf("encrypt failed: %v", err) - } - - decrypted, err := decrypt(key, encrypted) - if err != nil { - t.Fatalf("decrypt failed: %v", err) - } - - if len(decrypted) != 0 { - t.Errorf("decrypted should be empty, got %d bytes", len(decrypted)) - } -} - -func TestDecrypt_InvalidData(t *testing.T) { - key := [32]byte{ - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, - 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, - } - - tests := []struct { - name string - data string - }{ - {"invalid base64", "not-valid-base64!!!"}, - {"too short", "YWJj"}, // "abc" base64 encoded (3 bytes) - } - - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - _, err := decrypt(key, tt.data) - if err == nil { - t.Error("decrypt should return error for invalid data") - } - }) - } -} - -func TestDecrypt_WrongKey(t *testing.T) { - key1 := [32]byte{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, - 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f} - - key2 := [32]byte{0xff, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, - 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f} - - plaintext := []byte("Secret message") - - encrypted, err := encrypt(key1, plaintext) - if err != nil { - t.Fatalf("encrypt failed: %v", err) - } - - _, err = decrypt(key2, encrypted) - if err == nil { - t.Error("decrypt with wrong key should return error") - } -} - -func TestGetLockPath(t *testing.T) { - uniqueID := "com.example.myapp" - path := getLockPath(uniqueID) - - if path == "" { - t.Error("getLockPath should return non-empty path") - } - - expectedFileName := uniqueID + ".lock" - actualFileName := filepath.Base(path) - if actualFileName != expectedFileName { - t.Errorf("filename = %q, want %q", actualFileName, expectedFileName) - } - - // Path should be in temp directory - // Use filepath.Clean to normalize paths (os.TempDir may have trailing slash on macOS) - tmpDir := filepath.Clean(os.TempDir()) - if filepath.Dir(path) != tmpDir { - t.Errorf("path should be in temp directory %q, got %q", tmpDir, filepath.Dir(path)) - } -} - -func TestGetCurrentWorkingDir(t *testing.T) { - dir := getCurrentWorkingDir() - - // Should return a non-empty path - if dir == "" { - t.Error("getCurrentWorkingDir should return non-empty path") - } - - // Should match os.Getwd() - expected, err := os.Getwd() - if err != nil { - t.Skipf("os.Getwd failed: %v", err) - } - - if dir != expected { - t.Errorf("getCurrentWorkingDir() = %q, want %q", dir, expected) - } -} - -func TestSecondInstanceData_Fields(t *testing.T) { - data := SecondInstanceData{ - Args: []string{"arg1", "arg2"}, - WorkingDir: "/home/user", - AdditionalData: map[string]string{ - "key1": "value1", - "key2": "value2", - }, - } - - if len(data.Args) != 2 { - t.Error("Args not set correctly") - } - if data.WorkingDir != "/home/user" { - t.Error("WorkingDir not set correctly") - } - if len(data.AdditionalData) != 2 { - t.Error("AdditionalData not set correctly") - } -} - -func TestSingleInstanceOptions_Defaults(t *testing.T) { - opts := SingleInstanceOptions{} - - if opts.UniqueID != "" { - t.Error("UniqueID should default to empty string") - } - if opts.OnSecondInstanceLaunch != nil { - t.Error("OnSecondInstanceLaunch should default to nil") - } - if opts.AdditionalData != nil { - t.Error("AdditionalData should default to nil") - } - if opts.ExitCode != 0 { - t.Error("ExitCode should default to 0") - } - var zeroKey [32]byte - if opts.EncryptionKey != zeroKey { - t.Error("EncryptionKey should default to zero array") - } -} - -func TestSingleInstanceManager_Cleanup_Nil(t *testing.T) { - // Calling cleanup on nil manager should not panic - var m *singleInstanceManager - m.cleanup() // Should not panic -} - -func TestSingleInstanceManager_Cleanup_NilLock(t *testing.T) { - // Calling cleanup with nil lock should not panic - m := &singleInstanceManager{} - m.cleanup() // Should not panic -} - -func TestNewSingleInstanceManager_NilOptions(t *testing.T) { - manager, err := newSingleInstanceManager(nil, nil) - if err != nil { - t.Errorf("newSingleInstanceManager(nil, nil) should not return error: %v", err) - } - if manager != nil { - t.Error("newSingleInstanceManager(nil, nil) should return nil manager") - } -} - -func TestAlreadyRunningError(t *testing.T) { - if alreadyRunningError == nil { - t.Error("alreadyRunningError should not be nil") - } - if alreadyRunningError.Error() != "application is already running" { - t.Errorf("alreadyRunningError.Error() = %q", alreadyRunningError.Error()) - } -} diff --git a/v3/pkg/application/single_instance_windows.go b/v3/pkg/application/single_instance_windows.go deleted file mode 100644 index b92b2749a..000000000 --- a/v3/pkg/application/single_instance_windows.go +++ /dev/null @@ -1,129 +0,0 @@ -//go:build windows - -package application - -import ( - "errors" - "syscall" - "unsafe" - - "github.com/wailsapp/wails/v3/pkg/w32" - "golang.org/x/sys/windows" -) - -var ( - user32 = syscall.NewLazyDLL("user32.dll") -) - -type windowsLock struct { - handle syscall.Handle - uniqueID string - msgString string - hwnd w32.HWND - manager *singleInstanceManager - className string - windowName string -} - -func newPlatformLock(manager *singleInstanceManager) (platformLock, error) { - return &windowsLock{ - manager: manager, - }, nil -} - -func (l *windowsLock) acquire(uniqueID string) error { - if uniqueID == "" { - return errors.New("UniqueID is required for single instance lock") - } - - l.uniqueID = uniqueID - id := "wails-app-" + uniqueID - l.className = id + "-sic" - l.windowName = id + "-siw" - mutexName := id + "-sim" - - _, err := windows.CreateMutex(nil, false, windows.StringToUTF16Ptr(mutexName)) - if err != nil { - // Find the window - return alreadyRunningError - } else { - l.hwnd = createEventTargetWindow(l.className, l.windowName) - } - - return nil -} - -func (l *windowsLock) release() { - if l.handle != 0 { - syscall.CloseHandle(l.handle) - l.handle = 0 - } - if l.hwnd != 0 { - w32.DestroyWindow(l.hwnd) - l.hwnd = 0 - } -} - -func (l *windowsLock) notify(data string) error { - - // app is already running - hwnd := w32.FindWindowW(windows.StringToUTF16Ptr(l.className), windows.StringToUTF16Ptr(l.windowName)) - - if hwnd == 0 { - return errors.New("unable to notify other instance") - } - - w32.SendMessageToWindow(hwnd, data) - - return nil -} - -func createEventTargetWindow(className string, windowName string) w32.HWND { - var class w32.WNDCLASSEX - class.Size = uint32(unsafe.Sizeof(class)) - class.Style = 0 - class.WndProc = syscall.NewCallback(wndProc) - class.ClsExtra = 0 - class.WndExtra = 0 - class.Instance = w32.GetModuleHandle("") - class.Icon = 0 - class.Cursor = 0 - class.Background = 0 - class.MenuName = nil - class.ClassName = w32.MustStringToUTF16Ptr(className) - class.IconSm = 0 - - w32.RegisterClassEx(&class) - - // Create hidden message-only window - hwnd := w32.CreateWindowEx( - 0, - w32.MustStringToUTF16Ptr(className), - w32.MustStringToUTF16Ptr(windowName), - 0, - 0, - 0, - 0, - 0, - w32.HWND_MESSAGE, - 0, - w32.GetModuleHandle(""), - nil, - ) - - return hwnd -} - -func wndProc(hwnd w32.HWND, msg uint32, wparam w32.WPARAM, lparam w32.LPARAM) w32.LRESULT { - if msg == w32.WM_COPYDATA { - ldata := (*w32.COPYDATASTRUCT)(unsafe.Pointer(lparam)) - - if ldata.DwData == w32.WMCOPYDATA_SINGLE_INSTANCE_DATA { - serialized := windows.UTF16PtrToString((*uint16)(unsafe.Pointer(ldata.LpData))) - secondInstanceBuffer <- serialized - } - return w32.LRESULT(0) - } - - return w32.DefWindowProc(hwnd, msg, wparam, lparam) -} diff --git a/v3/pkg/application/system_tray_manager.go b/v3/pkg/application/system_tray_manager.go deleted file mode 100644 index 16bdf5153..000000000 --- a/v3/pkg/application/system_tray_manager.go +++ /dev/null @@ -1,44 +0,0 @@ -package application - -// SystemTrayManager manages system tray-related operations -type SystemTrayManager struct { - app *App -} - -// newSystemTrayManager creates a new SystemTrayManager instance -func newSystemTrayManager(app *App) *SystemTrayManager { - return &SystemTrayManager{ - app: app, - } -} - -// New creates a new system tray -func (stm *SystemTrayManager) New() *SystemTray { - id := stm.getNextID() - newSystemTray := newSystemTray(id) - - stm.app.systemTraysLock.Lock() - stm.app.systemTrays[id] = newSystemTray - stm.app.systemTraysLock.Unlock() - - stm.app.runOrDeferToAppRun(newSystemTray) - - return newSystemTray -} - -// getNextID generates the next system tray ID (internal use) -func (stm *SystemTrayManager) getNextID() uint { - stm.app.systemTrayIDLock.Lock() - defer stm.app.systemTrayIDLock.Unlock() - stm.app.systemTrayID++ - return stm.app.systemTrayID -} - -// destroy destroys a system tray (internal use) -func (stm *SystemTrayManager) destroy(tray *SystemTray) { - // Remove the system tray from the app.systemTrays map - stm.app.systemTraysLock.Lock() - delete(stm.app.systemTrays, tray.id) - stm.app.systemTraysLock.Unlock() - tray.destroy() -} diff --git a/v3/pkg/application/systemtray.go b/v3/pkg/application/systemtray.go deleted file mode 100644 index 1a93ba206..000000000 --- a/v3/pkg/application/systemtray.go +++ /dev/null @@ -1,369 +0,0 @@ -package application - -import ( - "errors" - "runtime" - "sync" - "time" -) - -type IconPosition int - -const ( - NSImageNone = iota - NSImageOnly - NSImageLeft - NSImageRight - NSImageBelow - NSImageAbove - NSImageOverlaps - NSImageLeading - NSImageTrailing -) - -type systemTrayImpl interface { - setLabel(label string) - setTooltip(tooltip string) - run() - setIcon(icon []byte) - setMenu(menu *Menu) - setIconPosition(position IconPosition) - setTemplateIcon(icon []byte) - destroy() - setDarkModeIcon(icon []byte) - bounds() (*Rect, error) - getScreen() (*Screen, error) - positionWindow(window Window, offset int) error - openMenu() - Show() - Hide() -} - -type SystemTray struct { - id uint - label string - tooltip string - icon []byte - darkModeIcon []byte - iconPosition IconPosition - - clickHandler func() - rightClickHandler func() - doubleClickHandler func() - rightDoubleClickHandler func() - mouseEnterHandler func() - mouseLeaveHandler func() - onMenuOpen func() - onMenuClose func() - - // Platform specific implementation - impl systemTrayImpl - menu *Menu - isTemplateIcon bool - attachedWindow WindowAttachConfig -} - -func newSystemTray(id uint) *SystemTray { - result := &SystemTray{ - id: id, - label: "", - tooltip: "", - iconPosition: NSImageLeading, - attachedWindow: WindowAttachConfig{ - Window: nil, - Offset: 0, - Debounce: 200 * time.Millisecond, - }, - } - return result -} - -func (s *SystemTray) SetLabel(label string) { - if s.impl == nil { - s.label = label - return - } - InvokeSync(func() { - s.impl.setLabel(label) - }) -} - -func (s *SystemTray) Label() string { - return s.label -} - -func (s *SystemTray) Run() { - if globalApplication == nil || globalApplication.running == false { - return - } - - s.applySmartDefaults() - s.impl = newSystemTrayImpl(s) - InvokeSync(s.impl.run) -} - -func (s *SystemTray) applySmartDefaults() { - hasWindow := s.attachedWindow.Window != nil - hasMenu := s.menu != nil - - if s.clickHandler == nil && hasWindow { - s.clickHandler = s.ToggleWindow - } - - if s.rightClickHandler == nil && hasMenu { - s.rightClickHandler = s.ShowMenu - } -} - -func (s *SystemTray) ToggleWindow() { - if s.attachedWindow.Window == nil { - return - } - - s.attachedWindow.initialClick.Do(func() { - s.attachedWindow.hasBeenShown = s.attachedWindow.Window.IsVisible() - }) - - if runtime.GOOS == "windows" && s.attachedWindow.justClosed { - return - } - - if s.attachedWindow.Window.IsVisible() { - s.attachedWindow.Window.Hide() - } else { - s.attachedWindow.hasBeenShown = true - _ = s.PositionWindow(s.attachedWindow.Window, s.attachedWindow.Offset) - s.attachedWindow.Window.Show().Focus() - } -} - -func (s *SystemTray) defaultClickHandler() { - if s.attachedWindow.Window == nil { - s.OpenMenu() - return - } - - // Check the initial visibility state - s.attachedWindow.initialClick.Do(func() { - s.attachedWindow.hasBeenShown = s.attachedWindow.Window.IsVisible() - }) - - if runtime.GOOS == "windows" && s.attachedWindow.justClosed { - return - } - - if s.attachedWindow.Window.IsVisible() { - s.attachedWindow.Window.Hide() - } else { - s.attachedWindow.hasBeenShown = true - _ = s.PositionWindow(s.attachedWindow.Window, s.attachedWindow.Offset) - s.attachedWindow.Window.Show().Focus() - } -} - -func (s *SystemTray) ShowMenu() { - s.OpenMenu() -} - -func (s *SystemTray) ShowWindow() { - if s.attachedWindow.Window == nil { - return - } - s.attachedWindow.hasBeenShown = true - _ = s.PositionWindow(s.attachedWindow.Window, s.attachedWindow.Offset) - s.attachedWindow.Window.Show().Focus() -} - -func (s *SystemTray) HideWindow() { - if s.attachedWindow.Window == nil { - return - } - s.attachedWindow.Window.Hide() -} - -func (s *SystemTray) PositionWindow(window Window, offset int) error { - if s.impl == nil { - return errors.New("system tray not running") - } - return InvokeSyncWithError(func() error { - return s.impl.positionWindow(window, offset) - }) -} - -func (s *SystemTray) SetIcon(icon []byte) *SystemTray { - if s.impl == nil { - s.icon = icon - } else { - InvokeSync(func() { - s.impl.setIcon(icon) - }) - } - return s -} - -func (s *SystemTray) SetDarkModeIcon(icon []byte) *SystemTray { - if s.impl == nil { - s.darkModeIcon = icon - } else { - InvokeSync(func() { - s.impl.setDarkModeIcon(icon) - }) - } - return s -} - -func (s *SystemTray) SetMenu(menu *Menu) *SystemTray { - if s.impl == nil { - s.menu = menu - } else { - InvokeSync(func() { - s.impl.setMenu(menu) - }) - } - return s -} - -func (s *SystemTray) SetIconPosition(iconPosition IconPosition) *SystemTray { - if s.impl == nil { - s.iconPosition = iconPosition - } else { - InvokeSync(func() { - s.impl.setIconPosition(iconPosition) - }) - } - return s -} - -func (s *SystemTray) SetTemplateIcon(icon []byte) *SystemTray { - if s.impl == nil { - s.icon = icon - s.isTemplateIcon = true - } else { - InvokeSync(func() { - s.impl.setTemplateIcon(icon) - }) - } - return s -} - -func (s *SystemTray) SetTooltip(tooltip string) { - if s.impl == nil { - s.tooltip = tooltip - return - } - InvokeSync(func() { - s.impl.setTooltip(tooltip) - }) -} - -func (s *SystemTray) Destroy() { - globalApplication.SystemTray.destroy(s) -} - -func (s *SystemTray) destroy() { - if s.impl == nil { - return - } - s.impl.destroy() -} - -func (s *SystemTray) OnClick(handler func()) *SystemTray { - s.clickHandler = handler - return s -} - -func (s *SystemTray) OnRightClick(handler func()) *SystemTray { - s.rightClickHandler = handler - return s -} - -func (s *SystemTray) OnDoubleClick(handler func()) *SystemTray { - s.doubleClickHandler = handler - return s -} - -func (s *SystemTray) OnRightDoubleClick(handler func()) *SystemTray { - s.rightDoubleClickHandler = handler - return s -} - -func (s *SystemTray) OnMouseEnter(handler func()) *SystemTray { - s.mouseEnterHandler = handler - return s -} - -func (s *SystemTray) OnMouseLeave(handler func()) *SystemTray { - s.mouseLeaveHandler = handler - return s -} - -func (s *SystemTray) Show() { - if s.impl == nil { - return - } - InvokeSync(func() { - s.impl.Show() - }) -} - -func (s *SystemTray) Hide() { - if s.impl == nil { - return - } - InvokeSync(func() { - s.impl.Hide() - }) -} - -type WindowAttachConfig struct { - // Window is the window to attach to the system tray. If it's null, the request to attach will be ignored. - Window Window - - // Offset indicates the gap in pixels between the system tray and the window - Offset int - - // Debounce is used by Windows to indicate how long to wait before responding to a mouse - // up event on the notification icon. See https://stackoverflow.com/questions/4585283/alternate-showing-hiding-window-when-notify-icon-is-clicked - Debounce time.Duration - - // Indicates that the window has just been closed - justClosed bool - - // Indicates that the window has been shown a first time - hasBeenShown bool - - // Used to ensure that the window state is read on first click - initialClick sync.Once -} - -// AttachWindow attaches a window to the system tray. The window will be shown when the system tray icon is clicked. -// The window will be hidden when the system tray icon is clicked again, or when the window loses focus. -func (s *SystemTray) AttachWindow(window Window) *SystemTray { - s.attachedWindow.Window = window - return s -} - -// WindowOffset sets the gap in pixels between the system tray and the window -func (s *SystemTray) WindowOffset(offset int) *SystemTray { - s.attachedWindow.Offset = offset - return s -} - -// WindowDebounce is used by Windows to indicate how long to wait before responding to a mouse -// up event on the notification icon. This prevents the window from being hidden and then immediately -// shown when the user clicks on the system tray icon. -// See https://stackoverflow.com/questions/4585283/alternate-showing-hiding-window-when-notify-icon-is-clicked -func (s *SystemTray) WindowDebounce(debounce time.Duration) *SystemTray { - s.attachedWindow.Debounce = debounce - return s -} - -func (s *SystemTray) OpenMenu() { - if s.menu == nil { - return - } - if s.impl == nil { - return - } - InvokeSync(s.impl.openMenu) -} diff --git a/v3/pkg/application/systemtray_android.go b/v3/pkg/application/systemtray_android.go deleted file mode 100644 index 489a58853..000000000 --- a/v3/pkg/application/systemtray_android.go +++ /dev/null @@ -1,102 +0,0 @@ -//go:build android - -package application - -// Android doesn't have system tray support -// These are placeholder implementations - -func (t *SystemTray) update() {} - -func (t *SystemTray) setMenu(menu *Menu) { - // Android doesn't have system tray -} - -func (t *SystemTray) close() { - // Android doesn't have system tray -} - -func (t *SystemTray) attachWindow(window *WebviewWindow) { - // Android doesn't have system tray -} - -func (t *SystemTray) detachWindow(windowID uint) { - // Android doesn't have system tray -} - -type androidSystemTray struct { - parent *SystemTray -} - -func newSystemTrayImpl(s *SystemTray) systemTrayImpl { - return &androidSystemTray{ - parent: s, - } -} - -func (s *androidSystemTray) run() { - // Android doesn't have system tray -} - -func (s *androidSystemTray) setLabel(_ string) { - // Android doesn't have system tray -} - -func (s *androidSystemTray) setMenu(_ *Menu) { - // Android doesn't have system tray -} - -func (s *androidSystemTray) setIcon(_ []byte) { - // Android doesn't have system tray -} - -func (s *androidSystemTray) setDarkModeIcon(_ []byte) { - // Android doesn't have system tray -} - -func (s *androidSystemTray) destroy() { - // Android doesn't have system tray -} - -func (s *androidSystemTray) setIconPosition(_ IconPosition) { - // Android doesn't have system tray -} - -func (s *androidSystemTray) positionWindow(_ Window, _ int) error { - return nil -} - -func (s *androidSystemTray) detachWindowPositioning(_ uint) { - // Android doesn't have system tray -} - -func (s *androidSystemTray) setTemplateIcon(_ []byte) { - // Android doesn't have system tray -} - -func (s *androidSystemTray) openMenu() { - // Android doesn't have system tray -} - -func (s *androidSystemTray) setTooltip(_ string) { - // Android doesn't have system tray -} - -func (s *androidSystemTray) bounds() (*Rect, error) { - return nil, nil -} - -func (s *androidSystemTray) getScreen() (*Screen, error) { - screens, err := getScreens() - if err != nil || len(screens) == 0 { - return nil, err - } - return screens[0], nil -} - -func (s *androidSystemTray) Show() { - // Android doesn't have system tray -} - -func (s *androidSystemTray) Hide() { - // Android doesn't have system tray -} diff --git a/v3/pkg/application/systemtray_bench_test.go b/v3/pkg/application/systemtray_bench_test.go deleted file mode 100644 index 3691f0f59..000000000 --- a/v3/pkg/application/systemtray_bench_test.go +++ /dev/null @@ -1,374 +0,0 @@ -//go:build bench - -package application - -import ( - "testing" - "time" -) - -// Note: SystemTray benchmarks are limited since actual system tray operations -// require platform-specific GUI initialization. These benchmarks focus on -// the Go-side logic that can be tested without a running GUI. - -// BenchmarkSystemTrayCreation measures the cost of creating SystemTray instances -func BenchmarkSystemTrayCreation(b *testing.B) { - for b.Loop() { - tray := newSystemTray(1) - _ = tray - } -} - -// BenchmarkSystemTrayConfiguration measures configuration operations -func BenchmarkSystemTrayConfiguration(b *testing.B) { - b.Run("SetLabel", func(b *testing.B) { - tray := newSystemTray(1) - // impl is nil, so this just sets the field - for b.Loop() { - tray.SetLabel("Test Label") - } - }) - - b.Run("SetTooltip", func(b *testing.B) { - tray := newSystemTray(1) - for b.Loop() { - tray.SetTooltip("Test Tooltip") - } - }) - - b.Run("SetIcon", func(b *testing.B) { - tray := newSystemTray(1) - icon := make([]byte, 1024) // 1KB icon data - for b.Loop() { - tray.SetIcon(icon) - } - }) - - b.Run("SetDarkModeIcon", func(b *testing.B) { - tray := newSystemTray(1) - icon := make([]byte, 1024) - for b.Loop() { - tray.SetDarkModeIcon(icon) - } - }) - - b.Run("SetTemplateIcon", func(b *testing.B) { - tray := newSystemTray(1) - icon := make([]byte, 1024) - for b.Loop() { - tray.SetTemplateIcon(icon) - } - }) - - b.Run("SetIconPosition", func(b *testing.B) { - tray := newSystemTray(1) - for b.Loop() { - tray.SetIconPosition(NSImageLeading) - } - }) - - b.Run("ChainedConfiguration", func(b *testing.B) { - icon := make([]byte, 1024) - for b.Loop() { - tray := newSystemTray(1) - tray.SetIcon(icon). - SetDarkModeIcon(icon). - SetIconPosition(NSImageLeading) - } - }) -} - -// BenchmarkClickHandlerExecution measures handler registration and invocation -func BenchmarkClickHandlerExecution(b *testing.B) { - b.Run("RegisterClickHandler", func(b *testing.B) { - for b.Loop() { - tray := newSystemTray(1) - tray.OnClick(func() {}) - } - }) - - b.Run("RegisterAllHandlers", func(b *testing.B) { - for b.Loop() { - tray := newSystemTray(1) - tray.OnClick(func() {}) - tray.OnRightClick(func() {}) - tray.OnDoubleClick(func() {}) - tray.OnRightDoubleClick(func() {}) - tray.OnMouseEnter(func() {}) - tray.OnMouseLeave(func() {}) - } - }) - - b.Run("InvokeClickHandler", func(b *testing.B) { - tray := newSystemTray(1) - counter := 0 - tray.OnClick(func() { - counter++ - }) - - b.ResetTimer() - for b.Loop() { - if tray.clickHandler != nil { - tray.clickHandler() - } - } - }) - - b.Run("InvokeAllHandlers", func(b *testing.B) { - tray := newSystemTray(1) - counter := 0 - handler := func() { counter++ } - tray.OnClick(handler) - tray.OnRightClick(handler) - tray.OnDoubleClick(handler) - tray.OnRightDoubleClick(handler) - tray.OnMouseEnter(handler) - tray.OnMouseLeave(handler) - - b.ResetTimer() - for b.Loop() { - if tray.clickHandler != nil { - tray.clickHandler() - } - if tray.rightClickHandler != nil { - tray.rightClickHandler() - } - if tray.doubleClickHandler != nil { - tray.doubleClickHandler() - } - if tray.rightDoubleClickHandler != nil { - tray.rightDoubleClickHandler() - } - if tray.mouseEnterHandler != nil { - tray.mouseEnterHandler() - } - if tray.mouseLeaveHandler != nil { - tray.mouseLeaveHandler() - } - } - }) -} - -// BenchmarkWindowAttachment measures window attachment configuration -func BenchmarkWindowAttachment(b *testing.B) { - b.Run("AttachWindow", func(b *testing.B) { - // We can't create real windows, but we can test the attachment logic - for b.Loop() { - tray := newSystemTray(1) - // AttachWindow accepts nil gracefully - tray.AttachWindow(nil) - } - }) - - b.Run("WindowOffset", func(b *testing.B) { - tray := newSystemTray(1) - for b.Loop() { - tray.WindowOffset(10) - } - }) - - b.Run("WindowDebounce", func(b *testing.B) { - tray := newSystemTray(1) - for b.Loop() { - tray.WindowDebounce(200 * time.Millisecond) - } - }) - - b.Run("ChainedAttachment", func(b *testing.B) { - for b.Loop() { - tray := newSystemTray(1) - tray.AttachWindow(nil). - WindowOffset(10). - WindowDebounce(200 * time.Millisecond) - } - }) -} - -// BenchmarkMenuConfiguration measures menu setup operations -func BenchmarkMenuConfiguration(b *testing.B) { - b.Run("SetNilMenu", func(b *testing.B) { - tray := newSystemTray(1) - for b.Loop() { - tray.SetMenu(nil) - } - }) - - b.Run("SetSimpleMenu", func(b *testing.B) { - menu := NewMenu() - menu.Add("Item 1") - menu.Add("Item 2") - menu.Add("Item 3") - - tray := newSystemTray(1) - b.ResetTimer() - for b.Loop() { - tray.SetMenu(menu) - } - }) - - b.Run("SetComplexMenu", func(b *testing.B) { - menu := NewMenu() - for i := 0; i < 20; i++ { - menu.Add("Item") - } - submenu := NewMenu() - for i := 0; i < 10; i++ { - submenu.Add("Subitem") - } - - tray := newSystemTray(1) - b.ResetTimer() - for b.Loop() { - tray.SetMenu(menu) - } - }) -} - -// BenchmarkIconSizes measures icon handling with different sizes -func BenchmarkIconSizes(b *testing.B) { - sizes := []struct { - name string - size int - }{ - {"16x16", 16 * 16 * 4}, // 1KB - small icon - {"32x32", 32 * 32 * 4}, // 4KB - medium icon - {"64x64", 64 * 64 * 4}, // 16KB - large icon - {"128x128", 128 * 128 * 4}, // 64KB - retina icon - {"256x256", 256 * 256 * 4}, // 256KB - high-res icon - } - - for _, size := range sizes { - b.Run(size.name, func(b *testing.B) { - icon := make([]byte, size.size) - tray := newSystemTray(1) - - b.ResetTimer() - for b.Loop() { - tray.SetIcon(icon) - } - }) - } -} - -// BenchmarkWindowAttachConfigInit measures WindowAttachConfig initialization -func BenchmarkWindowAttachConfigInit(b *testing.B) { - b.Run("DefaultConfig", func(b *testing.B) { - for b.Loop() { - config := WindowAttachConfig{ - Window: nil, - Offset: 0, - Debounce: 200 * time.Millisecond, - } - _ = config - } - }) - - b.Run("FullConfig", func(b *testing.B) { - for b.Loop() { - config := WindowAttachConfig{ - Window: nil, - Offset: 10, - Debounce: 300 * time.Millisecond, - justClosed: false, - hasBeenShown: true, - } - _ = config - } - }) -} - -// BenchmarkSystemTrayShowHide measures show/hide state changes -// Note: These operations are no-ops when impl is nil, but we measure the check overhead -func BenchmarkSystemTrayShowHide(b *testing.B) { - b.Run("Show", func(b *testing.B) { - tray := newSystemTray(1) - for b.Loop() { - tray.Show() - } - }) - - b.Run("Hide", func(b *testing.B) { - tray := newSystemTray(1) - for b.Loop() { - tray.Hide() - } - }) - - b.Run("ToggleShowHide", func(b *testing.B) { - tray := newSystemTray(1) - for b.Loop() { - tray.Show() - tray.Hide() - } - }) -} - -// BenchmarkIconPositionConstants measures icon position constant access -func BenchmarkIconPositionConstants(b *testing.B) { - positions := []IconPosition{ - NSImageNone, - NSImageOnly, - NSImageLeft, - NSImageRight, - NSImageBelow, - NSImageAbove, - NSImageOverlaps, - NSImageLeading, - NSImageTrailing, - } - - b.Run("SetAllPositions", func(b *testing.B) { - tray := newSystemTray(1) - for b.Loop() { - for _, pos := range positions { - tray.SetIconPosition(pos) - } - } - }) -} - -// BenchmarkLabelOperations measures label getter/setter performance -func BenchmarkLabelOperations(b *testing.B) { - b.Run("SetLabel", func(b *testing.B) { - tray := newSystemTray(1) - for b.Loop() { - tray.SetLabel("System Tray Label") - } - }) - - b.Run("GetLabel", func(b *testing.B) { - tray := newSystemTray(1) - tray.SetLabel("System Tray Label") - b.ResetTimer() - for b.Loop() { - _ = tray.Label() - } - }) - - b.Run("SetGetLabel", func(b *testing.B) { - tray := newSystemTray(1) - for b.Loop() { - tray.SetLabel("Label") - _ = tray.Label() - } - }) -} - -// BenchmarkDefaultClickHandler measures the default click handler logic -func BenchmarkDefaultClickHandler(b *testing.B) { - b.Run("NoAttachedWindow", func(b *testing.B) { - tray := newSystemTray(1) - // With no menu and no attached window, defaultClickHandler returns early - for b.Loop() { - tray.defaultClickHandler() - } - }) - - b.Run("WithNilWindow", func(b *testing.B) { - tray := newSystemTray(1) - tray.attachedWindow.Window = nil - for b.Loop() { - tray.defaultClickHandler() - } - }) -} diff --git a/v3/pkg/application/systemtray_darwin.go b/v3/pkg/application/systemtray_darwin.go deleted file mode 100644 index c88c835c0..000000000 --- a/v3/pkg/application/systemtray_darwin.go +++ /dev/null @@ -1,287 +0,0 @@ -//go:build darwin && !ios - -package application - -/* -#cgo CFLAGS: -mmacosx-version-min=10.13 -x objective-c -#cgo LDFLAGS: -framework Cocoa -framework WebKit - -#include "Cocoa/Cocoa.h" -#include "menuitem_darwin.h" -#include "systemtray_darwin.h" - -// Show the system tray icon -static void systemTrayShow(void* nsStatusItem) { - dispatch_async(dispatch_get_main_queue(), ^{ - // Get the NSStatusItem - NSStatusItem *statusItem = (NSStatusItem *)nsStatusItem; - [statusItem setVisible:YES]; - }); -} - -// Hide the system tray icon -static void systemTrayHide(void* nsStatusItem) { - dispatch_async(dispatch_get_main_queue(), ^{ - NSStatusItem *statusItem = (NSStatusItem *)nsStatusItem; - [statusItem setVisible:NO]; - }); -} - -*/ -import "C" -import ( - "errors" - "unsafe" - - "github.com/leaanthony/go-ansi-parser" -) - -type macosSystemTray struct { - id uint - label string - icon []byte - menu *Menu - - nsStatusItem unsafe.Pointer - nsImage unsafe.Pointer - nsMenu unsafe.Pointer - iconPosition IconPosition - isTemplateIcon bool - parent *SystemTray - lastClickedScreen unsafe.Pointer -} - -func (s *macosSystemTray) Show() { - if s.nsStatusItem == nil { - return - } - C.systemTrayShow(s.nsStatusItem) -} - -func (s *macosSystemTray) Hide() { - if s.nsStatusItem == nil { - return - } - C.systemTrayHide(s.nsStatusItem) -} - -func (s *macosSystemTray) openMenu() { - if s.nsMenu == nil { - return - } - C.showMenu(s.nsStatusItem, s.nsMenu) -} - -type button int - -const ( - leftButtonDown button = 1 - rightButtonDown button = 3 -) - -// system tray map -var systemTrayMap = make(map[uint]*macosSystemTray) - -//export systrayClickCallback -func systrayClickCallback(id C.long, buttonID C.int) { - // Get the system tray - systemTray := systemTrayMap[uint(id)] - if systemTray == nil { - globalApplication.error("system tray not found: %v", id) - return - } - systemTray.processClick(button(buttonID)) -} - -func (s *macosSystemTray) setIconPosition(position IconPosition) { - s.iconPosition = position -} - -func (s *macosSystemTray) setMenu(menu *Menu) { - s.menu = menu -} - -func (s *macosSystemTray) positionWindow(window Window, offset int) error { - // Get the platform-specific window implementation - nativeWindow := window.NativeWindow() - if nativeWindow == nil { - return errors.New("window native implementation unavailable") - } - - // Position the window relative to the systray - C.systemTrayPositionWindow(s.nsStatusItem, nativeWindow, C.int(offset)) - - return nil -} - -func (s *macosSystemTray) getScreen() (*Screen, error) { - if s.lastClickedScreen != nil { - // Get the screen frame - frame := C.NSScreen_frame(s.lastClickedScreen) - result := &Screen{ - Bounds: Rect{ - X: int(frame.origin.x), - Y: int(frame.origin.y), - Width: int(frame.size.width), - Height: int(frame.size.height), - }, - } - return result, nil - } - return nil, errors.New("no screen available") -} - -func (s *macosSystemTray) bounds() (*Rect, error) { - var rect C.NSRect - var screen unsafe.Pointer - C.systemTrayGetBounds(s.nsStatusItem, &rect, &screen) - - // Store the screen for use in positionWindow - s.lastClickedScreen = screen - - // Return the screen-relative coordinates - result := &Rect{ - X: int(rect.origin.x), - Y: int(rect.origin.y), - Width: int(rect.size.width), - Height: int(rect.size.height), - } - return result, nil -} - -func (s *macosSystemTray) run() { - globalApplication.dispatchOnMainThread(func() { - if s.nsStatusItem != nil { - Fatal("System tray '%d' already running", s.id) - } - s.nsStatusItem = unsafe.Pointer(C.systemTrayNew(C.long(s.id))) - - if s.label != "" { - s.setLabel(s.label) - } - if s.icon != nil { - s.nsImage = unsafe.Pointer(C.imageFromBytes((*C.uchar)(&s.icon[0]), C.int(len(s.icon)))) - C.systemTraySetIcon(s.nsStatusItem, s.nsImage, C.int(s.iconPosition), C.bool(s.isTemplateIcon)) - } - if s.menu != nil { - s.menu.Update() - // Convert impl to macosMenu object - s.nsMenu = (s.menu.impl).(*macosMenu).nsMenu - } - }) -} - -func (s *macosSystemTray) setIcon(icon []byte) { - s.icon = icon - globalApplication.dispatchOnMainThread(func() { - s.nsImage = unsafe.Pointer(C.imageFromBytes((*C.uchar)(&icon[0]), C.int(len(icon)))) - C.systemTraySetIcon(s.nsStatusItem, s.nsImage, C.int(s.iconPosition), C.bool(s.isTemplateIcon)) - }) -} - -func (s *macosSystemTray) setDarkModeIcon(icon []byte) { - s.setIcon(icon) -} - -func (s *macosSystemTray) setTemplateIcon(icon []byte) { - s.icon = icon - s.isTemplateIcon = true - globalApplication.dispatchOnMainThread(func() { - s.nsImage = unsafe.Pointer(C.imageFromBytes((*C.uchar)(&icon[0]), C.int(len(icon)))) - C.systemTraySetIcon(s.nsStatusItem, s.nsImage, C.int(s.iconPosition), C.bool(s.isTemplateIcon)) - }) -} - -func (s *macosSystemTray) setTooltip(tooltip string) { - // Tooltips not supported on macOS -} - -func newSystemTrayImpl(s *SystemTray) systemTrayImpl { - result := &macosSystemTray{ - parent: s, - id: s.id, - label: s.label, - icon: s.icon, - menu: s.menu, - iconPosition: s.iconPosition, - isTemplateIcon: s.isTemplateIcon, - } - systemTrayMap[s.id] = result - return result -} - -func extractAnsiTextParts(text *ansi.StyledText) (label *C.char, fg *C.char, bg *C.char) { - label = C.CString(text.Label) - if text.FgCol != nil { - fg = C.CString(text.FgCol.Hex) - } - if text.BgCol != nil { - bg = C.CString(text.BgCol.Hex) - } - return -} - -func (s *macosSystemTray) setLabel(label string) { - s.label = label - if !ansi.HasEscapeCodes(label) { - C.systemTraySetLabel(s.nsStatusItem, C.CString(label)) - } else { - parsed, err := ansi.Parse(label) - if err != nil { - C.systemTraySetLabel(s.nsStatusItem, C.CString(label)) - return - } - if len(parsed) == 0 { - return - } - label, fg, bg := extractAnsiTextParts(parsed[0]) - var attributedString = C.createAttributedString(label, fg, bg) - if len(parsed) > 1 { - for _, parsedPart := range parsed[1:] { - label, fg, bg = extractAnsiTextParts(parsedPart) - attributedString = C.appendAttributedString(attributedString, label, fg, bg) - } - } - - C.systemTraySetANSILabel(s.nsStatusItem, attributedString) - } -} - -func (s *macosSystemTray) destroy() { - // Remove the status item from the status bar and its associated menu - C.systemTrayDestroy(s.nsStatusItem) -} - -func (s *macosSystemTray) processClick(b button) { - switch b { - case leftButtonDown: - // Check if we have a callback - if s.parent.clickHandler != nil { - s.parent.clickHandler() - return - } - if s.parent.attachedWindow.Window != nil { - s.parent.defaultClickHandler() - return - } - if s.menu != nil { - C.showMenu(s.nsStatusItem, s.nsMenu) - } - case rightButtonDown: - // Check if we have a callback - if s.parent.rightClickHandler != nil { - s.parent.rightClickHandler() - return - } - if s.menu != nil { - if s.parent.attachedWindow.Window != nil { - s.parent.attachedWindow.Window.Hide() - } - C.showMenu(s.nsStatusItem, s.nsMenu) - return - } - if s.parent.attachedWindow.Window != nil { - s.parent.defaultClickHandler() - } - } -} diff --git a/v3/pkg/application/systemtray_darwin.h b/v3/pkg/application/systemtray_darwin.h deleted file mode 100644 index 29404e095..000000000 --- a/v3/pkg/application/systemtray_darwin.h +++ /dev/null @@ -1,24 +0,0 @@ -//go:build darwin && !ios - -#include - -@interface StatusItemController : NSObject -@property long id; -- (void)statusItemClicked:(id)sender; -@end - -void* systemTrayNew(long id); -void systemTraySetLabel(void* nsStatusItem, char *label); -void systemTraySetANSILabel(void* nsStatusItem, void* attributedString); -void systemTraySetLabelColor(void* nsStatusItem, char *fg, char *bg); -void* createAttributedString(char *title, char *FG, char *BG); -void* appendAttributedString(void* original, char* label, char* fg, char* bg); -NSImage* imageFromBytes(const unsigned char *bytes, int length); -void systemTraySetIcon(void* nsStatusItem, void* nsImage, int position, bool isTemplate); -void systemTrayDestroy(void* nsStatusItem); -void showMenu(void* nsStatusItem, void *nsMenu); -void systemTrayGetBounds(void* nsStatusItem, NSRect *rect, void **screen); -NSRect NSScreen_frame(void* screen); -void windowSetScreen(void* window, void* screen, int yOffset); -int statusBarHeight(); -void systemTrayPositionWindow(void* nsStatusItem, void* nsWindow, int offset); \ No newline at end of file diff --git a/v3/pkg/application/systemtray_darwin.m b/v3/pkg/application/systemtray_darwin.m deleted file mode 100644 index a715fc125..000000000 --- a/v3/pkg/application/systemtray_darwin.m +++ /dev/null @@ -1,244 +0,0 @@ -//go:build darwin && !ios - -#include "Cocoa/Cocoa.h" -#include "menuitem_darwin.h" -#include "systemtray_darwin.h" - -extern void systrayClickCallback(long, int); - -// StatusItemController.m -@implementation StatusItemController - -- (void)statusItemClicked:(id)sender { - NSEvent *event = [NSApp currentEvent]; - systrayClickCallback(self.id, event.type); -} - -@end - -// Create a new system tray -void* systemTrayNew(long id) { - StatusItemController *controller = [[StatusItemController alloc] init]; - controller.id = id; - NSStatusItem *statusItem = [[[NSStatusBar systemStatusBar] statusItemWithLength:NSVariableStatusItemLength] retain]; - [statusItem setTarget:controller]; - [statusItem setAction:@selector(statusItemClicked:)]; - NSButton *button = statusItem.button; - [button sendActionOn:(NSEventMaskLeftMouseDown|NSEventMaskRightMouseDown)]; - return (void*)statusItem; -} - -void systemTraySetLabel(void* nsStatusItem, char *label) { - if( label == NULL ) { - return; - } - // Set the label on the main thread - dispatch_async(dispatch_get_main_queue(), ^{ - NSStatusItem *statusItem = (NSStatusItem *)nsStatusItem; - statusItem.button.title = [NSString stringWithUTF8String:label]; - free(label); - }); -} - -void systemTraySetANSILabel(void* nsStatusItem, void* label) { - if( label == NULL ) { - return; - } - - NSMutableAttributedString* attributedString = (NSMutableAttributedString*) label; - - // Set the label - NSStatusItem *statusItem = (NSStatusItem *)nsStatusItem; - [statusItem setAttributedTitle:attributedString]; - // [attributedString release]; -} - -void* appendAttributedString(void *currentString, char *title, char *FG, char *BG) { - - NSMutableAttributedString* newString = createAttributedString(title, FG, BG); - if( currentString != NULL ) { - NSMutableAttributedString* current = (NSMutableAttributedString*)currentString; - [current appendAttributedString:newString]; - newString = current; - } - - return (void*)newString; -} - -void* createAttributedString(char *title, char *FG, char *BG) { - - NSMutableDictionary *dictionary = [NSMutableDictionary new]; - - // RGBA - if(FG != NULL && strlen(FG) > 0) { - unsigned short r, g, b, a; - - // white by default - r = g = b = a = 255; - int count = sscanf(FG, "#%02hx%02hx%02hx%02hx", &r, &g, &b, &a); - if (count > 0) { - NSColor *colour = [NSColor colorWithCalibratedRed:(CGFloat)r / 255.0 - green:(CGFloat)g / 255.0 - blue:(CGFloat)b / 255.0 - alpha:(CGFloat)a / 255.0]; - dictionary[NSForegroundColorAttributeName] = colour; - - } - } - - // Calculate BG colour - if(BG != NULL && strlen(BG) > 0) { - unsigned short r, g, b, a; - - // white by default - r = g = b = a = 255; - int count = sscanf(BG, "#%02hx%02hx%02hx%02hx", &r, &g, &b, &a); - if (count > 0) { - NSColor *colour = [NSColor colorWithCalibratedRed:(CGFloat)r / 255.0 - green:(CGFloat)g / 255.0 - blue:(CGFloat)b / 255.0 - alpha:(CGFloat)a / 255.0]; - dictionary[NSBackgroundColorAttributeName] = colour; - } - } - NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithString:[NSString stringWithUTF8String:title] attributes:dictionary]; - return (void*)attributedString; -} - -// Create an nsimage from a byte array -NSImage* imageFromBytes(const unsigned char *bytes, int length) { - NSData *data = [NSData dataWithBytes:bytes length:length]; - NSImage *image = [[NSImage alloc] initWithData:data]; - return image; -} - -// Set the icon on the system tray -void systemTraySetIcon(void* nsStatusItem, void* nsImage, int position, bool isTemplate) { - // Set the icon on the main thread - dispatch_async(dispatch_get_main_queue(), ^{ - NSStatusItem *statusItem = (NSStatusItem *)nsStatusItem; - NSImage *image = (NSImage *)nsImage; - - NSStatusBar *statusBar = [NSStatusBar systemStatusBar]; - CGFloat thickness = [statusBar thickness]; - [image setSize:NSMakeSize(thickness, thickness)]; - if( isTemplate ) { - [image setTemplate:YES]; - } - statusItem.button.image = [image autorelease]; - statusItem.button.imagePosition = position; - }); -} - -// Destroy system tray -void systemTrayDestroy(void* nsStatusItem) { - // Remove the status item from the status bar and its associated menu - dispatch_async(dispatch_get_main_queue(), ^{ - NSStatusItem *statusItem = (NSStatusItem *)nsStatusItem; - [[NSStatusBar systemStatusBar] removeStatusItem:statusItem]; - [statusItem release]; - }); -} - -void showMenu(void* nsStatusItem, void *nsMenu) { - // Show the menu on the main thread - dispatch_async(dispatch_get_main_queue(), ^{ - NSStatusItem *statusItem = (NSStatusItem *)nsStatusItem; - [statusItem popUpStatusItemMenu:(NSMenu *)nsMenu]; - // Post a mouse up event so the statusitem defocuses - NSEvent *event = [NSEvent mouseEventWithType:NSEventTypeLeftMouseUp - location:[NSEvent mouseLocation] - modifierFlags:0 - timestamp:[[NSProcessInfo processInfo] systemUptime] - windowNumber:0 - context:nil - eventNumber:0 - clickCount:1 - pressure:1]; - [NSApp postEvent:event atStart:NO]; - [statusItem.button highlight:NO]; - }); -} - -void systemTrayGetBounds(void* nsStatusItem, NSRect *rect, void **outScreen) { - NSStatusItem *statusItem = (NSStatusItem *)nsStatusItem; - NSStatusBarButton *button = statusItem.button; - - // Get mouse location and find the screen it's on - NSPoint mouseLocation = [NSEvent mouseLocation]; - NSScreen *screen = nil; - NSArray *screens = [NSScreen screens]; - - for (NSScreen *candidate in screens) { - NSRect frame = [candidate frame]; - if (NSPointInRect(mouseLocation, frame)) { - screen = candidate; - break; - } - } - if (!screen) { - screen = [NSScreen mainScreen]; - } - - // Get button frame in screen coordinates - NSRect buttonFrame = button.frame; - NSRect buttonFrameScreen = [button.window convertRectToScreen:buttonFrame]; - - *rect = buttonFrameScreen; - *outScreen = (void*)screen; -} - -NSRect NSScreen_frame(void* screen) { - return [(NSScreen*)screen frame]; -} - -int statusBarHeight() { - NSMenu *mainMenu = [NSApp mainMenu]; - CGFloat menuBarHeight = [mainMenu menuBarHeight]; - return (int)menuBarHeight; -} - -void systemTrayPositionWindow(void* nsStatusItem, void* nsWindow, int offset) { - // Get the status item's button - NSStatusBarButton *button = [(NSStatusItem*)nsStatusItem button]; - - // Get the frame in screen coordinates - NSRect frame = [button.window convertRectToScreen:button.frame]; - - // Get the screen that contains the status item - NSScreen *screen = [button.window screen]; - if (screen == nil) { - screen = [NSScreen mainScreen]; - } - - // Get screen's backing scale factor (DPI) - CGFloat scaleFactor = [screen backingScaleFactor]; - - // Get the window's frame - NSRect windowFrame = [(NSWindow*)nsWindow frame]; - - // Calculate the horizontal position (centered under the status item) - CGFloat windowX = frame.origin.x + (frame.size.width - windowFrame.size.width) / 2; - - // If the window would go off the right edge of the screen, adjust it - if (windowX + windowFrame.size.width > screen.frame.origin.x + screen.frame.size.width) { - windowX = screen.frame.origin.x + screen.frame.size.width - windowFrame.size.width; - } - // If the window would go off the left edge of the screen, adjust it - if (windowX < screen.frame.origin.x) { - windowX = screen.frame.origin.x; - } - - // Get screen metrics - NSRect screenFrame = [screen frame]; - NSRect visibleFrame = [screen visibleFrame]; - - // Calculate the vertical position - CGFloat scaledOffset = offset * scaleFactor; - CGFloat windowY = visibleFrame.origin.y + visibleFrame.size.height - windowFrame.size.height - scaledOffset; - - // Set the window's frame - windowFrame.origin.x = windowX; - windowFrame.origin.y = windowY; - [(NSWindow*)nsWindow setFrame:windowFrame display:YES animate:NO]; -} diff --git a/v3/pkg/application/systemtray_ios.go b/v3/pkg/application/systemtray_ios.go deleted file mode 100644 index faa4d0427..000000000 --- a/v3/pkg/application/systemtray_ios.go +++ /dev/null @@ -1,103 +0,0 @@ -//go:build ios - -package application - -// iOS doesn't have system tray support -// These are placeholder implementations - -func (t *SystemTray) update() {} - -func (t *SystemTray) setMenu(menu *Menu) { - // iOS doesn't have system tray -} - -func (t *SystemTray) close() { - // iOS doesn't have system tray -} - - -func (t *SystemTray) attachWindow(window *WebviewWindow) { - // iOS doesn't have system tray -} - -func (t *SystemTray) detachWindow(windowID uint) { - // iOS doesn't have system tray -} - -type iosSystemTray struct { - parent *SystemTray -} - -func newSystemTrayImpl(s *SystemTray) systemTrayImpl { - return &iosSystemTray{ - parent: s, - } -} - -func (s *iosSystemTray) run() { - // iOS doesn't have system tray -} - -func (s *iosSystemTray) setLabel(_ string) { - // iOS doesn't have system tray -} - -func (s *iosSystemTray) setMenu(_ *Menu) { - // iOS doesn't have system tray -} - -func (s *iosSystemTray) setIcon(_ []byte) { - // iOS doesn't have system tray -} - -func (s *iosSystemTray) setDarkModeIcon(_ []byte) { - // iOS doesn't have system tray -} - -func (s *iosSystemTray) destroy() { - // iOS doesn't have system tray -} - -func (s *iosSystemTray) setIconPosition(_ IconPosition) { - // iOS doesn't have system tray -} - -func (s *iosSystemTray) positionWindow(_ Window, _ int) error { - return nil -} - -func (s *iosSystemTray) detachWindowPositioning(_ uint) { - // iOS doesn't have system tray -} - -func (s *iosSystemTray) setTemplateIcon(_ []byte) { - // iOS doesn't have system tray -} - -func (s *iosSystemTray) openMenu() { - // iOS doesn't have system tray -} - -func (s *iosSystemTray) setTooltip(_ string) { - // iOS doesn't have system tray -} - -func (s *iosSystemTray) bounds() (*Rect, error) { - return nil, nil -} - -func (s *iosSystemTray) getScreen() (*Screen, error) { - screens, err := getScreens() - if err != nil || len(screens) == 0 { - return nil, err - } - return screens[0], nil -} - -func (s *iosSystemTray) Show() { - // iOS doesn't have system tray -} - -func (s *iosSystemTray) Hide() { - // iOS doesn't have system tray -} \ No newline at end of file diff --git a/v3/pkg/application/systemtray_linux.go b/v3/pkg/application/systemtray_linux.go deleted file mode 100644 index 6c8d03a82..000000000 --- a/v3/pkg/application/systemtray_linux.go +++ /dev/null @@ -1,783 +0,0 @@ -//go:build linux && !android && !server - -/* -Portions of this code are derived from the project: -- https://github.com/fyne-io/systray -*/ -package application - -import "C" -import ( - "fmt" - "os" - - "github.com/godbus/dbus/v5" - "github.com/godbus/dbus/v5/introspect" - "github.com/godbus/dbus/v5/prop" - "github.com/wailsapp/wails/v3/internal/dbus/menu" - "github.com/wailsapp/wails/v3/internal/dbus/notifier" - "github.com/wailsapp/wails/v3/pkg/icons" -) - -const ( - itemPath = "/StatusNotifierItem" - menuPath = "/StatusNotifierMenu" -) - -type linuxSystemTray struct { - parent *SystemTray - - id uint - label string - icon []byte - menu *Menu - - iconPosition IconPosition - isTemplateIcon bool - - quitChan chan struct{} - conn *dbus.Conn - props *prop.Properties - menuProps *prop.Properties - - menuVersion uint32 - itemMap map[int32]*systrayMenuItem - tooltip string - - lastClickX int - lastClickY int -} - -func (s *linuxSystemTray) getScreen() (*Screen, error) { - _, _, result := getMousePosition() - return result, nil -} - -// dbusMenu is a named struct to map into generated bindings. -// It represents the layout of a menu item -type dbusMenu = struct { - V0 int32 // items' unique id - V1 map[string]dbus.Variant // layout properties - V2 []dbus.Variant // child menu(s) -} - -// systrayMenuItem is an implementation of the menuItemImpl interface -type systrayMenuItem struct { - sysTray *linuxSystemTray - menuItem *MenuItem - dbusItem *dbusMenu -} - -func (s *systrayMenuItem) setBitmap(data []byte) { - s.dbusItem.V1["icon-data"] = dbus.MakeVariant(data) - s.sysTray.update(s) -} - -func (s *systrayMenuItem) setTooltip(v string) { - s.dbusItem.V1["tooltip"] = dbus.MakeVariant(v) - s.sysTray.update(s) -} - -func (s *systrayMenuItem) setLabel(v string) { - s.dbusItem.V1["label"] = dbus.MakeVariant(v) - s.sysTray.update(s) -} - -func (s *systrayMenuItem) setDisabled(disabled bool) { - v := dbus.MakeVariant(!disabled) - if s.dbusItem.V1["toggle-state"] != v { - s.dbusItem.V1["enabled"] = v - s.sysTray.update(s) - } -} - -func (s *systrayMenuItem) destroy() {} - -func (s *systrayMenuItem) setChecked(checked bool) { - v := dbus.MakeVariant(0) - if checked { - v = dbus.MakeVariant(1) - } - if s.dbusItem.V1["toggle-state"] != v { - s.dbusItem.V1["toggle-state"] = v - s.sysTray.update(s) - } -} - -func (s *systrayMenuItem) setAccelerator(accelerator *accelerator) {} -func (s *systrayMenuItem) setHidden(hidden bool) { - s.dbusItem.V1["visible"] = dbus.MakeVariant(!hidden) - s.sysTray.update(s) -} - -func (s *systrayMenuItem) dbus() *dbusMenu { - item := &dbusMenu{ - V0: int32(s.menuItem.id), - V1: map[string]dbus.Variant{}, - V2: []dbus.Variant{}, - } - return item -} - -func (s *linuxSystemTray) setIconPosition(position IconPosition) { - s.iconPosition = position -} - -func (s *linuxSystemTray) processMenu(menu *Menu, parentId int32) { - parentItem, ok := s.itemMap[int32(parentId)] - if !ok { - return - } - parent := parentItem.dbusItem - - for _, item := range menu.items { - menuItem := &dbusMenu{ - V0: int32(item.id), - V1: map[string]dbus.Variant{}, - V2: []dbus.Variant{}, - } - item.impl = &systrayMenuItem{ - sysTray: s, - menuItem: item, - dbusItem: menuItem, - } - s.itemMap[int32(item.id)] = item.impl.(*systrayMenuItem) - - menuItem.V1["enabled"] = dbus.MakeVariant(!item.disabled) - menuItem.V1["visible"] = dbus.MakeVariant(!item.hidden) - if item.label != "" { - menuItem.V1["label"] = dbus.MakeVariant(item.label) - } - if item.bitmap != nil { - menuItem.V1["icon-data"] = dbus.MakeVariant(item.bitmap) - } - switch item.itemType { - case checkbox: - menuItem.V1["toggle-type"] = dbus.MakeVariant("checkmark") - v := dbus.MakeVariant(0) - if item.checked { - v = dbus.MakeVariant(1) - } - menuItem.V1["toggle-state"] = v - case submenu: - menuItem.V1["children-display"] = dbus.MakeVariant("submenu") - s.processMenu(item.submenu, int32(item.id)) - case text: - case radio: - menuItem.V1["toggle-type"] = dbus.MakeVariant("radio") - v := dbus.MakeVariant(0) - if item.checked { - v = dbus.MakeVariant(1) - } - menuItem.V1["toggle-state"] = v - case separator: - menuItem.V1["type"] = dbus.MakeVariant("separator") - } - - parent.V2 = append(parent.V2, dbus.MakeVariant(menuItem)) - } -} - -func (s *linuxSystemTray) refresh() { - s.menuVersion++ - if err := s.menuProps.Set("com.canonical.dbusmenu", "Version", - dbus.MakeVariant(s.menuVersion)); err != nil { - globalApplication.error("systray error: failed to update menu version: %w", err) - return - } - if err := menu.Emit(s.conn, &menu.Dbusmenu_LayoutUpdatedSignal{ - Path: menuPath, - Body: &menu.Dbusmenu_LayoutUpdatedSignalBody{ - Revision: s.menuVersion, - }, - }); err != nil { - globalApplication.error("systray error: failed to emit layout updated signal: %w", err) - } -} - -func (s *linuxSystemTray) setMenu(menu *Menu) { - s.itemMap = map[int32]*systrayMenuItem{} - s.itemMap[0] = &systrayMenuItem{ - menuItem: nil, - dbusItem: &dbusMenu{ - V0: int32(0), - V1: map[string]dbus.Variant{}, - V2: []dbus.Variant{}, - }, - } - if menu != nil { - menu.processRadioGroups() - s.processMenu(menu, 0) - } - s.menu = menu - s.refresh() -} - -func (s *linuxSystemTray) positionWindow(window Window, offset int) error { - _, _, currentScreen := getMousePosition() - if currentScreen == nil { - return fmt.Errorf("unable to get screen information") - } - - screenX := currentScreen.X - screenY := currentScreen.Y - screenWidth := currentScreen.Size.Width - screenHeight := currentScreen.Size.Height - windowWidth := window.Width() - windowHeight := window.Height() - - if isTilingWM() { - newX := screenX + (screenWidth-windowWidth)/2 - newY := screenY + (screenHeight-windowHeight)/2 - window.SetPosition(newX, newY) - return nil - } - - clickX, clickY := s.lastClickX, s.lastClickY - if clickX == 0 && clickY == 0 { - if cx, cy, ok := getCursorPositionFromCompositor(); ok { - clickX, clickY = cx, cy - } else { - clickX = screenX + screenWidth/2 - clickY = screenY + screenHeight/2 - } - } - - newX := clickX - (windowWidth / 2) - if newX < screenX { - newX = screenX - } - if newX+windowWidth > screenX+screenWidth { - newX = screenX + screenWidth - windowWidth - } - - relativeY := clickY - screenY - topThreshold := screenHeight / 5 - bottomThreshold := screenHeight * 4 / 5 - - var newY int - if relativeY < topThreshold { - newY = clickY + offset - } else if relativeY > bottomThreshold { - newY = clickY - windowHeight - offset - } else { - newY = clickY - (windowHeight / 2) - } - - if newY < screenY { - newY = screenY - } - if newY+windowHeight > screenY+screenHeight { - newY = screenY + screenHeight - windowHeight - } - - window.SetPosition(newX, newY) - return nil -} - -func (s *linuxSystemTray) bounds() (*Rect, error) { - - // Best effort guess at the screen bounds - - return &Rect{}, nil - -} - -func (s *linuxSystemTray) run() { - conn, err := dbus.SessionBus() - if err != nil { - globalApplication.error("systray error: failed to connect to DBus: %w\n", err) - return - } - err = notifier.ExportStatusNotifierItem(conn, itemPath, s) - if err != nil { - globalApplication.error("systray error: failed to export status notifier item: %w\n", err) - } - - err = menu.ExportDbusmenu(conn, menuPath, s) - if err != nil { - globalApplication.error("systray error: failed to export status notifier menu: %w", err) - return - } - - name := fmt.Sprintf("org.kde.StatusNotifierItem-%d-1", os.Getpid()) // register id 1 for this process - _, err = conn.RequestName(name, dbus.NameFlagDoNotQueue) - if err != nil { - globalApplication.error("systray error: failed to request name: %w", err) - // it's not critical error: continue - } - props, err := prop.Export(conn, itemPath, s.createPropSpec()) - if err != nil { - globalApplication.error("systray error: failed to export notifier item properties to bus: %w", err) - return - } - menuProps, err := prop.Export(conn, menuPath, s.createMenuPropSpec()) - if err != nil { - globalApplication.error("systray error: failed to export notifier menu properties to bus: %w", err) - return - } - - s.conn = conn - s.props = props - s.menuProps = menuProps - - node := introspect.Node{ - Name: itemPath, - Interfaces: []introspect.Interface{ - introspect.IntrospectData, - prop.IntrospectData, - notifier.IntrospectDataStatusNotifierItem, - }, - } - err = conn.Export(introspect.NewIntrospectable(&node), itemPath, "org.freedesktop.DBus.Introspectable") - if err != nil { - globalApplication.error("systray error: failed to export node introspection: %w", err) - return - } - menuNode := introspect.Node{ - Name: menuPath, - Interfaces: []introspect.Interface{ - introspect.IntrospectData, - prop.IntrospectData, - menu.IntrospectDataDbusmenu, - }, - } - err = conn.Export(introspect.NewIntrospectable(&menuNode), menuPath, - "org.freedesktop.DBus.Introspectable") - if err != nil { - globalApplication.error("systray error: failed to export menu node introspection: %w", err) - return - } - s.setLabel(s.label) - go func() { - defer handlePanic() - s.register() - - if err := conn.AddMatchSignal( - dbus.WithMatchObjectPath("/org/freedesktop/DBus"), - dbus.WithMatchInterface("org.freedesktop.DBus"), - dbus.WithMatchSender("org.freedesktop.DBus"), - dbus.WithMatchMember("NameOwnerChanged"), - dbus.WithMatchArg(0, "org.kde.StatusNotifierWatcher"), - ); err != nil { - globalApplication.error("systray error: failed to register signal matching: %w", err) - return - } - - sc := make(chan *dbus.Signal, 10) - conn.Signal(sc) - - for { - select { - case sig := <-sc: - if sig == nil { - return // We get a nil signal when closing the window. - } - // sig.Body has the args, which are [name old_owner new_owner] - if sig.Body[2] != "" { - s.register() - } - - case <-s.quitChan: - return - } - } - }() - - if s.parent.label != "" { - s.setLabel(s.parent.label) - } - - if s.parent.tooltip != "" { - s.setTooltip(s.parent.tooltip) - } - s.setMenu(s.menu) -} - -func (s *linuxSystemTray) setTooltip(_ string) { - // TBD -} - -func (s *linuxSystemTray) setIcon(icon []byte) { - - s.icon = icon - - iconPx, err := iconToPX(icon) - if err != nil { - globalApplication.error("systray error: failed to convert icon to PX: %w", err) - return - } - s.props.SetMust("org.kde.StatusNotifierItem", "IconPixmap", []PX{iconPx}) - - if s.conn == nil { - return - } - - err = notifier.Emit(s.conn, ¬ifier.StatusNotifierItem_NewIconSignal{ - Path: itemPath, - Body: ¬ifier.StatusNotifierItem_NewIconSignalBody{}, - }) - if err != nil { - globalApplication.error("systray error: failed to emit new icon signal: %w", err) - return - } -} - -func (s *linuxSystemTray) setDarkModeIcon(icon []byte) { - s.setIcon(icon) -} - -func (s *linuxSystemTray) setTemplateIcon(icon []byte) { - s.icon = icon - s.isTemplateIcon = true - s.setIcon(icon) -} - -func newSystemTrayImpl(s *SystemTray) systemTrayImpl { - label := s.label - if label == "" { - label = "Wails" - } - - return &linuxSystemTray{ - parent: s, - id: s.id, - label: label, - icon: s.icon, - menu: s.menu, - iconPosition: s.iconPosition, - isTemplateIcon: s.isTemplateIcon, - quitChan: make(chan struct{}), - menuVersion: 1, - } -} - -func (s *linuxSystemTray) openMenu() { - // FIXME: Emit com.canonical to open? - globalApplication.info("systray error: openMenu not implemented on Linux") -} - -func (s *linuxSystemTray) setLabel(label string) { - s.label = label - - if err := s.props.Set("org.kde.StatusNotifierItem", "Title", dbus.MakeVariant(label)); err != nil { - globalApplication.error("systray error: failed to set Title prop: %w", err) - return - } - - if s.conn == nil { - return - } - - if err := notifier.Emit(s.conn, ¬ifier.StatusNotifierItem_NewTitleSignal{ - Path: itemPath, - Body: ¬ifier.StatusNotifierItem_NewTitleSignalBody{}, - }); err != nil { - globalApplication.error("systray error: failed to emit new title signal: %w", err) - return - } - -} - -func (s *linuxSystemTray) destroy() { - close(s.quitChan) -} - -func (s *linuxSystemTray) createMenuPropSpec() map[string]map[string]*prop.Prop { - return map[string]map[string]*prop.Prop{ - "com.canonical.dbusmenu": { - // update version each time we change something - "Version": { - Value: s.menuVersion, - Writable: true, - Emit: prop.EmitTrue, - Callback: nil, - }, - "TextDirection": { - Value: "ltr", - Writable: false, - Emit: prop.EmitTrue, - Callback: nil, - }, - "Status": { - Value: "normal", - Writable: false, - Emit: prop.EmitTrue, - Callback: nil, - }, - "IconThemePath": { - Value: []string{}, - Writable: false, - Emit: prop.EmitTrue, - Callback: nil, - }, - }, - } -} - -func (s *linuxSystemTray) createPropSpec() map[string]map[string]*prop.Prop { - props := map[string]*prop.Prop{ - "Status": { - Value: "Active", // Passive, Active or NeedsAttention - Writable: false, - Emit: prop.EmitTrue, - Callback: nil, - }, - "Title": { - Value: s.label, - Writable: true, - Emit: prop.EmitTrue, - Callback: nil, - }, - "Id": { - Value: s.label, - Writable: false, - Emit: prop.EmitTrue, - Callback: nil, - }, - "Category": { - Value: "ApplicationStatus", - Writable: false, - Emit: prop.EmitTrue, - Callback: nil, - }, - "IconData": { - Value: "", - Writable: false, - Emit: prop.EmitTrue, - Callback: nil, - }, - - "IconName": { - Value: "", - Writable: false, - Emit: prop.EmitTrue, - Callback: nil, - }, - "IconThemePath": { - Value: "", - Writable: false, - Emit: prop.EmitTrue, - Callback: nil, - }, - "ItemIsMenu": { - Value: false, - Writable: false, - Emit: prop.EmitTrue, - Callback: nil, - }, - "ToolTip": { - Value: tooltip{V2: s.label}, - Writable: true, - Emit: prop.EmitTrue, - Callback: nil, - }, - } - - if s.icon == nil { - s.icon = icons.WailsLogoWhiteTransparent - } - if iconPx, err := iconToPX(s.icon); err == nil { - props["IconPixmap"] = &prop.Prop{ - Value: []PX{iconPx}, - Writable: true, - Emit: prop.EmitTrue, - Callback: nil, - } - } - - if s.menu != nil { - props["Menu"] = &prop.Prop{ - Value: dbus.ObjectPath(menuPath), - Writable: true, - Emit: prop.EmitTrue, - Callback: nil, - } - } - - return map[string]map[string]*prop.Prop{ - "org.kde.StatusNotifierItem": props, - } -} - -func (s *linuxSystemTray) update(i *systrayMenuItem) { - s.itemMap[int32(i.menuItem.id)] = i - s.refresh() -} - -func (s *linuxSystemTray) register() bool { - obj := s.conn.Object("org.kde.StatusNotifierWatcher", "/StatusNotifierWatcher") - call := obj.Call("org.kde.StatusNotifierWatcher.RegisterStatusNotifierItem", 0, itemPath) - if call.Err != nil { - globalApplication.error("systray error: failed to register: %w", call.Err) - return false - } - - return true -} - -type PX struct { - W, H int - Pix []byte -} - -func iconToPX(icon []byte) (PX, error) { - img, err := pngToImage(icon) - if err != nil { - return PX{}, err - } - w, h, bytes := ToARGB(img) - return PX{ - W: w, - H: h, - Pix: bytes, - }, nil -} - -// AboutToShow is an implementation of the com.canonical.dbusmenu.AboutToShow method. -func (s *linuxSystemTray) AboutToShow(id int32) (needUpdate bool, err *dbus.Error) { - return -} - -// AboutToShowGroup is an implementation of the com.canonical.dbusmenu.AboutToShowGroup method. -func (s *linuxSystemTray) AboutToShowGroup(ids []int32) (updatesNeeded []int32, idErrors []int32, err *dbus.Error) { - return -} - -// GetProperty is an implementation of the com.canonical.dbusmenu.GetProperty method. -func (s *linuxSystemTray) GetProperty(id int32, name string) (value dbus.Variant, err *dbus.Error) { - if item, ok := s.itemMap[id]; ok { - if p, ok := item.dbusItem.V1[name]; ok { - return p, nil - } - } - return -} - -func (s *linuxSystemTray) Event(id int32, eventID string, data dbus.Variant, timestamp uint32) (err *dbus.Error) { - globalApplication.debug("systray Event called", "id", id, "eventID", eventID, "lastClick", fmt.Sprintf("(%d,%d)", s.lastClickX, s.lastClickY)) - switch eventID { - case "clicked": - if item, ok := s.itemMap[id]; ok { - InvokeAsync(item.menuItem.handleClick) - } - case "opened": - if s.parent.clickHandler != nil { - s.parent.clickHandler() - } - if s.parent.onMenuOpen != nil { - s.parent.onMenuOpen() - } - case "closed": - if s.parent.onMenuClose != nil { - s.parent.onMenuClose() - } - } - return -} - -// EventGroup is an implementation of the com.canonical.dbusmenu.EventGroup method. -func (s *linuxSystemTray) EventGroup(events []struct { - V0 int32 - V1 string - V2 dbus.Variant - V3 uint32 -}) (idErrors []int32, err *dbus.Error) { - for _, event := range events { - fmt.Printf("EventGroup: %v, %v, %v, %v\n", event.V0, event.V1, event.V2, event.V3) - if event.V1 == "clicked" { - item, ok := s.itemMap[event.V0] - if ok { - InvokeAsync(item.menuItem.handleClick) - } - } - } - return -} - -// GetGroupProperties is an implementation of the com.canonical.dbusmenu.GetGroupProperties method. -func (s *linuxSystemTray) GetGroupProperties(ids []int32, propertyNames []string) (properties []struct { - V0 int32 - V1 map[string]dbus.Variant -}, err *dbus.Error) { - // FIXME: RLock? - /* instance.menuLock.Lock() - defer instance.menuLock.Unlock() - */ - for _, id := range ids { - if m, ok := s.itemMap[id]; ok { - p := struct { - V0 int32 - V1 map[string]dbus.Variant - }{ - V0: m.dbusItem.V0, - V1: make(map[string]dbus.Variant, len(m.dbusItem.V1)), - } - for k, v := range m.dbusItem.V1 { - p.V1[k] = v - } - properties = append(properties, p) - } - } - return properties, nil -} - -// GetLayout is an implementation of the com.canonical.dbusmenu.GetLayout method. -func (s *linuxSystemTray) GetLayout(parentID int32, recursionDepth int32, propertyNames []string) (revision uint32, layout dbusMenu, err *dbus.Error) { - // FIXME: RLock? - if m, ok := s.itemMap[parentID]; ok { - return s.menuVersion, *m.dbusItem, nil - } - - return -} - -func (s *linuxSystemTray) Activate(x int32, y int32) (err *dbus.Error) { - s.lastClickX = int(x) - s.lastClickY = int(y) - globalApplication.debug("systray Activate called", "x", x, "y", y) - if s.parent.clickHandler != nil { - s.parent.clickHandler() - } - return -} - -func (s *linuxSystemTray) ContextMenu(x int32, y int32) (err *dbus.Error) { - s.lastClickX = int(x) - s.lastClickY = int(y) - return nil -} - -func (s *linuxSystemTray) Scroll(delta int32, orientation string) (err *dbus.Error) { - return -} - -func (s *linuxSystemTray) SecondaryActivate(x int32, y int32) (err *dbus.Error) { - s.lastClickX = int(x) - s.lastClickY = int(y) - if s.parent.rightClickHandler != nil { - s.parent.rightClickHandler() - } else if s.menu != nil { - s.parent.OpenMenu() - } - return -} - -// Show is a no-op for Linux -func (s *linuxSystemTray) Show() { - // No-op -} - -// Hide is a no-op for Linux -func (s *linuxSystemTray) Hide() { - // No-op -} - -// tooltip is our data for a tooltip property. -// Param names need to match the generated code... -type tooltip = struct { - V0 string // name - V1 []PX // icons - V2 string // title - V3 string // description -} diff --git a/v3/pkg/application/systemtray_windows.go b/v3/pkg/application/systemtray_windows.go deleted file mode 100644 index 55bea46e8..000000000 --- a/v3/pkg/application/systemtray_windows.go +++ /dev/null @@ -1,636 +0,0 @@ -//go:build windows - -package application - -import ( - "errors" - "fmt" - "syscall" - "unsafe" - - "github.com/wailsapp/wails/v3/pkg/icons" - - "github.com/wailsapp/wails/v3/pkg/events" - "github.com/wailsapp/wails/v3/pkg/w32" -) - -const ( - wmUserSystray = w32.WM_USER + 1 -) - -type windowsSystemTray struct { - parent *SystemTray - - menu *Win32Menu - - cancelTheme func() - uid uint32 - hwnd w32.HWND - - lightModeIcon w32.HICON - lightModeIconOwned bool - darkModeIcon w32.HICON - darkModeIconOwned bool - currentIcon w32.HICON - currentIconOwned bool -} - -// releaseIcon destroys an icon handle only when we own it and no new handle reuses it. -// Shared handles (e.g. from LoadIcon/LoadIconWithResourceID) must not be passed to DestroyIcon per https://learn.microsoft.com/windows/win32/api/winuser/nf-winuser-destroyicon. -func (s *windowsSystemTray) releaseIcon(handle w32.HICON, owned bool, keep ...w32.HICON) { - if !owned || handle == 0 { - return - } - for _, k := range keep { - if handle == k { - return - } - } - w32.DestroyIcon(handle) -} - -func (s *windowsSystemTray) openMenu() { - if s.menu == nil { - return - } - // Get the system tray bounds - trayBounds, err := s.bounds() - if err != nil { - return - } - if trayBounds == nil { - return - } - - // Show the menu at the tray bounds - s.menu.ShowAt(trayBounds.X, trayBounds.Y) -} - -func (s *windowsSystemTray) positionWindow(window Window, offset int) error { - // Get the current screen trayBounds - currentScreen, err := s.getScreen() - if err != nil { - return err - } - - screenBounds := currentScreen.WorkArea - windowBounds := window.Bounds() - - newX := screenBounds.Width - windowBounds.Width - offset - newY := screenBounds.Height - windowBounds.Height - offset - - // systray icons in windows can either be in the taskbar - // or in a flyout menu. - var iconIsInTrayBounds bool - iconIsInTrayBounds, err = s.iconIsInTrayBounds() - if err != nil { - return err - } - - var trayBounds *Rect - var centerAlignX, centerAlignY int - - // we only need the traybounds if the icon is in the tray - if iconIsInTrayBounds { - trayBounds, err = s.bounds() - if err != nil { - return err - } - if trayBounds == nil { - return errors.New("failed to get system tray bounds") - } - *trayBounds = PhysicalToDipRect(*trayBounds) - centerAlignX = trayBounds.X + (trayBounds.Width / 2) - (windowBounds.Width / 2) - centerAlignY = trayBounds.Y + (trayBounds.Height / 2) - (windowBounds.Height / 2) - } - - taskbarBounds := w32.GetTaskbarPosition() - if taskbarBounds == nil { - return errors.New("failed to get taskbar position") - } - - // Set the window position based on the icon location - // if the icon is in the taskbar (traybounds) then we need - // to adjust the position so the window is centered on the icon - switch taskbarBounds.UEdge { - case w32.ABE_LEFT: - if iconIsInTrayBounds && centerAlignY <= newY { - newY = centerAlignY - } - newX = screenBounds.X + offset - case w32.ABE_TOP: - if iconIsInTrayBounds && centerAlignX <= newX { - newX = centerAlignX - } - newY = screenBounds.Y + offset - case w32.ABE_RIGHT: - if iconIsInTrayBounds && centerAlignY <= newY { - newY = centerAlignY - } - case w32.ABE_BOTTOM: - if iconIsInTrayBounds && centerAlignX <= newX { - newX = centerAlignX - } - } - newPos := currentScreen.relativeToAbsoluteDipPoint(Point{X: newX, Y: newY}) - windowBounds.X = newPos.X - windowBounds.Y = newPos.Y - window.SetBounds(windowBounds) - return nil -} - -func (s *windowsSystemTray) bounds() (*Rect, error) { - if s.hwnd == 0 { - return nil, errors.New("system tray window handle not initialized") - } - - bounds, err := w32.GetSystrayBounds(s.hwnd, s.uid) - if err != nil { - return nil, err - } - if bounds == nil { - return nil, errors.New("GetSystrayBounds returned nil") - } - - monitor := w32.MonitorFromWindow(s.hwnd, w32.MONITOR_DEFAULTTONEAREST) - if monitor == 0 { - return nil, errors.New("failed to get monitor") - } - - return &Rect{ - X: int(bounds.Left), - Y: int(bounds.Top), - Width: int(bounds.Right - bounds.Left), - Height: int(bounds.Bottom - bounds.Top), - }, nil -} - -func (s *windowsSystemTray) iconIsInTrayBounds() (bool, error) { - if s.hwnd == 0 { - return false, errors.New("system tray window handle not initialized") - } - - bounds, err := w32.GetSystrayBounds(s.hwnd, s.uid) - if err != nil { - return false, err - } - if bounds == nil { - return false, errors.New("GetSystrayBounds returned nil") - } - - taskbarRect := w32.GetTaskbarPosition() - if taskbarRect == nil { - return false, errors.New("failed to get taskbar position") - } - - inTasksBar := w32.RectInRect(bounds, &taskbarRect.Rc) - if inTasksBar { - return true, nil - } - - return false, nil -} - -func (s *windowsSystemTray) getScreen() (*Screen, error) { - if s.hwnd == 0 { - return nil, errors.New("system tray window handle not initialized") - } - // Get the screen for this systray - return getScreenForWindowHwnd(s.hwnd) -} - -func (s *windowsSystemTray) setMenu(menu *Menu) { - s.updateMenu(menu) -} - -func (s *windowsSystemTray) run() { - s.hwnd = w32.CreateWindowEx( - 0, - w32.MustStringToUTF16Ptr(globalApplication.options.Windows.WndClass), - nil, - 0, - 0, - 0, - 0, - 0, - w32.HWND_MESSAGE, - 0, - 0, - nil) - if s.hwnd == 0 { - globalApplication.fatal("failed to create tray window: %s", syscall.GetLastError()) - return - } - - s.uid = uint32(s.parent.id) - - // Resolve the base icons once so we can reuse them for light/dark modes - defaultIcon := w32.LoadIconWithResourceID(w32.GetModuleHandle(""), w32.RT_ICON) - - // Priority: custom icon > default app icon > built-in icon - if s.parent.icon != nil { - icon, err := w32.CreateSmallHIconFromImage(s.parent.icon) - if err == nil { - s.lightModeIcon = icon - s.lightModeIconOwned = true - } else { - globalApplication.warning("failed to create systray icon: %v", err) - } - } - - if s.lightModeIcon == 0 && defaultIcon != 0 { - s.lightModeIcon = defaultIcon - s.lightModeIconOwned = false - } - - if s.lightModeIcon == 0 { - icon, err := w32.CreateSmallHIconFromImage(icons.SystrayLight) - if err != nil { - globalApplication.warning("failed to create systray icon: %v", err) - s.lightModeIcon = 0 - s.lightModeIconOwned = false - } else { - s.lightModeIcon = icon - s.lightModeIconOwned = true - } - } - - if s.parent.darkModeIcon != nil { - icon, err := w32.CreateSmallHIconFromImage(s.parent.darkModeIcon) - if err == nil { - s.darkModeIcon = icon - s.darkModeIconOwned = true - } else { - globalApplication.warning("failed to create systray dark mode icon: %v", err) - } - } - - if s.darkModeIcon == 0 && s.parent.icon != nil && s.lightModeIcon != 0 { - s.darkModeIcon = s.lightModeIcon - s.darkModeIconOwned = false - } - - if s.darkModeIcon == 0 && defaultIcon != 0 { - s.darkModeIcon = defaultIcon - s.darkModeIconOwned = false - } - - if s.darkModeIcon == 0 { - icon, err := w32.CreateSmallHIconFromImage(icons.SystrayDark) - if err != nil { - globalApplication.warning("failed to create systray dark mode icon: %v", err) - s.darkModeIcon = 0 - s.darkModeIconOwned = false - } else { - s.darkModeIcon = icon - s.darkModeIconOwned = true - } - } - - if _, err := s.show(); err != nil { - // Initial systray add can fail when the shell is not available. This is handled downstream via TaskbarCreated message. - globalApplication.warning("initial systray add failed: %v", err) - } - - if s.parent.menu != nil { - s.updateMenu(s.parent.menu) - } - - // Set Default Callbacks - if s.parent.clickHandler == nil { - s.parent.clickHandler = func() { - globalApplication.debug("Left Button Clicked") - } - } - - if s.parent.rightClickHandler == nil { - s.parent.rightClickHandler = func() { - if s.menu != nil { - s.openMenu() - } - } - } - - // Listen for dark mode changes - s.cancelTheme = globalApplication.Event.OnApplicationEvent(events.Windows.SystemThemeChanged, func(event *ApplicationEvent) { - s.updateIcon() - }) - - // Register the system tray - getNativeApplication().registerSystemTray(s) -} - -func (s *windowsSystemTray) updateIcon() { - var newIcon w32.HICON - if w32.IsCurrentlyDarkMode() { - newIcon = s.darkModeIcon - } else { - newIcon = s.lightModeIcon - } - if s.currentIcon == newIcon { - return - } - - // Store the old icon to destroy it after updating - oldIcon := s.currentIcon - oldIconOwned := s.currentIconOwned - - s.currentIcon = newIcon - nid := s.newNotifyIconData() - nid.UFlags = w32.NIF_ICON - if s.currentIcon != 0 { - nid.HIcon = s.currentIcon - } - - if !w32.ShellNotifyIcon(w32.NIM_MODIFY, &nid) { - panic(syscall.GetLastError()) - } - - // Track ownership of the current icon so we know if we can destroy it later - currentOwned := false - if newIcon != 0 { - if newIcon == s.lightModeIcon && s.lightModeIconOwned { - currentOwned = true - } else if newIcon == s.darkModeIcon && s.darkModeIconOwned { - currentOwned = true - } - } - s.currentIconOwned = currentOwned - - // Destroy the old icon handle if it exists, we owned it, and nothing else references it - s.releaseIcon(oldIcon, oldIconOwned, s.lightModeIcon, s.darkModeIcon) -} - -func (s *windowsSystemTray) newNotifyIconData() w32.NOTIFYICONDATA { - nid := w32.NOTIFYICONDATA{ - UID: s.uid, - HWnd: s.hwnd, - } - nid.CbSize = uint32(unsafe.Sizeof(nid)) - return nid -} - -func (s *windowsSystemTray) setIcon(icon []byte) { - newIcon, err := w32.CreateSmallHIconFromImage(icon) - if err != nil { - globalApplication.error("failed to create systray light mode icon: %v", err) - return - } - - oldLight := s.lightModeIcon - oldLightOwned := s.lightModeIconOwned - oldDark := s.darkModeIcon - oldDarkOwned := s.darkModeIconOwned - - s.lightModeIcon = newIcon - s.lightModeIconOwned = true - - // Keep dark mode in sync when both modes shared the same handle (or dark was unset). - if s.darkModeIcon == 0 || s.darkModeIcon == oldLight { - s.darkModeIcon = newIcon - s.darkModeIconOwned = false - } - - // Only free previous handles we own that are no longer referenced. - s.releaseIcon(oldLight, oldLightOwned, s.lightModeIcon, s.darkModeIcon) - if oldDark != s.darkModeIcon { - s.releaseIcon(oldDark, oldDarkOwned, s.lightModeIcon, s.darkModeIcon) - } - - s.updateIcon() -} - -func (s *windowsSystemTray) setDarkModeIcon(icon []byte) { - newIcon, err := w32.CreateSmallHIconFromImage(icon) - if err != nil { - globalApplication.error("failed to create systray dark mode icon: %v", err) - return - } - - oldDark := s.darkModeIcon - oldDarkOwned := s.darkModeIconOwned - oldLight := s.lightModeIcon - oldLightOwned := s.lightModeIconOwned - - s.darkModeIcon = newIcon - s.darkModeIconOwned = true - - lightReplaced := false - - // Keep light mode in sync when both modes shared the same handle (or light was unset). - if s.lightModeIcon == 0 || s.lightModeIcon == oldDark { - s.lightModeIcon = newIcon - s.lightModeIconOwned = false - lightReplaced = true - } - - // Only free the previous handle if nothing else keeps a reference to it. - s.releaseIcon(oldDark, oldDarkOwned, s.lightModeIcon, s.darkModeIcon) - if lightReplaced { - s.releaseIcon(oldLight, oldLightOwned, s.lightModeIcon, s.darkModeIcon) - } - - s.updateIcon() -} - -func newSystemTrayImpl(parent *SystemTray) systemTrayImpl { - return &windowsSystemTray{ - parent: parent, - } -} - -func (s *windowsSystemTray) wndProc(msg uint32, wParam, lParam uintptr) uintptr { - switch msg { - case wmUserSystray: - msg := lParam & 0xffff - switch msg { - case w32.WM_LBUTTONUP: - if s.parent.clickHandler != nil { - s.parent.clickHandler() - } - case w32.WM_RBUTTONUP: - if s.parent.rightClickHandler != nil { - s.parent.rightClickHandler() - } - case w32.WM_LBUTTONDBLCLK: - if s.parent.doubleClickHandler != nil { - s.parent.doubleClickHandler() - } - case w32.WM_RBUTTONDBLCLK: - if s.parent.rightDoubleClickHandler != nil { - s.parent.rightDoubleClickHandler() - } - case w32.NIN_POPUPOPEN: - if s.parent.mouseEnterHandler != nil { - s.parent.mouseEnterHandler() - } - case w32.NIN_POPUPCLOSE: - if s.parent.mouseLeaveHandler != nil { - s.parent.mouseLeaveHandler() - } - } - // println(w32.WMMessageToString(msg)) - - // Menu processing - case w32.WM_COMMAND: - cmdMsgID := int(wParam & 0xffff) - if s.menu != nil { - s.menu.ProcessCommand(cmdMsgID) - } - default: - // msg := int(wParam & 0xffff) - // println(w32.WMMessageToString(uintptr(msg))) - } - - return w32.DefWindowProc(s.hwnd, msg, wParam, lParam) -} - -func (s *windowsSystemTray) updateMenu(menu *Menu) { - s.menu = NewPopupMenu(s.hwnd, menu) - s.menu.onMenuOpen = s.parent.onMenuOpen - s.menu.onMenuClose = s.parent.onMenuClose - s.menu.Update() -} - -func (s *windowsSystemTray) setTooltip(tooltip string) { - // Create a new NOTIFYICONDATA structure - nid := s.newNotifyIconData() - nid.UFlags = w32.NIF_TIP | w32.NIF_SHOWTIP - - // Ensure the tooltip length is within the limit (128 characters including null terminate characters for szTip for Windows 2000 and later) - // https://learn.microsoft.com/en-us/windows/win32/api/shellapi/ns-shellapi-notifyicondataw - tooltipUTF16, err := w32.StringToUTF16(truncateUTF16(tooltip, 127)) - if err != nil { - return - } - - copy(nid.SzTip[:], tooltipUTF16) - - // Modify the tray icon with the new tooltip - if !w32.ShellNotifyIcon(w32.NIM_MODIFY, &nid) { - return - } -} - -// ---- Unsupported ---- -func (s *windowsSystemTray) setLabel(label string) {} - -func (s *windowsSystemTray) setTemplateIcon(_ []byte) { - // Unsupported - do nothing -} - -func (s *windowsSystemTray) setIconPosition(position IconPosition) { - // Unsupported - do nothing -} - -func (s *windowsSystemTray) destroy() { - if s.cancelTheme != nil { - s.cancelTheme() - s.cancelTheme = nil - } - // Remove and delete the system tray - getNativeApplication().unregisterSystemTray(s) - if s.menu != nil { - s.menu.Destroy() - } - - // destroy the notification icon - nid := s.newNotifyIconData() - if !w32.ShellNotifyIcon(w32.NIM_DELETE, &nid) { - globalApplication.debug(syscall.GetLastError().Error()) - } - - // Clean up icon handles - lightIcon := s.lightModeIcon - darkIcon := s.darkModeIcon - currentIcon := s.currentIcon - - s.releaseIcon(lightIcon, s.lightModeIconOwned) - s.releaseIcon(darkIcon, s.darkModeIconOwned, lightIcon) - s.releaseIcon(currentIcon, s.currentIconOwned, lightIcon, darkIcon) - - s.lightModeIcon = 0 - s.lightModeIconOwned = false - s.darkModeIcon = 0 - s.darkModeIconOwned = false - s.currentIcon = 0 - s.currentIconOwned = false - - w32.DestroyWindow(s.hwnd) - s.hwnd = 0 -} - -func (s *windowsSystemTray) Show() { - if s.hwnd == 0 { - return - } - - nid := s.newNotifyIconData() - nid.UFlags = w32.NIF_STATE - nid.DwStateMask = w32.NIS_HIDDEN - nid.DwState = 0 - if !w32.ShellNotifyIcon(w32.NIM_MODIFY, &nid) { - globalApplication.debug("ShellNotifyIcon NIM_MODIFY show failed", "error", syscall.GetLastError()) - } -} - -func (s *windowsSystemTray) Hide() { - if s.hwnd == 0 { - return - } - - nid := s.newNotifyIconData() - nid.UFlags = w32.NIF_STATE - nid.DwStateMask = w32.NIS_HIDDEN - nid.DwState = w32.NIS_HIDDEN - if !w32.ShellNotifyIcon(w32.NIM_MODIFY, &nid) { - globalApplication.debug("ShellNotifyIcon NIM_MODIFY hide failed", "error", syscall.GetLastError()) - } -} - -func (s *windowsSystemTray) show() (w32.NOTIFYICONDATA, error) { - nid := s.newNotifyIconData() - nid.UFlags = w32.NIF_ICON | w32.NIF_MESSAGE - nid.HIcon = s.currentIcon - nid.UCallbackMessage = wmUserSystray - - if !w32.ShellNotifyIcon(w32.NIM_ADD, &nid) { - err := syscall.GetLastError() - return nid, fmt.Errorf("ShellNotifyIcon NIM_ADD failed: %w", err) - } - - nid.UVersion = w32.NOTIFYICON_VERSION_4 - if !w32.ShellNotifyIcon(w32.NIM_SETVERSION, &nid) { - err := syscall.GetLastError() - return nid, fmt.Errorf("ShellNotifyIcon NIM_SETVERSION failed: %w", err) - } - - s.updateIcon() - - if s.parent.tooltip != "" { - s.setTooltip(s.parent.tooltip) - } - - return nid, nil -} - -func truncateUTF16(s string, maxUnits int) string { - var units int - for i, r := range s { - var u int - - // check if rune will take 2 UTF-16 units - if r > 0xFFFF { - u = 2 - } else { - u = 1 - } - - if units+u > maxUnits { - return s[:i] - } - units += u - } - - return s -} diff --git a/v3/pkg/application/transport.go b/v3/pkg/application/transport.go deleted file mode 100644 index a8437e954..000000000 --- a/v3/pkg/application/transport.go +++ /dev/null @@ -1,67 +0,0 @@ -package application - -import ( - "context" - "net/http" -) - -// Transport defines the interface for custom IPC transport implementations. -// Developers can provide their own transport (e.g., WebSocket, custom protocol) -// while retaining all Wails generated bindings and event communication. -// -// The transport is responsible for: -// - Receiving runtime call requests from the frontend -// - Processing them through Wails' MessageProcessor -// - Sending responses back to the frontend -// -// Example use case: Implementing WebSocket-based transport instead of HTTP fetch. -type Transport interface { - // Start initializes and starts the transport layer. - // The provided handler should be called to process Wails runtime requests. - // The context is the application context and will be cancelled on shutdown. - Start(ctx context.Context, messageProcessor *MessageProcessor) error - - JSClient() []byte - - // Stop gracefully shuts down the transport. - Stop() error -} - -// AssetServerTransport is an optional interface that transports can implement -// to serve assets over HTTP, enabling browser-based deployments. -// -// When a transport implements this interface, Wails will call ServeAssets() -// after Start() to provide the asset server handler. The transport should -// integrate this handler into its HTTP server to serve HTML, CSS, JS, and -// other static assets alongside the IPC transport. -// -// This is useful for: -// - Running Wails apps in a browser instead of a webview -// - Exposing the app over a network -// - Custom server configurations with both assets and IPC -type AssetServerTransport interface { - Transport - - // ServeAssets configures the transport to serve assets. - // The assetHandler is Wails' internal asset server that handles: - // - All static assets (HTML, CSS, JS, images, etc.) - // - /wails/runtime.js - The Wails runtime library - // - // The transport should integrate this handler into its HTTP server. - // Typically this means mounting it at "/" and ensuring the IPC endpoint - // (e.g., /wails/ws for WebSocket) is handled separately. - // - // This method is called after Start() completes successfully. - ServeAssets(assetHandler http.Handler) error -} - -// TransportHTTPHandler is an optional interface that transports can implement -// to provide HTTP middleware for the Wails asset server in webview scenarios. -// -// When a transport implements this interface, Wails will use Handler() in -// asset server middlewares that may provide handling for request done from webview to wails:// URLs. -// -// This is used by the default HTTP transport to handle IPC endpoints. -type TransportHTTPHandler interface { - Handler() func(next http.Handler) http.Handler -} diff --git a/v3/pkg/application/transport_event_ipc.go b/v3/pkg/application/transport_event_ipc.go deleted file mode 100644 index 4b3309ee6..000000000 --- a/v3/pkg/application/transport_event_ipc.go +++ /dev/null @@ -1,17 +0,0 @@ -package application - -type EventIPCTransport struct { - app *App -} - -func (t *EventIPCTransport) DispatchWailsEvent(event *CustomEvent) { - // Snapshot windows under RLock - t.app.windowsLock.RLock() - defer t.app.windowsLock.RUnlock() - for _, window := range t.app.windows { - if event.IsCancelled() { - return - } - window.DispatchWailsEvent(event) - } -} diff --git a/v3/pkg/application/transport_http.go b/v3/pkg/application/transport_http.go deleted file mode 100644 index c4e6b0bbf..000000000 --- a/v3/pkg/application/transport_http.go +++ /dev/null @@ -1,240 +0,0 @@ -package application - -import ( - "bytes" - "context" - "errors" - "io" - "log/slog" - "net/http" - "strconv" - "sync" - - "encoding/json" - - "github.com/wailsapp/wails/v3/pkg/errs" -) - -// bufferPool reduces allocations for reading request bodies. -// Buffers larger than maxPooledBufferSize are not returned to the pool -// to prevent memory bloat from occasional large requests (e.g., images). -const maxPooledBufferSize = 512 * 1024 // 512KB - -var bufferPool = sync.Pool{ - New: func() any { - return bytes.NewBuffer(make([]byte, 0, 4096)) - }, -} - -type HTTPTransport struct { - messageProcessor *MessageProcessor - logger *slog.Logger -} - -func NewHTTPTransport(opts ...HTTPTransportOption) *HTTPTransport { - t := &HTTPTransport{ - logger: slog.Default(), - } - - // Apply options - for _, opt := range opts { - opt(t) - } - - return t -} - -// HTTPTransportOption is a functional option for configuring HTTPTransport -type HTTPTransportOption func(*HTTPTransport) - -// HTTPTransportWithLogger is a functional option to set the logger for HTTPTransport. -func HTTPTransportWithLogger(logger *slog.Logger) HTTPTransportOption { - return func(t *HTTPTransport) { - t.logger = logger - } -} - -func (t *HTTPTransport) Start(ctx context.Context, processor *MessageProcessor) error { - t.messageProcessor = processor - - return nil -} - -func (t *HTTPTransport) JSClient() []byte { - return nil -} - -func (t *HTTPTransport) Stop() error { - return nil -} - -type request struct { - Object *int `json:"object"` - Method *int `json:"method"` - Args json.RawMessage `json:"args"` -} - -func (t *HTTPTransport) Handler() func(next http.Handler) http.Handler { - return func(next http.Handler) http.Handler { - return http.HandlerFunc(func(rw http.ResponseWriter, req *http.Request) { - path := req.URL.Path - switch path { - case "/wails/runtime": - t.handleRuntimeRequest(rw, req) - default: - next.ServeHTTP(rw, req) - } - }) - } -} - -func (t *HTTPTransport) handleRuntimeRequest(rw http.ResponseWriter, r *http.Request) { - var body request - var err error - - // Try to read from request body first (standard POST) - buf := bufferPool.Get().(*bytes.Buffer) - buf.Reset() - defer func() { - if buf.Cap() <= maxPooledBufferSize { - bufferPool.Put(buf) - } - }() - - _, err = io.Copy(buf, r.Body) - if err != nil { - t.httpError(rw, errs.WrapInvalidRuntimeCallErrorf(err, "Unable to read request body")) - return - } - - if buf.Len() > 0 { - err = json.Unmarshal(buf.Bytes(), &body) - if err != nil { - t.httpError(rw, errs.WrapInvalidRuntimeCallErrorf(err, "Unable to parse request body as JSON")) - return - } - } else { - // Fallback: WebKitGTK 6.0 may send POST data as query params for custom URI schemes - query := r.URL.Query() - if objStr := query.Get("object"); objStr != "" { - obj, parseErr := strconv.Atoi(objStr) - if parseErr == nil { - body.Object = &obj - } - } - if methStr := query.Get("method"); methStr != "" { - meth, parseErr := strconv.Atoi(methStr) - if parseErr == nil { - body.Method = &meth - } - } - if argsStr := query.Get("args"); argsStr != "" { - var args json.RawMessage - if json.Unmarshal([]byte(argsStr), &args) == nil { - body.Args = args - } - } - } - - if body.Object == nil { - t.httpError(rw, errs.NewInvalidRuntimeCallErrorf("missing object value")) - return - } - - if body.Method == nil { - t.httpError(rw, errs.NewInvalidRuntimeCallErrorf("missing method value")) - return - } - - windowIdStr := r.Header.Get(webViewRequestHeaderWindowId) - windowId := 0 - if windowIdStr != "" { - windowId, err = strconv.Atoi(windowIdStr) - if err != nil { - t.httpError(rw, errs.WrapInvalidRuntimeCallErrorf(err, "error decoding windowId value")) - return - } - } - - windowName := r.Header.Get(webViewRequestHeaderWindowName) - clientId := r.Header.Get("x-wails-client-id") - - resp, err := t.messageProcessor.HandleRuntimeCallWithIDs(r.Context(), &RuntimeRequest{ - Object: *body.Object, - Method: *body.Method, - Args: &Args{body.Args}, - WebviewWindowID: uint32(windowId), - WebviewWindowName: windowName, - ClientID: clientId, - }) - - if err != nil { - t.httpError(rw, err) - return - } - - if stringResp, ok := resp.(string); ok { - t.text(rw, stringResp) - return - } - - t.json(rw, resp) -} - -func (t *HTTPTransport) text(rw http.ResponseWriter, data string) { - rw.Header().Set("Content-Type", "text/plain") - rw.WriteHeader(http.StatusOK) - _, err := rw.Write([]byte(data)) - if err != nil { - t.error("Unable to write json payload. Please report this to the Wails team!", "error", err) - return - } -} - -func (t *HTTPTransport) json(rw http.ResponseWriter, data any) { - rw.Header().Set("Content-Type", "application/json") - rw.WriteHeader(http.StatusOK) - // convert data to json - var jsonPayload = []byte("{}") - var err error - if data != nil { - jsonPayload, err = json.Marshal(data) - if err != nil { - t.error("Unable to convert data to JSON. Please report this to the Wails team!", "error", err) - return - } - } - _, err = rw.Write(jsonPayload) - if err != nil { - t.error("Unable to write json payload. Please report this to the Wails team!", "error", err) - return - } -} - -func (t *HTTPTransport) httpError(rw http.ResponseWriter, err error) { - t.error(err.Error()) - // return JSON error if it's a CallError - var bytes []byte - if cerr := (*CallError)(nil); errors.As(err, &cerr) { - if data, jsonErr := json.Marshal(cerr); jsonErr == nil { - rw.Header().Set("Content-Type", "application/json") - bytes = data - } else { - rw.Header().Set("Content-Type", "text/plain") - bytes = []byte(err.Error()) - } - } else { - rw.Header().Set("Content-Type", "text/plain") - bytes = []byte(err.Error()) - } - rw.WriteHeader(http.StatusUnprocessableEntity) - - _, err = rw.Write(bytes) - if err != nil { - t.error("Unable to write error response:", "error", err) - } -} - -func (t *HTTPTransport) error(message string, args ...any) { - t.logger.Error(message, args...) -} diff --git a/v3/pkg/application/urlvalidator.go b/v3/pkg/application/urlvalidator.go deleted file mode 100644 index f9eecf0bb..000000000 --- a/v3/pkg/application/urlvalidator.go +++ /dev/null @@ -1,49 +0,0 @@ -package application - -import ( - "errors" - "fmt" - "net/url" - "regexp" - "strings" -) - -func ValidateAndSanitizeURL(rawURL string) (string, error) { - if strings.Contains(rawURL, "\x00") { - return "", errors.New("null bytes not allowed in URL") - } - - for i, r := range rawURL { - if r < 32 && r != 9 { - return "", fmt.Errorf("control character at position %d not allowed", i) - } - } - - shellDangerous := `[;|` + "`" + `$\\<>*{}\[\]()~! \t\n\r]` - if matched, _ := regexp.MatchString(shellDangerous, rawURL); matched { - return "", errors.New("shell metacharacters not allowed") - } - - unicodeDangerous := "[\u0000-\u001F\u007F\u00A0\u1680\u2000-\u200F\u2028-\u202F\u205F\u3000\uFEFF\u200B-\u200D\u2060\u2061\u2062\u2063\u2064\u206A-\u206F\uFFF0-\uFFFF]" - if matched, _ := regexp.MatchString(unicodeDangerous, rawURL); matched { - return "", errors.New("dangerous unicode characters not allowed") - } - - parsedURL, err := url.Parse(rawURL) - if err != nil { - return "", fmt.Errorf("invalid URL format: %v", err) - } - - scheme := strings.ToLower(parsedURL.Scheme) - - if scheme == "javascript" || scheme == "data" || scheme == "file" || scheme == "ftp" || scheme == "" { - return "", errors.New("scheme not allowed") - } - - if (scheme == "http" || scheme == "https") && parsedURL.Host == "" { - return "", fmt.Errorf("missing host for %s URL", scheme) - } - - sanitizedURL := parsedURL.String() - return sanitizedURL, nil -} diff --git a/v3/pkg/application/urlvalidator_test.go b/v3/pkg/application/urlvalidator_test.go deleted file mode 100644 index 803098899..000000000 --- a/v3/pkg/application/urlvalidator_test.go +++ /dev/null @@ -1,262 +0,0 @@ -package application_test - -import ( - "strings" - "testing" - - "github.com/wailsapp/wails/v3/pkg/application" -) - -func TestValidateURL(t *testing.T) { - testCases := []struct { - name string - url string - shouldErr bool - errMsg string - expected string - }{ - { - name: "valid https URL", - url: "https://www.example.com", - shouldErr: false, - expected: "https://www.example.com", - }, - { - name: "valid http URL", - url: "http://example.com", - shouldErr: false, - expected: "http://example.com", - }, - { - name: "URL with query parameters", - url: "https://example.com/search?q=cats&dogs", - shouldErr: false, - expected: "https://example.com/search?q=cats&dogs", - }, - { - name: "URL with port", - url: "https://example.com:8080/path", - shouldErr: false, - expected: "https://example.com:8080/path", - }, - { - name: "URL with fragment", - url: "https://example.com/page#section", - shouldErr: false, - expected: "https://example.com/page#section", - }, - { - name: "urlencode params", - url: "http://google.com/ ----browser-subprocess-path=C:\\\\Users\\\\Public\\\\test.bat", - shouldErr: true, - errMsg: "shell metacharacters", - }, - { - name: "javascript scheme", - url: "javascript:alert('XSS')", - shouldErr: true, - errMsg: "shell metacharacters", - }, - { - name: "data scheme", - url: "data:text/html,", - shouldErr: true, - errMsg: "shell metacharacters", - }, - { - name: "file scheme", - url: "file:///etc/passwd", - shouldErr: true, - errMsg: "scheme not allowed", - }, - { - name: "ftp scheme", - url: "ftp://ftp.example.com/file", - shouldErr: true, - errMsg: "scheme not allowed", - }, - { - name: "missing scheme", - url: "example.com", - shouldErr: true, - errMsg: "scheme not allowed", - }, - { - name: "empty string", - url: "", - shouldErr: true, - errMsg: "scheme not allowed", - }, - { - name: "null byte in URL", - url: "https://example.com\x00/malicious", - shouldErr: true, - errMsg: "null bytes not allowed", - }, - { - name: "control character", - url: "https://example.com\x01", - shouldErr: true, - errMsg: "control character", - }, - { - name: "shell injection with semicolon", - url: "https://example.com/;rm -rf /", - shouldErr: true, - errMsg: "shell metacharacters", - }, - { - name: "shell injection with pipe", - url: "https://example.com/|cat /etc/passwd", - shouldErr: true, - errMsg: "shell metacharacters", - }, - { - name: "shell injection with backtick", - url: "https://example.com/`whoami`", - shouldErr: true, - errMsg: "shell metacharacters", - }, - { - name: "shell injection with dollar", - url: "https://example.com/$(whoami)", - shouldErr: true, - errMsg: "shell metacharacters", - }, - { - name: "unicode null", - url: "https://example.com/\u0000", - shouldErr: true, - errMsg: "null bytes not allowed", - }, - { - name: "missing host for http", - url: "http:///path", - shouldErr: true, - errMsg: "missing host", - }, - { - name: "missing host for https", - url: "https:///path", - shouldErr: true, - errMsg: "missing host", - }, - { - name: "URL with newline", - url: "https://example.com/path\n/newline", - shouldErr: true, - errMsg: "control character", - }, - { - name: "URL with carriage return", - url: "https://example.com/path\r/return", - shouldErr: true, - errMsg: "control character", - }, - { - name: "URL with tab", - url: "https://example.com/path\t/tab", - shouldErr: true, - errMsg: "shell metacharacters", - }, - { - name: "URL with space in path", - url: "https://example.com/path with spaces", - shouldErr: true, - errMsg: "shell metacharacters", - }, - { - name: "URL with angle brackets", - url: "https://example.com/ - - -

                    DND NPM Runtime Test @wailsio/runtime

                    - - -

                    External File Drop

                    -
                    -

                    - This test uses the @wailsio/runtime npm module instead of the bundled /wails/runtime.js. - Drop files from your operating system to verify the fix works. -

                    -
                    - -
                    -
                    -

                    Drop files from your desktop or file manager here

                    -
                    - -
                    -
                    -

                    Documents

                    -
                      -
                    • No documents yet
                    • -
                    -
                    - -
                    -

                    Images

                    -
                      -
                    • No images yet
                    • -
                    -
                    - -
                    -

                    Other Files

                    -
                      -
                    • No other files yet
                    • -
                    -
                    -
                    -
                    - -
                    - Last action: No actions yet -
                    - - - diff --git a/v3/test/dnd-npm-runtime/frontend/index.html b/v3/test/dnd-npm-runtime/frontend/index.html deleted file mode 100644 index 32ed52e5b..000000000 --- a/v3/test/dnd-npm-runtime/frontend/index.html +++ /dev/null @@ -1,185 +0,0 @@ - - - - - - DND NPM Runtime Test - - - -

                    DND NPM Runtime Test @wailsio/runtime

                    - - -

                    External File Drop

                    -
                    -

                    - This test uses the @wailsio/runtime npm module instead of the bundled /wails/runtime.js. - Drop files from your operating system to verify the fix works. -

                    -
                    - -
                    -
                    -

                    Drop files from your desktop or file manager here

                    -
                    - -
                    -
                    -

                    Documents

                    -
                      -
                    • No documents yet
                    • -
                    -
                    - -
                    -

                    Images

                    -
                      -
                    • No images yet
                    • -
                    -
                    - -
                    -

                    Other Files

                    -
                      -
                    • No other files yet
                    • -
                    -
                    -
                    -
                    - -
                    - Last action: No actions yet -
                    - - - - diff --git a/v3/test/dnd-npm-runtime/frontend/main.js b/v3/test/dnd-npm-runtime/frontend/main.js deleted file mode 100644 index b47535cc8..000000000 --- a/v3/test/dnd-npm-runtime/frontend/main.js +++ /dev/null @@ -1,76 +0,0 @@ -/** - * DND NPM Runtime Test - * - * This file tests drag-and-drop functionality using the @wailsio/runtime npm module - * instead of the bundled /wails/runtime.js. - * - * The key difference: - * - Bundled runtime: import { Events } from '/wails/runtime.js' - * - NPM module: import { Events } from '@wailsio/runtime' - */ - -import { Events } from '@wailsio/runtime'; - -const documentsEl = document.getElementById('documents-list'); -const imagesEl = document.getElementById('images-list'); -const otherEl = document.getElementById('other-list'); -const dropDetails = document.getElementById('drop-details'); - -// ===== External File Drop ===== -const imageExtensions = ['.png', '.jpg', '.jpeg', '.gif', '.bmp', '.svg', '.webp', '.ico', '.tiff', '.tif']; -const documentExtensions = ['.pdf', '.doc', '.docx', '.txt', '.rtf', '.odt', '.xls', '.xlsx', '.ppt', '.pptx', '.md', '.csv', '.json', '.xml', '.html', '.htm']; - -function getFileName(path) { - return path.split(/[/\\]/).pop(); -} - -function getExtension(path) { - const name = getFileName(path); - const idx = name.lastIndexOf('.'); - return idx > 0 ? name.substring(idx).toLowerCase() : ''; -} - -function categoriseFile(path) { - const ext = getExtension(path); - if (imageExtensions.includes(ext)) return 'images'; - if (documentExtensions.includes(ext)) return 'documents'; - return 'other'; -} - -function addFileToList(listEl, fileName) { - const empty = listEl.querySelector('.empty'); - if (empty) empty.remove(); - - const li = document.createElement('li'); - li.textContent = fileName; - listEl.appendChild(li); -} - -// Listen for files-dropped event from Go backend -Events.On('files-dropped', (event) => { - const { files, details } = event.data; - - files.forEach(filePath => { - const fileName = getFileName(filePath); - const category = categoriseFile(filePath); - - switch (category) { - case 'documents': - addFileToList(documentsEl, fileName); - break; - case 'images': - addFileToList(imagesEl, fileName); - break; - default: - addFileToList(otherEl, fileName); - } - }); - - let info = `External: ${files.length} file(s) dropped`; - if (details) { - info += ` at (${details.x}, ${details.y})`; - } - dropDetails.textContent = info; -}); - -console.log('[DND NPM Test] Initialized with @wailsio/runtime'); diff --git a/v3/test/dnd-npm-runtime/frontend/package.json b/v3/test/dnd-npm-runtime/frontend/package.json deleted file mode 100644 index f4a9f9357..000000000 --- a/v3/test/dnd-npm-runtime/frontend/package.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "name": "dnd-npm-runtime-test", - "private": true, - "version": "1.0.0", - "type": "module", - "scripts": { - "dev": "vite", - "build": "vite build", - "preview": "vite preview" - }, - "dependencies": { - "@wailsio/runtime": "^3.0.0-alpha.79" - }, - "devDependencies": { - "vite": "^5.0.0" - } -} diff --git a/v3/test/dnd-npm-runtime/frontend/vite.config.js b/v3/test/dnd-npm-runtime/frontend/vite.config.js deleted file mode 100644 index 0098938b3..000000000 --- a/v3/test/dnd-npm-runtime/frontend/vite.config.js +++ /dev/null @@ -1,8 +0,0 @@ -import { defineConfig } from 'vite' - -export default defineConfig({ - build: { - outDir: 'dist', - emptyOutDir: true, - }, -}) diff --git a/v3/test/dnd-npm-runtime/main.go b/v3/test/dnd-npm-runtime/main.go deleted file mode 100644 index 043a35d93..000000000 --- a/v3/test/dnd-npm-runtime/main.go +++ /dev/null @@ -1,60 +0,0 @@ -package main - -import ( - "embed" - "log" - - "github.com/wailsapp/wails/v3/pkg/application" - "github.com/wailsapp/wails/v3/pkg/events" -) - -//go:embed frontend/dist -var assets embed.FS - -func main() { - app := application.New(application.Options{ - Name: "DND NPM Runtime Test", - Description: "Test drag and drop with npm @wailsio/runtime module", - Assets: application.AssetOptions{ - Handler: application.BundledAssetFileServer(assets), - }, - Mac: application.MacOptions{ - ApplicationShouldTerminateAfterLastWindowClosed: true, - }, - }) - - win := app.Window.NewWithOptions(application.WebviewWindowOptions{ - Title: "DND NPM Runtime Test", - Width: 800, - Height: 600, - EnableFileDrop: true, - Mac: application.MacWindow{ - Backdrop: application.MacBackdropTranslucent, - TitleBar: application.MacTitleBarHiddenInsetUnified, - InvisibleTitleBarHeight: 50, - }, - }) - - // Listen for file drop events - win.OnWindowEvent(events.Common.WindowFilesDropped, func(event *application.WindowEvent) { - files := event.Context().DroppedFiles() - details := event.Context().DropTargetDetails() - - log.Printf("Files dropped: %v", files) - if details != nil { - log.Printf("Drop target: id=%s, classes=%v, x=%d, y=%d", - details.ElementID, details.ClassList, details.X, details.Y) - } - - // Emit event to frontend - application.Get().Event.Emit("files-dropped", map[string]any{ - "files": files, - "details": details, - }) - }) - - err := app.Run() - if err != nil { - log.Fatal(err) - } -} diff --git a/v3/test/docker/Dockerfile.linux-arm64 b/v3/test/docker/Dockerfile.linux-arm64 deleted file mode 100644 index f1a8a6ea7..000000000 --- a/v3/test/docker/Dockerfile.linux-arm64 +++ /dev/null @@ -1,200 +0,0 @@ -# syntax=docker/dockerfile:1 -# Build Linux binaries for Wails v3 examples using Ubuntu 24.04 (ARM64 native) -FROM ubuntu:24.04 - -# Avoid interactive prompts during package installation -ENV DEBIAN_FRONTEND=noninteractive - -# Install system dependencies for Wails v3 (ARM64 native) -# GTK4/WebKitGTK 6.0 is the default build target -# GTK3/WebKit2GTK 4.1 is available for legacy builds with -tags gtk3 -RUN apt-get update && apt-get install -y \ - --no-install-recommends \ - # Core build tools for ARM64 - build-essential \ - gcc \ - g++ \ - pkg-config \ - # GTK4 and WebKitGTK 6.0 dependencies (DEFAULT) - libgtk-4-dev \ - libwebkitgtk-6.0-dev \ - # GTK3 and WebKit2GTK 4.1 dependencies (LEGACY - for -tags gtk3) - libgtk-3-dev \ - libwebkit2gtk-4.1-dev \ - # Additional dependencies that might be needed - libayatana-appindicator3-dev \ - # Git for go mod operations - git \ - # CA certificates for HTTPS - ca-certificates \ - # wget for downloading Go - wget \ - # Clean up apt cache and lists - && rm -rf /var/lib/apt/lists/* \ - && apt-get clean - -# Install Go 1.24 ARM64 version -ENV GO_VERSION=1.24.0 -RUN cd /tmp && \ - wget https://go.dev/dl/go${GO_VERSION}.linux-arm64.tar.gz && \ - wget https://go.dev/dl/go${GO_VERSION}.linux-arm64.tar.gz.sha256 && \ - echo "$(cat go${GO_VERSION}.linux-arm64.tar.gz.sha256) go${GO_VERSION}.linux-arm64.tar.gz" | sha256sum -c - && \ - tar -C /usr/local -xzf go${GO_VERSION}.linux-arm64.tar.gz && \ - rm go${GO_VERSION}.linux-arm64.tar.gz go${GO_VERSION}.linux-arm64.tar.gz.sha256 - -# Set Go environment for ARM64 native compilation -ENV PATH="/usr/local/go/bin:${PATH}" -ENV GOPATH="/go" -ENV PATH="${GOPATH}/bin:${PATH}" -ENV CGO_ENABLED=1 -ENV GOOS=linux -ENV GOARCH=arm64 - -# Set working directory -WORKDIR /build - -# Copy the entire v3 directory structure -COPY . /build/ - -# Create build script for ARM64 native compilation -# hadolint ignore=DL1000 -RUN cat > /build/build-linux-arm64.sh << 'EOF' -#!/bin/bash -set -e - -# Colors for output -RED='\033[0;31m' -GREEN='\033[0;32m' -YELLOW='\033[1;33m' -NC='\033[0m' # No Color - -echo "🐧 Building Wails v3 examples for Linux ARM64 (Ubuntu 24.04)" -echo "Go version: $(go version)" -echo "Architecture: $(uname -m)" -echo "Build directory: $(pwd)" -echo "" - -# Function to build a single example -build_example() { - local example_name="$1" - local example_dir="/build/examples/$example_name" - - if [ ! -d "$example_dir" ]; then - echo -e "${RED}✗${NC} Example directory $example_name not found" - return 1 - fi - - if [ ! -f "$example_dir/main.go" ]; then - echo -e "${YELLOW}⚠${NC} Skipping $example_name (no main.go)" - return 0 - fi - - echo -e "Building ${YELLOW}$example_name${NC} for ARM64..." - cd "$example_dir" - - # Update go.mod for Docker environment - if [ -f go.mod ]; then - go mod edit -dropreplace github.com/wailsapp/wails/v3 2>/dev/null || true - go mod edit -replace github.com/wailsapp/wails/v3=/build - fi - - # Tidy dependencies - echo " Running go mod tidy..." - if ! go mod tidy; then - echo -e "${RED}✗${NC} go mod tidy failed for $example_name" - return 1 - fi - - # Build the example for ARM64 - # Use BUILD_TAGS environment variable for GTK3 legacy builds - local build_tags="${BUILD_TAGS:-}" - local suffix="linux-arm64" - if [ -n "$build_tags" ]; then - suffix="linux-arm64-${build_tags}" - echo " Compiling for ARM64 with tags: $build_tags..." - else - echo " Compiling for ARM64 (GTK4 default)..." - fi - - if go build ${build_tags:+-tags "$build_tags"} -o "testbuild-$example_name-$suffix"; then - echo -e "${GREEN}✓${NC} Successfully built $example_name for ARM64" - ls -la "testbuild-$example_name-$suffix" - return 0 - else - echo -e "${RED}✗${NC} Build failed for $example_name" - return 1 - fi -} - -# Main execution -if [ $# -eq 0 ]; then - # Build all examples - echo "Building all examples for ARM64..." - cd /build/examples - - failed_examples=() - successful_examples=() - skipped_examples=() - - for example_dir in */; do - example_name=$(basename "$example_dir") - - if build_example "$example_name"; then - if [ -f "/build/examples/$example_name/testbuild-$example_name-linux-arm64" ]; then - successful_examples+=("$example_name") - else - skipped_examples+=("$example_name") - fi - else - failed_examples+=("$example_name") - fi - - echo "" - done - - echo "==============================" - echo "🏗️ ARM64 BUILD SUMMARY" - echo "==============================" - echo -e "${GREEN}✓ Successful builds (${#successful_examples[@]}):${NC}" - for example in "${successful_examples[@]}"; do - echo " $example" - done - - if [ ${#skipped_examples[@]} -gt 0 ]; then - echo -e "${YELLOW}⚠ Skipped (${#skipped_examples[@]}):${NC}" - for example in "${skipped_examples[@]}"; do - echo " $example (no main.go)" - done - fi - - if [ ${#failed_examples[@]} -gt 0 ]; then - echo -e "${RED}✗ Failed builds (${#failed_examples[@]}):${NC}" - for example in "${failed_examples[@]}"; do - echo " $example" - done - fi - - echo "" - echo "Total: ${#successful_examples[@]} successful, ${#failed_examples[@]} failed, ${#skipped_examples[@]} skipped" - - if [ ${#failed_examples[@]} -eq 0 ]; then - echo -e "${GREEN}🎉 All buildable examples compiled successfully for ARM64!${NC}" - exit 0 - else - echo -e "${RED}❌ Some examples failed to build for ARM64${NC}" - exit 1 - fi - -else - # Build specific example - example_name="$1" - echo "Building specific example for ARM64: $example_name" - build_example "$example_name" -fi -EOF - -# Make the script executable -RUN chmod +x /build/build-linux-arm64.sh - -# Default command -CMD ["/build/build-linux-arm64.sh"] \ No newline at end of file diff --git a/v3/test/docker/Dockerfile.linux-x86_64 b/v3/test/docker/Dockerfile.linux-x86_64 deleted file mode 100644 index 0d6b318eb..000000000 --- a/v3/test/docker/Dockerfile.linux-x86_64 +++ /dev/null @@ -1,200 +0,0 @@ -# syntax=docker/dockerfile:1 -# Build Linux binaries for Wails v3 examples using Ubuntu 24.04 (x86_64 native) -FROM --platform=linux/amd64 ubuntu:24.04 - -# Avoid interactive prompts during package installation -ENV DEBIAN_FRONTEND=noninteractive - -# Install system dependencies for Wails v3 (x86_64 native) -# GTK4/WebKitGTK 6.0 is the default build target -# GTK3/WebKit2GTK 4.1 is available for legacy builds with -tags gtk3 -RUN apt-get update && apt-get install -y \ - --no-install-recommends \ - # Core build tools for x86_64 - build-essential \ - gcc \ - g++ \ - pkg-config \ - # GTK4 and WebKitGTK 6.0 dependencies (DEFAULT) - libgtk-4-dev \ - libwebkitgtk-6.0-dev \ - # GTK3 and WebKit2GTK 4.1 dependencies (LEGACY - for -tags gtk3) - libgtk-3-dev \ - libwebkit2gtk-4.1-dev \ - # Additional dependencies that might be needed - libayatana-appindicator3-dev \ - # Git for go mod operations - git \ - # CA certificates for HTTPS - ca-certificates \ - # wget for downloading Go - wget \ - # Clean up apt cache and lists - && rm -rf /var/lib/apt/lists/* \ - && apt-get clean - -# Install Go 1.24 x86_64 version -ENV GO_VERSION=1.24.0 -RUN cd /tmp && \ - wget https://go.dev/dl/go${GO_VERSION}.linux-amd64.tar.gz && \ - wget https://go.dev/dl/go${GO_VERSION}.linux-amd64.tar.gz.sha256 && \ - echo "$(cat go${GO_VERSION}.linux-amd64.tar.gz.sha256) go${GO_VERSION}.linux-amd64.tar.gz" | sha256sum -c - && \ - tar -C /usr/local -xzf go${GO_VERSION}.linux-amd64.tar.gz && \ - rm go${GO_VERSION}.linux-amd64.tar.gz go${GO_VERSION}.linux-amd64.tar.gz.sha256 - -# Set Go environment for x86_64 native compilation -ENV PATH="/usr/local/go/bin:${PATH}" -ENV GOPATH="/go" -ENV PATH="${GOPATH}/bin:${PATH}" -ENV CGO_ENABLED=1 -ENV GOOS=linux -ENV GOARCH=amd64 - -# Set working directory -WORKDIR /build - -# Copy the entire v3 directory structure -COPY . /build/ - -# Create build script for x86_64 native compilation -# hadolint ignore=DL1000 -RUN cat > /build/build-linux-x86_64.sh << 'EOF' -#!/bin/bash -set -e - -# Colors for output -RED='\033[0;31m' -GREEN='\033[0;32m' -YELLOW='\033[1;33m' -NC='\033[0m' # No Color - -echo "🐧 Building Wails v3 examples for Linux x86_64 (Ubuntu 24.04)" -echo "Go version: $(go version)" -echo "Architecture: $(uname -m)" -echo "Build directory: $(pwd)" -echo "" - -# Function to build a single example -build_example() { - local example_name="$1" - local example_dir="/build/examples/$example_name" - - if [ ! -d "$example_dir" ]; then - echo -e "${RED}✗${NC} Example directory $example_name not found" - return 1 - fi - - if [ ! -f "$example_dir/main.go" ]; then - echo -e "${YELLOW}⚠${NC} Skipping $example_name (no main.go)" - return 0 - fi - - echo -e "Building ${YELLOW}$example_name${NC} for x86_64..." - cd "$example_dir" - - # Update go.mod for Docker environment - if [ -f go.mod ]; then - go mod edit -dropreplace github.com/wailsapp/wails/v3 2>/dev/null || true - go mod edit -replace github.com/wailsapp/wails/v3=/build - fi - - # Tidy dependencies - echo " Running go mod tidy..." - if ! go mod tidy; then - echo -e "${RED}✗${NC} go mod tidy failed for $example_name" - return 1 - fi - - # Build the example for x86_64 - # Use BUILD_TAGS environment variable for GTK3 legacy builds - local build_tags="${BUILD_TAGS:-}" - local suffix="linux-x86_64" - if [ -n "$build_tags" ]; then - suffix="linux-x86_64-${build_tags}" - echo " Compiling for x86_64 with tags: $build_tags..." - else - echo " Compiling for x86_64 (GTK4 default)..." - fi - - if go build ${build_tags:+-tags "$build_tags"} -o "testbuild-$example_name-$suffix"; then - echo -e "${GREEN}✓${NC} Successfully built $example_name for x86_64" - ls -la "testbuild-$example_name-$suffix" - return 0 - else - echo -e "${RED}✗${NC} Build failed for $example_name" - return 1 - fi -} - -# Main execution -if [ $# -eq 0 ]; then - # Build all examples - echo "Building all examples for x86_64..." - cd /build/examples - - failed_examples=() - successful_examples=() - skipped_examples=() - - for example_dir in */; do - example_name=$(basename "$example_dir") - - if build_example "$example_name"; then - if [ -f "/build/examples/$example_name/testbuild-$example_name-linux-x86_64" ]; then - successful_examples+=("$example_name") - else - skipped_examples+=("$example_name") - fi - else - failed_examples+=("$example_name") - fi - - echo "" - done - - echo "==============================" - echo "🏗️ x86_64 BUILD SUMMARY" - echo "==============================" - echo -e "${GREEN}✓ Successful builds (${#successful_examples[@]}):${NC}" - for example in "${successful_examples[@]}"; do - echo " $example" - done - - if [ ${#skipped_examples[@]} -gt 0 ]; then - echo -e "${YELLOW}⚠ Skipped (${#skipped_examples[@]}):${NC}" - for example in "${skipped_examples[@]}"; do - echo " $example (no main.go)" - done - fi - - if [ ${#failed_examples[@]} -gt 0 ]; then - echo -e "${RED}✗ Failed builds (${#failed_examples[@]}):${NC}" - for example in "${failed_examples[@]}"; do - echo " $example" - done - fi - - echo "" - echo "Total: ${#successful_examples[@]} successful, ${#failed_examples[@]} failed, ${#skipped_examples[@]} skipped" - - if [ ${#failed_examples[@]} -eq 0 ]; then - echo -e "${GREEN}🎉 All buildable examples compiled successfully for x86_64!${NC}" - exit 0 - else - echo -e "${RED}❌ Some examples failed to build for x86_64${NC}" - exit 1 - fi - -else - # Build specific example - example_name="$1" - echo "Building specific example for x86_64: $example_name" - build_example "$example_name" -fi -EOF - -# Make the script executable -RUN chmod +x /build/build-linux-x86_64.sh - -# Default command -CMD ["/build/build-linux-x86_64.sh"] \ No newline at end of file diff --git a/v3/test/manual/dialog/README.md b/v3/test/manual/dialog/README.md deleted file mode 100644 index 3859f5b2b..000000000 --- a/v3/test/manual/dialog/README.md +++ /dev/null @@ -1,211 +0,0 @@ -# Dialog Manual Tests - -Comprehensive test suite for the GTK4 dialog implementation. - -## Building - -```bash -cd v3/test/manual/dialog -task build:all -``` - -Binaries are output to `bin/` directory with GTK3/GTK4 variants. - -## Test Categories - -### Message Dialogs - -#### 1. message-info - -Tests info/information dialogs. - -| Test | Expected Behavior | -|------|-------------------| -| Basic Info | Dialog with title and message | -| Title Only | Dialog with only title | -| Message Only | Dialog with only message | -| Custom Icon | Dialog displays custom Wails icon | -| Long Message | Text wraps properly | -| Attached to Window | Dialog is modal to main window | - -#### 2. message-question - -Tests question dialogs with buttons. - -| Test | Expected Behavior | -|------|-------------------| -| Two Buttons | Yes/No buttons, callbacks work | -| Three Buttons | Save/Don't Save/Cancel buttons | -| With Default Button | Default button highlighted, Enter selects it | -| With Cancel Button | Escape key triggers cancel button | -| Custom Icon | Dialog displays custom icon | -| Attached to Window | Dialog is modal to main window | -| Button Callbacks | Each button triggers correct callback | - -#### 3. message-warning - -Tests warning dialogs. - -| Test | Expected Behavior | -|------|-------------------| -| Basic Warning | Warning dialog with title and message | -| Title Only | Warning with only title | -| Message Only | Warning with only message | -| Custom Icon | Warning with custom icon | -| Long Warning | Text wraps properly | -| Attached to Window | Dialog is modal to main window | - -#### 4. message-error - -Tests error dialogs. - -| Test | Expected Behavior | -|------|-------------------| -| Basic Error | Error dialog with title and message | -| Title Only | Error with only title | -| Message Only | Error with only message | -| Custom Icon | Error with custom icon | -| Technical Error | Long error message wraps properly | -| Attached to Window | Dialog is modal to main window | - -### File Dialogs - -#### 5. file-open - -Tests single file open dialogs. - -| Test | Expected Behavior | -|------|-------------------| -| Basic Open | File picker opens, selection returned | -| With Title | Dialog has custom title | -| Show Hidden Files | Hidden files (.*) visible | -| Start in Home | Dialog opens in home directory | -| Start in /tmp | Dialog opens in /tmp | -| Filter: Text Files | Only .txt, .md, .log files shown | -| Filter: Images | Only image files shown | -| Multiple Filters | Filter dropdown with multiple options | -| Custom Button Text | Open button has custom text | -| Attached to Window | Dialog is modal to main window | - -#### 6. file-open-multi - -Tests multiple file selection. - -| Test | Expected Behavior | -|------|-------------------| -| Select Multiple Files | Can select multiple files with Ctrl+click | -| With Hidden Files | Hidden files visible in selection | -| Filter: Source Code | Only source files shown | -| Filter: Documents | Only document files shown | -| Attached to Window | Dialog is modal to main window | - -#### 7. file-save - -Tests save file dialogs. - -| Test | Expected Behavior | -|------|-------------------| -| Basic Save | Save dialog opens | -| With Message | Dialog has custom message | -| With Default Filename | Filename field pre-populated | -| Start in Home | Dialog opens in home directory | -| Start in /tmp | Dialog opens in /tmp | -| Show Hidden Files | Hidden files visible | -| Can Create Directories | New folder button works | -| Cannot Create Directories | New folder button hidden/disabled | -| Custom Button Text | Save button has custom text | -| Attached to Window | Dialog is modal to main window | - -#### 8. file-directory - -Tests directory selection dialogs. - -| Test | Expected Behavior | -|------|-------------------| -| Basic Directory | Can only select directories | -| Start in Home | Dialog opens in home directory | -| Start in / | Dialog opens at root | -| Can Create Directories | New folder button works | -| Show Hidden | Hidden directories visible | -| Resolve Aliases/Symlinks | Symlinks resolved to real paths | -| Custom Button Text | Open button has custom text | -| Multiple Directories | Can select multiple directories | -| Attached to Window | Dialog is modal to main window | - -## GTK Version Matrix - -| Test | GTK4 | GTK3 | -|------|------|------| -| message-info | | | -| message-question | | | -| message-warning | | | -| message-error | | | -| file-open | | | -| file-open-multi | | | -| file-save | | | -| file-directory | | | - -## Running Individual Tests - -```bash -# GTK4 (default) -./bin/message-info-gtk4 -./bin/message-question-gtk4 -./bin/message-warning-gtk4 -./bin/message-error-gtk4 -./bin/file-open-gtk4 -./bin/file-open-multi-gtk4 -./bin/file-save-gtk4 -./bin/file-directory-gtk4 - -# GTK3 -./bin/message-info-gtk3 -./bin/message-question-gtk3 -./bin/message-warning-gtk3 -./bin/message-error-gtk3 -./bin/file-open-gtk3 -./bin/file-open-multi-gtk3 -./bin/file-save-gtk3 -./bin/file-directory-gtk3 -``` - -## Checklist for Full Verification - -### Message Dialogs - -- [ ] Dialog appears centered or attached correctly -- [ ] Title displays correctly -- [ ] Message displays correctly -- [ ] Custom icons display correctly -- [ ] Long text wraps properly -- [ ] OK/Close button dismisses dialog -- [ ] Escape key closes dialog (where applicable) - -### Question Dialogs - -- [ ] All buttons display correctly -- [ ] Button callbacks fire correctly -- [ ] Default button is highlighted -- [ ] Enter key activates default button -- [ ] Escape key activates cancel button -- [ ] Multiple buttons layout correctly - -### File Dialogs - -- [ ] Dialog opens in correct directory -- [ ] Filters work correctly -- [ ] Hidden files toggle works -- [ ] Create directory works (where enabled) -- [ ] Cancel returns empty string -- [ ] Selection returns correct path(s) -- [ ] Multiple selection works (multi tests) -- [ ] Custom button text displays - -### Known Issues - -Document any issues found during testing: - -``` -[GTK Version] [Test] - Issue description -Example: GTK4 file-open - Filter dropdown not visible -``` diff --git a/v3/test/manual/dialog/Taskfile.yaml b/v3/test/manual/dialog/Taskfile.yaml deleted file mode 100644 index b5bd97518..000000000 --- a/v3/test/manual/dialog/Taskfile.yaml +++ /dev/null @@ -1,125 +0,0 @@ -version: "3" - -vars: - BIN_DIR: "{{.ROOT_DIR}}/bin" - -tasks: - default: - desc: Build all dialog tests for GTK3 and GTK4 - cmds: - - task: build:all - - build:all: - desc: Build all tests for both GTK3 and GTK4 - deps: - - build:gtk4 - - build:gtk3 - - build:gtk4: - desc: Build all tests for GTK4 - cmds: - - task: build:message-info-gtk4 - - task: build:message-question-gtk4 - - task: build:message-warning-gtk4 - - task: build:message-error-gtk4 - - task: build:file-open-gtk4 - - task: build:file-open-multi-gtk4 - - task: build:file-save-gtk4 - - task: build:file-directory-gtk4 - - build:gtk3: - desc: Build all tests for GTK3 - cmds: - - task: build:message-info-gtk3 - - task: build:message-question-gtk3 - - task: build:message-warning-gtk3 - - task: build:message-error-gtk3 - - task: build:file-open-gtk3 - - task: build:file-open-multi-gtk3 - - task: build:file-save-gtk3 - - task: build:file-directory-gtk3 - - build:message-info-gtk4: - dir: message-info - cmds: - - go build -o "{{.BIN_DIR}}/message-info-gtk4" . - - build:message-info-gtk3: - dir: message-info - cmds: - - go build -tags gtk3 -o "{{.BIN_DIR}}/message-info-gtk3" . - - build:message-question-gtk4: - dir: message-question - cmds: - - go build -o "{{.BIN_DIR}}/message-question-gtk4" . - - build:message-question-gtk3: - dir: message-question - cmds: - - go build -tags gtk3 -o "{{.BIN_DIR}}/message-question-gtk3" . - - build:message-warning-gtk4: - dir: message-warning - cmds: - - go build -o "{{.BIN_DIR}}/message-warning-gtk4" . - - build:message-warning-gtk3: - dir: message-warning - cmds: - - go build -tags gtk3 -o "{{.BIN_DIR}}/message-warning-gtk3" . - - build:message-error-gtk4: - dir: message-error - cmds: - - go build -o "{{.BIN_DIR}}/message-error-gtk4" . - - build:message-error-gtk3: - dir: message-error - cmds: - - go build -tags gtk3 -o "{{.BIN_DIR}}/message-error-gtk3" . - - build:file-open-gtk4: - dir: file-open - cmds: - - go build -o "{{.BIN_DIR}}/file-open-gtk4" . - - build:file-open-gtk3: - dir: file-open - cmds: - - go build -tags gtk3 -o "{{.BIN_DIR}}/file-open-gtk3" . - - build:file-open-multi-gtk4: - dir: file-open-multi - cmds: - - go build -o "{{.BIN_DIR}}/file-open-multi-gtk4" . - - build:file-open-multi-gtk3: - dir: file-open-multi - cmds: - - go build -tags gtk3 -o "{{.BIN_DIR}}/file-open-multi-gtk3" . - - build:file-save-gtk4: - dir: file-save - cmds: - - go build -o "{{.BIN_DIR}}/file-save-gtk4" . - - build:file-save-gtk3: - dir: file-save - cmds: - - go build -tags gtk3 -o "{{.BIN_DIR}}/file-save-gtk3" . - - build:file-directory-gtk4: - dir: file-directory - cmds: - - go build -o "{{.BIN_DIR}}/file-directory-gtk4" . - - build:file-directory-gtk3: - dir: file-directory - cmds: - - go build -tags gtk3 -o "{{.BIN_DIR}}/file-directory-gtk3" . - - clean: - desc: Remove all built binaries - cmds: - - rm -rf "{{.BIN_DIR}}" diff --git a/v3/test/manual/dialog/bin/file-directory-gtk4 b/v3/test/manual/dialog/bin/file-directory-gtk4 deleted file mode 100755 index 4f0d2a45e..000000000 Binary files a/v3/test/manual/dialog/bin/file-directory-gtk4 and /dev/null differ diff --git a/v3/test/manual/dialog/bin/file-directory-gtk4-debug b/v3/test/manual/dialog/bin/file-directory-gtk4-debug deleted file mode 100755 index d20d8eb53..000000000 Binary files a/v3/test/manual/dialog/bin/file-directory-gtk4-debug and /dev/null differ diff --git a/v3/test/manual/dialog/bin/file-directory-gtk4-race b/v3/test/manual/dialog/bin/file-directory-gtk4-race deleted file mode 100755 index 8a7cb0d89..000000000 Binary files a/v3/test/manual/dialog/bin/file-directory-gtk4-race and /dev/null differ diff --git a/v3/test/manual/dialog/bin/file-open-gtk4 b/v3/test/manual/dialog/bin/file-open-gtk4 deleted file mode 100755 index fb37c7872..000000000 Binary files a/v3/test/manual/dialog/bin/file-open-gtk4 and /dev/null differ diff --git a/v3/test/manual/dialog/bin/file-open-gtk4-race b/v3/test/manual/dialog/bin/file-open-gtk4-race deleted file mode 100755 index b93b686af..000000000 Binary files a/v3/test/manual/dialog/bin/file-open-gtk4-race and /dev/null differ diff --git a/v3/test/manual/dialog/bin/file-open-multi-gtk4 b/v3/test/manual/dialog/bin/file-open-multi-gtk4 deleted file mode 100755 index eb7c88fd0..000000000 Binary files a/v3/test/manual/dialog/bin/file-open-multi-gtk4 and /dev/null differ diff --git a/v3/test/manual/dialog/bin/file-open-multi-gtk4-race b/v3/test/manual/dialog/bin/file-open-multi-gtk4-race deleted file mode 100755 index df0d7eae9..000000000 Binary files a/v3/test/manual/dialog/bin/file-open-multi-gtk4-race and /dev/null differ diff --git a/v3/test/manual/dialog/bin/file-save-gtk4 b/v3/test/manual/dialog/bin/file-save-gtk4 deleted file mode 100755 index 9529d5f88..000000000 Binary files a/v3/test/manual/dialog/bin/file-save-gtk4 and /dev/null differ diff --git a/v3/test/manual/dialog/bin/file-save-gtk4-race b/v3/test/manual/dialog/bin/file-save-gtk4-race deleted file mode 100755 index d53a800c0..000000000 Binary files a/v3/test/manual/dialog/bin/file-save-gtk4-race and /dev/null differ diff --git a/v3/test/manual/dialog/bin/message-error-gtk4 b/v3/test/manual/dialog/bin/message-error-gtk4 deleted file mode 100755 index 4abe345fd..000000000 Binary files a/v3/test/manual/dialog/bin/message-error-gtk4 and /dev/null differ diff --git a/v3/test/manual/dialog/bin/message-error-gtk4-race b/v3/test/manual/dialog/bin/message-error-gtk4-race deleted file mode 100755 index e874376c0..000000000 Binary files a/v3/test/manual/dialog/bin/message-error-gtk4-race and /dev/null differ diff --git a/v3/test/manual/dialog/bin/message-info-gtk4 b/v3/test/manual/dialog/bin/message-info-gtk4 deleted file mode 100755 index 9080df02c..000000000 Binary files a/v3/test/manual/dialog/bin/message-info-gtk4 and /dev/null differ diff --git a/v3/test/manual/dialog/bin/message-info-gtk4-race b/v3/test/manual/dialog/bin/message-info-gtk4-race deleted file mode 100755 index a79b85ce0..000000000 Binary files a/v3/test/manual/dialog/bin/message-info-gtk4-race and /dev/null differ diff --git a/v3/test/manual/dialog/bin/message-question-gtk4 b/v3/test/manual/dialog/bin/message-question-gtk4 deleted file mode 100755 index aa9011e4f..000000000 Binary files a/v3/test/manual/dialog/bin/message-question-gtk4 and /dev/null differ diff --git a/v3/test/manual/dialog/bin/message-question-gtk4-race b/v3/test/manual/dialog/bin/message-question-gtk4-race deleted file mode 100755 index 2848816b6..000000000 Binary files a/v3/test/manual/dialog/bin/message-question-gtk4-race and /dev/null differ diff --git a/v3/test/manual/dialog/bin/message-warning-gtk4 b/v3/test/manual/dialog/bin/message-warning-gtk4 deleted file mode 100755 index 03432c436..000000000 Binary files a/v3/test/manual/dialog/bin/message-warning-gtk4 and /dev/null differ diff --git a/v3/test/manual/dialog/bin/message-warning-gtk4-race b/v3/test/manual/dialog/bin/message-warning-gtk4-race deleted file mode 100755 index 6f03b2ef1..000000000 Binary files a/v3/test/manual/dialog/bin/message-warning-gtk4-race and /dev/null differ diff --git a/v3/test/manual/dialog/file-directory/main.go b/v3/test/manual/dialog/file-directory/main.go deleted file mode 100644 index e7374703c..000000000 --- a/v3/test/manual/dialog/file-directory/main.go +++ /dev/null @@ -1,158 +0,0 @@ -package main - -import ( - "log" - "os" - - "github.com/wailsapp/wails/v3/pkg/application" -) - -func main() { - app := application.New(application.Options{ - Name: "Dialog Test - Directory", - Assets: application.AlphaAssets, - }) - - menu := app.NewMenu() - - menu.Add("Basic Directory").OnClick(func(ctx *application.Context) { - result, err := app.Dialog.OpenFile(). - SetTitle("Select Directory"). - CanChooseDirectories(true). - CanChooseFiles(false). - PromptForSingleSelection() - showResult(app, "Basic Directory", result, err) - }) - - menu.Add("Start in Home").OnClick(func(ctx *application.Context) { - home, _ := os.UserHomeDir() - result, err := app.Dialog.OpenFile(). - SetTitle("Select from Home"). - SetDirectory(home). - CanChooseDirectories(true). - CanChooseFiles(false). - PromptForSingleSelection() - showResult(app, "Home Directory", result, err) - }) - - menu.Add("Start in /").OnClick(func(ctx *application.Context) { - result, err := app.Dialog.OpenFile(). - SetTitle("Select from Root"). - SetDirectory("/"). - CanChooseDirectories(true). - CanChooseFiles(false). - PromptForSingleSelection() - showResult(app, "Root Directory", result, err) - }) - - menu.Add("Can Create Directories").OnClick(func(ctx *application.Context) { - result, err := app.Dialog.OpenFile(). - SetTitle("Select Directory (Can Create)"). - CanChooseDirectories(true). - CanChooseFiles(false). - CanCreateDirectories(true). - PromptForSingleSelection() - showResult(app, "Create Dirs", result, err) - }) - - menu.Add("Show Hidden").OnClick(func(ctx *application.Context) { - result, err := app.Dialog.OpenFile(). - SetTitle("Select Directory (Hidden Visible)"). - CanChooseDirectories(true). - CanChooseFiles(false). - ShowHiddenFiles(true). - PromptForSingleSelection() - showResult(app, "Show Hidden", result, err) - }) - - menu.Add("Resolve Aliases/Symlinks").OnClick(func(ctx *application.Context) { - result, err := app.Dialog.OpenFile(). - SetTitle("Select Directory (Resolve Symlinks)"). - CanChooseDirectories(true). - CanChooseFiles(false). - ResolvesAliases(true). - PromptForSingleSelection() - showResult(app, "Resolve Aliases", result, err) - }) - - menu.Add("Custom Button Text").OnClick(func(ctx *application.Context) { - result, err := app.Dialog.OpenFile(). - SetTitle("Choose Project Folder"). - SetButtonText("Use This Folder"). - CanChooseDirectories(true). - CanChooseFiles(false). - PromptForSingleSelection() - showResult(app, "Custom Button", result, err) - }) - - menu.Add("Multiple Directories").OnClick(func(ctx *application.Context) { - results, err := app.Dialog.OpenFile(). - SetTitle("Select Multiple Directories"). - CanChooseDirectories(true). - CanChooseFiles(false). - PromptForMultipleSelection() - if err != nil { - log.Printf("[Multi Dir] Error: %v", err) - app.Dialog.Error().SetTitle("Error").SetMessage(err.Error()).Show() - return - } - if len(results) == 0 { - log.Printf("[Multi Dir] Cancelled") - app.Dialog.Info().SetTitle("Multi Dir").SetMessage("No directories selected").Show() - return - } - log.Printf("[Multi Dir] Selected %d directories", len(results)) - msg := "" - for _, r := range results { - msg += r + "\n" - } - app.Dialog.Info().SetTitle("Multi Dir").SetMessage(msg).Show() - }) - - menu.Add("Attached to Window").OnClick(func(ctx *application.Context) { - result, err := app.Dialog.OpenFile(). - SetTitle("Select Directory (Attached)"). - CanChooseDirectories(true). - CanChooseFiles(false). - AttachToWindow(app.Window.Current()). - PromptForSingleSelection() - showResult(app, "Attached", result, err) - }) - - menu.AddSeparator() - menu.Add("Quit").OnClick(func(ctx *application.Context) { - app.Quit() - }) - - window := app.Window.NewWithOptions(application.WebviewWindowOptions{ - Title: "Directory Dialog Tests", - Width: 400, - Height: 200, - Linux: application.LinuxWindow{ - MenuStyle: application.LinuxMenuStylePrimaryMenu, - }, - }) - window.SetMenu(menu) - - log.Println("Directory Dialog Tests") - log.Println("Use the Tests menu to run each test case") - - if err := app.Run(); err != nil { - log.Fatal(err) - } -} - -func showResult(app *application.App, test string, result string, err error) { - if err != nil { - log.Printf("[%s] Error: %v", test, err) - app.Dialog.Error().SetTitle("Error").SetMessage(err.Error()).Show() - return - } - if result == "" { - log.Printf("[%s] Cancelled", test) - app.Dialog.Info().SetTitle(test).SetMessage("No directory selected").Show() - return - } - log.Printf("[%s] Selected: %s", test, result) - app.Dialog.Info().SetTitle(test).SetMessage(result).Show() -} diff --git a/v3/test/manual/dialog/file-open-multi/main.go b/v3/test/manual/dialog/file-open-multi/main.go deleted file mode 100644 index 4cb27a446..000000000 --- a/v3/test/manual/dialog/file-open-multi/main.go +++ /dev/null @@ -1,106 +0,0 @@ -package main - -import ( - "fmt" - "log" - "strings" - - "github.com/wailsapp/wails/v3/pkg/application" -) - -func main() { - app := application.New(application.Options{ - Name: "Dialog Test - Open Multiple Files", - Assets: application.AlphaAssets, - }) - - menu := app.NewMenu() - - - - menu.Add("Select Multiple Files").OnClick(func(ctx *application.Context) { - results, err := app.Dialog.OpenFile(). - SetTitle("Select Multiple Files"). - CanChooseFiles(true). - PromptForMultipleSelection() - showResults(app, "Multi Select", results, err) - }) - - menu.Add("With Hidden Files").OnClick(func(ctx *application.Context) { - results, err := app.Dialog.OpenFile(). - SetTitle("Select Files (Hidden Visible)"). - CanChooseFiles(true). - ShowHiddenFiles(true). - PromptForMultipleSelection() - showResults(app, "Hidden Files", results, err) - }) - - menu.Add("Filter: Source Code").OnClick(func(ctx *application.Context) { - results, err := app.Dialog.OpenFile(). - SetTitle("Select Source Files"). - CanChooseFiles(true). - AddFilter("Go Files", "*.go"). - AddFilter("All Source", "*.go;*.js;*.ts;*.py;*.rs"). - PromptForMultipleSelection() - showResults(app, "Source Filter", results, err) - }) - - menu.Add("Filter: Documents").OnClick(func(ctx *application.Context) { - results, err := app.Dialog.OpenFile(). - SetTitle("Select Documents"). - CanChooseFiles(true). - AddFilter("Documents", "*.pdf;*.doc;*.docx;*.txt;*.md"). - PromptForMultipleSelection() - showResults(app, "Doc Filter", results, err) - }) - - menu.Add("Attached to Window").OnClick(func(ctx *application.Context) { - results, err := app.Dialog.OpenFile(). - SetTitle("Select Files (Attached)"). - CanChooseFiles(true). - AttachToWindow(app.Window.Current()). - PromptForMultipleSelection() - showResults(app, "Attached", results, err) - }) - - menu.AddSeparator() - menu.Add("Quit").OnClick(func(ctx *application.Context) { - app.Quit() - }) - - window := app.Window.NewWithOptions(application.WebviewWindowOptions{ - Title: "Open Multiple Files Tests", - Width: 400, - Height: 200, - Linux: application.LinuxWindow{ - MenuStyle: application.LinuxMenuStylePrimaryMenu, - }, - }) - window.SetMenu(menu) - - log.Println("Open Multiple Files Tests") - log.Println("Use the Tests menu to run each test case") - - if err := app.Run(); err != nil { - log.Fatal(err) - } -} - -func showResults(app *application.App, test string, results []string, err error) { - if err != nil { - log.Printf("[%s] Error: %v", test, err) - app.Dialog.Error().SetTitle("Error").SetMessage(err.Error()).Show() - return - } - if len(results) == 0 { - log.Printf("[%s] Cancelled", test) - app.Dialog.Info().SetTitle(test).SetMessage("No files selected").Show() - return - } - log.Printf("[%s] Selected %d files:", test, len(results)) - for _, r := range results { - log.Printf(" - %s", r) - } - msg := fmt.Sprintf("Selected %d files:\n%s", len(results), strings.Join(results, "\n")) - app.Dialog.Info().SetTitle(test).SetMessage(msg).Show() -} diff --git a/v3/test/manual/dialog/file-open/main.go b/v3/test/manual/dialog/file-open/main.go deleted file mode 100644 index 599f2e00a..000000000 --- a/v3/test/manual/dialog/file-open/main.go +++ /dev/null @@ -1,146 +0,0 @@ -package main - -import ( - "log" - "os" - - "github.com/wailsapp/wails/v3/pkg/application" -) - -func main() { - app := application.New(application.Options{ - Name: "Dialog Test - Open File", - Assets: application.AlphaAssets, - }) - - menu := app.NewMenu() - - - - menu.Add("Basic Open").OnClick(func(ctx *application.Context) { - result, err := app.Dialog.OpenFile(). - CanChooseFiles(true). - PromptForSingleSelection() - showResult(app, "Basic Open", result, err) - }) - - menu.Add("With Title").OnClick(func(ctx *application.Context) { - result, err := app.Dialog.OpenFile(). - SetTitle("Select a File"). - CanChooseFiles(true). - PromptForSingleSelection() - showResult(app, "With Title", result, err) - }) - - menu.Add("Show Hidden Files").OnClick(func(ctx *application.Context) { - result, err := app.Dialog.OpenFile(). - SetTitle("Select File (Hidden Visible)"). - CanChooseFiles(true). - ShowHiddenFiles(true). - PromptForSingleSelection() - showResult(app, "Show Hidden", result, err) - }) - - menu.Add("Start in Home Directory").OnClick(func(ctx *application.Context) { - home, _ := os.UserHomeDir() - result, err := app.Dialog.OpenFile(). - SetTitle("Select from Home"). - SetDirectory(home). - CanChooseFiles(true). - PromptForSingleSelection() - showResult(app, "Home Directory", result, err) - }) - - menu.Add("Start in /tmp").OnClick(func(ctx *application.Context) { - result, err := app.Dialog.OpenFile(). - SetTitle("Select from /tmp"). - SetDirectory("/tmp"). - CanChooseFiles(true). - PromptForSingleSelection() - showResult(app, "/tmp Directory", result, err) - }) - - menu.Add("Filter: Text Files").OnClick(func(ctx *application.Context) { - result, err := app.Dialog.OpenFile(). - SetTitle("Select Text File"). - CanChooseFiles(true). - AddFilter("Text Files", "*.txt;*.md;*.log"). - PromptForSingleSelection() - showResult(app, "Text Filter", result, err) - }) - - menu.Add("Filter: Images").OnClick(func(ctx *application.Context) { - result, err := app.Dialog.OpenFile(). - SetTitle("Select Image"). - CanChooseFiles(true). - AddFilter("Images", "*.png;*.jpg;*.jpeg;*.gif;*.webp"). - PromptForSingleSelection() - showResult(app, "Image Filter", result, err) - }) - - menu.Add("Multiple Filters").OnClick(func(ctx *application.Context) { - result, err := app.Dialog.OpenFile(). - SetTitle("Select File"). - CanChooseFiles(true). - AddFilter("Documents", "*.txt;*.md;*.pdf"). - AddFilter("Images", "*.png;*.jpg;*.gif"). - AddFilter("All Files", "*"). - PromptForSingleSelection() - showResult(app, "Multi Filter", result, err) - }) - - menu.Add("Custom Button Text").OnClick(func(ctx *application.Context) { - result, err := app.Dialog.OpenFile(). - SetTitle("Select File"). - SetButtonText("Choose This One"). - CanChooseFiles(true). - PromptForSingleSelection() - showResult(app, "Custom Button", result, err) - }) - - menu.Add("Attached to Window").OnClick(func(ctx *application.Context) { - result, err := app.Dialog.OpenFile(). - SetTitle("Attached Dialog"). - CanChooseFiles(true). - AttachToWindow(app.Window.Current()). - PromptForSingleSelection() - showResult(app, "Attached", result, err) - }) - - menu.AddSeparator() - menu.Add("Quit").OnClick(func(ctx *application.Context) { - app.Quit() - }) - - window := app.Window.NewWithOptions(application.WebviewWindowOptions{ - Title: "Open File Dialog Tests", - Width: 400, - Height: 200, - Linux: application.LinuxWindow{ - MenuStyle: application.LinuxMenuStylePrimaryMenu, - }, - }) - window.SetMenu(menu) - - log.Println("Open File Dialog Tests") - log.Println("Use the Tests menu to run each test case") - - if err := app.Run(); err != nil { - log.Fatal(err) - } -} - -func showResult(app *application.App, test string, result string, err error) { - if err != nil { - log.Printf("[%s] Error: %v", test, err) - app.Dialog.Error().SetTitle("Error").SetMessage(err.Error()).Show() - return - } - if result == "" { - log.Printf("[%s] Cancelled", test) - app.Dialog.Info().SetTitle(test).SetMessage("No file selected").Show() - return - } - log.Printf("[%s] Selected: %s", test, result) - app.Dialog.Info().SetTitle(test).SetMessage(result).Show() -} diff --git a/v3/test/manual/dialog/file-save/main.go b/v3/test/manual/dialog/file-save/main.go deleted file mode 100644 index 0c922599a..000000000 --- a/v3/test/manual/dialog/file-save/main.go +++ /dev/null @@ -1,137 +0,0 @@ -package main - -import ( - "log" - "os" - - "github.com/wailsapp/wails/v3/pkg/application" -) - -func main() { - app := application.New(application.Options{ - Name: "Dialog Test - Save File", - Assets: application.AlphaAssets, - }) - - menu := app.NewMenu() - - - - menu.Add("Basic Save").OnClick(func(ctx *application.Context) { - result, err := app.Dialog.SaveFile(). - PromptForSingleSelection() - showResult(app, "Basic Save", result, err) - }) - - menu.Add("With Message").OnClick(func(ctx *application.Context) { - result, err := app.Dialog.SaveFile(). - SetMessage("Save your file"). - PromptForSingleSelection() - showResult(app, "With Message", result, err) - }) - - menu.Add("With Default Filename").OnClick(func(ctx *application.Context) { - result, err := app.Dialog.SaveFile(). - SetMessage("Save Document"). - SetFilename("document.txt"). - PromptForSingleSelection() - showResult(app, "Default Filename", result, err) - }) - - menu.Add("Start in Home").OnClick(func(ctx *application.Context) { - home, _ := os.UserHomeDir() - result, err := app.Dialog.SaveFile(). - SetMessage("Save to Home"). - SetDirectory(home). - SetFilename("myfile.txt"). - PromptForSingleSelection() - showResult(app, "Home Directory", result, err) - }) - - menu.Add("Start in /tmp").OnClick(func(ctx *application.Context) { - result, err := app.Dialog.SaveFile(). - SetMessage("Save to /tmp"). - SetDirectory("/tmp"). - SetFilename("temp_file.txt"). - PromptForSingleSelection() - showResult(app, "/tmp Directory", result, err) - }) - - menu.Add("Show Hidden Files").OnClick(func(ctx *application.Context) { - result, err := app.Dialog.SaveFile(). - SetMessage("Save (Hidden Visible)"). - ShowHiddenFiles(true). - PromptForSingleSelection() - showResult(app, "Show Hidden", result, err) - }) - - menu.Add("Can Create Directories").OnClick(func(ctx *application.Context) { - result, err := app.Dialog.SaveFile(). - SetMessage("Save (Can Create Dirs)"). - CanCreateDirectories(true). - PromptForSingleSelection() - showResult(app, "Create Dirs", result, err) - }) - - menu.Add("Cannot Create Directories").OnClick(func(ctx *application.Context) { - result, err := app.Dialog.SaveFile(). - SetMessage("Save (No Create Dirs)"). - CanCreateDirectories(false). - PromptForSingleSelection() - showResult(app, "No Create Dirs", result, err) - }) - - menu.Add("Custom Button Text").OnClick(func(ctx *application.Context) { - result, err := app.Dialog.SaveFile(). - SetMessage("Export File"). - SetButtonText("Export"). - SetFilename("export.json"). - PromptForSingleSelection() - showResult(app, "Custom Button", result, err) - }) - - menu.Add("Attached to Window").OnClick(func(ctx *application.Context) { - result, err := app.Dialog.SaveFile(). - SetMessage("Save (Attached)"). - AttachToWindow(app.Window.Current()). - PromptForSingleSelection() - showResult(app, "Attached", result, err) - }) - - menu.AddSeparator() - menu.Add("Quit").OnClick(func(ctx *application.Context) { - app.Quit() - }) - - window := app.Window.NewWithOptions(application.WebviewWindowOptions{ - Title: "Save File Dialog Tests", - Width: 400, - Height: 200, - Linux: application.LinuxWindow{ - MenuStyle: application.LinuxMenuStylePrimaryMenu, - }, - }) - window.SetMenu(menu) - - log.Println("Save File Dialog Tests") - log.Println("Use the Tests menu to run each test case") - - if err := app.Run(); err != nil { - log.Fatal(err) - } -} - -func showResult(app *application.App, test string, result string, err error) { - if err != nil { - log.Printf("[%s] Error: %v", test, err) - app.Dialog.Error().SetTitle("Error").SetMessage(err.Error()).Show() - return - } - if result == "" { - log.Printf("[%s] Cancelled", test) - app.Dialog.Info().SetTitle(test).SetMessage("No file selected").Show() - return - } - log.Printf("[%s] Selected: %s", test, result) - app.Dialog.Info().SetTitle(test).SetMessage(result).Show() -} diff --git a/v3/test/manual/dialog/message-error/main.go b/v3/test/manual/dialog/message-error/main.go deleted file mode 100644 index 93f005099..000000000 --- a/v3/test/manual/dialog/message-error/main.go +++ /dev/null @@ -1,85 +0,0 @@ -package main - -import ( - "log" - - "github.com/wailsapp/wails/v3/pkg/application" - "github.com/wailsapp/wails/v3/pkg/icons" -) - -func main() { - app := application.New(application.Options{ - Name: "Dialog Test - Error", - Assets: application.AlphaAssets, - }) - - menu := app.NewMenu() - - - - menu.Add("Basic Error").OnClick(func(ctx *application.Context) { - app.Dialog.Error(). - SetTitle("Error"). - SetMessage("An error has occurred"). - Show() - }) - - menu.Add("Title Only").OnClick(func(ctx *application.Context) { - app.Dialog.Error(). - SetTitle("Error - Something went wrong"). - Show() - }) - - menu.Add("Message Only").OnClick(func(ctx *application.Context) { - app.Dialog.Error(). - SetMessage("Error message without a title"). - Show() - }) - - menu.Add("Custom Icon").OnClick(func(ctx *application.Context) { - app.Dialog.Error(). - SetTitle("Custom Error Icon"). - SetMessage("This error dialog has a custom icon"). - SetIcon(icons.WailsLogoBlack). - Show() - }) - - menu.Add("Technical Error").OnClick(func(ctx *application.Context) { - app.Dialog.Error(). - SetTitle("Connection Failed"). - SetMessage("Failed to connect to server at localhost:8080. " + - "Error: connection refused. " + - "Please check that the server is running and try again."). - Show() - }) - - menu.Add("Attached to Window").OnClick(func(ctx *application.Context) { - app.Dialog.Error(). - SetTitle("Attached Error"). - SetMessage("This error dialog is attached to the main window"). - AttachToWindow(app.Window.Current()). - Show() - }) - - menu.AddSeparator() - menu.Add("Quit").OnClick(func(ctx *application.Context) { - app.Quit() - }) - - window := app.Window.NewWithOptions(application.WebviewWindowOptions{ - Title: "Error Dialog Tests", - Width: 400, - Height: 200, - Linux: application.LinuxWindow{ - MenuStyle: application.LinuxMenuStylePrimaryMenu, - }, - }) - window.SetMenu(menu) - - log.Println("Error Dialog Tests") - log.Println("Use the Tests menu to run each test case") - - if err := app.Run(); err != nil { - log.Fatal(err) - } -} diff --git a/v3/test/manual/dialog/message-info/main.go b/v3/test/manual/dialog/message-info/main.go deleted file mode 100644 index 05577d952..000000000 --- a/v3/test/manual/dialog/message-info/main.go +++ /dev/null @@ -1,85 +0,0 @@ -package main - -import ( - "log" - - "github.com/wailsapp/wails/v3/pkg/application" - "github.com/wailsapp/wails/v3/pkg/icons" -) - -func main() { - app := application.New(application.Options{ - Name: "Dialog Test - Info", - Assets: application.AlphaAssets, - }) - - menu := app.NewMenu() - - - - menu.Add("Basic Info").OnClick(func(ctx *application.Context) { - app.Dialog.Info(). - SetTitle("Information"). - SetMessage("This is a basic info dialog"). - Show() - }) - - menu.Add("Title Only").OnClick(func(ctx *application.Context) { - app.Dialog.Info(). - SetTitle("Title Only - No Message"). - Show() - }) - - menu.Add("Message Only").OnClick(func(ctx *application.Context) { - app.Dialog.Info(). - SetMessage("Message only - no title set"). - Show() - }) - - menu.Add("Custom Icon").OnClick(func(ctx *application.Context) { - app.Dialog.Info(). - SetTitle("Custom Icon"). - SetMessage("This dialog has a custom icon"). - SetIcon(icons.WailsLogoBlackTransparent). - Show() - }) - - menu.Add("Long Message").OnClick(func(ctx *application.Context) { - app.Dialog.Info(). - SetTitle("Long Message Test"). - SetMessage("This is a very long message that should wrap properly in the dialog. " + - "It contains multiple sentences to test how the dialog handles longer content. " + - "The dialog should display this text in a readable manner without truncation."). - Show() - }) - - menu.Add("Attached to Window").OnClick(func(ctx *application.Context) { - app.Dialog.Info(). - SetTitle("Attached Dialog"). - SetMessage("This dialog is attached to the main window"). - AttachToWindow(app.Window.Current()). - Show() - }) - - menu.AddSeparator() - menu.Add("Quit").OnClick(func(ctx *application.Context) { - app.Quit() - }) - - window := app.Window.NewWithOptions(application.WebviewWindowOptions{ - Title: "Info Dialog Tests", - Width: 400, - Height: 200, - Linux: application.LinuxWindow{ - MenuStyle: application.LinuxMenuStylePrimaryMenu, - }, - }) - window.SetMenu(menu) - - log.Println("Info Dialog Tests") - log.Println("Use the Tests menu to run each test case") - - if err := app.Run(); err != nil { - log.Fatal(err) - } -} diff --git a/v3/test/manual/dialog/message-question/main.go b/v3/test/manual/dialog/message-question/main.go deleted file mode 100644 index 42dff6c06..000000000 --- a/v3/test/manual/dialog/message-question/main.go +++ /dev/null @@ -1,134 +0,0 @@ -package main - -import ( - "log" - - "github.com/wailsapp/wails/v3/pkg/application" - "github.com/wailsapp/wails/v3/pkg/icons" -) - -func main() { - app := application.New(application.Options{ - Name: "Dialog Test - Question", - Assets: application.AlphaAssets, - }) - - menu := app.NewMenu() - - testMenu := menu.AddSubmenu("Tests") - - testMenu.Add("Two Buttons").OnClick(func(ctx *application.Context) { - dialog := app.Dialog.Question(). - SetTitle("Question"). - SetMessage("Do you want to proceed?") - dialog.AddButton("Yes").OnClick(func() { - app.Dialog.Info().SetMessage("You clicked Yes").Show() - }) - dialog.AddButton("No").OnClick(func() { - app.Dialog.Info().SetMessage("You clicked No").Show() - }) - dialog.Show() - }) - - testMenu.Add("Three Buttons").OnClick(func(ctx *application.Context) { - dialog := app.Dialog.Question(). - SetTitle("Save Changes?"). - SetMessage("You have unsaved changes") - dialog.AddButton("Save").OnClick(func() { - app.Dialog.Info().SetMessage("Saving...").Show() - }) - dialog.AddButton("Don't Save").OnClick(func() { - app.Dialog.Info().SetMessage("Discarding changes").Show() - }) - dialog.AddButton("Cancel") - dialog.Show() - }) - - testMenu.Add("With Default Button").OnClick(func(ctx *application.Context) { - dialog := app.Dialog.Question(). - SetTitle("Confirm"). - SetMessage("Press Enter to select the default button") - dialog.AddButton("OK") - no := dialog.AddButton("Cancel") - dialog.SetDefaultButton(no) - dialog.Show() - }) - - testMenu.Add("With Cancel Button (Escape)").OnClick(func(ctx *application.Context) { - dialog := app.Dialog.Question(). - SetTitle("Escape Test"). - SetMessage("Press Escape to cancel") - ok := dialog.AddButton("OK").OnClick(func() { - app.Dialog.Info().SetMessage("OK clicked").Show() - }) - cancel := dialog.AddButton("Cancel").OnClick(func() { - app.Dialog.Info().SetMessage("Cancelled").Show() - }) - dialog.SetDefaultButton(ok) - dialog.SetCancelButton(cancel) - dialog.Show() - }) - - testMenu.Add("Custom Icon").OnClick(func(ctx *application.Context) { - dialog := app.Dialog.Question(). - SetTitle("Custom Icon"). - SetMessage("This question has a custom icon"). - SetIcon(icons.WailsLogoWhiteTransparent) - dialog.AddButton("Nice!").OnClick(func() { - app.Dialog.Info().SetMessage("Thanks!").Show() - }) - dialog.AddButton("Meh") - dialog.Show() - }) - - testMenu.Add("Attached to Window").OnClick(func(ctx *application.Context) { - dialog := app.Dialog.Question(). - SetTitle("Attached"). - SetMessage("This dialog is attached to the window"). - AttachToWindow(app.Window.Current()) - dialog.AddButton("OK") - dialog.AddButton("Cancel") - dialog.Show() - }) - - testMenu.Add("Button Callbacks").OnClick(func(ctx *application.Context) { - dialog := app.Dialog.Question(). - SetTitle("Callbacks"). - SetMessage("Each button has a callback") - dialog.AddButton("Option A").OnClick(func() { - log.Println("Option A selected") - app.Dialog.Info().SetMessage("You chose Option A").Show() - }) - dialog.AddButton("Option B").OnClick(func() { - log.Println("Option B selected") - app.Dialog.Info().SetMessage("You chose Option B").Show() - }) - dialog.AddButton("Option C").OnClick(func() { - log.Println("Option C selected") - app.Dialog.Info().SetMessage("You chose Option C").Show() - }) - dialog.Show() - }) - - testMenu.AddSeparator() - testMenu.Add("Quit").OnClick(func(ctx *application.Context) { - app.Quit() - }) - - window := app.Window.NewWithOptions(application.WebviewWindowOptions{ - Title: "Question Dialog Tests", - Width: 400, - Height: 200, - Linux: application.LinuxWindow{ - MenuStyle: application.LinuxMenuStylePrimaryMenu, - }, - }) - window.SetMenu(menu) - - log.Println("Question Dialog Tests") - log.Println("Use the Tests menu to run each test case") - - if err := app.Run(); err != nil { - log.Fatal(err) - } -} diff --git a/v3/test/manual/dialog/message-warning/main.go b/v3/test/manual/dialog/message-warning/main.go deleted file mode 100644 index 67e8f2623..000000000 --- a/v3/test/manual/dialog/message-warning/main.go +++ /dev/null @@ -1,85 +0,0 @@ -package main - -import ( - "log" - - "github.com/wailsapp/wails/v3/pkg/application" - "github.com/wailsapp/wails/v3/pkg/icons" -) - -func main() { - app := application.New(application.Options{ - Name: "Dialog Test - Warning", - Assets: application.AlphaAssets, - }) - - menu := app.NewMenu() - - - - menu.Add("Basic Warning").OnClick(func(ctx *application.Context) { - app.Dialog.Warning(). - SetTitle("Warning"). - SetMessage("This is a warning message"). - Show() - }) - - menu.Add("Title Only").OnClick(func(ctx *application.Context) { - app.Dialog.Warning(). - SetTitle("Warning - Title Only"). - Show() - }) - - menu.Add("Message Only").OnClick(func(ctx *application.Context) { - app.Dialog.Warning(). - SetMessage("Warning message without title"). - Show() - }) - - menu.Add("Custom Icon").OnClick(func(ctx *application.Context) { - app.Dialog.Warning(). - SetTitle("Custom Warning Icon"). - SetMessage("This warning has a custom icon"). - SetIcon(icons.ApplicationLightMode256). - Show() - }) - - menu.Add("Long Warning").OnClick(func(ctx *application.Context) { - app.Dialog.Warning(). - SetTitle("Important Warning"). - SetMessage("This is an important warning that contains a lot of text. " + - "You should read this carefully before proceeding. " + - "Ignoring this warning may result in unexpected behavior."). - Show() - }) - - menu.Add("Attached to Window").OnClick(func(ctx *application.Context) { - app.Dialog.Warning(). - SetTitle("Attached Warning"). - SetMessage("This warning is attached to the main window"). - AttachToWindow(app.Window.Current()). - Show() - }) - - menu.AddSeparator() - menu.Add("Quit").OnClick(func(ctx *application.Context) { - app.Quit() - }) - - window := app.Window.NewWithOptions(application.WebviewWindowOptions{ - Title: "Warning Dialog Tests", - Width: 400, - Height: 200, - Linux: application.LinuxWindow{ - MenuStyle: application.LinuxMenuStylePrimaryMenu, - }, - }) - window.SetMenu(menu) - - log.Println("Warning Dialog Tests") - log.Println("Use the Tests menu to run each test case") - - if err := app.Run(); err != nil { - log.Fatal(err) - } -} diff --git a/v3/test/manual/systray/.task/checksum/build-custom-handlers-gtk3 b/v3/test/manual/systray/.task/checksum/build-custom-handlers-gtk3 deleted file mode 100644 index ac32ec4ce..000000000 --- a/v3/test/manual/systray/.task/checksum/build-custom-handlers-gtk3 +++ /dev/null @@ -1 +0,0 @@ -56e330435e9c161841e231a8a3109528 diff --git a/v3/test/manual/systray/.task/checksum/build-custom-handlers-gtk4 b/v3/test/manual/systray/.task/checksum/build-custom-handlers-gtk4 deleted file mode 100644 index ac32ec4ce..000000000 --- a/v3/test/manual/systray/.task/checksum/build-custom-handlers-gtk4 +++ /dev/null @@ -1 +0,0 @@ -56e330435e9c161841e231a8a3109528 diff --git a/v3/test/manual/systray/.task/checksum/build-hide-options-gtk3 b/v3/test/manual/systray/.task/checksum/build-hide-options-gtk3 deleted file mode 100644 index 37796fa2a..000000000 --- a/v3/test/manual/systray/.task/checksum/build-hide-options-gtk3 +++ /dev/null @@ -1 +0,0 @@ -ffabb1e7ef242fd5215ad8671c49b38b diff --git a/v3/test/manual/systray/.task/checksum/build-hide-options-gtk4 b/v3/test/manual/systray/.task/checksum/build-hide-options-gtk4 deleted file mode 100644 index 37796fa2a..000000000 --- a/v3/test/manual/systray/.task/checksum/build-hide-options-gtk4 +++ /dev/null @@ -1 +0,0 @@ -ffabb1e7ef242fd5215ad8671c49b38b diff --git a/v3/test/manual/systray/.task/checksum/build-menu-only-gtk3 b/v3/test/manual/systray/.task/checksum/build-menu-only-gtk3 deleted file mode 100644 index b4d246ba9..000000000 --- a/v3/test/manual/systray/.task/checksum/build-menu-only-gtk3 +++ /dev/null @@ -1 +0,0 @@ -88e3074cc3503a9aaade145c12213e8d diff --git a/v3/test/manual/systray/.task/checksum/build-menu-only-gtk4 b/v3/test/manual/systray/.task/checksum/build-menu-only-gtk4 deleted file mode 100644 index b4d246ba9..000000000 --- a/v3/test/manual/systray/.task/checksum/build-menu-only-gtk4 +++ /dev/null @@ -1 +0,0 @@ -88e3074cc3503a9aaade145c12213e8d diff --git a/v3/test/manual/systray/.task/checksum/build-window-menu-gtk3 b/v3/test/manual/systray/.task/checksum/build-window-menu-gtk3 deleted file mode 100644 index 684a41ed2..000000000 --- a/v3/test/manual/systray/.task/checksum/build-window-menu-gtk3 +++ /dev/null @@ -1 +0,0 @@ -e8f8e8b2142681a880a3e91012f73f8d diff --git a/v3/test/manual/systray/.task/checksum/build-window-menu-gtk4 b/v3/test/manual/systray/.task/checksum/build-window-menu-gtk4 deleted file mode 100644 index 684a41ed2..000000000 --- a/v3/test/manual/systray/.task/checksum/build-window-menu-gtk4 +++ /dev/null @@ -1 +0,0 @@ -e8f8e8b2142681a880a3e91012f73f8d diff --git a/v3/test/manual/systray/.task/checksum/build-window-only-gtk3 b/v3/test/manual/systray/.task/checksum/build-window-only-gtk3 deleted file mode 100644 index d4e432741..000000000 --- a/v3/test/manual/systray/.task/checksum/build-window-only-gtk3 +++ /dev/null @@ -1 +0,0 @@ -cc2cc0be9fcf830e23609d4bd8efff14 diff --git a/v3/test/manual/systray/.task/checksum/build-window-only-gtk4 b/v3/test/manual/systray/.task/checksum/build-window-only-gtk4 deleted file mode 100644 index d4e432741..000000000 --- a/v3/test/manual/systray/.task/checksum/build-window-only-gtk4 +++ /dev/null @@ -1 +0,0 @@ -cc2cc0be9fcf830e23609d4bd8efff14 diff --git a/v3/test/manual/systray/README.md b/v3/test/manual/systray/README.md deleted file mode 100644 index c802471c4..000000000 --- a/v3/test/manual/systray/README.md +++ /dev/null @@ -1,157 +0,0 @@ -# Systray Manual Tests - -Comprehensive test suite for the Systray API v2 implementation. - -## Building - -```bash -cd v3/test/manual/systray -task build:all -``` - -Binaries are output to `bin/` directory with GTK3/GTK4 variants. - -## Test Scenarios - -### 1. window-only - -Tests systray with only an attached window (no menu). - -| Action | Expected Behavior | -|--------|-------------------| -| Left-click | Toggle window visibility | -| Right-click | Nothing | -| Double-click | Nothing | - -### 2. menu-only - -Tests systray with only a menu (no attached window). - -| Action | Expected Behavior | -|--------|-------------------| -| Left-click | Nothing | -| Right-click | Show menu | -| Double-click | Nothing | - -### 3. window-menu - -Tests systray with both attached window and menu. - -| Action | Expected Behavior | -|--------|-------------------| -| Left-click | Toggle window visibility | -| Right-click | Show menu | -| Double-click | Nothing | - -### 4. custom-handlers - -Tests custom click handlers overriding smart defaults. Demonstrates that custom handlers -can add logging/analytics while still using the standard systray methods. - -| Action | Expected Behavior | -|--------|-------------------| -| Left-click | Custom handler logs + toggles window | -| Right-click | Custom handler logs + opens menu | -| Double-click | Logs to console | - -### 5. hide-options - -Tests `HideOnEscape` and `HideOnFocusLost` window options. - -| Action | Expected Behavior | -|--------|-------------------| -| Left-click systray | Toggle window | -| Press Escape | Hide window | -| Click outside | Hide window (standard WMs only) | - -## Platform Test Matrix - -### Desktop Environments - -| Test | GNOME | KDE | XFCE | Hyprland | Sway | i3 | -|------|-------|-----|------|----------|------|-----| -| window-only | | | | | | | -| menu-only | | | | | | | -| window-menu | | | | | | | -| custom-handlers | | | | | | | -| hide-options | | | | | | | - -### GTK Version Matrix - -| Test | GTK4 | GTK3 | -|------|------|------| -| window-only | | | -| menu-only | | | -| window-menu | | | -| custom-handlers | | | -| hide-options | | | - -## Focus-Follows-Mouse Behavior - -On tiling WMs with focus-follows-mouse (Hyprland, Sway, i3): - -- `HideOnFocusLost` is **automatically disabled** -- This prevents the window from hiding immediately when the mouse moves away -- `HideOnEscape` still works normally - -### Testing HideOnFocusLost - -1. **Standard WM (GNOME, KDE)**: - - Run `hide-options` test - - Click systray to show window - - Click anywhere outside the window - - Window should hide - -2. **Tiling WM (Hyprland, Sway, i3)**: - - Run `hide-options` test - - Click systray to show window - - Move mouse outside window - - Window should NOT hide (feature disabled) - - Press Escape to hide (still works) - -## Checklist for Full Verification - -### Per-Environment Checklist - -- [ ] Systray icon appears in system tray -- [ ] Left-click behavior matches expected -- [ ] Right-click behavior matches expected -- [ ] Window appears near systray icon (not random position) -- [ ] Window stays on top when shown -- [ ] Multiple show/hide cycles work correctly -- [ ] Menu items are clickable and work -- [ ] Application quits cleanly - -### Hide Options Specific - -- [ ] Escape key hides window -- [ ] Focus lost hides window (standard WMs) -- [ ] Focus lost does NOT hide window (tiling WMs) -- [ ] Re-clicking systray after hide works - -### Known Issues - -Document any issues found during testing: - -``` -[Environment] [GTK Version] [Test] - Issue description -Example: Hyprland GTK4 window-menu - Menu appears at wrong position -``` - -## Running Individual Tests - -```bash -# GTK4 (default) -./bin/window-only-gtk4 -./bin/menu-only-gtk4 -./bin/window-menu-gtk4 -./bin/custom-handlers-gtk4 -./bin/hide-options-gtk4 - -# GTK3 -./bin/window-only-gtk3 -./bin/menu-only-gtk3 -./bin/window-menu-gtk3 -./bin/custom-handlers-gtk3 -./bin/hide-options-gtk3 -``` diff --git a/v3/test/manual/systray/Taskfile.yaml b/v3/test/manual/systray/Taskfile.yaml deleted file mode 100644 index 603d4143e..000000000 --- a/v3/test/manual/systray/Taskfile.yaml +++ /dev/null @@ -1,99 +0,0 @@ -version: "3" - -vars: - BIN_DIR: "{{.ROOT_DIR}}/bin" - -tasks: - default: - desc: Build all systray tests for GTK3 and GTK4 - cmds: - - task: build:all - - build:all: - desc: Build all tests for both GTK3 and GTK4 - deps: - - build:gtk4 - - build:gtk3 - - build:gtk4: - desc: Build all tests for GTK4 - cmds: - - task: build:window-only-gtk4 - - task: build:menu-only-gtk4 - - task: build:window-menu-gtk4 - - task: build:custom-handlers-gtk4 - - task: build:hide-options-gtk4 - - build:gtk3: - desc: Build all tests for GTK3 - cmds: - - task: build:window-only-gtk3 - - task: build:menu-only-gtk3 - - task: build:window-menu-gtk3 - - task: build:custom-handlers-gtk3 - - task: build:hide-options-gtk3 - - build:window-only-gtk4: - desc: Build window-only test (GTK4) - dir: window-only - cmds: - - go build -o "{{.BIN_DIR}}/window-only-gtk4" . - - build:window-only-gtk3: - desc: Build window-only test (GTK3) - dir: window-only - cmds: - - go build -tags gtk3 -o "{{.BIN_DIR}}/window-only-gtk3" . - - build:menu-only-gtk4: - desc: Build menu-only test (GTK4) - dir: menu-only - cmds: - - go build -o "{{.BIN_DIR}}/menu-only-gtk4" . - - build:menu-only-gtk3: - desc: Build menu-only test (GTK3) - dir: menu-only - cmds: - - go build -tags gtk3 -o "{{.BIN_DIR}}/menu-only-gtk3" . - - build:window-menu-gtk4: - desc: Build window-menu test (GTK4) - dir: window-menu - cmds: - - go build -o "{{.BIN_DIR}}/window-menu-gtk4" . - - build:window-menu-gtk3: - desc: Build window-menu test (GTK3) - dir: window-menu - cmds: - - go build -tags gtk3 -o "{{.BIN_DIR}}/window-menu-gtk3" . - - build:custom-handlers-gtk4: - desc: Build custom-handlers test (GTK4) - dir: custom-handlers - cmds: - - go build -o "{{.BIN_DIR}}/custom-handlers-gtk4" . - - build:custom-handlers-gtk3: - desc: Build custom-handlers test (GTK3) - dir: custom-handlers - cmds: - - go build -tags gtk3 -o "{{.BIN_DIR}}/custom-handlers-gtk3" . - - build:hide-options-gtk4: - desc: Build hide-options test (GTK4) - dir: hide-options - cmds: - - go build -o "{{.BIN_DIR}}/hide-options-gtk4" . - - build:hide-options-gtk3: - desc: Build hide-options test (GTK3) - dir: hide-options - cmds: - - go build -tags gtk3 -o "{{.BIN_DIR}}/hide-options-gtk3" . - - clean: - desc: Remove all built binaries - cmds: - - rm -rf "{{.BIN_DIR}}" diff --git a/v3/test/manual/systray/custom-handlers/main.go b/v3/test/manual/systray/custom-handlers/main.go deleted file mode 100644 index b3d471b23..000000000 --- a/v3/test/manual/systray/custom-handlers/main.go +++ /dev/null @@ -1,80 +0,0 @@ -package main - -import ( - _ "embed" - "log" - "runtime" - - "github.com/wailsapp/wails/v3/pkg/application" - "github.com/wailsapp/wails/v3/pkg/events" - "github.com/wailsapp/wails/v3/pkg/icons" -) - -func main() { - app := application.New(application.Options{ - Name: "Systray Custom Handlers", - Description: "Tests systray with custom click handlers overriding defaults", - Assets: application.AlphaAssets, - Mac: application.MacOptions{ - ActivationPolicy: application.ActivationPolicyAccessory, - }, - }) - - systray := app.SystemTray.New() - - window := app.Window.NewWithOptions(application.WebviewWindowOptions{ - Width: 400, - Height: 300, - Name: "Custom Handlers Test", - Title: "Custom Handlers - Check console for click events", - Frameless: true, - AlwaysOnTop: true, - Hidden: true, - DisableResize: true, - Windows: application.WindowsWindow{ - HiddenOnTaskbar: true, - }, - }) - - window.RegisterHook(events.Common.WindowClosing, func(e *application.WindowEvent) { - window.Hide() - e.Cancel() - }) - - menu := app.Menu.New() - menu.Add("Quit").OnClick(func(ctx *application.Context) { - app.Quit() - }) - - if runtime.GOOS == "darwin" { - systray.SetTemplateIcon(icons.SystrayMacTemplate) - } - - systray.AttachWindow(window).WindowOffset(5).SetMenu(menu) - - systray.OnClick(func() { - log.Println("Custom left-click handler called!") - log.Println(" -> Toggling window (custom behavior with logging)") - systray.ToggleWindow() - }) - - systray.OnRightClick(func() { - log.Println("Custom right-click handler called!") - log.Println(" -> Opening menu (custom behavior)") - systray.OpenMenu() - }) - - systray.OnDoubleClick(func() { - log.Println("Double-click detected!") - }) - - log.Println("Custom handlers test started") - log.Println("Expected behavior:") - log.Println(" - Left-click: Custom handler logs + toggles window") - log.Println(" - Right-click: Custom handler logs + opens menu") - log.Println(" - Double-click: Logs to console") - - if err := app.Run(); err != nil { - log.Fatal(err) - } -} diff --git a/v3/test/manual/systray/hide-options/main.go b/v3/test/manual/systray/hide-options/main.go deleted file mode 100644 index 864b65b04..000000000 --- a/v3/test/manual/systray/hide-options/main.go +++ /dev/null @@ -1,65 +0,0 @@ -package main - -import ( - _ "embed" - "log" - "runtime" - - "github.com/wailsapp/wails/v3/pkg/application" - "github.com/wailsapp/wails/v3/pkg/events" - "github.com/wailsapp/wails/v3/pkg/icons" -) - -func main() { - app := application.New(application.Options{ - Name: "Systray Hide Options", - Description: "Tests HideOnEscape and HideOnFocusLost options", - Assets: application.AlphaAssets, - Mac: application.MacOptions{ - ActivationPolicy: application.ActivationPolicyAccessory, - }, - }) - - systray := app.SystemTray.New() - - window := app.Window.NewWithOptions(application.WebviewWindowOptions{ - Width: 400, - Height: 300, - Name: "Hide Options Test", - Title: "Press Escape or click outside to hide", - Frameless: true, - AlwaysOnTop: true, - Hidden: true, - DisableResize: true, - HideOnEscape: true, - HideOnFocusLost: true, - Windows: application.WindowsWindow{ - HiddenOnTaskbar: true, - }, - }) - - window.RegisterHook(events.Common.WindowClosing, func(e *application.WindowEvent) { - window.Hide() - e.Cancel() - }) - - if runtime.GOOS == "darwin" { - systray.SetTemplateIcon(icons.SystrayMacTemplate) - } - - systray.AttachWindow(window).WindowOffset(5) - - log.Println("Hide options test started") - log.Println("Expected behavior:") - log.Println(" - Left-click systray: Toggle window") - log.Println(" - Press Escape: Hide window (HideOnEscape)") - log.Println(" - Click outside window: Hide window (HideOnFocusLost)") - log.Println("") - log.Println("NOTE: On focus-follows-mouse WMs (Hyprland, Sway, i3),") - log.Println(" HideOnFocusLost is automatically disabled to prevent") - log.Println(" immediate hiding when mouse moves away.") - - if err := app.Run(); err != nil { - log.Fatal(err) - } -} diff --git a/v3/test/manual/systray/menu-only/main.go b/v3/test/manual/systray/menu-only/main.go deleted file mode 100644 index b8af69e4d..000000000 --- a/v3/test/manual/systray/menu-only/main.go +++ /dev/null @@ -1,50 +0,0 @@ -package main - -import ( - _ "embed" - "log" - "runtime" - - "github.com/wailsapp/wails/v3/pkg/application" - "github.com/wailsapp/wails/v3/pkg/icons" -) - -func main() { - app := application.New(application.Options{ - Name: "Systray Menu Only", - Description: "Tests systray with menu only (no attached window)", - Assets: application.AlphaAssets, - Mac: application.MacOptions{ - ActivationPolicy: application.ActivationPolicyAccessory, - }, - }) - - systray := app.SystemTray.New() - - menu := app.Menu.New() - menu.Add("Action 1").OnClick(func(ctx *application.Context) { - log.Println("Action 1 clicked") - }) - menu.Add("Action 2").OnClick(func(ctx *application.Context) { - log.Println("Action 2 clicked") - }) - menu.AddSeparator() - menu.Add("Quit").OnClick(func(ctx *application.Context) { - app.Quit() - }) - - if runtime.GOOS == "darwin" { - systray.SetTemplateIcon(icons.SystrayMacTemplate) - } - - systray.SetMenu(menu) - - log.Println("Menu-only test started") - log.Println("Expected behavior:") - log.Println(" - Left-click: Nothing (no window)") - log.Println(" - Right-click: Show menu") - - if err := app.Run(); err != nil { - log.Fatal(err) - } -} diff --git a/v3/test/manual/systray/window-menu/main.go b/v3/test/manual/systray/window-menu/main.go deleted file mode 100644 index bbf208a2a..000000000 --- a/v3/test/manual/systray/window-menu/main.go +++ /dev/null @@ -1,70 +0,0 @@ -package main - -import ( - _ "embed" - "log" - "runtime" - - "github.com/wailsapp/wails/v3/pkg/application" - "github.com/wailsapp/wails/v3/pkg/events" - "github.com/wailsapp/wails/v3/pkg/icons" -) - -func main() { - app := application.New(application.Options{ - Name: "Systray Window + Menu", - Description: "Tests systray with both attached window and menu", - Assets: application.AlphaAssets, - Mac: application.MacOptions{ - ActivationPolicy: application.ActivationPolicyAccessory, - }, - }) - - systray := app.SystemTray.New() - - window := app.Window.NewWithOptions(application.WebviewWindowOptions{ - Width: 400, - Height: 300, - Name: "Window Menu Test", - Title: "Window + Menu - Left-click toggles, Right-click shows menu", - Frameless: true, - AlwaysOnTop: true, - Hidden: true, - DisableResize: true, - Windows: application.WindowsWindow{ - HiddenOnTaskbar: true, - }, - }) - - window.RegisterHook(events.Common.WindowClosing, func(e *application.WindowEvent) { - window.Hide() - e.Cancel() - }) - - menu := app.Menu.New() - menu.Add("Show Window").OnClick(func(ctx *application.Context) { - systray.ShowWindow() - }) - menu.Add("Hide Window").OnClick(func(ctx *application.Context) { - systray.HideWindow() - }) - menu.AddSeparator() - menu.Add("Quit").OnClick(func(ctx *application.Context) { - app.Quit() - }) - - if runtime.GOOS == "darwin" { - systray.SetTemplateIcon(icons.SystrayMacTemplate) - } - - systray.AttachWindow(window).WindowOffset(5).SetMenu(menu) - - log.Println("Window + Menu test started") - log.Println("Expected behavior:") - log.Println(" - Left-click: Toggle window visibility") - log.Println(" - Right-click: Show menu") - - if err := app.Run(); err != nil { - log.Fatal(err) - } -} diff --git a/v3/test/manual/systray/window-only/main.go b/v3/test/manual/systray/window-only/main.go deleted file mode 100644 index b645bfa9f..000000000 --- a/v3/test/manual/systray/window-only/main.go +++ /dev/null @@ -1,58 +0,0 @@ -package main - -import ( - _ "embed" - "log" - "runtime" - - "github.com/wailsapp/wails/v3/pkg/application" - "github.com/wailsapp/wails/v3/pkg/events" - "github.com/wailsapp/wails/v3/pkg/icons" -) - -func main() { - app := application.New(application.Options{ - Name: "Systray Window Only", - Description: "Tests systray with attached window only (no menu)", - Assets: application.AlphaAssets, - Mac: application.MacOptions{ - ActivationPolicy: application.ActivationPolicyAccessory, - }, - }) - - systray := app.SystemTray.New() - - window := app.Window.NewWithOptions(application.WebviewWindowOptions{ - Width: 400, - Height: 300, - Name: "Window Only Test", - Title: "Window Only - Left-click systray to toggle", - Frameless: true, - AlwaysOnTop: true, - Hidden: true, - DisableResize: true, - Windows: application.WindowsWindow{ - HiddenOnTaskbar: true, - }, - }) - - window.RegisterHook(events.Common.WindowClosing, func(e *application.WindowEvent) { - window.Hide() - e.Cancel() - }) - - if runtime.GOOS == "darwin" { - systray.SetTemplateIcon(icons.SystrayMacTemplate) - } - - systray.AttachWindow(window).WindowOffset(5) - - log.Println("Window-only test started") - log.Println("Expected behavior:") - log.Println(" - Left-click: Toggle window visibility") - log.Println(" - Right-click: Nothing (no menu)") - - if err := app.Run(); err != nil { - log.Fatal(err) - } -} diff --git a/v3/tests/gtk4-benchmark/.gitignore b/v3/tests/gtk4-benchmark/.gitignore deleted file mode 100644 index 25759c424..000000000 --- a/v3/tests/gtk4-benchmark/.gitignore +++ /dev/null @@ -1,3 +0,0 @@ -# Compiled binaries -benchmark-gtk3 -benchmark-gtk4 diff --git a/v3/tests/gtk4-benchmark/README.md b/v3/tests/gtk4-benchmark/README.md deleted file mode 100644 index 1b8c421d9..000000000 --- a/v3/tests/gtk4-benchmark/README.md +++ /dev/null @@ -1,75 +0,0 @@ -# GTK3 vs GTK4 Benchmark - -This benchmark suite compares the performance of Wails applications running on GTK3 vs GTK4. - -## Building - -Build both versions: - -```bash -# Build GTK3 version (default) -go build -o benchmark-gtk3 . - -# Build GTK4 version (experimental) -go build -tags gtk4 -o benchmark-gtk4 . -``` - -## Running Benchmarks - -Run each version to generate a report: - -```bash -# Run GTK4 benchmark -./benchmark-gtk4 - -# Run GTK3 benchmark -./benchmark-gtk3 -``` - -Each run will: -1. Display results in the console -2. Save a JSON report file (e.g., `benchmark-GTK4-WebKitGTK-6.0-20240115-143052.json`) - -## Comparing Results - -Use the comparison tool to analyze two reports: - -```bash -go run compare.go benchmark-GTK3-*.json benchmark-GTK4-*.json -``` - -This will output a side-by-side comparison showing: -- Average times for each benchmark -- Percentage change between GTK3 and GTK4 -- Summary of improvements and regressions - -## Benchmarks Included - -| Benchmark | Description | -|-----------|-------------| -| Screen Enumeration | Query all connected screens | -| Primary Screen Query | Get the primary display | -| Window Create/Destroy | Create and close windows | -| Window SetSize | Resize window operations | -| Window SetTitle | Update window title | -| Window Size Query | Get current window dimensions | -| Window Position Query | Get current window position | -| Window Center | Center window on screen | -| Window Show/Hide | Toggle window visibility | -| Menu Creation (Simple) | Create basic menus | -| Menu Creation (Complex) | Create nested menu structures | -| Menu with Accelerators | Menus with keyboard shortcuts | -| Event Emit | Dispatch custom events | -| Event Emit+Receive | Round-trip event handling | -| Dialog Setup (Info) | Create info dialog | -| Dialog Setup (Question) | Create question dialog | - -## Expected Results - -GTK4 improvements typically include: -- Better Wayland support -- Improved GPU rendering pipeline -- More efficient event dispatch -- Better fractional scaling support - -Performance varies by operation - some may be faster in GTK4, others similar to GTK3. diff --git a/v3/tests/gtk4-benchmark/assets/index.html b/v3/tests/gtk4-benchmark/assets/index.html deleted file mode 100644 index d247170bd..000000000 --- a/v3/tests/gtk4-benchmark/assets/index.html +++ /dev/null @@ -1,46 +0,0 @@ - - - - - GTK Benchmark - - - -

                    GTK Benchmark Suite

                    -
                    -

                    Running benchmarks... Check console for results.

                    - - diff --git a/v3/tests/gtk4-benchmark/benchmark-GTK3-WebKit2GTK-4.1-20260111-222734.json b/v3/tests/gtk4-benchmark/benchmark-GTK3-WebKit2GTK-4.1-20260111-222734.json deleted file mode 100644 index 0fc38cc76..000000000 --- a/v3/tests/gtk4-benchmark/benchmark-GTK3-WebKit2GTK-4.1-20260111-222734.json +++ /dev/null @@ -1,136 +0,0 @@ -{ - "gtk_version": "GTK3 (WebKit2GTK 4.1)", - "platform": "linux/amd64", - "go_version": "go1.25.4", - "timestamp": "2026-01-11T22:27:34.842898202+11:00", - "results": [ - { - "name": "Screen Enumeration", - "iterations": 100, - "total_time_ns": 167481, - "avg_time_ns": 1674, - "min_time_ns": 50, - "max_time_ns": 161808 - }, - { - "name": "Primary Screen Query", - "iterations": 100, - "total_time_ns": 6710, - "avg_time_ns": 67, - "min_time_ns": 40, - "max_time_ns": 1422 - }, - { - "name": "Window Create/Destroy", - "iterations": 20, - "total_time_ns": 433715992, - "avg_time_ns": 21685799, - "min_time_ns": 21370109, - "max_time_ns": 22185831 - }, - { - "name": "Window SetSize", - "iterations": 50, - "total_time_ns": 6996039, - "avg_time_ns": 139920, - "min_time_ns": 104358, - "max_time_ns": 1173112 - }, - { - "name": "Window SetTitle", - "iterations": 100, - "total_time_ns": 3398274, - "avg_time_ns": 33982, - "min_time_ns": 30308, - "max_time_ns": 59092 - }, - { - "name": "Window Size Query", - "iterations": 100, - "total_time_ns": 2871777, - "avg_time_ns": 28717, - "min_time_ns": 26229, - "max_time_ns": 37732 - }, - { - "name": "Window Position Query", - "iterations": 100, - "total_time_ns": 3027183, - "avg_time_ns": 30271, - "min_time_ns": 26841, - "max_time_ns": 142271 - }, - { - "name": "Window Center", - "iterations": 50, - "total_time_ns": 1615738, - "avg_time_ns": 32314, - "min_time_ns": 29016, - "max_time_ns": 52470 - }, - { - "name": "Window Show/Hide", - "iterations": 20, - "total_time_ns": 276611193, - "avg_time_ns": 13830559, - "min_time_ns": 10472545, - "max_time_ns": 39370867 - }, - { - "name": "Menu Creation (Simple)", - "iterations": 50, - "total_time_ns": 129326, - "avg_time_ns": 2586, - "min_time_ns": 250, - "max_time_ns": 76175 - }, - { - "name": "Menu Creation (Complex)", - "iterations": 20, - "total_time_ns": 460375, - "avg_time_ns": 23018, - "min_time_ns": 16171, - "max_time_ns": 60314 - }, - { - "name": "Menu with Accelerators", - "iterations": 50, - "total_time_ns": 106064, - "avg_time_ns": 2121, - "min_time_ns": 1172, - "max_time_ns": 8597 - }, - { - "name": "Event Emit", - "iterations": 100, - "total_time_ns": 1142611, - "avg_time_ns": 11426, - "min_time_ns": 541, - "max_time_ns": 506173 - }, - { - "name": "Event Emit+Receive", - "iterations": 50, - "total_time_ns": 395172, - "avg_time_ns": 7903, - "min_time_ns": 1042, - "max_time_ns": 105200 - }, - { - "name": "Dialog Setup (Info)", - "iterations": 20, - "total_time_ns": 1352, - "avg_time_ns": 67, - "min_time_ns": 50, - "max_time_ns": 290 - }, - { - "name": "Dialog Setup (Question)", - "iterations": 20, - "total_time_ns": 1024, - "avg_time_ns": 51, - "min_time_ns": 50, - "max_time_ns": 71 - } - ] -} \ No newline at end of file diff --git a/v3/tests/gtk4-benchmark/benchmark-GTK4-WebKitGTK-6.0-20260111-222428.json b/v3/tests/gtk4-benchmark/benchmark-GTK4-WebKitGTK-6.0-20260111-222428.json deleted file mode 100644 index 53a5ce944..000000000 --- a/v3/tests/gtk4-benchmark/benchmark-GTK4-WebKitGTK-6.0-20260111-222428.json +++ /dev/null @@ -1,136 +0,0 @@ -{ - "gtk_version": "GTK4 (WebKitGTK 6.0)", - "platform": "linux/amd64", - "go_version": "go1.25.4", - "timestamp": "2026-01-11T22:24:28.770802311+11:00", - "results": [ - { - "name": "Screen Enumeration", - "iterations": 100, - "total_time_ns": 49065976, - "avg_time_ns": 490659, - "min_time_ns": 40, - "max_time_ns": 49060802 - }, - { - "name": "Primary Screen Query", - "iterations": 100, - "total_time_ns": 4778, - "avg_time_ns": 47, - "min_time_ns": 40, - "max_time_ns": 110 - }, - { - "name": "Window Create/Destroy", - "iterations": 20, - "total_time_ns": 3783355772, - "avg_time_ns": 189167788, - "min_time_ns": 82048294, - "max_time_ns": 359631289 - }, - { - "name": "Window SetSize", - "iterations": 50, - "total_time_ns": 189389209, - "avg_time_ns": 3787784, - "min_time_ns": 113717, - "max_time_ns": 148270567 - }, - { - "name": "Window SetTitle", - "iterations": 100, - "total_time_ns": 3940155, - "avg_time_ns": 39401, - "min_time_ns": 32061, - "max_time_ns": 127723 - }, - { - "name": "Window Size Query", - "iterations": 100, - "total_time_ns": 3187990, - "avg_time_ns": 31879, - "min_time_ns": 28244, - "max_time_ns": 95472 - }, - { - "name": "Window Position Query", - "iterations": 100, - "total_time_ns": 3157760, - "avg_time_ns": 31577, - "min_time_ns": 27572, - "max_time_ns": 52790 - }, - { - "name": "Window Center", - "iterations": 50, - "total_time_ns": 1670267, - "avg_time_ns": 33405, - "min_time_ns": 29256, - "max_time_ns": 51037 - }, - { - "name": "Window Show/Hide", - "iterations": 20, - "total_time_ns": 149208499897, - "avg_time_ns": 7460424994, - "min_time_ns": 10363207, - "max_time_ns": 145362924705 - }, - { - "name": "Menu Creation (Simple)", - "iterations": 50, - "total_time_ns": 115039, - "avg_time_ns": 2300, - "min_time_ns": 471, - "max_time_ns": 23715 - }, - { - "name": "Menu Creation (Complex)", - "iterations": 20, - "total_time_ns": 1340059, - "avg_time_ns": 67002, - "min_time_ns": 23926, - "max_time_ns": 634788 - }, - { - "name": "Menu with Accelerators", - "iterations": 50, - "total_time_ns": 131468, - "avg_time_ns": 2629, - "min_time_ns": 1513, - "max_time_ns": 11362 - }, - { - "name": "Event Emit", - "iterations": 100, - "total_time_ns": 688025, - "avg_time_ns": 6880, - "min_time_ns": 681, - "max_time_ns": 115830 - }, - { - "name": "Event Emit+Receive", - "iterations": 50, - "total_time_ns": 1186158, - "avg_time_ns": 23723, - "min_time_ns": 551, - "max_time_ns": 994422 - }, - { - "name": "Dialog Setup (Info)", - "iterations": 20, - "total_time_ns": 710, - "avg_time_ns": 35, - "min_time_ns": 20, - "max_time_ns": 160 - }, - { - "name": "Dialog Setup (Question)", - "iterations": 20, - "total_time_ns": 601, - "avg_time_ns": 30, - "min_time_ns": 20, - "max_time_ns": 90 - } - ] -} \ No newline at end of file diff --git a/v3/tests/gtk4-benchmark/compare.go b/v3/tests/gtk4-benchmark/compare.go deleted file mode 100644 index f4793dfc6..000000000 --- a/v3/tests/gtk4-benchmark/compare.go +++ /dev/null @@ -1,164 +0,0 @@ -//go:build ignore - -package main - -import ( - "encoding/json" - "fmt" - "os" - "sort" - "strings" - "time" -) - -// BenchmarkResult mirrors the struct in main.go -type BenchmarkResult struct { - Name string `json:"name"` - Iterations int `json:"iterations"` - TotalTime time.Duration `json:"total_time_ns"` - AvgTime time.Duration `json:"avg_time_ns"` - MinTime time.Duration `json:"min_time_ns"` - MaxTime time.Duration `json:"max_time_ns"` -} - -// BenchmarkReport mirrors the struct in main.go -type BenchmarkReport struct { - GTKVersion string `json:"gtk_version"` - Platform string `json:"platform"` - GoVersion string `json:"go_version"` - Timestamp time.Time `json:"timestamp"` - Results []BenchmarkResult `json:"results"` -} - -func main() { - if len(os.Args) < 3 { - fmt.Println("Usage: go run compare.go ") - os.Exit(1) - } - - gtk3Report, err := loadReport(os.Args[1]) - if err != nil { - fmt.Fprintf(os.Stderr, "Error loading GTK3 report: %v\n", err) - os.Exit(1) - } - - gtk4Report, err := loadReport(os.Args[2]) - if err != nil { - fmt.Fprintf(os.Stderr, "Error loading GTK4 report: %v\n", err) - os.Exit(1) - } - - compareReports(gtk3Report, gtk4Report) -} - -func loadReport(filename string) (*BenchmarkReport, error) { - data, err := os.ReadFile(filename) - if err != nil { - return nil, err - } - - var report BenchmarkReport - if err := json.Unmarshal(data, &report); err != nil { - return nil, err - } - - return &report, nil -} - -func compareReports(gtk3, gtk4 *BenchmarkReport) { - fmt.Println("=" + strings.Repeat("=", 89)) - fmt.Println("GTK3 vs GTK4 Benchmark Comparison") - fmt.Println("=" + strings.Repeat("=", 89)) - fmt.Println() - - fmt.Println("Report Details:") - fmt.Printf(" GTK3: %s (%s)\n", gtk3.GTKVersion, gtk3.Timestamp.Format(time.RFC3339)) - fmt.Printf(" GTK4: %s (%s)\n", gtk4.GTKVersion, gtk4.Timestamp.Format(time.RFC3339)) - fmt.Printf(" Platform: %s\n", gtk3.Platform) - fmt.Println() - - // Build maps for easy lookup - gtk3Results := make(map[string]BenchmarkResult) - gtk4Results := make(map[string]BenchmarkResult) - - for _, r := range gtk3.Results { - gtk3Results[r.Name] = r - } - for _, r := range gtk4.Results { - gtk4Results[r.Name] = r - } - - // Get all benchmark names - names := make([]string, 0) - for name := range gtk3Results { - names = append(names, name) - } - sort.Strings(names) - - // Print comparison table - fmt.Printf("%-35s %12s %12s %12s %10s\n", "Benchmark", "GTK3 Avg", "GTK4 Avg", "Difference", "Change") - fmt.Println(strings.Repeat("-", 90)) - - var totalGTK3, totalGTK4 time.Duration - improvements := 0 - regressions := 0 - - for _, name := range names { - gtk3r, ok3 := gtk3Results[name] - gtk4r, ok4 := gtk4Results[name] - - if !ok3 || !ok4 { - continue - } - - diff := gtk4r.AvgTime - gtk3r.AvgTime - var pctChange float64 - if gtk3r.AvgTime > 0 { - pctChange = float64(diff) / float64(gtk3r.AvgTime) * 100 - } - - totalGTK3 += gtk3r.AvgTime - totalGTK4 += gtk4r.AvgTime - - changeSymbol := "" - if pctChange < -5 { - changeSymbol = "✓ FASTER" - improvements++ - } else if pctChange > 5 { - changeSymbol = "✗ SLOWER" - regressions++ - } else { - changeSymbol = "≈ SAME" - } - - fmt.Printf("%-35s %12v %12v %+12v %+9.1f%% %s\n", - name, gtk3r.AvgTime, gtk4r.AvgTime, diff, pctChange, changeSymbol) - } - - fmt.Println(strings.Repeat("-", 90)) - - // Summary - totalDiff := totalGTK4 - totalGTK3 - var totalPctChange float64 - if totalGTK3 > 0 { - totalPctChange = float64(totalDiff) / float64(totalGTK3) * 100 - } - - fmt.Printf("%-35s %12v %12v %+12v %+9.1f%%\n", - "TOTAL", totalGTK3, totalGTK4, totalDiff, totalPctChange) - - fmt.Println() - fmt.Println("Summary:") - fmt.Printf(" Improvements (>5%% faster): %d\n", improvements) - fmt.Printf(" Regressions (>5%% slower): %d\n", regressions) - fmt.Printf(" No significant change: %d\n", len(names)-improvements-regressions) - fmt.Println() - - if totalPctChange < 0 { - fmt.Printf("Overall: GTK4 is %.1f%% faster than GTK3\n", -totalPctChange) - } else if totalPctChange > 0 { - fmt.Printf("Overall: GTK4 is %.1f%% slower than GTK3\n", totalPctChange) - } else { - fmt.Println("Overall: No significant difference") - } -} diff --git a/v3/tests/gtk4-benchmark/main.go b/v3/tests/gtk4-benchmark/main.go deleted file mode 100644 index 381717f8d..000000000 --- a/v3/tests/gtk4-benchmark/main.go +++ /dev/null @@ -1,325 +0,0 @@ -//go:build linux - -package main - -import ( - "embed" - "encoding/json" - "fmt" - "os" - "runtime" - "strings" - "time" - - "github.com/wailsapp/wails/v3/pkg/application" -) - -//go:embed assets/* -var assets embed.FS - -// BenchmarkResult holds the result of a single benchmark -type BenchmarkResult struct { - Name string `json:"name"` - Iterations int `json:"iterations"` - TotalTime time.Duration `json:"total_time_ns"` - AvgTime time.Duration `json:"avg_time_ns"` - MinTime time.Duration `json:"min_time_ns"` - MaxTime time.Duration `json:"max_time_ns"` -} - -// BenchmarkReport holds all benchmark results -type BenchmarkReport struct { - GTKVersion string `json:"gtk_version"` - Platform string `json:"platform"` - GoVersion string `json:"go_version"` - Timestamp time.Time `json:"timestamp"` - Results []BenchmarkResult `json:"results"` -} - -var ( - app *application.App - report BenchmarkReport -) - -func main() { - report = BenchmarkReport{ - Platform: runtime.GOOS + "/" + runtime.GOARCH, - GoVersion: runtime.Version(), - Timestamp: time.Now(), - Results: []BenchmarkResult{}, - } - - app = application.New(application.Options{ - Name: "GTK Benchmark", - Description: "Benchmark comparing GTK3 vs GTK4 performance", - Assets: application.AssetOptions{ - Handler: application.BundledAssetFileServer(assets), - }, - }) - - app.Window.NewWithOptions(application.WebviewWindowOptions{ - Title: "GTK Benchmark", - Width: 800, - Height: 600, - URL: "/", - }) - - // Run benchmarks after a short delay to ensure app is initialized - go func() { - time.Sleep(1 * time.Second) - runBenchmarks() - }() - - err := app.Run() - if err != nil { - fmt.Fprintf(os.Stderr, "Error: %v\n", err) - os.Exit(1) - } -} - -func runBenchmarks() { - // Give the app a moment to fully initialize - time.Sleep(500 * time.Millisecond) - - fmt.Println("=" + strings.Repeat("=", 59)) - fmt.Println("GTK Benchmark Suite") - fmt.Println("=" + strings.Repeat("=", 59)) - - // Detect GTK version - report.GTKVersion = getGTKVersionString() - fmt.Printf("GTK Version: %s\n", report.GTKVersion) - fmt.Printf("Platform: %s\n", report.Platform) - fmt.Printf("Go Version: %s\n", report.GoVersion) - fmt.Println() - - // Run all benchmarks - benchmarkScreenEnumeration() - benchmarkWindowCreation() - benchmarkWindowOperations() - benchmarkMenuCreation() - benchmarkEventDispatch() - benchmarkDialogSetup() - - // Print and save report - printReport() - saveReport() - - // Exit after benchmarks complete - time.Sleep(500 * time.Millisecond) - app.Quit() -} - -func benchmark(name string, iterations int, fn func()) BenchmarkResult { - fmt.Printf("Running: %s (%d iterations)...\n", name, iterations) - - var times []time.Duration - var totalTime time.Duration - - for i := 0; i < iterations; i++ { - start := time.Now() - fn() - elapsed := time.Since(start) - times = append(times, elapsed) - totalTime += elapsed - } - - minTime := times[0] - maxTime := times[0] - for _, t := range times { - if t < minTime { - minTime = t - } - if t > maxTime { - maxTime = t - } - } - - result := BenchmarkResult{ - Name: name, - Iterations: iterations, - TotalTime: totalTime, - AvgTime: totalTime / time.Duration(iterations), - MinTime: minTime, - MaxTime: maxTime, - } - - report.Results = append(report.Results, result) - fmt.Printf(" Average: %v\n", result.AvgTime) - - return result -} - -func benchmarkScreenEnumeration() { - benchmark("Screen Enumeration", 100, func() { - _ = app.Screen.GetAll() - }) - - benchmark("Primary Screen Query", 100, func() { - _ = app.Screen.GetPrimary() - }) -} - -func benchmarkWindowCreation() { - benchmark("Window Create/Destroy", 20, func() { - w := app.Window.NewWithOptions(application.WebviewWindowOptions{ - Title: "Benchmark Window", - Width: 400, - Height: 300, - Hidden: true, - }) - // Small delay to ensure window is created - time.Sleep(10 * time.Millisecond) - w.Close() - time.Sleep(10 * time.Millisecond) - }) -} - -func benchmarkWindowOperations() { - // Create a test window - testWindow := app.Window.NewWithOptions(application.WebviewWindowOptions{ - Title: "Operations Test", - Width: 400, - Height: 300, - }) - time.Sleep(100 * time.Millisecond) - - benchmark("Window SetSize", 50, func() { - testWindow.SetSize(500, 400) - testWindow.SetSize(400, 300) - }) - - benchmark("Window SetTitle", 100, func() { - testWindow.SetTitle("Test Title " + time.Now().String()) - }) - - benchmark("Window Size Query", 100, func() { - _, _ = testWindow.Size() - }) - - benchmark("Window Position Query", 100, func() { - _, _ = testWindow.Position() - }) - - benchmark("Window Center", 50, func() { - testWindow.Center() - }) - - benchmark("Window Show/Hide", 20, func() { - testWindow.Hide() - time.Sleep(5 * time.Millisecond) - testWindow.Show() - time.Sleep(5 * time.Millisecond) - }) - - testWindow.Close() -} - -func benchmarkMenuCreation() { - benchmark("Menu Creation (Simple)", 50, func() { - menu := app.Menu.New() - menu.Add("Item 1") - menu.Add("Item 2") - menu.Add("Item 3") - }) - - benchmark("Menu Creation (Complex)", 20, func() { - menu := app.Menu.New() - for i := 0; i < 5; i++ { - submenu := menu.AddSubmenu(fmt.Sprintf("Menu %d", i)) - for j := 0; j < 10; j++ { - submenu.Add(fmt.Sprintf("Item %d-%d", i, j)) - } - } - }) - - benchmark("Menu with Accelerators", 50, func() { - menu := app.Menu.New() - menu.Add("Cut").SetAccelerator("CmdOrCtrl+X") - menu.Add("Copy").SetAccelerator("CmdOrCtrl+C") - menu.Add("Paste").SetAccelerator("CmdOrCtrl+V") - }) -} - -func benchmarkEventDispatch() { - received := make(chan struct{}, 1000) - - app.Event.On("benchmark-event", func(event *application.CustomEvent) { - select { - case received <- struct{}{}: - default: - } - }) - - benchmark("Event Emit", 100, func() { - app.Event.Emit("benchmark-event", map[string]interface{}{ - "timestamp": time.Now().UnixNano(), - "data": "test payload", - }) - }) - - benchmark("Event Emit+Receive", 50, func() { - app.Event.Emit("benchmark-event", nil) - select { - case <-received: - case <-time.After(100 * time.Millisecond): - } - }) -} - -func benchmarkDialogSetup() { - // Dialog benchmarks - measure setup time only (Show() would block) - benchmark("Dialog Setup (Info)", 20, func() { - _ = app.Dialog.Info(). - SetTitle("Benchmark"). - SetMessage("Test message") - }) - - benchmark("Dialog Setup (Question)", 20, func() { - _ = app.Dialog.Question(). - SetTitle("Benchmark"). - SetMessage("Test question?") - }) -} - -func printReport() { - fmt.Println() - fmt.Println("=" + strings.Repeat("=", 59)) - fmt.Println("Benchmark Results") - fmt.Println("=" + strings.Repeat("=", 59)) - fmt.Printf("GTK Version: %s\n", report.GTKVersion) - fmt.Printf("Platform: %s\n", report.Platform) - fmt.Printf("Timestamp: %s\n", report.Timestamp.Format(time.RFC3339)) - fmt.Println() - - fmt.Printf("%-35s %10s %12s %12s\n", "Benchmark", "Iterations", "Avg Time", "Total Time") - fmt.Println(strings.Repeat("-", 75)) - - for _, r := range report.Results { - fmt.Printf("%-35s %10d %12v %12v\n", - r.Name, r.Iterations, r.AvgTime, r.TotalTime) - } - fmt.Println() -} - -func saveReport() { - filename := fmt.Sprintf("benchmark-%s-%s.json", - strings.ReplaceAll(report.GTKVersion, " ", "-"), - report.Timestamp.Format("20060102-150405")) - filename = strings.ReplaceAll(filename, "/", "-") - filename = strings.ReplaceAll(filename, "(", "") - filename = strings.ReplaceAll(filename, ")", "") - - data, err := json.MarshalIndent(report, "", " ") - if err != nil { - fmt.Fprintf(os.Stderr, "Error marshaling report: %v\n", err) - return - } - - err = os.WriteFile(filename, data, 0644) - if err != nil { - fmt.Fprintf(os.Stderr, "Error writing report: %v\n", err) - return - } - - fmt.Printf("Report saved to: %s\n", filename) -} diff --git a/v3/tests/gtk4-benchmark/version_gtk3.go b/v3/tests/gtk4-benchmark/version_gtk3.go deleted file mode 100644 index ed7c49cef..000000000 --- a/v3/tests/gtk4-benchmark/version_gtk3.go +++ /dev/null @@ -1,7 +0,0 @@ -//go:build linux && !gtk4 - -package main - -func getGTKVersionString() string { - return "GTK3 (WebKit2GTK 4.1)" -} diff --git a/v3/tests/gtk4-benchmark/version_gtk4.go b/v3/tests/gtk4-benchmark/version_gtk4.go deleted file mode 100644 index aa7703abc..000000000 --- a/v3/tests/gtk4-benchmark/version_gtk4.go +++ /dev/null @@ -1,7 +0,0 @@ -//go:build linux && gtk4 - -package main - -func getGTKVersionString() string { - return "GTK4 (WebKitGTK 6.0)" -} diff --git a/v3/tests/window-visibility-test/.gitignore b/v3/tests/window-visibility-test/.gitignore deleted file mode 100644 index dc734a8b8..000000000 --- a/v3/tests/window-visibility-test/.gitignore +++ /dev/null @@ -1,19 +0,0 @@ -# Compiled binary -window-visibility-test -window-visibility-test.exe - -# Build artifacts -*.exe -*.exe~ -*.dll -*.so -*.dylib - -# Test binaries -*.test - -# Output of the go coverage tool -*.out - -# Go workspace file -go.work \ No newline at end of file diff --git a/v3/tests/window-visibility-test/README.md b/v3/tests/window-visibility-test/README.md deleted file mode 100644 index 04b4ec49e..000000000 --- a/v3/tests/window-visibility-test/README.md +++ /dev/null @@ -1,146 +0,0 @@ -# Window Visibility Test - Issue #2861 - -This example demonstrates and tests the fixes implemented for [Wails v3 Issue #2861](https://github.com/wailsapp/wails/issues/2861) regarding application windows not showing on Windows 10 Pro due to efficiency mode. - -## Problem Background - -On Windows systems, the "efficiency mode" feature could prevent Wails applications from displaying windows properly. This occurred because: - -1. **WebView2 NavigationCompleted events** could be delayed or missed in efficiency mode -2. **Window visibility was gated** behind WebView2 navigation completion -3. **No fallback mechanisms** existed for delayed or failed navigation events - -## Solution Implemented - -The fix implements a **robust cross-platform window visibility pattern**: - -### Windows Improvements -- ✅ **Decouple window container from WebView state** - Windows show immediately -- ✅ **3-second timeout fallback** - Shows WebView if navigation is delayed -- ✅ **Efficiency mode prevention** - Sets WebView2 `IsVisible=true` per Microsoft guidance -- ✅ **Enhanced state tracking** - Proper visibility state management - -### Cross-Platform Consistency -- ✅ **macOS** - Already robust, documented best practices -- ✅ **Linux** - Added missing show/hide methods for both CGO and purego builds - -## Test Scenarios - -This example provides comprehensive testing for: - -### 1. **Basic Window Tests** -- **Normal Window**: Standard window creation - should appear immediately -- **Delayed Content Window**: Simulates heavy content loading (like Vue.js apps) -- **Hidden → Show Test**: Tests delayed showing after initial creation - -### 2. **Stress Tests** -- **Multiple Windows**: Creates 3 windows simultaneously -- **Rapid Creation**: Creates windows in quick succession - -### 3. **Critical Issue #2861 Test** -- **Efficiency Mode Test**: Specifically designed to reproduce and verify the fix -- Tests window container vs content loading timing -- Includes heavy content simulation - -## How to Run - -```bash -cd /path/to/wails/v3/examples/window-visibility-test -wails dev -``` - -## Testing Instructions - -### What to Look For -1. **Immediate Window Appearance** - Windows should appear within 100ms of clicking buttons -2. **Progressive Loading** - Content may load progressively, but window container visible immediately -3. **No Efficiency Mode Issues** - Windows appear even if Task Manager shows "efficiency mode" -4. **Consistent Cross-Platform Behavior** - Similar behavior on Windows, macOS, and Linux - -### How to Test -1. **Note the current time** displayed in the app -2. **Click any test button** or use menu items -3. **Immediately observe** if a window appears (should be within 100ms) -4. **Wait for content** to load and check reported timing -5. **Try multiple tests** in sequence to test robustness -6. **Test both buttons and menu items** for comprehensive coverage - -### Expected Results -- ✅ Window containers appear immediately upon button click -- ✅ Content loads progressively within 2-3 seconds -- ✅ No blank or invisible windows, even under efficiency mode -- ✅ Activity log shows sub-100ms window creation times -- ✅ All test scenarios work consistently - -## Manual Testing Checklist - -### Windows 10 Pro (Primary Target) -- [ ] Test with efficiency mode enabled in Task Manager -- [ ] Create windows while system is under load -- [ ] Test rapid window creation scenarios -- [ ] Verify WebView2 content loads after container appears -- [ ] Check activity log for sub-100ms creation times - -### Windows 11 -- [ ] Verify consistent behavior with Windows 10 Pro fixes -- [ ] Test efficiency mode scenarios -- [ ] Validate timeout fallback mechanisms - -### macOS -- [ ] Confirm existing robust behavior maintained -- [ ] Test all window creation scenarios -- [ ] Verify no regressions introduced - -### Linux -- [ ] Test both CGO and purego builds -- [ ] Verify new show/hide methods work correctly -- [ ] Test window positioning and timing - -## Technical Implementation Details - -### Window Creation Flow -``` -1. User clicks button → JavaScript calls Go backend -2. Go creates WebviewWindow → Sets properties -3. Go calls window.Show() → IMMEDIATE window container display -4. WebView2 starts navigation → Progressive content loading -5. Timeout fallback ensures WebView shows even if navigation delayed -``` - -### Key Code Changes -- **Windows**: `/v3/pkg/application/webview_window_windows.go` -- **macOS**: `/v3/pkg/application/webview_window_darwin.go` -- **Linux**: `/v3/pkg/application/webview_window_linux.go`, `linux_cgo.go`, `linux_purego.go` - -## Reporting Test Results - -When testing, please report: - -1. **Platform & OS Version** (e.g., "Windows 10 Pro 21H2", "macOS 13.1", "Ubuntu 22.04") -2. **Window Creation Timing** (from activity log) -3. **Any Delayed or Missing Windows** -4. **Efficiency Mode Status** (Windows only - check Task Manager) -5. **Content Loading Behavior** (immediate container vs progressive content) -6. **Any Error Messages** in activity log or console - -### Sample Test Report Format -``` -Platform: Windows 10 Pro 21H2 -Efficiency Mode: Enabled -Results: -- Normal Window: ✅ Appeared immediately (<50ms) -- Delayed Content: ✅ Container immediate, content loaded in 2.1s -- Multiple Windows: ✅ All 3 appeared simultaneously -- Critical Test: ✅ Window appeared immediately, content progressive -Notes: No issues observed, all windows visible immediately -``` - -## Architecture Notes - -This example demonstrates the **preferred window visibility pattern** for web-based desktop applications: - -1. **Separate Concerns**: Window container vs web content readiness -2. **Immediate Feedback**: Users see window immediately -3. **Progressive Enhancement**: Content loads and appears when ready -4. **Robust Fallbacks**: Multiple strategies for edge cases -5. **Cross-Platform Consistency**: Same behavior on all platforms diff --git a/v3/tests/window-visibility-test/TESTING_GUIDE.md b/v3/tests/window-visibility-test/TESTING_GUIDE.md deleted file mode 100644 index dbb3bfd04..000000000 --- a/v3/tests/window-visibility-test/TESTING_GUIDE.md +++ /dev/null @@ -1,159 +0,0 @@ -# Testing Guide - Window Visibility Issue #2861 - -## Quick Start - -1. **Build and run the application:** - ```bash - cd v3/examples/window-visibility-test - ./build.sh - # OR - wails dev - ``` - -2. **Main testing interface:** - - The app opens with a comprehensive testing dashboard - - Contains multiple test scenarios accessible via buttons - - Also provides menu-based testing (File, Tests, Help menus) - - Real-time activity logging with precise timing - -## Critical Test Cases - -### 🎯 **Issue #2861 Reproduction Test** (Most Important) -**Button:** "Efficiency Mode Test" -**Expected:** Window container appears immediately, content loads progressively -**Watch for:** -- Window visible within 100ms of button click -- Content loading message appears initially -- Content completes loading after 2-3 seconds -- No blank or invisible windows - -### ⏳ **Delayed Content Simulation** -**Button:** "Create Delayed Content Window" -**Expected:** Tests navigation completion timing -**Watch for:** -- Window container appears immediately -- Loading spinner visible initially -- Content loads after 3-second delay -- Window remains visible throughout - -### 🔄 **Hidden → Show Robustness** -**Button:** "Hidden → Show Test" -**Expected:** Tests delayed show() calls -**Watch for:** -- Initial response in activity log -- Window appears after exactly 2 seconds -- No timing issues or failures - -## Platform-Specific Testing - -### Windows 10 Pro (Primary Target) -**Enable Efficiency Mode Testing:** -1. Open Task Manager → Processes tab -2. Find the test application process -3. Right-click → "Efficiency mode" (if available) -4. Run all test scenarios -5. Verify windows still appear immediately - -**Key Metrics:** -- Window creation: < 100ms -- Content loading: 2-3 seconds -- No invisible windows under any conditions - -### Windows 11 -**Similar to Windows 10 Pro but also test:** -- New Windows 11 efficiency features -- Multiple monitor scenarios -- High DPI scaling - -### macOS -**Focus on consistency:** -- All scenarios should work identical to Windows -- No regressions in existing robust behavior -- Test across different macOS versions if possible - -### Linux -**Test both build variants:** -```bash -# CGO build (default) -wails dev - -# Purego build -CGO_ENABLED=0 wails dev -``` -- Verify both variants behave identically -- Test across different Linux distributions - -## Success Criteria - -### ✅ **Pass Conditions** -- All windows appear within 100ms of button click -- Activity log shows consistent sub-100ms timing -- Content loads progressively without blocking window visibility -- No blank, invisible, or delayed windows under any test scenario -- Efficiency mode (Windows) does not prevent window appearance -- Menu and button testing yield identical results - -### ❌ **Fail Conditions** -- Any window takes >200ms to appear -- Blank or invisible windows under any condition -- Window visibility blocked by content loading -- Efficiency mode prevents window appearance -- Inconsistent behavior between test methods -- Platform-specific failures - -## Reporting Results - -**Please provide this information:** - -``` -Platform: [Windows 10 Pro/Windows 11/macOS/Linux distro + version] -Build Type: [CGO/Purego] (Linux only) -Efficiency Mode: [Enabled/Disabled/N/A] (Windows only) - -Test Results: -- Normal Window: [✅ Pass / ❌ Fail] - [timing in ms] -- Delayed Content: [✅ Pass / ❌ Fail] - [container timing / content timing] -- Hidden→Show: [✅ Pass / ❌ Fail] - [notes] -- Multiple Windows: [✅ Pass / ❌ Fail] - [notes] -- Efficiency Mode Test: [✅ Pass / ❌ Fail] - [critical timing results] - -Notes: -[Any additional observations, error messages, or unexpected behavior] -``` - -## Advanced Testing Scenarios - -### **Rapid Stress Testing** -1. Click "Rapid Creation Test" multiple times quickly -2. Use keyboard shortcuts to rapidly access menu items -3. Create multiple windows then close them rapidly -4. Test system under load (other applications running) - -### **Edge Case Testing** -1. Test during system startup (high load) -2. Test with multiple monitors -3. Test with different DPI scaling settings -4. Test while other WebView2 applications are running - -### **Timing Verification** -1. Use browser dev tools (F12) to check console timing -2. Compare activity log timing with system clock -3. Test on slower/older hardware if available -4. Verify timing consistency across multiple runs - -## Troubleshooting - -### **Common Issues** -- **Blank window**: Check activity log for error messages -- **Slow timing**: Verify system isn't under heavy load -- **Build failures**: Ensure Wails v3 CLI is latest version -- **Import errors**: Run `go mod tidy` in example directory - -### **Debug Information** -The application provides extensive logging: -- Browser console (F12) shows JavaScript timing -- Activity log shows backend call timing -- Go application logs show window creation details -- Check system Task Manager for process efficiency mode status - -This comprehensive testing should validate that the window visibility fixes successfully resolve issue #2861 across all supported platforms. \ No newline at end of file diff --git a/v3/tests/window-visibility-test/assets/index.html b/v3/tests/window-visibility-test/assets/index.html deleted file mode 100644 index 22023a5e3..000000000 --- a/v3/tests/window-visibility-test/assets/index.html +++ /dev/null @@ -1,431 +0,0 @@ - - - - - - Window Visibility Test - Issue #2861 - - - -
                    -
                    -

                    🪟 Window Visibility Test

                    -

                    Testing fixes for Wails v3 Issue #2861 - Windows 10 Pro Efficiency Mode

                    -
                    - Current Time: --:--:-- -
                    -
                    - -
                    -

                    Basic Window Tests

                    -

                    These tests verify that windows appear immediately when requested, regardless of WebView content loading state.

                    -
                    - - - -
                    -
                    - -
                    -

                    Stress Tests

                    -

                    These tests push the window system to verify robustness under load and timing edge cases.

                    -
                    - - -
                    -
                    - -
                    -

                    🔬Critical Issue #2861 Test

                    -

                    This test specifically targets the Windows efficiency mode bug where WebView2 NavigationCompleted events could be delayed or missed.

                    - -
                    -

                    Expected Behavior:

                    -
                      -
                    • Window container appears immediately upon button click
                    • -
                    • Content loads progressively (may take 2-3 seconds)
                    • -
                    • No blank or invisible windows, even under efficiency mode
                    • -
                    -
                    - -
                    - -
                    -
                    - -
                    -

                    📊Test Results & Timing

                    -

                    Monitor window creation timing and behavior. Each button click should result in immediate window visibility.

                    - -
                    -

                    Activity Log

                    -
                    -
                    Ready for testing... Click any button to begin.
                    -
                    -
                    -
                    - -
                    -

                    📝Testing Instructions

                    -
                    -

                    What to Look For:

                    -
                      -
                    • Immediate Window Appearance: Windows should appear within 100ms of clicking
                    • -
                    • Progressive Loading: Content may load progressively, but window container should be visible immediately
                    • -
                    • No Efficiency Mode Issues: On Windows, windows should still appear even if Task Manager shows "efficiency mode"
                    • -
                    • Consistent Behavior: All platforms (Windows, macOS, Linux) should behave similarly
                    • -
                    -
                    - -
                    -

                    How to Test:

                    -
                      -
                    1. Note the current time displayed above
                    2. -
                    3. Click any test button
                    4. -
                    5. Immediately observe if a window appears (should be within 100ms)
                    6. -
                    7. Wait for content to load and check the reported timing
                    8. -
                    9. Try multiple tests in sequence
                    10. -
                    11. Test both buttons and menu items
                    12. -
                    -
                    -
                    -
                    - - - - \ No newline at end of file diff --git a/v3/tests/window-visibility-test/go.mod b/v3/tests/window-visibility-test/go.mod deleted file mode 100644 index bc824bdac..000000000 --- a/v3/tests/window-visibility-test/go.mod +++ /dev/null @@ -1,52 +0,0 @@ -module window-visibility-test - -go 1.24 - -replace github.com/wailsapp/wails/v3 => ../../ - -require github.com/wailsapp/wails/v3 v3.0.0-alpha.62 - -require ( - dario.cat/mergo v1.0.2 // indirect - github.com/Microsoft/go-winio v0.6.2 // indirect - github.com/ProtonMail/go-crypto v1.3.0 // indirect - github.com/adrg/xdg v0.5.3 // indirect - github.com/bep/debounce v1.2.1 // indirect - github.com/cloudflare/circl v1.6.3 // indirect - github.com/coder/websocket v1.8.14 // indirect - github.com/cyphar/filepath-securejoin v0.6.1 // indirect - github.com/ebitengine/purego v0.9.1 // indirect - github.com/emirpasic/gods v1.18.1 // indirect - github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect - github.com/go-git/go-billy/v5 v5.7.0 // indirect - github.com/go-git/go-git/v5 v5.16.4 // indirect - github.com/go-ole/go-ole v1.3.0 // indirect - github.com/godbus/dbus/v5 v5.2.2 // indirect - github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect - github.com/google/uuid v1.6.0 // indirect - github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 // indirect - github.com/jchv/go-winloader v0.0.0-20250406163304-c1995be93bd1 // indirect - github.com/kevinburke/ssh_config v1.4.0 // indirect - github.com/klauspost/cpuid/v2 v2.3.0 // indirect - github.com/leaanthony/go-ansi-parser v1.6.1 // indirect - github.com/leaanthony/u v1.1.1 // indirect - github.com/lmittmann/tint v1.1.2 // indirect - github.com/mattn/go-colorable v0.1.14 // indirect - github.com/mattn/go-isatty v0.0.20 // indirect - github.com/pjbgf/sha1cd v0.5.0 // indirect - github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c // indirect - github.com/rivo/uniseg v0.4.7 // indirect - github.com/samber/lo v1.52.0 // indirect - github.com/sergi/go-diff v1.4.0 // indirect - github.com/skeema/knownhosts v1.3.2 // indirect - github.com/wailsapp/go-webview2 v1.0.23 // indirect - github.com/xanzy/ssh-agent v0.3.3 // indirect - golang.org/x/crypto v0.47.0 // indirect - golang.org/x/net v0.49.0 // indirect - golang.org/x/sys v0.40.0 // indirect - golang.org/x/text v0.33.0 // indirect - gopkg.in/warnings.v0 v0.1.2 // indirect -) - -// Add any other dependencies that might be needed -// These will be resolved when the user runs go mod tidy diff --git a/v3/tests/window-visibility-test/go.sum b/v3/tests/window-visibility-test/go.sum deleted file mode 100644 index 56f1153ea..000000000 --- a/v3/tests/window-visibility-test/go.sum +++ /dev/null @@ -1,147 +0,0 @@ -dario.cat/mergo v1.0.2 h1:85+piFYR1tMbRrLcDwR18y4UKJ3aH1Tbzi24VRW1TK8= -dario.cat/mergo v1.0.2/go.mod h1:E/hbnu0NxMFBjpMIE34DRGLWqDy0g5FuKDhCb31ngxA= -github.com/Microsoft/go-winio v0.5.2/go.mod h1:WpS1mjBmmwHBEWmogvA2mj8546UReBk4v8QkMxJ6pZY= -github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= -github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= -github.com/ProtonMail/go-crypto v1.3.0 h1:ILq8+Sf5If5DCpHQp4PbZdS1J7HDFRXz/+xKBiRGFrw= -github.com/ProtonMail/go-crypto v1.3.0/go.mod h1:9whxjD8Rbs29b4XWbB8irEcE8KHMqaR2e7GWU1R+/PE= -github.com/adrg/xdg v0.5.3 h1:xRnxJXne7+oWDatRhR1JLnvuccuIeCoBu2rtuLqQB78= -github.com/adrg/xdg v0.5.3/go.mod h1:nlTsY+NNiCBGCK2tpm09vRqfVzrc2fLmXGpBLF0zlTQ= -github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be h1:9AeTilPcZAjCFIImctFaOjnTIavg87rW78vTPkQqLI8= -github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be/go.mod h1:ySMOLuWl6zY27l47sB3qLNK6tF2fkHG55UZxx8oIVo4= -github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPdPJAN/hZIm0C4OItdklCFmMRWYpio= -github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs= -github.com/bep/debounce v1.2.1 h1:v67fRdBA9UQu2NhLFXrSg0Brw7CexQekrBwDMM8bzeY= -github.com/bep/debounce v1.2.1/go.mod h1:H8yggRPQKLUhUoqrJC1bO2xNya7vanpDl7xR3ISbCJ0= -github.com/cloudflare/circl v1.6.3 h1:9GPOhQGF9MCYUeXyMYlqTR6a5gTrgR/fBLXvUgtVcg8= -github.com/cloudflare/circl v1.6.3/go.mod h1:2eXP6Qfat4O/Yhh8BznvKnJ+uzEoTQ6jVKJRn81BiS4= -github.com/coder/websocket v1.8.14 h1:9L0p0iKiNOibykf283eHkKUHHrpG7f65OE3BhhO7v9g= -github.com/coder/websocket v1.8.14/go.mod h1:NX3SzP+inril6yawo5CQXx8+fk145lPDC6pumgx0mVg= -github.com/cyphar/filepath-securejoin v0.6.1 h1:5CeZ1jPXEiYt3+Z6zqprSAgSWiggmpVyciv8syjIpVE= -github.com/cyphar/filepath-securejoin v0.6.1/go.mod h1:A8hd4EnAeyujCJRrICiOWqjS1AX0a9kM5XL+NwKoYSc= -github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= -github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= -github.com/ebitengine/purego v0.9.1 h1:a/k2f2HQU3Pi399RPW1MOaZyhKJL9w/xFpKAg4q1s0A= -github.com/ebitengine/purego v0.9.1/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ= -github.com/elazarl/goproxy v1.7.2 h1:Y2o6urb7Eule09PjlhQRGNsqRfPmYI3KKQLFpCAV3+o= -github.com/elazarl/goproxy v1.7.2/go.mod h1:82vkLNir0ALaW14Rc399OTTjyNREgmdL2cVoIbS6XaE= -github.com/emirpasic/gods v1.18.1 h1:FXtiHYKDGKCW2KzwZKx0iC0PQmdlorYgdFG9jPXJ1Bc= -github.com/emirpasic/gods v1.18.1/go.mod h1:8tpGGwCnJ5H4r6BWwaV6OrWmMoPhUl5jm/FMNAnJvWQ= -github.com/gliderlabs/ssh v0.3.8 h1:a4YXD1V7xMF9g5nTkdfnja3Sxy1PVDCj1Zg4Wb8vY6c= -github.com/gliderlabs/ssh v0.3.8/go.mod h1:xYoytBv1sV0aL3CavoDuJIQNURXkkfPA/wxQ1pL1fAU= -github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 h1:+zs/tPmkDkHx3U66DAb0lQFJrpS6731Oaa12ikc+DiI= -github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376/go.mod h1:an3vInlBmSxCcxctByoQdvwPiA7DTK7jaaFDBTtu0ic= -github.com/go-git/go-billy/v5 v5.7.0 h1:83lBUJhGWhYp0ngzCMSgllhUSuoHP1iEWYjsPl9nwqM= -github.com/go-git/go-billy/v5 v5.7.0/go.mod h1:/1IUejTKH8xipsAcdfcSAlUlo2J7lkYV8GTKxAT/L3E= -github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399 h1:eMje31YglSBqCdIqdhKBW8lokaMrL3uTkpGYlE2OOT4= -github.com/go-git/go-git-fixtures/v4 v4.3.2-0.20231010084843-55a94097c399/go.mod h1:1OCfN199q1Jm3HZlxleg+Dw/mwps2Wbk9frAWm+4FII= -github.com/go-git/go-git/v5 v5.16.4 h1:7ajIEZHZJULcyJebDLo99bGgS0jRrOxzZG4uCk2Yb2Y= -github.com/go-git/go-git/v5 v5.16.4/go.mod h1:4Ge4alE/5gPs30F2H1esi2gPd69R0C39lolkucHBOp8= -github.com/go-json-experiment/json v0.0.0-20251027170946-4849db3c2f7e h1:Lf/gRkoycfOBPa42vU2bbgPurFong6zXeFtPoxholzU= -github.com/go-json-experiment/json v0.0.0-20251027170946-4849db3c2f7e/go.mod h1:uNVvRXArCGbZ508SxYYTC5v1JWoz2voff5pm25jU1Ok= -github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE= -github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78= -github.com/godbus/dbus/v5 v5.2.2 h1:TUR3TgtSVDmjiXOgAAyaZbYmIeP3DPkld3jgKGV8mXQ= -github.com/godbus/dbus/v5 v5.2.2/go.mod h1:3AAv2+hPq5rdnr5txxxRwiGjPXamgoIHgz9FPBfOp3c= -github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 h1:f+oWsMOmNPc8JmEHVZIycC7hBoQxHH9pNKQORJNozsQ= -github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8/go.mod h1:wcDNUvekVysuuOpQKo3191zZyTpiI6se1N1ULghS0sw= -github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= -github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= -github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= -github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99 h1:BQSFePA1RWJOlocH6Fxy8MmwDt+yVQYULKfN0RoTN8A= -github.com/jbenet/go-context v0.0.0-20150711004518-d14ea06fba99/go.mod h1:1lJo3i6rXxKeerYnT8Nvf0QmHCRC1n8sfWVwXF2Frvo= -github.com/jchv/go-winloader v0.0.0-20250406163304-c1995be93bd1 h1:njuLRcjAuMKr7kI3D85AXWkw6/+v9PwtV6M6o11sWHQ= -github.com/jchv/go-winloader v0.0.0-20250406163304-c1995be93bd1/go.mod h1:alcuEEnZsY1WQsagKhZDsoPCRoOijYqhZvPwLG0kzVs= -github.com/kevinburke/ssh_config v1.4.0 h1:6xxtP5bZ2E4NF5tuQulISpTO2z8XbtH8cg1PWkxoFkQ= -github.com/kevinburke/ssh_config v1.4.0/go.mod h1:q2RIzfka+BXARoNexmF9gkxEX7DmvbW9P4hIVx2Kg4M= -github.com/klauspost/cpuid/v2 v2.3.0 h1:S4CRMLnYUhGeDFDqkGriYKdfoFlDnMtqTiI/sFzhA9Y= -github.com/klauspost/cpuid/v2 v2.3.0/go.mod h1:hqwkgyIinND0mEev00jJYCxPNVRVXFQeu1XKlok6oO0= -github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= -github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= -github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= -github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= -github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= -github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= -github.com/leaanthony/go-ansi-parser v1.6.1 h1:xd8bzARK3dErqkPFtoF9F3/HgN8UQk0ed1YDKpEz01A= -github.com/leaanthony/go-ansi-parser v1.6.1/go.mod h1:+vva/2y4alzVmmIEpk9QDhA7vLC5zKDTRwfZGOp3IWU= -github.com/leaanthony/u v1.1.1 h1:TUFjwDGlNX+WuwVEzDqQwC2lOv0P4uhTQw7CMFdiK7M= -github.com/leaanthony/u v1.1.1/go.mod h1:9+o6hejoRljvZ3BzdYlVL0JYCwtnAsVuN9pVTQcaRfI= -github.com/lmittmann/tint v1.1.2 h1:2CQzrL6rslrsyjqLDwD11bZ5OpLBPU+g3G/r5LSfS8w= -github.com/lmittmann/tint v1.1.2/go.mod h1:HIS3gSy7qNwGCj+5oRjAutErFBl4BzdQP6cJZ0NfMwE= -github.com/matryer/is v1.4.0/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwMRU= -github.com/matryer/is v1.4.1 h1:55ehd8zaGABKLXQUe2awZ99BD/PTc2ls+KV/dXphgEQ= -github.com/matryer/is v1.4.1/go.mod h1:8I/i5uYgLzgsgEloJE1U6xx5HkBQpAZvepWuujKwMRU= -github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE= -github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8= -github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= -github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= -github.com/onsi/gomega v1.34.1 h1:EUMJIKUjM8sKjYbtxQI9A4z2o+rruxnzNvpknOXie6k= -github.com/onsi/gomega v1.34.1/go.mod h1:kU1QgUvBDLXBJq618Xvm2LUX6rSAfRaFRTcdOeDLwwY= -github.com/pjbgf/sha1cd v0.5.0 h1:a+UkboSi1znleCDUNT3M5YxjOnN1fz2FhN48FlwCxs0= -github.com/pjbgf/sha1cd v0.5.0/go.mod h1:lhpGlyHLpQZoxMv8HcgXvZEhcGs0PG/vsZnEJ7H0iCM= -github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmdv1U2eRNDiU2ErMBj1gwrq8eQ= -github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c/go.mod h1:7rwL4CYBLnjLxUqIJNnCWiEdr3bn6IUYi15bNlnbCCU= -github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= -github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= -github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= -github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= -github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ= -github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= -github.com/rogpeppe/go-internal v1.14.1 h1:UQB4HGPB6osV0SQTLymcB4TgvyWu6ZyliaW0tI/otEQ= -github.com/rogpeppe/go-internal v1.14.1/go.mod h1:MaRKkUm5W0goXpeCfT7UZI6fk/L7L7so1lCWt35ZSgc= -github.com/samber/lo v1.52.0 h1:Rvi+3BFHES3A8meP33VPAxiBZX/Aws5RxrschYGjomw= -github.com/samber/lo v1.52.0/go.mod h1:4+MXEGsJzbKGaUEQFKBq2xtfuznW9oz/WrgyzMzRoM0= -github.com/sergi/go-diff v1.4.0 h1:n/SP9D5ad1fORl+llWyN+D6qoUETXNZARKjyY2/KVCw= -github.com/sergi/go-diff v1.4.0/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4= -github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= -github.com/skeema/knownhosts v1.3.2 h1:EDL9mgf4NzwMXCTfaxSD/o/a5fxDw/xL9nkU28JjdBg= -github.com/skeema/knownhosts v1.3.2/go.mod h1:bEg3iQAuw+jyiw+484wwFJoKSLwcfd7fqRy+N0QTiow= -github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= -github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= -github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= -github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= -github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= -github.com/wailsapp/go-webview2 v1.0.23 h1:jmv8qhz1lHibCc79bMM/a/FqOnnzOGEisLav+a0b9P0= -github.com/wailsapp/go-webview2 v1.0.23/go.mod h1:qJmWAmAmaniuKGZPWwne+uor3AHMB5PFhqiK0Bbj8kc= -github.com/xanzy/ssh-agent v0.3.3 h1:+/15pJfg/RsTxqYcX6fHqOXZwwMP+2VyYWJeWM2qQFM= -github.com/xanzy/ssh-agent v0.3.3/go.mod h1:6dzNDKs0J9rVPHPhaGCukekBHKqfl+L3KghI1Bc68Uw= -golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.47.0 h1:V6e3FRj+n4dbpw86FJ8Fv7XVOql7TEwpHapKoMJ/GO8= -golang.org/x/crypto v0.47.0/go.mod h1:ff3Y9VzzKbwSSEzWqJsJVBnWmRwRSHt/6Op5n9bQc4A= -golang.org/x/exp v0.0.0-20260112195511-716be5621a96 h1:Z/6YuSHTLOHfNFdb8zVZomZr7cqNgTJvA8+Qz75D8gU= -golang.org/x/exp v0.0.0-20260112195511-716be5621a96/go.mod h1:nzimsREAkjBCIEFtHiYkrJyT+2uy9YZJB7H1k68CXZU= -golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.49.0 h1:eeHFmOGUTtaaPSGNmjBKpbng9MulQsJURQUAfUwY++o= -golang.org/x/net v0.49.0/go.mod h1:/ysNB2EvaqvesRkuLAyjI1ycPZlQHM3q01F02UY/MV8= -golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20200810151505-1b9f1253b3ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.40.0 h1:DBZZqJ2Rkml6QMQsZywtnjnnGvHza6BTfYFWY9kjEWQ= -golang.org/x/sys v0.40.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= -golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.39.0 h1:RclSuaJf32jOqZz74CkPA9qFuVTX7vhLlpfj/IGWlqY= -golang.org/x/term v0.39.0/go.mod h1:yxzUCTP/U+FzoxfdKmLaA0RV1WgE0VY7hXBwKtY/4ww= -golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.33.0 h1:B3njUFyqtHDUI5jMn1YIr5B0IE2U0qck04r6d4KPAxE= -golang.org/x/text v0.33.0/go.mod h1:LuMebE6+rBincTi9+xWTY8TztLzKHc/9C1uBCG27+q8= -golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= -gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= -gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= -gopkg.in/warnings.v0 v0.1.2 h1:wFXVbFY8DY5/xOe1ECiWdKCzZlxgshcYVNkBHstARME= -gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= -gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= -gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= -gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/v3/tests/window-visibility-test/main.go b/v3/tests/window-visibility-test/main.go deleted file mode 100644 index 247c1035c..000000000 --- a/v3/tests/window-visibility-test/main.go +++ /dev/null @@ -1,308 +0,0 @@ -package main - -import ( - "embed" - "fmt" - "log" - "time" - - "github.com/wailsapp/wails/v3/pkg/application" -) - -// WindowTestService provides methods for testing window visibility scenarios -type WindowTestService struct { - app *application.App -} - -// NewWindowTestService creates a new window test service -func NewWindowTestService() *WindowTestService { - return &WindowTestService{} -} - -// SetApp sets the application reference (internal method, not exposed to frontend) -func (w *WindowTestService) setApp(app *application.App) { - w.app = app -} - -// CreateNormalWindow creates a standard window - should show immediately -func (w *WindowTestService) CreateNormalWindow() string { - log.Println("Creating normal window...") - - w.app.Window.NewWithOptions(application.WebviewWindowOptions{ - Title: "Normal Window - Should Show Immediately", - Width: 600, - Height: 400, - X: 100, - Y: 100, - HTML: "Normal Window

                    ✅ Normal Window

                    This window should have appeared immediately after clicking the button.

                    Timestamp: " + time.Now().Format("15:04:05") + "

                    ", - }) - - return "Normal window created" -} - -// CreateDelayedContentWindow creates a window with delayed content to test navigation timing -func (w *WindowTestService) CreateDelayedContentWindow() string { - log.Println("Creating delayed content window...") - - // Use HTML that will take time to load (simulates heavy Vue app) - delayedHTML := ` - - - Delayed Content - - - -

                    ⏳ Delayed Content Window

                    -

                    This window tests navigation completion timing.

                    -
                    -

                    Loading... (simulates heavy content)

                    - -

                    Window container should be visible immediately, even during load.

                    - - ` - - w.app.Window.NewWithOptions(application.WebviewWindowOptions{ - Title: "Delayed Content Window - Test Navigation Timing", - Width: 600, - Height: 400, - X: 150, - Y: 150, - HTML: delayedHTML, - }) - - return "Delayed content window created" -} - -// CreateHiddenThenShowWindow creates a hidden window then shows it after delay -func (w *WindowTestService) CreateHiddenThenShowWindow() string { - log.Println("Creating hidden then show window...") - - window := w.app.Window.NewWithOptions(application.WebviewWindowOptions{ - Title: "Hidden Then Show Window - Test Show() Robustness", - Width: 600, - Height: 400, - X: 200, - Y: 200, - HTML: "Hidden Then Show

                    🔄 Hidden Then Show Window

                    This window was created hidden and then shown after 2 seconds.

                    Should test the robustness of the show() method.

                    Created at: " + time.Now().Format("15:04:05") + "

                    ", - Hidden: true, // Start hidden - }) - - // Show after 2 seconds to test delayed showing - go func() { - time.Sleep(2 * time.Second) - log.Println("Showing previously hidden window...") - window.Show() - }() - - return "Hidden window created, will show in 2 seconds" -} - -// CreateMultipleWindows creates multiple windows simultaneously to test performance -func (w *WindowTestService) CreateMultipleWindows() string { - log.Println("Creating multiple windows...") - - for i := 0; i < 3; i++ { - bgColors := []string{"#ff9a9e,#fecfef", "#a18cd1,#fbc2eb", "#fad0c4,#ffd1ff"} - content := fmt.Sprintf(` - - - Batch Window %d - - - -

                    🔢 Batch Window %d

                    -

                    Part of multiple windows stress test

                    -

                    All windows should appear quickly and simultaneously

                    -

                    Created at: %s

                    - - `, i+1, bgColors[i], i+1, time.Now().Format("15:04:05")) - - w.app.Window.NewWithOptions(application.WebviewWindowOptions{ - Title: fmt.Sprintf("Batch Window %d - Stress Test", i+1), - Width: 400, - Height: 300, - X: 250 + (i * 50), - Y: 250 + (i * 50), - HTML: content, - }) - } - - return "Created 3 windows simultaneously" -} - -// CreateEfficiencyModeTestWindow creates a window designed to trigger efficiency mode issues -func (w *WindowTestService) CreateEfficiencyModeTestWindow() string { - log.Println("Creating efficiency mode test window...") - - // Create content that might trigger efficiency mode or WebView2 delays - heavyHTML := ` - - - Efficiency Mode Test - - - -

                    ⚡ Efficiency Mode Test Window

                    -

                    This window tests the fix for Windows 10 Pro efficiency mode issue #2861

                    - -
                    -

                    Window Container Status

                    -

                    ✅ Window container is visible (this text proves it)

                    -
                    - -
                    -

                    WebView2 Status

                    -

                    ⏳ WebView2 navigation in progress...

                    - -
                    - -
                    -

                    Heavy Content (simulates Vue.js app)

                    -
                    - Loading heavy content... -
                    -
                    - - - - ` - - w.app.Window.NewWithOptions(application.WebviewWindowOptions{ - Title: "Efficiency Mode Test - Issue #2861 Reproduction", - Width: 700, - Height: 500, - X: 300, - Y: 300, - HTML: heavyHTML, - }) - - return "Efficiency mode test window created" -} - -// GetWindowCount returns the current number of windows -func (w *WindowTestService) GetWindowCount() int { - // This would need to be implemented based on the app's window tracking - // For now, return a placeholder - return 1 // Main window -} - -//go:embed assets/* -var assets embed.FS - -func main() { - // Create the service - service := NewWindowTestService() - - // Create application with menu - app := application.New(application.Options{ - Name: "Window Visibility Test", - Description: "Test application for window visibility robustness (Issue #2861)", - Services: []application.Service{ - application.NewService(service), - }, - Assets: application.AssetOptions{ - Handler: application.BundledAssetFileServer(assets), - }, - }) - - // Set app reference in service - service.setApp(app) - - // Create application menu - menu := app.NewMenu() - - // File menu - fileMenu := menu.AddSubmenu("File") - fileMenu.Add("New Normal Window").OnClick(func(ctx *application.Context) { - service.CreateNormalWindow() - }) - fileMenu.Add("New Delayed Content Window").OnClick(func(ctx *application.Context) { - service.CreateDelayedContentWindow() - }) - fileMenu.AddSeparator() - fileMenu.Add("Quit").OnClick(func(ctx *application.Context) { - app.Quit() - }) - - // Test menu - testMenu := menu.AddSubmenu("Tests") - testMenu.Add("Hidden Then Show Window").OnClick(func(ctx *application.Context) { - service.CreateHiddenThenShowWindow() - }) - testMenu.Add("Multiple Windows Stress Test").OnClick(func(ctx *application.Context) { - service.CreateMultipleWindows() - }) - testMenu.Add("Efficiency Mode Test").OnClick(func(ctx *application.Context) { - service.CreateEfficiencyModeTestWindow() - }) - - // Help menu - helpMenu := menu.AddSubmenu("Help") - helpMenu.Add("About").OnClick(func(ctx *application.Context) { - app.Window.NewWithOptions(application.WebviewWindowOptions{ - Title: "About Window Visibility Test", - Width: 500, - Height: 400, - X: 400, - Y: 300, - HTML: "About

                    Window Visibility Test

                    This application tests the fixes for Wails v3 issue #2861

                    Windows 10 Pro Efficiency Mode Fix

                    Tests window container vs WebView content visibility


                    Created for testing robust window visibility patterns

                    ", - }) - }) - - app.Menu.Set(menu) - - // Create main window - app.Window.NewWithOptions(application.WebviewWindowOptions{ - Title: "Window Visibility Test - Issue #2861", - Width: 800, - Height: 600, - X: 50, - Y: 50, - URL: "/index.html", - }) - - err := app.Run() - if err != nil { - log.Fatal(err) - } -} diff --git a/v3/verify-ios-setup.sh b/v3/verify-ios-setup.sh deleted file mode 100644 index 1a6e345c2..000000000 --- a/v3/verify-ios-setup.sh +++ /dev/null @@ -1,78 +0,0 @@ -#!/bin/bash - -echo "=== iOS Build System Verification ===" -echo -echo "Checking iOS build assets..." -echo - -# Check if files exist -echo "1. Checking build_assets/ios directory:" -if [ -d "internal/commands/build_assets/ios" ]; then - echo " ✅ iOS build_assets directory exists" - ls -la internal/commands/build_assets/ios/ -else - echo " ❌ iOS build_assets directory missing" -fi -echo - -echo "2. Checking updatable_build_assets/ios directory:" -if [ -d "internal/commands/updatable_build_assets/ios" ]; then - echo " ✅ iOS updatable_build_assets directory exists" - ls -la internal/commands/updatable_build_assets/ios/ -else - echo " ❌ iOS updatable_build_assets directory missing" -fi -echo - -echo "3. Checking iOS implementation files:" -for file in pkg/application/application_ios.go pkg/application/application_ios.h pkg/application/application_ios.m; do - if [ -f "$file" ]; then - echo " ✅ $file exists" - else - echo " ❌ $file missing" - fi -done -echo - -echo "4. Checking iOS example:" -if [ -d "examples/ios-poc" ]; then - echo " ✅ ios-poc example exists" - ls -la examples/ios-poc/ -else - echo " ❌ ios-poc example missing" -fi -echo - -echo "5. Checking main Taskfile includes iOS:" -if grep -q "ios:" internal/templates/_common/Taskfile.tmpl.yml 2>/dev/null; then - echo " ✅ iOS included in main Taskfile template" -else - echo " ❌ iOS not included in main Taskfile template" -fi -echo - -echo "6. Checking Xcode tools:" -if command -v xcrun &> /dev/null; then - echo " ✅ xcrun available" - echo " SDK Path: $(xcrun --sdk iphonesimulator --show-sdk-path 2>/dev/null || echo 'Not found')" -else - echo " ❌ xcrun not available" -fi -echo - -echo "7. iOS Build System Summary:" -echo " - Static assets: internal/commands/build_assets/ios/" -echo " - Templates: internal/commands/updatable_build_assets/ios/" -echo " - Implementation: pkg/application/application_ios.*" -echo " - Example: examples/ios-poc/" -echo " - Build script: build_ios.sh" -echo - -echo "=== Verification Complete ===" -echo -echo "The iOS build system structure is in place and ready for:" -echo "1. Creating new iOS projects with 'wails3 init'" -echo "2. Building with 'task ios:build'" -echo "3. Running with 'task ios:run'" -echo -echo "Note: Full compilation requires iOS development environment setup." \ No newline at end of file diff --git a/v3/wep/README.md b/v3/wep/README.md deleted file mode 100644 index 63ea57c98..000000000 --- a/v3/wep/README.md +++ /dev/null @@ -1,69 +0,0 @@ -# Wails Enhancement Proposal (WEP) Process - -## Introduction - -Welcome to the Wails Enhancement Proposal (WEP) process. This guide outlines the steps for proposing, discussing, and implementing feature enhancements in Wails. The process is divided into two main parts: - -1. **Submission of Proposal**: This part involves documenting your idea, submitting it for review, and discussing it with the community to gather feedback and refine the proposal. -2. **Implementation of Proposal**: Once a proposal is accepted, the implementation phase begins. This involves developing the feature, submitting a PR for the implementation, and iterating based on feedback until the feature is merged and documented. - -Following this structured approach ensures transparency, community involvement, and efficient enhancement of the Wails project. - -**NOTE**: This process is for proposing new functionality. For bug fixes, documentation improvements, and other minor changes, please follow the standard PR process. - -## Submission of Proposal - -### 1. Idea Initiation - -- **Document Your Idea**: - - Create a new directory: `v3/wep/proposals/` with the name of your proposal. - - Copy the WEP template located in `v3/wep/WEP_TEMPLATE.md` into `v3/wep/proposals//proposal.md`. - - Include any additional resources (images, diagrams, etc.) in the proposal directory. - - Fill in the template with the details of your proposal. Do not remove any sections. - -### 2. Submit Proposal - -- **Open a DRAFT PR**: - - Submit a DRAFT Pull Request (PR) for the proposal with the title `[WEP] `. - - It should only contain the proposal file and any additional resources (images, diagrams, etc.). - - Add a summary of the proposal in the PR description. - -### 3. Community Discussion - -- **Share Your Proposal**: Present your proposal to the Wails community. Try to get support for the proposal to increase the chances of acceptance. If you are on the discord server, create a post in the [`#enhancement-proposals`](https://discord.gg/TA8kbQds95) channel. -- **Gather Feedback**: Refine your proposal based on community input. All feedback should be added as comments in the PR. -- **Show Support**: Agreement with the proposal should be indicated by adding a thumbs-up emoji to the PR. The more thumbs-up emojis, the more likely the proposal will be accepted. -- **Iterate**: Make changes to the proposal based on feedback. -- **Agree on an Implementor**: To avoid stagnant proposals, we require someone agree to implement it. This could be the proposer. -- **Ready for Review**: Once the proposal is ready for review, change the PR status to `Ready for Review`. - -A minimum of 2 weeks should be given for community feedback and discussion. - -### 4. Final Decision - -- **Decision**: The Wails maintainers will make a final decision on the proposal based on community feedback and the proposal's merits. - - If accepted, the proposal will be assigned a WEP number and the PR merged. - - If rejected, the reasons will be provided in the PR comments. - -*NOTE*: If a proposal has not met the required support or has been inactive for more than a month, it may be closed. - -## Implementation of Proposal - -Once a proposal has been accepted and an implementation plan has been decided, the focus shifts to bringing the feature to life. This phase encompasses the actual development, review, and integration of the new feature. Here are the steps involved in the implementation process: - -### 1. Develop the Feature - -- **Follow Standards**: Implement the feature following Wails coding standards. -- **Document the Feature**: Ensure the feature is well-documented during the development process. -- **Submit a PR**: Once implemented, submit a PR for the feature. - -### 2. Feedback and Iteration - -- **Gather Feedback**: Collect feedback from the community. -- **Iterate**: Make improvements based on feedback. - -### 3. Merging - -- **Review of PR**: Address any review comments. -- **Merge**: The PR will be merged after satisfactory review. -The WEP process ensures structured and collaborative enhancement of Wails. Adhere to this guide to contribute effectively to the project's growth. \ No newline at end of file diff --git a/v3/wep/WEP_TEMPLATE.md b/v3/wep/WEP_TEMPLATE.md deleted file mode 100644 index c822c2361..000000000 --- a/v3/wep/WEP_TEMPLATE.md +++ /dev/null @@ -1,50 +0,0 @@ -# Wails Enhancement Proposal (WEP) - -## Title - -**Author**: [Your Name] -**Created**: [YYYY-MM-DD] - -## Summary - -Provide a concise summary of the proposal. - -## Motivation - -Explain the problem this proposal aims to solve and why it is necessary. - -## Detailed Design - -Provide a detailed description of the proposed feature, including: - -- Technical details -- Implementation steps -- Potential impact on existing functionality - -## Pros/Cons - -List the pros and cons of the proposed solution. - -## Alternatives Considered - -Discuss alternative solutions or approaches that were considered. - -## Backwards Compatibility - -Address any potential backward compatibility issues. - -## Test Plan - -Outline a testing strategy to ensure the feature works as expected. - -## Reference Implementation - -If applicable, include a link to a reference implementation or prototype. - -## Maintenance Plan - -Describe how the feature will be maintained and supported in the long term. - -## Conclusion - -Summarize the benefits of the proposal and any final considerations. diff --git a/v3/wep/proposals/.gitkeep b/v3/wep/proposals/.gitkeep deleted file mode 100644 index e69de29bb..000000000 diff --git a/v3/wep/proposals/titlebar-buttons/proposal.md b/v3/wep/proposals/titlebar-buttons/proposal.md deleted file mode 100644 index 8bd6b8c4f..000000000 --- a/v3/wep/proposals/titlebar-buttons/proposal.md +++ /dev/null @@ -1,137 +0,0 @@ -# Wails Enhancement Proposal (WEP) - -## Customising Window Controls in Wails - -**Author**: Lea Anthony -**Created**: 2024-05-20 - -## Summary - -This is a proposal for an API to control the appearance and functionality of window controls in Wails. -This will only be available on Windows and macOS. - -## Motivation - -We currently do not fully support the ability to customise window controls. - -## Detailed Design - -### Controlling Button State - -1. A new enum will be added: - -```go - type ButtonState int - - const ( - ButtonEnabled ButtonState = 0 - ButtonDisabled ButtonState = 1 - ButtonHidden ButtonState = 2 - ) -``` - -2. These options will be added to the `WebviewWindowOptions` option struct: - -```go - MinimiseButtonState ButtonState - MaximiseButtonState ButtonState - CloseButtonState ButtonState -``` - -3. These options will be removed from the current Windows/Mac options: - -- DisableMinimiseButton -- DisableMaximiseButton -- DisableCloseButton - -4. These methods will be added to the `Window` interface: - -```go - SetMinimizeButtonState(state ButtonState) - SetMaximizeButtonState(state ButtonState) - SetCloseButtonState(state ButtonState) -``` - -The settings translate to the following functionality on each platform: - -| | Windows | Mac | -|-----------------------|------------------------|------------------------| -| Disable Min/Max/Close | Disables Min/Max/Close | Disables Min/Max/Close | -| Hide Min | Disables Min | Hides Min button | -| Hide Max | Disables Max | Hides Max button | -| Hide Close | Hides all controls | Hides Close | - -Note: On Windows, it is not possible to hide the Min/Max buttons individually. -However, disabling both will hide both of the controls and only show the -close button. - -### Controlling Window Style (Windows) - -As Windows currently does not have much in the way of controlling the style of the -titlebar, a new option will be added to the `WebviewWindowOptions` option struct: - -```go - ExStyle int -``` - -If this is set, then the new Window will use the style specified in the `ExStyle` field. - -Example: -```go -package main - -import ( - "github.com/wailsapp/wails/v3/pkg/application" - "github.com/wailsapp/wails/v3/pkg/w32" -) - -func main() { - app := application.New(application.Options{ - Name: "My Application", - }) - - app.NewWebviewWindowWithOptions(application.WebviewWindowOptions{ - Windows: application.WindowsWindow{ - ExStyle: w32.WS_EX_TOOLWINDOW | w32.WS_EX_NOREDIRECTIONBITMAP | w32.WS_EX_TOPMOST, - }, - }) - - app.Run() -} -``` - -## Pros/Cons - -### Pros - -- We bring much needed customisation capabilities to both macOS and Windows - -### Cons - -- Windows works slightly different to macOS -- No Linux support (doesn't look like it's possible regardless of the solution) - -## Alternatives Considered - -The alternative is to draw your own titlebar, but this is a lot of work and often doesn't look good. - -## Backwards Compatibility - -This is not backwards compatible as we remove the old "disable button" options. - -## Test Plan - -As part of the implementation, the window example will be updated to test the functionality. - -## Reference Implementation - -There is a reference implementation as part of this proposal. - -## Maintenance Plan - -This feature will be maintained and supported by the Wails developers. - -## Conclusion - -This API would be a leap forward in giving developers greater control over their application window appearances. - diff --git a/website/blog/2025-03-16-security-incident-response.mdx b/website/blog/2025-03-16-security-incident-response.mdx new file mode 100644 index 000000000..e9903c570 --- /dev/null +++ b/website/blog/2025-03-16-security-incident-response.mdx @@ -0,0 +1,89 @@ +--- +slug: security-incident-response-march-2025 +title: Proactive Security Response - GitHub Actions Supply Chain Attack +authors: [leaanthony] +tags: [wails, security] +--- + +<div class="text--center"> + <img + src={require("@site/static/img/blog/shield.png").default} + width="150" + alt="Security Shield" + /> +</div> +<br /> + +:::note TL;DR +**Good news! Wails was NOT affected by this security incident.** Our thorough investigation confirmed that no secrets were leaked, and the Wails codebase and releases remain completely secure. We've already taken proactive measures to further strengthen our security posture. +::: + +## Introduction + +On 15th March 2025 (AEST), the Wails team was alerted to a security incident involving the `tj-actions/changed-files` GitHub Action. This widely-used action (with over 23,000 repositories depending on it) was compromised in a supply chain attack. While this action was used in some of our CI/CD workflows, we're pleased to confirm that Wails remained fully protected throughout. + +This post shares the details of the incident, our response, and the additional safeguards we've implemented to ensure the continued security of the Wails project. + +## Incident Details + +The security company StepSecurity [reported](https://www.stepsecurity.io/blog/harden-runner-detection-tj-actions-changed-files-action-is-compromised) that the `tj-actions/changed-files` GitHub Action was compromised beginning around 9:00 AM March 14th, 2025 Pacific Time (4:00 PM UTC). + +In this attack, malicious code was injected into the action that attempted to dump CI/CD secrets from GitHub Actions runner processes into public logs. The attackers modified the action's code and retroactively updated multiple version tags to reference the malicious commit. + +## Our Proactive Assessment + +Upon learning this, we immediately launched a comprehensive assessment of our systems: + +1. We identified the following Wails workflows that were using the action: + - For Wails v2: `pr-v2.yml` and `upload-source-documents.yml` + - For Wails v3: `pr-v3.yml`, `publish-npm.yml`, and `upload-source-documents.yml` + +2. Our security team conducted a thorough review of all workflow logs for the affected actions during the time period of the compromise. + +3. We're happy to confirm that **no secrets were leaked** in any of our workflow logs, and the Wails codebase remained completely secure. + +## Action Taken + +We took immediate steps to address this situation: + +1. We swiftly replaced all instances of the affected `tj-actions/changed-files` action with the secure alternative `step-security/changed-files` provided by StepSecurity. + +2. As an extra precautionary measure, we temporarily removed all secrets from our GitHub Actions workflows. + +## What This Means for You + +We want to reassure our community that: + +1. The Wails codebase was never compromised in any way. +2. No malicious code was introduced into any Wails releases. +3. This situation only potentially affected our CI/CD pipeline, not the actual Wails source code or releases. +4. No sensitive information or secrets were exposed during this time. + +**In short: All Wails releases remain secure and trustworthy, and no action is required on your part.** + +## Strengthening Our Security Posture + +To minimise exposure to similar potential incidents in the future, we're enhancing our security practices by: + +1. Implementing stricter version pinning for all third-party actions used in our workflows, preferably pinning to specific commit hashes rather than version tags. + +2. Establishing a regular security review process for our CI/CD pipelines and dependencies. + +3. Exploring the use of additional security tools like StepSecurity's Harden-Runner to provide enhanced protection for our GitHub Actions workflows. + +4. Developing a more comprehensive security incident response plan to ensure we can respond quickly and effectively to any future security concerns. + +It's worth noting that the Wails project already employs several security tools as part of our development process: + +- **Semgrep**: We use Semgrep for static code analysis to identify potential security vulnerabilities and code quality issues. +- **Snyk**: We employ Snyk to continuously monitor our dependencies for known vulnerabilities and receive alerts when security patches are needed. + +These existing security measures, combined with our enhanced preventative steps, demonstrate our ongoing commitment to maintaining the security and integrity of the Wails project. + +## Moving Forward + +The security of the Wails project and the trust of our community are our highest priorities. We remain committed to transparency and will continue to promptly address any security concerns that arise. + +We would like to thank StepSecurity for their quick response in identifying this issue and providing a secure alternative action. + +If you have any questions or concerns about this, please don't hesitate to reach out to us on [GitHub](https://github.com/wailsapp/wails) or [Discord](https://discord.gg/JDdSxwjhGf). We're always here to help. diff --git a/website/bun.lockb b/website/bun.lockb new file mode 100644 index 000000000..63ed1b159 Binary files /dev/null and b/website/bun.lockb differ diff --git a/website/docs/community/showcase/clustta.mdx b/website/docs/community/showcase/clustta.mdx new file mode 100644 index 000000000..7da3195df --- /dev/null +++ b/website/docs/community/showcase/clustta.mdx @@ -0,0 +1,27 @@ +--- +title: Clustta +description: File manager and project management tool for creative professionals. +slug: /community/showcase/clustta +image: /img/showcase/clustta.png +--- + +<div className="text--center"> + <img src="/img/showcase/clustta.png" alt="Clustta screenshot" loading="lazy" /> +</div> + +[Clustta](https://clustta.com) is a file manager and project management tool designed for creative professionals. Built with Wails, it simplifies file management, collaboration, and version control for creative workflows. + +## Features + +- **File Management**: Track all projects and files with easy access even months after completion. +- **Version Control**: Save unlimited revisions with descriptive notes, without duplicating files. +- **Collaboration**: Share files or entire projects securely through simple user tags with fine-grained permissions. +- **Recovery**: Restore corrupted files from saved checkpoints if your software crashes. +- **Templates**: Quick start with preset project and task templates. +- **Kanban Boards**: Visual task tracking to keep tasks organized. +- **Dependencies**: Track and version project resources and dependencies. +- **Checkpoints**: Create memorable milestones and explore alternate creative directions non-destructively. +- **Search & Filters**: Powerful instant search with metadata filtering (task types, tags, status, file extensions). +- **Workspaces**: Save search and filter combinations for easy access to specific task sets. +- **Integrations**: Connect with creative software packages and production management tools like Blender and Kitsu. +- **Self-Hosting**: Host private instances for teams or studios on your own servers. diff --git a/website/docs/community/showcase/gamestacker.mdx b/website/docs/community/showcase/gamestacker.mdx new file mode 100644 index 000000000..46245e146 --- /dev/null +++ b/website/docs/community/showcase/gamestacker.mdx @@ -0,0 +1,19 @@ +--- +title: GameStacker +description: A modern, console-like interface that unifies your game libraries. +slug: /community/showcase/gamestacker +image: /img/showcase/gamestacker.webp +--- + +<div className="text--center"> + <img src="/img/showcase/gamestacker.webp" alt="GameStacker main dashboard" loading="lazy" /> +</div> + +[GameStacker](https://gamestacker.io) is a modern, elegant console-like interface that unifies your entire game collection into one beautiful dashboard. + +## Features + +- **Unified Library**: Automatically detects and imports games from external libraries (such as Steam, LaunchBox, and RetroBat), bringing your modern and retro collections into a single, cohesive interface. +- **True Console Experience**: Built for controllers with responsive navigation, UI sound effects, and a dedicated in-game "Guide" overlay to control music and manage your session without alt-tabbing. +- **Achievement Integration**: Tracks your progress across supported services, allowing you to view unlocks and Gamerscore directly from the dashboard. +- **Multi-Profile Support**: Create unique profiles with custom avatars and specific color themes for a personalized experience. diff --git a/website/docs/community/showcase/grpcmd-gui.mdx b/website/docs/community/showcase/grpcmd-gui.mdx new file mode 100644 index 000000000..891350290 --- /dev/null +++ b/website/docs/community/showcase/grpcmd-gui.mdx @@ -0,0 +1,10 @@ +# grpcmd-gui + +```mdx-code-block +<p style={{ "text-align": "center" }}> + <img src={require("@site/static/img/showcase/grpcmd-gui.webp").default} /> + <br /> +</p> +``` + +[grpcmd-gui](https://grpc.md/gui) is a modern cross-platform desktop app and API client for gRPC development and testing. diff --git a/website/docs/community/showcase/kafka-king.mdx b/website/docs/community/showcase/kafka-king.mdx new file mode 100644 index 000000000..0ba78a6ad --- /dev/null +++ b/website/docs/community/showcase/kafka-king.mdx @@ -0,0 +1,22 @@ +# Kafka-King + +```mdx-code-block +<p style={{ "text-align": "center" }}> + <img src={require("@site/static/img/showcase/kafka-King-img_3.webp").default} /> + <br /> +</p> +``` + +[Kafka-King](https://github.com/Bronya0/Kafka-King) is a kafka GUI client that supports various systems and is compact and easy to use. +This is made of Wails+vue3 + +# Kafka-King function list +- [x] View the cluster node list, support dynamic configuration of broker and topic configuration items +- [x] Supports consumer clients, consumes the specified topic, size, and timeout according to the specified group, and displays the message information in various dimensions in a table +- [x] Supports PLAIN, SSL, SASL, kerberos, sasl_plaintext, etc. etc. +- [x] Create topics (support batches), delete topics, specify replicas, partitions +- [x] Support statistics of the total number of messages, total number of submissions, and backlog for each topic based on consumer groups +- [x] Support viewing topics Detailed information (offset) of the partition, and support adding additional partitions +- [x] Support simulated producers, batch sending messages, specify headers, partitions +- [x] Health check +- [x] Support viewing consumer groups , Consumer- …… diff --git a/website/docs/community/showcase/marasi.mdx b/website/docs/community/showcase/marasi.mdx new file mode 100644 index 000000000..5ff137523 --- /dev/null +++ b/website/docs/community/showcase/marasi.mdx @@ -0,0 +1,22 @@ +# Marasi + +```mdx-code-block +<p style={{ "text-align": "center" }}> + <img src={require("@site/static/img/showcase/marasi.webp").default} /> + <br /> +</p> +``` + +[Marasi](https://marasi.app/) is an open source application security testing proxy, it lets you intercept, inspect, modify, and extend requests as they flow through your applications. Read more about it on the [blog](https://marasi.app/blog/2025/introducing_marasi/). + +## Features + +- Desktop GUI Interface: Cross-platform desktop application built with Wails +- HTTP/HTTPS Proxy: TLS-capable proxy server with certificate management +- Request/Response Interception: Modify traffic in real-time with an intuitive interface +- Lua Extensions: Scriptable proxy behavior with built-in extensions +- Project Management: SQLite-based storage for all proxy data (requests, responses, metadata) +- Launchpad: Replay and modify HTTP requests +- Scope Management: Filter traffic with inclusion/exclusion rules +- Waypoints: Override hostnames for request routing +- Chrome Integration: Auto-configure Chrome with proxy settings \ No newline at end of file diff --git a/website/docs/community/showcase/minesweeper-xp.mdx b/website/docs/community/showcase/minesweeper-xp.mdx new file mode 100644 index 000000000..f127a005f --- /dev/null +++ b/website/docs/community/showcase/minesweeper-xp.mdx @@ -0,0 +1,10 @@ +# Minesweeper XP + +```mdx-code-block +<p style={{ "text-align": "center" }}> + <img src={require("@site/static/img/showcase/minesweeper-xp.webp").default} /> + <br /> +</p> +``` + +[Minesweeper-XP](https://git.new/Minesweeper-XP) allows you to experience the classic Minesweeper XP (+ 98 and 3.1) on macOS, Windows, and Linux! diff --git a/website/docs/community/showcase/resizem.mdx b/website/docs/community/showcase/resizem.mdx new file mode 100644 index 000000000..27f168f48 --- /dev/null +++ b/website/docs/community/showcase/resizem.mdx @@ -0,0 +1,10 @@ +# Resizem + +```mdx-code-block +<p style={{ "text-align": "center" }}> + <img src={require("@site/static/img/showcase/resizem.webp").default} /> + <br /> +</p> +``` + +[Resizem](https://github.com/barats/resizem) - is an app designed for bulk image process. It is particularly useful for users who need to resize, convert, and manage large numbers of image files at once. diff --git a/website/docs/community/showcase/upbeat.mdx b/website/docs/community/showcase/upbeat.mdx new file mode 100644 index 000000000..2f85b6cce --- /dev/null +++ b/website/docs/community/showcase/upbeat.mdx @@ -0,0 +1,18 @@ +--- +title: UpBeat +description: An RSS/Atom Feed Reader that filters out negative news with locally run ML models. +slug: /community/showcase/upbeat +image: /img/showcase/upbeat.png +--- + +<div className="text--center"> + <img src="/img/showcase/upbeat.png" alt="UpBeat screenshot" loading="lazy" /> +</div> + +[UpBeat](https://upbeat.mitchelltechnologies.co.uk) is An RSS/Atom Feed Reader for macOS that filters out negative news with locally running ML models. + +## Features + +- **Local ML**: UpBeat runs a transformer-based sentiment analysis model directly on your Mac's hardware. No waiting for a Cloud GPU to spin up before you can decide what you want to read +- **Apple Neural Engine Enabled**: UpBeat runs its ML models directly on the Neural Engine of Macs. That means you get super-fast inference, but without burning through your battery or electricity bill. +- **Widely Compatible**: Works with the vast majority of RSS + Atom versions. diff --git a/website/docs/community/showcase/wailsterm.mdx b/website/docs/community/showcase/wailsterm.mdx new file mode 100644 index 000000000..9924dace5 --- /dev/null +++ b/website/docs/community/showcase/wailsterm.mdx @@ -0,0 +1,10 @@ +# WailsTerm + +```mdx-code-block +<p style={{ "text-align": "center" }}> + <img src={require("@site/static/img/showcase/wailsterm.webp").default} /> + <br /> +</p> +``` + +[WailsTerm](https://github.com/rlshukhov/wailsterm) is a simple translucent terminal app powered by Wails and Xterm.js. diff --git a/website/docs/community/templates.mdx b/website/docs/community/templates.mdx index 446896849..3b020b60b 100644 --- a/website/docs/community/templates.mdx +++ b/website/docs/community/templates.mdx @@ -27,6 +27,8 @@ If you are unsure about a template, inspect `package.json` and `wails.json` for - [wails-template-quasar-js](https://github.com/sgosiaco/wails-template-quasar-js) - A template using JavaScript + Quasar V2 (Vue 3, Vite, Sass, Pinia, ESLint, Prettier) - [wails-template-quasar-ts](https://github.com/sgosiaco/wails-template-quasar-ts) - A template using TypeScript + Quasar V2 (Vue 3, Vite, Sass, Pinia, ESLint, Prettier, Composition API with <script setup>) - [wails-template-naive](https://github.com/tk103331/wails-template-naive) - Wails template based on Naive UI (A Vue 3 Component Library) +- [wails-template-primevue-sakai](https://github.com/TekWizely/wails-template-primevue-sakai) - Wails starter using [PrimeVue's Sakai Application Template](https://sakai.primevue.org) (Vite, Vue, PrimeVue, TailwindCSS, Vue Router, Themes, Dark Mode, UI Components, and more) +- [wails-template-tdesign-js](https://github.com/tongque0/wails-template-tdesign-js) - Wails template based on TDesign UI (a Vue 3 UI library by Tencent), using Vite, Pinia, Vue Router, ESLint, and Prettier. ## Angular @@ -40,15 +42,20 @@ If you are unsure about a template, inspect `package.json` and `wails.json` for - [wails-template-nextjs](https://github.com/LGiki/wails-template-nextjs) - A template using Next.js and TypeScript - [wails-template-nextjs-app-router](https://github.com/thisisvk-in/wails-template-nextjs-app-router) - A template using Next.js and TypeScript with App router - [wails-vite-react-ts-tailwind-template](https://github.com/hotafrika/wails-vite-react-ts-tailwind-template) - A template for React + TypeScript + Vite + TailwindCSS +- [Wails-vite-ts-tailwindcss-shadcn-template-2025](https://github.com/darkb0ts/Wails-vite-ts-tailwindcss-shadcn-template-2025) - A template for React + TypeScript + Vite - [wails-vite-react-ts-tailwind-shadcnui-template](https://github.com/Mahcks/wails-vite-react-tailwind-shadcnui-ts) - A template with Vite, React, TypeScript, TailwindCSS, and shadcn/ui +- [wails-nextjs-tailwind-template](https://github.com/kairo913/wails-nextjs-tailwind-template) - A template using Next.js and Typescript with TailwindCSS ## Svelte - [wails-svelte-template](https://github.com/raitonoberu/wails-svelte-template) - A template using Svelte - [wails-vite-svelte-template](https://github.com/BillBuilt/wails-vite-svelte-template) - A template using Svelte and Vite +- [wails-vite-svelte-ts-tailwind-template](https://github.com/xvertile/wails-vite-svelte-tailwind-template) - A template using Wails, Svelte, Vite, TypeScript, and TailwindCSS v3 - [wails-vite-svelte-tailwind-template](https://github.com/BillBuilt/wails-vite-svelte-tailwind-template) - A template using Svelte and Vite with TailwindCSS v3 - [wails-svelte-tailwind-vite-template](https://github.com/PylotLight/wails-vite-svelte-tailwind-template/tree/master) - An updated template using Svelte v4.2.0 and Vite with TailwindCSS v3.3.3 - [wails-sveltekit-template](https://github.com/h8gi/wails-sveltekit-template) - A template using SvelteKit +- [wails-template-sveltekit-less-prettier-eslint](https://github.com/Alex6357/wails-template-sveltekit-less-prettier-eslint) - A template using SvelteKit with less, Prettier and ESlint +- [wails-template-svelte-ts-less-prettier-eslint-vite](https://github.com/Alex6357/wails-template-svelte-ts-less-prettier-eslint-vite) - A template using Svelte5 + TypeScript + less + Prettier + ESlint + Vite ## Solid @@ -62,6 +69,7 @@ If you are unsure about a template, inspect `package.json` and `wails.json` for ## HTMX +- [wails-htmx-tailwind-daisyui-template](https://github.com/ltcovalt/wails-htmx-tailwind-daisyui-template) - HTMX template using Tailwind CSS + daisyUI for styling and the Go standard library for routing and HTML templating - [wails-htmx-templ-chi-tailwind](https://github.com/PylotLight/wails-hmtx-templ-template) - Use a unique combination of pure htmx for interactivity plus templ for creating components and forms ## Pure JavaScript (Vanilla) diff --git a/website/docs/gettingstarted/firstproject.mdx b/website/docs/gettingstarted/firstproject.mdx index 05f98c2d3..5cf4dff58 100644 --- a/website/docs/gettingstarted/firstproject.mdx +++ b/website/docs/gettingstarted/firstproject.mdx @@ -8,10 +8,6 @@ sidebar_position: 2 Now that the CLI is installed, you can generate a new project by using the `wails init` command. -:::tip[Performance Tip for Windows 11 Users] -Consider using [Dev Drive](https://learn.microsoft.com/en-us/windows/dev-drive/) to store your projects. Dev Drives are optimized for developer workloads and can significantly improve build times and disk access speeds by up to 30% compared to regular NTFS drives. -::: - Pick your favourite framework: ```mdx-code-block @@ -132,5 +128,3 @@ The `frontend` directory has nothing specific to Wails and can be any frontend p The `build` directory is used during the build process. These files may be updated to customise your builds. If files are removed from the build directory, default versions will be regenerated. - -The default module name in `go.mod` is "changeme". You should change this to something more appropriate. diff --git a/website/docs/gettingstarted/installation.mdx b/website/docs/gettingstarted/installation.mdx index 2fa095904..6189c6d83 100644 --- a/website/docs/gettingstarted/installation.mdx +++ b/website/docs/gettingstarted/installation.mdx @@ -7,7 +7,7 @@ sidebar_position: 1 ## Supported Platforms - Windows 10/11 AMD64/ARM64 -- MacOS 10.13+ AMD64 +- MacOS 10.15+ AMD64 for development, MacOS 10.13+ for release - MacOS 11.0+ ARM64 - Linux AMD64/ARM64 @@ -15,7 +15,7 @@ sidebar_position: 1 Wails has a number of common dependencies that are required before installation: -- Go 1.20+ +- Go 1.21+ (macOS 15+ requires Go 1.23.3+) - NPM (Node 15+) ### Go @@ -55,11 +55,17 @@ import TabItem from "@theme/TabItem"; </TabItem> <TabItem value="Windows"> Wails requires that the <a href="https://developer.microsoft.com/en-us/microsoft-edge/webview2/">WebView2</a> runtime is installed. Some Windows installations will already have this installed. You can check using the <code>wails doctor</code> command. - <br/><br/> - <strong>Performance Tip:</strong> For Windows 11 users, consider using <a href="https://learn.microsoft.com/en-us/windows/dev-drive/">Dev Drive</a> to store your projects. Dev Drives are optimized for developer workloads and can significantly improve build times and disk access speeds by up to 30% compared to regular NTFS drives. </TabItem> <TabItem value={"Linux"}> Linux requires the standard <code>gcc</code> build tools plus <code>libgtk3</code> and <code>libwebkit</code>. Rather than list a ton of commands for different distros, Wails can try to determine what the installation commands are for your specific distribution. Run <code>wails doctor</code> after installation to be shown how to install the dependencies. If your distro/package manager is not supported, please consult the <a href={"/docs/guides/linux-distro-support"}>Add Linux Distro</a> guide. + <br/><strong>Note:</strong><br/> + If you are using latest Linux version (example: Ubuntu 24.04) and it is not supporting <code>libwebkit2gtk-4.0-dev</code>, then you might encounter an issue in <code>wails doctor</code>: <code>libwebkit</code> not found. To resolve this issue you can install <code>libwebkit2gtk-4.1-dev</code> and during your build use the tag <code>-tags webkit2_41</code>. + <br/><br/> + After installing Wails via Go, ensure you run the following commands to update your PATH: + <br/> + <code>export PATH=$PATH:$(go env GOPATH)/bin</code> + <br/> + <code>source ~/.bashrc</code> or <code>source ~/.zshrc</code> </TabItem> </Tabs> ``` @@ -78,7 +84,9 @@ Note: If you get an error similar to this: ```shell ....\Go\pkg\mod\github.com\wailsapp\wails\v2@v2.1.0\pkg\templates\templates.go:28:12: pattern all:ides/*: no matching files found ``` + please check you have Go 1.18+ installed: + ```shell go version ``` diff --git a/website/docs/guides/application-development.mdx b/website/docs/guides/application-development.mdx index 78a6df3bc..adefa4b04 100644 --- a/website/docs/guides/application-development.mdx +++ b/website/docs/guides/application-development.mdx @@ -10,6 +10,10 @@ The pattern used by the default templates are that `main.go` is used for configu The `app.go` file will define a struct that has 2 methods which act as hooks into the main application: ```go title="app.go" +import ( + "context" +) + type App struct { ctx context.Context } @@ -28,7 +32,7 @@ func (a *App) shutdown(ctx context.Context) { - The startup method is called as soon as Wails allocates the resources it needs and is a good place for creating resources, setting up event listeners and anything else the application needs at startup. - It is given a `context.Context` which is usually saved in a struct field. This context is needed for calling the + It is given a [`context.Context`](https://pkg.go.dev/context) which is usually saved in a struct field. This context is needed for calling the [runtime](../reference/runtime/intro.mdx). If this method returns an error, the application will terminate. In dev mode, the error will be output to the console. @@ -55,7 +59,6 @@ func main() { log.Fatal(err) } } - ``` More information on application lifecycle hooks can be found [here](../howdoesitwork.mdx#application-lifecycle-callbacks). @@ -65,7 +68,12 @@ More information on application lifecycle hooks can be found [here](../howdoesit It is likely that you will want to call Go methods from the frontend. This is normally done by adding public methods to the already defined struct in `app.go`: -```go {16-18} title="app.go" +```go {3,21-23} title="app.go" +import ( + "context" + "fmt" +) + type App struct { ctx context.Context } @@ -82,7 +90,7 @@ func (a *App) shutdown(ctx context.Context) { } func (a *App) Greet(name string) string { - return fmt.Sprintf("Hello %s!", name) + return fmt.Sprintf("Hello %s!", name) } ``` @@ -99,15 +107,14 @@ func main() { Height: 600, OnStartup: app.startup, OnShutdown: app.shutdown, - Bind: []interface{}{ - app, - }, + Bind: []interface{}{ + app, + }, }) if err != nil { log.Fatal(err) } } - ``` This will bind all public methods in our `App` struct (it will never bind the startup and shutdown methods). @@ -133,10 +140,10 @@ func main() { otherStruct.SetContext(ctx) }, OnShutdown: app.shutdown, - Bind: []interface{}{ - app, + Bind: []interface{}{ + app, otherStruct - }, + }, }) if err != nil { log.Fatal(err) @@ -187,18 +194,17 @@ func main() { Height: 600, OnStartup: app.startup, OnShutdown: app.shutdown, - Bind: []interface{}{ - app, - }, - EnumBind: []interface{}{ - AllWeekdays, - }, + Bind: []interface{}{ + app, + }, + EnumBind: []interface{}{ + AllWeekdays, + }, }) if err != nil { log.Fatal(err) } } - ``` This will add missing enums to your `model.ts` file. @@ -223,15 +229,14 @@ func main() { OnStartup: app.startup, OnShutdown: app.shutdown, Menu: app.menu(), - Bind: []interface{}{ - app, - }, + Bind: []interface{}{ + app, + }, }) if err != nil { log.Fatal(err) } } - ``` ## Assets @@ -258,7 +263,7 @@ create files on the fly or process POST/PUT requests. GET requests are always first handled by the `assets` FS. If the FS doesn't find the requested file the request will be forwarded to the `http.Handler` for serving. Any requests other than GET will be directly processed by the `AssetsHandler` if specified. -It's also possible to only use the `AssetsHandler` by specifiy `nil` as the `Assets` option. +It's also possible to only use the `AssetsHandler` by specifying `nil` as the `Assets` option. ## Built in Dev Server diff --git a/website/docs/guides/crossplatform-build.mdx b/website/docs/guides/crossplatform-build.mdx index a9afc6161..f6fbc0f06 100644 --- a/website/docs/guides/crossplatform-build.mdx +++ b/website/docs/guides/crossplatform-build.mdx @@ -60,6 +60,6 @@ jobs: This example offers opportunities for various enhancements, including: - Caching dependencies - Code signing -- Uploading to platforms like S3, Supbase, etc. +- Uploading to platforms like S3, Supabase, etc. - Injecting secrets as environment variables - Utilizing environment variables as build variables (such as version variable extracted from the current Git tag) diff --git a/website/docs/guides/custom-protocol-schemes.mdx b/website/docs/guides/custom-protocol-schemes.mdx index c56634f0e..216fb7100 100644 --- a/website/docs/guides/custom-protocol-schemes.mdx +++ b/website/docs/guides/custom-protocol-schemes.mdx @@ -59,6 +59,24 @@ func main() { } ``` +If you want to handle universal links as well, follow this [guide](https://developer.apple.com/documentation/xcode/supporting-universal-links-in-your-app) to add required entitlements, add required keys to Info.plist and configure `apple-app-site-association` on your website. + +Here is example for Info.plist: +```xml +<key>NSUserActivityTypes</key> +<array> + <string>NSUserActivityTypeBrowsingWeb</string> +</array> +``` + +And for entitlements.plist +```xml +<key>com.apple.developer.associated-domains</key> +<array> + <string>applinks:myawesomeapp.com</string> +</array> +``` + ### Windows On Windows Custom Protocol Schemes is supported only with NSIS installer. During installation, the installer will create a diff --git a/website/docs/guides/frontend.mdx b/website/docs/guides/frontend.mdx index 1384087da..2c3c78e42 100644 --- a/website/docs/guides/frontend.mdx +++ b/website/docs/guides/frontend.mdx @@ -45,7 +45,7 @@ The options are as follows: | noautoinjectipc | Disable the autoinjection of `/wails/ipc.js` | | noautoinject | Disable all autoinjection of scripts | -Multiple options may be used provided they are comma seperated. +Multiple options may be used provided they are comma separated. This code is perfectly valid and operates the same as the autoinjection version: diff --git a/website/docs/guides/linux-distro-support.mdx b/website/docs/guides/linux-distro-support.mdx index 3cf73a7ae..b64ed0c03 100644 --- a/website/docs/guides/linux-distro-support.mdx +++ b/website/docs/guides/linux-distro-support.mdx @@ -108,86 +108,3 @@ Take a look at the other package managers code to get an idea how this works. If you add support for a new package manager, don't forget to also update this page! ::: - -## Runtime Dependencies - -When distributing your Wails application, end users need the GTK3 and WebKit2GTK runtime libraries installed. -The package names vary by distribution: - -| Distribution | GTK3 | WebKit2GTK | ABI | Installation Command | -|--------------|------|------------|-----|---------------------| -| Debian 12 / Ubuntu 22.04+ | libgtk-3-0 | libwebkit2gtk-4.1-0 | 4.1 | `apt install libgtk-3-0 libwebkit2gtk-4.1-0` | -| Debian 11 / Ubuntu 20.04 | libgtk-3-0 | libwebkit2gtk-4.0-37 | 4.0 | `apt install libgtk-3-0 libwebkit2gtk-4.0-37` | -| Fedora 40+ | gtk3 | webkit2gtk4.1 | 4.1 | `dnf install gtk3 webkit2gtk4.1` | -| RHEL / CentOS / AlmaLinux / Rocky 8-9 | gtk3 | webkit2gtk3 | 4.0 | `dnf install gtk3 webkit2gtk3` | -| openSUSE Leap / Tumbleweed | libgtk-3-0 | libwebkit2gtk-4_1-0 | 4.1 | `zypper install libgtk-3-0 libwebkit2gtk-4_1-0` | -| Arch Linux / Manjaro | gtk3 | webkit2gtk-4.1 | 4.1 | `pacman -S gtk3 webkit2gtk-4.1` | - -### WebKit2GTK ABI Versions - -WebKit2GTK has two ABI versions: -- **ABI 4.1** - Modern version, used by most current distributions -- **ABI 4.0** - Legacy version, required for older distributions (Debian 11, Ubuntu 20.04, RHEL/CentOS 8-9) - -When building your application, use the appropriate build tag: -- `-tags webkit2_41` for distributions with ABI 4.1 (default for most modern distros) -- `-tags webkit2_40` for RHEL-based systems and older Debian/Ubuntu - -### Notes - -- openSUSE provides both WebKitGTK 4.0 and 4.1; use `libwebkit2gtk-4_1-0` for the modern ABI -- Fedora only has `webkit2gtk4.1` starting from version 40; earlier versions use 4.0 -- On RHEL/AlmaLinux/Rocky/CentOS 8-9, `webkit2gtk3` corresponds to ABI 4.0; 4.1 is not available -- Arch Linux offers both `webkit2gtk` (4.0) and `webkit2gtk-4.1`; use the latter for modern ABI - -## Packaging with nfpm - -When creating Linux packages with [nfpm](https://nfpm.goreleaser.com/), you need to specify the correct dependencies for each distribution. - -### For Debian 12 / Ubuntu 22.04+ / openSUSE / Arch Linux (ABI 4.1) - -```yaml -depends: - - libgtk-3-0 - - libwebkit2gtk-4.1-0 -overrides: - rpm: - depends: - - libgtk-3-0 - - libwebkit2gtk-4_1-0 - archlinux: - depends: - - gtk3 - - webkit2gtk-4.1 -``` - -### For RHEL / CentOS / AlmaLinux / Rocky and older Debian/Ubuntu (ABI 4.0) - -```yaml -depends: - - gtk3 - - webkit2gtk3 -overrides: - deb: - depends: - - libgtk-3-0 - - libwebkit2gtk-4.0-37 - archlinux: - depends: - - gtk3 - - webkit2gtk -``` - -### For Fedora 40+ - -```yaml -depends: - - gtk3 - - webkit2gtk4.1 -``` - -:::tip - -To support multiple distributions, you may need separate nfpm configuration files for different ABI versions. - -::: diff --git a/website/docs/guides/linux.mdx b/website/docs/guides/linux.mdx index 1b55297b5..2cfc2e62a 100644 --- a/website/docs/guides/linux.mdx +++ b/website/docs/guides/linux.mdx @@ -70,3 +70,57 @@ If the added package does not resolve the issue, additional GStreamer dependenci - This issue impacts [Tauri apps](https://tauri.app/). Source: [developomp](https://github.com/developomp) on the [Tauri discussion board](https://github.com/tauri-apps/tauri/issues/4642#issuecomment-1643229562). + +## Panic Recovery / Signal Handling Issues + +### App crashes with "non-Go code set up signal handler without SA_ONSTACK flag" + +On Linux, if your application crashes with an error like: + +``` +signal 11 received but handler not on signal stack +fatal error: non-Go code set up signal handler without SA_ONSTACK flag +``` + +This occurs because WebKit (used for the webview) installs signal handlers that interfere with Go's panic recovery mechanism. +Normally, Go can convert signals like SIGSEGV (from nil pointer dereferences) into recoverable panics, but WebKit's signal +handlers prevent this. + +### Solution + +Use the `runtime.ResetSignalHandlers()` function immediately before code that might panic: + +```go +import "github.com/wailsapp/wails/v2/pkg/runtime" + +go func() { + defer func() { + if err := recover(); err != nil { + log.Printf("Recovered from panic: %v", err) + } + }() + // Reset signal handlers right before potentially dangerous code + runtime.ResetSignalHandlers() + + // Your code that might panic... +}() +``` + +:::warning Important + +- Call `ResetSignalHandlers()` in each goroutine where you need panic recovery +- Call it immediately before the code that might panic, as WebKit may reset the handlers at any time +- This is only necessary on Linux - the function is a no-op on other platforms + +::: + +### Why This Happens + +WebKit installs its own signal handlers for garbage collection and other internal processes. These handlers don't include +the `SA_ONSTACK` flag that Go requires to properly handle signals on the correct stack. When a signal like SIGSEGV occurs, +Go's runtime can't recover because the signal is being handled on the wrong stack. + +The `ResetSignalHandlers()` function adds the `SA_ONSTACK` flag to the signal handlers for SIGSEGV, SIGBUS, SIGFPE, and +SIGABRT, allowing Go's panic recovery to work correctly. + +Source: [GitHub Issue #3965](https://github.com/wailsapp/wails/issues/3965) diff --git a/website/docs/guides/mac-appstore.mdx b/website/docs/guides/mac-appstore.mdx index d2c3a9458..708528987 100644 --- a/website/docs/guides/mac-appstore.mdx +++ b/website/docs/guides/mac-appstore.mdx @@ -62,7 +62,7 @@ This is an example entitlements file from the [RiftShare](https://github.com/ach ``` **Add the Embedded Provisioning Profile** -The Provisioning Profile created above needs to be added to the root of the applicaton. It needs to be named embedded.provisionprofile. +The Provisioning Profile created above needs to be added to the root of the application. It needs to be named embedded.provisionprofile. #### Build and Sign the App Package @@ -81,9 +81,9 @@ wails build -platform darwin/universal -clean cp ./embedded.provisionprofile "./build/bin/$APP_NAME.app/Contents" -codesign --timestamp --options=runtime -s "$APP_CERTIFICATE" -v --entitlements ./build/darwin/entitlements.plist ./build/bin/$APP_NAME.app +codesign --timestamp --options=runtime -s "$APP_CERTIFICATE" -v --entitlements ./build/darwin/entitlements.plist "./build/bin/$APP_NAME.app" -productbuild --sign "$PKG_CERTIFICATE" --component ./build/bin/$APP_NAME.app /Applications ./$APP_NAME.pkg +productbuild --sign "$PKG_CERTIFICATE" --component "./build/bin/$APP_NAME.app" /Applications "./$APP_NAME.pkg" ``` #### Upload App Bundle diff --git a/website/docs/guides/mobile.mdx b/website/docs/guides/mobile.mdx deleted file mode 100644 index 630af624e..000000000 --- a/website/docs/guides/mobile.mdx +++ /dev/null @@ -1,342 +0,0 @@ -# Mobile Support - -:::danger EXPERIMENTAL -Mobile support in Wails v3 is currently **EXPERIMENTAL**. The API and build process may change significantly before the final release. Use at your own risk in production environments. -::: - -Wails v3 introduces experimental support for building native mobile applications for iOS and Android platforms. This allows you to use the same Go codebase and web frontend across desktop and mobile platforms. - -## Overview - -Mobile support enables you to build native iOS and Android applications using: -- **Go** for business logic and services -- **Web technologies** (HTML/CSS/JavaScript) for the UI -- Native WebView components for rendering - -### Architecture - -| Platform | WebView | Bridge Technology | Build Output | -|----------|---------|-------------------|--------------| -| iOS | WKWebView | CGO (C headers) | .app / .ipa | -| Android | Android WebView | JNI | .apk | - -## Prerequisites - -### iOS Development - -:::warning macOS Required -iOS development requires macOS with Xcode installed. -::: - -- **macOS** 12.0 or later -- **Xcode** 14.0 or later -- **Go** 1.21+ with CGO support -- **iOS SDK** (included with Xcode) - -### Android Development - -Android development is supported on macOS, Linux, and Windows. - -**Required Components:** -- **Go** 1.21+ with CGO support -- **Android SDK** with: - - Platform Tools (adb) - - Build Tools - - Android Emulator (optional, for testing) -- **Android NDK** r26d or later -- **Java JDK** 11+ - -### Environment Setup - -#### Android Environment Variables - -Add these to your shell profile (`~/.bashrc`, `~/.zshrc`, etc.): - -```bash -# macOS -export ANDROID_HOME="$HOME/Library/Android/sdk" - -# Linux -export ANDROID_HOME="$HOME/Android/Sdk" - -# NDK (adjust version as needed) -export ANDROID_NDK_HOME="$ANDROID_HOME/ndk/29.0.14206865" - -# Add tools to PATH -export PATH=$PATH:$ANDROID_HOME/platform-tools -export PATH=$PATH:$ANDROID_HOME/emulator -``` - -#### Installing Android SDK - -You can install the Android SDK through: -- **Android Studio** (easiest method - includes all tools) -- **Command line tools** from [developer.android.com](https://developer.android.com/studio#command-tools) - -After installing, use SDK Manager to install: -- Android SDK Platform (API 34 or later) -- Android SDK Build-Tools -- Android NDK (if not already included) - -## Building for Mobile - -### iOS Build - -```bash -# Build for iOS -task ios:build - -# Build and run on simulator -task ios:run - -# Build for device (requires code signing) -task ios:build:device -``` - -The build process will: -1. Compile Go code as a static library (`.a` file) -2. Generate Xcode project -3. Build the app using `xcodebuild` -4. Create an `.app` bundle (or `.ipa` for distribution) - -### Android Build - -```bash -# Build for Android (default: arm64 for device) -task android:build - -# Build for emulator (x86_64) -task android:build ARCH=x86_64 - -# Build for all architectures -task android:compile:go:all-archs - -# Package APK -task android:package - -# Run on emulator/device -task android:run - -# View logs -task android:logs -``` - -The build process will: -1. Compile Go code as a shared library (`.so` file) -2. Build Java/Kotlin code using Gradle -3. Package everything into an APK - -### Build Architectures - -**iOS:** -- `arm64` - iPhone 5s and later, all iPads with Apple Silicon - -**Android:** -| Architecture | Use Case | GOARCH | -|--------------|----------|---------| -| arm64-v8a | Modern devices (most common) | arm64 | -| x86_64 | Emulator | amd64 | -| armeabi-v7a | Older devices (optional) | arm | -| x86 | Older emulators (optional) | 386 | - -## Platform-Specific Configuration - -### iOS Options - -```go -app := application.New(application.Options{ - Name: "My App", - iOS: application.IOSOptions{ - // Disable bounce scroll effect - DisableBounce: true, - - // Enable zoom gestures - EnableZoom: false, - - // Custom user agent - UserAgent: "MyApp/1.0", - - // Background color - BackgroundColour: application.NewRGB(255, 255, 255), - }, -}) -``` - -### Android Options - -```go -app := application.New(application.Options{ - Name: "My App", - Android: application.AndroidOptions{ - // Disable scrolling - DisableScroll: false, - - // Disable overscroll bounce effect - DisableOverscroll: true, - - // Enable pinch-to-zoom - EnableZoom: false, - - // Custom user agent - UserAgent: "MyApp/1.0", - - // Background color - BackgroundColour: application.NewRGB(255, 255, 255), - - // Disable hardware acceleration (not recommended) - DisableHardwareAcceleration: false, - }, -}) -``` - -## Testing - -### iOS Testing - -```bash -# List available simulators -xcrun simctl list devices - -# Run on specific simulator -task ios:run SIMULATOR="iPhone 15 Pro" -``` - -### Android Testing - -```bash -# List available emulators -emulator -list-avds - -# Start emulator -emulator -avd Pixel_7_API_34 - -# Install and run -task android:run -``` - -## Platform Detection - -Your frontend JavaScript can detect the platform: - -```javascript -const platform = window.wails.System.Platform(); - -if (platform === 'ios') { - // iOS-specific code -} else if (platform === 'android') { - // Android-specific code -} else { - // Desktop code -} -``` - -## Limitations - -:::warning Current Limitations -The following features are not yet fully implemented on mobile platforms: -::: - -### iOS Limitations -- System tray/menu bar (not applicable) -- Multiple windows (single full-screen window only) -- File dialogs (limited by iOS sandboxing) -- Window manipulation (position, size, etc.) - -### Android Limitations -- System tray (not applicable) -- Multiple windows (single full-screen window only) -- File dialogs (use Storage Access Framework) -- Window manipulation (fullscreen only) -- Clipboard operations (partial support) - -## Architecture Documentation - -For detailed technical information about the mobile implementations: - -- **Android Architecture**: See [`ANDROID_ARCHITECTURE.md`](https://github.com/wailsapp/wails/blob/v3-alpha/v3/ANDROID_ARCHITECTURE.md) in the repository -- **iOS Architecture**: See [`IOS_ARCHITECTURE.md`](https://github.com/wailsapp/wails/blob/v3-alpha/v3/IOS_ARCHITECTURE.md) in the repository - -These documents provide comprehensive information about: -- Architecture and design patterns -- Build system internals -- Bridge implementations (JNI for Android, CGO for iOS) -- Asset serving mechanisms -- JavaScript bridge details -- Security considerations - -## Troubleshooting - -### iOS Issues - -**"Code signing required"** -- You need an Apple Developer account to run on physical devices -- Simulators don't require code signing - -**"Command Line Tools not found"** -```bash -# Install Xcode Command Line Tools -xcode-select --install -``` - -### Android Issues - -**"NDK not found"** -```bash -# Verify NDK installation -ls $ANDROID_HOME/ndk - -# Set NDK path explicitly -export ANDROID_NDK_HOME=$ANDROID_HOME/ndk/26.1.10909125 -``` - -**"UnsatisfiedLinkError: dlopen failed"** -- Architecture mismatch between Go library and device -- Rebuild for correct architecture (arm64 for device, x86_64 for emulator) - -**Blank WebView** -1. Enable WebView debugging (in development builds) -2. Use Chrome DevTools: `chrome://inspect/#devices` -3. Check asset serving in logcat: `task android:logs` - -### Build Issues - -**"cannot find package"** -```bash -# Clear and rebuild Go modules -go clean -modcache -go mod tidy -go mod download -``` - -**"CGO_ENABLED required"** -```bash -# Ensure CGO is enabled -export CGO_ENABLED=1 -``` - -## Examples - -Check out the example projects in the Wails repository: - -- **iOS Example**: `v3/examples/ios/` -- **Android Example**: `v3/examples/android/` - -These examples demonstrate: -- Basic app structure -- Service integration -- Event handling -- Asset serving -- Platform-specific features - -## Getting Help - -If you encounter issues with mobile support: - -1. Check the [GitHub Issues](https://github.com/wailsapp/wails/issues) for known problems -2. Review the architecture documentation linked above -3. Ask in the [Wails Discord](https://discord.gg/BrRSWTaxVK) #mobile channel -4. Report bugs with detailed logs and environment information - -:::info Feedback Welcome -Mobile support is actively being developed. Your feedback and bug reports are valuable for improving the implementation. Please share your experiences on GitHub or Discord! -::: diff --git a/website/docs/guides/nixos-font.mdx b/website/docs/guides/nixos-font.mdx index 141e4d68c..02188562e 100644 --- a/website/docs/guides/nixos-font.mdx +++ b/website/docs/guides/nixos-font.mdx @@ -1,6 +1,6 @@ # NixOS FontSize Bug -NixOS/Wayland can cause a bug where the `font-size` css property doesnt affect the rendered page. To fix this add the following to your devShell. +NixOS/Wayland can cause a bug where the `font-size` css property doesn't affect the rendered page. To fix this add the following to your devShell. ```shell shellHook = with pkgs; '' diff --git a/website/docs/guides/signing.mdx b/website/docs/guides/signing.mdx index 57b51806a..4ce5fd4b2 100644 --- a/website/docs/guides/signing.mdx +++ b/website/docs/guides/signing.mdx @@ -254,7 +254,7 @@ Now we need to configure some gon config files in our `build/darwin` directory: "bundle_id": "app.myapp", "apple_id": { "username": "my-appleid@email.com", - "password": "@env:APPLE_PASSWORD", + "password": "your-app-specific-password", "provider": "ABCDE12345" }, "sign": { @@ -268,11 +268,13 @@ Here is a brief break down of the above fields: - `source`: The location of your wails binary to be signed - `apple_id`: - `username`: Your Apple ID email address - - `password`: Your app-specific password, referenced using Gon's environment variable syntax + - `password`: Your app-specific password - `provider`: Your team ID for your App Store Connect account - `sign`: - `application_identity`: Your Apple developer identity +The (https://developer.apple.com/documentation/technotes/tn3147-migrating-to-the-latest-notarization-tool)[deprecated Apple's altool]'s syntax supporting `@env:` is no longer available since Apple has migrated to the new notarytool. + Your developer identity and team ID can both by found on macOS by running the following command: ```bash @@ -420,5 +422,3 @@ jobs: # End notes This guide inspired by the RiftShare project and its workflow, which is highly recommended to check out [here](https://github.com/achhabra2/riftshare/blob/main/.github/workflows/build.yaml). - -For another excellent guide on macOS code signing and notarization, see [Signing and Notarizing macOS Apps](https://armaan.cc/blog/signing-and-notarizing-macos) by Armaan. diff --git a/website/docs/guides/sveltekit.mdx b/website/docs/guides/sveltekit.mdx index e0357ca3c..afb67f630 100644 --- a/website/docs/guides/sveltekit.mdx +++ b/website/docs/guides/sveltekit.mdx @@ -1,7 +1,7 @@ # SvelteKit This guide will go into: -1. Miminal Installation Steps - The steps needed to get a minimum Wails setup working for SvelteKit. +1. Minimal Installation Steps - The steps needed to get a minimum Wails setup working for SvelteKit. 2. Install Script - Bash script for accomplishing the Minimal Installation Steps with optional Wails branding. 3. Important Notes - Issues that can be encountered when using SvelteKit + Wails and fixes. @@ -14,8 +14,8 @@ This guide will go into: - Navigate into your newly created myapp folder. - Delete the folder named "frontend" -##### While in the Wails project root. Use your favorite package manager and install SvelteKit as the new frontend. Follow the prompts. -- `npm create svelte@latest frontend` +##### While in the Wails project root. Use the Svelte CLI to create a SvelteKit project as the new frontend. Follow the prompts, nothing Wails specific is needed here. +- `npx sv create frontend` ##### Modify wails.json. - Add `"wailsjsdir": "./frontend/src/lib",` Do note that this is where your Go and runtime functions will appear. @@ -108,7 +108,7 @@ wails dev ``` See https://wails.io/docs/guides/frontend for more information. -##### Inital data can be loaded and refreshed from +page.ts/+page.js to +page.svelte. +##### Initial data can be loaded and refreshed from +page.ts/+page.js to +page.svelte. - +page.ts/+page.js works well with load() https://kit.svelte.dev/docs/load#page-data - invalidateAll() in +page.svelte will call load() from +page.ts/+page.js https://kit.svelte.dev/docs/load#rerunning-load-functions-manual-invalidation. diff --git a/website/docs/howdoesitwork.mdx b/website/docs/howdoesitwork.mdx index 48243f4eb..405930492 100644 --- a/website/docs/howdoesitwork.mdx +++ b/website/docs/howdoesitwork.mdx @@ -63,17 +63,17 @@ func main() { type App struct { - ctx context.Context + ctx context.Context } func (b *App) startup(ctx context.Context) { - b.ctx = ctx + b.ctx = ctx } func (b *App) shutdown(ctx context.Context) {} func (b *App) Greet(name string) string { - return fmt.Sprintf("Hello %s!", name) + return fmt.Sprintf("Hello %s!", name) } ``` @@ -178,18 +178,18 @@ func main() { type App struct { - ctx context.Context + ctx context.Context } func (a *App) Greet(name string) string { - return fmt.Sprintf("Hello %s!", name) + return fmt.Sprintf("Hello %s!", name) } ``` You may bind as many structs as you like. Just make sure you create an instance of it and pass it in `Bind`: ```go {10-12} - //... + //... err := wails.Run(&options.App{ Title: "Basic Demo", Width: 1024, @@ -203,7 +203,6 @@ You may bind as many structs as you like. Just make sure you create an instance &mystruct2{}, }, }) - ``` You may bind enums types as well. @@ -236,8 +235,8 @@ var AllWeekdays = []struct { } ``` -```go {10-12} - //... +```go {14-16} + //... err := wails.Run(&options.App{ Title: "Basic Demo", Width: 1024, @@ -250,11 +249,10 @@ var AllWeekdays = []struct { &mystruct1{}, &mystruct2{}, }, - EnumBind: []interface{}{ - AllWeekdays, - }, + EnumBind: []interface{}{ + AllWeekdays, + }, }) - ``` When you run `wails dev` (or `wails generate module`), a frontend module will be generated containing the following: diff --git a/website/docs/reference/cli.mdx b/website/docs/reference/cli.mdx index 9bb41d10c..1a85be22f 100644 --- a/website/docs/reference/cli.mdx +++ b/website/docs/reference/cli.mdx @@ -69,10 +69,11 @@ If you are unsure about a template, inspect `package.json` and `wails.json` for | -nsis | Generate NSIS installer for Windows | | | -o filename | Output filename | | | -obfuscated | Obfuscate the application using [garble](https://github.com/burrowers/garble) | | -| -platform | Build for the given (comma delimited) [platforms](../reference/cli.mdx#platforms) eg. `windows/arm64`. Note, if you do not give the architecture, `runtime.GOARCH` is used. | platform = `GOOS` environment variable if given else `runtime.GOOS`.<br/>arch = `GOARCH` envrionment variable if given else `runtime.GOARCH`. | +| -platform | Build for the given (comma delimited) [platforms](../reference/cli.mdx#platforms) eg. `windows/arm64`. Note, if you do not give the architecture, `runtime.GOARCH` is used. | platform = `GOOS` environment variable if given else `runtime.GOOS`.<br/>arch = `GOARCH` environment variable if given else `runtime.GOARCH`. | | -race | Build with Go's race detector | | | -s | Skip building the frontend | | | -skipbindings | Skip bindings generation | | +| -skipembedcreate | Skip automatic creation of non-existent embed directories and gitkeep files | | | -tags "extra tags" | Build tags to pass to Go compiler. Must be quoted. Space or comma (but not both) separated | | | -trimpath | Remove all file system paths from the resulting executable. | | | -u | Updates your project's `go.mod` to use the same version of Wails as the CLI | | @@ -103,6 +104,13 @@ There are [issues](https://github.com/upx/upx/issues/446) with using UPX with Ap ::: +:::info Set minimal version for MacOS + +You can override default [minimal version](../gettingstarted/installation#supported-platforms) of macOS for your app by providing version via `CGO_CFLAGS` and `CGO_LDFLAGS` environment variables. +e.g. `CGO_CFLAGS=-mmacosx-version-min=10.15.0 CGO_LDFLAGS=-mmacosx-version-min=10.15.0 wails build` + +::: + :::info UPX on Windows Some Antivirus vendors false positively mark `upx` compressed binaries as virus, see [issue](https://github.com/upx/upx/issues/437). @@ -186,6 +194,7 @@ Your system is ready for Wails development! | -extensions | Extensions to trigger rebuilds (comma separated) | go | | -forcebuild | Force build of application | | | -frontenddevserverurl "url" | Use 3rd party dev server url to serve assets, EG Vite | "" | +| -viteservertimeout | The timeout in seconds for Vite server detection when frontend dev server url is set to 'auto' | 10 | | -ldflags "flags" | Additional ldflags to pass to the compiler | | | -loglevel "loglevel" | Loglevel to use - Trace, Debug, Info, Warning, Error | Debug | | -nocolour | Turn off colour cli output | false | @@ -194,8 +203,9 @@ Your system is ready for Wails development! | -race | Build with Go's race detector | false | | -reloaddirs | Additional directories to trigger reloads (comma separated) | Value in `wails.json` | | -s | Skip building the frontend | false | -| -save | Saves the given `assetdir`, `reloaddirs`, `wailsjsdir`, `debounce`, `devserver` and `frontenddevserverurl` flags in `wails.json` to become the defaults for subsequent invocations. | | +| -save | Saves the given `assetdir`, `reloaddirs`, `wailsjsdir`, `debounce`, `devserver`, `frontenddevserverurl` and `viteservertimeout` flags in `wails.json` to become the defaults for subsequent invocations. | | | -skipbindings | Skip bindings generation | | +| -skipembedcreate | Skip automatic creation of non-existent embed directories and gitkeep files | | | -tags "extra tags" | Build tags to pass to compiler (quoted and space separated) | | | -v | Verbosity level (0 - silent, 1 - standard, 2 - verbose) | 1 | | -wailsjsdir | The directory to generate the generated Wails JS modules | Value in `wails.json` | diff --git a/website/docs/reference/menus.mdx b/website/docs/reference/menus.mdx index 7af0bf38f..52f399f0b 100644 --- a/website/docs/reference/menus.mdx +++ b/website/docs/reference/menus.mdx @@ -8,22 +8,41 @@ It is possible to add an application menu to Wails projects. This is achieved by setting it in the [`Menu`](../reference/options.mdx#menu) application config, or by calling the runtime method [MenuSetApplicationMenu](../reference/runtime/menu.mdx#menusetapplicationmenu). -An example of how to create a menu: +An example of how to create a menu, using [the `NewApp` scaffold](../guides/application-development.mdx): -```go +```go title="main.go" +package main +import ( + "log" + "runtime" + + "github.com/wailsapp/wails/v2" + "github.com/wailsapp/wails/v2/pkg/menu" + "github.com/wailsapp/wails/v2/pkg/menu/keys" + "github.com/wailsapp/wails/v2/pkg/options" + rt "github.com/wailsapp/wails/v2/pkg/runtime" +) + +func main() { app := NewApp() AppMenu := menu.NewMenu() + if runtime.GOOS == "darwin" { + AppMenu.Append(menu.AppMenu()) // On macOS platform, this must be done right after `NewMenu()` + } FileMenu := AppMenu.AddSubmenu("File") - FileMenu.AddText("&Open", keys.CmdOrCtrl("o"), openFile) + FileMenu.AddText("&Open", keys.CmdOrCtrl("o"), func(_ *menu.CallbackData) { + // do something + }) FileMenu.AddSeparator() FileMenu.AddText("Quit", keys.CmdOrCtrl("q"), func(_ *menu.CallbackData) { - runtime.Quit(app.ctx) + // `rt` is an alias of "github.com/wailsapp/wails/v2/pkg/runtime" to prevent collision with standard package + rt.Quit(app.ctx) }) if runtime.GOOS == "darwin" { - AppMenu.Append(menu.EditMenu()) // on macos platform, we should append EditMenu to enable Cmd+C,Cmd+V,Cmd+Z... shortcut + AppMenu.Append(menu.EditMenu()) // On macOS platform, EditMenu should be appended to enable Cmd+C, Cmd+V, Cmd+Z... shortcuts } err := wails.Run(&options.App{ @@ -34,8 +53,11 @@ An example of how to create a menu: Bind: []interface{}{ app, }, - ) - // ... + }) + if err != nil { + log.Fatal(err) + } +} ``` It is also possible to dynamically update the menu, by updating the menu struct and calling diff --git a/website/docs/reference/options.mdx b/website/docs/reference/options.mdx index a6026f126..8651a3205 100644 --- a/website/docs/reference/options.mdx +++ b/website/docs/reference/options.mdx @@ -73,8 +73,9 @@ func main() { Windows: &windows.Options{ WebviewIsTransparent: false, WindowIsTranslucent: false, + ContentProtection: false, BackdropType: windows.Mica, - DisablePinchZoom: false, + DisablePinchZoom: false, DisableWindowIcon: false, DisableFramelessWindowDecorations: false, WebviewUserDataPath: "", @@ -99,7 +100,9 @@ func main() { // OnResume is called when Windows resumes from low power mode OnResume: func(), // Disable GPU hardware acceleration for the webview - WebviewGpuDisabled: false, + WebviewGpuDisabled: false, + // Class name for the window. If empty, 'wailsWindow' will be used. + WindowClassName: "MyWindow", }, Mac: &mac.Options{ TitleBar: &mac.TitleBar{ @@ -115,6 +118,7 @@ func main() { Appearance: mac.NSAppearanceNameDarkAqua, WebviewIsTransparent: true, WindowIsTranslucent: false, + ContentProtection: false, About: &mac.AboutInfo{ Title: "My Application", Message: "© 2021 Me", @@ -130,6 +134,7 @@ func main() { Debug: options.Debug{ OpenInspectorOnStartup: false, }, + BindingsAllowedOrigins: "https://my.topapp,https://*.wails.isgreat", }) if err != nil { @@ -322,7 +327,7 @@ If not defined, the result is the following in cases where the Handler would hav :::info -This does not work with vite v5.0.0+ and wails v2 due to changes in vite. +This does not work with vite v5.0.0+ and wails v2 due to changes in vite. Changes are planned in v3 to support similar functionality under vite v5.0.0+. If you need this feature, stay with vite v4.0.0+. See [issue 3240](https://github.com/wailsapp/wails/issues/3240) for details @@ -485,21 +490,13 @@ services of Apple and Microsoft. Name: EnableFraudulentWebsiteDetection<br/> Type: `bool` -### ZoomFactor +### DisablePanicRecovery -Name: ZoomFactor<br/> -Type: `float64` +DisablePanicRecovery disables the automatic recovery from panics in message processing. By default, Wails will recover from panics in message processing and log the error. If you want to handle panics yourself, set this to `true`. -This defines the zoom factor for the WebView2. This is the option matching the Edge user activated zoom in or out. - -### IsZoomControlEnabled - -Name: IsZoomControlEnabled<br/> +Name: DisablePanicRecovery<br/> Type: `bool` -This enables the zoom factor to be changed by the user. Please note that the zoom factor can be set in the options while -disallowing the user to change it at runtime (f.e. for a kiosk application or similar). - ### Bind A slice of struct instances defining methods that need to be bound to the frontend. @@ -619,6 +616,17 @@ by Windows. To configure this, use the [BackdropType](#BackdropType) option. Name: WindowIsTranslucent<br/> Type: `bool` +#### ContentProtection + +Prevents window contents from being captured by other applications. + +On Windows it calls SetWindowDisplayAffinity with `WDA_EXCLUDEFROMCAPTURE`. +For Windows 10 version 2004 and later the window will be completely removed from capture. +Older Windows versions will call SetWindowDisplayAffinity with `WDA_MONITOR`, capturing a black window. + +Name: ContentProtection<br/> +Type: `bool` + #### BackdropType :::note @@ -642,6 +650,21 @@ The value can be one of the following: | Mica | Use [Mica](https://learn.microsoft.com/en-us/windows/apps/design/style/mica) effect | | Tabbed | Use Tabbed. This is a backdrop that is similar to Mica. | +#### ZoomFactor + +Name: ZoomFactor<br/> +Type: `float64` + +This defines the zoom factor for the WebView2. This is the option matching the Edge user activated zoom in or out. + +#### IsZoomControlEnabled + +Name: IsZoomControlEnabled<br/> +Type: `bool` + +This enables the zoom factor to be changed by the user. Please note that the zoom factor can be set in the options while +disallowing the user to change it at runtime (f.e. for a kiosk application or similar). + #### DisablePinchZoom Setting this to `true` will disable pinch zoom gestures. @@ -804,6 +827,13 @@ Setting this to `true` will enable swipe gestures for the webview. Name: EnableSwipeGestures<br/> Type: `bool` +#### WindowClassName + +Class name for the window. If empty, 'wailsWindow' will be used. + +Name: WindowClassName<br/> +Type: `string` + ### Mac This defines [Mac specific options](#mac). @@ -907,6 +937,15 @@ with [WebviewIsTransparent](#WebviewIsTransparent) to make frosty-looking applic Name: WindowIsTranslucent<br/> Type: `bool` +#### ContentProtection + +Prevents window contents from being captured by other applications. + +On MacOS it sets the NSWindow's sharingType to NSWindowSharingNone, removing the window from capture entirely. + +Name: ContentProtection<br/> +Type: `bool` + #### OnFileOpen Callback that is called when a file is opened with the application. @@ -1091,3 +1130,12 @@ Setting this to `true` will open the WebInspector on startup of the application. Name: OpenInspectorOnStartup<br/> Type: `bool` + +### BindingsAllowedOrigins + +Comma-separated list of additional allowed origins for JS ↔ Go bindings. +Supports “*” wildcards in hostnames for subdomain matching. +Example: `"https://*.myapp.com, https://example.com"` + +Name: BindingsAllowedOrigins<br/> +Type: `string`<br/> diff --git a/website/docs/reference/project-config.mdx b/website/docs/reference/project-config.mdx index 3a6f09495..a9f8785fa 100644 --- a/website/docs/reference/project-config.mdx +++ b/website/docs/reference/project-config.mdx @@ -18,6 +18,8 @@ The project config resides in the `wails.json` file in the project directory. Th "reloaddirs": "", // The directory where the build files reside. Defaults to 'build' "build:dir": "", + // Additional tags to include at build time regardless of environment + "build:tags": "", // Relative path to the frontend directory. Defaults to 'frontend' "frontend:dir": "", // The command to install node dependencies, run in the frontend directory - often `npm install` @@ -34,6 +36,8 @@ The project config resides in the `wails.json` file in the project directory. Th "frontend:dev:watcher": "", // URL to a 3rd party dev server to be used to serve assets, EG Vite. \nIf this is set to 'auto' then the devServerUrl will be inferred from the Vite output "frontend:dev:serverUrl": "", + // The timeout in seconds for Vite server detection when frontend:dev:serverUrl is set to 'auto'. Default: 10 + "viteServerTimeout": 10, // Relative path to the directory that the auto-generated JS modules will be created "wailsjsdir": "", // The name of the binary @@ -124,7 +128,7 @@ The project config resides in the `wails.json` file in the project directory. Th This file is read by the Wails CLI when running `wails build` or `wails dev`. -The `assetdir`, `reloaddirs`, `wailsjsdir`, `debounceMS`, `devserver` and `frontenddevserverurl` flags in `wails build/dev` will update the project config +The `assetdir`, `reloaddirs`, `wailsjsdir`, `debounceMS`, `devserver`, `frontenddevserverurl` and `viteservertimeout` flags in `wails build/dev` will update the project config and thus become defaults for subsequent runs. The JSON Schema for this file is located [here](https://wails.io/schemas/config.v2.json). diff --git a/website/docs/reference/runtime/events.mdx b/website/docs/reference/runtime/events.mdx index 138e03d73..909cb79e9 100644 --- a/website/docs/reference/runtime/events.mdx +++ b/website/docs/reference/runtime/events.mdx @@ -18,11 +18,18 @@ JS: `EventsOn(eventName string, callback function(optionalData?: any)): () => vo ### EventsOff -This method unregisters the listener for the given event name, optionally multiple listeneres can be unregistered via `additionalEventNames`. +This method unregisters the listener for the given event name, optionally multiple listeners can be unregistered via `additionalEventNames`. Go: `EventsOff(ctx context.Context, eventName string, additionalEventNames ...string)`<br/> JS: `EventsOff(eventName string, ...additionalEventNames)` +### EventsOffAll + +This method unregisters all event listeners. + +Go: `EventsOffAll(ctx context.Context)`<br/> +JS: `EventsOffAll()` + ### EventsOnce This method sets up a listener for the given event name, but will only trigger once. It returns a function to cancel diff --git a/website/docs/reference/runtime/intro.mdx b/website/docs/reference/runtime/intro.mdx index 3c491ecf0..d67e76c64 100644 --- a/website/docs/reference/runtime/intro.mdx +++ b/website/docs/reference/runtime/intro.mdx @@ -98,3 +98,46 @@ interface EnvironmentInfo { arch: string; } ``` + +### ResetSignalHandlers + +Resets signal handlers to allow panic recovery from nil pointer dereferences and other memory access violations. + +Go: `ResetSignalHandlers()` + +:::info Linux Only + +This function only has an effect on Linux. On macOS and Windows, it is a no-op. + +On Linux, WebKit (used for the webview) may install signal handlers without the `SA_ONSTACK` flag, which prevents +Go from properly recovering from panics caused by nil pointer dereferences (SIGSEGV) or other memory access violations. + +Call this function immediately before code that might panic to ensure the signal handlers are properly configured +for Go's panic recovery mechanism. + +::: + +#### Example + +```go +go func() { + defer func() { + if err := recover(); err != nil { + log.Printf("Recovered from panic: %v", err) + } + }() + // Reset signal handlers right before potentially dangerous code + runtime.ResetSignalHandlers() + + // Code that might cause a nil pointer dereference... + var t *time.Time + fmt.Println(t.Unix()) // This would normally crash on Linux +}() +``` + +:::warning + +This function must be called in each goroutine where you want panic recovery to work, and should be called +immediately before the code that might panic, as WebKit may reset the signal handlers at any time. + +::: diff --git a/website/docs/reference/runtime/window.mdx b/website/docs/reference/runtime/window.mdx index 625cd5e44..4e20f510e 100644 --- a/website/docs/reference/runtime/window.mdx +++ b/website/docs/reference/runtime/window.mdx @@ -235,7 +235,7 @@ JS: `WindowSetBackgroundColour(R, G, B, A)` ### WindowPrint -Opens tha native print dialog. +Opens the native print dialog. Go: `WindowPrint(ctx context.Context)`<br/> JS: `WindowPrint()` diff --git a/website/docusaurus.config.js b/website/docusaurus.config.js index 737218f07..16a289a5d 100644 --- a/website/docusaurus.config.js +++ b/website/docusaurus.config.js @@ -1,8 +1,9 @@ // @ts-check // Note: type annotations allow type checking and IDEs autocompletion -const lightCodeTheme = require("prism-react-renderer/themes/github"); -const darkCodeTheme = require("prism-react-renderer/themes/dracula"); +const { themes } = require("prism-react-renderer"); +const lightCodeTheme = themes.github; +const darkCodeTheme = themes.dracula; const { getTranslationProgress } = require("./src/api/crowdin.js"); @@ -14,28 +15,16 @@ module.exports = async function configCreatorAsync() { url: "https://wails.io", baseUrl: "/", onBrokenLinks: "warn", - onBrokenMarkdownLinks: "warn", favicon: "img/favicon.ico", organizationName: "wailsapp", projectName: "wails", - webpack: { - jsLoader: (isServer) => ({ - loader: require.resolve("swc-loader"), - options: { - jsc: { - parser: { - syntax: "typescript", - tsx: true, - }, - target: "es2017", - }, - module: { - type: isServer ? "commonjs" : "es6", - }, - }, - }), + markdown: { + hooks: { + onBrokenMarkdownLinks: "warn", + }, }, + i18n: { defaultLocale: "en", locales: ["en", "zh-Hans", "ja", "ru", "ko", "fr", "pt"], diff --git a/website/i18n/ar/docusaurus-plugin-content-docs/current/community/showcase/grpcmd-gui.mdx b/website/i18n/ar/docusaurus-plugin-content-docs/current/community/showcase/grpcmd-gui.mdx new file mode 100644 index 000000000..891350290 --- /dev/null +++ b/website/i18n/ar/docusaurus-plugin-content-docs/current/community/showcase/grpcmd-gui.mdx @@ -0,0 +1,10 @@ +# grpcmd-gui + +```mdx-code-block +<p style={{ "text-align": "center" }}> + <img src={require("@site/static/img/showcase/grpcmd-gui.webp").default} /> + <br /> +</p> +``` + +[grpcmd-gui](https://grpc.md/gui) is a modern cross-platform desktop app and API client for gRPC development and testing. diff --git a/website/i18n/ar/docusaurus-plugin-content-docs/current/community/showcase/kafka-king.mdx b/website/i18n/ar/docusaurus-plugin-content-docs/current/community/showcase/kafka-king.mdx new file mode 100644 index 000000000..9876cd9a0 --- /dev/null +++ b/website/i18n/ar/docusaurus-plugin-content-docs/current/community/showcase/kafka-king.mdx @@ -0,0 +1,23 @@ +# Kafka-King + +```mdx-code-block +<p style={{ "text-align": "center" }}> + <img src={require("@site/static/img/showcase/kafka-King-img_3.webp").default} /> + <br /> +</p> +``` + +[Kafka-King](https://github.com/Bronya0/Kafka-King) is a kafka GUI client that supports various systems and is compact and easy to use. +This is made of Wails+vue3 + +# Kafka-King function list + +- [x] View the cluster node list, support dynamic configuration of broker and topic configuration items +- [x] Supports consumer clients, consumes the specified topic, size, and timeout according to the specified group, and displays the message information in various dimensions in a table +- [x] Supports PLAIN, SSL, SASL, kerberos, sasl_plaintext, etc. etc. +- [x] Create topics (support batches), delete topics, specify replicas, partitions +- [x] Support statistics of the total number of messages, total number of submissions, and backlog for each topic based on consumer groups +- [x] Support viewing topics Detailed information (offset) of the partition, and support adding additional partitions +- [x] Support simulated producers, batch sending messages, specify headers, partitions +- [x] Health check +- [x] Support viewing consumer groups , Consumer- …… diff --git a/website/i18n/ar/docusaurus-plugin-content-docs/current/community/showcase/minesweeper-xp.mdx b/website/i18n/ar/docusaurus-plugin-content-docs/current/community/showcase/minesweeper-xp.mdx new file mode 100644 index 000000000..f127a005f --- /dev/null +++ b/website/i18n/ar/docusaurus-plugin-content-docs/current/community/showcase/minesweeper-xp.mdx @@ -0,0 +1,10 @@ +# Minesweeper XP + +```mdx-code-block +<p style={{ "text-align": "center" }}> + <img src={require("@site/static/img/showcase/minesweeper-xp.webp").default} /> + <br /> +</p> +``` + +[Minesweeper-XP](https://git.new/Minesweeper-XP) allows you to experience the classic Minesweeper XP (+ 98 and 3.1) on macOS, Windows, and Linux! diff --git a/website/i18n/ar/docusaurus-plugin-content-docs/current/community/showcase/resizem.mdx b/website/i18n/ar/docusaurus-plugin-content-docs/current/community/showcase/resizem.mdx new file mode 100644 index 000000000..27f168f48 --- /dev/null +++ b/website/i18n/ar/docusaurus-plugin-content-docs/current/community/showcase/resizem.mdx @@ -0,0 +1,10 @@ +# Resizem + +```mdx-code-block +<p style={{ "text-align": "center" }}> + <img src={require("@site/static/img/showcase/resizem.webp").default} /> + <br /> +</p> +``` + +[Resizem](https://github.com/barats/resizem) - is an app designed for bulk image process. It is particularly useful for users who need to resize, convert, and manage large numbers of image files at once. diff --git a/website/i18n/ar/docusaurus-plugin-content-docs/current/community/showcase/wailsterm.mdx b/website/i18n/ar/docusaurus-plugin-content-docs/current/community/showcase/wailsterm.mdx new file mode 100644 index 000000000..9924dace5 --- /dev/null +++ b/website/i18n/ar/docusaurus-plugin-content-docs/current/community/showcase/wailsterm.mdx @@ -0,0 +1,10 @@ +# WailsTerm + +```mdx-code-block +<p style={{ "text-align": "center" }}> + <img src={require("@site/static/img/showcase/wailsterm.webp").default} /> + <br /> +</p> +``` + +[WailsTerm](https://github.com/rlshukhov/wailsterm) is a simple translucent terminal app powered by Wails and Xterm.js. diff --git a/website/i18n/ar/docusaurus-plugin-content-docs/current/community/templates.mdx b/website/i18n/ar/docusaurus-plugin-content-docs/current/community/templates.mdx index 65f46a9e1..fb95b8ad9 100644 --- a/website/i18n/ar/docusaurus-plugin-content-docs/current/community/templates.mdx +++ b/website/i18n/ar/docusaurus-plugin-content-docs/current/community/templates.mdx @@ -26,6 +26,7 @@ If you are unsure about a template, inspect `package.json` and `wails.json` for - [wails-template-quasar-js](https://github.com/sgosiaco/wails-template-quasar-js) - A template using JavaScript + Quasar V2 (Vue 3, Vite, Sass, Pinia, ESLint, Prettier) - [wails-template-quasar-ts](https://github.com/sgosiaco/wails-template-quasar-ts) - A template using TypeScript + Quasar V2 (Vue 3, Vite, Sass, Pinia, ESLint, Prettier, Composition API with <script setup>) - [wails-template-naive](https://github.com/tk103331/wails-template-naive) - Wails template based on Naive UI (A Vue 3 Component Library) +- [wails-template-tdesign-js](https://github.com/tongque0/wails-template-tdesign-js) - Wails template based on TDesign UI (a Vue 3 UI library by Tencent), using Vite, Pinia, Vue Router, ESLint, and Prettier. ## Angular @@ -40,11 +41,13 @@ If you are unsure about a template, inspect `package.json` and `wails.json` for - [wails-template-nextjs-app-router](https://github.com/thisisvk-in/wails-template-nextjs-app-router) - A template using Next.js and TypeScript with App router - [wails-vite-react-ts-tailwind-template](https://github.com/hotafrika/wails-vite-react-ts-tailwind-template) - A template for React + TypeScript + Vite + TailwindCSS - [wails-vite-react-ts-tailwind-shadcnui-template](https://github.com/Mahcks/wails-vite-react-tailwind-shadcnui-ts) - A template with Vite, React, TypeScript, TailwindCSS, and shadcn/ui +- [wails-nextjs-tailwind-template](https://github.com/kairo913/wails-nextjs-tailwind-template) - A template using Next.js and Typescript with TailwindCSS ## Svelte - [wails-svelte-template](https://github.com/raitonoberu/wails-svelte-template) - A template using Svelte - [wails-vite-svelte-template](https://github.com/BillBuilt/wails-vite-svelte-template) - A template using Svelte and Vite +- [wails-vite-svelte-ts-tailwind-template](https://github.com/xvertile/wails-vite-svelte-tailwind-template) - A template using Wails, Svelte, Vite, TypeScript, and TailwindCSS v3 - [wails-vite-svelte-tailwind-template](https://github.com/BillBuilt/wails-vite-svelte-tailwind-template) - A template using Svelte and Vite with TailwindCSS v3 - [wails-svelte-tailwind-vite-template](https://github.com/PylotLight/wails-vite-svelte-tailwind-template/tree/master) - An updated template using Svelte v4.2.0 and Vite with TailwindCSS v3.3.3 - [wails-sveltekit-template](https://github.com/h8gi/wails-sveltekit-template) - A template using SvelteKit diff --git a/website/i18n/ar/docusaurus-plugin-content-docs/current/gettingstarted/firstproject.mdx b/website/i18n/ar/docusaurus-plugin-content-docs/current/gettingstarted/firstproject.mdx index 62ee97c84..e7cc86163 100644 --- a/website/i18n/ar/docusaurus-plugin-content-docs/current/gettingstarted/firstproject.mdx +++ b/website/i18n/ar/docusaurus-plugin-content-docs/current/gettingstarted/firstproject.mdx @@ -126,5 +126,3 @@ Wails projects have the following layout: The `frontend` directory has nothing specific to Wails and can be any frontend project of your choosing. The `build` directory is used during the build process. These files may be updated to customise your builds. If files are removed from the build directory, default versions will be regenerated. - -The default module name in `go.mod` is "changeme". You should change this to something more appropriate. diff --git a/website/i18n/ar/docusaurus-plugin-content-docs/current/gettingstarted/installation.mdx b/website/i18n/ar/docusaurus-plugin-content-docs/current/gettingstarted/installation.mdx index 401d26789..028b167da 100644 --- a/website/i18n/ar/docusaurus-plugin-content-docs/current/gettingstarted/installation.mdx +++ b/website/i18n/ar/docusaurus-plugin-content-docs/current/gettingstarted/installation.mdx @@ -7,7 +7,7 @@ sidebar_position: 1 ## Supported Platforms - Windows 10/11 AMD64/ARM64 -- MacOS 10.13+ AMD64 +- MacOS 10.15+ AMD64 for development, MacOS 10.13+ for release - MacOS 11.0+ ARM64 - Linux AMD64/ARM64 @@ -15,7 +15,7 @@ sidebar_position: 1 Wails has a number of common dependencies that are required before installation: -- Go 1.20+ +- Go 1.21+ (macOS 15+ requires Go 1.23.3+) - NPM (Node 15+) ### Go @@ -58,6 +58,8 @@ import TabItem from "@theme/TabItem"; </TabItem> <TabItem value={"Linux"}> Linux requires the standard <code>gcc</code> build tools plus <code>libgtk3</code> and <code>libwebkit</code>. Rather than list a ton of commands for different distros, Wails can try to determine what the installation commands are for your specific distribution. Run <code>wails doctor</code> after installation to be shown how to install the dependencies. If your distro/package manager is not supported, please consult the <a href={"/docs/guides/linux-distro-support"}>Add Linux Distro</a> guide. + <br/><strong>Note:</strong><br/> + If you are using latest Linux version (example: Ubuntu 24.04) and it is not supporting <code>libwebkit2gtk-4.0-dev</code>, then you might encounter an issue in <code>wails doctor</code>: <code>libwebkit</code> not found. To resolve this issue you can install <code>libwebkit2gtk-4.1-dev</code> and during your build use the tag <code>-tags webkit2_41</code>. </TabItem> </Tabs> ``` diff --git a/website/i18n/ar/docusaurus-plugin-content-docs/current/guides/application-development.mdx b/website/i18n/ar/docusaurus-plugin-content-docs/current/guides/application-development.mdx index 8ad521116..687b89791 100644 --- a/website/i18n/ar/docusaurus-plugin-content-docs/current/guides/application-development.mdx +++ b/website/i18n/ar/docusaurus-plugin-content-docs/current/guides/application-development.mdx @@ -235,7 +235,7 @@ If these 2 keys aren't given, then Wails does absolutely nothing with the fronte ### AssetsHandler -A Wails v2 app can optionally define a `http.Handler` in the `options.App`, which allows hooking into the AssetServer to create files on the fly or process POST/PUT requests. GET requests are always first handled by the `assets` FS. If the FS doesn't find the requested file the request will be forwarded to the `http.Handler` for serving. Any requests other than GET will be directly processed by the `AssetsHandler` if specified. It's also possible to only use the `AssetsHandler` by specifiy `nil` as the `Assets` option. +A Wails v2 app can optionally define a `http.Handler` in the `options.App`, which allows hooking into the AssetServer to create files on the fly or process POST/PUT requests. GET requests are always first handled by the `assets` FS. If the FS doesn't find the requested file the request will be forwarded to the `http.Handler` for serving. Any requests other than GET will be directly processed by the `AssetsHandler` if specified. It's also possible to only use the `AssetsHandler` by specifying `nil` as the `Assets` option. ## Built in Dev Server diff --git a/website/i18n/ar/docusaurus-plugin-content-docs/current/guides/crossplatform-build.mdx b/website/i18n/ar/docusaurus-plugin-content-docs/current/guides/crossplatform-build.mdx index ff217c845..e7ea6dfc8 100644 --- a/website/i18n/ar/docusaurus-plugin-content-docs/current/guides/crossplatform-build.mdx +++ b/website/i18n/ar/docusaurus-plugin-content-docs/current/guides/crossplatform-build.mdx @@ -61,6 +61,6 @@ This example offers opportunities for various enhancements, including: - Caching dependencies - Code signing -- Uploading to platforms like S3, Supbase, etc. +- Uploading to platforms like S3, Supabase, etc. - Injecting secrets as environment variables - Utilizing environment variables as build variables (such as version variable extracted from the current Git tag) diff --git a/website/i18n/ar/docusaurus-plugin-content-docs/current/guides/frontend.mdx b/website/i18n/ar/docusaurus-plugin-content-docs/current/guides/frontend.mdx index ac087ee45..f057056c1 100644 --- a/website/i18n/ar/docusaurus-plugin-content-docs/current/guides/frontend.mdx +++ b/website/i18n/ar/docusaurus-plugin-content-docs/current/guides/frontend.mdx @@ -44,7 +44,7 @@ The options are as follows: | noautoinjectipc | Disable the autoinjection of `/wails/ipc.js` | | noautoinject | Disable all autoinjection of scripts | -Multiple options may be used provided they are comma seperated. +Multiple options may be used provided they are comma separated. This code is perfectly valid and operates the same as the autoinjection version: diff --git a/website/i18n/ar/docusaurus-plugin-content-docs/current/guides/mac-appstore.mdx b/website/i18n/ar/docusaurus-plugin-content-docs/current/guides/mac-appstore.mdx index 961595711..4b6d3a1ab 100644 --- a/website/i18n/ar/docusaurus-plugin-content-docs/current/guides/mac-appstore.mdx +++ b/website/i18n/ar/docusaurus-plugin-content-docs/current/guides/mac-appstore.mdx @@ -61,7 +61,7 @@ This is an example entitlements file from the [RiftShare](https://github.com/ach </plist> ``` -**Add the Embedded Provisioning Profile** The Provisioning Profile created above needs to be added to the root of the applicaton. It needs to be named embedded.provisionprofile. +**Add the Embedded Provisioning Profile** The Provisioning Profile created above needs to be added to the root of the application. It needs to be named embedded.provisionprofile. #### Build and Sign the App Package @@ -80,9 +80,9 @@ wails build -platform darwin/universal -clean cp ./embedded.provisionprofile "./build/bin/$APP_NAME.app/Contents" -codesign --timestamp --options=runtime -s "$APP_CERTIFICATE" -v --entitlements ./build/darwin/entitlements.plist ./build/bin/$APP_NAME.app +codesign --timestamp --options=runtime -s "$APP_CERTIFICATE" -v --entitlements ./build/darwin/entitlements.plist "./build/bin/$APP_NAME.app" -productbuild --sign "$PKG_CERTIFICATE" --component ./build/bin/$APP_NAME.app /Applications ./$APP_NAME.pkg +productbuild --sign "$PKG_CERTIFICATE" --component "./build/bin/$APP_NAME.app" /Applications "./$APP_NAME.pkg" ``` #### Upload App Bundle diff --git a/website/i18n/ar/docusaurus-plugin-content-docs/current/guides/nixos-font.mdx b/website/i18n/ar/docusaurus-plugin-content-docs/current/guides/nixos-font.mdx index 141e4d68c..02188562e 100644 --- a/website/i18n/ar/docusaurus-plugin-content-docs/current/guides/nixos-font.mdx +++ b/website/i18n/ar/docusaurus-plugin-content-docs/current/guides/nixos-font.mdx @@ -1,6 +1,6 @@ # NixOS FontSize Bug -NixOS/Wayland can cause a bug where the `font-size` css property doesnt affect the rendered page. To fix this add the following to your devShell. +NixOS/Wayland can cause a bug where the `font-size` css property doesn't affect the rendered page. To fix this add the following to your devShell. ```shell shellHook = with pkgs; '' diff --git a/website/i18n/ar/docusaurus-plugin-content-docs/current/guides/signing.mdx b/website/i18n/ar/docusaurus-plugin-content-docs/current/guides/signing.mdx index 49b82d94c..67ed0810a 100644 --- a/website/i18n/ar/docusaurus-plugin-content-docs/current/guides/signing.mdx +++ b/website/i18n/ar/docusaurus-plugin-content-docs/current/guides/signing.mdx @@ -232,7 +232,7 @@ Now we need to configure some gon config files in our `build/darwin` directory: "bundle_id": "app.myapp", "apple_id": { "username": "my-appleid@email.com", - "password": "@env:APPLE_PASSWORD", + "password": "your-app-specific-password", "provider": "ABCDE12345" }, "sign": { @@ -246,11 +246,13 @@ Here is a brief break down of the above fields: - `source`: The location of your wails binary to be signed - `apple_id`: - `username`: Your Apple ID email address - - `password`: Your app-specific password, referenced using Gon's environment variable syntax + - `password`: Your app-specific password - `provider`: Your team ID for your App Store Connect account - `sign`: - `application_identity`: Your Apple developer identity +The (https://developer.apple.com/documentation/technotes/tn3147-migrating-to-the-latest-notarization-tool)[deprecated Apple's altool]'s syntax supporting `@env:` is no longer available since Apple has migrated to the new notarytool. + Your developer identity and team ID can both by found on macOS by running the following command: ```bash diff --git a/website/i18n/ar/docusaurus-plugin-content-docs/current/guides/sveltekit.mdx b/website/i18n/ar/docusaurus-plugin-content-docs/current/guides/sveltekit.mdx index 7de133a8a..56bbdd703 100644 --- a/website/i18n/ar/docusaurus-plugin-content-docs/current/guides/sveltekit.mdx +++ b/website/i18n/ar/docusaurus-plugin-content-docs/current/guides/sveltekit.mdx @@ -2,7 +2,7 @@ This guide will go into: -1. Miminal Installation Steps - The steps needed to get a minimum Wails setup working for SvelteKit. +1. Minimal Installation Steps - The steps needed to get a minimum Wails setup working for SvelteKit. 2. Install Script - Bash script for accomplishing the Minimal Installation Steps with optional Wails branding. 3. Important Notes - Issues that can be encountered when using SvelteKit + Wails and fixes. @@ -17,9 +17,9 @@ This guide will go into: - Navigate into your newly created myapp folder. - Delete the folder named "frontend" -##### While in the Wails project root. Use your favorite package manager and install SvelteKit as the new frontend. Follow the prompts. +##### While in the Wails project root. Use the Svelte CLI to create a SvelteKit project as the new frontend. Follow the prompts, nothing Wails specific is needed here. -- `npm create svelte@latest frontend` +- `npx sv create frontend` ##### Modify wails.json. @@ -124,7 +124,7 @@ wails dev See https://wails.io/docs/guides/frontend for more information. -##### Inital data can be loaded and refreshed from +page.ts/+page.js to +page.svelte. +##### Initial data can be loaded and refreshed from +page.ts/+page.js to +page.svelte. - \+page.ts/+page.js works well with load() https://kit.svelte.dev/docs/load#page-data - invalidateAll() in +page.svelte will call load() from +page.ts/+page.js https://kit.svelte.dev/docs/load#rerunning-load-functions-manual-invalidation. diff --git a/website/i18n/ar/docusaurus-plugin-content-docs/current/reference/cli.mdx b/website/i18n/ar/docusaurus-plugin-content-docs/current/reference/cli.mdx index 3e0388750..9c595c4f8 100644 --- a/website/i18n/ar/docusaurus-plugin-content-docs/current/reference/cli.mdx +++ b/website/i18n/ar/docusaurus-plugin-content-docs/current/reference/cli.mdx @@ -66,7 +66,7 @@ If you are unsure about a template, inspect `package.json` and `wails.json` for | -nsis | Generate NSIS installer for Windows | | | -o filename | Output filename | | | -obfuscated | Obfuscate the application using [garble](https://github.com/burrowers/garble) | | -| -platform | Build for the given (comma delimited) [platforms](../reference/cli.mdx#platforms) eg. `windows/arm64`. Note, if you do not give the architecture, `runtime.GOARCH` is used. | platform = `GOOS` environment variable if given else `runtime.GOOS`.<br/>arch = `GOARCH` envrionment variable if given else `runtime.GOARCH`. | +| -platform | Build for the given (comma delimited) [platforms](../reference/cli.mdx#platforms) eg. `windows/arm64`. Note, if you do not give the architecture, `runtime.GOARCH` is used. | platform = `GOOS` environment variable if given else `runtime.GOOS`.<br/>arch = `GOARCH` environment variable if given else `runtime.GOARCH`. | | -race | Build with Go's race detector | | | -s | Skip building the frontend | | | -skipbindings | Skip bindings generation | | @@ -99,6 +99,12 @@ There are [issues](https://github.com/upx/upx/issues/446) with using UPX with Ap ::: +:::info Set minimal version for MacOS + +You can override default [minimal version](../gettingstarted/installation#supported-platforms) of macOS for your app by providing version via `CGO_CFLAGS` and `CGO_LDFLAGS` environment variables. e.g. `CGO_CFLAGS=-mmacosx-version-min=10.15.0 CGO_LDFLAGS=-mmacosx-version-min=10.15.0 wails build` + +::: + :::info UPX on Windows Some Antivirus vendors false positively mark `upx` compressed binaries as virus, see [issue](https://github.com/upx/upx/issues/437). diff --git a/website/i18n/ar/docusaurus-plugin-content-docs/current/reference/menus.mdx b/website/i18n/ar/docusaurus-plugin-content-docs/current/reference/menus.mdx index ff9a24422..bcf0f2344 100644 --- a/website/i18n/ar/docusaurus-plugin-content-docs/current/reference/menus.mdx +++ b/website/i18n/ar/docusaurus-plugin-content-docs/current/reference/menus.mdx @@ -13,15 +13,21 @@ An example of how to create a menu: app := NewApp() AppMenu := menu.NewMenu() + if runtime.GOOS == "darwin" { + AppMenu.Append(menu.AppMenu()) // On macOS platform, this must be done right after `NewMenu()` + } FileMenu := AppMenu.AddSubmenu("File") - FileMenu.AddText("&Open", keys.CmdOrCtrl("o"), openFile) + FileMenu.AddText("&Open", keys.CmdOrCtrl("o"), func(_ *menu.CallbackData) { + // do something + }) FileMenu.AddSeparator() FileMenu.AddText("Quit", keys.CmdOrCtrl("q"), func(_ *menu.CallbackData) { - runtime.Quit(app.ctx) + // `rt` is an alias of "github.com/wailsapp/wails/v2/pkg/runtime" to prevent collision with standard package + rt.Quit(app.ctx) }) if runtime.GOOS == "darwin" { - AppMenu.Append(menu.EditMenu()) // on macos platform, we should append EditMenu to enable Cmd+C,Cmd+V,Cmd+Z... shortcut + AppMenu.Append(menu.EditMenu()) // On macOS platform, EditMenu should be appended to enable Cmd+C, Cmd+V, Cmd+Z... shortcuts } err := wails.Run(&options.App{ diff --git a/website/i18n/ar/docusaurus-plugin-content-docs/current/reference/options.mdx b/website/i18n/ar/docusaurus-plugin-content-docs/current/reference/options.mdx index 8bcf42047..6626b5717 100644 --- a/website/i18n/ar/docusaurus-plugin-content-docs/current/reference/options.mdx +++ b/website/i18n/ar/docusaurus-plugin-content-docs/current/reference/options.mdx @@ -98,7 +98,9 @@ func main() { // OnResume is called when Windows resumes from low power mode OnResume: func(), // Disable GPU hardware acceleration for the webview - WebviewGpuDisabled: false, + WebviewGpuDisabled: false, + // Class name for the window. If empty, 'wailsWindow' will be used. + WindowClassName: "MyWindow", }, Mac: &mac.Options{ TitleBar: &mac.TitleBar{ @@ -420,18 +422,6 @@ EnableFraudulentWebsiteDetection enables scan services for fraudulent content, s Name: EnableFraudulentWebsiteDetection<br/> Type: `bool` -### ZoomFactor - -Name: ZoomFactor<br/> Type: `float64` - -This defines the zoom factor for the WebView2. This is the option matching the Edge user activated zoom in or out. - -### IsZoomControlEnabled - -Name: IsZoomControlEnabled<br/> Type: `bool` - -This enables the zoom factor to be changed by the user. Please note that the zoom factor can be set in the options while disallowing the user to change it at runtime (f.e. for a kiosk application or similar). - ### Bind A slice of struct instances defining methods that need to be bound to the frontend. @@ -546,6 +536,18 @@ The value can be one of the following: | Mica | Use [Mica](https://learn.microsoft.com/en-us/windows/apps/design/style/mica) effect | | Tabbed | Use Tabbed. This is a backdrop that is similar to Mica. | +#### ZoomFactor + +Name: ZoomFactor<br/> Type: `float64` + +This defines the zoom factor for the WebView2. This is the option matching the Edge user activated zoom in or out. + +#### IsZoomControlEnabled + +Name: IsZoomControlEnabled<br/> Type: `bool` + +This enables the zoom factor to be changed by the user. Please note that the zoom factor can be set in the options while disallowing the user to change it at runtime (f.e. for a kiosk application or similar). + #### DisablePinchZoom Setting this to `true` will disable pinch zoom gestures. @@ -690,6 +692,12 @@ Setting this to `true` will enable swipe gestures for the webview. Name: EnableSwipeGestures<br/> Type: `bool` +#### WindowClassName + +Class name for the window. If empty, 'wailsWindow' will be used. + +Name: WindowClassName<br/> Type: `string` + ### Mac This defines [Mac specific options](#mac). diff --git a/website/i18n/ar/docusaurus-plugin-content-docs/current/reference/runtime/events.mdx b/website/i18n/ar/docusaurus-plugin-content-docs/current/reference/runtime/events.mdx index 856ba6f0c..7a2ebda7e 100644 --- a/website/i18n/ar/docusaurus-plugin-content-docs/current/reference/runtime/events.mdx +++ b/website/i18n/ar/docusaurus-plugin-content-docs/current/reference/runtime/events.mdx @@ -14,7 +14,7 @@ Go: `EventsOn(ctx context.Context, eventName string, callback func(optionalData ### EventsOff -This method unregisters the listener for the given event name, optionally multiple listeneres can be unregistered via `additionalEventNames`. +This method unregisters the listener for the given event name, optionally multiple listeners can be unregistered via `additionalEventNames`. Go: `EventsOff(ctx context.Context, eventName string, additionalEventNames ...string)`<br/> JS: `EventsOff(eventName string, ...additionalEventNames)` diff --git a/website/i18n/ar/docusaurus-plugin-content-docs/current/reference/runtime/window.mdx b/website/i18n/ar/docusaurus-plugin-content-docs/current/reference/runtime/window.mdx index b2ae6deba..f7cdae99f 100644 --- a/website/i18n/ar/docusaurus-plugin-content-docs/current/reference/runtime/window.mdx +++ b/website/i18n/ar/docusaurus-plugin-content-docs/current/reference/runtime/window.mdx @@ -202,7 +202,7 @@ Go: `WindowSetBackgroundColour(ctx context.Context, R, G, B, A uint8)`<br/> JS: ### WindowPrint -Opens tha native print dialog. +Opens the native print dialog. Go: `WindowPrint(ctx context.Context)`<br/> JS: `WindowPrint()` diff --git a/website/i18n/ar/docusaurus-plugin-content-docs/version-v2.10.json b/website/i18n/ar/docusaurus-plugin-content-docs/version-v2.10.json new file mode 100644 index 000000000..deb213d1a --- /dev/null +++ b/website/i18n/ar/docusaurus-plugin-content-docs/version-v2.10.json @@ -0,0 +1,38 @@ +{ + "version.label": { + "message": "v2.10", + "description": "The label for version v2.10" + }, + "sidebar.docs.category.Getting Started": { + "message": "Getting Started", + "description": "The label for category Getting Started in sidebar docs" + }, + "sidebar.docs.category.Reference": { + "message": "Reference", + "description": "The label for category Reference in sidebar docs" + }, + "sidebar.docs.category.Runtime": { + "message": "Runtime", + "description": "The label for category Runtime in sidebar docs" + }, + "sidebar.docs.category.Community": { + "message": "Community", + "description": "The label for category Community in sidebar docs" + }, + "sidebar.docs.category.Showcase": { + "message": "Showcase", + "description": "The label for category Showcase in sidebar docs" + }, + "sidebar.docs.category.Guides": { + "message": "Guides", + "description": "The label for category Guides in sidebar docs" + }, + "sidebar.docs.category.Tutorials": { + "message": "Tutorials", + "description": "The label for category Tutorials in sidebar docs" + }, + "sidebar.docs.link.Contributing": { + "message": "Contributing", + "description": "The label for link Contributing in sidebar docs, linking to /community-guide#ways-of-contributing" + } +} diff --git a/website/i18n/ar/docusaurus-plugin-content-pages/changelog.mdx b/website/i18n/ar/docusaurus-plugin-content-pages/changelog.mdx index d8d1039ac..4efaca467 100644 --- a/website/i18n/ar/docusaurus-plugin-content-pages/changelog.mdx +++ b/website/i18n/ar/docusaurus-plugin-content-pages/changelog.mdx @@ -13,6 +13,79 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), ## [Unreleased] +### Changed +- Updated recommendation for Svelte router in [#4085](https://github.com/wailsapp/wails/pull/4085) by [@benmccann](https://github.com/benmccann) + +### Added +- Added "Branding" section to `wails doctor` to correctly identify Windows 11 [#3891](https://github.com/wailsapp/wails/pull/3891) by [@ronen25](https://github.com/ronen25) + + +## v2.10.1 - 2025-02-24 + +### Fixed +- Fixed [listenerOff issue](https://github.com/wailsapp/wails/issues/3850) by @leaanthony. +- Fixed issues building with `darwin/universal` target by @leaanthony. + +## v2.10 - 2025-02-15 + +### Added +- Added option to set window class name on Windows. Added in [PR](https://github.com/wailsapp/wails/pull/3828) by @APshenkin + +### Fixed +- Fixed dev mode logging bug by @attperac in [#3972](https://wailsapp/wails/pull/3972) +- Fixed `reloaddirs` wails.json config options by @atterpac in [#4005](https//github.com/wailsapp/wails/pull/4005) +- Fixed cross compilation failed with CGO [PR](https://github.com/wailsapp/wails/pull/3795) by [@fcying](https://github.com/fcying) +- Using go-webview2 v0.1.17 to fix native webview2loader issue, by @leaanthony +- Fixed example for macOS menu by @takuyahara in [PR](https://github.com/wailsapp/wails/pull/3847) +- Fixed typo by @takuyahara in [PR](https://github.com/wailsapp/wails/pull/3846) +- Fixed incorrect TS definition of `WindowSetSize` by @leaanthony +- Ensure showHiddenFiles works with directory dialog by @leaanthony in [PR](https://github.com/wailsapp/wails/pull/3904) +- chore: fix some comments in [PR](https://github.com/wailsapp/wails/pull/3932) by @lvyaoting +- [windows] Fixed frameless window flickering when minimizing/restoring by preventing unnecessary redraws [#3951](https://github.com/wailsapp/wails/issues/3951) +- Fixed failed models.ts build due to non-json-encodable Go types [PR](https://github.com/wailsapp/wails/pull/3975) by [@pbnjay](https://github.com/pbnjay) +- Fixed more binding and typescript export bugs [PR](https://github.com/wailsapp/wails/pull/3978) by [@pbnjay](https://github.com/pbnjay) +- Fixed Dispatcher.ProcessMessage crash process instead of return error [PR](https://github.com/wailsapp/wails/pull/4016) [#4015](https://github.com/wailsapp/wails/issues/4015) by [@ronaldinho_x86](https://github.com/RonaldinhoL) +- Fixed Windows SaveDialog crash by [@leaanthony](https://github.com/leaanthony) +- Fixed `buildvcs` errors by [@leaanthony](https://github.com/leaanthony) +- Fixed updating menus on MacOS by [@stffabi](https://github.com/stffabi) +- Fixed a build error on macOS that occurred when the `outputfilename` and `name` fields in wails.json were different. Fixed in [PR](https://github.com/wailsapp/wails/pull/3789) by [@nickisworking](https://github.com/nickisworking) + +### Changed +- Removed documentation references for 'The default module name in go.mod is "changeme". You should change this to something more appropriate.' as it appears to be no longer relevant. +- Update script in Mac App Store guide to support app names containing spaces by @cristianrgreco +- Allow to specify macos-min-version externally. Implemented by @APshenkin in [PR](https://github.com/wailsapp/wails/pull/3756) +- Updated installation docs for latest linux os version and libwebkit issue [PR](https://github.com/wailsapp/wails/pull/3806) by [@pratikmota](https://github.com/pratikmota) + + + +## v2.9.3 - 2025-02-13 + +### Added +- Go 1.24 support by [@leaanthony](https://github.com/leaanthony) + +### Fixed +- Now using `-buildvcs=false` build tag by default to remove `error obtaining VCS status: exit status 128` errors by [@leaanthony](https://github.com/leaanthony) + +## v2.9.2 - 2024-09-18 + +### Fixed +- Fixed CGO memory issue on Darwin by @leaanthony in [PR](https://github.com/wailsapp/wails/pull/3590) +- Fixed an error that occurred when an author name contains a string that is not suitable for JSON. Fixed by @taiseiotsuka in [PR](https://github.com/wailsapp/wails/pull/3638) +- Fixed MacOS build to use `outputfilename` from wails.json. [#3200](https://github.com/wailsapp/wails/issues/3200) +- Fixed file drop events on windows. Fixed in [PR](https://github.com/wailsapp/wails/pull/3595) by @FrancescoLuzzi +- Fixed doctor command not finding pkg-config on Solus. [PR #3670](https://github.com/wailsapp/wails/pull/3670) by [@ianmjones](https://github.com/ianmjones) +- Fixed binding for struct fields that were exported but had no json tags. [PR #3678](https://github.com/wailsapp/wails/pull/3678) +- Fixed file drop events on Windows in [PR](https://github.com/wailsapp/wails/pull/3595) by @FrancescoLuzzi +- Modified `ZoomFactor` and `IsZoomControlEnabled` options to be Windows-only options in PR[#3644](https://github.com/wailsapp/wails/pull/3644) by @levinit +- Added nil check for Drag-n-Drop on Windows. Fixed by in [PR](https://github.com/wailsapp/wails/pull/3597) by @leaanthony based on the suggestion by @Alpa-1 in [#3596](https://github.com/wailsapp/wails/issues/3596). +- Fixed typos in various .mdx files. [PR #3628](https://github.com/wailsapp/wails/pull/3628) by [@deining](https://github.com/deining) +- Fixed `notifyListeners()` race condition when terminated mid-emission [PR](https://github.com/wailsapp/wails/pull/3695) by [@mrf345](https://github.com/mrf345) +- Fixed dialogs in Windows when using Go 1.23 in [PR](https://github.com/wailsapp/wails/pull/3707) by [@leaanthony](https://github.com/leaanthony) +- More syscall fixes for Go 1.23 support in [PR](https://github.com/wailsapp/wails/pull/3713) by [@leaanthony](https://github.com/leaanthony) +- Fixed drag and drop missing cursor icon [PR](https://github.com/wailsapp/wails/pull/3703) by [@mrf345](https://github.com/mrf345) + +### Changed +- Modified docs to reflect the correct password syntax for the `gon-sign.json` file [PR](https://github.com/wailsapp/wails/pull/3620) by [@ignasbernotas](github.com/ignasbernotas) ## v2.9.1 - 2024-06-18 ### Fixed diff --git a/website/i18n/ar/docusaurus-plugin-content-pages/credits.mdx b/website/i18n/ar/docusaurus-plugin-content-pages/credits.mdx index a46ca16e9..7d12dca6a 100644 --- a/website/i18n/ar/docusaurus-plugin-content-pages/credits.mdx +++ b/website/i18n/ar/docusaurus-plugin-content-pages/credits.mdx @@ -6,6 +6,7 @@ - [Atterpac](https://github.com/atterpac) - Developer, support guru, powerhouse - [Simon Thomas](mailto:enquiries@wails.io) - Growth Hacker - [Lyimmi](https://github.com/Lyimmi) - All things Linux +- [fbbdev](https://github.com/fbbdev) - Bindings Generator guru & core contributor ## Sponsors <img src="/img/sponsors.svg" style={{"width":"85%","max-width":"800px;"}} /> @@ -38,7 +39,7 @@ </tr> <tr> <td align="center" valign="top" width="12.5%"><a href="https://github.com/k-muchmore"><img src="https://avatars.githubusercontent.com/u/16393095?v=4?s=75" width="75px;" alt="k-muchmore"/><br /><sub><b>k-muchmore</b></sub></a><br /><a href="https://github.com/wailsapp/wails/commits?author=k-muchmore" title="Code">💻</a></td> - <td align="center" valign="top" width="12.5%"><a href="https://peakd.com/@snider"><img src="https://avatars.githubusercontent.com/u/631881?v=4?s=75" width="75px;" alt="Snider"/><br /><sub><b>Snider</b></sub></a><br /><a href="https://github.com/wailsapp/wails/commits?author=Snider" title="Code">💻</a> <a href="#ideas-Snider" title="Ideas, Planning, & Feedback">🤔</a> <a href="https://github.com/wailsapp/wails/commits?author=Snider" title="Documentation">📖</a> <a href="#financial-Snider" title="Financial">💵</a></td> + <td align="center" valign="top" width="12.5%"><a href="https://github.com/Snider"><img src="https://avatars.githubusercontent.com/u/631881?v=4?s=75" width="75px;" alt="Snider"/><br /><sub><b>Snider</b></sub></a><br /><a href="https://github.com/wailsapp/wails/commits?author=Snider" title="Code">💻</a> <a href="#ideas-Snider" title="Ideas, Planning, & Feedback">🤔</a> <a href="https://github.com/wailsapp/wails/commits?author=Snider" title="Documentation">📖</a> <a href="#financial-Snider" title="Financial">💵</a><a href="https://github.com/dappServer/wails-build-action" title="Tools">🔧</a></td> <td align="center" valign="top" width="12.5%"><a href="https://github.com/albert-sun"><img src="https://avatars.githubusercontent.com/u/54585592?v=4?s=75" width="75px;" alt="Albert Sun"/><br /><sub><b>Albert Sun</b></sub></a><br /><a href="https://github.com/wailsapp/wails/commits?author=albert-sun" title="Code">💻</a> <a href="https://github.com/wailsapp/wails/commits?author=albert-sun" title="Tests">⚠️</a></td> <td align="center" valign="top" width="12.5%"><a href="https://github.com/adalessa"><img src="https://avatars.githubusercontent.com/u/7914601?v=4?s=75" width="75px;" alt="Ariel"/><br /><sub><b>Ariel</b></sub></a><br /><a href="https://github.com/wailsapp/wails/commits?author=adalessa" title="Code">💻</a> <a href="https://github.com/wailsapp/wails/issues?q=author%3Aadalessa" title="Bug reports">🐛</a></td> <td align="center" valign="top" width="12.5%"><a href="https://triplebits.com/"><img src="https://avatars.githubusercontent.com/u/4365245?v=4?s=75" width="75px;" alt="Ilgıt Yıldırım"/><br /><sub><b>Ilgıt Yıldırım</b></sub></a><br /><a href="https://github.com/wailsapp/wails/commits?author=ilgityildirim" title="Code">💻</a> <a href="https://github.com/wailsapp/wails/issues?q=author%3Ailgityildirim" title="Bug reports">🐛</a> <a href="#financial-ilgityildirim" title="Financial">💵</a></td> @@ -265,5 +266,5 @@ - [Byron Chris](https://github.com/bh90210) - For his long term contributions to this project. - [Dustin Krysak](https://wiki.ubuntu.com/bashfulrobot) - His support and feedback has been invaluable. - [Justen Walker](https://github.com/justenwalker/) - For helping wrangle COM issues which got v2 over the line. -- [Wang, Chi](https://github.com/patr0nus/) - The DeskGap project was a huge influence on the direction of Wails v2. +- [Wang, Chi](https://github.com/branchseer) - The DeskGap project was a huge influence on the direction of Wails v2. - [Serge Zaitsev](https://github.com/zserge) - Whilst Wails does not use the Webview project, it is still a source of inspiration. diff --git a/website/i18n/ar/docusaurus-theme-classic/footer.json b/website/i18n/ar/docusaurus-theme-classic/footer.json index dd6667908..48e57df44 100644 --- a/website/i18n/ar/docusaurus-theme-classic/footer.json +++ b/website/i18n/ar/docusaurus-theme-classic/footer.json @@ -44,7 +44,7 @@ "description": "The label of footer link with label=Blog linking to /blog" }, "copyright": { - "message": "Copyright © 2022 Lea Anthony", + "message": "Copyright © 2025 Lea Anthony", "description": "The footer copyright" }, "link.item.label.Awesome": { diff --git a/website/i18n/de/code.json b/website/i18n/de/code.json new file mode 100644 index 000000000..c3b0bdfeb --- /dev/null +++ b/website/i18n/de/code.json @@ -0,0 +1,431 @@ +{ + "homepage.Features.Title1": { + "message": "Feature Rich" + }, + "homepage.Features.Description1": { + "message": "Build comprehensive cross-platform applications using native UI elements such as menus and dialogs." + }, + "homepage.Features.Title2": { + "message": "Familiar" + }, + "homepage.Features.Description2": { + "message": "Use the technologies you already know to build amazing applications." + }, + "homepage.Features.Title3": { + "message": "Fast" + }, + "homepage.Features.Description3": { + "message": "Quickly generate, build and package your projects using the Wails CLI." + }, + "homepage.Tagline": { + "message": "Build beautiful cross-platform applications using Go" + }, + "homepage.ButtonText": { + "message": "Get Started" + }, + "homepage.LearnMoreButtonText": { + "message": "Learn More" + }, + "theme.ErrorPageContent.title": { + "message": "This page crashed.", + "description": "The title of the fallback page when the page crashed" + }, + "theme.ErrorPageContent.tryAgain": { + "message": "Try again", + "description": "The label of the button to try again rendering when the React error boundary captures an error" + }, + "theme.NotFound.title": { + "message": "Page Not Found", + "description": "The title of the 404 page" + }, + "theme.NotFound.p1": { + "message": "We could not find what you were looking for.", + "description": "The first paragraph of the 404 page" + }, + "theme.NotFound.p2": { + "message": "Please contact the owner of the site that linked you to the original URL and let them know their link is broken.", + "description": "The 2nd paragraph of the 404 page" + }, + "theme.AnnouncementBar.closeButtonAriaLabel": { + "message": "Close", + "description": "The ARIA label for close button of announcement bar" + }, + "theme.blog.archive.title": { + "message": "Archive", + "description": "The page & hero title of the blog archive page" + }, + "theme.blog.archive.description": { + "message": "Archive", + "description": "The page & hero description of the blog archive page" + }, + "theme.BackToTopButton.buttonAriaLabel": { + "message": "Scroll back to top", + "description": "The ARIA label for the back to top button" + }, + "theme.blog.paginator.navAriaLabel": { + "message": "Blog list page navigation", + "description": "The ARIA label for the blog pagination" + }, + "theme.blog.paginator.newerEntries": { + "message": "Newer Entries", + "description": "The label used to navigate to the newer blog posts page (previous page)" + }, + "theme.blog.paginator.olderEntries": { + "message": "Older Entries", + "description": "The label used to navigate to the older blog posts page (next page)" + }, + "theme.blog.post.readingTime.plurals": { + "message": "One min read|{readingTime} min read", + "description": "Pluralized label for \"{readingTime} min read\". Use as much plural forms (separated by \"|\") as your language support (see https://www.unicode.org/cldr/cldr-aux/charts/34/supplemental/language_plural_rules.html)" + }, + "theme.blog.post.readMoreLabel": { + "message": "Read more about {title}", + "description": "The ARIA label for the link to full blog posts from excerpts" + }, + "theme.blog.post.readMore": { + "message": "Read More", + "description": "The label used in blog post item excerpts to link to full blog posts" + }, + "theme.blog.post.paginator.navAriaLabel": { + "message": "Blog post page navigation", + "description": "The ARIA label for the blog posts pagination" + }, + "theme.blog.post.paginator.newerPost": { + "message": "Newer Post", + "description": "The blog post button label to navigate to the newer/previous post" + }, + "theme.blog.post.paginator.olderPost": { + "message": "Older Post", + "description": "The blog post button label to navigate to the older/next post" + }, + "theme.blog.sidebar.navAriaLabel": { + "message": "Blog recent posts navigation", + "description": "The ARIA label for recent posts in the blog sidebar" + }, + "theme.blog.post.plurals": { + "message": "One post|{count} posts", + "description": "Pluralized label for \"{count} posts\". Use as much plural forms (separated by \"|\") as your language support (see https://www.unicode.org/cldr/cldr-aux/charts/34/supplemental/language_plural_rules.html)" + }, + "theme.blog.tagTitle": { + "message": "{nPosts} tagged with \"{tagName}\"", + "description": "The title of the page for a blog tag" + }, + "theme.tags.tagsPageLink": { + "message": "View All Tags", + "description": "The label of the link targeting the tag list page" + }, + "theme.CodeBlock.copyButtonAriaLabel": { + "message": "Copy code to clipboard", + "description": "The ARIA label for copy code blocks button" + }, + "theme.CodeBlock.copied": { + "message": "Copied", + "description": "The copied button label on code blocks" + }, + "theme.CodeBlock.copy": { + "message": "Copy", + "description": "The copy button label on code blocks" + }, + "theme.colorToggle.ariaLabel": { + "message": "Switch between dark and light mode (currently {mode})", + "description": "The ARIA label for the navbar color mode toggle" + }, + "theme.colorToggle.ariaLabel.mode.dark": { + "message": "dark mode", + "description": "The name for the dark color mode" + }, + "theme.colorToggle.ariaLabel.mode.light": { + "message": "light mode", + "description": "The name for the light color mode" + }, + "theme.docs.DocCard.categoryDescription": { + "message": "{count} items", + "description": "The default description for a category card in the generated index about how many items this category includes" + }, + "theme.docs.sidebar.expandButtonTitle": { + "message": "Expand sidebar", + "description": "The ARIA label and title attribute for expand button of doc sidebar" + }, + "theme.docs.sidebar.expandButtonAriaLabel": { + "message": "Expand sidebar", + "description": "The ARIA label and title attribute for expand button of doc sidebar" + }, + "theme.docs.paginator.navAriaLabel": { + "message": "Docs pages navigation", + "description": "The ARIA label for the docs pagination" + }, + "theme.docs.paginator.previous": { + "message": "Previous", + "description": "The label used to navigate to the previous doc" + }, + "theme.docs.paginator.next": { + "message": "Next", + "description": "The label used to navigate to the next doc" + }, + "theme.docs.sidebar.collapseButtonTitle": { + "message": "Collapse sidebar", + "description": "The title attribute for collapse button of doc sidebar" + }, + "theme.docs.sidebar.collapseButtonAriaLabel": { + "message": "Collapse sidebar", + "description": "The title attribute for collapse button of doc sidebar" + }, + "theme.DocSidebarItem.toggleCollapsedCategoryAriaLabel": { + "message": "Toggle the collapsible sidebar category '{label}'", + "description": "The ARIA label to toggle the collapsible sidebar category" + }, + "theme.docs.tagDocListPageTitle.nDocsTagged": { + "message": "One doc tagged|{count} docs tagged", + "description": "Pluralized label for \"{count} docs tagged\". Use as much plural forms (separated by \"|\") as your language support (see https://www.unicode.org/cldr/cldr-aux/charts/34/supplemental/language_plural_rules.html)" + }, + "theme.docs.tagDocListPageTitle": { + "message": "{nDocsTagged} with \"{tagName}\"", + "description": "The title of the page for a docs tag" + }, + "theme.docs.versionBadge.label": { + "message": "Version: {versionLabel}" + }, + "theme.docs.versions.unreleasedVersionLabel": { + "message": "This is unreleased documentation for {siteTitle} {versionLabel} version.", + "description": "The label used to tell the user that he's browsing an unreleased doc version" + }, + "theme.docs.versions.unmaintainedVersionLabel": { + "message": "This is documentation for {siteTitle} {versionLabel}, which is no longer actively maintained.", + "description": "The label used to tell the user that he's browsing an unmaintained doc version" + }, + "theme.docs.versions.latestVersionSuggestionLabel": { + "message": "For up-to-date documentation, see the {latestVersionLink} ({versionLabel}).", + "description": "The label used to tell the user to check the latest version" + }, + "theme.docs.versions.latestVersionLinkLabel": { + "message": "latest version", + "description": "The label used for the latest version suggestion link label" + }, + "theme.common.editThisPage": { + "message": "Edit this page", + "description": "The link label to edit the current page" + }, + "theme.common.headingLinkTitle": { + "message": "Direct link to heading", + "description": "Title for link to heading" + }, + "theme.lastUpdated.atDate": { + "message": " on {date}", + "description": "The words used to describe on which date a page has been last updated" + }, + "theme.lastUpdated.byUser": { + "message": " by {user}", + "description": "The words used to describe by who the page has been last updated" + }, + "theme.lastUpdated.lastUpdatedAtBy": { + "message": "Last updated{atDate}{byUser}", + "description": "The sentence used to display when a page has been last updated, and by who" + }, + "theme.navbar.mobileSidebarSecondaryMenu.backButtonLabel": { + "message": "← Back to main menu", + "description": "The label of the back button to return to main menu, inside the mobile navbar sidebar secondary menu (notably used to display the docs sidebar)" + }, + "theme.navbar.mobileVersionsDropdown.label": { + "message": "Versions", + "description": "The label for the navbar versions dropdown on mobile view" + }, + "theme.common.skipToMainContent": { + "message": "Skip to main content", + "description": "The skip to content label used for accessibility, allowing to rapidly navigate to main content with keyboard tab/enter navigation" + }, + "theme.tags.tagsListLabel": { + "message": "Tags:", + "description": "The label alongside a tag list" + }, + "theme.TOCCollapsible.toggleButtonLabel": { + "message": "On this page", + "description": "The label used by the button on the collapsible TOC component" + }, + "theme.navbar.mobileLanguageDropdown.label": { + "message": "Languages", + "description": "The label for the mobile language switcher dropdown" + }, + "theme.SearchBar.seeAll": { + "message": "See all {count} results" + }, + "theme.SearchBar.label": { + "message": "Search", + "description": "The ARIA label and placeholder for search button" + }, + "theme.SearchPage.documentsFound.plurals": { + "message": "One document found|{count} documents found", + "description": "Pluralized label for \"{count} documents found\". Use as much plural forms (separated by \"|\") as your language support (see https://www.unicode.org/cldr/cldr-aux/charts/34/supplemental/language_plural_rules.html)" + }, + "theme.SearchPage.existingResultsTitle": { + "message": "Search results for \"{query}\"", + "description": "The search page title for non-empty query" + }, + "theme.SearchPage.emptyResultsTitle": { + "message": "Search the documentation", + "description": "The search page title for empty query" + }, + "theme.SearchPage.inputPlaceholder": { + "message": "Type your search here", + "description": "The placeholder for search page input" + }, + "theme.SearchPage.inputLabel": { + "message": "Search", + "description": "The ARIA label for search page input" + }, + "theme.SearchPage.algoliaLabel": { + "message": "Search by Algolia", + "description": "The ARIA label for Algolia mention" + }, + "theme.SearchPage.noResultsText": { + "message": "No results were found", + "description": "The paragraph for empty search result" + }, + "theme.SearchPage.fetchingNewResults": { + "message": "Fetching new results...", + "description": "The paragraph for fetching new search results" + }, + "theme.tags.tagsPageTitle": { + "message": "Tags", + "description": "The title of the tag list page" + }, + "theme.docs.breadcrumbs.home": { + "message": "Home page", + "description": "The ARIA label for the home page in the breadcrumbs" + }, + "theme.docs.breadcrumbs.navAriaLabel": { + "message": "Breadcrumbs", + "description": "The ARIA label for the breadcrumbs" + }, + "theme.CodeBlock.wordWrapToggle": { + "message": "Toggle word wrap", + "description": "The title attribute for toggle word wrapping button of code block lines" + }, + "theme.admonition.note": { + "message": "note", + "description": "The default label used for the Note admonition (:::note)" + }, + "theme.admonition.tip": { + "message": "tip", + "description": "The default label used for the Tip admonition (:::tip)" + }, + "theme.admonition.danger": { + "message": "danger", + "description": "The default label used for the Danger admonition (:::danger)" + }, + "theme.admonition.info": { + "message": "info", + "description": "The default label used for the Info admonition (:::info)" + }, + "theme.admonition.caution": { + "message": "caution", + "description": "The default label used for the Caution admonition (:::caution)" + }, + "theme.SearchModal.searchBox.resetButtonTitle": { + "message": "Clear the query", + "description": "The label and ARIA label for search box reset button" + }, + "theme.SearchModal.searchBox.cancelButtonText": { + "message": "Cancel", + "description": "The label and ARIA label for search box cancel button" + }, + "theme.SearchModal.startScreen.recentSearchesTitle": { + "message": "Recent", + "description": "The title for recent searches" + }, + "theme.SearchModal.startScreen.noRecentSearchesText": { + "message": "No recent searches", + "description": "The text when no recent searches" + }, + "theme.SearchModal.startScreen.saveRecentSearchButtonTitle": { + "message": "Save this search", + "description": "The label for save recent search button" + }, + "theme.SearchModal.startScreen.removeRecentSearchButtonTitle": { + "message": "Remove this search from history", + "description": "The label for remove recent search button" + }, + "theme.SearchModal.startScreen.favoriteSearchesTitle": { + "message": "Favorite", + "description": "The title for favorite searches" + }, + "theme.SearchModal.startScreen.removeFavoriteSearchButtonTitle": { + "message": "Remove this search from favorites", + "description": "The label for remove favorite search button" + }, + "theme.SearchModal.errorScreen.titleText": { + "message": "Unable to fetch results", + "description": "The title for error screen of search modal" + }, + "theme.SearchModal.errorScreen.helpText": { + "message": "You might want to check your network connection.", + "description": "The help text for error screen of search modal" + }, + "theme.SearchModal.footer.selectText": { + "message": "to select", + "description": "The explanatory text of the action for the enter key" + }, + "theme.SearchModal.footer.selectKeyAriaLabel": { + "message": "Enter key", + "description": "The ARIA label for the Enter key button that makes the selection" + }, + "theme.SearchModal.footer.navigateText": { + "message": "to navigate", + "description": "The explanatory text of the action for the Arrow up and Arrow down key" + }, + "theme.SearchModal.footer.navigateUpKeyAriaLabel": { + "message": "Arrow up", + "description": "The ARIA label for the Arrow up key button that makes the navigation" + }, + "theme.SearchModal.footer.navigateDownKeyAriaLabel": { + "message": "Arrow down", + "description": "The ARIA label for the Arrow down key button that makes the navigation" + }, + "theme.SearchModal.footer.closeText": { + "message": "to close", + "description": "The explanatory text of the action for Escape key" + }, + "theme.SearchModal.footer.closeKeyAriaLabel": { + "message": "Escape key", + "description": "The ARIA label for the Escape key button that close the modal" + }, + "theme.SearchModal.footer.searchByText": { + "message": "Search by", + "description": "The text explain that the search is making by Algolia" + }, + "theme.SearchModal.noResultsScreen.noResultsText": { + "message": "No results for", + "description": "The text explains that there are no results for the following search" + }, + "theme.SearchModal.noResultsScreen.suggestedQueryText": { + "message": "Try searching for", + "description": "The text for the suggested query when no results are found for the following search" + }, + "theme.SearchModal.noResultsScreen.reportMissingResultsText": { + "message": "Believe this query should return results?", + "description": "The text for the question where the user thinks there are missing results" + }, + "theme.SearchModal.noResultsScreen.reportMissingResultsLinkText": { + "message": "Let us know.", + "description": "The text for the link to report missing results" + }, + "theme.SearchModal.placeholder": { + "message": "Search docs", + "description": "The placeholder of the input of the DocSearch pop-up modal" + }, + "theme.docs.sidebar.closeSidebarButtonAriaLabel": { + "message": "Close navigation bar", + "description": "The ARIA label for close button of mobile sidebar" + }, + "theme.docs.sidebar.toggleSidebarButtonAriaLabel": { + "message": "Toggle navigation bar", + "description": "The ARIA label for hamburger menu button of mobile navigation" + }, + "theme.NavBar.navAriaLabel": { + "message": "Main", + "description": "The ARIA label for the main navigation" + }, + "theme.docs.sidebar.navAriaLabel": { + "message": "Docs sidebar", + "description": "The ARIA label for the sidebar navigation" + } +} diff --git a/website/i18n/de/docusaurus-plugin-content-blog/2021-09-27-v2-beta1-release-notes.mdx b/website/i18n/de/docusaurus-plugin-content-blog/2021-09-27-v2-beta1-release-notes.mdx new file mode 100644 index 000000000..d01b542b1 --- /dev/null +++ b/website/i18n/de/docusaurus-plugin-content-blog/2021-09-27-v2-beta1-release-notes.mdx @@ -0,0 +1,161 @@ +--- +slug: wails-v2-beta-for-windows +title: Wails v2 Beta for Windows +authors: + - leaanthony +tags: + - wails + - v2 +--- + +```mdx-code-block +<div class="text--center"> + <img + src={require("@site/static/img/wails.webp").default} + width="40%" + class="screenshot" + /> +</div> +<br /> +``` + +When I first announced Wails on Reddit, just over 2 years ago from a train in Sydney, I did not expect it to get much attention. A few days later, a prolific tech vlogger released a tutorial video, gave it a positive review and from that point on, interest in the project has skyrocketed. + +It was clear that people were excited about adding web frontends to their Go projects, and almost immediately pushed the project beyond the proof of concept that I had created. At the time, Wails used the [webview](https://github.com/webview/webview) project to handle the frontend, and the only option for Windows was the IE11 renderer. Many bug reports were rooted in this limitation: poor JavaScript/CSS support and no dev tools to debug it. This was a frustrating development experience but there wasn't much that could have been done to rectify it. + +For a long time, I'd firmly believed that Microsoft would eventually have to sort out their browser situation. The world was moving on, frontend development was booming and IE wasn't cutting it. When Microsoft announced the move to using Chromium as the basis for their new browser direction, I knew it was only a matter of time until Wails could use it, and move the Windows developer experience to the next level. + +Today, I am pleased to announce: **Wails v2 Beta for Windows**! There's a huge amount to unpack in this release, so grab a drink, take a seat and we'll begin... + +### No CGO Dependency! + +No, I'm not joking: _No_ _CGO_ _dependency_ 🤯! The thing about Windows is that, unlike MacOS and Linux, it doesn't come with a default compiler. In addition, CGO requires a mingw compiler and there's a ton of different installation options. Removing the CGO requirement has massively simplified setup, as well as making debugging an awful lot easier. Whilst I have put a fair bit of effort in getting this working, the majority of the credit should go to [John Chadwick](https://github.com/jchv) for not only starting a couple of projects to make this possible, but also being open to someone taking those projects and building on them. Credit also to [Tad Vizbaras](https://github.com/tadvi) whose [winc](https://github.com/tadvi/winc) project started me down this path. + +### WebView2 Chromium Renderer + +```mdx-code-block +<div class="text--center"> + <img + src={require("@site/static/img/devtools.png").default} + width="75%" + class="screenshot" + /> +</div> +<br /> +``` + +Finally, Windows developers get a first class rendering engine for their applications! Gone are the days of contorting your frontend code to work on Windows. On top of that, you get a first-class developer tools experience! + +The WebView2 component does, however, have a requirement to have the `WebView2Loader.dll` sitting alongside the binary. This makes distribution just that little bit more painful than we gophers are used to. All solutions and libraries (that I know of) that use WebView2 have this dependency. + +However, I'm really excited to announce that Wails applications _have no such requirement_! Thanks to the wizardry of [John Chadwick](https://github.com/jchv), we are able to bundle this dll inside the binary and get Windows to load it as if it were present on disk. + +Gophers rejoice! The single binary dream lives on! + +### New Features + +```mdx-code-block +<div class="text--center"> + <img + src={require("@site/static/img/wails-menus.webp").default} + width="60%" + class="screenshot" + /> +</div> +<br /> +``` + +There were a lot of requests for native menu support. Wails has finally got you covered. Application menus are now available and include support for most native menu features. This includes standard menu items, checkboxes, radio groups, submenus and separators. + +There were a huge number of requests in v1 for the ability to have greater control of the window itself. I'm happy to announce that there's new runtime APIs specifically for this. It's feature-rich and supports multi-monitor configurations. There is also an improved dialogs API: Now, you can have modern, native dialogs with rich configuration to cater for all your dialog needs. + +There is now the option to generate IDE configuration along with your project. This means that if you open your project in a supported IDE, it will already be configured for building and debugging your application. Currently VSCode is supported but we hope to support other IDEs such as Goland soon. + +```mdx-code-block +<div class="text--center"> + <img + src={require("@site/static/img/vscode.webp").default} + width="100%" + class="screenshot" + /> +</div> +<br /> +``` + +### No requirement to bundle assets + +A huge pain-point of v1 was the need to condense your entire application down to single JS & CSS files. I'm happy to announce that for v2, there is no requirement to bundle assets, in any way, shape or form. Want to load a local image? Use an `<img>` tag with a local src path. Want to use a cool font? Copy it in and add the path to it in your CSS. + +> Wow, that sounds like a webserver... + +Yes, it works just like a webserver, except it isn't. + +> So how do I include my assets? + +You just pass a single `embed.FS` that contains all your assets into your application configuration. They don't even need to be in the top directory - Wails will just work it out for you. + +### New Development Experience + +```mdx-code-block +<div class="text--center"> + <img + src={require("@site/static/img/browser.webp").default} + width="60%" + class="screenshot" + /> +</div> +<br /> +``` + +Now that assets don't need to be bundled, it's enabled a whole new development experience. The new `wails dev` command will build and run your application, but instead of using the assets in the `embed.FS`, it loads them directly from disk. + +It also provides the additional features: + +- Hot reload - Any changes to frontend assets will trigger and auto reload of the application frontend +- Auto rebuild - Any changes to your Go code will rebuild and relaunch your application + +In addition to this, a webserver will start on port 34115. This will serve your application to any browser that connects to it. All connected web browsers will respond to system events like hot reload on asset change. + +In Go, we are used to dealing with structs in our applications. It's often useful to send structs to our frontend and use them as state in our application. In v1, this was a very manual process and a bit of a burden on the developer. I'm happy to announce that in v2, any application run in dev mode will automatically generate TypeScript models for all structs that are input or output parameters to bound methods. This enables seamless interchange of data models between the two worlds. + +In addition to this, another JS module is dynamically generated wrapping all your bound methods. This provides JSDoc for your methods, providing code completion and hinting in your IDE. It's really cool when you get data models auto-imported when hitting tab in an auto-generated module wrapping your Go code! + +### Remote Templates + +```mdx-code-block +<div class="text--center"> + <img + src={require("@site/static/img/remote.webp").default} + width="60%" + class="screenshot" + /> +</div> +<br /> +``` + +Getting an application up and running quickly was always a key goal for the Wails project. When we launched, we tried to cover a lot of the modern frameworks at the time: react, vue and angular. The world of frontend development is very opinionated, fast moving and hard to keep on top of! As a result, we found our base templates getting out of date pretty quickly and this caused a maintenance headache. It also meant that we didn't have cool modern templates for the latest and greatest tech stacks. + +With v2, I wanted to empower the community by giving you the ability to create and host templates yourselves, rather than rely on the Wails project. So now you can create projects using community supported templates! I hope this will inspire developers to create a vibrant ecosystem of project templates. I'm really quite excited about what our developer community can create! + +### In Conclusion + +Wails v2 represents a new foundation for the project. The aim of this release is to get feedback on the new approach, and to iron out any bugs before a full release. Your input would be most welcome. Please direct any feedback to the [v2 Beta](https://github.com/wailsapp/wails/discussions/828) discussion board. + +There were many twists and turns, pivots and u-turns to get to this point. This was due partly to early technical decisions that needed changing, and partly because some core problems we had spent time building workarounds for were fixed upstream: Go’s embed feature is a good example. Fortunately, everything came together at the right time, and today we have the very best solution that we can have. I believe the wait has been worth it - this would not have been possible even 2 months ago. + +I also need to give a huge thank you :pray: to the following people because without them, this release just wouldn't exist: + +- [Misite Bao](https://github.com/misitebao) - An absolute workhorse on the Chinese translations and an incredible bug finder. +- [John Chadwick](https://github.com/jchv) - His amazing work on [go-webview2](https://github.com/jchv/go-webview2) and [go-winloader](https://github.com/jchv/go-winloader) have made the Windows version we have today possible. +- [Tad Vizbaras](https://github.com/tadvi) - Experimenting with his [winc](https://github.com/tadvi/winc) project was the first step down the path to a pure Go Wails. +- [Mat Ryer](https://github.com/matryer) - His support, encouragement and feedback has really helped drive the project forward. + +And finally, I'd like to give a special thank you to all the [project sponsors](/credits#sponsors), including [JetBrains](https://www.jetbrains.com?from=Wails), whose support drive the project in many ways behind the scenes. + +I look forward to seeing what people build with Wails in this next exciting phase of the project! + +Lea. + +PS: MacOS and Linux users need not feel left out - porting to this new foundation is actively under way and most of the hard work has already been done. Hang in there! + +PPS: If you or your company find Wails useful, please consider [sponsoring the project](https://github.com/sponsors/leaanthony). Thanks! diff --git a/website/i18n/de/docusaurus-plugin-content-blog/2021-11-08-v2-beta2-release-notes.mdx b/website/i18n/de/docusaurus-plugin-content-blog/2021-11-08-v2-beta2-release-notes.mdx new file mode 100644 index 000000000..86d44616f --- /dev/null +++ b/website/i18n/de/docusaurus-plugin-content-blog/2021-11-08-v2-beta2-release-notes.mdx @@ -0,0 +1,170 @@ +--- +slug: wails-v2-beta-for-mac +title: Wails v2 Beta for MacOS +authors: + - leaanthony +tags: + - wails + - v2 +--- + +```mdx-code-block +<div class="text--center"> + <img + src={require("@site/static/img/wails-mac.webp").default} + width="60%" + class="screenshot" + /> +</div> +<br /> +``` + +Today marks the first beta release of Wails v2 for Mac! It's taken quite a while to get to this point and I'm hoping that today's release will give you something that's reasonably useful. There have been a number of twists and turns to get to this point and I'm hoping, with your help, to iron out the crinkles and get the Mac port polished for the final v2 release. + +You mean this isn't ready for production? For your use case, it may well be ready, but there are still a number of known issues so keep your eye on [this project board](https://github.com/wailsapp/wails/projects/7) and if you would like to contribute, you'd be very welcome! + +So what's new for Wails v2 for Mac vs v1? Hint: It's pretty similar to the Windows Beta :wink: + +### New Features + +```mdx-code-block +<div class="text--center"> + <img + src={require("@site/static/img/wails-menus-mac.webp").default} + width="80%" + class="screenshot" + /> +</div> +<br /> +``` + +There were a lot of requests for native menu support. Wails has finally got you covered. Application menus are now available and include support for most native menu features. This includes standard menu items, checkboxes, radio groups, submenus and separators. + +There were a huge number of requests in v1 for the ability to have greater control of the window itself. I'm happy to announce that there's new runtime APIs specifically for this. It's feature-rich and supports multi-monitor configurations. There is also an improved dialogs API: Now, you can have modern, native dialogs with rich configuration to cater for all your dialog needs. + +### Mac Specific Options + +In addition to the normal application options, Wails v2 for Mac also brings some Mac extras: + +- Make your window all funky and translucent, like all the pretty swift apps! +- Highly customisable titlebar +- We support the NSAppearance options for the application +- Simple config to auto-create an "About" menu + +### No requirement to bundle assets + +A huge pain-point of v1 was the need to condense your entire application down to single JS & CSS files. I'm happy to announce that for v2, there is no requirement to bundle assets, in any way, shape or form. Want to load a local image? Use an `<img>` tag with a local src path. Want to use a cool font? Copy it in and add the path to it in your CSS. + +> Wow, that sounds like a webserver... + +Yes, it works just like a webserver, except it isn't. + +> So how do I include my assets? + +You just pass a single `embed.FS` that contains all your assets into your application configuration. They don't even need to be in the top directory - Wails will just work it out for you. + +### New Development Experience + +Now that assets don't need to be bundled, it's enabled a whole new development experience. The new `wails dev` command will build and run your application, but instead of using the assets in the `embed.FS`, it loads them directly from disk. + +It also provides the additional features: + +- Hot reload - Any changes to frontend assets will trigger and auto reload of the application frontend +- Auto rebuild - Any changes to your Go code will rebuild and relaunch your application + +In addition to this, a webserver will start on port 34115. This will serve your application to any browser that connects to it. All connected web browsers will respond to system events like hot reload on asset change. + +In Go, we are used to dealing with structs in our applications. It's often useful to send structs to our frontend and use them as state in our application. In v1, this was a very manual process and a bit of a burden on the developer. I'm happy to announce that in v2, any application run in dev mode will automatically generate TypeScript models for all structs that are input or output parameters to bound methods. This enables seamless interchange of data models between the two worlds. + +In addition to this, another JS module is dynamically generated wrapping all your bound methods. This provides JSDoc for your methods, providing code completion and hinting in your IDE. It's really cool when you get data models auto-imported when hitting tab in an auto-generated module wrapping your Go code! + +### Remote Templates + +```mdx-code-block +<div class="text--center"> + <img + src={require("@site/static/img/remote-mac.webp").default} + width="80%" + class="screenshot" + /> +</div> +<br /> +``` + +Getting an application up and running quickly was always a key goal for the Wails project. When we launched, we tried to cover a lot of the modern frameworks at the time: react, vue and angular. The world of frontend development is very opinionated, fast moving and hard to keep on top of! As a result, we found our base templates getting out of date pretty quickly and this caused a maintenance headache. It also meant that we didn't have cool modern templates for the latest and greatest tech stacks. + +With v2, I wanted to empower the community by giving you the ability to create and host templates yourselves, rather than rely on the Wails project. So now you can create projects using community supported templates! I hope this will inspire developers to create a vibrant ecosystem of project templates. I'm really quite excited about what our developer community can create! + +### Native M1 Support + +Thanks to the amazing support of [Mat Ryer](https://github.com/matryer/), the Wails project now supports M1 native builds: + +```mdx-code-block +<div class="text--center"> + <img + src={require("@site/static/img/build-darwin-arm.webp").default} + width="80%" + class="screenshot" + /> +</div> +<br /> +``` + +You can also specify `darwin/amd64` as a target too: + +```mdx-code-block +<div class="text--center"> + <img + src={require("@site/static/img/build-darwin-amd.webp").default} + width="80%" + class="screenshot" + /> +</div> +<br /> +``` + +Oh, I almost forgot.... you can also do `darwin/universal`.... :wink: + +```mdx-code-block +<div class="text--center"> + <img + src={require("@site/static/img/build-darwin-universal.webp").default} + width="80%" + class="screenshot" + /> +</div> +<br /> +``` + +### Cross Compilation to Windows + +Because Wails v2 for Windows is pure Go, you can target Windows builds without docker. + +```mdx-code-block +<div class="text--center"> + <img + src={require("@site/static/img/build-cross-windows.webp").default} + width="80%" + class="screenshot" + /> +</div> +<br /> +``` + +### WKWebView Renderer + +V1 relied on a (now deprecated) WebView component. V2 uses the most recent WKWebKit component so expect the latest and greatest from Apple. + +### In Conclusion + +As I'd said in the Windows release notes, Wails v2 represents a new foundation for the project. The aim of this release is to get feedback on the new approach, and to iron out any bugs before a full release. Your input would be most welcome! Please direct any feedback to the [v2 Beta](https://github.com/wailsapp/wails/discussions/828) discussion board. + +And finally, I'd like to give a special thank you to all the [project sponsors](/credits#sponsors), including [JetBrains](https://www.jetbrains.com?from=Wails), whose support drive the project in many ways behind the scenes. + +I look forward to seeing what people build with Wails in this next exciting phase of the project! + +Lea. + +PS: Linux users, you're next! + +PPS: If you or your company find Wails useful, please consider [sponsoring the project](https://github.com/sponsors/leaanthony). Thanks! diff --git a/website/i18n/de/docusaurus-plugin-content-blog/2022-02-22-v2-beta3-release-notes.mdx b/website/i18n/de/docusaurus-plugin-content-blog/2022-02-22-v2-beta3-release-notes.mdx new file mode 100644 index 000000000..b405953cf --- /dev/null +++ b/website/i18n/de/docusaurus-plugin-content-blog/2022-02-22-v2-beta3-release-notes.mdx @@ -0,0 +1,114 @@ +--- +slug: wails-v2-beta-for-linux +title: Wails v2 Beta for Linux +authors: + - leaanthony +tags: + - wails + - v2 +--- + +```mdx-code-block +<div class="text--center"> + <img + src={require("@site/static/img/wails-linux.webp").default} + width="40%" + class="screenshot" + /> +</div> +<br /> +``` + +I'm pleased to finally announce that Wails v2 is now in beta for Linux! It is somewhat ironic that the very first experiments with v2 was on Linux and yet it has ended up as the last release. That being said, the v2 we have today is very different from those first experiments. So without further ado, let's go over the new features: + +### New Features + +```mdx-code-block +<div class="text--center"> + <img + src={require("@site/static/img/wails-menus-linux.webp").default} + width="50%" + class="screenshot" + /> +</div> +<br /> +``` + +There were a lot of requests for native menu support. Wails has finally got you covered. Application menus are now available and include support for most native menu features. This includes standard menu items, checkboxes, radio groups, submenus and separators. + +There were a huge number of requests in v1 for the ability to have greater control of the window itself. I'm happy to announce that there's new runtime APIs specifically for this. It's feature-rich and supports multi-monitor configurations. There is also an improved dialogs API: Now, you can have modern, native dialogs with rich configuration to cater for all your dialog needs. + +### No requirement to bundle assets + +A huge pain-point of v1 was the need to condense your entire application down to single JS & CSS files. I'm happy to announce that for v2, there is no requirement to bundle assets, in any way, shape or form. Want to load a local image? Use an `<img>` tag with a local src path. Want to use a cool font? Copy it in and add the path to it in your CSS. + +> Wow, that sounds like a webserver... + +Yes, it works just like a webserver, except it isn't. + +> So how do I include my assets? + +You just pass a single `embed.FS` that contains all your assets into your application configuration. They don't even need to be in the top directory - Wails will just work it out for you. + +### New Development Experience + +Now that assets don't need to be bundled, it's enabled a whole new development experience. The new `wails dev` command will build and run your application, but instead of using the assets in the `embed.FS`, it loads them directly from disk. + +It also provides the additional features: + +- Hot reload - Any changes to frontend assets will trigger and auto reload of the application frontend +- Auto rebuild - Any changes to your Go code will rebuild and relaunch your application + +In addition to this, a webserver will start on port 34115. This will serve your application to any browser that connects to it. All connected web browsers will respond to system events like hot reload on asset change. + +In Go, we are used to dealing with structs in our applications. It's often useful to send structs to our frontend and use them as state in our application. In v1, this was a very manual process and a bit of a burden on the developer. I'm happy to announce that in v2, any application run in dev mode will automatically generate TypeScript models for all structs that are input or output parameters to bound methods. This enables seamless interchange of data models between the two worlds. + +In addition to this, another JS module is dynamically generated wrapping all your bound methods. This provides JSDoc for your methods, providing code completion and hinting in your IDE. It's really cool when you get data models auto-imported when hitting tab in an auto-generated module wrapping your Go code! + +### Remote Templates + +```mdx-code-block +<div class="text--center"> + <img + src={require("@site/static/img/remote-linux.webp").default} + width="80%" + class="screenshot" + /> +</div> +<br /> +``` + +Getting an application up and running quickly was always a key goal for the Wails project. When we launched, we tried to cover a lot of the modern frameworks at the time: react, vue and angular. The world of frontend development is very opinionated, fast moving and hard to keep on top of! As a result, we found our base templates getting out of date pretty quickly and this caused a maintenance headache. It also meant that we didn't have cool modern templates for the latest and greatest tech stacks. + +With v2, I wanted to empower the community by giving you the ability to create and host templates yourselves, rather than rely on the Wails project. So now you can create projects using community supported templates! I hope this will inspire developers to create a vibrant ecosystem of project templates. I'm really quite excited about what our developer community can create! + +### Cross Compilation to Windows + +Because Wails v2 for Windows is pure Go, you can target Windows builds without docker. + +```mdx-code-block +<div class="text--center"> + <img + src={require("@site/static/img/linux-build-cross-windows.webp").default} + width="80%" + class="screenshot" + /> +</div> +<br /> +``` + +### In Conclusion + +As I'd said in the Windows release notes, Wails v2 represents a new foundation for the project. The aim of this release is to get feedback on the new approach, and to iron out any bugs before a full release. Your input would be most welcome! Please direct any feedback to the [v2 Beta](https://github.com/wailsapp/wails/discussions/828) discussion board. + +Linux is **hard** to support. We expect there to be a number of quirks with the beta. Please help us to help you by filing detailed bug reports! + +Finally, I'd like to give a special thank you to all the [project sponsors](/credits#sponsors) whose support drive the project in many ways behind the scenes. + +I look forward to seeing what people build with Wails in this next exciting phase of the project! + +Lea. + +PS: The v2 release isn't far off now! + +PPS: If you or your company find Wails useful, please consider [sponsoring the project](https://github.com/sponsors/leaanthony). Thanks! diff --git a/website/i18n/de/docusaurus-plugin-content-blog/2022-09-22-v2-release-notes.mdx b/website/i18n/de/docusaurus-plugin-content-blog/2022-09-22-v2-release-notes.mdx new file mode 100644 index 000000000..c321f5042 --- /dev/null +++ b/website/i18n/de/docusaurus-plugin-content-blog/2022-09-22-v2-release-notes.mdx @@ -0,0 +1,98 @@ +--- +slug: wails-v2-released +title: Wails v2 Released +authors: + - leaanthony +tags: + - wails + - v2 +--- + +```mdx-code-block +<div class="text--center"> + <img + src={require("@site/static/img/blog/montage.png").default} + width="75%" + /> +</div> +<br /> +``` + +# It's here! + +Today marks the release of [Wails](https://wails.io) v2. It's been about 18 months since the first v2 alpha and about a year from the first beta release. I'm truly grateful to everyone involved in the evolution of the project. + +Part of the reason it took that long was due to wanting to get to some definition of completeness before officially calling it v2. The truth is, there's never a perfect time to tag a release - there's always outstanding issues or "just one more" feature to squeeze in. What tagging an imperfect major release does do, however, is to provide a bit of stability for users of the project, as well as a bit of a reset for the developers. + +This release is more than I'd ever expected it to be. I hope it gives you as much pleasure as it has given us to develop it. + +# What _is_ Wails? + +If you are unfamiliar with Wails, it is a project that enables Go programmers to provide rich frontends for their Go programs using familiar web technologies. It's a lightweight, Go alternative to Electron. Much more information can be found on the [official site](https://wails.io/docs/introduction). + +# What's new? + +The v2 release is a huge leap forward for the project, addressing many of the pain points of v1. If you have not read any of the blog posts on the Beta releases for [macOS](/blog/wails-v2-beta-for-mac), [Windows](/blog/wails-v2-beta-for-windows) or [Linux](/blog/wails-v2-beta-for-linux), then I encourage you to do so as it covers all the major changes in more detail. In summary: + +- Webview2 component for Windows that supports modern web standards and debugging capabilities. +- [Dark / Light theme](/docs/reference/options#theme) + [custom theming](/docs/reference/options#customtheme) on Windows. +- Windows now has no CGO requirements. +- Out-of-the-box support for Svelte, Vue, React, Preact, Lit & Vanilla project templates. +- [Vite](https://vitejs.dev/) integration providing a hot-reload development environment for your application. +- Native application [menus](/docs/guides/application-development#application-menu) and [dialogs](/docs/reference/runtime/dialog). +- Native window translucency effects for [Windows](/docs/reference/options#windowistranslucent) and [macOS](/docs/reference/options#windowistranslucent-1). Support for Mica & Acrylic backdrops. +- Easily generate an [NSIS installer](/docs/guides/windows-installer) for Windows deployments. +- A rich [runtime library](/docs/reference/runtime/intro) providing utility methods for window manipulation, eventing, dialogs, menus and logging. +- Support for [obfuscating](/docs/guides/obfuscated) your application using [garble](https://github.com/burrowers/garble). +- Support for compressing your application using [UPX](https://upx.github.io/). +- Automatic TypeScript generation of Go structs. More info [here](/docs/howdoesitwork#calling-bound-go-methods). +- No extra libraries or DLLs are required to be shipped with your application. For any platform. +- No requirement to bundle frontend assets. Just develop your application like any other web application. + +# Credit & Thanks + +Getting to v2 has been a huge effort. There have been ~2.2K commits by 89 contributors between the initial alpha and the release today, and many, many more that have provided translations, testing, feedback and help on the discussion forums as well as the issue tracker. I'm so unbelievably grateful to each one of you. I'd also like to give an extra special thank you to all the project sponsors who have provided guidance, advice and feedback. Everything you do is hugely appreciated. + +There are a few people I'd like to give special mention to: + +Firstly, a **huge** thank you to [@stffabi](https://github.com/stffabi) who has provided so many contributions which we all benefit from, as well as providing a lot of support on many issues. He has provided some key features such as the external dev server support which transformed our dev mode offering by allowing us to hook into [Vite](https://vitejs.dev/)'s superpowers. It's fair to say that Wails v2 would be a far less exciting release without his [incredible contributions](https://github.com/wailsapp/wails/commits?author=stffabi&since=2020-01-04). Thank you so much @stffabi! + +I'd also like to give a huge shout-out to [@misitebao](https://github.com/misitebao) who has tirelessly been maintaining the website, as well as providing Chinese translations, managing Crowdin and helping new translators get up to speed. This is a hugely important task, and I'm extremely grateful for all the time and effort put into this! You rock! + +Last, but not least, a huge thank you to Mat Ryer who has provided advice and support during the development of v2. Writing xBar together using an early Alpha of v2 was helpful in shaping the direction of v2, as well as give me an understanding of some design flaws in the early releases. I'm happy to announce that as of today, we will start to port xBar to Wails v2, and it will become the flagship application for the project. Cheers Mat! + +# Lessons Learnt + +There are a number of lessons learnt in getting to v2 that will shape development moving forward. + +## Smaller, Quicker, Focused Releases + +In the course of developing v2, there were many features and bug fixes that were developed on an ad-hoc basis. This led to longer release cycles and were harder to debug. Moving forward, we are going to create releases more often that will include a reduced number of features. A release will involve updates to documentation as well as thorough testing. Hopefully, these smaller, quicker, focussed releases will lead to fewer regressions and better quality documentation. + +## Encourage Engagement + +When starting this project, I wanted to immediately help everyone who had a problem. Issues were "personal" and I wanted them resolved as quickly as possible. This is unsustainable and ultimately works against the longevity of the project. Moving forward, I will be giving more space for people to get involved in answering questions and triaging issues. It would be good to get some tooling to help with this so if you have any suggestions, please join in the discussion [here](https://github.com/wailsapp/wails/discussions/1855). + +## Learning to say No + +The more people that engage with an Open Source project, the more requests there will be for additional features that may or may not be useful to the majority of people. These features will take an initial amount of time to develop and debug, and incur an ongoing maintenance cost from that point on. I myself am the most guilty of this, often wanting to "boil the sea" rather than provide the minimum viable feature. Moving forward, we will need to say "No" a bit more to adding core features and focus our energies on a way to empower developers to provide that functionality themselves. We are looking seriously into plugins for this scenario. This will allow anyone to extend the project as they see fit, as well as providing an easy way to contribute towards the project. + +# Looking to the Future + +There are so many core features we are looking at to add to Wails in the next major development cycle already. The [roadmap](https://github.com/wailsapp/wails/discussions/1484) is full of interesting ideas, and I'm keen to start work on them. One of the big asks has been for multiple window support. It's a tricky one and to do it right, and we may need to look at providing an alternative API, as the current one was not designed with this in mind. Based on some preliminary ideas and feedback, I think you'll like where we're looking to go with it. + +I'm personally very excited at the prospect of getting Wails apps running on mobile. We already have a demo project showing that it is possible to run a Wails app on Android, so I'm really keen to explore where we can go with this! + +A final point I'd like to raise is that of feature parity. It has long been a core principle that we wouldn't add anything to the project without there being full cross-platform support for it. Whilst this has proven to be (mainly) achievable so far, it has really held the project back in releasing new features. Moving forward, we will be adopting a slightly different approach: any new feature that cannot be immediately released for all platforms will be released under an experimental configuration or API. This allows early adopters on certain platforms to try the feature and provide feedback that will feed into the final design of the feature. This, of course, means that there are no guarantees of API stability until it is fully supported by all the platforms it can be supported on, but at least it will unblock development. + +# Final Words + +I'm really proud of what we've been able to achieve with the V2 release. It's amazing to see what people have already been able to build using the beta releases so far. Quality applications like [Varly](https://varly.app/), [Surge](https://getsurge.io/) and [October](https://october.utf9k.net/). I encourage you to check them out. + +This release was achieved through the hard work of many contributors. Whilst it is free to download and use, it has not come about through zero cost. Make no mistakes, this project has come at considerable cost. It has not only been my time and the time of each and every contributor, but also the cost of absence from friends and families of each of those people too. That's why I'm extremely grateful for every second that has been dedicated to making this project happen. The more contributors we have, the more this effort can be spread out and the more we can achieve together. I'd like to encourage you all to pick one thing that you can contribute, whether it is confirming someone's bug, suggesting a fix, making a documentation change or helping out someone who needs it. All of these small things have such a huge impact! It would be so awesome if you too were part of the story in getting to v3. + +Enjoy! + +‐ Lea + +PS: If you or your company find Wails useful, please consider [sponsoring the project](https://github.com/sponsors/leaanthony). Thanks! diff --git a/website/i18n/de/docusaurus-plugin-content-blog/2023-01-17-v3-roadmap.mdx b/website/i18n/de/docusaurus-plugin-content-blog/2023-01-17-v3-roadmap.mdx new file mode 100644 index 000000000..9a137d09a --- /dev/null +++ b/website/i18n/de/docusaurus-plugin-content-blog/2023-01-17-v3-roadmap.mdx @@ -0,0 +1,184 @@ +--- +slug: the-road-to-wails-v3 +title: The Road to Wails v3 +authors: + - leaanthony +tags: + - wails + - v3 +--- + +```mdx-code-block +<div class="text--center"> + <img + src={require("@site/static/img/blog/multiwindow.webp").default} + width="90%" + /> +</div> +<br /> +``` + +# Introduction + +Wails is a project that simplifies the ability to write cross-platform desktop applications using Go. It uses native webview components for the frontend (not embedded browsers), bringing the power of the world's most popular UI system to Go, whilst remaining lightweight. + +Version 2 was released on the 22nd of September 2022 and brought with it a lot of enhancements including: + +- Live development, leveraging the popular Vite project +- Rich functionality for managing windows and creating menus +- Microsoft's WebView2 component +- Generation of Typescript models that mirror your Go structs +- Creating of NSIS Installer +- Obfuscated builds + +Right now, Wails v2 provides powerful tooling for creating rich, cross-platform desktop applications. + +This blog post aims to look at where the project is at right now and what we can improve on moving forward. + +# Where are we now? + +It's been incredible to see the popularity of Wails rising since the v2 release. I'm constantly amazed by the creativity of the community and the wonderful things that are being built with it. With more popularity, comes more eyes on the project. And with that, more feature requests and bug reports. + +Over time, I've been able to identify some of the most pressing issues facing the project. I've also been able to identify some of the things that are holding the project back. + +## Current issues + +I've identified the following areas that I feel are holding the project back: + +- The API +- Bindings generation +- The Build System + +### The API + +The API to build a Wails application currently consists of 2 parts: + +- The Application API +- The Runtime API + +The Application API famously has only 1 function: `Run()` which takes a heap of options which govern how the application will work. Whilst this is very simple to use, it is also very limiting. It is a "declarative" approach which hides a lot of the underlying complexity. For instance, there is no handle to the main window, so you can't interact with it directly. For that, you need to use the Runtime API. This is a problem when you start to want to do more complex things like create multiple windows. + +The Runtime API provides a lot of utility functions for the developer. This includes: + +- Window management +- Dialogs +- Menus +- Events +- Logs + +There are a number of things I am not happy with the Runtime API. The first is that it requires a "context" to be passed around. This is both frustrating and confusing for new developers who pass in a context and then get a runtime error. + +The biggest issue with the Runtime API is that it was designed for applications that only use a single window. Over time, the demand for multiple windows has grown and the API is not well suited to this. + +### Thoughts on the v3 API + +Wouldn't it be great if we could do something like this? + +```go +func main() { + app := wails.NewApplication(options.App{}) + myWindow := app.NewWindow(options.Window{}) + myWindow.SetTitle("My Window") + myWindow.On(events.Window.Close, func() { + app.Quit() + }) + app.Run() +} +``` + +This programmatic approach is far more intuitive and allows the developer to interact with the application elements directly. All current runtime methods for windows would simply be methods on the window object. For the other runtime methods, we could move them to the application object like so: + +```go +app := wails.NewApplication(options.App{}) +app.NewInfoDialog(options.InfoDialog{}) +app.Log.Info("Hello World") +``` + +This is a much more powerful API which will allow for more complex applications to be built. It also allows for the creation of multiple windows, [the most up-voted feature on GitHub](https://github.com/wailsapp/wails/issues/1480): + +```go +func main() { + app := wails.NewApplication(options.App{}) + myWindow := app.NewWindow(options.Window{}) + myWindow.SetTitle("My Window") + myWindow.On(events.Window.Close, func() { + app.Quit() + }) + myWindow2 := app.NewWindow(options.Window{}) + myWindow2.SetTitle("My Window 2") + myWindow2.On(events.Window.Close, func() { + app.Quit() + }) + app.Run() +} +``` + +### Bindings generation + +One of the key features of Wails is generating bindings for your Go methods so they may be called from Javascript. The current method for doing this is a bit of a hack. It involves building the application with a special flag and then running the resultant binary which uses reflection to determine what has been bound. This leads to a bit of a chicken and egg situation: You can't build the application without the bindings and you can't generate the bindings without building the application. There are many ways around this but the best one would be not to use this approach at all. + +There was a number of attempts at writing a static analyser for Wails projects but they didn't get very far. In more recent times, it has become slightly easier to do this with more material available on the subject. + +Compared to reflection, the AST approach is much faster however it is significantly more complicated. To start with, we may need to impose certain constraints on how to specify bindings in the code. The goal is to support the most common use cases and then expand it later on. + +### The Build System + +Like the declarative approach to the API, the build system was created to hide the complexities of building a desktop application. When you run `wails build`, it does a lot of things behind the scenes: +- Builds the backend binary for bindings and generates the bindings +- Installs the frontend dependencies +- Builds the frontend assets +- Determines if the application icon is present and if so, embeds it +- Builds the final binary +- If the build is for `darwin/universal` it builds 2 binaries, one for `darwin/amd64` and one for `darwin/arm64` and then creates a fat binary using `lipo` +- If compression is required, it compresses the binary with UPX +- Determines if this binary is to be packaged and if so: + - Ensures the icon and application manifest are compiled into the binary (Windows) + - Builds out the application bundle, generates the icon bundle and copies it, the binary and Info.plist to the application bundle (Mac) +- If an NSIS installer is required, it builds it + +This entire process, whilst very powerful, is also very opaque. It is very difficult to customise it and it is very difficult to debug. + +To address this in v3, I would like to move to a build system that exists outside of Wails. After using [Task](https://taskfile.dev/) for a while, I am a big fan of it. It is a great tool for configuring build systems and should be reasonably familiar to anyone who has used Makefiles. + +The build system would be configured using a `Taskfile.yml` file which would be generated by default with any of the supported templates. This would have all of the steps required to do all the current tasks, such as building or packaging the application, allowing for easy customisation. + +There will be no external requirement for this tooling as it would form part of the Wails CLI. This means that you can still use `wails build` and it will do all the things it does today. However, if you want to customise the build process, you can do so by editing the `Taskfile.yml` file. It also means you can easily understand the build steps and use your own build system if you wish. + +The missing piece in the build puzzle is the atomic operations in the build process, such as icon generation, compression and packaging. To require a bunch of external tooling would not be a great experience for the developer. To address this, the Wails CLI will provide all these capabilities as part of the CLI. This means that the builds still work as expected, with no extra external tooling, however you can replace any step of the build with any tool you like. + +This will be a much more transparent build system which will allow for easier customisation and address a lot of the issues that have been raised around it. + +## The Payoff + +These positive changes will be a huge benefit to the project: +- The new API will be much more intuitive and will allow for more complex applications to be built. +- Using static analysis for bindings generation will be much faster and reduce a lot of the complexity around the current process. +- Using an established, external build system will make the build process completely transparent, allowing for powerful customisation. + +Benefits to the project maintainers are: + +- The new API will be much easier to maintain and adapt to new features and platforms. +- The new build system will be much easier to maintain and extend. I hope this will lead to a new ecosystem of community driven build pipelines. +- Better separation of concerns within the project. This will make it easier to add new features and platforms. + +## The Plan + +A lot of the experimentation for this has already been done and it's looking good. There is no current timeline for this work but I'm hoping by the end of Q1 2023, there will be an alpha release for Mac to allow the community to test, experiment with and provide feedback. + +## Summary + +- The v2 API is declarative, hides a lot from the developer and not suitable for features such as multiple windows. A new API will be created which will be simpler, intuitive and more powerful. +- The build system is opaque and difficult to customise so we will move to an external build system which will open it all up. +- The bindings generation is slow and complex so we will move to static analysis which will remove a lot of the complexity the current method has. + +There has been a lot of work put into the guts of v2 and it's solid. It's now time to address the layer on top of it and make it a much better experience for the developer. + +I hope you are as excited about this as I am. I'm looking forward to hearing your thoughts and feedback. + +Regards, + +‐ Lea + +PS: If you or your company find Wails useful, please consider [sponsoring the project](https://github.com/sponsors/leaanthony). Thanks! + +PPS: Yes, that's a genuine screenshot of a multi-window application built with Wails. It's not a mockup. It's real. It's awesome. It's coming soon. \ No newline at end of file diff --git a/website/i18n/de/docusaurus-plugin-content-blog/authors.yml b/website/i18n/de/docusaurus-plugin-content-blog/authors.yml new file mode 100644 index 000000000..a1621fab6 --- /dev/null +++ b/website/i18n/de/docusaurus-plugin-content-blog/authors.yml @@ -0,0 +1,10 @@ +leaanthony: + name: Lea Anthony + title: Maintainer of Wails + url: https://github.com/leaanthony + image_url: https://github.com/leaanthony.png +misitebao: + name: Misite Bao + title: Architect + url: https://github.com/misitebao + image_url: https://github.com/misitebao.png diff --git a/website/i18n/de/docusaurus-plugin-content-blog/options.json b/website/i18n/de/docusaurus-plugin-content-blog/options.json new file mode 100644 index 000000000..9239ff706 --- /dev/null +++ b/website/i18n/de/docusaurus-plugin-content-blog/options.json @@ -0,0 +1,14 @@ +{ + "title": { + "message": "Blog", + "description": "The title for the blog used in SEO" + }, + "description": { + "message": "Blog", + "description": "The description for the blog used in SEO" + }, + "sidebar.title": { + "message": "Recent posts", + "description": "The label for the left sidebar" + } +} diff --git a/website/i18n/de/docusaurus-plugin-content-docs/current.json b/website/i18n/de/docusaurus-plugin-content-docs/current.json new file mode 100644 index 000000000..b4e63124d --- /dev/null +++ b/website/i18n/de/docusaurus-plugin-content-docs/current.json @@ -0,0 +1,38 @@ +{ + "version.label": { + "message": "Next Version 🚧", + "description": "The label for version current" + }, + "sidebar.docs.category.Getting Started": { + "message": "Getting Started", + "description": "The label for category Getting Started in sidebar docs" + }, + "sidebar.docs.category.Reference": { + "message": "Reference", + "description": "The label for category Reference in sidebar docs" + }, + "sidebar.docs.category.Runtime": { + "message": "Runtime", + "description": "The label for category Runtime in sidebar docs" + }, + "sidebar.docs.category.Community": { + "message": "Community", + "description": "The label for category Community in sidebar docs" + }, + "sidebar.docs.category.Showcase": { + "message": "Showcase", + "description": "The label for category Showcase in sidebar docs" + }, + "sidebar.docs.category.Guides": { + "message": "Guides", + "description": "The label for category Guides in sidebar docs" + }, + "sidebar.docs.category.Tutorials": { + "message": "Tutorials", + "description": "The label for category Tutorials in sidebar docs" + }, + "sidebar.docs.link.Contributing": { + "message": "Contributing", + "description": "The label for link Contributing in sidebar docs, linking to /community-guide#ways-of-contributing" + } +} diff --git a/website/i18n/de/docusaurus-plugin-content-docs/current/community/links.mdx b/website/i18n/de/docusaurus-plugin-content-docs/current/community/links.mdx new file mode 100644 index 000000000..e36a6edfe --- /dev/null +++ b/website/i18n/de/docusaurus-plugin-content-docs/current/community/links.mdx @@ -0,0 +1,26 @@ +--- +sidebar_position: 2 +--- + +# Links + +This page serves as a list for community related links. Please submit a PR (click `Edit this page` at the bottom) to submit links. + +## Awesome Wails + +The [definitive list](https://github.com/wailsapp/awesome-wails) of links related to Wails. + +## Support Channels + +- [Wails Discord Server](https://discord.gg/JDdSxwjhGf) +- [Github Issues](https://github.com/wailsapp/wails/issues) +- [v2 Beta Discussion Board](https://github.com/wailsapp/wails/discussions/828) + +## Social Media + +- [Twitter](https://twitter.com/wailsapp) +- [Wails Chinese Community QQ Group](https://qm.qq.com/cgi-bin/qm/qr?k=PmIURne5hFGNd7QWzW5qd6FV-INEjNJv&jump_from=webapi) - Group number: 1067173054 + +## Other Tutorials and Articles + +- [Building of Bulletin Board](https://blog.customct.com/building-bulletin-board) diff --git a/website/versioned_docs/version-v2.8.1/community/showcase/bulletinboard.mdx b/website/i18n/de/docusaurus-plugin-content-docs/current/community/showcase/bulletinboard.mdx similarity index 100% rename from website/versioned_docs/version-v2.8.1/community/showcase/bulletinboard.mdx rename to website/i18n/de/docusaurus-plugin-content-docs/current/community/showcase/bulletinboard.mdx diff --git a/website/versioned_docs/version-v2.8.1/community/showcase/cfntracker.mdx b/website/i18n/de/docusaurus-plugin-content-docs/current/community/showcase/cfntracker.mdx similarity index 100% rename from website/versioned_docs/version-v2.8.1/community/showcase/cfntracker.mdx rename to website/i18n/de/docusaurus-plugin-content-docs/current/community/showcase/cfntracker.mdx diff --git a/website/versioned_docs/version-v2.8.1/community/showcase/emailit.mdx b/website/i18n/de/docusaurus-plugin-content-docs/current/community/showcase/emailit.mdx similarity index 100% rename from website/versioned_docs/version-v2.8.1/community/showcase/emailit.mdx rename to website/i18n/de/docusaurus-plugin-content-docs/current/community/showcase/emailit.mdx diff --git a/website/versioned_docs/version-v2.8.1/community/showcase/encrypteasy.mdx b/website/i18n/de/docusaurus-plugin-content-docs/current/community/showcase/encrypteasy.mdx similarity index 100% rename from website/versioned_docs/version-v2.8.1/community/showcase/encrypteasy.mdx rename to website/i18n/de/docusaurus-plugin-content-docs/current/community/showcase/encrypteasy.mdx diff --git a/website/versioned_docs/version-v2.8.1/community/showcase/espstudio.mdx b/website/i18n/de/docusaurus-plugin-content-docs/current/community/showcase/espstudio.mdx similarity index 100% rename from website/versioned_docs/version-v2.8.1/community/showcase/espstudio.mdx rename to website/i18n/de/docusaurus-plugin-content-docs/current/community/showcase/espstudio.mdx diff --git a/website/i18n/de/docusaurus-plugin-content-docs/current/community/showcase/filehound.mdx b/website/i18n/de/docusaurus-plugin-content-docs/current/community/showcase/filehound.mdx new file mode 100644 index 000000000..bc569c3fe --- /dev/null +++ b/website/i18n/de/docusaurus-plugin-content-docs/current/community/showcase/filehound.mdx @@ -0,0 +1,16 @@ +# FileHound Export Utility + +```mdx-code-block +<p style={{ "text-align": "center" }}> + <img src={require("@site/static/img/showcase/filehound.webp").default} /> + <br /> +</p> +``` + +[FileHound Export Utility](https://www.filehound.co.uk/) FileHound is a cloud document management platform made for secure file retention, business process automation and SmartCapture capabilities. + +The FileHound Export Utility allows FileHound Administrators the ability to run a secure document and data extraction tasks for alternative back-up and recovery purposes. This application will download all documents and/or meta data saved in FileHound based on the filters you choose. The metadata will be exported in both JSON and XML formats. + +Backend built with: Go 1.15 Wails 1.11.0 go-sqlite3 1.14.6 go-linq 3.2 + +Frontend with: Vue 2.6.11 Vuex 3.4.0 TypeScript Tailwind 1.9.6 diff --git a/website/i18n/de/docusaurus-plugin-content-docs/current/community/showcase/grpcmd-gui.mdx b/website/i18n/de/docusaurus-plugin-content-docs/current/community/showcase/grpcmd-gui.mdx new file mode 100644 index 000000000..891350290 --- /dev/null +++ b/website/i18n/de/docusaurus-plugin-content-docs/current/community/showcase/grpcmd-gui.mdx @@ -0,0 +1,10 @@ +# grpcmd-gui + +```mdx-code-block +<p style={{ "text-align": "center" }}> + <img src={require("@site/static/img/showcase/grpcmd-gui.webp").default} /> + <br /> +</p> +``` + +[grpcmd-gui](https://grpc.md/gui) is a modern cross-platform desktop app and API client for gRPC development and testing. diff --git a/website/i18n/de/docusaurus-plugin-content-docs/current/community/showcase/hiposter.mdx b/website/i18n/de/docusaurus-plugin-content-docs/current/community/showcase/hiposter.mdx new file mode 100644 index 000000000..87e5837d3 --- /dev/null +++ b/website/i18n/de/docusaurus-plugin-content-docs/current/community/showcase/hiposter.mdx @@ -0,0 +1,10 @@ +# hiposter + +```mdx-code-block +<p style={{ "text-align": "center" }}> + <img src={require("@site/static/img/showcase/hiposter.webp").default} /> + <br /> +</p> +``` + +[hiposter](https://github.com/obity/hiposter) is a simple and efficient http API testing client tool. Based on Wails, Go and sveltejs. diff --git a/website/i18n/de/docusaurus-plugin-content-docs/current/community/showcase/kafka-king.mdx b/website/i18n/de/docusaurus-plugin-content-docs/current/community/showcase/kafka-king.mdx new file mode 100644 index 000000000..9876cd9a0 --- /dev/null +++ b/website/i18n/de/docusaurus-plugin-content-docs/current/community/showcase/kafka-king.mdx @@ -0,0 +1,23 @@ +# Kafka-King + +```mdx-code-block +<p style={{ "text-align": "center" }}> + <img src={require("@site/static/img/showcase/kafka-King-img_3.webp").default} /> + <br /> +</p> +``` + +[Kafka-King](https://github.com/Bronya0/Kafka-King) is a kafka GUI client that supports various systems and is compact and easy to use. +This is made of Wails+vue3 + +# Kafka-King function list + +- [x] View the cluster node list, support dynamic configuration of broker and topic configuration items +- [x] Supports consumer clients, consumes the specified topic, size, and timeout according to the specified group, and displays the message information in various dimensions in a table +- [x] Supports PLAIN, SSL, SASL, kerberos, sasl_plaintext, etc. etc. +- [x] Create topics (support batches), delete topics, specify replicas, partitions +- [x] Support statistics of the total number of messages, total number of submissions, and backlog for each topic based on consumer groups +- [x] Support viewing topics Detailed information (offset) of the partition, and support adding additional partitions +- [x] Support simulated producers, batch sending messages, specify headers, partitions +- [x] Health check +- [x] Support viewing consumer groups , Consumer- …… diff --git a/website/versioned_docs/version-v2.8.1/community/showcase/mchat.mdx b/website/i18n/de/docusaurus-plugin-content-docs/current/community/showcase/mchat.mdx similarity index 100% rename from website/versioned_docs/version-v2.8.1/community/showcase/mchat.mdx rename to website/i18n/de/docusaurus-plugin-content-docs/current/community/showcase/mchat.mdx diff --git a/website/versioned_docs/version-v2.8.1/community/showcase/minecraftupdater.mdx b/website/i18n/de/docusaurus-plugin-content-docs/current/community/showcase/minecraftupdater.mdx similarity index 100% rename from website/versioned_docs/version-v2.8.1/community/showcase/minecraftupdater.mdx rename to website/i18n/de/docusaurus-plugin-content-docs/current/community/showcase/minecraftupdater.mdx diff --git a/website/i18n/de/docusaurus-plugin-content-docs/current/community/showcase/minesweeper-xp.mdx b/website/i18n/de/docusaurus-plugin-content-docs/current/community/showcase/minesweeper-xp.mdx new file mode 100644 index 000000000..f127a005f --- /dev/null +++ b/website/i18n/de/docusaurus-plugin-content-docs/current/community/showcase/minesweeper-xp.mdx @@ -0,0 +1,10 @@ +# Minesweeper XP + +```mdx-code-block +<p style={{ "text-align": "center" }}> + <img src={require("@site/static/img/showcase/minesweeper-xp.webp").default} /> + <br /> +</p> +``` + +[Minesweeper-XP](https://git.new/Minesweeper-XP) allows you to experience the classic Minesweeper XP (+ 98 and 3.1) on macOS, Windows, and Linux! diff --git a/website/versioned_docs/version-v2.8.1/community/showcase/modalfilemanager.mdx b/website/i18n/de/docusaurus-plugin-content-docs/current/community/showcase/modalfilemanager.mdx similarity index 100% rename from website/versioned_docs/version-v2.8.1/community/showcase/modalfilemanager.mdx rename to website/i18n/de/docusaurus-plugin-content-docs/current/community/showcase/modalfilemanager.mdx diff --git a/website/versioned_docs/version-v2.8.1/community/showcase/mollywallet.mdx b/website/i18n/de/docusaurus-plugin-content-docs/current/community/showcase/mollywallet.mdx similarity index 100% rename from website/versioned_docs/version-v2.8.1/community/showcase/mollywallet.mdx rename to website/i18n/de/docusaurus-plugin-content-docs/current/community/showcase/mollywallet.mdx diff --git a/website/versioned_docs/version-v2.8.1/community/showcase/october.mdx b/website/i18n/de/docusaurus-plugin-content-docs/current/community/showcase/october.mdx similarity index 100% rename from website/versioned_docs/version-v2.8.1/community/showcase/october.mdx rename to website/i18n/de/docusaurus-plugin-content-docs/current/community/showcase/october.mdx diff --git a/website/versioned_docs/version-v2.8.1/community/showcase/optimus.mdx b/website/i18n/de/docusaurus-plugin-content-docs/current/community/showcase/optimus.mdx similarity index 100% rename from website/versioned_docs/version-v2.8.1/community/showcase/optimus.mdx rename to website/i18n/de/docusaurus-plugin-content-docs/current/community/showcase/optimus.mdx diff --git a/website/versioned_docs/version-v2.8.1/community/showcase/portfall.mdx b/website/i18n/de/docusaurus-plugin-content-docs/current/community/showcase/portfall.mdx similarity index 100% rename from website/versioned_docs/version-v2.8.1/community/showcase/portfall.mdx rename to website/i18n/de/docusaurus-plugin-content-docs/current/community/showcase/portfall.mdx diff --git a/website/i18n/de/docusaurus-plugin-content-docs/current/community/showcase/resizem.mdx b/website/i18n/de/docusaurus-plugin-content-docs/current/community/showcase/resizem.mdx new file mode 100644 index 000000000..27f168f48 --- /dev/null +++ b/website/i18n/de/docusaurus-plugin-content-docs/current/community/showcase/resizem.mdx @@ -0,0 +1,10 @@ +# Resizem + +```mdx-code-block +<p style={{ "text-align": "center" }}> + <img src={require("@site/static/img/showcase/resizem.webp").default} /> + <br /> +</p> +``` + +[Resizem](https://github.com/barats/resizem) - is an app designed for bulk image process. It is particularly useful for users who need to resize, convert, and manage large numbers of image files at once. diff --git a/website/versioned_docs/version-v2.8.1/community/showcase/restic-browser.mdx b/website/i18n/de/docusaurus-plugin-content-docs/current/community/showcase/restic-browser.mdx similarity index 100% rename from website/versioned_docs/version-v2.8.1/community/showcase/restic-browser.mdx rename to website/i18n/de/docusaurus-plugin-content-docs/current/community/showcase/restic-browser.mdx diff --git a/website/versioned_docs/version-v2.8.1/community/showcase/riftshare.mdx b/website/i18n/de/docusaurus-plugin-content-docs/current/community/showcase/riftshare.mdx similarity index 100% rename from website/versioned_docs/version-v2.8.1/community/showcase/riftshare.mdx rename to website/i18n/de/docusaurus-plugin-content-docs/current/community/showcase/riftshare.mdx diff --git a/website/versioned_docs/version-v2.8.1/community/showcase/scriptbar.mdx b/website/i18n/de/docusaurus-plugin-content-docs/current/community/showcase/scriptbar.mdx similarity index 100% rename from website/versioned_docs/version-v2.8.1/community/showcase/scriptbar.mdx rename to website/i18n/de/docusaurus-plugin-content-docs/current/community/showcase/scriptbar.mdx diff --git a/website/versioned_docs/version-v2.8.1/community/showcase/snippetexpander.mdx b/website/i18n/de/docusaurus-plugin-content-docs/current/community/showcase/snippetexpander.mdx similarity index 100% rename from website/versioned_docs/version-v2.8.1/community/showcase/snippetexpander.mdx rename to website/i18n/de/docusaurus-plugin-content-docs/current/community/showcase/snippetexpander.mdx diff --git a/website/versioned_docs/version-v2.8.1/community/showcase/surge.mdx b/website/i18n/de/docusaurus-plugin-content-docs/current/community/showcase/surge.mdx similarity index 100% rename from website/versioned_docs/version-v2.8.1/community/showcase/surge.mdx rename to website/i18n/de/docusaurus-plugin-content-docs/current/community/showcase/surge.mdx diff --git a/website/versioned_docs/version-v2.8.1/community/showcase/tinyrdm.mdx b/website/i18n/de/docusaurus-plugin-content-docs/current/community/showcase/tinyrdm.mdx similarity index 100% rename from website/versioned_docs/version-v2.8.1/community/showcase/tinyrdm.mdx rename to website/i18n/de/docusaurus-plugin-content-docs/current/community/showcase/tinyrdm.mdx diff --git a/website/i18n/de/docusaurus-plugin-content-docs/current/community/showcase/wailsterm.mdx b/website/i18n/de/docusaurus-plugin-content-docs/current/community/showcase/wailsterm.mdx new file mode 100644 index 000000000..9924dace5 --- /dev/null +++ b/website/i18n/de/docusaurus-plugin-content-docs/current/community/showcase/wailsterm.mdx @@ -0,0 +1,10 @@ +# WailsTerm + +```mdx-code-block +<p style={{ "text-align": "center" }}> + <img src={require("@site/static/img/showcase/wailsterm.webp").default} /> + <br /> +</p> +``` + +[WailsTerm](https://github.com/rlshukhov/wailsterm) is a simple translucent terminal app powered by Wails and Xterm.js. diff --git a/website/versioned_docs/version-v2.8.1/community/showcase/wally.mdx b/website/i18n/de/docusaurus-plugin-content-docs/current/community/showcase/wally.mdx similarity index 100% rename from website/versioned_docs/version-v2.8.1/community/showcase/wally.mdx rename to website/i18n/de/docusaurus-plugin-content-docs/current/community/showcase/wally.mdx diff --git a/website/i18n/de/docusaurus-plugin-content-docs/current/community/showcase/warmine.mdx b/website/i18n/de/docusaurus-plugin-content-docs/current/community/showcase/warmine.mdx new file mode 100644 index 000000000..950dc3f3d --- /dev/null +++ b/website/i18n/de/docusaurus-plugin-content-docs/current/community/showcase/warmine.mdx @@ -0,0 +1,19 @@ +# Minecraft launcher for WarMine + +```mdx-code-block +<p style={{ "text-align": "center" }}> + <img + src={require("@site/static/img/showcase/warmine1.png").default} + /> + <img + src={require("@site/static/img/showcase/warmine2.png").default} + /> + <br /> +</p> +``` + +[Minecraft launcher for WarMine](https://warmine.ru/) is a Wails application, that allows you to easily join modded game servers and manage your game accounts. + +The Launcher downloads the game files, checks their integrity and launches the game with a wide range of customization options for the launch arguments from the backend. + +Frontend is written in Svelte, whole launcher fits in 9MB and supports Windows 7-11. diff --git a/website/versioned_docs/version-v2.8.1/community/showcase/wombat.mdx b/website/i18n/de/docusaurus-plugin-content-docs/current/community/showcase/wombat.mdx similarity index 100% rename from website/versioned_docs/version-v2.8.1/community/showcase/wombat.mdx rename to website/i18n/de/docusaurus-plugin-content-docs/current/community/showcase/wombat.mdx diff --git a/website/versioned_docs/version-v2.8.1/community/showcase/ytd.mdx b/website/i18n/de/docusaurus-plugin-content-docs/current/community/showcase/ytd.mdx similarity index 100% rename from website/versioned_docs/version-v2.8.1/community/showcase/ytd.mdx rename to website/i18n/de/docusaurus-plugin-content-docs/current/community/showcase/ytd.mdx diff --git a/website/i18n/de/docusaurus-plugin-content-docs/current/community/templates.mdx b/website/i18n/de/docusaurus-plugin-content-docs/current/community/templates.mdx new file mode 100644 index 000000000..fb95b8ad9 --- /dev/null +++ b/website/i18n/de/docusaurus-plugin-content-docs/current/community/templates.mdx @@ -0,0 +1,76 @@ +--- +sidebar_position: 1 +--- + +# Templates + +This page serves as a list for community supported templates. Please submit a PR (click `Edit this page` at the bottom) to include your templates. To build your own template, please see the [Templates](../guides/templates.mdx) guide. + +To use these templates, run `wails init -n "Your Project Name" -t [the link below[@version]]` + +If there is no version suffix, the main branch code template is used by default. If there is a version suffix, the code template corresponding to the tag of this version is used. + +Example: `wails init -n "Your Project Name" -t https://github.com/misitebao/wails-template-vue` + +:::warning Attention + +**The Wails project does not maintain, is not responsible nor liable for 3rd party templates!** + +If you are unsure about a template, inspect `package.json` and `wails.json` for what scripts are run and what packages are installed. + +::: + +## Vue + +- [wails-template-vue](https://github.com/misitebao/wails-template-vue) - Wails template based on Vue ecology (Integrated TypeScript, Dark theme, Internationalization, Single page routing, TailwindCSS) +- [wails-template-quasar-js](https://github.com/sgosiaco/wails-template-quasar-js) - A template using JavaScript + Quasar V2 (Vue 3, Vite, Sass, Pinia, ESLint, Prettier) +- [wails-template-quasar-ts](https://github.com/sgosiaco/wails-template-quasar-ts) - A template using TypeScript + Quasar V2 (Vue 3, Vite, Sass, Pinia, ESLint, Prettier, Composition API with <script setup>) +- [wails-template-naive](https://github.com/tk103331/wails-template-naive) - Wails template based on Naive UI (A Vue 3 Component Library) +- [wails-template-tdesign-js](https://github.com/tongque0/wails-template-tdesign-js) - Wails template based on TDesign UI (a Vue 3 UI library by Tencent), using Vite, Pinia, Vue Router, ESLint, and Prettier. + +## Angular + +- [wails-template-angular](https://github.com/mateothegreat/wails-template-angular) - Angular 15+ action packed & ready to roll to production. +- [wails-angular-template](https://github.com/TAINCER/wails-angular-template) - Angular with TypeScript, Sass, Hot-Reload, Code-Splitting and i18n + +## React + +- [wails-react-template](https://github.com/AlienRecall/wails-react-template) - A template using reactjs +- [wails-react-template](https://github.com/flin7/wails-react-template) - A minimal template for React that supports live development +- [wails-template-nextjs](https://github.com/LGiki/wails-template-nextjs) - A template using Next.js and TypeScript +- [wails-template-nextjs-app-router](https://github.com/thisisvk-in/wails-template-nextjs-app-router) - A template using Next.js and TypeScript with App router +- [wails-vite-react-ts-tailwind-template](https://github.com/hotafrika/wails-vite-react-ts-tailwind-template) - A template for React + TypeScript + Vite + TailwindCSS +- [wails-vite-react-ts-tailwind-shadcnui-template](https://github.com/Mahcks/wails-vite-react-tailwind-shadcnui-ts) - A template with Vite, React, TypeScript, TailwindCSS, and shadcn/ui +- [wails-nextjs-tailwind-template](https://github.com/kairo913/wails-nextjs-tailwind-template) - A template using Next.js and Typescript with TailwindCSS + +## Svelte + +- [wails-svelte-template](https://github.com/raitonoberu/wails-svelte-template) - A template using Svelte +- [wails-vite-svelte-template](https://github.com/BillBuilt/wails-vite-svelte-template) - A template using Svelte and Vite +- [wails-vite-svelte-ts-tailwind-template](https://github.com/xvertile/wails-vite-svelte-tailwind-template) - A template using Wails, Svelte, Vite, TypeScript, and TailwindCSS v3 +- [wails-vite-svelte-tailwind-template](https://github.com/BillBuilt/wails-vite-svelte-tailwind-template) - A template using Svelte and Vite with TailwindCSS v3 +- [wails-svelte-tailwind-vite-template](https://github.com/PylotLight/wails-vite-svelte-tailwind-template/tree/master) - An updated template using Svelte v4.2.0 and Vite with TailwindCSS v3.3.3 +- [wails-sveltekit-template](https://github.com/h8gi/wails-sveltekit-template) - A template using SvelteKit + +## Solid + +- [wails-template-vite-solid-ts](https://github.com/xijaja/wails-template-solid-ts) - A template using Solid + Ts + Vite +- [wails-template-vite-solid-js](https://github.com/xijaja/wails-template-solid-js) - A template using Solid + Js + Vite + +## Elm + +- [wails-elm-template](https://github.com/benjamin-thomas/wails-elm-template) - Develop your GUI app with functional programming and a **snappy** hot-reload setup :tada: :rocket: +- [wails-template-elm-tailwind](https://github.com/rnice01/wails-template-elm-tailwind) - Combine the powers :muscle: of Elm + Tailwind CSS + Wails! Hot reloading supported. + +## HTMX + +- [wails-htmx-templ-chi-tailwind](https://github.com/PylotLight/wails-hmtx-templ-template) - Use a unique combination of pure htmx for interactivity plus templ for creating components and forms + +## Pure JavaScript (Vanilla) + +- [wails-pure-js-template](https://github.com/KiddoV/wails-pure-js-template) - A template with nothing but just basic JavaScript, HTML, and CSS + + +## Lit (web components) + +- [wails-lit-shoelace-esbuild-template](https://github.com/Braincompiler/wails-lit-shoelace-esbuild-template) - Wails template providing frontend with lit, Shoelace component library + pre-configured prettier and typescript. diff --git a/website/i18n/de/docusaurus-plugin-content-docs/current/gettingstarted/building.mdx b/website/i18n/de/docusaurus-plugin-content-docs/current/gettingstarted/building.mdx new file mode 100644 index 000000000..6dbe1cfd0 --- /dev/null +++ b/website/i18n/de/docusaurus-plugin-content-docs/current/gettingstarted/building.mdx @@ -0,0 +1,26 @@ +--- +sidebar_position: 6 +--- + +# Compiling your Project + +From the project directory, run `wails build`. This will compile your project and save the production-ready binary in the `build/bin` directory. + +:::info Linux +If you are using a Linux distribution that does not have webkit2gtk-4.0 (such as Ubuntu 24.04), you will need to add `-tags webkit2_41`. +::: + +If you run the binary, you should see the default application: + +```mdx-code-block +<div class="text--center"> + <img + src={require("@site/static/img/defaultproject.webp").default} + width="50%" + class="screenshot" + /> +</div> +<br /> +``` + +For more details on compilation options, please refer to the [CLI Reference](../reference/cli.mdx#build). diff --git a/website/versioned_docs/version-v2.8.1/gettingstarted/development.mdx b/website/i18n/de/docusaurus-plugin-content-docs/current/gettingstarted/development.mdx similarity index 100% rename from website/versioned_docs/version-v2.8.1/gettingstarted/development.mdx rename to website/i18n/de/docusaurus-plugin-content-docs/current/gettingstarted/development.mdx diff --git a/website/i18n/de/docusaurus-plugin-content-docs/current/gettingstarted/firstproject.mdx b/website/i18n/de/docusaurus-plugin-content-docs/current/gettingstarted/firstproject.mdx new file mode 100644 index 000000000..e7cc86163 --- /dev/null +++ b/website/i18n/de/docusaurus-plugin-content-docs/current/gettingstarted/firstproject.mdx @@ -0,0 +1,128 @@ +--- +sidebar_position: 2 +--- + +# Creating a Project + +## Project Generation + +Now that the CLI is installed, you can generate a new project by using the `wails init` command. + +Pick your favourite framework: + +```mdx-code-block +import Tabs from "@theme/Tabs"; +import TabItem from "@theme/TabItem"; + +<Tabs + defaultValue="Svelte" + values={[ + {label: "Svelte", value: "Svelte"}, + {label: "React", value: "React"}, + {label: "Vue", value: "Vue"}, + {label: "Preact", value: "Preact"}, + {label: "Lit", value: "Lit"}, + {label: "Vanilla", value: "Vanilla"}, + ]} +> +<TabItem value="Svelte"> + Generate a <a href={"https://svelte.dev/"}>Svelte</a> project using JavaScript with:<br/><br/> + + wails init -n myproject -t svelte + +If you would rather use TypeScript:<br/> + + wails init -n myproject -t svelte-ts + +</TabItem> +<TabItem value="React"> + Generate a <a href={"https://reactjs.org/"}>React</a> project using JavaScript with:<br/><br/> + + wails init -n myproject -t react + +If you would rather use TypeScript:<br/> + + wails init -n myproject -t react-ts + +</TabItem> +<TabItem value="Vue"> + Generate a <a href={"https://vuejs.org/"}>Vue</a> project using JavaScript with:<br/><br/> + + wails init -n myproject -t vue + +If you would rather use TypeScript:<br/> + + wails init -n myproject -t vue-ts + +</TabItem> +<TabItem value="Preact"> + Generate a <a href={"https://preactjs.com/"}>Preact</a> project using JavaScript with:<br/><br/> + + wails init -n myproject -t preact + +If you would rather use TypeScript:<br/> + + wails init -n myproject -t preact-ts + +</TabItem> +<TabItem value="Lit"> + Generate a <a href={"https://lit.dev/"}>Lit</a> project using JavaScript with:<br/><br/> + + wails init -n myproject -t lit + +If you would rather use TypeScript:<br/> + + wails init -n myproject -t lit-ts + +</TabItem> +<TabItem value="Vanilla"> + Generate a Vanilla project using JavaScript with:<br/><br/> + + wails init -n myproject -t vanilla + +If you would rather use TypeScript:<br/> + + wails init -n myproject -t vanilla-ts + +</TabItem> +</Tabs> +``` + +<hr /> + +There are also [community templates](../community/templates.mdx) available that offer different capabilities and frameworks. + +To see the other options available, you can run `wails init -help`. More details can be found in the [CLI Reference](../reference/cli.mdx#init). + +## Project Layout + +Wails projects have the following layout: + +``` +. +├── build/ +│ ├── appicon.png +│ ├── darwin/ +│ └── windows/ +├── frontend/ +├── go.mod +├── go.sum +├── main.go +└── wails.json +``` + +### Project structure rundown + +- `/main.go` - The main application +- `/frontend/` - Frontend project files +- `/build/` - Project build directory +- `/build/appicon.png` - The application icon +- `/build/darwin/` - Mac specific project files +- `/build/windows/` - Windows specific project files +- `/wails.json` - The project configuration +- `/go.mod` - Go module file +- `/go.sum` - Go module checksum file + +The `frontend` directory has nothing specific to Wails and can be any frontend project of your choosing. + +The `build` directory is used during the build process. These files may be updated to customise your builds. If files are removed from the build directory, default versions will be regenerated. diff --git a/website/i18n/de/docusaurus-plugin-content-docs/current/gettingstarted/installation.mdx b/website/i18n/de/docusaurus-plugin-content-docs/current/gettingstarted/installation.mdx new file mode 100644 index 000000000..028b167da --- /dev/null +++ b/website/i18n/de/docusaurus-plugin-content-docs/current/gettingstarted/installation.mdx @@ -0,0 +1,92 @@ +--- +sidebar_position: 1 +--- + +# Installation + +## Supported Platforms + +- Windows 10/11 AMD64/ARM64 +- MacOS 10.15+ AMD64 for development, MacOS 10.13+ for release +- MacOS 11.0+ ARM64 +- Linux AMD64/ARM64 + +## Dependencies + +Wails has a number of common dependencies that are required before installation: + +- Go 1.21+ (macOS 15+ requires Go 1.23.3+) +- NPM (Node 15+) + +### Go + +Download Go from the [Go Downloads Page](https://go.dev/dl/). + +Ensure that you follow the official [Go installation instructions](https://go.dev/doc/install). You will also need to ensure that your `PATH` environment variable also includes the path to your `~/go/bin` directory. Restart your terminal and do the following checks: + +- Check Go is installed correctly: `go version` +- Check "~/go/bin" is in your PATH variable: `echo $PATH | grep go/bin` + +### NPM + +Download NPM from the [Node Downloads Page](https://nodejs.org/en/download/). It is best to use the latest release as that is what we generally test against. + +Run `npm --version` to verify. + +## Platform Specific Dependencies + +You will also need to install platform specific dependencies: + +```mdx-code-block +import Tabs from "@theme/Tabs"; +import TabItem from "@theme/TabItem"; + +<Tabs + defaultValue="Windows" + values={[ + { label: "Windows", value: "Windows" }, + { label: "MacOS", value: "MacOS" }, + { label: "Linux", value: "Linux" }, + ]} +> + <TabItem value="MacOS"> + Wails requires that the xcode command line tools are installed. This can be + done by running <code>xcode-select --install</code>. + </TabItem> + <TabItem value="Windows"> + Wails requires that the <a href="https://developer.microsoft.com/en-us/microsoft-edge/webview2/">WebView2</a> runtime is installed. Some Windows installations will already have this installed. You can check using the <code>wails doctor</code> command. + </TabItem> + <TabItem value={"Linux"}> + Linux requires the standard <code>gcc</code> build tools plus <code>libgtk3</code> and <code>libwebkit</code>. Rather than list a ton of commands for different distros, Wails can try to determine what the installation commands are for your specific distribution. Run <code>wails doctor</code> after installation to be shown how to install the dependencies. If your distro/package manager is not supported, please consult the <a href={"/docs/guides/linux-distro-support"}>Add Linux Distro</a> guide. + <br/><strong>Note:</strong><br/> + If you are using latest Linux version (example: Ubuntu 24.04) and it is not supporting <code>libwebkit2gtk-4.0-dev</code>, then you might encounter an issue in <code>wails doctor</code>: <code>libwebkit</code> not found. To resolve this issue you can install <code>libwebkit2gtk-4.1-dev</code> and during your build use the tag <code>-tags webkit2_41</code>. + </TabItem> +</Tabs> +``` + +## Optional Dependencies + +- [UPX](https://upx.github.io/) for compressing your applications. +- [NSIS](https://wails.io/docs/guides/windows-installer/) for generating Windows installers. + +## Installing Wails + +Run `go install github.com/wailsapp/wails/v2/cmd/wails@latest` to install the Wails CLI. + +Note: If you get an error similar to this: + +```shell +....\Go\pkg\mod\github.com\wailsapp\wails\v2@v2.1.0\pkg\templates\templates.go:28:12: pattern all:ides/*: no matching files found +``` +please check you have Go 1.18+ installed: +```shell +go version +``` + +## System Check + +Running `wails doctor` will check if you have the correct dependencies installed. If not, it will advise on what is missing and help on how to rectify any problems. + +## The `wails` command appears to be missing? + +If your system is reporting that the `wails` command is missing, make sure you have followed the Go installation guide correctly. Normally, it means that the `go/bin` directory in your User's home directory is not in the `PATH` environment variable. You will also normally need to close and reopen any open command prompts so that changes to the environment made by the installer are reflected at the command prompt. diff --git a/website/i18n/de/docusaurus-plugin-content-docs/current/guides/angular.mdx b/website/i18n/de/docusaurus-plugin-content-docs/current/guides/angular.mdx new file mode 100644 index 000000000..2b6c5a845 --- /dev/null +++ b/website/i18n/de/docusaurus-plugin-content-docs/current/guides/angular.mdx @@ -0,0 +1,14 @@ +# Angular + +Whilst Wails does not have an Angular template, it is possible to use Angular with Wails. + +## Dev Mode + +To get dev mode working with Angular, you need to add the following to your `wails.json`: + +```json + "frontend:build": "npx ng build", + "frontend:install": "npm install", + "frontend:dev:watcher": "npx ng serve", + "frontend:dev:serverUrl": "http://localhost:4200", +``` \ No newline at end of file diff --git a/website/i18n/de/docusaurus-plugin-content-docs/current/guides/application-development.mdx b/website/i18n/de/docusaurus-plugin-content-docs/current/guides/application-development.mdx new file mode 100644 index 000000000..687b89791 --- /dev/null +++ b/website/i18n/de/docusaurus-plugin-content-docs/current/guides/application-development.mdx @@ -0,0 +1,273 @@ +# Application Development + +There are no hard and fast rules for developing applications with Wails, but there are some basic guidelines. + +## Application Setup + +The pattern used by the default templates are that `main.go` is used for configuring and running the application, whilst `app.go` is used for defining the application logic. + +The `app.go` file will define a struct that has 2 methods which act as hooks into the main application: + +```go title="app.go" +type App struct { + ctx context.Context +} + +func NewApp() *App { + return &App{} +} + +func (a *App) startup(ctx context.Context) { + a.ctx = ctx +} + +func (a *App) shutdown(ctx context.Context) { +} +``` + +- The startup method is called as soon as Wails allocates the resources it needs and is a good place for creating resources, setting up event listeners and anything else the application needs at startup. It is given a `context.Context` which is usually saved in a struct field. This context is needed for calling the [runtime](../reference/runtime/intro.mdx). If this method returns an error, the application will terminate. In dev mode, the error will be output to the console. + +- The shutdown method will be called by Wails right at the end of the shutdown process. This is a good place to deallocate memory and perform any shutdown tasks. + +The `main.go` file generally consists of a single call to `wails.Run()`, which accepts the application configuration. The pattern used by the templates is that before the call to `wails.Run()`, an instance of the struct we defined in `app.go` is created and saved in a variable called `app`. This configuration is where we add our callbacks: + +```go {3,9,10} title="main.go" +func main() { + + app := NewApp() + + err := wails.Run(&options.App{ + Title: "My App", + Width: 800, + Height: 600, + OnStartup: app.startup, + OnShutdown: app.shutdown, + }) + if err != nil { + log.Fatal(err) + } +} + +``` + +More information on application lifecycle hooks can be found [here](../howdoesitwork.mdx#application-lifecycle-callbacks). + +## Binding Methods + +It is likely that you will want to call Go methods from the frontend. This is normally done by adding public methods to the already defined struct in `app.go`: + +```go {16-18} title="app.go" +type App struct { + ctx context.Context +} + +func NewApp() *App { + return &App{} +} + +func (a *App) startup(ctx context.Context) { + a.ctx = ctx +} + +func (a *App) shutdown(ctx context.Context) { +} + +func (a *App) Greet(name string) string { + return fmt.Sprintf("Hello %s!", name) +} +``` + +In the main application configuration, the `Bind` key is where we can tell Wails what we want to bind: + +```go {11-13} title="main.go" +func main() { + + app := NewApp() + + err := wails.Run(&options.App{ + Title: "My App", + Width: 800, + Height: 600, + OnStartup: app.startup, + OnShutdown: app.shutdown, + Bind: []interface{}{ + app, + }, + }) + if err != nil { + log.Fatal(err) + } +} + +``` + +This will bind all public methods in our `App` struct (it will never bind the startup and shutdown methods). + +### Dealing with context when binding multiple structs + +If you want to bind methods for multiple structs but want each struct to keep a reference to the context so that you can use the runtime functions, a good pattern is to pass the context from the `OnStartup` method to your struct instances : + +```go +func main() { + + app := NewApp() + otherStruct := NewOtherStruct() + + err := wails.Run(&options.App{ + Title: "My App", + Width: 800, + Height: 600, + OnStartup: func(ctx context.Context){ + app.SetContext(ctx) + otherStruct.SetContext(ctx) + }, + OnShutdown: app.shutdown, + Bind: []interface{}{ + app, + otherStruct + }, + }) + if err != nil { + log.Fatal(err) + } +} +``` + +Also you might want to use Enums in your structs and have models for them on frontend. In that case you should create array that will contain all possible enum values, instrument enum type and bind it to the app: + +```go {16-18} title="app.go" +type Weekday string + +const ( + Sunday Weekday = "Sunday" + Monday Weekday = "Monday" + Tuesday Weekday = "Tuesday" + Wednesday Weekday = "Wednesday" + Thursday Weekday = "Thursday" + Friday Weekday = "Friday" + Saturday Weekday = "Saturday" +) + +var AllWeekdays = []struct { + Value Weekday + TSName string +}{ + {Sunday, "SUNDAY"}, + {Monday, "MONDAY"}, + {Tuesday, "TUESDAY"}, + {Wednesday, "WEDNESDAY"}, + {Thursday, "THURSDAY"}, + {Friday, "FRIDAY"}, + {Saturday, "SATURDAY"}, +} +``` + +In the main application configuration, the `EnumBind` key is where we can tell Wails what we want to bind enums as well: + +```go {11-13} title="main.go" +func main() { + + app := NewApp() + + err := wails.Run(&options.App{ + Title: "My App", + Width: 800, + Height: 600, + OnStartup: app.startup, + OnShutdown: app.shutdown, + Bind: []interface{}{ + app, + }, + EnumBind: []interface{}{ + AllWeekdays, + }, + }) + if err != nil { + log.Fatal(err) + } +} + +``` + +This will add missing enums to your `model.ts` file. + +More information on Binding can be found [here](../howdoesitwork.mdx#method-binding). + +## Application Menu + +Wails supports adding a menu to your application. This is done by passing a [Menu](../reference/menus.mdx#menu) struct to application config. It's common to use a method that returns a Menu, and even more common for that to be a method on the `App` struct used for the lifecycle hooks. + +```go {11} title="main.go" +func main() { + + app := NewApp() + + err := wails.Run(&options.App{ + Title: "My App", + Width: 800, + Height: 600, + OnStartup: app.startup, + OnShutdown: app.shutdown, + Menu: app.menu(), + Bind: []interface{}{ + app, + }, + }) + if err != nil { + log.Fatal(err) + } +} + +``` + +## Assets + +The great thing about the way Wails v2 handles assets is that it doesn't! The only thing you need to give Wails is an `embed.FS`. How you get to that is entirely up to you. You can use vanilla html/css/js files like the vanilla template. You could have some complicated build system, it doesn't matter. + +When `wails build` is run, it will check the `wails.json` project file at the project root. There are 2 keys in the project file that are read: + +- "frontend:install" +- "frontend:build" + +The first, if given, will be executed in the `frontend` directory to install the node modules. The second, if given, will be executed in the `frontend` directory to build the frontend project. + +If these 2 keys aren't given, then Wails does absolutely nothing with the frontend. It is only expecting that `embed.FS`. + +### AssetsHandler + +A Wails v2 app can optionally define a `http.Handler` in the `options.App`, which allows hooking into the AssetServer to create files on the fly or process POST/PUT requests. GET requests are always first handled by the `assets` FS. If the FS doesn't find the requested file the request will be forwarded to the `http.Handler` for serving. Any requests other than GET will be directly processed by the `AssetsHandler` if specified. It's also possible to only use the `AssetsHandler` by specifying `nil` as the `Assets` option. + +## Built in Dev Server + +Running `wails dev` will start the built in dev server which will start a file watcher in your project directory. By default, if any file changes, wails checks if it was an application file (default: `.go`, configurable with `-e` flag). If it was, then it will rebuild your application and relaunch it. If the changed file was in the assets, it will issue a reload after a short amount of time. + +The dev server uses a technique called "debouncing" which means it doesn't reload straight away, as there may be multiple files changed in a short amount of time. When a trigger occurs, it waits for a set amount of time before issuing a reload. If another trigger happens, it resets to the wait time again. By default this value is `100ms`. If this value doesn't work for your project, it can be configured using the `-debounce` flag. If used, this value will be saved to your project config and become the default. + +## External Dev Server + +Some frameworks come with their own live-reloading server, however they will not be able to take advantage of the Wails Go bindings. In this scenario, it is best to run a watcher script that rebuilds the project into the build directory, which Wails will be watching. For an example, see the default svelte template that uses [rollup](https://rollupjs.org/guide/en/). + +### Create React App + +The process for a Create-React-App project is slightly more complicated. In order to support live frontend reloading the following configuration needs to be added to your `wails.json`: + +```json + "frontend:dev:watcher": "yarn start", + "frontend:dev:serverUrl": "http://localhost:3000", +``` + +The `frontend:dev:watcher` command will start the Create-React-App development server (hosted on port `3000` typically). The `frontend:dev:serverUrl` command then instructs Wails to serve assets from the development server when loading the frontend rather than from the build folder. In addition to the above, the `index.html` needs to be updated with the following: + +```html + <head> + <meta name="wails-options" content="noautoinject" /> + <script src="/wails/ipc.js"></script> + <script src="/wails/runtime.js"></script> + </head> +``` + +This is required as the watcher command that rebuilds the frontend prevents Wails from injecting the required scripts. This circumvents that issue by ensuring the scripts are always injected. With this configuration, `wails dev` can be run which will appropriately build the frontend and backend with hot-reloading enabled. Additionally, when accessing the application from a browser the React developer tools can now be used on a non-minified version of the application for straightforward debugging. Finally, for faster builds, `wails dev -s` can be run to skip the default building of the frontend by Wails as this is an unnecessary step. + +## Go Module + +The default Wails templates generate a `go.mod` file that contains the module name "changeme". You should change this to something more appropriate after project generation. diff --git a/website/i18n/de/docusaurus-plugin-content-docs/current/guides/crossplatform-build.mdx b/website/i18n/de/docusaurus-plugin-content-docs/current/guides/crossplatform-build.mdx new file mode 100644 index 000000000..e7ea6dfc8 --- /dev/null +++ b/website/i18n/de/docusaurus-plugin-content-docs/current/guides/crossplatform-build.mdx @@ -0,0 +1,66 @@ +# Crossplatform build with Github Actions + +To build a Wails project for all the available platforms, you need to create an application build for each operating system. One effective method to achieve this is by utilizing GitHub Actions. + +An action that facilitates building a Wails app is available at: +https://github.com/dAppServer/wails-build-action + +In case the existing action doesn't fulfill your requirements, you can select only the necessary steps from the source: +https://github.com/dAppServer/wails-build-action/blob/main/action.yml + +Below is a comprehensive example that demonstrates building an app upon the creation of a new Git tag and subsequently uploading it to the Actions artifacts: + +```yaml +name: Wails build + +on: + push: + tags: + # Match any new tag + - '*' + +env: + # Necessary for most environments as build failure can occur due to OOM issues + NODE_OPTIONS: "--max-old-space-size=4096" + +jobs: + build: + strategy: + # Failure in one platform build won't impact the others + fail-fast: false + matrix: + build: + - name: 'App' + platform: 'linux/amd64' + os: 'ubuntu-latest' + - name: 'App' + platform: 'windows/amd64' + os: 'windows-latest' + - name: 'App' + platform: 'darwin/universal' + os: 'macos-latest' + + runs-on: ${{ matrix.build.os }} + steps: + - name: Checkout + uses: actions/checkout@v2 + with: + submodules: recursive + + - name: Build wails + uses: dAppServer/wails-build-action@v2.2 + id: build + with: + build-name: ${{ matrix.build.name }} + build-platform: ${{ matrix.build.platform }} + package: false + go-version: '1.20' +``` + +This example offers opportunities for various enhancements, including: + +- Caching dependencies +- Code signing +- Uploading to platforms like S3, Supabase, etc. +- Injecting secrets as environment variables +- Utilizing environment variables as build variables (such as version variable extracted from the current Git tag) diff --git a/website/i18n/de/docusaurus-plugin-content-docs/current/guides/custom-protocol-schemes.mdx b/website/i18n/de/docusaurus-plugin-content-docs/current/guides/custom-protocol-schemes.mdx new file mode 100644 index 000000000..3dccf4e3c --- /dev/null +++ b/website/i18n/de/docusaurus-plugin-content-docs/current/guides/custom-protocol-schemes.mdx @@ -0,0 +1,204 @@ +# Custom Protocol Scheme association + +Custom Protocols feature allows you to associate specific custom protocol with your app so that when users open links with this protocol, +your app is launched to handle them. This can be particularly useful to connect your desktop app with your web app. +In this guide, we'll walk through the steps to implement custom protocols in Wails app. + +## Set Up Custom Protocol Schemes Association: + +To set up custom protocol, you need to modify your application's wails.json file. +In "info" section add a "protocols" section specifying the protocols your app should be associated with. + +For example: + +```json +{ + "info": { + "protocols": [ + { + "scheme": "myapp", + "description": "My App Protocol", + "role": "Editor" + } + ] + } +} +``` + +| Property | Description | +| :---------- | :------------------------------------------------------------------------------------ | +| scheme | Custom Protocol scheme. e.g. myapp | +| description | Windows-only. The description. | +| role | macOS-only. The app’s role with respect to the type. Corresponds to CFBundleTypeRole. | + +## Platform Specifics: + +### macOS + +When you open custom protocol with your app, the system will launch your app and call the `OnUrlOpen` function in your Wails app. Example: + +```go title="main.go" +func main() { + // Create application with options + err := wails.Run(&options.App{ + Title: "wails-open-file", + Width: 1024, + Height: 768, + AssetServer: &assetserver.Options{ + Assets: assets, + }, + BackgroundColour: &options.RGBA{R: 27, G: 38, B: 54, A: 1}, + Mac: &mac.Options{ + OnUrlOpen: func(url string) { println(url) }, + }, + Bind: []interface{}{ + app, + }, + }) + + if err != nil { + println("Error:", err.Error()) + } +} +``` + +### Windows + +On Windows Custom Protocol Schemes is supported only with NSIS installer. During installation, the installer will create a +registry entry for your schemes. When you open url with your app, new instance of app is launched and url is passed +as argument to your app. To handle this you should parse command line arguments in your app. Example: + +```go title="main.go" +func main() { + argsWithoutProg := os.Args[1:] + + if len(argsWithoutProg) != 0 { + println("launchArgs", argsWithoutProg) + } +} +``` + +You also can enable single instance lock for your app. In this case, when you open url with your app, new instance of app is not launched +and arguments are passed to already running instance. Check single instance lock guide for details. Example: + +```go title="main.go" +func main() { + // Create application with options + err := wails.Run(&options.App{ + Title: "wails-open-file", + Width: 1024, + Height: 768, + AssetServer: &assetserver.Options{ + Assets: assets, + }, + BackgroundColour: &options.RGBA{R: 27, G: 38, B: 54, A: 1}, + SingleInstanceLock: &options.SingleInstanceLock{ + UniqueId: "e3984e08-28dc-4e3d-b70a-45e961589cdc", + OnSecondInstanceLaunch: app.onSecondInstanceLaunch, + }, + Bind: []interface{}{ + app, + }, + }) +} +``` + +### Linux + +Currently, Wails doesn't support bundling for Linux. So, you need to create file associations manually. +For example if you distribute your app as a .deb package, you can create file associations by adding required files in you bundle. +You can use [nfpm](https://nfpm.goreleaser.com/) to create .deb package for your app. + +1. Create a .desktop file for your app and specify file associations there (note that `%u` is important in Exec). Example: + +```ini +[Desktop Entry] +Categories=Office +Exec=/usr/bin/wails-open-file %u +Icon=wails-open-file.png +Name=wails-open-file +Terminal=false +Type=Application +MimeType=x-scheme-handler/myapp; +``` + +2. Prepare postInstall/postRemove scripts for your package. Example: + +```sh +# reload desktop database to load app in list of available +update-desktop-database /usr/share/applications +``` + +3. Configure nfpm to use your scripts and files. Example: + +```yaml +name: "wails-open-file" +arch: "arm64" +platform: "linux" +version: "1.0.0" +section: "default" +priority: "extra" +maintainer: "FooBarCorp <FooBarCorp@gmail.com>" +description: "Sample Package" +vendor: "FooBarCorp" +homepage: "http://example.com" +license: "MIT" +contents: +- src: ../bin/wails-open-file + dst: /usr/bin/wails-open-file +- src: ./main.desktop + dst: /usr/share/applications/wails-open-file.desktop +- src: ../appicon.svg + dst: /usr/share/icons/hicolor/scalable/apps/wails-open-file.svg +# copy icons to Yaru theme as well. For some reason Ubuntu didn't pick up fileicons from hicolor theme +- src: ../appicon.svg + dst: /usr/share/icons/Yaru/scalable/apps/wails-open-file.svg +scripts: + postinstall: ./postInstall.sh + postremove: ./postRemove.sh +``` + +6. Build your .deb package using nfpm: + +```sh +nfpm pkg --packager deb --target . +``` + +7. Now when your package is installed, your app will be associated with custom protocol scheme. When you open url with your app, + new instance of app is launched and file path is passed as argument to your app. + To handle this you should parse command line arguments in your app. Example: + +```go title="main.go" +func main() { + argsWithoutProg := os.Args[1:] + + if len(argsWithoutProg) != 0 { + println("launchArgs", argsWithoutProg) + } +} +``` + +You also can enable single instance lock for your app. In this case, when you open url with your app, new instance of app is not launched +and arguments are passed to already running instance. Check single instance lock guide for details. Example: + +```go title="main.go" +func main() { + // Create application with options + err := wails.Run(&options.App{ + Title: "wails-open-file", + Width: 1024, + Height: 768, + AssetServer: &assetserver.Options{ + Assets: assets, + }, + BackgroundColour: &options.RGBA{R: 27, G: 38, B: 54, A: 1}, + SingleInstanceLock: &options.SingleInstanceLock{ + UniqueId: "e3984e08-28dc-4e3d-b70a-45e961589cdc", + OnSecondInstanceLaunch: app.onSecondInstanceLaunch, + }, + Bind: []interface{}{ + app, + }, + }) +} +``` diff --git a/website/i18n/de/docusaurus-plugin-content-docs/current/guides/dynamic-assets.mdx b/website/i18n/de/docusaurus-plugin-content-docs/current/guides/dynamic-assets.mdx new file mode 100644 index 000000000..242276641 --- /dev/null +++ b/website/i18n/de/docusaurus-plugin-content-docs/current/guides/dynamic-assets.mdx @@ -0,0 +1,142 @@ +# Dynamic Assets + +:::info + +This does not work with vite v5.0.0+ and wails v2 due to changes in vite. Changes are planned in v3 to support similar functionality under vite v5.0.0+. If you need this feature, stay with vite v4.0.0+. See [issue 3240](https://github.com/wailsapp/wails/issues/3240) for details + +::: + +If you want to load or generate assets for your frontend dynamically, you can achieve that using the [AssetsHandler](../reference/options#assetshandler) option. The AssetsHandler is a generic `http.Handler` which will be called for any non GET request on the assets server and for GET requests which can not be served from the bundled assets because the file is not found. + +By installing a custom AssetsHandler, you can serve your own assets using a custom asset server. + +## Example + +In our example project, we will create a simple assets handler which will load files off disk: + +```go title=main.go {17-36,49} +package main + +import ( + "embed" + "fmt" + "github.com/wailsapp/wails/v2" + "github.com/wailsapp/wails/v2/pkg/options" + "github.com/wailsapp/wails/v2/pkg/options/assetserver" + "net/http" + "os" + "strings" +) + +//go:embed all:frontend/dist +var assets embed.FS + +type FileLoader struct { + http.Handler +} + +func NewFileLoader() *FileLoader { + return &FileLoader{} +} + +func (h *FileLoader) ServeHTTP(res http.ResponseWriter, req *http.Request) { + var err error + requestedFilename := strings.TrimPrefix(req.URL.Path, "/") + println("Requesting file:", requestedFilename) + fileData, err := os.ReadFile(requestedFilename) + if err != nil { + res.WriteHeader(http.StatusBadRequest) + res.Write([]byte(fmt.Sprintf("Could not load file %s", requestedFilename))) + } + + res.Write(fileData) +} + +func main() { + // Create an instance of the app structure + app := NewApp() + + // Create application with options + err := wails.Run(&options.App{ + Title: "helloworld", + Width: 1024, + Height: 768, + AssetServer: &assetserver.Options{ + Assets: assets, + Handler: NewFileLoader(), + }, + BackgroundColour: &options.RGBA{R: 27, G: 38, B: 54, A: 255}, + OnStartup: app.startup, + Bind: []interface{}{ + app, + }, + }) + + if err != nil { + println("Error:", err) + } +} +``` + +When we run the application in dev mode using `wails dev`, we will see the following output: + +``` +DEB | [ExternalAssetHandler] Loading 'http://localhost:3001/favicon.ico' +DEB | [ExternalAssetHandler] Loading 'http://localhost:3001/favicon.ico' failed, using AssetHandler +Requesting file: favicon.ico +``` + +As you can see, the assets handler is called when the default assets server is unable to serve the `favicon.ico` file. + +If you right click the main application and select "inspect" to bring up the devtools, you can test this feature out by typing the following into the console: + +``` +let response = await fetch('does-not-exist.txt'); +``` + +This will generate an error in the devtools. We can see that the error is what we expect, returned by our custom assets handler: + +```mdx-code-block +<p className="text--center"> + <img + src={require("@site/static/img/assetshandler-does-not-exist.webp").default} + /> +</p> +``` + +However, if we request `go.mod`, we will see the following output: + +```mdx-code-block +<p className="text--center"> + <img src={require("@site/static/img/assetshandler-go-mod.webp").default} /> +</p> +``` + +This technique can be used to load images directly into the page. If we updated our default vanilla template and replaced the logo image: + +```html +<img id="logo" class="logo" /> +``` + +with: + +```html +<img src="build/appicon.png" style="width: 300px" /> +``` + +Then we would see the following: + +```mdx-code-block +<p className="text--center"> + <img + src={require("@site/static/img/assetshandler-image.webp").default} + style={{ width: "75%" }} + /> +</p> +``` + +:::warning + +Exposing your filesystem in this way is a security risk. It is recommended that you properly manage access to your filesystem. + +::: diff --git a/website/i18n/de/docusaurus-plugin-content-docs/current/guides/file-association.mdx b/website/i18n/de/docusaurus-plugin-content-docs/current/guides/file-association.mdx new file mode 100644 index 000000000..15c6bbfcf --- /dev/null +++ b/website/i18n/de/docusaurus-plugin-content-docs/current/guides/file-association.mdx @@ -0,0 +1,244 @@ +# File Association + +File association feature allows you to associate specific file types with your app so that when users open those files, +your app is launched to handle them. This can be particularly useful for text editors, image viewers, or any application +that works with specific file formats. In this guide, we'll walk through the steps to implement file association in Wails app. + +## Set Up File Association: + +To set up file association, you need to modify your application's wails.json file. +In "info" section add a "fileAssociations" section specifying the file types your app should be associated with. + +For example: + +```json +{ + "info": { + "fileAssociations": [ + { + "ext": "wails", + "name": "Wails", + "description": "Wails Application File", + "iconName": "wailsFileIcon", + "role": "Editor" + }, + { + "ext": "jpg", + "name": "JPEG", + "description": "Image File", + "iconName": "jpegFileIcon", + "role": "Editor" + } + ] + } +} +``` + +| Property | Description | +| :---------- | :------------------------------------------------------------------------------------------------------------------------------------------------- | +| ext | The extension (minus the leading period). e.g. png | +| name | The name. e.g. PNG File | +| iconName | The icon name without extension. Icons should be located in build folder. Proper icons will be generated from .png file for both macOS and Windows | +| description | Windows-only. The description. It is displayed on the `Type` column on Windows Explorer. | +| role | macOS-only. The app’s role with respect to the type. Corresponds to CFBundleTypeRole. | + +## Platform Specifics: + +### macOS + +When you open file (or files) with your app, the system will launch your app and call the `OnFileOpen` function in your Wails app. Example: + +```go title="main.go" +func main() { + // Create application with options + err := wails.Run(&options.App{ + Title: "wails-open-file", + Width: 1024, + Height: 768, + AssetServer: &assetserver.Options{ + Assets: assets, + }, + BackgroundColour: &options.RGBA{R: 27, G: 38, B: 54, A: 1}, + Mac: &mac.Options{ + OnFileOpen: func(filePaths []string) { println(filestring) }, + }, + Bind: []interface{}{ + app, + }, + }) + + if err != nil { + println("Error:", err.Error()) + } +} +``` + +### Windows + +On Windows file association is supported only with NSIS installer. During installation, the installer will create a +registry entry for your file associations. When you open file with your app, new instance of app is launched and file path is passed +as argument to your app. To handle this you should parse command line arguments in your app. Example: + +```go title="main.go" +func main() { + argsWithoutProg := os.Args[1:] + + if len(argsWithoutProg) != 0 { + println("launchArgs", argsWithoutProg) + } +} +``` + +You also can enable single instance lock for your app. In this case, when you open file with your app, new instance of app is not launched +and arguments are passed to already running instance. Check single instance lock guide for details. Example: + +```go title="main.go" +func main() { + // Create application with options + err := wails.Run(&options.App{ + Title: "wails-open-file", + Width: 1024, + Height: 768, + AssetServer: &assetserver.Options{ + Assets: assets, + }, + BackgroundColour: &options.RGBA{R: 27, G: 38, B: 54, A: 1}, + SingleInstanceLock: &options.SingleInstanceLock{ + UniqueId: "e3984e08-28dc-4e3d-b70a-45e961589cdc", + OnSecondInstanceLaunch: app.onSecondInstanceLaunch, + }, + Bind: []interface{}{ + app, + }, + }) +} +``` + +### Linux + +Currently, Wails doesn't support bundling for Linux. So, you need to create file associations manually. +For example if you distribute your app as a .deb package, you can create file associations by adding required files in you bundle. +You can use [nfpm](https://nfpm.goreleaser.com/) to create .deb package for your app. + +1. Create a .desktop file for your app and specify file associations there. Example: + +```ini +[Desktop Entry] +Categories=Office +Exec=/usr/bin/wails-open-file %u +Icon=wails-open-file.png +Name=wails-open-file +Terminal=false +Type=Application +MimeType=application/x-wails;application/x-test +``` + +2. Create mime types file. Example: + +```xml +<?xml version="1.0" encoding="UTF-8"?> +<mime-info xmlns="http://www.freedesktop.org/standards/shared-mime-info"> + <mime-type type="application/x-wails"> + <comment>Wails Application File</comment> + <glob pattern="*.wails"/> + </mime-type> +</mime-info> +``` + +3. Create icons for your file types. SVG icons are recommended. +4. Prepare postInstall/postRemove scripts for your package. Example: + +```sh +# reload mime types to register file associations +update-mime-database /usr/share/mime +# reload desktop database to load app in list of available +update-desktop-database /usr/share/applications +# update icons +update-icon-caches /usr/share/icons/* +``` + +5. Configure nfpm to use your scripts and files. Example: + +```yaml +name: "wails-open-file" +arch: "arm64" +platform: "linux" +version: "1.0.0" +section: "default" +priority: "extra" +maintainer: "FooBarCorp <FooBarCorp@gmail.com>" +description: "Sample Package" +vendor: "FooBarCorp" +homepage: "http://example.com" +license: "MIT" +contents: +- src: ../bin/wails-open-file + dst: /usr/bin/wails-open-file +- src: ./main.desktop + dst: /usr/share/applications/wails-open-file.desktop +- src: ./application-wails-mime.xml + dst: /usr/share/mime/packages/application-x-wails.xml +- src: ./application-test-mime.xml + dst: /usr/share/mime/packages/application-x-test.xml +- src: ../appicon.svg + dst: /usr/share/icons/hicolor/scalable/apps/wails-open-file.svg +- src: ../wailsFileIcon.svg + dst: /usr/share/icons/hicolor/scalable/mimetypes/application-x-wails.svg +- src: ../testFileIcon.svg + dst: /usr/share/icons/hicolor/scalable/mimetypes/application-x-test.svg +# copy icons to Yaru theme as well. For some reason Ubuntu didn't pick up fileicons from hicolor theme +- src: ../appicon.svg + dst: /usr/share/icons/Yaru/scalable/apps/wails-open-file.svg +- src: ../wailsFileIcon.svg + dst: /usr/share/icons/Yaru/scalable/mimetypes/application-x-wails.svg +- src: ../testFileIcon.svg + dst: /usr/share/icons/Yaru/scalable/mimetypes/application-x-test.svg +scripts: + postinstall: ./postInstall.sh + postremove: ./postRemove.sh +``` + +6. Build your .deb package using nfpm: + +```sh +nfpm pkg --packager deb --target . +``` + +7. Now when your package is installed, your app will be associated with specified file types. When you open file with your app, + new instance of app is launched and file path is passed as argument to your app. + To handle this you should parse command line arguments in your app. Example: + +```go title="main.go" +func main() { + argsWithoutProg := os.Args[1:] + + if len(argsWithoutProg) != 0 { + println("launchArgs", argsWithoutProg) + } +} +``` + +You also can enable single instance lock for your app. In this case, when you open file with your app, new instance of app is not launched +and arguments are passed to already running instance. Check single instance lock guide for details. Example: + +```go title="main.go" +func main() { + // Create application with options + err := wails.Run(&options.App{ + Title: "wails-open-file", + Width: 1024, + Height: 768, + AssetServer: &assetserver.Options{ + Assets: assets, + }, + BackgroundColour: &options.RGBA{R: 27, G: 38, B: 54, A: 1}, + SingleInstanceLock: &options.SingleInstanceLock{ + UniqueId: "e3984e08-28dc-4e3d-b70a-45e961589cdc", + OnSecondInstanceLaunch: app.onSecondInstanceLaunch, + }, + Bind: []interface{}{ + app, + }, + }) +} +``` diff --git a/website/i18n/de/docusaurus-plugin-content-docs/current/guides/frameless.mdx b/website/i18n/de/docusaurus-plugin-content-docs/current/guides/frameless.mdx new file mode 100644 index 000000000..3845736f4 --- /dev/null +++ b/website/i18n/de/docusaurus-plugin-content-docs/current/guides/frameless.mdx @@ -0,0 +1,87 @@ +# Frameless Applications + +Wails supports application that have no frames. This can be achieved by using the [frameless](../reference/options.mdx#frameless) field in [Application Options](../reference/options.mdx#application-options). + +Wails offers a simple solution for dragging the window: Any HTML element that has the CSS style `--wails-draggable:drag` will act as a "drag handle". This property applies to all child elements. If you need to indicate that a nested element should not drag, then use the attribute '--wails-draggable:no-drag' on that element. + +```html +<html> + <head> + <link rel="stylesheet" href="/main.css" /> + </head> + + <body style="--wails-draggable:drag"> + <div id="logo"></div> + <div id="input" style="--wails-draggable:no-drag"> + <input id="name" type="text" /> + <button onclick="greet()">Greet</button> + </div> + <div id="result"></div> + + <script src="/main.js"></script> + </body> +</html> +``` + +For some projects, using a CSS variable may not be possible due to dynamic styling. In this case, you can use the `CSSDragProperty` and `CSSDragValue` application options to define a property and value that will be used to indicate draggable regions: + +```go title=main.go +package main + +import ( + "embed" + + "github.com/wailsapp/wails/v2" + "github.com/wailsapp/wails/v2/pkg/options" + "github.com/wailsapp/wails/v2/pkg/options/assetserver" +) + +//go:embed all:frontend/dist +var assets embed.FS + +func main() { + // Create an instance of the app structure + app := NewApp() + + // Create application with options + err := wails.Run(&options.App{ + Title: "alwaysontop", + Width: 1024, + Height: 768, + AssetServer: &assetserver.Options{ + Assets: assets, + }, + Frameless: true, + CSSDragProperty: "widows", + CSSDragValue: "1", + Bind: []interface{}{ + app, + }, + }) + + if err != nil { + println("Error:", err) + } +} +``` + +```html title=index.html +<!DOCTYPE html> +<html lang="en"> + <head> + <meta charset="UTF-8" /> + <meta content="width=device-width, initial-scale=1.0" name="viewport" /> + <title>alwaysontop + + +
                    + + + +``` + +:::info Fullscreen + +If you allow your application to go fullscreen, this drag functionality will be disabled. + +::: diff --git a/website/i18n/de/docusaurus-plugin-content-docs/current/guides/frontend.mdx b/website/i18n/de/docusaurus-plugin-content-docs/current/guides/frontend.mdx new file mode 100644 index 000000000..f057056c1 --- /dev/null +++ b/website/i18n/de/docusaurus-plugin-content-docs/current/guides/frontend.mdx @@ -0,0 +1,72 @@ +# Frontend + +## Script Injection + +When Wails serves your `index.html`, by default, it will inject 2 script entries into the `` tag to load `/wails/ipc.js` and `/wails/runtime.js`. These files install the bindings and runtime respectively. + +The code below shows where these are injected by default: + +```html + + + injection example + + + + + + + +
                    Please enter your name below 👇
                    +
                    + + +
                    + + + + +``` + +### Overriding Default Script Injection + +To provide more flexibility to developers, there is a meta tag that may be used to customise this behaviour: + +```html + +``` + +The options are as follows: + +| Value | Description | +| ------------------- | ------------------------------------------------ | +| noautoinjectruntime | Disable the autoinjection of `/wails/runtime.js` | +| noautoinjectipc | Disable the autoinjection of `/wails/ipc.js` | +| noautoinject | Disable all autoinjection of scripts | + +Multiple options may be used provided they are comma separated. + +This code is perfectly valid and operates the same as the autoinjection version: + +```html + + + injection example + + + + + + +
                    Please enter your name below 👇
                    +
                    + + +
                    + + + + + + +``` diff --git a/website/i18n/de/docusaurus-plugin-content-docs/current/guides/ides.mdx b/website/i18n/de/docusaurus-plugin-content-docs/current/guides/ides.mdx new file mode 100644 index 000000000..e59e144ee --- /dev/null +++ b/website/i18n/de/docusaurus-plugin-content-docs/current/guides/ides.mdx @@ -0,0 +1,127 @@ +# IDEs + +Wails aims to provide a great development experience. To that aim, we now support generating IDE specific configuration to provide smoother project setup. + +Currently, we support [Visual Studio Code](https://code.visualstudio.com/) and [Goland](https://www.jetbrains.com/go/). + +## Visual Studio Code + +```mdx-code-block +

                    + +

                    +``` + +When generating a project using the `-ide vscode` flags, IDE files will be created alongside the other project files. These files are placed into the `.vscode` directory and provide the correct configuration for debugging your application. + +The 2 files generated are `tasks.json` and `launch.json`. Below are the files generated for the default vanilla project: + +```json title="tasks.json" +{ + "version": "2.0.0", + "tasks": [ + { + "label": "build", + "type": "shell", + "options": { + "cwd": "${workspaceFolder}" + }, + "command": "go", + "args": [ + "build", + "-tags", + "dev", + "-gcflags", + "all=-N -l", + "-o", + "build/bin/myproject.exe" + ] + } + ] +} +``` + +```json title="launch.json" +{ + "version": "0.2.0", + "configurations": [ + { + "name": "Wails: Debug myproject", + "type": "go", + "request": "launch", + "mode": "exec", + "program": "${workspaceFolder}/build/bin/myproject.exe", + "preLaunchTask": "build", + "cwd": "${workspaceFolder}", + "env": {} + } + ] +} +``` + +### Configuring the install and build steps + +The `tasks.json` file is simple for the default project as there is no `npm install` or `npm run build` step needed. For projects that have a frontend build step, such as the svelte template, we would need to edit `tasks.json` to add the install and build steps: + +```json title="tasks.json" +{ + "version": "2.0.0", + "tasks": [ + { + "label": "npm install", + "type": "npm", + "script": "install", + "options": { + "cwd": "${workspaceFolder}/frontend" + }, + "presentation": { + "clear": true, + "panel": "shared", + "showReuseMessage": false + }, + "problemMatcher": [] + }, + { + "label": "npm run build", + "type": "npm", + "script": "build", + "options": { + "cwd": "${workspaceFolder}/frontend" + }, + "presentation": { + "clear": true, + "panel": "shared", + "showReuseMessage": false + }, + "problemMatcher": [] + }, + { + "label": "build", + "type": "shell", + "options": { + "cwd": "${workspaceFolder}" + }, + "command": "go", + "args": [ + "build", + "-tags", + "dev", + "-gcflags", + "all=-N -l", + "-o", + "build/bin/vscode.exe" + ], + "dependsOn": ["npm install", "npm run build"] + } + ] +} +``` + +:::info Future Enhancement + +In the future, we hope to generate a `tasks.json` that includes the install and build steps automatically. + +::: diff --git a/website/i18n/de/docusaurus-plugin-content-docs/current/guides/linux-distro-support.mdx b/website/i18n/de/docusaurus-plugin-content-docs/current/guides/linux-distro-support.mdx new file mode 100644 index 000000000..8b25c1575 --- /dev/null +++ b/website/i18n/de/docusaurus-plugin-content-docs/current/guides/linux-distro-support.mdx @@ -0,0 +1,103 @@ +# Linux Distro Support + +## Overview + +Wails offers Linux support but providing installation instructions for all available distributions is an impossible task. Instead, Wails tries to determine if the packages you need to develop applications are available via your system's package manager. Currently, we support the following package managers: + +- apt +- dnf +- emerge +- eopkg +- nixpkgs +- pacman +- zypper + +## Adding package names + +There may be circumstances where your distro uses one of the supported package managers but the package name is different. For example, you may use an Ubuntu derivative, but the package name for gtk may be different. Wails attempts to find the correct package by iterating through a list of package names. The list of packages are stored in the packagemanager specific file in the `v2/internal/system/packagemanager` directory. In our example, this would be `v2/internal/system/packagemanager/apt.go`. + +In this file, the list of packages are defined by the `Packages()` method: + +```go +func (a *Apt) Packages() packagemap { + return packagemap{ + "libgtk-3": []*Package{ + {Name: "libgtk-3-dev", SystemPackage: true, Library: true}, + }, + "libwebkit": []*Package{ + {Name: "libwebkit2gtk-4.0-dev", SystemPackage: true, Library: true}, + }, + "gcc": []*Package{ + {Name: "build-essential", SystemPackage: true}, + }, + "pkg-config": []*Package{ + {Name: "pkg-config", SystemPackage: true}, + }, + "npm": []*Package{ + {Name: "npm", SystemPackage: true}, + }, + "docker": []*Package{ + {Name: "docker.io", SystemPackage: true, Optional: true}, + }, + } +} +``` + +Let's assume that in our linux distro, `libgtk-3` is packaged under the name `lib-gtk3-dev`. We could add support for this by adding the following line: + +```go {5} +func (a *Apt) Packages() packagemap { + return packagemap{ + "libgtk-3": []*Package{ + {Name: "libgtk-3-dev", SystemPackage: true, Library: true}, + {Name: "lib-gtk3-dev", SystemPackage: true, Library: true}, + }, + "libwebkit": []*Package{ + {Name: "libwebkit2gtk-4.0-dev", SystemPackage: true, Library: true}, + }, + "gcc": []*Package{ + {Name: "build-essential", SystemPackage: true}, + }, + "pkg-config": []*Package{ + {Name: "pkg-config", SystemPackage: true}, + }, + "npm": []*Package{ + {Name: "npm", SystemPackage: true}, + }, + "docker": []*Package{ + {Name: "docker.io", SystemPackage: true, Optional: true}, + }, + } +} +``` + +## Adding new package managers + +To add a new package manager, perform the following steps: + +- Create a new file in `v2/internal/system/packagemanager` called `.go`, where `` is the name of the package manager. +- Define a struct that conforms to the package manager interface defined in `pm.go`: + +```go +type PackageManager interface { + Name() string + Packages() packagemap + PackageInstalled(*Package) (bool, error) + PackageAvailable(*Package) (bool, error) + InstallCommand(*Package) string +} +``` + +- `Name()` should return the name of the package manager +- `Packages()` should return a `packagemap`, that provides candidate filenames for dependencies +- `PackageInstalled()` should return `true` if the given package is installed +- `PackageAvailable()` should return `true` if the given package is not installed but available for installation +- `InstallCommand()` should return the exact command to install the given package name + +Take a look at the other package managers code to get an idea how this works. + +:::info Remember + +If you add support for a new package manager, don't forget to also update this page! + +::: diff --git a/website/i18n/de/docusaurus-plugin-content-docs/current/guides/linux.mdx b/website/i18n/de/docusaurus-plugin-content-docs/current/guides/linux.mdx new file mode 100644 index 000000000..f833ceffa --- /dev/null +++ b/website/i18n/de/docusaurus-plugin-content-docs/current/guides/linux.mdx @@ -0,0 +1,70 @@ +# Linux + +This page has miscellaneous guides related to developing Wails applications for Linux. + +## Video tag doesn't fire "ended" event + +When using a video tag, the "ended" event is not fired when the video is finished playing. This is a bug in WebkitGTK, however you can use the following workaround to fix it: + +```js +videoTag.addEventListener("timeupdate", (event) => { + if (event.target.duration - event.target.currentTime < 0.2) { + let ended = new Event("ended"); + event.target.dispatchEvent(ended); + } +}); +``` + +Source: [Lyimmi](https://github.com/Lyimmi) on the [discussions board](https://github.com/wailsapp/wails/issues/1729#issuecomment-1212291275) + +## GStreamer error when using Audio or Video elements + +If you are seeing the following error when including `